@fps-games/editor 0.1.5-beta.5 → 0.1.6-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 (218) hide show
  1. package/dist/build-info.json +16 -16
  2. package/dist/local-editor-agent-actions.d.ts +8 -1
  3. package/dist/local-editor-agent-actions.d.ts.map +1 -1
  4. package/dist/local-editor-agent-actions.js +171 -12
  5. package/dist/local-editor-agent-actions.js.map +1 -1
  6. package/dist/local-editor-agent-context.d.ts +29 -1
  7. package/dist/local-editor-agent-context.d.ts.map +1 -1
  8. package/dist/local-editor-agent-context.js +403 -0
  9. package/dist/local-editor-agent-context.js.map +1 -1
  10. package/dist/local-editor-harness.d.ts +103 -5
  11. package/dist/local-editor-harness.d.ts.map +1 -1
  12. package/dist/local-editor-harness.js +1982 -101
  13. package/dist/local-editor-harness.js.map +1 -1
  14. package/dist/local-editor-marker-graph.d.ts +92 -0
  15. package/dist/local-editor-marker-graph.d.ts.map +1 -0
  16. package/dist/local-editor-marker-graph.js +1432 -0
  17. package/dist/local-editor-marker-graph.js.map +1 -0
  18. package/dist/local-editor-performance-stats.js +1 -1
  19. package/dist/local-editor-performance-stats.js.map +1 -1
  20. package/dist/playable-babylon-facade.d.ts +2 -2
  21. package/dist/playable-babylon-facade.d.ts.map +1 -1
  22. package/dist/playable-babylon-facade.js +1 -1
  23. package/dist/playable-babylon-facade.js.map +1 -1
  24. package/dist/playable-local-editor-host.d.ts +52 -7
  25. package/dist/playable-local-editor-host.d.ts.map +1 -1
  26. package/dist/playable-local-editor-host.js +23 -1
  27. package/dist/playable-local-editor-host.js.map +1 -1
  28. package/dist/playable-sdk.d.ts +4 -2
  29. package/dist/playable-sdk.d.ts.map +1 -1
  30. package/dist/playable-sdk.js +2 -1
  31. package/dist/playable-sdk.js.map +1 -1
  32. package/node_modules/@fps-games/babylon-renderer/package.json +1 -1
  33. package/node_modules/@fps-games/editor-babylon/dist/camera-controller.d.ts.map +1 -1
  34. package/node_modules/@fps-games/editor-babylon/dist/camera-controller.js +11 -0
  35. package/node_modules/@fps-games/editor-babylon/dist/camera-controller.js.map +1 -1
  36. package/node_modules/@fps-games/editor-babylon/dist/editor-sky.d.ts +3 -1
  37. package/node_modules/@fps-games/editor-babylon/dist/editor-sky.d.ts.map +1 -1
  38. package/node_modules/@fps-games/editor-babylon/dist/editor-sky.js +114 -18
  39. package/node_modules/@fps-games/editor-babylon/dist/editor-sky.js.map +1 -1
  40. package/node_modules/@fps-games/editor-babylon/dist/editor-world.d.ts +1 -0
  41. package/node_modules/@fps-games/editor-babylon/dist/editor-world.d.ts.map +1 -1
  42. package/node_modules/@fps-games/editor-babylon/dist/editor-world.js +3 -0
  43. package/node_modules/@fps-games/editor-babylon/dist/editor-world.js.map +1 -1
  44. package/node_modules/@fps-games/editor-babylon/dist/index.d.ts +3 -0
  45. package/node_modules/@fps-games/editor-babylon/dist/index.d.ts.map +1 -1
  46. package/node_modules/@fps-games/editor-babylon/dist/index.js +3 -0
  47. package/node_modules/@fps-games/editor-babylon/dist/index.js.map +1 -1
  48. package/node_modules/@fps-games/editor-babylon/dist/marker-overlay.d.ts +52 -0
  49. package/node_modules/@fps-games/editor-babylon/dist/marker-overlay.d.ts.map +1 -0
  50. package/node_modules/@fps-games/editor-babylon/dist/marker-overlay.js +1395 -0
  51. package/node_modules/@fps-games/editor-babylon/dist/marker-overlay.js.map +1 -0
  52. package/node_modules/@fps-games/editor-babylon/dist/material-property-adapter.d.ts.map +1 -1
  53. package/node_modules/@fps-games/editor-babylon/dist/material-property-adapter.js +4 -65
  54. package/node_modules/@fps-games/editor-babylon/dist/material-property-adapter.js.map +1 -1
  55. package/node_modules/@fps-games/editor-babylon/dist/material-slot-source-resolver.d.ts +28 -0
  56. package/node_modules/@fps-games/editor-babylon/dist/material-slot-source-resolver.d.ts.map +1 -0
  57. package/node_modules/@fps-games/editor-babylon/dist/material-slot-source-resolver.js +235 -0
  58. package/node_modules/@fps-games/editor-babylon/dist/material-slot-source-resolver.js.map +1 -0
  59. package/node_modules/@fps-games/editor-babylon/dist/prefab-comparison-preview-controller.d.ts +37 -0
  60. package/node_modules/@fps-games/editor-babylon/dist/prefab-comparison-preview-controller.d.ts.map +1 -0
  61. package/node_modules/@fps-games/editor-babylon/dist/prefab-comparison-preview-controller.js +451 -0
  62. package/node_modules/@fps-games/editor-babylon/dist/prefab-comparison-preview-controller.js.map +1 -0
  63. package/node_modules/@fps-games/editor-babylon/dist/projection-asset-container-importer.d.ts.map +1 -1
  64. package/node_modules/@fps-games/editor-babylon/dist/projection-asset-container-importer.js +14 -3
  65. package/node_modules/@fps-games/editor-babylon/dist/projection-asset-container-importer.js.map +1 -1
  66. package/node_modules/@fps-games/editor-babylon/dist/projection-pick-resolver.d.ts +1 -0
  67. package/node_modules/@fps-games/editor-babylon/dist/projection-pick-resolver.d.ts.map +1 -1
  68. package/node_modules/@fps-games/editor-babylon/dist/projection-pick-resolver.js +20 -4
  69. package/node_modules/@fps-games/editor-babylon/dist/projection-pick-resolver.js.map +1 -1
  70. package/node_modules/@fps-games/editor-babylon/dist/projection-source-owner-path.d.ts +3 -6
  71. package/node_modules/@fps-games/editor-babylon/dist/projection-source-owner-path.d.ts.map +1 -1
  72. package/node_modules/@fps-games/editor-babylon/dist/projection-source-owner-path.js +4 -37
  73. package/node_modules/@fps-games/editor-babylon/dist/projection-source-owner-path.js.map +1 -1
  74. package/node_modules/@fps-games/editor-babylon/dist/projection.d.ts +44 -1
  75. package/node_modules/@fps-games/editor-babylon/dist/projection.d.ts.map +1 -1
  76. package/node_modules/@fps-games/editor-babylon/dist/projection.js +295 -41
  77. package/node_modules/@fps-games/editor-babylon/dist/projection.js.map +1 -1
  78. package/node_modules/@fps-games/editor-babylon/package.json +5 -5
  79. package/node_modules/@fps-games/editor-browser/dist/index.d.ts +5 -2
  80. package/node_modules/@fps-games/editor-browser/dist/index.d.ts.map +1 -1
  81. package/node_modules/@fps-games/editor-browser/dist/index.js +2 -0
  82. package/node_modules/@fps-games/editor-browser/dist/index.js.map +1 -1
  83. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-asset-kind.d.ts +5 -0
  84. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-asset-kind.d.ts.map +1 -0
  85. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-asset-kind.js +23 -0
  86. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-asset-kind.js.map +1 -0
  87. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-actions.d.ts.map +1 -1
  88. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-actions.js +69 -0
  89. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-actions.js.map +1 -1
  90. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-attach-dialog.d.ts.map +1 -1
  91. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-attach-dialog.js +1 -0
  92. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-attach-dialog.js.map +1 -1
  93. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.d.ts +2 -0
  94. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.d.ts.map +1 -1
  95. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.js +38 -1
  96. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-controller.js.map +1 -1
  97. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.d.ts +1 -1
  98. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-tree.d.ts.map +1 -1
  99. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-view.d.ts.map +1 -1
  100. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-view.js +8 -2
  101. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-hierarchy-view.js.map +1 -1
  102. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.d.ts +1 -1
  103. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.d.ts.map +1 -1
  104. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.js +7 -0
  105. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-icons.js.map +1 -1
  106. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panel-registry.js +1 -1
  107. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panel-registry.js.map +1 -1
  108. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.d.ts +4 -0
  109. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.d.ts.map +1 -1
  110. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.js +1471 -29
  111. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-panels.js.map +1 -1
  112. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-prefab-stage.d.ts +52 -0
  113. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-prefab-stage.d.ts.map +1 -0
  114. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-prefab-stage.js +131 -0
  115. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-prefab-stage.js.map +1 -0
  116. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-primitives.d.ts +1 -1
  117. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-primitives.d.ts.map +1 -1
  118. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-shared.d.ts.map +1 -1
  119. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-shared.js +9 -2
  120. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-shared.js.map +1 -1
  121. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts +234 -3
  122. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-types.d.ts.map +1 -1
  123. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-workbench.d.ts +10 -1
  124. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-workbench.d.ts.map +1 -1
  125. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-workbench.js +3 -1
  126. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui-workbench.js.map +1 -1
  127. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts +4 -3
  128. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.d.ts.map +1 -1
  129. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js +1274 -55
  130. package/node_modules/@fps-games/editor-browser/dist/local-editor-ui.js.map +1 -1
  131. package/node_modules/@fps-games/editor-browser/package.json +3 -3
  132. package/node_modules/@fps-games/editor-core/dist/scene-graph.d.ts +1 -1
  133. package/node_modules/@fps-games/editor-core/dist/scene-graph.d.ts.map +1 -1
  134. package/node_modules/@fps-games/editor-core/dist/viewport-tools.d.ts +2 -0
  135. package/node_modules/@fps-games/editor-core/dist/viewport-tools.d.ts.map +1 -1
  136. package/node_modules/@fps-games/editor-core/dist/viewport-tools.js +1 -0
  137. package/node_modules/@fps-games/editor-core/dist/viewport-tools.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-library/catalog.d.ts.map +1 -1
  141. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-library/catalog.js +17 -3
  142. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-library/catalog.js.map +1 -1
  143. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-library/document.d.ts.map +1 -1
  144. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-library/document.js +2 -1
  145. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-library/document.js.map +1 -1
  146. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-library/types.d.ts +3 -2
  147. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-library/types.d.ts.map +1 -1
  148. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.d.ts +1 -0
  149. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.d.ts.map +1 -1
  150. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.js +68 -2
  151. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/document.js.map +1 -1
  152. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/index.d.ts +1 -1
  153. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/index.d.ts.map +1 -1
  154. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/index.js +1 -1
  155. package/node_modules/@fps-games/editor-playable-sdk/dist/asset-placement/index.js.map +1 -1
  156. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.d.ts +56 -1
  157. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.d.ts.map +1 -1
  158. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.js +531 -0
  159. package/node_modules/@fps-games/editor-playable-sdk/dist/document/helpers.js.map +1 -1
  160. package/node_modules/@fps-games/editor-playable-sdk/dist/document/types.d.ts +103 -2
  161. package/node_modules/@fps-games/editor-playable-sdk/dist/document/types.d.ts.map +1 -1
  162. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/index.d.ts +1 -1
  163. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/index.d.ts.map +1 -1
  164. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/index.js +1 -1
  165. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/index.js.map +1 -1
  166. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.d.ts.map +1 -1
  167. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.js +9 -1
  168. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/schema.js.map +1 -1
  169. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/validators.d.ts +1 -0
  170. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/validators.d.ts.map +1 -1
  171. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/validators.js +3 -0
  172. package/node_modules/@fps-games/editor-playable-sdk/dist/field-schema/validators.js.map +1 -1
  173. package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/lifecycle.d.ts.map +1 -1
  174. package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/lifecycle.js +3 -7
  175. package/node_modules/@fps-games/editor-playable-sdk/dist/local-harness/lifecycle.js.map +1 -1
  176. package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/binding.d.ts.map +1 -1
  177. package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/binding.js +6 -0
  178. package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/binding.js.map +1 -1
  179. package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/types.d.ts +2 -10
  180. package/node_modules/@fps-games/editor-playable-sdk/dist/material-binding/types.d.ts.map +1 -1
  181. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.d.ts.map +1 -1
  182. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.js +8 -0
  183. package/node_modules/@fps-games/editor-playable-sdk/dist/mutation/field-patch.js.map +1 -1
  184. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.d.ts.map +1 -1
  185. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.js +66 -31
  186. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/nodes.js.map +1 -1
  187. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/types.d.ts +2 -1
  188. package/node_modules/@fps-games/editor-playable-sdk/dist/runtime-preview/types.d.ts.map +1 -1
  189. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/protocol.d.ts.map +1 -1
  190. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/protocol.js +40 -2
  191. package/node_modules/@fps-games/editor-playable-sdk/dist/scene-source/protocol.js.map +1 -1
  192. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.d.ts +1 -0
  193. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.d.ts.map +1 -1
  194. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.js +20 -0
  195. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/descriptors.js.map +1 -1
  196. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.d.ts.map +1 -1
  197. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.js +68 -27
  198. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/inspector.js.map +1 -1
  199. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/object.d.ts.map +1 -1
  200. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/object.js +7 -4
  201. package/node_modules/@fps-games/editor-playable-sdk/dist/serialized-property/object.js.map +1 -1
  202. package/node_modules/@fps-games/editor-playable-sdk/dist/session/hierarchy.d.ts.map +1 -1
  203. package/node_modules/@fps-games/editor-playable-sdk/dist/session/hierarchy.js +2 -1
  204. package/node_modules/@fps-games/editor-playable-sdk/dist/session/hierarchy.js.map +1 -1
  205. package/node_modules/@fps-games/editor-playable-sdk/package.json +3 -3
  206. package/node_modules/@fps-games/editor-protocol/dist/agent.d.ts +57 -3
  207. package/node_modules/@fps-games/editor-protocol/dist/agent.d.ts.map +1 -1
  208. package/node_modules/@fps-games/editor-protocol/dist/agent.js.map +1 -1
  209. package/node_modules/@fps-games/editor-protocol/dist/index.d.ts +19 -0
  210. package/node_modules/@fps-games/editor-protocol/dist/index.d.ts.map +1 -1
  211. package/node_modules/@fps-games/editor-protocol/dist/index.js +1 -0
  212. package/node_modules/@fps-games/editor-protocol/dist/index.js.map +1 -1
  213. package/node_modules/@fps-games/editor-protocol/dist/marker-graph.d.ts +128 -0
  214. package/node_modules/@fps-games/editor-protocol/dist/marker-graph.d.ts.map +1 -0
  215. package/node_modules/@fps-games/editor-protocol/dist/marker-graph.js +2 -0
  216. package/node_modules/@fps-games/editor-protocol/dist/marker-graph.js.map +1 -0
  217. package/node_modules/@fps-games/editor-protocol/package.json +1 -1
  218. package/package.json +8 -8
