sonolus.py 0.2.0__tar.gz → 0.3.0__tar.gz

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 (177) hide show
  1. sonolus_py-0.3.0/.python-version +1 -0
  2. sonolus_py-0.3.0/.run/Python tests in tests.run.xml +21 -0
  3. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/PKG-INFO +2 -2
  4. sonolus_py-0.3.0/README.md +2 -0
  5. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/doc_stubs/builtins.pyi +3 -0
  6. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/concepts/builtins.md +2 -1
  7. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/concepts/constructs.md +22 -17
  8. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/concepts/project.md +34 -2
  9. sonolus_py-0.3.0/docs/concepts/resources.md +304 -0
  10. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/concepts/types.md +47 -29
  11. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/index.md +1 -1
  12. sonolus_py-0.3.0/docs/reference/sonolus.script.stream.md +3 -0
  13. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/mkdocs.yml +2 -0
  14. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/pyproject.toml +12 -11
  15. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/ops.py +6 -0
  16. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/archetype.py +45 -7
  17. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/array.py +58 -29
  18. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/array_like.py +7 -2
  19. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/bucket.py +5 -3
  20. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/containers.py +166 -0
  21. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/debug.py +20 -2
  22. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/engine.py +2 -2
  23. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/internal/constant.py +6 -4
  24. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/internal/generic.py +7 -0
  25. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/internal/impl.py +10 -9
  26. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/internal/transient.py +3 -3
  27. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/internal/value.py +40 -11
  28. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/interval.py +3 -14
  29. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/num.py +29 -16
  30. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/options.py +18 -3
  31. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/particle.py +1 -0
  32. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/pointer.py +9 -1
  33. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/quad.py +58 -4
  34. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/record.py +15 -4
  35. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/runtime.py +17 -6
  36. sonolus_py-0.3.0/sonolus/script/stream.py +529 -0
  37. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/text.py +9 -0
  38. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/transform.py +3 -3
  39. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/ui.py +13 -4
  40. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/values.py +12 -1
  41. sonolus_py-0.3.0/tests/script/test_array_set.py +150 -0
  42. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/script/test_quad.py +21 -0
  43. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/uv.lock +1 -1
  44. sonolus_py-0.2.0/.python-version +0 -1
  45. sonolus_py-0.2.0/README.md +0 -2
  46. sonolus_py-0.2.0/docs/concepts/resources.md +0 -243
  47. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/.github/workflows/publish.yaml +0 -0
  48. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/.gitignore +0 -0
  49. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/LICENSE +0 -0
  50. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/doc_stubs/__init__.py +0 -0
  51. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/doc_stubs/math.pyi +0 -0
  52. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/doc_stubs/num.pyi +0 -0
  53. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/doc_stubs/random.pyi +0 -0
  54. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/CNAME +0 -0
  55. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/concepts/cli.md +0 -0
  56. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/concepts/index.md +0 -0
  57. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/builtins.md +0 -0
  58. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/index.md +0 -0
  59. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/math.md +0 -0
  60. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/random.md +0 -0
  61. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.archetype.md +0 -0
  62. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.array.md +0 -0
  63. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.array_like.md +0 -0
  64. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.bucket.md +0 -0
  65. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.containers.md +0 -0
  66. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.debug.md +0 -0
  67. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.easing.md +0 -0
  68. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.effect.md +0 -0
  69. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.engine.md +0 -0
  70. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.globals.md +0 -0
  71. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.instruction.md +0 -0
  72. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.interval.md +0 -0
  73. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.iterator.md +0 -0
  74. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.level.md +0 -0
  75. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.metadata.md +0 -0
  76. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.num.md +0 -0
  77. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.options.md +0 -0
  78. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.particle.md +0 -0
  79. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.printing.md +0 -0
  80. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.project.md +0 -0
  81. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.quad.md +0 -0
  82. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.record.md +0 -0
  83. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.runtime.md +0 -0
  84. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.sprite.md +0 -0
  85. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.text.md +0 -0
  86. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.timing.md +0 -0
  87. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.transform.md +0 -0
  88. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.ui.md +0 -0
  89. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.values.md +0 -0
  90. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/docs/reference/sonolus.script.vec.md +0 -0
  91. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/scripts/generate.py +0 -0
  92. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/scripts/runtimes/Engine/Tutorial/Blocks.json +0 -0
  93. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/scripts/runtimes/Functions.json +0 -0
  94. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/scripts/runtimes/Level/Play/Blocks.json +0 -0
  95. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/scripts/runtimes/Level/Preview/Blocks.json +0 -0
  96. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/scripts/runtimes/Level/Watch/Blocks.json +0 -0
  97. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/__init__.py +0 -0
  98. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/__init__.py +0 -0
  99. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/blocks.py +0 -0
  100. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/excepthook.py +0 -0
  101. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/finalize.py +0 -0
  102. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/interpret.py +0 -0
  103. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/ir.py +0 -0
  104. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/mode.py +0 -0
  105. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/node.py +0 -0
  106. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/optimize/__init__.py +0 -0
  107. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/optimize/allocate.py +0 -0
  108. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/optimize/constant_evaluation.py +0 -0
  109. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/optimize/copy_coalesce.py +0 -0
  110. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/optimize/dead_code.py +0 -0
  111. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/optimize/dominance.py +0 -0
  112. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/optimize/flow.py +0 -0
  113. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/optimize/inlining.py +0 -0
  114. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/optimize/liveness.py +0 -0
  115. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/optimize/optimize.py +0 -0
  116. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/optimize/passes.py +0 -0
  117. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/optimize/simplify.py +0 -0
  118. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/optimize/ssa.py +0 -0
  119. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/place.py +0 -0
  120. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/utils.py +0 -0
  121. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/backend/visitor.py +0 -0
  122. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/build/__init__.py +0 -0
  123. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/build/cli.py +0 -0
  124. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/build/collection.py +0 -0
  125. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/build/compile.py +0 -0
  126. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/build/engine.py +0 -0
  127. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/build/level.py +0 -0
  128. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/build/node.py +0 -0
  129. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/build/project.py +0 -0
  130. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/py.typed +0 -0
  131. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/__init__.py +0 -0
  132. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/easing.py +0 -0
  133. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/effect.py +0 -0
  134. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/globals.py +0 -0
  135. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/instruction.py +0 -0
  136. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/internal/__init__.py +0 -0
  137. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/internal/builtin_impls.py +0 -0
  138. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/internal/callbacks.py +0 -0
  139. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/internal/context.py +0 -0
  140. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/internal/descriptor.py +0 -0
  141. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/internal/dict_impl.py +0 -0
  142. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/internal/error.py +0 -0
  143. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/internal/introspection.py +0 -0
  144. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/internal/math_impls.py +0 -0
  145. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/internal/native.py +0 -0
  146. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/internal/random.py +0 -0
  147. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/internal/range.py +0 -0
  148. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/internal/tuple_impl.py +0 -0
  149. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/iterator.py +0 -0
  150. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/level.py +0 -0
  151. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/metadata.py +0 -0
  152. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/printing.py +0 -0
  153. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/project.py +0 -0
  154. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/sprite.py +0 -0
  155. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/timing.py +0 -0
  156. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/sonolus/script/vec.py +0 -0
  157. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/__init__.py +0 -0
  158. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/script/__init__.py +0 -0
  159. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/script/conftest.py +0 -0
  160. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/script/test_array.py +0 -0
  161. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/script/test_array_map.py +0 -0
  162. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/script/test_assert.py +0 -0
  163. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/script/test_dict.py +0 -0
  164. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/script/test_flow.py +0 -0
  165. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/script/test_functions.py +0 -0
  166. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/script/test_helpers.py +0 -0
  167. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/script/test_interval.py +0 -0
  168. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/script/test_match.py +0 -0
  169. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/script/test_num.py +0 -0
  170. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/script/test_operator.py +0 -0
  171. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/script/test_random.py +0 -0
  172. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/script/test_range.py +0 -0
  173. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/script/test_record.py +0 -0
  174. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/script/test_transform.py +0 -0
  175. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/script/test_tuple.py +0 -0
  176. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/script/test_var_array.py +0 -0
  177. {sonolus_py-0.2.0 → sonolus_py-0.3.0}/tests/script/test_vec.py +0 -0
