sonolus.py 0.5.1__py3-none-any.whl → 0.6.0__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.
sonolus/backend/utils.py CHANGED
@@ -1,4 +1,3 @@
1
- # ruff: noqa: N802
2
1
  import ast
3
2
  import inspect
4
3
  from collections.abc import Callable
@@ -1,4 +1,3 @@
1
- # ruff: noqa: N802
2
1
  from __future__ import annotations
3
2
 
4
3
  import ast
@@ -244,7 +244,9 @@ class Collection:
244
244
  use_item = level[key]
245
245
  if "item" not in use_item:
246
246
  continue
247
- use_item["item"] = self.get_item(category, use_item["item"])
247
+ name = use_item["item"]["name"]
248
+ if name in self.categories.get(category, {}):
249
+ use_item["item"] = self.get_item(category, name)
248
250
 
249
251
  def _create_base_directory(self, path: Asset) -> Path:
250
252
  base_dir = Path(path) / BASE_PATH.strip("/")
sonolus/build/project.py CHANGED
@@ -19,6 +19,9 @@ BLANK_AUDIO = (
19
19
 
20
20
  def build_project_to_collection(project: Project, config: BuildConfig | None):
21
21
  collection = load_resources_files_to_collection(project.resources)
22
+ if config.override_resource_level_engines:
23
+ for level in collection.categories.get("levels", {}).values():
24
+ level["item"]["engine"] = project.engine.name
22
25
  add_engine_to_collection(collection, project, project.engine, config)
23
26
  for level in project.levels:
24
27
  add_level_to_collection(collection, project, level)
@@ -245,6 +245,21 @@ class _KeyDescriptor(SonolusDescriptor):
245
245
  raise AttributeError("Archetype key is read-only and cannot be set")
246
246
 
247
247
 
248
+ class _ArchetypeLifeDescriptor(SonolusDescriptor):
249
+ def __get__(self, instance, owner):
250
+ if not ctx():
251
+ raise RuntimeError("Archetype life is only available during compilation")
252
+ if ctx().global_state.mode not in {Mode.PLAY, Mode.WATCH}:
253
+ raise RuntimeError(f"Archetype life is not available in mode '{ctx().global_state.mode.value}'")
254
+ if instance is not None:
255
+ return _deref(ctx().blocks.ArchetypeLife, instance.id * ArchetypeLife._size_(), ArchetypeLife)
256
+ else:
257
+ return _deref(ctx().blocks.ArchetypeLife, owner.id * ArchetypeLife._size_(), ArchetypeLife)
258
+
259
+ def __set__(self, instance, value):
260
+ raise AttributeError("Archetype life is read-only and cannot be set")
261
+
262
+
248
263
  def imported(*, name: str | None = None) -> Any:
249
264
  """Declare a field as imported.
250
265
 
@@ -459,7 +474,7 @@ class _BaseArchetype:
459
474
  still be the id of `A`.
460
475
  """
461
476
 
462
- key: int = -1
477
+ key: int | float = -1
463
478
  """An optional key for the archetype.
464
479
 
465
480
  May be useful to identify an archetype in an inheritance hierarchy without needing to check id.
@@ -467,7 +482,7 @@ class _BaseArchetype:
467
482
  If accessed on an entity, always returns the runtime key of the entity, even if it doesn't match the type
468
483
  that was used to access it.
469
484
 
470
- E.g. if an entity of archetype `A` is accessed via [`EntityRef[B]`][sonolus.script.archetype.EntityRef], the key
485
+ E.g. if an entity of archetype `A` is accessed via [`EntityRef[B]`][sonolus.script.archetype.EntityRef], the key
471
486
  will still be the key of `A`.
472
487
  """
473
488
 
@@ -590,6 +605,7 @@ class _BaseArchetype:
590
605
  cls.key = _KeyDescriptor(cls.key)
591
606
  cls.name = _NameDescriptor(cls.name)
592
607
  cls.is_scored = _IsScoredDescriptor(cls.is_scored)
608
+ cls.life = _ArchetypeLifeDescriptor()
593
609
 
594
610
  @classmethod
595
611
  def _init_fields(cls):
@@ -605,6 +621,7 @@ class _BaseArchetype:
605
621
  "id",
606
622
  "key",
607
623
  "name",
624
+ "life",
608
625
  "is_scored",
609
626
  "_key_",
610
627
  "_derived_base_",
@@ -751,8 +768,17 @@ class _BaseArchetype:
751
768
  def derive[T](cls: type[T], name: str, is_scored: bool, key: int | float | None = None) -> type[T]:
752
769
  """Derive a new archetype class from this archetype.
753
770
 
771
+ Roughly equivalent to returning:
772
+ ```python
773
+ class Derived(cls):
774
+ name = <name>
775
+ is_scored = <is_scored>
776
+ key = <key> # Only set if key is not None
777
+ ```
778
+
754
779
  This is used to create a new archetype with the same fields and callbacks, but with a different name and
755
- whether it is scored.
780
+ whether it is scored. Compared to manually subclassing, this method also enables faster compilation when
781
+ the same base archetype has multiple derived archetypes by compiling callbacks only once for the base archetype.
756
782
 
757
783
  Args:
758
784
  name: The name of the new archetype.
@@ -800,7 +826,10 @@ class PlayArchetype(_BaseArchetype):
800
826
  _supported_callbacks_ = PLAY_CALLBACKS
801
827
 
802
828
  is_scored: ClassVar[bool] = False
803
- """Whether the entity contributes to combo and score."""
829
+ """Whether entities of this archetype contribute to combo and score."""
830
+
831
+ life: ClassVar[ArchetypeLife]
832
+ """How this entities of this archetype contribute to life depending on judgment."""
804
833
 
805
834
  def preprocess(self):
806
835
  """Perform upfront processing.
@@ -916,18 +945,6 @@ class PlayArchetype(_BaseArchetype):
916
945
  """Whether this entity is despawned."""
917
946
  return self._info.state == 2
918
947
 
919
- @property
920
- @meta_fn
921
- def life(self) -> ArchetypeLife:
922
- """How this entity contributes to life."""
923
- if not ctx():
924
- raise RuntimeError("Calling life is only allowed within a callback")
925
- match self._data_:
926
- case _ArchetypeSelfData() | _ArchetypeReferenceData():
927
- return _deref(ctx().blocks.ArchetypeLife, self.id * ArchetypeLife._size_(), ArchetypeLife)
928
- case _:
929
- raise RuntimeError("Life is not available in level data")
930
-
931
948
  @property
932
949
  @meta_fn
933
950
  def result(self) -> PlayEntityInput:
@@ -964,6 +981,12 @@ class WatchArchetype(_BaseArchetype):
964
981
 
965
982
  _supported_callbacks_ = WATCH_ARCHETYPE_CALLBACKS
966
983
 
984
+ is_scored: ClassVar[bool] = False
985
+ """Whether entities of this archetype contribute to combo and score."""
986
+
987
+ life: ClassVar[ArchetypeLife]
988
+ """How this entities of this archetype contribute to life depending on judgment."""
989
+
967
990
  def preprocess(self):
968
991
  """Perform upfront processing.
969
992
 
@@ -1029,18 +1052,6 @@ class WatchArchetype(_BaseArchetype):
1029
1052
  """Whether this entity is active."""
1030
1053
  return self._info.state == 1
1031
1054
 
1032
- @property
1033
- @meta_fn
1034
- def life(self) -> ArchetypeLife:
1035
- """How this entity contributes to life."""
1036
- if not ctx():
1037
- raise RuntimeError("Calling life is only allowed within a callback")
1038
- match self._data_:
1039
- case _ArchetypeSelfData() | _ArchetypeReferenceData():
1040
- return _deref(ctx().blocks.ArchetypeLife, self.id * ArchetypeLife._size_(), ArchetypeLife)
1041
- case _:
1042
- raise RuntimeError("Life is not available in level data")
1043
-
1044
1055
  @property
1045
1056
  @meta_fn
1046
1057
  def result(self) -> WatchEntityInput:
@@ -1118,6 +1129,23 @@ class PreviewArchetype(_BaseArchetype):
1118
1129
  raise RuntimeError("Preview archetypes cannot have exported fields")
1119
1130
 
1120
1131
 
1132
+ @meta_fn
1133
+ def get_archetype_by_name(name: str) -> AnyArchetype:
1134
+ """Return the archetype with the given name in the current mode."""
1135
+ if not ctx():
1136
+ raise RuntimeError("Archetypes by name are only available during compilation.")
1137
+ name = validate_value(name)
1138
+ if not name._is_py_():
1139
+ raise TypeError(f"Invalid name: '{name}'")
1140
+ name = name._as_py_()
1141
+ if not isinstance(name, str):
1142
+ raise TypeError(f"Invalid name: '{name}'")
1143
+ archetypes_by_name = ctx().global_state.archetypes_by_name
1144
+ if name not in archetypes_by_name:
1145
+ raise KeyError(f"Unknown archetype: '{name}'")
1146
+ return archetypes_by_name[name]
1147
+
1148
+
1121
1149
  @meta_fn
1122
1150
  def entity_info_at(index: int) -> PlayEntityInfo | WatchEntityInfo | PreviewEntityInfo:
1123
1151
  """Retrieve entity info of the entity at the given index.
@@ -1137,23 +1165,6 @@ def entity_info_at(index: int) -> PlayEntityInfo | WatchEntityInfo | PreviewEnti
1137
1165
  raise RuntimeError(f"Entity info is not available in mode '{ctx().global_state.mode}'")
1138
1166
 
1139
1167
 
1140
- @meta_fn
1141
- def archetype_life_of(archetype: type[_BaseArchetype] | _BaseArchetype) -> ArchetypeLife:
1142
- """Retrieve the archetype life of the given archetype.
1143
-
1144
- Available in play and watch mode.
1145
- """
1146
- archetype = validate_value(archetype) # type: ignore
1147
- archetype = archetype._as_py_() # type: ignore
1148
- if not ctx():
1149
- raise RuntimeError("Calling archetype_life_of is only allowed within a callback")
1150
- match ctx().global_state.mode:
1151
- case Mode.PLAY | Mode.WATCH:
1152
- return _deref(ctx().blocks.ArchetypeLife, archetype.id * ArchetypeLife._size_(), ArchetypeLife)
1153
- case _:
1154
- raise RuntimeError(f"Archetype life is not available in mode '{ctx().global_state.mode}'")
1155
-
1156
-
1157
1168
  class PlayEntityInfo(Record):
1158
1169
  index: int
1159
1170
  archetype_id: int
@@ -1301,3 +1312,7 @@ class StandardArchetypeName(StrEnum):
1301
1312
 
1302
1313
  TIMESCALE_CHANGE = "#TIMESCALE_CHANGE"
1303
1314
  """Timescale change marker"""
1315
+
1316
+
1317
+ type AnyArchetype = PlayArchetype | WatchArchetype | PreviewArchetype
1318
+ """Union of all archetype types."""
sonolus/script/bucket.py CHANGED
@@ -230,7 +230,7 @@ def bucket(*, sprites: list[_BucketSprite], unit: str | None = None) -> Any:
230
230
  type Buckets = NewType("Buckets", Any) # type: ignore
231
231
 
232
232
 
233
- @dataclass_transform()
233
+ @dataclass_transform(kw_only_default=True)
234
234
  def buckets[T](cls: type[T]) -> T | Buckets:
235
235
  """Decorator to define a buckets class.
236
236
 
sonolus/script/debug.py CHANGED
@@ -82,6 +82,9 @@ def assert_false(value: int | float | bool, message: str | None = None):
82
82
 
83
83
  @meta_fn
84
84
  def assert_unreachable(message: str | None = None) -> Never:
85
+ # This works a bit differently from assert_never from typing in that it throws an error if the Sonolus.py
86
+ # compiler cannot guarantee that this function will not be called, which is different from what type checkers
87
+ # may be able to infer.
85
88
  message = validate_value(message)._as_py_() or "Unreachable code reached" # type: ignore
86
89
  raise RuntimeError(message)
87
90
 
sonolus/script/effect.py CHANGED
@@ -139,7 +139,7 @@ def effect(name: str) -> Any:
139
139
  type Effects = NewType("Effects", Any) # type: ignore
140
140
 
141
141
 
142
- @dataclass_transform()
142
+ @dataclass_transform(kw_only_default=True)
143
143
  def effects[T](cls: type[T]) -> T | Effects:
144
144
  """Decorator to define effect clips.
145
145
 
@@ -74,7 +74,7 @@ type TutorialInstructions = NewType("TutorialInstructions", Any) # type: ignore
74
74
  type TutorialInstructionIcons = NewType("TutorialInstructionIcons", Any) # type: ignore
75
75
 
76
76
 
77
- @dataclass_transform()
77
+ @dataclass_transform(kw_only_default=True)
78
78
  def instructions[T](cls: type[T]) -> T | TutorialInstructions:
79
79
  """Decorator to define tutorial instructions.
80
80
 
@@ -109,7 +109,7 @@ def instructions[T](cls: type[T]) -> T | TutorialInstructions:
109
109
  return instance
110
110
 
111
111
 
112
- @dataclass_transform()
112
+ @dataclass_transform(kw_only_default=True)
113
113
  def instruction_icons[T](cls: type[T]) -> T | TutorialInstructionIcons:
114
114
  """Decorator to define tutorial instruction icons.
115
115
 
@@ -1,3 +1,5 @@
1
+ from typing import Never, assert_never
2
+
1
3
  from sonolus.backend.ops import Op
2
4
  from sonolus.script.array import Array
3
5
  from sonolus.script.array_like import ArrayLike
@@ -78,10 +80,13 @@ def _reversed(iterable):
78
80
 
79
81
 
80
82
  @meta_fn
81
- def _zip(*iterables):
83
+ def _zip(*iterables, strict: bool = False):
82
84
  from sonolus.backend.visitor import compile_and_call
83
85
  from sonolus.script.containers import Pair
84
86
 
87
+ if validate_value(strict)._as_py_():
88
+ raise NotImplementedError("Strict zipping is not supported")
89
+
85
90
  if not iterables:
86
91
  return _EmptyIterator()
87
92
 
@@ -383,6 +388,11 @@ def _super(*args):
383
388
  return super(*(arg._as_py_() if arg._is_py_() else arg for arg in args))
384
389
 
385
390
 
391
+ @meta_fn
392
+ def _assert_never(arg: Never, /):
393
+ error("Expected code to be unreachable")
394
+
395
+
386
396
  # classmethod, property, staticmethod are supported as decorators, but not within functions
387
397
 
388
398
  BUILTIN_IMPLS = {
@@ -407,6 +417,7 @@ BUILTIN_IMPLS = {
407
417
  id(reversed): _reversed,
408
418
  id(super): _super,
409
419
  id(zip): _zip,
420
+ id(assert_never): _assert_never,
410
421
  **MATH_BUILTIN_IMPLS, # Includes round
411
422
  **RANDOM_BUILTIN_IMPLS,
412
423
  }
@@ -41,6 +41,7 @@ debug_var = ContextVar("debug_var", default=_disabled_debug_config)
41
41
 
42
42
  class GlobalContextState:
43
43
  archetypes: dict[type, int]
44
+ archetypes_by_name: dict[str, type]
44
45
  keys: Sequence[int] | None
45
46
  rom: ReadOnlyMemory
46
47
  const_mappings: dict[Any, int]
@@ -53,6 +54,7 @@ class GlobalContextState:
53
54
  from sonolus.script.array import Array
54
55
 
55
56
  self.archetypes = archetypes or {}
57
+ self.archetypes_by_name = {type_.name: type_ for type_, _ in self.archetypes.items()} # type: ignore
56
58
  self.keys = (
57
59
  Array(*((getattr(a, "_key_", -1)) for a in sorted(self.archetypes, key=lambda a: archetypes[a])))
58
60
  if archetypes
sonolus/script/options.py CHANGED
@@ -230,7 +230,7 @@ class _OptionField(SonolusDescriptor):
230
230
  raise AttributeError("Options are read-only")
231
231
 
232
232
 
233
- @dataclass_transform()
233
+ @dataclass_transform(kw_only_default=True)
234
234
  def options[T](cls: type[T]) -> T | Options:
235
235
  """Decorator to define options.
236
236
 
@@ -98,7 +98,7 @@ def particle(name: str) -> Any:
98
98
  type Particles = NewType("Particles", Any) # type: ignore
99
99
 
100
100
 
101
- @dataclass_transform()
101
+ @dataclass_transform(kw_only_default=True)
102
102
  def particles[T](cls: type[T]) -> T | Particles:
103
103
  """Decorator to define particles.
104
104
 
sonolus/script/project.py CHANGED
@@ -129,3 +129,6 @@ class BuildConfig:
129
129
 
130
130
  build_tutorial: bool = True
131
131
  """Whether to build the tutorial package."""
132
+
133
+ override_resource_level_engines: bool = True
134
+ """Whether to override any levels included in resources to use the engine of this project."""
sonolus/script/sprite.py CHANGED
@@ -283,7 +283,7 @@ class RenderMode(StrEnum):
283
283
  """Use the lightweight render mode with projective interpolation of textures."""
284
284
 
285
285
 
286
- @dataclass_transform()
286
+ @dataclass_transform(kw_only_default=True)
287
287
  def skin[T](cls: type[T]) -> T | Skin:
288
288
  """Decorator to define a skin.
289
289
 
sonolus/script/stream.py CHANGED
@@ -59,7 +59,7 @@ class _StreamDataField(SonolusDescriptor):
59
59
  self._get()._copy_from_(value)
60
60
 
61
61
 
62
- @dataclass_transform()
62
+ @dataclass_transform(kw_only_default=True)
63
63
  def streams[T](cls: type[T]) -> T:
64
64
  """Decorator to define streams and stream groups.
65
65
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sonolus.py
3
- Version: 0.5.1
3
+ Version: 0.6.0
4
4
  Summary: Sonolus engine development in Python
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -10,8 +10,8 @@ sonolus/backend/mode.py,sha256=NkcPZJm8dn83LX35uP24MtQOCnfRDFZ280dHeEEfauE,613
10
10
  sonolus/backend/node.py,sha256=eEzPP14jzWJp2xrZCAaPlNtokxdoqg0bSM7xQiwx1j8,1254
11
11
  sonolus/backend/ops.py,sha256=5weB_vIxbkwCSJuzYZyKUk7vVXsSIEDJYRlvE-2ke8A,10572
12
12
  sonolus/backend/place.py,sha256=7qwV732hZ4WP-9GNN8FQSEKssPJZELip1wLXTWfop7Y,4717
13
- sonolus/backend/utils.py,sha256=DDgYUVHh4h_eSY65v2KcxUaLSBYGYS6oHar5gTdV7QU,2356
14
- sonolus/backend/visitor.py,sha256=Dz_3w3gvmJraNC2fMMlkYthEmT0AkZfHGFsrracELuo,63121
13
+ sonolus/backend/utils.py,sha256=OwD1EPh8j-hsfkLzeKNzPQojT_3kklpJou0WTJNoCbc,2337
14
+ sonolus/backend/visitor.py,sha256=oq8IhuuhigXMZtNgxD9ZjI_ZLVrp9ikFm9Yz636F5Fo,63102
15
15
  sonolus/backend/optimize/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  sonolus/backend/optimize/allocate.py,sha256=CuumoMphkpQlGRNeKLHT4FBGE0XVj5pwhfNdrqiLFSs,7535
17
17
  sonolus/backend/optimize/constant_evaluation.py,sha256=U--9moGsXFzrgweWWwHIiEuuMzwetd1IOjjtrCscoNM,21450
@@ -27,40 +27,40 @@ sonolus/backend/optimize/simplify.py,sha256=RDNVTKfC7ByRyxY5z30_ShimOAKth_pKlVFV
27
27
  sonolus/backend/optimize/ssa.py,sha256=raQO0furQQRPYb8iIBKfNrJlj-_5wqtI4EWNfLZ8QFo,10834
28
28
  sonolus/build/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
29
  sonolus/build/cli.py,sha256=-_lTN8zT7nQB2lySM8itAEPVutcEQI-TJ13BcPIfGb4,10113
30
- sonolus/build/collection.py,sha256=kOVnpQC_KHAsyTM4nAplSh6QE16CgO-H6PP1GItWm78,12187
30
+ sonolus/build/collection.py,sha256=sMYLfEIVn6UydLy7iEnNwrpIXDs7bGG32uQQgHXyhSI,12289
31
31
  sonolus/build/compile.py,sha256=Yex-ZbSZmv9ujyAOVaMcfq-0NnZzFIqtmNYYaplF4Uc,6761
32
32
  sonolus/build/engine.py,sha256=zUl0KfRygqNhIM8BABNJkKG-0zXFwcYwck-5hJy59yk,13338
33
33
  sonolus/build/level.py,sha256=yXsQtnabkJK0vuVmZ_Wr1jx37jFLgInCS7lTlXjkv9Q,706
34
34
  sonolus/build/node.py,sha256=gnX71RYDUOK_gYMpinQi-bLWO4csqcfiG5gFmhxzSec,1330
35
- sonolus/build/project.py,sha256=mv2OuzgIDG-E9G4SIRiUDL5XiPCd1i81wVl1p7itFHA,6329
35
+ sonolus/build/project.py,sha256=eHh4ioOjaFtt26bcefUuDZhMhFw8NXnjRTYPiEInQV8,6505
36
36
  sonolus/script/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
- sonolus/script/archetype.py,sha256=jhxyH-Lic-ZfOzD4H7-rPu9OChp900mTD_HpkA00FoY,46638
37
+ sonolus/script/archetype.py,sha256=DMtg-wWId6UAoh1L_jbMq4EMwLuY6tPY29wVoB8oD6A,47279
38
38
  sonolus/script/array.py,sha256=9uOUHZIDMyMT9q3APcXJWXWt97yG-AZoRlxwrvSY6SU,12367
39
39
  sonolus/script/array_like.py,sha256=jFOfXkniTLrIK4ER6HO_tUyKn_TvwjyM4B3SDd9cUS8,9678
40
- sonolus/script/bucket.py,sha256=VxsSgHidYhY_Y5UXpBZY_tzjQff0TRgNJVj4Al8LVec,7654
40
+ sonolus/script/bucket.py,sha256=SNqnfLGpnO_u-3LFFazdgzNk332OdDUIlmZHsuoVZuE,7674
41
41
  sonolus/script/containers.py,sha256=WX0qRnr6gNtn3C0q7MwMyrzvY-C0Bd1tzLGxSkUwL9U,18680
42
- sonolus/script/debug.py,sha256=_Hg1cXQJ8fBXMiwhmoPb2X9CKcQ8QO26WNa59K518og,4305
42
+ sonolus/script/debug.py,sha256=Vi97opuk9fMB5bdpzPCBpa2oZeTff7FQ4WzdeDE5trk,4557
43
43
  sonolus/script/easing.py,sha256=txf0OPFP5v7cOFDvJKCyKLK-d2uKIOu56ntLEHfD9QI,11377
44
- sonolus/script/effect.py,sha256=mhl58IgHUl7GI6kDdwK6l_KWVXYWxxpAcfOjSkdrLj4,5944
44
+ sonolus/script/effect.py,sha256=OedYn0uOgYdZIGeJ6dATBSo5MSD21_v1Uvgoe6yVr9U,5964
45
45
  sonolus/script/engine.py,sha256=etI9dJsQ7V9YZICVNZg54WqpLijPxG8eTPHiV-_EiG8,10687
46
46
  sonolus/script/globals.py,sha256=USwh_TuyZh1qORPVLk6x9qe3ca9iLhf5gnqT773gVvY,10007
47
- sonolus/script/instruction.py,sha256=iBjY7nCNDT3w0SBJKlix3Z-85e7eE2qKeHp6C2Nq7KA,6753
47
+ sonolus/script/instruction.py,sha256=Dd-14D5Amo8nhPBr6DNyg2lpYw_rqZkT8Kix3HkfE7k,6793
48
48
  sonolus/script/interval.py,sha256=dj6F2wn5uP6I6_mcZn-wIREgRUQbsLzhvhzB0oEyAdU,11290
49
49
  sonolus/script/iterator.py,sha256=_ICY_yX7FG0Zbgs3NhVnaIBdVDpAeXjxJ_CQtq30l7Y,3774
50
50
  sonolus/script/level.py,sha256=vnotMbdr_4-MJUsTXMbvWiw2MlMjMHme3q0XRdNFXRg,6349
51
51
  sonolus/script/maybe.py,sha256=VYvTWgEfPzoXqI3i3zXhc4dz0pWBVoHmW8FtWH0GQvM,8194
52
52
  sonolus/script/metadata.py,sha256=ttRK27eojHf3So50KQJ-8yj3udZoN1bli5iD-knaeLw,753
53
53
  sonolus/script/num.py,sha256=924kWWZusW7oaWuvtQzdAMzkb4ZItWSJwNj3W9XrqZU,16041
54
- sonolus/script/options.py,sha256=KlOud4QOf_lW1o6avKXbkjcMCDPkhLcEwt5PW7ZCH3s,9435
55
- sonolus/script/particle.py,sha256=XczhwTJvU3dMOXXTxJI_5Mskro2LgVlNgrCSwYreO0Q,8369
54
+ sonolus/script/options.py,sha256=XVN-mL7Rwhd2Tu9YysYq9YDGpH_LazdmhqzSYE6nR3Q,9455
55
+ sonolus/script/particle.py,sha256=m6VLH_05zKQIyiqyVyD6z0sbzjOYhRuZwgPY82u-BOo,8389
56
56
  sonolus/script/pointer.py,sha256=FoOfyD93r0G5d_2BaKfeOT9SqkOP3hq6sqtOs_Rb0c8,1511
57
57
  sonolus/script/printing.py,sha256=mNYu9QWiacBBGZrnePZQMVwbbguoelUps9GiOK_aVRU,2096
58
- sonolus/script/project.py,sha256=2XVUXcW49iiTfljvcFuYqtFzqhQIRvD7H7OwH1Mm98w,4009
58
+ sonolus/script/project.py,sha256=BDGaae3lXWQqZgY3lF3_27VSSk_oGEA4sbN-gQFlhAM,4157
59
59
  sonolus/script/quad.py,sha256=XoAjaUqR60zIrC_CwheZs7HwS-DRS58yUmlj9GIjX7k,11179
60
60
  sonolus/script/record.py,sha256=-Ff60wBoF1v4-MJWzCNI9n5K3os6WphswZpdTBezeRs,12713
61
61
  sonolus/script/runtime.py,sha256=rJZM_KbKmnwpjhDEpR0DrM6EMSEu46apIErWA_pfLJA,33321
62
- sonolus/script/sprite.py,sha256=pgFQvzWB-uy9MsOfV8QabXKjnNgx5vN6md9uNYztHco,16297
63
- sonolus/script/stream.py,sha256=q3uJUfUP9fx0Go7qXQopl9DMh_RJkT-96p5WlAo4x0M,24693
62
+ sonolus/script/sprite.py,sha256=kqFESwQjR-tTJ3EEMnXmMBxX-gCjtPYwF5Pgx1OInNM,16317
63
+ sonolus/script/stream.py,sha256=qVljaCxJJtQs7aBwfUG15pYvztb4jFYzSLGDh5t4DTA,24713
64
64
  sonolus/script/text.py,sha256=wxujIgKYcCfl2AD2_Im8g3vh0lDEHYwTSRZg9wsBPEU,13402
65
65
  sonolus/script/timing.py,sha256=ZR0ypV2PIoDCMHHGOMfCeezStCsBQdzomdqaz5VKex0,2981
66
66
  sonolus/script/transform.py,sha256=w5mr7hTuNYU0eTAdnN_wTVibaQa0mZrkl-W-kgewJxQ,21345
@@ -68,10 +68,10 @@ sonolus/script/ui.py,sha256=DYPGWIjHj1IFPxW1zaEuIUQx0b32FJPXtiwCvrtJ6oo,7528
68
68
  sonolus/script/values.py,sha256=6iJG6h4IDlbcK8FH4GENSHOQc7C_7fCGa34wM80qToA,1629
69
69
  sonolus/script/vec.py,sha256=oVx5C5zGj8gX37F7y1FEJOrTYzb7EWfQWQuKU8KGLdc,7486
70
70
  sonolus/script/internal/__init__.py,sha256=T6rzLoiOUaiSQtaHMZ88SNO-ijSjSSv33TKtUwu-Ms8,136
71
- sonolus/script/internal/builtin_impls.py,sha256=POmWRyTQa-9mpQ_jATDYlFWo_n0a65vXAgqitkKYzGY,12870
71
+ sonolus/script/internal/builtin_impls.py,sha256=lu0Je_DD7xGjgF766sf0S0EiBEHiKuyre-2arI-ysZA,13170
72
72
  sonolus/script/internal/callbacks.py,sha256=vWzJG8uiJoEtsNnbeZPqOHogCwoLpz2D1MnHY2wVV8s,2801
73
73
  sonolus/script/internal/constant.py,sha256=3ycbGkDJVUwcrCZ96vLjAoAARgsvaqDM8rJ_YCrLrvo,4289
74
- sonolus/script/internal/context.py,sha256=JtKyjFlt7t2YwR1qFUGGjzYrE8v0yfsP-7XA196gtaQ,17211
74
+ sonolus/script/internal/context.py,sha256=jto68tBpmF3As_h22tNVNP7ctJjt4S0HySF_DbFhbok,17361
75
75
  sonolus/script/internal/descriptor.py,sha256=XRFey-EjiAm_--KsNl-8N0Mi_iyQwlPh68gDp0pKf3E,392
76
76
  sonolus/script/internal/dict_impl.py,sha256=alu_wKGSk1kZajNf64qbe7t71shEzD4N5xNIATH8Swo,1885
77
77
  sonolus/script/internal/error.py,sha256=ZNnsvQVQAnFKzcvsm6-sste2lo-tP5pPI8sD7XlAZWc,490
@@ -86,8 +86,8 @@ sonolus/script/internal/simulation_context.py,sha256=LGxLTvxbqBIhoe1R-SfwGajNIDw
86
86
  sonolus/script/internal/transient.py,sha256=y2AWABqF1aoaP6H4_2u4MMpNioC4OsZQCtPyNI0txqo,1634
87
87
  sonolus/script/internal/tuple_impl.py,sha256=DPNdmmRmupU8Ah4_XKq6-PdT336l4nt15_uCJKQGkkk,3587
88
88
  sonolus/script/internal/value.py,sha256=OngrCdmY_h6mV2Zgwqhuo4eYFad0kTk6263UAxctZcY,6963
89
- sonolus_py-0.5.1.dist-info/METADATA,sha256=RqZZ8ZVpQV4cKUJ2tVZQcdlBxMGbyoJjURrCYn9CSAc,302
90
- sonolus_py-0.5.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
91
- sonolus_py-0.5.1.dist-info/entry_points.txt,sha256=oTYspY_b7SA8TptEMTDxh4-Aj-ZVPnYC9f1lqH6s9G4,54
92
- sonolus_py-0.5.1.dist-info/licenses/LICENSE,sha256=JEKpqVhQYfEc7zg3Mj462sKbKYmO1K7WmvX1qvg9IJk,1067
93
- sonolus_py-0.5.1.dist-info/RECORD,,
89
+ sonolus_py-0.6.0.dist-info/METADATA,sha256=K_kv0PG-xEfUmeMziKncaw3lx6D_9Sl2OfqpNYFs5OM,302
90
+ sonolus_py-0.6.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
91
+ sonolus_py-0.6.0.dist-info/entry_points.txt,sha256=oTYspY_b7SA8TptEMTDxh4-Aj-ZVPnYC9f1lqH6s9G4,54
92
+ sonolus_py-0.6.0.dist-info/licenses/LICENSE,sha256=JEKpqVhQYfEc7zg3Mj462sKbKYmO1K7WmvX1qvg9IJk,1067
93
+ sonolus_py-0.6.0.dist-info/RECORD,,