diff --git a/index.html b/index.html index d6f1472..5461011 100644 --- a/index.html +++ b/index.html @@ -1,29 +1,31 @@ + + + 节奏医生编辑器教程 + + + + + + + + + + + + - - - 节奏医生编辑器教程 - - - - - - - - - - - - - - -
加载中...
- - + - - - - - - - - - - - - \ No newline at end of file + loadRDView(); + const originalCodeRenderer = $docsify.markdown + ?.renderer?.code; + function codeblockRender(code, lang) { + if (lang.trim().startsWith("rdview")) { + return RDViewRender(lang, code); + } + // else if (lang.trim().startsWith("rdtkview")) { + // 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); + // result.toString = () => result; + // return result; + // } + return originalCodeRenderer + ? originalCodeRenderer(code, lang) + : `
${
+                        escapeHtml(code)
+                    }
`; + } + $docsify = { + ...$docsify, + ...{ + markdown: { + renderer: { + code: (code, lang) => { + return codeblockRender(code, lang); + }, + image: function (src, title, alt) { + return `
${alt}${ + alt ? `

${alt}

` : "" + }
`; + }, + }, + }, + switchLightDarkMode: { + useSwitchMode: true, + top: 130, + right: 26, + svgColor: "#7d7b75", + }, + search: { + noData: { + "/": "没有找到结果!", + }, + paths: "auto", + placeholder: { + "/": "搜索", + }, + hideOtherSidebarContent: true, + }, + }, + }; + + + + + + + + + + + + + diff --git a/pages/appendix_audios.md b/pages/appendix_audios.md index e409040..f2f7e36 100644 --- a/pages/appendix_audios.md +++ b/pages/appendix_audios.md @@ -262,6 +262,24 @@ | sndTutorialDubstep | MD-1的教程音乐 | 114 | | sndTutorialDubstep_Bassless | MD-1的教程音乐,无贝斯 | 114 | | sndTutorialDubstep_Dotted | MD-1的教程音乐,有附点 | 114 | +| sndTutorialHouse_Base | 5-25-2N的教程音乐 | 120 | +| sndTutorialHouse_AmenFill | 5-25-2N的教程音乐开始练习前摇(镲声) | 120 | +| sndTutorialHouse_FreezeCPU | 5-2的教程音乐(伊恩演示) | 120 | +| sndTutorialHouse_Freeze1 | 5-2教程音乐的第一阶段 | 120 | +| sndTutorialHouse_Freeze2 | 5-2教程音乐的第二阶段 | 120 | +| sndTutorialHouse_BurnCPU | 5-2N的教程音乐(伊恩演示) | 120 | +| sndTutorialHouse_Burn1 | 5-2N教程音乐的第一阶段 | 120 | +| sndTutorialHouse_Burn2 | 5-2N教程音乐的第二阶段 | 120 | +| sndTutorialHouse_Rest | 5-25-2N的教程音乐(休息) | 120 | +| sndTutorialHouse_Riser | 5-25-2N的教程音乐开始练习前摇(鼓声) | 120 | +| sndTutorialSyncopation | 6-1的教程音乐开头 | 110 | +| sndTutorialSyncopation | 6-1的教程音乐开头,无开头空白 | 110 | +| sndTutorialSyncopation_Phase1 | 6-1教程音乐第一阶段 | 110 | +| sndTutorialSyncopation_Phase2 | 6-1教程音乐第二阶段 | 110 | +| sndTutorialHoldshot | 7-1的教程音乐 | 95 | +| sndTutorialHoldshot_Phase1 | 7-1的教程音乐第一阶段 | 95 | +| sndTutorialHoldshot_Phase2 | 7-1的教程音乐第二阶段 | 95 | +| sndTutorialHoldshot_Phase3 | 7-1的教程音乐第三阶段 | 95 | | sndOrientalTechno | 1-1东方电舞曲 | 100 | | sndOrientalTechnodown | 1-1N东方回响贝斯的开头部分 | | | sndOrientalDubstep | 1-1N东方回响贝斯 | 130 | @@ -271,14 +289,70 @@ | sndOrientalInsomniac2 | 1-X 东方不眠夜 第二部分 | | | sndOrientalInsomniac3 | 1-X 东方不眠夜 第三部分 | | | sndOrientalInsomniacHardRep | 1-XN超东方不眠夜 | 160~180 | +| sndGongXi | 1-CNY春节贺岁片 | 145 | +| sndHalloween | 1-BOO恐怖鸟主题 | 100 | +| sndLofi | 2-1Lo-fi Hip-Hop Beats To Treat Patients To | 75 | +| sndCareless | 2-1Nwish i could care less | 75~81 | +| sndCarelessCN | 2-1Nwish i could care less中文版 | 75~81 | | sndSupraventricular88 | 2-2室上性心动过速 | 88 | +| sndUnreachable | 2-2NUnreachable | 180 | +| sndPuffPiece | 2-3缭绕 | 127 | +| Pomeranian | 2-3N嗅炸弹的博美犬 | 127.2 | +| song_of_the_sea | 2-42-4N的背景音乐 | 60 | +| sndAllTheTimes | 2-XAll The Times 咖啡之歌 | 145 | +| sndAllTheTimesCN | 2-XAll The Times 咖啡之歌中文版 | 145 | +| sndBitterness | 2-XNBitter Times 爱情是苦和甜的交错前半段 | 112~195 | +| sndBitternessCutscene | 2-XNBitter Times 爱情是苦和甜的交错后半段 | 112->195->264->195 | | sndTutorialBeans | 2-B1武士豆子跳 | 110 | +| sndSleepyGarden | 3-1沉睡花园 | 158 | | sndLounge | 3-1N休息室 | 75 | | sndBarbra | 3-2典雅 | 115 | +| sndDistantDuet | 3-3分离二重唱 | 194 | +| sndDistantDuetNight | 3-3分离二重唱·夜 | 194 | +| sndDistantDuet | 3-3分离二重唱 | 194 | +| sndDistantDuetNight | 3-3分离二重唱·夜 | 194 | | sndLesMisBar1 | 3-X轮班之歌 | 100 | | sndLesMisBar39 | 3-X轮班之歌 从第39小节开始 | | +| sndMinersong | 4-1实习医生培训演练表现评估 | 128->225.9->140~110? | +| sndRollerdisco | 4-1N滑板迪斯科震颤 | 125.5 | +| sndInvisible | 4-24-2N | 190 | | sndSteinway | 4-3斯坦威 | 80 | +| sndKnowYou | 4-4懂你 | 157 | | sndMurmurs | 4-4N喃喃细语 | 65 | +| sndLuckyBreak | 5-1路吉摔了一跤 | 156 | +| sndOSTL | 5-2One Slip Too Late 创伤之歌 | 175~150 | +| sndOSTLCN | 5-2One Slip Too Late 创伤之歌中文版 | 175~150 | +| sndFreezeshot | 5-2Lo-fi Beats For Patients To Chill To | 140 | +| sndFreezeshotH | 5-2N无以为继的伤心欲绝 | 176->100->80 | +| sndTherapy1 | 5-3七局伸展操第一部分 | 128 | +| sndTherapy2 | 5-3七局伸展操第二部分 | 124 | +| sndTherapy3 | 5-3七局伸展操第三部分 | 136 | +| sndTherapyEnding | 5-3七局伸展操结尾 | 136 | +| sndCorazonesViejos | 5-3N偕老 | 249? | +| sndDDS | 5-X梦想永不歇 | 95->62.6->102.5 | +| sndDDSCN | 5-X梦想永不歇中文版 | 95->62.6->102.5 | +| sndHaileyDuet | 6-1想把心事和你说 | 94.5->190->220->181->206? | +| sndHaileyDuetCN | 6-1想把心事和你说中文版 | 94.5->190->220->181->206? | +| sndEdegaRave | 6-2欢迎回来 | 200->85->200 | +| sndBossStage_Main | 6-XBoss战(包括埃德加批评佩奇的一段) | 150~255 | +| sndBossStage_NoCutscene | 6-XBoss战(不包括埃德加批评佩奇的一段) | 150~255 | +| sndBossStage_EndingShort | 6-XBoss战结尾(包括埃德加批评佩奇的一段) | 165 | +| sndBossStage_EndingLong | 6-XBoss战结尾(不包括埃德加批评佩奇的一段) | 165 | +| sndBlurred | 7-1模糊 | 70 | +| sndMontage | 7-X奇迹除颤器 | 160 | +| sndMontageIntro | 7-X奇迹除颤器前奏 | | +| sndColeSongLeaves | 7-X2奇迹除颤器安可版(佩奇离职分支) | 91->121.2->182-->156->240?->228?-->360 | +| sndColeSongStays | 7-X2奇迹除颤器安可版(佩奇在职分支) | 91->121.2->182-->156->240?->228?-->360 | +| sndArtExercise | X-1美术练习 | 140 | +| sndHelpingHands | X-0伸出援手 | 178 | +| sndHelpingHandsCN | X-0伸出援手中文版 | 178 | +| sndBlackestLuxuryCar | MD-1BlackestLuxuryCar | 178 | +| sndTapeStopNight | MD-2Tape/Stop/Night | 115 | +| sndThe90sDecision | MD-3The90sDecision | 128 | +| sndMeetAndTweet | X-MATMeet And Tweet | 110 | +| sndWornOutTapes | X-WOTWorn Out Tapes | 149 | +| sndSparkLine | X-KOB气球王国 | 124 | +| sndVividStasis | X-FTS恋恋群星 | 150 | | sndOsmBluesRadio | 夜间的病房内过剧情 | 98? | | SoftPianoIntimate | 第一章末尾的过剧情 | 88 | diff --git a/pages/appendix_tools.md b/pages/appendix_tools.md index 70e9acb..f8fa85f 100644 --- a/pages/appendix_tools.md +++ b/pages/appendix_tools.md @@ -20,4 +20,74 @@ g 1 1 5 4 #0ff{ }; +--- + +完整功能支持请前往[此处](https://view.obugs.cn)。 + +
+ --- \ No newline at end of file diff --git a/pages/changelog.md b/pages/changelog.md index 255722d..ceb0c08 100644 --- a/pages/changelog.md +++ b/pages/changelog.md @@ -1,5 +1,13 @@ # 更新信息 +#### 2026-01-16 +- RDTKView(~~RDView2~~) 已完成部署 + +#### 2026-01-14 +- 制作人员表增加了 +- RDView 对正式版编辑器新特性的部分适配 +- 正在逐步同步 RDView2(RhythmBase.View) 的适配 + #### 2025-11-29 - 调整目录结构 - 双人模式措辞更改 diff --git a/pages/classicbeat.md b/pages/classicbeat.md index 2ef988d..2f7c987 100644 --- a/pages/classicbeat.md +++ b/pages/classicbeat.md @@ -10,14 +10,14 @@ 第二个选项“**摇摆**”就是剧情模式里老奶奶那样的摇摆普通拍子,可以使用拖动条来调节,对照下方绿色竖线的移动可以很直观地看到摇摆效果。不过拖动滑条你只能得到一些倍数十分规整的摇摆拍子,例如摇摆值为0.25,0.5,0.75等,如果你的音乐里真的有些更为不同寻常的摇摆幅度,那就要直接在框里填写数字了。 -```rdview 8 9 -eb.AddClassicBeat 1 1[swing=0.25,tick=6]; -eb.AddClassicBeat 1 2[swing=0.5,tick=6]; -eb.AddClassicBeat 1 3[swing=0.75,tick=6]; -eb.AddClassicBeat 1 4[tick=6]; -eb.AddClassicBeat 1 5[swing=1.25,tick=6]; -eb.AddClassicBeat 1 6[swing=1.5,tick=6]; -eb.AddClassicBeat 1 7[swing=1.75,tick=6]; +```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 }, +{"beat": 2, "y": 4, "type": "AddClassicBeat", "row": 0, "tick": 1, "swing": 1, "hold": 0 }, +{"beat": 2, "y": 5, "type": "AddClassicBeat", "row": 0, "tick": 1, "swing": 1.25, "hold": 0 }, +{"beat": 2, "y": 6, "type": "AddClassicBeat", "row": 0, "tick": 1, "swing": 1.5, "hold": 0 }, +{"beat": 2, "y": 7, "type": "AddClassicBeat", "row": 0, "tick": 1, "swing": 1.75, "hold": 0 } ``` > 不要把摇摆程度拖到滑条的最右端,这样会产生一个不带`X`记号但只有2,4,6,7拍的节奏,无法读谱。 diff --git a/pages/credits.md b/pages/credits.md index 55b1b96..f654e9c 100644 --- a/pages/credits.md +++ b/pages/credits.md @@ -12,6 +12,7 @@ - [RaYmondCheung](https://space.bilibili.com/1579208) - [NoMathExpectation](https://space.bilibili.com/184862524) - [0x4D2](https://space.bilibili.com/478595264) + - [正宗的小绿君](https://space.bilibili.com/1782518253) - 视频制作: - [吾夜犹明](https://space.bilibili.com/29219948) - [山不转水到渠成](https://space.bilibili.com/4870582) diff --git a/pages/intro.md b/pages/intro.md index 9d80e03..3029cae 100644 --- a/pages/intro.md +++ b/pages/intro.md @@ -14,7 +14,7 @@ ## 联系我们
-我们的 QQ 1044116596

我们的 QQ 群号是: 1044116596

+我们的 QQ 1044116596

我们的 QQ 群号是: 1044116596

如果你有做谱相关的问题,或是对本教程有什么意见和建议,可以点击链接加入 QQ 群 [1044116596](https://qm.qq.com/q/giuo0RDv4Q) 告知我们。你也可以在群里上传谱面给我们试玩,群友们都会热心为你提供谱面优化建议。真诚欢迎各位做谱萌新和大佬的加入。 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/rdviewAssets/assets.bin b/rdviewAssets/assets.bin new file mode 100644 index 0000000..2c1e294 Binary files /dev/null and b/rdviewAssets/assets.bin differ diff --git a/rdviewAssets/assets.json b/rdviewAssets/assets.json new file mode 100644 index 0000000..0bad0ca --- /dev/null +++ b/rdviewAssets/assets.json @@ -0,0 +1,253 @@ +{ "frames": [ + { + "filename": "0.ase", + "frame": { "x": 0, "y": 0, "w": 327, "h": 160 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 327, "h": 160 }, + "sourceSize": { "w": 327, "h": 160 }, + "duration": 100 + } + ], + "meta": { + "app": "https://www.aseprite.org/", + "version": "1.3.16-beta3-x64", + "image": "assets.png", + "format": "RGBA8888", + "size": { "w": 327, "h": 160 }, + "scale": "1", + "slices": [ + { "name": "event_SpinningRows", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 246, "y": 56, "w": 14, "h": 14 } }] }, + { "name": "event_SetMainWindow", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 246, "y": 42, "w": 14, "h": 14 } }] }, + { "name": "event_RenameWindow", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 246, "y": 28, "w": 14, "h": 14 } }] }, + { "name": "event_DesktopColor_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 249, "y": 20, "w": 8, "h": 5 }, "pivot": {"x": -3, "y": -6 } }] }, + { "name": "event_DesktopColor", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 232, "y": 28, "w": 14, "h": 14 } }] }, + { "name": "event_HideWindow", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 232, "y": 14, "w": 14, "h": 14 } }] }, + { "name": "event_ReorderWindows_3", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 162, "y": 84, "w": 14, "h": 14 } }] }, + { "name": "event_ReorderWindows_2", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 162, "y": 70, "w": 14, "h": 14 } }] }, + { "name": "event_ReorderWindows_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 162, "y": 56, "w": 14, "h": 14 } }] }, + { "name": "event_ReorderWindows_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 162, "y": 42, "w": 14, "h": 14 } }] }, + { "name": "event_ReorderWindows", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 162, "y": 42, "w": 14, "h": 56 } }] }, + { "name": "event_ReorderRooms_3", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 148, "y": 84, "w": 14, "h": 14 } }] }, + { "name": "event_ReorderRooms_2", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 148, "y": 70, "w": 14, "h": 14 } }] }, + { "name": "event_ReorderRooms_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 148, "y": 56, "w": 14, "h": 14 } }] }, + { "name": "event_ReorderRooms_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 148, "y": 42, "w": 14, "h": 14 } }] }, + { "name": "event_CustomFlash_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 190, "y": 56, "w": 14, "h": 14 } }] }, + { "name": "event_MacroEvent", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 78, "y": 84, "w": 14, "h": 14 } }] }, + { "name": "event_ForwardEvent", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 64, "y": 84, "w": 14, "h": 14 } }] }, + { "name": "event_ForwardDecorationEvent", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 106, "y": 70, "w": 14, "h": 14 } }] }, + { "name": "event_ForwardRowEvent", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 92, "y": 70, "w": 14, "h": 14 } }] }, + { "name": "event_SetWindowContent", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 78, "y": 56, "w": 14, "h": 14 } }] }, + { "name": "event_WindowResize", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 64, "y": 56, "w": 14, "h": 14 } }] }, + { "name": "event_Tile", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 120, "y": 56, "w": 14, "h": 14 } }] }, + { "name": "event_Blend", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 56, "w": 14, "h": 14 } }] }, + { "name": "event_ReorderSprite", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 106, "y": 56, "w": 14, "h": 14 } }] }, + { "name": "event_ShakeScreenCustom", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 232, "y": 42, "w": 14, "h": 14 } }] }, + { "name": "event_ReorderRow", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 92, "y": 56, "w": 14, "h": 14 } }] }, + { "name": "event_NarrateRowInfo", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 176, "y": 84, "w": 14, "h": 14 } }] }, + { "name": "event_ReadNarration", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 190, "y": 0, "w": 14, "h": 14 } }] }, + { "name": "tab_icon_sounds", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 35, "y": 0, "w": 15, "h": 13 } }] }, + { "name": "tab_color_sounds", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 22, "y": 39, "w": 2, "h": 13 } }] }, + { "name": "content_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 80, "y": 106, "w": 5, "h": 5 }, "center": {"x": 2, "y": 2, "w": 1, "h": 1 } }] }, + { "name": "tab_icon_rows", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 0, "y": 13, "w": 15, "h": 13 } }] }, + { "name": "tab_icon_actions", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 0, "y": 26, "w": 15, "h": 13 } }] }, + { "name": "tab_icon_rooms", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 0, "y": 39, "w": 15, "h": 13 } }] }, + { "name": "tab_icon_decorations", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 0, "y": 52, "w": 15, "h": 13 } }] }, + { "name": "tab_icon_windows", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 0, "y": 65, "w": 15, "h": 13 } }] }, + { "name": "tab_color_rows", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 24, "y": 39, "w": 2, "h": 13 } }] }, + { "name": "tab_color_actions", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 26, "y": 39, "w": 2, "h": 13 } }] }, + { "name": "tab_color_rooms", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 28, "y": 39, "w": 2, "h": 13 } }] }, + { "name": "tab_color_decorations", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 30, "y": 39, "w": 2, "h": 13 } }] }, + { "name": "tab_color_windows", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 32, "y": 39, "w": 2, "h": 13 } }] }, + { "name": "tab_color_unknown", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 34, "y": 39, "w": 2, "h": 13 } }] }, + { "name": "tab_icon_unknown", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 0, "y": 78, "w": 15, "h": 13 } }] }, + { "name": "content_2", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 85, "y": 105, "w": 7, "h": 7 }, "center": {"x": 3, "y": 3, "w": 1, "h": 1 } }] }, + { "name": "event_Comment", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 84, "w": 14, "h": 14 } }] }, + { "name": "event_ReorderRooms", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 148, "y": 42, "w": 14, "h": 56 } }] }, + { "name": "event_SetCrotchetsPerBar", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 78, "y": 0, "w": 14, "h": 14 } }] }, + { "name": "event_PlaySong", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 0, "w": 28, "h": 14 } }] }, + { "name": "event_PlaySound", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 190, "y": 70, "w": 14, "h": 14 } }] }, + { "name": "event_SetBeatsPerMinute", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 218, "y": 42, "w": 14, "h": 14 } }] }, + { "name": "event_SetClapSounds", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 176, "y": 42, "w": 14, "h": 14 } }] }, + { "name": "event_SetHeartExplodeVolume", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 134, "y": 84, "w": 14, "h": 14 } }] }, + { "name": "event_SetHeartExplodeInterval", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 134, "y": 0, "w": 14, "h": 14 } }] }, + { "name": "event_SetGameSound", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 148, "y": 0, "w": 14, "h": 14 } }] }, + { "name": "event_SetBeatSound", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 162, "y": 0, "w": 14, "h": 14 } }] }, + { "name": "event_SetCountingSound", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 176, "y": 0, "w": 14, "h": 14 } }] }, + { "name": "event_SetOneshotWave", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 78, "y": 14, "w": 14, "h": 14 } }] }, + { "name": "event_AddFreeTimeBeat", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 225, "y": 0, "w": 7, "h": 14 } }] }, + { "name": "event_PulseFreeTimeBeat", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 232, "y": 0, "w": 7, "h": 12 } }] }, + { "name": "event_SetTheme", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 28, "w": 14, "h": 14 } }] }, + { "name": "event_SetVFXPreset", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 190, "y": 84, "w": 14, "h": 14 } }] }, + { "name": "event_SetForeground", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 134, "y": 70, "w": 14, "h": 14 } }] }, + { "name": "event_SetBackgroundColor", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 134, "y": 42, "w": 14, "h": 14 } }] }, + { "name": "event_SetSpeed", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 204, "y": 84, "w": 14, "h": 14 } }] }, + { "name": "event_Flash", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 190, "y": 42, "w": 14, "h": 14 } }] }, + { "name": "event_CustomFlash", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 204, "y": 42, "w": 14, "h": 14 } }] }, + { "name": "event_NewWindowDance", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 70, "w": 14, "h": 14 } }] }, + { "name": "event_MoveCamera", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 176, "y": 56, "w": 14, "h": 14 } }] }, + { "name": "event_PulseCamera", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 120, "y": 42, "w": 14, "h": 14 } }] }, + { "name": "event_TextExplosion", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 134, "y": 28, "w": 14, "h": 14 } }] }, + { "name": "event_ShowDialogue", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 148, "y": 28, "w": 14, "h": 14 } }] }, + { "name": "event_ShowStatusSign", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 162, "y": 28, "w": 14, "h": 14 } }] }, + { "name": "event_AdvanceText", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 218, "y": 0, "w": 7, "h": 14 } }] }, + { "name": "event_TintRows", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 92, "y": 0, "w": 14, "h": 14 } }] }, + { "name": "event_Tint", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 106, "y": 0, "w": 14, "h": 14 } }] }, + { "name": "event_TagAction", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 162, "y": 14, "w": 14, "h": 14 } }] }, + { "name": "event_Stutter", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 78, "y": 42, "w": 14, "h": 14 } }] }, + { "name": "event_ShowHands", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 78, "y": 70, "w": 14, "h": 14 } }] }, + { "name": "event_ShakeScreen", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 204, "y": 14, "w": 14, "h": 14 } }] }, + { "name": "event_SetVisible", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 106, "y": 42, "w": 14, "h": 14 } }] }, + { "name": "event_SetRoomPerspective", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 64, "y": 42, "w": 14, "h": 14 } }] }, + { "name": "event_SetRoomContentMode", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 120, "y": 70, "w": 14, "h": 14 } }] }, + { "name": "event_SetPlayStyle", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 148, "y": 14, "w": 14, "h": 14 } }] }, + { "name": "event_SetHandOwner", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 134, "y": 14, "w": 14, "h": 14 } }] }, + { "name": "event_PaintHands", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 120, "y": 1, "w": 14, "h": 14 } }] }, + { "name": "event_PlayExpression", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 106, "y": 84, "w": 14, "h": 14 } }] }, + { "name": "event_MoveRoom", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 42, "w": 14, "h": 14 } }] }, + { "name": "event_MaskRoom", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 78, "y": 28, "w": 14, "h": 14 } }] }, + { "name": "event_MoveRow", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 204, "y": 70, "w": 14, "h": 14 } }] }, + { "name": "event_InvertColors", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 218, "y": 14, "w": 14, "h": 14 } }] }, + { "name": "event_HideRow", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 92, "y": 42, "w": 14, "h": 14 } }] }, + { "name": "event_FlipScreen_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 218, "y": 70, "w": 14, "h": 14 } }] }, + { "name": "event_FinishLevel", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 190, "y": 28, "w": 14, "h": 14 } }] }, + { "name": "event_ChangePlayersRows", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 176, "y": 28, "w": 14, "h": 14 } }] }, + { "name": "event_BassDrop", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 190, "y": 14, "w": 14, "h": 14 } }] }, + { "name": "event_CallCustomMethod", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 176, "y": 14, "w": 14, "h": 14 } }] }, + { "name": "event_PlayAnimation", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 92, "y": 84, "w": 14, "h": 14 } }] }, + { "name": "event_Move", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 176, "y": 70, "w": 14, "h": 14 } }] }, + { "name": "event_FadeRoom", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 64, "y": 28, "w": 14, "h": 14 } }] }, + { "name": "event_Unknown", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 64, "y": 70, "w": 14, "h": 14 } }] }, + { "name": "themes", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 15, "y": 39, "w": 7, "h": 13 } }] }, + { "name": "event_beat_pulse", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 98, "w": 3, "h": 14 }, "pivot": {"x": 1, "y": 0 } }] }, + { "name": "event_beat_hit", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 53, "y": 98, "w": 5, "h": 14 }, "pivot": {"x": 2, "y": 0 } }] }, + { "name": "event_beat_x", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 84, "y": 98, "w": 9, "h": 7 } }] }, + { "name": "char_0021", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 54, "y": 112, "w": 2, "h": 8 } }] }, + { "name": "char_0022", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 56, "y": 112, "w": 4, "h": 8 } }] }, + { "name": "char_0023", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 60, "y": 112, "w": 6, "h": 8 } }] }, + { "name": "char_0024", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 66, "y": 112, "w": 5, "h": 8 } }] }, + { "name": "char_0025", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 71, "y": 112, "w": 6, "h": 8 } }] }, + { "name": "char_0026", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 77, "y": 112, "w": 6, "h": 8 } }] }, + { "name": "char_0027", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 83, "y": 112, "w": 2, "h": 8 } }] }, + { "name": "char_0028", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 85, "y": 112, "w": 3, "h": 8 } }] }, + { "name": "char_0029", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 88, "y": 112, "w": 3, "h": 8 } }] }, + { "name": "char_002a", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 91, "y": 112, "w": 4, "h": 8 } }] }, + { "name": "char_002b", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 95, "y": 112, "w": 4, "h": 8 } }] }, + { "name": "char_002c", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 99, "y": 112, "w": 3, "h": 8 } }] }, + { "name": "char_002d", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 102, "y": 112, "w": 4, "h": 8 } }] }, + { "name": "char_002e", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 106, "y": 112, "w": 2, "h": 8 } }] }, + { "name": "char_002f", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 108, "y": 112, "w": 6, "h": 8 } }] }, + { "name": "char_0030", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 120, "w": 5, "h": 8 } }] }, + { "name": "char_0031", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 55, "y": 120, "w": 3, "h": 8 } }] }, + { "name": "char_0032", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 58, "y": 120, "w": 5, "h": 8 } }] }, + { "name": "char_0033", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 63, "y": 120, "w": 5, "h": 8 } }] }, + { "name": "char_0034", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 68, "y": 120, "w": 5, "h": 8 } }] }, + { "name": "char_0035", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 73, "y": 120, "w": 5, "h": 8 } }] }, + { "name": "char_0036", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 78, "y": 120, "w": 5, "h": 8 } }] }, + { "name": "char_0037", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 83, "y": 120, "w": 5, "h": 8 } }] }, + { "name": "char_0038", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 88, "y": 120, "w": 5, "h": 8 } }] }, + { "name": "char_0039", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 93, "y": 120, "w": 5, "h": 8 } }] }, + { "name": "char_003a", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 98, "y": 120, "w": 2, "h": 8 } }] }, + { "name": "char_003b", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 100, "y": 120, "w": 2, "h": 8 } }] }, + { "name": "char_003c", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 102, "y": 120, "w": 4, "h": 8 } }] }, + { "name": "char_003d", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 106, "y": 120, "w": 4, "h": 8 } }] }, + { "name": "char_003e", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 110, "y": 120, "w": 4, "h": 8 } }] }, + { "name": "char_003f", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 114, "y": 120, "w": 5, "h": 8 } }] }, + { "name": "char_0040", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 128, "w": 6, "h": 8 } }] }, + { "name": "char_0041", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 56, "y": 128, "w": 5, "h": 8 } }] }, + { "name": "char_0042", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 61, "y": 128, "w": 5, "h": 8 } }] }, + { "name": "char_0043", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 66, "y": 128, "w": 4, "h": 8 } }] }, + { "name": "char_0044", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 70, "y": 128, "w": 5, "h": 8 } }] }, + { "name": "char_0045", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 75, "y": 128, "w": 4, "h": 8 } }] }, + { "name": "char_0046", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 79, "y": 128, "w": 4, "h": 8 } }] }, + { "name": "char_0047", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 83, "y": 128, "w": 5, "h": 8 } }] }, + { "name": "char_0048", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 88, "y": 128, "w": 5, "h": 8 } }] }, + { "name": "char_0049", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 93, "y": 128, "w": 4, "h": 8 } }] }, + { "name": "char_004a", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 97, "y": 128, "w": 5, "h": 8 } }] }, + { "name": "char_004b", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 102, "y": 128, "w": 5, "h": 8 } }] }, + { "name": "char_004c", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 107, "y": 128, "w": 4, "h": 8 } }] }, + { "name": "char_004d", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 111, "y": 128, "w": 6, "h": 8 } }] }, + { "name": "char_004e", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 117, "y": 128, "w": 5, "h": 8 } }] }, + { "name": "char_004f", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 122, "y": 128, "w": 5, "h": 8 } }] }, + { "name": "char_0050", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 136, "w": 5, "h": 8 } }] }, + { "name": "char_0051", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 55, "y": 136, "w": 5, "h": 8 } }] }, + { "name": "char_0052", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 60, "y": 136, "w": 5, "h": 8 } }] }, + { "name": "char_0053", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 65, "y": 136, "w": 5, "h": 8 } }] }, + { "name": "char_0054", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 70, "y": 136, "w": 4, "h": 8 } }] }, + { "name": "char_0055", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 74, "y": 136, "w": 5, "h": 8 } }] }, + { "name": "char_0056", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 79, "y": 136, "w": 5, "h": 8 } }] }, + { "name": "char_0057", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 84, "y": 136, "w": 6, "h": 8 } }] }, + { "name": "char_0058", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 90, "y": 136, "w": 5, "h": 8 } }] }, + { "name": "char_0059", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 95, "y": 136, "w": 5, "h": 8 } }] }, + { "name": "char_005a", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 100, "y": 136, "w": 4, "h": 8 } }] }, + { "name": "char_005b", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 104, "y": 136, "w": 3, "h": 8 } }] }, + { "name": "char_005c", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 107, "y": 136, "w": 6, "h": 8 } }] }, + { "name": "char_005d", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 113, "y": 136, "w": 3, "h": 8 } }] }, + { "name": "char_005e", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 116, "y": 136, "w": 4, "h": 8 } }] }, + { "name": "char_005f", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 120, "y": 136, "w": 5, "h": 8 } }] }, + { "name": "char_0060", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 144, "w": 3, "h": 8 } }] }, + { "name": "char_0061", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 53, "y": 144, "w": 5, "h": 8 } }] }, + { "name": "char_0062", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 58, "y": 144, "w": 5, "h": 8 } }] }, + { "name": "char_0063", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 63, "y": 144, "w": 4, "h": 8 } }] }, + { "name": "char_0064", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 67, "y": 144, "w": 5, "h": 8 } }] }, + { "name": "char_0065", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 72, "y": 144, "w": 5, "h": 8 } }] }, + { "name": "char_0066", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 77, "y": 144, "w": 4, "h": 8 } }] }, + { "name": "char_0067", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 81, "y": 144, "w": 5, "h": 8 } }] }, + { "name": "char_0068", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 86, "y": 144, "w": 5, "h": 8 } }] }, + { "name": "char_0069", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 91, "y": 144, "w": 2, "h": 8 } }] }, + { "name": "char_006a", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 93, "y": 144, "w": 3, "h": 8 } }] }, + { "name": "char_006b", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 96, "y": 144, "w": 5, "h": 8 } }] }, + { "name": "char_006c", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 101, "y": 144, "w": 2, "h": 8 } }] }, + { "name": "char_006d", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 103, "y": 144, "w": 6, "h": 8 } }] }, + { "name": "char_006e", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 109, "y": 144, "w": 5, "h": 8 } }] }, + { "name": "char_006f", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 114, "y": 144, "w": 5, "h": 8 } }] }, + { "name": "char_0070", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 152, "w": 5, "h": 8 } }] }, + { "name": "char_0071", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 55, "y": 152, "w": 5, "h": 8 } }] }, + { "name": "char_0072", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 60, "y": 152, "w": 4, "h": 8 } }] }, + { "name": "char_0073", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 64, "y": 152, "w": 5, "h": 8 } }] }, + { "name": "char_0074", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 69, "y": 152, "w": 4, "h": 8 } }] }, + { "name": "char_0075", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 73, "y": 152, "w": 5, "h": 8 } }] }, + { "name": "char_0076", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 78, "y": 152, "w": 5, "h": 8 } }] }, + { "name": "char_0077", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 83, "y": 152, "w": 6, "h": 8 } }] }, + { "name": "char_0078", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 89, "y": 152, "w": 4, "h": 8 } }] }, + { "name": "char_0079", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 93, "y": 152, "w": 5, "h": 8 } }] }, + { "name": "char_007a", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 98, "y": 152, "w": 5, "h": 8 } }] }, + { "name": "char_007b", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 103, "y": 152, "w": 4, "h": 8 } }] }, + { "name": "char_007c", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 107, "y": 152, "w": 2, "h": 8 } }] }, + { "name": "char_007d", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 109, "y": 152, "w": 4, "h": 8 } }] }, + { "name": "char_007e", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 113, "y": 152, "w": 5, "h": 8 } }] }, + { "name": "char_0020", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 112, "w": 4, "h": 8 } }] }, + { "name": "event_tag", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 239, "y": 0, "w": 6, "h": 6 } }] }, + { "name": "event_tag_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 239, "y": 6, "w": 6, "h": 6 } }] }, + { "name": "event_beat_loop", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 75, "y": 98, "w": 9, "h": 8 }, "pivot": {"x": 5, "y": 4 } }] }, + { "name": "event_beat_cross", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 92, "y": 108, "w": 3, "h": 3 }, "pivot": {"x": 1, "y": -6 } }] }, + { "name": "event_beat_hit_burn", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 63, "y": 98, "w": 7, "h": 14 }, "pivot": {"x": 3, "y": 0 } }] }, + { "name": "event_beat_synco", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 93, "y": 98, "w": 9, "h": 7 } }] }, + { "name": "event_beat_hit_freeze", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 58, "y": 98, "w": 5, "h": 14 }, "pivot": {"x": 2, "y": 0 } }] }, + { "name": "event_beat_skip", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 70, "y": 98, "w": 5, "h": 14 } }] }, + { "name": "event_beat_area", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 95, "y": 105, "w": 3, "h": 4 }, "center": {"x": 0, "y": 1, "w": 2, "h": 2 } }] }, + { "name": "event_beat_line", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 102, "y": 98, "w": 9, "h": 7 } }] }, + { "name": "event_CustomFlash_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 204, "y": 56, "w": 14, "h": 14 } }] }, + { "name": "event_FlipScreen_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 232, "y": 56, "w": 14, "h": 14 } }] }, + { "name": "event_FlipScreen", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 218, "y": 56, "w": 14, "h": 14 } }] }, + { "name": "event_FlipScreen_2", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 232, "y": 70, "w": 14, "h": 14 } }] }, + { "name": "event_FloatingText_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 204, "y": 28, "w": 14, "h": 14 } }] }, + { "name": "event_FloatingText_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 218, "y": 28, "w": 14, "h": 14 } }] }, + { "name": "event_PaintHands_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 120, "y": 14, "w": 14, "h": 14 } }] }, + { "name": "event_PaintHands_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 120, "y": 28, "w": 14, "h": 14 } }] }, + { "name": "event_SetBackgroundColor_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 134, "y": 56, "w": 14, "h": 14 } }] }, + { "name": "event_SetBackgroundColor_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 137, "y": 60, "w": 8, "h": 6 }, "pivot": {"x": -3, "y": -4 } }] }, + { "name": "event_SetForeground_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 137, "y": 74, "w": 7, "h": 5 }, "pivot": {"x": -3, "y": -4 } }] }, + { "name": "event_Tint_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 106, "y": 14, "w": 14, "h": 14 } }] }, + { "name": "event_Tint_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 106, "y": 28, "w": 14, "h": 14 } }] }, + { "name": "event_TintRows_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 92, "y": 14, "w": 14, "h": 14 } }] }, + { "name": "event_TintRows_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 92, "y": 28, "w": 14, "h": 14 } }] }, + { "name": "event_ShowRooms_1", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 162, "y": 98, "w": 28, "h": 28 } }] }, + { "name": "event_ShowRooms_0", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 134, "y": 98, "w": 28, "h": 28 } }] }, + { "name": "event_ChangeCharacter", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 120, "y": 84, "w": 14, "h": 14 } }] }, + { "name": "event_SetRowXs", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 50, "y": 14, "w": 28, "h": 14 } }] }, + { "name": "event_outline", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 75, "y": 106, "w": 5, "h": 5 }, "center": {"x": 2, "y": 2, "w": 1, "h": 1 } }] }, + { "name": "event_back", "color": "#0000ffff", "keys": [{ "frame": 0, "bounds": {"x": 92, "y": 105, "w": 3, "h": 3 }, "center": {"x": 1, "y": 1, "w": 1, "h": 1 } }] } + ] + } +} diff --git a/rdviewAssets/assets.png b/rdviewAssets/assets.png new file mode 100644 index 0000000..7b9cbb9 Binary files /dev/null and b/rdviewAssets/assets.png differ diff --git a/script/rdtkview.js b/script/rdtkview.js new file mode 100644 index 0000000..7f6a805 --- /dev/null +++ b/script/rdtkview.js @@ -0,0 +1,1560 @@ +// 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; + 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) { + if (typeof r === "string" && g === void 0 && b === void 0 && a === void 0) { + r = r.trim(); + if (r[0] === "#") r = r.slice(1); + if (r.length === 8) { + return new _Color(r.slice(6, 8) + r.slice(0, 6)); + } else if (r.length === 6) return new _Color(r); + else if (r.length === 4) { + return new _Color(r[3] + r[3] + r.slice(0, 3).split("").map((i) => i + i).join("")); + } else if (r.length === 3) { + return new _Color("FF" + r.split("").map((i) => i + i).join("")); + } else return new _Color(); + } else if (typeof r === "number" && typeof g === "number" && typeof b === "number" && typeof a === "number") { + return new _Color(a, r, g, b); + } else { + return new _Color(); + } + } + 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; + get isNinePatch() { + return !this.center.isEmpty; + } +}; + +// assetManager.ts +var assetFilePath = "assets.png"; +var slicesFilePath = "assets.bin"; +var directoryPath = "./rdviewAssets"; +var assetSize = new Size(210, 160); +var assetUrl = directoryPath + "/" + assetFilePath; +async function readFromStream(stream) { + 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); + } + sliceInfos.set(key, sliceInfo); + } + return sliceInfos; +} +var assetLoaded = false; +var slices = await readFromStream(new DataView(await (await fetch(directoryPath + "/" + slicesFilePath)).arrayBuffer())).finally(() => { + assetLoaded = true; +}); + +// rdtkview.ts +var lineHeight = 6; +var charHeight = 8; +var iconSize = 14; +var IconStyle = class { + enabled = true; + active = false; + hover = false; + 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 createLayerFromBackground(key, bound, color, style, backgroundRepeat = false) { + const info = slices.get(key); + if (!info) return []; + if (info?.isNinePatch) { + const rectBound = bound ?? new Rect(0, 0, info.bounds.width, info.bounds.height); + const center = info.center; + 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); + } + } + } + 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 + ]; + } +} +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 * 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); + 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 measureRDFontText(text) { + let len = 0; + for (let i = 0; i < text.length; i++) { + const char = text.charAt(i); + if (char === "\n") { + len = 0; + } else { + const charCode = char.charCodeAt(0); + const charKey = `char_${charCode.toString(16).padStart(4, "0")}`; + const charInfo = slices.get(charKey); + len += charInfo?.bounds.width ?? 0; + } + } + return len; +} +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); + 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); + if (charInfo) { + const charLayer = createLayerFromBackground(charKey, new Point(start.x, start.y), color, style); + start.x += charInfo.bounds.width * style.scale; + 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 = 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 + ]; +} +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.style.opacity = "0"; + layer.onStateChange = (style) => { + if (style.hover) { + layer.style.opacity = "1.0"; + } else { + layer.style.opacity = "0"; + } + }; +} +function createHintLayer(hint, width, color) { + const hintLayer = document.createElement("div"); + hintLayer.style.position = "absolute"; + hintLayer.style.left = `${width}px`; + hintLayer.style.width = `max-content`; + hintLayer.innerHTML = hint; + hintLayer.style.fontSize = `${18}px`; + hintLayer.style.fontFamily = "d9, Arial, sans-serif"; + hintLayer.style.color = color.toRgbaString(); + hintLayer.style.fontWeight = "bold"; + hintLayer.style.textShadow = ` + 2px 2px 0 black, + 2px 0px 0 black, + 2px -2px 0 black, + 0px -2px 0 black, + -2px -2px 0 black, + -2px 0px 0 black, + -2px 2px 0 black, + 0px 2px 0 black + `; + hintLayer.style.pointerEvents = "none"; + hintLayer.style.opacity = "0"; + hintLayer.style.zIndex = "10"; + hintLayer.onStateChange = (style) => { + if (style.hover) { + hintLayer.style.opacity = "1.0"; + } else { + hintLayer.style.opacity = "0"; + } + }; + return hintLayer; +} +function createElementEvent(obj, style) { + style = { + ...new IconStyle(), + ...style + }; + 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 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 evinfo = EventInfos[evttype] ?? EventInfos[EventType.Unknown]; + 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 evbskip = "event_beat_skip"; + const beatColor = new Color(4284539717); + let iconWidth = iconSize; + const element = document.createElement("div"); + element.eventStyle = { + ...style + }; + const layersToAdd = []; + 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 prexs = obj.preXs ?? { + syncoBeat: -1, + syncoSwing: 0 + }; + const length = obj.length ?? 7; + 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 = 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 = 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: + { + 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 skip = obj.skipshot ?? 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 = hold ? iconSize * (interval - tick - delay) : 0; + 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 : mode === "Burnshot" ? hitb : null; + for (let l = 0; l <= loop; l++) { + for (let i = 0; i < subdiv; i++) { + 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 = createLayerFromBackground(hit, new Point(iconSize * (l * interval + delay + tick + i * tick / subdiv) - 1, 0), null, style); + pulses.push(...hitLayer2); + } + 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 = 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 ? 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`; + layersToAdd.push(...holdLayer); + layersToAdd.push(...backLayers2); + layersToAdd.push(...hitLayer); + layersToAdd.push(textLayer); + } + break; + case EventType.Comment: + { + 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(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 ? 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": + 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, null); + textLayer.style.left = `${1.5 * style.scale}px`; + textLayer.style.top = `${10 * style.scale}px`; + layersToAdd.push(...holdLayer); + layersToAdd.push(...backLayers2); + layersToAdd.push(...hitLayer); + layersToAdd.push(textLayer); + } + break; + case EventType.ReorderRooms: + case EventType.ReorderWindows: + { + const backLayers2 = createBackLayer(slcinfo.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 = createLayerFromBackground(`${key}_${order[i]}`, new Point(0, i * iconSize), null, style); + orderLayers.push(...orderLayer); + } + } + 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] + ]; + let lw = measureRDFontText(stringToJoin[0]); + const sw = measureRDFontText(" "); + const backLayers2 = createBackLayer(new Size(len * iconSize, iconSize), colorOf(obj.tab ?? evinfo.defaultTab), style); + const wordLayers = []; + for (let i = 1; i < stringToJoin.length; i++) { + const part = stringToJoin[i]; + const w = measureRDFontText(part); + if (lw + sw + w > len * iconSize * style.scale) { + lw = w; + stringToDraw.push(part); + } else { + lw += sw + w; + stringToDraw[stringToDraw.length - 1] += " " + part; + } + } + const c = Math.min(stringToDraw.length, 3); + let top = iconSize / 2 - charHeight * c / 4 + 1; + for (let i = 0; i < c; i++) { + const line = stringToDraw[i]; + const p = new Point((len * iconSize - measureRDFontText(line) / 2) / 2, top + (i * charHeight + lineHeight) / 2); + const wordLayer = createRDFontLayer(line, { + ...style, + scale: style.scale / 2 + }, null); + wordLayer.style.left = `${p.x * style.scale}px`; + wordLayer.style.top = `${p.y * style.scale}px`; + wordLayers.push(wordLayer); + } + layersToAdd.push(...backLayers2); + layersToAdd.push(...wordLayers); + } + break; + case EventType.SetRowXs: + { + const syncoBeat = obj.syncoBeat ?? -1; + 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(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 = createLayerFromBackground(p === "x" ? beatx : beatline, new Rect(left, top, width, iconBounds.height * s), null, style); + patternLayers.push(...beatxLayer); + left += width; + } + 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: + { + 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 = 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); + } + layersToAdd.push(...backLayers2); + layersToAdd.push(...roomLayers); + } + break; + default: + const backLayers = createBackLayer(slcinfo.bounds.size, colorOf(obj.tab ?? evinfo.defaultTab), style); + layersToAdd.push(...backLayers); + switch (evttype) { + case EventType.CustomFlash: + 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 = createLayerFromBackground(flip === 0 ? `${key}_0` : `${key}_${flip - 1}`, null, null, style); + layersToAdd.push(...iconLayer2); + } + break; + case EventType.FloatingText: + { + 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; + let height = (obj.scale ? obj.scale[1] ?? 0 : 100) / 100; + const pleft = (obj.pivot ? obj.pivot[0] ?? 0 : 50) / 100; + const ptop = (obj.pivot ? obj.pivot[1] ?? 0 : 50) / 100; + if (width === 0 || height === 0) break; + const uniform = Math.sqrt(width * width + height * height); + width /= uniform; + height /= uniform; + 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: + case EventType.Tint: + case EventType.TintRows: + { + const border = obj.border; + 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 = createLayerFromBackground(key, null, null, style); + const images = obj.image ?? []; + const imagePath = images.length > 0 ? images[0] : ""; + const contentInfo = slices.get(`${key}_1`); + 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 = createLayerFromBackground(key, null, null, style); + const cpbLayer = createRDFontLayer(cpb > 9 ? "-" : cpb.toString(), 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`; + layersToAdd.push(...iconLayer2); + layersToAdd.push(cpbLayer); + layersToAdd.push(bLayer); + } + break; + case EventType.SetForeground: + { + 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 ? 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 = createLayerFromBackground(hasType ? key : "event_Unknown", null, null, style); + layersToAdd.push(...layer); + break; + } + break; + } + if (evinfo.isDurationEvent) { + const duration = obj[evinfo.durationKey] ?? 0; + const durWidth = iconSize * duration; + 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); + const roomDisabled = new Color(4284177243); + if (evinfo.isRoomEvent) { + const roomLayers = []; + for (let i = 0; i < 4; i++) { + 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); + } + }); + 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 + }; + 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/rdview.js b/script/rdview.js index 90f77ca..fda7705 100644 --- a/script/rdview.js +++ b/script/rdview.js @@ -849,6 +849,9 @@ function ReadProperties(reader, event, pairs) { if (value = FindValue(pairs, "loop")) { event.BeatStyle.Loop = parseInt(value.Value); } + if (value = FindValue(pairs, "hold")) { + event.BeatStyle.Hold = parseFloat(value.Value); + } break; default: break; @@ -938,7 +941,7 @@ function ConstructDivObject(obj) { result += (((_a = obj.BeatStyle) === null || _a === void 0 ? void 0 : _a.RowXs[i]) === 'x') ? `
` : `
`; } return result; - }], [(obj.BeatType === BeatsSpecial.AddClassicBeat || obj.BeatType === BeatsSpecial.AddFreeTimeBeat || obj.BeatType === BeatsSpecial.PulseFreeTimeBeat) && ((_s = (_r = obj.BeatStyle) === null || _r === void 0 ? void 0 : _r.Hold) !== null && _s !== void 0 ? _s : 0) > 0, `holdbeat`, () => ''], [obj.BeatType === BeatsSpecial.AddOneshotBeat && obj.BeatStyle !== undefined && obj.BeatStyle.OneshotBeatSubType.includes(RDOneshotBeatSubType.Skipshot), `skipshot`, () => ''])}`; + }], [(obj.BeatType === BeatsSpecial.AddClassicBeat || obj.BeatType === BeatsSpecial.AddFreeTimeBeat || obj.BeatType === BeatsSpecial.PulseFreeTimeBeat || obj.BeatType === BeatsSpecial.AddOneshotBeat) && ((_s = (_r = obj.BeatStyle) === null || _r === void 0 ? void 0 : _r.Hold) !== null && _s !== void 0 ? _s : 0) > 0, `holdbeat`, () => ''], [obj.BeatType === BeatsSpecial.AddOneshotBeat && obj.BeatStyle !== undefined && obj.BeatStyle.OneshotBeatSubType.includes(RDOneshotBeatSubType.Skipshot), `skipshot`, () => ''])}`; } else if (obj instanceof RDGroup) { return `
0, `holdbeat`, () => ''], + [(obj.BeatType === BeatsSpecial.AddClassicBeat || obj.BeatType === BeatsSpecial.AddFreeTimeBeat || obj.BeatType === BeatsSpecial.PulseFreeTimeBeat || obj.BeatType === BeatsSpecial.AddOneshotBeat) && (obj.BeatStyle?.Hold ?? 0) > 0, `holdbeat`, () => ''], [obj.BeatType === BeatsSpecial.AddOneshotBeat && obj.BeatStyle !== undefined && obj.BeatStyle.OneshotBeatSubType.includes(RDOneshotBeatSubType.Skipshot), `skipshot`, () => ''], )}
`; } diff --git a/script/special.js b/script/special.js index 930c5cf..5e8ce8d 100644 --- a/script/special.js +++ b/script/special.js @@ -1,3 +1,5 @@ +import { createElementEvent } from "./rdtkview.js"; + let curx = 0; let cury = 0; let rowx; @@ -21,7 +23,7 @@ let positions = { "r5": { "y": 78, "name": "二轨时的第二轨/四轨时的第二轨" }, "r6": { "y": 57, "name": "三轨时的第一轨" }, "r7": { "y": 36, "name": "四轨时的第一轨" }, -} +}; function themePosition() { let theme_positions = document.getElementById("theme-positions"); @@ -61,45 +63,74 @@ function themePosition() { rowx = null; columny = null; for (let key in positions) { - if (positions[key].x !== null && Math.abs(x - positions[key].x) < 5) + if ( + positions[key].x !== null && Math.abs(x - positions[key].x) < 5 + ) { rowx = positions[key].x; - if (positions[key].y !== null && Math.abs(y - positions[key].y) < 5) + } + if ( + positions[key].y !== null && Math.abs(y - positions[key].y) < 5 + ) { columny = positions[key].y; + } } if (rowx) { - perx.innerText = (rowx / 3.52).toFixed(2) + "%" - perx.classList.add("c") - pxx.innerText = rowx + "px" - pxx.classList.add("c") - } - else { - perx.innerText = x_percent.toFixed(2) + "%" - perx.classList.remove("c") - pxx.innerText = x + "px" - pxx.classList.remove("c") + perx.innerText = (rowx / 3.52).toFixed(2) + "%"; + perx.classList.add("c"); + pxx.innerText = rowx + "px"; + pxx.classList.add("c"); + } else { + perx.innerText = x_percent.toFixed(2) + "%"; + perx.classList.remove("c"); + pxx.innerText = x + "px"; + pxx.classList.remove("c"); } if (columny) { - pery.innerText = (100 - columny / 1.98).toFixed(2) + "%" - pery.classList.add("c") - pxy.innerText = 198 - columny + "px" - pxy.classList.add("c") - } - else { - pery.innerText = (100 - y_percent).toFixed(2) + "%" - pery.classList.remove("c") - pxy.innerText = 198 - y + "px" - pxy.classList.remove("c") + pery.innerText = (100 - columny / 1.98).toFixed(2) + "%"; + pery.classList.add("c"); + pxy.innerText = 198 - columny + "px"; + pxy.classList.add("c"); + } else { + pery.innerText = (100 - y_percent).toFixed(2) + "%"; + pery.classList.remove("c"); + pxy.innerText = 198 - y + "px"; + pxy.classList.remove("c"); } infobox.style.right = "calc(" + (100 - x_percent) + "% + 10px)"; - infobox.style.top = "calc(" + (y_percent) + "% + 10px)"; - selectbox.style.left = rowx ? (rowx / 3.52 - 3.41) + "%" : columny ? "0" : "calc(" + x_percent + "% - 3px"; - selectbox.style.bottom = columny ? (100 - columny / 1.98 - 5.305) + "%" : rowx ? "0" : "calc(" + (100 - y_percent) + "% - 3px)"; + infobox.style.top = "calc(" + y_percent + "% + 10px)"; + selectbox.style.left = rowx + ? (rowx / 3.52 - 3.41) + "%" + : columny + ? "0" + : "calc(" + x_percent + "% - 3px"; + selectbox.style.bottom = columny + ? (100 - columny / 1.98 - 5.305) + "%" + : rowx + ? "0" + : "calc(" + (100 - y_percent) + "% - 3px)"; selectbox.style.width = rowx ? "6.82%" : columny ? "100%" : "6px"; selectbox.style.height = columny ? "10.61%" : rowx ? "100%" : "6px"; - let rowname = rowx ? positions[Object.keys(positions).find(key => positions[key].x === rowx)].name : ""; - let columnname = columny ? positions[Object.keys(positions).find(key => positions[key].y === columny)].name : ""; - theme_positions.querySelector(".other").innerText = rowname && columnname ? columnname + "上的" + rowname : rowname ? rowname : columnname ? columnname : ""; + let rowname = rowx + ? positions[ + Object.keys(positions).find((key) => positions[key].x === rowx) + ].name + : ""; + let columnname = columny + ? positions[ + Object.keys(positions).find((key) => + positions[key].y === columny + ) + ].name + : ""; + theme_positions.querySelector(".other").innerText = + rowname && columnname + ? columnname + "上的" + rowname + : rowname + ? rowname + : columnname + ? columnname + : ""; }); theme_positions.addEventListener("mouseleave", function (event) { perx.innerText = "100%"; @@ -112,13 +143,12 @@ function themePosition() { selectbox.style.bottom = "50%"; selectbox.style.width = "0"; selectbox.style.height = "0"; - perx.classList.remove("c") - pery.classList.remove("c") - pxx.classList.remove("c") - pxy.classList.remove("c") + perx.classList.remove("c"); + pery.classList.remove("c"); + pxx.classList.remove("c"); + pxy.classList.remove("c"); other.innerText = ""; }); - } function rdview() { @@ -129,21 +159,25 @@ function rdview() { let number = rdview.querySelector(".number"); const textareaStyles = window.getComputedStyle(textarea); [ - 'fontFamily', 'fontSize', 'fontWeight', - 'letterSpacing', 'lineHeight', 'padding', - ].forEach(property => { + "fontFamily", + "fontSize", + "fontWeight", + "letterSpacing", + "lineHeight", + "padding", + ].forEach((property) => { number.style[property] = textareaStyles[property]; }); - const canvas = document.createElement('canvas'); - const context = canvas.getContext('2d'); + const canvas = document.createElement("canvas"); + const context = canvas.getContext("2d"); const font = `${textareaStyles.fontSize} ${textareaStyles.fontFamily}`; context.font = font; function calcStringLines(sentence, width) { if (!width) return 0; - const words = sentence.split(''); + const words = sentence.split(""); let lineCount = 0; - let currentLine = ''; + let currentLine = ""; for (let i = 0; i < words.length; i++) { const wordWidth = context.measureText(words[i]).width; const lineWidth = context.measureText(currentLine).width; @@ -154,18 +188,22 @@ function rdview() { currentLine += words[i]; } } - if (currentLine.trim() !== '') lineCount++; + if (currentLine.trim() !== "") lineCount++; return lineCount; } function calcLines() { - const lines = textarea.value.split('\n'); + const lines = textarea.value.split("\n"); const textareaWidth = textarea.getBoundingClientRect().width; const textareaScrollWidth = textareaWidth - textarea.clientWidth; - const parseNumber = (v) => v.endsWith('px') ? parseInt(v.slice(0, -2), 10) : 0; + const parseNumber = (v) => + v.endsWith("px") ? parseInt(v.slice(0, -2), 10) : 0; const textareaPaddingLeft = parseNumber(textareaStyles.paddingLeft); const textareaPaddingRight = parseNumber(textareaStyles.paddingRight); - const textareaContentWidth = textareaWidth - textareaPaddingLeft - textareaPaddingRight - textareaScrollWidth; - const numLines = lines.map(lineString => calcStringLines(lineString, textareaContentWidth)); + const textareaContentWidth = textareaWidth - textareaPaddingLeft - + textareaPaddingRight - textareaScrollWidth; + const numLines = lines.map((lineString) => + calcStringLines(lineString, textareaContentWidth) + ); let lineNumbers = []; let i = 1; while (numLines.length > 0) { @@ -173,8 +211,8 @@ function rdview() { lineNumbers.push(i); if (numLinesOfSentence > 1) { Array(numLinesOfSentence - 1) - .fill('') - .forEach((_) => lineNumbers.push('')); + .fill("") + .forEach((_) => lineNumbers.push("")); } i++; } @@ -184,24 +222,172 @@ function rdview() { const lines = calcLines(); const lineDoms = Array.from({ length: lines.length, - }, (_, i) => `
${lines[i] || ' '}
`); - number.innerHTML = lineDoms.join(''); + }, (_, i) => `
${lines[i] || " "}
`); + number.innerHTML = lineDoms.join(""); } function initCanvas() { - const lang = textarea.value.split('\n')[0] - const code = textarea.value.split('\n').slice(1).join('\n') - rdcanvas.innerHTML = RDViewRender(lang, code) + const lang = textarea.value.split("\n")[0]; + const code = textarea.value.split("\n").slice(1).join("\n"); + rdcanvas.innerHTML = RDViewRender(lang, code); } - initCanvas() - initLineNumbers() - textarea.addEventListener('input', initLineNumbers); - textarea.addEventListener('input', initCanvas); + initCanvas(); + initLineNumbers(); + textarea.addEventListener("input", initLineNumbers); + textarea.addEventListener("input", initCanvas); } +function rdview2() { + let rdview = document.getElementsByClassName("rdview2")[0]; + if (!rdview) return; + let rdcanvas = rdview.querySelector(".canvas"); + let textarea = rdview.querySelector("textarea.area"); + let number = rdview.querySelector(".number"); + const textareaStyles = window.getComputedStyle(textarea); + [ + "fontFamily", + "fontSize", + "fontWeight", + "letterSpacing", + "lineHeight", + "padding", + ].forEach((property) => { + number.style[property] = textareaStyles[property]; + }); + const canvas = document.createElement("canvas"); + const context = canvas.getContext("2d"); + const font = `${textareaStyles.fontSize} ${textareaStyles.fontFamily}`; + context.font = font; + function calcStringLines(sentence, width) { + if (!width) return 0; + const words = sentence.split(""); + let lineCount = 0; + + let currentLine = ""; + for (let i = 0; i < words.length; i++) { + const wordWidth = context.measureText(words[i]).width; + const lineWidth = context.measureText(currentLine).width; + if (lineWidth + wordWidth > width) { + lineCount++; + currentLine = words[i]; + } else { + currentLine += words[i]; + } + } + if (currentLine.trim() !== "") lineCount++; + return lineCount; + } + function calcLines() { + const lines = textarea.value.split("\n"); + const textareaWidth = textarea.getBoundingClientRect().width; + const textareaScrollWidth = textareaWidth - textarea.clientWidth; + const parseNumber = (v) => + v.endsWith("px") ? parseInt(v.slice(0, -2), 10) : 0; + const textareaPaddingLeft = parseNumber(textareaStyles.paddingLeft); + const textareaPaddingRight = parseNumber(textareaStyles.paddingRight); + const textareaContentWidth = textareaWidth - textareaPaddingLeft - + textareaPaddingRight - textareaScrollWidth; + const numLines = lines.map((lineString) => + calcStringLines(lineString, textareaContentWidth) + ); + let lineNumbers = []; + let i = 1; + while (numLines.length > 0) { + const numLinesOfSentence = numLines.shift(); + lineNumbers.push(i); + if (numLinesOfSentence > 1) { + Array(numLinesOfSentence - 1) + .fill("") + .forEach((_) => lineNumbers.push("")); + } + i++; + } + return lineNumbers; + } + function initLineNumbers() { + const lines = calcLines(); + const lineDoms = Array.from({ + length: lines.length, + }, (_, i) => `
${lines[i] || " "}
`); + number.innerHTML = lineDoms.join(""); + } + function initCanvas() { + let objs = []; + try { + objs = JSON.parse(`[${textarea.value}]`); + rdcanvas.innerHTML = ""; + } catch (e) { + rdcanvas.innerHTML = + `
JSON解析错误:${e.message}
`; + return; + } + 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).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; + }); + 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(); + textarea.addEventListener("input", initLineNumbers); + textarea.addEventListener("input", initCanvas); +} window.$docsify.plugins = [].concat(window.$docsify.plugins, function (hook) { hook.doneEach(function () { themePosition(); rdview(); + rdview2(); document.documentElement.scrollTop = document.body.scrollTop = 0; }); }); + +import("./docsify.min.js").then(() => { +}); diff --git a/style/assets/beats/subdivision-area.png b/style/assets/beats/subdivision-area.png index 9915732..1bd906b 100644 Binary files a/style/assets/beats/subdivision-area.png and b/style/assets/beats/subdivision-area.png differ diff --git a/style/rdview.css b/style/rdview.css index 1780c62..e8bd658 100644 --- a/style/rdview.css +++ b/style/rdview.css @@ -1146,6 +1146,36 @@ } } + &>.beat:not(:has(.classicbeat)) { + &>div.holdbeat { + position: absolute; + width: calc((var(--hold) * 28 - 2) * 1px); + height: inherit; + background-size: auto 100%; + background-image: url(./assets/beats/hold-area.png); + transform: translate(calc(((var(--tick) + var(--delay) + var(--loop) * var(--interval)) * 28 - 4) * 1px), 0); + z-index: -2; + + &::after { + content: ''; + position: absolute; + width: 2px; + height: 28px; + background-size: auto 100%; + transform: translate(calc((var(--hold) * 28 - 2) * 1px), 0); + background-image: url(./assets/beats/hold-right.png); + } + } + + &:active>div.holdbeat { + background-image: url(./assets/beats/hold-hover-area.png); + + &::after { + background-image: url(./assets/beats/hold-hover-right.png); + } + } + } + &>.beat:has(.row-xs) { width: 56px; height: 28px; @@ -2180,6 +2210,36 @@ } } + &>.beat:not(:has(.classicbeat)) { + &>div.holdbeat { + position: absolute; + width: calc((var(--hold) * 28 - 2) * 1px); + height: inherit; + background-size: auto 100%; + background-image: url(./assets/beats/hold-area.png); + transform: translate(calc(((var(--tick) + var(--delay) + var(--loop) * var(--interval)) * 28 - 4) * 1px), 0); + z-index: -2; + + &::after { + content: ''; + position: absolute; + width: 2px; + height: 28px; + background-size: auto 100%; + transform: translate(calc((var(--hold) * 28 - 2) * 1px), 0); + background-image: url(./assets/beats/hold-right.png); + } + } + + &:active>div.holdbeat { + background-image: url(./assets/beats/hold-hover-area.png); + + &::after { + background-image: url(./assets/beats/hold-hover-right.png); + } + } + } + &>.beat:has(.row-xs) { width: 56px; height: 28px; diff --git a/style/special.css b/style/special.css index a5db117..7ca8cae 100644 --- a/style/special.css +++ b/style/special.css @@ -162,7 +162,7 @@ div.theme-positions>.infobox { .markdown-section:has(div.rdview) {} -div.rdview { +div.rdview, div.rdview2 { & div.canvas { width: 100%; }