sonolus.py 0.1.3__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.

Files changed (90) hide show
  1. sonolus/backend/blocks.py +756 -756
  2. sonolus/backend/excepthook.py +37 -37
  3. sonolus/backend/finalize.py +77 -69
  4. sonolus/backend/interpret.py +7 -7
  5. sonolus/backend/ir.py +29 -3
  6. sonolus/backend/mode.py +24 -24
  7. sonolus/backend/node.py +40 -40
  8. sonolus/backend/ops.py +197 -197
  9. sonolus/backend/optimize/__init__.py +0 -0
  10. sonolus/backend/optimize/allocate.py +126 -0
  11. sonolus/backend/optimize/constant_evaluation.py +374 -0
  12. sonolus/backend/optimize/copy_coalesce.py +85 -0
  13. sonolus/backend/optimize/dead_code.py +185 -0
  14. sonolus/backend/optimize/dominance.py +96 -0
  15. sonolus/backend/{flow.py → optimize/flow.py} +122 -92
  16. sonolus/backend/optimize/inlining.py +137 -0
  17. sonolus/backend/optimize/liveness.py +177 -0
  18. sonolus/backend/optimize/optimize.py +44 -0
  19. sonolus/backend/optimize/passes.py +52 -0
  20. sonolus/backend/optimize/simplify.py +191 -0
  21. sonolus/backend/optimize/ssa.py +200 -0
  22. sonolus/backend/place.py +17 -25
  23. sonolus/backend/utils.py +58 -48
  24. sonolus/backend/visitor.py +1151 -882
  25. sonolus/build/cli.py +7 -1
  26. sonolus/build/compile.py +88 -90
  27. sonolus/build/engine.py +10 -5
  28. sonolus/build/level.py +24 -23
  29. sonolus/build/node.py +43 -43
  30. sonolus/script/archetype.py +438 -139
  31. sonolus/script/array.py +27 -10
  32. sonolus/script/array_like.py +297 -0
  33. sonolus/script/bucket.py +253 -191
  34. sonolus/script/containers.py +257 -51
  35. sonolus/script/debug.py +26 -10
  36. sonolus/script/easing.py +365 -0
  37. sonolus/script/effect.py +191 -131
  38. sonolus/script/engine.py +71 -4
  39. sonolus/script/globals.py +303 -269
  40. sonolus/script/instruction.py +205 -151
  41. sonolus/script/internal/__init__.py +5 -5
  42. sonolus/script/internal/builtin_impls.py +255 -144
  43. sonolus/script/{callbacks.py → internal/callbacks.py} +127 -127
  44. sonolus/script/internal/constant.py +139 -0
  45. sonolus/script/internal/context.py +26 -9
  46. sonolus/script/internal/descriptor.py +17 -17
  47. sonolus/script/internal/dict_impl.py +65 -0
  48. sonolus/script/internal/generic.py +6 -9
  49. sonolus/script/internal/impl.py +38 -13
  50. sonolus/script/internal/introspection.py +17 -14
  51. sonolus/script/internal/math_impls.py +121 -0
  52. sonolus/script/internal/native.py +40 -38
  53. sonolus/script/internal/random.py +67 -0
  54. sonolus/script/internal/range.py +81 -0
  55. sonolus/script/internal/transient.py +51 -0
  56. sonolus/script/internal/tuple_impl.py +113 -0
  57. sonolus/script/internal/value.py +3 -3
  58. sonolus/script/interval.py +338 -112
  59. sonolus/script/iterator.py +167 -214
  60. sonolus/script/level.py +24 -0
  61. sonolus/script/num.py +80 -48
  62. sonolus/script/options.py +257 -191
  63. sonolus/script/particle.py +190 -157
  64. sonolus/script/pointer.py +30 -30
  65. sonolus/script/print.py +102 -81
  66. sonolus/script/project.py +8 -0
  67. sonolus/script/quad.py +263 -0
  68. sonolus/script/record.py +47 -16
  69. sonolus/script/runtime.py +52 -1
  70. sonolus/script/sprite.py +418 -333
  71. sonolus/script/text.py +409 -407
  72. sonolus/script/timing.py +114 -42
  73. sonolus/script/transform.py +332 -48
  74. sonolus/script/ui.py +216 -160
  75. sonolus/script/values.py +6 -13
  76. sonolus/script/vec.py +196 -78
  77. {sonolus_py-0.1.3.dist-info → sonolus_py-0.1.5.dist-info}/METADATA +1 -1
  78. sonolus_py-0.1.5.dist-info/RECORD +89 -0
  79. {sonolus_py-0.1.3.dist-info → sonolus_py-0.1.5.dist-info}/WHEEL +1 -1
  80. {sonolus_py-0.1.3.dist-info → sonolus_py-0.1.5.dist-info}/licenses/LICENSE +21 -21
  81. sonolus/backend/allocate.py +0 -51
  82. sonolus/backend/optimize.py +0 -9
  83. sonolus/backend/passes.py +0 -6
  84. sonolus/backend/simplify.py +0 -30
  85. sonolus/script/comptime.py +0 -160
  86. sonolus/script/graphics.py +0 -150
  87. sonolus/script/math.py +0 -92
  88. sonolus/script/range.py +0 -58
  89. sonolus_py-0.1.3.dist-info/RECORD +0 -75
  90. {sonolus_py-0.1.3.dist-info → sonolus_py-0.1.5.dist-info}/entry_points.txt +0 -0
