From 52474483e81173deeac5f7fd760cf85c49a34bfc Mon Sep 17 00:00:00 2001 From: OLDREDSTONE Date: Mon, 5 Oct 2026 16:32:09 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=B0=86=20rdview=20=E5=BA=95=E5=B1=82?= =?UTF-8?q?=E5=85=A8=E9=87=8F=E6=9B=BF=E6=8D=A2=E4=B8=BA=20rdtkview?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +- index.html | 84 +-- pages/appendix_tools.md | 16 +- pages/audiodesign.md | 36 +- pages/beatpatterndesign.md | 50 +- pages/captions.md | 20 +- pages/holdbeat.md | 40 +- pages/importandexport.md | 6 +- pages/moreclassicbeats.md | 134 ++-- pages/moreoneshotbeats.md | 238 +++---- pages/oneshotbeat.md | 136 ++-- pages/tag.md | 380 +++++----- rdviewAssets/assets.bin | Bin 4326 -> 4482 bytes rdviewAssets/assets.png | Bin 6646 -> 6591 bytes script/config.js | 36 + script/rdtkview.d.ts | 27 + script/rdtkview.js | 1356 +++++++++++++++++++++++++----------- script/rdview-init.js | 5 + script/rdview.js | 895 +++++++++--------------- script/rdview.ts | 909 ++++++++---------------- script/rdview_render.js | 30 + script/special.js | 89 ++- script/tsconfig.json | 4 +- style/rdview-rdtk.css | 66 ++ 24 files changed, 2313 insertions(+), 2250 deletions(-) create mode 100644 script/config.js create mode 100644 script/rdtkview.d.ts create mode 100644 script/rdview-init.js create mode 100644 script/rdview_render.js create mode 100644 style/rdview-rdtk.css diff --git a/README.md b/README.md index 9b866ac..b6d7f4d 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,9 @@ 如果成功安装,那么以下内容的 markdown 预览应当是一个事件栏。 ```rdview 7 5 1 -es.PlaySong 0 0[]; -es.SetCrotchetsPerBar_4 0 1[]; -eb.AddClassicBeat 0 2[tick=6]; +PlaySong 0 0[]; +SetCrotchetsPerBar 0 1[crotchetsPerBar=4]; +AddClassicBeat 0 2[tick=6]; ``` ### RhythmBase.View diff --git a/index.html b/index.html index 5461011..98acbce 100644 --- a/index.html +++ b/index.html @@ -15,93 +15,15 @@ + +
加载中...
- - + diff --git a/pages/appendix_tools.md b/pages/appendix_tools.md index f8fa85f..d29ac56 100644 --- a/pages/appendix_tools.md +++ b/pages/appendix_tools.md @@ -1,11 +1,11 @@ # RDView Playground
diff --git a/pages/audiodesign.md b/pages/audiodesign.md index 0a8dbcb..d383363 100644 --- a/pages/audiodesign.md +++ b/pages/audiodesign.md @@ -39,12 +39,12 @@ **心爆 3** :三次及以上累计的按拍 / 三个及以上重叠的按拍产生的心爆。 ```rdview 3 5 -eb.AddFreeTimeBeat 1 1[pulse=7]; -eb.AddFreeTimeBeat 1 2[pulse=7]; -eb.AddFreeTimeBeat 1 2[pulse=7]; -eb.AddFreeTimeBeat 1 3[pulse=7]; -eb.AddFreeTimeBeat 1 3[pulse=7]; -eb.AddFreeTimeBeat 1 3[pulse=7]; +AddFreeTimeBeat 1 1[pulse=6]; +AddFreeTimeBeat 1 2[pulse=6]; +AddFreeTimeBeat 1 2[pulse=6]; +AddFreeTimeBeat 1 3[pulse=6]; +AddFreeTimeBeat 1 3[pulse=6]; +AddFreeTimeBeat 1 3[pulse=6]; ``` ### 设置心跳音量 @@ -73,19 +73,19 @@ eb.AddFreeTimeBeat 1 3[pulse=7]; ```rdview 4 9 g 1 1{ g 1 0 0 1 #08f{}; - eb.AddFreeTimeBeat [pulse=7]; + AddFreeTimeBeat [pulse=6]; }; g 1.25 3 1.75 1 #08f{ g{}; - eb.AddFreeTimeBeat [pulse=7]; + AddFreeTimeBeat [pulse=6]; }; g 1.5 5 1.5 1 #08f{ g{}; - eb.AddFreeTimeBeat [pulse=7]; + AddFreeTimeBeat [pulse=6]; }; g 1.75 7 1.25 1 #08f{ g{}; - eb.AddFreeTimeBeat [pulse=7]; + AddFreeTimeBeat [pulse=6]; }; ``` @@ -97,35 +97,35 @@ g 1.75 7 1.25 1 #08f{ ```rdview 7 9 g 1 1 0.75 1 #08f{ g 0 0 0.25{}; - eb.AddFreeTimeBeat [pulse=7]; + AddFreeTimeBeat [pulse=6]; }; g 1 3 1.25 1 #08f{ g 0 0 0.75{}; - eb.AddFreeTimeBeat [pulse=7]; + AddFreeTimeBeat [pulse=6]; }; g 1 5 1.25{ g 1.25 0 0 1 #08f{}; - eb.AddFreeTimeBeat [pulse=7]; + AddFreeTimeBeat [pulse=6]; }; g 1 7 1.75 { g 1.75 0 0 1 #08f{}; - eb.AddFreeTimeBeat [pulse=7]; + AddFreeTimeBeat [pulse=6]; }; g 4 1 1 1 #08f{ g 0 0 0.5{}; - eb.AddFreeTimeBeat [pulse=7]; + AddFreeTimeBeat [pulse=6]; }; g 4 3 1.5 1 #08f{ g{}; - eb.AddFreeTimeBeat [pulse=7]; + AddFreeTimeBeat [pulse=6]; }; g 4 5 1.5{ g 1.5 0 0 1 #08f{}; - eb.AddFreeTimeBeat [pulse=7]; + AddFreeTimeBeat [pulse=6]; }; g 4 7 2 { g 2 0 0 1 #08f{}; - eb.AddFreeTimeBeat [pulse=7]; + AddFreeTimeBeat [pulse=6]; }; ``` diff --git a/pages/beatpatterndesign.md b/pages/beatpatterndesign.md index dc36528..d6760bb 100644 --- a/pages/beatpatterndesign.md +++ b/pages/beatpatterndesign.md @@ -47,15 +47,15 @@ 首先,剧情模式出现两次五拍子机制,它们出现的位置在节奏上都是连续附点的,即两个心跳之间的间隔都是1.5拍,这样五拍子的有声拍长也是6,和普通的普通拍子是完全一致的。在这种连续附点的压迫感之下设置五拍,与音乐非常契合。 ```rdview 14 4 -eb.AddClassicBeat 6 1[tick=6]; -eb.SetRowXs 1 2[rowxs=xx----]; -eb.AddFreeTimeBeat 3 2[pulse=1]; -eb.PulseFreeTimeBeat 4.5 2[pulse=9]; -eb.PulseFreeTimeBeat 6 2[pulse=9]; -eb.PulseFreeTimeBeat 7.5 2[pulse=9]; -eb.PulseFreeTimeBeat 9 2[pulse=9]; -eb.PulseFreeTimeBeat 10.5 2[pulse=9]; -eb.PulseFreeTimeBeat 12 2[pulse=9]; +AddClassicBeat 6 1[tick=6]; +SetRowXs 1 2[rowxs=xx----]; +AddFreeTimeBeat 3 2[pulse=1]; +PulseFreeTimeBeat 4.5 2[pulse=9]; +PulseFreeTimeBeat 6 2[pulse=9]; +PulseFreeTimeBeat 7.5 2[pulse=9]; +PulseFreeTimeBeat 9 2[pulse=9]; +PulseFreeTimeBeat 10.5 2[pulse=9]; +PulseFreeTimeBeat 12 2[pulse=9]; ``` 而我们自选音乐时很多时候遇到的情况都是连续五个采音点,但间隔都是1拍,这种情况与其精准采音`xx----`反而不如额外增加一个不存在的采音变成`-x----`或者`-----x`,这样既不损失与音乐的契合,又能把节奏归化简单。 @@ -89,22 +89,22 @@ eb.PulseFreeTimeBeat 12 2[pulse=9]; **三、**每一条轨道的**节奏功能做出严格的区分**,如果场上本身就有多轨,不要给一条轨道设计过多差距太大的节奏类型。同时,非必要尽量不要增添太多轨道。让很多轨道展现出花里胡哨的节奏但却在同一拍按键也会让人感觉很牵强。 ```rdview 14 4 -eb.AddClassicBeat 0 0[tick=1.5,swing=0.25]; -eb.AddClassicBeat 2 0[tick=3,swing=0.5]; -eb.AddClassicBeat 6 0[tick=3,hold=0.5,swing=0.5]; -eb.AddFreeTimeBeat 10 0[pulse=1]; -eb.PulseFreeTimeBeat 10.25[pulse=9]; -eb.PulseFreeTimeBeat 11[pulse=9]; -eb.PulseFreeTimeBeat 11.25[pulse=9]; -eb.PulseFreeTimeBeat 12[pulse=9]; -eb.PulseFreeTimeBeat 12.25[pulse=9]; -eb.PulseFreeTimeBeat 13[pulse=9]; -eb.AddClassicBeat 0 1[tick=6]; -eb.AddClassicBeat 7 1[tick=1.5,swing=0.25]; -eb.AddClassicBeat 9 1[tick=1.5,swing=0.25]; -eb.AddClassicBeat 0 2[tick=3,hold=0.5,swing=0.5]; -eb.AddClassicBeat 4 2[tick=3,swing=0.5]; -eb.AddClassicBeat 7 2[tick=6]; +AddClassicBeat 0 0[tick=1.5,swing=0.25]; +AddClassicBeat 2 0[tick=3,swing=0.5]; +AddClassicBeat 6 0[tick=3,hold=0.5,swing=0.5]; +AddFreeTimeBeat 10 0[pulse=1]; +PulseFreeTimeBeat 10.25[pulse=9]; +PulseFreeTimeBeat 11[pulse=9]; +PulseFreeTimeBeat 11.25[pulse=9]; +PulseFreeTimeBeat 12[pulse=9]; +PulseFreeTimeBeat 12.25[pulse=9]; +PulseFreeTimeBeat 13[pulse=9]; +AddClassicBeat 0 1[tick=6]; +AddClassicBeat 7 1[tick=1.5,swing=0.25]; +AddClassicBeat 9 1[tick=1.5,swing=0.25]; +AddClassicBeat 0 2[tick=3,hold=0.5,swing=0.5]; +AddClassicBeat 4 2[tick=3,swing=0.5]; +AddClassicBeat 7 2[tick=6]; ``` **四、**不要过度采音。更不要为了精准采音做出种类繁多,重复次数又少的自由拍子。节奏医生的游戏机制是和一般的音乐游戏不同的。音乐游戏是可以给每一个节奏点都设计按键(Note)的,但节奏医生却不能这样。节奏医生的本质是“提示拍 + 按键拍”的组合,**所有的提示拍全都应该按照没有按键的节奏点来设计**。如果像其他音乐游戏一样来设计节奏医生的谱面,得到的一定是塞爆谱。 diff --git a/pages/captions.md b/pages/captions.md index 3d6fa28..b8c7a7c 100644 --- a/pages/captions.md +++ b/pages/captions.md @@ -39,25 +39,25 @@ **创建文本递进**:如果想要把一整句歌词按歌词节奏一个一个地显示出来,就需要在文本中使用“`/`”将它们隔开。如果想要一个一个地覆盖掉之前显示的内容,就需要在文本中使用`回车键`将他们隔开。之后点击下面的“创建文本递进”,在工作区里面可以拖动右箭头事件来调整时机。如果你做好了又不想要了,那么再把下面的开启改成关闭即可,无需手动删除。如果你又反悔了,还是想要,再改成开启,又会恢复记录。 ```rdview 8 3 -ea.FloatingText 1 1; -ea.AdvanceText 2 1; -ea.AdvanceText 3 1; -ea.AdvanceText 4 1; -ea.AdvanceText 5 1; -ea.AdvanceText 6 1; -ea.AdvanceText 7 1; +FloatingText 1 1; +AdvanceText 2 1; +AdvanceText 3 1; +AdvanceText 4 1; +AdvanceText 5 1; +AdvanceText 6 1; +AdvanceText 7 1; ``` 音节的消失方式选择**淡出**就是慢慢消失,**立即**就是瞬间消失,音节显示的时长是按创建文本递进的最后一个事件往后数拍子的。 ```rdview 13 3 -ea.FloatingText 1 1; +FloatingText 1 1; g 3 1 4 1; g 7 1 0 1 #f80; -ea.AdvanceText 3 1; +AdvanceText 3 1; g 8 1 4 1; g 12 1 0 1 #f80; -ea.AdvanceText 8 1; +AdvanceText 8 1; ``` ## 更丰富的效果和技巧 diff --git a/pages/holdbeat.md b/pages/holdbeat.md index c9e4cac..1e5518b 100644 --- a/pages/holdbeat.md +++ b/pages/holdbeat.md @@ -9,8 +9,8 @@ 如果不对其添加任何其他设置,那么轨道会延续上一个“切换为修饰拍子设置”的模式,当然你可以在“设置X标记”这个项目里面选择跳过节拍的形式,默认有三种情况,比如选`—x—x—x`轨道就会自动变成 `—x—x—x————♥` 的模式,像`4-1`这关的矿工一样,也就是在1,3,5,7拍有按压的动画效果。 ```rdview 7 3 -eb.AddClassicBeat 3 1[tick=3,hold=0.3,swing=0.5]; -eb.SetRowXs 1 1[rowxs=---x--]; +AddClassicBeat 3 1[tick=0.5,hold=0.3,swing=0.5]; +SetRowXs 1 1[rowxs=---x--]; ``` 另外长按拍子在编辑器里面也可以分解为自由节拍,使用自由节拍时,需将脉冲出现与脉冲消失分别构成两个合法的普通拍,也即所有脉冲出现的相隔时长相同,且所有脉冲消失的相隔时长相同。 @@ -24,12 +24,12 @@ g 5 2 0 5 #f00{}; g 5.5 3 0 4 #d20{}; g 6 4 0 3 #b40{}; g 6.5 5 0 2 #960{}; -eb.AddFreeTimeBeat 1 1[offset=0 1,hold=4]; -eb.PulseFreeTimeBeat 2 1[offset=0 2,hold=3.5,pulse=3]; -eb.PulseFreeTimeBeat 3 1[offset=0 3,hold=3,pulse=5]; -eb.PulseFreeTimeBeat 4 1[offset=0 4,hold=2.5,pulse=7]; -eb.AddClassicBeat 1 6[tick=3,swing=0.5]; -eb.AddClassicBeat 5 6[tick=1.5,swing=0.25]; +AddFreeTimeBeat 1 1[pulse=0,offset=0 1,hold=4]; +PulseFreeTimeBeat 2 1[offset=0 2,hold=3.5,action=Custom,customPulse=2]; +PulseFreeTimeBeat 3 1[offset=0 3,hold=3,action=Custom,customPulse=4]; +PulseFreeTimeBeat 4 1[offset=0 4,hold=2.5,action=Custom,customPulse=6]; +AddClassicBeat 1 6[tick=0.5,swing=2]; +AddClassicBeat 5 6[tick=0.25,swing=2]; ``` ## 演示关卡 @@ -41,23 +41,23 @@ eb.AddClassicBeat 5 6[tick=1.5,swing=0.25]; **1、**在长按拍松手的时刻可以有其他的按拍。这在曾经的编辑器版本里是不允许的,目前官方修正了这一机制。 ```rdview 9 4 -eb.AddClassicBeat 1 1[tick=6,hold=1]; -eb.AddClassicBeat 2 2[tick=6]; +AddClassicBeat 1 1[tick=1,hold=1]; +AddClassicBeat 2 2[tick=1]; ``` **2、**当同时存在多个长按拍子时,这些长按拍的长按时间段必须完全一致。也就是说,长按时间段之间不能是包含、交叉或首尾相连的关系。 ```rdview 16 7 -eb.AddClassicBeat 1 1[tick=3,hold=1,swing=0.5]; -eb.AddClassicBeat 1 2[tick=3,hold=0.5,swing=0.5]; -eb.AddClassicBeat 6 1[tick=3,hold=1,swing=0.5]; -eb.AddClassicBeat 6.25 2[tick=3,hold=0.5,swing=0.5]; -eb.AddClassicBeat 11 1[tick=3,hold=1,swing=0.5]; -eb.AddClassicBeat 11.5 2[tick=3,hold=1,swing=0.5]; -eb.AddClassicBeat 1.5 4[tick=1.5,hold=1,swing=0.25]; -eb.AddClassicBeat 1 5[tick=3,hold=0.5,swing=0.5]; -eb.AddClassicBeat 6 4[tick=3,hold=1,swing=0.5]; -eb.AddClassicBeat 6.5 5[tick=3,hold=0.5,swing=0.5]; +AddClassicBeat 1 1[tick=0.5,hold=1,swing=0.5]; +AddClassicBeat 1 2[tick=0.5,hold=0.5,swing=0.5]; +AddClassicBeat 6 1[tick=0.5,hold=1,swing=0.5]; +AddClassicBeat 6.25 2[tick=0.5,hold=0.5,swing=0.5]; +AddClassicBeat 11 1[tick=0.5,hold=1,swing=0.5]; +AddClassicBeat 11.5 2[tick=0.5,hold=1,swing=0.5]; +AddClassicBeat 1.5 4[tick=0.5,hold=1,swing=0.25]; +AddClassicBeat 1 5[tick=0.5,hold=0.5,swing=0.5]; +AddClassicBeat 6 4[tick=0.5,hold=1,swing=0.5]; +AddClassicBeat 6.5 5[tick=0.5,hold=0.5,swing=0.5]; ``` **3、**凹兔的自动演示对于长按拍的处理十分诡异,可能会提前松掉长按拍子,但不必惊慌,这不是你的问题。 diff --git a/pages/importandexport.md b/pages/importandexport.md index f920229..5f59164 100644 --- a/pages/importandexport.md +++ b/pages/importandexport.md @@ -45,9 +45,9 @@ 接下来在左下角点击紫色星星图标进入紫色的版块,在能看到波形结束的地方点一下,然后往下翻到**结束关卡**按钮,这样的按钮一共必须放三个。 ```rdview 5 5 -ea.FinishLevel 1 1; -ea.FinishLevel 2 2; -ea.FinishLevel 3 3; +FinishLevel 1 1; +FinishLevel 2 2; +FinishLevel 3 3; ``` 最后我们回到红色的版块,点击**关卡设置**,选择上方的导出,有几个空栏是必须要填写的: diff --git a/pages/moreclassicbeats.md b/pages/moreclassicbeats.md index 70a39e8..209ddfa 100644 --- a/pages/moreclassicbeats.md +++ b/pages/moreclassicbeats.md @@ -7,13 +7,13 @@ 我们把一个普通的普通拍子分解为自由时长节拍后,可以看到它变成了一个大的`1`和六个小的`>` 。 ```rdview 8 2 -eb.AddFreeTimeBeat 1 0[pulse=1]; -eb.PulseFreeTimeBeat 2 0[pulse=9]; -eb.PulseFreeTimeBeat 3 0[pulse=9]; -eb.PulseFreeTimeBeat 4 0[pulse=9]; -eb.PulseFreeTimeBeat 5 0[pulse=9]; -eb.PulseFreeTimeBeat 6 0[pulse=9]; -eb.PulseFreeTimeBeat 7 0[pulse=9]; +AddFreeTimeBeat 1 0[pulse=0]; +PulseFreeTimeBeat 2 0[action=Increment]; +PulseFreeTimeBeat 3 0[action=Increment]; +PulseFreeTimeBeat 4 0[action=Increment]; +PulseFreeTimeBeat 5 0[action=Increment]; +PulseFreeTimeBeat 6 0[action=Increment]; +PulseFreeTimeBeat 7 0[action=Increment]; ``` 我们选中数字1对应的节拍,发现这个是设置起始脉冲位置的。你甚至可以将它改为第七拍,然后把六个小的`>`删掉,这样就没有任何节拍提示。如果你设计的关卡是一个和节奏医生没什么关联的创意谱(梦幻联动?),且按键密度很大,则可以考虑这样使用。相比于工作区里面重叠摆放一大堆普通普通拍子,这样会看上去更清爽。但如果你设计的就是节奏医生,**请不要在完全无节奏提示的情况下直接响起第七拍**。 @@ -23,20 +23,20 @@ eb.PulseFreeTimeBeat 7 0[pulse=9]; 剩下的大于号`>`即意味着心跳向右移动一格,数到7的时候则需要按拍。点选之后,把它改成 `<`,心跳还能向左移动一格;点击自定义,还可以任意指定到第几个节拍。每一组自由拍**必须使用较大的节拍作为开头**,较小的则数量不限,直到数到第七拍为止。 ```rdview 10 2 -eb.AddFreeTimeBeat 1 0[pulse=1]; -eb.PulseFreeTimeBeat 2 0[pulse=9]; -eb.PulseFreeTimeBeat 2.75 0[pulse=9]; -eb.PulseFreeTimeBeat 3.5 0[pulse=9]; -eb.PulseFreeTimeBeat 4 0[pulse=9]; -eb.PulseFreeTimeBeat 4.5 0[pulse=9]; -eb.PulseFreeTimeBeat 5 0[pulse=9]; -eb.AddFreeTimeBeat 5 0[pulse=1]; -eb.PulseFreeTimeBeat 6 0[pulse=9]; -eb.PulseFreeTimeBeat 6.75 0[pulse=9]; -eb.PulseFreeTimeBeat 7.5 0[pulse=9]; -eb.PulseFreeTimeBeat 8 0[pulse=9]; -eb.PulseFreeTimeBeat 8.5 0[pulse=9]; -eb.PulseFreeTimeBeat 9 0[pulse=9]; +AddFreeTimeBeat 1 0[pulse=0]; +PulseFreeTimeBeat 2 0[action=Increment]; +PulseFreeTimeBeat 2.75 0[action=Increment]; +PulseFreeTimeBeat 3.5 0[action=Increment]; +PulseFreeTimeBeat 4 0[action=Increment]; +PulseFreeTimeBeat 4.5 0[action=Increment]; +PulseFreeTimeBeat 5 0[action=Increment]; +AddFreeTimeBeat 5 0[pulse=0]; +PulseFreeTimeBeat 6 0[action=Increment]; +PulseFreeTimeBeat 6.75 0[action=Increment]; +PulseFreeTimeBeat 7.5 0[action=Increment]; +PulseFreeTimeBeat 8 0[action=Increment]; +PulseFreeTimeBeat 8.5 0[action=Increment]; +PulseFreeTimeBeat 9 0[action=Increment]; ``` 如果你想让一串自由节拍最后不需要按拍,而是节奏直接消失,就把这一组自由节拍的最后一个点选**垃圾桶**符号。 @@ -70,15 +70,15 @@ eb.PulseFreeTimeBeat 9 0[pulse=9]; 八拍子就更好理解了,我们直接额外增加一个节拍,让按拍的时机在第八拍响起的时候。但是轨道上是只能显示七个拍子的,所以我们依然要依赖**分解成自由拍**,以`2 1 2 3 4 5 6 7`的形式响起节拍。设置的方法如下图所示: ```rdview 10 3 -eb.AddClassicBeat 1 0[tick=6]; -eb.AddFreeTimeBeat 1 1[pulse=2]; -eb.PulseFreeTimeBeat 2 1[pulse=8]; -eb.PulseFreeTimeBeat 3 1[pulse=9]; -eb.PulseFreeTimeBeat 4 1[pulse=9]; -eb.PulseFreeTimeBeat 5 1[pulse=9]; -eb.PulseFreeTimeBeat 6 1[pulse=9]; -eb.PulseFreeTimeBeat 7 1[pulse=9]; -eb.PulseFreeTimeBeat 8 1[pulse=9]; +AddClassicBeat 1 0[tick=1]; +AddFreeTimeBeat 1 1[pulse=1]; +PulseFreeTimeBeat 2 1[action=Decrement]; +PulseFreeTimeBeat 3 1[action=Increment]; +PulseFreeTimeBeat 4 1[action=Increment]; +PulseFreeTimeBeat 5 1[action=Increment]; +PulseFreeTimeBeat 6 1[action=Increment]; +PulseFreeTimeBeat 7 1[action=Increment]; +PulseFreeTimeBeat 8 1[action=Increment]; ``` **如何提示** @@ -91,15 +91,15 @@ eb.PulseFreeTimeBeat 8 1[pulse=9]; 八拍子也可以是摇摆拍,只需要将所有偶数拍选择并拖动即可变成摇摆拍: ```rdview 10 3 -eb.AddClassicBeat 1 0[tick=6,swing=0.5]; -eb.AddFreeTimeBeat 1 1[pulse=2]; -eb.PulseFreeTimeBeat 2.5 1[pulse=8]; -eb.PulseFreeTimeBeat 3 1[pulse=9]; -eb.PulseFreeTimeBeat 4.5 1[pulse=9]; -eb.PulseFreeTimeBeat 5 1[pulse=9]; -eb.PulseFreeTimeBeat 6.5 1[pulse=9]; -eb.PulseFreeTimeBeat 7 1[pulse=9]; -eb.PulseFreeTimeBeat 8.5 1[pulse=9]; +AddClassicBeat 1 0[tick=1,swing=0.5]; +AddFreeTimeBeat 1 1[pulse=1]; +PulseFreeTimeBeat 2.5 1[action=Decrement]; +PulseFreeTimeBeat 3 1[action=Increment]; +PulseFreeTimeBeat 4.5 1[action=Increment]; +PulseFreeTimeBeat 5 1[action=Increment]; +PulseFreeTimeBeat 6.5 1[action=Increment]; +PulseFreeTimeBeat 7 1[action=Increment]; +PulseFreeTimeBeat 8.5 1[action=Increment]; ``` 在八拍子中,**激活拍子**与八拍子的对应关系如下图所示。不要给第1拍和第3拍设置X拍子,这样做它就相当于变回普通拍了。 @@ -118,33 +118,33 @@ eb.PulseFreeTimeBeat 8.5 1[pulse=9]; 整数拍和附点拍是交错排列的,即`0.25<->0.375<->0.5<->0.75<->1<->1.5<->2<->3<->4`。附点变速拍可以将整拍长变成附点拍长,也可以反过来,但只能变化到排列里它**相邻**的拍长上。 ```rdview 9 3 -eb.AddFreeTimeBeat 1 0; -eb.PulseFreeTimeBeat 2 0[pulse=9]; -eb.PulseFreeTimeBeat 3 0[pulse=9]; -eb.PulseFreeTimeBeat 4 0[pulse=9]; +AddFreeTimeBeat 1 0; +PulseFreeTimeBeat 2 0[action=Increment]; +PulseFreeTimeBeat 3 0[action=Increment]; +PulseFreeTimeBeat 4 0[action=Increment]; g 4 0 0.5 1 #08f[offset=0 0 #08f0]{ - eb.PulseFreeTimeBeat 1 0[pulse=9]; + PulseFreeTimeBeat 1 0[action=Increment]; g 1 0 0.5 1 #000[offset=0 0 #0000]{ g 0 0 0 0 #0000[offset=0.25]{ - eb.PulseFreeTimeBeat 0.75 0[pulse=9,offset=0.25]; + PulseFreeTimeBeat 0.75 0[action=Increment,offset=0.25]; g 0.75 0 0.5 1 #0000[offset=0.25]{ - eb.PulseFreeTimeBeat 0.75 0[pulse=9]; + PulseFreeTimeBeat 0.75 0[action=Increment]; g -1.75 0 3 1 #0000{}; }; }; }; }; -eb.AddFreeTimeBeat 1 1; -eb.PulseFreeTimeBeat 2 1[pulse=9]; -eb.PulseFreeTimeBeat 3 1[pulse=9]; -eb.PulseFreeTimeBeat 4 1[pulse=9]; +AddFreeTimeBeat 1 1; +PulseFreeTimeBeat 2 1[action=Increment]; +PulseFreeTimeBeat 3 1[action=Increment]; +PulseFreeTimeBeat 4 1[action=Increment]; g 4 1 0.5 1 #80f[offset=0 0 #08f0]{ - eb.PulseFreeTimeBeat 1 0[pulse=9]; + PulseFreeTimeBeat 1 0[action=Increment]; g 1 0 0.5 1 #000[offset=0 0 #0000]{ g 0 0 0 0 #0000[offset=-0.5]{ - eb.PulseFreeTimeBeat 1.5 0[pulse=9]; + PulseFreeTimeBeat 1.5 0[action=Increment]; g 1.5 0 0.5 1 #0000[offset=-0.5]{ - eb.PulseFreeTimeBeat 1.5 0[pulse=9]; + PulseFreeTimeBeat 1.5 0[action=Increment]; g -2.5 0 4.5 1 #0000{}; }; }; @@ -171,33 +171,33 @@ g 4 1 0.5 1 #80f[offset=0 0 #08f0]{ 变速普通拍的另一种形式是倍速变速拍,变速是拍长翻倍或减半,注意与附点变速拍区分。 ```rdview 11 3 -eb.AddFreeTimeBeat 1 0; -eb.PulseFreeTimeBeat 2 0[pulse=9]; -eb.PulseFreeTimeBeat 3 0[pulse=9]; -eb.PulseFreeTimeBeat 4 0[pulse=9]; +AddFreeTimeBeat 1 0; +PulseFreeTimeBeat 2 0[action=Increment]; +PulseFreeTimeBeat 3 0[action=Increment]; +PulseFreeTimeBeat 4 0[action=Increment]; g 4 0 0.5 1 #08f[offset=0 0 #08f0]{ - eb.PulseFreeTimeBeat 1 0[pulse=9]; + PulseFreeTimeBeat 1 0[action=Increment]; g 1 0 0.5 1 #000[offset=0 0 #0000]{ g 0 0 0 0 #0000[offset=0.5]{ - eb.PulseFreeTimeBeat 0.5 0[pulse=9]; + PulseFreeTimeBeat 0.5 0[action=Increment]; g 0.5 0 0.5 1 #0000[offset=0.5]{ - eb.PulseFreeTimeBeat 0.5 0[pulse=9]; + PulseFreeTimeBeat 0.5 0[action=Increment]; g -1.75 0 3 1 #0000{}; }; }; }; }; -eb.AddFreeTimeBeat 1 1; -eb.PulseFreeTimeBeat 2 1[pulse=9]; -eb.PulseFreeTimeBeat 3 1[pulse=9]; -eb.PulseFreeTimeBeat 4 1[pulse=9]; +AddFreeTimeBeat 1 1; +PulseFreeTimeBeat 2 1[action=Increment]; +PulseFreeTimeBeat 3 1[action=Increment]; +PulseFreeTimeBeat 4 1[action=Increment]; g 4 1 0.5 1 #08f[offset=0 0 #08f0]{ - eb.PulseFreeTimeBeat 1 0[pulse=9]; + PulseFreeTimeBeat 1 0[action=Increment]; g 1 0 0.5 1 #000[offset=0 0 #0000]{ g 0 0 0 0 #0000[offset=-1]{ - eb.PulseFreeTimeBeat 2 0[pulse=9]; + PulseFreeTimeBeat 2 0[action=Increment]; g 2 0 0.5 1 #0000[offset=-1]{ - eb.PulseFreeTimeBeat 2 0[pulse=9]; + PulseFreeTimeBeat 2 0[action=Increment]; g -2.5 0 4.5 1 #0000{}; }; }; diff --git a/pages/moreoneshotbeats.md b/pages/moreoneshotbeats.md index 43b0117..7176c15 100644 --- a/pages/moreoneshotbeats.md +++ b/pages/moreoneshotbeats.md @@ -7,10 +7,10 @@ 我们前面说过,护士提示的 Rea 和 Get 对应脉冲,Dy 和 Set 对应按拍,Go 代表单发拍开始,这种规则当然不仅仅适用于普通单发拍。先来看一个简单的摇摆单发拍: ```rdview 11 3 -es.SayReadyGetSetGo_Get 1[]; -es.SayReadyGetSetGo_Set 2.5[]; -es.SayReadyGetSetGo_Go 5[]; -eb.AddOneshotBeat 5 1[loop=1,tick=1.5,interval=4]; +SayReadyGetSetGo 1[phraseToSay=JustSayGet]; +SayReadyGetSetGo 2.5[phraseToSay=JustSaySet]; +SayReadyGetSetGo 5[phraseToSay=JustSayGo]; +AddOneshotBeat 5 1[loop=1,tick=1.5,interval=4]; ``` 可以看到,虽然 Get-Set 与 Set-Go 之间的间隔不同,但依然保持了上述的对应关系。实际上,这就是`4-4`使用的单发拍。 @@ -18,31 +18,31 @@ eb.AddOneshotBeat 5 1[loop=1,tick=1.5,interval=4]; 在`2-3`中也出现了摇摆单发拍,可以试着自己理解一下这关的单发拍提示: ```rdview 10 2 -eb.AddOneshotBeat 1[]; -eb.AddOneshotBeat 3[]; -eb.AddOneshotBeat 5[tick=0.75]; -eb.AddOneshotBeat 6[tick=0.75]; -eb.AddOneshotBeat 7[tick=0.75]; -eb.AddOneshotBeat 8[tick=0.75]; +AddOneshotBeat 1[]; +AddOneshotBeat 3[]; +AddOneshotBeat 5[tick=0.75]; +AddOneshotBeat 6[tick=0.75]; +AddOneshotBeat 7[tick=0.75]; +AddOneshotBeat 8[tick=0.75]; ``` 如果我们在此基础上更进一步,会发生什么呢?来看看`4-4N`中出现过的这段单发拍: ```rdview 12 4 g 1 1 4 2[offset=4]{ - es.SayReadyGetSetGo_Rea 0 0[]; - es.SayReadyGetSetGo_Dy 0.75 1[]; - es.SayReadyGetSetGo_Get 1.5 0[]; - es.SayReadyGetSetGo_Set 2.25 1[]; - es.SayReadyGetSetGo_Go 4 0[]; + SayReadyGetSetGo 0 0[phraseToSay=JustSayRea]; + SayReadyGetSetGo 0.75 1[phraseToSay=JustSayDy]; + SayReadyGetSetGo 1.5 0[phraseToSay=JustSayGet]; + SayReadyGetSetGo 2.25 1[phraseToSay=JustSaySet]; + SayReadyGetSetGo 4 0[phraseToSay=JustSayGo]; g 0 -1 0.75 3 #0f8[]{}; g 1.5 -1 0.75 3 #0f8[]{}; g 4 -1 0 3 #0f8[]{}; }; -eb.AddOneshotBeat 5[tick=0.75]; -eb.AddOneshotBeat 6.5[tick=0.75]; -eb.AddOneshotBeat 9[tick=0.75]; -eb.AddOneshotBeat 10.5[tick=0.75]; +AddOneshotBeat 5[tick=0.75]; +AddOneshotBeat 6.5[tick=0.75]; +AddOneshotBeat 9[tick=0.75]; +AddOneshotBeat 10.5[tick=0.75]; ``` 可以看到,图中的单发拍已不再局限于一个单发拍不断重复了,而是变成了若干个单发拍构成的单发拍组的不断重复,但前面讲过的与护士提示之间的对应关系仍保持不变。由此我们可以得到单发拍的核心规则: @@ -53,24 +53,24 @@ eb.AddOneshotBeat 10.5[tick=0.75]; ```rdview 13 4 g 1 1 4 2[offset=4]{ - es.SayReadyGetSetGo_Rea 0 0[]; - es.SayReadyGetSetGo_Dy 1 0[]; - es.SayReadyGetSetGo_Rea 2 0[]; - es.SayReadyGetSetGo_Dy 2.5 1[]; - es.SayReadyGetSetGo_Get 3 0[]; - es.SayReadyGetSetGo_Set 3.5 1[]; - es.SayReadyGetSetGo_Go 4 0[]; + SayReadyGetSetGo 0 0[phraseToSay=JustSayRea]; + SayReadyGetSetGo 1 0[phraseToSay=JustSayDy]; + SayReadyGetSetGo 2 0[phraseToSay=JustSayRea]; + SayReadyGetSetGo 2.5 1[phraseToSay=JustSayDy]; + SayReadyGetSetGo 3 0[phraseToSay=JustSayGet]; + SayReadyGetSetGo 3.5 1[phraseToSay=JustSaySet]; + SayReadyGetSetGo 4 0[phraseToSay=JustSayGo]; g 0 -1 1 2 #0f8[]{}; g 2 -1 0.5 3 #0f8[]{}; g 3 -1 0.5 3 #0f8[]{}; g 4 -1 0 3 #0f8[]{}; }; -eb.AddOneshotBeat 5[]; -eb.AddOneshotBeat 7[tick=0.5]; -eb.AddOneshotBeat 8[tick=0.5]; -eb.AddOneshotBeat 9[]; -eb.AddOneshotBeat 11[tick=0.5]; -eb.AddOneshotBeat 12[tick=0.5]; +AddOneshotBeat 5[]; +AddOneshotBeat 7[tick=0.5]; +AddOneshotBeat 8[tick=0.5]; +AddOneshotBeat 9[]; +AddOneshotBeat 11[tick=0.5]; +AddOneshotBeat 12[tick=0.5]; ``` 当你不确定一段单发拍提示是否正确时,可以把这段单发拍提示向后复制几份,首尾相连,如果发现所有的 Dy 和 Set 均对齐了按拍时机,就说明单发拍提示是正确的。 @@ -84,13 +84,13 @@ eb.AddOneshotBeat 12[tick=0.5]; 以下单发拍均是合法的: ```rdview 9 2 -eb.AddOneshotBeat 1[]; -eb.AddOneshotBeat 3[]; -eb.AddOneshotBeat 3.5[tick=0.5]; -eb.AddOneshotBeat 4.75[tick=1.25]; -eb.AddOneshotBeat 5[]; -eb.AddOneshotBeat 5.75[tick=0.25]; -eb.AddOneshotBeat 7.5[tick=0.5]; +AddOneshotBeat 1[]; +AddOneshotBeat 3[]; +AddOneshotBeat 3.5[tick=0.5]; +AddOneshotBeat 4.75[tick=1.25]; +AddOneshotBeat 5[]; +AddOneshotBeat 5.75[tick=0.25]; +AddOneshotBeat 7.5[tick=0.5]; ``` ![](../images/moreoneshotbeats-farmer.gif) @@ -103,31 +103,31 @@ eb.AddOneshotBeat 7.5[tick=0.5]; 举个例子:Rea-Dy-Get-Set-Go 与 Rea-Dy--GetSet-Go,尽管两者的按拍时机相同,但不同的 Rea、Get 位置会给人带来不同的游玩体验。 ```rdview 12 6 -eb.AddOneshotBeat 5[]; -eb.AddOneshotBeat 7.5[tick=0.5]; -eb.AddOneshotBeat 9[]; -eb.AddOneshotBeat 11.5[tick=0.5]; +AddOneshotBeat 5[]; +AddOneshotBeat 7.5[tick=0.5]; +AddOneshotBeat 9[]; +AddOneshotBeat 11.5[tick=0.5]; g 1 1 4 1 [offset=4]{ - es.SayReadyGetSetGo_Rea 0[]; - es.SayReadyGetSetGo_Dy 1[]; - es.SayReadyGetSetGo_Get 2.5[]; - es.SayReadyGetSetGo_Set 3[]; - es.SayReadyGetSetGo_Go 4[]; + SayReadyGetSetGo 0[phraseToSay=JustSayRea]; + SayReadyGetSetGo 1[phraseToSay=JustSayDy]; + SayReadyGetSetGo 2.5[phraseToSay=JustSayGet]; + SayReadyGetSetGo 3[phraseToSay=JustSaySet]; + SayReadyGetSetGo 4[phraseToSay=JustSayGo]; g 0 -1 1 2 #0f8[]{}; g 2.5 -1 0.5 2 #0f8[]{}; g 4 -1 0 2 #0f8[]{}; }; -eb.AddOneshotBeat 5 3[]; -eb.AddOneshotBeat 7 3[]; -eb.AddOneshotBeat 9 3[]; -eb.AddOneshotBeat 11 3[]; +AddOneshotBeat 5 3[]; +AddOneshotBeat 7 3[]; +AddOneshotBeat 9 3[]; +AddOneshotBeat 11 3[]; g 1 4 4 1 [offset=4]{ - es.SayReadyGetSetGo_Rea 0[]; - es.SayReadyGetSetGo_Dy 1[]; - es.SayReadyGetSetGo_Get 2[]; - es.SayReadyGetSetGo_Set 3[]; - es.SayReadyGetSetGo_Go 4[]; + SayReadyGetSetGo 0[phraseToSay=JustSayRea]; + SayReadyGetSetGo 1[phraseToSay=JustSayDy]; + SayReadyGetSetGo 2[phraseToSay=JustSayGet]; + SayReadyGetSetGo 3[phraseToSay=JustSaySet]; + SayReadyGetSetGo 4[phraseToSay=JustSayGo]; g 0 -1 1 2 #0f8[]{}; g 2 -1 1 2 #0f8[]{}; g 4 -1 0 2 #0f8[]{}; @@ -143,13 +143,13 @@ g 1 4 4 1 [offset=4]{ 需要注意的是,跳过单发拍会跳过下一次**击拍**,而不是下一个循环节。 ```rdview 7 4 -eb.AddOneshotBeat 1[type=skipshot]; -eb.AddOneshotBeat 5[]; -eb.AddOneshotBeat 1 2[type=skipshot]; -eb.AddOneshotBeat 3 2[tick=3]; -eb.AddOneshotBeat 3.75 2[tick=2.25]; -eb.AddOneshotBeat 4.5 2[tick=1.5]; -eb.AddOneshotBeat 5.25 2[tick=0.75]; +AddOneshotBeat 1[type=skipshot]; +AddOneshotBeat 5[]; +AddOneshotBeat 1 2[type=skipshot]; +AddOneshotBeat 3 2[tick=3]; +AddOneshotBeat 3.75 2[tick=2.25]; +AddOneshotBeat 4.5 2[tick=1.5]; +AddOneshotBeat 5.25 2[tick=0.75]; ``` 另外,在剧情关卡中,跳过拍的位置如果按下空格会计算成失误,但编辑器中默认是不会失误的。 @@ -167,10 +167,10 @@ eb.AddOneshotBeat 5.25 2[tick=0.75]; 除此之外,方块单发拍也需要护士提示。这种护士提示与普通单发拍的提示类似,唯一的不同点在于最后的 Go 被替换为了 One。 ```rdview 5 3 -eb.AddOneshotBeat 3[]; -es.SayReadyGetSetGo_Get 1 1[]; -es.SayReadyGetSetGo_Set 2 1[]; -es.SayReadyGetSetGo_One 3 1[]; +AddOneshotBeat 3[]; +SayReadyGetSetGo 1 1[phraseToSay=JustSayGet]; +SayReadyGetSetGo 2 1[phraseToSay=JustSaySet]; +SayReadyGetSetGo 3 1[]; ``` 如果相同拍长的方块单发拍连续出现了多次,无需为每次出现添加完整的护士提示。可以逐步减少护士提示,直到完全没有护士提示,只剩下特殊提示音。 @@ -186,32 +186,32 @@ es.SayReadyGetSetGo_One 3 1[]; ![](../images/moreoneshotbeats-amountofsubdivision.png) ```rdview 4 5 -eb.AddOneshotBeat 1[type=subdivision,subdivision=2]; -eb.AddOneshotBeat 1 1[type=subdivision,subdivision=3]; -eb.AddOneshotBeat 1 2[type=subdivision,subdivision=4]; -eb.AddOneshotBeat 1 3[type=subdivision,subdivision=5]; +AddOneshotBeat 1[type=subdivision,subdivision=2]; +AddOneshotBeat 1 1[type=subdivision,subdivision=3]; +AddOneshotBeat 1 2[type=subdivision,subdivision=4]; +AddOneshotBeat 1 3[type=subdivision,subdivision=5]; ``` 在护士提示方面,不同于方块单发拍,细分拍需要在出拍前的半拍长开始数拍提示。 ```rdview 13 -eb.AddOneshotBeat 1[type=subdivision,subdivision=2]; +AddOneshotBeat 1[type=subdivision,subdivision=2]; g 1 1 0.5 1 #0f0[]{}; g 1 1 1 1 #0f0[]{}; g 0.5 1 0.5 1[offset=0.5]{ - es.SayReadyGetSetGo_2 0 1[]; + SayReadyGetSetGo 0 1[phraseToSay=Count2]; }; -eb.AddOneshotBeat 4[tick=2,type=subdivision,subdivision=2,interval=4]; +AddOneshotBeat 4[tick=2,type=subdivision,subdivision=2,interval=4]; g 4 1 1 1 #0f0[]{}; g 4 1 2 1 #0f0[]{}; g 3 1 1 1[offset=1]{ - es.SayReadyGetSetGo_2 0 1[]; + SayReadyGetSetGo 0 1[phraseToSay=Count2]; }; -eb.AddOneshotBeat 9[tick=2,type=subdivision,subdivision=3,interval=4]; +AddOneshotBeat 9[tick=2,type=subdivision,subdivision=3,interval=4]; g 9 1 1 1 #0f0[]{}; g 9 1 2 1 #0f0[]{}; g 8 1 1 1[offset=1]{ - es.SayReadyGetSetGo_3 0 1[]; + SayReadyGetSetGo 0 1[phraseToSay=Count3]; }; ``` @@ -228,14 +228,14 @@ g 8 1 1 1[offset=1]{ 单独细分的提示**与正常单发拍的提示类似**,Rea Dy 或 Get Set 之间的间隔同样用于提示细分拍的拍长,且数字提示**和 Go! 提示一样不需要提前**。 ```rdview 14 3 -eb.AddOneshotBeat 3[type=subdivision,subdivision=2]; -es.SayReadyGetSetGo_Get 1 1[]; -es.SayReadyGetSetGo_Set 2 1[]; -es.SayReadyGetSetGo_2 3 1[]; -eb.AddOneshotBeat 9[tick=2,type=subdivision,subdivision=4,interval=4]; -es.SayReadyGetSetGo_Get 5 1[]; -es.SayReadyGetSetGo_Set 7 1[]; -es.SayReadyGetSetGo_4 9 1[]; +AddOneshotBeat 3[type=subdivision,subdivision=2]; +SayReadyGetSetGo 1 1[phraseToSay=JustSayGet]; +SayReadyGetSetGo 2 1[phraseToSay=JustSaySet]; +SayReadyGetSetGo 3 1[phraseToSay=Count2]; +AddOneshotBeat 9[tick=2,type=subdivision,subdivision=4,interval=4]; +SayReadyGetSetGo 5 1[phraseToSay=JustSayGet]; +SayReadyGetSetGo 7 1[phraseToSay=JustSaySet]; +SayReadyGetSetGo 9 1[phraseToSay=Count4]; ``` ## 冻结拍🧊 @@ -249,14 +249,14 @@ es.SayReadyGetSetGo_4 9 1[]; ![](../images/moreoneshotbeats-freezeshot.png) ```rdview 8 2 -eb.AddOneshotBeat 2[type=freezeshot,delay=0.5,interval=2]; -eb.AddOneshotBeat 5[type=freezeshot,delay=0.5,interval=2,tick=2]; +AddOneshotBeat 2[type=freezeshot,delay=0.5,interval=2]; +AddOneshotBeat 5[type=freezeshot,delay=0.5,interval=2,tick=2]; ``` 对于一个冻结拍而言,一共有五个关键的时间点:左十字,右十字,出拍点(绿线),原按拍点(蓝线),实际按拍点(黄线)。 ```rdview 4 2 -eb.AddOneshotBeat 2[type=freezeshot,delay=0.5,interval=2]; +AddOneshotBeat 2[type=freezeshot,delay=0.5,interval=2]; ``` - **左十字**和**右十字**会显示两次冰冻特效并分别播放不同的冰冻音效,用于预示拍延长的时间。 @@ -274,20 +274,20 @@ eb.AddOneshotBeat 2[type=freezeshot,delay=0.5,interval=2]; - **左十字**必须和上一个普通单发拍的按拍位置重合。 ```rdview 5 3 -eb.AddOneshotBeat 1[]; -eb.AddOneshotBeat 3[type=freezeshot,delay=0.5,interval=2]; -eb.AddOneshotBeat 1 1[grayscale=100,offset_grayscale=80]; -eb.AddOneshotBeat 3 1[grayscale=100,offset_grayscale=80]; +AddOneshotBeat 1[]; +AddOneshotBeat 3[type=freezeshot,delay=0.5,interval=2]; +AddOneshotBeat 1 1[grayscale=100,offset_grayscale=80]; +AddOneshotBeat 3 1[grayscale=100,offset_grayscale=80]; ``` 如果需要在冻结拍上叠加多个拍子来凸显鼓点,可以将他们的按拍点放在同一位置。 ```rdview 5 3 -eb.AddOneshotBeat 2[type=freezeshot,delay=0.5,interval=2]; +AddOneshotBeat 2[type=freezeshot,delay=0.5,interval=2]; g 2 -1 2 2 #0000[offset=0 1]{ - eb.AddOneshotBeat 0.5 1[]; + AddOneshotBeat 0.5 1[]; g 0 -2 2 3 #0000[offset=0 1]{ - eb.AddOneshotBeat -1 3[tick=2.5]; + AddOneshotBeat -1 3[tick=2.5]; }; }; ``` @@ -305,7 +305,7 @@ g 2 -1 2 2 #0000[offset=0 1]{ 类似地,对于一个灼热拍,一共有四个关键的时间点:左十字,右十字,出拍点(绿线),按拍点。为作区分且方便表述,将会把按拍点称为红线。 ```rdview 5 2 -eb.AddOneshotBeat 3[tick=0.5,type=burnshot,interval=2]; +AddOneshotBeat 3[tick=0.5,type=burnshot,interval=2]; ``` - **左十字**和**右十字**会显示两次热浪特效并分别播放不同的灼热音效,用于预示拍实际的时间。 @@ -320,20 +320,20 @@ eb.AddOneshotBeat 3[tick=0.5,type=burnshot,interval=2]; - **左十字**必须和上一个普通单发拍的原定出拍位置重合。 ```rdview 5 3 -eb.AddOneshotBeat 1[]; -eb.AddOneshotBeat 3[tick=0.5,type=burnshot,interval=2]; -eb.AddOneshotBeat 1 1[grayscale=100,offset_grayscale=80]; -eb.AddOneshotBeat 3 1[grayscale=100,offset_grayscale=80]; +AddOneshotBeat 1[]; +AddOneshotBeat 3[tick=0.5,type=burnshot,interval=2]; +AddOneshotBeat 1 1[grayscale=100,offset_grayscale=80]; +AddOneshotBeat 3 1[grayscale=100,offset_grayscale=80]; ``` 如果需要在灼热拍上叠加多个拍子来凸显鼓点,可以将他们的按拍点放在同一位置。 ```rdview 5 3 -eb.AddOneshotBeat 2[type=burnshot,delay=0.5,interval=2]; +AddOneshotBeat 2[type=burnshot,delay=0.5,interval=2]; g 0 -1 3 2 #0000[offset=0 1]{ - eb.AddOneshotBeat 1.5 1[tick=1.5]; + AddOneshotBeat 1.5 1[tick=1.5]; g 0 -1 3 3 #0000[offset=0 1]{ - eb.AddOneshotBeat 0.5 2[tick=2.5]; + AddOneshotBeat 0.5 2[tick=2.5]; }; }; ``` @@ -387,32 +387,32 @@ g 0 -1 3 2 #0000[offset=0 1]{ 最后我们针对细分拍、冻结拍、灼热拍做一个技术总结: ```rdview 19 7 -eb.AddOneshotBeat 1[loop=1]; -eb.AddOneshotBeat 5[type=freezeshot,delay=0.5,interval=2]; -eb.AddOneshotBeat 1 1[loop=1]; -eb.AddOneshotBeat 5 1[]; -eb.AddOneshotBeat 1 2[loop=1]; -eb.AddOneshotBeat 5 2[tick=0.5,type=burnshot,interval=2]; -eb.AddOneshotBeat 1 4[loop=1]; -eb.AddOneshotBeat 5 4[tick=1,type=subdivision,subdivision=2,interval=2]; -eb.AddOneshotBeat 7 4[tick=0.5,loop=1,interval=1]; -eb.AddOneshotBeat 9 4[tick=0.5,type=subdivision,subdivision=2,interval=1]; -eb.AddOneshotBeat 10 4[tick=2]; -eb.AddOneshotBeat 14 4[tick=2,type=subdivision,subdivision=3,interval=4]; +AddOneshotBeat 1[loop=1]; +AddOneshotBeat 5[type=freezeshot,delay=0.5,interval=2]; +AddOneshotBeat 1 1[loop=1]; +AddOneshotBeat 5 1[]; +AddOneshotBeat 1 2[loop=1]; +AddOneshotBeat 5 2[tick=0.5,type=burnshot,interval=2]; +AddOneshotBeat 1 4[loop=1]; +AddOneshotBeat 5 4[tick=1,type=subdivision,subdivision=2,interval=2]; +AddOneshotBeat 7 4[tick=0.5,loop=1,interval=1]; +AddOneshotBeat 9 4[tick=0.5,type=subdivision,subdivision=2,interval=1]; +AddOneshotBeat 10 4[tick=2]; +AddOneshotBeat 14 4[tick=2,type=subdivision,subdivision=3,interval=4]; g 5 5 0.5 1 #0f0[]{}; g 5 5 1 1 #0f0[]{}; g 4.5 5 0.5 1[offset=0.5]{ - es.SayReadyGetSetGo_2 0 1[]; + SayReadyGetSetGo 0 1[phraseToSay=Count2]; }; g 9 5 0.25 1 #0f0[]{}; g 9 5 0.5 1 #0f0[]{}; g 8.75 5 0.25 1[offset=0.25]{ - es.SayReadyGetSetGo_2 0 1[]; + SayReadyGetSetGo 0 1[phraseToSay=Count2]; }; g 14 5 1 1 #0f0[]{}; g 14 5 2 1 #0f0[]{}; g 13 5 1 1[offset=1]{ - es.SayReadyGetSetGo_2 0 1[]; + SayReadyGetSetGo 0 1[phraseToSay=Count2]; }; ``` diff --git a/pages/oneshotbeat.md b/pages/oneshotbeat.md index 370ed52..2b90137 100644 --- a/pages/oneshotbeat.md +++ b/pages/oneshotbeat.md @@ -15,14 +15,14 @@ 在“**循环**”的空栏里输入次数,这个单发拍就会被**额外**重复这么多次。当然了,直接输入循环次数的方法并不够方便,因为很多时候不听具体音乐自己也不知道该循环多少次。更方便的方法是,把鼠标移动到工作区的这个单发拍子上,右上角就会出现一个**红色的箭头符号**,按住它并拖动即可。 ```rdview 7 3 -eb.AddOneshotBeat 1 1[tick=1,loop=2]; +AddOneshotBeat 1 1[tick=1,loop=2]; ``` 在循环设置后,左上角又会多出一个“**间隔**”的设置,指的是两个绿线之间的时间长度。大多数时候,我们会将间隔设为拍长的两倍,这也就构成了一个普通单发拍子。但如果你想设计更为复杂的单发拍子节奏型,也可以试着将间隔改为其他数值:例如,把间隔改成`1`,拍长改成`0.75`,就变成了一种摇摆单发拍子。 ```rdview 10 3 -eb.AddOneshotBeat 1 1[loop=1]; -eb.AddOneshotBeat 5 1[tick=0.75,loop=3,interval=1]; +AddOneshotBeat 1 1[loop=1]; +AddOneshotBeat 5 1[tick=0.75,loop=3,interval=1]; ``` 配置好带有循环的单发拍之后,按一下“**分解为单发节拍**”,会发现它被拆散成了若干个没有循环的单发拍事件。分解后的单发拍更加便于修改,你可以为它们单独添加修饰符或额外的脉冲。 @@ -42,80 +42,80 @@ eb.AddOneshotBeat 5 1[tick=0.75,loop=3,interval=1]; 将护士语音的拍长与单发拍的拍长保持一致,并将护士**喊出`Go!`的位置**与 **第一个普通单发拍的脉冲位置** 对齐即可,这样就完成了对一个普通单发拍的提示。 ```rdview 16 12 -eb.AddOneshotBeat 5 1[tick=2]; -eb.AddOneshotBeat 9 1[tick=2]; -eb.AddOneshotBeat 13 1[tick=2]; +AddOneshotBeat 5 1[tick=2]; +AddOneshotBeat 9 1[tick=2]; +AddOneshotBeat 13 1[tick=2]; g 1 2 4 1[offset=4 0]{ g 0 -1 0 2 #0f08{ - es.SayReadyGetSetGo_Get 0 1; + SayReadyGetSetGo 0 1[phraseToSay=JustSayGet]; }; g 2 -1 0 2 #ff08{ - es.SayReadyGetSetGo_Set 0 1; + SayReadyGetSetGo 0 1[phraseToSay=JustSaySet]; }; g 4 -1 0 2 #f008{ - es.SayReadyGetSetGo_Go 0 1; + SayReadyGetSetGo 0 1[phraseToSay=JustSayGo]; }; }; -eb.AddOneshotBeat 5 4; -eb.AddOneshotBeat 7 4; -eb.AddOneshotBeat 9 4; -eb.AddOneshotBeat 11 4; -eb.AddOneshotBeat 13 4; +AddOneshotBeat 5 4; +AddOneshotBeat 7 4; +AddOneshotBeat 9 4; +AddOneshotBeat 11 4; +AddOneshotBeat 13 4; g 1 5 4 2[offset=4 0]{ - es.SayReadyGetSetGo_ReaDyGetSetGo 0 0; + SayReadyGetSetGo 0 0[phraseToSay=SayReaDyGetSetGoNew]; g 0 -1 0 3 #0f08{ - es.SayReadyGetSetGo_Rea 0 2; + SayReadyGetSetGo 0 2[phraseToSay=JustSayRea]; }; g 1 -1 0 3 #ff08{ - es.SayReadyGetSetGo_Dy 0 2; + SayReadyGetSetGo 0 2[phraseToSay=JustSayDy]; }; g 2 -1 0 3 #0f08{ - es.SayReadyGetSetGo_Get 0 2; + SayReadyGetSetGo 0 2[phraseToSay=JustSayGet]; }; g 3 -1 0 3 #ff08{ - es.SayReadyGetSetGo_Set 0 2; + SayReadyGetSetGo 0 2[phraseToSay=JustSaySet]; }; g 4 -1 0 3 #F008{ - es.SayReadyGetSetGo_Go 0 2; + SayReadyGetSetGo 0 2[phraseToSay=JustSayGo]; }; }; -eb.AddOneshotBeat 5 8[tick=0.5]; -eb.AddOneshotBeat 6 8[tick=0.5]; -eb.AddOneshotBeat 7 8[tick=0.5]; -eb.AddOneshotBeat 8 8[tick=0.5]; -eb.AddOneshotBeat 9 8[tick=0.5]; -eb.AddOneshotBeat 10 8[tick=0.5]; -eb.AddOneshotBeat 11 8[tick=0.5]; -eb.AddOneshotBeat 12 8[tick=0.5]; -eb.AddOneshotBeat 13 8[tick=0.5]; -eb.AddOneshotBeat 14 8[tick=0.5]; +AddOneshotBeat 5 8[tick=0.5]; +AddOneshotBeat 6 8[tick=0.5]; +AddOneshotBeat 7 8[tick=0.5]; +AddOneshotBeat 8 8[tick=0.5]; +AddOneshotBeat 9 8[tick=0.5]; +AddOneshotBeat 10 8[tick=0.5]; +AddOneshotBeat 11 8[tick=0.5]; +AddOneshotBeat 12 8[tick=0.5]; +AddOneshotBeat 13 8[tick=0.5]; +AddOneshotBeat 14 8[tick=0.5]; g 1 9 4 2[offset=4 0]{ g 0 -1 0 2 #0f08{ - es.SayReadyGetSetGo_Rea 0 1; + SayReadyGetSetGo 0 1[phraseToSay=JustSayRea]; }; g 0.5 -1 0 3 #ff08{ - es.SayReadyGetSetGo_Dy 0 2; + SayReadyGetSetGo 0 2[phraseToSay=JustSayDy]; }; g 1 -1 0 2 #0f08{ - es.SayReadyGetSetGo_Rea 0 1; + SayReadyGetSetGo 0 1[phraseToSay=JustSayRea]; }; g 1.5 -1 0 3 #ff08{ - es.SayReadyGetSetGo_Dy 0 2; + SayReadyGetSetGo 0 2[phraseToSay=JustSayDy]; }; g 2 -1 0 2 #0f08{ - es.SayReadyGetSetGo_Rea 0 1; + SayReadyGetSetGo 0 1[phraseToSay=JustSayRea]; }; g 2.5 -1 0 3 #ff08{ - es.SayReadyGetSetGo_Dy 0 2; + SayReadyGetSetGo 0 2[phraseToSay=JustSayDy]; }; g 3 -1 0 2 #0f08{ - es.SayReadyGetSetGo_Get 0 1; + SayReadyGetSetGo 0 1[phraseToSay=JustSayGet]; }; g 3.5 -1 0 3 #ff08{ - es.SayReadyGetSetGo_Set 0 2; + SayReadyGetSetGo 0 2[phraseToSay=JustSaySet]; }; g 4 -1 0 2 #F008{ - es.SayReadyGetSetGo_Go 0 1; + SayReadyGetSetGo 0 1[phraseToSay=JustSayGo]; }; }; ``` @@ -131,30 +131,30 @@ g 1 9 4 2[offset=4 0]{ 也可以让单发拍子在几种拍速之间来回切换,提示方法与前面所讲的相同。只需要注意一点:单发拍子的节奏型应该在**Go!的瞬间**完成切换,Go之前的护士提示不会影响当前正在进行的单发拍子,而 Go 之后也不应再出现前一种单发拍子的节拍。 ```rdview 20 5 -eb.AddOneshotBeat 3 1; -eb.AddOneshotBeat 5 1; -eb.AddOneshotBeat 7 1[tick=0.5]; -eb.AddOneshotBeat 8 1[tick=0.5]; -eb.AddOneshotBeat 9 1[tick=0.5]; -eb.AddOneshotBeat 10 1[tick=0.5]; -eb.AddOneshotBeat 11 1; -eb.AddOneshotBeat 13 1; -eb.AddOneshotBeat 15 1[tick=0.75]; -eb.AddOneshotBeat 16 1[tick=0.75]; -eb.AddOneshotBeat 17 1[tick=0.75]; -eb.AddOneshotBeat 18 1[tick=0.75]; -es.SayReadyGetSetGo_Get 1 2; -es.SayReadyGetSetGo_Set 2 2; -es.SayReadyGetSetGo_Go 3 2; -es.SayReadyGetSetGo_Get 6 2; -es.SayReadyGetSetGo_Set 6.5 3; -es.SayReadyGetSetGo_Go 7 2; -es.SayReadyGetSetGo_Get 9 2; -es.SayReadyGetSetGo_Set 10 2; -es.SayReadyGetSetGo_Go 11 2; -es.SayReadyGetSetGo_Get 14 2; -es.SayReadyGetSetGo_Set 14.75 3; -es.SayReadyGetSetGo_Go 15 2; +AddOneshotBeat 3 1; +AddOneshotBeat 5 1; +AddOneshotBeat 7 1[tick=0.5]; +AddOneshotBeat 8 1[tick=0.5]; +AddOneshotBeat 9 1[tick=0.5]; +AddOneshotBeat 10 1[tick=0.5]; +AddOneshotBeat 11 1; +AddOneshotBeat 13 1; +AddOneshotBeat 15 1[tick=0.75]; +AddOneshotBeat 16 1[tick=0.75]; +AddOneshotBeat 17 1[tick=0.75]; +AddOneshotBeat 18 1[tick=0.75]; +SayReadyGetSetGo 1 2[phraseToSay=JustSayGet]; +SayReadyGetSetGo 2 2[phraseToSay=JustSaySet]; +SayReadyGetSetGo 3 2[phraseToSay=JustSayGo]; +SayReadyGetSetGo 6 2[phraseToSay=JustSayGet]; +SayReadyGetSetGo 6.5 3[phraseToSay=JustSaySet]; +SayReadyGetSetGo 7 2[phraseToSay=JustSayGo]; +SayReadyGetSetGo 9 2[phraseToSay=JustSayGet]; +SayReadyGetSetGo 10 2[phraseToSay=JustSaySet]; +SayReadyGetSetGo 11 2[phraseToSay=JustSayGo]; +SayReadyGetSetGo 14 2[phraseToSay=JustSayGet]; +SayReadyGetSetGo 14.75 3[phraseToSay=JustSaySet]; +SayReadyGetSetGo 15 2[phraseToSay=JustSayGo]; ``` 一个单发拍子不可能无限循环下去,总会有停下来的时候,可以使用护士提示中的`Stop`告知玩家单发拍子的结束。通常情况下,应使`Stop`对齐单发拍子的**最后一次击拍位置**。 @@ -164,12 +164,12 @@ es.SayReadyGetSetGo_Go 15 2; 如果单发拍子的停止时机足够符合直觉,可以省略单发拍子的Stop,但必须保证玩家下意识多打出的拍子不会判Miss。最稳妥的方法永远是为所有单发拍子的停止都添加 Stop 提示。 ```rdview 10 3 -eb.AddClassicBeat 2.5[tick=6]; -eb.AddOneshotBeat 1 1[]; -eb.AddOneshotBeat 3 1[]; -eb.AddOneshotBeat 5 1[]; +AddClassicBeat 2.5[tick=1]; +AddOneshotBeat 1 1[]; +AddOneshotBeat 3 1[]; +AddOneshotBeat 5 1[]; g 7 1 1 1{ - eb.AddOneshotBeat[grayscale=100]; + AddOneshotBeat[grayscale=100]; }; ``` diff --git a/pages/tag.md b/pages/tag.md index b136fe9..2e3f818 100644 --- a/pages/tag.md +++ b/pages/tag.md @@ -9,58 +9,58 @@ ```rdview 18 3 g 1 0 4 2 #ff0{ g 0 -1 0 3 #08f[]{}; - ea.MoveRow [tag=true]; - ea.MoveRow 1[tag=true]; - ea.MoveCamera 2[tag=true]; - ea.Flash 2.5[tag=true]; - ea.HideRow 0 1[tag=true]; - ea.SetVFXPreset 1.5 1[tag=true]; - ea.SetVFXPreset 2 1[tag=true]; - ea.HideRow 3 1[tag=true]; + MoveRow [tag=action]; + MoveRow 1[tag=action]; + MoveCamera 2[tag=action]; + Flash 2.5[tag=action]; + HideRow 0 1[tag=action]; + SetVFXPreset 1.5 1[tag=action]; + SetVFXPreset 2 1[tag=action]; + HideRow 3 1[tag=action]; g 5 0 0 0 #0000[offset=0 -1]{ - ea.TagAction[offset_opacity=0]; + TagAction[offset_opacity=0,Tag=action]; g 0 1 4 2 #ff0[opacity=0,offset_opacity=100]{ g 0 -1 0 3 #08f[]{}; g 0 -1 1 1 #0000[]{}; - ea.MoveRow []; - ea.MoveRow 1[]; - ea.MoveCamera 2[]; - ea.Flash 2.5[]; - ea.HideRow 0 1[]; - ea.SetVFXPreset 1.5 1[]; - ea.SetVFXPreset 2 1[]; - ea.HideRow 3 1[]; + MoveRow []; + MoveRow 1[]; + MoveCamera 2[]; + Flash 2.5[]; + HideRow 0 1[]; + SetVFXPreset 1.5 1[]; + SetVFXPreset 2 1[]; + HideRow 3 1[]; }; }; g 9 0 0 0 #0000[offset=0 -1]{ - ea.TagAction[]; + TagAction[offset_opacity=0,Tag=action]; g 0 1 4 2 #ff0[opacity=0,offset_opacity=100]{ g 0 -1 0 3 #08f[]{}; g 0 -1 1 1 #0000[]{}; - ea.MoveRow []; - ea.MoveRow 1[]; - ea.MoveCamera 2[]; - ea.Flash 2.5[]; - ea.HideRow 0 1[]; - ea.SetVFXPreset 1.5 1[]; - ea.SetVFXPreset 2 1[]; - ea.HideRow 3 1[]; + MoveRow []; + MoveRow 1[]; + MoveCamera 2[]; + Flash 2.5[]; + HideRow 0 1[]; + SetVFXPreset 1.5 1[]; + SetVFXPreset 2 1[]; + HideRow 3 1[]; }; }; g 13 0 0 0 #0000[offset=0 -1]{ - ea.TagAction[]; + TagAction[offset_opacity=0,Tag=action]; g 0 1 4 2 #ff0[opacity=0,offset_opacity=100]{ g 0 -1 0 3 #08f[]{}; g 0 -1 1 1 #0000[]{}; - ea.MoveRow []; - ea.MoveRow 1[]; - ea.MoveCamera 2[]; - ea.Flash 2.5[]; - ea.HideRow 0 1[]; - ea.SetVFXPreset 1.5 1[]; - ea.SetVFXPreset 2 1[]; - ea.HideRow 3 1[]; + MoveRow []; + MoveRow 1[]; + MoveCamera 2[]; + Flash 2.5[]; + HideRow 0 1[]; + SetVFXPreset 1.5 1[]; + SetVFXPreset 2 1[]; + HideRow 3 1[]; }; }; }; @@ -111,75 +111,75 @@ g 1 0 4 2 #ff0{ ```rdview 16 5 g 1 1 2 1 #df0{ g 0 -1 0 2 #08f[]{}; - ea.MoveRow [tag=true]; - ea.MoveRow 1[tag=true]; + MoveRow [tag=move]; + MoveRow 1[tag=move]; g 4 0 0 0 #0000[offset=0 -1]{ - ea.TagAction[]; + TagAction[Tag=move]; g 0 1 2 1 #ff0[opacity=20,offset_opacity=100]{ g 0 -1 0 2 #08f[]{}; g 0 -1 1 1 #0000[]{}; - ea.MoveRow []; - ea.MoveRow 1[]; + MoveRow []; + MoveRow 1[]; }; }; g 6 0 0 0 #0000[offset=0 -1]{ - ea.TagAction[]; + TagAction[Tag=move]; g 0 1 2 1 #ff0[opacity=20,offset_opacity=100]{ g 0 -1 0 2 #08f[]{}; g 0 -1 1 1 #0000[]{}; - ea.MoveRow []; - ea.MoveRow 1[]; + MoveRow []; + MoveRow 1[]; }; }; g 8 0 0 0 #0000[offset=0 -1]{ - ea.TagAction[]; + TagAction[Tag=move]; g 0 1 2 1 #ff0[opacity=20,offset_opacity=100]{ g 0 -1 0 2 #08f[]{}; g 0 -1 1 1 #0000[]{}; - ea.MoveRow []; - ea.MoveRow 1[]; + MoveRow []; + MoveRow 1[]; }; }; g 10 0 0 0 #0000[offset=0 -1]{ - ea.TagAction[]; + TagAction[Tag=move]; g 0 1 2 1 #ff0[opacity=20,offset_opacity=100]{ g 0 -1 0 2 #08f[]{}; g 0 -1 1 1 #0000[]{}; - ea.MoveRow []; - ea.MoveRow 1[]; + MoveRow []; + MoveRow 1[]; }; }; }; g 1 3 3 1 #df0{ g 0 -1 0 2 #08f[]{}; - ea.MoveRow [tag=true]; - ea.MoveRow 1[tag=true]; - ea.TagAction 2[tag=true]; + MoveRow [tag=move]; + MoveRow 1[tag=move]; + TagAction 2[tag=move]; g 4 0 0 0 #0000[offset=0 -1]{ - ea.TagAction[offset_opacity=0]; + TagAction[offset_opacity=0,Tag=move]; g 0 1 3 1 #ff0[opacity=20,offset_opacity=100]{ g 0 -1 0 2 #08f[]{}; - ea.MoveRow []; - ea.MoveRow 1[]; + MoveRow []; + MoveRow 1[]; g 2 0 0 0 #0000[offset=0 -1]{ - ea.TagAction[]; + TagAction[offset_opacity=0,Tag=move]; g 0 1 2 1 #ff0[opacity=20,offset_opacity=100]{ g 0 -1 0 2 #08f[]{}; - ea.MoveRow []; - ea.MoveRow 1[]; + MoveRow []; + MoveRow 1[]; g 2 0 0 0 #0000[offset=0 -1]{ - ea.TagAction[]; + TagAction[offset_opacity=0,Tag=move]; g 0 1 2 1 #ff0[opacity=20,offset_opacity=100]{ g 0 -1 0 2 #08f[]{}; - ea.MoveRow []; - ea.MoveRow 1[]; + MoveRow []; + MoveRow 1[]; g 2 0 0 0 #0000[offset=0 -1]{ - ea.TagAction[]; + TagAction[offset_opacity=0,Tag=move]; g 0 1 2 1 #ff0[opacity=20,offset_opacity=100]{ g 0 -1 0 2 #08f[]{}; - ea.MoveRow []; - ea.MoveRow 1[]; + MoveRow []; + MoveRow 1[]; g -6 -4 1 5 #0000[]{}; }; }; @@ -189,7 +189,7 @@ g 1 3 3 1 #df0{ }; }; }; - ea.TagAction 12[]; + TagAction 12[]; }; ``` @@ -211,143 +211,143 @@ g 1 3 3 1 #df0{ ```rdview 19 4 g 0 0 19 1 #f00[]{ - ea.Comment []; - ea.FloatingText 0.5[]; - ea.FloatingText 1[]; - ea.FloatingText 1.5[]; - ea.FloatingText 2[]; - ea.FloatingText 2.5[]; - ea.FloatingText 3[]; - ea.FloatingText 3.5[]; - ea.FloatingText 4[]; - ea.AdvanceText 4.5[]; - ea.AdvanceText 5[]; - ea.AdvanceText 5.5[]; - ea.AdvanceText 6[]; - ea.AdvanceText 6.5[]; - ea.AdvanceText 7[]; - ea.AdvanceText 7.5[]; - ea.FloatingText 8[]; - ea.FloatingText 8.75[]; - ea.Comment 9.75[]; - ea.FloatingText 11.75[]; - ea.FloatingText 12.5[]; - ea.FloatingText 13.5[]; - ea.FloatingText 14[]; - ea.FloatingText 14.5[]; - ea.FloatingText 15[]; - ea.FloatingText 15.5[]; - ea.FloatingText 16[]; - ea.FloatingText 16.5[]; - ea.FloatingText 17[]; - ea.FloatingText 17.5[]; + Comment [color=ffff00]; + FloatingText 0.5[outlineColor=000000]; + FloatingText 1[outlineColor=000000]; + FloatingText 1.5[outlineColor=000000]; + FloatingText 2[outlineColor=000000]; + FloatingText 2.5[outlineColor=000000]; + FloatingText 3[outlineColor=000000]; + FloatingText 3.5[outlineColor=000000]; + FloatingText 4[outlineColor=000000]; + AdvanceText 4.5[]; + AdvanceText 5[]; + AdvanceText 5.5[]; + AdvanceText 6[]; + AdvanceText 6.5[]; + AdvanceText 7[]; + AdvanceText 7.5[]; + FloatingText 8[outlineColor=000000]; + FloatingText 8.75[outlineColor=000000]; + Comment 9.75[tab=Actions]; + FloatingText 11.75[outlineColor=000000]; + FloatingText 12.5[outlineColor=000000]; + FloatingText 13.5[outlineColor=000000]; + FloatingText 14[outlineColor=000000]; + FloatingText 14.5[outlineColor=000000]; + FloatingText 15[outlineColor=000000]; + FloatingText 15.5[outlineColor=000000]; + FloatingText 16[outlineColor=000000]; + FloatingText 16.5[outlineColor=000000]; + FloatingText 17[outlineColor=000000]; + FloatingText 17.5[outlineColor=000000]; }; g 0 1 6.25 1 #08f[]{ - ea.MoveCamera []; - ea.MoveCamera 0.5[]; - ea.MoveCamera 1[]; - ea.MoveCamera 1.5[]; - ea.MoveCamera 2[]; - ea.MoveCamera 2.5[]; - ea.MoveCamera 3[]; - ea.MoveCamera 3.5[]; - ea.MoveCamera 4[]; - ea.MoveCamera 5[]; - ea.SetForeground 5.25[]; + MoveCamera []; + MoveCamera 0.5[]; + MoveCamera 1[]; + MoveCamera 1.5[]; + MoveCamera 2[]; + MoveCamera 2.5[]; + MoveCamera 3[]; + MoveCamera 3.5[]; + MoveCamera 4[]; + MoveCamera 5[]; + SetForeground 5.25[]; }; -ea.Comment 6.25 1[]; -ea.MoveRow 7.75 1[]; -ea.MoveRow 8 1[]; -ea.MoveRow 8.75 1[]; -ea.MoveCamera 12 1[]; -ea.SetForeground 12.25 1[]; -ea.FloatingText 14.5 1[]; -ea.FloatingText 15 1[]; -ea.FloatingText 15.5 1[]; -ea.FloatingText 16 1[]; -ea.FloatingText 16.5 1[]; -ea.SetVFXPreset 18 1[]; +Comment 6.25 1[tab=Actions]; +MoveRow 7.75 1[]; +MoveRow 8 1[]; +MoveRow 8.75 1[]; +MoveCamera 12 1[]; +SetForeground 12.25 1[]; +FloatingText 14.5 1[outlineColor=000000]; +FloatingText 15 1[outlineColor=000000]; +FloatingText 15.5 1[outlineColor=000000]; +FloatingText 16 1[outlineColor=000000]; +FloatingText 16.5 1[outlineColor=000000]; +SetVFXPreset 18 1[]; g 0 2 13.875 1 #06f[]{ - ea.MoveRow []; - ea.MoveRow []; - ea.Comment 1.75[]; - ea.MoveRow 2.75[]; - ea.MoveRow 3[]; - ea.MoveRow 4.5[]; - ea.MoveRow 4.75[]; - ea.MoveRow 5[]; - ea.MoveRow 5.25[]; - ea.MoveRow 6.75[]; - ea.MoveRow 7[]; - ea.MoveRow 7.5[]; - ea.MoveRow 7.75[]; - ea.MoveRow 8.5[]; - ea.MoveRow 10[]; - ea.MoveRow 10.25[]; - ea.HideRow 11.5[]; - ea.HideRow 11.5[]; - ea.MoveRow 12.5[]; - ea.MoveRow 12.75[]; + MoveRow []; + MoveRow []; + Comment 1.75[tab=Actions]; + MoveRow 2.75[]; + MoveRow 3[]; + MoveRow 4.5[]; + MoveRow 4.75[]; + MoveRow 5[]; + MoveRow 5.25[]; + MoveRow 6.75[]; + MoveRow 7[]; + MoveRow 7.5[]; + MoveRow 7.75[]; + MoveRow 8.5[]; + MoveRow 10[]; + MoveRow 10.25[]; + HideRow 11.5[]; + HideRow 11.5[]; + MoveRow 12.5[]; + MoveRow 12.75[]; }; -ea.Comment 14 2[]; +Comment 14 2[tab=Actions]; g 0 3 18 1 #f80[]{ - ea.FloatingText 0.5[]; - ea.AdvanceText 1[]; - ea.AdvanceText 1.5[]; - ea.AdvanceText 2.5[]; - ea.AdvanceText 3[]; - ea.AdvanceText 4.5[]; - ea.AdvanceText 5[]; - ea.AdvanceText 5.5[]; - ea.AdvanceText 6[]; - ea.AdvanceText 6.5[]; - ea.AdvanceText 7[]; - ea.AdvanceText 8[]; - ea.AdvanceText 10.5[]; - ea.AdvanceText 11.5[]; - ea.AdvanceText 12[]; - ea.AdvanceText 12.5[]; - ea.AdvanceText 13[]; - ea.AdvanceText 13.5[]; - ea.AdvanceText 14[]; - ea.AdvanceText 14.5[]; - ea.AdvanceText 15[]; - ea.AdvanceText 15.5[]; - ea.AdvanceText 16[]; - ea.AdvanceText 16.5[]; - ea.AdvanceText 17[]; - ea.AdvanceText 17.5[]; + FloatingText 0.5[outlineColor=000000]; + AdvanceText 1[]; + AdvanceText 1.5[]; + AdvanceText 2.5[]; + AdvanceText 3[]; + AdvanceText 4.5[]; + AdvanceText 5[]; + AdvanceText 5.5[]; + AdvanceText 6[]; + AdvanceText 6.5[]; + AdvanceText 7[]; + AdvanceText 8[]; + AdvanceText 10.5[]; + AdvanceText 11.5[]; + AdvanceText 12[]; + AdvanceText 12.5[]; + AdvanceText 13[]; + AdvanceText 13.5[]; + AdvanceText 14[]; + AdvanceText 14.5[]; + AdvanceText 15[]; + AdvanceText 15.5[]; + AdvanceText 16[]; + AdvanceText 16.5[]; + AdvanceText 17[]; + AdvanceText 17.5[]; }; ``` 2. 如果有一串同类型的事件紧密排布,例如每1/4格或者1/2格放一个,那么可以考虑不放在同一行,而是上下交错排开。 ```rdview 16 4 -ea.MoveRow []; -ea.MoveRow 1[]; -ea.MoveRow 2[]; -ea.MoveRow 4[]; -ea.MoveRow 5[]; -ea.MoveRow 6[]; -ea.MoveRow 8[]; -ea.MoveRow 9[]; -ea.MoveRow 10[]; -ea.MoveRow 12[]; -ea.MoveRow 13[]; -ea.MoveRow 14[]; -ea.MoveRow 0.5 1[]; -ea.MoveRow 1.5 1[]; -ea.MoveRow 3 1[]; -ea.MoveRow 4.5 1[]; -ea.MoveRow 5.5 1[]; -ea.MoveRow 7 1[]; -ea.MoveRow 8.5 1[]; -ea.MoveRow 9.5 1[]; -ea.MoveRow 11 1[]; -ea.MoveRow 12.5 1[]; -ea.MoveRow 13.5 1[]; -ea.MoveRow 15 1[]; -ea.Comment 4 3[]; +MoveRow []; +MoveRow 1[]; +MoveRow 2[]; +MoveRow 4[]; +MoveRow 5[]; +MoveRow 6[]; +MoveRow 8[]; +MoveRow 9[]; +MoveRow 10[]; +MoveRow 12[]; +MoveRow 13[]; +MoveRow 14[]; +MoveRow 0.5 1[]; +MoveRow 1.5 1[]; +MoveRow 3 1[]; +MoveRow 4.5 1[]; +MoveRow 5.5 1[]; +MoveRow 7 1[]; +MoveRow 8.5 1[]; +MoveRow 9.5 1[]; +MoveRow 11 1[]; +MoveRow 12.5 1[]; +MoveRow 13.5 1[]; +MoveRow 15 1[]; +Comment 4 3[tab=Actions]; ``` 3. 对于事件总体数量不太高的情况,如果有操作房间和轨道类型的特效,可以考虑把他们放在对应数量的行里,找起来会更加方便。 diff --git a/rdviewAssets/assets.bin b/rdviewAssets/assets.bin index 2c1e294273840c8a547aecb8dd5761cf9caa2b25..66e3827bc99366bf6be9704c3f15e4551ac27153 100644 GIT binary patch delta 325 zcmaE+*rZ(lRv@)3HLoN-Br~rhB(-q20v93#4*fg9gBMt+FO;8du>6+ne(Vg|E- zV!Uv5Zuxm77Fuvs?)f44K0wJFH->YJ(qL6m@s25FiFwJXAiG^slkhBpas`_rP|GZ~6d?JZt%lKJat*r#qt@oB?5rFT7C>JL oK}-rr1O|vlVqQvdyrIS9P5fCxT0lu2h$JYm;tjPX>j~@t02O&~82|tP delta 191 zcmZotex}IyY~##sMy7(0$&O4COhyHh9hjt;3M@c8X@df-bBrRXWvO{3@j;M3xQa)Dz diff --git a/rdviewAssets/assets.png b/rdviewAssets/assets.png index 7b9cbb9235cda4699063f54216ca73a0946c1526..373a47701db7f24422e66d89b8d4efb652be3fa1 100644 GIT binary patch literal 6591 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 literal 6646 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 + alt ? `

