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.

@@ -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 execute from lowest to highest order. By default, callbacks have an order of 0.
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: Num
341
+ index: int
342
342
 
343
- def __init__(self, index: Num):
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: Num) -> Self:
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: Num) -> bool:
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: Num) -> PlayEntityInfo | WatchEntityInfo | PreviewEntityInfo:
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: Num
1050
+ perfect_increment: int
1051
1051
  """Life increment for a perfect judgment."""
1052
1052
 
1053
- great_increment: Num
1053
+ great_increment: int
1054
1054
  """Life increment for a great judgment."""
1055
1055
 
1056
- good_increment: Num
1056
+ good_increment: int
1057
1057
  """Life increment for a good judgment."""
1058
1058
 
1059
- miss_increment: Num
1059
+ miss_increment: int
1060
1060
  """Life increment for a miss judgment."""
1061
1061
 
1062
1062
  def update(
1063
1063
  self,
1064
- perfect_increment: Num | None = None,
1065
- great_increment: Num | None = None,
1066
- good_increment: Num | None = None,
1067
- miss_increment: Num | None = None,
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: Num) -> T:
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: Num, value: T):
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():
@@ -26,10 +26,10 @@ class ArrayLike[T]:
26
26
  def __len__(self) -> int:
27
27
  ...
28
28
 
29
- def __getitem__(self, index: Num) -> T:
29
+ def __getitem__(self, index: int) -> T:
30
30
  ...
31
31
 
32
- def __setitem__(self, index: Num, value: T):
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: Num) -> T:
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: Num, value: T):
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: Num = 0) -> SonolusIterator[T]:
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: Num = 0, stop: Num | None = None) -> Num:
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) -> Num:
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) -> Num:
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) -> Num:
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) -> Num:
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: Num, j: Num, /):
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: Num, end: Num, key: Callable[T, Any], reverse: bool):
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: Num, index: Num, reverse: bool):
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: Num, end: Num, reverse: bool):
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: Num) -> V:
284
+ def __getitem__(self, index: int) -> V:
285
285
  return self.array[len(self) - 1 - index]
286
286
 
287
- def __setitem__(self, index: Num, value: V):
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: Num, length: Num) -> Num:
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: Num):
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: Num):
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: Num, message: str | None = None):
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: Num, message: str | None = None):
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 PlayArchetype")
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 BaseArchetype")
242
+ raise ValueError(f"archetype {archetype} is not a PreviewArchetype")
243
243
 
244
244
 
245
245
  class TutorialMode:
@@ -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 InstructionText"
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: Num) -> Num:
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, Num]) -> Callable[P, Num]:
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: Num) -> Num:
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():
@@ -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[Num]):
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: Num, stop: Num | None = None, step: Num = 1):
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: Num) -> Num:
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: Num, value: Num):
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) -> Num:
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: Num, stop: Num | None = None, step: Num = 1) -> Range | tuple[Num, ...]:
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():
@@ -122,7 +122,7 @@ class Value:
122
122
  For instance:
123
123
  ```
124
124
  class X(Record):
125
- v: Num
125
+ v: int
126
126
 
127
127
  a = 1
128
128
  b = X(a) # (1) _get_() is called on a
@@ -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: Num, offset: Num, type_: type[T]) -> T:
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[Num] # A stream of Num values
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[Num, 10] # A group of 10 Num streams
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: Num # A data field of type Num
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: Num) -> Self:
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) -> Num:
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) -> Num:
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) -> Num:
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: Num) -> Self:
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: Num, pivot: Self) -> Self:
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:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sonolus.py
3
- Version: 0.3.3
3
+ Version: 0.3.4
4
4
  Summary: Sonolus engine development in Python
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -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=rECMAhTbVyCuxOYO3gyuBle9oCT8W18EhsUz2U_8alQ,41417
38
- sonolus/script/array.py,sha256=mq5-Im7PS0bJugBPI61D5M0gGZEUSbVcbOLORl-bfjM,11915
39
- sonolus/script/array_like.py,sha256=2otrTauxlkyR0PltjNLVHQoq4HbW4m4iWq5ygEJklaY,9390
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=JIMcGD6cQVWtIw3IIhq-5WenZZu0iArH6SAS1-XfR_8,5076
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=BhhQTrHuGAAAD6JPQ3R0jvHdimwW83PPghEIdAdtGMA,10683
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=PNfxC1dhT_hB0BxhDV3KXMn_kKxfI0t1iZmg8m6ddMU,6725
48
- sonolus/script/interval.py,sha256=9UmHjK0fzEu3Qt6cnRviy93WKcbRlI7UG8Ez-Vz-gps,11185
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=6un0Vdaporn0Ft_T71FlUAY57IFjJkCdio91e7FV6KU,15130
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=IH2_a0XE76uG_UyYM9jAYIf7qZ5LhUNc9ksXDIvAPZA,1511
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=o2GengeFlFU71WScql-75VgZCOKlq--IueHpZUBgo9s,12426
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=0Ikn5EUsFG301HORlF3n7tf5pq_nmQX-jBHycAC9pGM,24242
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=zA5aN9J63ihbiyYXvASIli-REVoIqWUac-STN6rtZVg,7404
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=Xk7tLMnV2npzPJWtHlspONQHt09Gh2YLdHhAjx4jkdE,2320
81
- sonolus/script/internal/native.py,sha256=XKlNnWSJ-lxbwVGWhGj_CSSoWsVN18imqT5sAsDJT1w,1551
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=rX4ixpy6vPEfT4HIAiMlAGKad50HjqL0StTCjqKBu-o,3370
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=gQVNQD_xGpgrN4-UXFDmWRZCJCe8wPZ_wYv4QoPRJkM,5379
88
- sonolus_py-0.3.3.dist-info/METADATA,sha256=xdAh3JPnlG9kHnswSNxBFsPBk34G8uycm0sPS2N56Gw,302
89
- sonolus_py-0.3.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
90
- sonolus_py-0.3.3.dist-info/entry_points.txt,sha256=oTYspY_b7SA8TptEMTDxh4-Aj-ZVPnYC9f1lqH6s9G4,54
91
- sonolus_py-0.3.3.dist-info/licenses/LICENSE,sha256=JEKpqVhQYfEc7zg3Mj462sKbKYmO1K7WmvX1qvg9IJk,1067
92
- sonolus_py-0.3.3.dist-info/RECORD,,
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,,