sonolus.py 0.1.4__py3-none-any.whl → 0.1.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of sonolus.py might be problematic. Click here for more details.
- sonolus/backend/finalize.py +18 -10
- sonolus/backend/interpret.py +7 -7
- sonolus/backend/ir.py +24 -0
- sonolus/backend/optimize/__init__.py +0 -0
- sonolus/backend/{allocate.py → optimize/allocate.py} +4 -3
- sonolus/backend/{constant_evaluation.py → optimize/constant_evaluation.py} +7 -7
- sonolus/backend/{coalesce.py → optimize/copy_coalesce.py} +3 -3
- sonolus/backend/optimize/dead_code.py +185 -0
- sonolus/backend/{dominance.py → optimize/dominance.py} +2 -17
- sonolus/backend/{flow.py → optimize/flow.py} +6 -5
- sonolus/backend/{inlining.py → optimize/inlining.py} +4 -17
- sonolus/backend/{liveness.py → optimize/liveness.py} +69 -65
- sonolus/backend/optimize/optimize.py +44 -0
- sonolus/backend/{passes.py → optimize/passes.py} +1 -1
- sonolus/backend/optimize/simplify.py +191 -0
- sonolus/backend/{ssa.py → optimize/ssa.py} +31 -18
- sonolus/backend/place.py +17 -25
- sonolus/backend/utils.py +10 -0
- sonolus/backend/visitor.py +360 -101
- sonolus/build/compile.py +8 -8
- sonolus/build/engine.py +10 -5
- sonolus/script/archetype.py +419 -137
- sonolus/script/array.py +25 -8
- sonolus/script/array_like.py +297 -0
- sonolus/script/bucket.py +73 -11
- sonolus/script/containers.py +234 -51
- sonolus/script/debug.py +8 -8
- sonolus/script/easing.py +147 -105
- sonolus/script/effect.py +60 -0
- sonolus/script/engine.py +71 -4
- sonolus/script/globals.py +66 -32
- sonolus/script/instruction.py +79 -25
- sonolus/script/internal/builtin_impls.py +138 -27
- sonolus/script/internal/constant.py +139 -0
- sonolus/script/internal/context.py +14 -5
- sonolus/script/internal/dict_impl.py +65 -0
- sonolus/script/internal/generic.py +6 -9
- sonolus/script/internal/impl.py +38 -13
- sonolus/script/internal/introspection.py +5 -2
- sonolus/script/{math.py → internal/math_impls.py} +28 -28
- sonolus/script/internal/native.py +3 -3
- sonolus/script/internal/random.py +67 -0
- sonolus/script/internal/range.py +81 -0
- sonolus/script/internal/transient.py +51 -0
- sonolus/script/internal/tuple_impl.py +113 -0
- sonolus/script/interval.py +234 -16
- sonolus/script/iterator.py +120 -167
- sonolus/script/level.py +24 -0
- sonolus/script/num.py +79 -47
- sonolus/script/options.py +78 -12
- sonolus/script/particle.py +37 -4
- sonolus/script/pointer.py +4 -4
- sonolus/script/print.py +22 -1
- sonolus/script/project.py +8 -0
- sonolus/script/{graphics.py → quad.py} +75 -12
- sonolus/script/record.py +44 -13
- sonolus/script/runtime.py +50 -1
- sonolus/script/sprite.py +197 -112
- sonolus/script/text.py +2 -0
- sonolus/script/timing.py +72 -0
- sonolus/script/transform.py +296 -66
- sonolus/script/ui.py +134 -78
- sonolus/script/values.py +6 -13
- sonolus/script/vec.py +118 -3
- {sonolus_py-0.1.4.dist-info → sonolus_py-0.1.5.dist-info}/METADATA +1 -1
- sonolus_py-0.1.5.dist-info/RECORD +89 -0
- sonolus/backend/dead_code.py +0 -80
- sonolus/backend/optimize.py +0 -37
- sonolus/backend/simplify.py +0 -47
- sonolus/script/comptime.py +0 -160
- sonolus/script/random.py +0 -14
- sonolus/script/range.py +0 -58
- sonolus_py-0.1.4.dist-info/RECORD +0 -84
- /sonolus/script/{callbacks.py → internal/callbacks.py} +0 -0
- {sonolus_py-0.1.4.dist-info → sonolus_py-0.1.5.dist-info}/WHEEL +0 -0
- {sonolus_py-0.1.4.dist-info → sonolus_py-0.1.5.dist-info}/entry_points.txt +0 -0
- {sonolus_py-0.1.4.dist-info → sonolus_py-0.1.5.dist-info}/licenses/LICENSE +0 -0
sonolus/script/globals.py
CHANGED
|
@@ -8,7 +8,7 @@ from sonolus.script.internal.generic import validate_concrete_type
|
|
|
8
8
|
from sonolus.script.internal.value import Value
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
class
|
|
11
|
+
class _GlobalInfo:
|
|
12
12
|
def __init__(self, name: str, size: int, blocks: dict[Mode, Block], offset: int | None):
|
|
13
13
|
self.name = name
|
|
14
14
|
self.size = size
|
|
@@ -16,7 +16,7 @@ class GlobalInfo:
|
|
|
16
16
|
self.offset = offset
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
class
|
|
19
|
+
class _GlobalField(SonolusDescriptor):
|
|
20
20
|
def __init__(self, name: str, type_: type[Value], index: int, offset: int):
|
|
21
21
|
self.name = name
|
|
22
22
|
self.type = type_
|
|
@@ -49,7 +49,7 @@ class GlobalField(SonolusDescriptor):
|
|
|
49
49
|
target._copy_from_(value)
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
class
|
|
52
|
+
class _GlobalPlaceholder:
|
|
53
53
|
def __init__(self, type_: type[Value], blocks: dict[Mode, Block], offset: int | None):
|
|
54
54
|
self.type = type_
|
|
55
55
|
self.blocks = blocks
|
|
@@ -65,10 +65,10 @@ class GlobalPlaceholder:
|
|
|
65
65
|
return self.type._from_place_(base)
|
|
66
66
|
|
|
67
67
|
|
|
68
|
-
def
|
|
68
|
+
def _create_global(cls: type, blocks: dict[Mode, Block], offset: int | None):
|
|
69
69
|
if issubclass(cls, Value):
|
|
70
70
|
cls = validate_concrete_type(cls)
|
|
71
|
-
return
|
|
71
|
+
return _GlobalPlaceholder(cls, blocks, offset)
|
|
72
72
|
if len(cls.__bases__) != 1:
|
|
73
73
|
raise TypeError("Expected a class with no bases or a Value subclass")
|
|
74
74
|
field_offset = 0
|
|
@@ -77,61 +77,61 @@ def create_global(cls: type, blocks: dict[Mode, Block], offset: int | None):
|
|
|
77
77
|
annotation,
|
|
78
78
|
) in enumerate(inspect.get_annotations(cls, eval_str=True).items()):
|
|
79
79
|
type_ = validate_concrete_type(annotation)
|
|
80
|
-
setattr(cls, name,
|
|
80
|
+
setattr(cls, name, _GlobalField(name, type_, i, field_offset))
|
|
81
81
|
field_offset += type_._size_()
|
|
82
|
-
cls._global_info_ =
|
|
82
|
+
cls._global_info_ = _GlobalInfo(cls.__name__, field_offset, blocks, offset)
|
|
83
83
|
cls._is_comptime_value_ = True
|
|
84
84
|
return cls()
|
|
85
85
|
|
|
86
86
|
|
|
87
87
|
@dataclass_transform()
|
|
88
88
|
def _play_runtime_environment[T](cls: type[T]) -> T:
|
|
89
|
-
return
|
|
89
|
+
return _create_global(cls, {Mode.PLAY: PlayBlock.RuntimeEnvironment}, 0)
|
|
90
90
|
|
|
91
91
|
|
|
92
92
|
@dataclass_transform()
|
|
93
93
|
def _watch_runtime_environment[T](cls: type[T]) -> T:
|
|
94
|
-
return
|
|
94
|
+
return _create_global(cls, {Mode.WATCH: WatchBlock.RuntimeEnvironment}, 0)
|
|
95
95
|
|
|
96
96
|
|
|
97
97
|
@dataclass_transform()
|
|
98
98
|
def _tutorial_runtime_environment[T](cls: type[T]) -> T:
|
|
99
|
-
return
|
|
99
|
+
return _create_global(cls, {Mode.TUTORIAL: TutorialBlock.RuntimeEnvironment}, 0)
|
|
100
100
|
|
|
101
101
|
|
|
102
102
|
@dataclass_transform()
|
|
103
103
|
def _preview_runtime_environment[T](cls: type[T]) -> T:
|
|
104
|
-
return
|
|
104
|
+
return _create_global(cls, {Mode.PREVIEW: PreviewBlock.RuntimeEnvironment}, 0)
|
|
105
105
|
|
|
106
106
|
|
|
107
107
|
@dataclass_transform()
|
|
108
108
|
def _play_runtime_update[T](cls: type[T]) -> T:
|
|
109
|
-
return
|
|
109
|
+
return _create_global(cls, {Mode.PLAY: PlayBlock.RuntimeUpdate}, 0)
|
|
110
110
|
|
|
111
111
|
|
|
112
112
|
@dataclass_transform()
|
|
113
113
|
def _watch_runtime_update[T](cls: type[T]) -> T:
|
|
114
|
-
return
|
|
114
|
+
return _create_global(cls, {Mode.WATCH: WatchBlock.RuntimeUpdate}, 0)
|
|
115
115
|
|
|
116
116
|
|
|
117
117
|
@dataclass_transform()
|
|
118
118
|
def _preview_runtime_canvas[T](cls: type[T]) -> T:
|
|
119
|
-
return
|
|
119
|
+
return _create_global(cls, {Mode.PREVIEW: PreviewBlock.RuntimeCanvas}, 0)
|
|
120
120
|
|
|
121
121
|
|
|
122
122
|
@dataclass_transform()
|
|
123
123
|
def _tutorial_runtime_update[T](cls: type[T]) -> T:
|
|
124
|
-
return
|
|
124
|
+
return _create_global(cls, {Mode.TUTORIAL: TutorialBlock.RuntimeUpdate}, 0)
|
|
125
125
|
|
|
126
126
|
|
|
127
127
|
@dataclass_transform()
|
|
128
128
|
def _runtime_touch_array[T](cls: type[T]) -> T:
|
|
129
|
-
return
|
|
129
|
+
return _create_global(cls, {Mode.PLAY: PlayBlock.RuntimeTouchArray}, 0)
|
|
130
130
|
|
|
131
131
|
|
|
132
132
|
@dataclass_transform()
|
|
133
133
|
def _runtime_skin_transform[T](cls: type[T]) -> T:
|
|
134
|
-
return
|
|
134
|
+
return _create_global(
|
|
135
135
|
cls,
|
|
136
136
|
{
|
|
137
137
|
Mode.PLAY: PlayBlock.RuntimeSkinTransform,
|
|
@@ -145,7 +145,7 @@ def _runtime_skin_transform[T](cls: type[T]) -> T:
|
|
|
145
145
|
|
|
146
146
|
@dataclass_transform()
|
|
147
147
|
def _runtime_particle_transform[T](cls: type[T]) -> T:
|
|
148
|
-
return
|
|
148
|
+
return _create_global(
|
|
149
149
|
cls,
|
|
150
150
|
{
|
|
151
151
|
Mode.PLAY: PlayBlock.RuntimeParticleTransform,
|
|
@@ -158,7 +158,7 @@ def _runtime_particle_transform[T](cls: type[T]) -> T:
|
|
|
158
158
|
|
|
159
159
|
@dataclass_transform()
|
|
160
160
|
def _runtime_background[T](cls: type[T]) -> T:
|
|
161
|
-
return
|
|
161
|
+
return _create_global(
|
|
162
162
|
cls,
|
|
163
163
|
{
|
|
164
164
|
Mode.PLAY: PlayBlock.RuntimeBackground,
|
|
@@ -171,52 +171,69 @@ def _runtime_background[T](cls: type[T]) -> T:
|
|
|
171
171
|
|
|
172
172
|
@dataclass_transform()
|
|
173
173
|
def _play_runtime_ui[T](cls: type[T]) -> T:
|
|
174
|
-
return
|
|
174
|
+
return _create_global(cls, {Mode.PLAY: PlayBlock.RuntimeUI}, 0)
|
|
175
175
|
|
|
176
176
|
|
|
177
177
|
@dataclass_transform()
|
|
178
178
|
def _watch_runtime_ui[T](cls: type[T]) -> T:
|
|
179
|
-
return
|
|
179
|
+
return _create_global(cls, {Mode.WATCH: WatchBlock.RuntimeUI}, 0)
|
|
180
180
|
|
|
181
181
|
|
|
182
182
|
@dataclass_transform()
|
|
183
183
|
def _tutorial_runtime_ui[T](cls: type[T]) -> T:
|
|
184
|
-
return
|
|
184
|
+
return _create_global(cls, {Mode.TUTORIAL: TutorialBlock.RuntimeUI}, 0)
|
|
185
185
|
|
|
186
186
|
|
|
187
187
|
@dataclass_transform()
|
|
188
188
|
def _preview_runtime_ui[T](cls: type[T]) -> T:
|
|
189
|
-
return
|
|
189
|
+
return _create_global(cls, {Mode.PREVIEW: PreviewBlock.RuntimeUI}, 0)
|
|
190
190
|
|
|
191
191
|
|
|
192
192
|
@dataclass_transform()
|
|
193
193
|
def _play_runtime_ui_configuration[T](cls: type[T]) -> T:
|
|
194
|
-
return
|
|
194
|
+
return _create_global(cls, {Mode.PLAY: PlayBlock.RuntimeUIConfiguration}, 0)
|
|
195
195
|
|
|
196
196
|
|
|
197
197
|
@dataclass_transform()
|
|
198
198
|
def _watch_runtime_ui_configuration[T](cls: type[T]) -> T:
|
|
199
|
-
return
|
|
199
|
+
return _create_global(cls, {Mode.WATCH: WatchBlock.RuntimeUIConfiguration}, 0)
|
|
200
200
|
|
|
201
201
|
|
|
202
202
|
@dataclass_transform()
|
|
203
203
|
def _tutorial_runtime_ui_configuration[T](cls: type[T]) -> T:
|
|
204
|
-
return
|
|
204
|
+
return _create_global(cls, {Mode.TUTORIAL: TutorialBlock.RuntimeUIConfiguration}, 0)
|
|
205
205
|
|
|
206
206
|
|
|
207
207
|
@dataclass_transform()
|
|
208
208
|
def _preview_runtime_ui_configuration[T](cls: type[T]) -> T:
|
|
209
|
-
return
|
|
209
|
+
return _create_global(cls, {Mode.PREVIEW: PreviewBlock.RuntimeUIConfiguration}, 0)
|
|
210
210
|
|
|
211
211
|
|
|
212
212
|
@dataclass_transform()
|
|
213
213
|
def _tutorial_instruction[T](cls: type[T]) -> T:
|
|
214
|
-
return
|
|
214
|
+
return _create_global(cls, {Mode.TUTORIAL: TutorialBlock.TutorialInstruction}, 0)
|
|
215
215
|
|
|
216
216
|
|
|
217
217
|
@dataclass_transform()
|
|
218
218
|
def level_memory[T](cls: type[T]) -> T:
|
|
219
|
-
|
|
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(
|
|
220
237
|
cls,
|
|
221
238
|
{
|
|
222
239
|
Mode.PLAY: PlayBlock.LevelMemory,
|
|
@@ -229,7 +246,24 @@ def level_memory[T](cls: type[T]) -> T:
|
|
|
229
246
|
|
|
230
247
|
@dataclass_transform()
|
|
231
248
|
def level_data[T](cls: type[T]) -> T:
|
|
232
|
-
|
|
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(
|
|
233
267
|
cls,
|
|
234
268
|
{
|
|
235
269
|
Mode.PLAY: PlayBlock.LevelData,
|
|
@@ -247,12 +281,12 @@ def level_data[T](cls: type[T]) -> T:
|
|
|
247
281
|
|
|
248
282
|
@dataclass_transform()
|
|
249
283
|
def _level_score[T](cls: type[T]) -> T:
|
|
250
|
-
return
|
|
284
|
+
return _create_global(cls, {Mode.PLAY: PlayBlock.LevelScore, Mode.WATCH: WatchBlock.LevelScore}, 0)
|
|
251
285
|
|
|
252
286
|
|
|
253
287
|
@dataclass_transform()
|
|
254
288
|
def _level_life[T](cls: type[T]) -> T:
|
|
255
|
-
return
|
|
289
|
+
return _create_global(cls, {Mode.PLAY: PlayBlock.LevelLife, Mode.WATCH: WatchBlock.LevelLife}, 0)
|
|
256
290
|
|
|
257
291
|
|
|
258
292
|
# engine_rom is handled by the compiler
|
sonolus/script/instruction.py
CHANGED
|
@@ -10,36 +10,64 @@ from sonolus.script.text import StandardText
|
|
|
10
10
|
from sonolus.script.vec import Vec2
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class
|
|
13
|
+
class Instruction(Record):
|
|
14
|
+
"""Tutorial instruction text.
|
|
15
|
+
|
|
16
|
+
Usage:
|
|
17
|
+
```python
|
|
18
|
+
Instruction(id: int)
|
|
19
|
+
```
|
|
20
|
+
"""
|
|
21
|
+
|
|
14
22
|
id: int
|
|
15
23
|
|
|
16
24
|
def show(self):
|
|
25
|
+
"""Show this instruction text."""
|
|
17
26
|
show_instruction(self)
|
|
18
27
|
|
|
19
28
|
|
|
20
29
|
class InstructionIcon(Record):
|
|
30
|
+
"""Tutorial instruction icon.
|
|
31
|
+
|
|
32
|
+
Usage:
|
|
33
|
+
```python
|
|
34
|
+
InstructionIcon(id: int)
|
|
35
|
+
```
|
|
36
|
+
"""
|
|
37
|
+
|
|
21
38
|
id: int
|
|
22
39
|
|
|
23
40
|
def paint(self, position: Vec2, size: float, rotation: float, z: float, a: float):
|
|
41
|
+
"""Paint this instruction icon.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
position: The position of the icon.
|
|
45
|
+
size: The size of the icon.
|
|
46
|
+
rotation: The rotation of the icon.
|
|
47
|
+
z: The z-index of the icon.
|
|
48
|
+
a: The alpha of the icon.
|
|
49
|
+
"""
|
|
24
50
|
_paint(self.id, position.x, position.y, size, rotation, z, a)
|
|
25
51
|
|
|
26
52
|
|
|
27
53
|
@dataclass
|
|
28
|
-
class
|
|
54
|
+
class _InstructionTextInfo:
|
|
29
55
|
name: str
|
|
30
56
|
|
|
31
57
|
|
|
32
58
|
@dataclass
|
|
33
|
-
class
|
|
59
|
+
class _InstructionIconInfo:
|
|
34
60
|
name: str
|
|
35
61
|
|
|
36
62
|
|
|
37
63
|
def instruction(name: str) -> Any:
|
|
38
|
-
|
|
64
|
+
"""Define an instruction with the given name."""
|
|
65
|
+
return _InstructionTextInfo(name=name)
|
|
39
66
|
|
|
40
67
|
|
|
41
68
|
def instruction_icon(name: str) -> Any:
|
|
42
|
-
|
|
69
|
+
"""Define an instruction icon with the given name."""
|
|
70
|
+
return _InstructionIconInfo(name=name)
|
|
43
71
|
|
|
44
72
|
|
|
45
73
|
type TutorialInstructions = NewType("TutorialInstructions", Any)
|
|
@@ -48,6 +76,16 @@ type TutorialInstructionIcons = NewType("TutorialInstructionIcons", Any)
|
|
|
48
76
|
|
|
49
77
|
@dataclass_transform()
|
|
50
78
|
def instructions[T](cls: type[T]) -> T | TutorialInstructions:
|
|
79
|
+
"""Decorator to define tutorial instructions.
|
|
80
|
+
|
|
81
|
+
Usage:
|
|
82
|
+
```python
|
|
83
|
+
@instructions
|
|
84
|
+
class Instructions:
|
|
85
|
+
tap: StandardInstruction.TAP
|
|
86
|
+
other_instruction: InstructionText = instruction("Other Instruction")
|
|
87
|
+
```
|
|
88
|
+
"""
|
|
51
89
|
if len(cls.__bases__) != 1:
|
|
52
90
|
raise ValueError("Instructions class must not inherit from any class (except object)")
|
|
53
91
|
instance = cls()
|
|
@@ -57,15 +95,15 @@ def instructions[T](cls: type[T]) -> T | TutorialInstructions:
|
|
|
57
95
|
raise TypeError(f"Invalid annotation for instruction: {annotation}")
|
|
58
96
|
annotation_type = annotation.__args__[0]
|
|
59
97
|
annotation_values = annotation.__metadata__
|
|
60
|
-
if annotation_type is not
|
|
98
|
+
if annotation_type is not Instruction:
|
|
61
99
|
raise TypeError(
|
|
62
100
|
f"Invalid annotation for instruction: {annotation}, expected annotation of type InstructionText"
|
|
63
101
|
)
|
|
64
|
-
if len(annotation_values) != 1 or not isinstance(annotation_values[0],
|
|
102
|
+
if len(annotation_values) != 1 or not isinstance(annotation_values[0], _InstructionTextInfo):
|
|
65
103
|
raise TypeError(f"Invalid annotation for instruction: {annotation}, expected a single annotation value")
|
|
66
104
|
instruction_name = annotation_values[0].name
|
|
67
105
|
names.append(instruction_name)
|
|
68
|
-
setattr(instance, name,
|
|
106
|
+
setattr(instance, name, Instruction(i))
|
|
69
107
|
instance._instructions_ = names
|
|
70
108
|
instance._is_comptime_value_ = True
|
|
71
109
|
return instance
|
|
@@ -73,6 +111,16 @@ def instructions[T](cls: type[T]) -> T | TutorialInstructions:
|
|
|
73
111
|
|
|
74
112
|
@dataclass_transform()
|
|
75
113
|
def instruction_icons[T](cls: type[T]) -> T | TutorialInstructionIcons:
|
|
114
|
+
"""Decorator to define tutorial instruction icons.
|
|
115
|
+
|
|
116
|
+
Usage:
|
|
117
|
+
```python
|
|
118
|
+
@instruction_icons
|
|
119
|
+
class InstructionIcons:
|
|
120
|
+
hand: StandardInstructionIcon.HAND
|
|
121
|
+
other_icon: InstructionIcon = instruction_icon("Other Icon")
|
|
122
|
+
```
|
|
123
|
+
"""
|
|
76
124
|
if len(cls.__bases__) != 1:
|
|
77
125
|
raise ValueError("Instruction icons class must not inherit from any class (except object)")
|
|
78
126
|
instance = cls()
|
|
@@ -86,7 +134,7 @@ def instruction_icons[T](cls: type[T]) -> T | TutorialInstructionIcons:
|
|
|
86
134
|
raise TypeError(
|
|
87
135
|
f"Invalid annotation for instruction icon: {annotation}, expected annotation of type InstructionIcon"
|
|
88
136
|
)
|
|
89
|
-
if len(annotation_values) != 1 or not isinstance(annotation_values[0],
|
|
137
|
+
if len(annotation_values) != 1 or not isinstance(annotation_values[0], _InstructionIconInfo):
|
|
90
138
|
raise TypeError(
|
|
91
139
|
f"Invalid annotation for instruction icon: {annotation}, expected a single annotation value"
|
|
92
140
|
)
|
|
@@ -99,23 +147,27 @@ def instruction_icons[T](cls: type[T]) -> T | TutorialInstructionIcons:
|
|
|
99
147
|
|
|
100
148
|
|
|
101
149
|
class StandardInstruction:
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
150
|
+
"""Standard instructions."""
|
|
151
|
+
|
|
152
|
+
TAP = Annotated[Instruction, instruction(StandardText.TAP)]
|
|
153
|
+
TAP_HOLD = Annotated[Instruction, instruction(StandardText.TAP_HOLD)]
|
|
154
|
+
TAP_RELEASE = Annotated[Instruction, instruction(StandardText.TAP_RELEASE)]
|
|
155
|
+
TAP_FLICK = Annotated[Instruction, instruction(StandardText.TAP_FLICK)]
|
|
156
|
+
TAP_SLIDE = Annotated[Instruction, instruction(StandardText.TAP_SLIDE)]
|
|
157
|
+
HOLD = Annotated[Instruction, instruction(StandardText.HOLD)]
|
|
158
|
+
HOLD_SLIDE = Annotated[Instruction, instruction(StandardText.HOLD_SLIDE)]
|
|
159
|
+
HOLD_FOLLOW = Annotated[Instruction, instruction(StandardText.HOLD_FOLLOW)]
|
|
160
|
+
RELEASE = Annotated[Instruction, instruction(StandardText.RELEASE)]
|
|
161
|
+
FLICK = Annotated[Instruction, instruction(StandardText.FLICK)]
|
|
162
|
+
SLIDE = Annotated[Instruction, instruction(StandardText.SLIDE)]
|
|
163
|
+
SLIDE_FLICK = Annotated[Instruction, instruction(StandardText.SLIDE_FLICK)]
|
|
164
|
+
AVOID = Annotated[Instruction, instruction(StandardText.AVOID)]
|
|
165
|
+
JIGGLE = Annotated[Instruction, instruction(StandardText.JIGGLE)]
|
|
116
166
|
|
|
117
167
|
|
|
118
168
|
class StandardInstructionIcon:
|
|
169
|
+
"""Standard instruction icons."""
|
|
170
|
+
|
|
119
171
|
HAND = Annotated[InstructionIcon, instruction_icon("#HAND")]
|
|
120
172
|
ARROW = Annotated[InstructionIcon, instruction_icon("#ARROW")]
|
|
121
173
|
|
|
@@ -139,13 +191,15 @@ def _paint(
|
|
|
139
191
|
rotation: float,
|
|
140
192
|
z: float,
|
|
141
193
|
a: float,
|
|
142
|
-
):
|
|
194
|
+
) -> None:
|
|
143
195
|
raise NotImplementedError()
|
|
144
196
|
|
|
145
197
|
|
|
146
|
-
def show_instruction(inst:
|
|
198
|
+
def show_instruction(inst: Instruction, /):
|
|
199
|
+
"""Show the given instruction text."""
|
|
147
200
|
_TutorialInstruction.text_id = inst.id
|
|
148
201
|
|
|
149
202
|
|
|
150
203
|
def clear_instruction():
|
|
204
|
+
"""Clear the current instruction text."""
|
|
151
205
|
_TutorialInstruction.text_id = -1
|