@fps-games/editor 0.1.4-beta.4 → 0.1.5-beta.1

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 (288) hide show
  1. package/dist/build-info.json +45 -0
  2. package/dist/local-editor-harness.d.ts +25 -5
  3. package/dist/local-editor-harness.d.ts.map +1 -1
  4. package/dist/local-editor-harness.js +518 -90
  5. package/dist/local-editor-harness.js.map +1 -1
  6. package/dist/local-editor-performance-stats.d.ts +12 -0
  7. package/dist/local-editor-performance-stats.d.ts.map +1 -0
  8. package/dist/local-editor-performance-stats.js +46 -0
  9. package/dist/local-editor-performance-stats.js.map +1 -0
  10. package/dist/playable-babylon-facade.d.ts +4 -4
  11. package/dist/playable-babylon-facade.d.ts.map +1 -1
  12. package/dist/playable-babylon-facade.js +2 -2
  13. package/dist/playable-babylon-facade.js.map +1 -1
  14. package/dist/playable-babylon-rendering.d.ts +66 -9
  15. package/dist/playable-babylon-rendering.d.ts.map +1 -1
  16. package/dist/playable-babylon-rendering.js +567 -13
  17. package/dist/playable-babylon-rendering.js.map +1 -1
  18. package/dist/playable-local-editor-host.d.ts +12 -9
  19. package/dist/playable-local-editor-host.d.ts.map +1 -1
  20. package/dist/playable-local-editor-host.js.map +1 -1
  21. package/dist/playable-sdk-vite.d.ts +2 -0
  22. package/dist/playable-sdk-vite.d.ts.map +1 -0
  23. package/dist/playable-sdk-vite.js +2 -0
  24. package/dist/playable-sdk-vite.js.map +1 -0
  25. package/dist/playable-sdk.d.ts +6 -4
  26. package/dist/playable-sdk.d.ts.map +1 -1
  27. package/dist/playable-sdk.js +3 -2
  28. package/dist/playable-sdk.js.map +1 -1
  29. package/dist/static-shadow-cpu-worker.d.ts +7 -0
  30. package/dist/static-shadow-cpu-worker.d.ts.map +1 -0
  31. package/dist/static-shadow-cpu-worker.js +221 -0
  32. package/dist/static-shadow-cpu-worker.js.map +1 -0
  33. package/node_modules/@fps-games/babylon-renderer/dist/index.d.ts +5 -0
  34. package/node_modules/@fps-games/babylon-renderer/dist/index.d.ts.map +1 -1
  35. package/node_modules/@fps-games/babylon-renderer/dist/index.js +5 -0
  36. package/node_modules/@fps-games/babylon-renderer/dist/index.js.map +1 -1
  37. package/node_modules/@fps-games/babylon-renderer/dist/shadows/blob-shadow-shaders.d.ts +5 -0
  38. package/node_modules/@fps-games/babylon-renderer/dist/shadows/blob-shadow-shaders.d.ts.map +1 -0
  39. package/node_modules/@fps-games/babylon-renderer/dist/shadows/blob-shadow-shaders.js +46 -0
  40. package/node_modules/@fps-games/babylon-renderer/dist/shadows/blob-shadow-shaders.js.map +1 -0
  41. package/node_modules/@fps-games/babylon-renderer/dist/shadows/blob-shadow-system.d.ts +5 -0
  42. package/node_modules/@fps-games/babylon-renderer/dist/shadows/blob-shadow-system.d.ts.map +1 -0
  43. package/node_modules/@fps-games/babylon-renderer/dist/shadows/blob-shadow-system.js +398 -0
  44. package/node_modules/@fps-games/babylon-renderer/dist/shadows/blob-shadow-system.js.map +1 -0
  45. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.d.ts +4 -0
  46. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.d.ts.map +1 -0
  47. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.js +584 -0
  48. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-artifact-system.js.map +1 -0
  49. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-atlas.d.ts +61 -0
  50. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-atlas.d.ts.map +1 -0
  51. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-atlas.js +382 -0
  52. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-atlas.js.map +1 -0
  53. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-bake.d.ts +47 -0
  54. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-bake.d.ts.map +1 -0
  55. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-bake.js +285 -0
  56. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-bake.js.map +1 -0
  57. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.d.ts +88 -0
  58. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.d.ts.map +1 -0
  59. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.js +813 -0
  60. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-baker.js.map +1 -0
  61. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-rendering.d.ts +27 -0
  62. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-rendering.d.ts.map +1 -0
  63. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-rendering.js +220 -0
  64. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-rendering.js.map +1 -0
  65. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-system.d.ts +38 -0
  66. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-system.d.ts.map +1 -0
  67. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-system.js +173 -0
  68. package/node_modules/@fps-games/babylon-renderer/dist/shadows/static-projected-shadow-system.js.map +1 -0
  69. package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.d.ts +286 -0
  70. package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.d.ts.map +1 -1
  71. package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.js +82 -0
  72. package/node_modules/@fps-games/babylon-renderer/dist/shadows/types.js.map +1 -1
  73. package/node_modules/@fps-games/babylon-renderer/package.json +1 -1
  74. package/node_modules/@fps-games/editor-babylon/dist/index.d.ts +3 -0
  75. package/node_modules/@fps-games/editor-babylon/dist/index.d.ts.map +1 -1
  76. package/node_modules/@fps-games/editor-babylon/dist/index.js +3 -0
  77. package/node_modules/@fps-games/editor-babylon/dist/index.js.map +1 -1
  78. package/node_modules/@fps-games/editor-babylon/dist/performance-monitor.d.ts +34 -0
  79. package/node_modules/@fps-games/editor-babylon/dist/performance-monitor.d.ts.map +1 -0
  80. package/node_modules/@fps-games/editor-babylon/dist/performance-monitor.js +272 -0
  81. package/node_modules/@fps-games/editor-babylon/dist/performance-monitor.js.map +1 -0
  82. package/node_modules/@fps-games/editor-babylon/dist/projection-asset-container-importer.d.ts +49 -0
  83. package/node_modules/@fps-games/editor-babylon/dist/projection-asset-container-importer.d.ts.map +1 -0
  84. package/node_modules/@fps-games/editor-babylon/dist/projection-asset-container-importer.js +141 -0
  85. package/node_modules/@fps-games/editor-babylon/dist/projection-asset-container-importer.js.map +1 -0
  86. package/node_modules/@fps-games/editor-babylon/dist/projection.d.ts +11 -0
  87. package/node_modules/@fps-games/editor-babylon/dist/projection.d.ts.map +1 -1
  88. package/node_modules/@fps-games/editor-babylon/dist/projection.js +137 -6
  89. package/node_modules/@fps-games/editor-babylon/dist/projection.js.map +1 -1
  90. package/node_modules/@fps-games/editor-babylon/dist/rendering.d.ts +19 -0
  91. package/node_modules/@fps-games/editor-babylon/dist/rendering.d.ts.map +1 -0
  92. package/node_modules/@fps-games/editor-babylon/dist/rendering.js +66 -0
  93. package/node_modules/@fps-games/editor-babylon/dist/rendering.js.map +1 -0
  94. package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.d.ts +17 -3
  95. package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.d.ts.map +1 -1
  96. package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.js +256 -8
  97. package/node_modules/@fps-games/editor-babylon/dist/shadow-preview-controller.js.map +1 -1
  98. package/node_modules/@fps-games/editor-babylon/dist/transform-gizmo-controller.d.ts.map +1 -1
  99. package/node_modules/@fps-games/editor-babylon/dist/transform-gizmo-controller.js +19 -2
  100. package/node_modules/@fps-games/editor-babylon/dist/transform-gizmo-controller.js.map +1 -1
  101. package/node_modules/@fps-games/editor-babylon/package.json +5 -5
  102. package/node_modules/@fps-games/editor-browser/dist/index.d.ts +1 -1
  103. package/node_modules/@fps-games/editor-browser/dist/index.d.ts.map +1 -1
  104. package/node_modules/@fps-games/editor-browser/dist/index.js.map +1 -1
  105. package/node_modules/@fps-games/editor-browser/dist/local-editor-rendering-actions.d.ts +8 -0
  106. package/node_modules/@fps-games/editor-browser/dist/local-editor-rendering-actions.d.ts.map +1 -0
  107. package/node_modules/@fps-games/editor-browser/dist/local-editor-rendering-actions.js +14 -0
  108. package/node_modules/@fps-games/editor-browser/dist/local-editor-rendering-actions.js.map +1 -0
  109. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.d.ts.map +1 -1
  110. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.js +10 -2
  111. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.js.map +1 -1
  112. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.d.ts +1 -1
  113. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.d.ts.map +1 -1
  114. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.js +17 -0
  115. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.js.map +1 -1
  116. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.d.ts.map +1 -1
  117. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.js +494 -43
  118. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.js.map +1 -1
  119. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts +72 -5
  120. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts.map +1 -1
  121. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts +1 -1
  122. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts.map +1 -1
  123. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js +595 -5
  124. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js.map +1 -1
  125. package/node_modules/@fps-games/editor-browser/package.json +3 -3
  126. package/node_modules/@fps-games/editor-core/dist/editor-session.d.ts +14 -1
  127. package/node_modules/@fps-games/editor-core/dist/editor-session.d.ts.map +1 -1
  128. package/node_modules/@fps-games/editor-core/dist/editor-session.js +34 -10
  129. package/node_modules/@fps-games/editor-core/dist/editor-session.js.map +1 -1
  130. package/node_modules/@fps-games/editor-core/dist/inspector.d.ts +2 -1
  131. package/node_modules/@fps-games/editor-core/dist/inspector.d.ts.map +1 -1
  132. package/node_modules/@fps-games/editor-core/dist/inspector.js +11 -1
  133. package/node_modules/@fps-games/editor-core/dist/inspector.js.map +1 -1
  134. package/node_modules/@fps-games/editor-core/dist/serialized-object.d.ts +7 -0
  135. package/node_modules/@fps-games/editor-core/dist/serialized-object.d.ts.map +1 -1
  136. package/node_modules/@fps-games/editor-core/dist/serialized-object.js +1 -0
  137. package/node_modules/@fps-games/editor-core/dist/serialized-object.js.map +1 -1
  138. package/node_modules/@fps-games/editor-core/package.json +2 -2
  139. package/node_modules/@fps-games/editor-forge-play/package.json +2 -2
  140. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.d.ts.map +1 -1
  141. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.js +10 -5
  142. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.js.map +1 -1
  143. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/placement.d.ts.map +1 -1
  144. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/placement.js +3 -1
  145. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/placement.js.map +1 -1
  146. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.d.ts +4 -1
  147. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.d.ts.map +1 -1
  148. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.js +29 -0
  149. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.js.map +1 -1
  150. package/node_modules/@fps-games/editor-playable-sdk/dist/document/types.d.ts +12 -0
  151. package/node_modules/@fps-games/editor-playable-sdk/dist/document/types.d.ts.map +1 -1
  152. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/index.d.ts +1 -1
  153. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/index.d.ts.map +1 -1
  154. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/index.js +1 -1
  155. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/index.js.map +1 -1
  156. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.d.ts.map +1 -1
  157. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.js +5 -1
  158. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.js.map +1 -1
  159. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/validators.d.ts +1 -0
  160. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/validators.d.ts.map +1 -1
  161. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/validators.js +8 -0
  162. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/validators.js.map +1 -1
  163. package/node_modules/@fps-games/editor-playable-sdk/dist/index.d.ts +1 -0
  164. package/node_modules/@fps-games/editor-playable-sdk/dist/index.d.ts.map +1 -1
  165. package/node_modules/@fps-games/editor-playable-sdk/dist/index.js +1 -0
  166. package/node_modules/@fps-games/editor-playable-sdk/dist/index.js.map +1 -1
  167. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.d.ts +34 -2
  168. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.d.ts.map +1 -1
  169. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.js +272 -0
  170. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/document-sections.js.map +1 -1
  171. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.d.ts +1 -1
  172. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.d.ts.map +1 -1
  173. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.js +1 -1
  174. package/node_modules/@fps-games/editor-playable-sdk/dist/inspector/index.js.map +1 -1
  175. package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/forge-play.d.ts.map +1 -1
  176. package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/forge-play.js +0 -4
  177. package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/forge-play.js.map +1 -1
  178. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.d.ts +12 -1
  179. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.d.ts.map +1 -1
  180. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.js +161 -1
  181. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.js.map +1 -1
  182. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/index.d.ts +4 -2
  183. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/index.d.ts.map +1 -1
  184. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/index.js +2 -1
  185. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/index.js.map +1 -1
  186. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/reducer.d.ts.map +1 -1
  187. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/reducer.js +4 -1
  188. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/reducer.js.map +1 -1
  189. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/rendering-alpha-index.d.ts +19 -0
  190. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/rendering-alpha-index.d.ts.map +1 -0
  191. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/rendering-alpha-index.js +57 -0
  192. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/rendering-alpha-index.js.map +1 -0
  193. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/types.d.ts +7 -1
  194. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/types.d.ts.map +1 -1
  195. package/node_modules/@fps-games/editor-playable-sdk/dist/package-resolution/aliases.d.ts +1 -1
  196. package/node_modules/@fps-games/editor-playable-sdk/dist/package-resolution/aliases.d.ts.map +1 -1
  197. package/node_modules/@fps-games/editor-playable-sdk/dist/package-resolution/aliases.js +5 -0
  198. package/node_modules/@fps-games/editor-playable-sdk/dist/package-resolution/aliases.js.map +1 -1
  199. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/panel.d.ts.map +1 -1
  200. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/panel.js +1003 -7
  201. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/panel.js.map +1 -1
  202. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/profile.d.ts +12 -3
  203. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/profile.d.ts.map +1 -1
  204. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/profile.js +521 -6
  205. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/profile.js.map +1 -1
  206. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/types.d.ts +217 -3
  207. package/node_modules/@fps-games/editor-playable-sdk/dist/rendering-profile/types.d.ts.map +1 -1
  208. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.d.ts.map +1 -1
  209. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.js +26 -0
  210. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.js.map +1 -1
  211. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/types.d.ts +3 -1
  212. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/types.d.ts.map +1 -1
  213. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/client.d.ts.map +1 -1
  214. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/client.js +4 -0
  215. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/client.js.map +1 -1
  216. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/companion-configs.d.ts +9 -1
  217. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/companion-configs.d.ts.map +1 -1
  218. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/companion-configs.js +12 -1
  219. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/companion-configs.js.map +1 -1
  220. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/types.d.ts +2 -0
  221. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/types.d.ts.map +1 -1
  222. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.d.ts +1 -0
  223. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.d.ts.map +1 -1
  224. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.js +75 -0
  225. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.js.map +1 -1
  226. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/index.d.ts +1 -0
  227. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/index.d.ts.map +1 -1
  228. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/index.js +1 -0
  229. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/index.js.map +1 -1
  230. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.d.ts +17 -0
  231. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.d.ts.map +1 -0
  232. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.js +262 -0
  233. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.js.map +1 -0
  234. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/object.d.ts.map +1 -1
  235. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/object.js +7 -3
  236. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/object.js.map +1 -1
  237. package/node_modules/@fps-games/editor-playable-sdk/dist/session/identity.d.ts +6 -0
  238. package/node_modules/@fps-games/editor-playable-sdk/dist/session/identity.d.ts.map +1 -1
  239. package/node_modules/@fps-games/editor-playable-sdk/dist/session/identity.js +31 -0
  240. package/node_modules/@fps-games/editor-playable-sdk/dist/session/identity.js.map +1 -1
  241. package/node_modules/@fps-games/editor-playable-sdk/dist/session/index.d.ts +2 -1
  242. package/node_modules/@fps-games/editor-playable-sdk/dist/session/index.d.ts.map +1 -1
  243. package/node_modules/@fps-games/editor-playable-sdk/dist/session/index.js +1 -1
  244. package/node_modules/@fps-games/editor-playable-sdk/dist/session/index.js.map +1 -1
  245. package/node_modules/@fps-games/editor-playable-sdk/dist/session/patches.d.ts.map +1 -1
  246. package/node_modules/@fps-games/editor-playable-sdk/dist/session/patches.js +21 -9
  247. package/node_modules/@fps-games/editor-playable-sdk/dist/session/patches.js.map +1 -1
  248. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.d.ts +151 -0
  249. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.d.ts.map +1 -0
  250. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.js +445 -0
  251. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/artifact.js.map +1 -0
  252. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/index.d.ts +2 -0
  253. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/index.d.ts.map +1 -0
  254. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/index.js +2 -0
  255. package/node_modules/@fps-games/editor-playable-sdk/dist/static-shadows/index.js.map +1 -0
  256. package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/index.d.ts +1 -1
  257. package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/index.d.ts.map +1 -1
  258. package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/index.js +1 -1
  259. package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/index.js.map +1 -1
  260. package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/inspectors.d.ts +2 -1
  261. package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/inspectors.d.ts.map +1 -1
  262. package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/inspectors.js +37 -0
  263. package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/inspectors.js.map +1 -1
  264. package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/types.d.ts +15 -0
  265. package/node_modules/@fps-games/editor-playable-sdk/dist/upgrade-doctor/types.d.ts.map +1 -1
  266. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/build-info-core.d.ts +36 -0
  267. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/build-info-core.d.ts.map +1 -0
  268. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/build-info-core.js +65 -0
  269. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/build-info-core.js.map +1 -0
  270. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/build-info-node.d.ts +4 -0
  271. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/build-info-node.d.ts.map +1 -0
  272. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/build-info-node.js +87 -0
  273. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/build-info-node.js.map +1 -0
  274. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/index.d.ts +5 -0
  275. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/index.d.ts.map +1 -0
  276. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/index.js +5 -0
  277. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/index.js.map +1 -0
  278. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/plugin.d.ts +8 -0
  279. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/plugin.d.ts.map +1 -0
  280. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/plugin.js +226 -0
  281. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/plugin.js.map +1 -0
  282. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/types.d.ts +64 -0
  283. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/types.d.ts.map +1 -0
  284. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/types.js +2 -0
  285. package/node_modules/@fps-games/editor-playable-sdk/dist/vite/types.js.map +1 -0
  286. package/node_modules/@fps-games/editor-playable-sdk/package.json +7 -3
  287. package/node_modules/@fps-games/editor-protocol/package.json +1 -1
  288. package/package.json +12 -8
