kipphi 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/env.ts CHANGED
@@ -1,7 +1,215 @@
1
1
 
2
+ // chart 1
3
+ // bpm 2
4
+ // nnnlist 3
5
+ // judgeline 4
6
+ // nnList 5
7
+ // EventNodeSequence 6
8
+ // notenode 7
9
+ // eventnode 8
10
+ // evaluator 9
11
+ // easing a
12
+ // note b
13
+
14
+
15
+ // 就挺神奇的!明明typeof后面跟值,这里却可以写成类型导入
16
+ import { type TimeT, type EventValueType } from "./chartTypes";
17
+ import { EventNode } from "./event";
18
+ import { toTimeString } from "./util";
19
+
20
+ // occupied 1
21
+ // invalid data 2
22
+ // invalid usage 3
23
+
24
+ const
25
+ CHART = 0x100,
26
+ BPM = 0x200,
27
+ NNN_LIST = 0x300,
28
+ JUDGE_LINE = 0x400,
29
+ NN_LIST = 0x500,
30
+ ENS = 0x600,
31
+ NOTE_NODE = 0x700,
32
+ EVENT_NODE = 0x800,
33
+ EVALUATOR = 0x900,
34
+ EASING = 0xA00,
35
+ NOTE = 0xB00,
36
+ TC = 0xC00,
37
+ MACRO = 0xD00,
38
+ INTERNAL = 0xF00,
39
+
40
+ OCCPIED = 0x10,
41
+ INVALID_DATA = 0x20, // 一般是指读取谱面时的无效事件类型、缓动号等等
42
+ INVALID_USAGE = 0x30, // 不知道归入哪里就放这吧(((
43
+ INVALID_TYPE = 0x40 // 这里的type指ECMAScript数据类型,事件类型错误可以归入此类
44
+ ;
45
+
46
+
47
+
48
+ export enum ERROR_IDS {
49
+ UI_OCCUPIED = CHART | OCCPIED,
50
+
51
+
52
+ SEQUENCE_NAME_OCCUPIED = ENS | OCCPIED | 0,
53
+ SEQUENCE_NODE_TIME_OCCUPIED = ENS | OCCPIED | 1,
54
+ INVALID_EVENT_NODE_SEQUENCE_TYPE = ENS | INVALID_DATA | 0,
55
+ EVENT_NODE_TIME_NOT_INCREMENTAL = ENS | INVALID_DATA | 1,
56
+ PARENT_SEQUENCE_NOT_FOUND = ENS | INVALID_USAGE | 1,
57
+ NEEDS_AT_LEAST_ONE_ENS = ENS | INVALID_USAGE | 2,
58
+ SEQUENCE_TYPE_NOT_CONSISTENT = ENS | INVALID_USAGE | 3,
59
+
60
+ EXPECTED_TYPED_ENS = ENS | INVALID_TYPE | 0,
61
+
62
+ CANNOT_SUBSTITUTE_EXPRESSION_EVALUATOR = EVENT_NODE | INVALID_USAGE | 0,
63
+ CANNOT_INSERT_BEFORE_HEAD = EVENT_NODE | INVALID_USAGE | 1,
64
+ CANNOT_GET_FULL_INTEGRAL_OF_FINAL_START_NODE = EVENT_NODE | INVALID_USAGE | 2,
65
+ CANNOT_INTERPOLATE_TAILING_START_NODE = EVENT_NODE | INVALID_USAGE | 3,
66
+
67
+ INVALID_EASING_ID = EASING | INVALID_DATA | 0,
68
+ CANNOT_IMPLEMENT_TEMEAS_WITH_NON_EASING_ENS = EASING | INVALID_DATA | 1,
69
+ CANNOT_IMPLEMENT_TEMEAS_WITH_NON_NUMERIC_ENS = EASING | INVALID_DATA | 2,
70
+ UNIMPLEMENTED_TEMPLATE_EASING = EASING | INVALID_DATA | 3,
71
+ MUST_INTERPOLATE_TEMPLATE_EASING = EASING | INVALID_USAGE | 0,
72
+ NODES_NOT_CONTINUOUS = EASING | INVALID_USAGE | 1,
73
+ NODES_NOT_BELONG_TO_SAME_SEQUENCE = EASING | INVALID_USAGE | 2,
74
+ NODES_HAS_ZERO_DELTA = EASING | INVALID_USAGE | 3,
75
+
76
+ CANNOT_DIVIDE_EXPRESSION_EVALUATOR = EVALUATOR | INVALID_USAGE | 0,
77
+ MISSING_MACRO_EVALUATOR_KEY = EVALUATOR | INVALID_DATA | 0,
78
+ MACRO_EVALUATOR_NOT_FOUND = EVALUATOR | INVALID_DATA | 1,
79
+
80
+
81
+
82
+ INVALID_NOTE_PROP_TYPE = NOTE | INVALID_TYPE | 0,
83
+
84
+
85
+ INVALID_TIME_TUPLE = TC | INVALID_DATA | 0,
86
+
87
+ TIME_MACRO_NOT_FOUND = MACRO | INVALID_DATA | 0,
88
+ VALUE_MACRO_NOT_FOUND = MACRO | INVALID_DATA | 1,
89
+ UNKNOWN_MACRO_EXPRESSION = MACRO | INVALID_DATA | 2,
90
+ JAVASCRIPT_SYNTAX_ERROR = MACRO | INVALID_DATA | 3,
91
+ PROTO_PRESENT_IN_NONPARAMETRIC = MACRO | INVALID_USAGE | 0,
92
+ PARAMETRIC_MACRO_REQUIRES_PROTO_KEY = MACRO | INVALID_DATA | 4,
93
+ MACRO_NOT_PARAMETRIC = MACRO | INVALID_DATA | 5,
94
+ }
95
+
96
+ export const ERRORS = {
97
+ UI_OCCUPIED: (name: string) =>
98
+ `UI '${name}' is occupied`,
99
+
100
+
101
+ SEQUENCE_NAME_OCCUPIED: (name: string) =>
102
+ `Sequence name '${name}' is occupied`,
103
+ SEQUENCE_NODE_TIME_OCCUPIED: (time: TimeT, id: string) =>
104
+ `Time ${toTimeString(time)} already has a node (in sequence ${id})`,
105
+ INVALID_EVENT_NODE_SEQUENCE_TYPE: (type: any) =>
106
+ `Invalid event node sequence type: '${type}'`,
107
+ EXPECTED_TYPED_ENS: (typeStr: keyof typeof EventValueType, id: string, value: unknown) =>
108
+ `Expected EventNodeSequence for ${typeStr} but seen value ${value} (Processing ${id})`,
109
+ EVENT_NODE_TIME_NOT_INCREMENTAL: (pos: string) =>
110
+ `EventNode time is not incremental (at ${pos})`,
111
+ PARENT_SEQUENCE_NOT_FOUND: (nodeTime: TimeT) =>
112
+ `Parent EventNodeSequence not found for an EventNode at time ${toTimeString(nodeTime)} (Did you forget to add it to a sequence?)`,
113
+ NEEDS_AT_LEAST_ONE_ENS: () =>
114
+ `Needs at least one EventNodeSequence`,
115
+ SEQUENCE_TYPE_NOT_CONSISTENT: (typeStr: string, but: string) =>
116
+ `EventNodeSequence type is not consistent (expected ${typeStr} but seen value ${but})`,
117
+
118
+
119
+ CANNOT_SUBSTITUTE_EXPRESSION_EVALUATOR: () =>
120
+ `Cannot substitute ExpressionEvaluator`,
121
+ CANNOT_INSERT_BEFORE_HEAD: () =>
122
+ "Cannot insert before the first EventStartNode",
123
+ CANNOT_GET_FULL_INTEGRAL_OF_FINAL_START_NODE: () =>
124
+ "Cannot get full integral of final start node",
125
+ CANNOT_INTERPOLATE_TAILING_START_NODE: () =>
126
+ "Cannot interpolate tailing start node",
127
+
128
+ INVALID_EASING_ID: (id: string) =>
129
+ `Invalid easing id: '${id}'`,
130
+ CANNOT_IMPLEMENT_TEMEAS_WITH_NON_EASING_ENS: (temEasName: string) =>
131
+ `Cannot implement TemplateEasing with a non-easing-typed EventNodeSequence (Processing template '${temEasName}')`,
132
+ CANNOT_IMPLEMENT_TEMEAS_WITH_NON_NUMERIC_ENS: (temEasName: string) =>
133
+ `Cannot implement TemplateEasing with a non-numeric EventNodeSequence (Processing template '${temEasName}')`,
134
+ MUST_INTERPOLATE_TEMPLATE_EASING: () =>
135
+ "Must interpolate template easing",
136
+
137
+ NODES_NOT_CONTINUOUS: () =>
138
+ "The EventNodes to encapsulate are not continuous",
139
+ NODES_NOT_BELONG_TO_SAME_SEQUENCE: () =>
140
+ "The EventNodes to encapsulate does not belong to same sequence",
141
+ NODES_HAS_ZERO_DELTA: () =>
142
+ "The EventNodes to encapsulate has zero delta",
143
+
144
+ INVALID_NOTE_PROP_TYPE: (prop: string, value: any, type: any) =>
145
+ `Invalid type for ${prop}. Got *${value}*, expected ${type}`,
146
+
147
+ INVALID_TIME_TUPLE: (tuple: any) =>
148
+ `Invalid time tuple: '${typeof tuple === "undefined" ? 'undefined' : tuple.valueOf()}'`,
149
+
150
+
151
+
152
+
153
+ CANNOT_DIVIDE_EXPRESSION_EVALUATOR: (id: string) =>
154
+ `Cannot divide ExpressionEvaluator (Compiling ${id})`,
155
+
156
+
157
+ UNIMPLEMENTED_TEMPLATE_EASING: (temEasName: string) =>
158
+ `Unimplemented template easing: '${temEasName}'`,
159
+
160
+ MISSING_MACRO_EVALUATOR_KEY: (pos: string) =>
161
+ `Missing Macro Evaluator key. At ${pos}`,
162
+ MACRO_EVALUATOR_NOT_FOUND: (evaluatorId: string, pos: string) =>
163
+ `Macro Evaluator '${evaluatorId}' not found. At ${pos}`,
164
+ TIME_MACRO_NOT_FOUND: (macroId: string, pos: string) =>
165
+ `Time Macro '${macroId}' not found. At ${pos}`,
166
+ VALUE_MACRO_NOT_FOUND: (macroId: string, pos: string) =>
167
+ `Value Macro '${macroId}' not found. At ${pos}`,
168
+ UNKNOWN_MACRO_EXPRESSION: (expression: string, macroId: string) =>
169
+ `Unknown Macro Expression '${expression}'. At ${macroId}`,
170
+ PROTO_PRESENT_IN_NONPARAMETRIC: (macroId: string) =>
171
+ `'@proto can only be used in parametric Macros. At ${macroId}'`,
172
+ JAVASCRIPT_SYNTAX_ERROR: (error: Error, macroId: string) =>
173
+ `JavaScript Syntax Error: ${error.message}. At ${macroId}`,
174
+ PARAMETRIC_MACRO_REQUIRES_PROTO_KEY: (pos) =>
175
+ `Parametric Macro requires key. At ${pos}`,
176
+ MACRO_NOT_PARAMETRIC: (macroId: string, pos) =>
177
+ `Macro '${macroId}' is not parametric. At ${pos}`,
178
+ } satisfies Record<keyof typeof ERROR_IDS, (...args: any[]) => string>
179
+
180
+ export class KPAError<ET extends ERROR_IDS> extends Error {
181
+ constructor(message: string, public id: ET) {
182
+ super(message);
183
+ }
184
+ /**
185
+ * 对于解析谱面等场景,有时可能需要找出全部的错误,不宜直接抛出错误中断代码执行
186
+ *
187
+ * 此时可以调用该方法,该方法会输出错误并把它保存到KPAError的一个`buffer`静态属性下。
188
+ */
189
+ warn() {
190
+ console.warn(this.stack);
191
+ KPAError.buffer.push(this);
192
+ }
193
+ static buffer: KPAError<ERROR_IDS>[] = [];
194
+ static flush() {
195
+ KPAError.buffer = [];
196
+ }
197
+ }
198
+
199
+ export const err = new Proxy(ERRORS, {
200
+ get(target, name) {
201
+ return (...args: any[]) => new KPAError(target[name](...args) + `(KP${ERROR_IDS[name].toString(16)})`, ERROR_IDS[name]);
202
+ }
203
+ }) as unknown as { [key in keyof typeof ERRORS]: (...args: Parameters<typeof ERRORS[key]>) => KPAError<typeof ERROR_IDS[key]>};
204
+
2
205
  export default {
3
206
  DEFAULT_TEMPLATE_LENGTH: 16,
4
207
  BEZIER_INTERPOLATION_DENSITY: 256,
5
208
  NNLIST_Y_OFFSET_HALF_SPAN: 100,
209
+ JUMPARRAY_MIN_LENGTH: 64,
210
+ JUMPARRAY_MAX_LENGTH: 4096,
211
+ JUMPARRAY_MINOR_SCALE_COUNT: 16,
212
+ ERROR_IDS,
213
+ err,
6
214
  freeze() { Object.freeze(this); }
7
215
  }
