// AssetManager.ts var Point = class _Point { x = 0; y = 0; constructor(x, y) { if (x !== void 0 && y !== void 0) { this.x = x; this.y = y; return; } } clone() { return new _Point(this.x, this.y); } }; var Size = class { width = 0; height = 0; constructor(width, height) { if (width !== void 0 && height !== void 0) { this.width = width; this.height = height; return; } } clone() { return new Point(this.width, this.height); } }; var Rect = class _Rect { left = 0; top = 0; right = 0; bottom = 0; get x() { return this.left; } set x(value) { const diff = value - this.left; this.left += diff; this.right += diff; } get y() { return this.top; } set y(value) { const diff = value - this.top; this.top += diff; this.bottom += diff; } get width() { return this.right - this.left; } set width(value) { this.right = this.left + value; } get height() { return this.bottom - this.top; } set height(value) { this.bottom = this.top + value; } get centerX() { return (this.left + this.right) / 2; } get centerY() { return (this.top + this.bottom) / 2; } get location() { let point = new Point(); point.x = this.centerX; point.y = this.centerY; return point; } set location(point) { let w = this.width; let h = this.height; this.left = point.x; this.right = this.left + w; this.top = point.y; this.bottom = this.top + h; } get size() { let size = new Size(); size.width = this.width; size.height = this.height; return size; } set size(size) { this.width = size.width; this.height = size.height; } get isEmpty() { return this.width <= 0 || this.height <= 0; } constructor(arg0, arg1, arg2, arg3) { if (typeof arg0 === "number" && typeof arg1 === "number") { if (typeof arg2 === "number" && typeof arg3 === "number") { this.left = arg0; this.top = arg1; this.right = arg0 + arg2; this.bottom = arg1 + arg3; return; } this.right = arg0; this.bottom = arg1; return; } else if (arg0 instanceof Point && arg1 instanceof Size) { this.left = arg0.x; this.top = arg0.y; this.right = arg0.x + arg1.width; this.bottom = arg0.y + arg1.height; return; } else if (arg0 instanceof Size) { this.right = arg0.width; this.bottom = arg0.height; return; } } inflate(dx, dy) { this.left -= dx; this.right += dx; this.top -= dy; this.bottom += dy; } clone() { return new _Rect(this.left, this.top, this.width, this.height); } union(rect) { const left = Math.min(this.left, rect.left); const top = Math.min(this.top, rect.top); const right = Math.max(this.right, rect.right); const bottom = Math.max(this.bottom, rect.bottom); return new _Rect(left, top, right - left, bottom - top); } }; var Color = class _Color { argb = 0; constructor(a, r, g, b) { if (typeof a === "string") { let s = a; if (s.startsWith("#")) { s = s.substring(1); } s = s.trim(); switch (s.length) { case 3: s = "ff" + s.split("").map((c) => c + c).join(""); break; case 4: s = s.split("").map((c) => c + c).join(""); break; case 6: s = "ff" + s; break; case 8: break; default: s = "ffffffff"; } const u = parseInt(s, 16); this.argb = u; return; } if (a !== void 0 && r === void 0 && g === void 0 && b === void 0) { this.argb = a; return; } if (a === void 0 && r !== void 0 && g !== void 0 && b !== void 0) { const u = 255 << 24 | (r & 255) << 16 | (g & 255) << 8 | b & 255; this.argb = u; return; } if (a !== void 0 && r !== void 0 && g !== void 0 && b !== void 0) { const u = a << 24 | (r & 255) << 16 | (g & 255) << 8 | b & 255; this.argb = u; return; } this.argb = 0; } get a() { return this.argb >>> 24 & 255; } set a(value) { const v = value & 255; this.argb = v << 24 | this.argb & 16777215; } get r() { return this.argb >>> 16 & 255; } set r(value) { const v = value & 255; this.argb = this.argb & 4278255615 | v << 16; } get g() { return this.argb >>> 8 & 255; } set g(value) { const v = value & 255; this.argb = this.argb & 4294902015 | v << 8; } get b() { return this.argb & 255; } set b(value) { const v = value & 255; this.argb = this.argb & 4294967040 | v; } toUint32() { return this.argb; } clone() { return new _Color(this.argb); } static FromRgba(r, g, b, a) { return new _Color(a, r, g, b); } toRgbaString() { return `rgba(${this.r}, ${this.g}, ${this.b}, ${this.a / 255})`; } toHexString(includeAlpha = true) { if (includeAlpha) { return `#${this.argb.toString(16).padStart(8, "0")}`; } else { const rgb = this.argb & 16777215; return `#${rgb.toString(16).padStart(6, "0")}`; } } equals(other) { return this.argb === other.argb; } static get Transparent() { return new _Color(0, 0, 0, 0); } static get Black() { return new _Color(255, 0, 0, 0); } static get White() { return new _Color(255, 255, 255, 255); } withAlpha(alpha) { return new _Color(alpha, this.r, this.g, this.b); } withRed(red) { return new _Color(this.a, red, this.g, this.b); } withGreen(green) { return new _Color(this.a, this.r, green, this.b); } withBlue(blue) { return new _Color(this.a, this.r, this.g, blue); } }; var SliceInfo = class { bounds = new Rect(); center = new Rect(); pivot = new Point(); scale = 1; blobUrl = ""; get isNinePatch() { return !this.center.isEmpty; } }; var assetFilePath = "assets.png"; var slicesFilePath = "assets.bin"; var directoryPath = "./script"; async function loadAssetFile() { const pngPath = directoryPath + "/" + assetFilePath; return await new Promise((resolve, reject) => { const img = new Image(); img.onload = () => resolve(img); img.onerror = (e) => reject(new Error(`Failed to load asset file: ${pngPath}`)); img.src = pngPath; }); } async function readFromStream(stream) { const canvas = new OffscreenCanvas(1, 1); let offset = 0; const count = stream.getUint8(0); offset += 1; const sliceInfos = /* @__PURE__ */ new Map(); for (let i = 0; i < count; i++) { const sliceInfo = new SliceInfo(); const keyLength = stream.getUint8(offset); offset += 1; const key = new TextDecoder().decode(new Uint8Array(stream.buffer, offset, keyLength)); offset += keyLength; const left = stream.getUint8(offset); offset += 1; const top = stream.getUint8(offset); offset += 1; const wh = stream.getUint16(offset, true); offset += 2; const width = wh & 31; const height = wh >> 5 & 63; sliceInfo.bounds = new Rect(left, top, width, height); const hasCenter = (wh & 32768) !== 0; const hasPivot = (wh & 16384) !== 0; if (hasCenter) { const centerByte = stream.getUint8(offset); offset += 1; const centerLeft = centerByte & 3; const centerTop = centerByte >> 2 & 3; const centerWidth = centerByte >> 4 & 3; const centerHeight = centerByte >> 6 & 3; sliceInfo.center = new Rect(centerLeft, centerTop, centerWidth, centerHeight); } if (hasPivot) { const pivotByte = stream.getUint8(offset); offset += 1; let pivotLeft = pivotByte & 7; let pivotTop = pivotByte >> 3 & 7; if ((pivotByte & 128) !== 0) { pivotLeft *= -1; } if ((pivotByte & 64) !== 0) { pivotTop *= -1; } sliceInfo.pivot = new Point(pivotLeft, pivotTop); } canvas.width = width; canvas.height = height; const ctx = canvas.getContext("2d"); if (ctx === null) { throw new Error("Failed to get 2D context"); } ctx.clearRect(0, 0, width, height); ctx.drawImage(assetFile, sliceInfo.bounds.left, sliceInfo.bounds.top, width, height, 0, 0, width, height); const blob = await canvas.convertToBlob({ type: "image/png" }); sliceInfo.blobUrl = URL.createObjectURL(blob); sliceInfos.set(key, sliceInfo); } return sliceInfos; } var assetLoaded = false; var assetFile = await loadAssetFile(); var slices = await readFromStream(new DataView(await (await fetch(directoryPath + "/" + slicesFilePath)).arrayBuffer())).finally(() => { assetLoaded = true; }); // Consts.ts var Tab = /* @__PURE__ */ function(Tab2) { Tab2["Sounds"] = "sounds"; Tab2["Rows"] = "rows"; Tab2["Actions"] = "actions"; Tab2["Decorations"] = "decorations"; Tab2["Rooms"] = "rooms"; Tab2["Windows"] = "windows"; Tab2["Unknown"] = "unknown"; return Tab2; }({}); var EventType = /* @__PURE__ */ function(EventType2) { EventType2["AddClassicBeat"] = "AddClassicBeat"; EventType2["AddFreeTimeBeat"] = "AddFreeTimeBeat"; EventType2["AddOneshotBeat"] = "AddOneshotBeat"; EventType2["AdvanceText"] = "AdvanceText"; EventType2["BassDrop"] = "BassDrop"; EventType2["Blend"] = "Blend"; EventType2["CallCustomMethod"] = "CallCustomMethod"; EventType2["ChangeCharacter"] = "ChangeCharacter"; EventType2["ChangePlayersRows"] = "ChangePlayersRows"; EventType2["Comment"] = "Comment"; EventType2["CustomFlash"] = "CustomFlash"; EventType2["DesktopColor"] = "DesktopColor"; EventType2["FadeRoom"] = "FadeRoom"; EventType2["FinishLevel"] = "FinishLevel"; EventType2["Flash"] = "Flash"; EventType2["FlipScreen"] = "FlipScreen"; EventType2["FloatingText"] = "FloatingText"; EventType2["ForwardDecorationEvent"] = "ForwardDecorationEvent"; EventType2["ForwardEvent"] = "ForwardEvent"; EventType2["ForwardRowEvent"] = "ForwardRowEvent"; EventType2["HideRow"] = "HideRow"; EventType2["HideWindow"] = "HideWindow"; EventType2["InvertColors"] = "InvertColors"; EventType2["MacroEvent"] = "MacroEvent"; EventType2["MaskRoom"] = "MaskRoom"; EventType2["Move"] = "Move"; EventType2["MoveCamera"] = "MoveCamera"; EventType2["MoveRoom"] = "MoveRoom"; EventType2["MoveRow"] = "MoveRow"; EventType2["NarrateRowInfo"] = "NarrateRowInfo"; EventType2["NewWindowDance"] = "NewWindowDance"; EventType2["PaintHands"] = "PaintHands"; EventType2["PlayAnimation"] = "PlayAnimation"; EventType2["PlayExpression"] = "PlayExpression"; EventType2["PlaySong"] = "PlaySong"; EventType2["PlaySound"] = "PlaySound"; EventType2["PulseCamera"] = "PulseCamera"; EventType2["PulseFreeTimeBeat"] = "PulseFreeTimeBeat"; EventType2["ReadNarration"] = "ReadNarration"; EventType2["RenameWindow"] = "RenameWindow"; EventType2["ReorderRooms"] = "ReorderRooms"; EventType2["ReorderRow"] = "ReorderRow"; EventType2["ReorderSprite"] = "ReorderSprite"; EventType2["ReorderWindows"] = "ReorderWindows"; EventType2["SayReadyGetSetGo"] = "SayReadyGetSetGo"; EventType2["SetBackgroundColor"] = "SetBackgroundColor"; EventType2["SetBeatSound"] = "SetBeatSound"; EventType2["SetBeatsPerMinute"] = "SetBeatsPerMinute"; EventType2["SetClapSounds"] = "SetClapSounds"; EventType2["SetCountingSound"] = "SetCountingSound"; EventType2["SetCrotchetsPerBar"] = "SetCrotchetsPerBar"; EventType2["SetForeground"] = "SetForeground"; EventType2["SetGameSound"] = "SetGameSound"; EventType2["SetHandOwner"] = "SetHandOwner"; EventType2["SetHeartExplodeInterval"] = "SetHeartExplodeInterval"; EventType2["SetHeartExplodeVolume"] = "SetHeartExplodeVolume"; EventType2["SetMainWindow"] = "SetMainWindow"; EventType2["SetOneshotWave"] = "SetOneshotWave"; EventType2["SetPlayStyle"] = "SetPlayStyle"; EventType2["SetRoomContentMode"] = "SetRoomContentMode"; EventType2["SetRoomPerspective"] = "SetRoomPerspective"; EventType2["SetRowXs"] = "SetRowXs"; EventType2["SetSpeed"] = "SetSpeed"; EventType2["SetTheme"] = "SetTheme"; EventType2["SetVFXPreset"] = "SetVFXPreset"; EventType2["SetVisible"] = "SetVisible"; EventType2["SetWindowContent"] = "SetWindowContent"; EventType2["ShakeScreen"] = "ShakeScreen"; EventType2["ShakeScreenCustom"] = "ShakeScreenCustom"; EventType2["ShowDialogue"] = "ShowDialogue"; EventType2["ShowHands"] = "ShowHands"; EventType2["ShowRooms"] = "ShowRooms"; EventType2["ShowStatusSign"] = "ShowStatusSign"; EventType2["ShowSubdivisionsRows"] = "ShowSubdivisionsRows"; EventType2["SpinningRows"] = "SpinningRows"; EventType2["Stutter"] = "Stutter"; EventType2["TagAction"] = "TagAction"; EventType2["TextExplosion"] = "TextExplosion"; EventType2["Tile"] = "Tile"; EventType2["Tint"] = "Tint"; EventType2["TintRows"] = "TintRows"; EventType2["WindowResize"] = "WindowResize"; return EventType2; }({}); var EventAttriblte = /* @__PURE__ */ function(EventAttriblte2) { EventAttriblte2[EventAttriblte2["None"] = 0] = "None"; EventAttriblte2[EventAttriblte2["DurationEvent"] = 1] = "DurationEvent"; EventAttriblte2[EventAttriblte2["RoomEvent"] = 2] = "RoomEvent"; return EventAttriblte2; }({}); var EventInfo = class { defaultTab; durationKey = "duration"; attr; get isDurationEvent() { return (this.attr & EventAttriblte.DurationEvent) !== 0; } get isRoomEvent() { return (this.attr & EventAttriblte.RoomEvent) !== 0; } constructor(tab, enumAttriblte, durationKey) { this.defaultTab = tab; this.attr = enumAttriblte ?? EventAttriblte.None; if (durationKey !== void 0) { this.durationKey = durationKey; } } }; var WordInfo = class { phrase; length; constructor(phrase, length) { this.phrase = phrase; this.length = length; } }; var WordInfos = { SayReaDyGetSetGoNew: new WordInfo("Rea, Dy, Get, Set, Go!", 4), SayReaDyGetSetOne: new WordInfo("Rea, Dy, Get, Set, One!", 4), SayGetSetGo: new WordInfo("Get, Set, Go!", 2), SayGetSetOne: new WordInfo("Get, Set, One!", 2), JustSayRea: new WordInfo("Rea", 0), JustSayDy: new WordInfo("Dy", 0), JustSayGet: new WordInfo("Get", 0), JustSaySet: new WordInfo("Set", 0), JustSayAnd: new WordInfo("And", 0), JustSayGo: new WordInfo("Go!", 0), JustSayStop: new WordInfo("Stop", 0), JustSayAndStop: new WordInfo("And Stop!", 0), SaySwitch: new WordInfo("Switch", 0), SayWatch: new WordInfo("Watch", 0), SayListen: new WordInfo("Listen", 0), Count1: new WordInfo("1", 0), Count2: new WordInfo("2", 0), Count3: new WordInfo("3", 0), Count4: new WordInfo("4", 0), Count5: new WordInfo("5", 0), Count6: new WordInfo("6", 0), Count7: new WordInfo("7", 0), Count8: new WordInfo("8", 0), Count9: new WordInfo("9", 0), Count10: new WordInfo("10", 0), SayReadyGetSetGo: new WordInfo("Ready, Get, Set, Go!", 4), JustSayReady: new WordInfo("Ready", 0) }; var EventInfos = { AddClassicBeat: new EventInfo(Tab.Rows), AddFreeTimeBeat: new EventInfo(Tab.Rows), AddOneshotBeat: new EventInfo(Tab.Rows), AdvanceText: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent), BassDrop: new EventInfo(Tab.Actions), Blend: new EventInfo(Tab.Decorations), CallCustomMethod: new EventInfo(Tab.Actions), ChangeCharacter: new EventInfo(Tab.Actions), ChangePlayersRows: new EventInfo(Tab.Actions), Comment: new EventInfo(Tab.Unknown), CustomFlash: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent), DesktopColor: new EventInfo(Tab.Windows, EventAttriblte.DurationEvent), FadeRoom: new EventInfo(Tab.Rooms, EventAttriblte.DurationEvent), FinishLevel: new EventInfo(Tab.Actions), Flash: new EventInfo(Tab.Actions), FlipScreen: new EventInfo(Tab.Actions), FloatingText: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent), ForwardDecorationEvent: new EventInfo(Tab.Decorations), ForwardEvent: new EventInfo(Tab.Unknown), ForwardRowEvent: new EventInfo(Tab.Rows), HideRow: new EventInfo(Tab.Actions), HideWindow: new EventInfo(Tab.Windows), InvertColors: new EventInfo(Tab.Actions), MacroEvent: new EventInfo(Tab.Unknown), MaskRoom: new EventInfo(Tab.Rooms), Move: new EventInfo(Tab.Decorations, EventAttriblte.DurationEvent), MoveCamera: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent), MoveRoom: new EventInfo(Tab.Rooms, EventAttriblte.DurationEvent), MoveRow: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent), NarrateRowInfo: new EventInfo(Tab.Sounds), NewWindowDance: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent), PaintHands: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent), PlayAnimation: new EventInfo(Tab.Decorations), PlayExpression: new EventInfo(Tab.Actions), PlaySong: new EventInfo(Tab.Sounds), PlaySound: new EventInfo(Tab.Sounds), PulseCamera: new EventInfo(Tab.Actions), PulseFreeTimeBeat: new EventInfo(Tab.Rows), ReadNarration: new EventInfo(Tab.Sounds), RenameWindow: new EventInfo(Tab.Windows), ReorderRooms: new EventInfo(Tab.Rooms), ReorderRow: new EventInfo(Tab.Rows), ReorderSprite: new EventInfo(Tab.Decorations), ReorderWindows: new EventInfo(Tab.Windows), SayReadyGetSetGo: new EventInfo(Tab.Sounds), SetBackgroundColor: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent), SetBeatSound: new EventInfo(Tab.Sounds), SetBeatsPerMinute: new EventInfo(Tab.Sounds), SetClapSounds: new EventInfo(Tab.Sounds), SetCountingSound: new EventInfo(Tab.Sounds), SetCrotchetsPerBar: new EventInfo(Tab.Sounds), SetForeground: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent), SetGameSound: new EventInfo(Tab.Sounds), SetHandOwner: new EventInfo(Tab.Actions), SetHeartExplodeInterval: new EventInfo(Tab.Sounds), SetHeartExplodeVolume: new EventInfo(Tab.Sounds), SetMainWindow: new EventInfo(Tab.Windows), SetOneshotWave: new EventInfo(Tab.Rows), SetPlayStyle: new EventInfo(Tab.Actions), SetRoomContentMode: new EventInfo(Tab.Rooms), SetRoomPerspective: new EventInfo(Tab.Rooms, EventAttriblte.DurationEvent), SetRowXs: new EventInfo(Tab.Rows), SetSpeed: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent), SetTheme: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent), SetVFXPreset: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent), SetVisible: new EventInfo(Tab.Decorations), SetWindowContent: new EventInfo(Tab.Windows, EventAttriblte.DurationEvent), ShakeScreen: new EventInfo(Tab.Actions), ShakeScreenCustom: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent), ShowDialogue: new EventInfo(Tab.Actions), ShowHands: new EventInfo(Tab.Actions), ShowRooms: new EventInfo(Tab.Rooms, EventAttriblte.DurationEvent), ShowStatusSign: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent), ShowSubdivisionsRows: new EventInfo(Tab.Actions), SpinningRows: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent), Stutter: new EventInfo(Tab.Actions), TagAction: new EventInfo(Tab.Actions), TextExplosion: new EventInfo(Tab.Actions), Tile: new EventInfo(Tab.Decorations, EventAttriblte.DurationEvent), Tint: new EventInfo(Tab.Decorations, EventAttriblte.DurationEvent), TintRows: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent), WindowResize: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent) }; // View.ts var lineHeight = 6; var charHeight = 8; var iconSize = 14; var IconStyle = class { enabled = true; active = false; hover = false; scale = 1; showDuration = false; }; function withState(color, active, enabled) { return (enabled ? color : new Color(4286874756)).withAlpha(active ? 192 : 91); } function createLayer(key, bound, color, style) { const layer = document.createElement("div"); const info = slices.get(key); layer.style.position = "absolute"; layer.style.boxSizing = "content-box"; if (info.isNinePatch) { const center = info.center; const width = bound?.width ?? info.bounds.width; const height = bound?.height ?? info.bounds.height; layer.style.left = `${(bound?.left ?? bound?.x ?? 0) * style.scale}px`; layer.style.top = `${(bound?.top ?? bound?.y ?? 0) * style.scale}px`; layer.style.borderStyle = "solid"; layer.style.borderWidth = `${center.top * style.scale}px ${(info.bounds.width - center.right) * style.scale}px ${(info.bounds.height - center.bottom) * style.scale}px ${center.left * style.scale}px`; layer.style.borderImageSource = `url(${info.blobUrl})`; layer.style.borderImageSlice = `${center.top} ${info.bounds.width - center.right} ${info.bounds.height - center.bottom} ${center.left} fill`; layer.style.borderImageWidth = `1`; layer.style.borderImageOutset = `0`; layer.style.borderImageRepeat = `repeat`; layer.style.width = `${(width - center.left - (info.bounds.width - center.right)) * style.scale}px`; layer.style.height = `${(height - center.top - (info.bounds.height - center.bottom)) * style.scale}px`; } else { layer.style.left = `${((bound?.left ?? bound?.x ?? 0) - info.pivot.x) * style.scale}px`; layer.style.top = `${((bound?.top ?? bound?.y ?? 0) - info.pivot.y) * style.scale}px`; layer.style.width = `${(bound?.width ?? info.bounds.width) * style.scale}px`; layer.style.height = `${(bound?.height ?? info.bounds.height) * style.scale}px`; layer.style.backgroundImage = `url(${info.blobUrl})`; layer.style.backgroundSize = `${bound?.width ?? info.bounds.width * style.scale}px ${bound?.height ?? info.bounds.height * style.scale}px`; } if (color && Color.White.equals(color) === false) { const filterId = getColorMatrixId(color); layer.style.filter = `url(#${filterId})`; layer.onColorChange = (color2) => { if (!color2) { return; } const newFilterId = getColorMatrixId(color2); layer.style.filter = `url(#${newFilterId})`; }; } else { } return layer; } var colorMatrixIds = /* @__PURE__ */ new Map(); var colorMatrixCache = document.createElement("div"); document.body.appendChild(colorMatrixCache); function getColorMatrixId(rgba) { if (colorMatrixIds.has(rgba.toUint32())) { return colorMatrixIds.get(rgba.toUint32()); } const feColorMatrix = document.createElementNS("http://www.w3.org/2000/svg", "feColorMatrix"); feColorMatrix.setAttribute("type", "matrix"); const r = rgba.r / 255; const g = rgba.g / 255; const b = rgba.b / 255; const a = rgba.a / 255; feColorMatrix.setAttribute("values", `${r} 0 0 0 0 0 ${g} 0 0 0 0 0 ${b} 0 0 0 0 0 ${a} 0`); const filter = document.createElementNS("http://www.w3.org/2000/svg", "filter"); filter.setAttribute("id", `filter_${rgba.toHexString()}`); filter.appendChild(feColorMatrix); const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svg.setAttribute("width", "0"); svg.setAttribute("height", "0"); svg.appendChild(filter); colorMatrixCache.appendChild(svg); colorMatrixIds.set(rgba.toUint32(), filter.getAttribute("id")); return filter.getAttribute("id"); } function createRDFontLayer(text, style) { const lineHead = new Point(0, -charHeight); const start = lineHead.clone(); const layer = document.createElement("div"); layer.style.position = "absolute"; for (let i = 0; i < text.length; i++) { const char = text.charAt(i); if (char === "\n") { start.x = lineHead.x; start.y += lineHeight * style.scale; } else { const charCode = char.charCodeAt(0); const charKey = `char_${charCode.toString(16).padStart(4, "0")}`; const charInfo = slices.get(charKey); const charLayer = createLayer(charKey, new Point(start.x, start.y), null, style); start.x += (charInfo?.bounds.width ?? charHeight) * style.scale; layer.appendChild(charLayer); } } return layer; } function createBackLayer(size, color, style) { const outline = "event_outline"; const back = "event_back"; const backLayer = createLayer(back, new Rect(1, 1, (size?.width ?? iconSize) - 2, (size?.height ?? iconSize) - 2), withState(color, style.active, style.enabled), style); const outlineLayer = createLayer(outline, size ? new Rect(size) : null, new Color(style.active ? 4294967295 : 4289243304), style); if (backLayer.onColorChange) { backLayer.onStateChange = (style2) => backLayer.onColorChange(withState(color, style2.active, style2.enabled)); } if (outlineLayer.onColorChange) { outlineLayer.onStateChange = (style2) => outlineLayer.onColorChange(new Color(style2.active ? 4294967295 : 4289243304)); } return [ backLayer, outlineLayer ]; } function colorOf(tab) { switch (tab) { case Tab.Sounds: return new Color("d92433"); case Tab.Rows: return new Color("2c4fdb"); case Tab.Actions: return new Color("c544b3"); case Tab.Rooms: return new Color("d8b811"); case Tab.Decorations: return new Color("00c459"); case Tab.Windows: return new Color("50b5d7"); default: return new Color("7d7d7d"); } } function layerHoverInit(layer) { layer.onStateChange = (style) => { if (style.hover) { layer.style.opacity = "1.0"; } else { layer.style.opacity = "0"; } }; } function createElementEvent(obj, style) { style = { ...new IconStyle(), ...style }; const evttype = obj.type; let key0 = `event_${obj.type}`; if (!slices.has(key0)) { console.warn(`Slice for event type ${evttype} not found, using Unknown.`); if (!slices.has("event_Unknown")) { return null; } key0 = "event_Unknown"; } const info = slices.get(key0); if (!info) { console.warn(`Slice info for event type ${evttype} not found.`); return null; } const evttypeEnum = EventType[evttype]; const evinfo = EventInfos[evttypeEnum]; const key = "event_" + evttype; const pulse = "event_beat_pulse"; const hit = "event_beat_hit"; const hitf = "event_beat_hit_freeze"; const hitb = "event_beat_hit_burn"; const beatcross = "event_beat_cross"; const beatx = "event_beat_x"; const beatsynco = "event_beat_synco"; const beatline = "event_beat_line"; const evtag = "event_tag"; const evbarea = "event_beat_area"; const beatColor = new Color(4284539717); const element = document.createElement("div"); const internalLayers = []; function addLayers(layers) { for (const layer of layers) { if (layer) { element.appendChild(layer); internalLayers.push(layer); } } } element.style.imageRendering = "pixelated"; switch (evttype) { case EventType.AddClassicBeat: { const tick = obj.tick ?? 1; const swing = (obj.swing ?? 0) || 1; const hold = obj.hold ?? 0; const syncoSwing = obj.syncoSwing ?? 0; const prexs = obj.preXs ?? { syncoBeat: -1, syncoSwing: 0 }; const length = obj.length ?? 7; const iconWidth = iconSize * (tick * (length - 1 - prexs.syncoSwing)); const holdBar = hold > 0 ? createLayer(evbarea, new Rect(iconWidth, 0, iconSize * hold, iconSize), new Color(style.active ? 4291839731 : 4286462352), style) : null; if (holdBar) { holdBar.style.pointerEvents = "none"; } const backLayers2 = createBackLayer(new Size(iconWidth, iconSize), colorOf(obj.tab ?? evinfo.defaultTab), style); const pulses = []; for (let i = 0; i < length - 1; i++) { const pulseLayer = createLayer(pulse, new Point(iconSize * (tick * (i + i % 2 * (1 - swing) - (i <= prexs.syncoBeat ? 0 : prexs.syncoSwing))), 0), null, style); layerHoverInit(pulseLayer); pulses.push(pulseLayer); } const hitLayer = createLayer(hit, new Point(iconSize * (tick * (length - 1 - (prexs.syncoSwing ?? 0))) - 1, 0), null, style); addLayers([ holdBar, ...backLayers2, ...pulses, hitLayer ]); } break; case EventType.AddOneshotBeat: { const tick = obj.tick ?? 1; const interval = obj.interval ?? 2; const loop = obj.loops ?? 0; const subdiv = obj.subdivisions ?? 1; const hold = obj.hold ?? false; const mode = obj.freezeBurnMode ?? null; const delay = obj.freezeBurnMode === "Freezeshot" ? obj.delay ?? 0 : 0; const subdivWidth = iconSize * (subdiv - 1) / subdiv * tick; const eventWidth = iconSize * (interval * loop + tick + delay); const off = interval - tick; const backLayers2 = createBackLayer(new Size(eventWidth, iconSize), colorOf(obj.tab ?? evinfo.defaultTab), style); const holdWidth = iconSize * (interval - tick - delay); const holdLayer = hold && holdWidth - subdivWidth > 0 ? createLayer(evbarea, new Rect(eventWidth + subdivWidth, 0, holdWidth - subdivWidth, iconSize), new Color(style.enabled ? 4291839731 : 4285493103), style) : null; const subdivLayer = subdiv > 1 ? createLayer(evbarea, new Rect(eventWidth, 0, subdivWidth, iconSize), new Color(style.enabled ? 4279480353 : 4285493103), style) : null; const skipshotLayer = obj.skipshot ?? false ? createLayer(evbarea, new Rect(eventWidth + Math.max(subdivWidth, holdWidth), 0, iconSize * interval - Math.max(subdivWidth, holdWidth), iconSize), new Color(style.enabled ? 4291115835 : 4285493103), style) : null; if (holdLayer) holdLayer.style.pointerEvents = "none"; if (subdivLayer) subdivLayer.style.pointerEvents = "none"; if (skipshotLayer) skipshotLayer.style.pointerEvents = "none"; const pulses = []; const crossLayers = []; const posx = -off * iconSize; const hittype = mode === "Freezeshot" ? hitf : hitb; for (let l = 0; l <= loop; l++) { for (let i = 0; i < subdiv; i++) { const pulseLayer = createLayer(pulse, new Point(iconSize * (l * interval + i * tick / subdiv), 0), null, style); layerHoverInit(pulseLayer); pulses.push(pulseLayer); } for (let i = 0; i < subdiv; i++) { const hitLayer2 = createLayer(hit, new Point(iconSize * (l * interval + delay + tick + i * tick / subdiv) - 1, 0), null, style); pulses.push(hitLayer2); } const crossLayer1 = mode || hold ? createLayer(beatcross, new Point(iconSize * l * interval + posx - 1, 0), null, style) : null; const crossLayer2 = mode ? createLayer(beatcross, new Point(iconSize * (l - (mode === "Freezeshot" ? 0 : 1)) * interval - 1, 0), null, style) : null; const hitLayer = createLayer(hittype, new Point(iconSize * (l * interval + tick) - 1, 0), null, style); if (crossLayer1) { layerHoverInit(crossLayer1); crossLayers.push(crossLayer1); } if (crossLayer2) { layerHoverInit(crossLayer2); crossLayers.push(crossLayer2); } pulses.push(hitLayer); } const loopLayer = createLayer("event_beat_loop", new Point(eventWidth, 0), null, style); loopLayer.style.opacity = "0"; loopLayer.onStateChange = (style2) => { if (style2.hover) { loopLayer.style.opacity = "1.0"; } else { loopLayer.style.opacity = "0"; } }; addLayers([ ...backLayers2, holdLayer, subdivLayer, skipshotLayer, ...pulses, loopLayer, ...crossLayers ]); } break; case EventType.Comment: { const backLayers2 = createBackLayer(info.bounds.size, new Color(obj.color ?? "7d7d7d"), style); const iconLayer = createLayer(key, null, null, style); addLayers([ ...backLayers2, iconLayer ]); } break; case EventType.AddFreeTimeBeat: { const hold = obj.hold ?? 0; const holdLayer = hold > 0 ? createLayer(evbarea, new Rect(info.bounds.width, 0, iconSize * hold - info.bounds.width, iconSize), new Color(style.active ? 4291839731 : 4286462352), style) : null; if (holdLayer) { holdLayer.style.pointerEvents = "none"; } const backLayers2 = createBackLayer(new Size(info.bounds.width, iconSize), beatColor, style); const hitLayer = obj.pulse === 6 ? createLayer(hit, new Point(0, 0), null, style) : null; const textLayer = createRDFontLayer(((obj.pulse ?? 0) + 1).toString(), style); textLayer.style.left = `${1.5 * style.scale}px`; textLayer.style.top = `${10 * style.scale}px`; addLayers([ holdLayer, ...backLayers2, hitLayer, textLayer ]); } break; case EventType.DesktopColor: { const duration = obj.duration ?? 0; const backLayers2 = createBackLayer(new Size(info.bounds.width, info.bounds.height * 4), colorOf(obj.tab ?? evinfo.defaultTab), style); const iconLayer = createLayer(`${key}_0`, new Point(0, info.bounds.height), null, style); const iconColorLayer = createLayer(key, new Point(0, info.bounds.height), null, style); const durationLayer = obj.duration > 1 ? createLayer(evbarea, new Rect(iconSize, 0, (duration - 1) * iconSize, info.bounds.height * 4), new Color(4283471790), style) : null; addLayers([ ...backLayers2, durationLayer, iconLayer, iconColorLayer ]); } break; case EventType.PulseFreeTimeBeat: { const hold = obj.hold ?? 0; const holdLayer = hold > 0 ? createLayer(evbarea, new Rect(info.bounds.width, 0, iconSize * hold - info.bounds.width, info.bounds.height), new Color(style.active ? 4291839731 : 4286462352), style) : null; if (holdLayer) { holdLayer.style.pointerEvents = "none"; } const backLayers2 = createBackLayer(new Size(info.bounds.width, info.bounds.height), beatColor, style); const hitLayer = obj.pulse === 6 ? createLayer(hit, new Point(0, 0), null, style) : null; let text = ""; switch (obj.action) { case "Custom": text = ((obj.customPulse ?? 0) + 1).toString(); break; case "Increment": text = ">"; break; case "Decrement": text = "<"; break; case "Remove": text = "x"; break; } const textLayer = createRDFontLayer(text, style); textLayer.style.left = `${1.5 * style.scale}px`; textLayer.style.top = `${10 * style.scale}px`; addLayers([ holdLayer, ...backLayers2, hitLayer, textLayer ]); } break; case EventType.ReorderRooms: case EventType.ReorderWindows: { const backLayers2 = createBackLayer(info.bounds.size, colorOf(obj.tab ?? evinfo.defaultTab), style); const orderLayers = []; const order = obj.order ?? [ 0, 1, 2, 3 ]; for (let i = 0; i < order.length; i++) { { const orderLayer = createLayer(`${key}_${order[i]}`, new Point(0, i * iconSize), null, style); orderLayers.push(orderLayer); } } addLayers([ ...backLayers2, ...orderLayers ]); } break; default: const backLayers = createBackLayer(info.bounds.size, colorOf(obj.tab ?? evinfo.defaultTab), style); addLayers(backLayers); switch (evttype) { case EventType.CustomFlash: addLayers([ createLayer(`${key}_0`, null, new Color(obj.startColor ?? "000000"), style), createLayer(`${key}_1`, null, new Color(obj.endColor ?? "000000"), style) ]); break; case EventType.FlipScreen: const flip = (obj.flipX ? 1 : 0) | (obj.flipY ? 1 : 0); if (flip === 0) { addLayers([ createLayer(key, null, null, style) ]); } else { addLayers([ createLayer(`${key}_${flip - 1}`, null, null, style) ]); } default: const layer = document.createElement("div"); layer.style.position = "absolute"; layer.style.left = "0"; layer.style.top = "0"; layer.style.width = `${info.bounds.width * style.scale}px`; layer.style.height = `${info.bounds.height * style.scale}px`; layer.style.backgroundSize = `${info.bounds.width * style.scale}px ${info.bounds.height * style.scale}px`; layer.style.backgroundImage = `url(${info.blobUrl})`; element.appendChild(layer); break; } break; } element.onStateChange = (style2) => { style2 = { ...style2 }; internalLayers.forEach((layer) => { if (layer.onStateChange) { layer.onStateChange(style2); } }); }; return element; } export { createElementEvent };