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/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<any>>();
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.updateCalculator()
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
- // let line = data.judgeLineList[0];
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
- chart.updateCalculator()
211
- chart.nnnList = new NNNList(chart.getEffectiveBeats())
212
- const envEasings = data.envEasings;
213
- const len = envEasings.length
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 = envEasings[i];
184
+ const easingData = templateEasings[i];
216
185
  chart.templateEasingLib.require(easingData.name);
217
186
  }
218
187
 
219
- if (data.version >= 200) {
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
- const sequence = EventNodeSequence.fromRPEJSON<typeof seqData.type, ValueTypeOfEventType<typeof seqData.type>>(seqData.type, seqData.events, chart, seqData.endValue);
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>>(seqData.type, seqData.events, chart, seqData.endValue);
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 = envEasings[i];
242
- chart.templateEasingLib.implement(easingData.name, chart.sequenceMap.get(easingData.content));
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 isOld = !data.version || data.version < 150
246
- for (let lineData of data.orphanLines) {
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
- updateCalculator() {
266
- this.timeCalculator.bpmList = this.bpmList;
253
+ initCalculator(bpmList: BPMSegmentData[]) {
254
+ this.timeCalculator.bpmList = bpmList;
267
255
  this.timeCalculator.duration = this.duration;
268
- this.timeCalculator.update()
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 (let line of this.orphanLines) {
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<any>[] = [];
285
- for (let sequence of eventNodeSequenceCollector) {
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
- envEasings: envEasings,
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
- return new NNNode(time)
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 new Error(`The name ${name} is occupied.`)
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
- countMaxCombo() {
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 new Error(`UI ${ui} is occupied`);
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
- return this.createEasedEvaluator(data, type);
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
- judgeLines: JudgeLine[];
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 < this.judgeLines.length; i++) {
460
- if (this.judgeLines[i].id > judgeLine.id) {
461
- this.judgeLines.splice(i, 0, judgeLine);
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
- this.judgeLines.push(judgeLine);
548
+ judgeLines.push(judgeLine);
467
549
 
468
550
  }
551
+ /**
552
+ * 从判定线组移除一条判定线
553
+ * @param judgeLine
554
+ */
469
555
  remove(judgeLine: JudgeLine) {
470
- const index = this.judgeLines.indexOf(judgeLine);
556
+ // 只读仅对外部作限制
557
+ const judgeLines = this.judgeLines as JudgeLine[];
558
+ const index = judgeLines.indexOf(judgeLine);
471
559
  if (index !== -1) {
472
- this.judgeLines.splice(index, 1);
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: EventDataRPELike<RGB>[];
313
- inclineEvents: EventDataRPELike[];
314
- scaleXEvents: EventDataRPELike[];
315
- scaleYEvents: EventDataRPELike[];
316
- textEvents: EventDataRPELike<string>[];
317
- gifEvents: EventDataRPELike<number>[];
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
- export interface CustomEasingData {
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: CustomEasingData[]; // New!
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
- envEasings: CustomEasingData[];
481
- eventNodeSequences: EventNodeSequenceDataKPA2<any>[];
482
- orphanLines: JudgeLineDataKPA[];
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