sonolus/script/globals.py CHANGED
@@ -1,269 +1,303 @@
1
- import inspect
2
- from typing import dataclass_transform
3
-
4
- from sonolus.backend.blocks import Block, PlayBlock, PreviewBlock, TutorialBlock, WatchBlock
5
- from sonolus.backend.mode import Mode
6
- from sonolus.script.internal.descriptor import SonolusDescriptor
7
- from sonolus.script.internal.generic import validate_concrete_type
8
- from sonolus.script.internal.value import Value
9
-
10
-
11
- class GlobalInfo:
12
- def __init__(self, name: str, size: int, blocks: dict[Mode, Block], offset: int | None):
13
- self.name = name
14
- self.size = size
15
- self.blocks = blocks
16
- self.offset = offset
17
-
18
-
19
- class GlobalField(SonolusDescriptor):
20
- def __init__(self, name: str, type_: type[Value], index: int, offset: int):
21
- self.name = name
22
- self.type = type_
23
- self.index = index
24
- self.offset = offset
25
-
26
- def __get__(self, instance, owner):
27
- if instance is None:
28
- return self
29
-
30
- from sonolus.script.internal.context import ctx
31
-
32
- info = owner._global_info_
33
- if not ctx():
34
- raise RuntimeError("Global field access outside of compilation")
35
- base = ctx().get_global_base(info)
36
- return self.type._from_place_(base.add_offset(self.offset))._get_()
37
-
38
- def __set__(self, instance, value):
39
- from sonolus.script.internal.context import ctx
40
-
41
- info = instance._global_info_
42
- if not ctx():
43
- raise RuntimeError("Global field access outside of compilation")
44
- base = ctx().get_global_base(info)
45
- target = self.type._from_place_(base.add_offset(self.offset))
46
- if self.type._is_value_type_():
47
- target._set_(value)
48
- else:
49
- target._copy_from_(value)
50
-
51
-
52
- class GlobalPlaceholder:
53
- def __init__(self, type_: type[Value], blocks: dict[Mode, Block], offset: int | None):
54
- self.type = type_
55
- self.blocks = blocks
56
- self.offset = offset
57
- self.size = type_._size_()
58
-
59
- def get(self):
60
- from sonolus.script.internal.context import ctx
61
-
62
- if not ctx():
63
- raise RuntimeError("Global access outside of compilation")
64
- base = ctx().get_global_base(self)
65
- return self.type._from_place_(base)
66
-
67
-
68
- def create_global(cls: type, blocks: dict[Mode, Block], offset: int | None):
69
- if issubclass(cls, Value):
70
- cls = validate_concrete_type(cls)
71
- return GlobalPlaceholder(cls, blocks, offset)
72
- if len(cls.__bases__) != 1:
73
- raise TypeError("Expected a class with no bases or a Value subclass")
74
- field_offset = 0
75
- for i, (
76
- name,
77
- annotation,
78
- ) in enumerate(inspect.get_annotations(cls, eval_str=True).items()):
79
- type_ = validate_concrete_type(annotation)
80
- setattr(cls, name, GlobalField(name, type_, i, field_offset))
81
- field_offset += type_._size_()
82
- cls._global_info_ = GlobalInfo(cls.__name__, field_offset, blocks, offset)
83
- cls._is_comptime_value_ = True
84
- return cls()
85
-
86
-
87
- @dataclass_transform()
88
- def _play_runtime_environment[T](cls: type[T]) -> T:
89
- return create_global(cls, {Mode.PLAY: PlayBlock.RuntimeEnvironment}, 0)
90
-
91
-
92
- @dataclass_transform()
93
- def _watch_runtime_environment[T](cls: type[T]) -> T:
94
- return create_global(cls, {Mode.WATCH: WatchBlock.RuntimeEnvironment}, 0)
95
-
96
-
97
- @dataclass_transform()
98
- def _tutorial_runtime_environment[T](cls: type[T]) -> T:
99
- return create_global(cls, {Mode.TUTORIAL: TutorialBlock.RuntimeEnvironment}, 0)
100
-
101
-
102
- @dataclass_transform()
103
- def _preview_runtime_environment[T](cls: type[T]) -> T:
104
- return create_global(cls, {Mode.PREVIEW: PreviewBlock.RuntimeEnvironment}, 0)
105
-
106
-
107
- @dataclass_transform()
108
- def _play_runtime_update[T](cls: type[T]) -> T:
109
- return create_global(cls, {Mode.PLAY: PlayBlock.RuntimeUpdate}, 0)
110
-
111
-
112
- @dataclass_transform()
113
- def _watch_runtime_update[T](cls: type[T]) -> T:
114
- return create_global(cls, {Mode.WATCH: WatchBlock.RuntimeUpdate}, 0)
115
-
116
-
117
- @dataclass_transform()
118
- def _preview_runtime_canvas[T](cls: type[T]) -> T:
119
- return create_global(cls, {Mode.PREVIEW: PreviewBlock.RuntimeCanvas}, 0)
120
-
121
-
122
- @dataclass_transform()
123
- def _tutorial_runtime_update[T](cls: type[T]) -> T:
124
- return create_global(cls, {Mode.TUTORIAL: TutorialBlock.RuntimeUpdate}, 0)
125
-
126
-
127
- @dataclass_transform()
128
- def _runtime_touch_array[T](cls: type[T]) -> T:
129
- return create_global(cls, {Mode.PLAY: PlayBlock.RuntimeTouchArray}, 0)
130
-
131
-
132
- @dataclass_transform()
133
- def _runtime_skin_transform[T](cls: type[T]) -> T:
134
- return create_global(
135
- cls,
136
- {
137
- Mode.PLAY: PlayBlock.RuntimeSkinTransform,
138
- Mode.WATCH: WatchBlock.RuntimeSkinTransform,
139
- Mode.PREVIEW: PreviewBlock.RuntimeSkinTransform,
140
- Mode.TUTORIAL: TutorialBlock.RuntimeSkinTransform,
141
- },
142
- 0,
143
- )
144
-
145
-
146
- @dataclass_transform()
147
- def _runtime_particle_transform[T](cls: type[T]) -> T:
148
- return create_global(
149
- cls,
150
- {
151
- Mode.PLAY: PlayBlock.RuntimeParticleTransform,
152
- Mode.WATCH: WatchBlock.RuntimeParticleTransform,
153
- Mode.TUTORIAL: TutorialBlock.RuntimeParticleTransform,
154
- },
155
- 0,
156
- )
157
-
158
-
159
- @dataclass_transform()
160
- def _runtime_background[T](cls: type[T]) -> T:
161
- return create_global(
162
- cls,
163
- {
164
- Mode.PLAY: PlayBlock.RuntimeBackground,
165
- Mode.WATCH: WatchBlock.RuntimeBackground,
166
- Mode.TUTORIAL: TutorialBlock.RuntimeBackground,
167
- },
168
- 0,
169
- )
170
-
171
-
172
- @dataclass_transform()
173
- def _play_runtime_ui[T](cls: type[T]) -> T:
174
- return create_global(cls, {Mode.PLAY: PlayBlock.RuntimeUI}, 0)
175
-
176
-
177
- @dataclass_transform()
178
- def _watch_runtime_ui[T](cls: type[T]) -> T:
179
- return create_global(cls, {Mode.WATCH: WatchBlock.RuntimeUI}, 0)
180
-
181
-
182
- @dataclass_transform()
183
- def _tutorial_runtime_ui[T](cls: type[T]) -> T:
184
- return create_global(cls, {Mode.TUTORIAL: TutorialBlock.RuntimeUI}, 0)
185
-
186
-
187
- @dataclass_transform()
188
- def _preview_runtime_ui[T](cls: type[T]) -> T:
189
- return create_global(cls, {Mode.PREVIEW: PreviewBlock.RuntimeUI}, 0)
190
-
191
-
192
- @dataclass_transform()
193
- def _play_runtime_ui_configuration[T](cls: type[T]) -> T:
194
- return create_global(cls, {Mode.PLAY: PlayBlock.RuntimeUIConfiguration}, 0)
195
-
196
-
197
- @dataclass_transform()
198
- def _watch_runtime_ui_configuration[T](cls: type[T]) -> T:
199
- return create_global(cls, {Mode.WATCH: WatchBlock.RuntimeUIConfiguration}, 0)
200
-
201
-
202
- @dataclass_transform()
203
- def _tutorial_runtime_ui_configuration[T](cls: type[T]) -> T:
204
- return create_global(cls, {Mode.TUTORIAL: TutorialBlock.RuntimeUIConfiguration}, 0)
205
-
206
-
207
- @dataclass_transform()
208
- def _preview_runtime_ui_configuration[T](cls: type[T]) -> T:
209
- return create_global(cls, {Mode.PREVIEW: PreviewBlock.RuntimeUIConfiguration}, 0)
210
-
211
-
212
- @dataclass_transform()
213
- def _tutorial_instruction[T](cls: type[T]) -> T:
214
- return create_global(cls, {Mode.TUTORIAL: TutorialBlock.TutorialInstruction}, 0)
215
-
216
-
217
- @dataclass_transform()
218
- def level_memory[T](cls: type[T]) -> T:
219
- return create_global(
220
- cls,
221
- {
222
- Mode.PLAY: PlayBlock.LevelMemory,
223
- Mode.WATCH: WatchBlock.LevelMemory,
224
- Mode.TUTORIAL: TutorialBlock.TutorialMemory,
225
- },
226
- None,
227
- )
228
-
229
-
230
- @dataclass_transform()
231
- def level_data[T](cls: type[T]) -> T:
232
- return create_global(
233
- cls,
234
- {
235
- Mode.PLAY: PlayBlock.LevelData,
236
- Mode.WATCH: WatchBlock.LevelData,
237
- Mode.PREVIEW: PreviewBlock.PreviewData,
238
- Mode.TUTORIAL: TutorialBlock.TutorialData,
239
- },
240
- None,
241
- )
242
-
243
-
244
- # level_option is handled by the options decorator
245
- # level_bucket is handled by the bucket decorator
246
-
247
-
248
- @dataclass_transform()
249
- def _level_score[T](cls: type[T]) -> T:
250
- return create_global(cls, {Mode.PLAY: PlayBlock.LevelScore, Mode.WATCH: WatchBlock.LevelScore}, 0)
251
-
252
-
253
- @dataclass_transform()
254
- def _level_life[T](cls: type[T]) -> T:
255
- return create_global(cls, {Mode.PLAY: PlayBlock.LevelLife, Mode.WATCH: WatchBlock.LevelLife}, 0)
256
-
257
-
258
- # engine_rom is handled by the compiler
259
- # entity memory is handled by the archetype
260
- # entity data is handled by the archetype
261
- # entity shared memory is handled by the archetype
262
- # entity info is handled by the archetype
263
- # entity despawn is handled by the archetype
264
- # entity input is handled by the archetype
265
- # entity data array is handled by the archetype
266
- # entity shared memory array is handled by the archetype
267
- # entity info array is handled by the archetype
268
- # archetype life is handled by the archetype
269
- # temporary memory is handled by the compiler
1
+ import inspect
2
+ from typing import dataclass_transform
3
+
4
+ from sonolus.backend.blocks import Block, PlayBlock, PreviewBlock, TutorialBlock, WatchBlock
5
+ from sonolus.backend.mode import Mode
6
+ from sonolus.script.internal.descriptor import SonolusDescriptor
7
+ from sonolus.script.internal.generic import validate_concrete_type
8
+ from sonolus.script.internal.value import Value
9
+
10
+
11
+ class _GlobalInfo:
12
+ def __init__(self, name: str, size: int, blocks: dict[Mode, Block], offset: int | None):
13
+ self.name = name
14
+ self.size = size
15
+ self.blocks = blocks
16
+ self.offset = offset
17
+
18
+
19
+ class _GlobalField(SonolusDescriptor):
20
+ def __init__(self, name: str, type_: type[Value], index: int, offset: int):
21
+ self.name = name
22
+ self.type = type_
23
+ self.index = index
24
+ self.offset = offset
25
+
26
+ def __get__(self, instance, owner):
27
+ if instance is None:
28
+ return self
29
+
30
+ from sonolus.script.internal.context import ctx
31
+
32
+ info = owner._global_info_
33
+ if not ctx():
34
+ raise RuntimeError("Global field access outside of compilation")
35
+ base = ctx().get_global_base(info)
36
+ return self.type._from_place_(base.add_offset(self.offset))._get_()
37
+
38
+ def __set__(self, instance, value):
39
+ from sonolus.script.internal.context import ctx
40
+
41
+ info = instance._global_info_
42
+ if not ctx():
43
+ raise RuntimeError("Global field access outside of compilation")
44
+ base = ctx().get_global_base(info)
45
+ target = self.type._from_place_(base.add_offset(self.offset))
46
+ if self.type._is_value_type_():
47
+ target._set_(value)
48
+ else:
49
+ target._copy_from_(value)
50
+
51
+
52
+ class _GlobalPlaceholder:
53
+ def __init__(self, type_: type[Value], blocks: dict[Mode, Block], offset: int | None):
54
+ self.type = type_
55
+ self.blocks = blocks
56
+ self.offset = offset
57
+ self.size = type_._size_()
58
+
59
+ def get(self):
60
+ from sonolus.script.internal.context import ctx
61
+
62
+ if not ctx():
63
+ raise RuntimeError("Global access outside of compilation")
64
+ base = ctx().get_global_base(self)
65
+ return self.type._from_place_(base)
66
+
67
+
68
+ def _create_global(cls: type, blocks: dict[Mode, Block], offset: int | None):
69
+ if issubclass(cls, Value):
70
+ cls = validate_concrete_type(cls)
71
+ return _GlobalPlaceholder(cls, blocks, offset)
72
+ if len(cls.__bases__) != 1:
73
+ raise TypeError("Expected a class with no bases or a Value subclass")
74
+ field_offset = 0
75
+ for i, (
76
+ name,
77
+ annotation,
78
+ ) in enumerate(inspect.get_annotations(cls, eval_str=True).items()):
79
+ type_ = validate_concrete_type(annotation)
80
+ setattr(cls, name, _GlobalField(name, type_, i, field_offset))
81
+ field_offset += type_._size_()
82
+ cls._global_info_ = _GlobalInfo(cls.__name__, field_offset, blocks, offset)
83
+ cls._is_comptime_value_ = True
84
+ return cls()
85
+
86
+
87
+ @dataclass_transform()
88
+ def _play_runtime_environment[T](cls: type[T]) -> T:
89
+ return _create_global(cls, {Mode.PLAY: PlayBlock.RuntimeEnvironment}, 0)
90
+
91
+
92
+ @dataclass_transform()
93
+ def _watch_runtime_environment[T](cls: type[T]) -> T:
94
+ return _create_global(cls, {Mode.WATCH: WatchBlock.RuntimeEnvironment}, 0)
95
+
96
+
97
+ @dataclass_transform()
98
+ def _tutorial_runtime_environment[T](cls: type[T]) -> T:
99
+ return _create_global(cls, {Mode.TUTORIAL: TutorialBlock.RuntimeEnvironment}, 0)
100
+
101
+
102
+ @dataclass_transform()
103
+ def _preview_runtime_environment[T](cls: type[T]) -> T:
104
+ return _create_global(cls, {Mode.PREVIEW: PreviewBlock.RuntimeEnvironment}, 0)
105
+
106
+
107
+ @dataclass_transform()
108
+ def _play_runtime_update[T](cls: type[T]) -> T:
109
+ return _create_global(cls, {Mode.PLAY: PlayBlock.RuntimeUpdate}, 0)
110
+
111
+
112
+ @dataclass_transform()
113
+ def _watch_runtime_update[T](cls: type[T]) -> T:
114
+ return _create_global(cls, {Mode.WATCH: WatchBlock.RuntimeUpdate}, 0)
115
+
116
+
117
+ @dataclass_transform()
118
+ def _preview_runtime_canvas[T](cls: type[T]) -> T:
119
+ return _create_global(cls, {Mode.PREVIEW: PreviewBlock.RuntimeCanvas}, 0)
120
+
121
+
122
+ @dataclass_transform()
123
+ def _tutorial_runtime_update[T](cls: type[T]) -> T:
124
+ return _create_global(cls, {Mode.TUTORIAL: TutorialBlock.RuntimeUpdate}, 0)
125
+
126
+
127
+ @dataclass_transform()
128
+ def _runtime_touch_array[T](cls: type[T]) -> T:
129
+ return _create_global(cls, {Mode.PLAY: PlayBlock.RuntimeTouchArray}, 0)
130
+
131
+
132
+ @dataclass_transform()
133
+ def _runtime_skin_transform[T](cls: type[T]) -> T:
134
+ return _create_global(
135
+ cls,
136
+ {
137
+ Mode.PLAY: PlayBlock.RuntimeSkinTransform,
138
+ Mode.WATCH: WatchBlock.RuntimeSkinTransform,
139
+ Mode.PREVIEW: PreviewBlock.RuntimeSkinTransform,
140
+ Mode.TUTORIAL: TutorialBlock.RuntimeSkinTransform,
141
+ },
142
+ 0,
143
+ )
144
+
145
+
146
+ @dataclass_transform()
147
+ def _runtime_particle_transform[T](cls: type[T]) -> T:
148
+ return _create_global(
149
+ cls,
150
+ {
151
+ Mode.PLAY: PlayBlock.RuntimeParticleTransform,
152
+ Mode.WATCH: WatchBlock.RuntimeParticleTransform,
153
+ Mode.TUTORIAL: TutorialBlock.RuntimeParticleTransform,
154
+ },
155
+ 0,
156
+ )
157
+
158
+
159
+ @dataclass_transform()
160
+ def _runtime_background[T](cls: type[T]) -> T:
161
+ return _create_global(
162
+ cls,
163
+ {
164
+ Mode.PLAY: PlayBlock.RuntimeBackground,
165
+ Mode.WATCH: WatchBlock.RuntimeBackground,
166
+ Mode.TUTORIAL: TutorialBlock.RuntimeBackground,
167
+ },
168
+ 0,
169
+ )
170
+
171
+
172
+ @dataclass_transform()
173
+ def _play_runtime_ui[T](cls: type[T]) -> T:
174
+ return _create_global(cls, {Mode.PLAY: PlayBlock.RuntimeUI}, 0)
175
+
176
+
177
+ @dataclass_transform()
178
+ def _watch_runtime_ui[T](cls: type[T]) -> T:
179
+ return _create_global(cls, {Mode.WATCH: WatchBlock.RuntimeUI}, 0)
180
+
181
+
182
+ @dataclass_transform()
183
+ def _tutorial_runtime_ui[T](cls: type[T]) -> T:
184
+ return _create_global(cls, {Mode.TUTORIAL: TutorialBlock.RuntimeUI}, 0)
185
+
186
+
187
+ @dataclass_transform()
188
+ def _preview_runtime_ui[T](cls: type[T]) -> T:
189
+ return _create_global(cls, {Mode.PREVIEW: PreviewBlock.RuntimeUI}, 0)
190
+
191
+
192
+ @dataclass_transform()
193
+ def _play_runtime_ui_configuration[T](cls: type[T]) -> T:
194
+ return _create_global(cls, {Mode.PLAY: PlayBlock.RuntimeUIConfiguration}, 0)
195
+
196
+
197
+ @dataclass_transform()
198
+ def _watch_runtime_ui_configuration[T](cls: type[T]) -> T:
199
+ return _create_global(cls, {Mode.WATCH: WatchBlock.RuntimeUIConfiguration}, 0)
200
+
201
+
202
+ @dataclass_transform()
203
+ def _tutorial_runtime_ui_configuration[T](cls: type[T]) -> T:
204
+ return _create_global(cls, {Mode.TUTORIAL: TutorialBlock.RuntimeUIConfiguration}, 0)
205
+
206
+
207
+ @dataclass_transform()
208
+ def _preview_runtime_ui_configuration[T](cls: type[T]) -> T:
209
+ return _create_global(cls, {Mode.PREVIEW: PreviewBlock.RuntimeUIConfiguration}, 0)
210
+
211
+
212
+ @dataclass_transform()
213
+ def _tutorial_instruction[T](cls: type[T]) -> T:
214
+ return _create_global(cls, {Mode.TUTORIAL: TutorialBlock.TutorialInstruction}, 0)
215
+
216
+
217
+ @dataclass_transform()
218
+ def level_memory[T](cls: type[T]) -> T:
219
+ """Define level memory.
220
+
221
+ Level memory may be modified during gameplay in sequential callbacks (`preprocess`, `update_sequential`, `touch`).
222
+
223
+ Usage:
224
+ ```python
225
+ @level_memory
226
+ class LevelMemory:
227
+ variable: int
228
+
229
+ variable = level_data(Array[int, 10])
230
+
231
+ def f():
232
+ LevelMemory.variable = 1
233
+ variable[0] = 2
234
+ ```
235
+ """
236
+ return _create_global(
237
+ cls,
238
+ {
239
+ Mode.PLAY: PlayBlock.LevelMemory,
240
+ Mode.WATCH: WatchBlock.LevelMemory,
241
+ Mode.TUTORIAL: TutorialBlock.TutorialMemory,
242
+ },
243
+ None,
244
+ )
245
+
246
+
247
+ @dataclass_transform()
248
+ def level_data[T](cls: type[T]) -> T:
249
+ """Define level data.
250
+
251
+ Level data may only be modified during preprocessing.
252
+
253
+ Usage:
254
+ ```python
255
+ @level_data
256
+ class LevelData:
257
+ variable: int
258
+
259
+ variable = level_data(Array[int, 10])
260
+
261
+ def f():
262
+ LevelData.variable = 1
263
+ variable[0] = 2
264
+ ```
265
+ """
266
+ return _create_global(
267
+ cls,
268
+ {
269
+ Mode.PLAY: PlayBlock.LevelData,
270
+ Mode.WATCH: WatchBlock.LevelData,
271
+ Mode.PREVIEW: PreviewBlock.PreviewData,
272
+ Mode.TUTORIAL: TutorialBlock.TutorialData,
273
+ },
274
+ None,
275
+ )
276
+
277
+
278
+ # level_option is handled by the options decorator
279
+ # level_bucket is handled by the bucket decorator
280
+
281
+
282
+ @dataclass_transform()
283
+ def _level_score[T](cls: type[T]) -> T:
284
+ return _create_global(cls, {Mode.PLAY: PlayBlock.LevelScore, Mode.WATCH: WatchBlock.LevelScore}, 0)
285
+
286
+
287
+ @dataclass_transform()
288
+ def _level_life[T](cls: type[T]) -> T:
289
+ return _create_global(cls, {Mode.PLAY: PlayBlock.LevelLife, Mode.WATCH: WatchBlock.LevelLife}, 0)
290
+
291
+
292
+ # engine_rom is handled by the compiler
293
+ # entity memory is handled by the archetype
294
+ # entity data is handled by the archetype
295
+ # entity shared memory is handled by the archetype
296
+ # entity info is handled by the archetype
297
+ # entity despawn is handled by the archetype
298
+ # entity input is handled by the archetype
299
+ # entity data array is handled by the archetype
300
+ # entity shared memory array is handled by the archetype
301
+ # entity info array is handled by the archetype
302
+ # archetype life is handled by the archetype
303
+ # temporary memory is handled by the compiler