diff --git a/images/moreoneshothold.png b/images/moreoneshothold.png new file mode 100644 index 0000000..a933422 Binary files /dev/null and b/images/moreoneshothold.png differ diff --git a/index.html b/index.html index 552e396..5461011 100644 --- a/index.html +++ b/index.html @@ -35,7 +35,8 @@ }; - + diff --git a/pages/appendix_tools.md b/pages/appendix_tools.md index b9fe73d..f8fa85f 100644 --- a/pages/appendix_tools.md +++ b/pages/appendix_tools.md @@ -22,6 +22,8 @@ g 1 1 5 4 #0ff{ --- +完整功能支持请前往[此处](https://view.obugs.cn)。 +
diff --git a/pages/changelog.md b/pages/changelog.md index a3038ea..ceb0c08 100644 --- a/pages/changelog.md +++ b/pages/changelog.md @@ -1,5 +1,8 @@ # 更新信息 +#### 2026-01-16 +- RDTKView(~~RDView2~~) 已完成部署 + #### 2026-01-14 - 制作人员表增加了 - RDView 对正式版编辑器新特性的部分适配 diff --git a/pages/classicbeat.md b/pages/classicbeat.md index 40abb2c..2f7c987 100644 --- a/pages/classicbeat.md +++ b/pages/classicbeat.md @@ -10,7 +10,7 @@ 第二个选项“**摇摆**”就是剧情模式里老奶奶那样的摇摆普通拍子,可以使用拖动条来调节,对照下方绿色竖线的移动可以很直观地看到摇摆效果。不过拖动滑条你只能得到一些倍数十分规整的摇摆拍子,例如摇摆值为0.25,0.5,0.75等,如果你的音乐里真的有些更为不同寻常的摇摆幅度,那就要直接在框里填写数字了。 -```rdview2 8 9 +```rdtkview 8 9 {"beat": 2, "y": 1, "type": "AddClassicBeat", "row": 0, "tick": 1, "swing": 0.25, "hold": 0 }, {"beat": 2, "y": 2, "type": "AddClassicBeat", "row": 0, "tick": 1, "swing": 0.5, "hold": 0 }, {"beat": 2, "y": 3, "type": "AddClassicBeat", "row": 0, "tick": 1, "swing": 0.75, "hold": 0 }, diff --git a/pages/moreoneshotbeats.md b/pages/moreoneshotbeats.md index d5712f6..a560277 100644 --- a/pages/moreoneshotbeats.md +++ b/pages/moreoneshotbeats.md @@ -338,6 +338,52 @@ g 0 -1 3 2 #0000[offset=0 1]{ }; ``` +## 长按单发拍 + +长按单发拍第一次出现在`7-1` + +当听到`咻噗`的声音时,说明下一次击拍需要长按到下一个出拍点。 + +在修饰符中选中进度条符号就创建了一个长按单发拍,会多出`间隔`与`长按提示选项`选项。 + +![](../images/moreoneshothold.png) + +对于长按单发拍,一共有四个关键的时间点:十字,出拍点(绿线),按拍点(黄线),长按(紫色格子)。 +```rdtkview 5 3 + { "bar": 1, "beat": 3, "y": 2, "type": "AddOneshotBeat","interval": 2, "tick": 1, "hold": true }, +``` + +- **十字**显示长按单发拍子的提示音。 +- **绿线**代表单发拍会在此响一次。 +- **黄线**表示长按的起始点,也就是说玩家应当从这里开始长按。 +- **紫格**就是此次长按所需的时间。 +- **绿线**与**黄线**之间的间隔就是`拍长`的时间。 +- **十字**与**黄线**或者**绿线**与**紫格**末端之间的间隔就是`间隔`的时间。 + +在`长按提示`有三个选项,分别是:自动、偏早、偏晚。 + +- 选择**偏早**时,`十字`的位置会在`绿线`之前。 +- 选择**偏晚**时,`十字`不会显示,但提示音会与`绿线`重合。 +- 选择**自动**时: +- 若**拍长**小于或等于1,则像`偏早`一样,长按单发拍子的提示音会在`绿线`之前; +- 若**拍长**大于1,则像`偏晚`一样,`十字`不会显示,但提示音会与`绿线`重合。 + +```rdtkview 5 5 + { "bar": 1, "beat": 3, "y": 2, "type": "AddOneshotBeat","interval": 2, "tick": 1, "hold": true }, + { "bar": 1, "beat": 3, "y": 3, "type": "AddOneshotBeat","interval": 2, "tick": 1, "hold": true }, + { "bar": 1, "beat": 3, "y": 4, "type": "AddOneshotBeat","interval": 2, "tick": 1, "hold": true } +``` + +若设计长按单发拍,还必须满足松手音效与提示音不可重叠 + +如果需要在长按单发拍上叠加多个拍子来凸显鼓点,可以将他们的按拍点放在同一位置。 + +```rdtkview 5 3 + { "bar": 1, "beat": 1.5, "y": 2, "tick": 2.5, "type": "AddOneshotBeat" }, + { "bar": 1, "beat": 2.5, "y": 2, "tick": 1.5, "type": "AddOneshotBeat" }, + { "bar": 1, "beat": 3, "y": 2, "type": "AddOneshotBeat","interval": 2, "tick": 1, "hold": true } +``` + 最后我们针对细分拍、冻结拍、灼热拍做一个技术总结: ```rdview 19 7 diff --git a/rdviewAssets/assets b/rdviewAssets/assets new file mode 100644 index 0000000..2c1e294 Binary files /dev/null and b/rdviewAssets/assets differ diff --git a/script/View.js b/script/rdtkview.js similarity index 56% rename from script/View.js rename to script/rdtkview.js index 52c6413..7f6a805 100644 --- a/script/View.js +++ b/script/rdtkview.js @@ -1,4 +1,282 @@ -// AssetManager.ts +// definition.ts +var Tab = /* @__PURE__ */ function(Tab2) { + Tab2["Sounds"] = "Sounds"; + Tab2["Rows"] = "Rows"; + Tab2["Actions"] = "Actions"; + Tab2["Decorations"] = "Sprites"; + Tab2["Rooms"] = "Rooms"; + Tab2["Windows"] = "Windows"; + Tab2["Unknown"] = "Unknown"; + return Tab2; +}(Tab || {}); +var SayReadyGetSetGoWords = /* @__PURE__ */ function(SayReadyGetSetGoWords2) { + SayReadyGetSetGoWords2["SayReaDyGetSetGoNew"] = "SayReaDyGetSetGoNew"; + SayReadyGetSetGoWords2["SayReaDyGetSetOne"] = "SayReaDyGetSetOne"; + SayReadyGetSetGoWords2["SayGetSetGo"] = "SayGetSetGo"; + SayReadyGetSetGoWords2["SayGetSetOne"] = "SayGetSetOne"; + SayReadyGetSetGoWords2["JustSayRea"] = "JustSayRea"; + SayReadyGetSetGoWords2["JustSayDy"] = "JustSayDy"; + SayReadyGetSetGoWords2["JustSayGet"] = "JustSayGet"; + SayReadyGetSetGoWords2["JustSaySet"] = "JustSaySet"; + SayReadyGetSetGoWords2["JustSayAnd"] = "JustSayAnd"; + SayReadyGetSetGoWords2["JustSayGo"] = "JustSayGo"; + SayReadyGetSetGoWords2["JustSayStop"] = "JustSayStop"; + SayReadyGetSetGoWords2["JustSayAndStop"] = "JustSayAndStop"; + SayReadyGetSetGoWords2["SaySwitch"] = "SaySwitch"; + SayReadyGetSetGoWords2["SayWatch"] = "SayWatch"; + SayReadyGetSetGoWords2["SayListen"] = "SayListen"; + SayReadyGetSetGoWords2["Count1"] = "Count1"; + SayReadyGetSetGoWords2["Count2"] = "Count2"; + SayReadyGetSetGoWords2["Count3"] = "Count3"; + SayReadyGetSetGoWords2["Count4"] = "Count4"; + SayReadyGetSetGoWords2["Count5"] = "Count5"; + SayReadyGetSetGoWords2["Count6"] = "Count6"; + SayReadyGetSetGoWords2["Count7"] = "Count7"; + SayReadyGetSetGoWords2["Count8"] = "Count8"; + SayReadyGetSetGoWords2["Count9"] = "Count9"; + SayReadyGetSetGoWords2["Count10"] = "Count10"; + SayReadyGetSetGoWords2["SayReadyGetSetGo"] = "SayReadyGetSetGo"; + SayReadyGetSetGoWords2["JustSayReady"] = "JustSayReady"; + return SayReadyGetSetGoWords2; +}(SayReadyGetSetGoWords || {}); +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["Unknown"] = "Unknown"; + EventType2["WindowResize"] = "WindowResize"; + return EventType2; +}(EventType || {}); +var hiddenEventType = [ + EventType.ForwardDecorationEvent, + EventType.ForwardEvent, + EventType.ForwardRowEvent, + EventType.MacroEvent, + EventType.SpinningRows, + EventType.ShowSubdivisionsRows +]; +var EventAttriblte = /* @__PURE__ */ function(EventAttriblte2) { + EventAttriblte2[EventAttriblte2["None"] = 0] = "None"; + EventAttriblte2[EventAttriblte2["DurationEvent"] = 1] = "DurationEvent"; + EventAttriblte2[EventAttriblte2["RoomEvent"] = 2] = "RoomEvent"; + return EventAttriblte2; +}(EventAttriblte || {}); +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; + this.durationKey = durationKey ?? "duration"; + } +}; +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, "duration"), + BassDrop: new EventInfo(Tab.Actions, EventAttriblte.RoomEvent), + 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 | EventAttriblte.RoomEvent, "duration"), + DesktopColor: new EventInfo(Tab.Windows, EventAttriblte.DurationEvent, "duration"), + FadeRoom: new EventInfo(Tab.Rooms, EventAttriblte.DurationEvent, "duration"), + FinishLevel: new EventInfo(Tab.Actions), + Flash: new EventInfo(Tab.Actions, EventAttriblte.RoomEvent), + FlipScreen: new EventInfo(Tab.Actions, EventAttriblte.RoomEvent), + FloatingText: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent | EventAttriblte.RoomEvent, "duration"), + ForwardDecorationEvent: new EventInfo(Tab.Decorations), + ForwardEvent: new EventInfo(Tab.Unknown, EventAttriblte.RoomEvent), + ForwardRowEvent: new EventInfo(Tab.Rows), + HideRow: new EventInfo(Tab.Actions), + HideWindow: new EventInfo(Tab.Windows), + InvertColors: new EventInfo(Tab.Actions, EventAttriblte.RoomEvent), + MacroEvent: new EventInfo(Tab.Unknown), + MaskRoom: new EventInfo(Tab.Rooms), + Move: new EventInfo(Tab.Decorations, EventAttriblte.DurationEvent, "duration"), + MoveCamera: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent | EventAttriblte.RoomEvent, "duration"), + MoveRoom: new EventInfo(Tab.Rooms, EventAttriblte.DurationEvent, "duration"), + MoveRow: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent, "duration"), + NarrateRowInfo: new EventInfo(Tab.Sounds), + NewWindowDance: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent, "duration"), + PaintHands: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent | EventAttriblte.RoomEvent, "duration"), + 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, EventAttriblte.RoomEvent), + PulseFreeTimeBeat: new EventInfo(Tab.Rows), + ReadNarration: new EventInfo(Tab.Sounds), + RenameWindow: new EventInfo(Tab.Windows), + ReorderRooms: new EventInfo(Tab.Rooms), + ReorderRow: new EventInfo(Tab.Actions), + ReorderSprite: new EventInfo(Tab.Decorations), + ReorderWindows: new EventInfo(Tab.Windows), + SayReadyGetSetGo: new EventInfo(Tab.Sounds, EventAttriblte.RoomEvent), + SetBackgroundColor: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent | EventAttriblte.RoomEvent, "duration"), + 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 | EventAttriblte.RoomEvent, "duration"), + SetGameSound: new EventInfo(Tab.Sounds), + SetHandOwner: new EventInfo(Tab.Actions, EventAttriblte.RoomEvent), + 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, "duration"), + SetRowXs: new EventInfo(Tab.Rows), + SetSpeed: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent, "duration"), + SetTheme: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent | EventAttriblte.RoomEvent, "duration"), + SetVFXPreset: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent | EventAttriblte.RoomEvent, "duration"), + SetVisible: new EventInfo(Tab.Decorations), + SetWindowContent: new EventInfo(Tab.Windows, EventAttriblte.DurationEvent, "duration"), + ShakeScreen: new EventInfo(Tab.Actions, EventAttriblte.RoomEvent), + ShakeScreenCustom: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent | EventAttriblte.RoomEvent, "duration"), + ShowDialogue: new EventInfo(Tab.Actions, EventAttriblte.RoomEvent), + ShowHands: new EventInfo(Tab.Actions, EventAttriblte.RoomEvent), + ShowRooms: new EventInfo(Tab.Rooms, EventAttriblte.DurationEvent, "duration"), + ShowStatusSign: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent, "duration"), + ShowSubdivisionsRows: new EventInfo(Tab.Actions), + SpinningRows: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent, "duration"), + Stutter: new EventInfo(Tab.Actions, EventAttriblte.RoomEvent), + TagAction: new EventInfo(Tab.Actions), + TextExplosion: new EventInfo(Tab.Actions, EventAttriblte.RoomEvent), + Tile: new EventInfo(Tab.Decorations, EventAttriblte.DurationEvent, "duration"), + Tint: new EventInfo(Tab.Decorations, EventAttriblte.DurationEvent, "duration"), + TintRows: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent | EventAttriblte.RoomEvent, "duration"), + Unknown: new EventInfo(Tab.Unknown), + WindowResize: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent, "duration") +}; var Point = class _Point { x = 0; y = 0; @@ -271,25 +549,18 @@ var SliceInfo = class { center = new Rect(); pivot = new Point(); scale = 1; - blobUrl = ""; get isNinePatch() { return !this.center.isEmpty; } }; + +// assetManager.ts var assetFilePath = "assets.png"; var slicesFilePath = "assets.bin"; var directoryPath = "./rdviewAssets"; -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; - }); -} +var assetSize = new Size(210, 160); +var assetUrl = directoryPath + "/" + assetFilePath; async function readFromStream(stream) { - const canvas = new OffscreenCanvas(1, 1); let offset = 0; const count = stream.getUint8(0); offset += 1; @@ -333,299 +604,16 @@ async function readFromStream(stream) { } 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 SayReadyGetSetGoWords = /* @__PURE__ */ function(SayReadyGetSetGoWords2) { - SayReadyGetSetGoWords2["SayReaDyGetSetGoNew"] = "SayReaDyGetSetGoNew"; - SayReadyGetSetGoWords2["SayReaDyGetSetOne"] = "SayReaDyGetSetOne"; - SayReadyGetSetGoWords2["SayGetSetGo"] = "SayGetSetGo"; - SayReadyGetSetGoWords2["SayGetSetOne"] = "SayGetSetOne"; - SayReadyGetSetGoWords2["JustSayRea"] = "JustSayRea"; - SayReadyGetSetGoWords2["JustSayDy"] = "JustSayDy"; - SayReadyGetSetGoWords2["JustSayGet"] = "JustSayGet"; - SayReadyGetSetGoWords2["JustSaySet"] = "JustSaySet"; - SayReadyGetSetGoWords2["JustSayAnd"] = "JustSayAnd"; - SayReadyGetSetGoWords2["JustSayGo"] = "JustSayGo"; - SayReadyGetSetGoWords2["JustSayStop"] = "JustSayStop"; - SayReadyGetSetGoWords2["JustSayAndStop"] = "JustSayAndStop"; - SayReadyGetSetGoWords2["SaySwitch"] = "SaySwitch"; - SayReadyGetSetGoWords2["SayWatch"] = "SayWatch"; - SayReadyGetSetGoWords2["SayListen"] = "SayListen"; - SayReadyGetSetGoWords2["Count1"] = "Count1"; - SayReadyGetSetGoWords2["Count2"] = "Count2"; - SayReadyGetSetGoWords2["Count3"] = "Count3"; - SayReadyGetSetGoWords2["Count4"] = "Count4"; - SayReadyGetSetGoWords2["Count5"] = "Count5"; - SayReadyGetSetGoWords2["Count6"] = "Count6"; - SayReadyGetSetGoWords2["Count7"] = "Count7"; - SayReadyGetSetGoWords2["Count8"] = "Count8"; - SayReadyGetSetGoWords2["Count9"] = "Count9"; - SayReadyGetSetGoWords2["Count10"] = "Count10"; - SayReadyGetSetGoWords2["SayReadyGetSetGo"] = "SayReadyGetSetGo"; - SayReadyGetSetGoWords2["JustSayReady"] = "JustSayReady"; - return SayReadyGetSetGoWords2; -}({}); -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; - this.durationKey = durationKey ?? "duration"; - } -}; -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, "duration"), - 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, "duration"), - DesktopColor: new EventInfo(Tab.Windows, EventAttriblte.DurationEvent, "duration"), - FadeRoom: new EventInfo(Tab.Rooms, EventAttriblte.DurationEvent, "duration"), - FinishLevel: new EventInfo(Tab.Actions), - Flash: new EventInfo(Tab.Actions), - FlipScreen: new EventInfo(Tab.Actions), - FloatingText: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent | EventAttriblte.RoomEvent, "duration"), - 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, "duration"), - MoveCamera: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent, "duration"), - MoveRoom: new EventInfo(Tab.Rooms, EventAttriblte.DurationEvent, "duration"), - MoveRow: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent, "duration"), - NarrateRowInfo: new EventInfo(Tab.Sounds), - NewWindowDance: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent, "duration"), - PaintHands: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent | EventAttriblte.RoomEvent, "duration"), - 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 | EventAttriblte.RoomEvent, "duration"), - 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 | EventAttriblte.RoomEvent, "duration"), - 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, "duration"), - SetRowXs: new EventInfo(Tab.Rows), - SetSpeed: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent, "duration"), - SetTheme: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent | EventAttriblte.RoomEvent, "duration"), - SetVFXPreset: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent | EventAttriblte.RoomEvent, "duration"), - SetVisible: new EventInfo(Tab.Decorations), - SetWindowContent: new EventInfo(Tab.Windows, EventAttriblte.DurationEvent, "duration"), - ShakeScreen: new EventInfo(Tab.Actions, EventAttriblte.RoomEvent), - ShakeScreenCustom: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent | EventAttriblte.RoomEvent, "duration"), - ShowDialogue: new EventInfo(Tab.Actions), - ShowHands: new EventInfo(Tab.Actions), - ShowRooms: new EventInfo(Tab.Rooms, EventAttriblte.DurationEvent, "duration"), - ShowStatusSign: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent, "duration"), - ShowSubdivisionsRows: new EventInfo(Tab.Actions), - SpinningRows: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent, "duration"), - Stutter: new EventInfo(Tab.Actions), - TagAction: new EventInfo(Tab.Actions), - TextExplosion: new EventInfo(Tab.Actions), - Tile: new EventInfo(Tab.Decorations, EventAttriblte.DurationEvent, "duration"), - Tint: new EventInfo(Tab.Decorations, EventAttriblte.DurationEvent, "duration"), - TintRows: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent | EventAttriblte.RoomEvent, "duration"), - WindowResize: new EventInfo(Tab.Actions, EventAttriblte.DurationEvent, "duration") -}; - -// View.ts +// rdtkview.ts var lineHeight = 6; var charHeight = 8; var iconSize = 14; @@ -636,63 +624,183 @@ var IconStyle = class { scale = 1; showDuration = false; }; +var FilterData = class { + color; + hue = 0; + saturation = 1; + brightness = 1; + getFilter() { + let filter = ""; + if (this.color) { + filter += `url(#${getColorMatrixId(this.color)}) `; + } + if (this.hue !== 0) { + filter += `hue-rotate(${this.hue * 360}deg) `; + } + if (this.saturation !== 1) { + filter += `saturate(${this.saturation}) `; + } + if (this.brightness !== 1) { + filter += `brightness(${this.brightness}) `; + } + return filter.trim() || "none"; + } +}; 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"); +function createLayerFromBackground(key, bound, color, style, backgroundRepeat = false) { const info = slices.get(key); - layer.style.position = "absolute"; - layer.style.boxSizing = "content-box"; + if (!info) return []; if (info?.isNinePatch) { + const rectBound = bound ?? new Rect(0, 0, info.bounds.width, info.bounds.height); 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 { - if (bound instanceof Rect) { - layer.style.left = `${(bound.left - (info?.pivot.x ?? 0)) * style.scale}px`; - layer.style.top = `${(bound.top - (info?.pivot.y ?? 0)) * style.scale}px`; - layer.style.width = `${(bound.width ?? info?.bounds.width ?? 0) * style.scale}px`; - layer.style.height = `${(bound.height ?? info?.bounds.height ?? 0) * style.scale}px`; - if (info) { - layer.style.backgroundImage = `url(${info.blobUrl})`; + const left = rectBound.left; + const top = rectBound.top; + const width = rectBound.width; + const height = rectBound.height; + const infoLeft = info.bounds.left; + const infoTop = info.bounds.top; + const srcXs = [ + 0, + center.left, + center.right, + info.bounds.width + ]; + const srcYs = [ + 0, + center.top, + center.bottom, + info.bounds.height + ]; + const layers = []; + for (let y = 0; y < 3; y++) { + const srcTop = srcYs[y]; + const srcHeight = srcYs[y + 1] - srcYs[y]; + const dstTop = top + (y < 2 ? srcTop : height - (info.bounds.height - srcYs[y])); + const dstHeight = y === 1 ? height - center.top - (info.bounds.height - center.bottom) : srcHeight; + const heightScale = dstHeight / srcHeight; + for (let x = 0; x < 3; x++) { + const srcLeft = srcXs[x]; + const srcWidth = srcXs[x + 1] - srcXs[x]; + const dstLeft = left + (x < 2 ? srcLeft : width - (info.bounds.width - srcXs[x])); + const dstWidth = x === 1 ? width - center.left - (info.bounds.width - center.right) : srcWidth; + const widthScale = dstWidth / srcWidth; + if (backgroundRepeat && x === 1 && y === 1) { + for (let dstt = 0; dstt < dstHeight; dstt += srcHeight) { + const dsth = Math.min(srcHeight, dstHeight - dstt); + for (let dstl = 0; dstl < dstWidth; dstl += srcWidth) { + const dstw = Math.min(srcWidth, dstWidth - dstl); + const patchLayer = document.createElement("div"); + patchLayer.filterData = new FilterData(); + patchLayer.updateFilter = () => { + patchLayer.style.filter = patchLayer.filterData.getFilter(); + }; + patchLayer.style.position = "absolute"; + patchLayer.style.boxSizing = "content-box"; + patchLayer.style.backgroundClip = "content-box"; + patchLayer.style.backgroundImage = `url('${assetUrl}')`; + patchLayer.style.left = `${(dstLeft + dstl) * style.scale}px`; + patchLayer.style.top = `${(dstTop + dstt) * style.scale}px`; + patchLayer.style.width = `${dstw * style.scale}px`; + patchLayer.style.height = `${dsth * style.scale}px`; + patchLayer.style.backgroundPosition = `-${(infoLeft + srcLeft) * style.scale}px -${(infoTop + srcTop) * style.scale}px`; + patchLayer.style.backgroundSize = `${assetSize.width * style.scale}px ${assetSize.height * style.scale}px`; + layers.push(patchLayer); + } + } + } else { + const patchLayer = document.createElement("div"); + patchLayer.filterData = new FilterData(); + patchLayer.updateFilter = () => { + patchLayer.style.filter = patchLayer.filterData.getFilter(); + }; + patchLayer.style.position = "absolute"; + patchLayer.style.boxSizing = "content-box"; + patchLayer.style.backgroundClip = "content-box"; + patchLayer.style.backgroundImage = `url('${assetUrl}')`; + patchLayer.style.left = `${dstLeft * style.scale}px`; + patchLayer.style.top = `${dstTop * style.scale}px`; + patchLayer.style.width = `${dstWidth * style.scale}px`; + patchLayer.style.height = `${dstHeight * style.scale}px`; + patchLayer.style.backgroundPosition = `-${(infoLeft + srcLeft) * widthScale * style.scale}px -${(infoTop + srcTop) * heightScale * style.scale}px`; + patchLayer.style.backgroundSize = `${assetSize.width * widthScale * style.scale}px ${assetSize.height * heightScale * style.scale}px`; + layers.push(patchLayer); + } } - layer.style.backgroundSize = `${(bound.width ?? info?.bounds.width ?? 0) * style.scale}px ${(bound.height ?? info?.bounds.height ?? 0) * style.scale}px`; - } else { - layer.style.left = `${((bound?.x ?? 0) - (info?.pivot.x ?? 0)) * style.scale}px`; - layer.style.top = `${((bound?.y ?? 0) - (info?.pivot.y ?? 0)) * style.scale}px`; - layer.style.width = `${(info?.bounds.width ?? 0) * style.scale}px`; - layer.style.height = `${(info?.bounds.height ?? 0) * style.scale}px`; - if (info) { - layer.style.backgroundImage = `url(${info.blobUrl})`; - } - layer.style.backgroundSize = `${(info?.bounds.width ?? 0) * style.scale}px ${(info?.bounds.height ?? 0) * 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})`; - }; + if (color && Color.White.equals(color) === false) { + layers.forEach((layer) => { + layer.onColorChange = (color2) => { + if (!color2) { + return; + } + layer.filterData.color = color2; + layer.updateFilter(); + }; + layer.onColorChange(color); + }); + } else { + } + return layers; } else { + const pivotX = info.pivot.x ?? 0; + const pivotY = info.pivot.y ?? 0; + const layer = document.createElement("div"); + layer.filterData = new FilterData(); + layer.updateFilter = () => { + layer.style.filter = layer.filterData.getFilter(); + }; + layer.style.position = "absolute"; + layer.style.boxSizing = "content-box"; + layer.style.backgroundClip = "content-box"; + layer.style.backgroundImage = `url('${assetUrl}')`; + if (bound instanceof Rect) { + const left = bound.left; + const top = bound.top; + const width = bound.width; + const height = bound.height; + const infoLeft = info.bounds.left; + const infoTop = info.bounds.top; + const widthScale = width / info.bounds.width; + const heightScale = height / info.bounds.height; + layer.style.left = `${(left - pivotX) * style.scale}px`; + layer.style.top = `${(top - pivotY) * style.scale}px`; + layer.style.width = `${width * style.scale}px`; + layer.style.height = `${height * style.scale}px`; + layer.style.backgroundPosition = `-${infoLeft * widthScale * style.scale}px -${infoTop * heightScale * style.scale}px`; + layer.style.backgroundSize = `${assetSize.width * widthScale * style.scale}px ${assetSize.height * heightScale * style.scale}px`; + console.log(layer.style.backgroundSize); + } else { + bound = bound ?? new Point(0, 0); + const left = bound.x; + const top = bound.y; + const width = info.bounds.width; + const height = info.bounds.height; + const infoLeft = info.bounds.left; + const infoTop = info.bounds.top; + layer.style.left = `${(left - pivotX) * style.scale}px`; + layer.style.top = `${(top - pivotY) * style.scale}px`; + layer.style.width = `${width * style.scale}px`; + layer.style.height = `${height * style.scale}px`; + layer.style.backgroundPosition = `-${infoLeft * style.scale}px -${infoTop * style.scale}px`; + layer.style.backgroundSize = `${assetSize.width * style.scale}px ${assetSize.height * style.scale}px`; + } + if (color && Color.White.equals(color) === false) { + layer.onColorChange = (color2) => { + if (!color2) { + return; + } + layer.filterData.color = color2; + layer.updateFilter(); + }; + layer.onColorChange(color); + } else { + } + return [ + layer + ]; } - return layer; } var colorMatrixIds = /* @__PURE__ */ new Map(); var colorMatrixCache = document.createElement("div"); @@ -707,7 +815,7 @@ function getColorMatrixId(rgba) { 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`); + feColorMatrix.setAttribute("values", `${r * r} 0 0 0 0 0 ${g * g} 0 0 0 0 0 ${b * 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); @@ -738,6 +846,7 @@ function createRDFontLayer(text, style, color) { const lineHead = new Point(0, -charHeight); const start = lineHead.clone(); const layer = document.createElement("div"); + const charLayers = []; layer.style.position = "absolute"; for (let i = 0; i < text.length; i++) { const char = text.charAt(i); @@ -749,28 +858,40 @@ function createRDFontLayer(text, style, color) { const charKey = `char_${charCode.toString(16).padStart(4, "0")}`; const charInfo = slices.get(charKey); if (charInfo) { - const charLayer = createLayer(charKey, new Point(start.x, start.y), color, style); + const charLayer = createLayerFromBackground(charKey, new Point(start.x, start.y), color, style); start.x += charInfo.bounds.width * style.scale; - layer.appendChild(charLayer); + charLayers.push(...charLayer); } } } + layer.updateFilter = () => { + charLayers.forEach((cl) => { + cl.updateFilter(); + }); + }; + charLayers.forEach((cl) => { + layer.appendChild(cl); + }); 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)); - } + const backLayer = createLayerFromBackground(back, new Rect(1, 1, (size?.width ?? iconSize) - 2, (size?.height ?? iconSize) - 2), withState(color, style.active, style.enabled), style); + backLayer.forEach((layer) => { + if (layer.onColorChange) { + layer.onStateChange = (style2) => layer.onColorChange(withState(color, style2.active, style2.enabled)); + } + }); + const outlineLayer = createLayerFromBackground(outline, size ? new Rect(size) : null, new Color(style.active ? 4294967295 : 4289243304), style); + outlineLayer.forEach((layer) => { + if (layer.onColorChange) { + layer.onStateChange = (style2) => layer.onColorChange(new Color(style2.active ? 4294967295 : 4289243304)); + } + }); return [ - backLayer, - outlineLayer + ...backLayer, + ...outlineLayer ]; } function colorOf(tab) { @@ -838,21 +959,24 @@ function createElementEvent(obj, style) { ...new IconStyle(), ...style }; - const evttype = obj.type ?? EventType.ForwardEvent; let key0 = `event_${obj.type}`; + const hasType = EventType.hasOwnProperty(obj.type); + if (!hasType) { + console.warn(obj.type ? `Unknown event type: ${obj.type}` : `Event type missing`); + } if (!slices.has(key0)) { if (!slices.has("event_Unknown")) { return null; } key0 = "event_Unknown"; } - const info = slices.get(key0); - if (!info) { + const evttype = obj.type ?? EventType.Unknown; + const slcinfo = slices.get(key0) ?? slices.get("event_Unknown"); + if (!slcinfo) { console.warn(`Slice info for event type ${evttype} not found.`); return null; } - const evttypeEnum = EventType[evttype]; - const evinfo = EventInfos[evttypeEnum]; + const evinfo = EventInfos[evttype] ?? EventInfos[EventType.Unknown]; const key = "event_" + evttype; const pulse = "event_beat_pulse"; const hit = "event_beat_hit"; @@ -866,19 +990,12 @@ function createElementEvent(obj, style) { const evbarea = "event_beat_area"; const evbskip = "event_beat_skip"; const beatColor = new Color(4284539717); + let iconWidth = iconSize; const element = document.createElement("div"); - const internalLayers = []; - if (evttype === EventType.NewWindowDance) { - obj.tab = obj.customTab ?? Tab.Windows; - } - function addLayers(layers) { - for (const layer of layers) { - if (layer) { - element.appendChild(layer); - internalLayers.push(layer); - } - } - } + element.eventStyle = { + ...style + }; + const layersToAdd = []; element.style.imageRendering = "pixelated"; switch (evttype) { case EventType.AddClassicBeat: @@ -886,31 +1003,32 @@ function createElementEvent(obj, style) { 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 iconWidth2 = iconSize * (tick * (length - 1 - prexs.syncoSwing)); + const holdBar = hold > 0 ? createLayerFromBackground(evbarea, new Rect(iconWidth2, 0, iconSize * hold, iconSize), new Color(style.active ? 4291839731 : 4286462352), style, true) : []; + holdBar.forEach((layer) => { + layer.style.pointerEvents = "none"; + return layer; + }); + const backLayers2 = createBackLayer(new Size(iconWidth2, 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 pulseLayer = createLayerFromBackground(pulse, new Point(iconSize * (tick * (i + i % 2 * (1 - swing) - (i <= prexs.syncoBeat ? 0 : prexs.syncoSwing))), 0), null, style); + pulseLayer.forEach((layer) => { + layerHoverInit(layer); + return layer; + }); + 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 - ]); + const hitLayer = createLayerFromBackground(hit, new Point(iconSize * (tick * (length - 1 - (prexs.syncoSwing ?? 0))) - 1, 0), null, style); + layersToAdd.push(...holdBar); + layersToAdd.push(...backLayers2); + layersToAdd.push(...pulses); + layersToAdd.push(...hitLayer); } break; case EventType.AddOneshotBeat: @@ -928,115 +1046,128 @@ function createElementEvent(obj, style) { const off = interval - tick; const backLayers2 = createBackLayer(new Size(eventWidth, iconSize), colorOf(obj.tab ?? evinfo.defaultTab), style); const holdWidth = hold ? iconSize * (interval - tick - delay) : 0; - 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 = skip ? createLayer(evbarea, new Rect(eventWidth + Math.max(subdivWidth, holdWidth), 0, iconSize * (interval - delay) - Math.max(subdivWidth, holdWidth), iconSize), new Color(style.enabled ? 4291115835 : 4285493103), style) : null; - const skipHitLayer = skip ? createLayer(evbskip, new Point(eventWidth + iconSize * (interval - delay) - 1, 0), null, style) : null; - if (holdLayer) holdLayer.style.pointerEvents = "none"; - if (subdivLayer) subdivLayer.style.pointerEvents = "none"; - if (skipshotLayer) skipshotLayer.style.pointerEvents = "none"; - if (skipHitLayer) skipHitLayer.style.pointerEvents = "none"; + const holdLayer = hold && holdWidth - subdivWidth > 0 ? createLayerFromBackground(evbarea, new Rect(eventWidth + subdivWidth, 0, holdWidth - subdivWidth, iconSize), new Color(style.enabled ? 4291839731 : 4285493103), style, true) : []; + holdLayer.forEach((layer) => { + layer.style.pointerEvents = "none"; + return layer; + }); + const subdivLayer = subdiv > 1 ? createLayerFromBackground(evbarea, new Rect(eventWidth, 0, subdivWidth, iconSize), new Color(style.enabled ? 4279480353 : 4285493103), style, true) : []; + subdivLayer.forEach((layer) => { + layer.style.pointerEvents = "none"; + return layer; + }); + const skipshotLayer = skip ? createLayerFromBackground(evbarea, new Rect(eventWidth + Math.max(subdivWidth, holdWidth), 0, iconSize * (interval - delay) - Math.max(subdivWidth, holdWidth), iconSize), new Color(style.enabled ? 4291115835 : 4285493103), style, true) : []; + skipshotLayer.forEach((layer) => { + layer.style.pointerEvents = "none"; + return layer; + }); + const skipHitLayer = skip ? createLayerFromBackground(evbskip, new Point(eventWidth + iconSize * (interval - delay) - 1, 0), null, style) : []; + skipHitLayer.forEach((layer) => { + layer.style.pointerEvents = "none"; + return layer; + }); const pulses = []; const crossLayers = []; const posx = -off * iconSize; - const hittype = mode === "Freezeshot" ? hitf : hitb; + const hittype = mode === "Freezeshot" ? hitf : mode === "Burnshot" ? hitb : null; 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); + const pulseLayer = createLayerFromBackground(pulse, new Point(iconSize * (l * interval + i * tick / subdiv), 0), null, style); + pulseLayer.forEach((layer) => { + layerHoverInit(layer); + return layer; + }); + 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 hitLayer2 = createLayerFromBackground(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 crossLayer1 = mode || hold ? createLayerFromBackground(beatcross, new Point(iconSize * l * interval + posx - 1, 0), null, style) : []; + crossLayer1.forEach((layer) => { + layerHoverInit(layer); + return layer; + }); + const crossLayer2 = mode ? createLayerFromBackground(beatcross, new Point(iconSize * (l - (mode === "Freezeshot" ? 0 : 1)) * interval - 1, 0), null, style) : []; + crossLayer2.forEach((layer) => { + layerHoverInit(layer); + return layer; + }); + const hitLayer = hittype ? createLayerFromBackground(hittype, new Point(iconSize * (l * interval + tick) - 1, 0), null, style) : []; + crossLayers.push(...crossLayer1); + crossLayers.push(...crossLayer2); + pulses.push(...hitLayer); } - const loopLayer = createLayer("event_beat_loop", new Point(eventWidth, 0), null, style); - loopLayer.style.opacity = "0"; - loopLayer.style.zIndex = "5"; - loopLayer.onStateChange = (style2) => { - if (style2.hover) { - loopLayer.style.opacity = "1.0"; - } else { - loopLayer.style.opacity = "0"; - } - }; - addLayers([ - ...backLayers2, - holdLayer, - subdivLayer, - skipshotLayer, - skipHitLayer, - ...pulses, - loopLayer, - ...crossLayers - ]); + const loopLayer = createLayerFromBackground("event_beat_loop", new Point(eventWidth, 0), null, style); + loopLayer.forEach((loopLayer2) => { + loopLayer2.style.opacity = "0"; + loopLayer2.style.zIndex = "5"; + loopLayer2.onStateChange = (style2) => { + if (style2.hover) { + loopLayer2.style.opacity = "1.0"; + } else { + loopLayer2.style.opacity = "0"; + } + }; + return loopLayer2; + }); + layersToAdd.push(...backLayers2); + layersToAdd.push(...holdLayer); + layersToAdd.push(...subdivLayer); + layersToAdd.push(...skipshotLayer); + layersToAdd.push(...skipHitLayer); + layersToAdd.push(...pulses); + layersToAdd.push(...loopLayer); + layersToAdd.push(...crossLayers); } 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 holdLayer = hold > 0 ? createLayerFromBackground(evbarea, new Rect(slcinfo.bounds.width, 0, iconSize * hold - slcinfo.bounds.width, iconSize), new Color(style.active ? 4291839731 : 4286462352), style, true) : []; + holdLayer.forEach((layer) => { + layer.style.pointerEvents = "none"; + return layer; + }); + const backLayers2 = createBackLayer(new Size(slcinfo.bounds.width, iconSize), beatColor, style); + const hitLayer = obj.pulse === 6 ? createLayerFromBackground(hit, new Point(0, 0), null, style) : []; const textLayer = createRDFontLayer(((obj.pulse ?? 0) + 1).toString(), style, null); textLayer.style.left = `${1.5 * style.scale}px`; textLayer.style.top = `${10 * style.scale}px`; - addLayers([ - holdLayer, - ...backLayers2, - hitLayer, - textLayer - ]); + layersToAdd.push(...holdLayer); + layersToAdd.push(...backLayers2); + layersToAdd.push(...hitLayer); + layersToAdd.push(textLayer); } 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 - ]); + const backLayers2 = createBackLayer(slcinfo.bounds.size, new Color(obj.color ?? "7d7d7d"), style); + const iconLayer = createLayerFromBackground(key, null, null, style); + layersToAdd.push(...backLayers2); + layersToAdd.push(...iconLayer); } break; case EventType.DesktopColor: { - const backLayers2 = createBackLayer(info.bounds.size, colorOf(obj.tab ?? evinfo.defaultTab), style); - console.log(info.bounds.size); - const iconColorLayer = createLayer(`${key}_0`, new Point(0, iconSize), new Color(obj.endColor ?? "ffffff"), style); - const iconLayer = createLayer(`${key}_1`, new Point(0, iconSize), null, style); - addLayers([ - ...backLayers2, - iconColorLayer, - iconLayer - ]); + const backLayers2 = createBackLayer(slcinfo.bounds.size, colorOf(obj.tab ?? evinfo.defaultTab), style); + const iconColorLayer = createLayerFromBackground(`${key}_0`, new Point(0, iconSize), new Color(obj.endColor ?? "ffffff"), style); + const iconLayer = createLayerFromBackground(`${key}_1`, new Point(0, iconSize), null, style); + layersToAdd.push(...backLayers2); + layersToAdd.push(...iconColorLayer); + layersToAdd.push(...iconLayer); } 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; + const holdLayer = hold > 0 ? createLayerFromBackground(evbarea, new Rect(slcinfo.bounds.width, 0, iconSize * hold - slcinfo.bounds.width, slcinfo.bounds.height), new Color(style.active ? 4291839731 : 4286462352), style, true) : []; + holdLayer.forEach((layer) => { + layer.style.pointerEvents = "none"; + return layer; + }); + const backLayers2 = createBackLayer(new Size(slcinfo.bounds.width, slcinfo.bounds.height), beatColor, style); + const hitLayer = obj.pulse === 6 ? createLayerFromBackground(hit, new Point(0, 0), null, style) : []; let text = ""; switch (obj.action) { case "Custom": @@ -1055,18 +1186,16 @@ function createElementEvent(obj, style) { const textLayer = createRDFontLayer(text, style, null); textLayer.style.left = `${1.5 * style.scale}px`; textLayer.style.top = `${10 * style.scale}px`; - addLayers([ - holdLayer, - ...backLayers2, - hitLayer, - textLayer - ]); + layersToAdd.push(...holdLayer); + layersToAdd.push(...backLayers2); + layersToAdd.push(...hitLayer); + layersToAdd.push(textLayer); } break; case EventType.ReorderRooms: case EventType.ReorderWindows: { - const backLayers2 = createBackLayer(info.bounds.size, colorOf(obj.tab ?? evinfo.defaultTab), style); + const backLayers2 = createBackLayer(slcinfo.bounds.size, colorOf(obj.tab ?? evinfo.defaultTab), style); const orderLayers = []; const order = obj.order ?? [ 0, @@ -1076,20 +1205,19 @@ function createElementEvent(obj, style) { ]; for (let i = 0; i < order.length; i++) { { - const orderLayer = createLayer(`${key}_${order[i]}`, new Point(0, i * iconSize), null, style); - orderLayers.push(orderLayer); + const orderLayer = createLayerFromBackground(`${key}_${order[i]}`, new Point(0, i * iconSize), null, style); + orderLayers.push(...orderLayer); } } - addLayers([ - ...backLayers2, - ...orderLayers - ]); + layersToAdd.push(...backLayers2); + layersToAdd.push(...orderLayers); } break; case EventType.SayReadyGetSetGo: { const wordInfo = WordInfos[obj.phraseToSay ?? SayReadyGetSetGoWords.JustSayGo]; const len = wordInfo.length * (obj.tick ?? 0) + 1; + iconWidth = len * iconSize; const stringToJoin = wordInfo.phrase.split(" "); const stringToDraw = [ stringToJoin[0] @@ -1122,33 +1250,32 @@ function createElementEvent(obj, style) { wordLayer.style.top = `${p.y * style.scale}px`; wordLayers.push(wordLayer); } - addLayers([ - ...backLayers2, - ...wordLayers - ]); + layersToAdd.push(...backLayers2); + layersToAdd.push(...wordLayers); } break; case EventType.SetRowXs: { const syncoBeat = obj.syncoBeat ?? -1; - const width = info.bounds.width / 6; + const width = slcinfo.bounds.width / 6; const iconBounds = slices.get(beatx).bounds; const s = width / iconBounds.width; let left = 0; const top = iconSize / 2 - iconBounds.height * s / 2; const patternLayers = []; - const backLayers2 = createBackLayer(new Size(info.bounds.width, info.bounds.height), colorOf(obj.tab ?? evinfo.defaultTab), style); + const backLayers2 = createBackLayer(new Size(slcinfo.bounds.width, slcinfo.bounds.height), colorOf(obj.tab ?? evinfo.defaultTab), style); + if (typeof obj.pattern !== "string" || obj.pattern.length !== 6) { + obj.pattern = "------"; + } for (let p of obj.pattern) { - const beatxLayer = createLayer(p === "x" ? beatx : beatline, new Rect(left, top, width, iconBounds.height * s), null, style); - patternLayers.push(beatxLayer); + const beatxLayer = createLayerFromBackground(p === "x" ? beatx : beatline, new Rect(left, top, width, iconBounds.height * s), null, style); + patternLayers.push(...beatxLayer); left += width; } - const syncoBeatLayer = syncoBeat >= 0 ? createLayer(beatsynco, new Rect(width * syncoBeat, top, width, iconBounds.height * s), null, style) : null; - addLayers([ - ...backLayers2, - ...patternLayers, - syncoBeatLayer - ]); + const syncoBeatLayer = syncoBeat >= 0 ? createLayerFromBackground(beatsynco, new Rect(width * syncoBeat, top, width, iconBounds.height * s), null, style) : []; + layersToAdd.push(...backLayers2); + layersToAdd.push(...patternLayers); + layersToAdd.push(...syncoBeatLayer); } break; case EventType.ShowRooms: @@ -1156,53 +1283,54 @@ function createElementEvent(obj, style) { const backLayers2 = createBackLayer(new Size(iconSize, iconSize * 4), colorOf(obj.tab ?? evinfo.defaultTab), style); const roomLayers = []; for (let i = 0; i < 4; i++) { - const roomLayer = createLayer(`${key}_${obj.rooms.indexOf(i) >= 0 ? "1" : "0"}`, new Point(0, i * iconSize * style.scale), null, { + const roomLayer = createLayerFromBackground(`${key}_${(obj.rooms ?? []).indexOf(i) >= 0 ? "1" : "0"}`, new Point(0, i * iconSize * style.scale), null, { ...style, scale: style.scale / 2 }); - roomLayers.push(roomLayer); + roomLayers.push(...roomLayer); } - addLayers([ - ...backLayers2, - ...roomLayers - ]); + layersToAdd.push(...backLayers2); + layersToAdd.push(...roomLayers); } break; default: - const backLayers = createBackLayer(info.bounds.size, colorOf(obj.tab ?? evinfo.defaultTab), style); - addLayers(backLayers); + const backLayers = createBackLayer(slcinfo.bounds.size, colorOf(obj.tab ?? evinfo.defaultTab), style); + layersToAdd.push(...backLayers); switch (evttype) { case EventType.CustomFlash: - const iconLayer = createLayer(key, null, null, style); - const startColorLayer = createLayer(`${key}_0`, null, new Color(obj.startColor ?? "000000").withAlpha((obj.startOpacity ?? 0) * 255), style); - const endColorLayer = createLayer(`${key}_1`, null, new Color(obj.endColor ?? "000000").withAlpha((obj.endOpacity ?? 0) * 255), style); - addLayers([ - iconLayer, - startColorLayer, - endColorLayer - ]); + const iconLayer = createLayerFromBackground(key, null, null, style); + const startColorLayer = createLayerFromBackground(`${key}_0`, null, new Color(obj.startColor ?? "000000").withAlpha((obj.startOpacity ?? 0) * 255), style); + const endColorLayer = createLayerFromBackground(`${key}_1`, null, new Color(obj.endColor ?? "000000").withAlpha((obj.endOpacity ?? 0) * 255), style); + layersToAdd.push(...iconLayer); + layersToAdd.push(...startColorLayer); + layersToAdd.push(...endColorLayer); break; case EventType.FlipScreen: { const flip = (obj.flipX ? 1 : 0) | (obj.flipY ? 2 : 0); - const iconLayer2 = createLayer(flip === 0 ? `${key}_0` : `${key}_${flip - 1}`, null, null, style); - addLayers([ - iconLayer2 - ]); + const iconLayer2 = createLayerFromBackground(flip === 0 ? `${key}_0` : `${key}_${flip - 1}`, null, null, style); + layersToAdd.push(...iconLayer2); } break; case EventType.FloatingText: { - const backColorLayer = createLayer(`${key}_0`, null, Color.FromRgba(obj.color ?? "FFFFFFFF"), style); - const foreColorLayer = createLayer(`${key}_1`, null, Color.FromRgba(obj.outlineColor ?? "FFFFFFFF"), style); - addLayers([ - backColorLayer, - foreColorLayer - ]); + const backColorLayer = createLayerFromBackground(`${key}_0`, null, Color.FromRgba(obj.color ?? "FFFFFFFF"), style); + const foreColorLayer = createLayerFromBackground(`${key}_1`, null, Color.FromRgba(obj.outlineColor ?? "FFFFFFFF"), style); + layersToAdd.push(...backColorLayer); + layersToAdd.push(...foreColorLayer); } break; case EventType.MoveRoom: { + obj.scale ??= [ + null, + null + ]; + const hasPivot = obj.pivot !== void 0; + obj.pivot ??= [ + null, + null + ]; const degree = obj.angle ?? 0; const radius = -degree * Math.PI / 180; let width = (obj.scale ? obj.scale[0] ?? 0 : 100) / 100; @@ -1213,23 +1341,26 @@ function createElementEvent(obj, style) { const uniform = Math.sqrt(width * width + height * height); width /= uniform; height /= uniform; - const roomLayer = createLayer(key, new Rect(iconSize / 2, iconSize / 2, iconSize * width, iconSize * height), null, style); - let pivotx = width * (1 - pleft * 2); - let pivoty = height * (1 - ptop * 2); - const widthrotated = pivotx * Math.cos(radius) + pivoty * Math.sin(radius); - const heightrotated = -pivotx * Math.sin(radius) + pivoty * Math.cos(radius); - const pointLayer = document.createElement("div"); - pointLayer.style.position = "absolute"; - pointLayer.style.width = `${style.scale}px`; - pointLayer.style.height = `${style.scale}px`; - pointLayer.style.left = `${iconSize * (1 - widthrotated) * style.scale / 2}px`; - pointLayer.style.top = `${iconSize * (1 + heightrotated) * style.scale / 2}px`; - pointLayer.style.backgroundColor = "#FF0000"; - roomLayer.style.transform = `translate(-50%, -50%) rotate(${-degree}deg)`; - addLayers([ - roomLayer, - pointLayer - ]); + const roomLayer = createLayerFromBackground(key, new Rect(iconSize / 2, iconSize / 2, iconSize * width, iconSize * height), null, style); + roomLayer.forEach((roomLayer2) => { + roomLayer2.style.transform = `translate(-50%, -50%) rotate(${-degree}deg)`; + return roomLayer2; + }); + layersToAdd.push(...roomLayer); + if (hasPivot) { + let pivotx = width * (1 - pleft * 2); + let pivoty = height * (1 - ptop * 2); + const widthrotated = pivotx * Math.cos(radius) + pivoty * Math.sin(radius); + const heightrotated = -pivotx * Math.sin(radius) + pivoty * Math.cos(radius); + const pointLayer = document.createElement("div"); + pointLayer.style.position = "absolute"; + pointLayer.style.width = `${style.scale}px`; + pointLayer.style.height = `${style.scale}px`; + pointLayer.style.left = `${iconSize * (1 - widthrotated) * style.scale / 2}px`; + pointLayer.style.top = `${iconSize * (1 + heightrotated) * style.scale / 2}px`; + pointLayer.style.backgroundColor = "#FF0000"; + layersToAdd.push(pointLayer); + } } break; case EventType.PaintHands: @@ -1237,77 +1368,73 @@ function createElementEvent(obj, style) { case EventType.TintRows: { const border = obj.border; - const backColorLayer = createLayer(key, null, Color.FromRgba(obj.tintColor ?? "FFFFFFFF"), style); - const foreColorLayer = border ? createLayer(border === "Outline" ? `${key}_0` : border === "Glow" ? `${key}_1` : "", null, Color.FromRgba(obj.borderColor ?? "FFFFFFFF"), style) : null; - addLayers([ - backColorLayer, - foreColorLayer - ]); + const backColorLayer = createLayerFromBackground(key, null, Color.FromRgba(obj.tintColor ?? "FFFFFFFF"), style); + const foreColorLayer = border ? createLayerFromBackground(border === "Outline" ? `${key}_0` : border === "Glow" ? `${key}_1` : "", null, Color.FromRgba(obj.borderColor ?? "FFFFFFFF"), style) : []; + layersToAdd.push(...backColorLayer); + layersToAdd.push(...foreColorLayer); } break; case EventType.SetBackgroundColor: { const backType = obj.backgroundType ?? "Color"; - const iconLayer2 = createLayer(key, null, null, style); + const iconLayer2 = createLayerFromBackground(key, null, null, style); const images = obj.image ?? []; const imagePath = images.length > 0 ? images[0] : ""; const contentInfo = slices.get(`${key}_1`); - const colorLayer = createLayer(`${key}_0`, null, Color.FromRgba((backType === "Color" ? obj.color : null) ?? "FFFFFF"), style); - const contentLayer = backType === "Image" ? createLayer("", contentInfo?.bounds ? new Rect(contentInfo?.bounds.size) : null, null, style) : null; - if (backType === "Image" && contentLayer) { - contentLayer.style.backgroundImage = `url(${imagePath})`; - contentLayer.style.left = `${-(contentInfo?.pivot.x ?? 0) * style.scale}px`; - contentLayer.style.top = `${-(contentInfo?.pivot.y ?? 0) * style.scale}px`; - } - addLayers([ - iconLayer2, - colorLayer, - contentLayer - ]); + const colorLayer = createLayerFromBackground(`${key}_0`, null, Color.FromRgba((backType === "Color" ? obj.color : null) ?? "FFFFFF"), style); + const contentLayer = backType === "Image" ? createLayerFromBackground("", contentInfo?.bounds ? new Rect(contentInfo?.bounds.size) : null, null, style) : []; + contentLayer.forEach((contentLayer2) => { + if (backType === "Image" && contentLayer2) { + contentLayer2.style.backgroundImage = `url(${imagePath})`; + contentLayer2.style.left = `${-(contentInfo?.pivot.x ?? 0) * style.scale}px`; + contentLayer2.style.top = `${-(contentInfo?.pivot.y ?? 0) * style.scale}px`; + } + return contentLayer2; + }); + layersToAdd.push(...iconLayer2); + layersToAdd.push(...colorLayer); + layersToAdd.push(...contentLayer); } break; case EventType.SetCrotchetsPerBar: { const cpb = obj.crotchetsPerBar ?? 0; - const iconLayer2 = createLayer(key, null, null, style); + const iconLayer2 = createLayerFromBackground(key, null, null, style); const cpbLayer = createRDFontLayer(cpb > 9 ? "-" : cpb.toString(), style, Color.Black); - const bLayer = createRDFontLayer("4", style, Color.Black); cpbLayer.style.left = `${2 * style.scale}px`; cpbLayer.style.top = `${9 * style.scale}px`; + const bLayer = createRDFontLayer("4", style, Color.Black); bLayer.style.left = `${8 * style.scale}px`; bLayer.style.top = `${14 * style.scale}px`; - addLayers([ - iconLayer2, - cpbLayer, - bLayer - ]); + layersToAdd.push(...iconLayer2); + layersToAdd.push(cpbLayer); + layersToAdd.push(bLayer); } break; case EventType.SetForeground: { - const iconLayer2 = createLayer(key, null, null, style); + const iconLayer2 = createLayerFromBackground(key, null, null, style); const images = obj.image ?? []; const imagePath = images.length > 0 ? images[0] : ""; const contentInfo = slices.get(`${key}_1`); - const colorLayer = imagePath ? createLayer(`${key}_0`, null, Color.Black, style) : null; - const contentLayer = imagePath ? createLayer("", contentInfo?.bounds ? new Rect(contentInfo?.bounds.size) : null, null, style) : null; - if (contentLayer) { - contentLayer.style.backgroundImage = `url(${imagePath})`; - contentLayer.style.left = `${-(contentInfo?.pivot.x ?? 0) * style.scale}px`; - contentLayer.style.top = `${-(contentInfo?.pivot.y ?? 0) * style.scale}px`; - } - addLayers([ - iconLayer2, - colorLayer, - contentLayer - ]); + const colorLayer = imagePath ? createLayerFromBackground(`${key}_0`, null, Color.Black, style) : []; + const contentLayer = imagePath ? createLayerFromBackground("", contentInfo?.bounds ? new Rect(contentInfo?.bounds.size) : null, null, style) : []; + contentLayer.forEach((contentLayer2) => { + if (contentLayer2) { + contentLayer2.style.backgroundImage = `url(${imagePath})`; + contentLayer2.style.left = `${-(contentInfo?.pivot.x ?? 0) * style.scale}px`; + contentLayer2.style.top = `${-(contentInfo?.pivot.y ?? 0) * style.scale}px`; + } + return contentLayer2; + }); + layersToAdd.push(...iconLayer2); + layersToAdd.push(...colorLayer); + layersToAdd.push(...contentLayer); } break; default: - const layer = createLayer(key, null, null, style); - addLayers([ - layer - ]); + const layer = createLayerFromBackground(hasType ? key : "event_Unknown", null, null, style); + layersToAdd.push(...layer); break; } break; @@ -1315,14 +1442,13 @@ function createElementEvent(obj, style) { if (evinfo.isDurationEvent) { const duration = obj[evinfo.durationKey] ?? 0; const durWidth = iconSize * duration; - const durationLayer = durWidth > info.bounds.width ? createLayer(evbarea, new Rect(info.bounds.width, 0, durWidth - info.bounds.width, info.bounds.height), colorOf(obj.tab ?? evinfo.defaultTab), style) : null; - if (durationLayer) { - durationLayer.style.pointerEvents = "none"; - layerHoverInit(durationLayer); - } - addLayers([ - durationLayer - ]); + const durationLayer = durWidth > slcinfo.bounds.width ? createLayerFromBackground(evbarea, new Rect(slcinfo.bounds.width, 0, durWidth - slcinfo.bounds.width, slcinfo.bounds.height), colorOf(obj.tab ?? evinfo.defaultTab), style, true) : []; + durationLayer.forEach((layer) => { + layer.style.pointerEvents = "none"; + layerHoverInit(layer); + return layer; + }); + layersToAdd.push(...durationLayer); } const rooms = obj.rooms ?? []; const roomEnabled = new Color(4292392977); @@ -1330,37 +1456,31 @@ function createElementEvent(obj, style) { if (evinfo.isRoomEvent) { const roomLayers = []; for (let i = 0; i < 4; i++) { - const roomLayer = createLayer(`room_${i}`, new Point(iconSize, 0), rooms.indexOf(i) > -1 ? roomEnabled : roomDisabled, style); + const roomLayer = createLayerFromBackground(`room_${i}`, new Point(iconWidth, 0), rooms.indexOf(i) > -1 ? roomEnabled : roomDisabled, style); + roomLayers.push(...roomLayer); + } + const roomTopLayer = rooms.indexOf(4) > -1 ? createLayerFromBackground(`room_top`, new Point(iconWidth, 0), roomEnabled, style) : []; + roomLayers.push(...roomTopLayer); + roomLayers.forEach((roomLayer) => { if (roomLayer) { layerHoverInit(roomLayer); } - roomLayers.push(roomLayer); - } - const roomTopLayer = rooms.indexOf(4) > -1 ? createLayer(`room_top`, new Point(iconSize, 0), roomEnabled, style) : null; - if (roomTopLayer) { - layerHoverInit(roomTopLayer); - } - roomLayers.push(roomTopLayer); - addLayers(roomLayers); + }); + layersToAdd.push(...roomLayers); } const condition = obj.if ?? ""; if (condition.length > 0) { const positive = /(? 0 ? `Error: Unknown type: ${obj.type}` : "Error: Type missing", slcinfo.bounds.width * style.scale, colorOf(obj.tab ?? evinfo.defaultTab)); + } + break; + } + if (hintLayer) { + layersToAdd.push(hintLayer); + } + if (obj["$style"]) { + const hsb = obj["$style"].hsb ?? [ + 0, + 1, + 1 + ]; + if (hsb.length === 3 && (hsb[0] !== 0 || hsb[1] !== 0 || hsb[2] !== 0)) { + layersToAdd.forEach((layer) => { + if (!layer.filterData) return; + layer.filterData.hue = hsb[0]; + layer.filterData.saturation = hsb[1]; + layer.filterData.brightness = hsb[2]; + }); + } + layersToAdd.forEach((layer) => { + layer.updateFilter?.(); + }); } element.onStateChange = (style2) => { style2 = { ...style2 }; - internalLayers.forEach((layer) => { + layersToAdd.forEach((layer) => { if (layer.onStateChange) { layer.onStateChange(style2); } }); }; + element.moveTo = function(x, y) { + this.style.left = `${x}px`; + this.style.top = `${y}px`; + }; + for (const layer of layersToAdd) { + if (layer) { + element.appendChild(layer); + } + } + element.eventData = obj; return element; } export { + IconStyle, + colorOf, createElementEvent }; diff --git a/script/rdtkview_render.js b/script/rdtkview_render.js new file mode 100644 index 0000000..5b0c074 --- /dev/null +++ b/script/rdtkview_render.js @@ -0,0 +1,79 @@ +import { createElementEvent } from "./rdtkview.js"; +export function render(data, width, height, scale = 2.0) { + const canvas = document.createElement("div"); + let objs = []; + try { + objs = JSON.parse(`[${data}]`); + canvas.innerHTML = ""; + } catch (e) { + canvas.innerHTML = + `
JSON解析错误:${e.message}
`; + return canvas; + } + const eventStyle = { "scale": scale, "showDuration": false }; + const elems = []; + for (let obj of objs) { + const style = { ...eventStyle, enabled: obj.active ?? true }; + const elem = createElementEvent(obj, style); + if (!elem) continue; + elem.eventStyle = style; + elem.style.position = "absolute"; + elem.style.left = `${ + ((((obj.bar ?? 1) - 1) * 8) + (obj.beat ?? 1) - 1) * 14 * + scale + }px`; + elem.style.top = `${(obj.y ?? obj.row ?? 0) * 14 * scale}px`; + elem.addEventListener("mousedown", (event) => { + const eStyle = elem.eventStyle; + eStyle.active = true; + elem.onStateChange(eStyle); + }); + elem.addEventListener("mouseover", (event) => { + const eStyle = elem.eventStyle; + eStyle.hover = true; + elem.onStateChange(eStyle); + }); + elem.addEventListener("mouseout", (event) => { + const eStyle = elem.eventStyle; + eStyle.hover = false; + eStyle.active = false; + elem.onStateChange(eStyle); + }); + elem.addEventListener("mouseup", (event) => { + const eStyle = elem.eventStyle; + eStyle.active = false; + elem.onStateChange(eStyle); + }); + elems.push(elem); + } + canvas.style.position = "relative"; + canvas.style.width = `${width * 14 * scale}px`; + canvas.style.height = `${height * 14 * scale}px`; + elems.forEach((elem) => { + canvas.appendChild(elem); + }); + return canvas; +} + +window.$docsify.plugins = [].concat(window.$docsify.plugins, (hook) => { + hook.doneEach(() => { + const pres = document.querySelectorAll("pre"); + pres.forEach((codeBlock) => { + const lang = codeBlock.getAttribute("data-lang") || ""; + if (lang.startsWith("rdtkview")) { + const code = codeBlock.querySelector("code").innerText || ""; + const args = lang.slice(8).trim().split(" "); + const width = parseInt(args[0]) || 8; + const height = parseInt(args[1]) || 4; + const scale = parseFloat(args[2]) || 2.0; + const result = render(code, width, height, scale); + const parent = document.createElement("div"); + parent.style.width = 100 + "%"; + parent.style.display = "flex"; + parent.style.justifyContent = "center"; + parent.appendChild(result); + codeBlock.replaceWith(parent); + } + }); + }); +}); diff --git a/script/special.js b/script/special.js index 1bf3445..5e8ce8d 100644 --- a/script/special.js +++ b/script/special.js @@ -1,4 +1,4 @@ -import { createElementEvent } from "./View.js"; +import { createElementEvent } from "./rdtkview.js"; let curx = 0; let cury = 0; @@ -322,52 +322,58 @@ function rdview2() { } const eventStyle = { "scale": 2.0, "showDuration": false }; let maxy = 0; + const elemPromises = []; for (let obj of objs) { const style = { ...eventStyle, enabled: obj.active ?? true }; - const elem = createElementEvent(obj, style); - elem.eventStyle = style; - elem.style.position = "absolute"; - elem.style.left = `${ - ((((obj.bar ?? 1) - 1) * 8) + (obj.beat ?? 1) - 1) * 14 * - eventStyle.scale - }px`; - elem.style.top = `${ - (obj.y ?? obj.row ?? 0) * 14 * eventStyle.scale - }px`; - if ( - ((obj.y ?? obj.row ?? 0) * 14 * eventStyle.scale) + - elem.offsetHeight > maxy - ) { - maxy = ((obj.y ?? obj.row ?? 0) * 14 * eventStyle.scale) + - elem.offsetHeight; - } - elem.addEventListener("mousedown", (event) => { - const eStyle = elem.eventStyle; - eStyle.active = true; - elem.onStateChange(eStyle); + const elem = createElementEvent(obj, style).then((elem) => { + elem.eventStyle = style; + elem.style.position = "absolute"; + elem.style.left = `${ + ((((obj.bar ?? 1) - 1) * 8) + (obj.beat ?? 1) - 1) * 14 * + eventStyle.scale + }px`; + elem.style.top = `${ + (obj.y ?? obj.row ?? 0) * 14 * eventStyle.scale + }px`; + if ( + ((obj.y ?? obj.row ?? 0) * 14 * eventStyle.scale) + + elem.offsetHeight > maxy + ) { + maxy = ((obj.y ?? obj.row ?? 0) * 14 * eventStyle.scale) + + elem.offsetHeight; + } + elem.addEventListener("mousedown", (event) => { + const eStyle = elem.eventStyle; + eStyle.active = true; + elem.onStateChange(eStyle); + }); + elem.addEventListener("mouseover", (event) => { + const eStyle = elem.eventStyle; + eStyle.hover = true; + elem.onStateChange(eStyle); + }); + elem.addEventListener("mouseout", (event) => { + const eStyle = elem.eventStyle; + eStyle.hover = false; + eStyle.active = false; + elem.onStateChange(eStyle); + }); + elem.addEventListener("mouseup", (event) => { + const eStyle = elem.eventStyle; + eStyle.active = false; + elem.onStateChange(eStyle); + }); + return elem; }); - elem.addEventListener("mouseover", (event) => { - const eStyle = elem.eventStyle; - eStyle.hover = true; - elem.onStateChange(eStyle); - }); - elem.addEventListener("mouseout", (event) => { - const eStyle = elem.eventStyle; - eStyle.hover = false; - eStyle.active = false; - elem.onStateChange(eStyle); - }); - elem.addEventListener("mouseup", (event) => { - const eStyle = elem.eventStyle; - eStyle.active = false; - elem.onStateChange(eStyle); - }); - rdcanvas.style.position = "relative"; - rdcanvas.style.height = `${maxy + 4 * 14 * eventStyle.scale}px`; - if (elem) { - rdcanvas.appendChild(elem); - } + elemPromises.push(elem); } + Promise.all(elemPromises).then((elems) => { + elems.forEach((elem) => { + rdcanvas.appendChild(elem); + }); + }); + rdcanvas.style.position = "relative"; + rdcanvas.style.height = `${maxy + 4 * 14 * eventStyle.scale}px`; } initCanvas(); initLineNumbers();