sonolus.py 0.3.3__py3-none-any.whl → 0.3.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/script/archetype.py +15 -15
- sonolus/script/array.py +3 -2
- sonolus/script/array_like.py +20 -20
- sonolus/script/debug.py +4 -4
- sonolus/script/engine.py +2 -2
- sonolus/script/instruction.py +1 -1
- sonolus/script/internal/math_impls.py +17 -0
- sonolus/script/internal/native.py +3 -3
- sonolus/script/internal/range.py +6 -6
- sonolus/script/internal/value.py +1 -1
- sonolus/script/interval.py +2 -2
- sonolus/script/num.py +13 -13
- sonolus/script/pointer.py +1 -1
- sonolus/script/record.py +5 -0
- sonolus/script/stream.py +3 -3
- sonolus/script/vec.py +6 -6
- {sonolus_py-0.3.3.dist-info → sonolus_py-0.3.4.dist-info}/METADATA +1 -1
- {sonolus_py-0.3.3.dist-info → sonolus_py-0.3.4.dist-info}/RECORD +21 -21
- {sonolus_py-0.3.3.dist-info → sonolus_py-0.3.4.dist-info}/WHEEL +0 -0
- {sonolus_py-0.3.3.dist-info → sonolus_py-0.3.4.dist-info}/entry_points.txt +0 -0
- {sonolus_py-0.3.3.dist-info → sonolus_py-0.3.4.dist-info}/licenses/LICENSE +0 -0
sonolus/script/archetype.py
CHANGED
|
@@ -312,7 +312,7 @@ class StandardImport:
|
|
|
312
312
|
def callback[T: Callable](*, order: int = 0) -> Callable[[T], T]:
|
|
313
313
|
"""Annotate a callback with its order.
|
|
314
314
|
|
|
315
|
-
Callbacks are
|
|
315
|
+
Callbacks are executed from lowest to highest order. By default, callbacks have an order of 0.
|
|
316
316
|
|
|
317
317
|
Usage:
|
|
318
318
|
```python
|
|
@@ -338,9 +338,9 @@ class _ArchetypeSelfData:
|
|
|
338
338
|
|
|
339
339
|
|
|
340
340
|
class _ArchetypeReferenceData:
|
|
341
|
-
index:
|
|
341
|
+
index: int
|
|
342
342
|
|
|
343
|
-
def __init__(self, index:
|
|
343
|
+
def __init__(self, index: int):
|
|
344
344
|
self.index = index
|
|
345
345
|
|
|
346
346
|
|
|
@@ -416,21 +416,21 @@ class _BaseArchetype:
|
|
|
416
416
|
|
|
417
417
|
@classmethod
|
|
418
418
|
@meta_fn
|
|
419
|
-
def at(cls, index:
|
|
419
|
+
def at(cls, index: int) -> Self:
|
|
420
420
|
result = cls._new()
|
|
421
421
|
result._data_ = _ArchetypeReferenceData(index=Num._accept_(index))
|
|
422
422
|
return result
|
|
423
423
|
|
|
424
424
|
@classmethod
|
|
425
425
|
@meta_fn
|
|
426
|
-
def is_at(cls, index:
|
|
426
|
+
def is_at(cls, index: int) -> bool:
|
|
427
427
|
if not ctx():
|
|
428
428
|
raise RuntimeError("is_at is only available during compilation")
|
|
429
429
|
return entity_info_at(index).archetype_id == cls.id()
|
|
430
430
|
|
|
431
431
|
@classmethod
|
|
432
432
|
@meta_fn
|
|
433
|
-
def id(cls):
|
|
433
|
+
def id(cls) -> int:
|
|
434
434
|
if not ctx():
|
|
435
435
|
raise RuntimeError("Archetype id is only available during compilation")
|
|
436
436
|
result = ctx().global_state.archetypes.get(cls)
|
|
@@ -992,7 +992,7 @@ class PreviewArchetype(_BaseArchetype):
|
|
|
992
992
|
|
|
993
993
|
|
|
994
994
|
@meta_fn
|
|
995
|
-
def entity_info_at(index:
|
|
995
|
+
def entity_info_at(index: int) -> PlayEntityInfo | WatchEntityInfo | PreviewEntityInfo:
|
|
996
996
|
"""Retrieve entity info of the entity at the given index.
|
|
997
997
|
|
|
998
998
|
Available in play, watch, and preview mode.
|
|
@@ -1047,24 +1047,24 @@ class PreviewEntityInfo(Record):
|
|
|
1047
1047
|
class ArchetypeLife(Record):
|
|
1048
1048
|
"""How an entity contributes to life."""
|
|
1049
1049
|
|
|
1050
|
-
perfect_increment:
|
|
1050
|
+
perfect_increment: int
|
|
1051
1051
|
"""Life increment for a perfect judgment."""
|
|
1052
1052
|
|
|
1053
|
-
great_increment:
|
|
1053
|
+
great_increment: int
|
|
1054
1054
|
"""Life increment for a great judgment."""
|
|
1055
1055
|
|
|
1056
|
-
good_increment:
|
|
1056
|
+
good_increment: int
|
|
1057
1057
|
"""Life increment for a good judgment."""
|
|
1058
1058
|
|
|
1059
|
-
miss_increment:
|
|
1059
|
+
miss_increment: int
|
|
1060
1060
|
"""Life increment for a miss judgment."""
|
|
1061
1061
|
|
|
1062
1062
|
def update(
|
|
1063
1063
|
self,
|
|
1064
|
-
perfect_increment:
|
|
1065
|
-
great_increment:
|
|
1066
|
-
good_increment:
|
|
1067
|
-
miss_increment:
|
|
1064
|
+
perfect_increment: int | None = None,
|
|
1065
|
+
great_increment: int | None = None,
|
|
1066
|
+
good_increment: int | None = None,
|
|
1067
|
+
miss_increment: int | None = None,
|
|
1068
1068
|
):
|
|
1069
1069
|
"""Update the life increments."""
|
|
1070
1070
|
if perfect_increment is not None:
|
sonolus/script/array.py
CHANGED
|
@@ -31,6 +31,7 @@ class Array[T, Size](GenericValue, ArrayLike[T], metaclass=ArrayMeta):
|
|
|
31
31
|
array_1 = Array(1, 2, 3)
|
|
32
32
|
array_2 = Array[int, 0]()
|
|
33
33
|
array_3 = +Array[int, 3] # Create a zero-initialized array
|
|
34
|
+
array_4 = +array_1 # Create a copy of array_1
|
|
34
35
|
```
|
|
35
36
|
"""
|
|
36
37
|
|
|
@@ -186,7 +187,7 @@ class Array[T, Size](GenericValue, ArrayLike[T], metaclass=ArrayMeta):
|
|
|
186
187
|
return self.size()
|
|
187
188
|
|
|
188
189
|
@meta_fn
|
|
189
|
-
def __getitem__(self, index:
|
|
190
|
+
def __getitem__(self, index: int) -> T:
|
|
190
191
|
index: Num = Num._accept_(get_positive_index(index, self.size()))
|
|
191
192
|
if index._is_py_() and 0 <= index._as_py_() < self.size():
|
|
192
193
|
const_index = index._as_py_()
|
|
@@ -230,7 +231,7 @@ class Array[T, Size](GenericValue, ArrayLike[T], metaclass=ArrayMeta):
|
|
|
230
231
|
raise InternalError("Unexpected array value")
|
|
231
232
|
|
|
232
233
|
@meta_fn
|
|
233
|
-
def __setitem__(self, index:
|
|
234
|
+
def __setitem__(self, index: int, value: T):
|
|
234
235
|
index: Num = Num._accept_(get_positive_index(index, self.size()))
|
|
235
236
|
value = self.element_type()._accept_(value)
|
|
236
237
|
if ctx():
|
sonolus/script/array_like.py
CHANGED
|
@@ -26,10 +26,10 @@ class ArrayLike[T]:
|
|
|
26
26
|
def __len__(self) -> int:
|
|
27
27
|
...
|
|
28
28
|
|
|
29
|
-
def __getitem__(self, index:
|
|
29
|
+
def __getitem__(self, index: int) -> T:
|
|
30
30
|
...
|
|
31
31
|
|
|
32
|
-
def __setitem__(self, index:
|
|
32
|
+
def __setitem__(self, index: int, value: T):
|
|
33
33
|
...
|
|
34
34
|
```
|
|
35
35
|
"""
|
|
@@ -41,7 +41,7 @@ class ArrayLike[T]:
|
|
|
41
41
|
"""Return the length of the array."""
|
|
42
42
|
|
|
43
43
|
@abstractmethod
|
|
44
|
-
def __getitem__(self, index:
|
|
44
|
+
def __getitem__(self, index: int) -> T:
|
|
45
45
|
"""Return the item at the given index.
|
|
46
46
|
|
|
47
47
|
Args:
|
|
@@ -49,7 +49,7 @@ class ArrayLike[T]:
|
|
|
49
49
|
"""
|
|
50
50
|
|
|
51
51
|
@abstractmethod
|
|
52
|
-
def __setitem__(self, index:
|
|
52
|
+
def __setitem__(self, index: int, value: T):
|
|
53
53
|
"""Set the value of the item at the given index.
|
|
54
54
|
|
|
55
55
|
Args:
|
|
@@ -78,10 +78,10 @@ class ArrayLike[T]:
|
|
|
78
78
|
"""Return a reversed view of the array."""
|
|
79
79
|
return _ArrayReverser(self)
|
|
80
80
|
|
|
81
|
-
def _enumerate_(self, start:
|
|
81
|
+
def _enumerate_(self, start: int = 0) -> SonolusIterator[T]:
|
|
82
82
|
return _ArrayEnumerator(0, start, self)
|
|
83
83
|
|
|
84
|
-
def index(self, value: T, start:
|
|
84
|
+
def index(self, value: T, start: int = 0, stop: int | None = None) -> int:
|
|
85
85
|
"""Return the index of the value in the array equal to the given value.
|
|
86
86
|
|
|
87
87
|
Args:
|
|
@@ -98,7 +98,7 @@ class ArrayLike[T]:
|
|
|
98
98
|
i += 1
|
|
99
99
|
return -1
|
|
100
100
|
|
|
101
|
-
def count(self, value: T) ->
|
|
101
|
+
def count(self, value: T) -> int:
|
|
102
102
|
"""Return the number of elements in the array equal to the given value.
|
|
103
103
|
|
|
104
104
|
Args:
|
|
@@ -112,7 +112,7 @@ class ArrayLike[T]:
|
|
|
112
112
|
i += 1
|
|
113
113
|
return count
|
|
114
114
|
|
|
115
|
-
def last_index(self, value: T) ->
|
|
115
|
+
def last_index(self, value: T) -> int:
|
|
116
116
|
"""Return the last index of the value in the array equal to the given value.
|
|
117
117
|
|
|
118
118
|
Args:
|
|
@@ -125,7 +125,7 @@ class ArrayLike[T]:
|
|
|
125
125
|
i -= 1
|
|
126
126
|
return -1
|
|
127
127
|
|
|
128
|
-
def index_of_max(self, *, key: Callable[T, Any] | None = None) ->
|
|
128
|
+
def index_of_max(self, *, key: Callable[[T], Any] | None = None) -> int:
|
|
129
129
|
"""Return the index of the maximum value in the array.
|
|
130
130
|
|
|
131
131
|
Args:
|
|
@@ -143,7 +143,7 @@ class ArrayLike[T]:
|
|
|
143
143
|
i += 1
|
|
144
144
|
return max_index
|
|
145
145
|
|
|
146
|
-
def index_of_min(self, *, key: Callable[T, Any] | None = None) ->
|
|
146
|
+
def index_of_min(self, *, key: Callable[[T], Any] | None = None) -> int:
|
|
147
147
|
"""Return the index of the minimum value in the array.
|
|
148
148
|
|
|
149
149
|
Args:
|
|
@@ -161,17 +161,17 @@ class ArrayLike[T]:
|
|
|
161
161
|
i += 1
|
|
162
162
|
return min_index
|
|
163
163
|
|
|
164
|
-
def _max_(self, key: Callable[T, Any] | None = None) -> T:
|
|
164
|
+
def _max_(self, key: Callable[[T], Any] | None = None) -> T:
|
|
165
165
|
index = self.index_of_max(key=key)
|
|
166
166
|
assert index != -1
|
|
167
167
|
return self[index]
|
|
168
168
|
|
|
169
|
-
def _min_(self, key: Callable[T, Any] | None = None) -> T:
|
|
169
|
+
def _min_(self, key: Callable[[T], Any] | None = None) -> T:
|
|
170
170
|
index = self.index_of_min(key=key)
|
|
171
171
|
assert index != -1
|
|
172
172
|
return self[index]
|
|
173
173
|
|
|
174
|
-
def swap(self, i:
|
|
174
|
+
def swap(self, i: int, j: int, /):
|
|
175
175
|
"""Swap the values at the given indices.
|
|
176
176
|
|
|
177
177
|
Args:
|
|
@@ -182,7 +182,7 @@ class ArrayLike[T]:
|
|
|
182
182
|
self[i] = self[j]
|
|
183
183
|
self[j] = temp
|
|
184
184
|
|
|
185
|
-
def sort(self, *, key: Callable[T, Any] | None = None, reverse: bool = False):
|
|
185
|
+
def sort(self, *, key: Callable[[T], Any] | None = None, reverse: bool = False):
|
|
186
186
|
"""Sort the values in the array in place.
|
|
187
187
|
|
|
188
188
|
Args:
|
|
@@ -216,7 +216,7 @@ def _identity[T](value: T) -> T:
|
|
|
216
216
|
return value
|
|
217
217
|
|
|
218
218
|
|
|
219
|
-
def _insertion_sort[T](array: ArrayLike[T], start:
|
|
219
|
+
def _insertion_sort[T](array: ArrayLike[T], start: int, end: int, key: Callable[[T], Any], reverse: bool):
|
|
220
220
|
i = start + 1
|
|
221
221
|
if reverse:
|
|
222
222
|
while i < end:
|
|
@@ -234,7 +234,7 @@ def _insertion_sort[T](array: ArrayLike[T], start: Num, end: Num, key: Callable[
|
|
|
234
234
|
i += 1
|
|
235
235
|
|
|
236
236
|
|
|
237
|
-
def _heapify[T](array: ArrayLike[T], end:
|
|
237
|
+
def _heapify[T](array: ArrayLike[T], end: int, index: int, reverse: bool):
|
|
238
238
|
while True:
|
|
239
239
|
left = index * 2 + 1
|
|
240
240
|
right = left + 1
|
|
@@ -249,7 +249,7 @@ def _heapify[T](array: ArrayLike[T], end: Num, index: Num, reverse: bool):
|
|
|
249
249
|
index = largest
|
|
250
250
|
|
|
251
251
|
|
|
252
|
-
def _heap_sort[T](array: ArrayLike[T], start:
|
|
252
|
+
def _heap_sort[T](array: ArrayLike[T], start: int, end: int, reverse: bool):
|
|
253
253
|
i = end // 2 - 1
|
|
254
254
|
while i >= start:
|
|
255
255
|
_heapify(array, end, i, reverse)
|
|
@@ -281,10 +281,10 @@ class _ArrayReverser[V: ArrayLike](Record, ArrayLike):
|
|
|
281
281
|
def __len__(self) -> int:
|
|
282
282
|
return len(self.array)
|
|
283
283
|
|
|
284
|
-
def __getitem__(self, index:
|
|
284
|
+
def __getitem__(self, index: int) -> V:
|
|
285
285
|
return self.array[len(self) - 1 - index]
|
|
286
286
|
|
|
287
|
-
def __setitem__(self, index:
|
|
287
|
+
def __setitem__(self, index: int, value: V):
|
|
288
288
|
self.array[len(self) - 1 - index] = value
|
|
289
289
|
|
|
290
290
|
def reversed(self) -> ArrayLike[V]:
|
|
@@ -307,7 +307,7 @@ class _ArrayEnumerator[V: ArrayLike](Record, SonolusIterator):
|
|
|
307
307
|
|
|
308
308
|
|
|
309
309
|
@meta_fn
|
|
310
|
-
def get_positive_index(index:
|
|
310
|
+
def get_positive_index(index: int, length: int) -> int:
|
|
311
311
|
"""Get the positive index for the given index in the array of the given length.
|
|
312
312
|
|
|
313
313
|
This is used to convert negative indixes relative to the end of the array to positive indices.
|
sonolus/script/debug.py
CHANGED
|
@@ -57,7 +57,7 @@ def static_error(message: str | None = None) -> Never:
|
|
|
57
57
|
|
|
58
58
|
|
|
59
59
|
@meta_fn
|
|
60
|
-
def debug_log(value:
|
|
60
|
+
def debug_log(value: int | float | bool):
|
|
61
61
|
"""Log a value in debug mode."""
|
|
62
62
|
if debug_log_callback.get(None):
|
|
63
63
|
return debug_log_callback.get()(value)
|
|
@@ -66,7 +66,7 @@ def debug_log(value: Num):
|
|
|
66
66
|
|
|
67
67
|
|
|
68
68
|
@native_function(Op.DebugLog)
|
|
69
|
-
def _debug_log(value:
|
|
69
|
+
def _debug_log(value: int | float | bool):
|
|
70
70
|
print(f"[DEBUG] {value}")
|
|
71
71
|
return 0
|
|
72
72
|
|
|
@@ -77,13 +77,13 @@ def debug_pause():
|
|
|
77
77
|
input("[DEBUG] Paused")
|
|
78
78
|
|
|
79
79
|
|
|
80
|
-
def assert_true(value:
|
|
80
|
+
def assert_true(value: int | float | bool, message: str | None = None):
|
|
81
81
|
message = message if message is not None else "Assertion failed"
|
|
82
82
|
if not value:
|
|
83
83
|
error(message)
|
|
84
84
|
|
|
85
85
|
|
|
86
|
-
def assert_false(value:
|
|
86
|
+
def assert_false(value: int | float | bool, message: str | None = None):
|
|
87
87
|
message = message if message is not None else "Assertion failed"
|
|
88
88
|
if value:
|
|
89
89
|
error(message)
|
sonolus/script/engine.py
CHANGED
|
@@ -217,7 +217,7 @@ class WatchMode:
|
|
|
217
217
|
|
|
218
218
|
for archetype in self.archetypes:
|
|
219
219
|
if not issubclass(archetype, WatchArchetype):
|
|
220
|
-
raise ValueError(f"archetype {archetype} is not a
|
|
220
|
+
raise ValueError(f"archetype {archetype} is not a WatchArchetype")
|
|
221
221
|
|
|
222
222
|
|
|
223
223
|
class PreviewMode:
|
|
@@ -239,7 +239,7 @@ class PreviewMode:
|
|
|
239
239
|
|
|
240
240
|
for archetype in self.archetypes:
|
|
241
241
|
if not issubclass(archetype, PreviewArchetype):
|
|
242
|
-
raise ValueError(f"archetype {archetype} is not a
|
|
242
|
+
raise ValueError(f"archetype {archetype} is not a PreviewArchetype")
|
|
243
243
|
|
|
244
244
|
|
|
245
245
|
class TutorialMode:
|
sonolus/script/instruction.py
CHANGED
|
@@ -97,7 +97,7 @@ def instructions[T](cls: type[T]) -> T | TutorialInstructions:
|
|
|
97
97
|
annotation_values = annotation.__metadata__
|
|
98
98
|
if annotation_type is not Instruction:
|
|
99
99
|
raise TypeError(
|
|
100
|
-
f"Invalid annotation for instruction: {annotation}, expected annotation of type
|
|
100
|
+
f"Invalid annotation for instruction: {annotation}, expected annotation of type Instruction"
|
|
101
101
|
)
|
|
102
102
|
if len(annotation_values) != 1 or not isinstance(annotation_values[0], _InstructionTextInfo):
|
|
103
103
|
raise TypeError(f"Invalid annotation for instruction: {annotation}, expected a single annotation value")
|
|
@@ -97,6 +97,22 @@ def _log(x: float, base: float | None = None) -> float:
|
|
|
97
97
|
return _ln(x) / _ln(base)
|
|
98
98
|
|
|
99
99
|
|
|
100
|
+
def _sqrt(x: float) -> float:
|
|
101
|
+
return x**0.5
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@native_function(Op.Degree)
|
|
105
|
+
def _degrees(x: float) -> float:
|
|
106
|
+
"""Convert radians to degrees."""
|
|
107
|
+
return math.degrees(x)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@native_function(Op.Radian)
|
|
111
|
+
def _radians(x: float) -> float:
|
|
112
|
+
"""Convert degrees to radians."""
|
|
113
|
+
return math.radians(x)
|
|
114
|
+
|
|
115
|
+
|
|
100
116
|
@native_function(Op.Rem)
|
|
101
117
|
def _remainder(x: float, y: float) -> float:
|
|
102
118
|
# This is different from math.remainder in Python's math package, which could be confusing
|
|
@@ -119,4 +135,5 @@ MATH_BUILTIN_IMPLS = {
|
|
|
119
135
|
id(math.trunc): _trunc,
|
|
120
136
|
id(round): _round,
|
|
121
137
|
id(math.log): _log,
|
|
138
|
+
id(math.sqrt): _sqrt,
|
|
122
139
|
}
|
|
@@ -9,7 +9,7 @@ from sonolus.script.internal.impl import meta_fn, validate_value
|
|
|
9
9
|
from sonolus.script.num import Num, _is_num
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
def native_call(op: Op, *args:
|
|
12
|
+
def native_call(op: Op, *args: int | float | bool) -> Num:
|
|
13
13
|
if not ctx():
|
|
14
14
|
raise RuntimeError("Unexpected native call")
|
|
15
15
|
args = tuple(validate_value(arg) for arg in args)
|
|
@@ -21,12 +21,12 @@ def native_call(op: Op, *args: Num) -> Num:
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
def native_function[**P, R](op: Op) -> Callable[[Callable[P, R]], Callable[P, R]]:
|
|
24
|
-
def decorator(fn: Callable[P,
|
|
24
|
+
def decorator(fn: Callable[P, int | float | bool]) -> Callable[P, Num]:
|
|
25
25
|
signature = inspect.signature(fn)
|
|
26
26
|
|
|
27
27
|
@functools.wraps(fn)
|
|
28
28
|
@meta_fn
|
|
29
|
-
def wrapper(*args:
|
|
29
|
+
def wrapper(*args: int | float | bool) -> Num:
|
|
30
30
|
if len(args) < sum(1 for p in signature.parameters.values() if p.default == inspect.Parameter.empty):
|
|
31
31
|
raise TypeError(f"Expected {len(signature.parameters)} arguments, got {len(args)}")
|
|
32
32
|
if ctx():
|
sonolus/script/internal/range.py
CHANGED
|
@@ -6,12 +6,12 @@ from sonolus.script.num import Num
|
|
|
6
6
|
from sonolus.script.record import Record
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
class Range(Record, ArrayLike[
|
|
9
|
+
class Range(Record, ArrayLike[int]):
|
|
10
10
|
start: int
|
|
11
11
|
stop: int
|
|
12
12
|
step: int
|
|
13
13
|
|
|
14
|
-
def __new__(cls, start:
|
|
14
|
+
def __new__(cls, start: int, stop: int | None = None, step: int = 1):
|
|
15
15
|
if stop is None:
|
|
16
16
|
start, stop = 0, start
|
|
17
17
|
return super().__new__(cls, start, stop, step)
|
|
@@ -37,14 +37,14 @@ class Range(Record, ArrayLike[Num]):
|
|
|
37
37
|
return 0
|
|
38
38
|
return (diff - self.step - 1) // -self.step
|
|
39
39
|
|
|
40
|
-
def __getitem__(self, index:
|
|
40
|
+
def __getitem__(self, index: int) -> int:
|
|
41
41
|
return self.start + get_positive_index(index, len(self)) * self.step
|
|
42
42
|
|
|
43
|
-
def __setitem__(self, index:
|
|
43
|
+
def __setitem__(self, index: int, value: int):
|
|
44
44
|
raise TypeError("Range does not support item assignment")
|
|
45
45
|
|
|
46
46
|
@property
|
|
47
|
-
def last(self) ->
|
|
47
|
+
def last(self) -> int:
|
|
48
48
|
return self[len(self) - 1]
|
|
49
49
|
|
|
50
50
|
def __eq__(self, other):
|
|
@@ -84,7 +84,7 @@ class RangeIterator(Record, SonolusIterator):
|
|
|
84
84
|
|
|
85
85
|
|
|
86
86
|
@meta_fn
|
|
87
|
-
def range_or_tuple(start:
|
|
87
|
+
def range_or_tuple(start: int, stop: int | None = None, step: int = 1) -> Range | tuple[int, ...]:
|
|
88
88
|
if stop is None:
|
|
89
89
|
start, stop = 0, start
|
|
90
90
|
if not ctx():
|
sonolus/script/internal/value.py
CHANGED
sonolus/script/interval.py
CHANGED
|
@@ -36,7 +36,7 @@ class Interval(Record):
|
|
|
36
36
|
|
|
37
37
|
@property
|
|
38
38
|
def is_empty(self) -> bool:
|
|
39
|
-
"""Whether the has a start greater than its end."""
|
|
39
|
+
"""Whether the interval has a start greater than its end."""
|
|
40
40
|
return self.start > self.end
|
|
41
41
|
|
|
42
42
|
@property
|
|
@@ -377,7 +377,7 @@ def interp_clamped(
|
|
|
377
377
|
xp: ArrayLike[float] | tuple[float, ...],
|
|
378
378
|
fp: ArrayLike[float] | tuple[float, ...],
|
|
379
379
|
x: float,
|
|
380
|
-
):
|
|
380
|
+
) -> float:
|
|
381
381
|
"""Linearly interpolate a value within a sequence of points.
|
|
382
382
|
|
|
383
383
|
The sequence must have at least 2 elements and be sorted in increasing order of x-coordinates.
|
sonolus/script/num.py
CHANGED
|
@@ -439,17 +439,17 @@ if TYPE_CHECKING:
|
|
|
439
439
|
|
|
440
440
|
@runtime_checkable
|
|
441
441
|
class Num[T](Protocol, int, bool, float):
|
|
442
|
-
def __add__(self, other: T, /) -> Num: ...
|
|
443
|
-
def __sub__(self, other: T, /) -> Num: ...
|
|
444
|
-
def __mul__(self, other: T, /) -> Num: ...
|
|
445
|
-
def __truediv__(self, other: T, /) -> Num: ...
|
|
446
|
-
def __floordiv__(self, other: T, /) -> Num: ...
|
|
447
|
-
def __mod__(self, other: T, /) -> Num: ...
|
|
448
|
-
def __pow__(self, other: T, /) -> Num: ...
|
|
449
|
-
|
|
450
|
-
def __neg__(self, /) -> Num: ...
|
|
451
|
-
def __pos__(self, /) -> Num: ...
|
|
452
|
-
def __abs__(self, /) -> Num: ...
|
|
442
|
+
def __add__(self, other: T, /) -> Num | int | bool | float: ...
|
|
443
|
+
def __sub__(self, other: T, /) -> Num | int | bool | float: ...
|
|
444
|
+
def __mul__(self, other: T, /) -> Num | int | bool | float: ...
|
|
445
|
+
def __truediv__(self, other: T, /) -> Num | int | bool | float: ...
|
|
446
|
+
def __floordiv__(self, other: T, /) -> Num | int | bool | float: ...
|
|
447
|
+
def __mod__(self, other: T, /) -> Num | int | bool | float: ...
|
|
448
|
+
def __pow__(self, other: T, /) -> Num | int | bool | float: ...
|
|
449
|
+
|
|
450
|
+
def __neg__(self, /) -> Num | int | bool | float: ...
|
|
451
|
+
def __pos__(self, /) -> Num | int | bool | float: ...
|
|
452
|
+
def __abs__(self, /) -> Num | int | bool | float: ...
|
|
453
453
|
|
|
454
454
|
def __eq__(self, other: Any, /) -> bool: ...
|
|
455
455
|
def __ne__(self, other: Any, /) -> bool: ...
|
|
@@ -461,10 +461,10 @@ if TYPE_CHECKING:
|
|
|
461
461
|
def __hash__(self, /) -> int: ...
|
|
462
462
|
|
|
463
463
|
@property
|
|
464
|
-
def real(self) -> Num: ...
|
|
464
|
+
def real(self) -> Num | int | bool | float: ...
|
|
465
465
|
|
|
466
466
|
@property
|
|
467
|
-
def imag(self) -> Num: ...
|
|
467
|
+
def imag(self) -> Num | int | bool | float: ...
|
|
468
468
|
else:
|
|
469
469
|
# Need to do this to satisfy type checkers (especially Pycharm)
|
|
470
470
|
_Num.__name__ = "Num"
|
sonolus/script/pointer.py
CHANGED
|
@@ -6,7 +6,7 @@ from sonolus.script.num import Num, _is_num
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
@meta_fn
|
|
9
|
-
def _deref[T: Value](block:
|
|
9
|
+
def _deref[T: Value](block: int, offset: int, type_: type[T]) -> T:
|
|
10
10
|
block = Num._accept_(block)
|
|
11
11
|
offset = Num._accept_(offset)
|
|
12
12
|
type_ = validate_value(type_)._as_py_()
|
sonolus/script/record.py
CHANGED
|
@@ -54,6 +54,11 @@ class Record(GenericValue, metaclass=RecordMeta):
|
|
|
54
54
|
record_4 = +MyRecord # Create a zero-initialized record
|
|
55
55
|
record_5 = +MyGenericRecord[int, int]
|
|
56
56
|
```
|
|
57
|
+
|
|
58
|
+
Copying a record:
|
|
59
|
+
```python
|
|
60
|
+
record_copy = +record
|
|
61
|
+
```
|
|
57
62
|
"""
|
|
58
63
|
|
|
59
64
|
_value: dict[str, Value]
|
sonolus/script/stream.py
CHANGED
|
@@ -80,12 +80,12 @@ def streams[T](cls: type[T]) -> T:
|
|
|
80
80
|
```python
|
|
81
81
|
@streams
|
|
82
82
|
class Streams:
|
|
83
|
-
stream_1: Stream[
|
|
83
|
+
stream_1: Stream[int] # A stream of int values
|
|
84
84
|
stream_2: Stream[Vec2] # A stream of Vec2 values
|
|
85
|
-
group_1: StreamGroup[
|
|
85
|
+
group_1: StreamGroup[int, 10] # A group of 10 int streams
|
|
86
86
|
group_2: StreamGroup[Vec2, 5] # A group of 5 Vec2 streams
|
|
87
87
|
|
|
88
|
-
data_field_1:
|
|
88
|
+
data_field_1: int # A data field of type int
|
|
89
89
|
data_field_2: Vec2 # A data field of type Vec2
|
|
90
90
|
```
|
|
91
91
|
"""
|
sonolus/script/vec.py
CHANGED
|
@@ -74,7 +74,7 @@ class Vec2(Record):
|
|
|
74
74
|
return cls(x=1, y=0)
|
|
75
75
|
|
|
76
76
|
@classmethod
|
|
77
|
-
def unit(cls, angle:
|
|
77
|
+
def unit(cls, angle: float) -> Self:
|
|
78
78
|
"""Return a unit vector (magnitude 1) at a given angle in radians.
|
|
79
79
|
|
|
80
80
|
Args:
|
|
@@ -86,7 +86,7 @@ class Vec2(Record):
|
|
|
86
86
|
return Vec2(x=cos(angle), y=sin(angle))
|
|
87
87
|
|
|
88
88
|
@property
|
|
89
|
-
def magnitude(self) ->
|
|
89
|
+
def magnitude(self) -> float:
|
|
90
90
|
"""Calculate the magnitude (length) of the vector.
|
|
91
91
|
|
|
92
92
|
Returns:
|
|
@@ -95,7 +95,7 @@ class Vec2(Record):
|
|
|
95
95
|
return (self.x**2 + self.y**2) ** 0.5
|
|
96
96
|
|
|
97
97
|
@property
|
|
98
|
-
def angle(self) ->
|
|
98
|
+
def angle(self) -> float:
|
|
99
99
|
"""Calculate the angle of the vector in radians from the positive x-axis.
|
|
100
100
|
|
|
101
101
|
Returns:
|
|
@@ -103,7 +103,7 @@ class Vec2(Record):
|
|
|
103
103
|
"""
|
|
104
104
|
return atan2(self.y, self.x)
|
|
105
105
|
|
|
106
|
-
def dot(self, other: Self) ->
|
|
106
|
+
def dot(self, other: Self) -> float:
|
|
107
107
|
"""Calculate the dot product of this vector with another vector.
|
|
108
108
|
|
|
109
109
|
Args:
|
|
@@ -114,7 +114,7 @@ class Vec2(Record):
|
|
|
114
114
|
"""
|
|
115
115
|
return self.x * other.x + self.y * other.y
|
|
116
116
|
|
|
117
|
-
def rotate(self, angle:
|
|
117
|
+
def rotate(self, angle: float) -> Self:
|
|
118
118
|
"""Rotate the vector by a given angle in radians and return a new vector.
|
|
119
119
|
|
|
120
120
|
Args:
|
|
@@ -128,7 +128,7 @@ class Vec2(Record):
|
|
|
128
128
|
y=self.x * sin(angle) + self.y * cos(angle),
|
|
129
129
|
)
|
|
130
130
|
|
|
131
|
-
def rotate_about(self, angle:
|
|
131
|
+
def rotate_about(self, angle: float, pivot: Self) -> Self:
|
|
132
132
|
"""Rotate the vector about a pivot by a given angle in radians and return a new vector.
|
|
133
133
|
|
|
134
134
|
Args:
|
|
@@ -34,38 +34,38 @@ sonolus/build/level.py,sha256=AjvK4725nqDcg7oGn5kWocBdG-AcirXpku74T7c2epA,673
|
|
|
34
34
|
sonolus/build/node.py,sha256=gnX71RYDUOK_gYMpinQi-bLWO4csqcfiG5gFmhxzSec,1330
|
|
35
35
|
sonolus/build/project.py,sha256=DhNqgHnm73qKUOhrg1JPlWEL0Vg7VxcGUbNokpMWzVE,6315
|
|
36
36
|
sonolus/script/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
37
|
-
sonolus/script/archetype.py,sha256=
|
|
38
|
-
sonolus/script/array.py,sha256=
|
|
39
|
-
sonolus/script/array_like.py,sha256=
|
|
37
|
+
sonolus/script/archetype.py,sha256=pQ_-J85Skf0tLT0YMoc36TUbJgc8t2HGBAzend_qmoI,41425
|
|
38
|
+
sonolus/script/array.py,sha256=8mC2LXEbYgsblkNcSi8elkAjODBYB29iN4A4-Lsfifo,11970
|
|
39
|
+
sonolus/script/array_like.py,sha256=MVFqTH2iKVpwUntMP8sxRICa9tYb9atyDs_6v0FwpNw,9402
|
|
40
40
|
sonolus/script/bucket.py,sha256=YFSyKS4ZngxerBlKwFBSCRAVewgQdwZ1-NqfPKcPZxI,7519
|
|
41
41
|
sonolus/script/containers.py,sha256=-6QooG0vIXF3fmP97Lxada7Jklm6sXQFwkevGzVNo7s,18403
|
|
42
|
-
sonolus/script/debug.py,sha256=
|
|
42
|
+
sonolus/script/debug.py,sha256=gyOXpduQwKhUrNZDoD_tODp3h6zIQ0yfZk7tKvVQ9x4,5136
|
|
43
43
|
sonolus/script/easing.py,sha256=7zaDKIfM_whUpb4FBz1DAF4NNG2vk_nDjl8kL2Y90aU,11396
|
|
44
44
|
sonolus/script/effect.py,sha256=V9bJvMzs1O4C1PjTOKgsAXov-l4AnDb2h38-DzmeWpI,5838
|
|
45
|
-
sonolus/script/engine.py,sha256=
|
|
45
|
+
sonolus/script/engine.py,sha256=etI9dJsQ7V9YZICVNZg54WqpLijPxG8eTPHiV-_EiG8,10687
|
|
46
46
|
sonolus/script/globals.py,sha256=gUvSbxXW1ZOsyQF6qb5iMRnW-eRrg07rWOK1PAYRwsE,9741
|
|
47
|
-
sonolus/script/instruction.py,sha256=
|
|
48
|
-
sonolus/script/interval.py,sha256=
|
|
47
|
+
sonolus/script/instruction.py,sha256=GKaYu6GwBLtbgj1nJilD6O2ebRRdmwHZvhYeVHbHcUc,6721
|
|
48
|
+
sonolus/script/interval.py,sha256=IhJZOuhivZZS-9nX_40ksIUPYICpTcHkekxCyo-WllE,11203
|
|
49
49
|
sonolus/script/iterator.py,sha256=wH6IM3ozLuMtCJZzhahIN3o2ykwUzDftU7ylbWo2UF8,4575
|
|
50
50
|
sonolus/script/level.py,sha256=wR23xk-NOcW_JMRb3R12sqIXCLSZL-7cM3y7IpMF1J0,6333
|
|
51
51
|
sonolus/script/metadata.py,sha256=ttRK27eojHf3So50KQJ-8yj3udZoN1bli5iD-knaeLw,753
|
|
52
|
-
sonolus/script/num.py,sha256=
|
|
52
|
+
sonolus/script/num.py,sha256=GplnvW11ZyC-bXLdk_RsRnupc__3-xNeduSpxijwNM8,15382
|
|
53
53
|
sonolus/script/options.py,sha256=OqvIPgdHbj03Ffzn857R_SrSJVUstrGy8o7Em6vv0y4,9419
|
|
54
54
|
sonolus/script/particle.py,sha256=oeVQF01xOeW2BEn04ZK1ZOP2HGvQzxBJCpITFjy9woQ,8353
|
|
55
|
-
sonolus/script/pointer.py,sha256=
|
|
55
|
+
sonolus/script/pointer.py,sha256=FoOfyD93r0G5d_2BaKfeOT9SqkOP3hq6sqtOs_Rb0c8,1511
|
|
56
56
|
sonolus/script/printing.py,sha256=mNYu9QWiacBBGZrnePZQMVwbbguoelUps9GiOK_aVRU,2096
|
|
57
57
|
sonolus/script/project.py,sha256=jLndgGJHdkqFYe-lDl_IzTjQ4gOSuy80en8WoSWXnB8,3340
|
|
58
58
|
sonolus/script/quad.py,sha256=wt0siM3SWPyQ2JEUP6sy_jVArZ62tLZjT-0ZOWPIcLw,11185
|
|
59
|
-
sonolus/script/record.py,sha256=
|
|
59
|
+
sonolus/script/record.py,sha256=1NeLkg-gufOwcUY9-B4zr8JzgzxINfUB5j9CYLrpMig,12513
|
|
60
60
|
sonolus/script/runtime.py,sha256=XaS3op1BewSQchIffbJoz8WWw-prqk1PqBx2hdI3AMY,32971
|
|
61
61
|
sonolus/script/sprite.py,sha256=CMcRAZ2hejXnaBmY2_n1_rj6hGOgPP5zEW-BpyaEVOY,16256
|
|
62
|
-
sonolus/script/stream.py,sha256=
|
|
62
|
+
sonolus/script/stream.py,sha256=G7oBMVvnDFIpivGNjKixB1OYVwDOkSZbQmc_UvNgg30,24242
|
|
63
63
|
sonolus/script/text.py,sha256=wxujIgKYcCfl2AD2_Im8g3vh0lDEHYwTSRZg9wsBPEU,13402
|
|
64
64
|
sonolus/script/timing.py,sha256=ZR0ypV2PIoDCMHHGOMfCeezStCsBQdzomdqaz5VKex0,2981
|
|
65
65
|
sonolus/script/transform.py,sha256=BKAokYC1EmyPcdlwapd5P1fA90LwVfJYrkDNDc4NHJ0,20904
|
|
66
66
|
sonolus/script/ui.py,sha256=DYPGWIjHj1IFPxW1zaEuIUQx0b32FJPXtiwCvrtJ6oo,7528
|
|
67
67
|
sonolus/script/values.py,sha256=woSW3we5OZZ1IaO3Qr0OAs_yuIpAzGw_IjwELKQHzv4,1469
|
|
68
|
-
sonolus/script/vec.py,sha256=
|
|
68
|
+
sonolus/script/vec.py,sha256=lFwMADvBYnNHkh7ejjNPRBKrFrfb1rgaVCVsx6x4Juw,7416
|
|
69
69
|
sonolus/script/internal/__init__.py,sha256=T6rzLoiOUaiSQtaHMZ88SNO-ijSjSSv33TKtUwu-Ms8,136
|
|
70
70
|
sonolus/script/internal/builtin_impls.py,sha256=VDeBpnLwu6v_r53qiXjgA1NF1aaBm9GTxP1XoWGkSLM,8569
|
|
71
71
|
sonolus/script/internal/callbacks.py,sha256=vWzJG8uiJoEtsNnbeZPqOHogCwoLpz2D1MnHY2wVV8s,2801
|
|
@@ -77,16 +77,16 @@ sonolus/script/internal/error.py,sha256=ZNnsvQVQAnFKzcvsm6-sste2lo-tP5pPI8sD7XlA
|
|
|
77
77
|
sonolus/script/internal/generic.py,sha256=F0-cCiRNGTaUJvYlpmkiOsU3Xge_XjoBpBwBhH_qS_s,7577
|
|
78
78
|
sonolus/script/internal/impl.py,sha256=0uIZ9UtZYqKbsvp2XKo-aVIzkiA8MRbiPIOt0OMmxVo,3018
|
|
79
79
|
sonolus/script/internal/introspection.py,sha256=SL2zaYjid0kkcj6ZbFLIwhgh7WKZBaAHhlbSJGr6PWs,974
|
|
80
|
-
sonolus/script/internal/math_impls.py,sha256=
|
|
81
|
-
sonolus/script/internal/native.py,sha256=
|
|
80
|
+
sonolus/script/internal/math_impls.py,sha256=nHSLgA7Tcx7jY1p07mYBCeSRmVx713bwdNayCIcaXSE,2652
|
|
81
|
+
sonolus/script/internal/native.py,sha256=rbQIpzE1Zec6IoCiQVC3kW9dJbEZmaIjDkVzrBeXQfk,1596
|
|
82
82
|
sonolus/script/internal/random.py,sha256=6Ku5edRcDUh7rtqEEYCJz0BQavw69RALsVHS25z50pI,1695
|
|
83
|
-
sonolus/script/internal/range.py,sha256=
|
|
83
|
+
sonolus/script/internal/range.py,sha256=OMYsGUB43K7jwX1sbIPnJBDk9j0gL1XPr81QUVok-C4,3370
|
|
84
84
|
sonolus/script/internal/simulation_context.py,sha256=jUgNxCOEc_b99w1yFyVz0nVb6rgkEsyuCBvcYxq34Vk,4819
|
|
85
85
|
sonolus/script/internal/transient.py,sha256=d6iYhM9f6DPUX5nkYQGm-x0b9XEfZUmB4AtUNnyhixo,1636
|
|
86
86
|
sonolus/script/internal/tuple_impl.py,sha256=DPNdmmRmupU8Ah4_XKq6-PdT336l4nt15_uCJKQGkkk,3587
|
|
87
|
-
sonolus/script/internal/value.py,sha256=
|
|
88
|
-
sonolus_py-0.3.
|
|
89
|
-
sonolus_py-0.3.
|
|
90
|
-
sonolus_py-0.3.
|
|
91
|
-
sonolus_py-0.3.
|
|
92
|
-
sonolus_py-0.3.
|
|
87
|
+
sonolus/script/internal/value.py,sha256=bfooiA5cMlZOCKqqchnUGNdJJc6-ec2jHoLsDZjbU_g,5379
|
|
88
|
+
sonolus_py-0.3.4.dist-info/METADATA,sha256=B9QIp4ebnYp4YO5F7TXa3bP-MHKoJJQ3cMMlgrA0JF4,302
|
|
89
|
+
sonolus_py-0.3.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
90
|
+
sonolus_py-0.3.4.dist-info/entry_points.txt,sha256=oTYspY_b7SA8TptEMTDxh4-Aj-ZVPnYC9f1lqH6s9G4,54
|
|
91
|
+
sonolus_py-0.3.4.dist-info/licenses/LICENSE,sha256=JEKpqVhQYfEc7zg3Mj462sKbKYmO1K7WmvX1qvg9IJk,1067
|
|
92
|
+
sonolus_py-0.3.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|