pygamestudio 1.0.0.dev5__tar.gz → 1.0.0.dev6__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.
Files changed (171) hide show
  1. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/PKG-INFO +3 -3
  2. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/README.md +1 -1
  3. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/README_zh-CN.md +1 -1
  4. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/pyproject.toml +2 -2
  5. pygamestudio-1.0.0.dev6/src/pygamestudio/api/__init__.py +7 -0
  6. pygamestudio-1.0.0.dev6/src/pygamestudio/api/core/audio.py +217 -0
  7. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/api/core/game.py +24 -2
  8. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/api/core/scene.py +121 -4
  9. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/i18n/languages/en.json +19 -2
  10. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/i18n/languages/zh_CN.json +20 -3
  11. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/i18n/translator.py +16 -0
  12. pygamestudio-1.0.0.dev6/src/pygamestudio/common/res/audios/game_start.mp3 +0 -0
  13. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/qss/dark.qss +8 -0
  14. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/qss/light.qss +8 -0
  15. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/templates/main_template.py +1 -0
  16. pygamestudio-1.0.0.dev6/src/pygamestudio/common/res/templates/object_script_template.py +12 -0
  17. pygamestudio-1.0.0.dev6/src/pygamestudio/common/utils/constant.py +1 -0
  18. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/utils/path.py +7 -0
  19. pygamestudio-1.0.0.dev6/src/pygamestudio/common/utils/system.py +87 -0
  20. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/game/core/command.py +29 -6
  21. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/game/core/manager.py +322 -55
  22. pygamestudio-1.0.0.dev6/src/pygamestudio/game/object/__init__.py +8 -0
  23. pygamestudio-1.0.0.dev6/src/pygamestudio/game/object/base.py +387 -0
  24. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/game/object/button.py +54 -3
  25. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/game/object/canvas.py +7 -3
  26. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/game/object/ellipse.py +6 -2
  27. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/game/object/image.py +12 -2
  28. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/game/object/line.py +58 -2
  29. pygamestudio-1.0.0.dev6/src/pygamestudio/game/object/rect.py +97 -0
  30. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/game/object/text.py +67 -11
  31. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/asset/tree.py +46 -13
  32. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/base/window.py +90 -43
  33. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/console/browser.py +55 -0
  34. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/console/widget.py +2 -3
  35. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/console/window.py +6 -3
  36. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/dashboard/config.py +5 -5
  37. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/dashboard/dialog.py +2 -1
  38. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/dashboard/list.py +29 -11
  39. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/hierarchy/tree.py +6 -6
  40. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/inspector/color.py +18 -11
  41. pygamestudio-1.0.0.dev6/src/pygamestudio/gui/inspector/component/lineedit.py +353 -0
  42. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/inspector/container.py +24 -8
  43. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/inspector/layout/button.py +12 -1
  44. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/inspector/layout/canvas.py +12 -1
  45. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/inspector/layout/ellipse.py +12 -1
  46. pygamestudio-1.0.0.dev5/src/pygamestudio/gui/inspector/layout/rect.py → pygamestudio-1.0.0.dev6/src/pygamestudio/gui/inspector/layout/image.py +25 -2
  47. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/inspector/layout/line.py +12 -1
  48. pygamestudio-1.0.0.dev5/src/pygamestudio/gui/inspector/layout/image.py → pygamestudio-1.0.0.dev6/src/pygamestudio/gui/inspector/layout/rect.py +8 -9
  49. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/inspector/layout/text.py +20 -9
  50. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/scene/gizmo.py +45 -4
  51. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/scene/screen.py +6 -8
  52. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/settings/project.py +0 -2
  53. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/window.py +27 -4
  54. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/main.py +16 -0
  55. pygamestudio-1.0.0.dev5/src/pygamestudio/api/__init__.py +0 -4
  56. pygamestudio-1.0.0.dev5/src/pygamestudio/common/utils/constant.py +0 -1
  57. pygamestudio-1.0.0.dev5/src/pygamestudio/game/object/base.py +0 -119
  58. pygamestudio-1.0.0.dev5/src/pygamestudio/game/object/rect.py +0 -52
  59. pygamestudio-1.0.0.dev5/src/pygamestudio/gui/inspector/component/lineedit.py +0 -188
  60. pygamestudio-1.0.0.dev5/src/pygamestudio/gui/settings/__init__.py +0 -0
  61. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/.github/FUNDING.yml +0 -0
  62. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/.gitignore +0 -0
  63. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/LICENSE +0 -0
  64. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/__init__.py +0 -0
  65. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/api/config/__init__.py +0 -0
  66. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/api/config/project.py +0 -0
  67. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/api/core/__init__.py +0 -0
  68. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/api/event/__init__.py +0 -0
  69. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/api/event/constant.py +0 -0
  70. {pygamestudio-1.0.0.dev5/src/pygamestudio/api/sound → pygamestudio-1.0.0.dev6/src/pygamestudio/common}/__init__.py +0 -0
  71. {pygamestudio-1.0.0.dev5/src/pygamestudio/common → pygamestudio-1.0.0.dev6/src/pygamestudio/common/i18n}/__init__.py +0 -0
  72. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/fonts/SIMHEI.ttf +0 -0
  73. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/add.png +0 -0
  74. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/add_item.png +0 -0
  75. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/browse.png +0 -0
  76. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/button.png +0 -0
  77. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/canvas.png +0 -0
  78. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/check.png +0 -0
  79. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/clear.png +0 -0
  80. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/close.png +0 -0
  81. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/create_project.png +0 -0
  82. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/down_arrow.png +0 -0
  83. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/ellipse.png +0 -0
  84. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/error.png +0 -0
  85. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/expand_or_collapse_all.png +0 -0
  86. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/eye_closed.png +0 -0
  87. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/eye_off.png +0 -0
  88. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/eye_open.png +0 -0
  89. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/heart.png +0 -0
  90. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/image.png +0 -0
  91. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/import_project.png +0 -0
  92. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/info.png +0 -0
  93. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/left_arrow.png +0 -0
  94. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/left_arrow_gray.png +0 -0
  95. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/line.png +0 -0
  96. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/logo.png +0 -0
  97. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/maximize.png +0 -0
  98. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/maximize_disabled.png +0 -0
  99. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/minimize.png +0 -0
  100. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/normalize.png +0 -0
  101. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/project_icon.png +0 -0
  102. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/rect.png +0 -0
  103. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/refresh_asset.png +0 -0
  104. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/right_arrow.png +0 -0
  105. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/right_arrow_gray.png +0 -0
  106. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/run.png +0 -0
  107. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/search.png +0 -0
  108. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/sort.png +0 -0
  109. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/text.png +0 -0
  110. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/tree_arrow_down.png +0 -0
  111. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/tree_arrow_right.png +0 -0
  112. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/up_arrow.png +0 -0
  113. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/images/warning.png +0 -0
  114. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/resources.qrc +0 -0
  115. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/resources_rc.py +0 -0
  116. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/templates/editor_template.pygs +0 -0
  117. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/res/templates/project_template.pygs +0 -0
  118. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/utils/config.py +0 -0
  119. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/common/utils/theme.py +0 -0
  120. {pygamestudio-1.0.0.dev5/src/pygamestudio/common/i18n → pygamestudio-1.0.0.dev6/src/pygamestudio/game}/__init__.py +0 -0
  121. {pygamestudio-1.0.0.dev5/src/pygamestudio/game → pygamestudio-1.0.0.dev6/src/pygamestudio/game/core}/__init__.py +0 -0
  122. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/game/object/type.py +0 -0
  123. {pygamestudio-1.0.0.dev5/src/pygamestudio/game/core → pygamestudio-1.0.0.dev6/src/pygamestudio/gui}/__init__.py +0 -0
  124. {pygamestudio-1.0.0.dev5/src/pygamestudio/gui → pygamestudio-1.0.0.dev6/src/pygamestudio/gui/about}/__init__.py +0 -0
  125. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/about/window.py +0 -0
  126. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/asset/delegate.py +0 -0
  127. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/asset/menu.py +0 -0
  128. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/asset/model.py +0 -0
  129. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/asset/search.py +0 -0
  130. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/asset/type.py +0 -0
  131. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/asset/widget.py +0 -0
  132. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/asset/window.py +0 -0
  133. {pygamestudio-1.0.0.dev5/src/pygamestudio/gui/about → pygamestudio-1.0.0.dev6/src/pygamestudio/gui/build}/__init__.py +0 -0
  134. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/build/desktop.py +0 -0
  135. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/build/window.py +0 -0
  136. {pygamestudio-1.0.0.dev5/src/pygamestudio/gui/build → pygamestudio-1.0.0.dev6/src/pygamestudio/gui/console}/__init__.py +0 -0
  137. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/console/logger.py +0 -0
  138. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/console/menu.py +0 -0
  139. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/console/search.py +0 -0
  140. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/console/type.py +0 -0
  141. {pygamestudio-1.0.0.dev5/src/pygamestudio/gui/console → pygamestudio-1.0.0.dev6/src/pygamestudio/gui/dashboard}/__init__.py +0 -0
  142. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/dashboard/delegate.py +0 -0
  143. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/dashboard/menu.py +0 -0
  144. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/dashboard/model.py +0 -0
  145. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/dashboard/search.py +0 -0
  146. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/dashboard/type.py +0 -0
  147. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/dashboard/widget.py +0 -0
  148. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/dashboard/window.py +0 -0
  149. {pygamestudio-1.0.0.dev5/src/pygamestudio/gui/dashboard → pygamestudio-1.0.0.dev6/src/pygamestudio/gui/hierarchy}/__init__.py +0 -0
  150. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/hierarchy/delegate.py +0 -0
  151. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/hierarchy/menu.py +0 -0
  152. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/hierarchy/search.py +0 -0
  153. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/hierarchy/widget.py +0 -0
  154. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/hierarchy/window.py +0 -0
  155. {pygamestudio-1.0.0.dev5/src/pygamestudio/gui/hierarchy → pygamestudio-1.0.0.dev6/src/pygamestudio/gui/inspector}/__init__.py +0 -0
  156. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/inspector/component/button.py +0 -0
  157. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/inspector/component/checkbox.py +0 -0
  158. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/inspector/component/combobox.py +0 -0
  159. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/inspector/component/label.py +0 -0
  160. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/inspector/component/picker.py +0 -0
  161. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/inspector/component/spinbox.py +0 -0
  162. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/inspector/component/textedit.py +0 -0
  163. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/inspector/widget.py +0 -0
  164. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/inspector/window.py +0 -0
  165. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/main.py +0 -0
  166. {pygamestudio-1.0.0.dev5/src/pygamestudio/gui/inspector → pygamestudio-1.0.0.dev6/src/pygamestudio/gui/scene}/__init__.py +0 -0
  167. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/scene/grid.py +0 -0
  168. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/scene/widget.py +0 -0
  169. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/scene/window.py +0 -0
  170. {pygamestudio-1.0.0.dev5/src/pygamestudio/gui/scene → pygamestudio-1.0.0.dev6/src/pygamestudio/gui/settings}/__init__.py +0 -0
  171. {pygamestudio-1.0.0.dev5 → pygamestudio-1.0.0.dev6}/src/pygamestudio/gui/settings/editor.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pygamestudio
