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/index.d.ts ADDED
@@ -0,0 +1,3055 @@
1
+ declare module "chartTypes" {
2
+ /** 尽管JSON中有布尔值字面量,RPEJSON中没有使用它 */
3
+ export type Bool = 1 | 0;
4
+ /** 三元组,用带分数表示的时间 */
5
+ export type TimeT = [number, number, number];
6
+ export type RGB = [number, number, number];
7
+ export interface ChartDataRPE {
8
+ /** BPM列表 */
9
+ BPMList: BPMSegmentData[];
10
+ /** 元数据 */
11
+ META: MetaData;
12
+ /** 判定线组 */
13
+ judgeLineGroup: string[];
14
+ /** 判定线列表 */
15
+ judgeLineList: JudgeLineDataRPE[];
16
+ chartTime?: number;
17
+ kpaChartTime?: number;
18
+ multiLineString: string;
19
+ multiScale: number;
20
+ }
21
+ export interface BPMSegmentData {
22
+ bpm: number;
23
+ startTime: TimeT;
24
+ }
25
+ export interface MetaData {
26
+ /** RPE版本(int) */
27
+ RPEVersion: number;
28
+ /** 背景图片路径 */
29
+ background: string;
30
+ /** 画师名称 */
31
+ illustration: string;
32
+ /** 谱师名称 */
33
+ charter: string;
34
+ /** 曲师名称 */
35
+ composer: string;
36
+ /** 谱面ID,即Resources文件夹下的文件夹名称 */
37
+ id: string;
38
+ /** 谱面难度 */
39
+ level: string;
40
+ /** 谱面名称 */
41
+ name: string;
42
+ /** 谱面偏移(以毫秒计量) */
43
+ offset: number;
44
+ /** 音乐文件路径 */
45
+ song: string;
46
+ /** 音乐时长(1.6(存疑)新增) */
47
+ duration?: number;
48
+ }
49
+ export interface NoteDataRPE {
50
+ /** 音符是否在判定线上方 (2为下方) */
51
+ above: Bool | 2;
52
+ /** 音符不透明度 */
53
+ alpha: number;
54
+ /** 音符结束时间,无论是否为Hold都有该属性 */
55
+ endTime: TimeT;
56
+ /** 音符是否为假 */
57
+ isFake: Bool;
58
+ /** 音符在判定线上落点位置 */
59
+ positionX: number;
60
+ /** 音符大小(默认1.0) */
61
+ size: number;
62
+ /** 音符速度 */
63
+ speed: number;
64
+ /** 音符开始时间 */
65
+ startTime: TimeT;
66
+ /** 音符类型(1 为 Tap,2 为 Hold,3 为 Flick,4 为 Drag)*/
67
+ type: NoteType;
68
+ /** 音符可视时间(打击前多少秒开始显现,默认99999.0) */
69
+ visibleTime: number;
70
+ /** y值偏移,使音符被打击时的位置偏离判定线 */
71
+ yOffset: number;
72
+ /** Sets the Z index for the object. */
73
+ zIndex?: number;
74
+ /**
75
+ * Sets the Z index for the hit effects of the note. Defaults to 7.
76
+ */
77
+ zIndexHitEffects?: number;
78
+ /** Sets the tint for the hit effects of the note. Defaults to null. */
79
+ tint?: RGB;
80
+ tintHitEffects?: RGB;
81
+ /** Determines the width of the judgment area of the note. Defaults to size. */
82
+ judgeSize?: number;
83
+ }
84
+ export interface NoteDataKPA {
85
+ /** 音符是否在判定线上方 (2为下方) */
86
+ above: Bool | 2;
87
+ /** 音符不透明度 */
88
+ alpha: number;
89
+ /** 音符结束时间,无论是否为Hold都有该属性 */
90
+ endTime: TimeT;
91
+ /** 音符是否为假 */
92
+ isFake: Bool;
93
+ /** 音符在判定线上落点位置 */
94
+ positionX: number;
95
+ /** 音符大小(默认1.0) */
96
+ size: number;
97
+ /** 音符速度 */
98
+ speed: number;
99
+ /** 音符开始时间 */
100
+ startTime: TimeT;
101
+ /** 音符类型(1 为 Tap,2 为 Hold,3 为 Flick,4 为 Drag)*/
102
+ type: NoteType;
103
+ /** 音符可视时间(打击前多少秒开始显现,默认99999.0) */
104
+ visibleTime?: number;
105
+ /** y值偏移,使音符被打击时的位置偏离判定线 */
106
+ yOffset: number;
107
+ /** Sets the Z index for the object. */
108
+ zIndex?: number;
109
+ /**
110
+ * Sets the Z index for the hit effects of the note. Defaults to 7.
111
+ */
112
+ zIndexHitEffects?: number;
113
+ /** Sets the tint for the hit effects of the note. Defaults to null. */
114
+ tint?: RGB;
115
+ tintHitEffects?: RGB;
116
+ /** Determines the width of the judgment area of the note. Defaults to size. */
117
+ judgeSize?: number;
118
+ visibleBeats?: number;
119
+ absoluteYOffset: number;
120
+ }
121
+ /** 事件 */
122
+ export interface EventDataRPELike<T = number> {
123
+ /** 是否使用贝塞尔曲线 */
124
+ bezier: Bool;
125
+ /** 贝塞尔控制点 */
126
+ bezierPoints: [number, number, number, number];
127
+ /** 截取缓动左边界 */
128
+ easingLeft: number;
129
+ /** 截取缓动右边界 */
130
+ easingRight: number;
131
+ /** 缓动类型 */
132
+ easingType: number | string;
133
+ /** 结束值 */
134
+ end: T;
135
+ /** 结束时间 */
136
+ endTime: TimeT;
137
+ /** 链接组 */
138
+ linkgroup: number;
139
+ /** 开始值 */
140
+ start: T;
141
+ /** 开始时间 */
142
+ startTime: TimeT;
143
+ }
144
+ export enum InterpreteAs {
145
+ str = 0,
146
+ int = 1,
147
+ float = 2
148
+ }
149
+ export interface EventDataKPA<T = number> extends EventDataRPELike<T> {
150
+ /** 若设为真,则easingType当做JS表达式解读 */
151
+ isParametric?: boolean;
152
+ interpreteAs?: InterpreteAs;
153
+ }
154
+ export enum EasingType {
155
+ normal = 0,
156
+ template = 1,
157
+ bezier = 2,
158
+ segmented = 3,
159
+ wrapper = 4
160
+ }
161
+ export interface NormalEasingData {
162
+ type: EasingType.normal;
163
+ identifier: number;
164
+ }
165
+ export interface TemplateEasingData {
166
+ identifier: string;
167
+ type: EasingType.template;
168
+ }
169
+ export interface WrapperEasingData {
170
+ type: EasingType.wrapper;
171
+ identifier: string;
172
+ }
173
+ export interface BezierEasingData {
174
+ type: EasingType.bezier;
175
+ bezier: [number, number, number, number];
176
+ }
177
+ export interface SegmentedEasingData {
178
+ type: EasingType.segmented;
179
+ left: number;
180
+ right: number;
181
+ inner: EasingDataKPA2;
182
+ }
183
+ export type EasingDataKPA2 = NormalEasingData | TemplateEasingData | BezierEasingData | SegmentedEasingData | WrapperEasingData;
184
+ export enum EvaluatorType {
185
+ eased = 0,
186
+ expressionbased = 1,
187
+ macro = 2
188
+ }
189
+ interface EasedEvaluatorDataKPA2<T> {
190
+ type: EvaluatorType.eased;
191
+ easing: EasingDataKPA2;
192
+ }
193
+ export type NumericEasedEvaluatorKPA2 = EasedEvaluatorDataKPA2<number>;
194
+ export type ColorEasedEvaluatorKPA2 = EasedEvaluatorDataKPA2<RGB>;
195
+ export interface TextEasedEvaluatorKPA2 extends EasedEvaluatorDataKPA2<string> {
196
+ interpretedAs: InterpreteAs;
197
+ }
198
+ export type EasedEvaluatorDataOfType<T> = T extends number ? NumericEasedEvaluatorKPA2 : T extends RGB ? ColorEasedEvaluatorKPA2 : TextEasedEvaluatorKPA2;
199
+ export interface ExpressionEvaluatorDataKPA2 {
200
+ type: EvaluatorType.expressionbased;
201
+ jsExpr: string;
202
+ }
203
+ export interface MacroEvaluatorDataKPA2 {
204
+ type: EvaluatorType.macro;
205
+ name: string;
206
+ compiled: string;
207
+ }
208
+ export type EvaluatorDataKPA2<T> = EasedEvaluatorDataOfType<T> | ExpressionEvaluatorDataKPA2 | MacroEvaluatorDataKPA2;
209
+ export type MacroData = [id: string, proto: number] | string;
210
+ export type MacroLink = [macroTypeAndId: `${'value' | 'time'}:${string}`, nodeId: number];
211
+ export interface EventDataKPA2<T = number> {
212
+ /** 开始时间 */
213
+ startTime: TimeT;
214
+ /** 结束时间 */
215
+ endTime: TimeT;
216
+ /** 起始值 */
217
+ start: T;
218
+ /** 终值 */
219
+ end: T;
220
+ /** 求值器 */
221
+ evaluator: EvaluatorDataKPA2<T>;
222
+ /** 终值绑定的宏的ID */
223
+ macroEnd?: MacroData;
224
+ /** 起始值绑定的宏的ID */
225
+ macroStart?: MacroData;
226
+ /** 起始时间绑定的宏的ID */
227
+ macroStartTime?: MacroData;
228
+ /** 将该事件的起始节点关联到一个宏的某个参数 */
229
+ startLinkedMacro?: MacroLink[];
230
+ endLinkedMacro?: MacroLink[];
231
+ }
232
+ export interface FinalEventStartNodeDataKPA2<T = number> {
233
+ /** 开始时间 */
234
+ startTime: TimeT;
235
+ /** 起始值 */
236
+ start: T;
237
+ /** 求值器 */
238
+ evaluator: EvaluatorDataKPA2<T>;
239
+ /** 起始值绑定的宏的ID */
240
+ macro?: MacroData;
241
+ /** 起始时间绑定的宏的ID */
242
+ macroTime?: MacroData;
243
+ /** 将该事件的起始节点关联到一个宏的某个参数 */
244
+ linkedMacro?: MacroLink[];
245
+ }
246
+ export enum EventValueType {
247
+ numeric = 0,
248
+ color = 1,
249
+ text = 2
250
+ }
251
+ export type EventValueTypeOfType<T extends EventValueESType> = T extends number ? EventValueType.numeric : T extends RGB ? EventValueType.color : EventValueType.text;
252
+ export type EventValueESType = string | number | RGB;
253
+ /**
254
+ * 五个种类的事件的start/end含义:
255
+ * X/Y方向移动:像素
256
+ * 旋转:角度(以度计)
257
+ * 不透明度改变:不透明度(0-255的整数)
258
+ * 速度改变:RPE速度单位(每个单位代表每秒下降120px)
259
+ */
260
+ /** 每条判定线的前四个事件层级。第五个是特殊事件,这里没有列入 */
261
+ export interface EventLayerDataRPE {
262
+ moveXEvents?: EventDataRPELike[];
263
+ moveYEvents?: EventDataRPELike[];
264
+ rotateEvents?: EventDataRPELike[];
265
+ alphaEvents?: EventDataRPELike[];
266
+ speedEvents?: EventDataRPELike[];
267
+ }
268
+ export interface Control {
269
+ easing: number;
270
+ x: number;
271
+ }
272
+ export interface AlphaControl extends Control {
273
+ alpha: number;
274
+ }
275
+ export interface PosControl extends Control {
276
+ pos: number;
277
+ }
278
+ export interface SizeControl extends Control {
279
+ size: number;
280
+ }
281
+ export interface SkewControl extends Control {
282
+ skew: number;
283
+ }
284
+ export interface YControl extends Control {
285
+ y: number;
286
+ }
287
+ /** 判定线 */
288
+ export interface JudgeLineDataRPE {
289
+ /** 音符数据
290
+ * 对音符的顺序没有要求,但RPE生成的标准RPEJSON中应当按照时间升序排列,
291
+ * 且非Hold类型与Hold分开排列,非Hold在前
292
+ */
293
+ notes: NoteDataRPE[];
294
+ /** 所在的判定线组,对应judgeLineGroup数组中的字符串的下标 */
295
+ Group: number;
296
+ /** 线名 */
297
+ Name: string;
298
+ /** 纹理图片的路径 */
299
+ Texture: string;
300
+ /** BPM因数 */
301
+ bpmfactor: 1.0;
302
+ /** 事件层级,这里没有介绍第五个 */
303
+ eventLayers: (EventLayerDataRPE | null)[];
304
+ /** 扩展事件 */
305
+ extended?: {
306
+ colorEvents?: EventDataRPELike<RGB>[];
307
+ inclineEvents?: EventDataRPELike[];
308
+ scaleXEvents?: EventDataRPELike[];
309
+ scaleYEvents?: EventDataRPELike[];
310
+ textEvents?: EventDataRPELike<string>[];
311
+ gifEvents?: EventDataRPELike<number>[];
312
+ };
313
+ /** 父线线号,没有父线则为-1 */
314
+ father: number;
315
+ /** 有无遮罩 */
316
+ isCover: Bool;
317
+ /** 音符数量 */
318
+ numOfNotes: number;
319
+ alphaControl?: AlphaControl[];
320
+ posControl?: PosControl[];
321
+ sizeControl?: SizeControl[];
322
+ skewControl?: SkewControl[];
323
+ yControl?: YControl[];
324
+ /** z轴顺序,决定重叠的顺序 */
325
+ zOrder?: number;
326
+ anchor: [number, number];
327
+ /** 背景是否为GIF */
328
+ isGif: Bool;
329
+ rotateWithFather?: boolean;
330
+ attachUI?: "pause" | "combonumber" | "combo" | "score" | "bar" | "name" | "level";
331
+ /** Decides how scaleX events affect notes. Defaults to 0.
332
+ * 0: none; 1: scale; 2: clip
333
+ */
334
+ scaleOnNotes?: 0 | 1 | 2;
335
+ /** Decides how the line will be displayed when a UI component or any video is attached to it.
336
+ * Color events will override the color defined by these options. Defaults to 0.
337
+ * 0: hidden; 1: white colored; 2: FC/AP colored
338
+ */
339
+ appearanceOnAttach?: 0 | 1 | 2;
340
+ /** Sets the Z index for the object.
341
+ * For a judgeline, this property, if set, overrides the zOrder property,
342
+ * allowing for more control over on which layer the line should be displayed. */
343
+ zIndex?: number;
344
+ }
345
+ export interface TemplateEasingBodyData {
346
+ content: string;
347
+ name: string;
348
+ }
349
+ export interface EventLayerDataKPA {
350
+ moveX: string;
351
+ moveY: string;
352
+ rotate: string;
353
+ alpha: string;
354
+ speed: string;
355
+ }
356
+ export interface EventLayerDataKPA2 {
357
+ moveX: string;
358
+ moveY: string;
359
+ rotate: string;
360
+ alpha: string;
361
+ }
362
+ export interface NoteNodeDataKPA {
363
+ notes: NoteDataKPA[];
364
+ startTime: TimeT;
365
+ }
366
+ export interface NNListDataKPA {
367
+ speed: number;
368
+ medianYOffset: number;
369
+ noteNodes: NoteNodeDataKPA[];
370
+ }
371
+ export interface JudgeLineDataKPA {
372
+ cover: boolean;
373
+ id: number;
374
+ group: number;
375
+ nnLists: {
376
+ [k: string]: NNListDataKPA;
377
+ };
378
+ hnLists: {
379
+ [k: string]: NNListDataKPA;
380
+ };
381
+ Name: string;
382
+ Texture: string;
383
+ eventLayers: EventLayerDataKPA[];
384
+ children: JudgeLineDataKPA[];
385
+ rotatesWithFather: boolean;
386
+ anchor: [number, number];
387
+ extended?: {
388
+ scaleXEvents: string;
389
+ scaleYEvents: string;
390
+ textEvents?: string;
391
+ colorEvents?: string;
392
+ };
393
+ zOrder: number;
394
+ }
395
+ export interface JudgeLineDataKPA2 {
396
+ cover: boolean;
397
+ id: number;
398
+ group: number;
399
+ nnLists: {
400
+ [k: string]: NNListDataKPA;
401
+ };
402
+ hnLists: {
403
+ [k: string]: NNListDataKPA;
404
+ };
405
+ name: string;
406
+ texture: string;
407
+ eventLayers: EventLayerDataKPA2[];
408
+ speedEventNodeSeq: string;
409
+ children: JudgeLineDataKPA2[];
410
+ rotatesWithFather: boolean;
411
+ anchor: [number, number];
412
+ extended?: {
413
+ scaleXEvents: string;
414
+ scaleYEvents: string;
415
+ textEvents?: string;
416
+ colorEvents?: string;
417
+ };
418
+ zOrder: number;
419
+ }
420
+ export interface EventNodeSequenceDataKPA<VT> {
421
+ events: EventDataKPA<VT>[];
422
+ id: string;
423
+ type: EventType;
424
+ endValue: VT;
425
+ }
426
+ export interface EventNodeSequenceDataKPA2<VT> {
427
+ events: EventDataKPA2<VT>[];
428
+ id: string;
429
+ type: EventType;
430
+ final: FinalEventStartNodeDataKPA2<VT>;
431
+ }
432
+ export interface WrapperEasingBodyData {
433
+ jsExpr: string;
434
+ start: number;
435
+ end: number;
436
+ id: string;
437
+ }
438
+ export interface MacroEvaluatorBodyData {
439
+ macro: string;
440
+ id: string;
441
+ }
442
+ export interface MacroTimeBodyData {
443
+ id: string;
444
+ macro: string;
445
+ parametric?: boolean;
446
+ }
447
+ export interface MacroValueBodyData {
448
+ id: string;
449
+ macro: string;
450
+ parametric?: boolean;
451
+ }
452
+ export interface ChartDataKPA {
453
+ version: number;
454
+ offset: number;
455
+ duration: number;
456
+ info: {
457
+ level: string;
458
+ name: string;
459
+ charter: string;
460
+ illustrator: string;
461
+ composer: string;
462
+ };
463
+ ui: {
464
+ pause: number;
465
+ combonumber: number;
466
+ combo: number;
467
+ score: number;
468
+ bar: number;
469
+ name: number;
470
+ level: number;
471
+ };
472
+ envEasings: TemplateEasingBodyData[];
473
+ eventNodeSequences: EventNodeSequenceDataKPA<any>[];
474
+ orphanLines: JudgeLineDataKPA[];
475
+ bpmList: BPMSegmentData[];
476
+ judgeLineGroups: string[];
477
+ chartTime?: number;
478
+ rpeChartTime?: number;
479
+ }
480
+ export interface ChartDataKPA2 {
481
+ version: number;
482
+ $schema: string;
483
+ offset: number;
484
+ duration: number;
485
+ info: {
486
+ level: string;
487
+ name: string;
488
+ charter: string;
489
+ illustrator: string;
490
+ composer: string;
491
+ };
492
+ ui: {
493
+ pause?: number;
494
+ combonumber?: number;
495
+ combo?: number;
496
+ score?: number;
497
+ bar?: number;
498
+ name?: number;
499
+ level?: number;
500
+ };
501
+ templateEasings: TemplateEasingBodyData[];
502
+ wrapperEasings: WrapperEasingBodyData[];
503
+ macroEvaluators: MacroEvaluatorBodyData[];
504
+ timeMacros: MacroTimeBodyData[];
505
+ valueMacros: MacroValueBodyData[];
506
+ eventNodeSequences: EventNodeSequenceDataKPA2<unknown>[];
507
+ orphanLines: JudgeLineDataKPA2[];
508
+ bpmList: BPMSegmentData[];
509
+ judgeLineGroups: string[];
510
+ chartTime?: number;
511
+ rpeChartTime?: number;
512
+ }
513
+ export enum EventType {
514
+ moveX = 0,
515
+ moveY = 1,
516
+ rotate = 2,
517
+ alpha = 3,
518
+ speed = 4,
519
+ easing = 5,
520
+ bpm = 6,
521
+ scaleX = 7,
522
+ scaleY = 8,
523
+ text = 9,
524
+ color = 10
525
+ }
526
+ export enum NoteType {
527
+ tap = 1,
528
+ drag = 4,
529
+ flick = 3,
530
+ hold = 2
531
+ }
532
+ export type ValueTypeOfEventType<T extends EventType> = [number, number, number, number, number, number, number, number, number, string, RGB][T];
533
+ export type ExtendedEventTypeName = "scaleX" | "scaleY" | "text" | "color";
534
+ }
535
+ declare module "version" {
536
+ export const VERSION = 210;
537
+ export const SCHEMA = "https://cdn.jsdelivr.net/npm/kipphi@2.1.0/chartType2.schema.json";
538
+ }
539
+ declare module "util" {
540
+ import type { RGB, TimeT } from "chartTypes";
541
+ export enum NodeType {
542
+ HEAD = 0,
543
+ TAIL = 1,
544
+ MIDDLE = 2
545
+ }
546
+ export type TupleCoord = [x: number, y: number];
547
+ /**
548
+ * 检查值的类型
549
+ * @param value
550
+ * @param type 为字符串时,用typeof检测,为构造函数时,用instanceof检测,为数组时,识别为元组类型。
551
+ */
552
+ export const checkType: (value: unknown, type: string | (string | typeof Function)[] | typeof Function) => any;
553
+ export const rgb2hex: (rgb: RGB) => number;
554
+ export const hex2rgb: (hex: number) => RGB;
555
+ export const numberToRatio: (num: number) => [number, number];
556
+ export const toTimeString: (beaT: TimeT) => string;
557
+ }
558
+ declare module "jumparray" {
559
+ import { NodeType } from "util";
560
+ type EndNextFn<T extends TwoDirectionNodeLike> = (node: T) => [endBeats: number, next: T];
561
+ interface TwoDirectionNodeLike {
562
+ next: this | null;
563
+ previous: this | null;
564
+ type: NodeType;
565
+ }
566
+ export class JumpArray<T extends TwoDirectionNodeLike> {
567
+ endNextFn: EndNextFn<T>;
568
+ nextFn: (node: T, beats: number) => T | false;
569
+ resolveLastNode: (node: T) => T;
570
+ header: T;
571
+ tailer: T;
572
+ array: (T[] | T)[];
573
+ averageBeats: number;
574
+ effectiveBeats: number;
575
+ goPrev: (node: T) => T;
576
+ readonly MINOR_SCALE_COUNT: number;
577
+ /**
578
+ *
579
+ * @param head 链表头
580
+ * @param tail 链表尾
581
+ * @param originalListLength
582
+ * @param effectiveBeats 有效拍数(等同于音乐拍数)
583
+ * @param endNextFn 接收一个节点,返回该节点分管区段拍数,并给出下个节点。若抵达尾部,返回[null, null](停止遍历的条件是抵达尾部而不是得到null)
584
+ * @param nextFn 接收一个节点,返回下个节点。如果应当停止,返回false。
585
+ */
586
+ constructor(head: T, tail: T, originalListLength: number, effectiveBeats: number, endNextFn: EndNextFn<T>, nextFn: (node: T, beats: number) => T | false, resolveLastNode?: (node: T) => T);
587
+ updateEffectiveBeats(val: number): void;
588
+ updateAverageBeats(): void;
589
+ /**
590
+ *
591
+ * @param firstNode 不含
592
+ * @param lastNode 含
593
+ */
594
+ updateRange(firstNode: T, lastNode: T): void;
595
+ getPreviousOf(node: T, beats: number): T;
596
+ /**
597
+ *
598
+ * @param beats 拍数
599
+ * @ param usePrev 可选,若设为true,则在取到事件头部时会返回前一个事件(即视为左开右闭)
600
+ * @returns 时间索引链表的节点,一般不是head
601
+ */
602
+ getNodeAt(beats: number): T;
603
+ }
604
+ }
605
+ declare module "bpm" {
606
+ import { type BPMSegmentData, type TimeT } from "chartTypes";
607
+ import { EventEndNode, EventNodeLike, EventNodeSequence, EventStartNode, type ENOrHead, type ENOrTail } from "event";
608
+ import { JumpArray } from "jumparray";
609
+ import { NodeType } from "util";
610
+ /**
611
+ * BPM起始节点类,表示BPM变化的开始点
612
+ * 每个BPMStartNode代表一个BPM值的开始,直到下一个BPM节点
613
+ */
614
+ export class BPMStartNode extends EventStartNode {
615
+ /** 每拍的秒数(Seconds Per Beat) */
616
+ spb: number;
617
+ /** 缓存的起始积分值,用于时间计算 */
618
+ cachedStartIntegral?: number;
619
+ /** 缓存的积分值,用于时间计算 */
620
+ cachedIntegral?: number;
621
+ /** 下一个BPM结束节点或尾部节点 */
622
+ next: BPMEndNode | BPMNodeLike<NodeType.TAIL>;
623
+ /** 上一个BPM结束节点或头部节点 */
624
+ previous: BPMEndNode | BPMNodeLike<NodeType.HEAD>;
625
+ /**
626
+ * 创建一个新的BPM起始节点
627
+ * @param startTime 节点开始时间
628
+ * @param bpm BPM值
629
+ */
630
+ constructor(startTime: TimeT, bpm: number);
631
+ /**
632
+ * 计算指定拍数对应的秒数
633
+ * @param beats 拍数
634
+ * @returns 对应的秒数
635
+ */
636
+ getSeconds(beats: number): number;
637
+ /**
638
+ * 获取当前BPM段的完整持续时间(秒)
639
+ * @this NonLastBPMStartNode 非最后一个BPM节点
640
+ * @returns 当前BPM段的持续时间(秒)
641
+ */
642
+ getFullSeconds(this: NonLastBPMStartNode): number;
643
+ }
644
+ /**
645
+ * BPM结束节点类,表示BPM段的结束点
646
+ * 用于标记BPM段的结束位置
647
+ */
648
+ export class BPMEndNode extends EventEndNode {
649
+ /** 每拍的秒数(Seconds Per Beat) */
650
+ spb: number;
651
+ /** 前一个BPM起始节点 */
652
+ previous: BPMStartNode;
653
+ /** 下一个BPM起始节点 */
654
+ next: BPMStartNode;
655
+ /**
656
+ * 创建一个新的BPM结束节点
657
+ * @param endTime 节点结束时间
658
+ */
659
+ constructor(endTime: TimeT);
660
+ }
661
+ /** 非最后一个BPM起始节点类型 */
662
+ type NonLastBPMStartNode = BPMStartNode & {
663
+ next: BPMEndNode;
664
+ };
665
+ /**
666
+ * BPM节点接口,定义了BPM节点的基本结构
667
+ */
668
+ interface BPMNodeLike<T extends NodeType> extends EventNodeLike<T> {
669
+ /** 下一个节点 */
670
+ next: [BPMStartNode, null, BNOrTail][T] | null;
671
+ /** 上一个节点 */
672
+ previous: [null, BPMStartNode, BNOrHead][T] | null;
673
+ }
674
+ /** BPM节点类型 */
675
+ type BPMNode = BPMStartNode | BPMEndNode;
676
+ /** 任意BPM节点类型 */
677
+ type AnyBN = (BPMNode | BPMNodeLike<NodeType.TAIL> | BPMNodeLike<NodeType.HEAD>);
678
+ /** BPM节点或尾部节点类型 */
679
+ type BNOrTail = BPMNode | BPMNodeLike<NodeType.TAIL>;
680
+ /** BPM节点或头部节点类型 */
681
+ type BNOrHead = BPMNode | BPMNodeLike<NodeType.HEAD>;
682
+ /**
683
+ * BPM序列类,管理BPM变化序列
684
+ * 拥有与事件类似的逻辑,每对节点之间代表一个BPM相同的片段
685
+ * 片段之间BPM可以发生改变
686
+ */
687
+ export class BPMSequence extends EventNodeSequence {
688
+ duration: number;
689
+ /** 头部节点 */
690
+ head: BPMNodeLike<NodeType.HEAD>;
691
+ /** 尾部节点 */
692
+ tail: BPMNodeLike<NodeType.TAIL>;
693
+ /** 从拍数访问节点的跳转数组 */
694
+ jump: JumpArray<AnyBN>;
695
+ /** 以秒计时的跳转数组,处理从秒访问节点 */
696
+ secondJump: JumpArray<AnyBN>;
697
+ /**
698
+ * 创建BPM序列
699
+ * @param bpmList BPM片段数据列表
700
+ * @param duration 总持续时间
701
+ */
702
+ constructor(bpmList: BPMSegmentData[], duration: number);
703
+ /**
704
+ * 初始化跳转数组
705
+ */
706
+ initJump(): void;
707
+ /**
708
+ * 更新秒跳转数组
709
+ */
710
+ updateSecondJump(): void;
711
+ /**
712
+ * 更新跳转数组
713
+ * @param from 起始节点
714
+ * @param to 结束节点
715
+ */
716
+ updateJump(from: ENOrHead, to: ENOrTail): void;
717
+ /**
718
+ * 根据秒数获取BPM起始节点
719
+ * @param seconds 秒数
720
+ * @returns 对应的BPM起始节点
721
+ */
722
+ getNodeBySeconds(seconds: number): BPMStartNode;
723
+ /**
724
+ * 导出BPM数据
725
+ * @returns BPM片段数据数组
726
+ */
727
+ dumpBPM(): BPMSegmentData[];
728
+ /**
729
+ * 根据拍数获取节点
730
+ * @param beats 拍数
731
+ * @param usePrev 是否使用前一个节点
732
+ * @returns 对应的BPM起始节点
733
+ */
734
+ getNodeAt(beats: number, usePrev?: boolean): BPMStartNode;
735
+ }
736
+ /**
737
+ * 时间计算器类,用于处理拍数与秒数之间的转换
738
+ */
739
+ export class TimeCalculator {
740
+ /** BPM片段数据列表 */
741
+ bpmList: BPMSegmentData[];
742
+ /** BPM序列 */
743
+ readonly bpmSequence: BPMSequence;
744
+ /** 总持续时间 */
745
+ duration: number;
746
+ /**
747
+ * 创建时间计算器
748
+ */
749
+ constructor();
750
+ /**
751
+ * 初始化BPM序列
752
+ */
753
+ initSequence(): void;
754
+ /**
755
+ * 将拍数转换为秒数
756
+ * @param beats 拍数
757
+ * @returns 对应的秒数
758
+ */
759
+ toSeconds(beats: number): number;
760
+ /**
761
+ * 获取从beats1到beats2的秒数
762
+ * @param beats1 起始拍数
763
+ * @param beats2 结束拍数
764
+ * @returns 两拍数之间的秒数差
765
+ */
766
+ segmentToSeconds(beats1: number, beats2: number): number;
767
+ /**
768
+ * 将秒数转换为拍数
769
+ * @param seconds 秒数
770
+ * @returns 对应的拍数
771
+ */
772
+ secondsToBeats(seconds: number): number;
773
+ /**
774
+ * 导出BPM数据
775
+ * @returns BPM片段数据数组
776
+ */
777
+ dump(): BPMSegmentData[];
778
+ }
779
+ }
780
+ declare module "note" {
781
+ /**
782
+ * @author Zes M Young
783
+ */
784
+ import type { Chart } from "chart";
785
+ import { NoteType, type NNListDataKPA, type NoteDataKPA, type NoteDataRPE, type NoteNodeDataKPA, type TimeT } from "chartTypes";
786
+ import type { JudgeLine } from "judgeline";
787
+ import { JumpArray } from "jumparray";
788
+ import { type TimeCalculator } from "bpm";
789
+ import { NodeType } from "util";
790
+ export type HEX = number;
791
+ export const notePropTypes: {
792
+ above: string;
793
+ alpha: string;
794
+ endTime: string[];
795
+ isFake: string;
796
+ positionX: string;
797
+ size: string;
798
+ speed: string;
799
+ startTime: string[];
800
+ type: string;
801
+ visibleTime: string;
802
+ visibleBeats: string;
803
+ yOffset: string;
804
+ tint: string[];
805
+ tintHitEffects: string[];
806
+ judgeSize: string;
807
+ };
808
+ /**
809
+ * 音符
810
+ * Basic element in music game.
811
+ * Has 4 types: tap, drag, flick and hold.
812
+ * Only hold has endTime; others' endTime is equal to startTime.
813
+ * For this reason, holds are store in a special list (HNList),
814
+ * which is sorted by both startTime and endTime,
815
+ * so that they are accessed correctly and rapidly in the renderer.
816
+ * Note that Hold and HoldNode are not individually-declared classes.
817
+ * Hold is a note with type being NoteType.hold,
818
+ * while HoldNode is a node that contains holds.
819
+ */
820
+ export class Note {
821
+ above: boolean;
822
+ alpha: number;
823
+ endTime: [number, number, number];
824
+ isFake: boolean;
825
+ /** x coordinate in the judge line */
826
+ positionX: number;
827
+ size: number;
828
+ speed: number;
829
+ startTime: [number, number, number];
830
+ type: NoteType;
831
+ /** @deprecated */
832
+ visibleTime: number;
833
+ visibleBeats: number;
834
+ yOffset: number;
835
+ parentNode: NoteNode;
836
+ tint: HEX;
837
+ tintHitEffects: HEX;
838
+ judgeSize: number;
839
+ constructor(data: NoteDataRPE | NoteDataKPA);
840
+ static fromKPAJSON(data: NoteDataKPA, timeCalculator: TimeCalculator): Note;
841
+ computeVisibleBeats(timeCalculator: TimeCalculator): void;
842
+ /**
843
+ *
844
+ * @param offset
845
+ * @returns
846
+ */
847
+ clone(offset: TimeT): Note;
848
+ dumpRPE(timeCalculator: TimeCalculator): NoteDataRPE;
849
+ dumpKPA(): NoteDataKPA;
850
+ }
851
+ export type NNOrHead = NoteNode | NoteNodeLike<NodeType.HEAD>;
852
+ export type NNOrTail = NoteNode | NoteNodeLike<NodeType.TAIL>;
853
+ export type AnyNN = NoteNode | NoteNodeLike<NodeType.HEAD> | NoteNodeLike<NodeType.TAIL>;
854
+ export class NoteNodeLike<T extends NodeType> {
855
+ type: T;
856
+ next: NNOrTail;
857
+ _previous: WeakRef<NNOrHead> | null;
858
+ parentSeq: NNList;
859
+ get previous(): any;
860
+ set previous(val: any);
861
+ constructor(type: T);
862
+ }
863
+ export class NoteNode extends NoteNodeLike<NodeType.MIDDLE> {
864
+ totalNode: NNNode;
865
+ readonly startTime: TimeT;
866
+ /**
867
+ * The notes it contains.
868
+ * If they are holds, they are ordered by their endTime, from late to early.
869
+ */
870
+ readonly notes: Note[];
871
+ parentSeq: NNList;
872
+ chart: Chart;
873
+ private static count;
874
+ id: number;
875
+ constructor(time: TimeT);
876
+ static fromKPAJSON(data: NoteNodeDataKPA, timeCalculator: TimeCalculator): NoteNode;
877
+ get isHold(): boolean;
878
+ get endTime(): TimeT;
879
+ add(note: Note): void;
880
+ sort(note: Note): void;
881
+ /**
882
+ * 其他部分均已有序,通过冒泡排序把发生变更的NoteNode移动到正确的位置
883
+ * @param index 待排序的Note的索引
884
+ */
885
+ sort(index: number): void;
886
+ remove(note: Note): void;
887
+ static disconnect(note1: NNOrHead, note2: NNOrTail): void;
888
+ static connect(note1: NNOrHead, note2: NNOrTail): void;
889
+ static insert(note1: NNOrHead, inserted: NoteNode, note2: NNOrTail): void;
890
+ dump(): NoteNodeDataKPA;
891
+ }
892
+ export class NNList {
893
+ speed: number;
894
+ medianYOffset: number;
895
+ /** 格式为#xxoxx或$xxoxx,亦可自命名 */
896
+ id: string;
897
+ head: NoteNodeLike<NodeType.HEAD>;
898
+ tail: NoteNodeLike<NodeType.TAIL>;
899
+ currentPoint: NNOrHead;
900
+ /** 定位上个Note头已过,本身未到的Note */
901
+ jump: JumpArray<AnyNN>;
902
+ timesWithNotes: number;
903
+ timeRanges: [number, number][];
904
+ effectiveBeats: number;
905
+ parentLine: JudgeLine;
906
+ constructor(speed: number, medianYOffset?: number, effectiveBeats?: number);
907
+ /** 此方法永远用于最新KPAJSON */
908
+ static fromKPAJSON<T extends boolean>(isHold: T, effectiveBeats: number, data: NNListDataKPA, nnnList: NNNList, timeCalculator: TimeCalculator): T extends true ? HNList : NNList;
909
+ initJump(): void;
910
+ /**
911
+ *
912
+ * @param beats 目标位置
913
+ * @param beforeEnd 指定选取该时刻之前还是之后第一个Node,对于非Hold无影响
914
+ * @param pointer 指针,实现查询位置缓存
915
+ * @returns
916
+ */
917
+ getNodeAt(beats: number, beforeEnd?: boolean): NNOrTail;
918
+ /**
919
+ * Get or create a node of given time
920
+ * @param time
921
+ * @returns
922
+ */
923
+ getNodeOf(time: TimeT): NoteNode;
924
+ dumpKPA(): NNListDataKPA;
925
+ getNodesFromOneAndRangeRight(node: NoteNode, rangeRight: TimeT): NoteNode[];
926
+ getNodesAfterOne(node: NoteNode): NoteNode[];
927
+ clearEmptyNodes(updatesJump?: boolean): void;
928
+ }
929
+ /**
930
+ * HoldNode的链表
931
+ * HN is the abbreviation of HoldNode, which is not individually declared.
932
+ * A NN that contains holds (a type of note) is a HN.
933
+ */
934
+ export class HNList extends NNList {
935
+ /**
936
+ * 最早的还未结束Hold
937
+ */
938
+ holdTailJump: JumpArray<AnyNN>;
939
+ constructor(speed: number, medianYOffset: number, effectiveBeats?: number);
940
+ initJump(): void;
941
+ getNodeAt(beats: number, beforeEnd?: boolean): NNOrTail;
942
+ insertNoteJumpUpdater(note: NoteNode): () => void;
943
+ }
944
+ export type NNNOrHead = NNNode | NNNodeLike<NodeType.HEAD>;
945
+ export type NNNOrTail = NNNode | NNNodeLike<NodeType.TAIL>;
946
+ type AnyNNN = NNNode | NNNodeLike<NodeType.HEAD> | NNNodeLike<NodeType.TAIL>;
947
+ export class NNNodeLike<T extends NodeType> {
948
+ type: T;
949
+ previous: NNNOrHead;
950
+ next: NNNOrTail;
951
+ startTime: TimeT;
952
+ constructor(type: T);
953
+ }
954
+ export class NNNode extends NNNodeLike<NodeType.MIDDLE> {
955
+ readonly noteNodes: NoteNode[];
956
+ readonly holdNodes: NoteNode[];
957
+ readonly startTime: TimeT;
958
+ noteOfType: [number, number, number, number];
959
+ constructor(time: TimeT);
960
+ get endTime(): TimeT;
961
+ add(node: NoteNode): void;
962
+ static connect(note1: NNNOrHead, note2: NNNOrTail): void;
963
+ static insert(note1: NNNOrHead, inserted: NNNode, note2: NNNOrTail): void;
964
+ }
965
+ /**
966
+ * 二级音符节点链表
967
+ * contains NNNs
968
+ * NNN is the abbreviation of NoteNodeNode, which store note (an element in music game) nodes with same startTime
969
+ * NN is the abbreviation of NoteNode, which stores the notes with the same startTime.
970
+ */
971
+ export class NNNList {
972
+ jump: JumpArray<AnyNNN>;
973
+ parentChart: Chart;
974
+ head: NNNodeLike<NodeType.HEAD>;
975
+ tail: NNNodeLike<NodeType.TAIL>;
976
+ effectiveBeats: number;
977
+ timesWithNotes: number;
978
+ constructor(effectiveBeats: number);
979
+ initJump(): void;
980
+ getNodeAt(beats: number, beforeEnd?: boolean): NNNode | NNNodeLike<NodeType.TAIL>;
981
+ getNode(time: TimeT): NNNode;
982
+ addNoteNode(noteNode: NoteNode): void;
983
+ }
984
+ }
985
+ declare module "judgeline" {
986
+ import type { Chart, JudgeLineGroup } from "chart";
987
+ import { JudgeLineDataKPA2, type JudgeLineDataKPA, type JudgeLineDataRPE, type NNListDataKPA, type RGB } from "chartTypes";
988
+ import type { TemplateEasingLib } from "easing";
989
+ import { EventNodeSequence, SpeedENS } from "event";
990
+ import { HNList, NNList, Note, NNNList } from "note";
991
+ import { type TimeCalculator } from "bpm";
992
+ export interface EventLayer {
993
+ moveX?: EventNodeSequence;
994
+ moveY?: EventNodeSequence;
995
+ rotate?: EventNodeSequence;
996
+ alpha?: EventNodeSequence;
997
+ }
998
+ export interface ExtendedLayer {
999
+ scaleX?: EventNodeSequence;
1000
+ scaleY?: EventNodeSequence;
1001
+ text?: EventNodeSequence<string>;
1002
+ color?: EventNodeSequence<RGB>;
1003
+ }
1004
+ export class JudgeLine {
1005
+ texture: string;
1006
+ group: JudgeLineGroup;
1007
+ cover: boolean;
1008
+ hnLists: Map<string, HNList>;
1009
+ nnLists: Map<string, NNList>;
1010
+ eventLayers: EventLayer[];
1011
+ speedSequence: SpeedENS;
1012
+ extendedLayer: ExtendedLayer;
1013
+ father: JudgeLine;
1014
+ children: Set<JudgeLine>;
1015
+ zOrder: number;
1016
+ anchor: [number, number];
1017
+ hasAttachUI: boolean;
1018
+ /**
1019
+ * 每帧渲染时所用的变换矩阵,缓存下来用于之后的UI绑定渲染
1020
+ *
1021
+ * 已移除,谱面NPM包不需要这个,播放器侧如要使用,可以用同名接口扩展此类
1022
+ * @removed since 2.0.1
1023
+ */
1024
+ /**
1025
+ * 是否随父线旋转
1026
+ */
1027
+ rotatesWithFather: boolean;
1028
+ id: number;
1029
+ name: string;
1030
+ readonly chart: Chart;
1031
+ constructor(chart: Chart);
1032
+ static fromRPEJSON(chart: Chart, id: number, data: JudgeLineDataRPE, templates: TemplateEasingLib, timeCalculator: TimeCalculator): JudgeLine;
1033
+ static fromKPAJSON(version: number, chart: Chart, id: number, data: JudgeLineDataKPA | JudgeLineDataKPA2, templates: TemplateEasingLib, timeCalculator: TimeCalculator): JudgeLine;
1034
+ getNNListFromOldKPAJSON(lists: Map<string, NNList>, namePrefix: string, isHold: boolean, effectiveBeats: number, listData: NNListDataKPA, nnnList: NNNList, timeCalculator: TimeCalculator): void;
1035
+ getLayer(index: "0" | "1" | "2" | "3" | "ex"): EventLayer | ExtendedLayer;
1036
+ /**
1037
+ * 判定线当前所在的FloorPosition
1038
+ *
1039
+ * 可以理解为:有一个假想的充满音符的瀑布流,判定线在其中或前进或后退
1040
+ */
1041
+ currentFloorPosition: number;
1042
+ cachedFloorPositions: Float64Array;
1043
+ computeCurrentFloorPosition(beats: number, timeCalculator: TimeCalculator): void;
1044
+ getRelativeFloorPositionAt(beats: number, timeCalculator: TimeCalculator): number;
1045
+ /**
1046
+ * 通过速度序列的FloorPosition反解出一个时间范围。
1047
+ *
1048
+ * KPA内核代码中最大的一坨史山,没有之一。
1049
+ *
1050
+ * 谱面渲染时最耗时的函数
1051
+ *
1052
+ * startY and endY must not be negative
1053
+ * @param beats
1054
+ * @param timeCalculator
1055
+ * @param startY
1056
+ * @param endY
1057
+ * @returns
1058
+ * /
1059
+ computeTimeRange(beats: number, timeCalculator: TimeCalculator , startY: number, endY: number): [number, number][] {
1060
+ //return [[0, Infinity]]
1061
+ //*
1062
+ // 提取所有有变化的时间点
1063
+ let times: number[] = [];
1064
+ const result: [number, number][] = [];
1065
+ for (const eventLayer of this.eventLayers) {
1066
+ const sequence = eventLayer?.speed;
1067
+ if (!sequence) {
1068
+ continue;
1069
+ }
1070
+ let node: EventStartNode = sequence.getNodeAt(beats);
1071
+ let endNode: EventEndNode | EventNodeLike<NodeType.TAIL>
1072
+ while (true) {
1073
+ times.push(TC.toBeats(node.time))
1074
+ if ((endNode = node.next).type === NodeType.TAIL) {
1075
+ break;
1076
+ }
1077
+
1078
+ node = endNode.next
1079
+ }
1080
+ }
1081
+ times = [...new Set(times)].sort((a, b) => a - b)
1082
+ const len = times.length;
1083
+ let nextTime = times[0]
1084
+ let nextPosY = this.getStackedFloorPosition(nextTime, timeCalculator)
1085
+ let nextSpeed = this.getStackedValue("speed", nextTime, true)
1086
+ let range: [number, number] = [undefined, undefined];
1087
+ // console.log(times)
1088
+ const computeTime = (speed: number, currentPos: number, fore: number) => timeCalculator.secondsToBeats(currentPos / (speed * 120) + timeCalculator.toSeconds(fore));
1089
+ for (let i = 0; i < len - 1;) {
1090
+ const thisTime = nextTime;
1091
+ const thisPosY = nextPosY;
1092
+ let thisSpeed = this.getStackedValue("speed", thisTime);
1093
+ if (Math.abs(thisSpeed) < 1e-8) {
1094
+ thisSpeed = 0; // 不这样做可能导致下面异号判断为真从而死循环
1095
+ }
1096
+ nextTime = times[i + 1]
1097
+ nextPosY = this.getStackedFloorPosition(nextTime, timeCalculator);
1098
+ nextSpeed = this.getStackedValue("speed", nextTime, true)
1099
+ // console.log(thisSpeed, nextSpeed, thisSpeed * nextSpeed < 0, i, [...result])
1100
+ if (thisSpeed * nextSpeed < 0) { // 有变号零点,再次切断,保证处理的每个区间单调性
1101
+ //debugger;
1102
+ nextTime = (nextTime - thisTime) * (0 - thisSpeed) / (nextSpeed - thisSpeed) + thisTime;
1103
+ nextSpeed = 0
1104
+ nextPosY = this.getStackedFloorPosition(nextTime, timeCalculator)
1105
+ //debugger
1106
+ } else {
1107
+ // console.log("i++")
1108
+ i++
1109
+ }
1110
+ if (range[0] === undefined) {
1111
+ // 变速区间直接全部囊括,匀速要算一下,因为好算
1112
+ /*
1113
+ 设两个时间点的位置为a,b
1114
+ 开始结束点为s,e
1115
+ 选中小段一部分在区间内:
1116
+ a < s <= b
1117
+ 或a > e >= b
1118
+ 全部在区间内
1119
+ s <= a <= b
1120
+ * /
1121
+ if (thisPosY < startY && startY <= nextPosY
1122
+ || thisPosY > endY && endY >= nextPosY) {
1123
+ range[0] = thisSpeed !== nextSpeed ? thisTime : computeTime(
1124
+ thisSpeed,
1125
+ (thisPosY < nextPosY ? startY : endY) - thisPosY, thisTime)
1126
+ } else if (startY <= thisPosY && thisPosY <= endY) {
1127
+ range[0] = thisTime;
1128
+ }
1129
+ }
1130
+ // 要注意这里不能合成双分支if因为想要的Y片段可能在一个区间内
1131
+ if (range[0] !== undefined) {
1132
+ if (thisPosY < endY && endY <= nextPosY || thisPosY > startY && startY >= nextPosY) {
1133
+ range[1] = thisSpeed !== nextSpeed ? nextTime : computeTime(
1134
+ thisSpeed,
1135
+ (thisPosY > nextPosY ? startY : endY) - thisPosY, thisTime)
1136
+ result.push(range)
1137
+ range = [undefined, undefined];
1138
+ }
1139
+ }
1140
+ }
1141
+ const thisPosY = nextPosY;
1142
+ const thisTime = nextTime;
1143
+ const thisSpeed = this.getStackedValue("speed", thisTime);
1144
+ const inf = thisSpeed > 0 ? Infinity : (thisSpeed < 0 ? -Infinity : thisPosY)
1145
+ if (range[0] === undefined) {
1146
+ // 变速区间直接全部囊括,匀速要算一下,因为好算
1147
+ if (thisPosY < startY && startY <= inf || thisPosY >= endY && endY > inf) {
1148
+ range[0] = computeTime(
1149
+ thisSpeed,
1150
+ (thisPosY < inf ? startY : endY) - thisPosY,
1151
+ thisTime)
1152
+ } else if (thisSpeed === 0) {
1153
+ range[0] = 0;
1154
+ }
1155
+ }
1156
+ // 要注意这里不能合成双分支if因为想要的Y片段可能在一个区间内
1157
+ if (range[0] !== undefined) {
1158
+ if (thisPosY < endY && endY <= inf || thisPosY >= startY && startY > inf) {
1159
+ range[1] = computeTime(
1160
+ thisSpeed,
1161
+ (thisPosY > inf ? startY : endY) - thisPosY,
1162
+ thisTime)
1163
+ result.push(range)
1164
+ } else if (thisSpeed === 0) {
1165
+ range[1] = Infinity;
1166
+ result.push(range)
1167
+ }
1168
+ }
1169
+ return result;
1170
+ //* /
1171
+ }*/
1172
+ /**
1173
+ * 通过速度序列的FloorPosition反解出一个时间范围。
1174
+ *
1175
+ * KPA内核代码中最大的一坨史山,没有之一。
1176
+ *
1177
+ * 谜面渲染时最耗时的函数
1178
+ *
1179
+ * 调用此方法前需要先更新判定线当前的FP。
1180
+ *
1181
+ * startY and endY must not be negative
1182
+ * @param beats
1183
+ * @param timeCalculator
1184
+ * @param startY
1185
+ * @param endY
1186
+ * @returns
1187
+ */
1188
+ computeTimeRange(beats: number, timeCalculator: TimeCalculator, startY: number, endY: number): [number, number][];
1189
+ /**
1190
+ *
1191
+ * @deprecated 1.7.0
1192
+ * @param beats
1193
+ * @param usePrev 如果取到节点,将使用EndNode的值。默认为FALSE
1194
+ * @returns
1195
+ */
1196
+ getValues(beats: number, usePrev?: boolean): [x: number, y: number, theta: number, alpha: number];
1197
+ getStackedValue(type: keyof EventLayer, beats: number, usePrev?: boolean): number;
1198
+ /**
1199
+ * 获取指定时间点的FloorPosition。
1200
+ *
1201
+ * <del>为了向后兼容,保留了多层速度事件的机制。</del>
1202
+ *
1203
+ * 已经删除了多层速度事件
1204
+ * @param beats
1205
+ * @param timeCalculator
1206
+ * @returns
1207
+ * /
1208
+ getStackedFloorPosition(beats: number, timeCalculator: TimeCalculator) {
1209
+
1210
+ const length = this.eventLayers.length;
1211
+ let current = 0;
1212
+ for (let index = 0; index < length; index++) {
1213
+ const layer = this.eventLayers[index];
1214
+ if (!layer || !layer.speed) {
1215
+ break;
1216
+ }
1217
+ current += layer.speed.getFloorPositionAt(beats, timeCalculator);
1218
+ }
1219
+ // console.log("integral", current)
1220
+ return current;
1221
+ }//*/
1222
+ /**
1223
+ * 获取对应速度和类型的Note树,没有则创建
1224
+ */
1225
+ getNNList(speed: number, yOffset: number, isHold: boolean, initsJump: boolean): any;
1226
+ getNode(note: Note, initsJump: boolean): any;
1227
+ /**
1228
+ *
1229
+ * @param eventNodeSequences To Collect the sequences used in this line
1230
+ * @returns
1231
+ */
1232
+ dumpKPA(eventNodeSequences: Set<EventNodeSequence<any>>, judgeLineGroups: JudgeLineGroup[]): JudgeLineDataKPA2;
1233
+ updateEffectiveBeats(EB: number): void;
1234
+ static checkinterdependency(judgeLine: JudgeLine, toBeFather: JudgeLine): boolean;
1235
+ }
1236
+ }
1237
+ declare module "macro" {
1238
+ import type { Chart } from "chart";
1239
+ import type { EventValueESType, MacroData, MacroEvaluatorBodyData, MacroLink, MacroTimeBodyData, MacroValueBodyData, RGB, TimeT } from "chartTypes";
1240
+ import { ERROR_IDS, KPAError } from "env";
1241
+ import { MacroEvaluator } from "evaluator";
1242
+ import type { EventNode, EventStartNode } from "event";
1243
+ import { Note } from "note";
1244
+ export const EVENT_MACROS: {
1245
+ "line.id": (node: EventStartNode<EventValueESType>, chart: Chart) => number;
1246
+ "line.name": (node: EventStartNode<EventValueESType>, chart: Chart) => string;
1247
+ "line.group": (node: EventStartNode<EventValueESType>, chart: Chart) => import("chart").JudgeLineGroup;
1248
+ "node.time": (node: EventStartNode<EventValueESType>) => TimeT;
1249
+ "node.value": (node: EventStartNode<EventValueESType>) => EventValueESType;
1250
+ "seq.id": (node: EventStartNode<EventValueESType>) => string;
1251
+ "seq.type": (node: EventStartNode<EventValueESType>) => import("chartTypes").EventType;
1252
+ };
1253
+ export type Macroable = number | string | TimeT | RGB | boolean;
1254
+ export type Macroee = EventNode<EventValueESType> | Note;
1255
+ export abstract class Macro<T extends Macroable, C extends Macroee, P extends Macroee> {
1256
+ macro: string;
1257
+ id: string;
1258
+ readonly parametric: boolean;
1259
+ readonly consumers: Map<C, number>;
1260
+ /**
1261
+ * **原形节点**
1262
+ *
1263
+ * 作为参数,向其他节点派生数值。
1264
+ *
1265
+ * 需要parametric为true。
1266
+ *
1267
+ * 如:若节点A存在于这个数组,下标为1:
1268
+ *
1269
+ * 节点B设有数值宏,即这个宏,宏表达式: @proto.value + 2。
1270
+ *
1271
+ * 那么评估B的宏时可以调用节点A的数值。
1272
+ *
1273
+ * 在转储时,是节点存储宏的ID,而不是宏去找节点,因为节点并没有全谱面编号系统。
1274
+ */
1275
+ readonly protoNodes: P[];
1276
+ /**
1277
+ *
1278
+ * @param macro
1279
+ * @param id
1280
+ * @param parametric 是否为参数宏,即是否可以把一个节点作为参数。
1281
+ */
1282
+ constructor(macro: string, id: string, parametric: boolean);
1283
+ abstract eval(consumer: C, chart: Chart): T;
1284
+ }
1285
+ export abstract class EventMacro<T extends Macroable> extends Macro<T, EventNode<EventValueESType>, EventNode<EventValueESType>> {
1286
+ eval(node: EventNode<EventValueESType>, chart: Chart): T;
1287
+ checkSyntax(): KPAError<ERROR_IDS.PROTO_PRESENT_IN_NONPARAMETRIC | ERROR_IDS.UNKNOWN_MACRO_EXPRESSION | ERROR_IDS.JAVASCRIPT_SYNTAX_ERROR> | null;
1288
+ bindNode(node: EventNode<EventValueESType>, macroData: MacroData, pos?: string): void;
1289
+ linkProtoNode(node: EventNode<EventValueESType>, id: number): void;
1290
+ dumpContent(): MacroValueBodyData;
1291
+ /**
1292
+ * 为单个节点导出宏名称和参数(若有)
1293
+ * @param node
1294
+ * @example
1295
+ * return {
1296
+ * start: node.value,
1297
+ * end: node.next.value,
1298
+ * macroStart: node.valueMacro.dumpForNode(node),
1299
+ * macroEnd: node.valueMacro.dumpForNode(node.next),
1300
+ * ...
1301
+ * } satisfies EvenDataKPA2
1302
+ *
1303
+ */
1304
+ dumpForNode(node: EventNode<EventValueESType>): MacroData;
1305
+ abstract dumpLinkForNode(node: EventNode<EventValueESType>): MacroLink;
1306
+ }
1307
+ export class EventMacroValue extends EventMacro<EventValueESType> {
1308
+ dumpLinkForNode(node: EventNode<EventValueESType>): MacroLink;
1309
+ }
1310
+ export class EventMacroTime extends EventMacro<TimeT> {
1311
+ dumpLinkForNode(node: EventNode<EventValueESType>): MacroLink;
1312
+ }
1313
+ export class MacroLib {
1314
+ timeMacros: Map<string, EventMacroTime>;
1315
+ valueMacros: Map<string, EventMacroValue>;
1316
+ macroEvaluators: Map<string, MacroEvaluator<EventValueESType>>;
1317
+ dumpTimeMacros(): MacroTimeBodyData[];
1318
+ readTimeMacros(data: MacroTimeBodyData[]): void;
1319
+ dumpValueMacros(): MacroValueBodyData[];
1320
+ readValueMacros(data: MacroValueBodyData[]): void;
1321
+ dumpMacroEvaluators(): MacroEvaluatorBodyData[];
1322
+ readMacroEvaluators(data: MacroEvaluatorBodyData[]): void;
1323
+ }
1324
+ }
1325
+ declare module "evaluator" {
1326
+ import { Easing } from "easing";
1327
+ import type { EventStartNode, NonLastStartNode } from "event";
1328
+ import { EventValueTypeOfType, InterpreteAs, MacroEvaluatorBodyData, MacroEvaluatorDataKPA2, type ColorEasedEvaluatorKPA2, type EvaluatorDataKPA2, type EventValueESType, type ExpressionEvaluatorDataKPA2, type NumericEasedEvaluatorKPA2, type RGB, type TextEasedEvaluatorKPA2 } from "chartTypes";
1329
+ import { Chart } from "chart";
1330
+ /**
1331
+ * **求值器**
1332
+ *
1333
+ * 基于给定的事件和拍数,返回事件在此点的值。
1334
+ *
1335
+ * 被求值的事件必须是拥有下一个节点的事件。序列尾部的节点(与尾节点相连的节点)不能被求值。
1336
+ * @immutable
1337
+ * @since 2.0.0
1338
+ */
1339
+ export abstract class Evaluator<T extends EventValueESType> {
1340
+ abstract eval(event: NonLastStartNode<T>, beats: number): T;
1341
+ abstract dumpFor(node: EventStartNode<T>): EvaluatorDataKPA2<T>;
1342
+ }
1343
+ export abstract class EasedEvaluator<T extends EventValueESType> extends Evaluator<T> {
1344
+ readonly easing: Easing;
1345
+ constructor(easing: Easing);
1346
+ eval(startNode: NonLastStartNode<T>, beats: number): T;
1347
+ abstract convert(start: T, end: T, progress: number): T;
1348
+ /**
1349
+ * 派生一个类型相同但使用不同缓动的求值器
1350
+ * @param easing
1351
+ * @returns
1352
+ */
1353
+ abstract deriveWithEasing(easing: Easing): EasedEvaluator<T>;
1354
+ static getEvaluatorFromEasing<T extends EventValueESType>(type: EventValueTypeOfType<T>, easing: Easing, interpretedAs?: InterpreteAs): EasedEvaluatorOfType<T>;
1355
+ }
1356
+ export type EasedEvaluatorOfType<T extends EventValueESType> = T extends number ? NumericEasedEvaluator : T extends RGB ? ColorEasedEvaluator : TextEasedEvaluator;
1357
+ export type EasedEvaluatorConstructorOfType<T extends EventValueESType> = T extends number ? typeof NumericEasedEvaluator : T extends RGB ? typeof ColorEasedEvaluator : typeof TextEasedEvaluator;
1358
+ export class NumericEasedEvaluator extends EasedEvaluator<number> {
1359
+ constructor(easing: Easing);
1360
+ private cache?;
1361
+ dumpFor(): NumericEasedEvaluatorKPA2;
1362
+ convert(start: number, end: number, progress: number): number;
1363
+ static default: NumericEasedEvaluator;
1364
+ static evaluatorsOfNormalEasing: NumericEasedEvaluator[];
1365
+ deriveWithEasing(easing: Easing): NumericEasedEvaluator;
1366
+ }
1367
+ export class ColorEasedEvaluator extends EasedEvaluator<RGB> {
1368
+ constructor(easing: Easing);
1369
+ dumpFor(): ColorEasedEvaluatorKPA2;
1370
+ convert(start: RGB, end: RGB, progress: number): RGB;
1371
+ static default: ColorEasedEvaluator;
1372
+ static evaluatorsOfNormalEasing: ColorEasedEvaluator[];
1373
+ deriveWithEasing(easing: Easing): ColorEasedEvaluator;
1374
+ }
1375
+ /**
1376
+ * 文本缓动求值器
1377
+ *
1378
+ * 文本缓动求值器可以将文本解读为字符串、浮点数和整形。
1379
+ *
1380
+ * 行为与RPE的`%P%`相似
1381
+ */
1382
+ export class TextEasedEvaluator extends EasedEvaluator<string> {
1383
+ readonly interpretedAs: InterpreteAs;
1384
+ constructor(easing: Easing, interpretedAs?: InterpreteAs);
1385
+ dumpFor(): TextEasedEvaluatorKPA2;
1386
+ convert(value: string, nextValue: string, progress: number): string;
1387
+ static default: TextEasedEvaluator;
1388
+ static evaluatorsOfNoEzAndItpAs: TextEasedEvaluator[][];
1389
+ deriveWithEasing(easing: Easing): EasedEvaluator<string>;
1390
+ }
1391
+ export class MacroEvaluator<T extends EventValueESType> extends Evaluator<T> {
1392
+ expression: string;
1393
+ id: string;
1394
+ readonly consumers: Map<EventStartNode<T>, ExpressionEvaluator<T>>;
1395
+ constructor(expression: string, id: string);
1396
+ compile(node: EventStartNode<T>, chart: Chart): ExpressionEvaluator<T>;
1397
+ assignTo(node: EventStartNode<T>, chart: Chart): void;
1398
+ eval(event: NonLastStartNode<T>, beats: number): T;
1399
+ dumpFor(node: EventStartNode<T>): MacroEvaluatorDataKPA2;
1400
+ dumpContent(): MacroEvaluatorBodyData;
1401
+ }
1402
+ export class ExpressionEvaluator<T extends EventValueESType> extends Evaluator<T> {
1403
+ readonly jsExpr: string;
1404
+ readonly func: (t: number) => T;
1405
+ constructor(jsExpr: string);
1406
+ eval(startNode: NonLastStartNode<T>, beats: number): T;
1407
+ dumpFor(): ExpressionEvaluatorDataKPA2;
1408
+ }
1409
+ }
1410
+ declare module "easing" {
1411
+ import { type TemplateEasingBodyData, type EasingDataKPA2, EventType, type SegmentedEasingData, type NormalEasingData, type BezierEasingData, type TemplateEasingData, WrapperEasingData, WrapperEasingBodyData } from "chartTypes";
1412
+ import { type EventNodeSequence } from "event";
1413
+ import { type TupleCoord } from "util";
1414
+ import { type ExpressionEvaluator } from "evaluator";
1415
+ export const easingFns: {
1416
+ linear: (x: number) => number;
1417
+ easeInSine: (x: number) => number;
1418
+ easeOutSine: (x: number) => number;
1419
+ easeInOutSine: (x: number) => number;
1420
+ easeInQuad: (x: number) => number;
1421
+ easeOutQuad: (x: number) => number;
1422
+ easeInOutQuad: (x: number) => number;
1423
+ easeInCubic: (x: number) => number;
1424
+ easeOutCubic: (x: number) => number;
1425
+ easeInOutCubic: (x: number) => number;
1426
+ easeInQuart: (x: number) => number;
1427
+ easeOutQuart: (x: number) => number;
1428
+ easeInOutQuart: (x: number) => number;
1429
+ easeInQuint: (x: number) => number;
1430
+ easeOutQuint: (x: number) => number;
1431
+ easeInOutQuint: (x: number) => number;
1432
+ easeInExpo: (x: number) => number;
1433
+ easeOutExpo: (x: number) => number;
1434
+ easeInOutExpo: (x: number) => number;
1435
+ easeInCirc: (x: number) => number;
1436
+ easeOutCirc: (x: number) => number;
1437
+ easeInOutCirc: (x: number) => number;
1438
+ easeInBack: (x: number) => number;
1439
+ easeOutBack: (x: number) => number;
1440
+ easeInOutBack: (x: number) => number;
1441
+ easeInElastic: (x: number) => number;
1442
+ easeOutElastic: (x: number) => number;
1443
+ easeInOutElastic: (x: number) => number;
1444
+ easeInBounce: (x: number) => number;
1445
+ easeOutBounce: (x: number) => number;
1446
+ easeInOutBounce: (x: number) => number;
1447
+ };
1448
+ type FuncType = "linear" | "sine" | "quad" | "cubic" | "quart" | "quint" | "expo" | "circ" | "back" | "elastic" | "bounce";
1449
+ export const easingFnMap: {
1450
+ [k in FuncType]: [(x: number) => number, (x: number) => number, (x: number) => number];
1451
+ };
1452
+ /**
1453
+ * 缓动基类
1454
+ * Easings are used to describe the rate of change of a parameter over time.
1455
+ * They are used in events, curve note filling, etc.
1456
+ */
1457
+ export abstract class Easing {
1458
+ constructor();
1459
+ /**
1460
+ * 返回当前变化量与变化量之比
1461
+ * 或者当前数值。(参数方程)
1462
+ * @param t 一个0-1的浮点数,代表当前经过时间与总时间之比
1463
+ */
1464
+ abstract getValue(t: number): number;
1465
+ abstract dump(): EasingDataKPA2;
1466
+ segmentedValueGetter(easingLeft: number, easingRight: number): (t: number) => number;
1467
+ }
1468
+ /**
1469
+ * @immutable
1470
+ */
1471
+ export class SegmentedEasing extends Easing {
1472
+ readonly easing: Easing;
1473
+ readonly left: number;
1474
+ readonly right: number;
1475
+ getter: (t: number) => number;
1476
+ constructor(easing: Easing, left: number, right: number);
1477
+ getValue(t: number): number;
1478
+ replace(easing: Easing): Easing;
1479
+ dump(): SegmentedEasingData;
1480
+ }
1481
+ /**
1482
+ * 普通缓动
1483
+ * See https://easings.net/zh-cn to learn about the basic types of easing.
1484
+ *
1485
+ */
1486
+ export class NormalEasing extends Easing {
1487
+ rpeId: number;
1488
+ id: number;
1489
+ funcType: string;
1490
+ easeType: string;
1491
+ _getValue: (t: number) => number;
1492
+ constructor(fn: (t: number) => number);
1493
+ constructor(fn: (t: number) => number);
1494
+ getValue(t: number): number;
1495
+ private dumpCache;
1496
+ dump(): NormalEasingData;
1497
+ }
1498
+ /**
1499
+ * 贝塞尔曲线缓动
1500
+ * uses the Bezier curve formula to describe an easing.
1501
+ */
1502
+ export class BezierEasing extends Easing {
1503
+ readonly cp1: TupleCoord;
1504
+ readonly cp2: TupleCoord;
1505
+ readonly xs: Float64Array;
1506
+ readonly ys: Float64Array;
1507
+ readonly jumper: Uint8Array;
1508
+ constructor(cp1: TupleCoord, cp2: TupleCoord);
1509
+ /**
1510
+ * 从横坐标获得纵坐标
1511
+ * @param t 并不是贝塞尔曲线的参数,它对应一个横坐标数值,范围[0, 1]
1512
+ * @returns
1513
+ */
1514
+ getValue(t: number): number;
1515
+ dump(): BezierEasingData;
1516
+ }
1517
+ /**
1518
+ * 模板缓动
1519
+ * to implement an easing with an eventNodeSequence.
1520
+ * 这是受wikitext的模板概念启发的。
1521
+ * This is inspired by the "template" concept in wikitext.
1522
+ */
1523
+ export class TemplateEasing extends Easing {
1524
+ eventNodeSequence: EventNodeSequence;
1525
+ name: string;
1526
+ constructor(name: string, sequence: EventNodeSequence);
1527
+ getValue(t: number): number;
1528
+ dump(): TemplateEasingData;
1529
+ get valueDelta(): number;
1530
+ get headValue(): number;
1531
+ }
1532
+ export class WrapperEasing extends Easing {
1533
+ evaluator: ExpressionEvaluator<number>;
1534
+ start: number;
1535
+ end: number;
1536
+ name: string;
1537
+ constructor(evaluator: ExpressionEvaluator<number>, start: number, end: number, name: string);
1538
+ getValue(t: number): number;
1539
+ dump(): WrapperEasingData;
1540
+ }
1541
+ /**
1542
+ * 缓动库
1543
+ * 用于管理模板缓动
1544
+ * for template easing management
1545
+ *
1546
+ * 谱面的一个属性
1547
+ * a property of chart
1548
+ *
1549
+ * 加载谱面时,先加载事件序列,所需的模板缓动会被加入到缓动库,但并不立即实现,在读取模板缓动时,才实现缓动。
1550
+ * To load a chart, the eventNodeSquences will be first loaded, during which process
1551
+ * the easings will be added to the easing library but not implemented immediately.
1552
+ * They will be implemented when the template easings are read from data.
1553
+ *
1554
+ */
1555
+ export class TemplateEasingLib {
1556
+ getNewSequence: (type: EventType, effectiveBeats: number) => EventNodeSequence<number>;
1557
+ ExpressionEvaluatorCon: typeof ExpressionEvaluator;
1558
+ easings: Map<string, TemplateEasing>;
1559
+ wrapperEasings: Map<string, WrapperEasing>;
1560
+ constructor(getNewSequence: (type: EventType, effectiveBeats: number) => EventNodeSequence<number>, ExpressionEvaluatorCon: typeof ExpressionEvaluator);
1561
+ getOrNew(name: string): TemplateEasing;
1562
+ readWrapperEasings(data: WrapperEasingBodyData[]): void;
1563
+ getWrapper(name: string): WrapperEasing;
1564
+ /**
1565
+ * 注册一个模板缓动,但不会实现它
1566
+ * register a template easing when reading eventNodeSequences, but does not implement it immediately
1567
+ */
1568
+ require(name: string): void;
1569
+ implement(name: string, sequence: EventNodeSequence): void;
1570
+ /**
1571
+ * 检查所有模板缓动是否实现
1572
+ * check if all easings are implemented
1573
+ * 应当在读取完所有模板缓动后调用
1574
+ * should be invoked after all template easings are read
1575
+ */
1576
+ check(): void;
1577
+ get(key: string): TemplateEasing | undefined;
1578
+ dump(eventNodeSequences: Set<EventNodeSequence>): TemplateEasingBodyData[];
1579
+ dumpWrapperEasings(): WrapperEasingBodyData[];
1580
+ }
1581
+ export const linearEasing: NormalEasing;
1582
+ export const fixedEasing: NormalEasing;
1583
+ export const easingMap: {
1584
+ fixed: {
1585
+ out: NormalEasing;
1586
+ in: NormalEasing;
1587
+ inout: NormalEasing;
1588
+ };
1589
+ linear: {
1590
+ out: NormalEasing;
1591
+ in: NormalEasing;
1592
+ inout: NormalEasing;
1593
+ };
1594
+ sine: {
1595
+ in: NormalEasing;
1596
+ out: NormalEasing;
1597
+ inout: NormalEasing;
1598
+ };
1599
+ quad: {
1600
+ in: NormalEasing;
1601
+ out: NormalEasing;
1602
+ inout: NormalEasing;
1603
+ };
1604
+ cubic: {
1605
+ in: NormalEasing;
1606
+ out: NormalEasing;
1607
+ inout: NormalEasing;
1608
+ };
1609
+ quart: {
1610
+ in: NormalEasing;
1611
+ out: NormalEasing;
1612
+ inout: NormalEasing;
1613
+ };
1614
+ quint: {
1615
+ in: NormalEasing;
1616
+ out: NormalEasing;
1617
+ inout: NormalEasing;
1618
+ };
1619
+ expo: {
1620
+ in: NormalEasing;
1621
+ out: NormalEasing;
1622
+ inout: NormalEasing;
1623
+ };
1624
+ circ: {
1625
+ in: NormalEasing;
1626
+ out: NormalEasing;
1627
+ inout: NormalEasing;
1628
+ };
1629
+ back: {
1630
+ in: NormalEasing;
1631
+ out: NormalEasing;
1632
+ inout: NormalEasing;
1633
+ };
1634
+ elastic: {
1635
+ in: NormalEasing;
1636
+ out: NormalEasing;
1637
+ inout: NormalEasing;
1638
+ };
1639
+ bounce: {
1640
+ in: NormalEasing;
1641
+ out: NormalEasing;
1642
+ inout: NormalEasing;
1643
+ };
1644
+ };
1645
+ /**
1646
+ * 按照KPA的编号
1647
+ */
1648
+ export const easingArray: NormalEasing[];
1649
+ export const rpeEasingArray: NormalEasing[];
1650
+ }
1651
+ declare module "chart" {
1652
+ import { TimeCalculator } from "bpm";
1653
+ import { Easing, TemplateEasingLib } from "easing";
1654
+ import { EventNodeSequence, EventStartNode, EventEndNode, EventNode } from "event";
1655
+ import { JudgeLine } from "judgeline";
1656
+ import { NNNList, NNNode } from "note";
1657
+ import { type TimeT, type ValueTypeOfEventType, type BPMSegmentData, type ChartDataRPE, type ChartDataKPA, type EasingDataKPA2, type EvaluatorDataKPA2, type EasedEvaluatorDataOfType, EventType, type EventValueTypeOfType, type EventValueESType, type ExpressionEvaluatorDataKPA2, type ChartDataKPA2, type EventDataKPA2, InterpreteAs, MacroEvaluatorDataKPA2, FinalEventStartNodeDataKPA2, MacroData, MacroLink } from "chartTypes";
1658
+ import { ExpressionEvaluator, type EasedEvaluatorOfType } from "evaluator";
1659
+ import { MacroLib } from "macro";
1660
+ export type BasicEventName = "moveX" | "moveY" | "rotate" | "alpha" | "speed";
1661
+ export type UIName = "combo" | "combonumber" | "score" | "pause" | "bar" | "name" | "level";
1662
+ /**
1663
+ * 表示一张谱面的核心数据结构
1664
+ *
1665
+ * 包含了谱面的所有元素:判定线、音符、事件序列等信息
1666
+ */
1667
+ export class Chart {
1668
+ /** 谱面中所有的判定线列表 */
1669
+ judgeLines: JudgeLine[];
1670
+ /** 时间计算器,用于处理BPM变化和时间转换 */
1671
+ readonly timeCalculator: TimeCalculator;
1672
+ /** 无父级的根判定线列表 */
1673
+ orphanLines: JudgeLine[];
1674
+ /** 谱面名称 */
1675
+ name: string;
1676
+ /** 谱面难度等级 */
1677
+ level: string;
1678
+ /** 曲师信息 */
1679
+ composer: string;
1680
+ /** 谱师信息 */
1681
+ charter: string;
1682
+ /** 插画师信息 */
1683
+ illustrator: string;
1684
+ /** 谱面偏移时间(秒) */
1685
+ offset: number;
1686
+ /** 模板缓动库,用于管理和复用缓动函数 */
1687
+ readonly templateEasingLib: TemplateEasingLib;
1688
+ readonly macroLib: MacroLib;
1689
+ /** 事件序列映射表,通过ID索引事件序列 */
1690
+ readonly sequenceMap: Map<string, EventNodeSequence<EventValueESType>>;
1691
+ /** 有效节拍数(基于谱面持续时间计算得出) */
1692
+ effectiveBeats: number;
1693
+ /** 音符节点列表,用于管理谱面上的所有音符 */
1694
+ nnnList: NNNList;
1695
+ /** 判定线组列表,用于组织和分类判定线 */
1696
+ judgeLineGroups: JudgeLineGroup[];
1697
+ /** 谱面持续时间(秒) */
1698
+ duration: number;
1699
+ /** 谱面制作所用时间(以秒计) */
1700
+ chartingSeconds: number;
1701
+ /** RPE格式的谱面制作时间(以秒计) */
1702
+ rpeChartingSeconds: number;
1703
+ /** 标记谱面是否已被修改 */
1704
+ modified: boolean;
1705
+ /** 谱面最大连击数 */
1706
+ maxCombo: number;
1707
+ /** 暂停按钮绑定的判定线 */
1708
+ pauseAttach: JudgeLine | null;
1709
+ /** 连击数字绑定的判定线 */
1710
+ combonumberAttach: JudgeLine | null;
1711
+ /** 连击标识绑定的判定线 */
1712
+ comboAttach: JudgeLine | null;
1713
+ /** 进度条绑定的判定线 */
1714
+ barAttach: JudgeLine | null;
1715
+ /** 分数显示绑定的判定线 */
1716
+ scoreAttach: JudgeLine | null;
1717
+ /** 歌曲名称显示绑定的判定线 */
1718
+ nameAttach: JudgeLine | null;
1719
+ /** 难度等级显示绑定的判定线 */
1720
+ levelAttach: JudgeLine | null;
1721
+ constructor();
1722
+ /**
1723
+ * 获取有效节拍数
1724
+ * @returns 基于谱面持续时间计算的有效节拍数
1725
+ */
1726
+ getEffectiveBeats(): number;
1727
+ /**
1728
+ * 从RPE格式的JSON数据创建谱面对象
1729
+ * @param data RPE格式的谱面数据
1730
+ * @param duration 谱面持续时间(秒)
1731
+ * @returns 创建的Chart对象
1732
+ */
1733
+ static fromRPEJSON(data: ChartDataRPE, duration: number): Chart;
1734
+ /**
1735
+ * 从KPA格式的JSON数据创建谱面对象
1736
+ * @param data KPA格式的谱面数据
1737
+ * @returns 创建的Chart对象
1738
+ */
1739
+ static fromKPAJSON(data: ChartDataKPA | ChartDataKPA2): Chart;
1740
+ /**
1741
+ * 初始化时间计算器
1742
+ * @param bpmList BPM变化列表
1743
+ */
1744
+ initCalculator(bpmList: BPMSegmentData[]): void;
1745
+ /**
1746
+ * 更新有效节拍数
1747
+ * @param duration 新的持续时间
1748
+ */
1749
+ updateEffectiveBeats(duration: number): void;
1750
+ /**
1751
+ * 导出为KPA格式数据
1752
+ * @returns KPA格式的谱面数据对象
1753
+ */
1754
+ dumpKPA(): Required<ChartDataKPA2>;
1755
+ /**
1756
+ * 创建一个新的二级音符节点
1757
+ * @param time 节点时间
1758
+ * @returns 新创建的NNNode对象
1759
+ */
1760
+ createNNNode(time: TimeT): NNNode;
1761
+ /**
1762
+ * 创建一个新的事件节点序列
1763
+ * @param type 事件类型
1764
+ * @param name 序列名称(ID)
1765
+ * @returns 新创建的事件节点序列
1766
+ * @throws {KPAError<ERROR_IDS.SEQUENCE_NAME_OCCUPIED>}
1767
+ */
1768
+ createEventNodeSequence<T extends EventType>(type: T, name: string): EventNodeSequence<ValueTypeOfEventType<T>>;
1769
+ registerEventNodeSequence<T extends EventType>(type: T, name: string, seq: EventNodeSequence<T>): void;
1770
+ /**
1771
+ * 对谱面物量进行重新计数。
1772
+ *
1773
+ * 不会返回值,谱面物量存储在 `this.maxCombo` 中。
1774
+ */
1775
+ countMaxCombo(): void;
1776
+ /**
1777
+ * 将UI绑定到某判定线
1778
+ * @param ui UI名称,与RPEJSON中的代号相同
1779
+ * @param judgeLine 所要绑定的目标判定线
1780
+ * @throws {KPAError<ERROR_IDS.UI_OCCUPIED>}
1781
+ */
1782
+ attachUIToLine(ui: UIName, judgeLine: JudgeLine): void;
1783
+ /**
1784
+ * 移除谱面中某个UI的绑定,使UI进入未绑定状态
1785
+ * @param ui UI名称,与RPEJSON中的相同
1786
+ * @returns
1787
+ */
1788
+ detachUI(ui: UIName): void;
1789
+ /**
1790
+ * 查询指定判定线上绑定的UI组件
1791
+ * @param judgeLine 目标判定线
1792
+ * @returns 绑定到该判定线上的UI组件名称数组
1793
+ */
1794
+ queryJudgeLineUI(judgeLine: JudgeLine): UIName[];
1795
+ /**
1796
+ * 扫描所有用到的判定线贴图(纹理)并返回
1797
+ *
1798
+ * 给谱面播放器的接口,谱面播放器需要在初加载时提供贴图
1799
+ * @returns 所有使用的纹理名称集合
1800
+ */
1801
+ scanAllTextures(): Set<string>;
1802
+ /**
1803
+ * 使用KPA2数据创建一个缓动对象。
1804
+ *
1805
+ * 只有对贝塞尔缓动和截段缓动才会创建新对象,其他几种缓动从缓动库等中的对象池获取
1806
+ * @param data 缓动数据
1807
+ * @returns 创建的缓动对象
1808
+ */
1809
+ createEasingFromData(data: EasingDataKPA2): any;
1810
+ /**
1811
+ * 使用KPA2数据创建一个求值器对象。
1812
+ *
1813
+ * 求值器只有缓动型和表达式型两类。
1814
+ * @param data 求值器数据
1815
+ * @param type 事件值类型
1816
+ * @returns 创建的求值器对象
1817
+ */
1818
+ bindEvaluator<T extends EventValueESType>(node: EventStartNode<T>, data: EvaluatorDataKPA2<T>, type: EventValueTypeOfType<T>, pos: string): void;
1819
+ /**
1820
+ * 使用KPA2数据创建一个缓动求值器。
1821
+ *
1822
+ * 对于普通缓动,这些求值器是从对应类构造器的静态对象池属性中获取的。
1823
+ * @param data 缓动求值器数据
1824
+ * @param type 事件值类型
1825
+ * @returns 创建的缓动求值器对象
1826
+ */
1827
+ createEasedEvaluator<T extends EventValueESType>(data: EasedEvaluatorDataOfType<T>, type: EventValueTypeOfType<T>): EasedEvaluatorOfType<T>;
1828
+ /**
1829
+ * 用一个缓动和事件类型获取一个缓动求值器
1830
+ * @param easing 缓动对象
1831
+ * @param type 事件值类型
1832
+ * @param interpreteAs 文本解释方式
1833
+ * @returns 对应类型的缓动求值器
1834
+ */
1835
+ getEasedEvaluator<T extends EventValueESType>(easing: Easing, type: EventValueTypeOfType<T>, interpreteAs?: InterpreteAs): EasedEvaluatorOfType<T>;
1836
+ /**
1837
+ * 根据JavaScript表达式创建表达式求值器
1838
+ * @param data 表达式求值器数据
1839
+ * @returns 创建的表达式求值器对象
1840
+ */
1841
+ createExpressionEvaluator<T extends EventValueESType>(data: ExpressionEvaluatorDataKPA2): ExpressionEvaluator<T>;
1842
+ bindMacroEvaluator(node: EventStartNode<EventValueESType>, data: MacroEvaluatorDataKPA2, pos: string): void;
1843
+ /**
1844
+ * 使用KPA2JSON创建一对面对面节点
1845
+ * @param data 事件数据
1846
+ * @param type 事件值类型
1847
+ * @returns 包含起始节点和结束节点的元组
1848
+ */
1849
+ createEventFromData<VT extends EventValueESType>(data: EventDataKPA2<VT>, type: EventValueTypeOfType<VT>, pos: string): [EventStartNode<VT>, EventEndNode<VT>];
1850
+ createFinalEventStartNodeFromData<VT extends EventValueESType>(data: FinalEventStartNodeDataKPA2<VT>, type: EventValueTypeOfType<VT>, pos: string): EventStartNode<VT>;
1851
+ bindTimeMacro(node: EventStartNode<any>, macroData: MacroData, pos: string): any;
1852
+ bindValueMacro(node: EventNode<any>, macroData: MacroData, pos: string): any;
1853
+ linkMacro(node: EventNode<EventValueESType>, linkData: MacroLink, pos: string): any;
1854
+ }
1855
+ /**
1856
+ * 表示一组判定线的容器
1857
+ *
1858
+ * 用于组织和管理具有相同属性或用途的判定线集合
1859
+ */
1860
+ export class JudgeLineGroup {
1861
+ name: string;
1862
+ /**
1863
+ * 该只读标记只是为了防止外部修改,内部可以修改
1864
+ *
1865
+ * 属于该组的判定线列表,按ID升序排列
1866
+ */
1867
+ judgeLines: readonly JudgeLine[];
1868
+ /**
1869
+ * 创建一个新的判定线组
1870
+ * @param name 组名称
1871
+ */
1872
+ constructor(name: string);
1873
+ /**
1874
+ * 向判定线组添加一条判定线,并且保证其内部的判定线ID是升序排列的。
1875
+ * @param judgeLine 要添加的判定线
1876
+ * @returns
1877
+ */
1878
+ add(judgeLine: JudgeLine): void;
1879
+ /**
1880
+ * 从判定线组移除一条判定线
1881
+ * @param judgeLine 要移除的判定线
1882
+ */
1883
+ remove(judgeLine: JudgeLine): void;
1884
+ /**
1885
+ * 检查该判定线组是否为默认组
1886
+ * @returns 该判定线组是否为默认判定线组,默认的判断标准是:名称为 "Default"(大小写不敏感)
1887
+ */
1888
+ isDefault(): boolean;
1889
+ }
1890
+ }
1891
+ declare module "event" {
1892
+ import type { Chart } from "chart";
1893
+ import { EventType, type TimeT, type EventDataKPA, type RGB, type EventDataRPELike, InterpreteAs, type ValueTypeOfEventType, type EventDataKPA2, type EventNodeSequenceDataKPA2, type EventValueESType, FinalEventStartNodeDataKPA2 } from "chartTypes";
1894
+ import { TemplateEasingLib, Easing } from "easing";
1895
+ import { type Evaluator } from "evaluator";
1896
+ import { JumpArray } from "jumparray";
1897
+ import { type TimeCalculator } from "bpm";
1898
+ import { NodeType } from "util";
1899
+ import { JudgeLine } from "judgeline";
1900
+ import { EventMacro, EventMacroTime, EventMacroValue, Macroable } from "macro";
1901
+ export class EventNodeLike<T extends NodeType, VT extends EventValueESType = number> {
1902
+ type: T;
1903
+ /** 后一个事件节点 */
1904
+ next: [EventStartNode<VT>, null, ENOrTail<VT>][T] | null;
1905
+ /** 前一个事件节点 */
1906
+ previous: [null, EventStartNode<VT>, ENOrHead<VT>][T] | null;
1907
+ parentSeq: EventNodeSequence<VT>;
1908
+ constructor(type: T);
1909
+ }
1910
+ export type ENOrTail<VT extends EventValueESType = number> = EventNode<VT> | EventNodeLike<NodeType.TAIL, VT>;
1911
+ export type ENOrHead<VT extends EventValueESType = number> = EventNode<VT> | EventNodeLike<NodeType.HEAD, VT>;
1912
+ export type AnyEN<VT extends EventValueESType = number> = EventNode<VT> | EventNodeLike<NodeType.HEAD, VT> | EventNodeLike<NodeType.TAIL, VT>;
1913
+ export type EvSoE<VT extends EventValueESType = number> = EventEndNode<VT> | EventStartNode<VT>;
1914
+ /**
1915
+ * 事件节点基类
1916
+ * event node.
1917
+ * 用于代表事件的开始和结束。(EventStartNode表开始,EventEndNode表结束)
1918
+ * Used to represent the starts (EventStartNode) and ends (EventEndNode) of events.
1919
+ * 事件指的是判定线在某个时间段上的状态变化。
1920
+ * Events is the changing of judge line's state in a certain time.
1921
+ * 五种事件类型:移动X,移动Y,旋转,透明度,速度。
1922
+ * 5 basic types of events: moveX, moveY, rotate, alpha, speed.
1923
+ * 事件节点没有类型,类型由它所属的序列决定。
1924
+ * Type is not event nodes' property; it is the property of EventNodeSequence.
1925
+ * Events' type is determined by which sequence it belongs to.
1926
+ * 与RPE不同的是,KPA使用两个节点来表示一个事件,而不是一个对象。
1927
+ * Different from that in RPE, KPA uses two nodes rather than one object to represent an event.
1928
+ */
1929
+ export abstract class EventNode<VT extends EventValueESType = number> extends EventNodeLike<NodeType.MIDDLE, VT> {
1930
+ time: TimeT;
1931
+ value: VT;
1932
+ evaluator: Evaluator<VT>;
1933
+ macroValue: EventMacroValue;
1934
+ linkedMacros: Set<EventMacro<Macroable>>;
1935
+ constructor(time: TimeT, value: VT);
1936
+ clone(offset: TimeT): EventStartNode<VT> | EventEndNode<VT>;
1937
+ /**
1938
+ *
1939
+ * @param data
1940
+ * @param templates
1941
+ * @returns
1942
+ * @deprecated
1943
+ */
1944
+ static getEasing(data: EventDataKPA<EventValueESType>, templates: TemplateEasingLib, notSegmented?: boolean): Easing;
1945
+ /**
1946
+ *
1947
+ * @param data
1948
+ * @param templates
1949
+ * @returns
1950
+ * @deprecated
1951
+ */
1952
+ static getEvaluator<VT extends EventValueESType>(data: EventDataKPA<VT>, templates: TemplateEasingLib, interpreteAs?: InterpreteAs): Evaluator<VT>;
1953
+ /**
1954
+ * constructs EventStartNode and EventEndNode from EventDataRPE
1955
+ * @param data
1956
+ * @param templates
1957
+ * @returns
1958
+ */
1959
+ static fromEvent<VT extends RGB | number>(data: EventDataRPELike<VT>, chart: Chart): [EventStartNode<VT>, EventEndNode<VT>];
1960
+ static fromTextEvent(data: EventDataRPELike<string>, templates: TemplateEasingLib): [EventStartNode<string>, EventEndNode<string>];
1961
+ static connect<VT extends EventValueESType>(node1: EventStartNode<VT>, node2: EventEndNode<VT> | EventNodeLike<NodeType.TAIL, VT>): void;
1962
+ static connect<VT extends EventValueESType>(node1: EventEndNode<VT> | EventNodeLike<NodeType.HEAD, VT>, node2: EventStartNode<VT>): void;
1963
+ /**
1964
+ *
1965
+ * @param endNode
1966
+ * @param startNode
1967
+ * @returns 应该在何范围内更新跳数组
1968
+ */
1969
+ static removeNodePair<VT extends EventValueESType>(endNode: EventEndNode<VT>, startNode: EventStartNode<VT>): [EventStartNode<VT> | EventNodeLike<NodeType.HEAD, VT>, EventStartNode<VT> | EventNodeLike<NodeType.TAIL, VT>];
1970
+ static insert<VT extends EventValueESType>(node: EventStartNode<VT>, tarPrev: EventStartNode<VT>): [EventNodeLike<NodeType.HEAD, VT> | EventStartNode<VT>, EventStartNode<VT> | EventNodeLike<NodeType.TAIL, VT>];
1971
+ /**
1972
+ *
1973
+ * @param node
1974
+ * @returns the next node if it is a tailer, otherwise the next start node
1975
+ */
1976
+ static nextStartOfStart<VT extends EventValueESType>(node: EventStartNode<VT>): EventStartNode<VT> | EventNodeLike<NodeType.TAIL, VT>;
1977
+ /**
1978
+ *
1979
+ * @param node
1980
+ * @returns itself if node is a tailer, otherwise the next start node
1981
+ */
1982
+ static nextStartOfEnd<VT extends EventValueESType>(node: EventEndNode<VT> | EventNodeLike<NodeType.TAIL, VT>): EventNodeLike<NodeType.TAIL, VT> | EventStartNode<VT>;
1983
+ static previousStartOfStart<VT extends EventValueESType>(node: EventStartNode<VT>): EventStartNode<VT> | EventNodeLike<NodeType.HEAD, VT>;
1984
+ /**
1985
+ * It does not return the start node which form an event with it.
1986
+ * @param node
1987
+ * @returns
1988
+ */
1989
+ static secondPreviousStartOfEnd<VT extends EventValueESType>(node: EventEndNode<VT>): EventStartNode<VT> | EventNodeLike<NodeType.HEAD, VT>;
1990
+ static nextStartInJumpArray<VT extends EventValueESType>(node: EventStartNode<VT>): EventStartNode<VT> | EventNodeLike<NodeType.TAIL, VT>;
1991
+ /**
1992
+ * 获得一对背靠背的节点。不适用于第一个StartNode
1993
+ * @param node
1994
+ * @returns
1995
+ */
1996
+ static getEndStart<VT extends EventValueESType>(node: EventStartNode<VT> | EventEndNode<VT>): [EventEndNode<VT>, EventStartNode<VT>];
1997
+ static getStartEnd<VT extends EventValueESType>(node: EventStartNode<VT> | EventEndNode<VT>): [EventStartNode<VT>, EventEndNode<VT>];
1998
+ static setToNewOrderedArray<VT extends EventValueESType>(dest: TimeT, set: Set<EventStartNode<VT>>): [EventStartNode<VT>[], EventStartNode<VT>[]];
1999
+ static belongToSequence(nodes: Set<EventStartNode>, sequence: EventNodeSequence): boolean;
2000
+ /**
2001
+ * 检验这些节点对是不是连续的
2002
+ * 如果不是不能封装为模板缓动
2003
+ * @param nodes 有序开始节点数组,必须都是带结束节点的(背靠背)(第一个除外)
2004
+ * @returns
2005
+ */
2006
+ static isContinuous(nodes: EventStartNode[]): boolean;
2007
+ }
2008
+ export class EventStartNode<VT extends EventValueESType = number> extends EventNode<VT> {
2009
+ next: EventEndNode<VT> | EventNodeLike<NodeType.TAIL, VT>;
2010
+ previous: EventEndNode<VT> | EventNodeLike<NodeType.HEAD, VT>;
2011
+ macroTime: EventMacroTime | null;
2012
+ /**
2013
+ * 对于速度事件,从0时刻到此节点的总积分
2014
+ */
2015
+ floorPosition: number;
2016
+ constructor(time: TimeT, value: VT);
2017
+ parentSeq: EventNodeSequence<VT>;
2018
+ /**
2019
+ * 因为是RPE和KPA共用的方法所以easingType可以为字符串
2020
+ * @returns
2021
+ */
2022
+ dump(): EventDataKPA2<VT>;
2023
+ dumpAsFinal(): FinalEventStartNodeDataKPA2<VT>;
2024
+ getValueAt(beats: number): VT;
2025
+ getSpeedValueAt(this: EventStartNode<number>, beats: number): number;
2026
+ /**
2027
+ * 积分获取位移
2028
+ */
2029
+ getLocalFloorPos(this: EventStartNode<number>, beats: number, timeCalculator: TimeCalculator): number;
2030
+ getFullLocalFloorPos(this: EventStartNode<number>, timeCalculator: TimeCalculator): number;
2031
+ isFirstStart(): boolean;
2032
+ isLastStart(): boolean;
2033
+ isSpeed(): boolean;
2034
+ clone(offset?: TimeT): EventStartNode<VT>;
2035
+ clonePair(offset: TimeT): EventStartNode<VT>;
2036
+ }
2037
+ export type NonLastStartNode<VT extends EventValueESType> = EventStartNode<VT> & {
2038
+ next: EventEndNode<VT>;
2039
+ };
2040
+ export class EventEndNode<VT extends EventValueESType = number> extends EventNode<VT> {
2041
+ next: EventStartNode<VT>;
2042
+ previous: EventStartNode<VT>;
2043
+ get parentSeq(): EventNodeSequence<VT>;
2044
+ set parentSeq(_parent: EventNodeSequence<VT>);
2045
+ constructor(time: TimeT, value: VT);
2046
+ getValueAt(beats: number): VT;
2047
+ clone(offset?: TimeT): EventEndNode<VT>;
2048
+ }
2049
+ export enum Monotonicity {
2050
+ increasing = 0,
2051
+ decreasing = 1,
2052
+ swinging = 2
2053
+ }
2054
+ /**
2055
+ * 为一个链表结构。会有一个数组进行快跳。
2056
+ * is the list of event nodes, but not purely start nodes.
2057
+ *
2058
+ * 结构如下:Header -> (StartNode -> [EndNode) -> (StartNode] -> [EndNode) -> ... -> StartNode] -> Tailer.
2059
+ * The structure is like this: Header -> (StartNode -> [EndNode) -> (StartNode] -> [EndNode) -> ... -> StartNode] -> Tailer.
2060
+ *
2061
+ * 用括号标出的两个节点是一个事件,用方括号标出的两个节点是同一时间点的节点。
2062
+ * The each 2 nodes marked by parentheses is an event; the each 2 nodes marked by brackets have the same time.
2063
+ *
2064
+ * 注意尾节点之前的节点不是一个结束节点,而是一个开始节点,其缓动无效。
2065
+ * Note that the node before the tailer is not an end node, but a start node whose easing is meaningless.
2066
+ *
2067
+ * 就是说最后一个节点后取值,显然会取得这个节点的值,与缓动无关。
2068
+ * (i. e. the value after the last event node is its value, not subject to easing, obviously.)
2069
+ *
2070
+ * 如果尾之前的节点是一个结束节点,那么取值会返回undefined,这是不期望的。
2071
+ * If so, the value after that will be undefined, which is not expected.
2072
+ * ("so" refers to the assumption that the node before the tailer is an end node)
2073
+ *
2074
+ * 和NNList和NNNList一样,有跳数组以加速随机读取。
2075
+ * Like NNList and NNNList, it has a jump array to speed up random reading.
2076
+ *
2077
+ * 插入或删除节点时,需要更新跳数组。
2078
+ * Remember to update the jump array when inserting or deleting nodes.
2079
+ */
2080
+ export class EventNodeSequence<VT extends EventValueESType = number> {
2081
+ type: EventType;
2082
+ effectiveBeats: number;
2083
+ /**
2084
+ * @deprecated 谱面属性未实装,以后有必要的时候会添加为其赋值的逻辑
2085
+ */
2086
+ chart: Chart;
2087
+ /** 标识名默认遵循`#${lineid}.${layerid}.${typename}`格式
2088
+ * id follows the format `#${lineid}.${layerid}.${typename}` by default
2089
+ */
2090
+ id: string;
2091
+ head: EventNodeLike<NodeType.HEAD, VT>;
2092
+ tail: EventNodeLike<NodeType.TAIL, VT>;
2093
+ jump?: JumpArray<AnyEN<VT>>;
2094
+ listLength: number;
2095
+ /** 一定是二的幂,避免浮点误差 */
2096
+ jumpAverageBeats: number;
2097
+ /**
2098
+ * 用于速度事件优化
2099
+ */
2100
+ monotonicity: Monotonicity;
2101
+ /**
2102
+ * 使用了该序列的判定线,当前仅用于速度事件对fp的更新
2103
+ */
2104
+ consumerLines: Set<JudgeLine>;
2105
+ constructor(type: EventType, effectiveBeats: number);
2106
+ /**
2107
+ * 获取指定事件类型的事件默认值。
2108
+ * Get the default value of the specified event type.
2109
+ *
2110
+ * 对于文字事件,默认值为空字符串。
2111
+ *
2112
+ * 对于缩放事件,默认值为1.0。
2113
+ *
2114
+ * 对于颜色事件,默认值为黑色([0, 0, 0])。
2115
+ *
2116
+ * 对于速度事件,默认值为10(1200像素/秒)。
2117
+ *
2118
+ * 对于一般数值事件,默认值为0。
2119
+ */
2120
+ static getDefaultValueFromEventType(type: EventType): number[] | 0 | "" | 1 | 10;
2121
+ /**
2122
+ * 从RPEJSON数据创建一个事件序列。
2123
+ *
2124
+ * KPAJSON 1.x也会使用此接口
2125
+ * @param type 事件类型(不是数值类型,也不是数值ECMAScript类型)
2126
+ * @param data 事件数据的数组
2127
+ * @param chart
2128
+ * @param pos 当前事件序列应当具有什么ID(用于报错和警告,外部调用可以写空字符串)
2129
+ * @param endValue 结束值(RPEJSON没有)
2130
+ * @returns
2131
+ */
2132
+ static fromRPEJSON<T extends EventType, VT extends EventValueESType = number>(type: T, data: EventDataRPELike<VT>[], chart: Chart, pos: string, endValue?: number): EventNodeSequence<VT>;
2133
+ /**
2134
+ * 从KPAJSON 2.x数据创建一个事件序列。
2135
+ * @param type 事件类型(不是数值类型,也不是数值ECMAScript类型)
2136
+ * @param data 事件数据的数组
2137
+ * @param chart
2138
+ * @param pos 当前事件序列应当具有什么ID(用于报错和警告)
2139
+ * @param finalNodeData 最终节点数据
2140
+ * @returns
2141
+ */
2142
+ static fromKPA2JSON<T extends EventType, VT extends EventValueESType = number>(type: T, data: EventDataKPA2<VT>[], chart: Chart, pos: string, finalNodeData: FinalEventStartNodeDataKPA2<VT>): EventNodeSequence<VT>;
2143
+ /**
2144
+ * 生成一个新的事件节点序列,仅拥有一个节点。
2145
+ * 需要分配ID!!!!!!
2146
+ * @param type
2147
+ * @param effectiveBeats
2148
+ * @returns
2149
+ */
2150
+ static newSeq<T extends EventType>(type: T, effectiveBeats: number): EventNodeSequence<ValueTypeOfEventType<T>>;
2151
+ initJump(): void;
2152
+ updateJump(from: ENOrHead<VT>, to: ENOrTail<VT>): void;
2153
+ getNodeAt(beats: number, usePrev?: boolean): EventStartNode<VT>;
2154
+ getValueAt(beats: number, usePrev?: boolean): VT;
2155
+ getFloorPositionAt(this: EventNodeSequence<number>, beats: number, timeCalculator: TimeCalculator): number;
2156
+ /**
2157
+ * 更新某个速度节点之后的FP
2158
+ *
2159
+ * 注意,修改节点并不会影响它的FP,而是它后面的所有节点的FP,节点存的是它所在位置的FP,节点在事件头部
2160
+ * @param this
2161
+ * @param node
2162
+ * @param tc
2163
+ *
2164
+ * @example
2165
+ * node.value += 1;
2166
+ * (node.parentSequence as SpeedENS).updateFloorPositionAfter(node, tc);
2167
+ */
2168
+ updateFloorPositionAfter(this: SpeedENS, node: EventStartNode, tc: TimeCalculator): void;
2169
+ dump(): EventNodeSequenceDataKPA2<VT>;
2170
+ getNodesFromOneAndRangeRight(node: EventStartNode<VT>, rangeRight: TimeT): EventStartNode<VT>[];
2171
+ getNodesAfterOne(node: EventStartNode<VT>): EventStartNode<VT>[];
2172
+ /**
2173
+ * 将多个事件层上的数值性事件节点序列合为一个
2174
+ *
2175
+ * 目前仅用于速度序列,因为就他是线性的(
2176
+ *
2177
+ * 会创建新序列
2178
+ * @param sequences
2179
+ * @throws {KPAError<ERROR_IDS.NEEDS_AT_LEAST_ONE_ENS>}
2180
+ */
2181
+ static mergeSequences(sequences: EventNodeSequence[]): EventNodeSequence<number>;
2182
+ }
2183
+ export type SpeedENS = EventNodeSequence<number> & {
2184
+ type: EventType.speed;
2185
+ };
2186
+ }
2187
+ declare module "env" {
2188
+ import { type TimeT, type EventValueType } from "chartTypes";
2189
+ export enum ERROR_IDS {
2190
+ UI_OCCUPIED = 272,
2191
+ SEQUENCE_NAME_OCCUPIED = 1552,
2192
+ SEQUENCE_NODE_TIME_OCCUPIED = 1553,
2193
+ INVALID_EVENT_NODE_SEQUENCE_TYPE = 1568,
2194
+ EVENT_NODE_TIME_NOT_INCREMENTAL = 1569,
2195
+ PARENT_SEQUENCE_NOT_FOUND = 1585,
2196
+ NEEDS_AT_LEAST_ONE_ENS = 1586,
2197
+ SEQUENCE_TYPE_NOT_CONSISTENT = 1587,
2198
+ EXPECTED_TYPED_ENS = 1600,
2199
+ CANNOT_SUBSTITUTE_EXPRESSION_EVALUATOR = 2096,
2200
+ CANNOT_INSERT_BEFORE_HEAD = 2097,
2201
+ CANNOT_GET_FULL_INTEGRAL_OF_FINAL_START_NODE = 2098,
2202
+ CANNOT_INTERPOLATE_TAILING_START_NODE = 2099,
2203
+ INVALID_EASING_ID = 2592,
2204
+ CANNOT_IMPLEMENT_TEMEAS_WITH_NON_EASING_ENS = 2593,
2205
+ CANNOT_IMPLEMENT_TEMEAS_WITH_NON_NUMERIC_ENS = 2594,
2206
+ UNIMPLEMENTED_TEMPLATE_EASING = 2595,
2207
+ MUST_INTERPOLATE_TEMPLATE_EASING = 2608,
2208
+ NODES_NOT_CONTINUOUS = 2609,
2209
+ NODES_NOT_BELONG_TO_SAME_SEQUENCE = 2610,
2210
+ NODES_HAS_ZERO_DELTA = 2611,
2211
+ CANNOT_DIVIDE_EXPRESSION_EVALUATOR = 2352,
2212
+ MISSING_MACRO_EVALUATOR_KEY = 2336,
2213
+ MACRO_EVALUATOR_NOT_FOUND = 2337,
2214
+ INVALID_NOTE_PROP_TYPE = 2880,
2215
+ INVALID_TIME_TUPLE = 3104,
2216
+ TIME_MACRO_NOT_FOUND = 3360,
2217
+ VALUE_MACRO_NOT_FOUND = 3361,
2218
+ UNKNOWN_MACRO_EXPRESSION = 3362,
2219
+ JAVASCRIPT_SYNTAX_ERROR = 3363,
2220
+ PROTO_PRESENT_IN_NONPARAMETRIC = 3376,
2221
+ PARAMETRIC_MACRO_REQUIRES_PROTO_KEY = 3364,
2222
+ MACRO_NOT_PARAMETRIC = 3365
2223
+ }
2224
+ export const ERRORS: {
2225
+ UI_OCCUPIED: (name: string) => string;
2226
+ SEQUENCE_NAME_OCCUPIED: (name: string) => string;
2227
+ SEQUENCE_NODE_TIME_OCCUPIED: (time: TimeT, id: string) => string;
2228
+ INVALID_EVENT_NODE_SEQUENCE_TYPE: (type: any) => string;
2229
+ EXPECTED_TYPED_ENS: (typeStr: keyof typeof EventValueType, id: string, value: unknown) => string;
2230
+ EVENT_NODE_TIME_NOT_INCREMENTAL: (pos: string) => string;
2231
+ PARENT_SEQUENCE_NOT_FOUND: (nodeTime: TimeT) => string;
2232
+ NEEDS_AT_LEAST_ONE_ENS: () => string;
2233
+ SEQUENCE_TYPE_NOT_CONSISTENT: (typeStr: string, but: string) => string;
2234
+ CANNOT_SUBSTITUTE_EXPRESSION_EVALUATOR: () => string;
2235
+ CANNOT_INSERT_BEFORE_HEAD: () => string;
2236
+ CANNOT_GET_FULL_INTEGRAL_OF_FINAL_START_NODE: () => string;
2237
+ CANNOT_INTERPOLATE_TAILING_START_NODE: () => string;
2238
+ INVALID_EASING_ID: (id: string) => string;
2239
+ CANNOT_IMPLEMENT_TEMEAS_WITH_NON_EASING_ENS: (temEasName: string) => string;
2240
+ CANNOT_IMPLEMENT_TEMEAS_WITH_NON_NUMERIC_ENS: (temEasName: string) => string;
2241
+ MUST_INTERPOLATE_TEMPLATE_EASING: () => string;
2242
+ NODES_NOT_CONTINUOUS: () => string;
2243
+ NODES_NOT_BELONG_TO_SAME_SEQUENCE: () => string;
2244
+ NODES_HAS_ZERO_DELTA: () => string;
2245
+ INVALID_NOTE_PROP_TYPE: (prop: string, value: any, type: any) => string;
2246
+ INVALID_TIME_TUPLE: (tuple: any) => string;
2247
+ CANNOT_DIVIDE_EXPRESSION_EVALUATOR: (id: string) => string;
2248
+ UNIMPLEMENTED_TEMPLATE_EASING: (temEasName: string) => string;
2249
+ MISSING_MACRO_EVALUATOR_KEY: (pos: string) => string;
2250
+ MACRO_EVALUATOR_NOT_FOUND: (evaluatorId: string, pos: string) => string;
2251
+ TIME_MACRO_NOT_FOUND: (macroId: string, pos: string) => string;
2252
+ VALUE_MACRO_NOT_FOUND: (macroId: string, pos: string) => string;
2253
+ UNKNOWN_MACRO_EXPRESSION: (expression: string, macroId: string) => string;
2254
+ PROTO_PRESENT_IN_NONPARAMETRIC: (macroId: string) => string;
2255
+ JAVASCRIPT_SYNTAX_ERROR: (error: Error, macroId: string) => string;
2256
+ PARAMETRIC_MACRO_REQUIRES_PROTO_KEY: (pos: any) => string;
2257
+ MACRO_NOT_PARAMETRIC: (macroId: string, pos: any) => string;
2258
+ };
2259
+ export class KPAError<ET extends ERROR_IDS> extends Error {
2260
+ id: ET;
2261
+ constructor(message: string, id: ET);
2262
+ /**
2263
+ * 对于解析谱面等场景,有时可能需要找出全部的错误,不宜直接抛出错误中断代码执行
2264
+ *
2265
+ * 此时可以调用该方法,该方法会输出错误并把它保存到KPAError的一个`buffer`静态属性下。
2266
+ */
2267
+ warn(): void;
2268
+ static buffer: KPAError<ERROR_IDS>[];
2269
+ static flush(): void;
2270
+ }
2271
+ export const err: { [key in keyof typeof ERRORS]: (...args: Parameters<(typeof ERRORS)[key]>) => KPAError<(typeof ERROR_IDS)[key]>; };
2272
+ const _default: {
2273
+ DEFAULT_TEMPLATE_LENGTH: number;
2274
+ BEZIER_INTERPOLATION_DENSITY: number;
2275
+ NNLIST_Y_OFFSET_HALF_SPAN: number;
2276
+ JUMPARRAY_MIN_LENGTH: number;
2277
+ JUMPARRAY_MAX_LENGTH: number;
2278
+ JUMPARRAY_MINOR_SCALE_COUNT: number;
2279
+ ERROR_IDS: typeof ERROR_IDS;
2280
+ err: {
2281
+ UI_OCCUPIED: (name: string) => KPAError<ERROR_IDS.UI_OCCUPIED>;
2282
+ SEQUENCE_NAME_OCCUPIED: (name: string) => KPAError<ERROR_IDS.SEQUENCE_NAME_OCCUPIED>;
2283
+ SEQUENCE_NODE_TIME_OCCUPIED: (time: TimeT, id: string) => KPAError<ERROR_IDS.SEQUENCE_NODE_TIME_OCCUPIED>;
2284
+ INVALID_EVENT_NODE_SEQUENCE_TYPE: (type: any) => KPAError<ERROR_IDS.INVALID_EVENT_NODE_SEQUENCE_TYPE>;
2285
+ EXPECTED_TYPED_ENS: (typeStr: "numeric" | "color" | "text", id: string, value: unknown) => KPAError<ERROR_IDS.EXPECTED_TYPED_ENS>;
2286
+ EVENT_NODE_TIME_NOT_INCREMENTAL: (pos: string) => KPAError<ERROR_IDS.EVENT_NODE_TIME_NOT_INCREMENTAL>;
2287
+ PARENT_SEQUENCE_NOT_FOUND: (nodeTime: TimeT) => KPAError<ERROR_IDS.PARENT_SEQUENCE_NOT_FOUND>;
2288
+ NEEDS_AT_LEAST_ONE_ENS: () => KPAError<ERROR_IDS.NEEDS_AT_LEAST_ONE_ENS>;
2289
+ SEQUENCE_TYPE_NOT_CONSISTENT: (typeStr: string, but: string) => KPAError<ERROR_IDS.SEQUENCE_TYPE_NOT_CONSISTENT>;
2290
+ CANNOT_SUBSTITUTE_EXPRESSION_EVALUATOR: () => KPAError<ERROR_IDS.CANNOT_SUBSTITUTE_EXPRESSION_EVALUATOR>;
2291
+ CANNOT_INSERT_BEFORE_HEAD: () => KPAError<ERROR_IDS.CANNOT_INSERT_BEFORE_HEAD>;
2292
+ CANNOT_GET_FULL_INTEGRAL_OF_FINAL_START_NODE: () => KPAError<ERROR_IDS.CANNOT_GET_FULL_INTEGRAL_OF_FINAL_START_NODE>;
2293
+ CANNOT_INTERPOLATE_TAILING_START_NODE: () => KPAError<ERROR_IDS.CANNOT_INTERPOLATE_TAILING_START_NODE>;
2294
+ INVALID_EASING_ID: (id: string) => KPAError<ERROR_IDS.INVALID_EASING_ID>;
2295
+ CANNOT_IMPLEMENT_TEMEAS_WITH_NON_EASING_ENS: (temEasName: string) => KPAError<ERROR_IDS.CANNOT_IMPLEMENT_TEMEAS_WITH_NON_EASING_ENS>;
2296
+ CANNOT_IMPLEMENT_TEMEAS_WITH_NON_NUMERIC_ENS: (temEasName: string) => KPAError<ERROR_IDS.CANNOT_IMPLEMENT_TEMEAS_WITH_NON_NUMERIC_ENS>;
2297
+ MUST_INTERPOLATE_TEMPLATE_EASING: () => KPAError<ERROR_IDS.MUST_INTERPOLATE_TEMPLATE_EASING>;
2298
+ NODES_NOT_CONTINUOUS: () => KPAError<ERROR_IDS.NODES_NOT_CONTINUOUS>;
2299
+ NODES_NOT_BELONG_TO_SAME_SEQUENCE: () => KPAError<ERROR_IDS.NODES_NOT_BELONG_TO_SAME_SEQUENCE>;
2300
+ NODES_HAS_ZERO_DELTA: () => KPAError<ERROR_IDS.NODES_HAS_ZERO_DELTA>;
2301
+ INVALID_NOTE_PROP_TYPE: (prop: string, value: any, type: any) => KPAError<ERROR_IDS.INVALID_NOTE_PROP_TYPE>;
2302
+ INVALID_TIME_TUPLE: (tuple: any) => KPAError<ERROR_IDS.INVALID_TIME_TUPLE>;
2303
+ CANNOT_DIVIDE_EXPRESSION_EVALUATOR: (id: string) => KPAError<ERROR_IDS.CANNOT_DIVIDE_EXPRESSION_EVALUATOR>;
2304
+ UNIMPLEMENTED_TEMPLATE_EASING: (temEasName: string) => KPAError<ERROR_IDS.UNIMPLEMENTED_TEMPLATE_EASING>;
2305
+ MISSING_MACRO_EVALUATOR_KEY: (pos: string) => KPAError<ERROR_IDS.MISSING_MACRO_EVALUATOR_KEY>;
2306
+ MACRO_EVALUATOR_NOT_FOUND: (evaluatorId: string, pos: string) => KPAError<ERROR_IDS.MACRO_EVALUATOR_NOT_FOUND>;
2307
+ TIME_MACRO_NOT_FOUND: (macroId: string, pos: string) => KPAError<ERROR_IDS.TIME_MACRO_NOT_FOUND>;
2308
+ VALUE_MACRO_NOT_FOUND: (macroId: string, pos: string) => KPAError<ERROR_IDS.VALUE_MACRO_NOT_FOUND>;
2309
+ UNKNOWN_MACRO_EXPRESSION: (expression: string, macroId: string) => KPAError<ERROR_IDS.UNKNOWN_MACRO_EXPRESSION>;
2310
+ PROTO_PRESENT_IN_NONPARAMETRIC: (macroId: string) => KPAError<ERROR_IDS.PROTO_PRESENT_IN_NONPARAMETRIC>;
2311
+ JAVASCRIPT_SYNTAX_ERROR: (error: Error, macroId: string) => KPAError<ERROR_IDS.JAVASCRIPT_SYNTAX_ERROR>;
2312
+ PARAMETRIC_MACRO_REQUIRES_PROTO_KEY: (pos: any) => KPAError<ERROR_IDS.PARAMETRIC_MACRO_REQUIRES_PROTO_KEY>;
2313
+ MACRO_NOT_PARAMETRIC: (macroId: string, pos: any) => KPAError<ERROR_IDS.MACRO_NOT_PARAMETRIC>;
2314
+ };
2315
+ freeze(): void;
2316
+ };
2317
+ export default _default;
2318
+ }
2319
+ declare module "time" {
2320
+ import { TimeT } from "chartTypes";
2321
+ /**
2322
+ * @static @final
2323
+ */
2324
+ export default class TC {
2325
+ private constructor();
2326
+ static toBeats(beaT: TimeT): number;
2327
+ static getDelta(beaT1: TimeT, beaT2: TimeT): number;
2328
+ /**
2329
+ * @returns beaT1 == beaT2
2330
+ */
2331
+ static eq(beaT1: TimeT, beaT2: TimeT): boolean;
2332
+ /** @returns beaT1 > beaT2 */
2333
+ static gt(beaT1: TimeT, beaT2: TimeT): boolean;
2334
+ /** @returns beaT1 < beaT2 */
2335
+ static lt(beaT1: TimeT, beaT2: TimeT): boolean;
2336
+ /** @returns beaT1 != beaT2 */
2337
+ static ne(beaT1: TimeT, beaT2: TimeT): boolean;
2338
+ /**
2339
+ * @returns beaT1 + beaT2
2340
+ */
2341
+ static add(beaT1: TimeT, beaT2: TimeT): TimeT;
2342
+ /**
2343
+ * @returns beaT1 - beaT2
2344
+ */
2345
+ static sub(beaT1: TimeT, beaT2: TimeT): TimeT;
2346
+ /**
2347
+ * @returns Ratio(a 2-number tuple) = beaT1 / beaT2
2348
+ */
2349
+ static div(beaT1: TimeT, beaT2: TimeT): [number, number];
2350
+ /**
2351
+ * @returns beaT1 * [numerator, denominator]
2352
+ */
2353
+ static mul(beaT: TimeT, ratio: [number, number]): TimeT;
2354
+ /**
2355
+ * 原地规范化时间元组,但仍然返回这个元组,方便使用
2356
+ * validate TimeT in place
2357
+ * @param beaT
2358
+ */
2359
+ static validateIp(beaT: TimeT): TimeT;
2360
+ /**
2361
+ * 相加并约简
2362
+ */
2363
+ static vadd(beaT1: TimeT, beaT2: TimeT): TimeT;
2364
+ /**
2365
+ * 相减并约简
2366
+ */
2367
+ static vsub(beaT1: TimeT, beaT2: TimeT): TimeT;
2368
+ /**
2369
+ * 相乘并约简
2370
+ */
2371
+ static vmul(beaT: TimeT, ratio: [number, number]): TimeT;
2372
+ static gcd(a: number, b: number): number;
2373
+ }
2374
+ }
2375
+ declare module "operation/basic" {
2376
+ import { Chart } from "chart";
2377
+ export type OpEventType = "do" | "undo" | "redo" | "error" | "needsupdate" | "maxcombochanged" | "noundo" | "noredo" | "firstmodified" | "needsreflow";
2378
+ interface DirectlyInstaciableEventMap {
2379
+ "noundo": OpEvent;
2380
+ "noredo": OpEvent;
2381
+ "firstmodified": OpEvent;
2382
+ }
2383
+ type CheckFinalOverrides<T> = {
2384
+ [K in keyof T]: K extends keyof OpEventMap ? T[K] extends OpEventMap[K] ? T[K] : never : T[K];
2385
+ };
2386
+ interface OpEventMap extends CheckFinalOverrides<DirectlyInstaciableEventMap> {
2387
+ "error": OperationErrorEvent;
2388
+ "maxcombochanged": MaxComboChangeEvent;
2389
+ "undo": OperationEvent;
2390
+ "redo": OperationEvent;
2391
+ "do": OperationEvent;
2392
+ "needsupdate": OperationEvent;
2393
+ "needsreflow": NeedsReflowEvent;
2394
+ }
2395
+ class OpEvent extends Event {
2396
+ protected constructor(type: OpEventType);
2397
+ /**
2398
+ * 如果这个类型没有对应子类应该用这个
2399
+ */
2400
+ static create(type: keyof DirectlyInstaciableEventMap): OpEvent;
2401
+ }
2402
+ export class NeedsReflowEvent extends OpEvent {
2403
+ condition: number;
2404
+ constructor(condition: number);
2405
+ }
2406
+ export class OperationEvent extends OpEvent {
2407
+ operation: Operation;
2408
+ constructor(t: "do" | "undo" | "redo" | "error" | "needsupdate", operation: Operation);
2409
+ }
2410
+ export class OperationErrorEvent extends OperationEvent {
2411
+ error: Error;
2412
+ constructor(operation: Operation, error: Error);
2413
+ }
2414
+ export class MaxComboChangeEvent extends OpEvent {
2415
+ comboDelta: number;
2416
+ constructor(comboDelta: number);
2417
+ }
2418
+ export class OperationList extends EventTarget {
2419
+ readonly chart: Chart;
2420
+ operations: Operation[];
2421
+ undoneOperations: Operation[];
2422
+ constructor(chart: Chart);
2423
+ undo(): void;
2424
+ redo(): void;
2425
+ do(operation: Operation): void;
2426
+ processFlags(operation: Operation): void;
2427
+ clear(): void;
2428
+ addEventListener<T extends OpEventType>(type: T, listener: (event: OpEventMap[T]) => void, options?: boolean | AddEventListenerOptions): void;
2429
+ }
2430
+ export abstract class Operation {
2431
+ ineffective: boolean;
2432
+ updatesEditor: boolean;
2433
+ reflows: number;
2434
+ /**
2435
+ * 此操作对谱面总物量产生了多少影响,正增负减。
2436
+ *
2437
+ * 如果操作自身无法评估,应返回NaN,导致全谱重新数清物量
2438
+ */
2439
+ comboDelta: number;
2440
+ constructor();
2441
+ abstract do(chart: Chart): void;
2442
+ abstract undo(chart: Chart): void;
2443
+ rewrite(op: this, chart: Chart): boolean;
2444
+ toString(): string;
2445
+ static lazy<C extends new (...args: any[]) => any = typeof this>(this: C, ...args: ConstructorParameters<C>): LazyOperation<C>;
2446
+ }
2447
+ /**
2448
+ * 懒操作,实例化的时候不记录任何数据,do的时候才执行真正实例化
2449
+ * 防止连续的操作中状态改变导致的错误
2450
+ */
2451
+ export class LazyOperation<C extends new (...args: any[]) => any> extends Operation {
2452
+ operationClass: C;
2453
+ args: ConstructorParameters<C>;
2454
+ operation: InstanceType<C> | null;
2455
+ constructor(operationClass: C, ...args: ConstructorParameters<C>);
2456
+ do(chart: Chart): void;
2457
+ undo(chart: Chart): void;
2458
+ }
2459
+ /**
2460
+ * C语言借来的概念
2461
+ *
2462
+ * 一个不确定类型的子操作
2463
+ *
2464
+ * 注意这个操作不懒,会在构造时就实例化子操作
2465
+ */
2466
+ export class UnionOperation<T extends Operation> extends Operation {
2467
+ operation: T;
2468
+ constructor(matcher: () => T);
2469
+ do(chart?: Chart): void;
2470
+ undo(chart?: Chart): void;
2471
+ }
2472
+ export class ComplexOperation<T extends Operation[]> extends Operation {
2473
+ subOperations: T;
2474
+ length: number;
2475
+ constructor(...sub: T);
2476
+ do(chart?: Chart): void;
2477
+ undo(chart?: Chart): void;
2478
+ }
2479
+ }
2480
+ declare module "operation/event" {
2481
+ import type { Chart } from "chart";
2482
+ import { type EventValueESType, type TimeT } from "chartTypes";
2483
+ import { TemplateEasing, TemplateEasingLib } from "easing";
2484
+ import { Evaluator } from "evaluator";
2485
+ import { EventEndNode, EventStartNode, EventNodeSequence, EventNode, NonLastStartNode, EventNodeLike } from "event";
2486
+ import { NodeType } from "util";
2487
+ import { ComplexOperation, LazyOperation, Operation, UnionOperation } from "operation/basic";
2488
+ /**
2489
+ * 移除一对节点(背靠背)
2490
+ */
2491
+ export class EventNodePairRemoveOperation extends Operation {
2492
+ updatesEditor: boolean;
2493
+ endNode: EventEndNode<any>;
2494
+ startNode: EventStartNode<any>;
2495
+ sequence: EventNodeSequence<any>;
2496
+ originalPrev: EventStartNode<any>;
2497
+ updatesFP: boolean;
2498
+ constructor(node: EventStartNode<any>, updatesFP?: boolean);
2499
+ do(chart: Chart): void;
2500
+ undo(chart: Chart): void;
2501
+ }
2502
+ /**
2503
+ * 将一对孤立的节点对插入到一个开始节点之后的操作。
2504
+ *
2505
+ * 如果这个节点对的时刻与节点对的时刻相同,那么抛出错误。
2506
+ */
2507
+ export class EventNodePairInsertOperation<VT extends EventValueESType> extends Operation {
2508
+ updatesEditor: boolean;
2509
+ node: EventStartNode<VT>;
2510
+ tarPrev: EventStartNode<VT>;
2511
+ sequence: EventNodeSequence<VT>;
2512
+ originalValue: VT;
2513
+ value: VT;
2514
+ updatesFP: boolean;
2515
+ /**
2516
+ *
2517
+ * @param node 要插入的节点 the node to insert
2518
+ * @param targetPrevious 要插在谁后面 The node to insert after, accessed through `EventNodeSequence.getNodeAt(TC.toBeats(node))`
2519
+ */
2520
+ constructor(node: EventStartNode<VT>, targetPrevious: EventStartNode<VT>, updatesFP?: boolean);
2521
+ do(): void;
2522
+ undo(): void;
2523
+ }
2524
+ export class EventNodePairInsertOrOverwriteOperation<VT extends EventValueESType> extends UnionOperation<LazyOperation<typeof EventNodePairInsertOperation<VT>> | EventNodeValueChangeOperation<VT>> {
2525
+ overlapping: boolean;
2526
+ constructor(node: EventStartNode<VT>, targetPrevious: EventStartNode<VT>, updatesFP?: boolean);
2527
+ }
2528
+ export class EventNodeValueChangeOperation<VT extends EventValueESType> extends Operation {
2529
+ updatesEditor: boolean;
2530
+ node: EventNode<VT>;
2531
+ value: VT;
2532
+ originalValue: VT;
2533
+ constructor(node: EventNode<VT>, val: VT);
2534
+ do(chart: Chart): void;
2535
+ undo(chart: Chart): void;
2536
+ updateSpeedENS(chart: Chart): void;
2537
+ rewrite(operation: EventNodeValueChangeOperation<VT>, chart: Chart): boolean;
2538
+ }
2539
+ export class EventNodeTimeChangeOperation extends Operation {
2540
+ updatesEditor: boolean;
2541
+ sequence: EventNodeSequence;
2542
+ /**
2543
+ * 这里两个node不是面对面,而是背靠背
2544
+ * i. e. EndNode -> StartNode
2545
+ */
2546
+ startNode: EventStartNode<any>;
2547
+ endNode: EventEndNode<any>;
2548
+ value: TimeT;
2549
+ originalValue: TimeT;
2550
+ originalPrevious: EventStartNode<any>;
2551
+ newPrevious: EventStartNode<any>;
2552
+ constructor(node: EventStartNode<any> | EventEndNode<any>, val: TimeT);
2553
+ do(): void;
2554
+ undo(): void;
2555
+ }
2556
+ export class EventNodeEvaluatorChangeOperation<VT extends EventValueESType> extends Operation {
2557
+ node: EventStartNode<VT>;
2558
+ value: Evaluator<VT>;
2559
+ updatesEditor: boolean;
2560
+ originalValue: Evaluator<VT>;
2561
+ constructor(node: EventStartNode<VT>, value: Evaluator<VT>);
2562
+ do(): void;
2563
+ undo(): void;
2564
+ }
2565
+ export class EventInterpolationOperation<VT extends EventValueESType> extends ComplexOperation<LazyOperation<typeof EventNodePairInsertOperation>[]> {
2566
+ eventStartNode: EventStartNode<VT>;
2567
+ step: TimeT;
2568
+ updatesEditor: boolean;
2569
+ constructor(eventStartNode: EventStartNode<VT>, step: TimeT);
2570
+ }
2571
+ export class EventSubstituteOperation<VT extends EventValueESType> extends ComplexOperation<[...LazyOperation<typeof EventNodePairInsertOperation>[], EventNodeEvaluatorChangeOperation<VT>, EventNodeValueChangeOperation<VT>]> {
2572
+ node: NonLastStartNode<VT>;
2573
+ updatesEditor: boolean;
2574
+ /**
2575
+ *
2576
+ * @param node
2577
+ * @throws {KPAError<ERROR_IDS.CANNOT_SUBSTITUTE_EXPRESSION_EVALUATOR>}
2578
+ * @throws {KPAError<ERROR_IDS.MUST_INTERPOLATE_TEMPLATE_EASING>}
2579
+ */
2580
+ constructor(node: NonLastStartNode<VT>);
2581
+ }
2582
+ export class EncapsuleOperation extends ComplexOperation<[MultiNodeDeleteOperation, EventNodeEvaluatorChangeOperation<number>, EventNodeValueChangeOperation<number>]> {
2583
+ updatesEditor: boolean;
2584
+ constructor(nodes: EventStartNode<number>[], easing: TemplateEasing);
2585
+ /**
2586
+ * 将一些来自sourceSequence的节点打包为一个用于模板缓动的事件序列
2587
+ * 然后把sourceSequence中的源节点集合替换为单个使用了该模板的事件
2588
+ * @param sourceSequence
2589
+ * @param sourceNodes
2590
+ */
2591
+ static encapsule(templateEasingLib: TemplateEasingLib, sourceSequence: EventNodeSequence, sourceNodes: Set<EventStartNode>, name: string): EncapsuleOperation;
2592
+ }
2593
+ /**
2594
+ * 批量添加节点对
2595
+ *
2596
+ * 节点对需要有序的,且不能有重叠
2597
+
2598
+ */
2599
+ export class MultiNodeAddOperation<VT extends EventValueESType> extends ComplexOperation<EventNodePairInsertOrOverwriteOperation<VT>[]> {
2600
+ nodes: EventStartNode<VT>[];
2601
+ seq: EventNodeSequence<VT>;
2602
+ updatesEditor: boolean;
2603
+ updatesFP: boolean;
2604
+ constructor(nodes: EventStartNode<VT>[], seq: EventNodeSequence<VT>);
2605
+ do(chart: Chart): void;
2606
+ undo(chart: Chart): void;
2607
+ }
2608
+ export class MultiNodeDeleteOperation extends ComplexOperation<LazyOperation<typeof EventNodePairRemoveOperation>[]> {
2609
+ updatesEditor: boolean;
2610
+ constructor(nodes: EventStartNode<any>[]);
2611
+ }
2612
+ export class EventNodeSequenceRenameOperation extends Operation {
2613
+ sequence: EventNodeSequence<EventValueESType>;
2614
+ newName: string;
2615
+ updatesEditor: boolean;
2616
+ originalName: string;
2617
+ constructor(sequence: EventNodeSequence<EventValueESType>, newName: string);
2618
+ do(chart: Chart): void;
2619
+ undo(chart: Chart): void;
2620
+ }
2621
+ type TimeRange = [TimeT, TimeT];
2622
+ /**
2623
+ * 所有节点事件加上一个值。
2624
+ * 此操作假定了节点被偏移时不会产生“碰撞”。
2625
+ * 节点要有序
2626
+ * @private
2627
+ */
2628
+ export class MultiNodeOffsetOperation extends Operation {
2629
+ nodes: readonly EventStartNode<any>[];
2630
+ offset: TimeT;
2631
+ constructor(nodes: readonly EventStartNode<any>[], offset: TimeT);
2632
+ do(): void;
2633
+ undo(): void;
2634
+ }
2635
+ export class ENSTimeRangeDeleteOperation extends ComplexOperation<[MultiNodeDeleteOperation, MultiNodeOffsetOperation]> {
2636
+ eventNodeSequence: EventNodeSequence<any>;
2637
+ timeRange: TimeRange;
2638
+ beforeToStart: EventStartNode<any> | EventNodeLike<NodeType.HEAD, any>;
2639
+ constructor(eventNodeSequence: EventNodeSequence<any>, timeRange: TimeRange);
2640
+ do(): void;
2641
+ undo(): void;
2642
+ }
2643
+ export class ENSAddBlankOperation extends MultiNodeOffsetOperation {
2644
+ ens: EventNodeSequence<any>;
2645
+ updatesEditor: boolean;
2646
+ constructor(ens: EventNodeSequence<any>, pos: TimeT, length: TimeT);
2647
+ do(): void;
2648
+ undo(): void;
2649
+ }
2650
+ }
2651
+ declare module "operation/note" {
2652
+ import { Operation, ComplexOperation, UnionOperation } from "operation/basic";
2653
+ import { TimeT } from "chartTypes";
2654
+ import { JudgeLine } from "judgeline";
2655
+ import { Note, NoteNode, NNList } from "note";
2656
+ type NotePropNamePhiZone = "judgeSize" | "tint" | "tintHitEffects";
2657
+ export type NotePropName = "speed" | "type" | "positionX" | "startTime" | "endTime" | "alpha" | "size" | "visibleBeats" | "yOffset" | "above" | "isFake" | NotePropNamePhiZone;
2658
+ /**
2659
+ * 修改 Note 的任意属性值
2660
+ * @example
2661
+ * // 修改 note 的 above 属性
2662
+ * operationList.do(new NotePropChangeOperation(note, "above", true));
2663
+ * // 修改 note 的 speed 属性
2664
+ * // 一般不会这样做,因为修改 note 的 speed 需要把note换到另一个序列(`NNList`)中
2665
+ * // 应使用NoteSpeedChangeOperation。YOffset也是同样的道理。
2666
+ * operationList.do(new NotePropChangeOperation(note, "speed", 1.5));
2667
+ * @template T - 要修改的属性名,必须是 `NotePropName` 类型
2668
+ */
2669
+ export class NotePropChangeOperation<T extends NotePropName> extends Operation {
2670
+ field: T;
2671
+ note: Note;
2672
+ previousValue: Note[T];
2673
+ value: Note[T];
2674
+ updatesEditor: boolean;
2675
+ constructor(note: Note, field: T, value: Note[T]);
2676
+ do(): void;
2677
+ undo(): void;
2678
+ rewrite(operation: NotePropChangeOperation<T>): boolean;
2679
+ }
2680
+ export class NoteRemoveOperation extends Operation {
2681
+ noteNode: NoteNode;
2682
+ note: Note;
2683
+ isHold: boolean;
2684
+ constructor(note: Note);
2685
+ do(): void;
2686
+ undo(): void;
2687
+ }
2688
+ /**
2689
+ * 删除一个 note(语义层面的删除)
2690
+ * 从语义上删除 Note 要用这个操作
2691
+ * 注意:实际移除由 NoteRemoveOperation 完成,NoteDeleteOperation 仅负责更新编辑器
2692
+ * @example
2693
+ * operationList.do(new NoteDeleteOperation(note));
2694
+ */
2695
+ export class NoteDeleteOperation extends NoteRemoveOperation {
2696
+ updatesEditor: boolean;
2697
+ }
2698
+ export class MultiNoteDeleteOperation extends ComplexOperation<NoteDeleteOperation[]> {
2699
+ updatesEditor: boolean;
2700
+ constructor(notes: Set<Note> | Note[]);
2701
+ }
2702
+ export class NoteAddOperation extends Operation {
2703
+ noteNode: NoteNode;
2704
+ note: Note;
2705
+ isHold: boolean;
2706
+ updatesEditor: boolean;
2707
+ constructor(note: Note, node: NoteNode);
2708
+ do(): void;
2709
+ undo(): void;
2710
+ }
2711
+ export class MultiNoteAddOperation extends ComplexOperation<NoteAddOperation[]> {
2712
+ updatesEditor: boolean;
2713
+ constructor(notes: Set<Note> | Note[], judgeLine: JudgeLine);
2714
+ }
2715
+ /**
2716
+ * 修改 Note 的时间位置(不直接修改 startTime,而是将 Note 移动到另一个 NoteNode)
2717
+ * 注意:不能直接修改 note.startTime 属性,需要通过 getNodeOf 获取目标时间的 NoteNode
2718
+ * @example
2719
+ * // 将 note 移动到目标时间位置
2720
+ * const targetNode = note.parentNode.parentSeq.getNodeOf(targetTime);
2721
+ * operationList.do(new NoteTimeChangeOperation(note, targetNode));
2722
+ */
2723
+ export class NoteTimeChangeOperation extends ComplexOperation<[
2724
+ NoteRemoveOperation,
2725
+ NotePropChangeOperation<"startTime">,
2726
+ NoteAddOperation,
2727
+ UnionOperation<NotePropChangeOperation<"endTime"> | null>
2728
+ ]> {
2729
+ note: Note;
2730
+ comboDelta: number;
2731
+ constructor(note: Note, noteNode: NoteNode);
2732
+ rewrite(operation: NoteTimeChangeOperation): boolean;
2733
+ }
2734
+ /**
2735
+ * 修改 hold 音符的 endTime 属性
2736
+ * 直接修改 hold 音符的 endTime(不同于 NoteTimeChangeOperation)
2737
+ * @example
2738
+ * // 修改 hold 音符的结束时间
2739
+ * operationList.do(new HoldEndTimeChangeOperation(note, newEndTime));
2740
+ */
2741
+ export class HoldEndTimeChangeOperation extends NotePropChangeOperation<"endTime"> {
2742
+ constructor(note: Note, value: TimeT);
2743
+ do(): void;
2744
+ undo(): void;
2745
+ rewrite(operation: HoldEndTimeChangeOperation): boolean;
2746
+ }
2747
+ /**
2748
+ * 修改 Note 的 speed 属性
2749
+ * 需要传入 JudgeLine 参数,因为 speed 变化会影响 note 在何 NNList 中
2750
+ * @example
2751
+ * // 修改 note 的 speed 值
2752
+ * operationList.do(new NoteSpeedChangeOperation(note, 2.0, judgeLine));
2753
+ */
2754
+ export class NoteSpeedChangeOperation extends ComplexOperation<[NotePropChangeOperation<"speed">, NoteRemoveOperation, NoteAddOperation]> {
2755
+ note: Note;
2756
+ updatesEditor: boolean;
2757
+ constructor(note: Note, value: number, line: JudgeLine);
2758
+ }
2759
+ export class NoteYOffsetChangeOperation extends ComplexOperation<[NotePropChangeOperation<"yOffset">, NoteRemoveOperation, NoteAddOperation]> {
2760
+ note: Note;
2761
+ updatesEditor: boolean;
2762
+ constructor(note: Note, value: number, line: JudgeLine);
2763
+ }
2764
+ /**
2765
+ * 修改 Note 的 type 属性(音符类型)
2766
+ * 在 tap/drag/flick/hold 之间切换,切换到/从 hold 时需要重新定位 NoteNode
2767
+ * @example
2768
+ * // 将 note 改为 hold 类型
2769
+ * operationList.do(new NoteTypeChangeOperation(note, NoteType.hold));
2770
+ */
2771
+ export class NoteTypeChangeOperation extends ComplexOperation<[NotePropChangeOperation<"type">, NoteRemoveOperation, NoteAddOperation] | [NotePropChangeOperation<"type">]> {
2772
+ note: Note;
2773
+ value: number;
2774
+ constructor(note: Note, value: number);
2775
+ }
2776
+ /**
2777
+ * @author Zes Minkey Young
2778
+ */
2779
+ export class MultiNoteOffsetOperation extends Operation {
2780
+ nnList: NNList;
2781
+ notes: readonly Note[];
2782
+ offset: TimeT;
2783
+ constructor(nnList: NNList, notes: readonly Note[], offset: TimeT);
2784
+ do(): void;
2785
+ undo(): void;
2786
+ private static lazy;
2787
+ }
2788
+ type TimeRange = [TimeT, TimeT];
2789
+ export class NNListTimeRangeDeleteOperation extends ComplexOperation<[MultiNoteDeleteOperation, MultiNoteOffsetOperation]> {
2790
+ nnList: NNList;
2791
+ timeRange: TimeRange;
2792
+ updatesJump: boolean;
2793
+ constructor(nnList: NNList, timeRange: TimeRange, updatesJump?: boolean);
2794
+ do(): void;
2795
+ undo(): void;
2796
+ }
2797
+ export class NNListAddBlankOperation extends MultiNoteOffsetOperation {
2798
+ updatesEditor: boolean;
2799
+ constructor(nnList: NNList, pos: TimeT, length: TimeT);
2800
+ }
2801
+ }
2802
+ declare module "operation/line" {
2803
+ import { Chart, JudgeLineGroup, BasicEventName, UIName } from "chart";
2804
+ import { ExtendedEventTypeName, RGB } from "chartTypes";
2805
+ import { EventNodeSequence } from "event";
2806
+ import { JudgeLine } from "judgeline";
2807
+ import { ComplexOperation, LazyOperation, Operation } from "operation/basic";
2808
+ import { EventNodeSequenceRenameOperation } from "operation/event";
2809
+ enum JudgeLinesEditorLayoutType {
2810
+ ordered = 1,
2811
+ tree = 2,
2812
+ grouped = 4
2813
+ }
2814
+ export class JudgeLineInheritanceChangeOperation extends Operation {
2815
+ chart: Chart;
2816
+ judgeLine: JudgeLine;
2817
+ value: JudgeLine | null;
2818
+ originalValue: JudgeLine | null;
2819
+ updatesEditor: boolean;
2820
+ static REFLOWS: JudgeLinesEditorLayoutType;
2821
+ reflows: JudgeLinesEditorLayoutType;
2822
+ constructor(chart: Chart, judgeLine: JudgeLine, value: JudgeLine | null);
2823
+ do(): void;
2824
+ undo(): void;
2825
+ }
2826
+ export class JudgeLineRenameOperation extends Operation {
2827
+ judgeLine: JudgeLine;
2828
+ value: string;
2829
+ updatesEditor: boolean;
2830
+ originalValue: string;
2831
+ constructor(judgeLine: JudgeLine, value: string);
2832
+ do(): void;
2833
+ undo(): void;
2834
+ }
2835
+ type JudgeLinePropName = "name" | "rotatesWithFather" | "anchor" | "texture" | "cover" | "zOrder";
2836
+ export class JudgeLinePropChangeOperation<T extends JudgeLinePropName> extends Operation {
2837
+ judgeLine: JudgeLine;
2838
+ field: T;
2839
+ value: JudgeLine[T];
2840
+ updatesEditor: boolean;
2841
+ originalValue: JudgeLine[T];
2842
+ constructor(judgeLine: JudgeLine, field: T, value: JudgeLine[T]);
2843
+ do(): void;
2844
+ undo(): void;
2845
+ }
2846
+ export class JudgeLineRegroupOperation extends Operation {
2847
+ judgeLine: JudgeLine;
2848
+ value: JudgeLineGroup;
2849
+ updatesEditor: boolean;
2850
+ reflows: JudgeLinesEditorLayoutType;
2851
+ originalValue: JudgeLineGroup;
2852
+ constructor(judgeLine: JudgeLine, value: JudgeLineGroup);
2853
+ do(): void;
2854
+ undo(): void;
2855
+ }
2856
+ export class JudgeLineCreateOperation extends Operation {
2857
+ chart: Chart;
2858
+ judgeLine: JudgeLine;
2859
+ reflows: number;
2860
+ constructor(chart: Chart, judgeLine: JudgeLine);
2861
+ do(): void;
2862
+ undo(): void;
2863
+ }
2864
+ class JudgeLineRemoveOperation extends Operation {
2865
+ chart: Chart;
2866
+ judgeLine: JudgeLine;
2867
+ readonly originalGroup: JudgeLineGroup;
2868
+ constructor(chart: Chart, judgeLine: JudgeLine);
2869
+ do(): void;
2870
+ undo(): void;
2871
+ }
2872
+ export class JudgeLineDeleteOperation extends ComplexOperation<[JudgeLineRemoveOperation, ...LazyOperation<typeof JudgeLineIdChangeOperation>[]]> {
2873
+ chart: Chart;
2874
+ judgeLine: JudgeLine;
2875
+ constructor(chart: Chart, judgeLine: JudgeLine);
2876
+ }
2877
+ export class JudgeLineENSChangeOperation extends Operation {
2878
+ judgeLine: JudgeLine;
2879
+ layerId: number;
2880
+ typeStr: BasicEventName;
2881
+ value: EventNodeSequence;
2882
+ originalValue: EventNodeSequence;
2883
+ constructor(judgeLine: JudgeLine, layerId: number, typeStr: BasicEventName, value: EventNodeSequence);
2884
+ do(): void;
2885
+ undo(): void;
2886
+ }
2887
+ export type ENSOfTypeName<T extends ExtendedEventTypeName> = {
2888
+ "scaleX": EventNodeSequence<number>;
2889
+ "scaleY": EventNodeSequence<number>;
2890
+ "text": EventNodeSequence<string>;
2891
+ "color": EventNodeSequence<RGB>;
2892
+ }[T];
2893
+ export class JudgeLineExtendENSChangeOperation<T extends ExtendedEventTypeName> extends Operation {
2894
+ judgeLine: JudgeLine;
2895
+ typeStr: T;
2896
+ value: ENSOfTypeName<T> | null;
2897
+ originalValue: ENSOfTypeName<T>;
2898
+ constructor(judgeLine: JudgeLine, typeStr: T, value: ENSOfTypeName<T> | null);
2899
+ do(): void;
2900
+ undo(): void;
2901
+ }
2902
+ export class UIAttachOperation extends Operation {
2903
+ chart: Chart;
2904
+ judgeLine: JudgeLine;
2905
+ ui: UIName;
2906
+ updatesEditor: boolean;
2907
+ constructor(chart: Chart, judgeLine: JudgeLine, ui: UIName);
2908
+ do(): void;
2909
+ undo(): void;
2910
+ }
2911
+ export class UIDetachOperation extends Operation {
2912
+ chart: Chart;
2913
+ ui: UIName;
2914
+ updatesEditor: boolean;
2915
+ judgeLine: JudgeLine;
2916
+ constructor(chart: Chart, ui: UIName);
2917
+ do(): void;
2918
+ undo(): void;
2919
+ }
2920
+ export class JudgeLineDetachAllUIOperation extends Operation {
2921
+ chart: Chart;
2922
+ judgeLine: JudgeLine;
2923
+ updatesEditor: boolean;
2924
+ uinames: UIName[];
2925
+ constructor(chart: Chart, judgeLine: JudgeLine);
2926
+ do(): void;
2927
+ undo(): void;
2928
+ }
2929
+ /**
2930
+ * 修改判定线id
2931
+ * 不需要自己传入ID
2932
+ */
2933
+ export class JudgeLineIdChangeOperation extends ComplexOperation<EventNodeSequenceRenameOperation[]> {
2934
+ originalValue: number;
2935
+ value: number;
2936
+ judgeLine: JudgeLine;
2937
+ /**
2938
+ *
2939
+ * @param judgeLine
2940
+ * @param renamesENS 是否对事件序列进行重命名
2941
+ */
2942
+ constructor(judgeLine: JudgeLine, renamesENS?: boolean);
2943
+ do(chart: Chart): void;
2944
+ undo(chart: Chart): void;
2945
+ }
2946
+ }
2947
+ declare module "operation/chart" {
2948
+ import { Chart } from "chart";
2949
+ import { Operation } from "operation/basic";
2950
+ export type ChartPropName = "name" | "level" | "composer" | "illustrator" | "charter" | "offset";
2951
+ export class ChartPropChangeOperation<T extends ChartPropName> extends Operation {
2952
+ chart: Chart;
2953
+ field: T;
2954
+ value: Chart[T];
2955
+ originalValue: Chart[T];
2956
+ constructor(chart: Chart, field: T, value: Chart[T]);
2957
+ do(): void;
2958
+ undo(): void;
2959
+ }
2960
+ }
2961
+ declare module "operation/macro" {
2962
+ import { Operation, ComplexOperation } from "operation/basic";
2963
+ import { EventMacroTime } from "macro";
2964
+ import { EventStartNode } from "event";
2965
+ import { Chart } from "chart";
2966
+ import { EventNodeTimeChangeOperation } from "operation/event";
2967
+ export class EventNodeMacroTimeReevaluateOperation extends EventNodeTimeChangeOperation {
2968
+ constructor(node: EventStartNode<any>, chart: Chart);
2969
+ }
2970
+ export class MacroTimeAssignOperation extends Operation {
2971
+ macroTime: EventMacroTime;
2972
+ node: EventStartNode<any>;
2973
+ originalMacroTime: EventMacroTime;
2974
+ private timeChangeOperation;
2975
+ constructor(macroTime: EventMacroTime, node: EventStartNode<any>);
2976
+ do(chart: Chart): void;
2977
+ undo(_chart: Chart): void;
2978
+ }
2979
+ export class MacroTimeDeassginOperation extends Operation {
2980
+ node: EventStartNode<any>;
2981
+ originalMacroTime: EventMacroTime;
2982
+ constructor(node: EventStartNode<any>);
2983
+ do(chart: Chart): void;
2984
+ undo(_chart: Chart): void;
2985
+ }
2986
+ export class MacroTimeReevaluateOperation extends ComplexOperation<EventNodeMacroTimeReevaluateOperation[]> {
2987
+ constructor(macroTime: EventMacroTime, chart: Chart);
2988
+ }
2989
+ }
2990
+ declare module "operation/index" {
2991
+ export * from "operation/basic";
2992
+ export * from "operation/event";
2993
+ export * from "operation/note";
2994
+ export * from "operation/line";
2995
+ export * from "operation/chart";
2996
+ export * from "operation/macro";
2997
+ }
2998
+ declare module "rpeChartCompiler" {
2999
+ import type { Chart } from "chart";
3000
+ import { type TimeT, type ChartDataRPE, type JudgeLineDataRPE, type EventDataRPELike, type NoteDataRPE, type EventValueESType } from "chartTypes";
3001
+ import { type EasedEvaluatorOfType } from "evaluator";
3002
+ import { EventEndNode, EventNodeSequence, EventStartNode } from "event";
3003
+ import type { JudgeLine } from "judgeline";
3004
+ import type { NNList, HNList } from "note";
3005
+ /**
3006
+ * 全生命周期只会编译一次,想多次就再构造一个
3007
+ */
3008
+ export class RPEChartCompiler {
3009
+ chart: Chart;
3010
+ sequenceMap: Map<EventNodeSequence<any>, EventNodeSequence<any>>;
3011
+ interpolationStep: TimeT;
3012
+ constructor(chart: Chart);
3013
+ compileChart(): ChartDataRPE;
3014
+ compileJudgeLine(judgeLine: JudgeLine): JudgeLineDataRPE;
3015
+ compileEasedEvent<VT extends EventValueESType>(snode: EventStartNode<VT> & {
3016
+ evaluator: EasedEvaluatorOfType<VT>;
3017
+ }, getValue: (node: EventStartNode<VT> | EventEndNode<VT>) => VT): EventDataRPELike<VT>;
3018
+ dumpEventNodeSequence<VT extends EventValueESType>(sequence: EventNodeSequence<VT>): EventDataRPELike<VT>[];
3019
+ compileNNLists(nnLists: NNList[], hnLists: HNList[]): NoteDataRPE[];
3020
+ /**
3021
+ * 倒序转换为数组
3022
+ * @param nnList
3023
+ * @returns 一个按照时间降序排列的数组
3024
+ */
3025
+ nnListToArray(nnList: NNList): NoteDataRPE[];
3026
+ /**
3027
+ * 将当前序列中所有通过模板缓动引用了其他序列的事件直接展开为被引用的序列内容
3028
+ * transform all events that reference other sequences by template easing
3029
+ * into the content of the referenced sequence
3030
+ *
3031
+ * 有点类似于MediaWiki的`{{subst:templateName}}`
3032
+ * @returns
3033
+ */
3034
+ substitute<VT extends EventValueESType>(seq: EventNodeSequence<VT>): EventNodeSequence<VT>;
3035
+ }
3036
+ }
3037
+ declare module "index" {
3038
+ export * from "time";
3039
+ export { default as TC } from "time";
3040
+ export * from "chartTypes";
3041
+ export * from "easing";
3042
+ export * from "evaluator";
3043
+ export * from "macro";
3044
+ export * from "event";
3045
+ export * from "note";
3046
+ export * from "judgeline";
3047
+ export * from "bpm";
3048
+ export * from "util";
3049
+ export * from "chart";
3050
+ export * from "jumparray";
3051
+ export * as Op from "operation/index";
3052
+ export * from "version";
3053
+ export { default as Environment, KPAError } from "env";
3054
+ export { RPEChartCompiler } from "rpeChartCompiler";
3055
+ }