Skip to content

Commit 7dbc2a0

Browse files
committed
[F] 修复使用绝对时间的星星,产生1-2[#3.45]这种“simai文档中没有提到过的语法”的问题。
同时新增`Workaround_ForceUseWaitTimeInsteadOfBPMForAbsDurationSlide`选项。 Fix MuNET-OSS/MaiChartManager#64
1 parent e8547e3 commit 7dbc2a0

1 file changed

Lines changed: 27 additions & 2 deletions

File tree

generator/mai/SimaiGenerator.cs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Globalization;
12
using System.Numerics;
23
using MuConvert.generator;
34
using MuConvert.utils;
@@ -32,6 +33,14 @@ public class SimaiGenerator : IGenerator<MaiChart>
3233
* 如果你不希望开启本选项,请new SimaiGenerator() { Workaround_ForceUseAbsDurationForSlidesWithNonStandardWaitTime = false } 即可。
3334
*/
3435
public bool Workaround_ForceUseAbsDurationForSlidesWithNonStandardWaitTime = true;
36+
/**
37+
* 这是一个Workaround的选项。
38+
* 形如[120#3.45]的,BPM+绝对时间的星星持续时长写法,尽管Simai官方文档中明确其为标准语法,但AstroDX中会无法解析(直接报错拒绝运行)。
39+
* 因此,这里提供了一个bool选项,默认为开启:
40+
* 当本选项开启时,对持续时间为绝对秒数的星星,不会生成形如[120#3.45]的语句出来,而是写成[0.5##3.45]这种绝对等待时间+绝对持续时间的写法。
41+
* 如果你不希望开启本选项,请new SimaiGenerator() { Workaround_ForceUseWaitTimeInsteadOfBPMForAbsDurationSlide = false } 即可。
42+
*/
43+
public bool Workaround_ForceUseWaitTimeInsteadOfBPMForAbsDurationSlide = true;
3544

3645
private readonly List<Alert> alerts = [];
3746
private string result = ""; // 不用StringBuilder是因为生成过程不可避免地需要对字符串做一些回溯的操作,需要倒着从字符串中查找字符。这样的场景下,StringBuilder并无性能优势,用string就够了。
@@ -190,15 +199,31 @@ private string DurationStr(Rational start, Duration duration, bool forceAbsTime
190199

191200
if (seg.Duration != null)
192201
{
193-
bool nonStdWaitTime = rollingTime == slide.Time && // 是带有时间标记的第一段
194-
slide.WaitTime.InvariantBar != new Rational(1, 4);
202+
bool isFirstDuration = rollingTime == slide.Time; // 是不是带有时间标记的第一段
203+
bool nonStdWaitTime = isFirstDuration && slide.WaitTime.InvariantBar != new Rational(1, 4);
195204
var durationStr = DurationStr(rollingTime, seg.Duration,
196205
// 对非标准等待时间的星星,如果相关Workaround选项开启,则强制其使用绝对时间。
197206
forceAbsTime: nonStdWaitTime && Workaround_ForceUseAbsDurationForSlidesWithNonStandardWaitTime);
198207
if (nonStdWaitTime)
199208
{ // 非标准等待时间的星星,应该加上等待时间标记。simai仅支持绝对时间的等待时间标记。
200209
durationStr = FormattableString.Invariant($"[{(decimal)slide.WaitTime.Seconds:0.####}##{durationStr[1..].TrimStart('#')}");
201210
}
211+
else if (durationStr[1] == '#')
212+
{
213+
// 对DurationStr函数,返回的是绝对时间[#3.45]的情况:
214+
// simai文档【SLIDE (基本・形状)】一节,并没给出`1-2[#3.45]`这种写法,因此无法认为这是“标准语法”;且经过测试,majdataplay和astrodx也都是不支持这种写法的。
215+
// simai文档中,只给出了`1-2[120#3.45]`或`1-2[0.5##3.45]`这两种写法。然后亲测,前者astrodx也是不支持的。
216+
// 所以现在的逻辑是:默认输出前者`1-2[120#3.45]`,但如果相关Workaround选项被开启,则使用后者1-2[0.5##3.45]`。
217+
if (!Workaround_ForceUseWaitTimeInsteadOfBPMForAbsDurationSlide)
218+
{
219+
durationStr = FormattableString.Invariant($"[{seg.Duration.InvariantBpm:0.####}#{durationStr[2..]}");
220+
}
221+
else
222+
{
223+
decimal waitSec = isFirstDuration ? (decimal)slide.WaitTime.Seconds : 0m;
224+
durationStr = FormattableString.Invariant($"[{waitSec:0.####}##{durationStr[2..]}");
225+
}
226+
}
202227
res += durationStr;
203228
rollingTime += seg.Duration.Bar;
204229
}

0 commit comments

Comments
 (0)