@@ -0,0 +1 @@
1
+ 3.13t
@@ -0,0 +1,21 @@
1
+ <component name="ProjectRunConfigurationManager">
2
+ <configuration default="false" name="Python tests in tests" type="tests" factoryName="Autodetect" nameIsGenerated="true">
3
+ <module name="sonolus" />
4
+ <option name="ENV_FILES" value="" />
5
+ <option name="INTERPRETER_OPTIONS" value="" />
6
+ <option name="PARENT_ENVS" value="true" />
7
+ <envs>
8
+ <env name="PYTHON_JIT" value="1" />
9
+ </envs>
10
+ <option name="SDK_HOME" value="" />
11
+ <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
12
+ <option name="IS_MODULE_SDK" value="true" />
13
+ <option name="ADD_CONTENT_ROOTS" value="true" />
14
+ <option name="ADD_SOURCE_ROOTS" value="true" />
15
+ <EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
16
+ <option name="_new_additionalArguments" value="&quot;-n 32 --cov sonolus --cov tests --cov-report xml&quot;" />
17
+ <option name="_new_target" value="&quot;$PROJECT_DIR$/tests&quot;" />
18
+ <option name="_new_targetType" value="&quot;PATH&quot;" />
19
+ <method v="2" />
20
+ </configuration>
21
+ </component>
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sonolus.py
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Sonolus engine development in Python
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
7
7
  Description-Content-Type: text/markdown