3
- Version: 1.0.0.dev5
4
- Summary: Let's create pygame visually!
3
+ Version: 1.0.0.dev6
4
+ Summary: Let's create python games visually!
5
5
  Project-URL: Documentation, https://pygamestudio.com/tutorial/installation
6
6
  Project-URL: Homepage, https://pygamestudio.com
7
7
  Project-URL: Github, https://github.com/pygamestudio/pygamestudio
@@ -42,7 +42,7 @@ Description-Content-Type: text/markdown
42
42
  English  |  [简体中文](https://github.com/pygamestudio/pygamestudio/blob/main/README_zh-CN.md)
43
43
  </div>
44
44
 
45
- **Pygame Studio** is a visual editor built specifically for **pygame-ce**, designed to help users create pygame-ce projects visually, making it easier for beginners, students, and hobby developers to get started with pygame development.
45
+ **Pygame Studio** is a visual editor built with **PyGame-ce** and **PySide6**, designed to help users create Python games visually, making it easier for beginners, students, and hobby developers to get started with game development.
46
46
 
47
47
  <br>
48
48
 
@@ -13,7 +13,7 @@
13
13
  English&nbsp; | &nbsp;[简体中文](https://github.com/pygamestudio/pygamestudio/blob/main/README_zh-CN.md)
14
14
  </div>
15
15
 
16
- **Pygame Studio** is a visual editor built specifically for **pygame-ce**, designed to help users create pygame-ce projects visually, making it easier for beginners, students, and hobby developers to get started with pygame development.
16
+ **Pygame Studio** is a visual editor built with **PyGame-ce** and **PySide6**, designed to help users create Python games visually, making it easier for beginners, students, and hobby developers to get started with game development.
17
17
 
18
18
  <br>
19
19
 
@@ -13,7 +13,7 @@
13
13
  [English](https://github.com/pygamestudio/pygamestudio) &nbsp;|&nbsp; 简体中文
14
14
  </div>
15
15
 
16
- **Pygame Studio** 是专为 **pygame-ce** 打造的可视化编辑器,支持以可视化方式制作 pygame-ce 项目,让编程新手、在校学生以及业余开发者都能更轻松地入门 Pygame 游戏开发。
16
+ **Pygame Studio** 是基于 **PyGame-ce** **PySide6** 打造的可视化编辑器,支持以可视化方式制作 Python 游戏,让编程新手、在校学生以及业余开发者都能更轻松地入门游戏开发。
17
17
 
18
18
  <br>
19
19
 
@@ -4,9 +4,9 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "pygamestudio"
7
- version = "1.0.0.dev5"
7
+ version = "1.0.0.dev6"
8
8
  authors = [{ name="Louis Ren", email="louis@pygamestudio.com" }]
9
- description = "Let's create pygame visually!"
9
+ description = "Let's create python games visually!"
10
10
  readme = "README.md"
11
11
  license-files = ["LICEN[CS]E*"]
12
12
  requires-python = ">=3.9"
@@ -0,0 +1,7 @@
1
+ from .config.project import *
2
+ from .core.game import *
3
+ from .core.scene import *
4
+ from .core.audio import *
5
+ from .event.constant import *
6
+
7
+ from pygamestudio.game.object import *
@@ -0,0 +1,217 @@
1
+ """
2
+ Audio manager API for generated games.
3
+
4
+ Provides a simple interface to play sound effects and background music:
5
+
6
+ import pygamestudio as studio
7
+
8
+ studio.play_sound('./audio/jump.wav')
9
+ studio.play_music('./audio/bgm.ogg', loops=-1)
10
+ studio.set_music_volume(0.5)
11
+ studio.stop_sound('./audio/jump.wav')
12
+
13
+ Sound files are resolved relative to the project path (the project's `audio/`
14
+ folder). The audio mixer is initialized lazily on first use; if no audio device
15
+ is available, all calls become no-ops with a warning instead of crashing.
16
+ """
17
+
18
+ import os
19
+ import pygame
20
+ from pathlib import Path
21
+ from pygamestudio.common.i18n.translator import Translator as T
22
+
23
+
24
+ class AudioManager:
25
+ def __init__(self):
26
+ self._is_available = False
27
+ self._sounds = {} # absolute path -> pygame.mixer.Sound
28
+ self._looping_channels = {} # absolute path -> Channel (looping sfx)
29
+ self._music_volume = 1.0
30
+
31
+ # ---------- internals ----------
32
+
33
+ def _init_mixer(self) -> bool:
34
+ """Initialize pygame.mixer lazily. Returns False when audio is unavailable."""
35
+ if self._is_available:
36
+ return True
37
+ try:
38
+ if not pygame.mixer.get_init():
39
+ pygame.mixer.init()
40
+ self._is_available = True
41
+ except Exception as e:
42
+ print(T.tr('api.fail_to_init_mixer', 'Failed to initialize audio mixer: {}').format(e))
43
+ self._is_available = False
44
+ return self._is_available
45
+
46
+ def _resolve_path(self, sound_path) -> Path:
47
+ path = Path(sound_path)
48
+ if path.is_absolute():
49
+ return path
50
+ return Path(os.environ.get('PROJECT_PATH', '')) / path
51
+
52
+ def _load_sound(self, sound_path):
53
+ if not self._init_mixer():
54
+ return None
55
+
56
+ absolute_path = self._resolve_path(sound_path)
57
+ if not absolute_path.exists():
58
+ print(T.tr('api.no_sound_path', 'The sound path {} does not exist.').format(absolute_path))
59
+ return None
60
+
61
+ key = absolute_path.as_posix()
62
+ if key not in self._sounds:
63
+ try:
64
+ self._sounds[key] = pygame.mixer.Sound(str(absolute_path))
65
+ except Exception as e:
66
+ print(T.tr('api.fail_to_load_sound', 'Failed to load sound {}: {}').format(absolute_path, e))
67
+ return None
68
+ return self._sounds[key]
69
+
70
+ # ---------- sound effects ----------
71
+
72
+ def load_sound(self, sound_path):
73
+ """Load (and cache) a sound effect. Returns a pygame Sound or None."""
74
+ return self._load_sound(sound_path)
75
+
76
+ def play_sound(self, sound_path, volume=1.0, loops=0, fade_ms=0):
77
+ """
78
+ Play a sound effect. Returns the pygame Channel, or None on failure.
79
+
80
+ :param sound_path: path relative to the project (e.g. './audio/jump.wav')
81
+ :param volume: playback volume in [0.0, 1.0]
82
+ :param loops: 0 = play once, -1 = loop forever, N = play N+1 times
83
+ :param fade_ms: fade-in duration in milliseconds
84
+ """
85
+ sound = self._load_sound(sound_path)
86
+ if sound is None:
87
+ return None
88
+
89
+ try:
90
+ channel = sound.play(loops=loops, fade_ms=fade_ms)
91
+ if channel:
92
+ channel.set_volume(max(0.0, min(1.0, float(volume))))
93
+ if loops != 0:
94
+ self._looping_channels[self._resolve_path(sound_path).as_posix()] = channel
95
+ return channel
96
+ except Exception as e:
97
+ print(T.tr('api.fail_to_play_sound', 'Failed to play sound {}: {}').format(self._resolve_path(sound_path), e))
98
+ return None
99
+
100
+ def stop_sound(self, sound_path):
101
+ """Stop a looping sound effect started with play_sound(loops=...)."""
102
+ key = self._resolve_path(sound_path).as_posix()
103
+ channel = self._looping_channels.pop(key, None)
104
+ if channel:
105
+ channel.stop()
106
+
107
+ def stop_all_sounds(self):
108
+ """Stop every currently playing sound effect."""
109
+ if self._is_available:
110
+ pygame.mixer.stop()
111
+ self._looping_channels.clear()
112
+
113
+ # ---------- background music ----------
114
+
115
+ def play_music(self, music_path, loops=-1, fade_ms=0):
116
+ """
117
+ Play a background music track (one stream at a time).
118
+
119
+ :param music_path: path relative to the project (e.g. './audio/bgm.ogg')
120
+ :param loops: -1 = loop forever (default), 0 = play once
121
+ :param fade_ms: fade-in duration in milliseconds
122
+ """
123
+ if not self._init_mixer():
124
+ return False
125
+
126
+ absolute_path = self._resolve_path(music_path)
127
+ if not absolute_path.exists():
128
+ print(T.tr('api.no_sound_path', 'The sound path {} does not exist.').format(absolute_path))
129
+ return False
130
+
131
+ try:
132
+ pygame.mixer.music.load(str(absolute_path))
133
+ pygame.mixer.music.set_volume(self._music_volume)
134
+ pygame.mixer.music.play(loops=loops, fade_ms=fade_ms)
135
+ return True
136
+ except Exception as e:
137
+ print(T.tr('api.fail_to_play_music', 'Failed to play music {}: {}').format(absolute_path, e))
138
+ return False
139
+
140
+ def stop_music(self, fade_ms=0):
141
+ """Stop the background music (with an optional fade-out in ms)."""
142
+ if not self._is_available:
143
+ return
144
+ if fade_ms > 0:
145
+ pygame.mixer.music.fadeout(fade_ms)
146
+ else:
147
+ pygame.mixer.music.stop()
148
+
149
+ def pause_music(self):
150
+ if self._is_available:
151
+ pygame.mixer.music.pause()
152
+
153
+ def resume_music(self):
154
+ if self._is_available:
155
+ pygame.mixer.music.unpause()
156
+
157
+ def is_music_playing(self) -> bool:
158
+ if not self._is_available:
159
+ return False
160
+ return pygame.mixer.music.get_busy()
161
+
162
+ def set_music_volume(self, volume):
163
+ """Set background music volume in [0.0, 1.0]."""
164
+ self._music_volume = max(0.0, min(1.0, float(volume)))
165
+ if self._is_available:
166
+ pygame.mixer.music.set_volume(self._music_volume)
167
+
168
+ def get_music_volume(self) -> float:
169
+ return self._music_volume
170
+
171
+
172
+ # Module-level singleton, mirroring scene_loader.
173
+ audio_manager = AudioManager()
174
+
175
+
176
+ def load_sound(sound_path):
177
+ return audio_manager.load_sound(sound_path)
178
+
179
+
180
+ def play_sound(sound_path, volume=1.0, loops=0, fade_ms=0):
181
+ return audio_manager.play_sound(sound_path, volume, loops, fade_ms)
182
+
183
+
184
+ def stop_sound(sound_path):
185
+ return audio_manager.stop_sound(sound_path)
186
+
187
+
188
+ def stop_all_sounds():
189
+ return audio_manager.stop_all_sounds()
190
+
191
+
192
+ def play_music(music_path, loops=-1, fade_ms=0):
193
+ return audio_manager.play_music(music_path, loops, fade_ms)
194
+
195
+
196
+ def stop_music(fade_ms=0):
197
+ return audio_manager.stop_music(fade_ms)
198
+
199
+
200
+ def pause_music():
201
+ return audio_manager.pause_music()
202
+
203
+
204
+ def resume_music():
205
+ return audio_manager.resume_music()
206
+
207
+
208
+ def is_music_playing() -> bool:
209
+ return audio_manager.is_music_playing()
210
+
211
+
212
+ def set_music_volume(volume):
213
+ return audio_manager.set_music_volume(volume)
214
+
215
+
216
+ def get_music_volume() -> float:
217
+ return audio_manager.get_music_volume()
@@ -3,10 +3,18 @@ import sys
3
3
  import pygame
4
4
  import inspect
5
5
  from pathlib import Path
6
+ from pygamestudio.api.core.scene import scene_loader
6
7
  from pygamestudio.api.config.project import get_project_config
7
8
 
8
9
 
9
10
  class Game:
11
+ """Runtime game class used by every built/exported project.
12
+
13
+ Subclass it in the project's main.py and override the on_* hooks. run()
14
+ starts the main loop: it auto-detects the project root from the caller's
15
+ file, initializes pygame, dispatches every pygame event to the matching
16
+ on_* hook, then calls on_update(delta_time) and flips the display.
17
+ """
10
18
  _instance = None
11
19
 
12
20
  def __init__(self):
@@ -17,6 +25,11 @@ class Game:
17
25
  self._running = False
18
26
 
19
27
  def _init_game(self):
28
+ """Set up pygame and resolve the project root from the calling file.
29
+
30
+ The project path is derived from the stack frame of whoever created
31
+ the Game (the project's main.py), so no path config is required.
32
+ """
20
33
  caller_frame = inspect.stack()[-1]
21
34
  caller_file_path = caller_frame.filename
22
35
  self._project_path = Path(caller_file_path).parent.resolve().as_posix()
@@ -29,6 +42,7 @@ class Game:
29
42
  self._clock = pygame.time.Clock()
30
43
 
31
44
  def run(self):
45
+ """Start the game loop. Blocks until the window is closed."""
32
46
  Game._instance = self
33
47
  self._init_game()
34
48
  self._running = True
@@ -36,6 +50,7 @@ class Game:
36
50
  self.on_start()
37
51
 
38
52
  while self._running:
53
+ # --- 1. Dispatch all pending pygame events to the on_* hooks. ---
39
54
  for event in pygame.event.get():
40
55
  # ---------- Quit Event ----------
41
56
  if event.type == pygame.QUIT:
@@ -55,7 +70,7 @@ class Game:
55
70
  elif event.type == pygame.MOUSEBUTTONUP:
56
71
  self.on_mouse_button_up(event.pos, event.button, getattr(event, 'touch', 0), getattr(event, "clicks", 1), getattr(event, 'window', None))
57
72
  elif event.type == pygame.MOUSEWHEEL:
58
- self.on_mouse_wheel(event.which, event.flipped, event.x, event.y, getattr(event, 'touch', 0), event.precise_x, event.precise_y, getattr(event, 'window', None))
73
+ self.on_mouse_wheel(event.flipped, event.x, event.y, getattr(event, 'touch', 0), event.precise_x, event.precise_y, getattr(event, 'window', None))
59
74
 
60
75
  # ---------- Joystick Event ----------
61
76
  elif event.type == pygame.JOYAXISMOTION:
@@ -181,9 +196,16 @@ class Game:
181
196
 
182
197
 
183
198
  delta_time = self._clock.tick(self._fps) / 1000
199
+ # Make the current frame's delta time available to the scene's
200
+ # scripts (their on_update(delta_time) hooks).
201
+ scene_loader._set_delta_time(delta_time)
202
+ # --- 2. Fixed/step logic: user update + draw, then present. ---
184
203
  self.on_update(delta_time)
185
204
  pygame.display.flip()
186
205
 
206
+ # Let every attached behavior script run its on_destroy() cleanup hook
207
+ # before the game exits (mirrors on_start fired on scene load).
208
+ scene_loader._destroy_scripts()
187
209
  self.on_quit()
188
210
  pygame.quit()
189
211
  sys.exit()
@@ -215,7 +237,7 @@ class Game:
215
237
  def on_mouse_button_up(self, pos, btn, touch=0, clicks=1, window=None):
216
238
  pass
217
239
 
218
- def on_mouse_wheel(self, which, flipped, x, y, touch=0, precise_x=0.0, precise_y=0.0, window=None):
240
+ def on_mouse_wheel(self, flipped, x, y, touch=0, precise_x=0.0, precise_y=0.0, window=None):
219
241
  pass
220
242
 
221
243
  # ---------- Joystick Event Hooks ----------
@@ -1,6 +1,9 @@
1
1
  import os
2
+ import sys
2
3
  import re
3
4
  import json
5
+ import inspect
6
+ import importlib.util
4
7
  import pygame
5
8
  from pathlib import Path
6
9
  from pygamestudio.game.object.type import *
@@ -16,9 +19,19 @@ from pygamestudio.common.i18n.translator import Translator as T
16
19
 
17
20
 
18
21
  class SceneLoader:
22
+ """Runtime mirror of the editor's scene tree.
23
+
24
+ Reads the .scene JSON produced by the editor and rebuilds the same object
25
+ tree with is_for_api=True objects, rendering them each frame and driving
26
+ the attached behavior scripts (on_start / on_update / on_destroy).
27
+ """
28
+
19
29
  def __init__(self):
20
30
  self._current_scene_path = ''
21
31
  self._all_object_tree_struct = {}
32
+ # Seconds elapsed since the last frame, updated by Game.run() each
33
+ # frame and passed to the scripts' on_update(delta_time) hooks.
34
+ self._delta_time = 0
22
35
 
23
36
  def load_scene(self, screen_surface:pygame.Surface, scene_path:str=''):
24
37
  if not scene_path and self._current_scene_path or scene_path and scene_path==self._current_scene_path:
@@ -35,6 +48,9 @@ class SceneLoader:
35
48
  if not Path(scene_path).exists():
36
49
  raise RuntimeError(T.tr('api.no_scene_path', 'The scene path {} does not exist.').format(scene_path))
37
50
 
51
+ if self._all_object_tree_struct:
52
+ # The current scene is about to be replaced; let its scripts clean up.
53
+ self._destroy_scripts()
38
54
  self._all_object_tree_struct = {}
39
55
  self._current_scene_path = scene_path
40
56
  with open(scene_path, 'r', encoding='utf-8') as f:
@@ -55,6 +71,8 @@ class SceneLoader:
55
71
  _l(key, child_object_tree_struct)
56
72
 
57
73
  _l('', scene_data)
74
+ # The whole object tree now exists; fire the scripts' on_start hooks.
75
+ self._start_scripts()
58
76
  self._update_scene(screen_surface)
59
77
 
60
78
  def _add(self, parent_uuid, object_type, object_data={}):
@@ -84,7 +102,61 @@ class SceneLoader:
84
102
  obj = ObjectImage(self, object_data, is_for_api=True)
85
103
  elif object_type == OBJECT_BUTTON:
86
104
  obj = ObjectButton(self, object_data, is_for_api=True)
105
+ else:
106
+ raise RuntimeError(T.tr('api.unknown_object_type', 'Unknown object type: {}').format(object_type))
107
+
108
+ # Attach the behavior script (if any) so the script's lifecycle hooks
109
+ # can be driven later (see ObjectBase._start/_update_surface/_destroy).
110
+ obj.script_instance = self._load_script(obj)
87
111
  return obj
112
+
113
+ def _load_script(self, obj):
114
+ """
115
+ Dynamically load and instantiate the object's behavior script.
116
+
117
+ The script module (obj.script_path, relative to the project) is loaded
118
+ with importlib, the first user-defined class is instantiated with
119
+ owner=obj, and the instance is stored on obj.script_instance. Returns
120
+ None when no script is attached or it fails to load (the failure is
121
+ reported to stderr but does not stop the game).
122
+ """
123
+ if not obj.script_path:
124
+ return None
125
+
126
+ script_absolute_path = Path(os.environ.get('PROJECT_PATH', '')) / obj.script_path
127
+ if not script_absolute_path.exists():
128
+ print(T.tr('api.no_script_path', 'The script path {} does not exist.').format(script_absolute_path), file=sys.stderr)
129
+ return None
130
+
131
+ try:
132
+ # A unique module name per object keeps every scene (re)load fresh,
133
+ # so the latest script content is always picked up.
134
+ module_name = f'pygamestudio_runtime_script_{obj.uuid}'
135
+ spec = importlib.util.spec_from_file_location(module_name, script_absolute_path)
136
+ module = importlib.util.module_from_spec(spec)
137
+ spec.loader.exec_module(module)
138
+ except Exception:
139
+ print(T.tr('api.fail_to_load_script', 'Failed to load script {}: {}').format(script_absolute_path, e), file=sys.stderr)
140
+ return None
141
+
142
+ script_class = self._get_script_class(module)
143
+ if script_class is None:
144
+ print(T.tr('api.no_script_class', 'No script class found in {}.').format(script_absolute_path), file=sys.stderr)
145
+ return None
146
+
147
+ try:
148
+ return script_class(obj)
149
+ except Exception as e:
150
+ print(T.tr('api.fail_to_init_script', 'Failed to initialize script {}: {}').format(script_absolute_path, e), file=sys.stderr)
151
+ return None
152
+
153
+ @staticmethod
154
+ def _get_script_class(module):
155
+ """Return the first class defined in the given script module (ignores imports)."""
156
+ for name, value in module.__dict__.items():
157
+ if inspect.isclass(value) and value.__module__ == module.__name__:
158
+ return value
159
+ return None
88
160
 
89
161
  def _add_object_tree_struct(self, parent_uuid, object_tree_struct_to_add):
90
162
  if not self._all_object_tree_struct:
@@ -114,16 +186,61 @@ class SceneLoader:
114
186
  def _update(object_tree_struct, parent_surface):
115
187
  value = list(object_tree_struct.values())[0]
116
188
  obj = value['object']
117
- obj.update_surface()
189
+ obj._update_surface()
190
+ self._update_script(obj)
118
191
 
119
- if obj.is_visible:
192
+ if obj.visible:
120
193
  for child_object_tree_struct in value['children']:
121
- _update(child_object_tree_struct, obj.get_surface())
194
+ _update(child_object_tree_struct, obj._get_surface())
122
195
 
123
- obj.draw(parent_surface)
196
+ obj._draw(parent_surface)
124
197
 
125
198
  _update(self._all_object_tree_struct, screen_surface)
126
199
 
200
+ def _set_delta_time(self, delta_time):
201
+ """Set the per-frame delta time (seconds) passed to scripts' on_update."""
202
+ self._delta_time = delta_time
203
+
204
+ def _start_scripts(self):
205
+ """Fire on_start() on every attached script (after the scene is loaded)."""
206
+ for obj in self._iter_objects():
207
+ if not obj.script_instance:
208
+ continue
209
+ try:
210
+ obj.script_instance.on_start()
211
+ except Exception as e:
212
+ print(T.tr('api.script_start_error', 'Script on_start error for {}: {}').format(obj.name, e), file=sys.stderr)
213
+
214
+ def _update_script(self, obj):
215
+ """Fire on_update(delta_time) on an object's attached script (per frame)."""
216
+ if not obj.script_instance:
217
+ return
218
+ try:
219
+ obj.script_instance.on_update(self._delta_time)
220
+ except Exception as e:
221
+ print(T.tr('api.script_update_error', 'Script on_update error for {}: {}').format(obj.name, e), file=sys.stderr)
222
+
223
+ def _destroy_scripts(self):
224
+ """Fire on_destroy() on every attached script (before the scene is replaced)."""
225
+ for obj in self._iter_objects():
226
+ if not obj.script_instance:
227
+ continue
228
+ try:
229
+ obj.script_instance.on_destroy()
230
+ except Exception as e:
231
+ print(T.tr('api.script_destroy_error', 'Script on_destroy error for {}: {}').format(obj.name, e), file=sys.stderr)
232
+
233
+ def _iter_objects(self):
234
+ """Yield every object in the current scene tree (depth-first)."""
235
+ def _gen(object_tree_struct):
236
+ value = list(object_tree_struct.values())[0]
237
+ yield value['object']
238
+ for child_object_tree_struct in value['children']:
239
+ yield from _gen(child_object_tree_struct)
240
+
241
+ if self._all_object_tree_struct:
242
+ yield from _gen(self._all_object_tree_struct)
243
+
127
244
  def _get_object_tree_struct_by_path(self, object_path):
128
245
  def _get(name, target_item_index, current_item_index, recursion_time, part_number, object_tree_struct):
129
246
  key = list(object_tree_struct.keys())[0]
@@ -9,7 +9,7 @@
9
9
  "warning_title": "Warning",
10
10
  "warning_scene_save_content": "The current scene data has been modified. Do you want to save it?",
11
11
  "quesiton_title": "Confirm",
12
- "question_delete_asset_item_content": "Sure to delete {} item(s)? This cannot be undone.\n{}",
12
+ "question_delete_asset_item_content": "Sure to delete {} item(s)?\n{}",
13
13
  "question_delete_hierarchy_item_content": "Sure to delete the selected item(s)?",
14
14
  "question_delete_project_content": "Sure to delete the project?",
15
15
  "question_overwrite_content": "Sure to overwrite the following duplicate resources?\n{}",
@@ -27,6 +27,7 @@
27
27
  "critical_open_project": "Failed to open the project. Couldn't find project.pygs.",
28
28
  "critical_find_project": "Couldn't find the project.",
29
29
  "critical_delete_project": "Couldn't delete the project: {}",
30
+ "critical_move_to_trash": "Failed to move the project to the recycle bin.",
30
31
  "critical_main_not_found": "main.py is not found. Please make sure main.py is in the project root directory.",
31
32
  "critical_app_icon_not_exist": "App icon not exist",
32
33
  "critical_no_output_dir": "Please choose the output dir",
@@ -116,7 +117,8 @@
116
117
  "scene": "Scene",
117
118
  "scene_saved": "Scene saved",
118
119
  "run_project": "Run Project {}",
119
- "failed_to_run_project": "Failed to Run Project {}: {}"
120
+ "failed_to_run_project": "Failed to Run Project {}: {}",
121
+ "run_project_finished": "Project {} exited with code {}"
120
122
  },
121
123
 
122
124
  "hierarchy": {
@@ -156,6 +158,8 @@
156
158
  "image_path": "Image Path",
157
159
  "select_image": "Select Image",
158
160
  "font_path": "Font Path",
161
+ "script_path": "Script Path",
162
+ "select_script": "Select Script",
159
163
  "format": "Format"
160
164
  },
161
165
 
@@ -219,6 +223,19 @@
219
223
 
220
224
  "api": {
221
225
  "no_scene_path": "The scene path {} does not exist.",
226
+ "no_script_path": "The script path {} does not exist.",
227
+ "fail_to_load_script": "Failed to load script {}: {}",
228
+ "no_script_class": "No script class found in {}.",
229
+ "fail_to_init_script": "Failed to initialize script {}: {}",
230
+ "unknown_object_type": "Unknown object type: {}",
231
+ "script_start_error": "Script on_start error for {}: {}",
232
+ "script_update_error": "Script on_update error for {}: {}",
233
+ "script_destroy_error": "Script on_destroy error for {}: {}",
234
+ "fail_to_init_mixer": "Failed to initialize audio mixer: {}",
235
+ "no_sound_path": "The sound path {} does not exist.",
236
+ "fail_to_load_sound": "Failed to load sound {}: {}",
237
+ "fail_to_play_sound": "Failed to play sound {}: {}",
238
+ "fail_to_play_music": "Failed to play music {}: {}",
222
239
  "no_project_pygs": "Failed to find config file project.pygs in the project root directory.",
223
240
  "fail_to_load_project_pygs": "Failed to load config file project.pygs: {}"
224
241
  },
@@ -9,7 +9,7 @@
9
9
  "warning_title": "警告",
10
10
  "warning_scene_save_content": "当前场景数据已被修改,是否保存?",
11
11
  "quesiton_title": "确认",
12
- "question_delete_asset_item_content": "是否删除这{}项?此操作无法撤销。\n{}",
12
+ "question_delete_asset_item_content": "是否删除这{}项?\n{}",
13
13
  "question_delete_hierarchy_item_content": "是否删除选中的对象?",
14
14
  "question_delete_project_content": "是否删除该项目?",
15
15
  "question_overwrite_content": "是否覆盖以下重复资源?\n{}",
@@ -27,6 +27,7 @@
27
27
  "critical_open_project": "打开项目失败,找不到project.pygs。",
28
28
  "critical_find_project": "找不到该项目。",
29
29
  "critical_delete_project": "无法删除项目:{}",
30
+ "critical_move_to_trash": "无法将项目移入回收站。",
30
31
  "critical_app_icon_not_exist": "图标文件不存在",
31
32
  "critical_no_output_dir": "请选择输出目录",
32
33
  "critical_output_dir_not_exist": "输出目录不存在",
@@ -116,7 +117,8 @@
116
117
  "scene": "场景编辑器",
117
118
  "scene_saved": "场景已保存",
118
119
  "run_project": "运行项目{}",
119
- "failed_to_run_project": "项目{}运行失败:{}"
120
+ "failed_to_run_project": "项目{}运行失败:{}",
121
+ "run_project_finished": "项目{}已退出,退出码:{}"
120
122
  },
121
123
 
122
124
  "hierarchy": {
@@ -155,7 +157,9 @@
155
157
  "select_color": "选择颜色",
156
158
  "image_path": "图片路径",
157
159
  "font_path": "字体路径",
160
+ "script_path": "脚本路径",
158
161
  "select_image": "选择图片",
162
+ "select_script": "选择脚本",
159
163
  "format": "格式"
160
164
  },
161
165
 
@@ -219,7 +223,20 @@
219
223
 
220
224
  "api": {
221
225
  "no_scene_path": "场景路径{}不存在。",
222
- "no_project_pygs": "没有在项目根目录下找到project.pygs配置文件",
226
+ "no_script_path": "脚本路径{}不存在。",
227
+ "fail_to_load_script": "脚本{}加载失败:{}",
228
+ "no_script_class": "在{}中没有找到脚本类。",
229
+ "fail_to_init_script": "脚本{}初始化失败:{}",
230
+ "unknown_object_type": "未知对象类型:{}",
231
+ "script_start_error": "脚本{}的on_start错误:{}",
232
+ "script_update_error": "脚本{}的on_update错误:{}",
233
+ "script_destroy_error": "脚本{}的on_destroy错误:{}",
234
+ "fail_to_init_mixer": "音频混音器初始化失败:{}",
235
+ "no_sound_path": "音频路径{}不存在。",
236
+ "fail_to_load_sound": "音频{}加载失败:{}",
237
+ "fail_to_play_sound": "音频{}播放失败:{}",
238
+ "fail_to_play_music": "音乐{}播放失败:{}",
239
+ "no_project_pygs": "没有在项目根目录下找到project.pygs配置文件。",
223
240
  "fail_to_load_project_pygs": "配置文件project.pygs加载失败:{}"
224
241
  },
225
242