@@ -0,0 +1,1395 @@
1
+ import { isEditorTransformTrsSnapshot, } from '@fps-games/editor-core';
2
+ const UNIT_BOX_LINES = [
3
+ [{ x: -0.5, y: -0.5, z: -0.5 }, { x: 0.5, y: -0.5, z: -0.5 }],
4
+ [{ x: 0.5, y: -0.5, z: -0.5 }, { x: 0.5, y: 0.5, z: -0.5 }],
5
+ [{ x: 0.5, y: 0.5, z: -0.5 }, { x: -0.5, y: 0.5, z: -0.5 }],
6
+ [{ x: -0.5, y: 0.5, z: -0.5 }, { x: -0.5, y: -0.5, z: -0.5 }],
7
+ [{ x: -0.5, y: -0.5, z: 0.5 }, { x: 0.5, y: -0.5, z: 0.5 }],
8
+ [{ x: 0.5, y: -0.5, z: 0.5 }, { x: 0.5, y: 0.5, z: 0.5 }],
9
+ [{ x: 0.5, y: 0.5, z: 0.5 }, { x: -0.5, y: 0.5, z: 0.5 }],
10
+ [{ x: -0.5, y: 0.5, z: 0.5 }, { x: -0.5, y: -0.5, z: 0.5 }],
11
+ [{ x: -0.5, y: -0.5, z: -0.5 }, { x: -0.5, y: -0.5, z: 0.5 }],
12
+ [{ x: 0.5, y: -0.5, z: -0.5 }, { x: 0.5, y: -0.5, z: 0.5 }],
13
+ [{ x: 0.5, y: 0.5, z: -0.5 }, { x: 0.5, y: 0.5, z: 0.5 }],
14
+ [{ x: -0.5, y: 0.5, z: -0.5 }, { x: -0.5, y: 0.5, z: 0.5 }],
15
+ ];
16
+ const MARKER_FRAME_LINES = [
17
+ [{ x: -0.08, y: 0, z: 0 }, { x: 0.08, y: 0, z: 0 }],
18
+ [{ x: 0, y: -0.08, z: 0 }, { x: 0, y: 0.08, z: 0 }],
19
+ [{ x: 0, y: 0, z: -0.08 }, { x: 0, y: 0, z: 0.08 }],
20
+ [{ x: 0, y: 0, z: 0 }, { x: 0, y: 0, z: 0.72 }],
21
+ [{ x: 0, y: 0, z: 0.72 }, { x: -0.08, y: 0, z: 0.58 }],
22
+ [{ x: 0, y: 0, z: 0.72 }, { x: 0.08, y: 0, z: 0.58 }],
23
+ [{ x: 0, y: 0, z: 0.72 }, { x: 0, y: 0.08, z: 0.58 }],
24
+ [{ x: 0, y: 0, z: 0.72 }, { x: 0, y: -0.08, z: 0.58 }],
25
+ ];
26
+ const RELATION_DASH_MAX_COUNT = 64;
27
+ const RELATION_DASH_MIN_SEGMENT_LENGTH = 0.04;
28
+ const RELATION_ACTIVE_PULSE_PERIOD_MS = 1100;
29
+ const MARKER_LABEL_WORLD_SCALE = 1.55;
30
+ export function createBabylonEditorMarkerOverlayController(options) {
31
+ const overlays = new Map();
32
+ const relationOverlays = new Map();
33
+ let relationAnimationObserver = null;
34
+ let relationAnimationTimeMs = 0;
35
+ let disposed = false;
36
+ function disposeOverlay(markerRowId) {
37
+ const overlay = overlays.get(markerRowId);
38
+ if (!overlay)
39
+ return false;
40
+ disposeActiveMarkerOverlay(overlay);
41
+ overlays.delete(markerRowId);
42
+ return true;
43
+ }
44
+ function disposeRelationOverlay(relationId) {
45
+ const overlay = relationOverlays.get(relationId);
46
+ if (!overlay)
47
+ return false;
48
+ disposeActiveMarkerRelationOverlay(overlay);
49
+ relationOverlays.delete(relationId);
50
+ syncRelationAnimationObserver();
51
+ return true;
52
+ }
53
+ function sync(input) {
54
+ if (disposed)
55
+ return false;
56
+ let changed = false;
57
+ const nextRowIds = new Set();
58
+ const selectedMarkerRowIds = new Set(input.selectedMarkerRowIds ?? []);
59
+ for (const entry of input.markers) {
60
+ if (!entry.markerRowId)
61
+ continue;
62
+ const presentation = resolveMarkerOverlayPresentation(entry.marker);
63
+ nextRowIds.add(entry.markerRowId);
64
+ let overlay = overlays.get(entry.markerRowId) ?? null;
65
+ if (!overlay || overlay.markerId !== entry.marker.id || overlay.presentation !== presentation) {
66
+ if (overlay)
67
+ disposeOverlay(entry.markerRowId);
68
+ overlay = createActiveMarkerOverlay(options, entry.markerRowId, entry.marker.id, presentation);
69
+ if (!overlay)
70
+ continue;
71
+ overlays.set(entry.markerRowId, overlay);
72
+ changed = true;
73
+ }
74
+ const selected = entry.selected === true || selectedMarkerRowIds.has(entry.markerRowId);
75
+ const active = entry.active === true || input.activeMarkerRowId === entry.markerRowId;
76
+ const color = readMarkerOverlayColor(entry.marker);
77
+ const labelText = createMarkerOverlayLabelText(entry.marker, entry.markerTypeLabel);
78
+ if (overlay.selected !== selected
79
+ || overlay.active !== active
80
+ || !markerOverlayColorsEqual(overlay.color, color)
81
+ || overlay.labelText !== labelText)
82
+ changed = true;
83
+ overlay.selected = selected;
84
+ overlay.active = active;
85
+ overlay.color = color;
86
+ overlay.labelText = labelText;
87
+ applyMarkerGeometryToOverlay(options, overlay, entry.marker);
88
+ applyMarkerVisualState(options, overlay);
89
+ applyMarkerLabelVisualState(options, overlay);
90
+ changed = true;
91
+ }
92
+ for (const markerRowId of [...overlays.keys()]) {
93
+ if (!nextRowIds.has(markerRowId))
94
+ changed = disposeOverlay(markerRowId) || changed;
95
+ }
96
+ changed = syncRelationOverlays(input.relations ?? []) || changed;
97
+ return changed;
98
+ }
99
+ function getAttachableRoot(markerRowId) {
100
+ if (disposed)
101
+ return null;
102
+ return overlays.get(markerRowId)?.root ?? null;
103
+ }
104
+ function readMarkerTransform(markerRowId) {
105
+ if (disposed)
106
+ return null;
107
+ return readRootTransform(overlays.get(markerRowId)?.root ?? null);
108
+ }
109
+ function readMarkerTransforms(markerRowIds) {
110
+ const transforms = {};
111
+ for (const markerRowId of markerRowIds) {
112
+ const transform = readMarkerTransform(markerRowId);
113
+ if (transform)
114
+ transforms[markerRowId] = transform;
115
+ }
116
+ return transforms;
117
+ }
118
+ function setMarkerTransformPreview(markerRowId, transform) {
119
+ if (disposed)
120
+ return false;
121
+ const overlay = overlays.get(markerRowId);
122
+ if (!overlay)
123
+ return false;
124
+ if (!isEditorTransformTrsSnapshot(transform))
125
+ return false;
126
+ applyTransformToOverlay(options, overlay, transform);
127
+ return true;
128
+ }
129
+ function setMarkerTransformsPreview(transforms) {
130
+ const applied = [];
131
+ for (const [markerRowId, transform] of Object.entries(transforms)) {
132
+ if (setMarkerTransformPreview(markerRowId, transform))
133
+ applied.push(markerRowId);
134
+ }
135
+ return applied;
136
+ }
137
+ function getSelectionPivot(markerRowIds) {
138
+ const transforms = Object.values(readMarkerTransforms(markerRowIds));
139
+ if (transforms.length === 0)
140
+ return null;
141
+ return {
142
+ mode: 'selection-center',
143
+ position: averagePositions(transforms),
144
+ };
145
+ }
146
+ function getSelectionBounds(markerRowIds) {
147
+ const transforms = Object.values(readMarkerTransforms(markerRowIds));
148
+ if (transforms.length === 0)
149
+ return null;
150
+ return combineTransformBounds(transforms);
151
+ }
152
+ function resolvePickSelectionNodeId(target) {
153
+ if (disposed)
154
+ return null;
155
+ let current = target;
156
+ while (current) {
157
+ const markerRowId = current.metadata?.editorMarkerRowId;
158
+ if (typeof markerRowId === 'string' && overlays.has(markerRowId))
159
+ return markerRowId;
160
+ current = current.parent ?? null;
161
+ }
162
+ return null;
163
+ }
164
+ function pickMarkerRowIdAt(clientX, clientY) {
165
+ if (disposed)
166
+ return null;
167
+ const scene = options.scene;
168
+ const canvas = scene.getEngine?.().getRenderingCanvas?.() ?? null;
169
+ if (!canvas || typeof scene.pick !== 'function')
170
+ return null;
171
+ const rect = typeof canvas.getBoundingClientRect === 'function'
172
+ ? canvas.getBoundingClientRect()
173
+ : { left: 0, top: 0 };
174
+ const pickResult = scene.pick(clientX - (rect.left ?? 0), clientY - (rect.top ?? 0), (mesh) => resolvePickSelectionNodeId(mesh) != null);
175
+ return resolvePickSelectionNodeId(pickResult?.pickedMesh ?? null);
176
+ }
177
+ return {
178
+ sync,
179
+ getAttachableRoot,
180
+ readMarkerTransform,
181
+ readMarkerTransforms,
182
+ setMarkerTransformPreview,
183
+ setMarkerTransformsPreview,
184
+ getSelectionPivot,
185
+ getSelectionBounds,
186
+ resolvePickSelectionNodeId,
187
+ pickMarkerRowIdAt,
188
+ dispose() {
189
+ if (disposed)
190
+ return;
191
+ for (const markerRowId of [...overlays.keys()])
192
+ disposeOverlay(markerRowId);
193
+ for (const relationId of [...relationOverlays.keys()])
194
+ disposeRelationOverlay(relationId);
195
+ removeRelationAnimationObserver();
196
+ disposed = true;
197
+ },
198
+ };
199
+ function syncRelationOverlays(relations) {
200
+ let changed = false;
201
+ const nextRelationIds = new Set();
202
+ for (const entry of relations) {
203
+ if (!entry.id)
204
+ continue;
205
+ nextRelationIds.add(entry.id);
206
+ let overlay = relationOverlays.get(entry.id) ?? null;
207
+ if (!overlay) {
208
+ overlay = createActiveMarkerRelationOverlay(options, entry);
209
+ if (!overlay)
210
+ continue;
211
+ relationOverlays.set(entry.id, overlay);
212
+ changed = true;
213
+ }
214
+ const color = entry.color ?? createMarkerRelationOverlayColor(entry.type);
215
+ const directed = entry.directed !== false;
216
+ const active = entry.active === true;
217
+ if (!markerOverlayColorsEqual(overlay.color, color)
218
+ || overlay.directed !== directed
219
+ || overlay.active !== active)
220
+ changed = true;
221
+ overlay.color = color;
222
+ overlay.directed = directed;
223
+ overlay.active = active;
224
+ applyMarkerRelationOverlayState(options, overlay, entry);
225
+ changed = true;
226
+ }
227
+ for (const relationId of [...relationOverlays.keys()]) {
228
+ if (!nextRelationIds.has(relationId))
229
+ changed = disposeRelationOverlay(relationId) || changed;
230
+ }
231
+ syncRelationAnimationObserver();
232
+ return changed;
233
+ }
234
+ function syncRelationAnimationObserver() {
235
+ if (disposed)
236
+ return;
237
+ const shouldAnimate = [...relationOverlays.values()].some(overlay => overlay.active);
238
+ const observable = options.scene.onBeforeRenderObservable;
239
+ if (shouldAnimate && !relationAnimationObserver && typeof observable?.add === 'function') {
240
+ relationAnimationObserver = observable.add(() => updateActiveRelationAnimations());
241
+ updateActiveRelationAnimations(0);
242
+ return;
243
+ }
244
+ if (!shouldAnimate)
245
+ removeRelationAnimationObserver();
246
+ }
247
+ function removeRelationAnimationObserver() {
248
+ if (!relationAnimationObserver)
249
+ return;
250
+ try {
251
+ options.scene.onBeforeRenderObservable?.remove?.(relationAnimationObserver);
252
+ }
253
+ catch { }
254
+ relationAnimationObserver = null;
255
+ }
256
+ function updateActiveRelationAnimations(deltaOverrideMs) {
257
+ const rawDelta = deltaOverrideMs ?? Number(options.scene.getEngine?.()?.getDeltaTime?.() ?? 16.67);
258
+ const deltaMs = Number.isFinite(rawDelta) ? Math.max(0, Math.min(80, rawDelta)) : 16.67;
259
+ relationAnimationTimeMs = (relationAnimationTimeMs + deltaMs) % RELATION_ACTIVE_PULSE_PERIOD_MS;
260
+ for (const overlay of relationOverlays.values()) {
261
+ if (overlay.active)
262
+ applyMarkerRelationPulseFrame(options, overlay, relationAnimationTimeMs);
263
+ }
264
+ }
265
+ }
266
+ export function createBabylonMarkerOverlayProjectionAdapter(projection, markerOverlay) {
267
+ return {
268
+ ...projection,
269
+ getAttachableRoot(nodeId) {
270
+ return markerOverlay.getAttachableRoot(nodeId) ?? projection.getAttachableRoot(nodeId);
271
+ },
272
+ readNodeTransform(nodeId) {
273
+ return markerOverlay.readMarkerTransform(nodeId) ?? projection.readNodeTransform(nodeId);
274
+ },
275
+ readNodeTransforms(nodeIds) {
276
+ return {
277
+ ...projection.readNodeTransforms(nodeIds),
278
+ ...markerOverlay.readMarkerTransforms(nodeIds),
279
+ };
280
+ },
281
+ setNodeTransformPreview(nodeId, transform) {
282
+ if (markerOverlay.setMarkerTransformPreview(nodeId, transform))
283
+ return;
284
+ projection.setNodeTransformPreview(nodeId, transform);
285
+ },
286
+ setNodeTransformsPreview(transforms) {
287
+ const markerIds = new Set(markerOverlay.setMarkerTransformsPreview(transforms));
288
+ const projectionTransforms = {};
289
+ for (const [nodeId, transform] of Object.entries(transforms)) {
290
+ if (!markerIds.has(nodeId))
291
+ projectionTransforms[nodeId] = transform;
292
+ }
293
+ projection.setNodeTransformsPreview(projectionTransforms);
294
+ },
295
+ syncNodeMetadata(node) {
296
+ projection.syncNodeMetadata(node);
297
+ },
298
+ getSelectionPivot(nodeIds) {
299
+ const markerPivot = markerOverlay.getSelectionPivot(nodeIds);
300
+ if (!markerPivot)
301
+ return projection.getSelectionPivot(nodeIds);
302
+ const transforms = {
303
+ ...projection.readNodeTransforms(nodeIds),
304
+ ...markerOverlay.readMarkerTransforms(nodeIds),
305
+ };
306
+ const values = Object.values(transforms).filter(isEditorTransformTrsSnapshot);
307
+ return values.length > 0
308
+ ? { mode: 'selection-center', position: averagePositions(values) }
309
+ : markerPivot;
310
+ },
311
+ getSelectionBounds(nodeIds) {
312
+ const markerBounds = markerOverlay.getSelectionBounds(nodeIds);
313
+ const projectionBounds = projection.getSelectionBounds(nodeIds);
314
+ return combineBounds(projectionBounds, markerBounds);
315
+ },
316
+ resolvePickSelectionNodeId(target) {
317
+ return markerOverlay.resolvePickSelectionNodeId(target) ?? projection.resolvePickSelectionNodeId(target);
318
+ },
319
+ pickNodeIdAt(clientX, clientY) {
320
+ return markerOverlay.pickMarkerRowIdAt(clientX, clientY) ?? projection.pickNodeIdAt(clientX, clientY);
321
+ },
322
+ };
323
+ }
324
+ function createActiveMarkerOverlay(options, markerRowId, markerId, presentation) {
325
+ const TransformNode = options.babylon.TransformNode;
326
+ if (!TransformNode)
327
+ return null;
328
+ const root = new TransformNode(`editor.markerGraph.${presentation}.${markerId}`, options.scene);
329
+ root.metadata = {
330
+ ...(root.metadata ?? {}),
331
+ editorProjectionHelper: true,
332
+ editorMarkerOverlay: true,
333
+ editorMarkerPresentation: presentation,
334
+ editorMarkerId: markerId,
335
+ editorMarkerRowId: markerRowId,
336
+ };
337
+ root.isPickable = false;
338
+ const lines = presentation === 'region' || presentation === 'object'
339
+ ? createBoxLineHelper(options, root, markerId, markerRowId)
340
+ : null;
341
+ const frameHelper = createMarkerFrameHelper(options, markerId, markerRowId);
342
+ const { pickMesh, pickMaterial } = presentation === 'region' || presentation === 'object'
343
+ ? createBoxPickHelper(options, root, markerId, markerRowId)
344
+ : createPointPickHelper(options, root, markerId, markerRowId, presentation);
345
+ const { labelRoot, labelPlane, labelMaterial, labelTexture } = createMarkerLabelHelper(options, markerId, markerRowId);
346
+ return {
347
+ markerRowId,
348
+ markerId,
349
+ presentation,
350
+ root,
351
+ lines,
352
+ ...frameHelper,
353
+ pickMesh,
354
+ pickMaterial,
355
+ labelRoot,
356
+ labelPlane,
357
+ labelMaterial,
358
+ labelTexture,
359
+ labelText: '',
360
+ selected: false,
361
+ active: false,
362
+ color: createMarkerOverlayColor(0.1, 0.85, 1),
363
+ };
364
+ }
365
+ function disposeActiveMarkerOverlay(overlay) {
366
+ try {
367
+ overlay.lines?.dispose?.();
368
+ }
369
+ catch { }
370
+ try {
371
+ overlay.anchorMesh?.dispose?.();
372
+ }
373
+ catch { }
374
+ try {
375
+ overlay.forwardShaft?.dispose?.();
376
+ }
377
+ catch { }
378
+ try {
379
+ overlay.forwardHead?.dispose?.();
380
+ }
381
+ catch { }
382
+ try {
383
+ overlay.frameLines?.dispose?.();
384
+ }
385
+ catch { }
386
+ try {
387
+ overlay.frameMaterial?.dispose?.();
388
+ }
389
+ catch { }
390
+ try {
391
+ overlay.frameRoot?.dispose?.();
392
+ }
393
+ catch { }
394
+ try {
395
+ overlay.pickMesh?.dispose?.();
396
+ }
397
+ catch { }
398
+ try {
399
+ overlay.pickMaterial?.dispose?.();
400
+ }
401
+ catch { }
402
+ try {
403
+ overlay.labelPlane?.dispose?.();
404
+ }
405
+ catch { }
406
+ try {
407
+ overlay.labelTexture?.dispose?.();
408
+ }
409
+ catch { }
410
+ try {
411
+ overlay.labelMaterial?.dispose?.();
412
+ }
413
+ catch { }
414
+ try {
415
+ overlay.labelRoot?.dispose?.();
416
+ }
417
+ catch { }
418
+ try {
419
+ overlay.root?.dispose?.();
420
+ }
421
+ catch { }
422
+ }
423
+ function createActiveMarkerRelationOverlay(options, entry) {
424
+ const TransformNode = options.babylon.TransformNode;
425
+ const MeshBuilder = options.babylon.MeshBuilder;
426
+ const StandardMaterial = options.babylon.StandardMaterial;
427
+ const Color3 = options.babylon.Color3;
428
+ if (!TransformNode || !MeshBuilder?.CreateCylinder)
429
+ return null;
430
+ const root = new TransformNode(`editor.markerGraph.relation.${entry.id}`, options.scene);
431
+ root.metadata = createMarkerRelationMetadata(root.metadata, entry);
432
+ root.isPickable = false;
433
+ const material = StandardMaterial
434
+ ? new StandardMaterial(`editor.markerGraph.relation.${entry.id}.material`, options.scene)
435
+ : null;
436
+ if (material) {
437
+ material.backFaceCulling = false;
438
+ material.disableLighting = true;
439
+ material.disableDepthWrite = true;
440
+ material.alpha = 0.96;
441
+ material.zOffset = -3;
442
+ }
443
+ if (Color3 && material) {
444
+ const color = entry.color ?? createMarkerRelationOverlayColor(entry.type);
445
+ material.diffuseColor = new Color3(color.r, color.g, color.b);
446
+ material.emissiveColor = new Color3(color.r, color.g, color.b);
447
+ }
448
+ const arrowHead = MeshBuilder.CreateCylinder
449
+ ? MeshBuilder.CreateCylinder(`editor.markerGraph.relation.${entry.id}.arrow`, { height: 1, diameterTop: 0, diameterBottom: 1, tessellation: 24 }, options.scene)
450
+ : null;
451
+ if (arrowHead) {
452
+ arrowHead.parent = root;
453
+ arrowHead.isPickable = false;
454
+ arrowHead.metadata = createMarkerRelationMetadata(arrowHead.metadata, entry, {
455
+ editorMarkerRelationArrow: true,
456
+ });
457
+ arrowHead.renderingGroupId = 2;
458
+ arrowHead.material = material;
459
+ }
460
+ return {
461
+ id: entry.id,
462
+ root,
463
+ dashMeshes: [],
464
+ dashGeometryKey: '',
465
+ arrowHead,
466
+ material,
467
+ color: entry.color ?? createMarkerRelationOverlayColor(entry.type),
468
+ directed: entry.directed !== false,
469
+ active: entry.active === true,
470
+ };
471
+ }
472
+ function disposeActiveMarkerRelationOverlay(overlay) {
473
+ disposeMarkerRelationDashMeshes(overlay);
474
+ try {
475
+ overlay.arrowHead?.dispose?.();
476
+ }
477
+ catch { }
478
+ try {
479
+ overlay.material?.dispose?.();
480
+ }
481
+ catch { }
482
+ try {
483
+ overlay.root?.dispose?.();
484
+ }
485
+ catch { }
486
+ }
487
+ function createMarkerRelationMetadata(metadata, entry, extras) {
488
+ return {
489
+ ...(metadata ?? {}),
490
+ editorProjectionHelper: true,
491
+ editorMarkerOverlay: true,
492
+ editorMarkerRelationOverlay: true,
493
+ editorMarkerRelationId: entry.id,
494
+ editorMarkerRelationType: entry.type,
495
+ ...(extras ?? {}),
496
+ };
497
+ }
498
+ function createMarkerFrameHelper(options, markerId, markerRowId) {
499
+ const TransformNode = options.babylon.TransformNode;
500
+ const MeshBuilder = options.babylon.MeshBuilder;
501
+ const StandardMaterial = options.babylon.StandardMaterial;
502
+ const Color3 = options.babylon.Color3;
503
+ const Vector3 = options.babylon.Vector3;
504
+ if (!TransformNode || !Vector3) {
505
+ return {
506
+ frameRoot: null,
507
+ frameLines: null,
508
+ anchorMesh: null,
509
+ forwardShaft: null,
510
+ forwardHead: null,
511
+ frameMaterial: null,
512
+ };
513
+ }
514
+ const frameRoot = new TransformNode(`editor.markerGraph.box.${markerId}.frameRoot`, options.scene);
515
+ frameRoot.metadata = createMarkerFrameMetadata(frameRoot.metadata, markerId, markerRowId);
516
+ frameRoot.isPickable = false;
517
+ let frameMaterial = null;
518
+ if (StandardMaterial) {
519
+ frameMaterial = new StandardMaterial(`editor.markerGraph.box.${markerId}.frameMaterial`, options.scene);
520
+ if (Color3) {
521
+ frameMaterial.diffuseColor = new Color3(1, 0.9, 0.08);
522
+ frameMaterial.emissiveColor = new Color3(1, 0.72, 0.05);
523
+ }
524
+ frameMaterial.alpha = 0.98;
525
+ frameMaterial.backFaceCulling = false;
526
+ frameMaterial.disableLighting = true;
527
+ frameMaterial.disableDepthWrite = true;
528
+ frameMaterial.zOffset = -2;
529
+ }
530
+ const anchorMesh = MeshBuilder?.CreateSphere
531
+ ? MeshBuilder.CreateSphere(`editor.markerGraph.box.${markerId}.anchor`, { diameter: 1, segments: 16 }, options.scene)
532
+ : null;
533
+ if (anchorMesh)
534
+ configureMarkerFrameMesh(anchorMesh, frameRoot, frameMaterial, markerId, markerRowId);
535
+ const forwardShaft = MeshBuilder?.CreateCylinder
536
+ ? MeshBuilder.CreateCylinder(`editor.markerGraph.box.${markerId}.forwardShaft`, { height: 1, diameter: 1, tessellation: 16 }, options.scene)
537
+ : null;
538
+ if (forwardShaft) {
539
+ configureMarkerFrameMesh(forwardShaft, frameRoot, frameMaterial, markerId, markerRowId);
540
+ forwardShaft.rotation = new Vector3(Math.PI / 2, 0, 0);
541
+ }
542
+ const forwardHead = MeshBuilder?.CreateCylinder
543
+ ? MeshBuilder.CreateCylinder(`editor.markerGraph.box.${markerId}.forwardHead`, { height: 1, diameterTop: 0, diameterBottom: 1, tessellation: 24 }, options.scene)
544
+ : null;
545
+ if (forwardHead) {
546
+ configureMarkerFrameMesh(forwardHead, frameRoot, frameMaterial, markerId, markerRowId);
547
+ forwardHead.rotation = new Vector3(Math.PI / 2, 0, 0);
548
+ }
549
+ const frameLines = !anchorMesh && !forwardShaft && !forwardHead && MeshBuilder?.CreateLineSystem
550
+ ? MeshBuilder.CreateLineSystem(`editor.markerGraph.box.${markerId}.frame`, {
551
+ lines: MARKER_FRAME_LINES.map(line => line.map(point => new Vector3(point.x, point.y, point.z))),
552
+ updatable: false,
553
+ }, options.scene)
554
+ : null;
555
+ if (frameLines) {
556
+ frameLines.parent = frameRoot;
557
+ frameLines.isPickable = true;
558
+ frameLines.metadata = createMarkerFrameMetadata(frameLines.metadata, markerId, markerRowId);
559
+ frameLines.renderingGroupId = 2;
560
+ if (Color3)
561
+ frameLines.color = new Color3(1, 0.9, 0.08);
562
+ }
563
+ return {
564
+ frameRoot,
565
+ frameLines,
566
+ anchorMesh,
567
+ forwardShaft,
568
+ forwardHead,
569
+ frameMaterial,
570
+ };
571
+ }
572
+ function configureMarkerFrameMesh(mesh, frameRoot, material, markerId, markerRowId) {
573
+ mesh.parent = frameRoot;
574
+ mesh.isPickable = true;
575
+ mesh.material = material;
576
+ mesh.metadata = createMarkerFrameMetadata(mesh.metadata, markerId, markerRowId);
577
+ mesh.renderingGroupId = 2;
578
+ }
579
+ function createMarkerFrameMetadata(metadata, markerId, markerRowId) {
580
+ return {
581
+ ...(metadata ?? {}),
582
+ editorProjectionHelper: true,
583
+ editorMarkerOverlay: true,
584
+ editorMarkerFrame: true,
585
+ editorMarkerId: markerId,
586
+ editorMarkerRowId: markerRowId,
587
+ };
588
+ }
589
+ function createBoxLineHelper(options, root, markerId, markerRowId) {
590
+ const MeshBuilder = options.babylon.MeshBuilder;
591
+ const Color3 = options.babylon.Color3;
592
+ const Vector3 = options.babylon.Vector3;
593
+ if (!MeshBuilder?.CreateLineSystem || !Vector3)
594
+ return null;
595
+ const lines = MeshBuilder.CreateLineSystem(`editor.markerGraph.box.${markerId}.lines`, {
596
+ lines: UNIT_BOX_LINES.map(line => line.map(point => new Vector3(point.x, point.y, point.z))),
597
+ updatable: false,
598
+ }, options.scene);
599
+ lines.parent = root;
600
+ lines.isPickable = true;
601
+ lines.metadata = {
602
+ ...(lines.metadata ?? {}),
603
+ editorProjectionHelper: true,
604
+ editorMarkerOverlay: true,
605
+ editorMarkerId: markerId,
606
+ editorMarkerRowId: markerRowId,
607
+ };
608
+ if (Color3)
609
+ lines.color = new Color3(0.1, 0.85, 1);
610
+ return lines;
611
+ }
612
+ function createBoxPickHelper(options, root, markerId, markerRowId) {
613
+ const MeshBuilder = options.babylon.MeshBuilder;
614
+ const StandardMaterial = options.babylon.StandardMaterial;
615
+ const Color3 = options.babylon.Color3;
616
+ if (!MeshBuilder?.CreateBox)
617
+ return { pickMesh: null, pickMaterial: null };
618
+ const pickMesh = MeshBuilder.CreateBox(`editor.markerGraph.box.${markerId}.pick`, { size: 1 }, options.scene);
619
+ pickMesh.parent = root;
620
+ pickMesh.isPickable = true;
621
+ pickMesh.metadata = {
622
+ ...(pickMesh.metadata ?? {}),
623
+ editorProjectionHelper: true,
624
+ editorMarkerOverlay: true,
625
+ editorMarkerOverlayPickTarget: true,
626
+ editorMarkerId: markerId,
627
+ editorMarkerRowId: markerRowId,
628
+ };
629
+ let pickMaterial = null;
630
+ if (StandardMaterial) {
631
+ pickMaterial = new StandardMaterial(`editor.markerGraph.box.${markerId}.material`, options.scene);
632
+ if (Color3) {
633
+ pickMaterial.diffuseColor = new Color3(0.1, 0.85, 1);
634
+ pickMaterial.emissiveColor = new Color3(0.02, 0.18, 0.22);
635
+ }
636
+ pickMaterial.alpha = 0.065;
637
+ pickMaterial.backFaceCulling = false;
638
+ pickMesh.material = pickMaterial;
639
+ }
640
+ else {
641
+ pickMesh.visibility = 0.065;
642
+ }
643
+ return { pickMesh, pickMaterial };
644
+ }
645
+ function createPointPickHelper(options, root, markerId, markerRowId, presentation) {
646
+ const MeshBuilder = options.babylon.MeshBuilder;
647
+ const StandardMaterial = options.babylon.StandardMaterial;
648
+ const Color3 = options.babylon.Color3;
649
+ if (!MeshBuilder?.CreateSphere)
650
+ return { pickMesh: null, pickMaterial: null };
651
+ const diameter = presentation === 'anchor' ? 0.82 : presentation === 'object' ? 0.72 : 0.62;
652
+ const pickMesh = MeshBuilder.CreateSphere(`editor.markerGraph.${presentation}.${markerId}.pick`, { diameter, segments: 24 }, options.scene);
653
+ pickMesh.parent = root;
654
+ pickMesh.isPickable = true;
655
+ pickMesh.metadata = {
656
+ ...(pickMesh.metadata ?? {}),
657
+ editorProjectionHelper: true,
658
+ editorMarkerOverlay: true,
659
+ editorMarkerOverlayPickTarget: true,
660
+ editorMarkerPresentation: presentation,
661
+ editorMarkerId: markerId,
662
+ editorMarkerRowId: markerRowId,
663
+ };
664
+ let pickMaterial = null;
665
+ if (StandardMaterial) {
666
+ pickMaterial = new StandardMaterial(`editor.markerGraph.${presentation}.${markerId}.material`, options.scene);
667
+ if (Color3) {
668
+ pickMaterial.diffuseColor = new Color3(0.1, 0.85, 1);
669
+ pickMaterial.emissiveColor = new Color3(0.04, 0.35, 0.42);
670
+ }
671
+ pickMaterial.alpha = 0.38;
672
+ pickMaterial.backFaceCulling = false;
673
+ pickMaterial.disableLighting = true;
674
+ pickMesh.material = pickMaterial;
675
+ }
676
+ else {
677
+ pickMesh.visibility = 0.38;
678
+ }
679
+ return { pickMesh, pickMaterial };
680
+ }
681
+ function createMarkerLabelHelper(options, markerId, markerRowId) {
682
+ const TransformNode = options.babylon.TransformNode;
683
+ const MeshBuilder = options.babylon.MeshBuilder;
684
+ const StandardMaterial = options.babylon.StandardMaterial;
685
+ const DynamicTexture = options.babylon.DynamicTexture;
686
+ const Color3 = options.babylon.Color3;
687
+ const Mesh = options.babylon.Mesh;
688
+ if (!TransformNode)
689
+ return { labelRoot: null, labelPlane: null, labelMaterial: null, labelTexture: null };
690
+ const labelRoot = new TransformNode(`editor.markerGraph.box.${markerId}.labelRoot`, options.scene);
691
+ labelRoot.metadata = {
692
+ ...(labelRoot.metadata ?? {}),
693
+ editorProjectionHelper: true,
694
+ editorMarkerOverlay: true,
695
+ editorMarkerLabel: true,
696
+ editorMarkerId: markerId,
697
+ editorMarkerRowId: markerRowId,
698
+ };
699
+ labelRoot.isPickable = false;
700
+ if (!MeshBuilder?.CreatePlane)
701
+ return { labelRoot, labelPlane: null, labelMaterial: null, labelTexture: null };
702
+ const labelPlane = MeshBuilder.CreatePlane(`editor.markerGraph.box.${markerId}.label`, { size: 1 }, options.scene);
703
+ labelPlane.parent = labelRoot;
704
+ labelPlane.isPickable = false;
705
+ labelPlane.billboardMode = Mesh?.BILLBOARDMODE_ALL ?? 7;
706
+ labelPlane.metadata = {
707
+ ...(labelPlane.metadata ?? {}),
708
+ editorProjectionHelper: true,
709
+ editorMarkerOverlay: true,
710
+ editorMarkerLabel: true,
711
+ editorMarkerId: markerId,
712
+ editorMarkerRowId: markerRowId,
713
+ };
714
+ let labelTexture = null;
715
+ let labelMaterial = null;
716
+ if (DynamicTexture) {
717
+ labelTexture = new DynamicTexture(`editor.markerGraph.box.${markerId}.labelTexture`, { width: 512, height: 192 }, options.scene, false);
718
+ labelTexture.hasAlpha = true;
719
+ }
720
+ if (StandardMaterial) {
721
+ labelMaterial = new StandardMaterial(`editor.markerGraph.box.${markerId}.labelMaterial`, options.scene);
722
+ if (Color3) {
723
+ labelMaterial.emissiveColor = new Color3(1, 1, 1);
724
+ labelMaterial.diffuseColor = new Color3(1, 1, 1);
725
+ }
726
+ labelMaterial.backFaceCulling = false;
727
+ labelMaterial.disableLighting = true;
728
+ labelMaterial.alpha = 0.94;
729
+ if (labelTexture) {
730
+ labelMaterial.diffuseTexture = labelTexture;
731
+ labelMaterial.emissiveTexture = labelTexture;
732
+ labelMaterial.useAlphaFromDiffuseTexture = true;
733
+ }
734
+ labelPlane.material = labelMaterial;
735
+ }
736
+ return { labelRoot, labelPlane, labelMaterial, labelTexture };
737
+ }
738
+ function applyMarkerVisualState(options, overlay) {
739
+ const Color3 = options.babylon.Color3;
740
+ const selected = overlay.selected || overlay.active;
741
+ if (Color3 && overlay.lines) {
742
+ const lineColor = selected ? brightenMarkerOverlayColor(overlay.color, 0.28) : overlay.color;
743
+ overlay.lines.color = new Color3(lineColor.r, lineColor.g, lineColor.b);
744
+ }
745
+ if (Color3 && overlay.frameLines) {
746
+ const frameColor = selected ? createMarkerOverlayColor(1, 0.96, 0.22) : createMarkerOverlayColor(1, 0.78, 0.08);
747
+ overlay.frameLines.color = new Color3(frameColor.r, frameColor.g, frameColor.b);
748
+ }
749
+ if (Color3 && overlay.frameMaterial) {
750
+ const frameColor = selected ? createMarkerOverlayColor(1, 0.96, 0.22) : createMarkerOverlayColor(1, 0.78, 0.08);
751
+ overlay.frameMaterial.diffuseColor = new Color3(frameColor.r, frameColor.g, frameColor.b);
752
+ overlay.frameMaterial.emissiveColor = new Color3(frameColor.r, Math.max(0.45, frameColor.g * 0.82), 0.04);
753
+ overlay.frameMaterial.alpha = selected ? 1 : 0.96;
754
+ }
755
+ const alpha = overlay.presentation === 'region'
756
+ ? (overlay.active ? 0.18 : overlay.selected ? 0.13 : 0.065)
757
+ : overlay.presentation === 'object'
758
+ ? (overlay.active ? 0.16 : overlay.selected ? 0.1 : 0.055)
759
+ : (overlay.active ? 0.84 : overlay.selected ? 0.68 : 0.46);
760
+ if (overlay.pickMaterial) {
761
+ overlay.pickMaterial.alpha = alpha;
762
+ if (Color3) {
763
+ const fillColor = selected ? brightenMarkerOverlayColor(overlay.color, 0.18) : overlay.color;
764
+ overlay.pickMaterial.diffuseColor = new Color3(fillColor.r, fillColor.g, fillColor.b);
765
+ overlay.pickMaterial.emissiveColor = new Color3(Math.min(0.28, fillColor.r * 0.18), Math.min(0.28, fillColor.g * 0.18), Math.min(0.28, fillColor.b * 0.18));
766
+ }
767
+ }
768
+ else if (overlay.pickMesh) {
769
+ overlay.pickMesh.visibility = alpha;
770
+ }
771
+ }
772
+ function applyMarkerRelationOverlayState(options, overlay, entry) {
773
+ const Color3 = options.babylon.Color3;
774
+ const active = entry.active === true;
775
+ const visualColor = active ? createMarkerOverlayColor(1, 0.86, 0.1) : overlay.color;
776
+ if (Color3 && overlay.material) {
777
+ overlay.material.diffuseColor = new Color3(visualColor.r, visualColor.g, visualColor.b);
778
+ overlay.material.emissiveColor = new Color3(visualColor.r, visualColor.g, visualColor.b);
779
+ overlay.material.alpha = active ? 1 : 0.96;
780
+ overlay.material.zOffset = active ? -5 : -3;
781
+ }
782
+ const directed = entry.directed !== false;
783
+ updateMarkerRelationDashes(options, overlay, entry, directed, active);
784
+ updateMarkerRelationArrow(options, overlay, entry.from, entry.to, directed, active);
785
+ if (active)
786
+ applyMarkerRelationPulseFrame(options, overlay, 0);
787
+ else
788
+ resetMarkerRelationPulseState(options, overlay);
789
+ }
790
+ function applyMarkerRelationPulseFrame(options, overlay, timeMs) {
791
+ const Color3 = options.babylon.Color3;
792
+ const Vector3 = options.babylon.Vector3;
793
+ const phase = (timeMs % RELATION_ACTIVE_PULSE_PERIOD_MS) / RELATION_ACTIVE_PULSE_PERIOD_MS;
794
+ const pulse = 0.5 + 0.5 * Math.sin(phase * Math.PI * 2);
795
+ const color = brightenMarkerOverlayColor(createMarkerOverlayColor(1, 0.86, 0.08), 0.38 * pulse);
796
+ if (Color3 && overlay.material) {
797
+ overlay.material.diffuseColor = new Color3(color.r, color.g, color.b);
798
+ overlay.material.emissiveColor = new Color3(color.r, color.g, color.b);
799
+ overlay.material.alpha = 0.72 + 0.28 * pulse;
800
+ overlay.material.zOffset = -6;
801
+ }
802
+ if (Vector3) {
803
+ const pulseScale = 1.0 + 0.55 * pulse;
804
+ for (const dash of overlay.dashMeshes) {
805
+ dash.scaling = new Vector3(pulseScale, 1, pulseScale);
806
+ }
807
+ }
808
+ }
809
+ function resetMarkerRelationPulseState(options, overlay) {
810
+ const Vector3 = options.babylon.Vector3;
811
+ if (!Vector3)
812
+ return;
813
+ for (const dash of overlay.dashMeshes) {
814
+ dash.scaling = new Vector3(1, 1, 1);
815
+ }
816
+ }
817
+ function updateMarkerRelationDashes(options, overlay, entry, directed, active) {
818
+ const MeshBuilder = options.babylon.MeshBuilder;
819
+ const Vector3 = options.babylon.Vector3;
820
+ if (!MeshBuilder?.CreateCylinder || !Vector3)
821
+ return;
822
+ const nextDashGeometryKey = createMarkerRelationDashGeometryKey(entry.from, entry.to, directed, active);
823
+ if (overlay.dashGeometryKey === nextDashGeometryKey)
824
+ return;
825
+ overlay.dashGeometryKey = nextDashGeometryKey;
826
+ disposeMarkerRelationDashMeshes(overlay);
827
+ const direction = subtractVec3(entry.to, entry.from);
828
+ const length = vec3Length(direction);
829
+ if (length < 0.000001)
830
+ return;
831
+ const unit = scaleVec3(direction, 1 / length);
832
+ const arrowClearance = directed ? Math.max(0.28, Math.min(0.56, length * 0.14)) : 0;
833
+ const usableLength = Math.max(0, length - arrowClearance);
834
+ if (usableLength < RELATION_DASH_MIN_SEGMENT_LENGTH)
835
+ return;
836
+ const dashLength = Math.max(0.3, Math.min(0.74, length * 0.12));
837
+ const gapLength = Math.max(0.18, Math.min(0.44, dashLength * 0.62));
838
+ const baseDashDiameter = Math.max(0.0375, Math.min(0.065, length * 0.009));
839
+ const dashDiameter = active ? baseDashDiameter * 2.6 : baseDashDiameter;
840
+ let cursor = 0;
841
+ let dashIndex = 0;
842
+ while (cursor < usableLength && dashIndex < RELATION_DASH_MAX_COUNT) {
843
+ const dashEnd = Math.min(cursor + dashLength, usableLength);
844
+ const segmentLength = dashEnd - cursor;
845
+ if (segmentLength >= RELATION_DASH_MIN_SEGMENT_LENGTH) {
846
+ const segmentCenterDistance = cursor + segmentLength / 2;
847
+ const center = addVec3(entry.from, scaleVec3(unit, segmentCenterDistance));
848
+ const dash = MeshBuilder.CreateCylinder(`editor.markerGraph.relation.${entry.id}.dash.${dashIndex}`, {
849
+ height: segmentLength,
850
+ diameter: dashDiameter,
851
+ tessellation: 12,
852
+ }, options.scene);
853
+ if (dash) {
854
+ dash.parent = overlay.root;
855
+ dash.isPickable = false;
856
+ dash.metadata = createMarkerRelationMetadata(dash.metadata, entry, {
857
+ editorMarkerRelationDash: true,
858
+ editorMarkerRelationDashIndex: dashIndex,
859
+ });
860
+ dash.renderingGroupId = 2;
861
+ dash.material = overlay.material;
862
+ dash.position = new Vector3(center.x, center.y, center.z);
863
+ dash.rotationQuaternion = null;
864
+ dash.rotation = createCylinderRotationTowardDirection(options, unit);
865
+ overlay.dashMeshes.push(dash);
866
+ }
867
+ }
868
+ cursor += dashLength + gapLength;
869
+ dashIndex += 1;
870
+ }
871
+ }
872
+ function disposeMarkerRelationDashMeshes(overlay) {
873
+ for (const dash of overlay.dashMeshes) {
874
+ try {
875
+ dash?.dispose?.();
876
+ }
877
+ catch { }
878
+ }
879
+ overlay.dashMeshes = [];
880
+ }
881
+ function createMarkerRelationDashGeometryKey(from, to, directed, active) {
882
+ return [
883
+ from.x,
884
+ from.y,
885
+ from.z,
886
+ to.x,
887
+ to.y,
888
+ to.z,
889
+ ].map(value => value.toFixed(4)).join(':') + `:${directed ? 1 : 0}:${active ? 1 : 0}`;
890
+ }
891
+ function updateMarkerRelationArrow(options, overlay, from, to, directed, active) {
892
+ const Vector3 = options.babylon.Vector3;
893
+ if (!overlay.arrowHead || !Vector3)
894
+ return;
895
+ overlay.arrowHead.setEnabled?.(directed);
896
+ overlay.arrowHead.isVisible = directed;
897
+ if (!directed)
898
+ return;
899
+ const direction = subtractVec3(to, from);
900
+ const length = vec3Length(direction);
901
+ if (length < 0.000001) {
902
+ overlay.arrowHead.isVisible = false;
903
+ return;
904
+ }
905
+ const unit = scaleVec3(direction, 1 / length);
906
+ const arrowLength = Math.max(0.18, Math.min(0.42, length * 0.12));
907
+ const baseArrowDiameter = Math.max(0.12, Math.min(0.28, arrowLength * 0.72));
908
+ const arrowDiameter = active ? baseArrowDiameter * 1.35 : baseArrowDiameter;
909
+ const center = addVec3(to, scaleVec3(unit, -arrowLength / 2));
910
+ overlay.arrowHead.position = new Vector3(center.x, center.y, center.z);
911
+ overlay.arrowHead.scaling = new Vector3(arrowDiameter, arrowLength, arrowDiameter);
912
+ overlay.arrowHead.rotationQuaternion = null;
913
+ overlay.arrowHead.rotation = createCylinderRotationTowardDirection(options, unit);
914
+ }
915
+ function createCylinderRotationTowardDirection(options, direction) {
916
+ const Vector3 = options.babylon.Vector3;
917
+ const yaw = Math.atan2(direction.x, direction.z);
918
+ const horizontal = Math.sqrt(direction.x * direction.x + direction.z * direction.z);
919
+ const pitch = Math.atan2(direction.y, horizontal);
920
+ return Vector3 ? new Vector3(Math.PI / 2 - pitch, yaw, 0) : { x: Math.PI / 2 - pitch, y: yaw, z: 0 };
921
+ }
922
+ function applyMarkerLabelTransform(options, overlay, transform) {
923
+ if (!isEditorTransformTrsSnapshot(transform))
924
+ return;
925
+ const Vector3 = options.babylon.Vector3;
926
+ if (!overlay.labelRoot || !Vector3)
927
+ return;
928
+ overlay.labelRoot.position = new Vector3(transform.position.x, transform.position.y + Math.abs(transform.scale.y) / 2 + 0.78, transform.position.z);
929
+ overlay.labelRoot.rotationQuaternion = null;
930
+ overlay.labelRoot.rotation = new Vector3(0, 0, 0);
931
+ overlay.labelRoot.scaling = new Vector3(1, 1, 1);
932
+ }
933
+ function applyMarkerLabelVisualState(options, overlay) {
934
+ if (!overlay.labelPlane)
935
+ return;
936
+ const Vector3 = options.babylon.Vector3;
937
+ const lines = normalizeMarkerOverlayLabelLines(overlay.labelText);
938
+ const maxChars = Math.max(...lines.map(line => line.length), 8);
939
+ const width = Math.max(0.85, Math.min(1.85, 0.045 * maxChars + 0.35)) * MARKER_LABEL_WORLD_SCALE;
940
+ const height = Math.max(0.3, Math.min(0.54, 0.11 * lines.length + 0.16)) * MARKER_LABEL_WORLD_SCALE;
941
+ if (Vector3)
942
+ overlay.labelPlane.scaling = new Vector3(width, height, 1);
943
+ updateMarkerLabelTexture(options, overlay, lines);
944
+ if (overlay.labelMaterial)
945
+ overlay.labelMaterial.alpha = overlay.active || overlay.selected ? 0.98 : 0.86;
946
+ }
947
+ function updateMarkerLabelTexture(_options, overlay, lines) {
948
+ const texture = overlay.labelTexture;
949
+ if (!texture)
950
+ return;
951
+ const context = texture.getContext?.();
952
+ if (!context) {
953
+ texture.drawText?.(lines.join(' / '), 18, 76, 'bold 42px sans-serif', 'rgba(255, 255, 255, 0.94)', 'rgba(12, 18, 24, 0.86)', true);
954
+ return;
955
+ }
956
+ const width = 512;
957
+ const height = 192;
958
+ context.save?.();
959
+ context.clearRect?.(0, 0, width, height);
960
+ context.fillStyle = 'rgba(12, 18, 24, 0.78)';
961
+ context.fillRect?.(0, 0, width, height);
962
+ context.fillStyle = markerOverlayColorToCss(overlay.color);
963
+ context.fillRect?.(0, 0, 10, height);
964
+ context.fillStyle = 'rgba(255, 255, 255, 0.94)';
965
+ context.font = '700 42px system-ui, -apple-system, BlinkMacSystemFont, sans-serif';
966
+ context.textBaseline = 'top';
967
+ context.fillText?.(truncateMarkerLabelLine(lines[0] ?? '', 26), 28, 22);
968
+ context.font = '600 30px system-ui, -apple-system, BlinkMacSystemFont, sans-serif';
969
+ context.fillStyle = 'rgba(225, 235, 245, 0.86)';
970
+ if (lines[1])
971
+ context.fillText?.(truncateMarkerLabelLine(lines[1], 34), 28, 78);
972
+ if (lines[2])
973
+ context.fillText?.(truncateMarkerLabelLine(lines[2], 40), 28, 120);
974
+ context.restore?.();
975
+ texture.update?.();
976
+ }
977
+ function createMarkerOverlayLabelText(marker, markerTypeLabel) {
978
+ const tags = marker.tags?.filter(tag => !!tag.trim()).join(', ') ?? '';
979
+ return [
980
+ marker.label,
981
+ `Type: ${markerTypeLabel || marker.markerType}`,
982
+ tags ? `Tags: ${tags}` : '',
983
+ ].filter(Boolean).join('\n');
984
+ }
985
+ function normalizeMarkerOverlayLabelLines(text) {
986
+ const lines = text.split('\n').map(line => line.trim()).filter(Boolean);
987
+ return lines.length > 0 ? lines.slice(0, 3) : ['Marker'];
988
+ }
989
+ function truncateMarkerLabelLine(line, maxLength) {
990
+ return line.length > maxLength ? `${line.slice(0, Math.max(0, maxLength - 1))}...` : line;
991
+ }
992
+ function markerOverlayColorToCss(color) {
993
+ const r = Math.round(Math.min(1, Math.max(0, color.r)) * 255);
994
+ const g = Math.round(Math.min(1, Math.max(0, color.g)) * 255);
995
+ const b = Math.round(Math.min(1, Math.max(0, color.b)) * 255);
996
+ return `rgb(${r}, ${g}, ${b})`;
997
+ }
998
+ function readMarkerOverlayColor(marker) {
999
+ const raw = marker.metadata?.color;
1000
+ if (!raw || typeof raw !== 'object')
1001
+ return createMarkerOverlayColor(0.1, 0.85, 1);
1002
+ const candidate = raw;
1003
+ const r = readMarkerOverlayColorChannel(candidate.r);
1004
+ const g = readMarkerOverlayColorChannel(candidate.g);
1005
+ const b = readMarkerOverlayColorChannel(candidate.b);
1006
+ return r == null || g == null || b == null
1007
+ ? createMarkerOverlayColor(0.1, 0.85, 1)
1008
+ : createMarkerOverlayColor(r, g, b);
1009
+ }
1010
+ function readMarkerOverlayColorChannel(value) {
1011
+ const channel = Number(value);
1012
+ if (!Number.isFinite(channel))
1013
+ return null;
1014
+ return Math.min(1, Math.max(0, channel));
1015
+ }
1016
+ function createMarkerOverlayColor(r, g, b) {
1017
+ return { r, g, b };
1018
+ }
1019
+ function createMarkerRelationOverlayColor(type) {
1020
+ let hash = 2166136261;
1021
+ for (const char of type) {
1022
+ hash ^= char.charCodeAt(0);
1023
+ hash = Math.imul(hash, 16777619);
1024
+ }
1025
+ const hue = Math.abs(hash % 360);
1026
+ return hslToMarkerOverlayColor(hue / 360, 0.72, 0.58);
1027
+ }
1028
+ function hslToMarkerOverlayColor(h, s, l) {
1029
+ const hueToRgb = (p, q, tInput) => {
1030
+ let t = tInput;
1031
+ if (t < 0)
1032
+ t += 1;
1033
+ if (t > 1)
1034
+ t -= 1;
1035
+ if (t < 1 / 6)
1036
+ return p + (q - p) * 6 * t;
1037
+ if (t < 1 / 2)
1038
+ return q;
1039
+ if (t < 2 / 3)
1040
+ return p + (q - p) * (2 / 3 - t) * 6;
1041
+ return p;
1042
+ };
1043
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
1044
+ const p = 2 * l - q;
1045
+ return {
1046
+ r: hueToRgb(p, q, h + 1 / 3),
1047
+ g: hueToRgb(p, q, h),
1048
+ b: hueToRgb(p, q, h - 1 / 3),
1049
+ };
1050
+ }
1051
+ function brightenMarkerOverlayColor(color, amount) {
1052
+ return {
1053
+ r: color.r + (1 - color.r) * amount,
1054
+ g: color.g + (1 - color.g) * amount,
1055
+ b: color.b + (1 - color.b) * amount,
1056
+ };
1057
+ }
1058
+ function markerOverlayColorsEqual(left, right) {
1059
+ return Math.abs(left.r - right.r) < 0.000001
1060
+ && Math.abs(left.g - right.g) < 0.000001
1061
+ && Math.abs(left.b - right.b) < 0.000001;
1062
+ }
1063
+ function resolveMarkerOverlayPresentation(marker) {
1064
+ const kind = marker.kind?.trim().toLowerCase();
1065
+ if (kind === 'region')
1066
+ return 'region';
1067
+ if (kind === 'anchor')
1068
+ return 'anchor';
1069
+ if (isObjectBoundMarkerPresentation(kind, marker.geometry.kind))
1070
+ return 'object';
1071
+ if (marker.geometry.kind === 'box' && !kind)
1072
+ return 'region';
1073
+ return 'point';
1074
+ }
1075
+ function isObjectBoundMarkerPresentation(kind, geometryKind) {
1076
+ return kind === 'object'
1077
+ || kind === 'object-bound'
1078
+ || kind === 'object-bounds'
1079
+ || geometryKind === 'object-bounds';
1080
+ }
1081
+ function applyMarkerGeometryToOverlay(options, overlay, marker) {
1082
+ applyTransformToOverlay(options, overlay, createMarkerOverlayTransform(marker, overlay.presentation));
1083
+ }
1084
+ function applyBoxGeometryToOverlay(options, overlay, geometry) {
1085
+ applyTransformToOverlay(options, overlay, {
1086
+ position: geometry.center,
1087
+ rotation: geometry.rotation ?? { x: 0, y: 0, z: 0 },
1088
+ scale: geometry.size,
1089
+ });
1090
+ }
1091
+ function createMarkerOverlayTransform(marker, presentation) {
1092
+ const origin = getMarkerOverlayOrigin(marker.geometry, marker, presentation);
1093
+ return {
1094
+ position: origin,
1095
+ rotation: getMarkerOverlayRotation(marker),
1096
+ scale: getMarkerOverlayScale(marker, presentation),
1097
+ };
1098
+ }
1099
+ function getMarkerOverlayOrigin(geometry, marker, presentation) {
1100
+ if (presentation === 'object') {
1101
+ if (marker.spatial?.bounds?.center)
1102
+ return { ...marker.spatial.bounds.center };
1103
+ if (marker.spatial?.origin)
1104
+ return { ...marker.spatial.origin };
1105
+ }
1106
+ switch (geometry.kind) {
1107
+ case 'box':
1108
+ return { ...geometry.center };
1109
+ case 'point':
1110
+ if (geometry.coordinateSpace === 'world')
1111
+ return { ...geometry.position };
1112
+ return marker.semanticFrame?.origin
1113
+ ? { ...marker.semanticFrame.origin }
1114
+ : marker.spatial?.origin
1115
+ ? { ...marker.spatial.origin }
1116
+ : { ...geometry.position };
1117
+ case 'object-bounds':
1118
+ if (marker.spatial?.bounds?.center)
1119
+ return { ...marker.spatial.bounds.center };
1120
+ if (marker.spatial?.origin)
1121
+ return { ...marker.spatial.origin };
1122
+ if (marker.semanticFrame?.origin)
1123
+ return { ...marker.semanticFrame.origin };
1124
+ return { x: 0, y: 0, z: 0 };
1125
+ case 'polyhedron':
1126
+ return marker.semanticFrame?.origin
1127
+ ? { ...marker.semanticFrame.origin }
1128
+ : geometry.vertices.length > 0
1129
+ ? averageVec3(geometry.vertices)
1130
+ : { x: 0, y: 0, z: 0 };
1131
+ }
1132
+ }
1133
+ function getMarkerOverlayRotation(marker) {
1134
+ if (marker.geometry.kind === 'box')
1135
+ return marker.geometry.rotation ? { ...marker.geometry.rotation } : { x: 0, y: 0, z: 0 };
1136
+ const forward = marker.semanticFrame?.forward ?? marker.spatial?.localFrame?.forward;
1137
+ return forward ? createEulerFromForward(forward) : { x: 0, y: 0, z: 0 };
1138
+ }
1139
+ function getMarkerOverlayScale(marker, presentation) {
1140
+ if (presentation === 'region' && marker.geometry.kind === 'box')
1141
+ return { ...marker.geometry.size };
1142
+ if (presentation === 'object' && marker.spatial?.bounds?.size)
1143
+ return { ...marker.spatial.bounds.size };
1144
+ if (presentation === 'anchor')
1145
+ return { x: 0.66, y: 0.66, z: 0.66 };
1146
+ if (presentation === 'object')
1147
+ return { x: 0.58, y: 0.58, z: 0.58 };
1148
+ return { x: 0.5, y: 0.5, z: 0.5 };
1149
+ }
1150
+ function averageVec3(points) {
1151
+ return {
1152
+ x: points.reduce((sum, point) => sum + point.x, 0) / points.length,
1153
+ y: points.reduce((sum, point) => sum + point.y, 0) / points.length,
1154
+ z: points.reduce((sum, point) => sum + point.z, 0) / points.length,
1155
+ };
1156
+ }
1157
+ function createEulerFromForward(forward) {
1158
+ const length = vec3Length(forward);
1159
+ if (length < 0.000001)
1160
+ return { x: 0, y: 0, z: 0 };
1161
+ const unit = scaleVec3(forward, 1 / length);
1162
+ const yaw = Math.atan2(unit.x, unit.z);
1163
+ const horizontal = Math.sqrt(unit.x * unit.x + unit.z * unit.z);
1164
+ const pitch = -Math.atan2(unit.y, horizontal);
1165
+ return { x: pitch, y: yaw, z: 0 };
1166
+ }
1167
+ function applyTransformToOverlay(options, overlay, transform) {
1168
+ applyTransformToRoot(options, overlay.root, transform);
1169
+ applyMarkerFocusFrameToRoot(overlay.root, transform);
1170
+ applyMarkerFrameTransform(options, overlay, transform);
1171
+ applyMarkerLabelTransform(options, overlay, transform);
1172
+ }
1173
+ function applyMarkerFocusFrameToRoot(root, transform) {
1174
+ if (!root)
1175
+ return;
1176
+ const bounds = createTransformBounds(transform);
1177
+ const radius = Math.max(1, Math.hypot(bounds.size.x, bounds.size.y, bounds.size.z) / 2);
1178
+ root.metadata = {
1179
+ ...(root.metadata ?? {}),
1180
+ editorFocusFrame: {
1181
+ center: { ...bounds.center },
1182
+ radius,
1183
+ },
1184
+ };
1185
+ }
1186
+ function applyMarkerFrameTransform(options, overlay, transform) {
1187
+ const Vector3 = options.babylon.Vector3;
1188
+ if (!Vector3 || !overlay.frameRoot)
1189
+ return;
1190
+ overlay.frameRoot.position = new Vector3(transform.position.x, transform.position.y, transform.position.z);
1191
+ overlay.frameRoot.rotationQuaternion = null;
1192
+ overlay.frameRoot.rotation = new Vector3(transform.rotation.x, transform.rotation.y, transform.rotation.z);
1193
+ overlay.frameRoot.scaling = new Vector3(1, 1, 1);
1194
+ applyMarkerFrameDimensions(options, overlay, transform.scale);
1195
+ }
1196
+ function applyMarkerFrameDimensions(options, overlay, markerSize) {
1197
+ const Vector3 = options.babylon.Vector3;
1198
+ if (!Vector3)
1199
+ return;
1200
+ const maxSize = Math.max(Math.abs(markerSize.x), Math.abs(markerSize.y), Math.abs(markerSize.z));
1201
+ const presentationScale = overlay.presentation === 'anchor' ? 1.55 : overlay.presentation === 'point' ? 1.18 : 1;
1202
+ const shaftLength = Math.max(0.75, Math.min(2.2, maxSize * 0.45 * presentationScale));
1203
+ const headLength = Math.max(0.2, Math.min(0.34, shaftLength * 0.28));
1204
+ const shaftDiameter = Math.max(0.055, Math.min(0.12, shaftLength * 0.075 * presentationScale));
1205
+ const headDiameter = Math.max(0.18, Math.min(0.3, shaftLength * 0.22));
1206
+ const anchorDiameter = Math.max(0.18, Math.min(0.34, shaftLength * 0.2 * presentationScale));
1207
+ if (overlay.anchorMesh) {
1208
+ overlay.anchorMesh.position = new Vector3(0, 0, 0);
1209
+ overlay.anchorMesh.scaling = new Vector3(anchorDiameter, anchorDiameter, anchorDiameter);
1210
+ }
1211
+ if (overlay.forwardShaft) {
1212
+ overlay.forwardShaft.position = new Vector3(0, 0, shaftLength / 2);
1213
+ overlay.forwardShaft.scaling = new Vector3(shaftDiameter, shaftLength, shaftDiameter);
1214
+ }
1215
+ if (overlay.forwardHead) {
1216
+ overlay.forwardHead.position = new Vector3(0, 0, shaftLength + headLength / 2);
1217
+ overlay.forwardHead.scaling = new Vector3(headDiameter, headLength, headDiameter);
1218
+ }
1219
+ if (overlay.frameLines) {
1220
+ const lineScale = Math.max(1, Math.min(3, shaftLength / 0.72));
1221
+ overlay.frameLines.scaling = new Vector3(lineScale, lineScale, lineScale);
1222
+ }
1223
+ }
1224
+ function applyTransformToRoot(options, root, transform) {
1225
+ const Vector3 = options.babylon.Vector3;
1226
+ if (!root || !Vector3)
1227
+ return;
1228
+ root.position = new Vector3(transform.position.x, transform.position.y, transform.position.z);
1229
+ root.rotationQuaternion = null;
1230
+ root.rotation = new Vector3(transform.rotation.x, transform.rotation.y, transform.rotation.z);
1231
+ root.scaling = new Vector3(transform.scale.x, transform.scale.y, transform.scale.z);
1232
+ }
1233
+ function readRootTransform(root) {
1234
+ if (!root)
1235
+ return null;
1236
+ const rotation = root.rotationQuaternion?.toEulerAngles?.() ?? root.rotation;
1237
+ const transform = {
1238
+ position: readVec3(root.position),
1239
+ rotation: readVec3(rotation),
1240
+ scale: readVec3(root.scaling),
1241
+ };
1242
+ if (!transform.position || !transform.rotation || !transform.scale)
1243
+ return null;
1244
+ return transform;
1245
+ }
1246
+ function readVec3(value) {
1247
+ if (!Number.isFinite(value?.x) || !Number.isFinite(value?.y) || !Number.isFinite(value?.z))
1248
+ return null;
1249
+ return {
1250
+ x: Number(value.x),
1251
+ y: Number(value.y),
1252
+ z: Number(value.z),
1253
+ };
1254
+ }
1255
+ function averagePositions(transforms) {
1256
+ return {
1257
+ x: transforms.reduce((sum, transform) => sum + transform.position.x, 0) / transforms.length,
1258
+ y: transforms.reduce((sum, transform) => sum + transform.position.y, 0) / transforms.length,
1259
+ z: transforms.reduce((sum, transform) => sum + transform.position.z, 0) / transforms.length,
1260
+ };
1261
+ }
1262
+ function addVec3(left, right) {
1263
+ return {
1264
+ x: left.x + right.x,
1265
+ y: left.y + right.y,
1266
+ z: left.z + right.z,
1267
+ };
1268
+ }
1269
+ function subtractVec3(left, right) {
1270
+ return {
1271
+ x: left.x - right.x,
1272
+ y: left.y - right.y,
1273
+ z: left.z - right.z,
1274
+ };
1275
+ }
1276
+ function scaleVec3(value, scalar) {
1277
+ return {
1278
+ x: value.x * scalar,
1279
+ y: value.y * scalar,
1280
+ z: value.z * scalar,
1281
+ };
1282
+ }
1283
+ function vec3Length(value) {
1284
+ return Math.sqrt(value.x * value.x + value.y * value.y + value.z * value.z);
1285
+ }
1286
+ function combineTransformBounds(transforms) {
1287
+ let combined = null;
1288
+ for (const transform of transforms) {
1289
+ combined = combineBounds(combined, createTransformBounds(transform));
1290
+ }
1291
+ return combined;
1292
+ }
1293
+ function createTransformBounds(transform) {
1294
+ const half = {
1295
+ x: Math.abs(transform.scale.x) / 2,
1296
+ y: Math.abs(transform.scale.y) / 2,
1297
+ z: Math.abs(transform.scale.z) / 2,
1298
+ };
1299
+ const corners = [
1300
+ { x: -half.x, y: -half.y, z: -half.z },
1301
+ { x: half.x, y: -half.y, z: -half.z },
1302
+ { x: -half.x, y: half.y, z: -half.z },
1303
+ { x: half.x, y: half.y, z: -half.z },
1304
+ { x: -half.x, y: -half.y, z: half.z },
1305
+ { x: half.x, y: -half.y, z: half.z },
1306
+ { x: -half.x, y: half.y, z: half.z },
1307
+ { x: half.x, y: half.y, z: half.z },
1308
+ ].map(corner => addVec3(rotateVec3ByEuler(corner, transform.rotation), transform.position));
1309
+ const min = {
1310
+ x: Math.min(...corners.map(corner => corner.x)),
1311
+ y: Math.min(...corners.map(corner => corner.y)),
1312
+ z: Math.min(...corners.map(corner => corner.z)),
1313
+ };
1314
+ const max = {
1315
+ x: Math.max(...corners.map(corner => corner.x)),
1316
+ y: Math.max(...corners.map(corner => corner.y)),
1317
+ z: Math.max(...corners.map(corner => corner.z)),
1318
+ };
1319
+ return {
1320
+ min,
1321
+ max,
1322
+ center: {
1323
+ x: (min.x + max.x) / 2,
1324
+ y: (min.y + max.y) / 2,
1325
+ z: (min.z + max.z) / 2,
1326
+ },
1327
+ size: {
1328
+ x: max.x - min.x,
1329
+ y: max.y - min.y,
1330
+ z: max.z - min.z,
1331
+ },
1332
+ };
1333
+ }
1334
+ function rotateVec3ByEuler(value, rotation) {
1335
+ const cx = Math.cos(rotation.x);
1336
+ const sx = Math.sin(rotation.x);
1337
+ const cy = Math.cos(rotation.y);
1338
+ const sy = Math.sin(rotation.y);
1339
+ const cz = Math.cos(rotation.z);
1340
+ const sz = Math.sin(rotation.z);
1341
+ const afterX = {
1342
+ x: value.x,
1343
+ y: value.y * cx - value.z * sx,
1344
+ z: value.y * sx + value.z * cx,
1345
+ };
1346
+ const afterY = {
1347
+ x: afterX.x * cy + afterX.z * sy,
1348
+ y: afterX.y,
1349
+ z: -afterX.x * sy + afterX.z * cy,
1350
+ };
1351
+ return {
1352
+ x: afterY.x * cz - afterY.y * sz,
1353
+ y: afterY.x * sz + afterY.y * cz,
1354
+ z: afterY.z,
1355
+ };
1356
+ }
1357
+ function combineBounds(left, right) {
1358
+ if (!left)
1359
+ return right ? cloneBounds(right) : null;
1360
+ if (!right)
1361
+ return cloneBounds(left);
1362
+ const min = {
1363
+ x: Math.min(left.min.x, right.min.x),
1364
+ y: Math.min(left.min.y, right.min.y),
1365
+ z: Math.min(left.min.z, right.min.z),
1366
+ };
1367
+ const max = {
1368
+ x: Math.max(left.max.x, right.max.x),
1369
+ y: Math.max(left.max.y, right.max.y),
1370
+ z: Math.max(left.max.z, right.max.z),
1371
+ };
1372
+ return {
1373
+ min,
1374
+ max,
1375
+ center: {
1376
+ x: (min.x + max.x) / 2,
1377
+ y: (min.y + max.y) / 2,
1378
+ z: (min.z + max.z) / 2,
1379
+ },
1380
+ size: {
1381
+ x: max.x - min.x,
1382
+ y: max.y - min.y,
1383
+ z: max.z - min.z,
1384
+ },
1385
+ };
1386
+ }
1387
+ function cloneBounds(bounds) {
1388
+ return {
1389
+ min: { ...bounds.min },
1390
+ max: { ...bounds.max },
1391
+ center: { ...bounds.center },
1392
+ size: { ...bounds.size },
1393
+ };
1394
+ }
1395
+ //# sourceMappingURL=marker-overlay.js.map