高级功能
高级功能
本页面讲解 DyNode 包含的进阶编辑功能。
命令
你可以通过 DyNode 内置的控制台与一系列编辑命令来对谱面进行快捷和高级的操作。
使用 . 或 / 来打开控制台。
使用不同的键位打开控制台会为命令添加不同的前缀 . 与 / 。
- 如果最终执行的命令前缀为
.,则命令执行完毕之后控制台将会立即关闭,便于你快速对谱面进行连续的编辑操作。 - 如果最终执行的命令前缀为
/,则命令执行完毕之后控制台将不会关闭。 - 最终执行的命令也可以不具有前缀。
一条命令由命令名称与不定长的命令参数组成。不同的命令可能要求不同的参数数量。如果你需要使用某个命令,你需要查看命令的名称、要求的参数数量和类型以及其效果。你也可以使用命令的缩写来代替命令的名称。命令参数和命令名称必须通过空格分隔。
一条命令也可能有多种变体,不同的变体会要求不同的参数数量,并可能具有不同的效果。
下面将会列出所有可用的命令及其详情,命令将以下面的基本格式进行描述。
.<命令名称> <必需参数1> <必需参数2> ... [可选参数1] [可选参数2] ...
// 命令的效果
.<命令的缩写1>
.<命令的缩写2>
...不同的命令变体在描述时将被视为不同的命令,但不会重复其缩写。
额外地,如果一个命令具有仅一个参数的变体,且这个参数是一个实数,那么下面的命令格式也是可被识别的。这方便你快速输入较短的命令。
.<命令名称><参数1>例如:
.w1.5 // 修改选中音符宽度为 1.5
.p2.5 // 修改选中音符位置为 2.5
.s2 // 修改选中音符所在侧面为右侧如果你输入的参数大于匹配到的最大参数数量的变体,则多出来的这些参数会被拼接到最后一个参数上,以空格分隔。这方便你输入需求单个字符串参数的命令。你也可以使用双引号将需要被识别为单个参数的内容包含起来。
你可以使用 ↑ / ↓ 来快速跳转到你曾经使用过的命令。
你可以使用 ESC 或 .q 来关闭控制台。
快速上手
提示
如果你需要快速上手命令功能,则下面是一个供你简单了解命令作用的指南。
你可以通过下面的操作来快速批量地修改音符到你想要的宽度值。
- 选中你想要修改的音符。
- 按下 . 键。
- 输入
w1.5。或者将1.5修改为你想要的任意值。 - 按下回车键。
你可以通过下面的操作来快速地在选中的音符之间按时间顺序排列生成曲线并用音符进行填充。
- 选中你想要进行连接的同一侧面的音符。
- 按下 . 键。
- 输入
lin或cub。 - 按下回车键。


关于曲线命令变体
你也可以输入 lin8。其中 8 代表覆盖的节拍细分。在这一细分下,填充的音符将是 32 分音符。默认情况下,曲线生成指令将使用当前你正在使用的节拍细分。
或者输入 lin tap。其中 tap 代表你想要填充的音符类型。
这两个参数可以以任意顺序排列。你可以输入 lin 8 tap,也可以输入 lin tap 8。
但 lin8 tap 是不行的。短命令格式仅支持一个参数的变种。
基本属性编辑
你可以使用下面的一系列命令快速编辑选中音符的基本属性。
.width <实数>
// 修改选中音符的宽度
.w
.wid
.position <实数>
// 修改选中音符的位置
.p
.pos
.side <0|1|2|任意整数>
// 修改选中音符的所在侧面。0 - 正面;1 - 左侧;2 - 右侧。
// 你也可以输入任意整数,它们最终会被映射到一个0到2之间的值。
.s
.time <实数>
// 修改选中音符的时间,以毫秒为单位
.t曲线填充
你可以使用下面的一系列命令对选中的音符生成曲线并在音符与音符之间的节拍线上平滑地填充音符。
.linear <可变参数>
// 曲线填充 - 线性
.lin
.cosine <可变参数>
// 曲线填充 - 余弦
.cos
.cubic <可变参数>
// 曲线填充 - 自然三次样条
.cub
.catrom <可变参数>
// 曲线填充 - 向心 Catmull-Rom 样条
.crom这些命令将获取你选中的所有音符并将它们按照时间排列,按这一序列生成曲线之后再在音符与音符之间进行平滑的填充。
上面的所有命令都共享同样的参数和效果,它们只有使用的曲线生成算法不同。
你选中的音符必须处于同一下落面。
你可以为上面的所有命令附带任意长度的参数。他们将按顺序作用于本次的曲线生成上。
- 如果参数是一个正整数
x,则它将覆盖你正在使用的节拍细分设置。填充的音符将会是4*x分音符。 - 如果参数是一个负整数
-x,则它将覆盖你正在使用的节拍间隔设置。- 将从第一个音符的下
x个节拍线开始放置音符,随后在放置音符后的下x个节拍线放置第二个音符,直到超过本段的最后一个音符为止。 - 间隔设置默认为
1。
- 将从第一个音符的下
- 如果参数是一个音符类型,则填充的音符将会是你选择的音符类型。
- TAP: 使用
tap/normal/note表示。 - SLIDE: 使用
slide/chain表示。 - HOLD: 使用
hold表示。 - 如果你没有使用这个参数,则一段曲线填充的音符类型将从这段曲线头部的音符类型进行复制。
- TAP: 使用
例如,.cubic slide 8 代表使用 SLIDE 音符在选中的音符之间按自然三次样条生成的曲线以 32 分音符进行填充。

