kipphi 2.0.0 → 2.0.1
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/bpm.ts +213 -0
- package/chart.ts +172 -80
- package/chartTypes.ts +62 -20
- package/easing.ts +89 -83
- package/env.ts +173 -0
- package/evaluator.ts +35 -11
- package/event.ts +273 -225
- package/index.ts +14 -11
- package/judgeline.ts +381 -84
- package/jumparray.ts +11 -11
- package/note.ts +31 -54
- package/operation.ts +1378 -0
- package/package.json +1 -1
- package/rpeChartCompiler.ts +133 -98
- package/time.ts +35 -223
- package/tsconfig.json +1 -2
- package/util.ts +21 -1
- package/version.ts +1 -1
package/chart.ts
CHANGED
|
@@ -2,13 +2,12 @@
|
|
|
2
2
|
import { VERSION } from "./version";
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
|
-
TimeCalculator
|
|
6
|
-
BPMSequence
|
|
7
|
-
} from "./time";
|
|
5
|
+
TimeCalculator} from "./bpm";
|
|
8
6
|
|
|
9
7
|
import {
|
|
10
8
|
BezierEasing,
|
|
11
9
|
Easing,
|
|
10
|
+
NormalEasing,
|
|
12
11
|
rpeEasingArray,
|
|
13
12
|
SegmentedEasing,
|
|
14
13
|
TemplateEasingLib,
|
|
@@ -16,13 +15,10 @@ import {
|
|
|
16
15
|
|
|
17
16
|
import {
|
|
18
17
|
EventNodeSequence,
|
|
19
|
-
type AnyEN,
|
|
20
|
-
type ENOrHead,
|
|
21
|
-
type ENOrTail,
|
|
22
|
-
EventNodeLike,
|
|
23
18
|
EventStartNode,
|
|
24
19
|
EventEndNode,
|
|
25
20
|
EventNode,
|
|
21
|
+
SpeedENS,
|
|
26
22
|
} from "./event";
|
|
27
23
|
|
|
28
24
|
import {
|
|
@@ -34,19 +30,13 @@ import {
|
|
|
34
30
|
} from "./judgeline";
|
|
35
31
|
|
|
36
32
|
import {
|
|
37
|
-
Note,
|
|
38
|
-
NNList,
|
|
39
33
|
NNNList,
|
|
40
|
-
type NNNOrHead,
|
|
41
34
|
type NNNOrTail,
|
|
42
35
|
NNNode
|
|
43
36
|
} from "./note";
|
|
44
37
|
|
|
45
38
|
import {
|
|
46
|
-
type RGB,
|
|
47
39
|
type TimeT,
|
|
48
|
-
type EventType,
|
|
49
|
-
type EventNodeSequenceDataKPA,
|
|
50
40
|
type ValueTypeOfEventType,
|
|
51
41
|
type BPMSegmentData,
|
|
52
42
|
type ChartDataRPE,
|
|
@@ -57,6 +47,7 @@ import {
|
|
|
57
47
|
type EvaluatorDataKPA2,
|
|
58
48
|
EvaluatorType,
|
|
59
49
|
type EasedEvaluatorDataOfType,
|
|
50
|
+
EventType,
|
|
60
51
|
EventValueType,
|
|
61
52
|
type EventValueTypeOfType,
|
|
62
53
|
type EventValueESType,
|
|
@@ -64,11 +55,11 @@ import {
|
|
|
64
55
|
type TextEasedEvaluatorKPA2,
|
|
65
56
|
type EventNodeSequenceDataKPA2,
|
|
66
57
|
type ChartDataKPA2,
|
|
67
|
-
type EventDataKPA2
|
|
58
|
+
type EventDataKPA2,
|
|
59
|
+
InterpreteAs
|
|
68
60
|
} from "./chartTypes";
|
|
69
|
-
import { ProgramUpdateLevel } from "typescript";
|
|
70
61
|
import { ColorEasedEvaluator, Evaluator, ExpressionEvaluator, NumericEasedEvaluator, TextEasedEvaluator, type EasedEvaluatorOfType } from "./evaluator";
|
|
71
|
-
|
|
62
|
+
import { err, ERROR_IDS, KPAError } from "./env";
|
|
72
63
|
|
|
73
64
|
/// #declaration:global
|
|
74
65
|
|
|
@@ -76,33 +67,13 @@ import { ColorEasedEvaluator, Evaluator, ExpressionEvaluator, NumericEasedEvalua
|
|
|
76
67
|
export type BasicEventName = "moveX" | "moveY" | "rotate" | "alpha" | "speed";
|
|
77
68
|
|
|
78
69
|
|
|
79
|
-
type Plain<T> = Record<string, T>;
|
|
80
|
-
|
|
81
70
|
|
|
82
|
-
/**
|
|
83
|
-
* 相当于 Python 推导式
|
|
84
|
-
* @param obj
|
|
85
|
-
* @param expr
|
|
86
|
-
* @param guard
|
|
87
|
-
* @returns
|
|
88
|
-
*/
|
|
89
|
-
function dictForIn<T, RT>(obj: Plain<T>, expr: (v: T) => RT, guard?: (v: T) => boolean): Plain<RT> {
|
|
90
|
-
let ret: Plain<RT> = {}
|
|
91
|
-
for (let key in obj) {
|
|
92
|
-
const each = obj[key]
|
|
93
|
-
if (!guard || guard && guard(each)) {
|
|
94
|
-
ret[key] = expr(each)
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return ret;
|
|
98
|
-
}
|
|
99
71
|
|
|
100
72
|
|
|
101
73
|
export type UIName = "combo" | "combonumber" | "score" | "pause" | "bar" | "name" | "level"
|
|
102
74
|
|
|
103
75
|
export class Chart {
|
|
104
76
|
judgeLines: JudgeLine[] = [];
|
|
105
|
-
bpmList: BPMSegmentData[] = [];
|
|
106
77
|
timeCalculator = new TimeCalculator();
|
|
107
78
|
orphanLines: JudgeLine[] = [];
|
|
108
79
|
// comboMapping: ComboMapping;
|
|
@@ -113,8 +84,8 @@ export class Chart {
|
|
|
113
84
|
illustrator: string = "unknown";
|
|
114
85
|
offset: number = 0;
|
|
115
86
|
|
|
116
|
-
templateEasingLib = new TemplateEasingLib;
|
|
117
|
-
sequenceMap = new Map<string, EventNodeSequence<
|
|
87
|
+
templateEasingLib = new TemplateEasingLib(EventNodeSequence.newSeq<EventType.easing>, ExpressionEvaluator);
|
|
88
|
+
sequenceMap = new Map<string, EventNodeSequence<EventValueESType>>();
|
|
118
89
|
|
|
119
90
|
effectiveBeats: number;
|
|
120
91
|
nnnList: NNNList;
|
|
@@ -149,7 +120,6 @@ export class Chart {
|
|
|
149
120
|
static fromRPEJSON(data: ChartDataRPE, duration: number) {
|
|
150
121
|
const chart = new Chart();
|
|
151
122
|
chart.judgeLineGroups = data.judgeLineGroup.map(group => new JudgeLineGroup(group));
|
|
152
|
-
chart.bpmList = data.BPMList;
|
|
153
123
|
chart.name = data.META.name;
|
|
154
124
|
chart.level = data.META.level;
|
|
155
125
|
chart.offset = data.META.offset;
|
|
@@ -160,18 +130,12 @@ export class Chart {
|
|
|
160
130
|
chart.chartingTime = data.kpaChartTime
|
|
161
131
|
chart.rpeChartingTime = data.chartTime ? Math.round(data.chartTime / 60) : 0;
|
|
162
132
|
chart.chartingTime = 0;
|
|
163
|
-
chart.
|
|
133
|
+
chart.initCalculator(data.BPMList)
|
|
164
134
|
console.log(chart, chart.getEffectiveBeats())
|
|
165
135
|
chart.nnnList = new NNNList(chart.getEffectiveBeats())
|
|
166
136
|
|
|
167
|
-
/*
|
|
168
|
-
if (data.envEasings) {
|
|
169
|
-
chart.templateEasingLib.add(...data.envEasings)
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
*/
|
|
173
137
|
|
|
174
|
-
|
|
138
|
+
|
|
175
139
|
const judgeLineDataList: JudgeLineDataRPE[] = <JudgeLineDataRPE[]>data.judgeLineList;
|
|
176
140
|
const judgeLineList: JudgeLine[] = judgeLineDataList.map(
|
|
177
141
|
(lineData, id) =>
|
|
@@ -196,7 +160,6 @@ export class Chart {
|
|
|
196
160
|
static fromKPAJSON(data: ChartDataKPA | ChartDataKPA2) {
|
|
197
161
|
const chart = new Chart();
|
|
198
162
|
|
|
199
|
-
chart.bpmList = data.bpmList;
|
|
200
163
|
chart.duration = data.duration;
|
|
201
164
|
chart.name = data.info.name;
|
|
202
165
|
chart.level = data.info.level;
|
|
@@ -207,21 +170,35 @@ export class Chart {
|
|
|
207
170
|
chart.judgeLineGroups = data.judgeLineGroups.map(group => new JudgeLineGroup(group));
|
|
208
171
|
chart.chartingTime = data.chartTime ?? 0;
|
|
209
172
|
chart.rpeChartingTime = data.rpeChartTime ?? 0;
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
chart.initCalculator(data.bpmList);
|
|
176
|
+
chart.nnnList = new NNNList(chart.getEffectiveBeats());
|
|
177
|
+
/**
|
|
178
|
+
* 影响事件的格式、是否存在“求值器”这一中间层以及判定线的属性名
|
|
179
|
+
*/
|
|
180
|
+
const isKPA2 = data.version >= 200;
|
|
181
|
+
const templateEasings = isKPA2 ? (data as ChartDataKPA2).templateEasings : (data as ChartDataKPA).envEasings;
|
|
182
|
+
const len = templateEasings.length
|
|
214
183
|
for (let i = 0; i < len; i++) {
|
|
215
|
-
const easingData =
|
|
184
|
+
const easingData = templateEasings[i];
|
|
216
185
|
chart.templateEasingLib.require(easingData.name);
|
|
217
186
|
}
|
|
218
187
|
|
|
219
|
-
if (
|
|
188
|
+
if (isKPA2) {
|
|
189
|
+
chart.templateEasingLib.readWrapperEasings((data as ChartDataKPA2).wrapperEasings);
|
|
220
190
|
const sequences = (data as ChartDataKPA2).eventNodeSequences;
|
|
221
191
|
const length = sequences.length;
|
|
222
192
|
for (let i = 0; i < length; i++) {
|
|
223
193
|
const seqData = sequences[i];
|
|
224
|
-
|
|
194
|
+
type VT = ValueTypeOfEventType<typeof seqData.type>
|
|
195
|
+
const sequence = EventNodeSequence.fromKPA2JSON<typeof seqData.type, VT>(
|
|
196
|
+
seqData.type,
|
|
197
|
+
seqData.events as EventDataKPA2<VT>[],
|
|
198
|
+
chart,
|
|
199
|
+
seqData.id,
|
|
200
|
+
seqData.endValue as VT
|
|
201
|
+
);
|
|
225
202
|
sequence.id = seqData.id;
|
|
226
203
|
chart.sequenceMap.set(sequence.id, sequence);
|
|
227
204
|
}
|
|
@@ -231,20 +208,31 @@ export class Chart {
|
|
|
231
208
|
const length = sequences.length
|
|
232
209
|
for (let i = 0; i < length; i++) {
|
|
233
210
|
const seqData = sequences[i];
|
|
234
|
-
const sequence = EventNodeSequence.fromRPEJSON<typeof seqData.type, ValueTypeOfEventType<typeof seqData.type>>(
|
|
211
|
+
const sequence = EventNodeSequence.fromRPEJSON<typeof seqData.type, ValueTypeOfEventType<typeof seqData.type>>(
|
|
212
|
+
seqData.type,
|
|
213
|
+
seqData.events,
|
|
214
|
+
chart,
|
|
215
|
+
seqData.id,
|
|
216
|
+
seqData.endValue);
|
|
235
217
|
sequence.id = seqData.id;
|
|
236
218
|
chart.sequenceMap.set(sequence.id, sequence);
|
|
237
219
|
}
|
|
238
220
|
}
|
|
239
221
|
|
|
240
222
|
for (let i = 0; i < len; i++) {
|
|
241
|
-
const easingData =
|
|
242
|
-
|
|
223
|
+
const easingData = templateEasings[i];
|
|
224
|
+
const sequence = chart.sequenceMap.get(easingData.content);
|
|
225
|
+
if (sequence.type !== EventType.easing) {
|
|
226
|
+
throw err.CANNOT_IMPLEMENT_TEMEAS_WITH_NON_EASING_ENS(easingData.name);
|
|
227
|
+
}
|
|
228
|
+
if (typeof sequence.head.next.value !== "number") {
|
|
229
|
+
throw err.CANNOT_IMPLEMENT_TEMEAS_WITH_NON_NUMERIC_ENS(easingData.name);
|
|
230
|
+
}
|
|
231
|
+
chart.templateEasingLib.implement(easingData.name, sequence as EventNodeSequence<number>);
|
|
243
232
|
}
|
|
244
233
|
chart.templateEasingLib.check()
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
const line: JudgeLine = JudgeLine.fromKPAJSON(isOld, chart, lineData.id, lineData, chart.templateEasingLib, chart.timeCalculator)
|
|
234
|
+
for (const lineData of data.orphanLines) {
|
|
235
|
+
const line: JudgeLine = JudgeLine.fromKPAJSON(data.version, chart, lineData.id, lineData, chart.templateEasingLib, chart.timeCalculator)
|
|
248
236
|
chart.orphanLines.push(line)
|
|
249
237
|
}
|
|
250
238
|
chart.judgeLines.sort((a, b) => a.id - b.id);
|
|
@@ -262,10 +250,10 @@ export class Chart {
|
|
|
262
250
|
}
|
|
263
251
|
return chart;
|
|
264
252
|
}
|
|
265
|
-
|
|
266
|
-
this.timeCalculator.bpmList =
|
|
253
|
+
initCalculator(bpmList: BPMSegmentData[]) {
|
|
254
|
+
this.timeCalculator.bpmList = bpmList;
|
|
267
255
|
this.timeCalculator.duration = this.duration;
|
|
268
|
-
this.timeCalculator.
|
|
256
|
+
this.timeCalculator.initSequence()
|
|
269
257
|
}
|
|
270
258
|
updateEffectiveBeats(duration: number) {
|
|
271
259
|
const EB = this.timeCalculator.secondsToBeats(duration);
|
|
@@ -277,19 +265,20 @@ export class Chart {
|
|
|
277
265
|
dumpKPA(): Required<ChartDataKPA2> {
|
|
278
266
|
const eventNodeSequenceCollector = new Set<EventNodeSequence>();
|
|
279
267
|
const orphanLines = [];
|
|
280
|
-
for (
|
|
268
|
+
for (const line of this.orphanLines) {
|
|
281
269
|
orphanLines.push(line.dumpKPA(eventNodeSequenceCollector, this.judgeLineGroups));
|
|
282
270
|
}
|
|
283
271
|
const envEasings = this.templateEasingLib.dump(eventNodeSequenceCollector);
|
|
284
|
-
const eventNodeSequenceData: EventNodeSequenceDataKPA2<
|
|
285
|
-
for (
|
|
272
|
+
const eventNodeSequenceData: EventNodeSequenceDataKPA2<EventValueESType>[] = [];
|
|
273
|
+
for (const sequence of eventNodeSequenceCollector) {
|
|
286
274
|
eventNodeSequenceData.push(sequence.dump());
|
|
287
275
|
}
|
|
288
276
|
return {
|
|
289
277
|
version: VERSION,
|
|
290
278
|
duration: this.duration,
|
|
291
279
|
bpmList: this.timeCalculator.dump(),
|
|
292
|
-
|
|
280
|
+
templateEasings: envEasings,
|
|
281
|
+
wrapperEasings: this.templateEasingLib.dumpWrapperEasings(),
|
|
293
282
|
eventNodeSequences: eventNodeSequenceData,
|
|
294
283
|
info: {
|
|
295
284
|
level: this.level,
|
|
@@ -315,18 +304,30 @@ export class Chart {
|
|
|
315
304
|
};
|
|
316
305
|
}
|
|
317
306
|
createNNNode(time: TimeT) {
|
|
318
|
-
|
|
307
|
+
return new NNNode(time)
|
|
319
308
|
}
|
|
309
|
+
/**
|
|
310
|
+
*
|
|
311
|
+
* @param type
|
|
312
|
+
* @param name
|
|
313
|
+
* @returns
|
|
314
|
+
* @throws {KPAError<ERROR_IDS.SEQUENCE_NAME_OCCUPIED>}
|
|
315
|
+
*/
|
|
320
316
|
createEventNodeSequence<T extends EventType>(type: T, name: string) {
|
|
321
317
|
if (this.sequenceMap.has(name)) {
|
|
322
|
-
throw
|
|
318
|
+
throw err.SEQUENCE_NAME_OCCUPIED(name);
|
|
323
319
|
}
|
|
324
320
|
const seq = EventNodeSequence.newSeq(type, this.getEffectiveBeats());
|
|
325
321
|
seq.id = name;
|
|
326
322
|
this.sequenceMap.set(name, seq);
|
|
327
323
|
return seq;
|
|
328
324
|
}
|
|
329
|
-
|
|
325
|
+
/**
|
|
326
|
+
* 对谱面物量进行重新计数。
|
|
327
|
+
*
|
|
328
|
+
* 不会返回值,谱面物量存储在 `this.maxCombo` 中。
|
|
329
|
+
*/
|
|
330
|
+
countMaxCombo(): void {
|
|
330
331
|
let combo = 0;
|
|
331
332
|
const nnnlist = this.nnnList;
|
|
332
333
|
for (let node: NNNOrTail = nnnlist.head.next; node.type !== NodeType.TAIL; node = node.next) {
|
|
@@ -345,14 +346,25 @@ export class Chart {
|
|
|
345
346
|
}
|
|
346
347
|
this.maxCombo = combo;
|
|
347
348
|
}
|
|
349
|
+
/**
|
|
350
|
+
* 将UI绑定到某判定线
|
|
351
|
+
* @param ui UI名称,与RPEJSON中的代号相同
|
|
352
|
+
* @param judgeLine 所要绑定的目标判定线
|
|
353
|
+
* @throws {KPAError<ERROR_IDS.UI_OCCUPIED>}
|
|
354
|
+
*/
|
|
348
355
|
attachUIToLine(ui: UIName, judgeLine: JudgeLine) {
|
|
349
356
|
const key = `${ui}Attach` satisfies keyof Chart;
|
|
350
357
|
if (this[key]) {
|
|
351
|
-
throw
|
|
358
|
+
throw err.UI_OCCUPIED(ui);
|
|
352
359
|
}
|
|
353
360
|
this[key] = judgeLine;
|
|
354
361
|
judgeLine.hasAttachUI = true;
|
|
355
362
|
}
|
|
363
|
+
/**
|
|
364
|
+
* 移除谱面中某个UI的绑定,使UI进入未绑定状态
|
|
365
|
+
* @param ui UI名称,与RPEJSON中的相同
|
|
366
|
+
* @returns
|
|
367
|
+
*/
|
|
356
368
|
detachUI(ui: UIName) {
|
|
357
369
|
const key = `${ui}Attach` satisfies keyof Chart;
|
|
358
370
|
const judgeLine = this[key];
|
|
@@ -381,6 +393,12 @@ export class Chart {
|
|
|
381
393
|
}
|
|
382
394
|
return arr;
|
|
383
395
|
}
|
|
396
|
+
/**
|
|
397
|
+
* 扫描所有用到的判定线贴图(纹理)并返回
|
|
398
|
+
*
|
|
399
|
+
* 给谱面播放器的接口,谱面播放器需要在初加载时提供贴图
|
|
400
|
+
* @returns
|
|
401
|
+
*/
|
|
384
402
|
scanAllTextures() {
|
|
385
403
|
const textures: Set<string> = new Set;
|
|
386
404
|
for (const line of this.judgeLines) {
|
|
@@ -388,6 +406,13 @@ export class Chart {
|
|
|
388
406
|
}
|
|
389
407
|
return textures
|
|
390
408
|
}
|
|
409
|
+
/**
|
|
410
|
+
* 使用KPA2数据创建一个缓动对象。
|
|
411
|
+
*
|
|
412
|
+
* 只有对贝塞尔缓动和截段缓动才会创建新对象,其他几种缓动从缓动库等中的对象池获取
|
|
413
|
+
* @param data
|
|
414
|
+
* @returns
|
|
415
|
+
*/
|
|
391
416
|
createEasingFromData(data: EasingDataKPA2) {
|
|
392
417
|
switch (data.type) {
|
|
393
418
|
case EasingType.bezier:
|
|
@@ -398,16 +423,35 @@ export class Chart {
|
|
|
398
423
|
return new SegmentedEasing(this.createEasingFromData(data), data.left, data.right);
|
|
399
424
|
case EasingType.template:
|
|
400
425
|
return this.templateEasingLib.get(data.identifier);
|
|
426
|
+
case EasingType.wrapper:
|
|
427
|
+
return this.templateEasingLib.getWrapper(data.identifier);
|
|
401
428
|
}
|
|
402
429
|
}
|
|
430
|
+
/**
|
|
431
|
+
* 使用KPA2数据创建一个求值器对象。
|
|
432
|
+
*
|
|
433
|
+
* 求值器只有缓动型和表达式型两类。
|
|
434
|
+
* @param data
|
|
435
|
+
* @param type
|
|
436
|
+
* @returns
|
|
437
|
+
*/
|
|
403
438
|
createEvaluator<T extends EventValueESType>(data: EvaluatorDataKPA2<T>, type: EventValueTypeOfType<T>): Evaluator<T> {
|
|
404
439
|
switch (data.type) {
|
|
405
440
|
case EvaluatorType.eased:
|
|
406
|
-
|
|
441
|
+
// 我管你这的那的 —— 小奶椰
|
|
442
|
+
return this.createEasedEvaluator(data, type) as unknown as Evaluator<T>;
|
|
407
443
|
case EvaluatorType.expressionbased:
|
|
408
444
|
return this.createExpressionEvaluator(data) as ExpressionEvaluator<T>;
|
|
409
445
|
}
|
|
410
446
|
}
|
|
447
|
+
/**
|
|
448
|
+
* 使用KPA2数据创建一个缓动求值器。
|
|
449
|
+
*
|
|
450
|
+
* 对于普通缓动,这些求值器是从对应类构造器的静态对象池属性中获取的。
|
|
451
|
+
* @param data
|
|
452
|
+
* @param type
|
|
453
|
+
* @returns
|
|
454
|
+
*/
|
|
411
455
|
createEasedEvaluator<T extends EventValueESType>(data: EasedEvaluatorDataOfType<T>, type: EventValueTypeOfType<T>): EasedEvaluatorOfType<T> {
|
|
412
456
|
switch (type) {
|
|
413
457
|
case EventValueType.numeric:
|
|
@@ -424,6 +468,30 @@ export class Chart {
|
|
|
424
468
|
: new TextEasedEvaluator(this.createEasingFromData(data.easing), (data as TextEasedEvaluatorKPA2).interpretedAs) as EasedEvaluatorOfType<T>
|
|
425
469
|
}
|
|
426
470
|
}
|
|
471
|
+
/**
|
|
472
|
+
* 用一个缓动和事件类型获取一个缓动求值器
|
|
473
|
+
* @param easing
|
|
474
|
+
* @param type
|
|
475
|
+
* @param interpreteAs
|
|
476
|
+
*/
|
|
477
|
+
getEasedEvaluator<T extends string>(easing: Easing, type: EventValueType.text, interpreteAs: InterpreteAs): TextEasedEvaluator;
|
|
478
|
+
getEasedEvaluator<T extends EventValueESType>(easing: Easing, type: EventValueTypeOfType<T>, interpreteAs?: InterpreteAs): EasedEvaluatorOfType<T> {
|
|
479
|
+
const easingIsNormal = easing instanceof NormalEasing;
|
|
480
|
+
switch (type) {
|
|
481
|
+
case EventValueType.numeric:
|
|
482
|
+
return easingIsNormal
|
|
483
|
+
? NumericEasedEvaluator.evaluatorsOfNormalEasing[easing.rpeId] as EasedEvaluatorOfType<T>
|
|
484
|
+
: new NumericEasedEvaluator(easing) as EasedEvaluatorOfType<T>;
|
|
485
|
+
case EventValueType.color:
|
|
486
|
+
return easingIsNormal
|
|
487
|
+
? ColorEasedEvaluator.evaluatorsOfNormalEasing[easing.rpeId] as EasedEvaluatorOfType<T>
|
|
488
|
+
: new ColorEasedEvaluator(easing) as EasedEvaluatorOfType<T>;
|
|
489
|
+
case EventValueType.text:
|
|
490
|
+
return easingIsNormal
|
|
491
|
+
? TextEasedEvaluator.evaluatorsOfNoEzAndItpAs[easing.rpeId][interpreteAs] as EasedEvaluatorOfType<T>
|
|
492
|
+
: new TextEasedEvaluator(easing, interpreteAs) as EasedEvaluatorOfType<T>
|
|
493
|
+
}
|
|
494
|
+
}
|
|
427
495
|
createExpressionEvaluator<T extends EventValueESType>(data: ExpressionEvaluatorDataKPA2) {
|
|
428
496
|
return new ExpressionEvaluator<T>(data.jsExpr);
|
|
429
497
|
}
|
|
@@ -440,38 +508,62 @@ export class Chart {
|
|
|
440
508
|
EventNode.connect(start, end);
|
|
441
509
|
return [start, end];
|
|
442
510
|
}
|
|
511
|
+
/* 暂时不用此方法,因为谱面播放器里面还是用反解法弄的
|
|
512
|
+
updateNNListsFromENS(speedENS: SpeedENS) {
|
|
513
|
+
|
|
514
|
+
}
|
|
515
|
+
*/
|
|
443
516
|
}
|
|
444
517
|
|
|
445
518
|
export class JudgeLineGroup {
|
|
446
|
-
|
|
519
|
+
/**
|
|
520
|
+
* 该只读标记只是为了防止外部修改,内部可以修改
|
|
521
|
+
*/
|
|
522
|
+
judgeLines: readonly JudgeLine[];
|
|
447
523
|
constructor(public name: string) {
|
|
448
524
|
this.judgeLines = []
|
|
449
525
|
}
|
|
526
|
+
/**
|
|
527
|
+
* 向判定线组添加一条判定线,并且保证其内部的判定线ID是升序排列的。
|
|
528
|
+
* @param judgeLine 要添加的判定线
|
|
529
|
+
* @returns
|
|
530
|
+
*/
|
|
450
531
|
add(judgeLine: JudgeLine) {
|
|
451
532
|
// 加入之前已经按照ID升序排列
|
|
452
533
|
// 加入时将新判定线插入到正确位置
|
|
534
|
+
const judgeLines = this.judgeLines as JudgeLine[];
|
|
453
535
|
if (judgeLine.group) {
|
|
454
536
|
judgeLine.group.remove(judgeLine);
|
|
455
537
|
}
|
|
456
538
|
judgeLine.group = this;
|
|
457
539
|
|
|
458
540
|
// 找到正确的位置插入,保持按ID升序排列
|
|
459
|
-
for (let i = 0; i <
|
|
460
|
-
if (
|
|
461
|
-
|
|
541
|
+
for (let i = 0; i < judgeLines.length; i++) {
|
|
542
|
+
if (judgeLines[i].id > judgeLine.id) {
|
|
543
|
+
judgeLines.splice(i, 0, judgeLine);
|
|
462
544
|
return;
|
|
463
545
|
}
|
|
464
546
|
}
|
|
465
547
|
// 如果没有找到比它大的ID,则插入到末尾
|
|
466
|
-
|
|
548
|
+
judgeLines.push(judgeLine);
|
|
467
549
|
|
|
468
550
|
}
|
|
551
|
+
/**
|
|
552
|
+
* 从判定线组移除一条判定线
|
|
553
|
+
* @param judgeLine
|
|
554
|
+
*/
|
|
469
555
|
remove(judgeLine: JudgeLine) {
|
|
470
|
-
|
|
556
|
+
// 只读仅对外部作限制
|
|
557
|
+
const judgeLines = this.judgeLines as JudgeLine[];
|
|
558
|
+
const index = judgeLines.indexOf(judgeLine);
|
|
471
559
|
if (index !== -1) {
|
|
472
|
-
|
|
560
|
+
judgeLines.splice(index, 1);
|
|
473
561
|
}
|
|
474
562
|
}
|
|
563
|
+
/**
|
|
564
|
+
*
|
|
565
|
+
* @returns 该判定线组是否为默认判定线组,默认的判断标准是:名称为 "Default"(大小写不敏感)
|
|
566
|
+
*/
|
|
475
567
|
isDefault() {
|
|
476
568
|
return this.name.toLowerCase() === "default";
|
|
477
569
|
}
|
package/chartTypes.ts
CHANGED
|
@@ -177,7 +177,8 @@ export enum EasingType {
|
|
|
177
177
|
normal,
|
|
178
178
|
template,
|
|
179
179
|
bezier,
|
|
180
|
-
segmented
|
|
180
|
+
segmented,
|
|
181
|
+
wrapper
|
|
181
182
|
}
|
|
182
183
|
|
|
183
184
|
export interface NormalEasingData {
|
|
@@ -190,6 +191,11 @@ export interface TemplateEasingData {
|
|
|
190
191
|
type: EasingType.template;
|
|
191
192
|
}
|
|
192
193
|
|
|
194
|
+
export interface WrapperEasingData {
|
|
195
|
+
type: EasingType.wrapper;
|
|
196
|
+
identifier: string;
|
|
197
|
+
}
|
|
198
|
+
|
|
193
199
|
export interface BezierEasingData {
|
|
194
200
|
type: EasingType.bezier;
|
|
195
201
|
bezier: [number, number, number, number];
|
|
@@ -202,7 +208,7 @@ export interface SegmentedEasingData {
|
|
|
202
208
|
inner: EasingDataKPA2;
|
|
203
209
|
}
|
|
204
210
|
|
|
205
|
-
export type EasingDataKPA2 = NormalEasingData | TemplateEasingData | BezierEasingData | SegmentedEasingData;
|
|
211
|
+
export type EasingDataKPA2 = NormalEasingData | TemplateEasingData | BezierEasingData | SegmentedEasingData | WrapperEasingData;
|
|
206
212
|
|
|
207
213
|
export enum EvaluatorType {
|
|
208
214
|
eased,
|
|
@@ -219,7 +225,6 @@ interface EasedEvaluatorDataKPA2<T> {
|
|
|
219
225
|
export type NumericEasedEvaluatorKPA2 = EasedEvaluatorDataKPA2<number>;
|
|
220
226
|
export type ColorEasedEvaluatorKPA2 = EasedEvaluatorDataKPA2<RGB>;
|
|
221
227
|
export interface TextEasedEvaluatorKPA2 extends EasedEvaluatorDataKPA2<string> {
|
|
222
|
-
font: string;
|
|
223
228
|
interpretedAs: InterpreteAs;
|
|
224
229
|
}
|
|
225
230
|
|
|
@@ -309,12 +314,12 @@ export interface JudgeLineDataRPE {
|
|
|
309
314
|
eventLayers: (EventLayerDataRPE | null)[];
|
|
310
315
|
/** 扩展事件 */
|
|
311
316
|
extended?: {
|
|
312
|
-
colorEvents
|
|
313
|
-
inclineEvents
|
|
314
|
-
scaleXEvents
|
|
315
|
-
scaleYEvents
|
|
316
|
-
textEvents
|
|
317
|
-
gifEvents
|
|
317
|
+
colorEvents?: EventDataRPELike<RGB>[];
|
|
318
|
+
inclineEvents?: EventDataRPELike[];
|
|
319
|
+
scaleXEvents?: EventDataRPELike[];
|
|
320
|
+
scaleYEvents?: EventDataRPELike[];
|
|
321
|
+
textEvents?: EventDataRPELike<string>[];
|
|
322
|
+
gifEvents?: EventDataRPELike<number>[];
|
|
318
323
|
};
|
|
319
324
|
/** 父线线号,没有父线则为-1 */
|
|
320
325
|
father: number;
|
|
@@ -355,19 +360,17 @@ export interface JudgeLineDataRPE {
|
|
|
355
360
|
zIndex?: number;
|
|
356
361
|
}
|
|
357
362
|
|
|
358
|
-
export interface JudgeLineDataRPEExtended extends JudgeLineDataRPE {
|
|
359
|
-
_id?: number;
|
|
360
|
-
children: number[]
|
|
361
|
-
}
|
|
362
363
|
|
|
363
|
-
|
|
364
|
+
|
|
365
|
+
export interface TemplateEasingBodyData {
|
|
364
366
|
content: string;
|
|
365
367
|
name: string;
|
|
366
|
-
usedBy: string[];
|
|
367
|
-
dependencies: string[];
|
|
368
|
+
// usedBy: string[];
|
|
369
|
+
// dependencies: string[];
|
|
368
370
|
}
|
|
369
371
|
|
|
370
372
|
|
|
373
|
+
|
|
371
374
|
// 使用对应标识符来标记事件节点序列
|
|
372
375
|
|
|
373
376
|
export interface EventLayerDataKPA {
|
|
@@ -378,6 +381,14 @@ export interface EventLayerDataKPA {
|
|
|
378
381
|
speed: string;
|
|
379
382
|
}
|
|
380
383
|
|
|
384
|
+
export interface EventLayerDataKPA2 {
|
|
385
|
+
moveX: string;
|
|
386
|
+
moveY: string;
|
|
387
|
+
rotate: string;
|
|
388
|
+
alpha: string;
|
|
389
|
+
// 移除了速度事件可以有多层的性质
|
|
390
|
+
}
|
|
391
|
+
|
|
381
392
|
|
|
382
393
|
export interface NoteNodeDataKPA {
|
|
383
394
|
notes: NoteDataKPA[];
|
|
@@ -412,6 +423,28 @@ export interface JudgeLineDataKPA {
|
|
|
412
423
|
zOrder: number;
|
|
413
424
|
}
|
|
414
425
|
|
|
426
|
+
export interface JudgeLineDataKPA2 {
|
|
427
|
+
cover: boolean;
|
|
428
|
+
id: number;
|
|
429
|
+
group: number;
|
|
430
|
+
nnLists: {[k: string]: NNListDataKPA};
|
|
431
|
+
hnLists: {[k: string]: NNListDataKPA};
|
|
432
|
+
name: string;
|
|
433
|
+
texture: string;
|
|
434
|
+
eventLayers: EventLayerDataKPA2[];
|
|
435
|
+
speedEventNodeSeq: string;
|
|
436
|
+
children: JudgeLineDataKPA2[];
|
|
437
|
+
rotatesWithFather: boolean;
|
|
438
|
+
|
|
439
|
+
anchor: [number, number];
|
|
440
|
+
extended?: {
|
|
441
|
+
scaleXEvents: string;
|
|
442
|
+
scaleYEvents: string;
|
|
443
|
+
textEvents?: string;
|
|
444
|
+
colorEvents?: string;
|
|
445
|
+
}
|
|
446
|
+
zOrder: number;
|
|
447
|
+
}
|
|
415
448
|
|
|
416
449
|
|
|
417
450
|
export interface EventNodeSequenceDataKPA<VT> {
|
|
@@ -428,6 +461,13 @@ export interface EventNodeSequenceDataKPA2<VT> {
|
|
|
428
461
|
endValue: VT;
|
|
429
462
|
}
|
|
430
463
|
|
|
464
|
+
export interface WrapperEasingBodyData {
|
|
465
|
+
jsExpr: string;
|
|
466
|
+
start: number;
|
|
467
|
+
end: number;
|
|
468
|
+
id: string;
|
|
469
|
+
}
|
|
470
|
+
|
|
431
471
|
export interface ChartDataKPA {
|
|
432
472
|
version: number;
|
|
433
473
|
offset: number;
|
|
@@ -448,7 +488,7 @@ export interface ChartDataKPA {
|
|
|
448
488
|
name: number;
|
|
449
489
|
level: number;
|
|
450
490
|
}
|
|
451
|
-
envEasings:
|
|
491
|
+
envEasings: TemplateEasingBodyData[]; // New!
|
|
452
492
|
eventNodeSequences: EventNodeSequenceDataKPA<any>[];
|
|
453
493
|
orphanLines: JudgeLineDataKPA[];
|
|
454
494
|
bpmList: BPMSegmentData[];
|
|
@@ -477,9 +517,10 @@ export interface ChartDataKPA2 {
|
|
|
477
517
|
name: number;
|
|
478
518
|
level: number;
|
|
479
519
|
}
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
520
|
+
templateEasings: TemplateEasingBodyData[];
|
|
521
|
+
wrapperEasings: WrapperEasingBodyData[]
|
|
522
|
+
eventNodeSequences: EventNodeSequenceDataKPA2<unknown>[];
|
|
523
|
+
orphanLines: JudgeLineDataKPA2[];
|
|
483
524
|
bpmList: BPMSegmentData[];
|
|
484
525
|
judgeLineGroups: string[];
|
|
485
526
|
chartTime?: number;
|
|
@@ -509,4 +550,5 @@ export enum NoteType {
|
|
|
509
550
|
|
|
510
551
|
export type ValueTypeOfEventType<T extends EventType> = [number, number, number, number, number, number, number, number, number, string, RGB][T]
|
|
511
552
|
|
|
553
|
+
export type ExtendedEventTypeName = "scaleX" | "scaleY" | "text" | "color"
|
|
512
554
|
/// #enddeclaration
|