package/evaluator.ts CHANGED
@@ -6,11 +6,13 @@ import {
6
6
  } from "./easing";
7
7
 
8
8
 
9
- import { TimeCalculator as TC } from "./time"
9
+ import TC from "./time";
10
10
 
11
- import type { Chart } from "./chart";
12
- import type { EventEndNode, EventStartNode } from "./event";
13
- import { EvaluatorType, EventValueType, InterpreteAs, type ColorEasedEvaluatorKPA2, type EasedEvaluatorDataOfType, type EvaluatorDataKPA2, type EventValueESType, type EventValueTypeOfType, type ExpressionEvaluatorDataKPA2, type NumericEasedEvaluatorKPA2, type RGB, type TextEasedEvaluatorKPA2 } from "./chartTypes";
11
+ import type { EventEndNode, EventStartNode, NonLastStartNode } from "./event";
12
+ import { EasingType, EvaluatorType, EventValueType, EventValueTypeOfType, InterpreteAs, MacroEvaluatorBodyData, MacroEvaluatorDataKPA2, type ColorEasedEvaluatorKPA2, type EvaluatorDataKPA2, type EventValueESType, type ExpressionEvaluatorDataKPA2, type NumericEasedEvaluatorKPA2, type RGB, type TextEasedEvaluatorKPA2 } from "./chartTypes";
13
+ import type { JudgeLine } from "./judgeline";
14
+ import { Chart } from "./chart";
15
+ import { EVENT_MACROS } from "./macro";
14
16
 