${alt}

` : "" + }`; + }, + }, + }, + switchLightDarkMode: { + useSwitchMode: true, + top: 130, + right: 26, + svgColor: "#7d7b75", + }, + search: { + noData: { + "/": "没有找到结果!", + }, + paths: "auto", + placeholder: { + "/": "搜索", + }, + hideOtherSidebarContent: true, + }, +}; diff --git a/script/rdtkview.d.ts b/script/rdtkview.d.ts new file mode 100644 index 0000000..08de6d3 --- /dev/null +++ b/script/rdtkview.d.ts @@ -0,0 +1,27 @@ +export declare class IconStyle { + enabled: boolean; + active: boolean; + hover: boolean; + scale: number; + showDuration: boolean; +} + +export interface HTMLLayerElement extends HTMLDivElement { + onStateChange?: (style: IconStyle) => void; + filterData: unknown; + updateFilter: () => void; +} + +export interface HTMLEventElement extends HTMLDivElement { + onStateChange: (style: IconStyle) => void; + eventStyle: IconStyle; + eventData: object; + moveTo: (x: number, y: number) => void; +} + +export declare function createElementEvent( + obj: any, + style: IconStyle, +): HTMLEventElement | null; + +export declare function colorOf(tab: string): any; diff --git a/script/rdtkview.js b/script/rdtkview.js index 7f6a805..3213fdd 100644 --- a/script/rdtkview.js +++ b/script/rdtkview.js @@ -1,49 +1,10 @@ -// 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) { +// D:/CSharp/RhythmBase.View/RhythmBase.View/definition.ts +var EventType = /* @__PURE__ */ ((EventType2) => { EventType2["AddClassicBeat"] = "AddClassicBeat"; EventType2["AddFreeTimeBeat"] = "AddFreeTimeBeat"; EventType2["AddOneshotBeat"] = "AddOneshotBeat"; EventType2["AdvanceText"] = "AdvanceText"; + EventType2["AdvanceTextDecoration"] = "AdvanceTextDecoration"; EventType2["BassDrop"] = "BassDrop"; EventType2["Blend"] = "Blend"; EventType2["CallCustomMethod"] = "CallCustomMethod"; @@ -60,10 +21,11 @@ var EventType = /* @__PURE__ */ function(EventType2) { EventType2["ForwardDecorationEvent"] = "ForwardDecorationEvent"; EventType2["ForwardEvent"] = "ForwardEvent"; EventType2["ForwardRowEvent"] = "ForwardRowEvent"; + EventType2["GoToLevel"] = "GoToLevel"; EventType2["HideRow"] = "HideRow"; EventType2["HideWindow"] = "HideWindow"; EventType2["InvertColors"] = "InvertColors"; - EventType2["MacroEvent"] = "MacroEvent"; + EventType2["LinkRows"] = "LinkRows"; EventType2["MaskRoom"] = "MaskRoom"; EventType2["Move"] = "Move"; EventType2["MoveCamera"] = "MoveCamera"; @@ -80,9 +42,9 @@ var EventType = /* @__PURE__ */ function(EventType2) { EventType2["PulseFreeTimeBeat"] = "PulseFreeTimeBeat"; EventType2["ReadNarration"] = "ReadNarration"; EventType2["RenameWindow"] = "RenameWindow"; + EventType2["ReorderDecoration"] = "ReorderDecoration"; EventType2["ReorderRooms"] = "ReorderRooms"; EventType2["ReorderRow"] = "ReorderRow"; - EventType2["ReorderSprite"] = "ReorderSprite"; EventType2["ReorderWindows"] = "ReorderWindows"; EventType2["SayReadyGetSetGo"] = "SayReadyGetSetGo"; EventType2["SetBackgroundColor"] = "SetBackgroundColor"; @@ -91,6 +53,7 @@ var EventType = /* @__PURE__ */ function(EventType2) { EventType2["SetClapSounds"] = "SetClapSounds"; EventType2["SetCountingSound"] = "SetCountingSound"; EventType2["SetCrotchetsPerBar"] = "SetCrotchetsPerBar"; + EventType2["SetFont"] = "SetFont"; EventType2["SetForeground"] = "SetForeground"; EventType2["SetGameSound"] = "SetGameSound"; EventType2["SetHandOwner"] = "SetHandOwner"; @@ -103,8 +66,9 @@ var EventType = /* @__PURE__ */ function(EventType2) { EventType2["SetRoomPerspective"] = "SetRoomPerspective"; EventType2["SetRowXs"] = "SetRowXs"; EventType2["SetSpeed"] = "SetSpeed"; + EventType2["SetText"] = "SetText"; EventType2["SetTheme"] = "SetTheme"; - EventType2["SetVFXPreset"] = "SetVFXPreset"; + EventType2["SetVfxPreset"] = "SetVfxPreset"; EventType2["SetVisible"] = "SetVisible"; EventType2["SetWindowContent"] = "SetWindowContent"; EventType2["ShakeScreen"] = "ShakeScreen"; @@ -121,37 +85,24 @@ var EventType = /* @__PURE__ */ function(EventType2) { EventType2["Tile"] = "Tile"; EventType2["Tint"] = "Tint"; EventType2["TintRows"] = "TintRows"; + EventType2["TintText"] = "TintText"; 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 || {}); +})(EventType || {}); var EventInfo = class { defaultTab; durationKey = "duration"; attr; get isDurationEvent() { - return (this.attr & EventAttriblte.DurationEvent) !== 0; + return (this.attr & 1 /* DurationEvent */) !== 0; } get isRoomEvent() { - return (this.attr & EventAttriblte.RoomEvent) !== 0; + return (this.attr & 2 /* RoomEvent */) !== 0; } constructor(tab, enumAttriblte, durationKey) { this.defaultTab = tab; - this.attr = enumAttriblte ?? EventAttriblte.None; + this.attr = enumAttriblte ?? 0 /* None */; this.durationKey = durationKey ?? "duration"; } }; @@ -193,89 +144,210 @@ var WordInfos = { 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") + AddClassicBeat: new EventInfo("Rows" /* Rows */), + AddFreeTimeBeat: new EventInfo("Rows" /* Rows */), + AddOneshotBeat: new EventInfo("Rows" /* Rows */), + AdvanceText: new EventInfo( + "Actions" /* Actions */, + 1 /* DurationEvent */ | 2 /* RoomEvent */, + "duration" + ), + AdvanceTextDecoration: new EventInfo( + "Sprites" /* Decorations */, + 1 /* DurationEvent */, + "duration" + ), + BassDrop: new EventInfo("Actions" /* Actions */, 2 /* RoomEvent */), + Blend: new EventInfo("Sprites" /* Decorations */), + CallCustomMethod: new EventInfo("Actions" /* Actions */), + ChangeCharacter: new EventInfo("Actions" /* Actions */), + ChangePlayersRows: new EventInfo("Actions" /* Actions */), + Comment: new EventInfo("Sounds" /* Sounds */), + CustomFlash: new EventInfo( + "Actions" /* Actions */, + 1 /* DurationEvent */ | 2 /* RoomEvent */, + "duration" + ), + DesktopColor: new EventInfo( + "Windows" /* Windows */, + 1 /* DurationEvent */, + "duration" + ), + FadeRoom: new EventInfo( + "Rooms" /* Rooms */, + 1 /* DurationEvent */, + "duration" + ), + FinishLevel: new EventInfo("Actions" /* Actions */), + Flash: new EventInfo("Actions" /* Actions */, 2 /* RoomEvent */), + FlipScreen: new EventInfo("Actions" /* Actions */, 2 /* RoomEvent */), + FloatingText: new EventInfo( + "Actions" /* Actions */, + 1 /* DurationEvent */ | 2 /* RoomEvent */, + "duration" + ), + ForwardDecorationEvent: new EventInfo("Sprites" /* Decorations */), + ForwardEvent: new EventInfo("Unknown" /* Unknown */, 2 /* RoomEvent */), + ForwardRowEvent: new EventInfo("Rows" /* Rows */), + GoToLevel: new EventInfo("Actions" /* Actions */), + HideRow: new EventInfo("Actions" /* Actions */), + HideWindow: new EventInfo("Windows" /* Windows */), + InvertColors: new EventInfo("Actions" /* Actions */, 2 /* RoomEvent */), + LinkRows: new EventInfo("Actions" /* Actions */), + MaskRoom: new EventInfo("Rooms" /* Rooms */), + Move: new EventInfo( + "Sprites" /* Decorations */, + 1 /* DurationEvent */, + "duration" + ), + MoveCamera: new EventInfo( + "Actions" /* Actions */, + 1 /* DurationEvent */ | 2 /* RoomEvent */, + "duration" + ), + MoveRoom: new EventInfo( + "Rooms" /* Rooms */, + 1 /* DurationEvent */, + "duration" + ), + MoveRow: new EventInfo( + "Actions" /* Actions */, + 1 /* DurationEvent */, + "duration" + ), + NarrateRowInfo: new EventInfo("Sounds" /* Sounds */), + NewWindowDance: new EventInfo( + "Windows" /* Windows */, + 1 /* DurationEvent */, + "duration" + ), + PaintHands: new EventInfo( + "Actions" /* Actions */, + 1 /* DurationEvent */ | 2 /* RoomEvent */, + "duration" + ), + PlayAnimation: new EventInfo("Sprites" /* Decorations */), + PlayExpression: new EventInfo("Actions" /* Actions */), + PlaySong: new EventInfo("Sounds" /* Sounds */), + PlaySound: new EventInfo("Sounds" /* Sounds */), + PulseCamera: new EventInfo("Actions" /* Actions */, 2 /* RoomEvent */), + PulseFreeTimeBeat: new EventInfo("Rows" /* Rows */), + ReadNarration: new EventInfo("Sounds" /* Sounds */), + RenameWindow: new EventInfo("Windows" /* Windows */), + ReorderDecoration: new EventInfo("Sprites" /* Decorations */), + ReorderRooms: new EventInfo("Rooms" /* Rooms */), + ReorderRow: new EventInfo("Actions" /* Actions */), + ReorderWindows: new EventInfo("Windows" /* Windows */), + SayReadyGetSetGo: new EventInfo("Sounds" /* Sounds */, 2 /* RoomEvent */), + SetBackgroundColor: new EventInfo( + "Actions" /* Actions */, + 1 /* DurationEvent */ | 2 /* RoomEvent */, + "duration" + ), + SetBeatSound: new EventInfo("Sounds" /* Sounds */), + SetBeatsPerMinute: new EventInfo("Sounds" /* Sounds */), + SetClapSounds: new EventInfo("Sounds" /* Sounds */), + SetCountingSound: new EventInfo("Sounds" /* Sounds */), + SetCrotchetsPerBar: new EventInfo("Sounds" /* Sounds */), + SetFont: new EventInfo("Sprites" /* Decorations */), + SetForeground: new EventInfo( + "Actions" /* Actions */, + 1 /* DurationEvent */ | 2 /* RoomEvent */, + "duration" + ), + SetGameSound: new EventInfo("Sounds" /* Sounds */), + SetHandOwner: new EventInfo("Actions" /* Actions */, 2 /* RoomEvent */), + SetHeartExplodeInterval: new EventInfo("Sounds" /* Sounds */), + SetHeartExplodeVolume: new EventInfo("Sounds" /* Sounds */), + SetMainWindow: new EventInfo("Windows" /* Windows */), + SetOneshotWave: new EventInfo("Rows" /* Rows */), + SetPlayStyle: new EventInfo("Actions" /* Actions */), + SetRoomContentMode: new EventInfo("Rooms" /* Rooms */), + SetRoomPerspective: new EventInfo( + "Rooms" /* Rooms */, + 1 /* DurationEvent */, + "duration" + ), + SetRowXs: new EventInfo("Rows" /* Rows */), + SetSpeed: new EventInfo( + "Actions" /* Actions */, + 1 /* DurationEvent */, + "duration" + ), + SetText: new EventInfo( + "Actions" /* Actions */, + 1 /* DurationEvent */ | 2 /* RoomEvent */, + "duration" + ), + SetTheme: new EventInfo( + "Actions" /* Actions */, + 1 /* DurationEvent */ | 2 /* RoomEvent */, + "duration" + ), + SetVfxPreset: new EventInfo( + "Actions" /* Actions */, + 1 /* DurationEvent */ | 2 /* RoomEvent */, + "duration" + ), + SetVisible: new EventInfo("Sprites" /* Decorations */), + SetWindowContent: new EventInfo( + "Windows" /* Windows */, + 1 /* DurationEvent */, + "duration" + ), + ShakeScreen: new EventInfo("Actions" /* Actions */, 2 /* RoomEvent */), + ShakeScreenCustom: new EventInfo( + "Actions" /* Actions */, + 1 /* DurationEvent */ | 2 /* RoomEvent */, + "duration" + ), + ShowDialogue: new EventInfo("Actions" /* Actions */, 2 /* RoomEvent */), + ShowHands: new EventInfo("Actions" /* Actions */, 2 /* RoomEvent */), + ShowRooms: new EventInfo( + "Rooms" /* Rooms */, + 1 /* DurationEvent */ | 2 /* RoomEvent */, + "duration" + ), + ShowStatusSign: new EventInfo( + "Actions" /* Actions */, + 1 /* DurationEvent */, + "duration" + ), + ShowSubdivisionsRows: new EventInfo("Actions" /* Actions */), + SpinningRows: new EventInfo( + "Actions" /* Actions */, + 1 /* DurationEvent */ | 2 /* RoomEvent */, + "duration" + ), + Stutter: new EventInfo("Actions" /* Actions */, 2 /* RoomEvent */), + TagAction: new EventInfo("Actions" /* Actions */), + TextExplosion: new EventInfo("Actions" /* Actions */, 2 /* RoomEvent */), + Tile: new EventInfo( + "Sprites" /* Decorations */, + 1 /* DurationEvent */, + "duration" + ), + Tint: new EventInfo( + "Sprites" /* Decorations */, + 1 /* DurationEvent */, + "duration" + ), + TintRows: new EventInfo( + "Actions" /* Actions */, + 1 /* DurationEvent */ | 2 /* RoomEvent */, + "duration" + ), + TintText: new EventInfo( + "Sprites" /* Decorations */, + 1 /* DurationEvent */, + "duration" + ), + Unknown: new EventInfo("Unknown" /* Unknown */), + WindowResize: new EventInfo( + "Windows" /* Windows */, + 1 /* DurationEvent */ | 2 /* RoomEvent */, + "duration" + ) }; var Point = class _Point { x = 0; @@ -498,7 +570,9 @@ var Color = class _Color { 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("")); + 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(); @@ -554,7 +628,7 @@ var SliceInfo = class { } }; -// assetManager.ts +// D:/CSharp/RhythmBase.View/RhythmBase.View/assetManager.ts var assetFilePath = "assets.png"; var slicesFilePath = "assets.bin"; var directoryPath = "./rdviewAssets"; @@ -569,7 +643,13 @@ async function readFromStream(stream) { const sliceInfo = new SliceInfo(); const keyLength = stream.getUint8(offset); offset += 1; - const key = new TextDecoder().decode(new Uint8Array(stream.buffer, offset, keyLength)); + const key = new TextDecoder().decode( + new Uint8Array( + stream.buffer, + offset, + keyLength + ) + ); offset += keyLength; const left = stream.getUint8(offset); offset += 1; @@ -589,7 +669,12 @@ async function readFromStream(stream) { const centerTop = centerByte >> 2 & 3; const centerWidth = centerByte >> 4 & 3; const centerHeight = centerByte >> 6 & 3; - sliceInfo.center = new Rect(centerLeft, centerTop, centerWidth, centerHeight); + sliceInfo.center = new Rect( + centerLeft, + centerTop, + centerWidth, + centerHeight + ); } if (hasPivot) { const pivotByte = stream.getUint8(offset); @@ -609,11 +694,17 @@ async function readFromStream(stream) { return sliceInfos; } var assetLoaded = false; -var slices = await readFromStream(new DataView(await (await fetch(directoryPath + "/" + slicesFilePath)).arrayBuffer())).finally(() => { +var slices = await readFromStream( + new DataView( + await (await fetch( + directoryPath + "/" + slicesFilePath + )).arrayBuffer() + ) +).finally(() => { assetLoaded = true; }); -// rdtkview.ts +// D:/CSharp/RhythmBase.View/RhythmBase.View/rdtkview.ts var lineHeight = 6; var charHeight = 8; var iconSize = 14; @@ -661,18 +752,8 @@ function createLayerFromBackground(key, bound, color, style, backgroundRepeat = 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 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]; @@ -691,7 +772,9 @@ function createLayerFromBackground(key, bound, color, style, backgroundRepeat = 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"); + const patchLayer = document.createElement( + "div" + ); patchLayer.filterData = new FilterData(); patchLayer.updateFilter = () => { patchLayer.style.filter = patchLayer.filterData.getFilter(); @@ -710,7 +793,9 @@ function createLayerFromBackground(key, bound, color, style, backgroundRepeat = } } } else { - const patchLayer = document.createElement("div"); + const patchLayer = document.createElement( + "div" + ); patchLayer.filterData = new FilterData(); patchLayer.updateFilter = () => { patchLayer.style.filter = patchLayer.filterData.getFilter(); @@ -770,7 +855,6 @@ function createLayerFromBackground(key, bound, color, style, backgroundRepeat = 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; @@ -797,9 +881,7 @@ function createLayerFromBackground(key, bound, color, style, backgroundRepeat = layer.onColorChange(color); } else { } - return [ - layer - ]; + return [layer]; } } var colorMatrixIds = /* @__PURE__ */ new Map(); @@ -809,14 +891,45 @@ function getColorMatrixId(rgba) { if (colorMatrixIds.has(rgba.toUint32())) { return colorMatrixIds.get(rgba.toUint32()); } - const feColorMatrix = document.createElementNS("http://www.w3.org/2000/svg", "feColorMatrix"); + 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"); + feColorMatrix.setAttribute( + "values", + [ + r, + 0, + 0, + 0, + 0, + 0, + g, + 0, + 0, + 0, + 0, + 0, + b, + 0, + 0, + 0, + 0, + 0, + a, + 0 + ].join(" ") + ); + feColorMatrix.setAttribute("color-interpolation-filters", "sRGB"); + 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"); @@ -842,25 +955,32 @@ function measureRDFontText(text) { } return len; } -function createRDFontLayer(text, style, color) { - const lineHead = new Point(0, -charHeight); - const start = lineHead.clone(); +function createRDFontLayer(text, destX, destY, style, color, textScale = 1, canvasScale = 1) { 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); + const start = new Point(destX, destY - lineHeight * textScale); + const devScale = textScale * style.scale * canvasScale; + if (devScale > 0) { + for (let i = 0; i < text.length; i++) { + const char = text.charAt(i); + if (char === "\n") { + start.x = destX; + start.y += lineHeight * textScale; + } 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 / textScale, start.y / textScale), + color, + { ...style, scale: devScale } + ); + start.x += charInfo.bounds.width * textScale; + charLayers.push(...charLayer); + } } } } @@ -874,39 +994,78 @@ function createRDFontLayer(text, style, color) { }); return layer; } +function createImageLayer(path, info, color, style) { + const layer = document.createElement("div"); + layer.filterData = new FilterData(); + layer.updateFilter = () => { + layer.style.filter = layer.filterData.getFilter(); + }; + layer.style.position = "absolute"; + layer.style.left = `${-info.pivot.x * style.scale}px`; + layer.style.top = `${-info.pivot.y * style.scale}px`; + layer.style.width = `${info.bounds.width * style.scale}px`; + layer.style.height = `${info.bounds.height * style.scale}px`; + layer.style.backgroundSize = "100% 100%"; + layer.style.backgroundRepeat = "no-repeat"; + const overlay = color && !Color.White.equals(color) ? `linear-gradient(${color.toRgbaString()}, ${color.toRgbaString()}), ` : ""; + layer.style.backgroundImage = `${overlay}url(${path})`; + 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); + 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)); + 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); + 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)); + layer.onStateChange = (style2) => layer.onColorChange( + new Color(style2.active ? 4294967295 : 4289243304) + ); } }); - return [ - ...backLayer, - ...outlineLayer - ]; + return [...backLayer, ...outlineLayer]; } function colorOf(tab) { switch (tab) { - case Tab.Sounds: + case "Sounds" /* Sounds */: return new Color("d92433"); - case Tab.Rows: + case "Rows" /* Rows */: return new Color("2c4fdb"); - case Tab.Actions: + case "Actions" /* Actions */: return new Color("c544b3"); - case Tab.Rooms: + case "Rooms" /* Rooms */: return new Color("d8b811"); - case Tab.Decorations: + case "Sprites" /* Decorations */: return new Color("00c459"); - case Tab.Windows: + case "Windows" /* Windows */: return new Color("50b5d7"); default: return new Color("7d7d7d"); @@ -955,14 +1114,13 @@ function createHintLayer(hint, width, color) { return hintLayer; } function createElementEvent(obj, style) { - style = { - ...new IconStyle(), - ...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`); + console.warn( + obj.type ? `Unknown event type: ${obj.type}` : `Event type missing` + ); } if (!slices.has(key0)) { if (!slices.has("event_Unknown")) { @@ -970,13 +1128,13 @@ function createElementEvent(obj, style) { } key0 = "event_Unknown"; } - const evttype = obj.type ?? EventType.Unknown; + const evttype = obj.type ?? "Unknown" /* 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 evinfo = EventInfos[evttype] ?? EventInfos["Unknown" /* Unknown */]; const key = "event_" + evttype; const pulse = "event_beat_pulse"; const hit = "event_beat_hit"; @@ -992,46 +1150,67 @@ function createElementEvent(obj, style) { const beatColor = new Color(4284539717); let iconWidth = iconSize; const element = document.createElement("div"); - element.eventStyle = { - ...style - }; + element.eventStyle = { ...style }; const layersToAdd = []; element.style.imageRendering = "pixelated"; switch (evttype) { - case EventType.AddClassicBeat: + case "AddClassicBeat" /* 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 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) : []; + 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 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); + 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); + 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: + case "AddOneshotBeat" /* AddOneshotBeat */: { const tick = obj.tick ?? 1; const interval = obj.interval ?? 2; @@ -1044,24 +1223,67 @@ function createElementEvent(obj, style) { 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 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) : []; + const holdLayer = hold && holdWidth - subdivWidth > 0 ? createLayerFromBackground( + evbarea, + new Rect( + eventWidth + subdivWidth, + 0, + holdWidth - subdivWidth, + iconSize + ), + new Color(4291839731), + 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) : []; + const subdivLayer = subdiv > 1 ? createLayerFromBackground( + evbarea, + new Rect(eventWidth, 0, subdivWidth, iconSize), + new Color(4279480353), + 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) : []; + const skipshotLayer = skip ? createLayerFromBackground( + evbarea, + new Rect( + eventWidth + Math.max(subdivWidth, holdWidth), + 0, + iconSize * (interval - delay) - Math.max(subdivWidth, holdWidth), + iconSize + ), + new Color(4291115835), + 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) : []; + const skipHitLayer = skip ? createLayerFromBackground( + evbskip, + new Point( + eventWidth + iconSize * (interval - delay) - 1, + 0 + ), + null, + style + ) : []; skipHitLayer.forEach((layer) => { layer.style.pointerEvents = "none"; return layer; @@ -1072,33 +1294,76 @@ function createElementEvent(obj, style) { 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); + 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); + 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) : []; + const crossLayer1 = mode || hold ? createLayerFromBackground( + beatcross, + new Point(iconSize * (l * interval - off) - 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) : []; + const crossLayer2 = mode ? createLayerFromBackground( + beatcross, + new Point( + iconSize * (l * interval - off + (mode === "Freezeshot" ? delay : -tick)) + (mode === "Freezeshot" ? -1 : 0), + 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) : []; + 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); + const loopLayer = createLayerFromBackground( + "event_beat_loop", + new Point( + eventWidth, + 0 + ), + null, + style + ); loopLayer.forEach((loopLayer2) => { loopLayer2.style.opacity = "0"; loopLayer2.style.zIndex = "5"; @@ -1121,57 +1386,134 @@ function createElementEvent(obj, style) { layersToAdd.push(...crossLayers); } break; - case EventType.AddFreeTimeBeat: + case "AddFreeTimeBeat" /* 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) : []; + 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`; + 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(), + 1.5, + 10, + style, + Color.White + ); layersToAdd.push(...holdLayer); layersToAdd.push(...backLayers2); layersToAdd.push(...hitLayer); layersToAdd.push(textLayer); } break; - case EventType.Comment: + case "Comment" /* Comment */: { - const backLayers2 = createBackLayer(slcinfo.bounds.size, new Color(obj.color ?? "7d7d7d"), style); - const iconLayer = createLayerFromBackground(key, null, null, style); + 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: + case "DesktopColor" /* 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); + 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: + case "PulseFreeTimeBeat" /* 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) : []; + 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) : []; + const backLayers2 = createBackLayer( + new Size(slcinfo.bounds.width, slcinfo.bounds.height), + beatColor, + style + ); + const customPulse = Number(obj.customPulse ?? 0); + const hitInfo = slices.get(hit); + const hitHeight = slcinfo.bounds.height; + const hitWidth = hitInfo ? hitInfo.bounds.width * (hitHeight / hitInfo.bounds.height) : hitHeight; + const hitTop = (slcinfo.bounds.height - hitHeight) / 2; + const hitLayer = obj.action === "Custom" && customPulse === 6 ? createLayerFromBackground( + hit, + new Rect( + 0, + hitTop, + hitWidth, + hitHeight + ), + null, + style + ) : []; let text = ""; switch (obj.action) { case "Custom": - text = ((obj.customPulse ?? 0) + 1).toString(); + text = (customPulse + 1).toString(); break; case "Increment": text = ">"; @@ -1183,29 +1525,37 @@ function createElementEvent(obj, style) { text = "x"; break; } - const textLayer = createRDFontLayer(text, style, null); - textLayer.style.left = `${1.5 * style.scale}px`; - textLayer.style.top = `${10 * style.scale}px`; + const textLayer = createRDFontLayer( + text, + 1.5, + 8, + style, + Color.White + ); layersToAdd.push(...holdLayer); layersToAdd.push(...backLayers2); layersToAdd.push(...hitLayer); layersToAdd.push(textLayer); } break; - case EventType.ReorderRooms: - case EventType.ReorderWindows: + case "ReorderRooms" /* ReorderRooms */: + case "ReorderWindows" /* ReorderWindows */: { - const backLayers2 = createBackLayer(slcinfo.bounds.size, colorOf(obj.tab ?? evinfo.defaultTab), style); + const backLayers2 = createBackLayer( + slcinfo.bounds.size, + colorOf(obj.tab ?? evinfo.defaultTab), + style + ); const orderLayers = []; - const order = obj.order ?? [ - 0, - 1, - 2, - 3 - ]; - for (let i = 0; i < order.length; i++) { + const order = obj.order ?? [0, 1, 2, 3]; + for (let i = 0; i < Math.min(order.length, 4); i++) { { - const orderLayer = createLayerFromBackground(`${key}_${order[i]}`, new Point(0, i * iconSize), null, style); + const orderLayer = createLayerFromBackground( + `${key}_${order[i]}`, + new Point(0, i * iconSize), + null, + style + ); orderLayers.push(...orderLayer); } } @@ -1213,48 +1563,55 @@ function createElementEvent(obj, style) { layersToAdd.push(...orderLayers); } break; - case EventType.SayReadyGetSetGo: + case "SayReadyGetSetGo" /* SayReadyGetSetGo */: { - const wordInfo = WordInfos[obj.phraseToSay ?? SayReadyGetSetGoWords.JustSayGo]; + const wordInfo = WordInfos[obj.phraseToSay ?? "JustSayGo" /* JustSayGo */]; const len = wordInfo.length * (obj.tick ?? 0) + 1; iconWidth = len * iconSize; const stringToJoin = wordInfo.phrase.split(" "); - const stringToDraw = [ - stringToJoin[0] - ]; + 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 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) { + if (lw + w + sw > (len * iconSize * 2 - 2) * style.scale) { lw = w; stringToDraw.push(part); } else { - lw += sw + w; + lw += w + sw; stringToDraw[stringToDraw.length - 1] += " " + part; } } const c = Math.min(stringToDraw.length, 3); - let top = iconSize / 2 - charHeight * c / 4 + 1; + const textScale = Math.trunc(style.scale / 2); + const top = (iconSize - charHeight * c / 2) * style.scale / 2; 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`; + const px = (len * iconSize * 2 - measureRDFontText(line) * textScale) / 2; + const py = top + (i * charHeight + lineHeight) * style.scale / 2; + const wordLayer = createRDFontLayer( + line, + px, + py, + style, + Color.White, + textScale, + 0.5 + ); wordLayers.push(wordLayer); } layersToAdd.push(...backLayers2); layersToAdd.push(...wordLayers); } break; - case EventType.SetRowXs: + case "SetRowXs" /* SetRowXs */: { const syncoBeat = obj.syncoBeat ?? -1; const width = slcinfo.bounds.width / 6; @@ -1263,30 +1620,55 @@ function createElementEvent(obj, style) { 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); + 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); + 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) : []; + 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: + case "ShowRooms" /* ShowRooms */: { - const backLayers2 = createBackLayer(new Size(iconSize, iconSize * 4), colorOf(obj.tab ?? evinfo.defaultTab), style); + const backLayers2 = createBackLayer( + new Size(iconSize, iconSize * 4), + colorOf(obj.tab ?? evinfo.defaultTab), + style + ); const roomLayers = []; for (let i = 0; i < 4; i++) { - const roomLayer = createLayerFromBackground(`${key}_${(obj.rooms ?? []).indexOf(i) >= 0 ? "1" : "0"}`, new Point(0, i * iconSize * style.scale), null, { - ...style, - scale: style.scale / 2 - }); + 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); @@ -1294,43 +1676,77 @@ function createElementEvent(obj, style) { } break; default: - const backLayers = createBackLayer(slcinfo.bounds.size, colorOf(obj.tab ?? evinfo.defaultTab), style); + 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); + case "CustomFlash" /* 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: + case "FlipScreen" /* FlipScreen */: { const flip = (obj.flipX ? 1 : 0) | (obj.flipY ? 2 : 0); - const iconLayer2 = createLayerFromBackground(flip === 0 ? `${key}_0` : `${key}_${flip - 1}`, null, null, style); + const iconLayer2 = createLayerFromBackground( + flip === 0 ? `${key}_0` : `${key}_${flip - 1}`, + null, + null, + style + ); layersToAdd.push(...iconLayer2); } break; - case EventType.FloatingText: + case "FloatingText" /* 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); + 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: + case "MoveRoom" /* MoveRoom */: { - obj.scale ??= [ - null, - null - ]; + obj.scale ??= [null, null]; const hasPivot = obj.pivot !== void 0; - obj.pivot ??= [ - null, - null - ]; + 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; @@ -1338,10 +1754,22 @@ function createElementEvent(obj, style) { 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); + 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); + 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; @@ -1352,7 +1780,9 @@ function createElementEvent(obj, style) { 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"); + const pointLayer = document.createElement( + "div" + ); pointLayer.style.position = "absolute"; pointLayer.style.width = `${style.scale}px`; pointLayer.style.height = `${style.scale}px`; @@ -1363,86 +1793,186 @@ function createElementEvent(obj, style) { } } break; - case EventType.PaintHands: - case EventType.Tint: - case EventType.TintRows: + case "SetText" /* SetText */: + { + const textColorLayer = createLayerFromBackground( + `${key}_0`, + null, + Color.FromRgba(obj.color ?? "FFFFFFFF"), + style + ); + const outlineColorLayer = createLayerFromBackground( + `${key}_1`, + null, + Color.FromRgba( + obj.outlineColor ?? "FFFFFFFF" + ), + style + ); + layersToAdd.push(...textColorLayer); + layersToAdd.push(...outlineColorLayer); + } + break; + case "PaintHands" /* PaintHands */: + case "Tint" /* Tint */: + case "TintRows" /* 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) : []; + 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: + case "TintText" /* TintText */: + { + const tintColorLayer = createLayerFromBackground( + `${key}_0`, + null, + obj.tintColor ? Color.FromRgba(obj.tintColor) : Color.White, + style + ); + const borderColorLayer = obj.borderColor ? createLayerFromBackground( + `${key}_1`, + null, + Color.FromRgba(obj.borderColor), + style + ) : []; + layersToAdd.push(...tintColorLayer); + layersToAdd.push(...borderColorLayer); + } + break; + case "SetBackgroundColor" /* SetBackgroundColor */: { const backType = obj.backgroundType ?? "Color"; - const iconLayer2 = createLayerFromBackground(key, null, null, style); + const iconLayer2 = createLayerFromBackground( + key, + null, + null, + style + ); const images = obj.image ?? []; const imagePath = images.length > 0 ? images[0] : ""; const contentInfo = slices.get(`${key}_1`); - const colorLayer = 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; - }); + const colorLayer = createLayerFromBackground( + `${key}_0`, + null, + Color.FromRgba( + (backType === "Color" ? obj.color : null) ?? "FFFFFF" + ), + style + ); + const contentLayer = backType === "Image" && imagePath && contentInfo ? [ + createImageLayer( + imagePath, + contentInfo, + Color.FromRgba( + obj.color ?? "FFFFFFFF" + ), + style + ) + ] : []; layersToAdd.push(...iconLayer2); layersToAdd.push(...colorLayer); layersToAdd.push(...contentLayer); } break; - case EventType.SetCrotchetsPerBar: + case "SetCrotchetsPerBar" /* 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`; + const iconLayer2 = createLayerFromBackground( + key, + null, + null, + style + ); + const cpbLayer = createRDFontLayer( + cpb > 9 ? "-" : cpb.toString(), + 2, + 7, + style, + Color.Black + ); + const bLayer = createRDFontLayer( + "4", + 8, + 12, + style, + Color.Black + ); layersToAdd.push(...iconLayer2); layersToAdd.push(cpbLayer); layersToAdd.push(bLayer); } break; - case EventType.SetForeground: + case "SetForeground" /* SetForeground */: { - const iconLayer2 = createLayerFromBackground(key, null, null, style); + const iconLayer2 = createLayerFromBackground( + key, + null, + null, + style + ); const images = obj.image ?? []; const imagePath = images.length > 0 ? images[0] : ""; const contentInfo = slices.get(`${key}_1`); - const colorLayer = imagePath ? 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; - }); + const contentLayer = imagePath && contentInfo ? [ + createImageLayer( + imagePath, + contentInfo, + Color.FromRgba( + obj.color ?? "FFFFFFFF" + ), + style + ) + ] : []; layersToAdd.push(...iconLayer2); - layersToAdd.push(...colorLayer); layersToAdd.push(...contentLayer); } break; default: - const layer = createLayerFromBackground(hasType ? key : "event_Unknown", null, null, style); + const layer = createLayerFromBackground( + key0, + null, + null, + style + ); layersToAdd.push(...layer); break; } break; } - if (evinfo.isDurationEvent) { + if (evinfo.isDurationEvent && style.enabled) { 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) : []; + const durationLayer = (style.active || duration > 1) && durWidth > slcinfo.bounds.width ? createLayerFromBackground( + evbarea, + new Rect( + slcinfo.bounds.width, + 0, + durWidth - slcinfo.bounds.width, + slcinfo.bounds.height + ), + colorOf(obj.tab ?? evinfo.defaultTab).withAlpha( + style.active ? 192 : 91 + ), + style, + true + ) : []; durationLayer.forEach((layer) => { layer.style.pointerEvents = "none"; layerHoverInit(layer); @@ -1456,10 +1986,20 @@ function createElementEvent(obj, style) { 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); + 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) : []; + const roomTopLayer = rooms.indexOf(4) > -1 ? createLayerFromBackground( + `room_top`, + new Point(iconWidth, 0), + roomEnabled, + style + ) : []; roomLayers.push(...roomTopLayer); roomLayers.forEach((roomLayer) => { if (roomLayer) { @@ -1472,41 +2012,79 @@ function createElementEvent(obj, style) { 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)); + hintLayer = createHintLayer( + obj.type && obj.type.toString().length > 0 ? `Error: Unknown type: ${obj.type}` : "Error: Type missing", + slcinfo.bounds.width * style.scale, + colorOf(obj.tab ?? evinfo.defaultTab) + ); } break; } @@ -1514,14 +2092,12 @@ function createElementEvent(obj, style) { layersToAdd.push(hintLayer); } if (obj["$style"]) { - const hsb = obj["$style"].hsb ?? [ - 0, - 1, - 1 - ]; + 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; + if (!layer.filterData) { + return; + } layer.filterData.hue = hsb[0]; layer.filterData.saturation = hsb[1]; layer.filterData.brightness = hsb[2]; @@ -1532,9 +2108,7 @@ function createElementEvent(obj, style) { }); } element.onStateChange = (style2) => { - style2 = { - ...style2 - }; + style2 = { ...style2 }; layersToAdd.forEach((layer) => { if (layer.onStateChange) { layer.onStateChange(style2); diff --git a/script/rdview-init.js b/script/rdview-init.js new file mode 100644 index 0000000..4a6a81c --- /dev/null +++ b/script/rdview-init.js @@ -0,0 +1,5 @@ +import "./rdview.js"; +import "./rdtkview_render.js"; +import "./rdview_render.js"; + +window.loadRDView(); diff --git a/script/rdview.js b/script/rdview.js index fda7705..098fa68 100644 --- a/script/rdview.js +++ b/script/rdview.js @@ -1,124 +1,4 @@ -"use strict"; -var tilePosition = { - "events": { - "sounds": [ - { "name": "Empty", "position": [0, 0, 1, 1] }, - { "name": "SetCrotchetsPerBar_1", "position": [0, 1, 1, 1] }, - { "name": "SetCrotchetsPerBar_2", "position": [1, 1, 1, 1] }, - { "name": "SetCrotchetsPerBar_3", "position": [2, 1, 1, 1] }, - { "name": "SetCrotchetsPerBar_4", "position": [3, 1, 1, 1] }, - { "name": "SetCrotchetsPerBar_5", "position": [4, 1, 1, 1] }, - { "name": "SetCrotchetsPerBar_6", "position": [5, 1, 1, 1] }, - { "name": "SetCrotchetsPerBar_7", "position": [6, 1, 1, 1] }, - { "name": "SetCrotchetsPerBar_8", "position": [7, 1, 1, 1] }, - { "name": "SetCrotchetsPerBar_9", "position": [8, 1, 1, 1] }, - { "name": "SetCrotchetsPerBar", "position": [9, 2, 1, 1] }, - { "name": "SayReadyGetSetGo_1", "position": [0, 2, 1, 1] }, - { "name": "SayReadyGetSetGo_2", "position": [1, 2, 1, 1] }, - { "name": "SayReadyGetSetGo_3", "position": [2, 2, 1, 1] }, - { "name": "SayReadyGetSetGo_4", "position": [3, 2, 1, 1] }, - { "name": "SayReadyGetSetGo_5", "position": [4, 2, 1, 1] }, - { "name": "SayReadyGetSetGo_6", "position": [5, 2, 1, 1] }, - { "name": "SayReadyGetSetGo_7", "position": [6, 2, 1, 1] }, - { "name": "SayReadyGetSetGo_8", "position": [7, 2, 1, 1] }, - { "name": "SayReadyGetSetGo_9", "position": [8, 2, 1, 1] }, - { "name": "SayReadyGetSetGo_10", "position": [9, 2, 1, 1] }, - { "name": "PlaySong", "position": [0, 3, 2, 1] }, - { "name": "PlaySound", "position": [2, 3, 1, 1] }, - { "name": "SetBeatsPerMinute", "position": [3, 3, 1, 1] }, - { "name": "SetClapSounds", "position": [4, 3, 1, 1] }, - { "name": "SetHeartExplodeVolume", "position": [5, 3, 1, 1] }, - { "name": "SetHeartExplodeInterval", "position": [6, 3, 1, 1] }, - { "name": "SetGameSound", "position": [7, 3, 1, 1] }, - { "name": "SetBeatSound", "position": [8, 3, 1, 1] }, - { "name": "SetCountingSound", "position": [9, 3, 1, 1] }, - { "name": "SayReadyGetSetGo_Rea", "position": [1, 0, 1, 1] }, - { "name": "SayReadyGetSetGo_Dy", "position": [2, 0, 1, 1] }, - { "name": "SayReadyGetSetGo_Get", "position": [3, 0, 1, 1] }, - { "name": "SayReadyGetSetGo_Set", "position": [4, 0, 1, 1] }, - { "name": "SayReadyGetSetGo_Go", "position": [5, 0, 1, 1] }, - { "name": "SayReadyGetSetGo_Ready", "position": [10, 0, 1, 1] }, - { "name": "SayReadyGetSetGo_And", "position": [10, 1, 1, 1] }, - { "name": "SayReadyGetSetGo_GetSetGo", "position": [11, 0, 3, 1] }, - { "name": "SayReadyGetSetGo_GetSetOne", "position": [11, 1, 3, 1] }, - { "name": "SayReadyGetSetGo_Stop", "position": [14, 0, 1, 1] }, - { "name": "SayReadyGetSetGo_AndStop", "position": [14, 1, 1, 1] }, - { "name": "SayReadyGetSetGo_ReaDyGetSetGo", "position": [10, 2, 5, 1] }, - { "name": "SayReadyGetSetGo_ReaDyGetSetOne", "position": [10, 3, 5, 1] }, - { "name": "Comment", "position": [15, 0, 1, 1] } - ], - "rows": [ - { "name": "Empty", "position": [0, 0, 1, 1] }, - { "name": "SetOneshotWave", "position": [1, 0, 1, 1] } - ], - "actions": [ - { "name": "Empty", "position": [0, 0, 1, 1] }, - { "name": "SetTheme", "position": [1, 0, 1, 1] }, - { "name": "SetVFXPreset", "position": [2, 0, 1, 1] }, - { "name": "SetBackgroundColor", "position": [3, 0, 1, 1] }, - { "name": "SetForeground", "position": [4, 0, 1, 1] }, - { "name": "SetSpeed", "position": [5, 0, 1, 1] }, - { "name": "Flash", "position": [6, 0, 1, 1] }, - { "name": "CustomFlash", "position": [7, 0, 1, 1] }, - { "name": "NewWindowDance", "position": [8, 0, 1, 1] }, - { "name": "MoveCamera", "position": [0, 1, 1, 1] }, - { "name": "PulseCamera", "position": [1, 1, 1, 1] }, - { "name": "TextExplosion", "position": [2, 1, 1, 1] }, - { "name": "ShowDialogue", "position": [3, 1, 1, 1] }, - { "name": "ShowStatusSign", "position": [4, 1, 1, 1] }, - { "name": "FloatingText", "position": [5, 1, 1, 1] }, - { "name": "AdvanceText", "position": [6, 1, 0.5, 1] }, - { "name": "ChangePlayersRows", "position": [7, 1, 1, 1] }, - { "name": "Comment", "position": [8, 1, 1, 1] }, - { "name": "FinishLevel", "position": [0, 2, 1, 1] }, - { "name": "Stutter", "position": [1, 2, 1, 1] }, - { "name": "HideRow", "position": [2, 2, 1, 1] }, - { "name": "MoveRow", "position": [3, 2, 1, 1] }, - { "name": "PlayExpression", "position": [4, 2, 1, 1] }, - { "name": "TintRows", "position": [5, 2, 1, 1] }, - { "name": "BassDrop", "position": [6, 2, 1, 1] }, - { "name": "ShakeScreen", "position": [7, 2, 1, 1] }, - { "name": "FlipScreen", "position": [0, 3, 1, 1] }, - { "name": "InvertColors", "position": [1, 3, 1, 1] }, - { "name": "ShowHands", "position": [2, 3, 1, 1] }, - { "name": "PaintHands", "position": [3, 3, 1, 1] }, - { "name": "SetHandOwner", "position": [4, 3, 1, 1] }, - { "name": "SetPlayStyle", "position": [5, 3, 1, 1] }, - { "name": "TagAction", "position": [6, 3, 1, 1] }, - { "name": "CallCustomMethod", "position": [7, 3, 1, 1] } - ], - "decorations": [ - { "name": "Empty", "position": [0, 0, 1, 1] }, - { "name": "PlayAnimation", "position": [1, 0, 1, 1] }, - { "name": "Tint", "position": [0, 1, 1, 1] }, - { "name": "Comment", "position": [1, 1, 1, 1] }, - { "name": "SetVisible", "position": [0, 2, 1, 1] }, - { "name": "Move", "position": [0, 3, 1, 1] } - ], - "rooms": [ - { "name": "Empty", "position": [0, 0, 1, 1] }, - { "name": "MoveRoom", "position": [0, 1, 1, 1] }, - { "name": "FadeRoom", "position": [0, 2, 1, 1] }, - { "name": "MaskRoom", "position": [0, 3, 1, 1] }, - { "name": "ShowRooms", "position": [1, 0, 1, 4] }, - { "name": "ReorderRooms", "position": [2, 0, 1, 4] }, - { "name": "SetRoomContentMode", "position": [3, 0, 1, 1] }, - { "name": "SetRoomPerspective", "position": [3, 1, 1, 1] }, - { "name": "Comment", "position": [3, 2, 1, 1] } - ], - "custom": [ - { "name": "Empty", "position": [0, 0, 1, 1] }, - { "name": "Comment", "position": [0, 1, 1, 1] } - ], - "beatsSpecial": [ - "AddClassicBeat", - "AddOneshotBeat", - "AddFreeTimeBeat", - "PulseFreeTimeBeat", - "SetRowXs" - ] - } -}; +import { createElementEvent } from "./rdtkview.js"; function loadRDView() { window.RDViewRender = RDViewRender; } @@ -131,23 +11,6 @@ class Color { } ; } -var EventType; -(function (EventType) { - EventType["sounds"] = "sounds"; - EventType["rows"] = "rows"; - EventType["actions"] = "actions"; - EventType["decorations"] = "decorations"; - EventType["rooms"] = "rooms"; - EventType["custom"] = "custom"; -})(EventType || (EventType = {})); -var BeatsSpecial; -(function (BeatsSpecial) { - BeatsSpecial[BeatsSpecial["AddClassicBeat"] = 0] = "AddClassicBeat"; - BeatsSpecial[BeatsSpecial["AddFreeTimeBeat"] = 1] = "AddFreeTimeBeat"; - BeatsSpecial[BeatsSpecial["PulseFreeTimeBeat"] = 2] = "PulseFreeTimeBeat"; - BeatsSpecial[BeatsSpecial["AddOneshotBeat"] = 3] = "AddOneshotBeat"; - BeatsSpecial[BeatsSpecial["SetRowXs"] = 4] = "SetRowXs"; -})(BeatsSpecial || (BeatsSpecial = {})); var EventCondition; (function (EventCondition) { EventCondition["true"] = "true"; @@ -156,7 +19,6 @@ var EventCondition; })(EventCondition || (EventCondition = {})); class RDViewWindow { constructor() { - this.Objects = []; this.Row = 4; this.Column = 8; this.Scale = 1; @@ -164,81 +26,18 @@ class RDViewWindow { } class RDEvent { constructor() { - this.SubType = EventType.custom; - this.BeatType = undefined; - this.Width = 1; - this.Height = 1; - this.EventX = 0; - this.EventY = 0; + this.Name = ""; + this.PrefixTab = undefined; + this.Properties = []; this.Style = { Beat: 0, Y: 0 }; } } -class RDDescription { - constructor() { - this.Width = 4; - this.Lines = []; - } -} -class RDDescriptionLine { - constructor() { - this.BoxCount = 1; - this.IconCount = 0; - this.Items = []; - } -} -class RDDescriptionText { - constructor() { - this.Text = ""; - } -} -class RDDescriptionBox { - constructor() { - this.Items = []; - } -} -class RDDescriptionBoxInput { - constructor() { - this.Tips = ""; - this.Text = ""; - } -} -class RDDescriptionBoxScroll { - constructor() { - this.Scroll = 0; - } -} -class RDDescriptionBoxButton { - constructor() { - this.Text = ""; - } -} -class RDDescriptionBoxSelect { - constructor() { - this.Items = []; - this.SelectedIndex = 0; - } -} -class RDDescriptionIcon { -} class RDStyle { constructor() { this.Beat = 0; this.Y = 0; } } -class RDBeatStyle { - constructor() { - this.OneshotBeatSubType = []; - this.RowXs = '------'; - } -} -var RDOneshotBeatSubType; -(function (RDOneshotBeatSubType) { - RDOneshotBeatSubType[RDOneshotBeatSubType["Freezeshot"] = 0] = "Freezeshot"; - RDOneshotBeatSubType[RDOneshotBeatSubType["Burnshot"] = 1] = "Burnshot"; - RDOneshotBeatSubType[RDOneshotBeatSubType["Skipshot"] = 2] = "Skipshot"; - RDOneshotBeatSubType[RDOneshotBeatSubType["Subdivision"] = 3] = "Subdivision"; -})(RDOneshotBeatSubType || (RDOneshotBeatSubType = {})); class RDGroup { constructor() { this.Width = 1; @@ -250,97 +49,72 @@ class RDGroup { } } function RDViewRender(lang, code) { - const lines = code.split('\n'); - const window = new RDViewWindow(); + const view = new RDViewWindow(); var objs = []; try { - window.Objects = ReadObjs(code); + objs = ReadObjs(code); } catch (error) { - return errorHtml(`${error}`); + return ErrorElement(`${error}`); } const args = lang.split(/\s+/g); if (1 < args.length && args.length <= 4) { if (args[1]) { - window.Column = parseInt(args[1]); + view.Column = parseInt(args[1]); } if (args[2]) { - window.Row = parseInt(args[2]); + view.Row = parseInt(args[2]); } if (args[3]) { - window.Scale = parseFloat(args[3]); + view.Scale = parseFloat(args[3]); } } - return ConstructObjs(window); + return ConstructObjs(view, objs); } -function errorHtml(message = "") { - return `
${message.length ? `${message}` : ""}
`; +function ErrorElement(message = "") { + const el = document.createElement("div"); + el.className = "rdtk-error"; + el.textContent = message; + return el; +} +function PrefixToTab(prefix) { + switch (prefix) { + case "es": return "Sounds"; + case "eb": return "Rows"; + case "ea": return "Actions"; + case "ed": return "Sprites"; + case "er": return "Rooms"; + case "ec": return "Unknown"; + default: return undefined; + } } function ReadObjs(line) { const objs = []; var reader = new Reader(line); while (!reader.IsEnd()) { var event; + var name = ""; + var prefix = ""; try { - const type = reader.ReadSymbol().toLowerCase(); - event = ReadType(type); + name = reader.ReadSymbol(); + if (reader.TestRead('.', false)) { + prefix = name; + name = reader.ReadSymbol(); + } } catch (e) { - event = new RDEvent(); + name = ""; + } + if (name.toLowerCase() === 'g') { + event = new RDGroup(); + } + else { + const ev = new RDEvent(); + ev.Name = name; + ev.PrefixTab = PrefixToTab(prefix); + event = ev; } if (event instanceof RDEvent) { - reader.TestRead('.', true); - const name = reader.ReadSymbol(); - var collection; - switch (event.SubType) { - case EventType.sounds: - collection = tilePosition.events.sounds; - break; - case EventType.rows: - collection = tilePosition.events.rows; - switch (name) { - case 'AddClassicBeat': - event.BeatType = BeatsSpecial.AddClassicBeat; - break; - case 'AddFreeTimeBeat': - event.BeatType = BeatsSpecial.AddFreeTimeBeat; - break; - case 'PulseFreeTimeBeat': - event.BeatType = BeatsSpecial.PulseFreeTimeBeat; - break; - case 'AddOneshotBeat': - event.BeatType = BeatsSpecial.AddOneshotBeat; - break; - case 'SetRowXs': - event.BeatType = BeatsSpecial.SetRowXs; - break; - default: - break; - } - break; - case EventType.actions: - collection = tilePosition.events.actions; - break; - case EventType.decorations: - collection = tilePosition.events.decorations; - break; - case EventType.rooms: - collection = tilePosition.events.rooms; - break; - case EventType.custom: - collection = tilePosition.events.custom; - break; - default: - collection = tilePosition.events.custom; - break; - } - const pos = collection.filter(i => i.name.toLowerCase() === name.toLowerCase())[0]; - if (pos) { - event.EventX = pos.position[0]; - event.EventY = pos.position[1]; - event.Width = pos.position[2]; - event.Height = pos.position[3]; - } try { event.Style.Beat = reader.ReadFloat(); } @@ -595,7 +369,7 @@ class Reader { line += this.line; position = this.position; } - return `
at "${s[line]}".`; //, at ${line + 1}:${position - curp}`; + return `
at "${s[line]}".`; } } function FindValue(pairs, key) { @@ -605,78 +379,21 @@ function FindValue(pairs, key) { } return undefined; } -function ReadType(typename) { - var t = EventType.custom; - var event; - switch (typename[0]) { - case 'e': - event = new RDEvent(); - switch (typename[1]) { - case 's': - t = EventType.sounds; - break; - case 'b': - t = EventType.rows; - break; - case 'a': - t = EventType.actions; - break; - case 'd': - t = EventType.decorations; - break; - case 'r': - t = EventType.rooms; - break; - case 'c': - t = EventType.custom; - break; - default: - t = EventType.custom; - } - event.SubType = t; - break; - case 'g': - event = new RDGroup(); - break; - default: - event = new RDEvent(); - } - return event; -} function ReadProperties(reader, event, pairs) { - var _a, _b, _c, _d, _e, _f; + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; if (event instanceof RDGroup) { + var value; if (value = FindValue(pairs, "hue")) { - try { - event.Style.Hue = parseFloat(value.Value); - } - catch (e) { - throw new Error(`Expecting a number, but find "${value.Value}".`); - } + event.Style.Hue = parseFloat(value.Value); } if (value = FindValue(pairs, "brightness")) { - try { - event.Style.Brightness = parseFloat(value.Value); - } - catch (e) { - throw new Error(`Expecting a number, but find "${value.Value}".`); - } + event.Style.Brightness = parseFloat(value.Value); } if (value = FindValue(pairs, "grayscale")) { - try { - event.Style.Grayscale = parseFloat(value.Value); - } - catch (e) { - throw new Error(`Expecting a number, but find "${value.Value}".`); - } + event.Style.Grayscale = parseFloat(value.Value); } if (value = FindValue(pairs, "opacity")) { - try { - event.Style.Opacity = parseFloat(value.Value); - } - catch (e) { - throw new Error(`Expecting a number, but find "${value.Value}".`); - } + event.Style.Opacity = parseFloat(value.Value); } if (value = FindValue(pairs, "offset")) { reader = new Reader(value.Value); @@ -712,281 +429,293 @@ function ReadProperties(reader, event, pairs) { } } else if (event instanceof RDEvent) { - var value; - if (value = FindValue(pairs, "if")) { - if (["true", "false", "both"].find(i => i === (value === null || value === void 0 ? void 0 : value.Value))) { - event.Condition = value.Value === "true" ? EventCondition.true : - value.Value === "false" ? EventCondition.false : EventCondition.both; - } - else { - throw new Error(`Expecting "true", "false" or "both", but find "${value.Value}".`); - } - } - if (value = FindValue(pairs, "tag")) { - event.Tag = value.Value === "true" ? true : false; - } - if (value = FindValue(pairs, "hue")) { - event.Style.Hue = parseFloat(value.Value); - } - if (value = FindValue(pairs, "brightness")) { - event.Style.Brightness = parseFloat(value.Value); - } - if (value = FindValue(pairs, "grayscale")) { - event.Style.Grayscale = parseFloat(value.Value); - } - if (value = FindValue(pairs, "opacity")) { - event.Style.Opacity = parseFloat(value.Value); - } - (_f = event.ClickStyle) !== null && _f !== void 0 ? _f : (event.ClickStyle = new RDStyle()); - if (value = FindValue(pairs, "offset")) { - reader = new Reader(value.Value); - try { - event.ClickStyle.Beat = reader.ReadFloat(); - } - catch (e) { } - try { - event.ClickStyle.Y = reader.ReadInt(); - } - catch (e) { } - } - if (value = FindValue(pairs, "offset_hue")) { - event.ClickStyle.Hue = parseFloat(value.Value); - } - if (value = FindValue(pairs, "offset_brightness")) { - event.ClickStyle.Brightness = parseFloat(value.Value); - } - if (value = FindValue(pairs, "offset_grayscale")) { - event.ClickStyle.Grayscale = parseFloat(value.Value); - } - if (value = FindValue(pairs, "offset_opacity")) { - event.ClickStyle.Opacity = parseFloat(value.Value); - } - if (event.BeatType !== undefined) { - event.BeatStyle = new RDBeatStyle(); - if (value = FindValue(pairs, "tick")) { - event.BeatStyle.Tick = parseFloat(value.Value); - } - switch (event.BeatType) { - case BeatsSpecial.AddClassicBeat: - if (value = FindValue(pairs, "swing")) { - event.BeatStyle.Swing = parseFloat(value.Value); + for (const pair of pairs) { + const key = pair.Key; + const value = pair.Value; + switch (key) { + case "if": + if (["true", "false", "both"].find(i => i === value)) { + event.Condition = value === "true" ? EventCondition.true : + value === "false" ? EventCondition.false : EventCondition.both; } - if (value = FindValue(pairs, "hold")) { - event.BeatStyle.Hold = parseFloat(value.Value); + else { + throw new Error(`Expecting "true", "false" or "both", but find "${value}".`); } break; - case BeatsSpecial.AddFreeTimeBeat: - if (value = FindValue(pairs, "pulse")) { - event.BeatStyle.Pulse = parseFloat(value.Value); - } - if (value = FindValue(pairs, "hold")) { - event.BeatStyle.Hold = parseFloat(value.Value); - } + case "tag": + event.Tag = value === "true"; break; - case BeatsSpecial.PulseFreeTimeBeat: - if (value = FindValue(pairs, "pulse")) { - event.BeatStyle.Pulse = parseFloat(value.Value); - } - if (value = FindValue(pairs, "hold")) { - event.BeatStyle.Hold = parseFloat(value.Value); - } + case "hue": + event.Style.Hue = parseFloat(value); break; - case BeatsSpecial.SetRowXs: - if ((value = FindValue(pairs, "rowxs"))) { - if (value.Value.match(/^[-x]{6}$/)) { - event.BeatStyle.RowXs = value.Value; - } - else { - throw new Error(`Expect a string of length 6, consisting of "x" and "-", instead of "${value === null || value === void 0 ? void 0 : value.Value}".`); - } - } + case "brightness": + event.Style.Brightness = parseFloat(value); break; - case BeatsSpecial.AddOneshotBeat: - if (value = FindValue(pairs, "type")) { - const types = value.Value.split(/\s+/); - var illegal; - if ((illegal = types.filter(i => { - ![ - "freezeshot", - "burnshot", - "skipshot", - "subdivision" - ].includes(i); - })).length) { - throw new Error(`Expecting "freezeshot", "burnshot", "skipshot" or "subdivision", but find ${illegal.map(i => `"${i}"`).join(', ')}.`); - } - else { - types.map(i => { - var _a, _b, _c, _d; - switch (i) { - case "freezeshot": - (_a = event.BeatStyle) === null || _a === void 0 ? void 0 : _a.OneshotBeatSubType.push(RDOneshotBeatSubType.Freezeshot); - break; - case "burnshot": - (_b = event.BeatStyle) === null || _b === void 0 ? void 0 : _b.OneshotBeatSubType.push(RDOneshotBeatSubType.Burnshot); - break; - case "skipshot": - (_c = event.BeatStyle) === null || _c === void 0 ? void 0 : _c.OneshotBeatSubType.push(RDOneshotBeatSubType.Skipshot); - break; - case "subdivision": - (_d = event.BeatStyle) === null || _d === void 0 ? void 0 : _d.OneshotBeatSubType.push(RDOneshotBeatSubType.Subdivision); - break; - } - }); - } + case "grayscale": + event.Style.Grayscale = parseFloat(value); + break; + case "opacity": + event.Style.Opacity = parseFloat(value); + break; + case "offset": { + const offsetReader = new Reader(value); + (_f = event.ClickStyle) !== null && _f !== void 0 ? _f : (event.ClickStyle = new RDStyle()); + try { + event.ClickStyle.Beat = offsetReader.ReadFloat(); } - if (value = FindValue(pairs, "interval")) { - event.BeatStyle.Interval = parseFloat(value.Value); - } - if ((value = FindValue(pairs, "delay")) - && event.BeatStyle.OneshotBeatSubType.includes(RDOneshotBeatSubType.Freezeshot)) { - event.BeatStyle.Delay = parseFloat(value.Value); - } - if ((value = FindValue(pairs, "subdivision")) - && event.BeatStyle.OneshotBeatSubType.includes(RDOneshotBeatSubType.Subdivision)) { - event.BeatStyle.Subdivision = parseFloat(value.Value); - } - if (value = FindValue(pairs, "loop")) { - event.BeatStyle.Loop = parseInt(value.Value); - } - if (value = FindValue(pairs, "hold")) { - event.BeatStyle.Hold = parseFloat(value.Value); + catch (e) { } + try { + event.ClickStyle.Y = offsetReader.ReadInt(); } + catch (e) { } + break; + } + case "offset_hue": + (_g = event.ClickStyle) !== null && _g !== void 0 ? _g : (event.ClickStyle = new RDStyle()); + event.ClickStyle.Hue = parseFloat(value); + break; + case "offset_brightness": + (_h = event.ClickStyle) !== null && _h !== void 0 ? _h : (event.ClickStyle = new RDStyle()); + event.ClickStyle.Brightness = parseFloat(value); + break; + case "offset_grayscale": + (_j = event.ClickStyle) !== null && _j !== void 0 ? _j : (event.ClickStyle = new RDStyle()); + event.ClickStyle.Grayscale = parseFloat(value); + break; + case "offset_opacity": + (_k = event.ClickStyle) !== null && _k !== void 0 ? _k : (event.ClickStyle = new RDStyle()); + event.ClickStyle.Opacity = parseFloat(value); break; default: - break; + event.Properties.push(pair); } } } } -function ConstructObjs(window) { - var html = `
` - + `
`; - for (var obj of window.Objects) { - html += ConstructDivObject(obj); +const CELL_SIZE = 28; +const RDTK_SCALE = 2; +const NUMERIC_KEYS = new Set([ + "tick", "swing", "hold", "pulse", "customPulse", "interval", "delay", "loop", + "subdivision", "crotchetsPerBar", "syncoBeat", "duration", "angle", "bpm", + "beatsPerMinute", "volume", "speed", "startOpacity", "endOpacity", "subdivOffset", +]); +const SAY_PHRASES = new Set([ + "SayReaDyGetSetGoNew", "SayReaDyGetSetOne", "SayGetSetGo", "SayGetSetOne", + "JustSayRea", "JustSayDy", "JustSayGet", "JustSaySet", "JustSayAnd", + "JustSayGo", "JustSayStop", "JustSayAndStop", "SaySwitch", "SayWatch", + "SayListen", "Count1", "Count2", "Count3", "Count4", "Count5", "Count6", + "Count7", "Count8", "Count9", "Count10", "SayReadyGetSetGo", "JustSayReady", +]); +function CoerceValue(key, value) { + if (value === "true") { + return true; } - html += `
`; - return html; + if (value === "false") { + return false; + } + if (NUMERIC_KEYS.has(key) && /^[+-]?(\d+(\.\d+)?|\.\d+)$/.test(value)) { + return Number(value); + } + return value; } -function ConstructDivObject(obj) { - var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t; - if (obj instanceof RDEvent) { - return `
${ConstructSubDiv([obj.Condition !== undefined, `condition-${obj.Condition}`, () => ''], [obj.Tag === true, `tag`, () => ''], [obj.BeatType === BeatsSpecial.AddClassicBeat, `classicbeat`, () => { - var result = ''; - for (var i = 0; i < 6; i++) { - result += `
`; +function ToRDtkObject(ev) { + const obj = { type: ev.Name }; + let tab = undefined; + for (const pair of ev.Properties) { + let key = pair.Key; + const value = pair.Value; + if (key === "tab") { + tab = value; + continue; + } + if (key === "tag") { + continue; + } + if (ev.Name === "AddOneshotBeat" && key === "type") { + const types = value.split(/\s+/).filter(i => i.length > 0); + for (const t of types) { + switch (t) { + case "freezeshot": + obj.freezeBurnMode = "Freezeshot"; + break; + case "burnshot": + obj.freezeBurnMode = "Burnshot"; + break; + case "skipshot": + obj.skipshot = true; + break; } - return result; - }], [obj.BeatType === BeatsSpecial.AddFreeTimeBeat, `add freetime`, () => { return ''; }], [obj.BeatType === BeatsSpecial.PulseFreeTimeBeat, `pulse freetime`, () => ''], [((_q = obj.BeatStyle) === null || _q === void 0 ? void 0 : _q.Loop) !== undefined && obj.BeatStyle.Loop > 0, `loop`, () => { - var _a, _b; - var result = ''; - for (var i = 0; i < ((_b = (_a = obj.BeatStyle) === null || _a === void 0 ? void 0 : _a.Loop) !== null && _b !== void 0 ? _b : 0); i++) { - result += `
`; - } - return result; - }], [obj.BeatType === BeatsSpecial.AddOneshotBeat && obj.BeatStyle !== undefined && obj.BeatStyle.OneshotBeatSubType.includes(RDOneshotBeatSubType.Freezeshot), `freezeshots`, () => { - var _a, _b; - var result = ''; - for (var i = 0; i < ((_b = (_a = obj.BeatStyle) === null || _a === void 0 ? void 0 : _a.Loop) !== null && _b !== void 0 ? _b : 0) + 1; i++) { - result += `
`; - } - return result; - }], [obj.BeatType === BeatsSpecial.AddOneshotBeat && obj.BeatStyle !== undefined && obj.BeatStyle.OneshotBeatSubType.includes(RDOneshotBeatSubType.Burnshot), `burnshots`, () => { - var _a, _b; - var result = ''; - for (var i = 0; i < ((_b = (_a = obj.BeatStyle) === null || _a === void 0 ? void 0 : _a.Loop) !== null && _b !== void 0 ? _b : 0) + 1; i++) { - result += `
`; - } - return result; - }], [obj.BeatType === BeatsSpecial.AddOneshotBeat && obj.BeatStyle !== undefined && obj.BeatStyle.OneshotBeatSubType.includes(RDOneshotBeatSubType.Subdivision), `subdivisions`, () => { - var _a, _b, _c, _d; - var result = ''; - for (var l = 0; l < ((_b = (_a = obj.BeatStyle) === null || _a === void 0 ? void 0 : _a.Loop) !== null && _b !== void 0 ? _b : 0) + 1; l++) { - result += `
`; - for (var i = 0; i < ((_d = (_c = obj.BeatStyle) === null || _c === void 0 ? void 0 : _c.Subdivision) !== null && _d !== void 0 ? _d : 1); i++) { - result += `
`; - } - result += `
`; - } - return result; - }], [obj.BeatType === BeatsSpecial.SetRowXs, `row-xs`, () => { - var _a; - var result = ''; - for (var i = 0; i < 6; i++) { - 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 || 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`, () => ''])}
`; + } + continue; + } + if (ev.Name === "AddOneshotBeat" && key === "hold") { + obj.hold = !(value === "false" || value === "0" || value === "0.0"); + continue; + } + if (key === "rowxs") { + key = "pattern"; + } + else if (ev.Name === "AddOneshotBeat" && key === "loop") { + key = "loops"; + } + else if (ev.Name === "AddOneshotBeat" && key === "subdivision") { + key = "subdivisions"; + } + if (ev.Name === "SayReadyGetSetGo" && key === "phraseToSay") { + if (SAY_PHRASES.has(value)) { + obj.phraseToSay = value; + } + continue; + } + obj[key] = CoerceValue(key, value); } - else if (obj instanceof RDGroup) { - return `
${obj.Children.map(i => ConstructDivObject(i)).join('')}
`; + if (tab !== undefined) { + obj.tab = tab; + } + else if (ev.PrefixTab !== undefined) { + obj.tab = ev.PrefixTab; + } + if (ev.Tag === true) { + obj.tag = true; + } + return obj; +} +function ConstructObjs(view, objs) { + const content = document.createElement("div"); + content.className = "RDViewContent"; + content.style.setProperty("--column", `${view.Column}`); + content.style.setProperty("--row", `${view.Row}`); + content.style.setProperty("--scale", `${view.Scale}`); + const canvas = document.createElement("div"); + canvas.className = "RDView rdtk-rdview"; + canvas.style.setProperty("--column", `${view.Column}`); + canvas.style.setProperty("--row", `${view.Row}`); + canvas.style.setProperty("--scale", `${view.Scale}`); + for (const obj of objs) { + const node = BuildObject(obj); + if (node) { + canvas.appendChild(node); + } + } + content.appendChild(canvas); + return content; +} +function BuildObject(obj) { + return obj instanceof RDGroup ? BuildGroup(obj) : BuildEvent(obj); +} +function BuildEvent(ev) { + var _a, _b, _c, _d; + const wrapper = document.createElement("div"); + wrapper.className = "rdtk-event"; + wrapper.style.left = `${ev.Style.Beat * CELL_SIZE}px`; + wrapper.style.top = `${ev.Style.Y * CELL_SIZE}px`; + const state = { enabled: true, active: false, hover: false, scale: RDTK_SCALE, showDuration: false }; + const rdobj = ToRDtkObject(ev); + const inner = rdobj ? createElementEvent(rdobj, state) : null; + if (inner) { + inner.style.position = "absolute"; + inner.style.left = "0px"; + inner.style.top = "0px"; + wrapper.appendChild(inner); } else { - return ''; + wrapper.classList.add("rdtk-unknown"); + wrapper.textContent = ev.Name || "unknown"; } + ApplyFilter(wrapper, ev.Style); + if (ev.Condition !== undefined) { + const condition = document.createElement("div"); + condition.className = `rdtk-condition condition-${ev.Condition}`; + wrapper.appendChild(condition); + } + const offsetBeat = (_b = (_a = ev.ClickStyle) === null || _a === void 0 ? void 0 : _a.Beat) !== null && _b !== void 0 ? _b : 0; + const offsetY = (_d = (_c = ev.ClickStyle) === null || _c === void 0 ? void 0 : _c.Y) !== null && _d !== void 0 ? _d : 0; + const hasOffset = offsetBeat !== 0 || offsetY !== 0; + function setState(hover, active) { + state.hover = hover; + state.active = active; + inner === null || inner === void 0 ? void 0 : inner.onStateChange(state); + wrapper.classList.toggle("hover", hover); + wrapper.classList.toggle("active", active); + wrapper.style.transform = (active && hasOffset) + ? `translate(${offsetBeat * CELL_SIZE}px, ${offsetY * CELL_SIZE}px)` + : ""; + ApplyFilter(wrapper, active && ev.ClickStyle ? ev.ClickStyle : ev.Style); + } + wrapper.addEventListener("mouseover", (e) => { + if (!wrapper.contains(e.relatedTarget)) { + setState(true, state.active); + } + }); + wrapper.addEventListener("mouseout", (e) => { + if (!wrapper.contains(e.relatedTarget)) { + setState(false, false); + } + }); + wrapper.addEventListener("mousedown", () => setState(true, true)); + wrapper.addEventListener("mouseup", () => setState(state.hover, false)); + wrapper.__setRDtkState = setState; + return wrapper; } -function ConstructCssPropertiesIfExists(pairs) { - var result = ''; - for (const [key, value] of pairs) { - result += value !== undefined ? `--${key}:${value};` : ``; +function BuildGroup(grp) { + var _a, _b, _c, _d; + const wrapper = document.createElement("div"); + wrapper.className = "rdtk-group"; + wrapper.style.left = `${grp.Style.Beat * CELL_SIZE}px`; + wrapper.style.top = `${grp.Style.Y * CELL_SIZE}px`; + wrapper.style.width = `${grp.Width * CELL_SIZE}px`; + wrapper.style.height = `${grp.Height * CELL_SIZE}px`; + wrapper.style.outlineColor = ToHex(grp.Outline); + ApplyFilter(wrapper, grp.Style); + for (const child of grp.Children) { + const node = BuildObject(child); + if (node) { + wrapper.appendChild(node); + } } - return result; + const offsetBeat = (_b = (_a = grp.ClickStyle) === null || _a === void 0 ? void 0 : _a.Beat) !== null && _b !== void 0 ? _b : 0; + const offsetY = (_d = (_c = grp.ClickStyle) === null || _c === void 0 ? void 0 : _c.Y) !== null && _d !== void 0 ? _d : 0; + const hasOffset = offsetBeat !== 0 || offsetY !== 0; + function setState(hover, active) { + var _a; + wrapper.classList.toggle("hover", hover); + wrapper.classList.toggle("active", active); + wrapper.style.transform = (active && hasOffset) + ? `translate(${offsetBeat * CELL_SIZE}px, ${offsetY * CELL_SIZE}px)` + : ""; + wrapper.style.outlineColor = active ? ToHex((_a = grp.ClickOutline) !== null && _a !== void 0 ? _a : grp.Outline) : ToHex(grp.Outline); + ApplyFilter(wrapper, active && grp.ClickStyle ? grp.ClickStyle : grp.Style); + } + wrapper.addEventListener("mouseover", (e) => { + if (!wrapper.contains(e.relatedTarget)) { + setState(true, false); + } + }); + wrapper.addEventListener("mouseout", (e) => { + if (!wrapper.contains(e.relatedTarget)) { + setState(false, false); + } + }); + wrapper.addEventListener("mousedown", () => setState(true, true)); + wrapper.addEventListener("mouseup", () => setState(true, false)); + wrapper.__setRDtkState = setState; + return wrapper; } -function ConstructCssProperties(pairs) { - var result = ''; - for (const [key, value] of pairs) { - result += `--${key}:${value};`; +function ApplyFilter(el, style) { + const parts = []; + if (style.Hue !== undefined) { + parts.push(`hue-rotate(${style.Hue}deg)`); } - return result; -} -function ConstructSubDiv(...pairs) { - var result = ''; - for (const [key, name, func] of pairs) { - result += key ? `
${func()}
` : ``; + if (style.Brightness !== undefined) { + parts.push(`brightness(${style.Brightness}%)`); } - return result; + if (style.Grayscale !== undefined) { + parts.push(`grayscale(${style.Grayscale}%)`); + } + if (style.Opacity !== undefined) { + parts.push(`opacity(${style.Opacity}%)`); + } + el.style.filter = parts.join(" "); } function ToHex(color) { const hex = parseInt(color.red.toFixed(0)).toString(16).padStart(2, '0') + diff --git a/script/rdview.ts b/script/rdview.ts index 9e455e3..9505371 100644 --- a/script/rdview.ts +++ b/script/rdview.ts @@ -1,123 +1,5 @@ -var tilePosition = { - "events": { - "sounds": [ - { "name": "Empty", "position": [0, 0, 1, 1] }, - { "name": "SetCrotchetsPerBar_1", "position": [0, 1, 1, 1] }, - { "name": "SetCrotchetsPerBar_2", "position": [1, 1, 1, 1] }, - { "name": "SetCrotchetsPerBar_3", "position": [2, 1, 1, 1] }, - { "name": "SetCrotchetsPerBar_4", "position": [3, 1, 1, 1] }, - { "name": "SetCrotchetsPerBar_5", "position": [4, 1, 1, 1] }, - { "name": "SetCrotchetsPerBar_6", "position": [5, 1, 1, 1] }, - { "name": "SetCrotchetsPerBar_7", "position": [6, 1, 1, 1] }, - { "name": "SetCrotchetsPerBar_8", "position": [7, 1, 1, 1] }, - { "name": "SetCrotchetsPerBar_9", "position": [8, 1, 1, 1] }, - { "name": "SetCrotchetsPerBar", "position": [9, 2, 1, 1] }, - { "name": "SayReadyGetSetGo_1", "position": [0, 2, 1, 1] }, - { "name": "SayReadyGetSetGo_2", "position": [1, 2, 1, 1] }, - { "name": "SayReadyGetSetGo_3", "position": [2, 2, 1, 1] }, - { "name": "SayReadyGetSetGo_4", "position": [3, 2, 1, 1] }, - { "name": "SayReadyGetSetGo_5", "position": [4, 2, 1, 1] }, - { "name": "SayReadyGetSetGo_6", "position": [5, 2, 1, 1] }, - { "name": "SayReadyGetSetGo_7", "position": [6, 2, 1, 1] }, - { "name": "SayReadyGetSetGo_8", "position": [7, 2, 1, 1] }, - { "name": "SayReadyGetSetGo_9", "position": [8, 2, 1, 1] }, - { "name": "SayReadyGetSetGo_10", "position": [9, 2, 1, 1] }, - { "name": "PlaySong", "position": [0, 3, 2, 1] }, - { "name": "PlaySound", "position": [2, 3, 1, 1] }, - { "name": "SetBeatsPerMinute", "position": [3, 3, 1, 1] }, - { "name": "SetClapSounds", "position": [4, 3, 1, 1] }, - { "name": "SetHeartExplodeVolume", "position": [5, 3, 1, 1] }, - { "name": "SetHeartExplodeInterval", "position": [6, 3, 1, 1] }, - { "name": "SetGameSound", "position": [7, 3, 1, 1] }, - { "name": "SetBeatSound", "position": [8, 3, 1, 1] }, - { "name": "SetCountingSound", "position": [9, 3, 1, 1] }, - { "name": "SayReadyGetSetGo_Rea", "position": [1, 0, 1, 1] }, - { "name": "SayReadyGetSetGo_Dy", "position": [2, 0, 1, 1] }, - { "name": "SayReadyGetSetGo_Get", "position": [3, 0, 1, 1] }, - { "name": "SayReadyGetSetGo_Set", "position": [4, 0, 1, 1] }, - { "name": "SayReadyGetSetGo_Go", "position": [5, 0, 1, 1] }, - { "name": "SayReadyGetSetGo_Ready", "position": [10, 0, 1, 1] }, - { "name": "SayReadyGetSetGo_And", "position": [10, 1, 1, 1] }, - { "name": "SayReadyGetSetGo_GetSetGo", "position": [11, 0, 3, 1] }, - { "name": "SayReadyGetSetGo_GetSetOne", "position": [11, 1, 3, 1] }, - { "name": "SayReadyGetSetGo_Stop", "position": [14, 0, 1, 1] }, - { "name": "SayReadyGetSetGo_AndStop", "position": [14, 1, 1, 1] }, - { "name": "SayReadyGetSetGo_ReaDyGetSetGo", "position": [10, 2, 5, 1] }, - { "name": "SayReadyGetSetGo_ReaDyGetSetOne", "position": [10, 3, 5, 1] }, - { "name": "Comment", "position": [15, 0, 1, 1] } - ], - "rows": [ - { "name": "Empty", "position": [0, 0, 1, 1] }, - { "name": "SetOneshotWave", "position": [1, 0, 1, 1] } - ], - "actions": [ - { "name": "Empty", "position": [0, 0, 1, 1] }, - { "name": "SetTheme", "position": [1, 0, 1, 1] }, - { "name": "SetVFXPreset", "position": [2, 0, 1, 1] }, - { "name": "SetBackgroundColor", "position": [3, 0, 1, 1] }, - { "name": "SetForeground", "position": [4, 0, 1, 1] }, - { "name": "SetSpeed", "position": [5, 0, 1, 1] }, - { "name": "Flash", "position": [6, 0, 1, 1] }, - { "name": "CustomFlash", "position": [7, 0, 1, 1] }, - { "name": "NewWindowDance", "position": [8, 0, 1, 1] }, - { "name": "MoveCamera", "position": [0, 1, 1, 1] }, - { "name": "PulseCamera", "position": [1, 1, 1, 1] }, - { "name": "TextExplosion", "position": [2, 1, 1, 1] }, - { "name": "ShowDialogue", "position": [3, 1, 1, 1] }, - { "name": "ShowStatusSign", "position": [4, 1, 1, 1] }, - { "name": "FloatingText", "position": [5, 1, 1, 1] }, - { "name": "AdvanceText", "position": [6, 1, 0.5, 1] }, - { "name": "ChangePlayersRows", "position": [7, 1, 1, 1] }, - { "name": "Comment", "position": [8, 1, 1, 1] }, - { "name": "FinishLevel", "position": [0, 2, 1, 1] }, - { "name": "Stutter", "position": [1, 2, 1, 1] }, - { "name": "HideRow", "position": [2, 2, 1, 1] }, - { "name": "MoveRow", "position": [3, 2, 1, 1] }, - { "name": "PlayExpression", "position": [4, 2, 1, 1] }, - { "name": "TintRows", "position": [5, 2, 1, 1] }, - { "name": "BassDrop", "position": [6, 2, 1, 1] }, - { "name": "ShakeScreen", "position": [7, 2, 1, 1] }, - { "name": "FlipScreen", "position": [0, 3, 1, 1] }, - { "name": "InvertColors", "position": [1, 3, 1, 1] }, - { "name": "ShowHands", "position": [2, 3, 1, 1] }, - { "name": "PaintHands", "position": [3, 3, 1, 1] }, - { "name": "SetHandOwner", "position": [4, 3, 1, 1] }, - { "name": "SetPlayStyle", "position": [5, 3, 1, 1] }, - { "name": "TagAction", "position": [6, 3, 1, 1] }, - { "name": "CallCustomMethod", "position": [7, 3, 1, 1] } - ], - "decorations": [ - { "name": "Empty", "position": [0, 0, 1, 1] }, - { "name": "PlayAnimation", "position": [1, 0, 1, 1] }, - { "name": "Tint", "position": [0, 1, 1, 1] }, - { "name": "Comment", "position": [1, 1, 1, 1] }, - { "name": "SetVisible", "position": [0, 2, 1, 1] }, - { "name": "Move", "position": [0, 3, 1, 1] } - ], - "rooms": [ - { "name": "Empty", "position": [0, 0, 1, 1] }, - { "name": "MoveRoom", "position": [0, 1, 1, 1] }, - { "name": "FadeRoom", "position": [0, 2, 1, 1] }, - { "name": "MaskRoom", "position": [0, 3, 1, 1] }, - { "name": "ShowRooms", "position": [1, 0, 1, 4] }, - { "name": "ReorderRooms", "position": [2, 0, 1, 4] }, - { "name": "SetRoomContentMode", "position": [3, 0, 1, 1] }, - { "name": "SetRoomPerspective", "position": [3, 1, 1, 1] }, - { "name": "Comment", "position": [3, 2, 1, 1] } - ], - "custom": [ - { "name": "Empty", "position": [0, 0, 1, 1] }, - { "name": "Comment", "position": [0, 1, 1, 1] } - ], - "beatsSpecial": [ - "AddClassicBeat", - "AddOneshotBeat", - "AddFreeTimeBeat", - "PulseFreeTimeBeat", - "SetRowXs" - ] - } -} +import { createElementEvent, IconStyle } from "./rdtkview.js"; + function loadRDView() { (window as any).RDViewRender = RDViewRender; } @@ -133,88 +15,24 @@ class Color { this.alpha = alpha; }; } -enum EventType { - sounds = "sounds", - rows = "rows", - actions = "actions", - decorations = "decorations", - rooms = "rooms", - custom = "custom", -} -enum BeatsSpecial { - AddClassicBeat, - AddFreeTimeBeat, - PulseFreeTimeBeat, - AddOneshotBeat, - SetRowXs, -} enum EventCondition { true = "true", false = "false", both = "both", } class RDViewWindow { - Objects: (RDEvent | RDGroup)[] = []; Row: number = 4; Column: number = 8; Scale: number = 1; } class RDEvent { - SubType: EventType = EventType.custom; - BeatType?: BeatsSpecial = undefined; - BeatStyle?: RDBeatStyle; - Width: number = 1; - Height: number = 1; - EventX: number = 0; - EventY: number = 0; + Name: string = ""; + PrefixTab?: string = undefined; + Properties: KeyValuePair[] = []; Style: RDStyle = { Beat: 0, Y: 0 }; ClickStyle?: RDStyle; Condition?: EventCondition; Tag?: boolean; - Description?: RDDescription; -} -class RDDescription { - Width: number = 4; - Lines: RDDescriptionLine[] = []; -} -class RDDescriptionLine { - BoxCount: number = 1; - IconCount: number = 0; - Items: (RDDescriptionText | RDDescriptionBox | RDDescriptionIcon)[] = []; -} -class RDDescriptionText { - Middle?: boolean; - Hoverable?: boolean; - FGray?: boolean; - Highlight?: boolean; - Text: string = ""; -} -class RDDescriptionBox { - Items: (RDDescriptionBoxButton | RDDescriptionBoxInput | RDDescriptionBoxScroll | RDDescriptionBoxSelect)[] = []; -} -class RDDescriptionBoxInput { - Tips?: string = ""; - Middle?: boolean; - FGray?: boolean; - BlackBack?: boolean; - Highlight?: boolean; - Text: string = ""; -} -class RDDescriptionBoxScroll { - Scroll: number = 0; -} -class RDDescriptionBoxButton { - Middle?: boolean; - Active?: boolean; - GrayBack?: boolean; - Highlight?: boolean; - Text: string = ""; -} -class RDDescriptionBoxSelect { - Items: string[] = []; - SelectedIndex: number = 0; -} -class RDDescriptionIcon { } class RDStyle { Beat: number = 0; @@ -224,24 +42,6 @@ class RDStyle { Grayscale?: number; Opacity?: number; } -class RDBeatStyle { - Tick?: number; - OneshotBeatSubType: RDOneshotBeatSubType[] = []; - Interval?: number; - Delay?: number; - Subdivision?: number; - Swing?: number; - Hold?: number; - Pulse?: number; - RowXs: string = '------'; - Loop?: number; -} -enum RDOneshotBeatSubType { - Freezeshot, - Burnshot, - Skipshot, - Subdivision, -} class RDGroup { Width: number = 1; Height: number = 1; @@ -251,97 +51,72 @@ class RDGroup { ClickOutline?: Color; Children: (RDEvent | RDGroup)[] = []; } -function RDViewRender(lang: string, code: string): string { - const lines: string[] = code.split('\n'); - const window: RDViewWindow = new RDViewWindow(); +function RDViewRender(lang: string, code: string): HTMLElement { + const view: RDViewWindow = new RDViewWindow(); var objs: (RDEvent | RDGroup)[] = []; try { - window.Objects = ReadObjs(code); + objs = ReadObjs(code); } catch (error) { - return errorHtml(`${error}`); + return ErrorElement(`${error}`); } const args = lang.split(/\s+/g); if (1 < args.length && args.length <= 4) { if (args[1]) { - window.Column = parseInt(args[1]); + view.Column = parseInt(args[1]); } if (args[2]) { - window.Row = parseInt(args[2]); + view.Row = parseInt(args[2]); } if (args[3]) { - window.Scale = parseFloat(args[3]); + view.Scale = parseFloat(args[3]); } } - return ConstructObjs(window); + return ConstructObjs(view, objs); } -function errorHtml(message: string = ""): string { - return `
${message.length ? `${message}` : ""}
`; +function ErrorElement(message: string = ""): HTMLElement { + const el = document.createElement("div"); + el.className = "rdtk-error"; + el.textContent = message; + return el; +} +function PrefixToTab(prefix: string): string | undefined { + switch (prefix) { + case "es": return "Sounds"; + case "eb": return "Rows"; + case "ea": return "Actions"; + case "ed": return "Sprites"; + case "er": return "Rooms"; + case "ec": return "Unknown"; + default: return undefined; + } } function ReadObjs(line: string): (RDEvent | RDGroup)[] { const objs: (RDEvent | RDGroup)[] = []; var reader = new Reader(line); while (!reader.IsEnd()) { var event: (RDEvent | RDGroup); + var name: string = ""; + var prefix: string = ""; try { - const type = reader.ReadSymbol().toLowerCase(); - event = ReadType(type); + name = reader.ReadSymbol(); + if (reader.TestRead('.', false)) { + prefix = name; + name = reader.ReadSymbol(); + } } catch (e) { - event = new RDEvent(); + name = ""; + } + if (name.toLowerCase() === 'g') { + event = new RDGroup(); + } + else { + const ev = new RDEvent(); + ev.Name = name; + ev.PrefixTab = PrefixToTab(prefix); + event = ev; } if (event instanceof RDEvent) { - reader.TestRead('.', true); - const name = reader.ReadSymbol(); - var collection; - switch (event.SubType) { - case EventType.sounds: - collection = tilePosition.events.sounds; - break; - case EventType.rows: - collection = tilePosition.events.rows; - switch (name) { - case 'AddClassicBeat': - event.BeatType = BeatsSpecial.AddClassicBeat; - break; - case 'AddFreeTimeBeat': - event.BeatType = BeatsSpecial.AddFreeTimeBeat; - break; - case 'PulseFreeTimeBeat': - event.BeatType = BeatsSpecial.PulseFreeTimeBeat; - break; - case 'AddOneshotBeat': - event.BeatType = BeatsSpecial.AddOneshotBeat; - break; - case 'SetRowXs': - event.BeatType = BeatsSpecial.SetRowXs; - break; - default: - break; - } - break; - case EventType.actions: - collection = tilePosition.events.actions; - break; - case EventType.decorations: - collection = tilePosition.events.decorations; - break; - case EventType.rooms: - collection = tilePosition.events.rooms; - break; - case EventType.custom: - collection = tilePosition.events.custom; - break; - default: - collection = tilePosition.events.custom; - break; - } - const pos = collection.filter(i => i.name.toLowerCase() === name.toLowerCase())[0]; - if (pos) { - event.EventX = pos.position[0]; - event.EventY = pos.position[1]; - event.Width = pos.position[2]; - event.Height = pos.position[3]; - } try { event.Style.Beat = reader.ReadFloat(); } catch (e) { } try { event.Style.Y = reader.ReadInt(); } catch (e) { } if (reader.TestPeek('[')) { @@ -591,7 +366,7 @@ class Reader { line += this.line; position = this.position; } - return `
at "${s[line]}".`;//, at ${line + 1}:${position - curp}`; + return `
at "${s[line]}".`; } } function FindValue(pairs: KeyValuePair[], key: string): KeyValuePair | undefined { @@ -601,79 +376,13 @@ function FindValue(pairs: KeyValuePair[], key: string): KeyValuePair | undefined } return undefined; } -function ReadType(typename: string): (RDEvent | RDGroup) { - var t: EventType = EventType.custom; - var event: RDEvent | RDGroup; - switch (typename[0]) { - case 'e': - event = new RDEvent(); - switch (typename[1]) { - case 's': - t = EventType.sounds; - break; - case 'b': - t = EventType.rows; - break; - case 'a': - t = EventType.actions; - break; - case 'd': - t = EventType.decorations; - break; - case 'r': - t = EventType.rooms; - break; - case 'c': - t = EventType.custom; - break; - default: - t = EventType.custom; - } - event.SubType = t; - break; - case 'g': - event = new RDGroup(); - break; - default: - event = new RDEvent(); - } - return event; -} function ReadProperties(reader: Reader, event: RDEvent | RDGroup, pairs: KeyValuePair[]) { - if (event instanceof RDGroup) { - if (value = FindValue(pairs, "hue")) { - try { - event.Style.Hue = parseFloat(value.Value); - } - catch (e) { - throw new Error(`Expecting a number, but find "${value.Value}".`); - } - } - if (value = FindValue(pairs, "brightness")) { - try { - event.Style.Brightness = parseFloat(value.Value); - } - catch (e) { - throw new Error(`Expecting a number, but find "${value.Value}".`); - } - } - if (value = FindValue(pairs, "grayscale")) { - try { - event.Style.Grayscale = parseFloat(value.Value); - } - catch (e) { - throw new Error(`Expecting a number, but find "${value.Value}".`); - } - } - if (value = FindValue(pairs, "opacity")) { - try { - event.Style.Opacity = parseFloat(value.Value); - } - catch (e) { - throw new Error(`Expecting a number, but find "${value.Value}".`); - } - } + var value: KeyValuePair | undefined; + if (value = FindValue(pairs, "hue")) { event.Style.Hue = parseFloat(value.Value); } + if (value = FindValue(pairs, "brightness")) { event.Style.Brightness = parseFloat(value.Value); } + if (value = FindValue(pairs, "grayscale")) { event.Style.Grayscale = parseFloat(value.Value); } + if (value = FindValue(pairs, "opacity")) { event.Style.Opacity = parseFloat(value.Value); } if (value = FindValue(pairs, "offset")) { reader = new Reader(value.Value); event.ClickStyle ??= new RDStyle(); @@ -681,302 +390,270 @@ function ReadProperties(reader: Reader, event: RDEvent | RDGroup, pairs: KeyValu try { event.ClickStyle.Y = reader.ReadInt(); } catch (e) { } try { event.ClickOutline = reader.ReadColor(); } catch (e) { } } - if (value = FindValue(pairs, "offset_hue")) { - event.ClickStyle ??= new RDStyle(); - event.ClickStyle.Hue = parseFloat(value.Value); - } - if (value = FindValue(pairs, "offset_brightness")) { - event.ClickStyle ??= new RDStyle(); - event.ClickStyle.Brightness = parseFloat(value.Value); - } - if (value = FindValue(pairs, "offset_grayscale")) { - event.ClickStyle ??= new RDStyle(); - event.ClickStyle.Grayscale = parseFloat(value.Value); - } - if (value = FindValue(pairs, "offset_opacity")) { - event.ClickStyle ??= new RDStyle(); - event.ClickStyle.Opacity = parseFloat(value.Value); - } + if (value = FindValue(pairs, "offset_hue")) { event.ClickStyle ??= new RDStyle(); event.ClickStyle.Hue = parseFloat(value.Value); } + if (value = FindValue(pairs, "offset_brightness")) { event.ClickStyle ??= new RDStyle(); event.ClickStyle.Brightness = parseFloat(value.Value); } + if (value = FindValue(pairs, "offset_grayscale")) { event.ClickStyle ??= new RDStyle(); event.ClickStyle.Grayscale = parseFloat(value.Value); } + if (value = FindValue(pairs, "offset_opacity")) { event.ClickStyle ??= new RDStyle(); event.ClickStyle.Opacity = parseFloat(value.Value); } } else if (event instanceof RDEvent) { - var value: KeyValuePair | undefined; - if (value = FindValue(pairs, "if")) { - if (["true", "false", "both"].find(i => i === value?.Value)) { - event.Condition = value.Value === "true" ? EventCondition.true : - value.Value === "false" ? EventCondition.false : EventCondition.both; - } - else { - throw new Error(`Expecting "true", "false" or "both", but find "${value.Value}".`); - } - } - if (value = FindValue(pairs, "tag")) { - event.Tag = value.Value === "true" ? true : false; - } - if (value = FindValue(pairs, "hue")) { - event.Style.Hue = parseFloat(value.Value); - } - if (value = FindValue(pairs, "brightness")) { - event.Style.Brightness = parseFloat(value.Value); - } - if (value = FindValue(pairs, "grayscale")) { - event.Style.Grayscale = parseFloat(value.Value); - } - if (value = FindValue(pairs, "opacity")) { - event.Style.Opacity = parseFloat(value.Value); - } - event.ClickStyle ??= new RDStyle(); - if (value = FindValue(pairs, "offset")) { - reader = new Reader(value.Value); - try { event.ClickStyle.Beat = reader.ReadFloat(); } catch (e) { } - try { event.ClickStyle.Y = reader.ReadInt(); } catch (e) { } - } - if (value = FindValue(pairs, "offset_hue")) { - event.ClickStyle.Hue = parseFloat(value.Value); - } - if (value = FindValue(pairs, "offset_brightness")) { - event.ClickStyle.Brightness = parseFloat(value.Value); - } - if (value = FindValue(pairs, "offset_grayscale")) { - event.ClickStyle.Grayscale = parseFloat(value.Value); - } - if (value = FindValue(pairs, "offset_opacity")) { - event.ClickStyle.Opacity = parseFloat(value.Value); - } - if (event.BeatType !== undefined) { - event.BeatStyle = new RDBeatStyle(); - if (value = FindValue(pairs, "tick")) { - event.BeatStyle.Tick = parseFloat(value.Value); - } - switch (event.BeatType) { - case BeatsSpecial.AddClassicBeat: - if (value = FindValue(pairs, "swing")) { - event.BeatStyle.Swing = parseFloat(value.Value); + for (const pair of pairs) { + const key = pair.Key; + const value = pair.Value; + switch (key) { + case "if": + if (["true", "false", "both"].find(i => i === value)) { + event.Condition = value === "true" ? EventCondition.true : + value === "false" ? EventCondition.false : EventCondition.both; } - if (value = FindValue(pairs, "hold")) { - event.BeatStyle.Hold = parseFloat(value.Value); + else { + throw new Error(`Expecting "true", "false" or "both", but find "${value}".`); } break; - case BeatsSpecial.AddFreeTimeBeat: - if (value = FindValue(pairs, "pulse")) { - event.BeatStyle.Pulse = parseFloat(value.Value); - } - if (value = FindValue(pairs, "hold")) { - event.BeatStyle.Hold = parseFloat(value.Value); - } + case "tag": + event.Tag = value === "true"; break; - case BeatsSpecial.PulseFreeTimeBeat: - if (value = FindValue(pairs, "pulse")) { - event.BeatStyle.Pulse = parseFloat(value.Value); - } - if (value = FindValue(pairs, "hold")) { - event.BeatStyle.Hold = parseFloat(value.Value); - } + case "hue": + event.Style.Hue = parseFloat(value); break; - case BeatsSpecial.SetRowXs: - if ((value = FindValue(pairs, "rowxs"))) { - if (value.Value.match(/^[-x]{6}$/)) { - event.BeatStyle.RowXs = value.Value; - } - else { - throw new Error(`Expect a string of length 6, consisting of "x" and "-", instead of "${value?.Value}".`); - } - } + case "brightness": + event.Style.Brightness = parseFloat(value); break; - case BeatsSpecial.AddOneshotBeat: - if (value = FindValue(pairs, "type")) { - const types: string[] = value.Value.split(/\s+/); - var illegal: string[] | undefined; - if ((illegal = types.filter(i => { - ![ - "freezeshot", - "burnshot", - "skipshot", - "subdivision" - ].includes(i); - })).length) { - throw new Error(`Expecting "freezeshot", "burnshot", "skipshot" or "subdivision", but find ${illegal.map(i => `"${i}"`).join(', ')}.`); - } - else { - types.map(i => { - switch (i) { - case "freezeshot": - event.BeatStyle?.OneshotBeatSubType.push(RDOneshotBeatSubType.Freezeshot); - break; - case "burnshot": - event.BeatStyle?.OneshotBeatSubType.push(RDOneshotBeatSubType.Burnshot); - break; - case "skipshot": - event.BeatStyle?.OneshotBeatSubType.push(RDOneshotBeatSubType.Skipshot); - break; - case "subdivision": - event.BeatStyle?.OneshotBeatSubType.push(RDOneshotBeatSubType.Subdivision); - break; - } - }); - } - } - if (value = FindValue(pairs, "interval")){ - event.BeatStyle.Interval = parseFloat(value.Value); - } - if ((value = FindValue(pairs, "delay")) - && event.BeatStyle.OneshotBeatSubType.includes(RDOneshotBeatSubType.Freezeshot)) { - event.BeatStyle.Delay = parseFloat(value.Value); - } - if ((value = FindValue(pairs, "subdivision")) - && event.BeatStyle.OneshotBeatSubType.includes(RDOneshotBeatSubType.Subdivision)) { - event.BeatStyle.Subdivision = parseFloat(value.Value); - } - if (value = FindValue(pairs, "loop")) { - event.BeatStyle.Loop = parseInt(value.Value); - } - if (value = FindValue(pairs, "hold")) { - event.BeatStyle.Hold = parseFloat(value.Value); - } + case "grayscale": + event.Style.Grayscale = parseFloat(value); + break; + case "opacity": + event.Style.Opacity = parseFloat(value); + break; + case "offset": { + const offsetReader = new Reader(value); + event.ClickStyle ??= new RDStyle(); + try { event.ClickStyle.Beat = offsetReader.ReadFloat(); } catch (e) { } + try { event.ClickStyle.Y = offsetReader.ReadInt(); } catch (e) { } + break; + } + case "offset_hue": + event.ClickStyle ??= new RDStyle(); + event.ClickStyle.Hue = parseFloat(value); + break; + case "offset_brightness": + event.ClickStyle ??= new RDStyle(); + event.ClickStyle.Brightness = parseFloat(value); + break; + case "offset_grayscale": + event.ClickStyle ??= new RDStyle(); + event.ClickStyle.Grayscale = parseFloat(value); + break; + case "offset_opacity": + event.ClickStyle ??= new RDStyle(); + event.ClickStyle.Opacity = parseFloat(value); break; default: - break; + event.Properties.push(pair); } } } } -function ConstructObjs(window: RDViewWindow) { - var html: string = `
` - +`
`; - for (var obj of window.Objects) { - html += ConstructDivObject(obj); + +const CELL_SIZE = 28; +const RDTK_SCALE = 2; + +const NUMERIC_KEYS = new Set([ + "tick", "swing", "hold", "pulse", "customPulse", "interval", "delay", "loop", + "subdivision", "crotchetsPerBar", "syncoBeat", "duration", "angle", "bpm", + "beatsPerMinute", "volume", "speed", "startOpacity", "endOpacity", "subdivOffset", +]); + +const SAY_PHRASES = new Set([ + "SayReaDyGetSetGoNew", "SayReaDyGetSetOne", "SayGetSetGo", "SayGetSetOne", + "JustSayRea", "JustSayDy", "JustSayGet", "JustSaySet", "JustSayAnd", + "JustSayGo", "JustSayStop", "JustSayAndStop", "SaySwitch", "SayWatch", + "SayListen", "Count1", "Count2", "Count3", "Count4", "Count5", "Count6", + "Count7", "Count8", "Count9", "Count10", "SayReadyGetSetGo", "JustSayReady", +]); + +function CoerceValue(key: string, value: string): any { + if (value === "true") { return true; } + if (value === "false") { return false; } + if (NUMERIC_KEYS.has(key) && /^[+-]?(\d+(\.\d+)?|\.\d+)$/.test(value)) { + return Number(value); } - html += `
`; - return html; + return value; } -function ConstructDivObject(obj: RDEvent | RDGroup): string { - if (obj instanceof RDEvent) { - return `
${ConstructSubDiv( - [obj.Condition !== undefined, `condition-${obj.Condition}`, () => ''], - [obj.Tag === true, `tag`, () => ''], - [obj.BeatType === BeatsSpecial.AddClassicBeat, `classicbeat`, () => { - var result: string = ''; - for (var i = 0; i < 6; i++) { - result += `
`; - } - return result; - }], - [obj.BeatType === BeatsSpecial.AddFreeTimeBeat, `add freetime`, () => {return '';}], - [obj.BeatType === BeatsSpecial.PulseFreeTimeBeat, `pulse freetime`, () => ''], - [obj.BeatStyle?.Loop !== undefined && obj.BeatStyle.Loop > 0, `loop`, () => { - var result: string = ''; - for (var i = 0; i < (obj.BeatStyle?.Loop ?? 0); i++) { - result += `
`; - } - return result; - }], - [obj.BeatType === BeatsSpecial.AddOneshotBeat && obj.BeatStyle !== undefined && obj.BeatStyle.OneshotBeatSubType.includes(RDOneshotBeatSubType.Freezeshot), `freezeshots`, () => { - var result: string = ''; - for (var i = 0; i < (obj.BeatStyle?.Loop ?? 0) + 1; i++) { - result += `
`; - } - return result; - }], - [obj.BeatType === BeatsSpecial.AddOneshotBeat && obj.BeatStyle !== undefined && obj.BeatStyle.OneshotBeatSubType.includes(RDOneshotBeatSubType.Burnshot), `burnshots`, () => { - var result: string = ''; - for (var i = 0; i < (obj.BeatStyle?.Loop ?? 0) + 1; i++) { - result += `
`; - } - return result; - }], - [obj.BeatType === BeatsSpecial.AddOneshotBeat && obj.BeatStyle !== undefined && obj.BeatStyle.OneshotBeatSubType.includes(RDOneshotBeatSubType.Subdivision), `subdivisions`, () => { - var result: string = ''; - for(var l = 0; l < (obj.BeatStyle?.Loop ?? 0) + 1; l++){ - result += `
`; - for (var i = 0; i < (obj.BeatStyle?.Subdivision ?? 1); i++) { - result += `
`; - } - result += `
`; - } - return result; - }], - [obj.BeatType === BeatsSpecial.SetRowXs, `row-xs`, () => { - var result: string = ''; - for (var i = 0; i < 6; i++) { - result += (obj.BeatStyle?.RowXs[i] === 'x') ? `
` : `
`; - } - return result; - }], - [(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`, () => ''], - )}
`; + +function ToRDtkObject(ev: RDEvent): any { + const obj: any = { type: ev.Name }; + let tab: string | undefined = undefined; + for (const pair of ev.Properties) { + let key = pair.Key; + const value = pair.Value; + if (key === "tab") { tab = value; continue; } + if (key === "tag") { continue; } + if (ev.Name === "AddOneshotBeat" && key === "type") { + const types = value.split(/\s+/).filter(i => i.length > 0); + for (const t of types) { + switch (t) { + case "freezeshot": obj.freezeBurnMode = "Freezeshot"; break; + case "burnshot": obj.freezeBurnMode = "Burnshot"; break; + case "skipshot": obj.skipshot = true; break; + } + } + continue; + } + if (ev.Name === "AddOneshotBeat" && key === "hold") { + obj.hold = !(value === "false" || value === "0" || value === "0.0"); + continue; + } + if (key === "rowxs") { key = "pattern"; } + else if (ev.Name === "AddOneshotBeat" && key === "loop") { key = "loops"; } + else if (ev.Name === "AddOneshotBeat" && key === "subdivision") { key = "subdivisions"; } + if (ev.Name === "SayReadyGetSetGo" && key === "phraseToSay") { + if (SAY_PHRASES.has(value)) { obj.phraseToSay = value; } + continue; + } + obj[key] = CoerceValue(key, value); } - else if (obj instanceof RDGroup) { - return `
${obj.Children.map(i => ConstructDivObject(i)).join('')}
`; + if (tab !== undefined) { + obj.tab = tab; } - else { return ''; } + else if (ev.PrefixTab !== undefined) { + obj.tab = ev.PrefixTab; + } + if (ev.Tag === true) { + obj.tag = true; + } + return obj; } -function ConstructCssPropertiesIfExists(pairs: Map): string { - var result: string = ''; - for (const [key, value] of pairs) { - result += value !== undefined ? `--${key}:${value};` : ``; - } - return result; + +interface RDtkNode extends HTMLElement { + __setRDtkState?: (hover: boolean, active: boolean) => void; } -function ConstructCssProperties(pairs: Map): string { - var result: string = ''; - for (const [key, value] of pairs) { - result += `--${key}:${value};`; + +function ConstructObjs(view: RDViewWindow, objs: (RDEvent | RDGroup)[]): HTMLElement { + const content = document.createElement("div"); + content.className = "RDViewContent"; + content.style.setProperty("--column", `${view.Column}`); + content.style.setProperty("--row", `${view.Row}`); + content.style.setProperty("--scale", `${view.Scale}`); + const canvas = document.createElement("div"); + canvas.className = "RDView rdtk-rdview"; + canvas.style.setProperty("--column", `${view.Column}`); + canvas.style.setProperty("--row", `${view.Row}`); + canvas.style.setProperty("--scale", `${view.Scale}`); + for (const obj of objs) { + const node = BuildObject(obj); + if (node) { canvas.appendChild(node); } } - return result; + content.appendChild(canvas); + return content; } -function ConstructSubDiv(...pairs: [shouldDo: boolean, name: string, func: () => string][]) { - var result: string = ''; - for (const [key, name, func] of pairs) { - result += key ? `
${func()}
` : ``; + +function BuildObject(obj: RDEvent | RDGroup): HTMLElement { + return obj instanceof RDGroup ? BuildGroup(obj) : BuildEvent(obj); +} + +function BuildEvent(ev: RDEvent): HTMLElement { + const wrapper = document.createElement("div"); + wrapper.className = "rdtk-event"; + wrapper.style.left = `${ev.Style.Beat * CELL_SIZE}px`; + wrapper.style.top = `${ev.Style.Y * CELL_SIZE}px`; + + const state: IconStyle = { enabled: true, active: false, hover: false, scale: RDTK_SCALE, showDuration: false }; + const rdobj = ToRDtkObject(ev); + const inner = rdobj ? createElementEvent(rdobj, state) : null; + if (inner) { + inner.style.position = "absolute"; + inner.style.left = "0px"; + inner.style.top = "0px"; + wrapper.appendChild(inner); } - return result; + else { + wrapper.classList.add("rdtk-unknown"); + wrapper.textContent = ev.Name || "unknown"; + } + + ApplyFilter(wrapper, ev.Style); + if (ev.Condition !== undefined) { + const condition = document.createElement("div"); + condition.className = `rdtk-condition condition-${ev.Condition}`; + wrapper.appendChild(condition); + } + + const offsetBeat = ev.ClickStyle?.Beat ?? 0; + const offsetY = ev.ClickStyle?.Y ?? 0; + const hasOffset = offsetBeat !== 0 || offsetY !== 0; + + function setState(hover: boolean, active: boolean): void { + state.hover = hover; + state.active = active; + inner?.onStateChange(state); + wrapper.classList.toggle("hover", hover); + wrapper.classList.toggle("active", active); + wrapper.style.transform = (active && hasOffset) + ? `translate(${offsetBeat * CELL_SIZE}px, ${offsetY * CELL_SIZE}px)` + : ""; + ApplyFilter(wrapper, active && ev.ClickStyle ? ev.ClickStyle : ev.Style); + } + wrapper.addEventListener("mouseover", (e) => { + if (!wrapper.contains(e.relatedTarget as Node | null)) { setState(true, state.active); } + }); + wrapper.addEventListener("mouseout", (e) => { + if (!wrapper.contains(e.relatedTarget as Node | null)) { setState(false, false); } + }); + wrapper.addEventListener("mousedown", () => setState(true, true)); + wrapper.addEventListener("mouseup", () => setState(state.hover, false)); + (wrapper as RDtkNode).__setRDtkState = setState; + return wrapper; } + +function BuildGroup(grp: RDGroup): HTMLElement { + const wrapper = document.createElement("div"); + wrapper.className = "rdtk-group"; + wrapper.style.left = `${grp.Style.Beat * CELL_SIZE}px`; + wrapper.style.top = `${grp.Style.Y * CELL_SIZE}px`; + wrapper.style.width = `${grp.Width * CELL_SIZE}px`; + wrapper.style.height = `${grp.Height * CELL_SIZE}px`; + wrapper.style.outlineColor = ToHex(grp.Outline); + ApplyFilter(wrapper, grp.Style); + + for (const child of grp.Children) { + const node = BuildObject(child); + if (node) { wrapper.appendChild(node); } + } + + const offsetBeat = grp.ClickStyle?.Beat ?? 0; + const offsetY = grp.ClickStyle?.Y ?? 0; + const hasOffset = offsetBeat !== 0 || offsetY !== 0; + + function setState(hover: boolean, active: boolean): void { + wrapper.classList.toggle("hover", hover); + wrapper.classList.toggle("active", active); + wrapper.style.transform = (active && hasOffset) + ? `translate(${offsetBeat * CELL_SIZE}px, ${offsetY * CELL_SIZE}px)` + : ""; + wrapper.style.outlineColor = active ? ToHex(grp.ClickOutline ?? grp.Outline) : ToHex(grp.Outline); + ApplyFilter(wrapper, active && grp.ClickStyle ? grp.ClickStyle : grp.Style); + } + wrapper.addEventListener("mouseover", (e) => { + if (!wrapper.contains(e.relatedTarget as Node | null)) { setState(true, false); } + }); + wrapper.addEventListener("mouseout", (e) => { + if (!wrapper.contains(e.relatedTarget as Node | null)) { setState(false, false); } + }); + wrapper.addEventListener("mousedown", () => setState(true, true)); + wrapper.addEventListener("mouseup", () => setState(true, false)); + (wrapper as RDtkNode).__setRDtkState = setState; + return wrapper; +} + +function ApplyFilter(el: HTMLElement, style: RDStyle): void { + const parts: string[] = []; + if (style.Hue !== undefined) { parts.push(`hue-rotate(${style.Hue}deg)`); } + if (style.Brightness !== undefined) { parts.push(`brightness(${style.Brightness}%)`); } + if (style.Grayscale !== undefined) { parts.push(`grayscale(${style.Grayscale}%)`); } + if (style.Opacity !== undefined) { parts.push(`opacity(${style.Opacity}%)`); } + el.style.filter = parts.join(" "); +} + function ToHex(color: Color) { const hex = parseInt(color.red.toFixed(0)).toString(16).padStart(2, '0') + @@ -986,4 +663,4 @@ function ToHex(color: Color) { return '#' + hex; } -(window as any).loadRDView = loadRDView; \ No newline at end of file +(window as any).loadRDView = loadRDView; diff --git a/script/rdview_render.js b/script/rdview_render.js new file mode 100644 index 0000000..aaf7a15 --- /dev/null +++ b/script/rdview_render.js @@ -0,0 +1,30 @@ +window.$docsify.plugins = [].concat(window.$docsify.plugins, (hook) => { + hook.doneEach(() => { + if (typeof window.RDViewRender !== "function") { + return; + } + const codeBlocks = document.querySelectorAll("pre[data-lang]"); + codeBlocks.forEach((codeBlock) => { + const lang = codeBlock.getAttribute("data-lang") || ""; + if (!lang.trim().startsWith("rdview")) { + return; + } + const codeEl = codeBlock.querySelector("code"); + const code = codeEl ? codeEl.innerText : codeBlock.innerText; + let node; + try { + node = window.RDViewRender(lang, code); + } catch (e) { + console.error("rdview render failed:", lang, e); + return; + } + if (!node) { + return; + } + const parent = document.createElement("div"); + parent.className = "rdtk-rdview-wrap"; + parent.appendChild(node); + codeBlock.replaceWith(parent); + }); + }); +}); diff --git a/script/special.js b/script/special.js index a3f0a7d..c17ce7c 100644 --- a/script/special.js +++ b/script/special.js @@ -228,7 +228,7 @@ function rdview() { function initCanvas() { const lang = textarea.value.split("\n")[0]; const code = textarea.value.split("\n").slice(1).join("\n"); - rdcanvas.innerHTML = RDViewRender(lang, code); + rdcanvas.replaceChildren(RDViewRender(lang, code)); } initCanvas(); initLineNumbers(); @@ -322,55 +322,52 @@ function rdview2() { } const eventStyle = { "scale": 2.0, "showDuration": false }; let maxy = 0; - const elemPromises = []; + const elems = []; 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; + 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 * + 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); }); - elemPromises.push(elem); + elem.addEventListener("mouseover", (event) => { + const eStyle = elem.eventStyle; + eStyle.hover = true; + elem.onStateChange(eStyle); + }); + elem.addEventListener("mouseout", (event) => { + const eStyle = elem.eventStyle; + eStyle.hover = false; + eStyle.active = false; + elem.onStateChange(eStyle); + }); + elem.addEventListener("mouseup", (event) => { + const eStyle = elem.eventStyle; + eStyle.active = false; + elem.onStateChange(eStyle); + }); + elems.push(elem); } - Promise.all(elemPromises).then((elems) => { - elems.forEach((elem) => { - rdcanvas.appendChild(elem); - }); + elems.forEach((elem) => { + rdcanvas.appendChild(elem); }); rdcanvas.style.position = "relative"; rdcanvas.style.height = `${maxy + 4 * 14 * eventStyle.scale}px`; diff --git a/script/tsconfig.json b/script/tsconfig.json index 276fa60..c4e4659 100644 --- a/script/tsconfig.json +++ b/script/tsconfig.json @@ -5,8 +5,8 @@ "es2017", "dom" ], - "module": "es6", - "moduleResolution": "node", + "module": "esnext", + "moduleResolution": "bundler", "strict": true, "esModuleInterop": true, "skipLibCheck": true, diff --git a/style/rdview-rdtk.css b/style/rdview-rdtk.css new file mode 100644 index 0000000..a5fe8c1 --- /dev/null +++ b/style/rdview-rdtk.css @@ -0,0 +1,66 @@ +.rdtk-rdview-wrap { + margin: 0; +} + +.rdtk-rdview { + position: relative; + overflow: visible; +} + +.rdtk-event { + position: absolute; + cursor: pointer; + z-index: 0; + transition: transform 0.3s, filter 0.3s; +} + +.rdtk-event.hover { + z-index: 2; +} + +.rdtk-group { + position: absolute; + outline-style: solid; + outline-width: 2px; + transition: transform 0.3s, filter 0.3s, outline-color 0.3s; +} + +.rdtk-group.hover { + z-index: 1; +} + +.rdtk-condition { + position: absolute; + top: 0; + left: 0; + width: 12px; + height: 12px; + background-size: contain; + background-repeat: no-repeat; + pointer-events: none; + z-index: 5; +} + +.rdtk-condition.condition-true { + background-image: url(./assets/condition-true.png); +} + +.rdtk-condition.condition-false { + background-image: url(./assets/condition-false.png); +} + +.rdtk-condition.condition-both { + background-image: url(./assets/condition-both.png); +} + +.rdtk-unknown { + color: red; + font-weight: bold; + font-size: 12px; +} + +.rdtk-error { + color: red; + font-weight: bold; + white-space: pre-wrap; +} -- 2.48.1.windows.1 From 2af05f761e165375251921da85c776c52cdfb58f Mon Sep 17 00:00:00 2001 From: OLDREDSTONE Date: Mon, 5 Oct 2026 17:55:10 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E7=AE=80=E5=8D=95=E7=9A=84=E8=87=AA=E5=AE=9A=E4=B9=89=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E6=9F=A5=E8=AF=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 1 + pages/custommethod.md | 12 + script/custommethod-data.js | 4149 +++++++++++++++++++++++++++++++++ script/custommethod-search.js | 655 +++++- script/custommethod-search.ts | 683 +++++- script/tsconfig.json | 6 +- style/special.css | 219 ++ 7 files changed, 5666 insertions(+), 59 deletions(-) create mode 100644 script/custommethod-data.js diff --git a/index.html b/index.html index 98acbce..88128f0 100644 --- a/index.html +++ b/index.html @@ -32,6 +32,7 @@ +