@@ -1,9 +1,35 @@
1
+ const SHADOW_RENDERING_GROUP_BLOB = {
2
+ id: 'shadow-group-moving-object',
3
+ label: 'Moving Object Shadows',
4
+ summary: 'Blob: lightweight for moving objects and project-default fallback.',
5
+ };
6
+ const SHADOW_RENDERING_GROUP_STATIC = {
7
+ id: 'shadow-group-static-scene',
8
+ label: 'Static Scene Shadows',
9
+ summary: 'Consumes baked artifacts; update during authoring/build, runtime only displays results.',
10
+ };
11
+ const SHADOW_RENDERING_GROUP_PLANAR = {
12
+ id: 'shadow-group-directional-planar',
13
+ label: 'Directional Planar Shadows',
14
+ summary: 'Real-time planar projection following the directional light.',
15
+ };
16
+ const SHADOW_RENDERING_GROUP_COMPAT = {
17
+ id: 'shadow-group-compatibility',
18
+ label: 'Compatibility Shadows',
19
+ summary: 'Legacy ShadowGenerator / CSM read-only compatibility paths.',
20
+ };
1
21
  export function createEditorSceneRenderingPanelState(profile, state = {}, options = {}) {
22
+ const blob = profile.shadows.blob;
23
+ const staticProjected = profile.shadows.staticProjected;
2
24
  const planar = profile.shadows.planar;
3
25
  const environment = profile.environment;
4
26
  const postProcess = profile.postProcess;
5
27
  const dirty = state.dirty === true;
6
28
  const lastError = state.lastError ?? null;
29
+ const language = options.language ?? 'en';
30
+ const staticShadowBake = resolveStaticShadowBakeLifecycleState(state.staticShadowBake, staticProjected.enabled);
31
+ const staticShadowStatus = formatStaticShadowBakeLifecycleStatus(staticShadowBake, language);
32
+ const staticShadowBakeInProgress = staticShadowBake.status === 'baking';
7
33
  const panel = {
8
34
  title: 'Rendering',
9
35
  summary: 'Project-level rendering settings shared by editor preview and runtime.',
@@ -19,7 +45,7 @@ export function createEditorSceneRenderingPanelState(profile, state = {}, option
19
45
  ? 'Revert rendering settings to the last saved rendering settings.'
20
46
  : 'Rendering settings already match the last saved rendering settings.',
21
47
  }],
22
- sections: [{
48
+ sections: [createRenderingGroupsSection(profile.renderingGroups.slots), {
23
49
  id: 'environment',
24
50
  title: 'Environment / IBL',
25
51
  summary: 'World environment texture and reflection lighting shared by editor preview and runtime.',
@@ -220,11 +246,300 @@ export function createEditorSceneRenderingPanelState(profile, state = {}, option
220
246
  id: 'shadows',
221
247
  title: 'Shadows',
222
248
  summary: 'Global shadow systems for editor preview and runtime.',
249
+ layout: 'list',
250
+ systemsCollapsible: true,
223
251
  systems: [
252
+ {
253
+ id: 'blob-shadow',
254
+ label: 'Blob Shadow',
255
+ kind: 'blob-shadow',
256
+ group: { ...SHADOW_RENDERING_GROUP_BLOB },
257
+ active: blob.enabled,
258
+ summary: 'Default object shadow',
259
+ properties: [
260
+ {
261
+ path: 'shadows.defaultMode',
262
+ label: 'Default Mode',
263
+ valueType: 'enum',
264
+ control: 'enum',
265
+ value: profile.shadows.defaultMode,
266
+ options: createShadowDefaultModeOptions(options.language ?? 'en'),
267
+ tooltip: 'Default shadow mode for GameObjects that use the project default.',
268
+ commitMode: 'immediate',
269
+ },
270
+ {
271
+ path: 'shadows.blob.enabled',
272
+ label: 'Enabled',
273
+ valueType: 'boolean',
274
+ control: 'boolean',
275
+ value: blob.enabled,
276
+ tooltip: 'Enable the shared blob shadow system.',
277
+ commitMode: 'immediate',
278
+ },
279
+ {
280
+ path: 'shadows.blob.appearance.color',
281
+ label: 'Color',
282
+ valueType: 'color',
283
+ control: 'color',
284
+ value: blob.appearance.color,
285
+ tooltip: 'Blob shadow RGB color. Opacity is edited separately.',
286
+ commitMode: 'immediate',
287
+ },
288
+ {
289
+ path: 'shadows.blob.appearance.color.a',
290
+ label: 'Opacity',
291
+ valueType: 'number',
292
+ control: 'number',
293
+ value: blob.appearance.color.a,
294
+ min: 0,
295
+ max: 1,
296
+ step: 0.01,
297
+ tooltip: 'Blob shadow opacity, clamped between 0 and 1.',
298
+ commitMode: 'live',
299
+ },
300
+ {
301
+ path: 'shadows.blob.appearance.edgeSoftness',
302
+ label: 'Soft Edge',
303
+ valueType: 'number',
304
+ control: 'number',
305
+ value: blob.appearance.edgeSoftness,
306
+ min: 0,
307
+ max: 0.98,
308
+ step: 0.01,
309
+ tooltip: 'Blob shadow soft edge start. Higher values keep the center denser before fading out.',
310
+ commitMode: 'live',
311
+ },
312
+ {
313
+ path: 'shadows.blob.plane.height',
314
+ label: 'Height',
315
+ valueType: 'number',
316
+ control: 'number',
317
+ value: blob.plane.height,
318
+ step: 0.01,
319
+ unit: 'm',
320
+ tooltip: 'Ground plane height used by blob shadows.',
321
+ commitMode: 'live',
322
+ },
323
+ {
324
+ path: 'shadows.blob.plane.yOffset',
325
+ label: 'Y Offset',
326
+ valueType: 'number',
327
+ control: 'number',
328
+ value: blob.plane.yOffset,
329
+ min: 0,
330
+ step: 0.01,
331
+ unit: 'm',
332
+ tooltip: 'Vertical offset above the blob shadow plane to reduce z-fighting.',
333
+ commitMode: 'live',
334
+ },
335
+ {
336
+ path: 'shadows.blob.size.sizeMultiplier',
337
+ label: 'Size Multiplier',
338
+ valueType: 'number',
339
+ control: 'number',
340
+ value: blob.size.sizeMultiplier,
341
+ min: 0,
342
+ step: 0.01,
343
+ tooltip: 'Scale blob shadow size from each caster bounds.',
344
+ commitMode: 'live',
345
+ },
346
+ {
347
+ path: 'shadows.blob.size.minSize',
348
+ label: 'Min Size',
349
+ valueType: 'number',
350
+ control: 'number',
351
+ value: blob.size.minSize,
352
+ min: 0,
353
+ step: 0.01,
354
+ unit: 'm',
355
+ tooltip: 'Minimum blob shadow size for tiny objects.',
356
+ commitMode: 'live',
357
+ },
358
+ {
359
+ path: 'shadows.blob.size.maxSize',
360
+ label: 'Max Size',
361
+ valueType: 'number',
362
+ control: 'number',
363
+ value: blob.size.maxSize,
364
+ min: 0.01,
365
+ step: 0.01,
366
+ unit: 'm',
367
+ tooltip: 'Maximum blob shadow size for large objects.',
368
+ commitMode: 'live',
369
+ },
370
+ ],
371
+ },
372
+ {
373
+ id: 'static-projected-shadow',
374
+ label: 'Static Baked Shadow',
375
+ kind: 'static-projected-shadow',
376
+ group: { ...SHADOW_RENDERING_GROUP_STATIC },
377
+ active: staticProjected.enabled,
378
+ summary: staticShadowStatus.summary,
379
+ status: staticShadowStatus.status,
380
+ details: createStaticShadowBakeDetails(staticShadowBake, language),
381
+ progress: staticShadowStatus.progress,
382
+ actions: [{
383
+ id: 'bake-static-shadows',
384
+ label: 'Bake Static Shadows',
385
+ icon: 'save',
386
+ disabled: !staticProjected.enabled || staticShadowBakeInProgress,
387
+ tooltip: staticShadowBakeInProgress
388
+ ? 'Static shadow bake is already running.'
389
+ : staticProjected.enabled
390
+ ? 'Bake static shadow chunks for objects authored as Static Baked Shadow.'
391
+ : 'Enable Static Baked Shadow before baking.',
392
+ }],
393
+ properties: [
394
+ {
395
+ path: 'shadows.staticProjected.enabled',
396
+ label: 'Enabled',
397
+ valueType: 'boolean',
398
+ control: 'boolean',
399
+ value: staticProjected.enabled,
400
+ tooltip: 'Enable the shared static projected shadow system.',
401
+ commitMode: 'immediate',
402
+ },
403
+ {
404
+ path: 'shadows.staticProjected.appearance.color',
405
+ label: 'Color',
406
+ valueType: 'color',
407
+ control: 'color',
408
+ value: staticProjected.appearance.color,
409
+ tooltip: 'Static shadow RGB color. Opacity is edited separately.',
410
+ commitMode: 'immediate',
411
+ },
412
+ {
413
+ path: 'shadows.staticProjected.appearance.color.a',
414
+ label: 'Opacity',
415
+ valueType: 'number',
416
+ control: 'number',
417
+ value: staticProjected.appearance.color.a,
418
+ min: 0,
419
+ max: 1,
420
+ step: 0.01,
421
+ tooltip: 'Static shadow opacity, clamped between 0 and 1.',
422
+ commitMode: 'live',
423
+ },
424
+ {
425
+ path: 'shadows.staticProjected.plane.height',
426
+ label: 'Height',
427
+ valueType: 'number',
428
+ control: 'number',
429
+ value: staticProjected.plane.height,
430
+ step: 0.01,
431
+ unit: 'm',
432
+ tooltip: 'Ground plane height used by static projected shadows.',
433
+ commitMode: 'live',
434
+ },
435
+ {
436
+ path: 'shadows.staticProjected.plane.yOffset',
437
+ label: 'Y Offset',
438
+ valueType: 'number',
439
+ control: 'number',
440
+ value: staticProjected.plane.yOffset,
441
+ min: 0,
442
+ step: 0.01,
443
+ unit: 'm',
444
+ tooltip: 'Vertical offset above the static shadow plane to reduce z-fighting.',
445
+ commitMode: 'live',
446
+ },
447
+ {
448
+ path: 'shadows.staticProjected.bake.texelsPerMeter',
449
+ label: 'Texels per Meter',
450
+ valueType: 'number',
451
+ control: 'number',
452
+ value: staticProjected.bake.texelsPerMeter,
453
+ min: 1,
454
+ step: 1,
455
+ tooltip: 'Target SDF atlas texel density for baked static shadows.',
456
+ commitMode: 'blur',
457
+ },
458
+ {
459
+ path: 'shadows.staticProjected.bake.atlasSize',
460
+ label: 'Atlas Size',
461
+ valueType: 'number',
462
+ control: 'number',
463
+ value: staticProjected.bake.atlasSize,
464
+ min: 16,
465
+ step: 1,
466
+ tooltip: 'Maximum width and height for each static shadow atlas page.',
467
+ commitMode: 'blur',
468
+ },
469
+ {
470
+ path: 'shadows.staticProjected.bake.maxAtlasPages',
471
+ label: 'Page Budget',
472
+ valueType: 'number',
473
+ control: 'number',
474
+ value: staticProjected.bake.maxAtlasPages,
475
+ min: 1,
476
+ step: 1,
477
+ tooltip: 'Maximum atlas pages allowed before bake lowers the effective texel density.',
478
+ commitMode: 'blur',
479
+ },
480
+ {
481
+ path: 'shadows.staticProjected.bake.sdfRadiusPx',
482
+ label: 'SDF Radius',
483
+ valueType: 'number',
484
+ control: 'number',
485
+ value: staticProjected.bake.sdfRadiusPx,
486
+ min: 0,
487
+ step: 1,
488
+ tooltip: 'Signed-distance radius in pixels used to preserve crisp controllable edges.',
489
+ commitMode: 'blur',
490
+ },
491
+ {
492
+ path: 'shadows.staticProjected.bake.padding',
493
+ label: 'Padding',
494
+ valueType: 'number',
495
+ control: 'number',
496
+ value: staticProjected.bake.padding,
497
+ min: 0,
498
+ step: 0.01,
499
+ tooltip: 'Extra projected bounds padding before baking the static shadow.',
500
+ commitMode: 'live',
501
+ },
502
+ {
503
+ path: 'shadows.staticProjected.bake.blur',
504
+ label: 'Blur',
505
+ valueType: 'number',
506
+ control: 'number',
507
+ value: staticProjected.bake.blur,
508
+ min: 0,
509
+ step: 0.5,
510
+ tooltip: 'Reserved blur radius for static shadow bake softness.',
511
+ commitMode: 'live',
512
+ },
513
+ {
514
+ path: 'shadows.staticProjected.bake.spatialChunkSize',
515
+ label: 'Spatial Chunk Size',
516
+ valueType: 'number',
517
+ control: 'number',
518
+ value: staticProjected.bake.spatialChunkSize,
519
+ min: 0.01,
520
+ step: 0.01,
521
+ unit: 'm',
522
+ tooltip: 'World size of each spatial bake chunk before atlas packing.',
523
+ commitMode: 'live',
524
+ },
525
+ {
526
+ path: 'shadows.staticProjected.bake.targetChunkCount',
527
+ label: 'Target Chunks',
528
+ valueType: 'number',
529
+ control: 'number',
530
+ value: staticProjected.bake.targetChunkCount,
531
+ min: 1,
532
+ step: 1,
533
+ tooltip: 'Soft chunk-count budget. Large scenes automatically enlarge spatial chunks to stay near this target.',
534
+ commitMode: 'blur',
535
+ },
536
+ ],
537
+ },
224
538
  {
225
539
  id: 'planar-main',
226
540
  label: 'Planar Main',
227
541
  kind: 'planar-shadow',
542
+ group: { ...SHADOW_RENDERING_GROUP_PLANAR },
228
543
  active: planar.enabled,
229
544
  summary: 'Follow Directional Light',
230
545
  properties: [
@@ -355,6 +670,7 @@ export function createEditorSceneRenderingPanelState(profile, state = {}, option
355
670
  id: 'legacy-shadow',
356
671
  label: 'Legacy Shadow',
357
672
  kind: 'legacy-shadow',
673
+ group: { ...SHADOW_RENDERING_GROUP_COMPAT },
358
674
  active: profile.shadows.enabled && !planar.enabled,
359
675
  readOnly: true,
360
676
  summary: profile.shadows.enabled ? 'Compatibility path' : 'Disabled',
@@ -368,6 +684,7 @@ export function createEditorSceneRenderingPanelState(profile, state = {}, option
368
684
  id: 'csm-shadow',
369
685
  label: 'CSM',
370
686
  kind: 'csm-shadow',
687
+ group: { ...SHADOW_RENDERING_GROUP_COMPAT },
371
688
  active: profile.shadows.enabled && profile.shadows.useCsm && !planar.enabled,
372
689
  readOnly: true,
373
690
  summary: profile.shadows.useCsm ? 'Compatibility path' : 'Disabled',
@@ -380,7 +697,382 @@ export function createEditorSceneRenderingPanelState(profile, state = {}, option
380
697
  ],
381
698
  }],
382
699
  };
383
- return localizeRenderingPanelState(panel, options.language ?? 'en', dirty);
700
+ return localizeRenderingPanelState(panel, language, dirty);
701
+ }
702
+ function resolveStaticShadowBakeLifecycleState(state, enabled) {
703
+ if (!enabled) {
704
+ return {
705
+ status: 'disabled',
706
+ chunkCount: 0,
707
+ };
708
+ }
709
+ return state ?? {
710
+ status: 'missing',
711
+ chunkCount: 0,
712
+ };
713
+ }
714
+ function formatStaticShadowBakeLifecycleStatus(state, language) {
715
+ const chunkCount = Math.max(0, Math.trunc(state.chunkCount ?? 0));
716
+ const chunkText = language === 'zh'
717
+ ? `${chunkCount} 个分块`
718
+ : `${chunkCount} chunk${chunkCount === 1 ? '' : 's'}`;
719
+ if (state.status === 'baking') {
720
+ const progress = state.progress ?? {
721
+ label: language === 'zh' ? '正在烘焙静态阴影' : 'Baking static shadows',
722
+ indeterminate: true,
723
+ };
724
+ return {
725
+ summary: language === 'zh' ? '正在烘焙' : 'Baking',
726
+ status: language === 'zh'
727
+ ? formatChineseStaticShadowBakingStatus(state)
728
+ : state.reason ?? 'Baking static shadow artifact.',
729
+ progress: {
730
+ ...progress,
731
+ label: language === 'zh' ? formatChineseStaticShadowProgressLabel(state) : progress.label,
732
+ },
733
+ };
734
+ }
735
+ if (state.status === 'disabled') {
736
+ const fallback = 'Static Baked Shadow is disabled.';
737
+ return {
738
+ summary: language === 'zh' ? '已禁用' : 'Disabled',
739
+ status: resolveLocalizedStaticShadowStatusReason(state.reason, fallback, '静态烘焙阴影已禁用。', language),
740
+ };
741
+ }
742
+ if (state.status === 'missing') {
743
+ const fallback = 'No static shadow bake artifact is available.';
744
+ return {
745
+ summary: language === 'zh' ? '缺少烘焙' : 'Missing bake',
746
+ status: resolveLocalizedStaticShadowStatusReason(state.reason, fallback, '当前没有可用的静态阴影烘焙数据。', language),
747
+ };
748
+ }
749
+ if (state.status === 'preview-unsaved') {
750
+ const fallback = 'Static shadow preview has not been saved yet.';
751
+ return {
752
+ summary: language === 'zh' ? `预览未保存 · ${chunkText}` : `Preview unsaved · ${chunkText}`,
753
+ status: resolveLocalizedStaticShadowStatusReason(state.reason, fallback, '静态阴影预览尚未保存。', language),
754
+ };
755
+ }
756
+ if (state.status === 'out-of-date') {
757
+ const fallback = 'Static shadow bake is out of date.';
758
+ return {
759
+ summary: language === 'zh' ? `已过期 · ${chunkText}` : `Out of date · ${chunkText}`,
760
+ status: resolveLocalizedStaticShadowStatusReason(state.reason, fallback, '静态阴影烘焙已过期。', language),
761
+ };
762
+ }
763
+ if (state.status === 'invalid') {
764
+ const fallback = 'Static shadow bake artifact is invalid.';
765
+ return {
766
+ summary: language === 'zh' ? '烘焙无效' : 'Invalid bake',
767
+ status: resolveLocalizedStaticShadowStatusReason(state.reason, fallback, '静态阴影烘焙数据无效。', language),
768
+ };
769
+ }
770
+ const fallback = 'Static shadow bake artifact is up to date.';
771
+ if (chunkCount === 0) {
772
+ return {
773
+ summary: language === 'zh' ? '无静态投射物' : 'No static casters',
774
+ status: resolveLocalizedStaticShadowStatusReason(state.reason, fallback, '没有物体被显式设置为静态烘焙阴影。', language),
775
+ };
776
+ }
777
+ return {
778
+ summary: language === 'zh' ? `最新 · ${chunkText}` : `Up to date · ${chunkText}`,
779
+ status: resolveLocalizedStaticShadowStatusReason(state.reason, fallback, '静态阴影烘焙数据已是最新。', language),
780
+ };
781
+ }
782
+ function resolveLocalizedStaticShadowStatusReason(reason, englishFallback, localizedFallback, language) {
783
+ if (language !== 'zh')
784
+ return reason ?? englishFallback;
785
+ return !reason || reason === englishFallback ? localizedFallback : reason;
786
+ }
787
+ function formatChineseStaticShadowBakingStatus(state) {
788
+ const stats = state.stats ?? null;
789
+ const phase = stats?.phase;
790
+ const attempted = stats?.attemptedChunkCount ?? 0;
791
+ const completed = stats?.chunkCount ?? 0;
792
+ const atlasPages = stats?.pageCount ?? stats?.textureCount ?? 0;
793
+ const encodedPages = stats?.textureCount ?? 0;
794
+ if (phase === 'collect') {
795
+ if ((stats?.sourceRootCount ?? 0) > 0)
796
+ return `已收集 ${stats?.sourceRootCount ?? 0} 个静态投射物,正在准备空间分块。`;
797
+ return '正在收集静态阴影投射物。';
798
+ }
799
+ if (phase === 'sdf') {
800
+ if (attempted > 0)
801
+ return `正在生成静态阴影 SDF ${Math.min(completed + 1, attempted)} / ${attempted}。`;
802
+ return '正在生成静态阴影 SDF。';
803
+ }
804
+ if (phase === 'pack') {
805
+ return `正在将 ${completed} 个静态阴影分块打包到 ${atlasPages} 张 Atlas。`;
806
+ }
807
+ if (phase === 'encode') {
808
+ return `正在编码静态阴影 Atlas ${Math.min(encodedPages + 1, atlasPages || encodedPages + 1)} / ${atlasPages || encodedPages + 1}。`;
809
+ }
810
+ if (phase === 'complete')
811
+ return '正在写入静态阴影烘焙数据。';
812
+ if (attempted > 0)
813
+ return `正在烘焙静态阴影分块 ${Math.min(completed + 1, attempted)} / ${attempted}。`;
814
+ if ((stats?.sourceRootCount ?? 0) > 0)
815
+ return `已收集 ${stats?.sourceRootCount ?? 0} 个静态投射物,正在准备分块。`;
816
+ return '正在收集静态阴影投射物。';
817
+ }
818
+ function formatChineseStaticShadowProgressLabel(state) {
819
+ const stats = state.stats ?? null;
820
+ const phase = stats?.phase;
821
+ const attempted = stats?.attemptedChunkCount ?? 0;
822
+ const completed = stats?.chunkCount ?? 0;
823
+ if (phase === 'collect')
824
+ return '收集静态投射物';
825
+ if (phase === 'pack')
826
+ return '打包静态阴影 Atlas';
827
+ if (phase === 'encode') {
828
+ const atlasPages = stats?.pageCount ?? stats?.textureCount ?? 0;
829
+ const encodedPages = stats?.textureCount ?? 0;
830
+ return `静态阴影 Atlas ${Math.min(encodedPages, atlasPages)} / ${atlasPages}`;
831
+ }
832
+ return attempted > 0
833
+ ? `静态阴影烘焙 ${Math.min(completed, attempted)} / ${attempted}`
834
+ : '正在烘焙静态阴影';
835
+ }
836
+ function createStaticShadowBakeDetails(state, language) {
837
+ const stats = state.stats ?? null;
838
+ const details = [];
839
+ const add = (labelEn, labelZh, value, tone) => {
840
+ if (value == null || value === '')
841
+ return;
842
+ details.push({
843
+ label: language === 'zh' ? labelZh : labelEn,
844
+ value: String(value),
845
+ ...(tone ? { tone } : {}),
846
+ });
847
+ };
848
+ const chunkCount = stats?.chunkCount ?? state.chunkCount;
849
+ const performance = calculateStaticShadowPerformanceDetails(stats, chunkCount);
850
+ add('Static casters', '静态投射物', formatOptionalCount(stats?.sourceRootCount));
851
+ add('Bake meshes', '参与 Mesh', formatOptionalCount(stats?.sourceMeshCount));
852
+ add('Chunks', '分块', formatOptionalCount(chunkCount), chunkCount === 0 ? 'warning' : undefined);
853
+ add('Atlas pages', 'Atlas 页', formatOptionalCount(stats?.pageCount ?? stats?.textureCount ?? chunkCount));
854
+ add('Texture memory', '贴图显存', performance.textureMemoryText, performance.textureMemoryTone);
855
+ add('Texture pixels', '贴图像素', performance.atlasPixelsText);
856
+ add('Atlas occupancy', 'Atlas 利用率', performance.atlasOccupancyText, performance.atlasOccupancyTone);
857
+ add('Atlas used', 'Atlas 已用', performance.atlasUsedPixelsText);
858
+ add('Atlas allocated', 'Atlas 分配', performance.atlasAllocatedPixelsText);
859
+ add('Runtime draws', '运行时 Draw', performance.drawCallsText);
860
+ add('Shadow mesh', '阴影 Mesh', performance.meshText);
861
+ add('Triangles', '三角形', performance.triangleText);
862
+ add('Vertices', '顶点', performance.vertexText);
863
+ add('Effective texels / m', '实际每米像素', formatOptionalNumber(stats?.effectiveTexelsPerMeter ?? stats?.texelsPerMeter));
864
+ if (stats?.effectiveTexelsPerMeter != null
865
+ && stats?.texelsPerMeter != null
866
+ && Math.abs(stats.effectiveTexelsPerMeter - stats.texelsPerMeter) > 0.001) {
867
+ add('Target texels / m', '目标每米像素', formatOptionalNumber(stats.texelsPerMeter), 'warning');
868
+ }
869
+ add('Atlas size', 'Atlas 尺寸', stats?.atlasSize ? `${stats.atlasSize}px` : null);
870
+ add('Page budget', '页预算', formatOptionalCount(stats?.maxAtlasPages));
871
+ add('SDF radius', 'SDF 半径', stats?.sdfRadiusPx != null ? `${stats.sdfRadiusPx}px` : null);
872
+ add('Spatial chunk', '空间分块', stats?.spatialChunkSize ? formatMeters(stats.spatialChunkSize) : null);
873
+ if (stats?.effectiveSpatialChunkSize != null
874
+ && stats?.spatialChunkSize != null
875
+ && Math.abs(stats.effectiveSpatialChunkSize - stats.spatialChunkSize) > 0.001) {
876
+ add('Effective chunk', '实际分块', formatMeters(stats.effectiveSpatialChunkSize), 'warning');
877
+ }
878
+ add('Target chunks', '目标分块', formatOptionalCount(stats?.targetChunkCount));
879
+ add('Baked chunks', '重烘分块', formatOptionalCount(stats?.bakedChunkCount));
880
+ add('Reused chunks', '复用分块', formatOptionalCount(stats?.reusedChunkCount), stats?.reusedChunkCount ? 'success' : undefined);
881
+ add('Resolution', '贴图尺寸', stats?.resolution ? `${stats.resolution}px` : null);
882
+ add('Chunk size', '分块尺寸', stats?.chunkSize ? formatMeters(stats.chunkSize) : null);
883
+ add('Duration', '耗时', formatDurationMs(stats?.durationMs, language));
884
+ if (state.status === 'baking') {
885
+ add('Current chunk', '当前分块', stats?.currentChunkId);
886
+ const attempted = stats?.attemptedChunkCount;
887
+ const completed = stats?.chunkCount;
888
+ if (stats?.phase)
889
+ add('Stage', '阶段', formatStaticShadowBakePhase(stats.phase, language));
890
+ if (attempted != null && completed != null) {
891
+ add('Progress', '进度', language === 'zh' ? `${completed} / ${attempted} 个分块` : `${completed} / ${attempted} chunks`);
892
+ }
893
+ }
894
+ else {
895
+ add('Skipped chunks', '跳过分块', formatOptionalCount(stats?.skippedChunkCount), stats?.skippedChunkCount ? 'warning' : undefined);
896
+ }
897
+ return details;
898
+ }
899
+ function calculateStaticShadowPerformanceDetails(stats, fallbackChunkCount) {
900
+ if (!stats) {
901
+ return {
902
+ textureMemoryText: null,
903
+ atlasPixelsText: null,
904
+ atlasUsedPixelsText: null,
905
+ atlasAllocatedPixelsText: null,
906
+ atlasOccupancyText: null,
907
+ drawCallsText: null,
908
+ meshText: null,
909
+ triangleText: null,
910
+ vertexText: null,
911
+ };
912
+ }
913
+ const chunkCount = Math.max(0, Math.trunc(stats.chunkCount ?? fallbackChunkCount ?? 0));
914
+ const isAtlas = stats.pageCount != null || stats.atlasSize != null || stats.effectiveTexelsPerMeter != null;
915
+ const textureCount = Math.max(0, Math.trunc(isAtlas
916
+ ? stats.pageCount ?? stats.textureCount ?? 0
917
+ : stats.textureCount ?? chunkCount));
918
+ const textureSize = isAtlas ? stats.atlasSize : stats.resolution;
919
+ const fallbackTextureBytes = textureCount > 0 && textureSize != null && Number.isFinite(textureSize) && textureSize > 0
920
+ ? textureCount * textureSize * textureSize * 4
921
+ : null;
922
+ const allocatedPixels = isAtlas
923
+ ? stats.atlasAllocatedPixels ?? (fallbackTextureBytes != null ? fallbackTextureBytes / 4 : null)
924
+ : (fallbackTextureBytes != null ? fallbackTextureBytes / 4 : null);
925
+ const usedPixels = isAtlas ? stats.atlasUsedPixels ?? null : null;
926
+ const textureBytes = allocatedPixels != null ? allocatedPixels * 4 : null;
927
+ const occupancy = isAtlas
928
+ ? stats.atlasOccupancy ?? (allocatedPixels != null && allocatedPixels > 0 && usedPixels != null
929
+ ? usedPixels / allocatedPixels
930
+ : null)
931
+ : null;
932
+ const drawCalls = textureCount > 0 ? textureCount : null;
933
+ const renderMeshes = isAtlas ? drawCalls : chunkCount || null;
934
+ const triangles = chunkCount > 0 ? chunkCount * 2 : null;
935
+ const vertices = chunkCount > 0 ? chunkCount * 4 : null;
936
+ return {
937
+ textureMemoryText: formatBytes(textureBytes),
938
+ textureMemoryTone: textureBytes != null && textureBytes >= 256 * 1024 * 1024 ? 'warning' : undefined,
939
+ atlasPixelsText: formatPixelCount(allocatedPixels),
940
+ atlasUsedPixelsText: formatPixelCount(usedPixels),
941
+ atlasAllocatedPixelsText: formatPixelCount(allocatedPixels),
942
+ atlasOccupancyText: formatPercentage(occupancy),
943
+ atlasOccupancyTone: occupancy != null && occupancy < 0.35 ? 'warning' : undefined,
944
+ drawCallsText: formatOptionalCount(drawCalls),
945
+ meshText: formatOptionalCount(renderMeshes),
946
+ triangleText: formatOptionalCount(triangles),
947
+ vertexText: formatOptionalCount(vertices),
948
+ };
949
+ }
950
+ function formatStaticShadowBakePhase(phase, language) {
951
+ if (language !== 'zh')
952
+ return phase;
953
+ switch (phase) {
954
+ case 'collect': return '收集';
955
+ case 'reuse': return '复用已有分块';
956
+ case 'chunk': return '烘焙分块';
957
+ case 'sdf': return '生成 SDF';
958
+ case 'pack': return '打包 Atlas';
959
+ case 'encode': return '编码 Atlas';
960
+ case 'complete': return '写入结果';
961
+ default: return phase;
962
+ }
963
+ }
964
+ function formatOptionalCount(value) {
965
+ if (value == null || !Number.isFinite(value))
966
+ return null;
967
+ return String(Math.max(0, Math.trunc(value)));
968
+ }
969
+ function formatOptionalNumber(value) {
970
+ if (value == null || !Number.isFinite(value))
971
+ return null;
972
+ return Number.isInteger(value) ? String(value) : value.toFixed(2).replace(/\.?0+$/, '');
973
+ }
974
+ function formatPixelCount(value) {
975
+ if (value == null || !Number.isFinite(value))
976
+ return null;
977
+ const pixels = Math.max(0, value);
978
+ if (pixels >= 1000000)
979
+ return `${formatOptionalNumber(pixels / 1000000)} MP`;
980
+ if (pixels >= 1000)
981
+ return `${formatOptionalNumber(pixels / 1000)} KP`;
982
+ return formatOptionalCount(pixels);
983
+ }
984
+ function formatPercentage(value) {
985
+ if (value == null || !Number.isFinite(value))
986
+ return null;
987
+ return `${formatOptionalNumber(Math.max(0, Math.min(1, value)) * 100)}%`;
988
+ }
989
+ function formatBytes(value) {
990
+ if (value == null || !Number.isFinite(value))
991
+ return null;
992
+ const bytes = Math.max(0, value);
993
+ if (bytes >= 1024 * 1024 * 1024)
994
+ return `${formatOptionalNumber(bytes / (1024 * 1024 * 1024))} GiB`;
995
+ if (bytes >= 1024 * 1024)
996
+ return `${formatOptionalNumber(bytes / (1024 * 1024))} MiB`;
997
+ if (bytes >= 1024)
998
+ return `${formatOptionalNumber(bytes / 1024)} KiB`;
999
+ return `${formatOptionalCount(bytes)} B`;
1000
+ }
1001
+ function formatMeters(value) {
1002
+ const text = Number.isInteger(value) ? String(value) : value.toFixed(2).replace(/\.?0+$/, '');
1003
+ return `${text} m`;
1004
+ }
1005
+ function formatDurationMs(value, language) {
1006
+ if (value == null || !Number.isFinite(value))
1007
+ return null;
1008
+ const duration = Math.max(0, value);
1009
+ if (duration < 1000)
1010
+ return `${Math.round(duration)} ms`;
1011
+ const seconds = duration / 1000;
1012
+ const text = seconds < 10 ? seconds.toFixed(1) : String(Math.round(seconds));
1013
+ return language === 'zh' ? `${text} 秒` : `${text}s`;
1014
+ }
1015
+ function createRenderingGroupsSection(slots) {
1016
+ return {
1017
+ id: 'rendering-groups',
1018
+ title: 'Rendering Groups / Order Presets',
1019
+ summary: 'Named Babylon rendering groups and alphaIndex presets used by object Inspector dropdowns.',
1020
+ layout: 'list',
1021
+ systems: slots.map((slot) => ({
1022
+ id: `rendering-group-${slot.renderingGroupId}`,
1023
+ label: slot.name,
1024
+ kind: 'rendering-group',
1025
+ active: true,
1026
+ summary: `Babylon group ${slot.renderingGroupId}`,
1027
+ actions: [{
1028
+ id: 'rendering-alpha-preset.add',
1029
+ label: 'Add Order Preset',
1030
+ icon: 'plus',
1031
+ tooltip: 'Add a named alphaIndex preset for this rendering group.',
1032
+ params: { renderingGroupId: slot.renderingGroupId },
1033
+ }],
1034
+ properties: [
1035
+ createReadonlyRenderingProperty(`renderingGroups.slots.${slot.renderingGroupId}.renderingGroupId`, 'Group ID', slot.renderingGroupId),
1036
+ {
1037
+ path: `renderingGroups.slots.${slot.renderingGroupId}.name`,
1038
+ label: 'Group Name',
1039
+ valueType: 'string',
1040
+ control: 'string',
1041
+ value: slot.name,
1042
+ tooltip: 'Display name for this fixed Babylon rendering group id.',
1043
+ commitMode: 'blur',
1044
+ },
1045
+ ...slot.alphaIndexPresets.flatMap((preset, index) => [
1046
+ {
1047
+ path: `renderingGroups.slots.${slot.renderingGroupId}.alphaIndexPresets.${index}.name`,
1048
+ label: `Preset ${index + 1} Name`,
1049
+ valueType: 'string',
1050
+ control: 'string',
1051
+ value: preset.name,
1052
+ tooltip: 'User-facing name shown in object Inspector dropdowns.',
1053
+ commitMode: 'blur',
1054
+ actions: [{
1055
+ id: 'rendering-alpha-preset.delete',
1056
+ label: 'Delete',
1057
+ icon: 'trash',
1058
+ tooltip: 'Delete this alphaIndex preset. Existing objects keep their numeric alphaIndex.',
1059
+ params: { renderingGroupId: slot.renderingGroupId, presetIndex: index },
1060
+ }],
1061
+ },
1062
+ {
1063
+ path: `renderingGroups.slots.${slot.renderingGroupId}.alphaIndexPresets.${index}.alphaIndex`,
1064
+ label: `Preset ${index + 1} Value`,
1065
+ valueType: 'number',
1066
+ control: 'number',
1067
+ value: preset.alphaIndex,
1068
+ step: 1,
1069
+ tooltip: 'Babylon alphaIndex value stored on objects that use this preset.',
1070
+ commitMode: 'blur',
1071
+ },
1072
+ ]),
1073
+ ],
1074
+ })),
1075
+ };
384
1076
  }
385
1077
  function createReadonlyRenderingProperty(path, label, value) {
386
1078
  return {
@@ -436,6 +1128,21 @@ function createEnvironmentTexturePickerControlOptions(input) {
436
1128
  ],
437
1129
  };
438
1130
  }
1131
+ function createShadowDefaultModeOptions(language) {
1132
+ return language === 'zh'
1133
+ ? [
1134
+ { label: '无阴影', value: 'none' },
1135
+ { label: 'Blob 阴影', value: 'blob' },
1136
+ { label: '静态烘焙阴影', value: 'static' },
1137
+ { label: '主平面阴影', value: 'planar' },
1138
+ ]
1139
+ : [
1140
+ { label: 'None', value: 'none' },
1141
+ { label: 'Blob', value: 'blob' },
1142
+ { label: 'Static Baked', value: 'static' },
1143
+ { label: 'Planar', value: 'planar' },
1144
+ ];
1145
+ }
439
1146
  function isEditorSceneEnvironmentTextureAsset(texture) {
440
1147
  if (texture.capabilities?.environmentTexture === true)
441
1148
  return true;
@@ -464,7 +1171,15 @@ const RENDERING_PANEL_TEXT = {
464
1171
  revert: 'Revert',
465
1172
  revertDirty: 'Revert rendering settings to the last saved rendering settings.',
466
1173
  revertClean: 'Rendering settings already match the last saved rendering settings.',
1174
+ bakeStatic: 'Bake Static Shadows',
1175
+ bakeStaticReady: 'Bake static shadow chunks for objects authored as Static Baked Shadow.',
1176
+ bakeStaticDisabled: 'Enable Static Baked Shadow before baking.',
1177
+ bakeStaticRunning: 'Static shadow bake is already running.',
467
1178
  sections: {
1179
+ 'rendering-groups': {
1180
+ title: 'Rendering Groups / Order Presets',
1181
+ summary: 'Named Babylon rendering groups and alphaIndex presets used by object Inspector dropdowns.',
1182
+ },
468
1183
  environment: {
469
1184
  title: 'Environment / IBL',
470
1185
  summary: 'World environment texture and reflection lighting shared by editor preview and runtime.',
@@ -478,6 +1193,24 @@ const RENDERING_PANEL_TEXT = {
478
1193
  summary: 'Global shadow systems for editor preview and runtime.',
479
1194
  },
480
1195
  },
1196
+ groups: {
1197
+ 'shadow-group-moving-object': {
1198
+ label: 'Moving Object Shadows',
1199
+ summary: 'Blob: lightweight for moving objects and project-default fallback.',
1200
+ },
1201
+ 'shadow-group-static-scene': {
1202
+ label: 'Static Scene Shadows',
1203
+ summary: 'Consumes baked artifacts; update during authoring/build, runtime only displays results.',
1204
+ },
1205
+ 'shadow-group-directional-planar': {
1206
+ label: 'Directional Planar Shadows',
1207
+ summary: 'Real-time planar projection following the directional light.',
1208
+ },
1209
+ 'shadow-group-compatibility': {
1210
+ label: 'Compatibility Shadows',
1211
+ summary: 'Legacy ShadowGenerator / CSM read-only compatibility paths.',
1212
+ },
1213
+ },
481
1214
  systems: {
482
1215
  'environment-global': {
483
1216
  label: 'Environment Texture',
@@ -490,6 +1223,14 @@ const RENDERING_PANEL_TEXT = {
490
1223
  label: 'Planar Main',
491
1224
  summary: 'Follow Directional Light',
492
1225
  },
1226
+ 'blob-shadow': {
1227
+ label: 'Blob Shadow',
1228
+ summary: 'Default object shadow',
1229
+ },
1230
+ 'static-projected-shadow': {
1231
+ label: 'Static Baked Shadow',
1232
+ summary: 'Baked object shape',
1233
+ },
493
1234
  'legacy-shadow': {
494
1235
  label: 'Legacy Shadow',
495
1236
  disabled: 'Disabled',
@@ -514,6 +1255,106 @@ const RENDERING_PANEL_TEXT = {
514
1255
  label: 'IBL Rotation',
515
1256
  tooltip: 'Y-axis rotation applied to the environment texture.',
516
1257
  },
1258
+ 'shadows.defaultMode': {
1259
+ label: 'Default Mode',
1260
+ tooltip: 'Default shadow mode for GameObjects that use the project default.',
1261
+ },
1262
+ 'shadows.blob.enabled': {
1263
+ label: 'Enabled',
1264
+ tooltip: 'Enable the shared blob shadow system.',
1265
+ },
1266
+ 'shadows.blob.appearance.color': {
1267
+ label: 'Color',
1268
+ tooltip: 'Blob shadow RGB color. Opacity is edited separately.',
1269
+ },
1270
+ 'shadows.blob.appearance.color.a': {
1271
+ label: 'Opacity',
1272
+ tooltip: 'Blob shadow opacity, clamped between 0 and 1.',
1273
+ },
1274
+ 'shadows.blob.appearance.edgeSoftness': {
1275
+ label: 'Soft Edge',
1276
+ tooltip: 'Blob shadow soft edge start. Higher values keep the center denser before fading out.',
1277
+ },
1278
+ 'shadows.blob.plane.height': {
1279
+ label: 'Height',
1280
+ tooltip: 'Ground plane height used by blob shadows.',
1281
+ },
1282
+ 'shadows.blob.plane.yOffset': {
1283
+ label: 'Y Offset',
1284
+ tooltip: 'Vertical offset above the blob shadow plane to reduce z-fighting.',
1285
+ },
1286
+ 'shadows.blob.size.sizeMultiplier': {
1287
+ label: 'Size Multiplier',
1288
+ tooltip: 'Scale blob shadow size from each caster bounds.',
1289
+ },
1290
+ 'shadows.blob.size.minSize': {
1291
+ label: 'Min Size',
1292
+ tooltip: 'Minimum blob shadow size for tiny objects.',
1293
+ },
1294
+ 'shadows.blob.size.maxSize': {
1295
+ label: 'Max Size',
1296
+ tooltip: 'Maximum blob shadow size for large objects.',
1297
+ },
1298
+ 'shadows.staticProjected.enabled': {
1299
+ label: 'Enabled',
1300
+ tooltip: 'Enable the shared static projected shadow system.',
1301
+ },
1302
+ 'shadows.staticProjected.appearance.color': {
1303
+ label: 'Color',
1304
+ tooltip: 'Static shadow RGB color. Opacity is edited separately.',
1305
+ },
1306
+ 'shadows.staticProjected.appearance.color.a': {
1307
+ label: 'Opacity',
1308
+ tooltip: 'Static shadow opacity, clamped between 0 and 1.',
1309
+ },
1310
+ 'shadows.staticProjected.plane.height': {
1311
+ label: 'Height',
1312
+ tooltip: 'Ground plane height used by static projected shadows.',
1313
+ },
1314
+ 'shadows.staticProjected.plane.yOffset': {
1315
+ label: 'Y Offset',
1316
+ tooltip: 'Vertical offset above the static shadow plane to reduce z-fighting.',
1317
+ },
1318
+ 'shadows.staticProjected.bake.resolution': {
1319
+ label: 'Legacy Resolution',
1320
+ tooltip: 'Legacy v1 mask resolution. v2 SDF atlas bake uses Texels per Meter and Atlas Size.',
1321
+ },
1322
+ 'shadows.staticProjected.bake.padding': {
1323
+ label: 'Padding',
1324
+ tooltip: 'Extra projected bounds padding before baking the static shadow.',
1325
+ },
1326
+ 'shadows.staticProjected.bake.blur': {
1327
+ label: 'Blur',
1328
+ tooltip: 'Reserved blur radius for static shadow bake softness.',
1329
+ },
1330
+ 'shadows.staticProjected.bake.maxSize': {
1331
+ label: 'Legacy Max Size',
1332
+ tooltip: 'Legacy alias for Spatial Chunk Size.',
1333
+ },
1334
+ 'shadows.staticProjected.bake.texelsPerMeter': {
1335
+ label: 'Texels per Meter',
1336
+ tooltip: 'Target SDF atlas texel density for baked static shadows.',
1337
+ },
1338
+ 'shadows.staticProjected.bake.atlasSize': {
1339
+ label: 'Atlas Size',
1340
+ tooltip: 'Maximum width and height for each static shadow atlas page.',
1341
+ },
1342
+ 'shadows.staticProjected.bake.maxAtlasPages': {
1343
+ label: 'Page Budget',
1344
+ tooltip: 'Maximum atlas pages before bake lowers the effective texel density.',
1345
+ },
1346
+ 'shadows.staticProjected.bake.sdfRadiusPx': {
1347
+ label: 'SDF Radius',
1348
+ tooltip: 'Signed-distance radius in pixels used for crisp controllable edges.',
1349
+ },
1350
+ 'shadows.staticProjected.bake.spatialChunkSize': {
1351
+ label: 'Spatial Chunk Size',
1352
+ tooltip: 'World size of each spatial bake chunk before atlas packing.',
1353
+ },
1354
+ 'shadows.staticProjected.bake.targetChunkCount': {
1355
+ label: 'Target Chunks',
1356
+ tooltip: 'Soft chunk-count budget. Large scenes automatically enlarge spatial chunks to stay near this target.',
1357
+ },
517
1358
  },
518
1359
  },
519
1360
  zh: {
@@ -523,7 +1364,15 @@ const RENDERING_PANEL_TEXT = {
523
1364
  revert: '还原',
524
1365
  revertDirty: '还原到上一次保存的渲染设置。',
525
1366
  revertClean: '当前渲染设置已经和上一次保存状态一致。',
1367
+ bakeStatic: '烘焙静态阴影',
1368
+ bakeStaticReady: '为标记为静态烘焙阴影的物体生成分块阴影。',
1369
+ bakeStaticDisabled: '请先启用静态烘焙阴影。',
1370
+ bakeStaticRunning: '静态阴影正在烘焙中。',
526
1371
  sections: {
1372
+ 'rendering-groups': {
1373
+ title: '渲染分组 / 顺序预设',
1374
+ summary: '项目级 Babylon rendering group 名称和 alphaIndex 预设,用于物体 Inspector 下拉选择。',
1375
+ },
527
1376
  environment: {
528
1377
  title: '环境 / IBL',
529
1378
  summary: '世界环境贴图与 PBR 环境反射,编辑器预览和运行时共用。',
@@ -537,6 +1386,24 @@ const RENDERING_PANEL_TEXT = {
537
1386
  summary: '项目级阴影系统,编辑器预览和运行时共用。',
538
1387
  },
539
1388
  },
1389
+ groups: {
1390
+ 'shadow-group-moving-object': {
1391
+ label: '移动物体阴影',
1392
+ summary: 'Blob:低成本,适合移动物体,也可作为项目默认阴影。',
1393
+ },
1394
+ 'shadow-group-static-scene': {
1395
+ label: '静态场景阴影',
1396
+ summary: '只显示已烘焙 artifact;编辑器/构建期更新,运行时消费结果。',
1397
+ },
1398
+ 'shadow-group-directional-planar': {
1399
+ label: '主平面实时阴影',
1400
+ summary: '跟随直射光动态投影,适合需要方向感的物体。',
1401
+ },
1402
+ 'shadow-group-compatibility': {
1403
+ label: '兼容阴影',
1404
+ summary: '旧 ShadowGenerator / CSM 只读兼容路径。',
1405
+ },
1406
+ },
540
1407
  systems: {
541
1408
  'environment-global': {
542
1409
  label: '环境贴图',
@@ -549,6 +1416,14 @@ const RENDERING_PANEL_TEXT = {
549
1416
  label: '主平面阴影',
550
1417
  summary: '跟随直射光',
551
1418
  },
1419
+ 'blob-shadow': {
1420
+ label: 'Blob 阴影',
1421
+ summary: '默认物体阴影',
1422
+ },
1423
+ 'static-projected-shadow': {
1424
+ label: '静态烘焙阴影',
1425
+ summary: '烘焙物体轮廓',
1426
+ },
552
1427
  'legacy-shadow': {
553
1428
  label: '旧版阴影',
554
1429
  disabled: '已禁用',
@@ -626,6 +1501,106 @@ const RENDERING_PANEL_TEXT = {
626
1501
  label: 'Bloom 缩放',
627
1502
  tooltip: 'Bloom 渲染缩放比例。较低数值更省性能,较高数值细节更稳定。',
628
1503
  },
1504
+ 'shadows.defaultMode': {
1505
+ label: '默认模式',
1506
+ tooltip: '使用项目默认阴影的 GameObject 会采用这个模式。',
1507
+ },
1508
+ 'shadows.blob.enabled': {
1509
+ label: '启用',
1510
+ tooltip: '启用共用的 Blob 阴影系统。',
1511
+ },
1512
+ 'shadows.blob.appearance.color': {
1513
+ label: '颜色',
1514
+ tooltip: 'Blob 阴影颜色。透明度单独编辑。',
1515
+ },
1516
+ 'shadows.blob.appearance.color.a': {
1517
+ label: '不透明度',
1518
+ tooltip: 'Blob 阴影不透明度,范围 0 到 1。',
1519
+ },
1520
+ 'shadows.blob.appearance.edgeSoftness': {
1521
+ label: '柔边',
1522
+ tooltip: 'Blob 阴影柔边起点。数值越高,中心区域越实,边缘再逐渐淡出。',
1523
+ },
1524
+ 'shadows.blob.plane.height': {
1525
+ label: '高度',
1526
+ tooltip: 'Blob 阴影所在的地面高度。',
1527
+ },
1528
+ 'shadows.blob.plane.yOffset': {
1529
+ label: 'Y 偏移',
1530
+ tooltip: 'Blob 阴影相对地面的垂直偏移,用于避免 z-fighting。',
1531
+ },
1532
+ 'shadows.blob.size.sizeMultiplier': {
1533
+ label: '尺寸倍率',
1534
+ tooltip: '根据投射物包围盒计算 Blob 阴影尺寸时使用的倍率。',
1535
+ },
1536
+ 'shadows.blob.size.minSize': {
1537
+ label: '最小尺寸',
1538
+ tooltip: '很小物体使用的最小 Blob 阴影尺寸。',
1539
+ },
1540
+ 'shadows.blob.size.maxSize': {
1541
+ label: '最大尺寸',
1542
+ tooltip: '大型物体使用的最大 Blob 阴影尺寸。',
1543
+ },
1544
+ 'shadows.staticProjected.enabled': {
1545
+ label: '启用',
1546
+ tooltip: '启用共用的静态烘焙阴影系统。',
1547
+ },
1548
+ 'shadows.staticProjected.appearance.color': {
1549
+ label: '颜色',
1550
+ tooltip: '静态烘焙阴影颜色。透明度单独编辑。',
1551
+ },
1552
+ 'shadows.staticProjected.appearance.color.a': {
1553
+ label: '不透明度',
1554
+ tooltip: '静态烘焙阴影不透明度,范围 0 到 1。',
1555
+ },
1556
+ 'shadows.staticProjected.plane.height': {
1557
+ label: '高度',
1558
+ tooltip: '静态烘焙阴影所在的地面高度。',
1559
+ },
1560
+ 'shadows.staticProjected.plane.yOffset': {
1561
+ label: 'Y 偏移',
1562
+ tooltip: '静态烘焙阴影相对地面的垂直偏移,用于避免 z-fighting。',
1563
+ },
1564
+ 'shadows.staticProjected.bake.resolution': {
1565
+ label: '旧版贴图尺寸',
1566
+ tooltip: '旧版 v1 mask 分辨率。v2 SDF atlas 烘焙使用每米像素和 Atlas 尺寸。',
1567
+ },
1568
+ 'shadows.staticProjected.bake.padding': {
1569
+ label: '留白',
1570
+ tooltip: '烘焙静态阴影前给投影范围增加的留白。',
1571
+ },
1572
+ 'shadows.staticProjected.bake.blur': {
1573
+ label: '模糊',
1574
+ tooltip: '静态阴影烘焙柔化预留半径。',
1575
+ },
1576
+ 'shadows.staticProjected.bake.maxSize': {
1577
+ label: '旧版最大尺寸',
1578
+ tooltip: '旧版字段,作为空间分块尺寸的兼容别名。',
1579
+ },
1580
+ 'shadows.staticProjected.bake.texelsPerMeter': {
1581
+ label: '每米像素',
1582
+ tooltip: '静态阴影 SDF atlas 的目标像素密度。',
1583
+ },
1584
+ 'shadows.staticProjected.bake.atlasSize': {
1585
+ label: 'Atlas 尺寸',
1586
+ tooltip: '每张静态阴影 atlas 页的最大宽高。',
1587
+ },
1588
+ 'shadows.staticProjected.bake.maxAtlasPages': {
1589
+ label: '页预算',
1590
+ tooltip: '超过该 atlas 页数时,烘焙会降低实际每米像素以保护运行时成本。',
1591
+ },
1592
+ 'shadows.staticProjected.bake.sdfRadiusPx': {
1593
+ label: 'SDF 半径',
1594
+ tooltip: '用于重建清晰可控边缘的有符号距离半径,单位像素。',
1595
+ },
1596
+ 'shadows.staticProjected.bake.spatialChunkSize': {
1597
+ label: '空间分块尺寸',
1598
+ tooltip: '进入 atlas packing 前,每个空间烘焙分块覆盖的世界尺寸。',
1599
+ },
1600
+ 'shadows.staticProjected.bake.targetChunkCount': {
1601
+ label: '目标分块数',
1602
+ tooltip: '分块数量软预算。大场景会自动放大空间分块,尽量接近该数量。',
1603
+ },
629
1604
  'shadows.planar.enabled': {
630
1605
  label: '启用',
631
1606
  tooltip: '启用共用的平面阴影系统。运行时和编辑器预览会使用同一套参数。',
@@ -712,10 +1687,7 @@ function localizeRenderingPanelState(panel, language, dirty) {
712
1687
  if (panel.status === RENDERING_PANEL_TEXT.en.dirtyStatus)
713
1688
  panel.status = text.dirtyStatus;
714
1689
  for (const action of panel.actions ?? []) {
715
- if (action.id !== 'revert-rendering')
716
- continue;
717
- action.label = text.revert;
718
- action.tooltip = dirty ? text.revertDirty : text.revertClean;
1690
+ localizeRenderingAction(action, text, dirty);
719
1691
  }
720
1692
  for (const section of panel.sections) {
721
1693
  const sectionText = text.sections[section.id];
@@ -725,10 +1697,18 @@ function localizeRenderingPanelState(panel, language, dirty) {
725
1697
  section.summary = sectionText.summary;
726
1698
  for (const system of section.systems) {
727
1699
  const systemText = text.systems[system.id];
1700
+ if (system.group) {
1701
+ const groupText = text.groups[system.group.id];
1702
+ if (groupText?.label)
1703
+ system.group.label = groupText.label;
1704
+ if (groupText?.summary)
1705
+ system.group.summary = groupText.summary;
1706
+ }
728
1707
  if (systemText?.label)
729
1708
  system.label = systemText.label;
730
- if (systemText?.summary)
1709
+ if (systemText?.summary && !(system.id === 'static-projected-shadow' && system.status)) {
731
1710
  system.summary = systemText.summary;
1711
+ }
732
1712
  if (language === 'zh' && system.id === 'environment-global' && system.summary === 'No IBL texture') {
733
1713
  system.summary = '未设置 IBL 贴图';
734
1714
  }
@@ -736,12 +1716,28 @@ function localizeRenderingPanelState(panel, language, dirty) {
736
1716
  system.summary = systemText.disabled;
737
1717
  if (systemText?.compatibility && system.summary === RENDERING_PANEL_TEXT.en.systems[system.id]?.compatibility)
738
1718
  system.summary = systemText.compatibility;
1719
+ for (const action of system.actions ?? [])
1720
+ localizeRenderingAction(action, text, dirty);
739
1721
  for (const property of system.properties)
740
1722
  localizeRenderingProperty(property, text);
741
1723
  }
742
1724
  }
743
1725
  return panel;
744
1726
  }
1727
+ function localizeRenderingAction(action, text, dirty) {
1728
+ if (action.id === 'revert-rendering') {
1729
+ action.label = text.revert;
1730
+ action.tooltip = dirty ? text.revertDirty : text.revertClean;
1731
+ }
1732
+ if (action.id === 'bake-static-shadows') {
1733
+ action.label = text.bakeStatic;
1734
+ action.tooltip = action.disabled
1735
+ ? action.tooltip === RENDERING_PANEL_TEXT.en.bakeStaticRunning
1736
+ ? text.bakeStaticRunning
1737
+ : text.bakeStaticDisabled
1738
+ : text.bakeStaticReady;
1739
+ }
1740
+ }
745
1741
  function localizeRenderingProperty(property, text) {
746
1742
  const propertyText = text.properties[property.path];
747
1743
  if (!propertyText)