kipphi 2.1.2 → 2.1.3-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bpm.ts +26 -6
- package/chart.ts +10 -1
- package/chartTypes.ts +26 -5
- package/easing.ts +31 -2
- package/env.ts +3 -0
- package/evaluator.ts +39 -14
- package/event.ts +26 -9
- package/index.d.ts +62 -10
- package/index.js +193 -76
- package/judgeline.ts +100 -43
- package/note.ts +16 -18
- package/operation/easy.ts +131 -0
- package/operation/event.ts +7 -0
- package/package.json +1 -1
- package/rpeChartCompiler.ts +39 -10
- package/tsconfig.json +2 -2
- package/util.ts +4 -2
- package/version.ts +1 -1
package/index.js
CHANGED
|
@@ -35,8 +35,9 @@ var rgb2hex = (rgb) => {
|
|
|
35
35
|
var hex2rgb = (hex) => {
|
|
36
36
|
return [hex >> 16, hex >> 8 & 255, hex & 255];
|
|
37
37
|
};
|
|
38
|
+
var DENO = 324324000;
|
|
38
39
|
var numberToRatio = (num) => {
|
|
39
|
-
return [Math.round(num *
|
|
40
|
+
return [Math.round(num * DENO), DENO];
|
|
40
41
|
};
|
|
41
42
|
var toTimeString = (beaT) => `${beaT[0]}:${beaT[1]}/${beaT[2]}`;
|
|
42
43
|
|
|
@@ -77,6 +78,7 @@ var ERROR_IDS;
|
|
|
77
78
|
ERROR_IDS2[ERROR_IDS2["NODES_NOT_CONTINUOUS"] = EASING | INVALID_USAGE | 1] = "NODES_NOT_CONTINUOUS";
|
|
78
79
|
ERROR_IDS2[ERROR_IDS2["NODES_NOT_BELONG_TO_SAME_SEQUENCE"] = EASING | INVALID_USAGE | 2] = "NODES_NOT_BELONG_TO_SAME_SEQUENCE";
|
|
79
80
|
ERROR_IDS2[ERROR_IDS2["NODES_HAS_ZERO_DELTA"] = EASING | INVALID_USAGE | 3] = "NODES_HAS_ZERO_DELTA";
|
|
81
|
+
ERROR_IDS2[ERROR_IDS2["TEMPLATE_EASING_CIRCULAR_REFERENCE"] = EASING | INVALID_USAGE | 4] = "TEMPLATE_EASING_CIRCULAR_REFERENCE";
|
|
80
82
|
ERROR_IDS2[ERROR_IDS2["CANNOT_DIVIDE_EXPRESSION_EVALUATOR"] = EVALUATOR | INVALID_USAGE | 0] = "CANNOT_DIVIDE_EXPRESSION_EVALUATOR";
|
|
81
83
|
ERROR_IDS2[ERROR_IDS2["MISSING_MACRO_EVALUATOR_KEY"] = EVALUATOR | INVALID_DATA | 0] = "MISSING_MACRO_EVALUATOR_KEY";
|
|
82
84
|
ERROR_IDS2[ERROR_IDS2["MACRO_EVALUATOR_NOT_FOUND"] = EVALUATOR | INVALID_DATA | 1] = "MACRO_EVALUATOR_NOT_FOUND";
|
|
@@ -126,7 +128,8 @@ var ERRORS = {
|
|
|
126
128
|
PARAMETRIC_MACRO_REQUIRES_PROTO_KEY: (pos) => `Parametric Macro requires key. At ${pos}`,
|
|
127
129
|
MACRO_NOT_PARAMETRIC: (macroId, pos) => `Macro '${macroId}' is not parametric. At ${pos}`,
|
|
128
130
|
EVENT_NODE_NOT_DENSE: (pos) => `EventNode is not dense. At ${pos}`,
|
|
129
|
-
HOLD_HAS_NO_DURATION: () => `Hold should have a duration
|
|
131
|
+
HOLD_HAS_NO_DURATION: () => `Hold should have a duration.`,
|
|
132
|
+
TEMPLATE_EASING_CIRCULAR_REFERENCE: (temEasName) => `Template Easing '${temEasName}' has circular reference`
|
|
130
133
|
};
|
|
131
134
|
|
|
132
135
|
class KPAError extends Error {
|
|
@@ -548,6 +551,9 @@ class TemplateEasing extends Easing {
|
|
|
548
551
|
this.name = name;
|
|
549
552
|
}
|
|
550
553
|
getValue(t) {
|
|
554
|
+
if (t === 1) {
|
|
555
|
+
return 1;
|
|
556
|
+
}
|
|
551
557
|
const seq = this.eventNodeSequence;
|
|
552
558
|
const delta = this.valueDelta;
|
|
553
559
|
if (delta === 0) {
|
|
@@ -569,6 +575,28 @@ class TemplateEasing extends Easing {
|
|
|
569
575
|
get headValue() {
|
|
570
576
|
return this.eventNodeSequence.head.next.value;
|
|
571
577
|
}
|
|
578
|
+
segmentedValueGetter(easingLeft, easingRight) {
|
|
579
|
+
return (t) => {
|
|
580
|
+
const leftValue = this.getValue(easingLeft);
|
|
581
|
+
const rightValue = this.getValue(easingRight);
|
|
582
|
+
const timeDelta = easingRight - easingLeft;
|
|
583
|
+
const delta = rightValue - leftValue;
|
|
584
|
+
if (delta === 0) {
|
|
585
|
+
return 0;
|
|
586
|
+
}
|
|
587
|
+
return (this.getValue(easingLeft + timeDelta * t) - leftValue) / delta;
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
static checkCircularReference(seq, template) {
|
|
591
|
+
const seq2 = template.eventNodeSequence;
|
|
592
|
+
if (seq === seq2) {
|
|
593
|
+
return true;
|
|
594
|
+
}
|
|
595
|
+
if (seq2.hasReferenceTo(seq)) {
|
|
596
|
+
return true;
|
|
597
|
+
}
|
|
598
|
+
return false;
|
|
599
|
+
}
|
|
572
600
|
}
|
|
573
601
|
|
|
574
602
|
class WrapperEasing extends Easing {
|
|
@@ -952,16 +980,24 @@ class EasedEvaluator extends Evaluator {
|
|
|
952
980
|
super();
|
|
953
981
|
this.easing = easing;
|
|
954
982
|
}
|
|
955
|
-
eval(startNode,
|
|
983
|
+
eval(startNode, beatsOrSeconds, timeCalculator) {
|
|
956
984
|
const next = startNode.next;
|
|
957
|
-
const timeDelta = TC2.getDelta(next.time, startNode.time);
|
|
958
|
-
const current = beats - TC2.toBeats(startNode.time);
|
|
959
985
|
const nextValue = startNode.next.value;
|
|
960
986
|
const value = startNode.value;
|
|
961
987
|
if (nextValue === value) {
|
|
962
988
|
return value;
|
|
963
989
|
}
|
|
964
|
-
|
|
990
|
+
if (timeCalculator) {
|
|
991
|
+
const startSecs = timeCalculator.toSeconds(TC2.toBeats(startNode.time));
|
|
992
|
+
const endSecs = timeCalculator.toSeconds(TC2.toBeats(next.time));
|
|
993
|
+
const current = beatsOrSeconds - startSecs;
|
|
994
|
+
const timeDelta = endSecs - startSecs;
|
|
995
|
+
return this.convert(value, nextValue, this.easing.getValue(current / timeDelta));
|
|
996
|
+
} else {
|
|
997
|
+
const timeDelta = TC2.getDelta(next.time, startNode.time);
|
|
998
|
+
const current = beatsOrSeconds - TC2.toBeats(startNode.time);
|
|
999
|
+
return this.convert(value, nextValue, this.easing.getValue(current / timeDelta));
|
|
1000
|
+
}
|
|
965
1001
|
}
|
|
966
1002
|
static getEvaluatorFromEasing(type, easing, interpretedAs) {
|
|
967
1003
|
const easingIsNormal = easing instanceof NormalEasing;
|
|
@@ -1046,11 +1082,11 @@ class TextEasedEvaluator extends EasedEvaluator {
|
|
|
1046
1082
|
if (interpretedAs === 2 /* float */) {
|
|
1047
1083
|
const start = parseFloat(value);
|
|
1048
1084
|
const delta = parseFloat(nextValue) - start;
|
|
1049
|
-
return start + progress * delta + "";
|
|
1085
|
+
return (start + progress * delta).toFixed(3) + "";
|
|
1050
1086
|
} else if (interpretedAs === 1 /* int */) {
|
|
1051
1087
|
const start = parseInt(value);
|
|
1052
1088
|
const delta = parseInt(nextValue) - start;
|
|
1053
|
-
return start + Math.
|
|
1089
|
+
return start + Math.floor(progress * delta) + "";
|
|
1054
1090
|
} else if (value.startsWith(nextValue)) {
|
|
1055
1091
|
const startLen = nextValue.length;
|
|
1056
1092
|
const deltaLen = value.length - startLen;
|
|
@@ -1104,8 +1140,8 @@ class MacroEvaluator extends Evaluator {
|
|
|
1104
1140
|
node.evaluator = this;
|
|
1105
1141
|
this.consumers.set(node, this.compile(node, chart));
|
|
1106
1142
|
}
|
|
1107
|
-
eval(event, beats) {
|
|
1108
|
-
return this.consumers.get(event).eval(event, beats);
|
|
1143
|
+
eval(event, beats, timeCalculator) {
|
|
1144
|
+
return this.consumers.get(event).eval(event, beats, timeCalculator);
|
|
1109
1145
|
}
|
|
1110
1146
|
dumpFor(node) {
|
|
1111
1147
|
return {
|
|
@@ -1130,11 +1166,19 @@ class ExpressionEvaluator extends Evaluator {
|
|
|
1130
1166
|
this.jsExpr = jsExpr;
|
|
1131
1167
|
this.func = new Function("t", "return " + jsExpr);
|
|
1132
1168
|
}
|
|
1133
|
-
eval(startNode,
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1169
|
+
eval(startNode, beatsOrSecs, timeCalculator) {
|
|
1170
|
+
if (timeCalculator) {
|
|
1171
|
+
const startSecs = timeCalculator.toSeconds(TC2.toBeats(startNode.time));
|
|
1172
|
+
const endSecs = timeCalculator.toSeconds(TC2.toBeats(startNode.next.time));
|
|
1173
|
+
const current = beatsOrSecs - startSecs;
|
|
1174
|
+
const timeDelta = endSecs - startSecs;
|
|
1175
|
+
return this.func(current / timeDelta);
|
|
1176
|
+
} else {
|
|
1177
|
+
const next = startNode.next;
|
|
1178
|
+
const timeDelta = TC2.getDelta(next.time, startNode.time);
|
|
1179
|
+
const current = beatsOrSecs - TC2.toBeats(startNode.time);
|
|
1180
|
+
return this.func(current / timeDelta);
|
|
1181
|
+
}
|
|
1138
1182
|
}
|
|
1139
1183
|
dumpFor() {
|
|
1140
1184
|
return {
|
|
@@ -1352,11 +1396,6 @@ class EventNode extends EventNodeLike {
|
|
|
1352
1396
|
return ret;
|
|
1353
1397
|
}
|
|
1354
1398
|
static getEasing(data, templates, notSegmented = false) {
|
|
1355
|
-
const left = data.easingLeft;
|
|
1356
|
-
const right = data.easingRight;
|
|
1357
|
-
if (!notSegmented && (left && right) && (left !== 0 || right !== 1)) {
|
|
1358
|
-
return new SegmentedEasing(EventNode.getEasing(data, templates, true), left, right);
|
|
1359
|
-
}
|
|
1360
1399
|
if (data.bezier) {
|
|
1361
1400
|
const bp = data.bezierPoints;
|
|
1362
1401
|
const easing = new BezierEasing([bp[0], bp[1]], [bp[2], bp[3]]);
|
|
@@ -1563,11 +1602,11 @@ class EventStartNode extends EventNode {
|
|
|
1563
1602
|
linkedMacro: [...this.linkedMacros].map((macro) => macro.dumpLinkForNode(this))
|
|
1564
1603
|
};
|
|
1565
1604
|
}
|
|
1566
|
-
getValueAt(
|
|
1605
|
+
getValueAt(beatsOrSecs, timeCalculator) {
|
|
1567
1606
|
if (this.next.type === 1 /* TAIL */) {
|
|
1568
1607
|
return this.value;
|
|
1569
1608
|
}
|
|
1570
|
-
return this.evaluator.eval(this,
|
|
1609
|
+
return this.evaluator.eval(this, beatsOrSecs, timeCalculator);
|
|
1571
1610
|
}
|
|
1572
1611
|
getSpeedValueAt(beats) {
|
|
1573
1612
|
if (this.next.type === 1 /* TAIL */) {
|
|
@@ -1845,6 +1884,9 @@ class EventNodeSequence {
|
|
|
1845
1884
|
getValueAt(beats, usePrev = false) {
|
|
1846
1885
|
return this.getNodeAt(beats, usePrev).getValueAt(beats);
|
|
1847
1886
|
}
|
|
1887
|
+
getValueAtBySecs(beats, seconds, timeCalculator, usePrev = false) {
|
|
1888
|
+
return this.getNodeAt(beats, usePrev).getValueAt(seconds, timeCalculator);
|
|
1889
|
+
}
|
|
1848
1890
|
getFloorPositionAt(beats, timeCalculator) {
|
|
1849
1891
|
const node = this.getNodeAt(beats);
|
|
1850
1892
|
const value = node.getLocalFloorPos(beats, timeCalculator) + node.floorPosition;
|
|
@@ -1861,7 +1903,7 @@ class EventNodeSequence {
|
|
|
1861
1903
|
const prevStart = node.previous.previous;
|
|
1862
1904
|
currentFP = prevStart.floorPosition + prevStart.getFullLocalFloorPos(tc);
|
|
1863
1905
|
} else {
|
|
1864
|
-
currentFP = 0;
|
|
1906
|
+
node.floorPosition = currentFP = 0;
|
|
1865
1907
|
}
|
|
1866
1908
|
while (true) {
|
|
1867
1909
|
const canBeEnd = node.next;
|
|
@@ -1980,24 +2022,40 @@ class EventNodeSequence {
|
|
|
1980
2022
|
currentNode = currentNode.next.next;
|
|
1981
2023
|
}
|
|
1982
2024
|
}
|
|
2025
|
+
hasReferenceTo(seq) {
|
|
2026
|
+
let node = this.head.next;
|
|
2027
|
+
while (true) {
|
|
2028
|
+
const endNode = node.next;
|
|
2029
|
+
if (endNode.type === 1 /* TAIL */) {
|
|
2030
|
+
break;
|
|
2031
|
+
}
|
|
2032
|
+
const evaluator = node.evaluator;
|
|
2033
|
+
if (evaluator instanceof EasedEvaluator && evaluator.easing instanceof TemplateEasing) {
|
|
2034
|
+
if (TemplateEasing.checkCircularReference(seq, evaluator.easing)) {
|
|
2035
|
+
return true;
|
|
2036
|
+
}
|
|
2037
|
+
}
|
|
2038
|
+
node = endNode.next;
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
1983
2041
|
}
|
|
1984
2042
|
// src/note.ts
|
|
1985
2043
|
var notePropTypes = {
|
|
1986
2044
|
above: "boolean",
|
|
1987
|
-
alpha: "
|
|
2045
|
+
alpha: "int[0,255]",
|
|
1988
2046
|
endTime: ["number", "number", "number"],
|
|
1989
2047
|
isFake: "boolean",
|
|
1990
2048
|
positionX: "number",
|
|
1991
|
-
size: "number",
|
|
2049
|
+
size: "number(0,+)",
|
|
1992
2050
|
speed: "number",
|
|
1993
2051
|
startTime: ["number", "number", "number"],
|
|
1994
|
-
type: "
|
|
1995
|
-
visibleTime: "number",
|
|
1996
|
-
visibleBeats: "number",
|
|
2052
|
+
type: "int[1,4]",
|
|
2053
|
+
visibleTime: "number(0,+)",
|
|
2054
|
+
visibleBeats: "number(0,+)",
|
|
1997
2055
|
yOffset: "number",
|
|
1998
|
-
tint: ["
|
|
1999
|
-
tintHitEffects: ["
|
|
2000
|
-
judgeSize: "number"
|
|
2056
|
+
tint: ["int[0,255]", "int[0,255]", "int[0,255]"],
|
|
2057
|
+
tintHitEffects: ["int[0,255]", "int[0,255]", "int[0,255]"],
|
|
2058
|
+
judgeSize: "number(0,+)"
|
|
2001
2059
|
};
|
|
2002
2060
|
|
|
2003
2061
|
class Note {
|
|
@@ -2030,9 +2088,10 @@ class Note {
|
|
|
2030
2088
|
this.visibleTime = data.visibleTime;
|
|
2031
2089
|
this.yOffset = data.absoluteYOffset ?? data.yOffset * this.speed;
|
|
2032
2090
|
this.visibleBeats = data.visibleBeats;
|
|
2033
|
-
|
|
2091
|
+
const color = data.tint ?? data.color;
|
|
2092
|
+
this.tint = color ? rgb2hex(color) : undefined;
|
|
2034
2093
|
this.tintHitEffects = data.tintHitEffects ? rgb2hex(data.tintHitEffects) : undefined;
|
|
2035
|
-
this.judgeSize = data.judgeSize ?? this.size;
|
|
2094
|
+
this.judgeSize = data.judgeSize ?? data.judgeArea ?? this.size;
|
|
2036
2095
|
}
|
|
2037
2096
|
static fromKPAJSON(data, timeCalculator) {
|
|
2038
2097
|
const note = new Note(data);
|
|
@@ -2079,7 +2138,8 @@ class Note {
|
|
|
2079
2138
|
yOffset: this.yOffset / this.speed,
|
|
2080
2139
|
speed: this.speed,
|
|
2081
2140
|
tint: this.tint !== undefined ? hex2rgb(this.tint) : undefined,
|
|
2082
|
-
tintHitEffects: this.tint !== undefined ? hex2rgb(this.tintHitEffects) : undefined
|
|
2141
|
+
tintHitEffects: this.tint !== undefined ? hex2rgb(this.tintHitEffects) : undefined,
|
|
2142
|
+
judgeArea: this.judgeSize
|
|
2083
2143
|
};
|
|
2084
2144
|
}
|
|
2085
2145
|
dumpKPA() {
|
|
@@ -2636,17 +2696,17 @@ class JudgeLine {
|
|
|
2636
2696
|
line.speedSequence = speedSequences[0];
|
|
2637
2697
|
chart.registerEventNodeSequence(4 /* speed */, `#${id}.speed`, speedSequences[0]);
|
|
2638
2698
|
}
|
|
2699
|
+
if (data.extended?.scaleXEvents) {
|
|
2700
|
+
line.extendedLayer.scaleX = createExtendedSequence(7 /* scaleX */, data.extended.scaleXEvents);
|
|
2701
|
+
} else {
|
|
2702
|
+
line.extendedLayer.scaleX = chart.createEventNodeSequence(7 /* scaleX */, `#${id}.ex.scaleX`);
|
|
2703
|
+
}
|
|
2704
|
+
if (data.extended?.scaleYEvents) {
|
|
2705
|
+
line.extendedLayer.scaleY = createExtendedSequence(8 /* scaleY */, data.extended.scaleYEvents);
|
|
2706
|
+
} else {
|
|
2707
|
+
line.extendedLayer.scaleY = chart.createEventNodeSequence(8 /* scaleY */, `#${id}.ex.scaleY`);
|
|
2708
|
+
}
|
|
2639
2709
|
if (data.extended) {
|
|
2640
|
-
if (data.extended.scaleXEvents) {
|
|
2641
|
-
line.extendedLayer.scaleX = createExtendedSequence(7 /* scaleX */, data.extended.scaleXEvents);
|
|
2642
|
-
} else {
|
|
2643
|
-
line.extendedLayer.scaleX = chart.createEventNodeSequence(7 /* scaleX */, `#${id}.ex.scaleX`);
|
|
2644
|
-
}
|
|
2645
|
-
if (data.extended.scaleYEvents) {
|
|
2646
|
-
line.extendedLayer.scaleY = createExtendedSequence(8 /* scaleY */, data.extended.scaleYEvents);
|
|
2647
|
-
} else {
|
|
2648
|
-
line.extendedLayer.scaleY = chart.createEventNodeSequence(8 /* scaleY */, `#${id}.ex.scaleY`);
|
|
2649
|
-
}
|
|
2650
2710
|
if (data.extended.textEvents) {
|
|
2651
2711
|
line.extendedLayer.text = createExtendedSequence(9 /* text */, data.extended.textEvents);
|
|
2652
2712
|
}
|
|
@@ -2815,7 +2875,7 @@ class JudgeLine {
|
|
|
2815
2875
|
if (lineMonotonicity === 0 /* increasing */ && startY >= 0 && endY > 0) {
|
|
2816
2876
|
return result;
|
|
2817
2877
|
}
|
|
2818
|
-
const computeTime = (speed, currentPos, fore) => timeCalculator.secondsToBeats(currentPos / (speed * 120) + timeCalculator.toSeconds(fore));
|
|
2878
|
+
const computeTime = (speed, currentPos, fore) => speed * currentPos <= 0 ? fore : timeCalculator.secondsToBeats(currentPos / (speed * 120) + timeCalculator.toSeconds(fore));
|
|
2819
2879
|
while (true) {
|
|
2820
2880
|
const thisTime = TC2.toBeats(startNode.time);
|
|
2821
2881
|
const endNode = startNode.next;
|
|
@@ -2823,17 +2883,21 @@ class JudgeLine {
|
|
|
2823
2883
|
if (endNode.type === 1 /* TAIL */) {
|
|
2824
2884
|
const thisPosY2 = startNode.floorPosition - currentJudgeLineFloorPos;
|
|
2825
2885
|
const thisSpeed2 = startNode.value;
|
|
2826
|
-
const inf = thisSpeed2 > 0 ? Infinity : thisSpeed2 < 0 ? -Infinity : thisPosY2;
|
|
2827
2886
|
if (range[0] === undefined) {
|
|
2828
|
-
if (
|
|
2829
|
-
range[0] = computeTime(thisSpeed2,
|
|
2830
|
-
} else if (thisSpeed2
|
|
2831
|
-
range[0] =
|
|
2887
|
+
if (thisSpeed2 > 0 && endY > thisPosY2) {
|
|
2888
|
+
range[0] = computeTime(thisSpeed2, startY - thisPosY2, thisTime);
|
|
2889
|
+
} else if (thisSpeed2 < 0 && startY < thisPosY2) {
|
|
2890
|
+
range[0] = computeTime(thisSpeed2, endY - thisPosY2, thisTime);
|
|
2891
|
+
} else if (thisSpeed2 === 0 && startY <= thisPosY2 && thisPosY2 <= endY) {
|
|
2892
|
+
range[0] = thisTime;
|
|
2832
2893
|
}
|
|
2833
2894
|
}
|
|
2834
2895
|
if (range[0] !== undefined) {
|
|
2835
|
-
if (
|
|
2836
|
-
range[1] = computeTime(thisSpeed2,
|
|
2896
|
+
if (thisSpeed2 > 0 && endY > thisPosY2) {
|
|
2897
|
+
range[1] = computeTime(thisSpeed2, endY - thisPosY2, thisTime);
|
|
2898
|
+
result.push(range);
|
|
2899
|
+
} else if (thisSpeed2 < 0 && startY < thisPosY2) {
|
|
2900
|
+
range[1] = computeTime(thisSpeed2, startY - thisPosY2, thisTime);
|
|
2837
2901
|
result.push(range);
|
|
2838
2902
|
} else if (thisSpeed2 === 0) {
|
|
2839
2903
|
range[1] = Infinity;
|
|
@@ -2846,7 +2910,7 @@ class JudgeLine {
|
|
|
2846
2910
|
const thisPosY = startNode.floorPosition - currentJudgeLineFloorPos;
|
|
2847
2911
|
const nextPosY = nextStart.floorPosition - currentJudgeLineFloorPos;
|
|
2848
2912
|
let thisSpeed = startNode.value;
|
|
2849
|
-
let nextSpeed =
|
|
2913
|
+
let nextSpeed = endNode.value;
|
|
2850
2914
|
if (Math.abs(thisSpeed) < 0.00000001) {
|
|
2851
2915
|
thisSpeed = 0;
|
|
2852
2916
|
}
|
|
@@ -2858,15 +2922,13 @@ class JudgeLine {
|
|
|
2858
2922
|
const zeroPosY = speedSequence.getFloorPositionAt(zeroTime, timeCalculator) - currentJudgeLineFloorPos;
|
|
2859
2923
|
const zeroSpeed = 0;
|
|
2860
2924
|
if (range[0] === undefined) {
|
|
2861
|
-
if (
|
|
2862
|
-
range[0] = thisSpeed !== zeroSpeed ? thisTime : computeTime(thisSpeed, (thisPosY < zeroPosY ? startY : endY) - thisPosY, thisTime);
|
|
2863
|
-
} else if (startY <= thisPosY && thisPosY <= endY) {
|
|
2925
|
+
if (thisSpeed > 0 && endY >= thisPosY || thisSpeed < 0 && startY <= thisPosY) {
|
|
2864
2926
|
range[0] = thisTime;
|
|
2865
2927
|
}
|
|
2866
2928
|
}
|
|
2867
2929
|
if (range[0] !== undefined) {
|
|
2868
|
-
if (
|
|
2869
|
-
range[1] =
|
|
2930
|
+
if (thisSpeed > 0 && endY <= zeroPosY || thisSpeed < 0 && startY >= zeroPosY) {
|
|
2931
|
+
range[1] = zeroTime;
|
|
2870
2932
|
result.push(range);
|
|
2871
2933
|
if (lineMonotonicity !== 2 /* swinging */) {
|
|
2872
2934
|
return result;
|
|
@@ -2875,15 +2937,13 @@ class JudgeLine {
|
|
|
2875
2937
|
}
|
|
2876
2938
|
}
|
|
2877
2939
|
if (range[0] === undefined) {
|
|
2878
|
-
if (
|
|
2879
|
-
range[0] = zeroSpeed !== nextSpeed ? zeroTime : computeTime(nextSpeed, (zeroPosY < nextPosY ? startY : endY) - zeroPosY, zeroTime);
|
|
2880
|
-
} else if (startY <= zeroPosY && zeroPosY <= endY) {
|
|
2940
|
+
if (nextSpeed > 0 && endY >= zeroPosY || nextSpeed < 0 && startY <= zeroPosY) {
|
|
2881
2941
|
range[0] = zeroTime;
|
|
2882
2942
|
}
|
|
2883
2943
|
}
|
|
2884
2944
|
if (range[0] !== undefined) {
|
|
2885
|
-
if (
|
|
2886
|
-
range[1] =
|
|
2945
|
+
if (nextSpeed > 0 && endY <= nextPosY || nextSpeed < 0 && startY >= nextPosY) {
|
|
2946
|
+
range[1] = nextTime;
|
|
2887
2947
|
result.push(range);
|
|
2888
2948
|
if (lineMonotonicity !== 2 /* swinging */) {
|
|
2889
2949
|
return result;
|
|
@@ -2893,15 +2953,24 @@ class JudgeLine {
|
|
|
2893
2953
|
}
|
|
2894
2954
|
} else {
|
|
2895
2955
|
if (range[0] === undefined) {
|
|
2896
|
-
if (
|
|
2897
|
-
range[0] = thisSpeed !== nextSpeed ? thisTime : computeTime(thisSpeed,
|
|
2898
|
-
} else if (startY <= thisPosY &&
|
|
2956
|
+
if (thisSpeed > 0 && endY >= thisPosY && startY < nextPosY) {
|
|
2957
|
+
range[0] = thisSpeed !== nextSpeed ? thisTime : computeTime(thisSpeed, startY - thisPosY, thisTime);
|
|
2958
|
+
} else if (thisSpeed < 0 && startY <= thisPosY && endY > nextPosY) {
|
|
2959
|
+
range[0] = thisSpeed !== nextSpeed ? thisTime : computeTime(thisSpeed, endY - thisPosY, thisTime);
|
|
2960
|
+
} else if (thisSpeed === 0 && startY <= thisPosY && thisPosY <= endY) {
|
|
2899
2961
|
range[0] = thisTime;
|
|
2900
2962
|
}
|
|
2901
2963
|
}
|
|
2902
2964
|
if (range[0] !== undefined) {
|
|
2903
|
-
if (
|
|
2904
|
-
range[1] = thisSpeed !== nextSpeed ? nextTime : computeTime(thisSpeed,
|
|
2965
|
+
if (thisSpeed > 0 && endY <= nextPosY) {
|
|
2966
|
+
range[1] = thisSpeed !== nextSpeed ? nextTime : computeTime(thisSpeed, endY - thisPosY, thisTime);
|
|
2967
|
+
result.push(range);
|
|
2968
|
+
if (lineMonotonicity !== 2 /* swinging */) {
|
|
2969
|
+
return result;
|
|
2970
|
+
}
|
|
2971
|
+
range = [undefined, undefined];
|
|
2972
|
+
} else if (thisSpeed < 0 && startY >= thisPosY) {
|
|
2973
|
+
range[1] = thisSpeed !== nextSpeed ? nextTime : computeTime(thisSpeed, startY - thisPosY, thisTime);
|
|
2905
2974
|
result.push(range);
|
|
2906
2975
|
if (lineMonotonicity !== 2 /* swinging */) {
|
|
2907
2976
|
return result;
|
|
@@ -2934,6 +3003,18 @@ class JudgeLine {
|
|
|
2934
3003
|
}
|
|
2935
3004
|
return current;
|
|
2936
3005
|
}
|
|
3006
|
+
getStackedValueBySeconds(type, beats, seconds, timeCalculator, usePrev = false) {
|
|
3007
|
+
const length = this.eventLayers.length;
|
|
3008
|
+
let current = 0;
|
|
3009
|
+
for (let index = 0;index < length; index++) {
|
|
3010
|
+
const layer = this.eventLayers[index];
|
|
3011
|
+
if (!layer || !layer[type]) {
|
|
3012
|
+
break;
|
|
3013
|
+
}
|
|
3014
|
+
current += layer[type].getValueAtBySecs(beats, seconds, timeCalculator, usePrev);
|
|
3015
|
+
}
|
|
3016
|
+
return current;
|
|
3017
|
+
}
|
|
2937
3018
|
getNNList(speed, yOffset, isHold, initsJump) {
|
|
2938
3019
|
const lists = isHold ? this.hnLists : this.nnLists;
|
|
2939
3020
|
const medianYOffset = getRangeMedian(yOffset);
|
|
@@ -3190,6 +3271,9 @@ class TimeCalculator {
|
|
|
3190
3271
|
duration;
|
|
3191
3272
|
constructor() {}
|
|
3192
3273
|
initSequence() {
|
|
3274
|
+
if (!this.bpmList || !this.duration) {
|
|
3275
|
+
throw new Error("TimeCalculator: bpmList and duration must be set before initSequence");
|
|
3276
|
+
}
|
|
3193
3277
|
const bpmList = this.bpmList;
|
|
3194
3278
|
this.bpmSequence = new BPMSequence(bpmList, this.duration);
|
|
3195
3279
|
}
|
|
@@ -3211,7 +3295,7 @@ class TimeCalculator {
|
|
|
3211
3295
|
}
|
|
3212
3296
|
}
|
|
3213
3297
|
// src/version.ts
|
|
3214
|
-
var VERSION =
|
|
3298
|
+
var VERSION = 213;
|
|
3215
3299
|
var SCHEMA = "https://cdn.jsdelivr.net/npm/kipphi@2.1.0/chartType2.schema.json";
|
|
3216
3300
|
|
|
3217
3301
|
// src/chart.ts
|
|
@@ -3251,7 +3335,7 @@ class Chart {
|
|
|
3251
3335
|
}
|
|
3252
3336
|
static fromRPEJSON(data, duration) {
|
|
3253
3337
|
const chart = new Chart;
|
|
3254
|
-
chart.judgeLineGroups = data.judgeLineGroup.map((group) => new JudgeLineGroup(group));
|
|
3338
|
+
chart.judgeLineGroups = (data.judgeLineGroup || ["Default"]).map((group) => new JudgeLineGroup(group));
|
|
3255
3339
|
chart.name = data.META.name;
|
|
3256
3340
|
chart.level = data.META.level;
|
|
3257
3341
|
chart.offset = data.META.offset;
|
|
@@ -3342,6 +3426,13 @@ class Chart {
|
|
|
3342
3426
|
}
|
|
3343
3427
|
chart.templateEasingLib.implement(easingData.name, sequence);
|
|
3344
3428
|
}
|
|
3429
|
+
for (let i = 0;i < len; i++) {
|
|
3430
|
+
const easingData = templateEasings[i];
|
|
3431
|
+
const sequence = chart.sequenceMap.get(easingData.content);
|
|
3432
|
+
if (sequence.hasReferenceTo(sequence)) {
|
|
3433
|
+
throw err.TEMPLATE_EASING_CIRCULAR_REFERENCE(easingData.name);
|
|
3434
|
+
}
|
|
3435
|
+
}
|
|
3345
3436
|
chart.templateEasingLib.check();
|
|
3346
3437
|
for (const lineData of data.orphanLines) {
|
|
3347
3438
|
const line = JudgeLine.fromKPAJSON(data.version, chart, lineData.id, lineData, chart.templateEasingLib, chart.timeCalculator);
|
|
@@ -4156,6 +4247,13 @@ class EventNodeEvaluatorChangeOperation extends Operation {
|
|
|
4156
4247
|
this.node = node;
|
|
4157
4248
|
this.value = value;
|
|
4158
4249
|
this.originalValue = this.node.evaluator;
|
|
4250
|
+
const seq = node.parentSeq;
|
|
4251
|
+
if (seq.type === 5 /* easing */ && value instanceof EasedEvaluator && value.easing instanceof TemplateEasing) {
|
|
4252
|
+
const circular = TemplateEasing.checkCircularReference(seq, value.easing);
|
|
4253
|
+
if (circular) {
|
|
4254
|
+
throw err.TEMPLATE_EASING_CIRCULAR_REFERENCE(value.easing.name);
|
|
4255
|
+
}
|
|
4256
|
+
}
|
|
4159
4257
|
}
|
|
4160
4258
|
do() {
|
|
4161
4259
|
this.node.evaluator = this.value;
|
|
@@ -5194,14 +5292,34 @@ class RPEChartCompiler {
|
|
|
5194
5292
|
chart;
|
|
5195
5293
|
sequenceMap = new Map;
|
|
5196
5294
|
interpolationStep = [0, 1, 16];
|
|
5295
|
+
deletesEmptyLines = true;
|
|
5197
5296
|
constructor(chart2) {
|
|
5198
5297
|
this.chart = chart2;
|
|
5199
5298
|
}
|
|
5200
5299
|
compileChart() {
|
|
5201
|
-
console.time("compileChart");
|
|
5202
5300
|
const chart2 = this.chart;
|
|
5203
5301
|
const judgeLineGroups = chart2.judgeLineGroups.map((group) => group.name);
|
|
5204
|
-
const
|
|
5302
|
+
const filter = this.deletesEmptyLines ? (line2) => {
|
|
5303
|
+
return line2.nnLists.size > 0 || line2.hnLists.size > 0 || line2.eventLayers.length > 0 || ["moveX", "moveY", "rotate", "alpha"].some((evType) => {
|
|
5304
|
+
const seq = line2.eventLayers[0][evType];
|
|
5305
|
+
let node = seq.head.next;
|
|
5306
|
+
for (let i = 0;i < 2; i++) {
|
|
5307
|
+
const endNode = node.next;
|
|
5308
|
+
if (node.value !== 0) {
|
|
5309
|
+
return true;
|
|
5310
|
+
}
|
|
5311
|
+
if (endNode.type === 1 /* TAIL */) {
|
|
5312
|
+
return false;
|
|
5313
|
+
}
|
|
5314
|
+
if (endNode.value !== 0) {
|
|
5315
|
+
return true;
|
|
5316
|
+
}
|
|
5317
|
+
node = endNode.next;
|
|
5318
|
+
}
|
|
5319
|
+
return true;
|
|
5320
|
+
});
|
|
5321
|
+
} : () => true;
|
|
5322
|
+
const judgeLineList = chart2.judgeLines.filter(filter).map((line2) => this.compileJudgeLine(line2));
|
|
5205
5323
|
const BPMList = chart2.timeCalculator.dump();
|
|
5206
5324
|
const META = {
|
|
5207
5325
|
RPEVersion: 1,
|
|
@@ -5240,7 +5358,6 @@ class RPEChartCompiler {
|
|
|
5240
5358
|
lineData.attachUI = uiName;
|
|
5241
5359
|
}
|
|
5242
5360
|
}
|
|
5243
|
-
console.timeEnd("compileChart");
|
|
5244
5361
|
return {
|
|
5245
5362
|
BPMList,
|
|
5246
5363
|
META,
|
|
@@ -5248,8 +5365,8 @@ class RPEChartCompiler {
|
|
|
5248
5365
|
judgeLineGroup: judgeLineGroups,
|
|
5249
5366
|
multiLineString: "",
|
|
5250
5367
|
multiScale: 1,
|
|
5251
|
-
chartTime: chart2.
|
|
5252
|
-
kpaChartTime: chart2.
|
|
5368
|
+
chartTime: chart2.rpeChartingSeconds,
|
|
5369
|
+
kpaChartTime: chart2.chartingSeconds
|
|
5253
5370
|
};
|
|
5254
5371
|
}
|
|
5255
5372
|
compileJudgeLine(judgeLine) {
|
|
@@ -5296,7 +5413,7 @@ class RPEChartCompiler {
|
|
|
5296
5413
|
bezierPoints: innerEasing instanceof BezierEasing ? [innerEasing.cp1[0], innerEasing.cp1[1], innerEasing.cp2[0], innerEasing.cp2[1]] : [0, 0, 0, 0],
|
|
5297
5414
|
easingLeft: isSegmented ? easing.left : 0,
|
|
5298
5415
|
easingRight: isSegmented ? easing.right : 1,
|
|
5299
|
-
easingType: easing instanceof NormalEasing ? easing.rpeId ?? 1 : null,
|
|
5416
|
+
easingType: isSegmented ? easing.easing instanceof NormalEasing ? easing.easing.rpeId ?? 1 : null : easing instanceof NormalEasing ? easing.rpeId ?? 1 : null,
|
|
5300
5417
|
end,
|
|
5301
5418
|
endTime: endNode.time,
|
|
5302
5419
|
linkgroup: 0,
|