kipphi 2.1.2-rc.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/env.ts CHANGED
@@ -81,6 +81,7 @@ export enum ERROR_IDS {
81
81
 
82
82
 
83
83
  INVALID_NOTE_PROP_TYPE = NOTE | INVALID_TYPE | 0,
84
+ HOLD_HAS_NO_DURATION = NOTE | INVALID_DATA | 0,
84
85
 
85
86
 
86
87
  INVALID_TIME_TUPLE = TC | INVALID_DATA | 0,
@@ -178,6 +179,8 @@ export const ERRORS = {
178
179
  `Macro '${macroId}' is not parametric. At ${pos}`,
179
180
  EVENT_NODE_NOT_DENSE: (pos: string) =>
180
181
  `EventNode is not dense. At ${pos}`,
182
+ HOLD_HAS_NO_DURATION: () =>
183
+ `Hold should have a duration.`,
181
184
  } satisfies Record<keyof typeof ERROR_IDS, (...args: any[]) => string>
182
185
 
183
186
  type EnumKeys<E extends Record<string, string | number>> = E[keyof E];
package/index.d.ts CHANGED
@@ -2217,6 +2217,7 @@ declare module "env" {
2217
2217
  MISSING_MACRO_EVALUATOR_KEY = 2336,
2218
2218
  MACRO_EVALUATOR_NOT_FOUND = 2337,
2219
2219
  INVALID_NOTE_PROP_TYPE = 2880,
2220
+ HOLD_HAS_NO_DURATION = 2848,
2220
2221
  INVALID_TIME_TUPLE = 3104,
2221
2222
  TIME_MACRO_NOT_FOUND = 3360,
2222
2223
  VALUE_MACRO_NOT_FOUND = 3361,
@@ -2261,6 +2262,7 @@ declare module "env" {
2261
2262
  PARAMETRIC_MACRO_REQUIRES_PROTO_KEY: (pos: any) => string;
2262
2263
  MACRO_NOT_PARAMETRIC: (macroId: string, pos: any) => string;
2263
2264
  EVENT_NODE_NOT_DENSE: (pos: string) => string;
2265
+ HOLD_HAS_NO_DURATION: () => string;
2264
2266
  };
2265
2267
  interface ErrorMap extends Record<keyof typeof ERROR_IDS, Array<any>> {
2266
2268
  EVENT_NODE_NOT_DENSE: [EventNode];
@@ -2325,6 +2327,7 @@ declare module "env" {
2325
2327
  PARAMETRIC_MACRO_REQUIRES_PROTO_KEY: (pos: any) => KPAError<ERROR_IDS.PARAMETRIC_MACRO_REQUIRES_PROTO_KEY>;
2326
2328
  MACRO_NOT_PARAMETRIC: (macroId: string, pos: any) => KPAError<ERROR_IDS.MACRO_NOT_PARAMETRIC>;
2327
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>;
2328
2331
  };
2329
2332
  freeze(): void;
2330
2333
  };
@@ -2437,6 +2440,7 @@ declare module "operation/basic" {
2437
2440
  undo(): void;
2438
2441
  redo(): void;
2439
2442
  do(operation: Operation): void;
2443
+ tryDo(returnOperation: () => Operation): void;
2440
2444
  processFlags(operation: Operation): void;
2441
2445
  clear(): void;
2442
2446
  addEventListener<T extends OpEventType>(type: T, listener: (event: OpEventMap[T]) => void, options?: boolean | AddEventListenerOptions): void;
@@ -2532,8 +2536,8 @@ declare module "operation/event" {
2532
2536
  * @param targetPrevious 要插在谁后面 The node to insert after, accessed through `EventNodeSequence.getNodeAt(TC.toBeats(node))`
2533
2537
  */
2534
2538
  constructor(node: EventStartNode<VT>, targetPrevious: EventStartNode<VT>, updatesFP?: boolean);
2535
- do(): void;
2536
- undo(): void;
2539
+ do(chart: Chart): void;
2540
+ undo(chart: Chart): void;
2537
2541
  }
2538
2542
  export class EventNodePairInsertOrOverwriteOperation<VT extends EventValueESType> extends UnionOperation<LazyOperation<typeof EventNodePairInsertOperation<VT>> | EventNodeValueChangeOperation<VT>> {
2539
2543
  overlapping: boolean;
package/index.js CHANGED
@@ -81,6 +81,7 @@ var ERROR_IDS;
81
81
  ERROR_IDS2[ERROR_IDS2["MISSING_MACRO_EVALUATOR_KEY"] = EVALUATOR | INVALID_DATA | 0] = "MISSING_MACRO_EVALUATOR_KEY";
82
82
  ERROR_IDS2[ERROR_IDS2["MACRO_EVALUATOR_NOT_FOUND"] = EVALUATOR | INVALID_DATA | 1] = "MACRO_EVALUATOR_NOT_FOUND";
83
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";
84
85
  ERROR_IDS2[ERROR_IDS2["INVALID_TIME_TUPLE"] = TC | INVALID_DATA | 0] = "INVALID_TIME_TUPLE";
85
86
  ERROR_IDS2[ERROR_IDS2["TIME_MACRO_NOT_FOUND"] = MACRO | INVALID_DATA | 0] = "TIME_MACRO_NOT_FOUND";
86
87
  ERROR_IDS2[ERROR_IDS2["VALUE_MACRO_NOT_FOUND"] = MACRO | INVALID_DATA | 1] = "VALUE_MACRO_NOT_FOUND";
@@ -124,7 +125,8 @@ var ERRORS = {
124
125
  JAVASCRIPT_SYNTAX_ERROR: (error, macroId) => `JavaScript Syntax Error: ${error.message}. At ${macroId}`,
125
126
  PARAMETRIC_MACRO_REQUIRES_PROTO_KEY: (pos) => `Parametric Macro requires key. At ${pos}`,
126
127
  MACRO_NOT_PARAMETRIC: (macroId, pos) => `Macro '${macroId}' is not parametric. At ${pos}`,
127
- EVENT_NODE_NOT_DENSE: (pos) => `EventNode is not dense. At ${pos}`
128
+ EVENT_NODE_NOT_DENSE: (pos) => `EventNode is not dense. At ${pos}`,
129
+ HOLD_HAS_NO_DURATION: () => `Hold should have a duration.`
128
130
  };
129
131
 
130
132
  class KPAError extends Error {
@@ -3850,6 +3852,16 @@ class OperationList extends EventTarget {
3850
3852
  this.dispatchEvent(new OperationEvent("do", operation));
3851
3853
  this.processFlags(operation);
3852
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);
3864
+ }
3853
3865
  processFlags(operation) {
3854
3866
  if (operation.updatesEditor) {
3855
3867
  this.dispatchEvent(new OperationEvent("needsupdate", operation));
@@ -4013,12 +4025,18 @@ class EventNodePairInsertOperation extends Operation {
4013
4025
  }
4014
4026
  this.updatesFP = updatesFP && targetPrevious.isSpeed();
4015
4027
  }
4016
- do() {
4028
+ do(chart) {
4017
4029
  const [endNode, startNode] = EventNode.insert(this.node, this.tarPrev);
4018
4030
  this.node.parentSeq.updateJump(endNode, startNode);
4031
+ if (this.updatesFP) {
4032
+ this.sequence.updateFloorPositionAfter(this.tarPrev, chart.timeCalculator);
4033
+ }
4019
4034
  }
4020
- undo() {
4035
+ undo(chart) {
4021
4036
  this.sequence.updateJump(...EventNode.removeNodePair(...EventNode.getEndStart(this.node)));
4037
+ if (this.updatesFP) {
4038
+ this.sequence.updateFloorPositionAfter(this.tarPrev, chart.timeCalculator);
4039
+ }
4022
4040
  }
4023
4041
  }
4024
4042
 
@@ -4504,6 +4522,11 @@ class NoteAddOperation extends Operation {
4504
4522
  super();
4505
4523
  this.note = note;
4506
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
+ }
4507
4530
  this.noteNode = node;
4508
4531
  this.comboDelta = note.isFake ? 0 : 1;
4509
4532
  }
@@ -152,6 +152,16 @@ export class OperationList extends EventTarget {
152
152
  this.dispatchEvent(new OperationEvent("do", operation));
153
153
  this.processFlags(operation);
154
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
+ }
155
165
  processFlags(operation: Operation) {
156
166
 
157
167
  if (operation.updatesEditor) {
@@ -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,7 +1,7 @@
1
1
  {
2
2
  "name": "kipphi",
3
3
  "description": "Parse your Phigros Chart(.rpe.json or .kpa.json) into an editor-friendly format.",
4
- "version": "2.1.2-rc.1",
4
+ "version": "2.1.2",
5
5
  "author": "Team Zincs (https://github.com/TeamZincs)",
6
6
  "license": "MIT",
7
7
  "repository": {
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
- }