15
17
 
16
18
  /// #declaration:global
@@ -24,19 +26,19 @@ import { EvaluatorType, EventValueType, InterpreteAs, type ColorEasedEvaluatorKP
24
26
  * @immutable
25
27
  * @since 2.0.0
26
28
  */
27
- export abstract class Evaluator<T> {
28
- abstract eval(event: EventStartNode<T>, beats: number): T;
29
- abstract dump(): EvaluatorDataKPA2<T>;
29
+ export abstract class Evaluator<T extends EventValueESType> {
30
+ abstract eval(event: NonLastStartNode<T>, beats: number): T;
31
+ abstract dumpFor(node: EventStartNode<T>): EvaluatorDataKPA2<T>;
30
32
  }
31
33
 
32
34
 
33
- export abstract class EasedEvaluator<T> extends Evaluator<T> {
35
+ export abstract class EasedEvaluator<T extends EventValueESType> extends Evaluator<T> {
34
36
  readonly easing: Easing;
35
37
  constructor(easing: Easing) {
36
38
  super();
37
39
  this.easing = easing;
38
40
  }
39
- override eval(startNode: EventStartNode<T> & { next: EventEndNode }, beats: number): T {
41
+ override eval(startNode: NonLastStartNode<T>, beats: number): T {
40
42
  const next = startNode.next;
41
43
  const timeDelta = TC.getDelta(next.time, startNode.time)
42
44
  const current = beats - TC.toBeats(startNode.time)
@@ -48,7 +50,31 @@ export abstract class EasedEvaluator<T> extends Evaluator<T> {
48
50
  // 其他类型,包括普通缓动和非钩定模板缓动
49
51
  return this.convert(value, nextValue, this.easing.getValue(current / timeDelta));
50
52
  }
51
- abstract convert(start: T, end: T, t: number): T;
53
+ abstract convert(start: T, end: T, progress: number): T;
54
+ /**
55
+ * 派生一个类型相同但使用不同缓动的求值器
56
+ * @param easing
57
+ * @returns
58
+ */
59
+ abstract deriveWithEasing(easing: Easing): EasedEvaluator<T>;
60
+
61
+ static getEvaluatorFromEasing<T extends EventValueESType>(type: EventValueTypeOfType<T>, easing: Easing, interpretedAs?: InterpreteAs): EasedEvaluatorOfType<T> {
62
+ const easingIsNormal = easing instanceof NormalEasing;
63
+ switch (type) {
64
+ case EventValueType.numeric:
65
+ return easingIsNormal
66
+ ? NumericEasedEvaluator.evaluatorsOfNormalEasing[easing.rpeId] as EasedEvaluatorOfType<T>
67
+ : new NumericEasedEvaluator(easing) as EasedEvaluatorOfType<T>;
68
+ case EventValueType.color:
69
+ return easingIsNormal
70
+ ? ColorEasedEvaluator.evaluatorsOfNormalEasing[easing.rpeId] as EasedEvaluatorOfType<T>
71
+ : new ColorEasedEvaluator(easing) as EasedEvaluatorOfType<T>;
72
+ case EventValueType.text:
73
+ return easingIsNormal
74
+ ? TextEasedEvaluator.evaluatorsOfNoEzAndItpAs[easing.rpeId][interpretedAs ?? InterpreteAs.str] as EasedEvaluatorOfType<T>
75
+ : new TextEasedEvaluator(easing, interpretedAs) as EasedEvaluatorOfType<T>
76
+ }
77
+ }
52
78
  }
53
79
 
54
80
  export type EasedEvaluatorOfType<T extends EventValueESType> = T extends number ? NumericEasedEvaluator : T extends RGB ? ColorEasedEvaluator : TextEasedEvaluator;
@@ -59,7 +85,7 @@ export class NumericEasedEvaluator extends EasedEvaluator<number> {
59
85
  super(easing);
60
86
  }
61
87
  private cache?: NumericEasedEvaluatorKPA2
62
- override dump(): NumericEasedEvaluatorKPA2 {
88
+ override dumpFor(): NumericEasedEvaluatorKPA2 {
63
89
  return this.cache ??= {
64
90
  type: EvaluatorType.eased,
65
91
  easing: this.easing.dump()
@@ -70,13 +96,20 @@ export class NumericEasedEvaluator extends EasedEvaluator<number> {
70
96
  }
71
97
  static default = new NumericEasedEvaluator(linearEasing);
72
98
  static evaluatorsOfNormalEasing: NumericEasedEvaluator[] = rpeEasingArray.map(easing => new NumericEasedEvaluator(easing));
99
+ override deriveWithEasing(easing: Easing): NumericEasedEvaluator {
100
+ if (easing instanceof NormalEasing) {
101
+ return NumericEasedEvaluator.evaluatorsOfNormalEasing[easing.rpeId];
102
+ } else {
103
+ return new NumericEasedEvaluator(easing);
104
+ }
105
+ }
73
106
  }
74
107
 
75
108
  export class ColorEasedEvaluator extends EasedEvaluator<RGB> {
76
109
  constructor(easing: Easing) {
77
110
  super(easing);
78
111
  }
79
- override dump(): ColorEasedEvaluatorKPA2 {
112
+ override dumpFor(): ColorEasedEvaluatorKPA2 {
80
113
  return {
81
114
  type: EvaluatorType.eased,
82
115
  easing: this.easing.dump()
@@ -90,6 +123,13 @@ export class ColorEasedEvaluator extends EasedEvaluator<RGB> {
90
123
  }
91
124
  static default = new ColorEasedEvaluator(linearEasing);
92
125
  static evaluatorsOfNormalEasing: ColorEasedEvaluator[] = rpeEasingArray.map(easing => new ColorEasedEvaluator(easing));
126
+ override deriveWithEasing(easing: Easing): ColorEasedEvaluator {
127
+ if (easing instanceof NormalEasing) {
128
+ return ColorEasedEvaluator.evaluatorsOfNormalEasing[easing.rpeId];
129
+ } else {
130
+ return new ColorEasedEvaluator(easing);
131
+ }
132
+ }
93
133
  }
94
134
 
95
135
 
@@ -102,18 +142,16 @@ export class ColorEasedEvaluator extends EasedEvaluator<RGB> {
102
142
  */
103
143
  export class TextEasedEvaluator extends EasedEvaluator<string> {
104
144
  constructor(easing: Easing,
105
- public readonly interpretedAs: InterpreteAs = InterpreteAs.str,
106
- public readonly font: string = "cmdysj.ttf"
145
+ public readonly interpretedAs: InterpreteAs = InterpreteAs.str
107
146
  )
108
147
  {
109
148
  super(easing);
110
149
  }
111
- override dump(): TextEasedEvaluatorKPA2 {
150
+ override dumpFor(): TextEasedEvaluatorKPA2 {
112
151
  return {
113
152
  type: EvaluatorType.eased,
114
153
  easing: this.easing.dump(),
115
- interpretedAs: this.interpretedAs,
116
- font: this.font
154
+ interpretedAs: this.interpretedAs
117
155
  }
118
156
  }
119
157
  override convert(value: string, nextValue: string, progress: number): string {
@@ -148,21 +186,69 @@ export class TextEasedEvaluator extends EasedEvaluator<string> {
148
186
  new TextEasedEvaluator(easing, InterpreteAs.int),
149
187
  new TextEasedEvaluator(easing, InterpreteAs.float),
150
188
  ]);
189
+ override deriveWithEasing(easing: Easing): EasedEvaluator<string> {
190
+ if (easing instanceof NormalEasing) {
191
+ return TextEasedEvaluator.evaluatorsOfNoEzAndItpAs[easing.rpeId][this.interpretedAs];
192
+ } else {
193
+ return new TextEasedEvaluator(easing, this.interpretedAs);
194
+ }
195
+ }
196
+ }
197
+
198
+
199
+
200
+ export class MacroEvaluator<T extends EventValueESType> extends Evaluator<T> {
201
+ readonly consumers: Map<EventStartNode<T>, ExpressionEvaluator<T>> = new Map();
202
+ constructor(public expression: string, public id: string) {
203
+ super();
204
+ }
205
+ compile(node: EventStartNode<T>, chart: Chart): ExpressionEvaluator<T> {
206
+ const jsExpr = this.expression
207
+ .replace(/@([a-z\.]+)/, (k) => {
208
+ return JSON.stringify(EVENT_MACROS[k](node, chart)) + " "
209
+ }).replace(/@\{\{(.+?)\}\}/g, (k) => {
210
+ const replaced = k.replace(new RegExp(Object.keys(EVENT_MACROS).join("|"), "g"), (k) => {
211
+ return JSON.stringify(EVENT_MACROS[k](node, chart)) + " "
212
+ });
213
+ return JSON.stringify(new Function("return " + replaced)()) + " ";
214
+ });
215
+ return new ExpressionEvaluator(jsExpr);
216
+ }
217
+ assignTo(node: EventStartNode<T>, chart: Chart): void {
218
+ node.evaluator = this;
219
+ this.consumers.set(node, this.compile(node, chart));
220
+ }
221
+ eval(event: NonLastStartNode<T>, beats: number): T {
222
+ return this.consumers.get(event)!.eval(event, beats);
223
+ }
224
+ dumpFor(node: EventStartNode<T>): MacroEvaluatorDataKPA2 {
225
+ return {
226
+ type: EvaluatorType.macro,
227
+ name: this.id,
228
+ compiled: this.consumers.get(node)!.jsExpr
229
+ }
230
+ }
231
+ dumpContent(): MacroEvaluatorBodyData {
232
+ return {
233
+ id: this.id,
234
+ macro: this.expression
235
+ }
236
+ }
151
237
  }
152
238
 
153
- export class ExpressionEvaluator<T> extends Evaluator<T> {
239
+ export class ExpressionEvaluator<T extends EventValueESType> extends Evaluator<T> {
154
240
  readonly func: (t: number) => T;
155
241
  constructor(public readonly jsExpr: string) {
156
242
  super();
157
243
  this.func = new Function("t", "return " + jsExpr) as (t: number) => T;
158
244
  }
159
- override eval(startNode: EventStartNode<T> & { next: EventEndNode }, beats: number): T {
245
+ override eval(startNode: NonLastStartNode<T>, beats: number): T {
160
246
  const next = startNode.next;
161
247
  const timeDelta = TC.getDelta(next.time, startNode.time)
162
248
  const current = beats - TC.toBeats(startNode.time)
163
249
  return this.func(current / timeDelta);
164
250
  }
165
- override dump(): ExpressionEvaluatorDataKPA2 {
251
+ override dumpFor(): ExpressionEvaluatorDataKPA2 {
166
252
  return {
167
253
  type: EvaluatorType.expressionbased,
168
254
  jsExpr: this.jsExpr