kipphi 2.1.1 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bpm.ts +9 -0
- package/env.ts +40 -1
- package/event.ts +38 -19
- package/index.d.ts +22 -4
- package/index.js +86 -20
- package/operation/basic.ts +12 -1
- package/operation/event.ts +10 -2
- package/operation/note.ts +5 -0
- package/package.json +23 -23
- package/version.ts +1 -1
- package/line.ts +0 -246
package/bpm.ts
CHANGED
|
@@ -63,6 +63,15 @@ export class BPMEndNode extends EventEndNode {
|
|
|
63
63
|
override previous: BPMStartNode;
|
|
64
64
|
/** 下一个BPM起始节点 */
|
|
65
65
|
override next: BPMStartNode;
|
|
66
|
+
|
|
67
|
+
// @ts-expect-error 强加一个getter
|
|
68
|
+
get value(): number {
|
|
69
|
+
return this.previous.value;
|
|
70
|
+
}
|
|
71
|
+
set value(value: number) {
|
|
72
|
+
if (!this.previous) { return; }
|
|
73
|
+
this.previous.value = value;
|
|
74
|
+
}
|
|
66
75
|
|
|
67
76
|
/**
|
|
68
77
|
* 创建一个新的BPM结束节点
|
package/env.ts
CHANGED
|
@@ -53,6 +53,7 @@ export enum ERROR_IDS {
|
|
|
53
53
|
SEQUENCE_NODE_TIME_OCCUPIED = ENS | OCCPIED | 1,
|
|
54
54
|
INVALID_EVENT_NODE_SEQUENCE_TYPE = ENS | INVALID_DATA | 0,
|
|
55
55
|
EVENT_NODE_TIME_NOT_INCREMENTAL = ENS | INVALID_DATA | 1,
|
|
56
|
+
EVENT_NODE_NOT_DENSE = ENS | INVALID_DATA | 2,
|
|
56
57
|
PARENT_SEQUENCE_NOT_FOUND = ENS | INVALID_USAGE | 1,
|
|
57
58
|
NEEDS_AT_LEAST_ONE_ENS = ENS | INVALID_USAGE | 2,
|
|
58
59
|
SEQUENCE_TYPE_NOT_CONSISTENT = ENS | INVALID_USAGE | 3,
|
|
@@ -80,6 +81,7 @@ export enum ERROR_IDS {
|
|
|
80
81
|
|
|
81
82
|
|
|
82
83
|
INVALID_NOTE_PROP_TYPE = NOTE | INVALID_TYPE | 0,
|
|
84
|
+
HOLD_HAS_NO_DURATION = NOTE | INVALID_DATA | 0,
|
|
83
85
|
|
|
84
86
|
|
|
85
87
|
INVALID_TIME_TUPLE = TC | INVALID_DATA | 0,
|
|
@@ -175,9 +177,39 @@ export const ERRORS = {
|
|
|
175
177
|
`Parametric Macro requires key. At ${pos}`,
|
|
176
178
|
MACRO_NOT_PARAMETRIC: (macroId: string, pos) =>
|
|
177
179
|
`Macro '${macroId}' is not parametric. At ${pos}`,
|
|
180
|
+
EVENT_NODE_NOT_DENSE: (pos: string) =>
|
|
181
|
+
`EventNode is not dense. At ${pos}`,
|
|
182
|
+
HOLD_HAS_NO_DURATION: () =>
|
|
183
|
+
`Hold should have a duration.`,
|
|
178
184
|
} satisfies Record<keyof typeof ERROR_IDS, (...args: any[]) => string>
|
|
179
185
|
|
|
186
|
+
type EnumKeys<E extends Record<string, string | number>> = E[keyof E];
|
|
187
|
+
|
|
188
|
+
// 工具类型:检查 T 的键是否恰好等于枚举的值集合
|
|
189
|
+
type AssertExactEnumKeys<T, E extends Record<string, string | number>> =
|
|
190
|
+
// 1. 收集 T 的键(作为字符串字面量类型)
|
|
191
|
+
(keyof T) extends (keyof E) // 不能有多余键
|
|
192
|
+
? (keyof E) extends (keyof T) // 不能缺键
|
|
193
|
+
? T // 通过检查
|
|
194
|
+
: { error: any/*error: "Interface is missing some enum keys"*/ }
|
|
195
|
+
: { error: "Interface has extra keys not in enum" };
|
|
196
|
+
|
|
197
|
+
// 用类型别名做“编译期断言”
|
|
198
|
+
type _CheckMap = AssertExactEnumKeys<ErrorMap, typeof ERROR_IDS>;
|
|
199
|
+
interface _Error extends _CheckMap {
|
|
200
|
+
error: "";
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
interface ErrorMap extends Record<keyof typeof ERROR_IDS, Array<any>>{
|
|
205
|
+
EVENT_NODE_NOT_DENSE: [EventNode];
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
type ArgsOf<ET extends ERROR_IDS> = ET extends keyof ErrorMap ? ErrorMap[ET] : never;
|
|
209
|
+
|
|
180
210
|
export class KPAError<ET extends ERROR_IDS> extends Error {
|
|
211
|
+
fixed = false;
|
|
212
|
+
args: ArgsOf<ET> | [];
|
|
181
213
|
constructor(message: string, public id: ET) {
|
|
182
214
|
super(message);
|
|
183
215
|
}
|
|
@@ -186,8 +218,15 @@ export class KPAError<ET extends ERROR_IDS> extends Error {
|
|
|
186
218
|
*
|
|
187
219
|
* 此时可以调用该方法,该方法会输出错误并把它保存到KPAError的一个`buffer`静态属性下。
|
|
188
220
|
*/
|
|
189
|
-
warn() {
|
|
221
|
+
warn(...args: ArgsOf<ET> | []) {
|
|
190
222
|
console.warn(this.stack);
|
|
223
|
+
this.args = args;
|
|
224
|
+
KPAError.buffer.push(this);
|
|
225
|
+
}
|
|
226
|
+
fix(...args: ArgsOf<ET> | []) {
|
|
227
|
+
console.warn("[Auto Fixed]" + this.stack);
|
|
228
|
+
this.fixed = true;
|
|
229
|
+
this.args = args;
|
|
191
230
|
KPAError.buffer.push(this);
|
|
192
231
|
}
|
|
193
232
|
static buffer: KPAError<ERROR_IDS>[] = [];
|
package/event.ts
CHANGED
|
@@ -505,7 +505,7 @@ export class EventNodeSequence<VT extends EventValueESType = number> { // 泛型
|
|
|
505
505
|
return type === EventType.speed ? 10 :
|
|
506
506
|
type === EventType.scaleX || type === EventType.scaleY ? 1.0 :
|
|
507
507
|
type === EventType.text ? "" :
|
|
508
|
-
type === EventType.color ? [
|
|
508
|
+
type === EventType.color ? [255, 255, 255] :
|
|
509
509
|
0
|
|
510
510
|
}
|
|
511
511
|
/**
|
|
@@ -649,32 +649,28 @@ export class EventNodeSequence<VT extends EventValueESType = number> { // 泛型
|
|
|
649
649
|
err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}] and the previous`).warn()
|
|
650
650
|
}
|
|
651
651
|
if (!TC.lt(event.startTime, event.endTime)) {
|
|
652
|
-
|
|
652
|
+
if (TC.eq(event.startTime, event.endTime)) {
|
|
653
|
+
// 零长事件直接忽略,并认为已经修复
|
|
654
|
+
err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}]`).fix();
|
|
655
|
+
continue;
|
|
656
|
+
} else {
|
|
657
|
+
err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}]`).warn()
|
|
658
|
+
}
|
|
653
659
|
}
|
|
654
|
-
lastEndTime = event.endTime;
|
|
655
660
|
if (lastEnd.type === NodeType.HEAD) {
|
|
656
661
|
EventNode.connect(lastEnd, start)
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
EventNode.connect(lastEnd, start)
|
|
664
|
-
} else if (TC.eq(lastEnd.time, start.time)) {
|
|
665
|
-
const val = lastEnd.value;
|
|
666
|
-
const midStart = new EventStartNode(lastEnd.time, val);
|
|
667
|
-
const midEnd = new EventEndNode(start.time, val);
|
|
668
|
-
midStart.evaluator = lastEnd.previous.evaluator;
|
|
669
|
-
EventNode.connect(lastEnd, midStart);
|
|
670
|
-
EventNode.connect(midStart, midEnd);
|
|
662
|
+
} else if (TC.gt(event.startTime, lastEndTime)) {
|
|
663
|
+
err.EVENT_NODE_NOT_DENSE(`${pos}.events[${index}]`).warn();
|
|
664
|
+
const mid = new EventStartNode(lastEndTime, start.value);
|
|
665
|
+
const midEnd = new EventEndNode(event.startTime, end.value);
|
|
666
|
+
EventNode.connect(lastEnd, mid);
|
|
667
|
+
EventNode.connect(mid, midEnd);
|
|
671
668
|
EventNode.connect(midEnd, start);
|
|
672
|
-
listLength++;
|
|
673
669
|
} else {
|
|
674
|
-
|
|
675
670
|
EventNode.connect(lastEnd, start)
|
|
676
671
|
}
|
|
677
672
|
|
|
673
|
+
lastEndTime = event.endTime;
|
|
678
674
|
lastEnd = end;
|
|
679
675
|
}
|
|
680
676
|
const last = lastEnd;
|
|
@@ -948,6 +944,29 @@ export class EventNodeSequence<VT extends EventValueESType = number> { // 泛型
|
|
|
948
944
|
dest.initJump();
|
|
949
945
|
return dest;
|
|
950
946
|
}
|
|
947
|
+
checkErrors() {
|
|
948
|
+
let currentNode: EventStartNode<VT> = this.head.next;
|
|
949
|
+
if (TC.ne(currentNode.time, [0, 0, 1])) {
|
|
950
|
+
err.EVENT_NODE_NOT_DENSE(`${this.id}, ${currentNode.time}`).fix();
|
|
951
|
+
currentNode.time = [0, 0, 1];
|
|
952
|
+
}
|
|
953
|
+
const endNode = currentNode.next;
|
|
954
|
+
if (endNode.type === NodeType.TAIL) {
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
let lastEnd: EventEndNode<VT> = endNode;
|
|
959
|
+
while (true) {
|
|
960
|
+
const endNode = currentNode.next;
|
|
961
|
+
if (endNode.type === NodeType.TAIL) {
|
|
962
|
+
break;
|
|
963
|
+
}
|
|
964
|
+
if (TC.ne(lastEnd.time, currentNode.time)) {
|
|
965
|
+
err.EVENT_NODE_NOT_DENSE(`${this.id}, ${currentNode.time}`).warn();
|
|
966
|
+
}
|
|
967
|
+
currentNode = currentNode.next.next;
|
|
968
|
+
}
|
|
969
|
+
}
|
|
951
970
|
}
|
|
952
971
|
|
|
953
972
|
export type SpeedENS = EventNodeSequence<number> & { type: EventType.speed };
|
package/index.d.ts
CHANGED
|
@@ -533,7 +533,7 @@ declare module "chartTypes" {
|
|
|
533
533
|
export type ExtendedEventTypeName = "scaleX" | "scaleY" | "text" | "color";
|
|
534
534
|
}
|
|
535
535
|
declare module "version" {
|
|
536
|
-
export const VERSION =
|
|
536
|
+
export const VERSION = 212;
|
|
537
537
|
export const SCHEMA = "https://cdn.jsdelivr.net/npm/kipphi@2.1.0/chartType2.schema.json";
|
|
538
538
|
}
|
|
539
539
|
declare module "util" {
|
|
@@ -652,6 +652,8 @@ declare module "bpm" {
|
|
|
652
652
|
previous: BPMStartNode;
|
|
653
653
|
/** 下一个BPM起始节点 */
|
|
654
654
|
next: BPMStartNode;
|
|
655
|
+
get value(): number;
|
|
656
|
+
set value(value: number);
|
|
655
657
|
/**
|
|
656
658
|
* 创建一个新的BPM结束节点
|
|
657
659
|
* @param endTime 节点结束时间
|
|
@@ -2179,6 +2181,7 @@ declare module "event" {
|
|
|
2179
2181
|
* @throws {KPAError<ERROR_IDS.NEEDS_AT_LEAST_ONE_ENS>}
|
|
2180
2182
|
*/
|
|
2181
2183
|
static mergeSequences(sequences: EventNodeSequence[]): EventNodeSequence<number>;
|
|
2184
|
+
checkErrors(): void;
|
|
2182
2185
|
}
|
|
2183
2186
|
export type SpeedENS = EventNodeSequence<number> & {
|
|
2184
2187
|
type: EventType.speed;
|
|
@@ -2186,12 +2189,14 @@ declare module "event" {
|
|
|
2186
2189
|
}
|
|
2187
2190
|
declare module "env" {
|
|
2188
2191
|
import { type TimeT, type EventValueType } from "chartTypes";
|
|
2192
|
+
import { EventNode } from "event";
|
|
2189
2193
|
export enum ERROR_IDS {
|
|
2190
2194
|
UI_OCCUPIED = 272,
|
|
2191
2195
|
SEQUENCE_NAME_OCCUPIED = 1552,
|
|
2192
2196
|
SEQUENCE_NODE_TIME_OCCUPIED = 1553,
|
|
2193
2197
|
INVALID_EVENT_NODE_SEQUENCE_TYPE = 1568,
|
|
2194
2198
|
EVENT_NODE_TIME_NOT_INCREMENTAL = 1569,
|
|
2199
|
+
EVENT_NODE_NOT_DENSE = 1570,
|
|
2195
2200
|
PARENT_SEQUENCE_NOT_FOUND = 1585,
|
|
2196
2201
|
NEEDS_AT_LEAST_ONE_ENS = 1586,
|
|
2197
2202
|
SEQUENCE_TYPE_NOT_CONSISTENT = 1587,
|
|
@@ -2212,6 +2217,7 @@ declare module "env" {
|
|
|
2212
2217
|
MISSING_MACRO_EVALUATOR_KEY = 2336,
|
|
2213
2218
|
MACRO_EVALUATOR_NOT_FOUND = 2337,
|
|
2214
2219
|
INVALID_NOTE_PROP_TYPE = 2880,
|
|
2220
|
+
HOLD_HAS_NO_DURATION = 2848,
|
|
2215
2221
|
INVALID_TIME_TUPLE = 3104,
|
|
2216
2222
|
TIME_MACRO_NOT_FOUND = 3360,
|
|
2217
2223
|
VALUE_MACRO_NOT_FOUND = 3361,
|
|
@@ -2255,16 +2261,25 @@ declare module "env" {
|
|
|
2255
2261
|
JAVASCRIPT_SYNTAX_ERROR: (error: Error, macroId: string) => string;
|
|
2256
2262
|
PARAMETRIC_MACRO_REQUIRES_PROTO_KEY: (pos: any) => string;
|
|
2257
2263
|
MACRO_NOT_PARAMETRIC: (macroId: string, pos: any) => string;
|
|
2264
|
+
EVENT_NODE_NOT_DENSE: (pos: string) => string;
|
|
2265
|
+
HOLD_HAS_NO_DURATION: () => string;
|
|
2258
2266
|
};
|
|
2267
|
+
interface ErrorMap extends Record<keyof typeof ERROR_IDS, Array<any>> {
|
|
2268
|
+
EVENT_NODE_NOT_DENSE: [EventNode];
|
|
2269
|
+
}
|
|
2270
|
+
type ArgsOf<ET extends ERROR_IDS> = ET extends keyof ErrorMap ? ErrorMap[ET] : never;
|
|
2259
2271
|
export class KPAError<ET extends ERROR_IDS> extends Error {
|
|
2260
2272
|
id: ET;
|
|
2273
|
+
fixed: boolean;
|
|
2274
|
+
args: ArgsOf<ET> | [];
|
|
2261
2275
|
constructor(message: string, id: ET);
|
|
2262
2276
|
/**
|
|
2263
2277
|
* 对于解析谱面等场景,有时可能需要找出全部的错误,不宜直接抛出错误中断代码执行
|
|
2264
2278
|
*
|
|
2265
2279
|
* 此时可以调用该方法,该方法会输出错误并把它保存到KPAError的一个`buffer`静态属性下。
|
|
2266
2280
|
*/
|
|
2267
|
-
warn(): void;
|
|
2281
|
+
warn(...args: ArgsOf<ET> | []): void;
|
|
2282
|
+
fix(...args: ArgsOf<ET> | []): void;
|
|
2268
2283
|
static buffer: KPAError<ERROR_IDS>[];
|
|
2269
2284
|
static flush(): void;
|
|
2270
2285
|
}
|
|
@@ -2311,6 +2326,8 @@ declare module "env" {
|
|
|
2311
2326
|
JAVASCRIPT_SYNTAX_ERROR: (error: Error, macroId: string) => KPAError<ERROR_IDS.JAVASCRIPT_SYNTAX_ERROR>;
|
|
2312
2327
|
PARAMETRIC_MACRO_REQUIRES_PROTO_KEY: (pos: any) => KPAError<ERROR_IDS.PARAMETRIC_MACRO_REQUIRES_PROTO_KEY>;
|
|
2313
2328
|
MACRO_NOT_PARAMETRIC: (macroId: string, pos: any) => KPAError<ERROR_IDS.MACRO_NOT_PARAMETRIC>;
|
|
2329
|
+
EVENT_NODE_NOT_DENSE: (pos: string) => KPAError<ERROR_IDS.EVENT_NODE_NOT_DENSE>;
|
|
2330
|
+
HOLD_HAS_NO_DURATION: () => KPAError<ERROR_IDS.HOLD_HAS_NO_DURATION>;
|
|
2314
2331
|
};
|
|
2315
2332
|
freeze(): void;
|
|
2316
2333
|
};
|
|
@@ -2423,6 +2440,7 @@ declare module "operation/basic" {
|
|
|
2423
2440
|
undo(): void;
|
|
2424
2441
|
redo(): void;
|
|
2425
2442
|
do(operation: Operation): void;
|
|
2443
|
+
tryDo(returnOperation: () => Operation): void;
|
|
2426
2444
|
processFlags(operation: Operation): void;
|
|
2427
2445
|
clear(): void;
|
|
2428
2446
|
addEventListener<T extends OpEventType>(type: T, listener: (event: OpEventMap[T]) => void, options?: boolean | AddEventListenerOptions): void;
|
|
@@ -2518,8 +2536,8 @@ declare module "operation/event" {
|
|
|
2518
2536
|
* @param targetPrevious 要插在谁后面 The node to insert after, accessed through `EventNodeSequence.getNodeAt(TC.toBeats(node))`
|
|
2519
2537
|
*/
|
|
2520
2538
|
constructor(node: EventStartNode<VT>, targetPrevious: EventStartNode<VT>, updatesFP?: boolean);
|
|
2521
|
-
do(): void;
|
|
2522
|
-
undo(): void;
|
|
2539
|
+
do(chart: Chart): void;
|
|
2540
|
+
undo(chart: Chart): void;
|
|
2523
2541
|
}
|
|
2524
2542
|
export class EventNodePairInsertOrOverwriteOperation<VT extends EventValueESType> extends UnionOperation<LazyOperation<typeof EventNodePairInsertOperation<VT>> | EventNodeValueChangeOperation<VT>> {
|
|
2525
2543
|
overlapping: boolean;
|
package/index.js
CHANGED
|
@@ -60,6 +60,7 @@ var ERROR_IDS;
|
|
|
60
60
|
ERROR_IDS2[ERROR_IDS2["SEQUENCE_NODE_TIME_OCCUPIED"] = ENS | OCCPIED | 1] = "SEQUENCE_NODE_TIME_OCCUPIED";
|
|
61
61
|
ERROR_IDS2[ERROR_IDS2["INVALID_EVENT_NODE_SEQUENCE_TYPE"] = ENS | INVALID_DATA | 0] = "INVALID_EVENT_NODE_SEQUENCE_TYPE";
|
|
62
62
|
ERROR_IDS2[ERROR_IDS2["EVENT_NODE_TIME_NOT_INCREMENTAL"] = ENS | INVALID_DATA | 1] = "EVENT_NODE_TIME_NOT_INCREMENTAL";
|
|
63
|
+
ERROR_IDS2[ERROR_IDS2["EVENT_NODE_NOT_DENSE"] = ENS | INVALID_DATA | 2] = "EVENT_NODE_NOT_DENSE";
|
|
63
64
|
ERROR_IDS2[ERROR_IDS2["PARENT_SEQUENCE_NOT_FOUND"] = ENS | INVALID_USAGE | 1] = "PARENT_SEQUENCE_NOT_FOUND";
|
|
64
65
|
ERROR_IDS2[ERROR_IDS2["NEEDS_AT_LEAST_ONE_ENS"] = ENS | INVALID_USAGE | 2] = "NEEDS_AT_LEAST_ONE_ENS";
|
|
65
66
|
ERROR_IDS2[ERROR_IDS2["SEQUENCE_TYPE_NOT_CONSISTENT"] = ENS | INVALID_USAGE | 3] = "SEQUENCE_TYPE_NOT_CONSISTENT";
|
|
@@ -80,6 +81,7 @@ var ERROR_IDS;
|
|
|
80
81
|
ERROR_IDS2[ERROR_IDS2["MISSING_MACRO_EVALUATOR_KEY"] = EVALUATOR | INVALID_DATA | 0] = "MISSING_MACRO_EVALUATOR_KEY";
|
|
81
82
|
ERROR_IDS2[ERROR_IDS2["MACRO_EVALUATOR_NOT_FOUND"] = EVALUATOR | INVALID_DATA | 1] = "MACRO_EVALUATOR_NOT_FOUND";
|
|
82
83
|
ERROR_IDS2[ERROR_IDS2["INVALID_NOTE_PROP_TYPE"] = NOTE | INVALID_TYPE | 0] = "INVALID_NOTE_PROP_TYPE";
|
|
84
|
+
ERROR_IDS2[ERROR_IDS2["HOLD_HAS_NO_DURATION"] = NOTE | INVALID_DATA | 0] = "HOLD_HAS_NO_DURATION";
|
|
83
85
|
ERROR_IDS2[ERROR_IDS2["INVALID_TIME_TUPLE"] = TC | INVALID_DATA | 0] = "INVALID_TIME_TUPLE";
|
|
84
86
|
ERROR_IDS2[ERROR_IDS2["TIME_MACRO_NOT_FOUND"] = MACRO | INVALID_DATA | 0] = "TIME_MACRO_NOT_FOUND";
|
|
85
87
|
ERROR_IDS2[ERROR_IDS2["VALUE_MACRO_NOT_FOUND"] = MACRO | INVALID_DATA | 1] = "VALUE_MACRO_NOT_FOUND";
|
|
@@ -122,17 +124,28 @@ var ERRORS = {
|
|
|
122
124
|
PROTO_PRESENT_IN_NONPARAMETRIC: (macroId) => `'@proto can only be used in parametric Macros. At ${macroId}'`,
|
|
123
125
|
JAVASCRIPT_SYNTAX_ERROR: (error, macroId) => `JavaScript Syntax Error: ${error.message}. At ${macroId}`,
|
|
124
126
|
PARAMETRIC_MACRO_REQUIRES_PROTO_KEY: (pos) => `Parametric Macro requires key. At ${pos}`,
|
|
125
|
-
MACRO_NOT_PARAMETRIC: (macroId, pos) => `Macro '${macroId}' is not parametric. At ${pos}
|
|
127
|
+
MACRO_NOT_PARAMETRIC: (macroId, pos) => `Macro '${macroId}' is not parametric. At ${pos}`,
|
|
128
|
+
EVENT_NODE_NOT_DENSE: (pos) => `EventNode is not dense. At ${pos}`,
|
|
129
|
+
HOLD_HAS_NO_DURATION: () => `Hold should have a duration.`
|
|
126
130
|
};
|
|
127
131
|
|
|
128
132
|
class KPAError extends Error {
|
|
129
133
|
id;
|
|
134
|
+
fixed = false;
|
|
135
|
+
args;
|
|
130
136
|
constructor(message, id) {
|
|
131
137
|
super(message);
|
|
132
138
|
this.id = id;
|
|
133
139
|
}
|
|
134
|
-
warn() {
|
|
140
|
+
warn(...args) {
|
|
135
141
|
console.warn(this.stack);
|
|
142
|
+
this.args = args;
|
|
143
|
+
KPAError.buffer.push(this);
|
|
144
|
+
}
|
|
145
|
+
fix(...args) {
|
|
146
|
+
console.warn("[Auto Fixed]" + this.stack);
|
|
147
|
+
this.fixed = true;
|
|
148
|
+
this.args = args;
|
|
136
149
|
KPAError.buffer.push(this);
|
|
137
150
|
}
|
|
138
151
|
static buffer = [];
|
|
@@ -1643,7 +1656,7 @@ class EventNodeSequence {
|
|
|
1643
1656
|
this.listLength = 1;
|
|
1644
1657
|
}
|
|
1645
1658
|
static getDefaultValueFromEventType(type) {
|
|
1646
|
-
return type === 4 /* speed */ ? 10 : type === 7 /* scaleX */ || type === 8 /* scaleY */ ? 1 : type === 9 /* text */ ? "" : type === 10 /* color */ ? [
|
|
1659
|
+
return type === 4 /* speed */ ? 10 : type === 7 /* scaleX */ || type === 8 /* scaleY */ ? 1 : type === 9 /* text */ ? "" : type === 10 /* color */ ? [255, 255, 255] : 0;
|
|
1647
1660
|
}
|
|
1648
1661
|
static fromRPEJSON(type, data, chart, pos, endValue) {
|
|
1649
1662
|
const { templateEasingLib: templates } = chart;
|
|
@@ -1723,26 +1736,26 @@ class EventNodeSequence {
|
|
|
1723
1736
|
err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}] and the previous`).warn();
|
|
1724
1737
|
}
|
|
1725
1738
|
if (!TC2.lt(event.startTime, event.endTime)) {
|
|
1726
|
-
|
|
1739
|
+
if (TC2.eq(event.startTime, event.endTime)) {
|
|
1740
|
+
err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}]`).fix();
|
|
1741
|
+
continue;
|
|
1742
|
+
} else {
|
|
1743
|
+
err.EVENT_NODE_TIME_NOT_INCREMENTAL(`${pos}.events[${index}]`).warn();
|
|
1744
|
+
}
|
|
1727
1745
|
}
|
|
1728
|
-
lastEndTime = event.endTime;
|
|
1729
1746
|
if (lastEnd.type === 0 /* HEAD */) {
|
|
1730
1747
|
EventNode.connect(lastEnd, start);
|
|
1731
|
-
} else if (
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
const midEnd = new EventEndNode(start.time, val);
|
|
1738
|
-
midStart.evaluator = lastEnd.previous.evaluator;
|
|
1739
|
-
EventNode.connect(lastEnd, midStart);
|
|
1740
|
-
EventNode.connect(midStart, midEnd);
|
|
1748
|
+
} else if (TC2.gt(event.startTime, lastEndTime)) {
|
|
1749
|
+
err.EVENT_NODE_NOT_DENSE(`${pos}.events[${index}]`).warn();
|
|
1750
|
+
const mid = new EventStartNode(lastEndTime, start.value);
|
|
1751
|
+
const midEnd = new EventEndNode(event.startTime, end.value);
|
|
1752
|
+
EventNode.connect(lastEnd, mid);
|
|
1753
|
+
EventNode.connect(mid, midEnd);
|
|
1741
1754
|
EventNode.connect(midEnd, start);
|
|
1742
|
-
listLength++;
|
|
1743
1755
|
} else {
|
|
1744
1756
|
EventNode.connect(lastEnd, start);
|
|
1745
1757
|
}
|
|
1758
|
+
lastEndTime = event.endTime;
|
|
1746
1759
|
lastEnd = end;
|
|
1747
1760
|
}
|
|
1748
1761
|
const last = lastEnd;
|
|
@@ -1945,6 +1958,28 @@ class EventNodeSequence {
|
|
|
1945
1958
|
dest.initJump();
|
|
1946
1959
|
return dest;
|
|
1947
1960
|
}
|
|
1961
|
+
checkErrors() {
|
|
1962
|
+
let currentNode = this.head.next;
|
|
1963
|
+
if (TC2.ne(currentNode.time, [0, 0, 1])) {
|
|
1964
|
+
err.EVENT_NODE_NOT_DENSE(`${this.id}, ${currentNode.time}`).fix();
|
|
1965
|
+
currentNode.time = [0, 0, 1];
|
|
1966
|
+
}
|
|
1967
|
+
const endNode = currentNode.next;
|
|
1968
|
+
if (endNode.type === 1 /* TAIL */) {
|
|
1969
|
+
return;
|
|
1970
|
+
}
|
|
1971
|
+
let lastEnd = endNode;
|
|
1972
|
+
while (true) {
|
|
1973
|
+
const endNode2 = currentNode.next;
|
|
1974
|
+
if (endNode2.type === 1 /* TAIL */) {
|
|
1975
|
+
break;
|
|
1976
|
+
}
|
|
1977
|
+
if (TC2.ne(lastEnd.time, currentNode.time)) {
|
|
1978
|
+
err.EVENT_NODE_NOT_DENSE(`${this.id}, ${currentNode.time}`).warn();
|
|
1979
|
+
}
|
|
1980
|
+
currentNode = currentNode.next.next;
|
|
1981
|
+
}
|
|
1982
|
+
}
|
|
1948
1983
|
}
|
|
1949
1984
|
// src/note.ts
|
|
1950
1985
|
var notePropTypes = {
|
|
@@ -3033,6 +3068,15 @@ class BPMEndNode extends EventEndNode {
|
|
|
3033
3068
|
spb;
|
|
3034
3069
|
previous;
|
|
3035
3070
|
next;
|
|
3071
|
+
get value() {
|
|
3072
|
+
return this.previous.value;
|
|
3073
|
+
}
|
|
3074
|
+
set value(value) {
|
|
3075
|
+
if (!this.previous) {
|
|
3076
|
+
return;
|
|
3077
|
+
}
|
|
3078
|
+
this.previous.value = value;
|
|
3079
|
+
}
|
|
3036
3080
|
constructor(endTime) {
|
|
3037
3081
|
super(endTime, null);
|
|
3038
3082
|
}
|
|
@@ -3167,7 +3211,7 @@ class TimeCalculator {
|
|
|
3167
3211
|
}
|
|
3168
3212
|
}
|
|
3169
3213
|
// src/version.ts
|
|
3170
|
-
var VERSION =
|
|
3214
|
+
var VERSION = 212;
|
|
3171
3215
|
var SCHEMA = "https://cdn.jsdelivr.net/npm/kipphi@2.1.0/chartType2.schema.json";
|
|
3172
3216
|
|
|
3173
3217
|
// src/chart.ts
|
|
@@ -3803,9 +3847,20 @@ class OperationList extends EventTarget {
|
|
|
3803
3847
|
this.dispatchEvent(new OperationErrorEvent(operation, e));
|
|
3804
3848
|
return;
|
|
3805
3849
|
}
|
|
3850
|
+
this.undoneOperations = [];
|
|
3851
|
+
this.operations.push(operation);
|
|
3806
3852
|
this.dispatchEvent(new OperationEvent("do", operation));
|
|
3807
3853
|
this.processFlags(operation);
|
|
3808
|
-
|
|
3854
|
+
}
|
|
3855
|
+
tryDo(returnOperation) {
|
|
3856
|
+
let op;
|
|
3857
|
+
try {
|
|
3858
|
+
op = returnOperation();
|
|
3859
|
+
} catch (e) {
|
|
3860
|
+
this.dispatchEvent(new OperationErrorEvent(op, e));
|
|
3861
|
+
return;
|
|
3862
|
+
}
|
|
3863
|
+
this.do(op);
|
|
3809
3864
|
}
|
|
3810
3865
|
processFlags(operation) {
|
|
3811
3866
|
if (operation.updatesEditor) {
|
|
@@ -3970,12 +4025,18 @@ class EventNodePairInsertOperation extends Operation {
|
|
|
3970
4025
|
}
|
|
3971
4026
|
this.updatesFP = updatesFP && targetPrevious.isSpeed();
|
|
3972
4027
|
}
|
|
3973
|
-
do() {
|
|
4028
|
+
do(chart) {
|
|
3974
4029
|
const [endNode, startNode] = EventNode.insert(this.node, this.tarPrev);
|
|
3975
4030
|
this.node.parentSeq.updateJump(endNode, startNode);
|
|
4031
|
+
if (this.updatesFP) {
|
|
4032
|
+
this.sequence.updateFloorPositionAfter(this.tarPrev, chart.timeCalculator);
|
|
4033
|
+
}
|
|
3976
4034
|
}
|
|
3977
|
-
undo() {
|
|
4035
|
+
undo(chart) {
|
|
3978
4036
|
this.sequence.updateJump(...EventNode.removeNodePair(...EventNode.getEndStart(this.node)));
|
|
4037
|
+
if (this.updatesFP) {
|
|
4038
|
+
this.sequence.updateFloorPositionAfter(this.tarPrev, chart.timeCalculator);
|
|
4039
|
+
}
|
|
3979
4040
|
}
|
|
3980
4041
|
}
|
|
3981
4042
|
|
|
@@ -4461,6 +4522,11 @@ class NoteAddOperation extends Operation {
|
|
|
4461
4522
|
super();
|
|
4462
4523
|
this.note = note;
|
|
4463
4524
|
this.isHold = note.type === 2 /* hold */;
|
|
4525
|
+
if (this.isHold) {
|
|
4526
|
+
if (TC2.lt(note.endTime, note.startTime)) {
|
|
4527
|
+
throw err.HOLD_HAS_NO_DURATION();
|
|
4528
|
+
}
|
|
4529
|
+
}
|
|
4464
4530
|
this.noteNode = node;
|
|
4465
4531
|
this.comboDelta = note.isFake ? 0 : 1;
|
|
4466
4532
|
}
|
package/operation/basic.ts
CHANGED
|
@@ -147,10 +147,21 @@ export class OperationList extends EventTarget {
|
|
|
147
147
|
this.dispatchEvent(new OperationErrorEvent(operation, e as Error))
|
|
148
148
|
return
|
|
149
149
|
}
|
|
150
|
+
this.undoneOperations = [];
|
|
151
|
+
this.operations.push(operation);
|
|
150
152
|
this.dispatchEvent(new OperationEvent("do", operation));
|
|
151
153
|
this.processFlags(operation);
|
|
152
|
-
this.operations.push(operation);
|
|
153
154
|
}
|
|
155
|
+
tryDo(returnOperation: () => Operation) {
|
|
156
|
+
let op: Operation;
|
|
157
|
+
try {
|
|
158
|
+
op = returnOperation();
|
|
159
|
+
} catch (e) {
|
|
160
|
+
this.dispatchEvent(new OperationErrorEvent(op, e as Error))
|
|
161
|
+
return
|
|
162
|
+
}
|
|
163
|
+
this.do(op);
|
|
164
|
+
}
|
|
154
165
|
processFlags(operation: Operation) {
|
|
155
166
|
|
|
156
167
|
if (operation.updatesEditor) {
|
package/operation/event.ts
CHANGED
|
@@ -81,12 +81,20 @@ export class EventNodePairInsertOperation <VT extends EventValueESType> extends
|
|
|
81
81
|
}
|
|
82
82
|
this.updatesFP = updatesFP && targetPrevious.isSpeed();
|
|
83
83
|
}
|
|
84
|
-
do() {
|
|
84
|
+
do(chart: Chart) {
|
|
85
85
|
const [endNode, startNode] = EventNode.insert(this.node, this.tarPrev);
|
|
86
86
|
this.node.parentSeq.updateJump(endNode, startNode)
|
|
87
|
+
if (this.updatesFP) {
|
|
88
|
+
// updatesFP的校验确保了序列为速度序列
|
|
89
|
+
(this.sequence as SpeedENS).updateFloorPositionAfter(this.tarPrev as EventStartNode, chart.timeCalculator)
|
|
90
|
+
}
|
|
87
91
|
}
|
|
88
|
-
undo() {
|
|
92
|
+
undo(chart: Chart) {
|
|
89
93
|
this.sequence.updateJump(...EventNode.removeNodePair(...EventNode.getEndStart(this.node)))
|
|
94
|
+
if (this.updatesFP) {
|
|
95
|
+
// updatesFP的校验确保了序列为速度序列
|
|
96
|
+
(this.sequence as SpeedENS).updateFloorPositionAfter(this.tarPrev as EventStartNode, chart.timeCalculator)
|
|
97
|
+
}
|
|
90
98
|
}
|
|
91
99
|
}
|
|
92
100
|
|
package/operation/note.ts
CHANGED
|
@@ -140,6 +140,11 @@ export class NoteAddOperation extends Operation {
|
|
|
140
140
|
super()
|
|
141
141
|
this.note = note;
|
|
142
142
|
this.isHold = note.type === NoteType.hold;
|
|
143
|
+
if (this.isHold) {
|
|
144
|
+
if (TC.lt(note.endTime, note.startTime)) {
|
|
145
|
+
throw err.HOLD_HAS_NO_DURATION();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
143
148
|
this.noteNode = node;
|
|
144
149
|
// 一般来说,操作是对于在谱里面的NoteNode,谱外面的不需要操作
|
|
145
150
|
this.comboDelta = note.isFake ? 0 : +1;
|
package/package.json
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
2
|
+
"name": "kipphi",
|
|
3
|
+
"description": "Parse your Phigros Chart(.rpe.json or .kpa.json) into an editor-friendly format.",
|
|
4
|
+
"version": "2.1.2",
|
|
5
|
+
"author": "Team Zincs (https://github.com/TeamZincs)",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/TeamZincs/kipphi.git"
|
|
10
|
+
},
|
|
11
|
+
"module": "index.ts",
|
|
12
|
+
"main": "index.ts",
|
|
13
|
+
"type": "module",
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/bun": "latest"
|
|
16
|
+
},
|
|
17
|
+
"peerDependencies": {
|
|
18
|
+
"typescript": "^5"
|
|
19
|
+
},
|
|
20
|
+
"exports": {
|
|
21
|
+
"./operation": null,
|
|
22
|
+
".": {
|
|
23
|
+
"import": "./index.ts"
|
|
24
|
+
}
|
|
24
25
|
}
|
|
25
|
-
}
|
|
26
26
|
}
|
package/version.ts
CHANGED
package/line.ts
DELETED
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
import { Chart, JudgeLineGroup, BasicEventName, UIName } from "../chart";
|
|
2
|
-
import { ExtendedEventTypeName, RGB } from "../chartTypes";
|
|
3
|
-
import { EventNodeSequence } from "../event";
|
|
4
|
-
import { JudgeLine, ExtendedLayer } from "../judgeline";
|
|
5
|
-
import { Operation } from "./basic";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
// 有点怪异,感觉破坏了纯净性。不管了(
|
|
10
|
-
enum JudgeLinesEditorLayoutType {
|
|
11
|
-
ordered = 0b001,
|
|
12
|
-
tree = 0b010,
|
|
13
|
-
grouped = 0b100
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
export class JudgeLineInheritanceChangeOperation extends Operation {
|
|
18
|
-
originalValue: JudgeLine | null;
|
|
19
|
-
updatesEditor = true;
|
|
20
|
-
static REFLOWS = JudgeLinesEditorLayoutType.tree;
|
|
21
|
-
reflows = JudgeLineInheritanceChangeOperation.REFLOWS;
|
|
22
|
-
constructor(public chart: Chart, public judgeLine: JudgeLine, public value: JudgeLine | null) {
|
|
23
|
-
super();
|
|
24
|
-
this.originalValue = judgeLine.father;
|
|
25
|
-
// 这里只会让它静默失败,外面调用的时候能够在判断一次并抛错误才是最好的
|
|
26
|
-
if (JudgeLine.checkinterdependency(judgeLine, value)) {
|
|
27
|
-
this.ineffective = true;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
do() {
|
|
31
|
-
const line = this.judgeLine;
|
|
32
|
-
line.father = this.value;
|
|
33
|
-
if (this.originalValue) {
|
|
34
|
-
this.originalValue.children.delete(line);
|
|
35
|
-
} else {
|
|
36
|
-
const index = this.chart.orphanLines.indexOf(line);
|
|
37
|
-
if (index >= 0) // Impossible to be false, theoretically
|
|
38
|
-
this.chart.orphanLines.splice(index, 1)
|
|
39
|
-
}
|
|
40
|
-
if (this.value) {
|
|
41
|
-
this.value.children.add(line);
|
|
42
|
-
} else {
|
|
43
|
-
this.chart.orphanLines.push(line);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
undo() {
|
|
47
|
-
const line = this.judgeLine;
|
|
48
|
-
line.father = this.originalValue;
|
|
49
|
-
if (this.originalValue) {
|
|
50
|
-
this.originalValue.children.add(line);
|
|
51
|
-
} else {
|
|
52
|
-
this.chart.orphanLines.push(line);
|
|
53
|
-
}
|
|
54
|
-
if (this.value) {
|
|
55
|
-
this.value.children.delete(line);
|
|
56
|
-
} else {
|
|
57
|
-
const index = this.chart.orphanLines.indexOf(line);
|
|
58
|
-
if (index >= 0) // Impossible to be false, theoretically
|
|
59
|
-
this.chart.orphanLines.splice(index, 1)
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export class JudgeLineRenameOperation extends Operation {
|
|
65
|
-
updatesEditor = true;
|
|
66
|
-
originalValue: string;
|
|
67
|
-
constructor(public judgeLine: JudgeLine, public value: string) {
|
|
68
|
-
super();
|
|
69
|
-
this.originalValue = judgeLine.name;
|
|
70
|
-
}
|
|
71
|
-
do() {
|
|
72
|
-
this.judgeLine.name = this.value;
|
|
73
|
-
}
|
|
74
|
-
undo() {
|
|
75
|
-
this.judgeLine.name = this.originalValue;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
type JudgeLinePropName = "name" | "rotatesWithFather" | "anchor" | "texture" | "cover" | "zOrder";
|
|
80
|
-
|
|
81
|
-
export class JudgeLinePropChangeOperation<T extends JudgeLinePropName> extends Operation {
|
|
82
|
-
updatesEditor = true;
|
|
83
|
-
originalValue: JudgeLine[T];
|
|
84
|
-
constructor(public judgeLine: JudgeLine, public field: T, public value: JudgeLine[T]) {
|
|
85
|
-
super();
|
|
86
|
-
this.originalValue = judgeLine[field];
|
|
87
|
-
}
|
|
88
|
-
do() {
|
|
89
|
-
this.judgeLine[this.field] = this.value;
|
|
90
|
-
}
|
|
91
|
-
undo() {
|
|
92
|
-
this.judgeLine[this.field] = this.originalValue;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export class JudgeLineRegroupOperation extends Operation {
|
|
97
|
-
updatesEditor = true;
|
|
98
|
-
reflows = JudgeLinesEditorLayoutType.grouped;
|
|
99
|
-
originalValue: JudgeLineGroup;
|
|
100
|
-
constructor(public judgeLine: JudgeLine, public value: JudgeLineGroup) {
|
|
101
|
-
super();
|
|
102
|
-
this.originalValue = judgeLine.group;
|
|
103
|
-
}
|
|
104
|
-
do() {
|
|
105
|
-
this.judgeLine.group = this.value;
|
|
106
|
-
this.value.add(this.judgeLine);
|
|
107
|
-
this.originalValue.remove(this.judgeLine);
|
|
108
|
-
}
|
|
109
|
-
undo() {
|
|
110
|
-
this.judgeLine.group = this.originalValue;
|
|
111
|
-
this.originalValue.add(this.judgeLine);
|
|
112
|
-
this.value.remove(this.judgeLine);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export class JudgeLineCreateOperation extends Operation {
|
|
117
|
-
reflows = JudgeLinesEditorLayoutType.grouped | JudgeLinesEditorLayoutType.tree | JudgeLinesEditorLayoutType.ordered;
|
|
118
|
-
// 之前把=写成了:半天不知道咋错了
|
|
119
|
-
constructor(public chart: Chart, public judgeLine: JudgeLine) {
|
|
120
|
-
super();
|
|
121
|
-
}
|
|
122
|
-
do() {
|
|
123
|
-
const id = this.chart.judgeLines.length;
|
|
124
|
-
this.judgeLine.id = id;
|
|
125
|
-
this.chart.judgeLines.push(this.judgeLine);
|
|
126
|
-
this.chart.orphanLines.push(this.judgeLine);
|
|
127
|
-
this.chart.judgeLineGroups[0].add(this.judgeLine);
|
|
128
|
-
}
|
|
129
|
-
undo() {
|
|
130
|
-
this.chart.judgeLineGroups[0].remove(this.judgeLine);
|
|
131
|
-
this.chart.judgeLines.splice(this.chart.judgeLines.indexOf(this.judgeLine), 1);
|
|
132
|
-
this.chart.orphanLines.splice(this.chart.orphanLines.indexOf(this.judgeLine), 1);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export class JudgeLineDeleteOperation extends Operation {
|
|
137
|
-
readonly originalGroup: JudgeLineGroup;
|
|
138
|
-
constructor(public chart: Chart, public judgeLine: JudgeLine) {
|
|
139
|
-
super();
|
|
140
|
-
if (!this.chart.judgeLines.includes(this.judgeLine)) {
|
|
141
|
-
this.ineffective = true;
|
|
142
|
-
}
|
|
143
|
-
this.originalGroup = judgeLine.group;
|
|
144
|
-
}
|
|
145
|
-
do() {
|
|
146
|
-
this.chart.judgeLines.splice(this.chart.judgeLines.indexOf(this.judgeLine), 1);
|
|
147
|
-
if (this.chart.orphanLines.includes(this.judgeLine)) {
|
|
148
|
-
this.chart.orphanLines.splice(this.chart.orphanLines.indexOf(this.judgeLine), 1);
|
|
149
|
-
}
|
|
150
|
-
this.originalGroup.remove(this.judgeLine);
|
|
151
|
-
}
|
|
152
|
-
undo() {
|
|
153
|
-
this.chart.judgeLines.push(this.judgeLine);
|
|
154
|
-
this.chart.orphanLines.push(this.judgeLine);
|
|
155
|
-
this.originalGroup.add(this.judgeLine);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
export class JudgeLineENSChangeOperation extends Operation {
|
|
162
|
-
originalValue: EventNodeSequence;
|
|
163
|
-
constructor(public judgeLine: JudgeLine, public layerId: number, public typeStr: BasicEventName, public value: EventNodeSequence) {
|
|
164
|
-
super();
|
|
165
|
-
this.originalValue = judgeLine.eventLayers[layerId][typeStr];
|
|
166
|
-
}
|
|
167
|
-
do() {
|
|
168
|
-
this.judgeLine.eventLayers[this.layerId][this.typeStr] = this.value;
|
|
169
|
-
}
|
|
170
|
-
undo() {
|
|
171
|
-
this.judgeLine.eventLayers[this.layerId][this.typeStr] = this.originalValue;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
export type ENSOfTypeName<T extends ExtendedEventTypeName> = {
|
|
177
|
-
"scaleX": EventNodeSequence<number>,
|
|
178
|
-
"scaleY": EventNodeSequence<number>
|
|
179
|
-
"text": EventNodeSequence<string>,
|
|
180
|
-
"color": EventNodeSequence<RGB>
|
|
181
|
-
}[T]
|
|
182
|
-
export class JudgeLineExtendENSChangeOperation<T extends ExtendedEventTypeName> extends Operation {
|
|
183
|
-
originalValue: ENSOfTypeName<T>;
|
|
184
|
-
constructor(public judgeLine: JudgeLine, public typeStr: T, public value: ENSOfTypeName<T> | null) {
|
|
185
|
-
super();
|
|
186
|
-
this.originalValue = judgeLine.extendedLayer[typeStr satisfies keyof ExtendedLayer] as ENSOfTypeName<T>;
|
|
187
|
-
}
|
|
188
|
-
do() {
|
|
189
|
-
this.judgeLine.extendedLayer[this.typeStr] = this.value
|
|
190
|
-
}
|
|
191
|
-
undo() {
|
|
192
|
-
this.judgeLine.extendedLayer[this.typeStr] = this.originalValue
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
export class UIAttachOperation extends Operation {
|
|
198
|
-
updatesEditor = true;
|
|
199
|
-
constructor(public chart: Chart, public judgeLine: JudgeLine, public ui: UIName) {
|
|
200
|
-
super();
|
|
201
|
-
}
|
|
202
|
-
do() {
|
|
203
|
-
this.chart.attachUIToLine(this.ui, this.judgeLine);
|
|
204
|
-
}
|
|
205
|
-
undo() {
|
|
206
|
-
this.chart.detachUI(this.ui);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
export class UIDetachOperation extends Operation {
|
|
211
|
-
updatesEditor = true;
|
|
212
|
-
judgeLine: JudgeLine;
|
|
213
|
-
constructor(public chart: Chart, public ui: UIName) {
|
|
214
|
-
super();
|
|
215
|
-
if (chart[`${ui}Attach` satisfies keyof Chart]) {
|
|
216
|
-
this.judgeLine = chart[`${ui}Attach` satisfies keyof Chart];
|
|
217
|
-
} else {
|
|
218
|
-
this.ineffective = true;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
do() {
|
|
222
|
-
this.chart.detachUI(this.ui);
|
|
223
|
-
}
|
|
224
|
-
undo() {
|
|
225
|
-
this.chart.attachUIToLine(this.ui, this.judgeLine);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
export class JudgeLineDetachAllUIOperation extends Operation {
|
|
230
|
-
updatesEditor = true;
|
|
231
|
-
uinames: UIName[];
|
|
232
|
-
constructor(public chart: Chart, public judgeLine: JudgeLine) {
|
|
233
|
-
super();
|
|
234
|
-
this.uinames = chart.queryJudgeLineUI(this.judgeLine);
|
|
235
|
-
}
|
|
236
|
-
do() {
|
|
237
|
-
for (const ui of this.uinames) {
|
|
238
|
-
this.chart.detachUI(ui);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
undo() {
|
|
242
|
-
for (const ui of this.uinames) {
|
|
243
|
-
this.chart.attachUIToLine(ui, this.judgeLine);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
}
|