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/README.md +1 -3
- package/basic.ts +285 -0
- package/bpm.ts +332 -0
- package/chart.ts +418 -106
- package/chartType.schema.json +584 -0
- package/chartType2.schema.json +1107 -0
- package/chartTypes.ts +131 -30
- package/easing.ts +125 -90
- package/env.ts +208 -0
- package/evaluator.ts +106 -20
- package/event.ts +357 -255
- package/index.d.ts +3055 -0
- package/index.js +5530 -0
- package/index.ts +17 -11
- package/judgeline.ts +395 -94
- package/jumparray.ts +10 -11
- package/line.ts +246 -0
- package/macro.ts +215 -0
- package/note.ts +32 -55
- package/operation/basic.ts +285 -0
- package/operation/chart.ts +21 -0
- package/operation/event.ts +511 -0
- package/operation/index.ts +6 -0
- package/operation/line.ts +304 -0
- package/operation/macro.ts +60 -0
- package/operation/note.ts +457 -0
- package/package.json +7 -1
- package/rpeChartCompiler.ts +133 -98
- package/time.ts +35 -223
- package/tsconfig.json +2 -3
- package/util.ts +21 -1
- package/version.ts +2 -1
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
|
|
9
|
+
import TC from "./time";
|
|
10
10
|
|
|
11
|
-
import type {
|
|
12
|
-
import type
|
|
13
|
-
import
|
|
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:
|
|
29
|
-
abstract
|
|
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:
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
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
|
|
251
|
+
override dumpFor(): ExpressionEvaluatorDataKPA2 {
|
|
166
252
|
return {
|
|
167
253
|
type: EvaluatorType.expressionbased,
|
|
168
254
|
jsExpr: this.jsExpr
|