.cubic 8 -2 使生成的音符两两间隔一个 32 分音符。这使你可以交错地生成曲线。

批量高级操作
你可以使用下面的一系列命令对音符进行高级操作。
吸附指令
snap 指令方便你批量修复偏移的音符到正确的时间点上。
.snap [pre|post|nearest]
// 将选中的所有音符批量吸附到拍线上。
// 参数决定吸附的拍线对象。
// pre 为无参数时的默认值。不同的参数将决定吸附的目标。
pre每一个音符都将吸附到所在时间的前一个最近拍线上。post每一个音符都将吸附到所在时间的后一个最近拍线上。nearest每一个音符都将吸附到离所在时间最近的拍线上。
复制与去重指令
duplicate 指令可以使你快速地多次批量进行快速复制。这一功能等价于对选中的音符连续使用多次快速复制功能。
.duplicate [整数]
// 将选中的音符批量复制到最晚音符的下一个节拍线上。
// 可选的复制次数表示将该功能重复执行多次。
.dupdeduplicate 指令可以使你快速地对选中或所有音符进行去重指令。对所有具有同样属性的音符,该指令将只保留其中的一个音符。
.deduplicate
// 对选中或所有的音符进行去重。
.dedup其它指令
.center
// 移动选中的音符,使其最左端和最右端居中对称。
.cen
.purge
// 删除所有音符。
.fix
// 修复有关音符的常见错误。
// - 修复出界音符,将所有出界音符移动到界内。
.expr <表达式>
// 对选中的音符执行表达式。详见指南的[高级功能/表达式]。
.e杂项指令
.echo <字符串>
// 输出一行内容。
.quit
// 关闭控制台
.q表达式
使用 0 或通过 .expr / .e 命令来输入表达式。
一个合法的表达式是由一系列运算符、数字、变量与函数排列组合构成的一个有意义的式子,例如:a=10+b*c,100>90等。
表达式支持基本的四则运算符 +,-,*,/,%,位运算符 <<,>>,|,&,逻辑运算符 &&,||,!,关系运算符 >,<,>=,<=,==,!=,赋值 = 等。
通过 函数名(参数1, 参数2, ...) 的方式来调用函数。例如 sin(0),pow(2,3) 等。
你可以以符合直觉的方式以类似C语言的语法来撰写该表达式,一些合法的表达式例子如下:
a=(10+20)*30 // a=900
b=a // b=900
b=a=20 // b=(a=20),右结合
c=10*20/20 // c=(10*20)/20,左结合
a=rand(5) // rand(5) 的结果是 [0,5] 内的任意实数
b=pow(2,3) // b=8, pow(2,3) 的结果是 2 的 3 次方,即 8
c=sin(0)+cos(0) // c=1你可以通过表达式的计算来批量修改全部音符/选中音符的属性。
当前支持的属性变量见下表:
| 属性 | 作用 | 单位 | 音符限制 |
|---|---|---|---|
| time | 音符所在的时间 | ms | |
| pos | 音符所在的位置 | ||
| side | 音符所在的下落侧(0-正面/1-左侧/2-右侧) | ||
| wid | 音符的宽度 | ||
| index | 当前处理的音符在所有被处理的音符序列中的位置,从0开始计数 | ||
| len | 音符的持续时间 | ms | HOLD |
| htime | 音符头部的所在时间 | ms | HOLD |
| etime | 音符尾部的所在时间 | ms | HOLD |
index 是一个特殊的变量。表达式将对你选中的音符按照时间、位置的优先级从小到大排列(时间越小则越先被处理),而后第一个被处理的音符的 index 变量即为 0,第二个被处理的音符的 index 变量即为 1 ... 以此类推。这个变量可以被修改,但修改这个变量不会产生任何效果。
当前支持的函数和内置变量见下表:
| 函数 | 作用 |
|---|---|
pow(a, b) | 返回 a 的 b 次方 |
pi() | 返回圆周率 π 的精确值 |
sin(x) | 返回 x 的正弦值(弧度) |
cos(x) | 返回 x 的余弦值(弧度) |
step(edge, x) | 阶跃函数,若 x >= edge 返回 1,否则返回 0 |
clamp(x, min, max) | 将 x 限制在 min 和 max 之间 |
exp(x) | 返回自然常数 e 的 x 次方 |
floor(x) | 对 x 向下取整 |
ceil(x) | 对 x 向上取整 |
round(x) | 对 x 四舍五入 |
rand(x) | 返回 [0, x] 范围内的随机实数 |
randr(l, r) | 返回 [l, r] 范围内的随机实数 |
irand(x) | 返回 [0, x] 范围内的随机整数 |
irandr(l, r) | 返回 [l, r] 范围内的随机整数 |
表达式在每个音符上的计算是独立的。表达式计算的过程可以概括如下:
- 根据音符的属性初始化表达式的变量。
- 计算表达式,中途表达式的变量产生变化。
- 读取表达式的变量,根据变量的变化修改音符的属性。
在 DyNode 中,输入的表达式以 ; 分隔,他们将依次按顺序执行。变量的存储类型为双精度浮点数。
特别的,一些变量存在音符限制,这意味着他们只在一部分音符上能够生效。所有表达式的计算都将忽略 SUB 类型的音符(HOLD 尾部音符),详见 HOLD 属性的修改 。
特别的,下落侧的属性(side)最终总会对 3 取模。举例而言,将 side 设置为 1,4 或 -2 是等价的。
下面是一些表达式的合法实例,其中一行代表一个例子:
wid=wid*2 // 音符的宽度翻倍
pos=2.5 // 音符的位置全部设置为2.5
time=time+10 // 音符的所在时间+10ms(添加音符延迟)
pos=2*2.5-pos // 将音符按照屏幕的中线进行对称(屏幕中线的位置为2.5)
time=time/1.5;len=len/1.5 // 谱面1.5倍速(所有音符的时间除以1.5,所有HOLD的长度除以1.5)
a=20;time=a // 定义变量a,并将a赋值给time
side=side+1 // 正面音符移动到左侧,左侧音符移动到右侧,右侧音符移动到正面
pos=(side==0)*2+(side!=0)*pos // 仅修改正面音符的位置为2
side=-side // 将左右侧音符进行交换HOLD 属性的修改
所有表达式的计算都将忽略 SUB 类型的音符,取而代之的是针对 HOLD 类型的音符存在一些特殊的属性变量。
| 属性 | 作用 | 单位 |
|---|---|---|
| len | 音符的持续时间 | ms |
| htime | 音符头部的所在时间 | ms |
| etime | 音符尾部的所在时间 | ms |
这意味着当你修改 HOLD 的 time 属性时,它实际不会修改 HOLD 的持续时间,也即修改 time 意味着将 HOLD 进行整体的移动而非头部与尾部分别进行修改。
如果你想实现头部与尾部分别进行修改,你需要修改 htime 与 etime 属性,而非 time 属性。
你可能发现这三个属性实际上会产生冲突,即若你修改了 htime 与 etime,那么 len 属性理论上也会发生变化,但当前在表达式的计算过程中变量不会绑定,也即一个变量不会因为另一个变量的变动而变动。
在实际的操作中,我们不推荐你在一个表达式中同时出现两个与 HOLD 属性相关的变量。以下是 DyNode 对 HOLD 属性相关变量冲突的处理方法:
- 若
time属性与htime属性同时被修改,htime的修改将覆盖time的修改。 - 若
len属性与etime属性同时被修改,len的修改将覆盖etime的修改。
下面是一些合法的修改 HOLD 属性的表达式例子:
htime=htime+10;etime=etime-10 // 所有HOLD音符的头部时间+10,所有HOLD音符的尾部时间-10
len=len/2 // 所有HOLD的持续时间除以2
htime=100 // 修改所有HOLD音符的头部时间为100
htime=100;len=100 // 等价于 time=100;len=100