sonolus.py 0.1.2__py3-none-any.whl → 0.1.4__py3-none-any.whl
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.
Potentially problematic release.
This version of sonolus.py might be problematic. Click here for more details.
- sonolus/backend/allocate.py +125 -51
- sonolus/backend/blocks.py +756 -756
- sonolus/backend/coalesce.py +85 -0
- sonolus/backend/constant_evaluation.py +374 -0
- sonolus/backend/dead_code.py +80 -0
- sonolus/backend/dominance.py +111 -0
- sonolus/backend/excepthook.py +37 -37
- sonolus/backend/finalize.py +69 -69
- sonolus/backend/flow.py +121 -92
- sonolus/backend/inlining.py +150 -0
- sonolus/backend/ir.py +5 -3
- sonolus/backend/liveness.py +173 -0
- sonolus/backend/mode.py +24 -24
- sonolus/backend/node.py +40 -40
- sonolus/backend/ops.py +197 -197
- sonolus/backend/optimize.py +37 -9
- sonolus/backend/passes.py +52 -6
- sonolus/backend/simplify.py +47 -30
- sonolus/backend/ssa.py +187 -0
- sonolus/backend/utils.py +48 -48
- sonolus/backend/visitor.py +892 -880
- sonolus/build/cli.py +7 -1
- sonolus/build/compile.py +88 -90
- sonolus/build/engine.py +55 -5
- sonolus/build/level.py +24 -23
- sonolus/build/node.py +43 -43
- sonolus/script/archetype.py +23 -6
- sonolus/script/array.py +2 -2
- sonolus/script/bucket.py +191 -191
- sonolus/script/callbacks.py +127 -115
- sonolus/script/comptime.py +1 -1
- sonolus/script/containers.py +23 -0
- sonolus/script/debug.py +19 -3
- sonolus/script/easing.py +323 -0
- sonolus/script/effect.py +131 -131
- sonolus/script/engine.py +37 -1
- sonolus/script/globals.py +269 -269
- sonolus/script/graphics.py +200 -150
- sonolus/script/instruction.py +151 -0
- sonolus/script/internal/__init__.py +5 -5
- sonolus/script/internal/builtin_impls.py +144 -144
- sonolus/script/internal/context.py +12 -4
- sonolus/script/internal/descriptor.py +17 -17
- sonolus/script/internal/introspection.py +14 -14
- sonolus/script/internal/native.py +40 -38
- sonolus/script/internal/value.py +3 -3
- sonolus/script/interval.py +120 -112
- sonolus/script/iterator.py +214 -211
- sonolus/script/math.py +30 -1
- sonolus/script/num.py +1 -1
- sonolus/script/options.py +191 -191
- sonolus/script/particle.py +157 -157
- sonolus/script/pointer.py +30 -30
- sonolus/script/{preview.py → print.py} +81 -81
- sonolus/script/random.py +14 -0
- sonolus/script/range.py +58 -58
- sonolus/script/record.py +3 -3
- sonolus/script/runtime.py +45 -6
- sonolus/script/sprite.py +333 -333
- sonolus/script/text.py +407 -407
- sonolus/script/timing.py +42 -42
- sonolus/script/transform.py +77 -23
- sonolus/script/ui.py +160 -160
- sonolus/script/vec.py +81 -72
- {sonolus_py-0.1.2.dist-info → sonolus_py-0.1.4.dist-info}/METADATA +1 -2
- sonolus_py-0.1.4.dist-info/RECORD +84 -0
- {sonolus_py-0.1.2.dist-info → sonolus_py-0.1.4.dist-info}/WHEEL +1 -1
- {sonolus_py-0.1.2.dist-info → sonolus_py-0.1.4.dist-info}/licenses/LICENSE +21 -21
- sonolus/build/defaults.py +0 -32
- sonolus/script/icon.py +0 -73
- sonolus_py-0.1.2.dist-info/RECORD +0 -76
- {sonolus_py-0.1.2.dist-info → sonolus_py-0.1.4.dist-info}/entry_points.txt +0 -0
sonolus/script/timing.py
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
|
-
from sonolus.backend.ops import Op
|
|
2
|
-
from sonolus.script.internal.native import native_function
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
@native_function(Op.BeatToBPM)
|
|
6
|
-
def beat_to_bpm(beat: float) -> float:
|
|
7
|
-
raise NotImplementedError
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
@native_function(Op.BeatToTime)
|
|
11
|
-
def beat_to_time(beat: float) -> float:
|
|
12
|
-
raise NotImplementedError
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@native_function(Op.BeatToStartingBeat)
|
|
16
|
-
def beat_to_starting_beat(beat: float) -> float:
|
|
17
|
-
raise NotImplementedError
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
@native_function(Op.BeatToStartingTime)
|
|
21
|
-
def beat_to_starting_time(beat: float) -> float:
|
|
22
|
-
raise NotImplementedError
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
@native_function(Op.TimeToScaledTime)
|
|
26
|
-
def time_to_scaled_time(time: float) -> float:
|
|
27
|
-
raise NotImplementedError
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
@native_function(Op.TimeToStartingScaledTime)
|
|
31
|
-
def time_to_starting_scaled_time(time: float) -> float:
|
|
32
|
-
raise NotImplementedError
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
@native_function(Op.TimeToStartingTime)
|
|
36
|
-
def time_to_starting_time(time: float) -> float:
|
|
37
|
-
raise NotImplementedError
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
@native_function(Op.TimeToTimeScale)
|
|
41
|
-
def time_to_timescale(time: float) -> float:
|
|
42
|
-
raise NotImplementedError
|
|
1
|
+
from sonolus.backend.ops import Op
|
|
2
|
+
from sonolus.script.internal.native import native_function
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@native_function(Op.BeatToBPM)
|
|
6
|
+
def beat_to_bpm(beat: float) -> float:
|
|
7
|
+
raise NotImplementedError
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@native_function(Op.BeatToTime)
|
|
11
|
+
def beat_to_time(beat: float) -> float:
|
|
12
|
+
raise NotImplementedError
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@native_function(Op.BeatToStartingBeat)
|
|
16
|
+
def beat_to_starting_beat(beat: float) -> float:
|
|
17
|
+
raise NotImplementedError
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@native_function(Op.BeatToStartingTime)
|
|
21
|
+
def beat_to_starting_time(beat: float) -> float:
|
|
22
|
+
raise NotImplementedError
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@native_function(Op.TimeToScaledTime)
|
|
26
|
+
def time_to_scaled_time(time: float) -> float:
|
|
27
|
+
raise NotImplementedError
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@native_function(Op.TimeToStartingScaledTime)
|
|
31
|
+
def time_to_starting_scaled_time(time: float) -> float:
|
|
32
|
+
raise NotImplementedError
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@native_function(Op.TimeToStartingTime)
|
|
36
|
+
def time_to_starting_time(time: float) -> float:
|
|
37
|
+
raise NotImplementedError
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@native_function(Op.TimeToTimeScale)
|
|
41
|
+
def time_to_timescale(time: float) -> float:
|
|
42
|
+
raise NotImplementedError
|
sonolus/script/transform.py
CHANGED
|
@@ -16,93 +16,147 @@ class Transform2d(Record):
|
|
|
16
16
|
a12: float
|
|
17
17
|
a20: float
|
|
18
18
|
a21: float
|
|
19
|
+
a22: float
|
|
19
20
|
|
|
20
21
|
@classmethod
|
|
21
22
|
def new(cls) -> Self:
|
|
23
|
+
"""Create a new identity transform."""
|
|
22
24
|
return cls(
|
|
23
25
|
1, 0, 0,
|
|
24
26
|
0, 1, 0,
|
|
25
|
-
0, 0,
|
|
27
|
+
0, 0, 1,
|
|
26
28
|
)
|
|
27
29
|
|
|
28
30
|
def _compose(self,
|
|
29
31
|
b00: float, b01: float, b02: float,
|
|
30
32
|
b10: float, b11: float, b12: float,
|
|
31
|
-
b20: float, b21: float,
|
|
33
|
+
b20: float, b21: float, b22: float,
|
|
32
34
|
) -> Self:
|
|
33
35
|
"""Multiply the matrix with another matrix on the left."""
|
|
34
36
|
a00 = self.a00 * b00 + self.a10 * b01 + self.a20 * b02
|
|
35
37
|
a01 = self.a01 * b00 + self.a11 * b01 + self.a21 * b02
|
|
36
|
-
a02 = self.a02 * b00 + self.a12 * b01 + b02
|
|
38
|
+
a02 = self.a02 * b00 + self.a12 * b01 + self.a22 * b02
|
|
37
39
|
a10 = self.a00 * b10 + self.a10 * b11 + self.a20 * b12
|
|
38
40
|
a11 = self.a01 * b10 + self.a11 * b11 + self.a21 * b12
|
|
39
|
-
a12 = self.a02 * b10 + self.a12 * b11 + b12
|
|
40
|
-
a20 = self.a00 * b20 + self.a10 * b21 +
|
|
41
|
-
a21 = self.a01 * b20 + self.a11 * b21 +
|
|
42
|
-
a22 = self.a02 * b20 + self.a12 * b21 +
|
|
41
|
+
a12 = self.a02 * b10 + self.a12 * b11 + self.a22 * b12
|
|
42
|
+
a20 = self.a00 * b20 + self.a10 * b21 + self.a20 * b22
|
|
43
|
+
a21 = self.a01 * b20 + self.a11 * b21 + self.a21 * b22
|
|
44
|
+
a22 = self.a02 * b20 + self.a12 * b21 + self.a22 * b22
|
|
43
45
|
return Transform2d(
|
|
44
|
-
a00
|
|
45
|
-
a10
|
|
46
|
-
a20
|
|
46
|
+
a00, a01, a02,
|
|
47
|
+
a10, a11, a12,
|
|
48
|
+
a20, a21, a22,
|
|
47
49
|
)
|
|
48
50
|
|
|
49
51
|
def translate(self, translation: Vec2, /) -> Self:
|
|
52
|
+
"""Translate along the x and y axes."""
|
|
50
53
|
return self._compose(
|
|
51
54
|
1, 0, translation.x,
|
|
52
55
|
0, 1, translation.y,
|
|
53
|
-
0, 0,
|
|
56
|
+
0, 0, 1,
|
|
54
57
|
)
|
|
55
58
|
|
|
56
59
|
def scale(self, factor: Vec2, /) -> Self:
|
|
60
|
+
"""Scale around the origin."""
|
|
57
61
|
return self._compose(
|
|
58
62
|
factor.x, 0, 0,
|
|
59
63
|
0, factor.y, 0,
|
|
60
|
-
0, 0,
|
|
64
|
+
0, 0, 1,
|
|
61
65
|
)
|
|
62
66
|
|
|
63
|
-
def
|
|
67
|
+
def scale_about(self, factor: Vec2, /, pivot: Vec2) -> Self:
|
|
68
|
+
"""Scale around the pivot."""
|
|
69
|
+
return self.translate(-pivot).scale(factor).translate(pivot)
|
|
70
|
+
|
|
71
|
+
def rotate(self, angle: float, /) -> Self:
|
|
72
|
+
"""Rotate around the origin."""
|
|
64
73
|
c = cos(angle)
|
|
65
74
|
s = sin(angle)
|
|
66
75
|
return self._compose(
|
|
67
76
|
c, -s, 0,
|
|
68
77
|
s, c, 0,
|
|
69
|
-
0, 0,
|
|
78
|
+
0, 0, 1,
|
|
70
79
|
)
|
|
71
80
|
|
|
72
|
-
def
|
|
81
|
+
def rotate_about(self, angle: float, /, pivot: Vec2) -> Self:
|
|
82
|
+
"""Rotate around the pivot."""
|
|
83
|
+
return self.translate(-pivot).rotate(angle).translate(pivot)
|
|
84
|
+
|
|
85
|
+
def shear_x(self, m: float, /) -> Self:
|
|
73
86
|
"""Shear along the x-axis."""
|
|
74
87
|
return self._compose(
|
|
75
88
|
1, m, 0,
|
|
76
89
|
0, 1, 0,
|
|
77
|
-
0, 0,
|
|
90
|
+
0, 0, 1,
|
|
78
91
|
)
|
|
79
92
|
|
|
80
|
-
def shear_y(self, m: float) -> Self:
|
|
93
|
+
def shear_y(self, m: float, /) -> Self:
|
|
81
94
|
"""Shear along the y-axis."""
|
|
82
95
|
return self._compose(
|
|
83
96
|
1, 0, 0,
|
|
84
97
|
m, 1, 0,
|
|
85
|
-
0, 0,
|
|
98
|
+
0, 0, 1,
|
|
86
99
|
)
|
|
87
100
|
|
|
88
|
-
def perspective_vanish_y(self, y: float) -> Self:
|
|
101
|
+
def perspective_vanish_y(self, y: float, /) -> Self:
|
|
102
|
+
"""Apply perspective vanish along the y-axis with vanish point at the given y coordinate.
|
|
103
|
+
|
|
104
|
+
Note: Conveniently, the inverse can be obtained simply by negating the argument.
|
|
105
|
+
"""
|
|
89
106
|
return self._compose(
|
|
90
107
|
1, 0, 0,
|
|
91
108
|
0, 1, 0,
|
|
92
|
-
0, 1 / y,
|
|
109
|
+
0, 1 / y, 1,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
def perspective(self, foreground_y, vanishing_point: Vec2, /) -> Self:
|
|
113
|
+
"""Apply a perspective transformation.
|
|
114
|
+
|
|
115
|
+
When the original y is 0, the transformed x coordinate will be unchanged and the y coordinates will
|
|
116
|
+
be equal to foreground_y.
|
|
117
|
+
As the original y coordinate approaches infinity in the direction of the vanishing point,
|
|
118
|
+
the transformed x and y coordinates will approach the vanishing point.
|
|
119
|
+
"""
|
|
120
|
+
return (
|
|
121
|
+
self
|
|
122
|
+
.perspective_vanish_y(vanishing_point.y - foreground_y)
|
|
123
|
+
.shear_x(vanishing_point.x / (vanishing_point.y - foreground_y))
|
|
124
|
+
.translate(Vec2(0, foreground_y))
|
|
93
125
|
)
|
|
94
126
|
|
|
95
|
-
def
|
|
127
|
+
def inverse_perspective(self, foreground_y, vanishing_point: Vec2, /) -> Self:
|
|
128
|
+
"""Apply the inverse of a perspective transformation."""
|
|
129
|
+
return (
|
|
130
|
+
self
|
|
131
|
+
.translate(Vec2(0, -foreground_y))
|
|
132
|
+
.shear_x(-vanishing_point.x / (vanishing_point.y - foreground_y))
|
|
133
|
+
.perspective_vanish_y(-vanishing_point.y + foreground_y)
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
def normalize(self):
|
|
137
|
+
"""Normalize the transform to have a 1 in the bottom right corner."""
|
|
138
|
+
return Transform2d(
|
|
139
|
+
self.a00 / self.a22, self.a01 / self.a22, self.a02 / self.a22,
|
|
140
|
+
self.a10 / self.a22, self.a11 / self.a22, self.a12 / self.a22,
|
|
141
|
+
self.a20 / self.a22, self.a21 / self.a22, 1,
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
def compose(self, other: Self, /) -> Self:
|
|
145
|
+
"""Compose with another transform which is applied after this transform."""
|
|
96
146
|
return self._compose(
|
|
97
147
|
other.a00, other.a01, other.a02,
|
|
98
148
|
other.a10, other.a11, other.a12,
|
|
99
|
-
other.a20, other.a21,
|
|
149
|
+
other.a20, other.a21, other.a22,
|
|
100
150
|
)
|
|
101
151
|
|
|
152
|
+
def compose_before(self, other: Self, /) -> Self:
|
|
153
|
+
"""Compose with another transform which is applied before this transform."""
|
|
154
|
+
return other.compose(self)
|
|
155
|
+
|
|
102
156
|
def transform_vec(self, v: Vec2) -> Vec2:
|
|
103
157
|
x = self.a00 * v.x + self.a01 * v.y + self.a02
|
|
104
158
|
y = self.a10 * v.x + self.a11 * v.y + self.a12
|
|
105
|
-
w = self.a20 * v.x + self.a21 * v.y +
|
|
159
|
+
w = self.a20 * v.x + self.a21 * v.y + self.a22
|
|
106
160
|
return Vec2(x / w, y / w)
|
|
107
161
|
|
|
108
162
|
def transform_quad(self, quad: QuadLike) -> Quad:
|
sonolus/script/ui.py
CHANGED
|
@@ -1,160 +1,160 @@
|
|
|
1
|
-
from dataclasses import dataclass, field
|
|
2
|
-
from typing import Literal
|
|
3
|
-
|
|
4
|
-
UiMetric = Literal[
|
|
5
|
-
"arcade",
|
|
6
|
-
"arcadePercentage",
|
|
7
|
-
"accuracy",
|
|
8
|
-
"accuracyPercentage",
|
|
9
|
-
"life",
|
|
10
|
-
"perfect",
|
|
11
|
-
"perfectPercentage",
|
|
12
|
-
"greatGoodMiss",
|
|
13
|
-
"greatGoodMissPercentage",
|
|
14
|
-
"miss",
|
|
15
|
-
"missPercentage",
|
|
16
|
-
"errorHeatmap",
|
|
17
|
-
]
|
|
18
|
-
|
|
19
|
-
UiJudgmentErrorStyle = Literal[
|
|
20
|
-
"none",
|
|
21
|
-
"plus",
|
|
22
|
-
"minus",
|
|
23
|
-
"arrowUp",
|
|
24
|
-
"arrowDown",
|
|
25
|
-
"arrowLeft",
|
|
26
|
-
"arrowRight",
|
|
27
|
-
"triangleUp",
|
|
28
|
-
"triangleDown",
|
|
29
|
-
"triangleLeft",
|
|
30
|
-
"triangleRight",
|
|
31
|
-
]
|
|
32
|
-
|
|
33
|
-
UiJudgmentErrorPlacement = Literal["both", "left", "right"]
|
|
34
|
-
|
|
35
|
-
EaseType = Literal[
|
|
36
|
-
"linear",
|
|
37
|
-
"none",
|
|
38
|
-
"inSine",
|
|
39
|
-
"inQuad",
|
|
40
|
-
"inCubic",
|
|
41
|
-
"inQuart",
|
|
42
|
-
"inQuint",
|
|
43
|
-
"inExpo",
|
|
44
|
-
"inCirc",
|
|
45
|
-
"inBack",
|
|
46
|
-
"inElastic",
|
|
47
|
-
"outSine",
|
|
48
|
-
"outQuad",
|
|
49
|
-
"outCubic",
|
|
50
|
-
"outQuart",
|
|
51
|
-
"outQuint",
|
|
52
|
-
"outExpo",
|
|
53
|
-
"outCirc",
|
|
54
|
-
"outBack",
|
|
55
|
-
"outElastic",
|
|
56
|
-
"inOutSine",
|
|
57
|
-
"inOutQuad",
|
|
58
|
-
"inOutCubic",
|
|
59
|
-
"inOutQuart",
|
|
60
|
-
"inOutQuint",
|
|
61
|
-
"inOutExpo",
|
|
62
|
-
"inOutCirc",
|
|
63
|
-
"inOutBack",
|
|
64
|
-
"inOutElastic",
|
|
65
|
-
"outInSine",
|
|
66
|
-
"outInQuad",
|
|
67
|
-
"outInCubic",
|
|
68
|
-
"outInQuart",
|
|
69
|
-
"outInQuint",
|
|
70
|
-
"outInExpo",
|
|
71
|
-
"outInCirc",
|
|
72
|
-
"outInBack",
|
|
73
|
-
"outInElastic",
|
|
74
|
-
]
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
@dataclass
|
|
78
|
-
class UiAnimationTween:
|
|
79
|
-
start: float
|
|
80
|
-
end: float
|
|
81
|
-
duration: float
|
|
82
|
-
ease: EaseType
|
|
83
|
-
|
|
84
|
-
def to_dict(self):
|
|
85
|
-
return {
|
|
86
|
-
"from": self.start,
|
|
87
|
-
"to": self.end,
|
|
88
|
-
"duration": self.duration,
|
|
89
|
-
"ease": self.ease,
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
@dataclass
|
|
94
|
-
class UiAnimation:
|
|
95
|
-
scale: UiAnimationTween = field(default_factory=lambda: UiAnimationTween(1, 1, 0, "none"))
|
|
96
|
-
alpha: UiAnimationTween = field(default_factory=lambda: UiAnimationTween(1, 0, 0.2, "outCubic"))
|
|
97
|
-
|
|
98
|
-
def to_dict(self):
|
|
99
|
-
return {
|
|
100
|
-
"scale": self.scale.to_dict(),
|
|
101
|
-
"alpha": self.alpha.to_dict(),
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
@dataclass
|
|
106
|
-
class UiVisibility:
|
|
107
|
-
scale: float = 1.0
|
|
108
|
-
alpha: float = 1.0
|
|
109
|
-
|
|
110
|
-
def to_dict(self):
|
|
111
|
-
return {
|
|
112
|
-
"scale": self.scale,
|
|
113
|
-
"alpha": self.alpha,
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
@dataclass
|
|
118
|
-
class UiConfig:
|
|
119
|
-
scope: str | None = None
|
|
120
|
-
primary_metric: UiMetric = "arcade"
|
|
121
|
-
secondary_metric: UiMetric = "life"
|
|
122
|
-
menu_visibility: UiVisibility = field(default_factory=UiVisibility)
|
|
123
|
-
judgment_visibility: UiVisibility = field(default_factory=UiVisibility)
|
|
124
|
-
combo_visibility: UiVisibility = field(default_factory=UiVisibility)
|
|
125
|
-
primary_metric_visibility: UiVisibility = field(default_factory=UiVisibility)
|
|
126
|
-
secondary_metric_visibility: UiVisibility = field(default_factory=UiVisibility)
|
|
127
|
-
progress_visibility: UiVisibility = field(default_factory=UiVisibility)
|
|
128
|
-
tutorial_navigation_visibility: UiVisibility = field(default_factory=UiVisibility)
|
|
129
|
-
tutorial_instruction_visibility: UiVisibility = field(default_factory=UiVisibility)
|
|
130
|
-
judgment_animation: UiAnimation = field(default_factory=UiAnimation)
|
|
131
|
-
combo_animation: UiAnimation = field(
|
|
132
|
-
default_factory=lambda: UiAnimation(
|
|
133
|
-
scale=UiAnimationTween(1.2, 1, 0.2, "inCubic"), alpha=UiAnimationTween(1, 1, 0, "none")
|
|
134
|
-
)
|
|
135
|
-
)
|
|
136
|
-
judgment_error_style: UiJudgmentErrorStyle = "none"
|
|
137
|
-
judgment_error_placement: UiJudgmentErrorPlacement = "both"
|
|
138
|
-
judgment_error_min: float = 0.0
|
|
139
|
-
|
|
140
|
-
def to_dict(self):
|
|
141
|
-
data = {
|
|
142
|
-
"primaryMetric": self.primary_metric,
|
|
143
|
-
"secondaryMetric": self.secondary_metric,
|
|
144
|
-
"menuVisibility": self.menu_visibility.to_dict(),
|
|
145
|
-
"judgmentVisibility": self.judgment_visibility.to_dict(),
|
|
146
|
-
"comboVisibility": self.combo_visibility.to_dict(),
|
|
147
|
-
"primaryMetricVisibility": self.primary_metric_visibility.to_dict(),
|
|
148
|
-
"secondaryMetricVisibility": self.secondary_metric_visibility.to_dict(),
|
|
149
|
-
"progressVisibility": self.progress_visibility.to_dict(),
|
|
150
|
-
"tutorialNavigationVisibility": self.tutorial_navigation_visibility.to_dict(),
|
|
151
|
-
"tutorialInstructionVisibility": self.tutorial_instruction_visibility.to_dict(),
|
|
152
|
-
"judgmentAnimation": self.judgment_animation.to_dict(),
|
|
153
|
-
"comboAnimation": self.combo_animation.to_dict(),
|
|
154
|
-
"judgmentErrorStyle": self.judgment_error_style,
|
|
155
|
-
"judgmentErrorPlacement": self.judgment_error_placement,
|
|
156
|
-
"judgmentErrorMin": self.judgment_error_min,
|
|
157
|
-
}
|
|
158
|
-
if self.scope is not None:
|
|
159
|
-
data["scope"] = self.scope
|
|
160
|
-
return data
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from typing import Literal
|
|
3
|
+
|
|
4
|
+
UiMetric = Literal[
|
|
5
|
+
"arcade",
|
|
6
|
+
"arcadePercentage",
|
|
7
|
+
"accuracy",
|
|
8
|
+
"accuracyPercentage",
|
|
9
|
+
"life",
|
|
10
|
+
"perfect",
|
|
11
|
+
"perfectPercentage",
|
|
12
|
+
"greatGoodMiss",
|
|
13
|
+
"greatGoodMissPercentage",
|
|
14
|
+
"miss",
|
|
15
|
+
"missPercentage",
|
|
16
|
+
"errorHeatmap",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
UiJudgmentErrorStyle = Literal[
|
|
20
|
+
"none",
|
|
21
|
+
"plus",
|
|
22
|
+
"minus",
|
|
23
|
+
"arrowUp",
|
|
24
|
+
"arrowDown",
|
|
25
|
+
"arrowLeft",
|
|
26
|
+
"arrowRight",
|
|
27
|
+
"triangleUp",
|
|
28
|
+
"triangleDown",
|
|
29
|
+
"triangleLeft",
|
|
30
|
+
"triangleRight",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
UiJudgmentErrorPlacement = Literal["both", "left", "right"]
|
|
34
|
+
|
|
35
|
+
EaseType = Literal[
|
|
36
|
+
"linear",
|
|
37
|
+
"none",
|
|
38
|
+
"inSine",
|
|
39
|
+
"inQuad",
|
|
40
|
+
"inCubic",
|
|
41
|
+
"inQuart",
|
|
42
|
+
"inQuint",
|
|
43
|
+
"inExpo",
|
|
44
|
+
"inCirc",
|
|
45
|
+
"inBack",
|
|
46
|
+
"inElastic",
|
|
47
|
+
"outSine",
|
|
48
|
+
"outQuad",
|
|
49
|
+
"outCubic",
|
|
50
|
+
"outQuart",
|
|
51
|
+
"outQuint",
|
|
52
|
+
"outExpo",
|
|
53
|
+
"outCirc",
|
|
54
|
+
"outBack",
|
|
55
|
+
"outElastic",
|
|
56
|
+
"inOutSine",
|
|
57
|
+
"inOutQuad",
|
|
58
|
+
"inOutCubic",
|
|
59
|
+
"inOutQuart",
|
|
60
|
+
"inOutQuint",
|
|
61
|
+
"inOutExpo",
|
|
62
|
+
"inOutCirc",
|
|
63
|
+
"inOutBack",
|
|
64
|
+
"inOutElastic",
|
|
65
|
+
"outInSine",
|
|
66
|
+
"outInQuad",
|
|
67
|
+
"outInCubic",
|
|
68
|
+
"outInQuart",
|
|
69
|
+
"outInQuint",
|
|
70
|
+
"outInExpo",
|
|
71
|
+
"outInCirc",
|
|
72
|
+
"outInBack",
|
|
73
|
+
"outInElastic",
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@dataclass
|
|
78
|
+
class UiAnimationTween:
|
|
79
|
+
start: float
|
|
80
|
+
end: float
|
|
81
|
+
duration: float
|
|
82
|
+
ease: EaseType
|
|
83
|
+
|
|
84
|
+
def to_dict(self):
|
|
85
|
+
return {
|
|
86
|
+
"from": self.start,
|
|
87
|
+
"to": self.end,
|
|
88
|
+
"duration": self.duration,
|
|
89
|
+
"ease": self.ease,
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@dataclass
|
|
94
|
+
class UiAnimation:
|
|
95
|
+
scale: UiAnimationTween = field(default_factory=lambda: UiAnimationTween(1, 1, 0, "none"))
|
|
96
|
+
alpha: UiAnimationTween = field(default_factory=lambda: UiAnimationTween(1, 0, 0.2, "outCubic"))
|
|
97
|
+
|
|
98
|
+
def to_dict(self):
|
|
99
|
+
return {
|
|
100
|
+
"scale": self.scale.to_dict(),
|
|
101
|
+
"alpha": self.alpha.to_dict(),
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
@dataclass
|
|
106
|
+
class UiVisibility:
|
|
107
|
+
scale: float = 1.0
|
|
108
|
+
alpha: float = 1.0
|
|
109
|
+
|
|
110
|
+
def to_dict(self):
|
|
111
|
+
return {
|
|
112
|
+
"scale": self.scale,
|
|
113
|
+
"alpha": self.alpha,
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@dataclass
|
|
118
|
+
class UiConfig:
|
|
119
|
+
scope: str | None = None
|
|
120
|
+
primary_metric: UiMetric = "arcade"
|
|
121
|
+
secondary_metric: UiMetric = "life"
|
|
122
|
+
menu_visibility: UiVisibility = field(default_factory=UiVisibility)
|
|
123
|
+
judgment_visibility: UiVisibility = field(default_factory=UiVisibility)
|
|
124
|
+
combo_visibility: UiVisibility = field(default_factory=UiVisibility)
|
|
125
|
+
primary_metric_visibility: UiVisibility = field(default_factory=UiVisibility)
|
|
126
|
+
secondary_metric_visibility: UiVisibility = field(default_factory=UiVisibility)
|
|
127
|
+
progress_visibility: UiVisibility = field(default_factory=UiVisibility)
|
|
128
|
+
tutorial_navigation_visibility: UiVisibility = field(default_factory=UiVisibility)
|
|
129
|
+
tutorial_instruction_visibility: UiVisibility = field(default_factory=UiVisibility)
|
|
130
|
+
judgment_animation: UiAnimation = field(default_factory=UiAnimation)
|
|
131
|
+
combo_animation: UiAnimation = field(
|
|
132
|
+
default_factory=lambda: UiAnimation(
|
|
133
|
+
scale=UiAnimationTween(1.2, 1, 0.2, "inCubic"), alpha=UiAnimationTween(1, 1, 0, "none")
|
|
134
|
+
)
|
|
135
|
+
)
|
|
136
|
+
judgment_error_style: UiJudgmentErrorStyle = "none"
|
|
137
|
+
judgment_error_placement: UiJudgmentErrorPlacement = "both"
|
|
138
|
+
judgment_error_min: float = 0.0
|
|
139
|
+
|
|
140
|
+
def to_dict(self):
|
|
141
|
+
data = {
|
|
142
|
+
"primaryMetric": self.primary_metric,
|
|
143
|
+
"secondaryMetric": self.secondary_metric,
|
|
144
|
+
"menuVisibility": self.menu_visibility.to_dict(),
|
|
145
|
+
"judgmentVisibility": self.judgment_visibility.to_dict(),
|
|
146
|
+
"comboVisibility": self.combo_visibility.to_dict(),
|
|
147
|
+
"primaryMetricVisibility": self.primary_metric_visibility.to_dict(),
|
|
148
|
+
"secondaryMetricVisibility": self.secondary_metric_visibility.to_dict(),
|
|
149
|
+
"progressVisibility": self.progress_visibility.to_dict(),
|
|
150
|
+
"tutorialNavigationVisibility": self.tutorial_navigation_visibility.to_dict(),
|
|
151
|
+
"tutorialInstructionVisibility": self.tutorial_instruction_visibility.to_dict(),
|
|
152
|
+
"judgmentAnimation": self.judgment_animation.to_dict(),
|
|
153
|
+
"comboAnimation": self.combo_animation.to_dict(),
|
|
154
|
+
"judgmentErrorStyle": self.judgment_error_style,
|
|
155
|
+
"judgmentErrorPlacement": self.judgment_error_placement,
|
|
156
|
+
"judgmentErrorMin": self.judgment_error_min,
|
|
157
|
+
}
|
|
158
|
+
if self.scope is not None:
|
|
159
|
+
data["scope"] = self.scope
|
|
160
|
+
return data
|