sonolus.py 0.1.3__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 -882
- sonolus/build/cli.py +7 -1
- sonolus/build/compile.py +88 -90
- 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 -127
- 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/globals.py +269 -269
- sonolus/script/graphics.py +200 -150
- sonolus/script/instruction.py +151 -151
- 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 -214
- 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/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 +2 -0
- 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 -78
- {sonolus_py-0.1.3.dist-info → sonolus_py-0.1.4.dist-info}/METADATA +1 -1
- sonolus_py-0.1.4.dist-info/RECORD +84 -0
- {sonolus_py-0.1.3.dist-info → sonolus_py-0.1.4.dist-info}/WHEEL +1 -1
- {sonolus_py-0.1.3.dist-info → sonolus_py-0.1.4.dist-info}/licenses/LICENSE +21 -21
- sonolus_py-0.1.3.dist-info/RECORD +0 -75
- {sonolus_py-0.1.3.dist-info → sonolus_py-0.1.4.dist-info}/entry_points.txt +0 -0
sonolus/script/particle.py
CHANGED
|
@@ -1,157 +1,157 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from dataclasses import dataclass
|
|
4
|
-
from typing import Annotated, Any, NewType, dataclass_transform, get_origin
|
|
5
|
-
|
|
6
|
-
from sonolus.backend.ops import Op
|
|
7
|
-
from sonolus.script.graphics import QuadLike, flatten_quad
|
|
8
|
-
from sonolus.script.internal.introspection import get_field_specifiers
|
|
9
|
-
from sonolus.script.internal.native import native_function
|
|
10
|
-
from sonolus.script.record import Record
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class Particle(Record):
|
|
14
|
-
id: int
|
|
15
|
-
|
|
16
|
-
def is_available(self) -> bool:
|
|
17
|
-
return _has_particle_effect(self.id)
|
|
18
|
-
|
|
19
|
-
def spawn(self, quad: QuadLike, duration: float, loop: bool = False) -> ParticleHandle:
|
|
20
|
-
return ParticleHandle(_spawn_particle_effect(self.id, *flatten_quad(quad), duration, loop))
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class ParticleHandle(Record):
|
|
24
|
-
id: int
|
|
25
|
-
|
|
26
|
-
def move(self, quad: QuadLike) -> None:
|
|
27
|
-
_move_particle_effect(self.id, *flatten_quad(quad))
|
|
28
|
-
|
|
29
|
-
def destroy(self) -> None:
|
|
30
|
-
_destroy_particle_effect(self.id)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
@native_function(Op.HasParticleEffect)
|
|
34
|
-
def _has_particle_effect(particle_id: int) -> bool:
|
|
35
|
-
raise NotImplementedError
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
@native_function(Op.SpawnParticleEffect)
|
|
39
|
-
def _spawn_particle_effect(
|
|
40
|
-
particle_id: int,
|
|
41
|
-
x1: float,
|
|
42
|
-
y1: float,
|
|
43
|
-
x2: float,
|
|
44
|
-
y2: float,
|
|
45
|
-
x3: float,
|
|
46
|
-
y3: float,
|
|
47
|
-
x4: float,
|
|
48
|
-
y4: float,
|
|
49
|
-
duration: float,
|
|
50
|
-
loop: bool,
|
|
51
|
-
) -> int:
|
|
52
|
-
raise NotImplementedError
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
@native_function(Op.MoveParticleEffect)
|
|
56
|
-
def _move_particle_effect(
|
|
57
|
-
handle: int, x1: float, y1: float, x2: float, y2: float, x3: float, y3: float, x4: float, y4: float
|
|
58
|
-
) -> None:
|
|
59
|
-
raise NotImplementedError
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
@native_function(Op.DestroyParticleEffect)
|
|
63
|
-
def _destroy_particle_effect(handle: int) -> None:
|
|
64
|
-
raise NotImplementedError
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
@dataclass
|
|
68
|
-
class ParticleInfo:
|
|
69
|
-
name: str
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def particle(name: str) -> Any:
|
|
73
|
-
return ParticleInfo(name)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
type Particles = NewType("Particles", Any)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
@dataclass_transform()
|
|
80
|
-
def particles[T](cls: type[T]) -> T | Particles:
|
|
81
|
-
if len(cls.__bases__) != 1:
|
|
82
|
-
raise ValueError("Particles class must not inherit from any class (except object)")
|
|
83
|
-
instance = cls()
|
|
84
|
-
names = []
|
|
85
|
-
for i, (name, annotation) in enumerate(get_field_specifiers(cls).items()):
|
|
86
|
-
if get_origin(annotation) is not Annotated:
|
|
87
|
-
raise TypeError(f"Invalid annotation for particles: {annotation}")
|
|
88
|
-
annotation_type = annotation.__args__[0]
|
|
89
|
-
annotation_values = annotation.__metadata__
|
|
90
|
-
if annotation_type is not Particle:
|
|
91
|
-
raise TypeError(f"Invalid annotation for particles: {annotation}, expected annotation of type Particle")
|
|
92
|
-
if len(annotation_values) != 1 or not isinstance(annotation_values[0], ParticleInfo):
|
|
93
|
-
raise TypeError(
|
|
94
|
-
f"Invalid annotation for particles: {annotation}, expected a single string annotation value"
|
|
95
|
-
)
|
|
96
|
-
particle_name = annotation_values[0].name
|
|
97
|
-
names.append(particle_name)
|
|
98
|
-
setattr(instance, name, Particle(i))
|
|
99
|
-
instance._particles_ = names
|
|
100
|
-
instance._is_comptime_value_ = True
|
|
101
|
-
return instance
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
class StandardParticle:
|
|
105
|
-
NOTE_CIRCULAR_TAP_NEUTRAL = Annotated[Particle, particle("#NOTE_CIRCULAR_TAP_NEUTRAL")]
|
|
106
|
-
NOTE_CIRCULAR_TAP_RED = Annotated[Particle, particle("#NOTE_CIRCULAR_TAP_RED")]
|
|
107
|
-
NOTE_CIRCULAR_TAP_GREEN = Annotated[Particle, particle("#NOTE_CIRCULAR_TAP_GREEN")]
|
|
108
|
-
NOTE_CIRCULAR_TAP_BLUE = Annotated[Particle, particle("#NOTE_CIRCULAR_TAP_BLUE")]
|
|
109
|
-
NOTE_CIRCULAR_TAP_YELLOW = Annotated[Particle, particle("#NOTE_CIRCULAR_TAP_YELLOW")]
|
|
110
|
-
NOTE_CIRCULAR_TAP_PURPLE = Annotated[Particle, particle("#NOTE_CIRCULAR_TAP_PURPLE")]
|
|
111
|
-
NOTE_CIRCULAR_TAP_CYAN = Annotated[Particle, particle("#NOTE_CIRCULAR_TAP_CYAN")]
|
|
112
|
-
NOTE_CIRCULAR_ALTERNATIVE_NEUTRAL = Annotated[Particle, particle("#NOTE_CIRCULAR_ALTERNATIVE_NEUTRAL")]
|
|
113
|
-
NOTE_CIRCULAR_ALTERNATIVE_RED = Annotated[Particle, particle("#NOTE_CIRCULAR_ALTERNATIVE_RED")]
|
|
114
|
-
NOTE_CIRCULAR_ALTERNATIVE_GREEN = Annotated[Particle, particle("#NOTE_CIRCULAR_ALTERNATIVE_GREEN")]
|
|
115
|
-
NOTE_CIRCULAR_ALTERNATIVE_BLUE = Annotated[Particle, particle("#NOTE_CIRCULAR_ALTERNATIVE_BLUE")]
|
|
116
|
-
NOTE_CIRCULAR_ALTERNATIVE_YELLOW = Annotated[Particle, particle("#NOTE_CIRCULAR_ALTERNATIVE_YELLOW")]
|
|
117
|
-
NOTE_CIRCULAR_ALTERNATIVE_PURPLE = Annotated[Particle, particle("#NOTE_CIRCULAR_ALTERNATIVE_PURPLE")]
|
|
118
|
-
NOTE_CIRCULAR_ALTERNATIVE_CYAN = Annotated[Particle, particle("#NOTE_CIRCULAR_ALTERNATIVE_CYAN")]
|
|
119
|
-
NOTE_CIRCULAR_HOLD_NEUTRAL = Annotated[Particle, particle("#NOTE_CIRCULAR_HOLD_NEUTRAL")]
|
|
120
|
-
NOTE_CIRCULAR_HOLD_RED = Annotated[Particle, particle("#NOTE_CIRCULAR_HOLD_RED")]
|
|
121
|
-
NOTE_CIRCULAR_HOLD_GREEN = Annotated[Particle, particle("#NOTE_CIRCULAR_HOLD_GREEN")]
|
|
122
|
-
NOTE_CIRCULAR_HOLD_BLUE = Annotated[Particle, particle("#NOTE_CIRCULAR_HOLD_BLUE")]
|
|
123
|
-
NOTE_CIRCULAR_HOLD_YELLOW = Annotated[Particle, particle("#NOTE_CIRCULAR_HOLD_YELLOW")]
|
|
124
|
-
NOTE_CIRCULAR_HOLD_PURPLE = Annotated[Particle, particle("#NOTE_CIRCULAR_HOLD_PURPLE")]
|
|
125
|
-
NOTE_CIRCULAR_HOLD_CYAN = Annotated[Particle, particle("#NOTE_CIRCULAR_HOLD_CYAN")]
|
|
126
|
-
NOTE_LINEAR_TAP_NEUTRAL = Annotated[Particle, particle("#NOTE_LINEAR_TAP_NEUTRAL")]
|
|
127
|
-
NOTE_LINEAR_TAP_RED = Annotated[Particle, particle("#NOTE_LINEAR_TAP_RED")]
|
|
128
|
-
NOTE_LINEAR_TAP_GREEN = Annotated[Particle, particle("#NOTE_LINEAR_TAP_GREEN")]
|
|
129
|
-
NOTE_LINEAR_TAP_BLUE = Annotated[Particle, particle("#NOTE_LINEAR_TAP_BLUE")]
|
|
130
|
-
NOTE_LINEAR_TAP_YELLOW = Annotated[Particle, particle("#NOTE_LINEAR_TAP_YELLOW")]
|
|
131
|
-
NOTE_LINEAR_TAP_PURPLE = Annotated[Particle, particle("#NOTE_LINEAR_TAP_PURPLE")]
|
|
132
|
-
NOTE_LINEAR_TAP_CYAN = Annotated[Particle, particle("#NOTE_LINEAR_TAP_CYAN")]
|
|
133
|
-
NOTE_LINEAR_ALTERNATIVE_NEUTRAL = Annotated[Particle, particle("#NOTE_LINEAR_ALTERNATIVE_NEUTRAL")]
|
|
134
|
-
NOTE_LINEAR_ALTERNATIVE_RED = Annotated[Particle, particle("#NOTE_LINEAR_ALTERNATIVE_RED")]
|
|
135
|
-
NOTE_LINEAR_ALTERNATIVE_GREEN = Annotated[Particle, particle("#NOTE_LINEAR_ALTERNATIVE_GREEN")]
|
|
136
|
-
NOTE_LINEAR_ALTERNATIVE_BLUE = Annotated[Particle, particle("#NOTE_LINEAR_ALTERNATIVE_BLUE")]
|
|
137
|
-
NOTE_LINEAR_ALTERNATIVE_YELLOW = Annotated[Particle, particle("#NOTE_LINEAR_ALTERNATIVE_YELLOW")]
|
|
138
|
-
NOTE_LINEAR_ALTERNATIVE_PURPLE = Annotated[Particle, particle("#NOTE_LINEAR_ALTERNATIVE_PURPLE")]
|
|
139
|
-
NOTE_LINEAR_ALTERNATIVE_CYAN = Annotated[Particle, particle("#NOTE_LINEAR_ALTERNATIVE_CYAN")]
|
|
140
|
-
NOTE_LINEAR_HOLD_NEUTRAL = Annotated[Particle, particle("#NOTE_LINEAR_HOLD_NEUTRAL")]
|
|
141
|
-
NOTE_LINEAR_HOLD_RED = Annotated[Particle, particle("#NOTE_LINEAR_HOLD_RED")]
|
|
142
|
-
NOTE_LINEAR_HOLD_GREEN = Annotated[Particle, particle("#NOTE_LINEAR_HOLD_GREEN")]
|
|
143
|
-
NOTE_LINEAR_HOLD_BLUE = Annotated[Particle, particle("#NOTE_LINEAR_HOLD_BLUE")]
|
|
144
|
-
NOTE_LINEAR_HOLD_YELLOW = Annotated[Particle, particle("#NOTE_LINEAR_HOLD_YELLOW")]
|
|
145
|
-
NOTE_LINEAR_HOLD_PURPLE = Annotated[Particle, particle("#NOTE_LINEAR_HOLD_PURPLE")]
|
|
146
|
-
NOTE_LINEAR_HOLD_CYAN = Annotated[Particle, particle("#NOTE_LINEAR_HOLD_CYAN")]
|
|
147
|
-
LANE_CIRCULAR = Annotated[Particle, particle("#LANE_CIRCULAR")]
|
|
148
|
-
LANE_LINEAR = Annotated[Particle, particle("#LANE_LINEAR")]
|
|
149
|
-
SLOT_CIRCULAR = Annotated[Particle, particle("#SLOT_CIRCULAR")]
|
|
150
|
-
SLOT_LINEAR = Annotated[Particle, particle("#SLOT_LINEAR")]
|
|
151
|
-
JUDGE_LINE_CIRCULAR = Annotated[Particle, particle("#JUDGE_LINE_CIRCULAR")]
|
|
152
|
-
JUDGE_LINE_LINEAR = Annotated[Particle, particle("#JUDGE_LINE_LINEAR")]
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
@particles
|
|
156
|
-
class EmptyParticles:
|
|
157
|
-
pass
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Annotated, Any, NewType, dataclass_transform, get_origin
|
|
5
|
+
|
|
6
|
+
from sonolus.backend.ops import Op
|
|
7
|
+
from sonolus.script.graphics import QuadLike, flatten_quad
|
|
8
|
+
from sonolus.script.internal.introspection import get_field_specifiers
|
|
9
|
+
from sonolus.script.internal.native import native_function
|
|
10
|
+
from sonolus.script.record import Record
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Particle(Record):
|
|
14
|
+
id: int
|
|
15
|
+
|
|
16
|
+
def is_available(self) -> bool:
|
|
17
|
+
return _has_particle_effect(self.id)
|
|
18
|
+
|
|
19
|
+
def spawn(self, quad: QuadLike, duration: float, loop: bool = False) -> ParticleHandle:
|
|
20
|
+
return ParticleHandle(_spawn_particle_effect(self.id, *flatten_quad(quad), duration, loop))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ParticleHandle(Record):
|
|
24
|
+
id: int
|
|
25
|
+
|
|
26
|
+
def move(self, quad: QuadLike) -> None:
|
|
27
|
+
_move_particle_effect(self.id, *flatten_quad(quad))
|
|
28
|
+
|
|
29
|
+
def destroy(self) -> None:
|
|
30
|
+
_destroy_particle_effect(self.id)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@native_function(Op.HasParticleEffect)
|
|
34
|
+
def _has_particle_effect(particle_id: int) -> bool:
|
|
35
|
+
raise NotImplementedError
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@native_function(Op.SpawnParticleEffect)
|
|
39
|
+
def _spawn_particle_effect(
|
|
40
|
+
particle_id: int,
|
|
41
|
+
x1: float,
|
|
42
|
+
y1: float,
|
|
43
|
+
x2: float,
|
|
44
|
+
y2: float,
|
|
45
|
+
x3: float,
|
|
46
|
+
y3: float,
|
|
47
|
+
x4: float,
|
|
48
|
+
y4: float,
|
|
49
|
+
duration: float,
|
|
50
|
+
loop: bool,
|
|
51
|
+
) -> int:
|
|
52
|
+
raise NotImplementedError
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@native_function(Op.MoveParticleEffect)
|
|
56
|
+
def _move_particle_effect(
|
|
57
|
+
handle: int, x1: float, y1: float, x2: float, y2: float, x3: float, y3: float, x4: float, y4: float
|
|
58
|
+
) -> None:
|
|
59
|
+
raise NotImplementedError
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@native_function(Op.DestroyParticleEffect)
|
|
63
|
+
def _destroy_particle_effect(handle: int) -> None:
|
|
64
|
+
raise NotImplementedError
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@dataclass
|
|
68
|
+
class ParticleInfo:
|
|
69
|
+
name: str
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def particle(name: str) -> Any:
|
|
73
|
+
return ParticleInfo(name)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
type Particles = NewType("Particles", Any)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@dataclass_transform()
|
|
80
|
+
def particles[T](cls: type[T]) -> T | Particles:
|
|
81
|
+
if len(cls.__bases__) != 1:
|
|
82
|
+
raise ValueError("Particles class must not inherit from any class (except object)")
|
|
83
|
+
instance = cls()
|
|
84
|
+
names = []
|
|
85
|
+
for i, (name, annotation) in enumerate(get_field_specifiers(cls).items()):
|
|
86
|
+
if get_origin(annotation) is not Annotated:
|
|
87
|
+
raise TypeError(f"Invalid annotation for particles: {annotation}")
|
|
88
|
+
annotation_type = annotation.__args__[0]
|
|
89
|
+
annotation_values = annotation.__metadata__
|
|
90
|
+
if annotation_type is not Particle:
|
|
91
|
+
raise TypeError(f"Invalid annotation for particles: {annotation}, expected annotation of type Particle")
|
|
92
|
+
if len(annotation_values) != 1 or not isinstance(annotation_values[0], ParticleInfo):
|
|
93
|
+
raise TypeError(
|
|
94
|
+
f"Invalid annotation for particles: {annotation}, expected a single string annotation value"
|
|
95
|
+
)
|
|
96
|
+
particle_name = annotation_values[0].name
|
|
97
|
+
names.append(particle_name)
|
|
98
|
+
setattr(instance, name, Particle(i))
|
|
99
|
+
instance._particles_ = names
|
|
100
|
+
instance._is_comptime_value_ = True
|
|
101
|
+
return instance
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class StandardParticle:
|
|
105
|
+
NOTE_CIRCULAR_TAP_NEUTRAL = Annotated[Particle, particle("#NOTE_CIRCULAR_TAP_NEUTRAL")]
|
|
106
|
+
NOTE_CIRCULAR_TAP_RED = Annotated[Particle, particle("#NOTE_CIRCULAR_TAP_RED")]
|
|
107
|
+
NOTE_CIRCULAR_TAP_GREEN = Annotated[Particle, particle("#NOTE_CIRCULAR_TAP_GREEN")]
|
|
108
|
+
NOTE_CIRCULAR_TAP_BLUE = Annotated[Particle, particle("#NOTE_CIRCULAR_TAP_BLUE")]
|
|
109
|
+
NOTE_CIRCULAR_TAP_YELLOW = Annotated[Particle, particle("#NOTE_CIRCULAR_TAP_YELLOW")]
|
|
110
|
+
NOTE_CIRCULAR_TAP_PURPLE = Annotated[Particle, particle("#NOTE_CIRCULAR_TAP_PURPLE")]
|
|
111
|
+
NOTE_CIRCULAR_TAP_CYAN = Annotated[Particle, particle("#NOTE_CIRCULAR_TAP_CYAN")]
|
|
112
|
+
NOTE_CIRCULAR_ALTERNATIVE_NEUTRAL = Annotated[Particle, particle("#NOTE_CIRCULAR_ALTERNATIVE_NEUTRAL")]
|
|
113
|
+
NOTE_CIRCULAR_ALTERNATIVE_RED = Annotated[Particle, particle("#NOTE_CIRCULAR_ALTERNATIVE_RED")]
|
|
114
|
+
NOTE_CIRCULAR_ALTERNATIVE_GREEN = Annotated[Particle, particle("#NOTE_CIRCULAR_ALTERNATIVE_GREEN")]
|
|
115
|
+
NOTE_CIRCULAR_ALTERNATIVE_BLUE = Annotated[Particle, particle("#NOTE_CIRCULAR_ALTERNATIVE_BLUE")]
|
|
116
|
+
NOTE_CIRCULAR_ALTERNATIVE_YELLOW = Annotated[Particle, particle("#NOTE_CIRCULAR_ALTERNATIVE_YELLOW")]
|
|
117
|
+
NOTE_CIRCULAR_ALTERNATIVE_PURPLE = Annotated[Particle, particle("#NOTE_CIRCULAR_ALTERNATIVE_PURPLE")]
|
|
118
|
+
NOTE_CIRCULAR_ALTERNATIVE_CYAN = Annotated[Particle, particle("#NOTE_CIRCULAR_ALTERNATIVE_CYAN")]
|
|
119
|
+
NOTE_CIRCULAR_HOLD_NEUTRAL = Annotated[Particle, particle("#NOTE_CIRCULAR_HOLD_NEUTRAL")]
|
|
120
|
+
NOTE_CIRCULAR_HOLD_RED = Annotated[Particle, particle("#NOTE_CIRCULAR_HOLD_RED")]
|
|
121
|
+
NOTE_CIRCULAR_HOLD_GREEN = Annotated[Particle, particle("#NOTE_CIRCULAR_HOLD_GREEN")]
|
|
122
|
+
NOTE_CIRCULAR_HOLD_BLUE = Annotated[Particle, particle("#NOTE_CIRCULAR_HOLD_BLUE")]
|
|
123
|
+
NOTE_CIRCULAR_HOLD_YELLOW = Annotated[Particle, particle("#NOTE_CIRCULAR_HOLD_YELLOW")]
|
|
124
|
+
NOTE_CIRCULAR_HOLD_PURPLE = Annotated[Particle, particle("#NOTE_CIRCULAR_HOLD_PURPLE")]
|
|
125
|
+
NOTE_CIRCULAR_HOLD_CYAN = Annotated[Particle, particle("#NOTE_CIRCULAR_HOLD_CYAN")]
|
|
126
|
+
NOTE_LINEAR_TAP_NEUTRAL = Annotated[Particle, particle("#NOTE_LINEAR_TAP_NEUTRAL")]
|
|
127
|
+
NOTE_LINEAR_TAP_RED = Annotated[Particle, particle("#NOTE_LINEAR_TAP_RED")]
|
|
128
|
+
NOTE_LINEAR_TAP_GREEN = Annotated[Particle, particle("#NOTE_LINEAR_TAP_GREEN")]
|
|
129
|
+
NOTE_LINEAR_TAP_BLUE = Annotated[Particle, particle("#NOTE_LINEAR_TAP_BLUE")]
|
|
130
|
+
NOTE_LINEAR_TAP_YELLOW = Annotated[Particle, particle("#NOTE_LINEAR_TAP_YELLOW")]
|
|
131
|
+
NOTE_LINEAR_TAP_PURPLE = Annotated[Particle, particle("#NOTE_LINEAR_TAP_PURPLE")]
|
|
132
|
+
NOTE_LINEAR_TAP_CYAN = Annotated[Particle, particle("#NOTE_LINEAR_TAP_CYAN")]
|
|
133
|
+
NOTE_LINEAR_ALTERNATIVE_NEUTRAL = Annotated[Particle, particle("#NOTE_LINEAR_ALTERNATIVE_NEUTRAL")]
|
|
134
|
+
NOTE_LINEAR_ALTERNATIVE_RED = Annotated[Particle, particle("#NOTE_LINEAR_ALTERNATIVE_RED")]
|
|
135
|
+
NOTE_LINEAR_ALTERNATIVE_GREEN = Annotated[Particle, particle("#NOTE_LINEAR_ALTERNATIVE_GREEN")]
|
|
136
|
+
NOTE_LINEAR_ALTERNATIVE_BLUE = Annotated[Particle, particle("#NOTE_LINEAR_ALTERNATIVE_BLUE")]
|
|
137
|
+
NOTE_LINEAR_ALTERNATIVE_YELLOW = Annotated[Particle, particle("#NOTE_LINEAR_ALTERNATIVE_YELLOW")]
|
|
138
|
+
NOTE_LINEAR_ALTERNATIVE_PURPLE = Annotated[Particle, particle("#NOTE_LINEAR_ALTERNATIVE_PURPLE")]
|
|
139
|
+
NOTE_LINEAR_ALTERNATIVE_CYAN = Annotated[Particle, particle("#NOTE_LINEAR_ALTERNATIVE_CYAN")]
|
|
140
|
+
NOTE_LINEAR_HOLD_NEUTRAL = Annotated[Particle, particle("#NOTE_LINEAR_HOLD_NEUTRAL")]
|
|
141
|
+
NOTE_LINEAR_HOLD_RED = Annotated[Particle, particle("#NOTE_LINEAR_HOLD_RED")]
|
|
142
|
+
NOTE_LINEAR_HOLD_GREEN = Annotated[Particle, particle("#NOTE_LINEAR_HOLD_GREEN")]
|
|
143
|
+
NOTE_LINEAR_HOLD_BLUE = Annotated[Particle, particle("#NOTE_LINEAR_HOLD_BLUE")]
|
|
144
|
+
NOTE_LINEAR_HOLD_YELLOW = Annotated[Particle, particle("#NOTE_LINEAR_HOLD_YELLOW")]
|
|
145
|
+
NOTE_LINEAR_HOLD_PURPLE = Annotated[Particle, particle("#NOTE_LINEAR_HOLD_PURPLE")]
|
|
146
|
+
NOTE_LINEAR_HOLD_CYAN = Annotated[Particle, particle("#NOTE_LINEAR_HOLD_CYAN")]
|
|
147
|
+
LANE_CIRCULAR = Annotated[Particle, particle("#LANE_CIRCULAR")]
|
|
148
|
+
LANE_LINEAR = Annotated[Particle, particle("#LANE_LINEAR")]
|
|
149
|
+
SLOT_CIRCULAR = Annotated[Particle, particle("#SLOT_CIRCULAR")]
|
|
150
|
+
SLOT_LINEAR = Annotated[Particle, particle("#SLOT_LINEAR")]
|
|
151
|
+
JUDGE_LINE_CIRCULAR = Annotated[Particle, particle("#JUDGE_LINE_CIRCULAR")]
|
|
152
|
+
JUDGE_LINE_LINEAR = Annotated[Particle, particle("#JUDGE_LINE_LINEAR")]
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
@particles
|
|
156
|
+
class EmptyParticles:
|
|
157
|
+
pass
|
sonolus/script/pointer.py
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
from sonolus.backend.place import BlockPlace
|
|
2
|
-
from sonolus.script.internal.impl import meta_fn, validate_value
|
|
3
|
-
from sonolus.script.internal.value import Value
|
|
4
|
-
from sonolus.script.num import Num, is_num
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
@meta_fn
|
|
8
|
-
def deref[T: Value](block: Num, offset: Num, type_: type[T]) -> T:
|
|
9
|
-
block = Num._accept_(block)
|
|
10
|
-
offset = Num._accept_(offset)
|
|
11
|
-
type_ = validate_value(type_)._as_py_()
|
|
12
|
-
if block._is_py_():
|
|
13
|
-
block = block._as_py_()
|
|
14
|
-
if not isinstance(block, int):
|
|
15
|
-
raise TypeError("block must be an integer")
|
|
16
|
-
else:
|
|
17
|
-
if not is_num(block):
|
|
18
|
-
raise TypeError("block must be a Num")
|
|
19
|
-
block = block.index()
|
|
20
|
-
if offset._is_py_():
|
|
21
|
-
offset = offset._as_py_()
|
|
22
|
-
if not isinstance(offset, int):
|
|
23
|
-
raise TypeError("offset must be an integer")
|
|
24
|
-
else:
|
|
25
|
-
if not is_num(offset):
|
|
26
|
-
raise TypeError("offset must be a Num")
|
|
27
|
-
offset = offset.index()
|
|
28
|
-
if not (isinstance(type_, type) and issubclass(type_, Value)):
|
|
29
|
-
raise TypeError("type_ must be a Value")
|
|
30
|
-
return type_._from_place_(BlockPlace(block, offset))
|
|
1
|
+
from sonolus.backend.place import BlockPlace
|
|
2
|
+
from sonolus.script.internal.impl import meta_fn, validate_value
|
|
3
|
+
from sonolus.script.internal.value import Value
|
|
4
|
+
from sonolus.script.num import Num, is_num
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@meta_fn
|
|
8
|
+
def deref[T: Value](block: Num, offset: Num, type_: type[T]) -> T:
|
|
9
|
+
block = Num._accept_(block)
|
|
10
|
+
offset = Num._accept_(offset)
|
|
11
|
+
type_ = validate_value(type_)._as_py_()
|
|
12
|
+
if block._is_py_():
|
|
13
|
+
block = block._as_py_()
|
|
14
|
+
if not isinstance(block, int):
|
|
15
|
+
raise TypeError("block must be an integer")
|
|
16
|
+
else:
|
|
17
|
+
if not is_num(block):
|
|
18
|
+
raise TypeError("block must be a Num")
|
|
19
|
+
block = block.index()
|
|
20
|
+
if offset._is_py_():
|
|
21
|
+
offset = offset._as_py_()
|
|
22
|
+
if not isinstance(offset, int):
|
|
23
|
+
raise TypeError("offset must be an integer")
|
|
24
|
+
else:
|
|
25
|
+
if not is_num(offset):
|
|
26
|
+
raise TypeError("offset must be a Num")
|
|
27
|
+
offset = offset.index()
|
|
28
|
+
if not (isinstance(type_, type) and issubclass(type_, Value)):
|
|
29
|
+
raise TypeError("type_ must be a Value")
|
|
30
|
+
return type_._from_place_(BlockPlace(block, offset))
|
sonolus/script/print.py
CHANGED
|
@@ -1,81 +1,81 @@
|
|
|
1
|
-
from enum import IntEnum
|
|
2
|
-
|
|
3
|
-
from sonolus.backend.ops import Op
|
|
4
|
-
from sonolus.script.internal.native import native_function
|
|
5
|
-
from sonolus.script.runtime import HorizontalAlign
|
|
6
|
-
from sonolus.script.vec import Vec2
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class PrintFormat(IntEnum):
|
|
10
|
-
NUMBER = 0
|
|
11
|
-
PERCENTAGE = 1
|
|
12
|
-
TIME = 10
|
|
13
|
-
SCORE = 11
|
|
14
|
-
BPM = 20
|
|
15
|
-
TIMESCALE = 21
|
|
16
|
-
BEAT_COUNT = 30
|
|
17
|
-
MEASURE_COUNT = 31
|
|
18
|
-
ENTITY_COUNT = 32
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class PrintColor(IntEnum):
|
|
22
|
-
THEME = -1
|
|
23
|
-
NEUTRAL = 0
|
|
24
|
-
RED = 1
|
|
25
|
-
GREEN = 2
|
|
26
|
-
BLUE = 3
|
|
27
|
-
YELLOW = 4
|
|
28
|
-
PURPLE = 5
|
|
29
|
-
CYAN = 6
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
@native_function(Op.Print)
|
|
33
|
-
def _print(
|
|
34
|
-
value: int | float,
|
|
35
|
-
format: PrintFormat, # noqa: A002
|
|
36
|
-
decimal_places: int,
|
|
37
|
-
anchor_x: float,
|
|
38
|
-
anchor_y: float,
|
|
39
|
-
pivot_x: float,
|
|
40
|
-
pivot_y: float,
|
|
41
|
-
width: float,
|
|
42
|
-
height: float,
|
|
43
|
-
rotation: float,
|
|
44
|
-
color: PrintColor,
|
|
45
|
-
alpha: float,
|
|
46
|
-
horizontal_align: HorizontalAlign,
|
|
47
|
-
background: bool,
|
|
48
|
-
):
|
|
49
|
-
raise NotImplementedError
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def print_number(
|
|
53
|
-
value: int | float,
|
|
54
|
-
*,
|
|
55
|
-
fmt: PrintFormat,
|
|
56
|
-
decimal_places: int = 0,
|
|
57
|
-
anchor: Vec2,
|
|
58
|
-
pivot: Vec2,
|
|
59
|
-
dimensions: Vec2,
|
|
60
|
-
rotation: float = 0,
|
|
61
|
-
color: PrintColor = PrintColor.THEME,
|
|
62
|
-
alpha: float = 1,
|
|
63
|
-
horizontal_align: HorizontalAlign = HorizontalAlign.LEFT,
|
|
64
|
-
background: bool = False,
|
|
65
|
-
):
|
|
66
|
-
_print(
|
|
67
|
-
value,
|
|
68
|
-
fmt,
|
|
69
|
-
decimal_places,
|
|
70
|
-
anchor.x,
|
|
71
|
-
anchor.y,
|
|
72
|
-
pivot.x,
|
|
73
|
-
pivot.y,
|
|
74
|
-
dimensions.x,
|
|
75
|
-
dimensions.y,
|
|
76
|
-
rotation,
|
|
77
|
-
color,
|
|
78
|
-
alpha,
|
|
79
|
-
horizontal_align,
|
|
80
|
-
background,
|
|
81
|
-
)
|
|
1
|
+
from enum import IntEnum
|
|
2
|
+
|
|
3
|
+
from sonolus.backend.ops import Op
|
|
4
|
+
from sonolus.script.internal.native import native_function
|
|
5
|
+
from sonolus.script.runtime import HorizontalAlign
|
|
6
|
+
from sonolus.script.vec import Vec2
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class PrintFormat(IntEnum):
|
|
10
|
+
NUMBER = 0
|
|
11
|
+
PERCENTAGE = 1
|
|
12
|
+
TIME = 10
|
|
13
|
+
SCORE = 11
|
|
14
|
+
BPM = 20
|
|
15
|
+
TIMESCALE = 21
|
|
16
|
+
BEAT_COUNT = 30
|
|
17
|
+
MEASURE_COUNT = 31
|
|
18
|
+
ENTITY_COUNT = 32
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class PrintColor(IntEnum):
|
|
22
|
+
THEME = -1
|
|
23
|
+
NEUTRAL = 0
|
|
24
|
+
RED = 1
|
|
25
|
+
GREEN = 2
|
|
26
|
+
BLUE = 3
|
|
27
|
+
YELLOW = 4
|
|
28
|
+
PURPLE = 5
|
|
29
|
+
CYAN = 6
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@native_function(Op.Print)
|
|
33
|
+
def _print(
|
|
34
|
+
value: int | float,
|
|
35
|
+
format: PrintFormat, # noqa: A002
|
|
36
|
+
decimal_places: int,
|
|
37
|
+
anchor_x: float,
|
|
38
|
+
anchor_y: float,
|
|
39
|
+
pivot_x: float,
|
|
40
|
+
pivot_y: float,
|
|
41
|
+
width: float,
|
|
42
|
+
height: float,
|
|
43
|
+
rotation: float,
|
|
44
|
+
color: PrintColor,
|
|
45
|
+
alpha: float,
|
|
46
|
+
horizontal_align: HorizontalAlign,
|
|
47
|
+
background: bool,
|
|
48
|
+
):
|
|
49
|
+
raise NotImplementedError
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def print_number(
|
|
53
|
+
value: int | float,
|
|
54
|
+
*,
|
|
55
|
+
fmt: PrintFormat,
|
|
56
|
+
decimal_places: int = 0,
|
|
57
|
+
anchor: Vec2,
|
|
58
|
+
pivot: Vec2,
|
|
59
|
+
dimensions: Vec2,
|
|
60
|
+
rotation: float = 0,
|
|
61
|
+
color: PrintColor = PrintColor.THEME,
|
|
62
|
+
alpha: float = 1,
|
|
63
|
+
horizontal_align: HorizontalAlign = HorizontalAlign.LEFT,
|
|
64
|
+
background: bool = False,
|
|
65
|
+
):
|
|
66
|
+
_print(
|
|
67
|
+
value,
|
|
68
|
+
fmt,
|
|
69
|
+
decimal_places,
|
|
70
|
+
anchor.x,
|
|
71
|
+
anchor.y,
|
|
72
|
+
pivot.x,
|
|
73
|
+
pivot.y,
|
|
74
|
+
dimensions.x,
|
|
75
|
+
dimensions.y,
|
|
76
|
+
rotation,
|
|
77
|
+
color,
|
|
78
|
+
alpha,
|
|
79
|
+
horizontal_align,
|
|
80
|
+
background,
|
|
81
|
+
)
|
sonolus/script/random.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import random as _random
|
|
2
|
+
|
|
3
|
+
from sonolus.backend.ops import Op
|
|
4
|
+
from sonolus.script.internal.native import native_function
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@native_function(Op.Random)
|
|
8
|
+
def random_float(lo: float = 0.0, hi: float = 1.0, /) -> float:
|
|
9
|
+
return lo + (hi - lo) * _random.random()
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@native_function(Op.RandomInteger)
|
|
13
|
+
def random_integer(lo: int, hi: int, /) -> int:
|
|
14
|
+
return _random.randint(lo, hi)
|