sonolus.py 0.1.4__py3-none-any.whl → 0.1.5__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/finalize.py +18 -10
- sonolus/backend/interpret.py +7 -7
- sonolus/backend/ir.py +24 -0
- sonolus/backend/optimize/__init__.py +0 -0
- sonolus/backend/{allocate.py → optimize/allocate.py} +4 -3
- sonolus/backend/{constant_evaluation.py → optimize/constant_evaluation.py} +7 -7
- sonolus/backend/{coalesce.py → optimize/copy_coalesce.py} +3 -3
- sonolus/backend/optimize/dead_code.py +185 -0
- sonolus/backend/{dominance.py → optimize/dominance.py} +2 -17
- sonolus/backend/{flow.py → optimize/flow.py} +6 -5
- sonolus/backend/{inlining.py → optimize/inlining.py} +4 -17
- sonolus/backend/{liveness.py → optimize/liveness.py} +69 -65
- sonolus/backend/optimize/optimize.py +44 -0
- sonolus/backend/{passes.py → optimize/passes.py} +1 -1
- sonolus/backend/optimize/simplify.py +191 -0
- sonolus/backend/{ssa.py → optimize/ssa.py} +31 -18
- sonolus/backend/place.py +17 -25
- sonolus/backend/utils.py +10 -0
- sonolus/backend/visitor.py +360 -101
- sonolus/build/compile.py +8 -8
- sonolus/build/engine.py +10 -5
- sonolus/script/archetype.py +419 -137
- sonolus/script/array.py +25 -8
- sonolus/script/array_like.py +297 -0
- sonolus/script/bucket.py +73 -11
- sonolus/script/containers.py +234 -51
- sonolus/script/debug.py +8 -8
- sonolus/script/easing.py +147 -105
- sonolus/script/effect.py +60 -0
- sonolus/script/engine.py +71 -4
- sonolus/script/globals.py +66 -32
- sonolus/script/instruction.py +79 -25
- sonolus/script/internal/builtin_impls.py +138 -27
- sonolus/script/internal/constant.py +139 -0
- sonolus/script/internal/context.py +14 -5
- sonolus/script/internal/dict_impl.py +65 -0
- sonolus/script/internal/generic.py +6 -9
- sonolus/script/internal/impl.py +38 -13
- sonolus/script/internal/introspection.py +5 -2
- sonolus/script/{math.py → internal/math_impls.py} +28 -28
- sonolus/script/internal/native.py +3 -3
- sonolus/script/internal/random.py +67 -0
- sonolus/script/internal/range.py +81 -0
- sonolus/script/internal/transient.py +51 -0
- sonolus/script/internal/tuple_impl.py +113 -0
- sonolus/script/interval.py +234 -16
- sonolus/script/iterator.py +120 -167
- sonolus/script/level.py +24 -0
- sonolus/script/num.py +79 -47
- sonolus/script/options.py +78 -12
- sonolus/script/particle.py +37 -4
- sonolus/script/pointer.py +4 -4
- sonolus/script/print.py +22 -1
- sonolus/script/project.py +8 -0
- sonolus/script/{graphics.py → quad.py} +75 -12
- sonolus/script/record.py +44 -13
- sonolus/script/runtime.py +50 -1
- sonolus/script/sprite.py +197 -112
- sonolus/script/text.py +2 -0
- sonolus/script/timing.py +72 -0
- sonolus/script/transform.py +296 -66
- sonolus/script/ui.py +134 -78
- sonolus/script/values.py +6 -13
- sonolus/script/vec.py +118 -3
- {sonolus_py-0.1.4.dist-info → sonolus_py-0.1.5.dist-info}/METADATA +1 -1
- sonolus_py-0.1.5.dist-info/RECORD +89 -0
- sonolus/backend/dead_code.py +0 -80
- sonolus/backend/optimize.py +0 -37
- sonolus/backend/simplify.py +0 -47
- sonolus/script/comptime.py +0 -160
- sonolus/script/random.py +0 -14
- sonolus/script/range.py +0 -58
- sonolus_py-0.1.4.dist-info/RECORD +0 -84
- /sonolus/script/{callbacks.py → internal/callbacks.py} +0 -0
- {sonolus_py-0.1.4.dist-info → sonolus_py-0.1.5.dist-info}/WHEEL +0 -0
- {sonolus_py-0.1.4.dist-info → sonolus_py-0.1.5.dist-info}/entry_points.txt +0 -0
- {sonolus_py-0.1.4.dist-info → sonolus_py-0.1.5.dist-info}/licenses/LICENSE +0 -0
sonolus/script/project.py
CHANGED
|
@@ -6,6 +6,14 @@ from sonolus.script.level import Level
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class Project:
|
|
9
|
+
"""A Sonolus.py project.
|
|
10
|
+
|
|
11
|
+
Args:
|
|
12
|
+
engine: The engine of the project.
|
|
13
|
+
levels: The levels of the project.
|
|
14
|
+
resources: The path to the resources of the project.
|
|
15
|
+
"""
|
|
16
|
+
|
|
9
17
|
def __init__(
|
|
10
18
|
self,
|
|
11
19
|
engine: Engine,
|
|
@@ -7,16 +7,33 @@ from sonolus.script.vec import Vec2
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class Quad(Record):
|
|
10
|
+
"""A quad defined by its four corners.
|
|
11
|
+
|
|
12
|
+
Usage:
|
|
13
|
+
```
|
|
14
|
+
Quad(bl: Vec2, tl: Vec2, tr: Vec2, br: Vec2)
|
|
15
|
+
```
|
|
16
|
+
"""
|
|
17
|
+
|
|
10
18
|
bl: Vec2
|
|
19
|
+
"""The bottom-left corner of the quad."""
|
|
20
|
+
|
|
11
21
|
tl: Vec2
|
|
22
|
+
"""The top-left corner of the quad."""
|
|
23
|
+
|
|
12
24
|
tr: Vec2
|
|
25
|
+
"""The top-right corner of the quad."""
|
|
26
|
+
|
|
13
27
|
br: Vec2
|
|
28
|
+
"""The bottom-right corner of the quad."""
|
|
14
29
|
|
|
15
30
|
@property
|
|
16
31
|
def center(self) -> Vec2:
|
|
32
|
+
"""The center of the quad."""
|
|
17
33
|
return (self.bl + self.tr + self.tl + self.br) / 4
|
|
18
34
|
|
|
19
35
|
def translate(self, translation: Vec2, /) -> Self:
|
|
36
|
+
"""Translate the quad by the given translation and return a new quad."""
|
|
20
37
|
return Quad(
|
|
21
38
|
bl=self.bl + translation,
|
|
22
39
|
tl=self.tl + translation,
|
|
@@ -25,6 +42,7 @@ class Quad(Record):
|
|
|
25
42
|
)
|
|
26
43
|
|
|
27
44
|
def scale(self, factor: Vec2, /) -> Self:
|
|
45
|
+
"""Scale the quad by the given factor about the origin and return a new quad."""
|
|
28
46
|
return Quad(
|
|
29
47
|
bl=self.bl * factor,
|
|
30
48
|
tl=self.tl * factor,
|
|
@@ -33,6 +51,7 @@ class Quad(Record):
|
|
|
33
51
|
)
|
|
34
52
|
|
|
35
53
|
def scale_about(self, factor: Vec2, /, pivot: Vec2) -> Self:
|
|
54
|
+
"""Scale the quad by the given factor about the given pivot and return a new quad."""
|
|
36
55
|
return Quad(
|
|
37
56
|
bl=(self.bl - pivot) * factor + pivot,
|
|
38
57
|
tl=(self.tl - pivot) * factor + pivot,
|
|
@@ -41,6 +60,7 @@ class Quad(Record):
|
|
|
41
60
|
)
|
|
42
61
|
|
|
43
62
|
def scale_centered(self, factor: Vec2, /) -> Self:
|
|
63
|
+
"""Scale the quad by the given factor about its center and return a new quad."""
|
|
44
64
|
return Quad(
|
|
45
65
|
bl=self.bl * factor,
|
|
46
66
|
tl=self.tl * factor,
|
|
@@ -49,6 +69,7 @@ class Quad(Record):
|
|
|
49
69
|
).translate(self.center * (Vec2(1, 1) - factor))
|
|
50
70
|
|
|
51
71
|
def rotate(self, angle: float, /) -> Self:
|
|
72
|
+
"""Rotate the quad by the given angle about the origin and return a new quad."""
|
|
52
73
|
return Quad(
|
|
53
74
|
bl=self.bl.rotate(angle),
|
|
54
75
|
tl=self.tl.rotate(angle),
|
|
@@ -62,6 +83,7 @@ class Quad(Record):
|
|
|
62
83
|
/,
|
|
63
84
|
pivot: Vec2,
|
|
64
85
|
) -> Self:
|
|
86
|
+
"""Rotate the quad by the given angle about the given pivot and return a new quad."""
|
|
65
87
|
return Quad(
|
|
66
88
|
bl=self.bl.rotate_about(angle, pivot),
|
|
67
89
|
tl=self.tl.rotate_about(angle, pivot),
|
|
@@ -70,17 +92,34 @@ class Quad(Record):
|
|
|
70
92
|
)
|
|
71
93
|
|
|
72
94
|
def rotate_centered(self, angle: float, /) -> Self:
|
|
95
|
+
"""Rotate the quad by the given angle about its center and return a new quad."""
|
|
73
96
|
return self.rotate_about(angle, self.center)
|
|
74
97
|
|
|
75
98
|
|
|
76
99
|
class Rect(Record):
|
|
100
|
+
"""A rectangle defined by its top, right, bottom, and left edges.
|
|
101
|
+
|
|
102
|
+
Usage:
|
|
103
|
+
```
|
|
104
|
+
Rect(t: float, r: float, b: float, l: float)
|
|
105
|
+
```
|
|
106
|
+
"""
|
|
107
|
+
|
|
77
108
|
t: float
|
|
109
|
+
"""The top edge of the rectangle."""
|
|
110
|
+
|
|
78
111
|
r: float
|
|
112
|
+
"""The right edge of the rectangle."""
|
|
113
|
+
|
|
79
114
|
b: float
|
|
115
|
+
"""The bottom edge of the rectangle."""
|
|
116
|
+
|
|
80
117
|
l: float # noqa: E741
|
|
118
|
+
"""The left edge of the rectangle."""
|
|
81
119
|
|
|
82
120
|
@classmethod
|
|
83
121
|
def from_center(cls, center: Vec2, dimensions: Vec2) -> Rect:
|
|
122
|
+
"""Create a rectangle from its center and dimensions."""
|
|
84
123
|
return cls(
|
|
85
124
|
t=center.y + dimensions.y / 2,
|
|
86
125
|
r=center.x + dimensions.x / 2,
|
|
@@ -90,33 +129,41 @@ class Rect(Record):
|
|
|
90
129
|
|
|
91
130
|
@property
|
|
92
131
|
def w(self) -> float:
|
|
132
|
+
"""The width of the rectangle."""
|
|
93
133
|
return self.r - self.l
|
|
94
134
|
|
|
95
135
|
@property
|
|
96
136
|
def h(self) -> float:
|
|
137
|
+
"""The height of the rectangle."""
|
|
97
138
|
return self.t - self.b
|
|
98
139
|
|
|
99
140
|
@property
|
|
100
141
|
def bl(self) -> Vec2:
|
|
142
|
+
"""The bottom-left corner of the rectangle."""
|
|
101
143
|
return Vec2(self.l, self.b)
|
|
102
144
|
|
|
103
145
|
@property
|
|
104
146
|
def tl(self) -> Vec2:
|
|
147
|
+
"""The top-left corner of the rectangle."""
|
|
105
148
|
return Vec2(self.l, self.t)
|
|
106
149
|
|
|
107
150
|
@property
|
|
108
151
|
def tr(self) -> Vec2:
|
|
152
|
+
"""The top-right corner of the rectangle."""
|
|
109
153
|
return Vec2(self.r, self.t)
|
|
110
154
|
|
|
111
155
|
@property
|
|
112
156
|
def br(self) -> Vec2:
|
|
157
|
+
"""The bottom-right corner of the rectangle."""
|
|
113
158
|
return Vec2(self.r, self.b)
|
|
114
159
|
|
|
115
160
|
@property
|
|
116
161
|
def center(self) -> Vec2:
|
|
162
|
+
"""The center of the rectangle."""
|
|
117
163
|
return Vec2((self.l + self.r) / 2, (self.t + self.b) / 2)
|
|
118
164
|
|
|
119
165
|
def as_quad(self) -> Quad:
|
|
166
|
+
"""Convert the rectangle to a quad."""
|
|
120
167
|
return Quad(
|
|
121
168
|
bl=self.bl,
|
|
122
169
|
tl=self.tl,
|
|
@@ -125,6 +172,7 @@ class Rect(Record):
|
|
|
125
172
|
)
|
|
126
173
|
|
|
127
174
|
def translate(self, translation: Vec2, /) -> Self:
|
|
175
|
+
"""Translate the rectangle by the given translation and return a new rectangle."""
|
|
128
176
|
return Rect(
|
|
129
177
|
t=self.t + translation.y,
|
|
130
178
|
r=self.r + translation.x,
|
|
@@ -133,6 +181,7 @@ class Rect(Record):
|
|
|
133
181
|
)
|
|
134
182
|
|
|
135
183
|
def scale(self, factor: Vec2, /) -> Self:
|
|
184
|
+
"""Scale the rectangle by the given factor about the origin and return a new rectangle."""
|
|
136
185
|
return Rect(
|
|
137
186
|
t=self.t * factor.y,
|
|
138
187
|
r=self.r * factor.x,
|
|
@@ -141,6 +190,7 @@ class Rect(Record):
|
|
|
141
190
|
)
|
|
142
191
|
|
|
143
192
|
def scale_about(self, factor: Vec2, /, pivot: Vec2) -> Self:
|
|
193
|
+
"""Scale the rectangle by the given factor about the given pivot and return a new rectangle."""
|
|
144
194
|
return Rect(
|
|
145
195
|
t=(self.t - pivot.y) * factor.y + pivot.y,
|
|
146
196
|
r=(self.r - pivot.x) * factor.x + pivot.x,
|
|
@@ -149,6 +199,7 @@ class Rect(Record):
|
|
|
149
199
|
)
|
|
150
200
|
|
|
151
201
|
def scale_centered(self, factor: Vec2, /) -> Self:
|
|
202
|
+
"""Scale the rectangle by the given factor about its center and return a new rectangle."""
|
|
152
203
|
return Rect(
|
|
153
204
|
t=self.t * factor.y,
|
|
154
205
|
r=self.r * factor.x,
|
|
@@ -157,6 +208,7 @@ class Rect(Record):
|
|
|
157
208
|
).translate(self.center * (Vec2(1, 1) - factor))
|
|
158
209
|
|
|
159
210
|
def expand(self, expansion: Vec2, /) -> Self:
|
|
211
|
+
"""Expand the rectangle by the given amount and return a new rectangle."""
|
|
160
212
|
return Rect(
|
|
161
213
|
t=self.t + expansion.y,
|
|
162
214
|
r=self.r + expansion.x,
|
|
@@ -165,6 +217,7 @@ class Rect(Record):
|
|
|
165
217
|
)
|
|
166
218
|
|
|
167
219
|
def shrink(self, shrinkage: Vec2, /) -> Self:
|
|
220
|
+
"""Shrink the rectangle by the given amount and return a new rectangle."""
|
|
168
221
|
return Rect(
|
|
169
222
|
t=self.t - shrinkage.y,
|
|
170
223
|
r=self.r - shrinkage.x,
|
|
@@ -174,27 +227,37 @@ class Rect(Record):
|
|
|
174
227
|
|
|
175
228
|
|
|
176
229
|
class QuadLike(Protocol):
|
|
230
|
+
"""A protocol for types that can be used as quads."""
|
|
231
|
+
|
|
177
232
|
@property
|
|
178
|
-
def bl(self) -> Vec2:
|
|
233
|
+
def bl(self) -> Vec2:
|
|
234
|
+
"""The bottom-left corner of the quad."""
|
|
179
235
|
|
|
180
236
|
@property
|
|
181
|
-
def tl(self) -> Vec2:
|
|
237
|
+
def tl(self) -> Vec2:
|
|
238
|
+
"""The top-left corner of the quad."""
|
|
182
239
|
|
|
183
240
|
@property
|
|
184
|
-
def tr(self) -> Vec2:
|
|
241
|
+
def tr(self) -> Vec2:
|
|
242
|
+
"""The top-right corner of the quad."""
|
|
185
243
|
|
|
186
244
|
@property
|
|
187
|
-
def br(self) -> Vec2:
|
|
245
|
+
def br(self) -> Vec2:
|
|
246
|
+
"""The bottom-right corner of the quad."""
|
|
188
247
|
|
|
189
248
|
|
|
190
249
|
def flatten_quad(quad: QuadLike) -> tuple[float, float, float, float, float, float, float, float]:
|
|
250
|
+
bl = quad.bl
|
|
251
|
+
tl = quad.tl
|
|
252
|
+
tr = quad.tr
|
|
253
|
+
br = quad.br
|
|
191
254
|
return (
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
255
|
+
bl.x,
|
|
256
|
+
bl.y,
|
|
257
|
+
tl.x,
|
|
258
|
+
tl.y,
|
|
259
|
+
tr.x,
|
|
260
|
+
tr.y,
|
|
261
|
+
br.x,
|
|
262
|
+
br.y,
|
|
200
263
|
)
|
sonolus/script/record.py
CHANGED
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import inspect
|
|
4
4
|
from collections.abc import Iterable
|
|
5
5
|
from inspect import getmro
|
|
6
|
-
from typing import Any, ClassVar, Self, dataclass_transform, get_origin
|
|
6
|
+
from typing import Any, ClassVar, Self, TypeVar, dataclass_transform, get_origin
|
|
7
7
|
|
|
8
8
|
from sonolus.backend.place import BlockPlace
|
|
9
9
|
from sonolus.script.internal.context import ctx
|
|
@@ -22,15 +22,33 @@ from sonolus.script.num import Num
|
|
|
22
22
|
|
|
23
23
|
@dataclass_transform(eq_default=True)
|
|
24
24
|
class Record(GenericValue):
|
|
25
|
+
"""Base class for user-defined data structures.
|
|
26
|
+
|
|
27
|
+
Usage:
|
|
28
|
+
A regular record:
|
|
29
|
+
```python
|
|
30
|
+
class MyRecord(Record):
|
|
31
|
+
field1: int
|
|
32
|
+
field2: bool
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
A generic record:
|
|
36
|
+
```python
|
|
37
|
+
class MyGenericRecord[T, U](Record):
|
|
38
|
+
field1: T
|
|
39
|
+
field2: U
|
|
40
|
+
```
|
|
41
|
+
"""
|
|
42
|
+
|
|
25
43
|
_value: dict[str, Value]
|
|
26
|
-
_fields: ClassVar[list[
|
|
44
|
+
_fields: ClassVar[list[_RecordField] | None] = None
|
|
27
45
|
_constructor_signature: ClassVar[inspect.Signature]
|
|
28
46
|
|
|
29
47
|
@classmethod
|
|
30
|
-
def
|
|
48
|
+
def _validate_type_args_(cls, args: tuple[Any, ...]) -> tuple[Any, ...]:
|
|
31
49
|
if cls._fields is None:
|
|
32
50
|
raise TypeError("Base Record class cannot have type arguments")
|
|
33
|
-
return super().
|
|
51
|
+
return super()._validate_type_args_(args)
|
|
34
52
|
|
|
35
53
|
def __init_subclass__(cls, **kwargs):
|
|
36
54
|
super().__init_subclass__()
|
|
@@ -43,7 +61,7 @@ class Record(GenericValue):
|
|
|
43
61
|
for generic_field in cls._fields:
|
|
44
62
|
resolved_type = validate_and_resolve_type(generic_field.type, cls._type_vars_to_args_)
|
|
45
63
|
resolved_type = validate_concrete_type(resolved_type)
|
|
46
|
-
field =
|
|
64
|
+
field = _RecordField(generic_field.name, resolved_type, generic_field.index, offset)
|
|
47
65
|
fields.append(field)
|
|
48
66
|
setattr(cls, field.name, field)
|
|
49
67
|
offset += resolved_type._size_()
|
|
@@ -70,7 +88,7 @@ class Record(GenericValue):
|
|
|
70
88
|
if hasattr(cls, name):
|
|
71
89
|
raise TypeError("Default values are not supported for Record fields")
|
|
72
90
|
type_ = validate_type_spec(hint)
|
|
73
|
-
fields.append(
|
|
91
|
+
fields.append(_RecordField(name, type_, index, offset))
|
|
74
92
|
if isinstance(type_, type) and issubclass(type_, Value) and type_._is_concrete_():
|
|
75
93
|
offset += type_._size_()
|
|
76
94
|
setattr(cls, name, fields[-1])
|
|
@@ -194,7 +212,7 @@ class Record(GenericValue):
|
|
|
194
212
|
field.__set__(self, field.__get__(value))
|
|
195
213
|
|
|
196
214
|
def _copy_(self) -> Self:
|
|
197
|
-
return type(self)(**{field.name: self._value[field.name]._copy_() for field in self._fields})
|
|
215
|
+
return type(self)._raw(**{field.name: self._value[field.name]._copy_() for field in self._fields})
|
|
198
216
|
|
|
199
217
|
@classmethod
|
|
200
218
|
def _alloc_(cls) -> Self:
|
|
@@ -214,7 +232,7 @@ class Record(GenericValue):
|
|
|
214
232
|
)
|
|
215
233
|
|
|
216
234
|
@meta_fn
|
|
217
|
-
def __eq__(self, other):
|
|
235
|
+
def __eq__(self, other: Any) -> bool:
|
|
218
236
|
if not isinstance(other, type(self)):
|
|
219
237
|
return False
|
|
220
238
|
result: Num = Num._accept_(True)
|
|
@@ -223,7 +241,7 @@ class Record(GenericValue):
|
|
|
223
241
|
return result
|
|
224
242
|
|
|
225
243
|
@meta_fn
|
|
226
|
-
def __ne__(self, other):
|
|
244
|
+
def __ne__(self, other: Any) -> bool:
|
|
227
245
|
if not isinstance(other, type(self)):
|
|
228
246
|
return True
|
|
229
247
|
result: Num = Num._accept_(False)
|
|
@@ -232,10 +250,23 @@ class Record(GenericValue):
|
|
|
232
250
|
return result
|
|
233
251
|
|
|
234
252
|
def __hash__(self):
|
|
235
|
-
|
|
253
|
+
return hash(tuple(field.__get__(self) for field in self._fields))
|
|
254
|
+
|
|
255
|
+
@classmethod
|
|
256
|
+
@meta_fn
|
|
257
|
+
def type_var_value(cls, var: TypeVar, /) -> Any:
|
|
258
|
+
"""Return the value of a type variable.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
var: The type variable to get the value of.
|
|
262
|
+
|
|
263
|
+
Returns:
|
|
264
|
+
The value of the type variable.
|
|
265
|
+
"""
|
|
266
|
+
return super().type_var_value(var)
|
|
236
267
|
|
|
237
268
|
|
|
238
|
-
class
|
|
269
|
+
class _RecordField(SonolusDescriptor):
|
|
239
270
|
def __init__(self, name: str, type_: type[Value], index: int, offset: int):
|
|
240
271
|
self.name = name
|
|
241
272
|
self.type = type_
|
|
@@ -259,7 +290,7 @@ class RecordField(SonolusDescriptor):
|
|
|
259
290
|
instance._value[self.name]._copy_from_(value)
|
|
260
291
|
|
|
261
292
|
|
|
262
|
-
|
|
293
|
+
_ops_to_inplace_ops = {
|
|
263
294
|
"__add__": "__iadd__",
|
|
264
295
|
"__sub__": "__isub__",
|
|
265
296
|
"__mul__": "__imul__",
|
|
@@ -277,7 +308,7 @@ ops_to_inplace_ops = {
|
|
|
277
308
|
|
|
278
309
|
|
|
279
310
|
def _add_inplace_ops(cls):
|
|
280
|
-
for op, inplace_op in
|
|
311
|
+
for op, inplace_op in _ops_to_inplace_ops.items():
|
|
281
312
|
if hasattr(cls, op) and not hasattr(cls, inplace_op):
|
|
282
313
|
setattr(cls, inplace_op, _make_inplace_op(op))
|
|
283
314
|
return cls
|
sonolus/script/runtime.py
CHANGED
|
@@ -28,10 +28,10 @@ from sonolus.script.globals import (
|
|
|
28
28
|
_watch_runtime_ui_configuration,
|
|
29
29
|
_watch_runtime_update,
|
|
30
30
|
)
|
|
31
|
-
from sonolus.script.graphics import Quad, Rect
|
|
32
31
|
from sonolus.script.internal.context import ctx
|
|
33
32
|
from sonolus.script.internal.impl import meta_fn
|
|
34
33
|
from sonolus.script.num import Num
|
|
34
|
+
from sonolus.script.quad import Quad, Rect
|
|
35
35
|
from sonolus.script.record import Record
|
|
36
36
|
from sonolus.script.transform import Transform2d
|
|
37
37
|
from sonolus.script.vec import Vec2
|
|
@@ -433,6 +433,7 @@ class _TutorialInstruction:
|
|
|
433
433
|
|
|
434
434
|
@meta_fn
|
|
435
435
|
def is_debug() -> bool:
|
|
436
|
+
"""Check if the game is running in debug mode."""
|
|
436
437
|
if not ctx():
|
|
437
438
|
return False
|
|
438
439
|
match ctx().global_state.mode:
|
|
@@ -450,6 +451,7 @@ def is_debug() -> bool:
|
|
|
450
451
|
|
|
451
452
|
@meta_fn
|
|
452
453
|
def aspect_ratio() -> float:
|
|
454
|
+
"""Get the aspect ratio of the game."""
|
|
453
455
|
if not ctx():
|
|
454
456
|
return 16 / 9
|
|
455
457
|
match ctx().global_state.mode:
|
|
@@ -465,6 +467,10 @@ def aspect_ratio() -> float:
|
|
|
465
467
|
|
|
466
468
|
@meta_fn
|
|
467
469
|
def audio_offset() -> float:
|
|
470
|
+
"""Get the audio offset of the game.
|
|
471
|
+
|
|
472
|
+
Returns 0 in preview mode.
|
|
473
|
+
"""
|
|
468
474
|
if not ctx():
|
|
469
475
|
return 0
|
|
470
476
|
match ctx().global_state.mode:
|
|
@@ -480,6 +486,10 @@ def audio_offset() -> float:
|
|
|
480
486
|
|
|
481
487
|
@meta_fn
|
|
482
488
|
def input_offset() -> float:
|
|
489
|
+
"""Get the input offset of the game.
|
|
490
|
+
|
|
491
|
+
Returns 0 in preview mode and tutorial mode.
|
|
492
|
+
"""
|
|
483
493
|
if not ctx():
|
|
484
494
|
return 0
|
|
485
495
|
match ctx().global_state.mode:
|
|
@@ -493,6 +503,10 @@ def input_offset() -> float:
|
|
|
493
503
|
|
|
494
504
|
@meta_fn
|
|
495
505
|
def is_multiplayer() -> bool:
|
|
506
|
+
"""Check if the game is running in multiplayer mode.
|
|
507
|
+
|
|
508
|
+
Returns False if not in play mode.
|
|
509
|
+
"""
|
|
496
510
|
if not ctx():
|
|
497
511
|
return False
|
|
498
512
|
match ctx().global_state.mode:
|
|
@@ -504,6 +518,10 @@ def is_multiplayer() -> bool:
|
|
|
504
518
|
|
|
505
519
|
@meta_fn
|
|
506
520
|
def is_replay() -> bool:
|
|
521
|
+
"""Check if the game is running in replay mode.
|
|
522
|
+
|
|
523
|
+
Returns False if not in watch mode.
|
|
524
|
+
"""
|
|
507
525
|
if not ctx():
|
|
508
526
|
return False
|
|
509
527
|
match ctx().global_state.mode:
|
|
@@ -515,6 +533,10 @@ def is_replay() -> bool:
|
|
|
515
533
|
|
|
516
534
|
@meta_fn
|
|
517
535
|
def time() -> float:
|
|
536
|
+
"""Get the current time of the game.
|
|
537
|
+
|
|
538
|
+
Returns 0 in preview mode.
|
|
539
|
+
"""
|
|
518
540
|
if not ctx():
|
|
519
541
|
return 0
|
|
520
542
|
match ctx().global_state.mode:
|
|
@@ -530,6 +552,10 @@ def time() -> float:
|
|
|
530
552
|
|
|
531
553
|
@meta_fn
|
|
532
554
|
def delta_time() -> float:
|
|
555
|
+
"""Get the time elapsed since the last frame.
|
|
556
|
+
|
|
557
|
+
Returns 0 in preview mode.
|
|
558
|
+
"""
|
|
533
559
|
if not ctx():
|
|
534
560
|
return 0
|
|
535
561
|
match ctx().global_state.mode:
|
|
@@ -545,6 +571,10 @@ def delta_time() -> float:
|
|
|
545
571
|
|
|
546
572
|
@meta_fn
|
|
547
573
|
def scaled_time() -> float:
|
|
574
|
+
"""Get the current time of the game affected by the time scale.
|
|
575
|
+
|
|
576
|
+
Returns the unscaled time in tutorial mode and 0 in preview mode.
|
|
577
|
+
"""
|
|
548
578
|
if not ctx():
|
|
549
579
|
return 0
|
|
550
580
|
match ctx().global_state.mode:
|
|
@@ -560,6 +590,7 @@ def scaled_time() -> float:
|
|
|
560
590
|
|
|
561
591
|
@meta_fn
|
|
562
592
|
def touches() -> VarArray[Touch, 999]:
|
|
593
|
+
"""Get the current touches of the game."""
|
|
563
594
|
if not ctx():
|
|
564
595
|
return VarArray(0, Array[Touch, 0]())
|
|
565
596
|
match ctx().global_state.mode:
|
|
@@ -571,6 +602,10 @@ def touches() -> VarArray[Touch, 999]:
|
|
|
571
602
|
|
|
572
603
|
@meta_fn
|
|
573
604
|
def is_skip() -> bool:
|
|
605
|
+
"""Check if there was a time skip this frame.
|
|
606
|
+
|
|
607
|
+
Returns False if not in watch mode.
|
|
608
|
+
"""
|
|
574
609
|
if not ctx():
|
|
575
610
|
return False
|
|
576
611
|
match ctx().global_state.mode:
|
|
@@ -582,6 +617,10 @@ def is_skip() -> bool:
|
|
|
582
617
|
|
|
583
618
|
@meta_fn
|
|
584
619
|
def navigation_direction() -> int:
|
|
620
|
+
"""Get the navigation direction of the tutorial.
|
|
621
|
+
|
|
622
|
+
Returns 0 if not in tutorial mode.
|
|
623
|
+
"""
|
|
585
624
|
if not ctx():
|
|
586
625
|
return 0
|
|
587
626
|
match ctx().global_state.mode:
|
|
@@ -592,28 +631,34 @@ def navigation_direction() -> int:
|
|
|
592
631
|
|
|
593
632
|
|
|
594
633
|
def skin_transform() -> Transform2d:
|
|
634
|
+
"""Get the global skin transform."""
|
|
595
635
|
return _SkinTransform.transform
|
|
596
636
|
|
|
597
637
|
|
|
598
638
|
@meta_fn
|
|
599
639
|
def set_skin_transform(value: Transform2d):
|
|
640
|
+
"""Set the global skin transform."""
|
|
600
641
|
_SkinTransform.transform._copy_from_(value)
|
|
601
642
|
|
|
602
643
|
|
|
603
644
|
def particle_transform() -> Transform2d:
|
|
645
|
+
"""Get the global particle transform."""
|
|
604
646
|
return _ParticleTransform.transform
|
|
605
647
|
|
|
606
648
|
|
|
607
649
|
@meta_fn
|
|
608
650
|
def set_particle_transform(value: Transform2d):
|
|
651
|
+
"""Set the global particle transform."""
|
|
609
652
|
_ParticleTransform.transform._copy_from_(value)
|
|
610
653
|
|
|
611
654
|
|
|
612
655
|
def background() -> Quad:
|
|
656
|
+
"""Get the background quad."""
|
|
613
657
|
return _Background.value
|
|
614
658
|
|
|
615
659
|
|
|
616
660
|
def set_background(value: Quad):
|
|
661
|
+
"""Set the background quad."""
|
|
617
662
|
_Background.value = value
|
|
618
663
|
|
|
619
664
|
|
|
@@ -628,16 +673,20 @@ tutorial_ui_configs = _TutorialRuntimeUiConfigs
|
|
|
628
673
|
|
|
629
674
|
|
|
630
675
|
def canvas() -> _PreviewRuntimeCanvas:
|
|
676
|
+
"""Get the preview canvas."""
|
|
631
677
|
return _PreviewRuntimeCanvas
|
|
632
678
|
|
|
633
679
|
|
|
634
680
|
def screen() -> Rect:
|
|
681
|
+
"""Get the screen boundaries as a rectangle."""
|
|
635
682
|
return Rect(t=1, r=aspect_ratio(), b=-1, l=-aspect_ratio())
|
|
636
683
|
|
|
637
684
|
|
|
638
685
|
def level_score() -> _LevelScore:
|
|
686
|
+
"""Get the level score configuration."""
|
|
639
687
|
return _LevelScore
|
|
640
688
|
|
|
641
689
|
|
|
642
690
|
def level_life() -> _LevelLife:
|
|
691
|
+
"""Get the level life configuration."""
|
|
643
692
|
return _LevelLife
|