8
8
 
9
9
  # Sonolus.py
10
- Sonolus engine development in Python.
10
+ Sonolus engine development in Python. See [docs](https://sonolus.py.qwewqa.xyz) for more information.
@@ -0,0 +1,2 @@
1
+ # Sonolus.py
2
+ Sonolus engine development in Python. See [docs](https://sonolus.py.qwewqa.xyz) for more information.
@@ -148,6 +148,9 @@ def len(s: object) -> builtins.int:
148
148
  def map[T, S](function: Callable[[T], S], iterable: Iterable[T]) -> Iterator[S]:
149
149
  """Apply a function to every item of an iterable and return an iterator.
150
150
 
151
+ Unlike the standard Python map function, it is possible that the function may be called more than once on the
152
+ same item.
153
+
151
154
  Args:
152
155
  function: The function to apply.
153
156
  iterable: The iterable to process.
@@ -11,7 +11,8 @@ Sonolus.py comes with support for a number of built-in functions.
11
11
  - `isinstance(object, classinfo)`
12
12
  - `issubclass(class, classinfo)`
13
13
  - `len(s)`
14
- - `map(function, iterable)`
14
+ - `map(function, iterable)` (note: may differ from standard Python behavior, see
15
+ [`map`](../reference/builtins.md#doc_stubs.builtins.map))
15
16
  - `max(iterable, *, key=None)`, `max(arg1, arg2, *args, key=None)`
16
17
  - `min(iterable, *, key=None)`, `min(arg1, arg2, *args, key=None)`
17
18
  - `range(stop)`, `range(start, stop[, step])`
@@ -18,6 +18,8 @@ Most standard Python constructs are supported in Sonolus.py.
18
18
 
19
19
  ## Overview
20
20
 
21
+ The following constructs are supported in Sonolus.py:
22
+
21
23
  - Expressions:
22
24
  - Literals:
23
25
  - Numbers (excluding complex numbers): `0`, `1`, `1.0`, `1e3`, `0x1`, `0b1`, `0o1`
@@ -28,8 +30,8 @@ Most standard Python constructs are supported in Sonolus.py.
28
30
  - Unary: `+`, `-`, `not`, `~`
29
31
  - Binary: `+`, `-`, `*`, `/`, `//`, `%`, `**`, `&`, `|`, `^`, `<<`, `>>`
30
32
  - Comparison: `==`, `!=`, `>`, `<`, `>=`, `<=`, `is`, `is not`, `in`, `not in`
31
- - Logical: `and`, `or` (for `Num` arguments only)
32
- - Ternary: `a if <condition> else b` (for `Num` conditions only)
33
+ - Logical: `and`, `or` (for [`Num`](types.md#num) arguments only)
34
+ - Ternary: `a if <condition> else b` (for [`Num`](types.md#num) conditions only)
33
35
  - Attribute: `a.b`
34
36
  - Indexing: `a[b]`
35
37
  - Call: `f(a, b, c)`
@@ -80,18 +82,20 @@ Some expressions can be evaluated at compile time:
80
82
  - Comparison: for compile time constant operands: `a == b`, `a != b`, `a > b`, `a < b`, `a >= b`, `a <= b`, ...
81
83
  - Variables assigned to compile time constants: `a = 1`, `b = a + 1`, ...
82
84
 
83
- The compiler can make additional inferences when compile time constants are used in certain contexts like control flow:
85
+ Some values like array sizes must be compile-time constants.
86
+
87
+ The compiler will eliminate branches known to be unreachable at compile time:
84
88
 
85
89
  ```python
86
- x = ...
90
+ def f(a):
91
+ if isinstance(a, Num):
92
+ debug_log(a)
93
+ else:
94
+ debug_log(a.x + a.y)
87
95
 
88
- # This code works because the compiler knows which branch will be taken based on the type of 'x'
89
- if isinstance(x, Num):
90
- debug_log(x)
91
- elif isinstance(x, Vec2):
92
- debug_log(x.x + x.y)
93
- else:
94
- debug_log(-1)
96
+ # This works because `isinstance` is evaluated at compile time and only the first (if) branch is reachable.
97
+ # The second (else) branch is eliminated, so we don't get an error that a does not have 'x' and 'y' attributes.
98
+ f(123)
95
99
  ```
96
100
 
97
101
  ## Variables
@@ -181,7 +185,7 @@ h = g[0] + g[1] + g[2]
181
185
  (i := 1)
182
186
  ```
183
187
 
184
- The ternary operator is supported for, but the condition must be a `Num`. If the operands are not nums,
188
+ The ternary operator is supported for, but the condition must be a [`Num`](types.md#num). If the operands are not nums,
185
189
  the condition must be a compile-time constant or this will be considered an error:
186
190
 
187
191
  ```python
@@ -385,7 +389,8 @@ def g(a):
385
389
  ```
386
390
 
387
391
  Function returns follow the same rules as variable access. If a function returns a non-num value, it most only
388
- return that value. There is no restriction of a function only returns a num.
392
+ return that value. If the function always returns a num, it may have any number of returns. Similarly, if a function
393
+ always returns None (`return None` or just `return`), it may have any number of returns.
389
394
 
390
395
  The following are allowed:
391
396
 
@@ -439,11 +444,11 @@ def k():
439
444
  return Vec2(1, 2)
440
445
  ```
441
446
 
442
- Most functions returning a non-num value should have a single `return` statement at the end.
447
+ Outside of functions returning `None` or a num, most functions should have a single `return` statement at the end.
443
448
 
444
449
  ### Classes
445
450
 
446
- Classes are supported at the module level. User defined classes should subclass `Record` or have a supported
451
+ Classes are supported at the module level. User defined classes should subclass [`Record`][sonolus.script.record.Record] or have a supported
447
452
  Sonolus.py decorator such as `@level_memory`.
448
453
 
449
454
  Methods may have the `@staticmethod`, `@classmethod`, or `@property` decorators.
@@ -475,8 +480,8 @@ Imports are supported at the module level, but not within functions.
475
480
 
476
481
  ### assert
477
482
 
478
- Assertions are supported. Since error handling is not supported, assertion failures will terminate the current
479
- callback when running in the Sonolus app.
483
+ Assertions are supported. Assertion failures cannot be handled and will terminate the current
484
+ callback when running in the Sonolus app. In debug mode, the game will also pause to indicate the error.
480
485
 
481
486
  ```python
482
487
  assert a > 0, 'a must be positive'
@@ -54,7 +54,9 @@ resources/
54
54
  ```
55
55
 
56
56
  ## Modes
57
- Modes are defined using the `PlayMode`, `WatchMode`, `PreviewMode`, and `TutorialMode` classes:
57
+ Modes are defined using the [`PlayMode`][sonolus.script.engine.PlayMode], [`WatchMode`][sonolus.script.engine.WatchMode], [`PreviewMode`][sonolus.script.engine.PreviewMode], and [`TutorialMode`][sonolus.script.engine.TutorialMode] classes.
58
+
59
+ ### Play Mode
58
60
 
59
61
  ```python
60
62
  from sonolus.script.engine import PlayMode
@@ -78,6 +80,14 @@ play_mode = PlayMode(
78
80
 
79
81
  ```
80
82
 
83
+ Play mode archetypes subclass [`PlayArchetype`][sonolus.script.archetype.PlayArchetype] and should implement the [`should_spawn`][sonolus.script.archetype.PlayArchetype.should_spawn] callback. They may also implement
84
+ the [`preprocess`][sonolus.script.archetype.PlayArchetype.preprocess], [`spawn_order`][sonolus.script.archetype.PlayArchetype.spawn_order], [`initialize`][sonolus.script.archetype.PlayArchetype.initialize], [`update_sequential`][sonolus.script.archetype.PlayArchetype.update_sequential], [`update_parallel`][sonolus.script.archetype.PlayArchetype.update_parallel], [`touch`][sonolus.script.archetype.PlayArchetype.touch], and
85
+ [`terminate`][sonolus.script.archetype.PlayArchetype.terminate] callbacks.
86
+
87
+ Archetypes for scored notes should have the [`is_scored`][sonolus.script.archetype.PlayArchetype.is_scored] class variable set to `True`.
88
+
89
+ ### Watch Mode
90
+
81
91
  ```python
82
92
  from sonolus.script.engine import WatchMode
83
93
 
@@ -100,6 +110,16 @@ watch_mode = WatchMode(
100
110
  )
101
111
  ```
102
112
 
113
+ Watch mode archetypes subclass [`WatchArchetype`][sonolus.script.archetype.WatchArchetype] and should implement the [`spawn_time`][sonolus.script.archetype.WatchArchetype.spawn_time] and [`despawn_time`][sonolus.script.archetype.WatchArchetype.despawn_time] callbacks.
114
+ They may also implement the [`preprocess`][sonolus.script.archetype.WatchArchetype.preprocess], [`initialize`][sonolus.script.archetype.WatchArchetype.initialize], [`update_sequential`][sonolus.script.archetype.WatchArchetype.update_sequential], [`update_parallel`][sonolus.script.archetype.WatchArchetype.update_parallel], and
115
+ [`terminate`][sonolus.script.archetype.WatchArchetype.terminate] callbacks.
116
+
117
+ Watch mode also has the `update_spawn` global callback, which is invoked every frame and should return the reference
118
+ time to compare against spawn and despawn times of archetypes. Typically, this can be either the current time or the
119
+ current scaled time.
120
+
121
+ ### Preview Mode
122
+
103
123
  ```python
104
124
  from sonolus.script.engine import PreviewMode
105
125
 
@@ -115,6 +135,10 @@ preview_mode = PreviewMode(
115
135
  )
116
136
  ```
117
137
 
138
+ Preview mode archetypes subclass [`PreviewArchetype`][sonolus.script.archetype.PreviewArchetype] and may implement the [`preprocess`][sonolus.script.archetype.PreviewArchetype.preprocess] and [`render`][sonolus.script.archetype.PreviewArchetype.render] callbacks.
139
+
140
+ ### Tutorial Mode
141
+
118
142
  ```python
119
143
  from sonolus.script.engine import TutorialMode
120
144
 
@@ -138,8 +162,16 @@ tutorial_mode = TutorialMode(
138
162
  )
139
163
  ```
140
164
 
165
+ Tutorial mode does not have archetypes, but it has `preprocess`, `navigate`, and `update` global callbacks.
166
+
167
+ `preprocess` is invoked once before the tutorial starts.
168
+
169
+ `navigate` is invoked when the player navigates forward or backward in the tutorial.
170
+
171
+ `update` is invoked every frame and should handle most of the drawing logic.
172
+
141
173
  ## Levels
142
- Levels are defined using the `Level` class:
174
+ Levels are defined using the [`Level`][sonolus.script.level.Level] class:
143
175
 
144
176
  ```python
145
177
  from sonolus.script.level import LevelData, BpmChange, Level, TimescaleChange
@@ -0,0 +1,304 @@
1
+ # Resources & Declarations
2
+
3
+ ## Level Memory & Level Data
4
+ Level memory and level data are defined with the [`@level_memory`][sonolus.script.globals.level_memory] and [`@level_data`][sonolus.script.globals.level_data] class decorators, respectively:
5
+
6
+ ```python
7
+ from sonolus.script.globals import level_memory, level_data
8
+
9
+
10
+ @level_memory
11
+ class LevelMemory:
12
+ value: int
13
+
14
+
15
+ @level_data
16
+ class LevelData:
17
+ value: int
18
+ ```
19
+
20
+ Alternatively, they may be called as functions as well by passing the type as an argument:
21
+ ```python
22
+ from sonolus.script.globals import level_memory, level_data
23
+ from sonolus.script.vec import Vec2
24
+
25
+
26
+ level_memory_value = level_memory(Vec2)
27
+ level_data_value = level_data(Vec2)
28
+ ```
29
+
30
+ ## Streams
31
+ Streams are defined with the [`@streams`][sonolus.script.stream.streams] decorator:
32
+
33
+ ```python
34
+ from sonolus.script.stream import streams, Stream, StreamGroup
35
+ from sonolus.script.num import Num
36
+ from sonolus.script.vec import Vec2
37
+
38
+ @streams
39
+ class Streams:
40
+ stream_1: Stream[Num] # A stream of Num values
41
+ stream_2: Stream[Vec2] # A stream of Vec2 values
42
+ group_1: StreamGroup[Num, 10] # A group of 10 Num streams
43
+ group_2: StreamGroup[Vec2, 5] # A group of 5 Vec2 streams
44
+
45
+ data_field_1: Num # A data field of type Num
46
+ data_field_2: Vec2 # A data field of type Vec2
47
+ ```
48
+
49
+ Streams and stream groups are declared by annotating class attributes with [`Stream`][sonolus.script.stream.Stream] or [`StreamGroup`][sonolus.script.stream.StreamGroup].
50
+
51
+ Other types are also supported in the form of data fields. They may be used to store additional data to export from
52
+ Play to Watch mode.
53
+
54
+ In either case, data is write-only in Play mode and read-only in Watch mode.
55
+
56
+ This should only be used once in most projects, as multiple decorated classes will overlap with each other and
57
+ interfere when both are used at the same time.
58
+
59
+ For backwards compatibility, new streams and stream groups should be added to the end of existing ones, and
60
+ lengths and element types of existing streams and stream groups should not be changed. Otherwise, old replays may
61
+ not work on new versions of the engine.
62
+
63
+ ## Skins
64
+ Skins are defined with the [`@skin`][sonolus.script.sprite.skin] decorator:
65
+
66
+ ```python
67
+ from sonolus.script.sprite import skin, StandardSprite, sprite, Sprite, RenderMode
68
+
69
+
70
+ @skin
71
+ class Skin:
72
+ render_mode: RenderMode = RenderMode.DEFAULT
73
+
74
+ note: StandardSprite.NOTE_HEAD_RED
75
+ other: Sprite = sprite("other")
76
+ ```
77
+
78
+ Standard sprites are defined by annotating the field with the corresponding value from [`StandardSprite`][sonolus.script.sprite.StandardSprite].
79
+
80
+ Custom sprites are defined by annotating the field with [`Sprite`][sonolus.script.sprite.Sprite] and calling [`sprite`][sonolus.script.sprite.sprite] with the sprite name.
81
+
82
+ To set the render mode for the skin, set the `render_mode` field to the desired value from [`RenderMode`][sonolus.script.sprite.RenderMode].
83
+
84
+ ## Sound Effects
85
+ Sound effects are defined with the [`@effects`][sonolus.script.effect.effects] decorator:
86
+
87
+ ```python
88
+ from sonolus.script.effect import effects, StandardEffect, Effect, effect
89
+
90
+
91
+ @effects
92
+ class Effects:
93
+ tap_perfect: StandardEffect.PERFECT
94
+ other: Effect = effect("other")
95
+ ```
96
+
97
+ Standard sound effects are defined by annotating the field with the corresponding value from [`StandardEffect`][sonolus.script.effect.StandardEffect].
98
+
99
+ Custom sound effects are defined by annotating the field with [`Effect`][sonolus.script.effect.Effect] and calling [`effect`][sonolus.script.effect.effect] with the effect name.
100
+
101
+ ## Particles
102
+ Particles are defined with the [`@particles`][sonolus.script.particle.particles] decorator:
103
+
104
+ ```python
105
+ from sonolus.script.particle import particles, StandardParticle, Particle, particle
106
+
107
+
108
+ @particles
109
+ class Particles:
110
+ tap: StandardParticle.NOTE_CIRCULAR_TAP_RED
111
+ other: Particle = particle("other")
112
+ ```
113
+
114
+ Standard particles are defined by annotating the field with the corresponding value from [`StandardParticle`][sonolus.script.particle.StandardParticle].
115
+
116
+ Custom particles are defined by annotating the field with [`Particle`][sonolus.script.particle.Particle] and calling [`particle`][sonolus.script.particle.particle] with the particle name.
117
+
118
+ ## Buckets
119
+ Buckets are defined with the [`@buckets`][sonolus.script.bucket.buckets] decorator:
120
+
121
+ ```python
122
+ from sonolus.script.bucket import buckets, bucket_sprite, bucket, Bucket
123
+ from sonolus.script.text import StandardText
124
+ from my_engine.common.skin import Skin
125
+
126
+ @buckets
127
+ class Buckets:
128
+ note: Bucket = bucket(
129
+ sprites=[
130
+ bucket_sprite(
131
+ sprite=Skin.note,
132
+ x=0,
133
+ y=0,
134
+ w=2,
135
+ h=2,
136
+ )
137
+ ],
138
+ unit=StandardText.MILLISECOND_UNIT,
139
+ )
140
+ ```
141
+
142
+ Buckets are defined by annotating the field with [`Bucket`][sonolus.script.bucket.Bucket] and calling [`bucket`][sonolus.script.bucket.bucket] with the bucket name.
143
+
144
+ ## Tutorial Instructions
145
+ Tutorial instructions are defined with the [`@instructions`][sonolus.script.instruction.instructions] decorator:
146
+
147
+ ```python
148
+ from sonolus.script.instruction import instructions, StandardInstruction, Instruction, instruction
149
+
150
+
151
+ @instructions
152
+ class Instructions:
153
+ tap: StandardInstruction.TAP
154
+ other: Instruction = instruction("other")
155
+ ```
156
+
157
+ Standard instructions are defined by annotating the field with the corresponding value from [`StandardInstruction`][sonolus.script.instruction.StandardInstruction].
158
+
159
+ Custom instructions are defined by annotating the field with [`Instruction`][sonolus.script.instruction.Instruction] and calling [`instruction`][sonolus.script.instruction.instruction] with the instruction name.
160
+
161
+ ## Tutorial Instruction Icons
162
+ Tutorial instruction icons are defined with the [`@instruction_icons`][sonolus.script.instruction.instruction_icons] decorator:
163
+
164
+ ```python
165
+ from sonolus.script.instruction import instruction_icons, StandardInstructionIcon, InstructionIcon, instruction_icon
166
+
167
+
168
+ @instruction_icons
169
+ class InstructionIcons:
170
+ hand: StandardInstructionIcon.HAND
171
+ other: InstructionIcon = instruction_icon("other")
172
+ ```
173
+
174
+ Standard instruction icons are defined by annotating the field with the corresponding value from [`StandardInstructionIcon`][sonolus.script.instruction.StandardInstructionIcon].
175
+
176
+ Custom instruction icons are defined by annotating the field with [`InstructionIcon`][sonolus.script.instruction.InstructionIcon] and calling [`instruction_icon`][sonolus.script.instruction.instruction_icon] with the icon name.
177
+
178
+ ## Options
179
+ Engine options are defined with the [`@options`][sonolus.script.options.options] decorator:
180
+
181
+ ```python
182
+ from sonolus.script.options import options, select_option, slider_option, toggle_option
183
+
184
+
185
+ @options
186
+ class Options:
187
+ slider_option: float = slider_option(
188
+ name="Slider Option",
189
+ standard=True,
190
+ advanced=False,
191
+ default=0.5,
192
+ min=0,
193
+ max=1,
194
+ step=0.1,
195
+ unit="unit",
196
+ scope="scope",
197
+ )
198
+ toggle_option: bool = toggle_option(
199
+ name="Toggle Option",
200
+ standard=True,
201
+ advanced=False,
202
+ default=True,
203
+ scope="scope",
204
+ )
205
+ select_option: int = select_option(
206
+ name="Select Option",
207
+ standard=True,
208
+ advanced=False,
209
+ default="value",
210
+ values=["value"],
211
+ scope="scope",
212
+ )
213
+ ```
214
+
215
+ There are three types of options available:
216
+
217
+ 1. [`slider_option`][sonolus.script.options.slider_option]: A slider control for numeric values
218
+ 2. [`toggle_option`][sonolus.script.options.toggle_option]: A toggle switch for boolean values
219
+ 3. [`select_option`][sonolus.script.options.select_option]: A dropdown menu for selecting from predefined values
220
+
221
+ ## UI
222
+ Ui configuration is defined with the [`UiConfig`][sonolus.script.ui.UiConfig] class:
223
+
224
+ ```python
225
+ from sonolus.script.ui import (
226
+ EaseType,
227
+ UiAnimation,
228
+ UiAnimationTween,
229
+ UiConfig,
230
+ UiJudgmentErrorPlacement,
231
+ UiJudgmentErrorStyle,
232
+ UiMetric,
233
+ UiVisibility,
234
+ )
235
+
236
+ ui_config = UiConfig(
237
+ scope="my_engine",
238
+ primary_metric=UiMetric.ARCADE,
239
+ secondary_metric=UiMetric.LIFE,
240
+ menu_visibility=UiVisibility(
241
+ scale=1.0,
242
+ alpha=1.0,
243
+ ),
244
+ judgment_visibility=UiVisibility(
245
+ scale=1.0,
246
+ alpha=1.0,
247
+ ),
248
+ combo_visibility=UiVisibility(
249
+ scale=1.0,
250
+ alpha=1.0,
251
+ ),
252
+ primary_metric_visibility=UiVisibility(
253
+ scale=1.0,
254
+ alpha=1.0,
255
+ ),
256
+ secondary_metric_visibility=UiVisibility(
257
+ scale=1.0,
258
+ alpha=1.0,
259
+ ),
260
+ progress_visibility=UiVisibility(
261
+ scale=1.0,
262
+ alpha=1.0,
263
+ ),
264
+ tutorial_navigation_visibility=UiVisibility(
265
+ scale=1.0,
266
+ alpha=1.0,
267
+ ),
268
+ tutorial_instruction_visibility=UiVisibility(
269
+ scale=1.0,
270
+ alpha=1.0,
271
+ ),
272
+ judgment_animation=UiAnimation(
273
+ scale=UiAnimationTween(
274
+ start=1.0,
275
+ end=1.0,
276
+ duration=0.0,
277
+ ease=EaseType.NONE,
278
+ ),
279
+ alpha=UiAnimationTween(
280
+ start=1.0,
281
+ end=1.0,
282
+ duration=0.0,
283
+ ease=EaseType.NONE,
284
+ ),
285
+ ),
286
+ combo_animation=UiAnimation(
287
+ scale=UiAnimationTween(
288
+ start=1.2,
289
+ end=1.0,
290
+ duration=0.2,
291
+ ease=EaseType.IN_CUBIC,
292
+ ),
293
+ alpha=UiAnimationTween(
294
+ start=1.0,
295
+ end=1.0,
296
+ duration=0.0,
297
+ ease=EaseType.NONE,
298
+ ),
299
+ ),
300
+ judgment_error_style=UiJudgmentErrorStyle.LATE,
301
+ judgment_error_placement=UiJudgmentErrorPlacement.TOP,
302
+ judgment_error_min=0.0,
303
+ )
304
+ ```