@planara/core 2.8.0 → 3.1.0

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 (283) hide show
  1. package/README.md +5 -0
  2. package/dist/api/modules/controls-state-api.d.ts +23 -0
  3. package/dist/api/modules/controls-state-api.d.ts.map +1 -0
  4. package/dist/api/modules/index.d.ts +5 -0
  5. package/dist/api/modules/index.d.ts.map +1 -0
  6. package/dist/api/modules/mesh-api.d.ts +30 -0
  7. package/dist/api/modules/mesh-api.d.ts.map +1 -0
  8. package/dist/api/modules/raycast-api.d.ts +28 -0
  9. package/dist/api/modules/raycast-api.d.ts.map +1 -0
  10. package/dist/api/modules/transform-api.d.ts +33 -0
  11. package/dist/api/modules/transform-api.d.ts.map +1 -0
  12. package/dist/api/renderer/camera-api.d.ts +26 -0
  13. package/dist/api/renderer/camera-api.d.ts.map +1 -0
  14. package/dist/api/renderer/dom-api.d.ts +24 -0
  15. package/dist/api/renderer/dom-api.d.ts.map +1 -0
  16. package/dist/api/renderer/index.d.ts +4 -0
  17. package/dist/api/renderer/index.d.ts.map +1 -0
  18. package/dist/api/renderer/scene-api.d.ts +26 -0
  19. package/dist/api/renderer/scene-api.d.ts.map +1 -0
  20. package/dist/constants/colors.d.ts +12 -0
  21. package/dist/constants/colors.d.ts.map +1 -1
  22. package/dist/constants/figure-geometries.d.ts +55 -4
  23. package/dist/constants/figure-geometries.d.ts.map +1 -1
  24. package/dist/constants/index.d.ts +6 -0
  25. package/dist/constants/index.d.ts.map +1 -0
  26. package/dist/constants/layers.d.ts +12 -0
  27. package/dist/constants/layers.d.ts.map +1 -1
  28. package/dist/constants/messages.d.ts +18 -0
  29. package/dist/constants/messages.d.ts.map +1 -0
  30. package/dist/constants/threshold.d.ts +42 -2
  31. package/dist/constants/threshold.d.ts.map +1 -1
  32. package/dist/controllers/index.d.ts +2 -0
  33. package/dist/controllers/index.d.ts.map +1 -0
  34. package/dist/controllers/renderer-controller.d.ts +72 -0
  35. package/dist/controllers/renderer-controller.d.ts.map +1 -0
  36. package/dist/core/index.d.ts +2 -0
  37. package/dist/core/index.d.ts.map +1 -0
  38. package/dist/core/renderer.d.ts +105 -78
  39. package/dist/core/renderer.d.ts.map +1 -1
  40. package/dist/decorators/index.d.ts +3 -0
  41. package/dist/decorators/index.d.ts.map +1 -0
  42. package/dist/decorators/use-policy.d.ts +5 -0
  43. package/dist/decorators/use-policy.d.ts.map +1 -0
  44. package/dist/decorators/use-validator.d.ts +5 -0
  45. package/dist/decorators/use-validator.d.ts.map +1 -0
  46. package/dist/errors/index.d.ts +3 -0
  47. package/dist/errors/index.d.ts.map +1 -0
  48. package/dist/errors/policy-error.d.ts +9 -0
  49. package/dist/errors/policy-error.d.ts.map +1 -0
  50. package/dist/errors/validation-error.d.ts +9 -0
  51. package/dist/errors/validation-error.d.ts.map +1 -0
  52. package/dist/events/editor-events.d.ts +3 -7
  53. package/dist/events/editor-events.d.ts.map +1 -1
  54. package/dist/events/event-bus.d.ts +103 -6
  55. package/dist/events/event-bus.d.ts.map +1 -1
  56. package/dist/events/event-topics.d.ts +3 -3
  57. package/dist/events/event-topics.d.ts.map +1 -1
  58. package/dist/events/index.d.ts +4 -0
  59. package/dist/events/index.d.ts.map +1 -0
  60. package/dist/handlers/display/index.d.ts +2 -0
  61. package/dist/handlers/display/index.d.ts.map +1 -0
  62. package/dist/handlers/display/wireframe-handler.d.ts +4 -2
  63. package/dist/handlers/display/wireframe-handler.d.ts.map +1 -1
  64. package/dist/handlers/scene/add-figure-scene-handler.d.ts +4 -2
  65. package/dist/handlers/scene/add-figure-scene-handler.d.ts.map +1 -1
  66. package/dist/handlers/scene/delete-figure-scene-handler.d.ts +4 -4
  67. package/dist/handlers/scene/delete-figure-scene-handler.d.ts.map +1 -1
  68. package/dist/handlers/scene/export-scene-handler.d.ts +23 -0
  69. package/dist/handlers/scene/export-scene-handler.d.ts.map +1 -0
  70. package/dist/handlers/scene/index.d.ts +6 -0
  71. package/dist/handlers/scene/index.d.ts.map +1 -0
  72. package/dist/handlers/scene/load-figure-scene-handler.d.ts +23 -0
  73. package/dist/handlers/scene/load-figure-scene-handler.d.ts.map +1 -0
  74. package/dist/handlers/scene/load-scene-handler.d.ts +23 -0
  75. package/dist/handlers/scene/load-scene-handler.d.ts.map +1 -0
  76. package/dist/handlers/select/edge-select-handler.d.ts +11 -8
  77. package/dist/handlers/select/edge-select-handler.d.ts.map +1 -1
  78. package/dist/handlers/select/face-select-handler.d.ts +11 -8
  79. package/dist/handlers/select/face-select-handler.d.ts.map +1 -1
  80. package/dist/handlers/select/index.d.ts +5 -0
  81. package/dist/handlers/select/index.d.ts.map +1 -0
  82. package/dist/handlers/select/mesh-select-handler.d.ts +8 -7
  83. package/dist/handlers/select/mesh-select-handler.d.ts.map +1 -1
  84. package/dist/handlers/select/vertex-select-handler.d.ts +11 -8
  85. package/dist/handlers/select/vertex-select-handler.d.ts.map +1 -1
  86. package/dist/handlers/tool/base-tool-handler.d.ts +10 -7
  87. package/dist/handlers/tool/base-tool-handler.d.ts.map +1 -1
  88. package/dist/handlers/tool/index.d.ts +4 -0
  89. package/dist/handlers/tool/index.d.ts.map +1 -0
  90. package/dist/handlers/tool/rotate-tool-handler.d.ts +4 -3
  91. package/dist/handlers/tool/rotate-tool-handler.d.ts.map +1 -1
  92. package/dist/handlers/tool/scale-tool-handler.d.ts +4 -3
  93. package/dist/handlers/tool/scale-tool-handler.d.ts.map +1 -1
  94. package/dist/handlers/tool/translate-tool-handler.d.ts +4 -3
  95. package/dist/handlers/tool/translate-tool-handler.d.ts.map +1 -1
  96. package/dist/hub/editor-hub.d.ts +26 -18
  97. package/dist/hub/editor-hub.d.ts.map +1 -1
  98. package/dist/hub/index.d.ts +26 -0
  99. package/dist/hub/index.d.ts.map +1 -0
  100. package/dist/hub/viewer-hub.d.ts +30 -0
  101. package/dist/hub/viewer-hub.d.ts.map +1 -0
  102. package/dist/index.cjs.js +20 -2
  103. package/dist/index.d.ts +16 -9
  104. package/dist/index.d.ts.map +1 -1
  105. package/dist/index.es.js +2615 -1627
  106. package/dist/index.full.d.ts +650 -245
  107. package/dist/index.public.d.ts +665 -160
  108. package/dist/index.umd.js +20 -2
  109. package/dist/interfaces/api/camera-api.d.ts +64 -0
  110. package/dist/interfaces/api/camera-api.d.ts.map +1 -0
  111. package/dist/interfaces/api/controls-state-api.d.ts +63 -0
  112. package/dist/interfaces/api/controls-state-api.d.ts.map +1 -0
  113. package/dist/interfaces/api/dom-api.d.ts +49 -0
  114. package/dist/interfaces/api/dom-api.d.ts.map +1 -0
  115. package/dist/interfaces/api/index.d.ts +9 -0
  116. package/dist/interfaces/api/index.d.ts.map +1 -0
  117. package/dist/interfaces/api/mesh-api.d.ts +93 -12
  118. package/dist/interfaces/api/mesh-api.d.ts.map +1 -1
  119. package/dist/interfaces/api/raycast-api.d.ts +6 -1
  120. package/dist/interfaces/api/raycast-api.d.ts.map +1 -1
  121. package/dist/interfaces/api/renderer/index.d.ts +6 -0
  122. package/dist/interfaces/api/renderer/index.d.ts.map +1 -0
  123. package/dist/interfaces/api/renderer/renderable.d.ts +45 -0
  124. package/dist/interfaces/api/renderer/renderable.d.ts.map +1 -0
  125. package/dist/interfaces/api/renderer/renderer-access.d.ts +34 -0
  126. package/dist/interfaces/api/renderer/renderer-access.d.ts.map +1 -0
  127. package/dist/interfaces/api/renderer/renderer-camera-access.d.ts +37 -0
  128. package/dist/interfaces/api/renderer/renderer-camera-access.d.ts.map +1 -0
  129. package/dist/interfaces/api/renderer/renderer-dom-access.d.ts +51 -0
  130. package/dist/interfaces/api/renderer/renderer-dom-access.d.ts.map +1 -0
  131. package/dist/interfaces/api/renderer/renderer-scene-access.d.ts +45 -0
  132. package/dist/interfaces/api/renderer/renderer-scene-access.d.ts.map +1 -0
  133. package/dist/interfaces/api/renderer-api.d.ts +35 -0
  134. package/dist/interfaces/api/renderer-api.d.ts.map +1 -0
  135. package/dist/interfaces/api/scene-api.d.ts +66 -26
  136. package/dist/interfaces/api/scene-api.d.ts.map +1 -1
  137. package/dist/interfaces/api/transform-api.d.ts +120 -0
  138. package/dist/interfaces/api/transform-api.d.ts.map +1 -0
  139. package/dist/interfaces/command/index.d.ts +9 -0
  140. package/dist/interfaces/command/index.d.ts.map +1 -0
  141. package/dist/interfaces/controller/index.d.ts +38 -0
  142. package/dist/interfaces/controller/index.d.ts.map +1 -0
  143. package/dist/interfaces/handler/display-handler.d.ts +9 -1
  144. package/dist/interfaces/handler/display-handler.d.ts.map +1 -1
  145. package/dist/interfaces/handler/handler.d.ts +2 -0
  146. package/dist/interfaces/handler/handler.d.ts.map +1 -1
  147. package/dist/interfaces/handler/index.d.ts +6 -0
  148. package/dist/interfaces/handler/index.d.ts.map +1 -0
  149. package/dist/interfaces/handler/scene-handler.d.ts +1 -0
  150. package/dist/interfaces/handler/scene-handler.d.ts.map +1 -1
  151. package/dist/interfaces/handler/select-handler.d.ts +1 -0
  152. package/dist/interfaces/handler/select-handler.d.ts.map +1 -1
  153. package/dist/interfaces/handler/tool-handler.d.ts +1 -0
  154. package/dist/interfaces/handler/tool-handler.d.ts.map +1 -1
  155. package/dist/interfaces/manager/display-manager.d.ts +3 -1
  156. package/dist/interfaces/manager/display-manager.d.ts.map +1 -1
  157. package/dist/interfaces/manager/index.d.ts +6 -0
  158. package/dist/interfaces/manager/index.d.ts.map +1 -0
  159. package/dist/interfaces/manager/manager.d.ts +12 -1
  160. package/dist/interfaces/manager/manager.d.ts.map +1 -1
  161. package/dist/interfaces/manager/scene-manager.d.ts +3 -1
  162. package/dist/interfaces/manager/scene-manager.d.ts.map +1 -1
  163. package/dist/interfaces/manager/select-manager.d.ts +3 -1
  164. package/dist/interfaces/manager/select-manager.d.ts.map +1 -1
  165. package/dist/interfaces/manager/tool-manager.d.ts +3 -1
  166. package/dist/interfaces/manager/tool-manager.d.ts.map +1 -1
  167. package/dist/interfaces/mediator/index.d.ts +51 -0
  168. package/dist/interfaces/mediator/index.d.ts.map +1 -0
  169. package/dist/interfaces/middleware/index.d.ts +50 -0
  170. package/dist/interfaces/middleware/index.d.ts.map +1 -0
  171. package/dist/interfaces/module/index.d.ts +4 -0
  172. package/dist/interfaces/module/index.d.ts.map +1 -0
  173. package/dist/interfaces/module/renderable-module.d.ts +27 -0
  174. package/dist/interfaces/module/renderable-module.d.ts.map +1 -0
  175. package/dist/interfaces/module/runtime-module.d.ts +54 -0
  176. package/dist/interfaces/module/runtime-module.d.ts.map +1 -0
  177. package/dist/interfaces/module/updatable-module.d.ts +48 -0
  178. package/dist/interfaces/module/updatable-module.d.ts.map +1 -0
  179. package/dist/interfaces/policy/index.d.ts +21 -0
  180. package/dist/interfaces/policy/index.d.ts.map +1 -0
  181. package/dist/interfaces/store/display-store.d.ts +21 -0
  182. package/dist/interfaces/store/display-store.d.ts.map +1 -0
  183. package/dist/interfaces/store/export-store.d.ts +8 -0
  184. package/dist/interfaces/store/export-store.d.ts.map +1 -0
  185. package/dist/interfaces/store/index.d.ts +6 -0
  186. package/dist/interfaces/store/index.d.ts.map +1 -0
  187. package/dist/interfaces/store/select-store.d.ts +44 -0
  188. package/dist/interfaces/store/select-store.d.ts.map +1 -0
  189. package/dist/interfaces/store/tool-store.d.ts +27 -0
  190. package/dist/interfaces/store/tool-store.d.ts.map +1 -0
  191. package/dist/interfaces/store/transform-store.d.ts +11 -0
  192. package/dist/interfaces/store/transform-store.d.ts.map +1 -0
  193. package/dist/interfaces/validator/index.d.ts +21 -0
  194. package/dist/interfaces/validator/index.d.ts.map +1 -0
  195. package/dist/ioc/container.d.ts +3 -1
  196. package/dist/ioc/container.d.ts.map +1 -1
  197. package/dist/managers/display/display-manager.d.ts +7 -4
  198. package/dist/managers/display/display-manager.d.ts.map +1 -1
  199. package/dist/managers/display/index.d.ts +2 -0
  200. package/dist/managers/display/index.d.ts.map +1 -0
  201. package/dist/managers/index.d.ts +5 -0
  202. package/dist/managers/index.d.ts.map +1 -0
  203. package/dist/managers/scene/index.d.ts +2 -0
  204. package/dist/managers/scene/index.d.ts.map +1 -0
  205. package/dist/managers/scene/scene-manager.d.ts +7 -4
  206. package/dist/managers/scene/scene-manager.d.ts.map +1 -1
  207. package/dist/managers/select/index.d.ts +2 -0
  208. package/dist/managers/select/index.d.ts.map +1 -0
  209. package/dist/managers/select/select-manager.d.ts +8 -5
  210. package/dist/managers/select/select-manager.d.ts.map +1 -1
  211. package/dist/managers/tool/index.d.ts +2 -0
  212. package/dist/managers/tool/index.d.ts.map +1 -0
  213. package/dist/managers/tool/tool-manager.d.ts +9 -6
  214. package/dist/managers/tool/tool-manager.d.ts.map +1 -1
  215. package/dist/mediator/index.d.ts +14 -0
  216. package/dist/mediator/index.d.ts.map +1 -0
  217. package/dist/middlewares/exception-middleware.d.ts +12 -0
  218. package/dist/middlewares/exception-middleware.d.ts.map +1 -0
  219. package/dist/middlewares/index.d.ts +2 -0
  220. package/dist/middlewares/index.d.ts.map +1 -0
  221. package/dist/modules/controls-module.d.ts +60 -0
  222. package/dist/modules/controls-module.d.ts.map +1 -0
  223. package/dist/modules/gizmo-module.d.ts +32 -0
  224. package/dist/modules/gizmo-module.d.ts.map +1 -0
  225. package/dist/modules/index.d.ts +6 -0
  226. package/dist/modules/index.d.ts.map +1 -0
  227. package/dist/modules/raycast-module.d.ts +87 -0
  228. package/dist/modules/raycast-module.d.ts.map +1 -0
  229. package/dist/modules/scene-module.d.ts +31 -0
  230. package/dist/modules/scene-module.d.ts.map +1 -0
  231. package/dist/modules/scene-preview-module.d.ts +26 -0
  232. package/dist/modules/scene-preview-module.d.ts.map +1 -0
  233. package/dist/policy/index.d.ts +2 -0
  234. package/dist/policy/index.d.ts.map +1 -0
  235. package/dist/policy/tool-policy.d.ts +18 -0
  236. package/dist/policy/tool-policy.d.ts.map +1 -0
  237. package/dist/store/editor-store.d.ts +33 -0
  238. package/dist/store/editor-store.d.ts.map +1 -0
  239. package/dist/store/export-store.d.ts +12 -0
  240. package/dist/store/export-store.d.ts.map +1 -0
  241. package/dist/store/index.d.ts +2 -45
  242. package/dist/store/index.d.ts.map +1 -1
  243. package/dist/types/camera/index.d.ts +2 -0
  244. package/dist/types/camera/index.d.ts.map +1 -0
  245. package/dist/types/event/index.d.ts +2 -0
  246. package/dist/types/event/index.d.ts.map +1 -0
  247. package/dist/types/feature/feature-type.d.ts +16 -0
  248. package/dist/types/feature/feature-type.d.ts.map +1 -0
  249. package/dist/types/feature/index.d.ts +2 -0
  250. package/dist/types/feature/index.d.ts.map +1 -0
  251. package/dist/types/listener/index.d.ts +3 -0
  252. package/dist/types/listener/index.d.ts.map +1 -0
  253. package/dist/types/select/index.d.ts +2 -0
  254. package/dist/types/select/index.d.ts.map +1 -0
  255. package/dist/utils/default-renderer-config.d.ts +9 -0
  256. package/dist/utils/default-renderer-config.d.ts.map +1 -0
  257. package/dist/utils/helpers.d.ts +14 -1
  258. package/dist/utils/helpers.d.ts.map +1 -1
  259. package/dist/utils/index.d.ts +3 -0
  260. package/dist/utils/index.d.ts.map +1 -0
  261. package/dist/validators/index.d.ts +2 -0
  262. package/dist/validators/index.d.ts.map +1 -0
  263. package/dist/validators/obj-validator.d.ts +12 -0
  264. package/dist/validators/obj-validator.d.ts.map +1 -0
  265. package/package.json +2 -2
  266. package/dist/core/editor-renderer.d.ts +0 -89
  267. package/dist/core/editor-renderer.d.ts.map +0 -1
  268. package/dist/core/preview-renderer.d.ts +0 -16
  269. package/dist/core/preview-renderer.d.ts.map +0 -1
  270. package/dist/hub/app-hub.d.ts +0 -13
  271. package/dist/hub/app-hub.d.ts.map +0 -1
  272. package/dist/interfaces/api/transform-helpers-api.d.ts +0 -26
  273. package/dist/interfaces/api/transform-helpers-api.d.ts.map +0 -1
  274. package/dist/interfaces/policy/tool-availability-policy.d.ts +0 -12
  275. package/dist/interfaces/policy/tool-availability-policy.d.ts.map +0 -1
  276. package/dist/interfaces/store/editor-store.d.ts +0 -52
  277. package/dist/interfaces/store/editor-store.d.ts.map +0 -1
  278. package/dist/policy/tool-availability-policy.d.ts +0 -13
  279. package/dist/policy/tool-availability-policy.d.ts.map +0 -1
  280. package/dist/types/api/editor-api.d.ts +0 -4
  281. package/dist/types/api/editor-api.d.ts.map +0 -1
  282. package/dist/utils/renderer-api.d.ts +0 -43
  283. package/dist/utils/renderer-api.d.ts.map +0 -1
package/dist/index.es.js CHANGED
@@ -1,1141 +1,1746 @@
1
1
  import "reflect-metadata";
2
- import * as a from "three";
3
- import { Controls as Ke, Vector3 as I, MOUSE as Y, TOUCH as z, Quaternion as Ee, Spherical as xe, Vector2 as L, Ray as qe, Plane as Qe, MathUtils as Je } from "three";
4
- import { FigureType as D, SelectMode as y, Figure as et, DisplayMode as $, DEFAULT_TOOL_RULES as Pe, ToolType as F, SceneMode as U } from "@planara/types";
5
- import { SymmetricAxesHelper as tt, OrbitWithState as st, CameraAxesGizmo as it, ModelingTransformControls as rt } from "@planara/three";
6
- import { injectable as M, inject as _, injectAll as G, container as ot } from "tsyringe";
7
- import { EventEmitter as nt } from "events";
8
- import { makeAutoObservable as at } from "mobx";
9
- const ht = {
10
- [D.Plane]: () => new a.PlaneGeometry(1, 1, 1, 1),
11
- [D.Cube]: () => new a.BoxGeometry(1, 1, 1, 1, 1, 1),
12
- [D.UVSphere]: () => new a.SphereGeometry(0.5, 32, 16),
13
- [D.Icosphere]: () => new a.IcosahedronGeometry(0.5, 0),
14
- [D.Cylinder]: () => new a.CylinderGeometry(0.5, 0.5, 1, 32, 1, !1),
15
- [D.Cone]: () => new a.ConeGeometry(0.5, 1, 32, 1, !1),
16
- [D.Torus]: () => new a.TorusGeometry(0.5, 0.2, 16, 64),
17
- [D.Circle]: () => new a.CircleGeometry(0.5, 32),
18
- [D.Sphere]: () => new a.SphereGeometry(0.5, 32, 16),
19
- [D.Custom]: function() {
20
- throw new Error("Custom geometry is not generated here.");
21
- }
22
- }, ze = new a.MeshStandardMaterial({
23
- color: 12566463,
24
- metalness: 0,
25
- roughness: 0.6
26
- }), lt = 8;
27
- class Ne {
28
- /** Корневой объект сцены */
29
- scene;
30
- /** Камера для сцены */
31
- camera;
32
- /** Экземпляр рендерера Three.js */
33
- renderer;
34
- /** HTML-элемент canvas, на котором рендерится сцена */
35
- canvas;
36
- /** Массив моделей на сцене */
37
- meshes = [];
2
+ import * as l from "three";
3
+ import { Loader as Ut, FileLoader as Nt, Color as St, SRGBColorSpace as wt, Group as Xt, BufferGeometry as it, Float32BufferAttribute as X, LineBasicMaterial as Se, Material as nt, PointsMaterial as ee, MeshPhongMaterial as Yt, LineSegments as ot, Points as we, Mesh as at, Vector3 as W, Vector2 as qt, Matrix3 as Zt, ColorManagement as Kt } from "three";
4
+ import { injectable as w, inject as _, injectAll as B, container as Jt } from "tsyringe";
5
+ import { FigureType as L, Figure as Qt, SelectMode as P, DisplayMode as K, SceneMode as T, ToolType as U, DEFAULT_TOOL_RULES as es, ResponseType as G } from "@planara/types";
6
+ import { OrbitWithState as ts, ModelingTransformControls as ss, CameraAxesGizmo as rs, SymmetricAxesHelper as is } from "@planara/three";
7
+ import { EventEmitter as ns } from "events";
8
+ import { makeAutoObservable as At, observable as os } from "mobx";
9
+ const as = /^[og]\s*(.+)?/, ls = /^mtllib /, cs = /^usemtl /, hs = /^usemap /, lt = /\s+/, ct = new W(), Ae = new W(), ht = new W(), dt = new W(), j = new W(), te = new St();
10
+ function ds() {
11
+ const e = {
12
+ objects: [],
13
+ object: {},
14
+ vertices: [],
15
+ normals: [],
16
+ colors: [],
17
+ uvs: [],
18
+ materials: {},
19
+ materialLibraries: [],
20
+ startObject: function(t, s) {
21
+ if (this.object && this.object.fromDeclaration === !1) {
22
+ this.object.name = t, this.object.fromDeclaration = s !== !1;
23
+ return;
24
+ }
25
+ const r = this.object && typeof this.object.currentMaterial == "function" ? this.object.currentMaterial() : void 0;
26
+ if (this.object && typeof this.object._finalize == "function" && this.object._finalize(!0), this.object = {
27
+ name: t || "",
28
+ fromDeclaration: s !== !1,
29
+ geometry: {
30
+ vertices: [],
31
+ normals: [],
32
+ colors: [],
33
+ uvs: [],
34
+ hasUVIndices: !1
35
+ },
36
+ materials: [],
37
+ smooth: !0,
38
+ startMaterial: function(i, n) {
39
+ const o = this._finalize(!1);
40
+ o && (o.inherited || o.groupCount <= 0) && this.materials.splice(o.index, 1);
41
+ const c = {
42
+ index: this.materials.length,
43
+ name: i || "",
44
+ mtllib: Array.isArray(n) && n.length > 0 ? n[n.length - 1] : "",
45
+ smooth: o !== void 0 ? o.smooth : this.smooth,
46
+ groupStart: o !== void 0 ? o.groupEnd : 0,
47
+ groupEnd: -1,
48
+ groupCount: -1,
49
+ inherited: !1,
50
+ clone: function(u) {
51
+ const d = {
52
+ index: typeof u == "number" ? u : this.index,
53
+ name: this.name,
54
+ mtllib: this.mtllib,
55
+ smooth: this.smooth,
56
+ groupStart: 0,
57
+ groupEnd: -1,
58
+ groupCount: -1,
59
+ inherited: !1
60
+ };
61
+ return d.clone = this.clone.bind(d), d;
62
+ }
63
+ };
64
+ return this.materials.push(c), c;
65
+ },
66
+ currentMaterial: function() {
67
+ if (this.materials.length > 0)
68
+ return this.materials[this.materials.length - 1];
69
+ },
70
+ _finalize: function(i) {
71
+ const n = this.currentMaterial();
72
+ if (n && n.groupEnd === -1 && (n.groupEnd = this.geometry.vertices.length / 3, n.groupCount = n.groupEnd - n.groupStart, n.inherited = !1), i && this.materials.length > 1)
73
+ for (let o = this.materials.length - 1; o >= 0; o--)
74
+ this.materials[o].groupCount <= 0 && this.materials.splice(o, 1);
75
+ return i && this.materials.length === 0 && this.materials.push({
76
+ name: "",
77
+ smooth: this.smooth
78
+ }), n;
79
+ }
80
+ }, r && r.name && typeof r.clone == "function") {
81
+ const i = r.clone(0);
82
+ i.inherited = !0, this.object.materials.push(i);
83
+ }
84
+ this.objects.push(this.object);
85
+ },
86
+ finalize: function() {
87
+ this.object && typeof this.object._finalize == "function" && this.object._finalize(!0);
88
+ },
89
+ parseVertexIndex: function(t, s) {
90
+ const r = parseInt(t, 10);
91
+ return (r >= 0 ? r - 1 : r + s / 3) * 3;
92
+ },
93
+ parseNormalIndex: function(t, s) {
94
+ const r = parseInt(t, 10);
95
+ return (r >= 0 ? r - 1 : r + s / 3) * 3;
96
+ },
97
+ parseUVIndex: function(t, s) {
98
+ const r = parseInt(t, 10);
99
+ return (r >= 0 ? r - 1 : r + s / 2) * 2;
100
+ },
101
+ addVertex: function(t, s, r) {
102
+ const i = this.vertices, n = this.object.geometry.vertices;
103
+ n.push(i[t + 0], i[t + 1], i[t + 2]), n.push(i[s + 0], i[s + 1], i[s + 2]), n.push(i[r + 0], i[r + 1], i[r + 2]);
104
+ },
105
+ addVertexPoint: function(t) {
106
+ const s = this.vertices;
107
+ this.object.geometry.vertices.push(s[t + 0], s[t + 1], s[t + 2]);
108
+ },
109
+ addVertexLine: function(t) {
110
+ const s = this.vertices;
111
+ this.object.geometry.vertices.push(s[t + 0], s[t + 1], s[t + 2]);
112
+ },
113
+ addNormal: function(t, s, r) {
114
+ const i = this.normals, n = this.object.geometry.normals;
115
+ n.push(i[t + 0], i[t + 1], i[t + 2]), n.push(i[s + 0], i[s + 1], i[s + 2]), n.push(i[r + 0], i[r + 1], i[r + 2]);
116
+ },
117
+ addFaceNormal: function(t, s, r) {
118
+ const i = this.vertices, n = this.object.geometry.normals;
119
+ ct.fromArray(i, t), Ae.fromArray(i, s), ht.fromArray(i, r), j.subVectors(ht, Ae), dt.subVectors(ct, Ae), j.cross(dt), j.normalize(), n.push(j.x, j.y, j.z), n.push(j.x, j.y, j.z), n.push(j.x, j.y, j.z);
120
+ },
121
+ addColor: function(t, s, r) {
122
+ const i = this.colors, n = this.object.geometry.colors;
123
+ i[t] !== void 0 && n.push(i[t + 0], i[t + 1], i[t + 2]), i[s] !== void 0 && n.push(i[s + 0], i[s + 1], i[s + 2]), i[r] !== void 0 && n.push(i[r + 0], i[r + 1], i[r + 2]);
124
+ },
125
+ addUV: function(t, s, r) {
126
+ const i = this.uvs, n = this.object.geometry.uvs;
127
+ n.push(i[t + 0], i[t + 1]), n.push(i[s + 0], i[s + 1]), n.push(i[r + 0], i[r + 1]);
128
+ },
129
+ addDefaultUV: function() {
130
+ const t = this.object.geometry.uvs;
131
+ t.push(0, 0), t.push(0, 0), t.push(0, 0);
132
+ },
133
+ addUVLine: function(t) {
134
+ const s = this.uvs;
135
+ this.object.geometry.uvs.push(s[t + 0], s[t + 1]);
136
+ },
137
+ addFace: function(t, s, r, i, n, o, c, u, d) {
138
+ const m = this.vertices.length;
139
+ let p = this.parseVertexIndex(t, m), g = this.parseVertexIndex(s, m), f = this.parseVertexIndex(r, m);
140
+ if (this.addVertex(p, g, f), this.addColor(p, g, f), c !== void 0 && c !== "") {
141
+ const h = this.normals.length;
142
+ p = this.parseNormalIndex(c, h), g = this.parseNormalIndex(u, h), f = this.parseNormalIndex(d, h), this.addNormal(p, g, f);
143
+ } else
144
+ this.addFaceNormal(p, g, f);
145
+ if (i !== void 0 && i !== "") {
146
+ const h = this.uvs.length;
147
+ p = this.parseUVIndex(i, h), g = this.parseUVIndex(n, h), f = this.parseUVIndex(o, h), this.addUV(p, g, f), this.object.geometry.hasUVIndices = !0;
148
+ } else
149
+ this.addDefaultUV();
150
+ },
151
+ addPointGeometry: function(t) {
152
+ this.object.geometry.type = "Points";
153
+ const s = this.vertices.length;
154
+ for (let r = 0, i = t.length; r < i; r++) {
155
+ const n = this.parseVertexIndex(t[r], s);
156
+ this.addVertexPoint(n), this.addColor(n);
157
+ }
158
+ },
159
+ addLineGeometry: function(t, s) {
160
+ this.object.geometry.type = "Line";
161
+ const r = this.vertices.length, i = this.uvs.length;
162
+ for (let n = 0, o = t.length; n < o; n++)
163
+ this.addVertexLine(this.parseVertexIndex(t[n], r));
164
+ for (let n = 0, o = s.length; n < o; n++)
165
+ this.addUVLine(this.parseUVIndex(s[n], i));
166
+ }
167
+ };
168
+ return e.startObject("", !1), e;
169
+ }
170
+ class us extends Ut {
38
171
  /**
39
- * Конструктор рендерера
40
- * @param canvas - HTMLCanvasElement для рендеринга
172
+ * Constructs a new OBJ loader.
173
+ *
174
+ * @param {LoadingManager} [manager] - The loading manager.
41
175
  */
42
- constructor(e) {
43
- this.canvas = e, this.scene = new a.Scene(), this.scene.background = new a.Color(1710618), this.camera = new a.PerspectiveCamera(
44
- 45,
45
- e.clientWidth / e.clientHeight,
46
- 0.1,
47
- 1e3
48
- ), this.camera.position.set(1, 1, 7), this.renderer = new a.WebGLRenderer({ canvas: e, antialias: !0 }), this.renderer.setSize(e.clientWidth, e.clientHeight);
49
- const s = new a.AmbientLight(16777215, 0.5);
50
- this.scene.add(s);
51
- const i = new a.DirectionalLight(16777215, 1);
52
- i.position.set(5, 10, 7), this.scene.add(i);
176
+ constructor(t) {
177
+ super(t), this.materials = null;
53
178
  }
54
179
  /**
55
- * Обновляет размер рендерера и камеры при изменении размеров canvas.
180
+ * Starts loading from the given URL and passes the loaded OBJ asset
181
+ * to the `onLoad()` callback.
182
+ *
183
+ * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
184
+ * @param {function(Group)} onLoad - Executed when the loading process has been finished.
185
+ * @param {onProgressCallback} onProgress - Executed while the loading is in progress.
186
+ * @param {onErrorCallback} onError - Executed when errors occur.
56
187
  */
57
- resize() {
58
- this.camera.aspect = this.canvas.clientWidth / this.canvas.clientHeight, this.camera.updateProjectionMatrix(), this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
188
+ load(t, s, r, i) {
189
+ const n = this, o = new Nt(this.manager);
190
+ o.setPath(this.path), o.setRequestHeader(this.requestHeader), o.setWithCredentials(this.withCredentials), o.load(t, function(c) {
191
+ try {
192
+ s(n.parse(c));
193
+ } catch (u) {
194
+ i ? i(u) : console.error(u), n.manager.itemError(t);
195
+ }
196
+ }, r, i);
59
197
  }
60
198
  /**
61
- * Выполняет рендеринг сцены с текущей камерой.
199
+ * Sets the material creator for this OBJ. This object is loaded via {@link MTLLoader}.
200
+ *
201
+ * @param {MaterialCreator} materials - An object that creates the materials for this OBJ.
202
+ * @return {OBJLoader} A reference to this loader.
62
203
  */
63
- render() {
64
- this.renderer.render(this.scene, this.camera);
204
+ setMaterials(t) {
205
+ return this.materials = t, this;
65
206
  }
66
207
  /**
67
- * Метод для обновления логики рендерера.
208
+ * Parses the given OBJ data and returns the resulting group.
209
+ *
210
+ * @param {string} text - The raw OBJ data as a string.
211
+ * @return {Group} The parsed OBJ.
68
212
  */
69
- update() {
213
+ parse(t) {
214
+ const s = new ds();
215
+ t.indexOf(`\r
216
+ `) !== -1 && (t = t.replace(/\r\n/g, `
217
+ `)), t.indexOf(`\\
218
+ `) !== -1 && (t = t.replace(/\\\n/g, ""));
219
+ const r = t.split(`
220
+ `);
221
+ let i = [];
222
+ for (let c = 0, u = r.length; c < u; c++) {
223
+ const d = r[c].trimStart();
224
+ if (d.length === 0) continue;
225
+ const m = d.charAt(0);
226
+ if (m !== "#")
227
+ if (m === "v") {
228
+ const p = d.split(lt);
229
+ switch (p[0]) {
230
+ case "v":
231
+ s.vertices.push(
232
+ parseFloat(p[1]),
233
+ parseFloat(p[2]),
234
+ parseFloat(p[3])
235
+ ), p.length >= 7 ? (te.setRGB(
236
+ parseFloat(p[4]),
237
+ parseFloat(p[5]),
238
+ parseFloat(p[6]),
239
+ wt
240
+ ), s.colors.push(te.r, te.g, te.b)) : s.colors.push(void 0, void 0, void 0);
241
+ break;
242
+ case "vn":
243
+ s.normals.push(
244
+ parseFloat(p[1]),
245
+ parseFloat(p[2]),
246
+ parseFloat(p[3])
247
+ );
248
+ break;
249
+ case "vt":
250
+ s.uvs.push(
251
+ parseFloat(p[1]),
252
+ parseFloat(p[2])
253
+ );
254
+ break;
255
+ }
256
+ } else if (m === "f") {
257
+ const g = d.slice(1).trim().split(lt), f = [];
258
+ for (let v = 0, y = g.length; v < y; v++) {
259
+ const A = g[v];
260
+ if (A.length > 0) {
261
+ const S = A.split("/");
262
+ f.push(S);
263
+ }
264
+ }
265
+ const h = f[0];
266
+ for (let v = 1, y = f.length - 1; v < y; v++) {
267
+ const A = f[v], S = f[v + 1];
268
+ s.addFace(
269
+ h[0],
270
+ A[0],
271
+ S[0],
272
+ h[1],
273
+ A[1],
274
+ S[1],
275
+ h[2],
276
+ A[2],
277
+ S[2]
278
+ );
279
+ }
280
+ } else if (m === "l") {
281
+ const p = d.substring(1).trim().split(" ");
282
+ let g = [];
283
+ const f = [];
284
+ if (d.indexOf("/") === -1)
285
+ g = p;
286
+ else
287
+ for (let h = 0, v = p.length; h < v; h++) {
288
+ const y = p[h].split("/");
289
+ y[0] !== "" && g.push(y[0]), y[1] !== "" && f.push(y[1]);
290
+ }
291
+ s.addLineGeometry(g, f);
292
+ } else if (m === "p") {
293
+ const g = d.slice(1).trim().split(" ");
294
+ s.addPointGeometry(g);
295
+ } else if ((i = as.exec(d)) !== null) {
296
+ const p = (" " + i[0].slice(1).trim()).slice(1);
297
+ s.startObject(p);
298
+ } else if (cs.test(d))
299
+ s.object.startMaterial(d.substring(7).trim(), s.materialLibraries);
300
+ else if (ls.test(d))
301
+ s.materialLibraries.push(d.substring(7).trim());
302
+ else if (hs.test(d))
303
+ console.warn('THREE.OBJLoader: Rendering identifier "usemap" not supported. Textures must be defined in MTL files.');
304
+ else if (m === "s") {
305
+ if (i = d.split(" "), i.length > 1) {
306
+ const g = i[1].trim().toLowerCase();
307
+ s.object.smooth = g !== "0" && g !== "off";
308
+ } else
309
+ s.object.smooth = !0;
310
+ const p = s.object.currentMaterial();
311
+ p && (p.smooth = s.object.smooth);
312
+ } else {
313
+ if (d === "\0") continue;
314
+ console.warn('THREE.OBJLoader: Unexpected line: "' + d + '"');
315
+ }
316
+ }
317
+ s.finalize();
318
+ const n = new Xt();
319
+ if (n.materialLibraries = [].concat(s.materialLibraries), !(s.objects.length === 1 && s.objects[0].geometry.vertices.length === 0) === !0)
320
+ for (let c = 0, u = s.objects.length; c < u; c++) {
321
+ const d = s.objects[c], m = d.geometry, p = d.materials, g = m.type === "Line", f = m.type === "Points";
322
+ let h = !1;
323
+ if (m.vertices.length === 0) continue;
324
+ const v = new it();
325
+ v.setAttribute("position", new X(m.vertices, 3)), m.normals.length > 0 && v.setAttribute("normal", new X(m.normals, 3)), m.colors.length > 0 && (h = !0, v.setAttribute("color", new X(m.colors, 3))), m.hasUVIndices === !0 && v.setAttribute("uv", new X(m.uvs, 2));
326
+ const y = [];
327
+ for (let S = 0, x = p.length; S < x; S++) {
328
+ const b = p[S], C = b.name + "_" + b.smooth + "_" + h;
329
+ let M = s.materials[C];
330
+ if (this.materials !== null) {
331
+ if (M = this.materials.create(b.name), g && M && !(M instanceof Se)) {
332
+ const I = new Se();
333
+ nt.prototype.copy.call(I, M), I.color.copy(M.color), M = I;
334
+ } else if (f && M && !(M instanceof ee)) {
335
+ const I = new ee({ size: 10, sizeAttenuation: !1 });
336
+ nt.prototype.copy.call(I, M), I.color.copy(M.color), I.map = M.map, M = I;
337
+ }
338
+ }
339
+ M === void 0 && (g ? M = new Se() : f ? M = new ee({ size: 1, sizeAttenuation: !1 }) : M = new Yt(), M.name = b.name, M.flatShading = !b.smooth, M.vertexColors = h, s.materials[C] = M), y.push(M);
340
+ }
341
+ let A;
342
+ if (y.length > 1) {
343
+ for (let S = 0, x = p.length; S < x; S++) {
344
+ const b = p[S];
345
+ v.addGroup(b.groupStart, b.groupCount, S);
346
+ }
347
+ g ? A = new ot(v, y) : f ? A = new we(v, y) : A = new at(v, y);
348
+ } else
349
+ g ? A = new ot(v, y[0]) : f ? A = new we(v, y[0]) : A = new at(v, y[0]);
350
+ A.name = d.name, n.add(A);
351
+ }
352
+ else if (s.vertices.length > 0) {
353
+ const c = new ee({ size: 1, sizeAttenuation: !1 }), u = new it();
354
+ u.setAttribute("position", new X(s.vertices, 3)), s.colors.length > 0 && s.colors[0] !== void 0 && (u.setAttribute("color", new X(s.colors, 3)), c.vertexColors = !0);
355
+ const d = new we(u, c);
356
+ n.add(d);
357
+ }
358
+ return n;
70
359
  }
360
+ }
361
+ const Me = 16776960, xe = 16755200, _s = 2236962, ps = 2236962, ms = {
71
362
  /**
72
- * Запускает основной цикл рендеринга.
363
+ * Плоскость (PlaneGeometry)
364
+ * @returns Плоскость размером 1x1 с одной сегментацией
73
365
  */
74
- loop() {
75
- this.update(), this.render(), requestAnimationFrame(() => this.loop());
76
- }
366
+ [L.Plane]: () => new l.PlaneGeometry(1, 1, 1, 1),
77
367
  /**
78
- * Добавление фигуры на сцену.
79
- * @param figure - Данные фигуры: position, normal, uv
368
+ * Куб (BoxGeometry)
369
+ * @returns Куб размером 1x1x1 с одной сегментацией по каждой оси
80
370
  */
81
- addFigure(e) {
82
- const s = new a.BufferGeometry();
83
- s.setAttribute("position", new a.Float32BufferAttribute(e.position, 3)), e.normal && s.setAttribute("normal", new a.Float32BufferAttribute(e.normal, 3)), e.uv && s.setAttribute("uv", new a.Float32BufferAttribute(e.uv, 2));
84
- const i = new a.Mesh(s, ze);
85
- return this.scene.add(i), this.meshes.push(i), i;
371
+ [L.Cube]: () => new l.BoxGeometry(1, 1, 1, 1, 1, 1),
372
+ /**
373
+ * Сфера (SphereGeometry)
374
+ * @returns Сфера радиусом 0.5, 32 сегмента по ширине, 16 по высоте
375
+ */
376
+ [L.Sphere]: () => new l.SphereGeometry(0.5, 32, 16),
377
+ /**
378
+ * UV-сфера (SphereGeometry) с гладкой поверхностью
379
+ * @returns Сфера радиусом 0.5, 32 сегмента по ширине, 16 по высоте
380
+ */
381
+ [L.UVSphere]: () => new l.SphereGeometry(0.5, 32, 16),
382
+ /**
383
+ * Икосфера (IcosahedronGeometry) — сфера из треугольников
384
+ * @returns Икосфера радиусом 0.5, уровень детализации 0
385
+ */
386
+ [L.Icosphere]: () => new l.IcosahedronGeometry(0.5, 0),
387
+ /**
388
+ * Цилиндр (CylinderGeometry)
389
+ * @returns Цилиндр радиусом 0.5, высотой 1, 32 сегмента
390
+ */
391
+ [L.Cylinder]: () => new l.CylinderGeometry(0.5, 0.5, 1, 32, 1, !1),
392
+ /**
393
+ * Конус (ConeGeometry)
394
+ * @returns Конус радиусом 0.5, высотой 1, 32 сегмента
395
+ */
396
+ [L.Cone]: () => new l.ConeGeometry(0.5, 1, 32, 1, !1),
397
+ /**
398
+ * Пирамида с квадратным основанием.
399
+ * @returns Пирамида высотой 1 и радиусом основания 0.5
400
+ */
401
+ [L.Pyramid]: () => new l.ConeGeometry(0.5, 1, 4, 1, !1),
402
+ /**
403
+ * Тетраэдр (TetrahedronGeometry)
404
+ * @returns Тетраэдр радиусом 0.5
405
+ */
406
+ [L.Tetrahedron]: () => new l.TetrahedronGeometry(0.5, 0),
407
+ /**
408
+ * Октаэдр (OctahedronGeometry)
409
+ * @returns Октаэдр радиусом 0.5
410
+ */
411
+ [L.Octahedron]: () => new l.OctahedronGeometry(0.5, 0),
412
+ /**
413
+ * Додекаэдр (DodecahedronGeometry)
414
+ * @returns Додекаэдр радиусом 0.5
415
+ */
416
+ [L.Dodecahedron]: () => new l.DodecahedronGeometry(0.5, 0),
417
+ /**
418
+ * Тор (TorusGeometry)
419
+ * @returns Тор радиусом 0.5, толщиной 0.2, 16 сегментов по радиусу, 64 по трубке
420
+ */
421
+ [L.Torus]: () => new l.TorusGeometry(0.5, 0.2, 16, 64),
422
+ /**
423
+ * Тор-кнот (TorusKnotGeometry)
424
+ * @returns Тор-кнот радиусом 0.4 и толщиной 0.12
425
+ */
426
+ [L.TorusKnot]: () => new l.TorusKnotGeometry(0.4, 0.12, 96, 16),
427
+ /**
428
+ * Круг (CircleGeometry)
429
+ * @returns Круг радиусом 0.5, 32 сегмента
430
+ */
431
+ [L.Circle]: () => new l.CircleGeometry(0.5, 32),
432
+ /**
433
+ * Кольцо (RingGeometry)
434
+ * @returns Кольцо с внутренним радиусом 0.25 и внешним радиусом 0.5
435
+ */
436
+ [L.Ring]: () => new l.RingGeometry(0.25, 0.5, 32),
437
+ /**
438
+ * Капсула (CapsuleGeometry)
439
+ * @returns Капсула радиусом 0.3 и длиной 0.8
440
+ */
441
+ [L.Capsule]: () => new l.CapsuleGeometry(0.3, 0.8, 8, 16),
442
+ /**
443
+ * Кастомная геометрия (не реализовано в фабрике)
444
+ * @throws {Error} Всегда выбрасывает ошибку
445
+ */
446
+ [L.Custom]: function() {
447
+ throw new Error("Custom geometry is not generated here.");
448
+ }
449
+ }, Ot = new l.MeshStandardMaterial({
450
+ color: 12566463,
451
+ metalness: 0,
452
+ roughness: 0.6
453
+ }), gs = 8, z = 0, Ct = 1, It = 2, $ = 31, fs = 0.03, vs = 0.05, et = (e) => !!e && e.isMesh, Pt = (e) => {
454
+ let t = e;
455
+ for (; t; ) {
456
+ if (t.isMesh) return t;
457
+ t = t.parent;
458
+ }
459
+ return null;
460
+ }, Lt = (e) => {
461
+ const t = new l.BufferGeometry();
462
+ t.setAttribute("position", e.getAttribute("position")), t.computeBoundingSphere(), t.computeBoundingBox();
463
+ const s = new l.PointsMaterial({
464
+ color: ps,
465
+ size: 6,
466
+ sizeAttenuation: !1,
467
+ depthTest: !1,
468
+ depthWrite: !1,
469
+ transparent: !0,
470
+ opacity: 0.9
471
+ }), r = new l.Points(t, s);
472
+ return r.layers.set(It), r.renderOrder = 1e3, r.visible = !1, r;
473
+ }, Et = (e) => {
474
+ const t = new l.EdgesGeometry(e), s = new l.LineSegments(
475
+ t,
476
+ new l.LineBasicMaterial({ color: _s, linewidth: 1 })
477
+ );
478
+ return s.layers.set(Ct), s;
479
+ }, ys = (e) => {
480
+ const t = { x: e.position.x, y: e.position.y, z: e.position.z }, s = { x: e.rotation.x, y: e.rotation.y, z: e.rotation.z }, r = { x: e.scale.x, y: e.scale.y, z: e.scale.z }, i = new l.Box3().setFromObject(e), n = new l.Vector3();
481
+ i.getSize(n);
482
+ const o = { x: n.x, y: n.y, z: n.z };
483
+ return { position: t, rotation: s, scale: r, size: o };
484
+ }, Tt = (e, t) => t ? {
485
+ background: {
486
+ ...e.background,
487
+ ...t.background
488
+ },
489
+ camera: {
490
+ ...e.camera,
491
+ ...t.camera,
492
+ position: {
493
+ ...e.camera.position,
494
+ ...t.camera?.position
495
+ }
496
+ },
497
+ renderer: {
498
+ ...e.renderer,
499
+ ...t.renderer
500
+ },
501
+ lights: {
502
+ ambient: {
503
+ ...e.lights.ambient,
504
+ ...t.lights?.ambient
505
+ },
506
+ directional: {
507
+ ...e.lights.directional,
508
+ ...t.lights?.directional,
509
+ position: {
510
+ ...e.lights.directional.position,
511
+ ...t.lights?.directional?.position
512
+ }
513
+ }
514
+ }
515
+ } : e, Y = (e) => (e.userData.isProxy = !0, e.userData.isExportable = !1, e), N = (e) => (e.userData.isExportable = !1, e), Vt = (e) => e.userData.isProxy === !0, bs = (e) => {
516
+ let t = e;
517
+ for (; t; ) {
518
+ if (t.userData.isExportable === !1)
519
+ return !0;
520
+ t = t.parent;
521
+ }
522
+ return !1;
523
+ }, Ms = (e) => !et(e) || !e.visible || Vt(e) || bs(e) ? !1 : e.userData.isExportable !== !1, xs = (e) => {
524
+ const t = new l.Group();
525
+ return t.name = "Planara_OBJ_Export", e.updateMatrixWorld(!0), e.traverse((s) => {
526
+ if (!Ms(s))
527
+ return;
528
+ const r = s.clone(!1);
529
+ r.geometry = s.geometry.clone(), Array.isArray(s.material) ? r.material = s.material.map((i) => i.clone()) : r.material = s.material.clone(), r.matrix.copy(s.matrixWorld), r.matrixAutoUpdate = !1, t.add(r);
530
+ }), t;
531
+ }, Dt = (e) => {
532
+ const s = new us().parse(e);
533
+ s.updateMatrixWorld(!0);
534
+ const r = [];
535
+ return s.traverse((i) => {
536
+ if (!et(i))
537
+ return;
538
+ const n = i.geometry.clone();
539
+ n.applyMatrix4(i.matrixWorld), n.computeBoundingBox();
540
+ const o = n.boundingBox;
541
+ if (!o)
542
+ return;
543
+ const c = new l.Vector3();
544
+ o.getCenter(c), n.translate(-c.x, -c.y, -c.z), n.computeBoundingBox(), n.computeBoundingSphere(), n.computeVertexNormals();
545
+ const u = n.getAttribute("position");
546
+ u && u.setUsage && u.setUsage(l.DynamicDrawUsage);
547
+ const d = new l.Mesh(n, Ot.clone());
548
+ d.position.copy(c), d.layers.enable(z);
549
+ const m = n.index ? n.toNonIndexed() : n, p = N(Et(m));
550
+ p.layers.enable(z), d.add(p);
551
+ const g = N(Lt(m));
552
+ g.layers.enable(z), d.add(g), r.push(d);
553
+ }), r;
554
+ }, jt = {
555
+ background: {
556
+ color: 1710618,
557
+ transparent: !1
558
+ },
559
+ camera: {
560
+ fov: 45,
561
+ near: 0.1,
562
+ far: 1e3,
563
+ position: {
564
+ x: 1,
565
+ y: 1,
566
+ z: 7
567
+ }
568
+ },
569
+ renderer: {
570
+ antialias: !0,
571
+ alpha: !1
572
+ },
573
+ lights: {
574
+ ambient: {
575
+ enabled: !0,
576
+ color: 16777215,
577
+ intensity: 0.5
578
+ },
579
+ directional: {
580
+ enabled: !0,
581
+ color: 16777215,
582
+ intensity: 1,
583
+ position: {
584
+ x: 5,
585
+ y: 10,
586
+ z: 7
587
+ }
588
+ }
86
589
  }
590
+ };
591
+ var Ss = Object.getOwnPropertyDescriptor, ws = (e, t, s, r) => {
592
+ for (var i = r > 1 ? void 0 : r ? Ss(t, s) : t, n = e.length - 1, o; n >= 0; n--)
593
+ (o = e[n]) && (i = o(i) || i);
594
+ return i;
595
+ }, ut = (e, t) => (s, r) => t(s, r, e);
596
+ let ae = class {
87
597
  /**
88
- * Добавляет фигуру в сцену и сохраняет его во внутреннем массиве.
598
+ * Конструктор рендерера.
89
599
  *
90
- * @param mesh - Фигура для добавления в сцену.
91
- * @internal
600
+ * @param _canvas - HTMLCanvasElement для рендеринга
601
+ * @param _config - Конфиг для настройки рендерера
602
+ *
603
+ * @remarks
604
+ * Инициализирует сцену, камеру, WebGLRenderer и базовое освещение
605
+ * на основе переданного `RendererConfig`.
606
+ *
607
+ * По умолчанию используется тёмный фон, перспективная камера
608
+ * и два источника света: AmbientLight и DirectionalLight.
609
+ *
610
+ * @public
611
+ * @constructor
92
612
  */
93
- addMesh(e) {
94
- this.scene && (this.scene.add(e), this.meshes.push(e));
613
+ constructor(e, t) {
614
+ if (this._config = t, this.canvas = e, this.scene = new l.Scene(), this._config.background.transparent ? this.scene.background = null : this.scene.background = new l.Color(this._config.background.color), this.camera = new l.PerspectiveCamera(
615
+ this._config.camera.fov,
616
+ this.canvas.clientWidth / this.canvas.clientHeight,
617
+ this._config.camera.near,
618
+ this._config.camera.far
619
+ ), this.camera.position.set(
620
+ this._config.camera.position.x,
621
+ this._config.camera.position.y,
622
+ this._config.camera.position.z
623
+ ), this.renderer = new l.WebGLRenderer({
624
+ canvas: this.canvas,
625
+ antialias: this._config.renderer.antialias,
626
+ alpha: this._config.background.transparent || this._config.renderer.alpha
627
+ }), this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight), this._config.background.transparent ? this.renderer.setClearAlpha(0) : this.renderer.setClearColor(this._config.background.color, 1), this._config.lights.ambient.enabled) {
628
+ const s = new l.AmbientLight(
629
+ this._config.lights.ambient.color,
630
+ this._config.lights.ambient.intensity
631
+ );
632
+ this.scene.add(N(s));
633
+ }
634
+ if (this._config.lights.directional.enabled) {
635
+ const s = new l.DirectionalLight(
636
+ this._config.lights.directional.color,
637
+ this._config.lights.directional.intensity
638
+ );
639
+ s.position.set(
640
+ this._config.lights.directional.position.x,
641
+ this._config.lights.directional.position.y,
642
+ this._config.lights.directional.position.z
643
+ ), this.scene.add(N(s));
644
+ }
95
645
  }
96
646
  /**
97
- * Убирает фигуру со сцены
647
+ * Корневой объект сцены Three.js.
98
648
  *
99
- * @param mesh - Фигура для удаления со сцены.
100
- * @internal
649
+ * @protected
650
+ * @member
101
651
  */
102
- removeMesh(e) {
103
- this.scene && (this.scene.remove(e), this.meshes = this.meshes.filter((s) => s !== e));
104
- }
652
+ scene;
105
653
  /**
106
- * Возвращает список всех фигур, находящихся в сцене.
654
+ * Камера для сцены Three.js.
107
655
  *
108
- * @returns Массив текущих фигур.
109
- * @internal
656
+ * @protected
657
+ * @member
110
658
  */
111
- getMeshes() {
112
- return this.meshes;
113
- }
659
+ camera;
114
660
  /**
115
- * Добавляет объект в сцену и (опционально) выставляет ему слой.
661
+ * Экземпляр Three.js WebGLRenderer.
116
662
  *
117
- * @param obj - Объект, который нужно добавить в сцену.
118
- * @param layer - (Опц.) Номер слоя, который следует установить объекту перед добавлением.
663
+ * @protected
664
+ * @member
665
+ */
666
+ renderer;
667
+ /**
668
+ * HTML-элемент canvas, на котором рендерится сцена.
669
+ *
670
+ * @protected
671
+ * @member
672
+ */
673
+ canvas;
674
+ /**
675
+ * Обновляет размер рендерера и пропорции камеры.
119
676
  *
120
677
  * @remarks
121
- * Если рендерер уже диспоузнут (scene отсутствует), метод тихо завершится.
122
- * Слой задаётся через `obj.layers.set(layer)`, после чего объект добавляется в `this.scene`.
678
+ * Вызывается при изменении размеров canvas (например, при ресайзе окна браузера).
123
679
  *
124
680
  * @example
125
- * // Добавить оверлей на слой подсветок:
126
- * add(overlayLine, OVERLAY_LAYER);
681
+ * ```typescript
682
+ * window.addEventListener('resize', () => renderer.resize());
683
+ * ```
127
684
  *
128
- * @internal
685
+ * @public
686
+ * @method
129
687
  */
130
- addObject(e, s) {
131
- this.scene && (typeof s == "number" && e.layers.set(s), this.scene.add(e));
688
+ resize() {
689
+ this.camera.aspect = this.canvas.clientWidth / this.canvas.clientHeight, this.camera.updateProjectionMatrix(), this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
132
690
  }
133
691
  /**
134
- * Удаляет объект из сцены (или из его родителя, если он есть).
135
- *
136
- * @param obj - Объект, который необходимо удалить.
692
+ * Выполняет рендеринг текущего кадра.
137
693
  *
138
694
  * @remarks
139
- * Если у объекта есть `parent`, он будет удалён из родителя. Иначе — метод попытается
140
- * удалить его напрямую из `this.scene`. В рамках данного API метод не отвечает за
141
- * освобождение GPU-ресурсов; освобождайте геометрию/материалы отдельно при необходимости.
695
+ * Рендерит сцену с текущей камерой.
696
+ * Вызывается автоматически в цикле `loop()`.
142
697
  *
143
- * @example
144
- * // Снять оверлей со сцены:
145
- * removeObject(overlayLine);
146
- *
147
- * @internal
698
+ * @public
699
+ * @method
148
700
  */
149
- removeObject(e) {
150
- this.scene && (e.parent ? e.parent.remove(e) : this.scene.remove(e));
701
+ render() {
702
+ this.renderer.render(this.scene, this.camera);
151
703
  }
152
704
  /**
153
- * Включает указанный слой у активной камеры.
705
+ * Обновляет состояние рендерера перед рендерингом.
706
+ *
707
+ * @remarks
708
+ * Пустой метод, предназначен для переопределения в наследниках
709
+ * (например, для обновления контролов камеры).
154
710
  *
155
- * @param layer - Номер слоя, который требуется сделать видимым для камеры.
711
+ * @protected
712
+ * @method
713
+ * @virtual
714
+ */
715
+ update() {
716
+ }
717
+ /**
718
+ * Запускает основной цикл рендеринга.
156
719
  *
157
720
  * @remarks
158
- * Полезно для показа служебных оверлеев (например, подсветки) на отдельном слое.
159
- * Метод не изменяет слои Raycaster — ими должен управлять другой слой API (например, IRaycastAPI).
721
+ * Вызывает `update()` и `render()` каждый кадр с помощью `requestAnimationFrame`.
722
+ * **Важно:** вызывать метод только один раз.
160
723
  *
161
724
  * @example
162
- * // Убедиться, что камера видит слой оверлеев:
163
- * enableCameraLayer(OVERLAY_LAYER);
725
+ * ```typescript
726
+ * renderer.loop();
727
+ * ```
164
728
  *
165
- * @internal
729
+ * @public
730
+ * @method
166
731
  */
167
- enableCameraLayer(e) {
168
- this.camera && this.camera.layers.enable(e);
169
- }
170
- /** Освобождает ресурсы рендерера, очищает внутренние данные. */
171
- dispose() {
172
- this.meshes && (this.meshes.length = 0, this.meshes = []), this.scene = null, this.camera = null, this.renderer?.dispose(), this.canvas = null;
173
- }
174
- }
175
- var ct = Object.getOwnPropertyDescriptor, dt = (t, e, s, i) => {
176
- for (var r = i > 1 ? void 0 : i ? ct(e, s) : e, o = t.length - 1, n; o >= 0; o--)
177
- (n = t[o]) && (r = n(r) || r);
178
- return r;
179
- };
180
- let Q = class {
181
- _emitter;
182
- constructor() {
183
- this._emitter = new nt();
732
+ loop() {
733
+ this.update(), this.render(), requestAnimationFrame(() => this.loop());
184
734
  }
185
- /** Публикация события */
186
- emit(t, e) {
187
- this._emitter.emit(t, e);
735
+ getCamera() {
736
+ return this.camera;
188
737
  }
189
- /** Подписка на событие */
190
- on(t, e) {
191
- this._emitter.on(t, e);
738
+ getRenderer() {
739
+ return this.renderer;
192
740
  }
193
- /** Отписка от события */
194
- off(t, e) {
195
- this._emitter.off(t, e);
741
+ getCanvas() {
742
+ return this.canvas;
196
743
  }
197
- };
198
- Q = dt([
199
- M()
200
- ], Q);
201
- var H = /* @__PURE__ */ ((t) => (t.SelectHover = "select.hover", t.SelectClick = "select.click", t.ToolSelect = "tool.select", t))(H || {});
202
- const _t = 0.03, ut = 0.05, J = 0, pt = 1, mt = 2, T = 31, Z = 16776960, X = 16755200, ft = 2236962, gt = 2236962, bt = (t) => !!t && t.isMesh, Ye = (t) => {
203
- let e = t;
204
- for (; e; ) {
205
- if (e.isMesh) return e;
206
- e = e.parent;
744
+ getDomElement() {
745
+ return this.renderer.domElement;
207
746
  }
208
- return null;
209
- }, $e = (t) => {
210
- const e = new a.BufferGeometry();
211
- e.setAttribute("position", t.getAttribute("position")), e.computeBoundingSphere(), e.computeBoundingBox();
212
- const s = new a.PointsMaterial({
213
- color: gt,
214
- size: 6,
215
- sizeAttenuation: !1,
216
- depthTest: !1,
217
- depthWrite: !1,
218
- transparent: !0,
219
- opacity: 0.9
220
- }), i = new a.Points(e, s);
221
- return i.layers.set(mt), i.renderOrder = 1e3, i.visible = !1, i;
222
- }, Ue = (t) => {
223
- const e = new a.EdgesGeometry(t), s = new a.LineSegments(
224
- e,
225
- new a.LineBasicMaterial({ color: ft, linewidth: 1 })
226
- );
227
- return s.layers.set(pt), s;
228
- }, vt = (t) => {
229
- const e = { x: t.position.x, y: t.position.y, z: t.position.z }, s = { x: t.rotation.x, y: t.rotation.y, z: t.rotation.z }, i = { x: t.scale.x, y: t.scale.y, z: t.scale.z }, r = new a.Box3().setFromObject(t), o = new a.Vector3();
230
- r.getSize(o);
231
- const n = { x: o.x, y: o.y, z: o.z };
232
- return { position: e, rotation: s, scale: i, size: n };
233
- };
234
- var yt = Object.getOwnPropertyDescriptor, Mt = (t, e, s, i) => {
235
- for (var r = i > 1 ? void 0 : i ? yt(e, s) : e, o = t.length - 1, n; o >= 0; o--)
236
- (n = t[o]) && (r = n(r) || r);
237
- return r;
238
- }, Oe = (t, e) => (s, i) => e(s, i, t);
239
- let ee = class extends Ne {
240
- constructor(t, e) {
241
- super(t), this._canvas = t, this._bus = e;
242
- const s = new a.GridHelper(10, 10);
243
- s.position.y = -1e-3, this.scene.add(s);
244
- const i = new tt(6);
245
- this.scene.add(i), this._orbit = new st(this.camera, this.renderer.domElement), this._orbit.enableDamping = !0, this._orbit.dampingFactor = 0.05, this._cameraGizmo = new it(this.renderer, this.camera, {
246
- size: 96,
247
- // Размер квадрата
248
- margin: 36
249
- // Отступы по сторонам (снизу и справа)
250
- }), this._raycaster = new a.Raycaster(), this._mouse = new a.Vector2(), this.scene.add(new a.HemisphereLight(16777215, 4473924, 0.6)), this.camera.layers.enable(0), this.camera.layers.enable(1), this._transform = new rt(this.camera, this.renderer.domElement), this._transformHelper = this._transform.getHelper(), this.scene.add(this._transformHelper), this._isEventListenersAdded || this._initMouseListeners();
747
+ getScene() {
748
+ return this.scene;
251
749
  }
252
- /** Orbit-контроллер для управления камерой */
253
- _orbit;
254
- /** Transform-контроллер для редактирования */
255
- _transform;
256
- _transformHelper;
257
- /** Raycast для получения событий наведения/клика по модели*/
258
- _raycaster;
259
- /** Курсор мыши */
260
- _mouse;
261
- /** Были ли инициализированы обработчики событий (hover/click) */
262
- _isEventListenersAdded = !1;
263
750
  /**
264
- * Ключ последней модели, на которую наводились,
265
- * необходима для отправки только уникальных событий в event bus
751
+ * Освобождает ресурсы рендерера.
752
+ *
753
+ * @remarks
754
+ * Удаляет ссылки на сцену, камеру и canvas, вызывает `dispose()` у WebGLRenderer.
755
+ * Вызывается при уничтожении редактора IOC-контейнером.
756
+ *
757
+ * @public
758
+ * @method
266
759
  */
267
- _lastHoverKey = null;
268
- _currentRaycastMode = y.Mesh;
269
- /** Gizmo для управления отображением perspective camera */
270
- _cameraGizmo;
271
- _transformListeners = /* @__PURE__ */ new Set();
760
+ dispose() {
761
+ this.scene = null, this.camera = null, this.renderer?.dispose(), this.canvas = null;
762
+ }
763
+ };
764
+ ae = ws([
765
+ w(),
766
+ ut(0, _("Canvas")),
767
+ ut(1, _("RendererConfig"))
768
+ ], ae);
769
+ class mi {
770
+ /** Позиции вершин */
771
+ _positions = [];
772
+ /** Нормали вершин */
773
+ _normals = [];
774
+ /** UV-координаты (опционально) */
775
+ _uvs = [];
776
+ // Временные поля для парсинга файла
777
+ _tmpPositions = [];
778
+ _tmpNormals = [];
779
+ _tmpUVs = [];
272
780
  /**
273
- * Обновление состояния рендерера.
781
+ * Загружает OBJ-модель в Figure
782
+ * @param objContent - Строка содержимого .obj файла
274
783
  */
275
- update() {
276
- this._orbit.update();
277
- }
278
- /** Добавление фигуры на сцену */
279
- addFigure(t) {
280
- const e = super.addFigure(t);
281
- e.layers.enable(J);
282
- const s = Ue(e.geometry);
283
- e.add(s);
284
- const i = $e(e.geometry);
285
- return e.add(i), e;
784
+ load(t) {
785
+ const s = t.split(`
786
+ `);
787
+ for (const i of s) {
788
+ if (!i.trim() || i.startsWith("#")) continue;
789
+ const n = i.trim().split(/\s+/);
790
+ switch (n[0]) {
791
+ case "v":
792
+ this._tmpPositions.push(n.slice(1).map(Number));
793
+ break;
794
+ case "vn":
795
+ this._tmpNormals.push(n.slice(1).map(Number));
796
+ break;
797
+ case "vt":
798
+ this._tmpUVs.push(n.slice(1).map(Number));
799
+ break;
800
+ case "f":
801
+ this.processFaceLine(n);
802
+ break;
803
+ }
804
+ }
805
+ const r = {
806
+ type: L.Custom,
807
+ position: this._positions,
808
+ ...this._normals.length > 0 && { normal: this._normals },
809
+ ...this._uvs.length > 0 && { uv: this._uvs }
810
+ };
811
+ return new Qt(r);
286
812
  }
287
813
  /**
288
- * Смена отображения `TransformControls` в зависимости от типа инструмента.
289
- * @param mode - тип инструмента для отображения `TransformControls`.
290
- * @internal
814
+ * Обрабатывает строку face (f) и разворачивает индексы в массивы для рендеринга
291
815
  */
292
- setTransformControlsMode(t) {
293
- this._transform.setMode(t);
816
+ processFaceLine(t) {
817
+ for (let s = 1; s < t.length; s++) {
818
+ const r = t[s];
819
+ if (!r) continue;
820
+ const [i, n, o] = r.split("/"), c = i ? parseInt(i, 10) : void 0, u = n ? parseInt(n, 10) : void 0, d = o ? parseInt(o, 10) : void 0;
821
+ if (c !== void 0) {
822
+ const m = this._tmpPositions[c - 1];
823
+ m && this._positions.push(...m);
824
+ }
825
+ if (u !== void 0) {
826
+ const m = this._tmpUVs[u - 1];
827
+ m && this._uvs.push(...m);
828
+ }
829
+ if (d !== void 0) {
830
+ const m = this._tmpNormals[d - 1];
831
+ m && this._normals.push(...m);
832
+ }
833
+ }
294
834
  }
835
+ }
836
+ var As = Object.getOwnPropertyDescriptor, Os = (e, t, s, r) => {
837
+ for (var i = r > 1 ? void 0 : r ? As(t, s) : t, n = e.length - 1, o; n >= 0; n--)
838
+ (o = e[n]) && (i = o(i) || i);
839
+ return i;
840
+ }, se = (e, t) => (s, r) => t(s, r, e);
841
+ let le = class {
295
842
  /**
296
- * Добавление `TransformControls` к объекту.
297
- * @param object - объект, к которому добавляются `TransformControls`.
843
+ * Конструктор контроллера.
844
+ *
845
+ * @param _updatable - модули, требующие обновления каждый кадр
846
+ * @param _renderable - модули, требующие кастомного рендеринга
847
+ * @param _runtime - модули, требующие инициализации
848
+ * @param _renderer - рендерер (должен реализовывать `IRenderable`)
849
+ *
298
850
  * @internal
851
+ * @constructor
299
852
  */
300
- attachTransformControls(t) {
301
- this._transform.attach(t);
853
+ constructor(e, t, s, r) {
854
+ this._updatable = e, this._renderable = t, this._runtime = s, this._renderer = r;
302
855
  }
303
856
  /**
304
- * Удаление `TransformControls` с последнего выбранного объекта.
305
- * @internal
857
+ * ID анимационного цикла (для остановки)
858
+ *
859
+ * @private
860
+ * @member
306
861
  */
307
- detachTransformControls() {
308
- this._transform.detach();
862
+ _animationId = null;
863
+ start() {
864
+ const e = [...this._runtime, ...this._updatable, ...this._renderable];
865
+ new Set(e).forEach((t) => t.init()), this._loop();
309
866
  }
310
867
  /**
311
- * Подписывает слушателя на изменения трансформации текущего объекта.
312
- * @internal
868
+ * Внутренний анимационный цикл.
869
+ *
870
+ * @remarks
871
+ * Каждый кадр:
872
+ * 1. Обновляет модули (`update()`)
873
+ * 2. Рендерит сцену
874
+ * 3. Рендерит дополнительные модули (`render()`)
875
+ *
876
+ * @private
877
+ * @method
313
878
  */
314
- onTransformChange(t) {
315
- return this._transformListeners.add(t), () => this._transformListeners.delete(t);
879
+ _loop() {
880
+ this._updatable.forEach((e) => e.update()), this._renderer.render(), this._renderable.forEach((e) => e.render()), this._animationId = requestAnimationFrame(() => this._loop());
881
+ }
882
+ stop() {
883
+ this._animationId && (cancelAnimationFrame(this._animationId), this._animationId = null);
316
884
  }
317
885
  /**
318
- * Настройка режимов для `Raycaster`.
319
- * @internal
886
+ * Освобождает ресурсы контроллера.
887
+ *
888
+ * @public
889
+ * @method
320
890
  */
321
- setRaycastMode(t) {
322
- const e = this._raycaster;
323
- switch (e.params.Line.threshold = 0, e.params.Points.threshold = 0, this._currentRaycastMode = t, this._lastHoverKey = null, t) {
324
- case y.Mesh:
325
- case y.Face:
326
- e.layers.set(0);
327
- break;
328
- case y.Edge:
329
- e.layers.set(1), e.params.Line.threshold = _t;
330
- break;
331
- case y.Vertex:
332
- e.layers.set(2), e.params.Points.threshold = ut;
333
- break;
334
- }
335
- }
336
891
  dispose() {
337
- this._isEventListenersAdded && (this._canvas.removeEventListener("mousemove", this._handleMouseMove, !1), this._canvas.removeEventListener("click", this._handleMouseClick, !1), this._canvas.removeEventListener("dblclick", this._handleDoubleClick, !1), this._canvas.removeEventListener("pointerdown", (t) => this._transform.pointerDown(t)), this._canvas.removeEventListener("pointermove", (t) => this._transform.pointerMove(t)), this._canvas.removeEventListener("pointerup", (t) => this._transform.pointerUp(t)), this._canvas.removeEventListener("pointerleave", () => this._transform.pointerHover(null)), this._transform.removeEventListener("dragging-changed", () => {
338
- this._orbit.enabled = !this._transform.dragging;
339
- }), this._transformListeners.clear(), this._isEventListenersAdded = !1), this._orbit?.dispose(), this._transform?.dispose(), this._transformHelper?.parent && this._transformHelper.parent.remove(this._transformHelper), this._lastHoverKey = null, super.dispose();
892
+ this._animationId = null;
340
893
  }
341
- render() {
342
- super.render(), this._cameraGizmo.render(this._canvas.width, this._canvas.height);
894
+ };
895
+ le = Os([
896
+ w(),
897
+ se(0, B("IUpdatableModule", { isOptional: !0 })),
898
+ se(1, B("IRenderableModule", { isOptional: !0 })),
899
+ se(2, B("IRuntimeModule", { isOptional: !0 })),
900
+ se(3, _("IRenderable"))
901
+ ], le);
902
+ var Cs = Object.getOwnPropertyDescriptor, Is = (e, t, s, r) => {
903
+ for (var i = r > 1 ? void 0 : r ? Cs(t, s) : t, n = e.length - 1, o; n >= 0; n--)
904
+ (o = e[n]) && (i = o(i) || i);
905
+ return i;
906
+ }, Ps = (e, t) => (s, r) => t(s, r, e);
907
+ let Ee = class {
908
+ /** @constructor */
909
+ constructor(e) {
910
+ this._controlsModule = e;
343
911
  }
344
- /** Инициализация обработчиков событий на hover/click */
345
- _initMouseListeners() {
346
- this._canvas.addEventListener("mousemove", this._handleMouseMove, !1), this._canvas.addEventListener("click", this._handleMouseClick, !1), this._canvas.addEventListener("dblclick", this._handleDoubleClick, !1), this._canvas.addEventListener("pointerdown", (t) => this._transform.pointerDown(t)), this._canvas.addEventListener("pointermove", (t) => this._transform.pointerMove(t)), this._canvas.addEventListener("pointerup", (t) => this._transform.pointerUp(t)), this._canvas.addEventListener("pointerleave", () => this._transform.pointerHover(null)), this._transform.addEventListener("dragging-changed", () => {
347
- this._orbit.enabled = !this._transform.dragging;
348
- }), this._transform.addEventListener("objectChange", () => {
349
- for (const t of this._transformListeners) t();
350
- }), this._isEventListenersAdded = !0;
912
+ isOrbitInteracting() {
913
+ return this._controlsModule.isOrbitInteracting();
351
914
  }
352
- /** Обработчик события для hover */
353
- _handleMouseMove = (t) => {
354
- this._processRaycastEvent(t, H.SelectHover, !0);
915
+ isTransformDragging() {
916
+ return this._controlsModule.isTransformDragging();
917
+ }
918
+ };
919
+ Ee = Is([
920
+ w(),
921
+ Ps(0, _("ControlsModule"))
922
+ ], Ee);
923
+ var Ls = Object.getOwnPropertyDescriptor, Es = (e, t, s, r) => {
924
+ for (var i = r > 1 ? void 0 : r ? Ls(t, s) : t, n = e.length - 1, o; n >= 0; n--)
925
+ (o = e[n]) && (i = o(i) || i);
926
+ return i;
927
+ }, Ts = (e, t) => (s, r) => t(s, r, e);
928
+ let ce = class {
929
+ /** @constructor */
930
+ constructor(e) {
931
+ this._sceneModule = e;
932
+ }
933
+ addMesh(e) {
934
+ this._sceneModule.addMesh(e);
935
+ }
936
+ addMeshes(e) {
937
+ this._sceneModule.addMeshes(e);
938
+ }
939
+ removeMesh(e) {
940
+ this._sceneModule.removeMesh(e);
941
+ }
942
+ removeMeshes(e) {
943
+ this._sceneModule.removeMeshes(e);
944
+ }
945
+ getMeshes() {
946
+ return this._sceneModule.getMeshes();
947
+ }
948
+ };
949
+ ce = Es([
950
+ w(),
951
+ Ts(0, _("SceneModule"))
952
+ ], ce);
953
+ var Vs = Object.getOwnPropertyDescriptor, Ds = (e, t, s, r) => {
954
+ for (var i = r > 1 ? void 0 : r ? Vs(t, s) : t, n = e.length - 1, o; n >= 0; n--)
955
+ (o = e[n]) && (i = o(i) || i);
956
+ return i;
957
+ }, js = (e, t) => (s, r) => t(s, r, e);
958
+ let Te = class {
959
+ /** @constructor */
960
+ constructor(e) {
961
+ this._raycastModule = e;
962
+ }
963
+ setRaycastMode(e) {
964
+ this._raycastModule.setRaycastMode(e);
965
+ }
966
+ };
967
+ Te = Ds([
968
+ w(),
969
+ js(0, _("RaycastModule"))
970
+ ], Te);
971
+ var $s = Object.getOwnPropertyDescriptor, Rs = (e, t, s, r) => {
972
+ for (var i = r > 1 ? void 0 : r ? $s(t, s) : t, n = e.length - 1, o; n >= 0; n--)
973
+ (o = e[n]) && (i = o(i) || i);
974
+ return i;
975
+ }, Fs = (e, t) => (s, r) => t(s, r, e);
976
+ let Ve = class {
977
+ /** @constructor */
978
+ constructor(e) {
979
+ this._controlsModule = e;
980
+ }
981
+ attachTransform(e) {
982
+ this._controlsModule.attachTransform(e);
983
+ }
984
+ detachTransform() {
985
+ this._controlsModule.detachTransform();
986
+ }
987
+ setTransformMode(e) {
988
+ this._controlsModule.setTransformMode(e);
989
+ }
990
+ onTransformChange(e) {
991
+ return this._controlsModule.onTransformChange(e);
992
+ }
993
+ };
994
+ Ve = Rs([
995
+ w(),
996
+ Fs(0, _("ControlsModule"))
997
+ ], Ve);
998
+ var Hs = Object.getOwnPropertyDescriptor, Bs = (e, t, s, r) => {
999
+ for (var i = r > 1 ? void 0 : r ? Hs(t, s) : t, n = e.length - 1, o; n >= 0; n--)
1000
+ (o = e[n]) && (i = o(i) || i);
1001
+ return i;
1002
+ }, ks = (e, t) => (s, r) => t(s, r, e);
1003
+ let he = class {
1004
+ constructor(e) {
1005
+ this._cameraAccessApi = e;
1006
+ }
1007
+ getCamera() {
1008
+ return this._cameraAccessApi.getCamera();
1009
+ }
1010
+ enableCameraLayer(e) {
1011
+ this._cameraAccessApi.getCamera().layers.enable(e);
1012
+ }
1013
+ disableCameraLayer(e) {
1014
+ this._cameraAccessApi.getCamera().layers.disable(e);
1015
+ }
1016
+ };
1017
+ he = Bs([
1018
+ w(),
1019
+ ks(0, _("IRendererCameraAccess"))
1020
+ ], he);
1021
+ var zs = Object.getOwnPropertyDescriptor, Gs = (e, t, s, r) => {
1022
+ for (var i = r > 1 ? void 0 : r ? zs(t, s) : t, n = e.length - 1, o; n >= 0; n--)
1023
+ (o = e[n]) && (i = o(i) || i);
1024
+ return i;
1025
+ }, Ws = (e, t) => (s, r) => t(s, r, e);
1026
+ let de = class {
1027
+ constructor(e) {
1028
+ this._domAccessApi = e;
1029
+ }
1030
+ getCanvas() {
1031
+ return this._domAccessApi.getCanvas();
1032
+ }
1033
+ getDomElement() {
1034
+ return this._domAccessApi.getDomElement();
1035
+ }
1036
+ };
1037
+ de = Gs([
1038
+ w(),
1039
+ Ws(0, _("IRendererDomAccess"))
1040
+ ], de);
1041
+ var Us = Object.getOwnPropertyDescriptor, Ns = (e, t, s, r) => {
1042
+ for (var i = r > 1 ? void 0 : r ? Us(t, s) : t, n = e.length - 1, o; n >= 0; n--)
1043
+ (o = e[n]) && (i = o(i) || i);
1044
+ return i;
1045
+ }, Xs = (e, t) => (s, r) => t(s, r, e);
1046
+ let ue = class {
1047
+ constructor(e) {
1048
+ this._sceneAccessApi = e;
1049
+ }
1050
+ getScene() {
1051
+ return this._sceneAccessApi.getScene();
1052
+ }
1053
+ addToScene(e) {
1054
+ this._sceneAccessApi.getScene().add(e);
1055
+ }
1056
+ removeFromScene(e) {
1057
+ this._sceneAccessApi.getScene().remove(e);
1058
+ }
1059
+ addObject(e, t) {
1060
+ const s = this._sceneAccessApi.getScene();
1061
+ s && (typeof t == "number" && e.layers.set(t), s.add(e));
1062
+ }
1063
+ };
1064
+ ue = Ns([
1065
+ w(),
1066
+ Xs(0, _("IRendererSceneAccess"))
1067
+ ], ue);
1068
+ var Ys = Object.getOwnPropertyDescriptor, qs = (e, t, s, r) => {
1069
+ for (var i = r > 1 ? void 0 : r ? Ys(t, s) : t, n = e.length - 1, o; n >= 0; n--)
1070
+ (o = e[n]) && (i = o(i) || i);
1071
+ return i;
1072
+ }, Oe = (e, t) => (s, r) => t(s, r, e);
1073
+ let _e = class {
1074
+ constructor(e, t, s) {
1075
+ this._cameraApi = e, this._domApi = t, this._sceneApi = s;
1076
+ }
1077
+ /** Orbit-контроллер для управления камерой */
1078
+ _orbit = null;
1079
+ /** Transform-контроллер для редактирования */
1080
+ _transform = null;
1081
+ _transformHelper = null;
1082
+ _transformListeners = /* @__PURE__ */ new Set();
1083
+ /** Были ли инициализированы обработчики событий (hover/click) */
1084
+ _isEventListenersAdded = !1;
1085
+ init() {
1086
+ this._orbit = new ts(this._cameraApi.getCamera(), this._domApi.getDomElement()), this._orbit.enableDamping = !0, this._orbit.dampingFactor = 0.05, this._transform = new ss(
1087
+ this._cameraApi.getCamera(),
1088
+ this._domApi.getDomElement()
1089
+ ), this._transformHelper = this._transform.getHelper(), this._sceneApi.addToScene(N(this._transformHelper)), this._initMouseListeners();
1090
+ }
1091
+ attachTransform(e) {
1092
+ this._transform?.attach(e);
1093
+ }
1094
+ detachTransform() {
1095
+ this._transform?.detach();
1096
+ }
1097
+ update() {
1098
+ this._orbit?.update();
1099
+ }
1100
+ setTransformMode(e) {
1101
+ this._transform?.setMode(e);
1102
+ }
1103
+ onTransformChange(e) {
1104
+ return this._transformListeners.add(e), () => this._transformListeners.delete(e);
1105
+ }
1106
+ isOrbitInteracting() {
1107
+ return !!this._orbit?.isInteracting;
1108
+ }
1109
+ isTransformDragging() {
1110
+ return !!this._transform?.dragging;
1111
+ }
1112
+ _handlePointerDown = (e) => {
1113
+ this._transform?.pointerDown(e);
355
1114
  };
356
- /** Обработчик события на click */
357
- _handleMouseClick = (t) => {
358
- this._processRaycastEvent(t, H.SelectClick, !1);
1115
+ _handlePointerMove = (e) => {
1116
+ this._transform?.pointerMove(e);
359
1117
  };
360
- /** Возвращает ближайшее пересечение по текущему положению курсора */
361
- _getHitIntersection(t) {
362
- if (this._orbit.isInteracting || this._transform.dragging) return;
363
- const e = this._canvas.getBoundingClientRect();
364
- this._mouse.x = (t.clientX - e.left) / e.width * 2 - 1, this._mouse.y = -((t.clientY - e.top) / e.height) * 2 + 1, this._raycaster.setFromCamera(this._mouse, this.camera);
365
- const s = this._raycaster.intersectObjects(this.meshes, !0)[0] ?? null;
366
- if (this._currentRaycastMode === y.Mesh || this._currentRaycastMode === y.Face)
367
- return s;
368
- const i = this._raycaster.layers.mask;
369
- this._raycaster.layers.set(J);
370
- const r = this._raycaster.intersectObjects(this.meshes, !0)[0] ?? null;
371
- return this._raycaster.layers.mask = i, this._getVisibleHit(s, r);
372
- }
373
- _handleDoubleClick = (t) => {
374
- const e = this._getHitIntersection(t);
375
- e !== void 0 && (e || this._bus.emit(H.SelectClick, null));
1118
+ _handlePointerUp = (e) => {
1119
+ this._transform?.pointerUp(e);
376
1120
  };
377
- // Hover сравнивается не только по object, но и по режимному ключу попадания.
378
- // Это нужно для Face/Edge/Vertex режимов, где разные элементы могут принадлежать одному и тому же Object3D.
379
- /** Вспомогательный метод для получения модели, которую выбрали и отправки события в event bus */
380
- _processRaycastEvent(t, e, s) {
381
- const i = this._getHitIntersection(t);
382
- if (i === void 0) return;
383
- const r = i?.object ?? null;
384
- if (s) {
385
- if (!i) {
386
- this.meshes.forEach((n) => n.userData.isHit = !1), this._lastHoverKey = null, this._bus.emit(e, null);
387
- return;
388
- }
389
- const o = this._makeHoverKey(i);
390
- o !== this._lastHoverKey && (this.meshes.forEach((n) => n.userData.isHit = !1), r && (r.userData.isHit = !0), this._lastHoverKey = o, this._bus.emit(e, { intersection: i }));
391
- return;
1121
+ _handlePointerLeave = () => {
1122
+ this._transform?.pointerHover(null);
1123
+ };
1124
+ _handleDraggingChanged = () => {
1125
+ this._orbit && (this._orbit.enabled = !this._transform?.dragging);
1126
+ };
1127
+ _handleObjectChange = () => {
1128
+ for (const e of this._transformListeners)
1129
+ e();
1130
+ };
1131
+ /** Инициализация обработчиков событий на hover/click */
1132
+ _initMouseListeners() {
1133
+ const e = this._domApi.getCanvas();
1134
+ !this._transform || !this._orbit || (e.addEventListener("pointerdown", this._handlePointerDown), e.addEventListener("pointermove", this._handlePointerMove), e.addEventListener("pointerup", this._handlePointerUp), e.addEventListener("pointerleave", this._handlePointerLeave), this._transform.addEventListener("dragging-changed", this._handleDraggingChanged), this._transform.addEventListener("objectChange", this._handleObjectChange), this._isEventListenersAdded = !0);
1135
+ }
1136
+ /** Освобождает ресурсы модуля */
1137
+ dispose() {
1138
+ if (this._isEventListenersAdded) {
1139
+ const e = this._domApi.getCanvas();
1140
+ if (!this._transform || !this._orbit) return;
1141
+ e.removeEventListener("pointerdown", this._handlePointerDown), e.removeEventListener("pointermove", this._handlePointerMove), e.removeEventListener("pointerup", this._handlePointerUp), e.removeEventListener("pointerleave", this._handlePointerLeave), this._transform.removeEventListener("dragging-changed", this._handleDraggingChanged), this._transform.removeEventListener("objectChange", this._handleObjectChange), this._transformListeners.clear(), this._isEventListenersAdded = !1;
392
1142
  }
393
- i && this._bus.emit(e, { intersection: i });
1143
+ this._orbit?.dispose(), this._orbit = null, this._transform?.dispose(), this._transform = null, this._transformHelper?.parent && this._transformHelper.parent.remove(this._transformHelper);
394
1144
  }
395
- /** Поиск видимой части меша
396
- * необходимо это для того, чтобы отправлять только видимые элементы модели, а не все попадания
397
- */
398
- _getVisibleHit(t, e, s = 1e-4) {
399
- return t ? e ? t.distance <= e.distance + s ? t : null : t : null;
1145
+ };
1146
+ _e = qs([
1147
+ w(),
1148
+ Oe(0, _("ICameraApi")),
1149
+ Oe(1, _("IDomApi")),
1150
+ Oe(2, _("ISceneApi"))
1151
+ ], _e);
1152
+ var Zs = Object.getOwnPropertyDescriptor, Ks = (e, t, s, r) => {
1153
+ for (var i = r > 1 ? void 0 : r ? Zs(t, s) : t, n = e.length - 1, o; n >= 0; n--)
1154
+ (o = e[n]) && (i = o(i) || i);
1155
+ return i;
1156
+ }, Ce = (e, t) => (s, r) => t(s, r, e);
1157
+ let De = class {
1158
+ constructor(e, t, s) {
1159
+ this._cameraApi = e, this._domApi = t, this._rendererApi = s;
400
1160
  }
401
- /** Строит ключ hover-пересечения с учетом текущего режима выборки */
402
- _makeHoverKey(t) {
403
- if (!t) return null;
404
- const e = t.object.uuid;
405
- switch (this._currentRaycastMode) {
406
- case y.Face:
407
- return `${e}:face:${t.faceIndex ?? -1}`;
408
- case y.Edge:
409
- return `${e}:edge:${Math.floor((t.index ?? -1) / 2)}`;
410
- case y.Vertex:
411
- return `${e}:vertex:${t.index ?? -1}`;
412
- case y.Mesh:
413
- default:
414
- return `${e}:mesh`;
415
- }
1161
+ /** Gizmo для управления отображением perspective camera */
1162
+ _cameraGizmo = null;
1163
+ init() {
1164
+ const e = this._cameraApi.getCamera(), t = this._rendererApi.getRenderer();
1165
+ this._cameraGizmo = new rs(t, e, {
1166
+ size: 96,
1167
+ // Размер квадрата
1168
+ margin: 36
1169
+ // Отступы по сторонам (снизу и справа)
1170
+ });
1171
+ }
1172
+ render() {
1173
+ const e = this._domApi.getCanvas();
1174
+ this._cameraGizmo?.render(e.width, e.height);
416
1175
  }
1176
+ /** Освобождение ресурсов модуля */
1177
+ dispose() {
1178
+ this._cameraGizmo?.dispose(), this._cameraGizmo = null;
1179
+ }
1180
+ };
1181
+ De = Ks([
1182
+ w(),
1183
+ Ce(0, _("ICameraApi")),
1184
+ Ce(1, _("IDomApi")),
1185
+ Ce(2, _("IRendererAccess"))
1186
+ ], De);
1187
+ var Js = Object.getOwnPropertyDescriptor, Qs = (e, t, s, r) => {
1188
+ for (var i = r > 1 ? void 0 : r ? Js(t, s) : t, n = e.length - 1, o; n >= 0; n--)
1189
+ (o = e[n]) && (i = o(i) || i);
1190
+ return i;
417
1191
  };
418
- ee = Mt([
419
- M(),
420
- Oe(0, _("Canvas")),
421
- Oe(1, _("EventBus"))
422
- ], ee);
423
- const Te = { type: "change" }, be = { type: "start" }, Be = { type: "end" }, B = new qe(), Le = new Qe(), wt = Math.cos(70 * Je.DEG2RAD), v = new I(), P = 2 * Math.PI, p = {
424
- NONE: -1,
425
- ROTATE: 0,
426
- DOLLY: 1,
427
- PAN: 2,
428
- TOUCH_ROTATE: 3,
429
- TOUCH_PAN: 4,
430
- TOUCH_DOLLY_PAN: 5,
431
- TOUCH_DOLLY_ROTATE: 6
432
- }, K = 1e-6;
433
- class St extends Ke {
1192
+ let je = class {
434
1193
  /**
435
- * Constructs a new controls instance.
1194
+ * Внутренний эмиттер событий Node.js.
436
1195
  *
437
- * @param {Object3D} object - The object that is managed by the controls.
438
- * @param {?HTMLElement} domElement - The HTML element used for event listeners.
1196
+ * @private
1197
+ * @member
439
1198
  */
440
- constructor(e, s = null) {
441
- super(e, s), this.state = p.NONE, this.target = new I(), this.cursor = new I(), this.minDistance = 0, this.maxDistance = 1 / 0, this.minZoom = 0, this.maxZoom = 1 / 0, this.minTargetRadius = 0, this.maxTargetRadius = 1 / 0, this.minPolarAngle = 0, this.maxPolarAngle = Math.PI, this.minAzimuthAngle = -1 / 0, this.maxAzimuthAngle = 1 / 0, this.enableDamping = !1, this.dampingFactor = 0.05, this.enableZoom = !0, this.zoomSpeed = 1, this.enableRotate = !0, this.rotateSpeed = 1, this.keyRotateSpeed = 1, this.enablePan = !0, this.panSpeed = 1, this.screenSpacePanning = !0, this.keyPanSpeed = 7, this.zoomToCursor = !1, this.autoRotate = !1, this.autoRotateSpeed = 2, this.keys = { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" }, this.mouseButtons = { LEFT: Y.ROTATE, MIDDLE: Y.DOLLY, RIGHT: Y.PAN }, this.touches = { ONE: z.ROTATE, TWO: z.DOLLY_PAN }, this.target0 = this.target.clone(), this.position0 = this.object.position.clone(), this.zoom0 = this.object.zoom, this._domElementKeyEvents = null, this._lastPosition = new I(), this._lastQuaternion = new Ee(), this._lastTargetPosition = new I(), this._quat = new Ee().setFromUnitVectors(e.up, new I(0, 1, 0)), this._quatInverse = this._quat.clone().invert(), this._spherical = new xe(), this._sphericalDelta = new xe(), this._scale = 1, this._panOffset = new I(), this._rotateStart = new L(), this._rotateEnd = new L(), this._rotateDelta = new L(), this._panStart = new L(), this._panEnd = new L(), this._panDelta = new L(), this._dollyStart = new L(), this._dollyEnd = new L(), this._dollyDelta = new L(), this._dollyDirection = new I(), this._mouse = new L(), this._performCursorZoom = !1, this._pointers = [], this._pointerPositions = {}, this._controlActive = !1, this._onPointerMove = xt.bind(this), this._onPointerDown = Et.bind(this), this._onPointerUp = Pt.bind(this), this._onContextMenu = It.bind(this), this._onMouseWheel = Lt.bind(this), this._onKeyDown = Dt.bind(this), this._onTouchStart = Ct.bind(this), this._onTouchMove = At.bind(this), this._onMouseDown = Ot.bind(this), this._onMouseMove = Tt.bind(this), this._interceptControlDown = jt.bind(this), this._interceptControlUp = Rt.bind(this), this.domElement !== null && this.connect(this.domElement), this.update();
442
- }
443
- connect(e) {
444
- super.connect(e), this.domElement.addEventListener("pointerdown", this._onPointerDown), this.domElement.addEventListener("pointercancel", this._onPointerUp), this.domElement.addEventListener("contextmenu", this._onContextMenu), this.domElement.addEventListener("wheel", this._onMouseWheel, { passive: !1 }), this.domElement.getRootNode().addEventListener("keydown", this._interceptControlDown, { passive: !0, capture: !0 }), this.domElement.style.touchAction = "none";
445
- }
446
- disconnect() {
447
- this.domElement.removeEventListener("pointerdown", this._onPointerDown), this.domElement.removeEventListener("pointermove", this._onPointerMove), this.domElement.removeEventListener("pointerup", this._onPointerUp), this.domElement.removeEventListener("pointercancel", this._onPointerUp), this.domElement.removeEventListener("wheel", this._onMouseWheel), this.domElement.removeEventListener("contextmenu", this._onContextMenu), this.stopListenToKeyEvents(), this.domElement.getRootNode().removeEventListener("keydown", this._interceptControlDown, { capture: !0 }), this.domElement.style.touchAction = "auto";
1199
+ _emitter;
1200
+ /** @constructor */
1201
+ constructor() {
1202
+ this._emitter = new ns();
448
1203
  }
449
- dispose() {
450
- this.disconnect();
1204
+ /**
1205
+ * Публикует событие в шину.
1206
+ *
1207
+ * @param event - название события (из `EventTopics`)
1208
+ * @param payload - данные события (тип зависит от события)
1209
+ *
1210
+ * @typeParam K - ключ события из `EditorEvents`
1211
+ *
1212
+ * @remarks
1213
+ * Все подписчики, зарегистрированные на это событие, получат payload.
1214
+ *
1215
+ * @example
1216
+ * ```typescript
1217
+ * // Публикация события клика
1218
+ * eventBus.emit(EventTopics.SelectClick, { intersection: hit });
1219
+ *
1220
+ * // Публикация события сброса выделения
1221
+ * eventBus.emit(EventTopics.SelectClick, null);
1222
+ * ```
1223
+ *
1224
+ * @public
1225
+ * @method
1226
+ */
1227
+ emit(e, t) {
1228
+ this._emitter.emit(e, t);
451
1229
  }
452
1230
  /**
453
- * Get the current vertical rotation, in radians.
1231
+ * Подписывается на событие.
1232
+ *
1233
+ * @param event - название события (из `EventTopics`)
1234
+ * @param listener - функция-обработчик, получающая payload
454
1235
  *
455
- * @return {number} The current vertical rotation, in radians.
1236
+ * @typeParam K - ключ события из `EditorEvents`
1237
+ *
1238
+ * @remarks
1239
+ * **Важно:** для предотвращения утечек памяти необходимо отписываться от событий
1240
+ * в `dispose()` методах компонентов.
1241
+ *
1242
+ * @example
1243
+ * ```typescript
1244
+ * // Подписка на событие hover
1245
+ * this._eventBus.on(EventTopics.SelectHover, (payload) => {
1246
+ * if (payload) {
1247
+ * this._handleHover(payload.intersection);
1248
+ * } else {
1249
+ * this._clearHover();
1250
+ * }
1251
+ * });
1252
+ * ```
1253
+ *
1254
+ * @public
1255
+ * @method
456
1256
  */
457
- getPolarAngle() {
458
- return this._spherical.phi;
1257
+ on(e, t) {
1258
+ this._emitter.on(e, t);
459
1259
  }
460
1260
  /**
461
- * Get the current horizontal rotation, in radians.
1261
+ * Отписывается от события.
1262
+ *
1263
+ * @param event - название события (из `EventTopics`)
1264
+ * @param listener - функция-обработчик, которую нужно отписать
1265
+ *
1266
+ * @typeParam K - ключ события из `EditorEvents`
1267
+ *
1268
+ * @remarks
1269
+ * Для корректной отписки необходимо передать ту же самую функцию,
1270
+ * которая использовалась при подписке.
1271
+ *
1272
+ * @example
1273
+ * ```typescript
1274
+ * // Сохранение ссылки на обработчик
1275
+ * private _handleClick = (payload) => { ... };
1276
+ *
1277
+ * // Подписка
1278
+ * eventBus.on(EventTopics.SelectClick, this._handleClick);
462
1279
  *
463
- * @return {number} The current horizontal rotation, in radians.
1280
+ * // Отписка dispose)
1281
+ * eventBus.off(EventTopics.SelectClick, this._handleClick);
1282
+ * ```
1283
+ *
1284
+ * @public
1285
+ * @method
464
1286
  */
465
- getAzimuthalAngle() {
466
- return this._spherical.theta;
1287
+ off(e, t) {
1288
+ this._emitter.off(e, t);
1289
+ }
1290
+ };
1291
+ je = Qs([
1292
+ w()
1293
+ ], je);
1294
+ var k = /* @__PURE__ */ ((e) => (e.SelectHover = "select.hover", e.SelectClick = "select.click", e))(k || {}), er = Object.getOwnPropertyDescriptor, tr = (e, t, s, r) => {
1295
+ for (var i = r > 1 ? void 0 : r ? er(t, s) : t, n = e.length - 1, o; n >= 0; n--)
1296
+ (o = e[n]) && (i = o(i) || i);
1297
+ return i;
1298
+ }, q = (e, t) => (s, r) => t(s, r, e);
1299
+ let $e = class {
1300
+ constructor(e, t, s, r, i) {
1301
+ this._domApi = e, this._cameraApi = t, this._meshApi = s, this._controlsState = r, this._bus = i;
467
1302
  }
468
1303
  /**
469
- * Returns the distance from the camera to the target.
1304
+ * Raycast для получения событий наведения/клика по модели
470
1305
  *
471
- * @return {number} The distance from the camera to the target.
1306
+ * @private
1307
+ * @member
472
1308
  */
473
- getDistance() {
474
- return this.object.position.distanceTo(this.target);
475
- }
1309
+ _raycaster;
476
1310
  /**
477
- * Adds key event listeners to the given DOM element.
478
- * `window` is a recommended argument for using this method.
1311
+ * Курсор мыши
479
1312
  *
480
- * @param {HTMLElement} domElement - The DOM element
1313
+ * @private
1314
+ * @member
481
1315
  */
482
- listenToKeyEvents(e) {
483
- e.addEventListener("keydown", this._onKeyDown), this._domElementKeyEvents = e;
484
- }
1316
+ _mouse;
485
1317
  /**
486
- * Removes the key event listener previously defined with `listenToKeyEvents()`.
1318
+ * Ключ последней модели, на которую наводились,
1319
+ * необходим для отправки только уникальных событий в event bus
1320
+ *
1321
+ * @private
1322
+ * @member
487
1323
  */
488
- stopListenToKeyEvents() {
489
- this._domElementKeyEvents !== null && (this._domElementKeyEvents.removeEventListener("keydown", this._onKeyDown), this._domElementKeyEvents = null);
490
- }
1324
+ _lastHoverKey = null;
491
1325
  /**
492
- * Save the current state of the controls. This can later be recovered with `reset()`.
1326
+ * Текущий режим для raycaster
1327
+ *
1328
+ * @private
1329
+ * @member
493
1330
  */
494
- saveState() {
495
- this.target0.copy(this.target), this.position0.copy(this.object.position), this.zoom0 = this.object.zoom;
496
- }
1331
+ _currentRaycastMode = P.Mesh;
497
1332
  /**
498
- * Reset the controls to their state from either the last time the `saveState()`
499
- * was called, or the initial state.
1333
+ * Были ли инициализированы обработчики событий (hover/click)
1334
+ *
1335
+ * @private
1336
+ * @member
500
1337
  */
501
- reset() {
502
- this.target.copy(this.target0), this.object.position.copy(this.position0), this.object.zoom = this.zoom0, this.object.updateProjectionMatrix(), this.dispatchEvent(Te), this.update(), this.state = p.NONE;
503
- }
504
- update(e = null) {
505
- const s = this.object.position;
506
- v.copy(s).sub(this.target), v.applyQuaternion(this._quat), this._spherical.setFromVector3(v), this.autoRotate && this.state === p.NONE && this._rotateLeft(this._getAutoRotationAngle(e)), this.enableDamping ? (this._spherical.theta += this._sphericalDelta.theta * this.dampingFactor, this._spherical.phi += this._sphericalDelta.phi * this.dampingFactor) : (this._spherical.theta += this._sphericalDelta.theta, this._spherical.phi += this._sphericalDelta.phi);
507
- let i = this.minAzimuthAngle, r = this.maxAzimuthAngle;
508
- isFinite(i) && isFinite(r) && (i < -Math.PI ? i += P : i > Math.PI && (i -= P), r < -Math.PI ? r += P : r > Math.PI && (r -= P), i <= r ? this._spherical.theta = Math.max(i, Math.min(r, this._spherical.theta)) : this._spherical.theta = this._spherical.theta > (i + r) / 2 ? Math.max(i, this._spherical.theta) : Math.min(r, this._spherical.theta)), this._spherical.phi = Math.max(this.minPolarAngle, Math.min(this.maxPolarAngle, this._spherical.phi)), this._spherical.makeSafe(), this.enableDamping === !0 ? this.target.addScaledVector(this._panOffset, this.dampingFactor) : this.target.add(this._panOffset), this.target.sub(this.cursor), this.target.clampLength(this.minTargetRadius, this.maxTargetRadius), this.target.add(this.cursor);
509
- let o = !1;
510
- if (this.zoomToCursor && this._performCursorZoom || this.object.isOrthographicCamera)
511
- this._spherical.radius = this._clampDistance(this._spherical.radius);
512
- else {
513
- const n = this._spherical.radius;
514
- this._spherical.radius = this._clampDistance(this._spherical.radius * this._scale), o = n != this._spherical.radius;
515
- }
516
- if (v.setFromSpherical(this._spherical), v.applyQuaternion(this._quatInverse), s.copy(this.target).add(v), this.object.lookAt(this.target), this.enableDamping === !0 ? (this._sphericalDelta.theta *= 1 - this.dampingFactor, this._sphericalDelta.phi *= 1 - this.dampingFactor, this._panOffset.multiplyScalar(1 - this.dampingFactor)) : (this._sphericalDelta.set(0, 0, 0), this._panOffset.set(0, 0, 0)), this.zoomToCursor && this._performCursorZoom) {
517
- let n = null;
518
- if (this.object.isPerspectiveCamera) {
519
- const h = v.length();
520
- n = this._clampDistance(h * this._scale);
521
- const l = h - n;
522
- this.object.position.addScaledVector(this._dollyDirection, l), this.object.updateMatrixWorld(), o = !!l;
523
- } else if (this.object.isOrthographicCamera) {
524
- const h = new I(this._mouse.x, this._mouse.y, 0);
525
- h.unproject(this.object);
526
- const l = this.object.zoom;
527
- this.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom / this._scale)), this.object.updateProjectionMatrix(), o = l !== this.object.zoom;
528
- const c = new I(this._mouse.x, this._mouse.y, 0);
529
- c.unproject(this.object), this.object.position.sub(c).add(h), this.object.updateMatrixWorld(), n = v.length();
530
- } else
531
- console.warn("WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled."), this.zoomToCursor = !1;
532
- n !== null && (this.screenSpacePanning ? this.target.set(0, 0, -1).transformDirection(this.object.matrix).multiplyScalar(n).add(this.object.position) : (B.origin.copy(this.object.position), B.direction.set(0, 0, -1).transformDirection(this.object.matrix), Math.abs(this.object.up.dot(B.direction)) < wt ? this.object.lookAt(this.target) : (Le.setFromNormalAndCoplanarPoint(this.object.up, this.target), B.intersectPlane(Le, this.target))));
533
- } else if (this.object.isOrthographicCamera) {
534
- const n = this.object.zoom;
535
- this.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom / this._scale)), n !== this.object.zoom && (this.object.updateProjectionMatrix(), o = !0);
536
- }
537
- return this._scale = 1, this._performCursorZoom = !1, o || this._lastPosition.distanceToSquared(this.object.position) > K || 8 * (1 - this._lastQuaternion.dot(this.object.quaternion)) > K || this._lastTargetPosition.distanceToSquared(this.target) > K ? (this.dispatchEvent(Te), this._lastPosition.copy(this.object.position), this._lastQuaternion.copy(this.object.quaternion), this._lastTargetPosition.copy(this.target), !0) : !1;
538
- }
539
- _getAutoRotationAngle(e) {
540
- return e !== null ? P / 60 * this.autoRotateSpeed * e : P / 60 / 60 * this.autoRotateSpeed;
541
- }
542
- _getZoomScale(e) {
543
- const s = Math.abs(e * 0.01);
544
- return Math.pow(0.95, this.zoomSpeed * s);
545
- }
546
- _rotateLeft(e) {
547
- this._sphericalDelta.theta -= e;
548
- }
549
- _rotateUp(e) {
550
- this._sphericalDelta.phi -= e;
551
- }
552
- _panLeft(e, s) {
553
- v.setFromMatrixColumn(s, 0), v.multiplyScalar(-e), this._panOffset.add(v);
554
- }
555
- _panUp(e, s) {
556
- this.screenSpacePanning === !0 ? v.setFromMatrixColumn(s, 1) : (v.setFromMatrixColumn(s, 0), v.crossVectors(this.object.up, v)), v.multiplyScalar(e), this._panOffset.add(v);
557
- }
558
- // deltaX and deltaY are in pixels; right and down are positive
559
- _pan(e, s) {
560
- const i = this.domElement;
561
- if (this.object.isPerspectiveCamera) {
562
- const r = this.object.position;
563
- v.copy(r).sub(this.target);
564
- let o = v.length();
565
- o *= Math.tan(this.object.fov / 2 * Math.PI / 180), this._panLeft(2 * e * o / i.clientHeight, this.object.matrix), this._panUp(2 * s * o / i.clientHeight, this.object.matrix);
566
- } else this.object.isOrthographicCamera ? (this._panLeft(e * (this.object.right - this.object.left) / this.object.zoom / i.clientWidth, this.object.matrix), this._panUp(s * (this.object.top - this.object.bottom) / this.object.zoom / i.clientHeight, this.object.matrix)) : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."), this.enablePan = !1);
567
- }
568
- _dollyOut(e) {
569
- this.object.isPerspectiveCamera || this.object.isOrthographicCamera ? this._scale /= e : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."), this.enableZoom = !1);
570
- }
571
- _dollyIn(e) {
572
- this.object.isPerspectiveCamera || this.object.isOrthographicCamera ? this._scale *= e : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."), this.enableZoom = !1);
573
- }
574
- _updateZoomParameters(e, s) {
575
- if (!this.zoomToCursor)
576
- return;
577
- this._performCursorZoom = !0;
578
- const i = this.domElement.getBoundingClientRect(), r = e - i.left, o = s - i.top, n = i.width, h = i.height;
579
- this._mouse.x = r / n * 2 - 1, this._mouse.y = -(o / h) * 2 + 1, this._dollyDirection.set(this._mouse.x, this._mouse.y, 1).unproject(this.object).sub(this.object.position).normalize();
580
- }
581
- _clampDistance(e) {
582
- return Math.max(this.minDistance, Math.min(this.maxDistance, e));
583
- }
584
- //
585
- // event callbacks - update the object state
586
- //
587
- _handleMouseDownRotate(e) {
588
- this._rotateStart.set(e.clientX, e.clientY);
589
- }
590
- _handleMouseDownDolly(e) {
591
- this._updateZoomParameters(e.clientX, e.clientX), this._dollyStart.set(e.clientX, e.clientY);
592
- }
593
- _handleMouseDownPan(e) {
594
- this._panStart.set(e.clientX, e.clientY);
595
- }
596
- _handleMouseMoveRotate(e) {
597
- this._rotateEnd.set(e.clientX, e.clientY), this._rotateDelta.subVectors(this._rotateEnd, this._rotateStart).multiplyScalar(this.rotateSpeed);
598
- const s = this.domElement;
599
- this._rotateLeft(P * this._rotateDelta.x / s.clientHeight), this._rotateUp(P * this._rotateDelta.y / s.clientHeight), this._rotateStart.copy(this._rotateEnd), this.update();
600
- }
601
- _handleMouseMoveDolly(e) {
602
- this._dollyEnd.set(e.clientX, e.clientY), this._dollyDelta.subVectors(this._dollyEnd, this._dollyStart), this._dollyDelta.y > 0 ? this._dollyOut(this._getZoomScale(this._dollyDelta.y)) : this._dollyDelta.y < 0 && this._dollyIn(this._getZoomScale(this._dollyDelta.y)), this._dollyStart.copy(this._dollyEnd), this.update();
603
- }
604
- _handleMouseMovePan(e) {
605
- this._panEnd.set(e.clientX, e.clientY), this._panDelta.subVectors(this._panEnd, this._panStart).multiplyScalar(this.panSpeed), this._pan(this._panDelta.x, this._panDelta.y), this._panStart.copy(this._panEnd), this.update();
1338
+ _isEventListenersAdded = !1;
1339
+ init() {
1340
+ this._raycaster = new l.Raycaster(), this._mouse = new l.Vector2(), this._applyRaycastParamsByMode(), this._isEventListenersAdded || (this._initMouseListeners(), this._isEventListenersAdded = !0);
606
1341
  }
607
- _handleMouseWheel(e) {
608
- this._updateZoomParameters(e.clientX, e.clientY), e.deltaY < 0 ? this._dollyIn(this._getZoomScale(e.deltaY)) : e.deltaY > 0 && this._dollyOut(this._getZoomScale(e.deltaY)), this.update();
1342
+ setRaycastMode(e) {
1343
+ if (this._currentRaycastMode === e) return;
1344
+ const t = this._raycaster;
1345
+ t.params.Line.threshold = 0, t.params.Points.threshold = 0, this._currentRaycastMode = e, this._lastHoverKey = null, this._applyRaycastParamsByMode();
609
1346
  }
610
- _handleKeyDown(e) {
611
- let s = !1;
612
- switch (e.code) {
613
- case this.keys.UP:
614
- e.ctrlKey || e.metaKey || e.shiftKey ? this.enableRotate && this._rotateUp(P * this.keyRotateSpeed / this.domElement.clientHeight) : this.enablePan && this._pan(0, this.keyPanSpeed), s = !0;
615
- break;
616
- case this.keys.BOTTOM:
617
- e.ctrlKey || e.metaKey || e.shiftKey ? this.enableRotate && this._rotateUp(-P * this.keyRotateSpeed / this.domElement.clientHeight) : this.enablePan && this._pan(0, -this.keyPanSpeed), s = !0;
1347
+ /** Применяет параметры raycaster в зависимости от текущего режима */
1348
+ _applyRaycastParamsByMode() {
1349
+ const e = this._raycaster;
1350
+ switch (e.params.Line.threshold = 0, e.params.Points.threshold = 0, this._currentRaycastMode) {
1351
+ case P.Mesh:
1352
+ case P.Face:
1353
+ e.layers.set(z);
618
1354
  break;
619
- case this.keys.LEFT:
620
- e.ctrlKey || e.metaKey || e.shiftKey ? this.enableRotate && this._rotateLeft(P * this.keyRotateSpeed / this.domElement.clientHeight) : this.enablePan && this._pan(this.keyPanSpeed, 0), s = !0;
1355
+ case P.Edge:
1356
+ e.layers.set(Ct), e.params.Line.threshold = fs;
621
1357
  break;
622
- case this.keys.RIGHT:
623
- e.ctrlKey || e.metaKey || e.shiftKey ? this.enableRotate && this._rotateLeft(-P * this.keyRotateSpeed / this.domElement.clientHeight) : this.enablePan && this._pan(-this.keyPanSpeed, 0), s = !0;
1358
+ case P.Vertex:
1359
+ e.layers.set(It), e.params.Points.threshold = vs;
624
1360
  break;
625
1361
  }
626
- s && (e.preventDefault(), this.update());
627
- }
628
- _handleTouchStartRotate(e) {
629
- if (this._pointers.length === 1)
630
- this._rotateStart.set(e.pageX, e.pageY);
631
- else {
632
- const s = this._getSecondPointerPosition(e), i = 0.5 * (e.pageX + s.x), r = 0.5 * (e.pageY + s.y);
633
- this._rotateStart.set(i, r);
634
- }
635
- }
636
- _handleTouchStartPan(e) {
637
- if (this._pointers.length === 1)
638
- this._panStart.set(e.pageX, e.pageY);
639
- else {
640
- const s = this._getSecondPointerPosition(e), i = 0.5 * (e.pageX + s.x), r = 0.5 * (e.pageY + s.y);
641
- this._panStart.set(i, r);
642
- }
643
1362
  }
644
- _handleTouchStartDolly(e) {
645
- const s = this._getSecondPointerPosition(e), i = e.pageX - s.x, r = e.pageY - s.y, o = Math.sqrt(i * i + r * r);
646
- this._dollyStart.set(0, o);
1363
+ /** Возвращает ближайшее пересечение по текущему положению курсора */
1364
+ _getHitIntersection(e) {
1365
+ const t = this._controlsState.isOrbitInteracting() || this._controlsState.isTransformDragging(), s = this._domApi.getCanvas(), r = this._cameraApi.getCamera(), i = this._meshApi.getMeshes();
1366
+ if (t) return;
1367
+ const n = s.getBoundingClientRect();
1368
+ this._mouse.x = (e.clientX - n.left) / n.width * 2 - 1, this._mouse.y = -((e.clientY - n.top) / n.height) * 2 + 1, this._raycaster.setFromCamera(this._mouse, r);
1369
+ const o = this._raycaster.intersectObjects(i, !0)[0] ?? null;
1370
+ if (this._currentRaycastMode === P.Mesh || this._currentRaycastMode === P.Face)
1371
+ return o;
1372
+ const c = this._raycaster.layers.mask;
1373
+ this._raycaster.layers.set(z);
1374
+ const u = this._raycaster.intersectObjects(i, !0)[0] ?? null;
1375
+ return this._raycaster.layers.mask = c, this._getVisibleHit(o, u);
647
1376
  }
648
- _handleTouchStartDollyPan(e) {
649
- this.enableZoom && this._handleTouchStartDolly(e), this.enablePan && this._handleTouchStartPan(e);
1377
+ // Hover сравнивается не только по object, но и по режимному ключу попадания.
1378
+ // Это нужно для Face/Edge/Vertex режимов, где разные элементы могут принадлежать одному и тому же Object3D.
1379
+ /** Вспомогательный метод для получения модели, которую выбрали и отправки события в event bus */
1380
+ _processRaycastEvent(e, t, s) {
1381
+ const r = this._getHitIntersection(e), i = this._meshApi.getMeshes();
1382
+ if (r === void 0) return;
1383
+ const n = r?.object ?? null;
1384
+ if (s) {
1385
+ if (!r) {
1386
+ i.forEach((c) => c.userData.isHit = !1), this._lastHoverKey = null, this._bus.emit(t, null);
1387
+ return;
1388
+ }
1389
+ const o = this._makeHoverKey(r);
1390
+ o !== this._lastHoverKey && (i.forEach((c) => c.userData.isHit = !1), n && (n.userData.isHit = !0), this._lastHoverKey = o, this._bus.emit(t, { intersection: r }));
1391
+ return;
1392
+ }
1393
+ r && this._bus.emit(t, { intersection: r });
650
1394
  }
651
- _handleTouchStartDollyRotate(e) {
652
- this.enableZoom && this._handleTouchStartDolly(e), this.enableRotate && this._handleTouchStartRotate(e);
1395
+ /** Поиск видимой части меша
1396
+ * необходимо это для того, чтобы отправлять только видимые элементы модели, а не все попадания
1397
+ */
1398
+ _getVisibleHit(e, t, s = 1e-4) {
1399
+ return e ? t ? e.distance <= t.distance + s ? e : null : e : null;
653
1400
  }
654
- _handleTouchMoveRotate(e) {
655
- if (this._pointers.length == 1)
656
- this._rotateEnd.set(e.pageX, e.pageY);
657
- else {
658
- const i = this._getSecondPointerPosition(e), r = 0.5 * (e.pageX + i.x), o = 0.5 * (e.pageY + i.y);
659
- this._rotateEnd.set(r, o);
660
- }
661
- this._rotateDelta.subVectors(this._rotateEnd, this._rotateStart).multiplyScalar(this.rotateSpeed);
662
- const s = this.domElement;
663
- this._rotateLeft(P * this._rotateDelta.x / s.clientHeight), this._rotateUp(P * this._rotateDelta.y / s.clientHeight), this._rotateStart.copy(this._rotateEnd);
664
- }
665
- _handleTouchMovePan(e) {
666
- if (this._pointers.length === 1)
667
- this._panEnd.set(e.pageX, e.pageY);
668
- else {
669
- const s = this._getSecondPointerPosition(e), i = 0.5 * (e.pageX + s.x), r = 0.5 * (e.pageY + s.y);
670
- this._panEnd.set(i, r);
1401
+ /** Строит ключ hover-пересечения с учетом текущего режима выборки */
1402
+ _makeHoverKey(e) {
1403
+ if (!e) return null;
1404
+ const t = e.object.uuid;
1405
+ switch (this._currentRaycastMode) {
1406
+ case P.Face:
1407
+ return `${t}:face:${e.faceIndex ?? -1}`;
1408
+ case P.Edge:
1409
+ return `${t}:edge:${Math.floor((e.index ?? -1) / 2)}`;
1410
+ case P.Vertex:
1411
+ return `${t}:vertex:${e.index ?? -1}`;
1412
+ case P.Mesh:
1413
+ default:
1414
+ return `${t}:mesh`;
671
1415
  }
672
- this._panDelta.subVectors(this._panEnd, this._panStart).multiplyScalar(this.panSpeed), this._pan(this._panDelta.x, this._panDelta.y), this._panStart.copy(this._panEnd);
673
1416
  }
674
- _handleTouchMoveDolly(e) {
675
- const s = this._getSecondPointerPosition(e), i = e.pageX - s.x, r = e.pageY - s.y, o = Math.sqrt(i * i + r * r);
676
- this._dollyEnd.set(0, o), this._dollyDelta.set(0, Math.pow(this._dollyEnd.y / this._dollyStart.y, this.zoomSpeed)), this._dollyOut(this._dollyDelta.y), this._dollyStart.copy(this._dollyEnd);
677
- const n = (e.pageX + s.x) * 0.5, h = (e.pageY + s.y) * 0.5;
678
- this._updateZoomParameters(n, h);
1417
+ /** Обработчик события для hover */
1418
+ _handleMouseMove = (e) => {
1419
+ this._processRaycastEvent(e, k.SelectHover, !0);
1420
+ };
1421
+ /** Обработчик события на click */
1422
+ _handleMouseClick = (e) => {
1423
+ this._processRaycastEvent(e, k.SelectClick, !1);
1424
+ };
1425
+ /** Обработчик двойного клика */
1426
+ _handleDoubleClick = (e) => {
1427
+ const t = this._getHitIntersection(e);
1428
+ t !== void 0 && (t || this._bus.emit(k.SelectClick, null));
1429
+ };
1430
+ /** Обработчик ухода курсора с canvas */
1431
+ _handleMouseLeave = () => {
1432
+ this._lastHoverKey = null, this._bus.emit(k.SelectHover, null);
1433
+ };
1434
+ /** Инициализация обработчиков событий на hover/click */
1435
+ _initMouseListeners() {
1436
+ const e = this._domApi.getCanvas();
1437
+ e.addEventListener("mousemove", this._handleMouseMove, !1), e.addEventListener("click", this._handleMouseClick, !1), e.addEventListener("dblclick", this._handleDoubleClick, !1), e.addEventListener("mouseleave", this._handleMouseLeave), this._isEventListenersAdded = !0;
679
1438
  }
680
- _handleTouchMoveDollyPan(e) {
681
- this.enableZoom && this._handleTouchMoveDolly(e), this.enablePan && this._handleTouchMovePan(e);
1439
+ _removeMouseListeners() {
1440
+ const e = this._domApi.getCanvas();
1441
+ e.removeEventListener("mousemove", this._handleMouseMove), e.removeEventListener("click", this._handleMouseClick), e.removeEventListener("dblclick", this._handleDoubleClick), e.removeEventListener("mouseleave", this._handleMouseLeave);
682
1442
  }
683
- _handleTouchMoveDollyRotate(e) {
684
- this.enableZoom && this._handleTouchMoveDolly(e), this.enableRotate && this._handleTouchMoveRotate(e);
1443
+ dispose() {
1444
+ this._removeMouseListeners(), this._isEventListenersAdded = !1, this._lastHoverKey = null;
685
1445
  }
686
- // pointers
687
- _addPointer(e) {
688
- this._pointers.push(e.pointerId);
1446
+ };
1447
+ $e = tr([
1448
+ w(),
1449
+ q(0, _("IDomApi")),
1450
+ q(1, _("ICameraApi")),
1451
+ q(2, _("IMeshApi")),
1452
+ q(3, _("IControlsStateApi")),
1453
+ q(4, _("EventBus"))
1454
+ ], $e);
1455
+ var sr = Object.getOwnPropertyDescriptor, rr = (e, t, s, r) => {
1456
+ for (var i = r > 1 ? void 0 : r ? sr(t, s) : t, n = e.length - 1, o; n >= 0; n--)
1457
+ (o = e[n]) && (i = o(i) || i);
1458
+ return i;
1459
+ }, ir = (e, t) => (s, r) => t(s, r, e);
1460
+ let Re = class {
1461
+ constructor(e) {
1462
+ this._api = e;
1463
+ }
1464
+ /** Объекты редактора, участвующие в raycast и редактировании */
1465
+ _meshes = [];
1466
+ /** Сетка сцены */
1467
+ _grid = null;
1468
+ /** Оси сцены */
1469
+ _axes = null;
1470
+ /** Базовый свет сцены */
1471
+ _light = null;
1472
+ init() {
1473
+ this._grid = new l.GridHelper(10, 10), this._grid.position.y = -1e-3, this._api.addToScene(this._grid), this._axes = new is(6), this._api.addToScene(this._axes), this._light = new l.HemisphereLight(16777215, 4473924, 0.6), this._api.addToScene(this._light);
689
1474
  }
690
- _removePointer(e) {
691
- delete this._pointerPositions[e.pointerId];
692
- for (let s = 0; s < this._pointers.length; s++)
693
- if (this._pointers[s] == e.pointerId) {
694
- this._pointers.splice(s, 1);
695
- return;
696
- }
1475
+ getMeshes() {
1476
+ return this._meshes;
697
1477
  }
698
- _isTrackingPointer(e) {
699
- for (let s = 0; s < this._pointers.length; s++)
700
- if (this._pointers[s] == e.pointerId) return !0;
701
- return !1;
1478
+ addMesh(e) {
1479
+ this._meshes.includes(e) || (this._meshes.push(e), this._api.addToScene(e));
702
1480
  }
703
- _trackPointer(e) {
704
- let s = this._pointerPositions[e.pointerId];
705
- s === void 0 && (s = new L(), this._pointerPositions[e.pointerId] = s), s.set(e.pageX, e.pageY);
1481
+ removeMesh(e) {
1482
+ const t = this._meshes.indexOf(e);
1483
+ t >= 0 && this._meshes.splice(t, 1), this._api.removeFromScene(e);
706
1484
  }
707
- _getSecondPointerPosition(e) {
708
- const s = e.pointerId === this._pointers[0] ? this._pointers[1] : this._pointers[0];
709
- return this._pointerPositions[s];
1485
+ addMeshes(e) {
1486
+ for (const t of e)
1487
+ this.addMesh(t);
710
1488
  }
711
- //
712
- _customWheelEvent(e) {
713
- const s = e.deltaMode, i = {
714
- clientX: e.clientX,
715
- clientY: e.clientY,
716
- deltaY: e.deltaY
717
- };
718
- switch (s) {
719
- case 1:
720
- i.deltaY *= 16;
721
- break;
722
- case 2:
723
- i.deltaY *= 100;
724
- break;
725
- }
726
- return e.ctrlKey && !this._controlActive && (i.deltaY *= 10), i;
1489
+ removeMeshes(e) {
1490
+ for (const t of e)
1491
+ this.removeMesh(t);
727
1492
  }
728
- }
729
- function Et(t) {
730
- this.enabled !== !1 && (this._pointers.length === 0 && (this.domElement.setPointerCapture(t.pointerId), this.domElement.addEventListener("pointermove", this._onPointerMove), this.domElement.addEventListener("pointerup", this._onPointerUp)), !this._isTrackingPointer(t) && (this._addPointer(t), t.pointerType === "touch" ? this._onTouchStart(t) : this._onMouseDown(t)));
731
- }
732
- function xt(t) {
733
- this.enabled !== !1 && (t.pointerType === "touch" ? this._onTouchMove(t) : this._onMouseMove(t));
734
- }
735
- function Pt(t) {
736
- switch (this._removePointer(t), this._pointers.length) {
737
- case 0:
738
- this.domElement.releasePointerCapture(t.pointerId), this.domElement.removeEventListener("pointermove", this._onPointerMove), this.domElement.removeEventListener("pointerup", this._onPointerUp), this.dispatchEvent(Be), this.state = p.NONE;
739
- break;
740
- case 1:
741
- const e = this._pointers[0], s = this._pointerPositions[e];
742
- this._onTouchStart({ pointerId: e, pageX: s.x, pageY: s.y });
743
- break;
1493
+ /** Освобождает ресурсы модуля */
1494
+ dispose() {
1495
+ for (const e of this._meshes)
1496
+ this._api.removeFromScene(e);
1497
+ this._meshes.length = 0, this._grid && (this._api.removeFromScene(this._grid), this._grid.geometry.dispose(), this._grid.material.dispose(), this._grid = null), this._axes && (this._api.removeFromScene(this._axes), this._axes = null), this._light && (this._api.removeFromScene(this._light), this._light = null);
744
1498
  }
745
- }
746
- function Ot(t) {
747
- let e;
748
- switch (t.button) {
749
- case 0:
750
- e = this.mouseButtons.LEFT;
751
- break;
752
- case 1:
753
- e = this.mouseButtons.MIDDLE;
754
- break;
755
- case 2:
756
- e = this.mouseButtons.RIGHT;
757
- break;
758
- default:
759
- e = -1;
760
- }
761
- switch (e) {
762
- case Y.DOLLY:
763
- if (this.enableZoom === !1) return;
764
- this._handleMouseDownDolly(t), this.state = p.DOLLY;
765
- break;
766
- case Y.ROTATE:
767
- if (t.ctrlKey || t.metaKey || t.shiftKey) {
768
- if (this.enablePan === !1) return;
769
- this._handleMouseDownPan(t), this.state = p.PAN;
770
- } else {
771
- if (this.enableRotate === !1) return;
772
- this._handleMouseDownRotate(t), this.state = p.ROTATE;
773
- }
774
- break;
775
- case Y.PAN:
776
- if (t.ctrlKey || t.metaKey || t.shiftKey) {
777
- if (this.enableRotate === !1) return;
778
- this._handleMouseDownRotate(t), this.state = p.ROTATE;
779
- } else {
780
- if (this.enablePan === !1) return;
781
- this._handleMouseDownPan(t), this.state = p.PAN;
782
- }
783
- break;
784
- default:
785
- this.state = p.NONE;
1499
+ };
1500
+ Re = rr([
1501
+ w(),
1502
+ ir(0, _("ISceneApi"))
1503
+ ], Re);
1504
+ var nr = Object.getOwnPropertyDescriptor, or = (e, t, s, r) => {
1505
+ for (var i = r > 1 ? void 0 : r ? nr(t, s) : t, n = e.length - 1, o; n >= 0; n--)
1506
+ (o = e[n]) && (i = o(i) || i);
1507
+ return i;
1508
+ }, ar = (e, t) => (s, r) => t(s, r, e);
1509
+ let Fe = class {
1510
+ constructor(e) {
1511
+ this._api = e;
786
1512
  }
787
- this.state !== p.NONE && this.dispatchEvent(be);
788
- }
789
- function Tt(t) {
790
- switch (this.state) {
791
- case p.ROTATE:
792
- if (this.enableRotate === !1) return;
793
- this._handleMouseMoveRotate(t);
794
- break;
795
- case p.DOLLY:
796
- if (this.enableZoom === !1) return;
797
- this._handleMouseMoveDolly(t);
798
- break;
799
- case p.PAN:
800
- if (this.enablePan === !1) return;
801
- this._handleMouseMovePan(t);
802
- break;
1513
+ /** Объекты вьювера */
1514
+ _meshes = [];
1515
+ /** Базовый свет сцены */
1516
+ _light = null;
1517
+ init() {
1518
+ this._light = new l.HemisphereLight(16777215, 4473924, 0.6), this._api.addToScene(this._light);
803
1519
  }
804
- }
805
- function Lt(t) {
806
- this.enabled === !1 || this.enableZoom === !1 || this.state !== p.NONE || (t.preventDefault(), this.dispatchEvent(be), this._handleMouseWheel(this._customWheelEvent(t)), this.dispatchEvent(Be));
807
- }
808
- function Dt(t) {
809
- this.enabled !== !1 && this._handleKeyDown(t);
810
- }
811
- function Ct(t) {
812
- switch (this._trackPointer(t), this._pointers.length) {
813
- case 1:
814
- switch (this.touches.ONE) {
815
- case z.ROTATE:
816
- if (this.enableRotate === !1) return;
817
- this._handleTouchStartRotate(t), this.state = p.TOUCH_ROTATE;
818
- break;
819
- case z.PAN:
820
- if (this.enablePan === !1) return;
821
- this._handleTouchStartPan(t), this.state = p.TOUCH_PAN;
822
- break;
823
- default:
824
- this.state = p.NONE;
825
- }
826
- break;
827
- case 2:
828
- switch (this.touches.TWO) {
829
- case z.DOLLY_PAN:
830
- if (this.enableZoom === !1 && this.enablePan === !1) return;
831
- this._handleTouchStartDollyPan(t), this.state = p.TOUCH_DOLLY_PAN;
832
- break;
833
- case z.DOLLY_ROTATE:
834
- if (this.enableZoom === !1 && this.enableRotate === !1) return;
835
- this._handleTouchStartDollyRotate(t), this.state = p.TOUCH_DOLLY_ROTATE;
836
- break;
837
- default:
838
- this.state = p.NONE;
839
- }
840
- break;
841
- default:
842
- this.state = p.NONE;
1520
+ getMeshes() {
1521
+ return this._meshes;
843
1522
  }
844
- this.state !== p.NONE && this.dispatchEvent(be);
845
- }
846
- function At(t) {
847
- switch (this._trackPointer(t), this.state) {
848
- case p.TOUCH_ROTATE:
849
- if (this.enableRotate === !1) return;
850
- this._handleTouchMoveRotate(t), this.update();
851
- break;
852
- case p.TOUCH_PAN:
853
- if (this.enablePan === !1) return;
854
- this._handleTouchMovePan(t), this.update();
855
- break;
856
- case p.TOUCH_DOLLY_PAN:
857
- if (this.enableZoom === !1 && this.enablePan === !1) return;
858
- this._handleTouchMoveDollyPan(t), this.update();
859
- break;
860
- case p.TOUCH_DOLLY_ROTATE:
861
- if (this.enableZoom === !1 && this.enableRotate === !1) return;
862
- this._handleTouchMoveDollyRotate(t), this.update();
863
- break;
864
- default:
865
- this.state = p.NONE;
1523
+ addMesh(e) {
1524
+ this._meshes.includes(e) || (this._meshes.push(e), this._api.addToScene(e));
866
1525
  }
867
- }
868
- function It(t) {
869
- this.enabled !== !1 && t.preventDefault();
870
- }
871
- function jt(t) {
872
- t.key === "Control" && (this._controlActive = !0, this.domElement.getRootNode().addEventListener("keyup", this._interceptControlUp, { passive: !0, capture: !0 }));
873
- }
874
- function Rt(t) {
875
- t.key === "Control" && (this._controlActive = !1, this.domElement.getRootNode().removeEventListener("keyup", this._interceptControlUp, { passive: !0, capture: !0 }));
876
- }
877
- class Ls extends Ne {
878
- /** Orbit-контроллер для управления камерой */
879
- _orbit;
880
- constructor(e) {
881
- super(e), this.camera.position.set(1, 1, 7), this.camera.lookAt(0, 0, 0), this._orbit = new St(this.camera, this.canvas), this._orbit.target.set(0, 0, 0), this._orbit.minPolarAngle = Math.PI / 2, this._orbit.maxPolarAngle = Math.PI / 2, this._orbit.enableRotate = !0, this._orbit.enableZoom = !1, this._orbit.enablePan = !1;
1526
+ removeMesh(e) {
1527
+ const t = this._meshes.indexOf(e);
1528
+ t >= 0 && this._meshes.splice(t, 1), this._api.removeFromScene(e);
882
1529
  }
883
- /**
884
- * Обновление состояния рендерера.
885
- */
886
- update() {
887
- this._orbit?.update();
1530
+ addMeshes(e) {
1531
+ for (const t of e)
1532
+ this.addMesh(t);
888
1533
  }
889
- }
890
- class Ds {
891
- /** Позиции вершин */
892
- _positions = [];
893
- /** Нормали вершин */
894
- _normals = [];
895
- /** UV-координаты (опционально) */
896
- _uvs = [];
897
- // Временные поля для парсинга файла
898
- _tmpPositions = [];
899
- _tmpNormals = [];
900
- _tmpUVs = [];
901
- /**
902
- * Загружает OBJ-модель в Figure
903
- * @param objContent - Строка содержимого .obj файла
904
- */
905
- load(e) {
906
- const s = e.split(`
907
- `);
908
- for (const r of s) {
909
- if (!r.trim() || r.startsWith("#")) continue;
910
- const o = r.trim().split(/\s+/);
911
- switch (o[0]) {
912
- case "v":
913
- this._tmpPositions.push(o.slice(1).map(Number));
914
- break;
915
- case "vn":
916
- this._tmpNormals.push(o.slice(1).map(Number));
917
- break;
918
- case "vt":
919
- this._tmpUVs.push(o.slice(1).map(Number));
920
- break;
921
- case "f":
922
- this.processFaceLine(o);
923
- break;
924
- }
925
- }
926
- const i = {
927
- type: D.Custom,
928
- position: this._positions,
929
- ...this._normals.length > 0 && { normal: this._normals },
930
- ...this._uvs.length > 0 && { uv: this._uvs }
931
- };
932
- return new et(i);
1534
+ removeMeshes(e) {
1535
+ for (const t of e)
1536
+ this.removeMesh(t);
933
1537
  }
934
- /**
935
- * Обрабатывает строку face (f) и разворачивает индексы в массивы для рендеринга
936
- */
937
- processFaceLine(e) {
938
- for (let s = 1; s < e.length; s++) {
939
- const i = e[s];
940
- if (!i) continue;
941
- const [r, o, n] = i.split("/"), h = r ? parseInt(r, 10) : void 0, l = o ? parseInt(o, 10) : void 0, c = n ? parseInt(n, 10) : void 0;
942
- if (h !== void 0) {
943
- const d = this._tmpPositions[h - 1];
944
- d && this._positions.push(...d);
945
- }
946
- if (l !== void 0) {
947
- const d = this._tmpUVs[l - 1];
948
- d && this._uvs.push(...d);
949
- }
950
- if (c !== void 0) {
951
- const d = this._tmpNormals[c - 1];
952
- d && this._normals.push(...d);
953
- }
954
- }
1538
+ /** Освобождает ресурсы модуля */
1539
+ dispose() {
1540
+ for (const e of this._meshes)
1541
+ this._api.removeFromScene(e);
1542
+ this._meshes.length = 0, this._light && (this._api.removeFromScene(this._light), this._light = null);
955
1543
  }
956
- }
957
- var Vt = Object.getOwnPropertyDescriptor, kt = (t, e, s, i) => {
958
- for (var r = i > 1 ? void 0 : i ? Vt(e, s) : e, o = t.length - 1, n; o >= 0; o--)
959
- (n = t[o]) && (r = n(r) || r);
960
- return r;
961
- }, De = (t, e) => (s, i) => e(s, i, t);
962
- let te = class {
963
- constructor(t, e) {
964
- this._store = e, this._handlers = new Map(t.map((s) => [s.mode, s]));
1544
+ };
1545
+ Fe = or([
1546
+ w(),
1547
+ ar(0, _("ISceneApi"))
1548
+ ], Fe);
1549
+ var E = /* @__PURE__ */ ((e) => (e[e.Display = 0] = "Display", e[e.Scene = 1] = "Scene", e[e.Select = 2] = "Select", e[e.Tool = 3] = "Tool", e))(E || {}), lr = Object.getOwnPropertyDescriptor, cr = (e, t, s, r) => {
1550
+ for (var i = r > 1 ? void 0 : r ? lr(t, s) : t, n = e.length - 1, o; n >= 0; n--)
1551
+ (o = e[n]) && (i = o(i) || i);
1552
+ return i;
1553
+ }, _t = (e, t) => (s, r) => t(s, r, e);
1554
+ let He = class {
1555
+ constructor(e, t) {
1556
+ this._store = t, this._handlers = new Map(e.map((s) => [s.mode, s]));
965
1557
  }
966
1558
  /** Текущий режим отображения */
967
- _currentMode = $.Plane;
1559
+ _currentMode = K.Plane;
968
1560
  /** Хендлеры, которые управляют отображением */
969
1561
  _handlers;
1562
+ /** Тип фичи, за которую отвечает менеджер. */
1563
+ type = E.Display;
970
1564
  /** Установка режима отображения */
971
- manage(t) {
972
- t !== this._currentMode && (this._handlers.get(this._currentMode)?.rollback(), t !== $.Plane && this._handlers.get(t)?.handle(), this._currentMode = t, this._store.setDisplayMode(this._currentMode));
1565
+ manage(e) {
1566
+ e !== this._currentMode && (this._handlers.get(this._currentMode)?.rollback(), e !== K.Plane && this._handlers.get(e)?.handle(), this._currentMode = e, this._store.setDisplayMode(this._currentMode));
1567
+ }
1568
+ /** Освобождает ресурсы менеджера. */
1569
+ dispose() {
1570
+ this._handlers && this._handlers.clear(), this._currentMode = K.Plane, this._store.setDisplayMode(this._currentMode);
1571
+ }
1572
+ };
1573
+ He = cr([
1574
+ w(),
1575
+ _t(0, B("IDisplayHandler")),
1576
+ _t(1, _("EditorStore"))
1577
+ ], He);
1578
+ var hr = Object.getOwnPropertyDescriptor, dr = (e, t, s, r) => {
1579
+ for (var i = r > 1 ? void 0 : r ? hr(t, s) : t, n = e.length - 1, o; n >= 0; n--)
1580
+ (o = e[n]) && (i = o(i) || i);
1581
+ return i;
1582
+ }, ur = (e, t) => (s, r) => t(s, r, e);
1583
+ let pe = class {
1584
+ /** Текущий режим редактирования сцены */
1585
+ _currentMode = T.AddFigure;
1586
+ /** Хендлеры, которые управляют отображением */
1587
+ _handlers;
1588
+ /** Тип фичи, за которую отвечает менеджер. */
1589
+ type = E.Scene;
1590
+ constructor(e) {
1591
+ this._handlers = new Map(e.map((t) => [t.mode, t]));
1592
+ }
1593
+ /** Установка режима редактирования сцены */
1594
+ manage(e, t) {
1595
+ this._handlers.get(e)?.handle(t), this._currentMode = e;
973
1596
  }
974
1597
  /** Освобождает ресурсы менеджера. */
975
1598
  dispose() {
976
- this._handlers && this._handlers.clear(), this._currentMode = $.Plane, this._store.setDisplayMode(this._currentMode);
1599
+ this._handlers && this._handlers.clear(), this._currentMode = T.AddFigure;
977
1600
  }
978
1601
  };
979
- te = kt([
980
- M(),
981
- De(0, G("IDisplayHandler")),
982
- De(1, _("IEditorStore"))
983
- ], te);
984
- var C = /* @__PURE__ */ ((t) => (t.Hover = "hover", t.Click = "click", t))(C || {}), Ht = Object.getOwnPropertyDescriptor, Ft = (t, e, s, i) => {
985
- for (var r = i > 1 ? void 0 : i ? Ht(e, s) : e, o = t.length - 1, n; o >= 0; o--)
986
- (n = t[o]) && (r = n(r) || r);
987
- return r;
988
- }, q = (t, e) => (s, i) => e(s, i, t);
989
- let se = class {
990
- constructor(t, e, s) {
991
- this._eventBus = t, this._store = s, this._handlers = new Map(e.map((i) => [i.mode, i])), this._eventBus.on(H.SelectHover, this._onHover), this._eventBus.on(H.SelectClick, this._onClick);
1602
+ pe = dr([
1603
+ w(),
1604
+ ur(0, B("ISceneHandler"))
1605
+ ], pe);
1606
+ var F = /* @__PURE__ */ ((e) => (e.Hover = "hover", e.Click = "click", e))(F || {}), _r = Object.getOwnPropertyDescriptor, pr = (e, t, s, r) => {
1607
+ for (var i = r > 1 ? void 0 : r ? _r(t, s) : t, n = e.length - 1, o; n >= 0; n--)
1608
+ (o = e[n]) && (i = o(i) || i);
1609
+ return i;
1610
+ }, Ie = (e, t) => (s, r) => t(s, r, e);
1611
+ let Be = class {
1612
+ constructor(e, t, s) {
1613
+ this._eventBus = e, this._store = s, this._handlers = new Map(t.map((r) => [r.mode, r])), this._eventBus.on(k.SelectHover, this._onHover), this._eventBus.on(k.SelectClick, this._onClick);
992
1614
  }
993
1615
  /** Текущий режим выборки */
994
- _currentMode = y.Mesh;
1616
+ _currentMode = P.Mesh;
995
1617
  /** Хендлеры, которые управляют выборкой */
996
1618
  _handlers;
1619
+ /** Тип фичи, за которую отвечает менеджер. */
1620
+ type = E.Select;
997
1621
  /** Переключает режим выбора */
998
- manage(t) {
999
- t !== this._currentMode && (this._handlers.get(this._currentMode)?.rollback(), this._currentMode = t, this._store.setSelectMode(this._currentMode));
1622
+ manage(e) {
1623
+ e !== this._currentMode && (this._handlers.get(this._currentMode)?.rollback(), this._currentMode = e, this._store.setSelectMode(this._currentMode));
1000
1624
  }
1001
1625
  /** Обработчик события наведения на модель */
1002
- _onHover = (t) => {
1003
- this._handlers.get(this._currentMode)?.handle(t, C.Hover);
1626
+ _onHover = (e) => {
1627
+ this._handlers.get(this._currentMode)?.handle(e, F.Hover);
1004
1628
  };
1005
1629
  /** Обработчик события клика на модель */
1006
- _onClick = (t) => {
1007
- this._handlers.get(this._currentMode)?.handle(t, C.Click);
1630
+ _onClick = (e) => {
1631
+ this._handlers.get(this._currentMode)?.handle(e, F.Click);
1008
1632
  };
1009
1633
  /** Освобождает ресурсы менеджера. */
1010
1634
  dispose() {
1011
- this._handlers && this._handlers.clear(), this._eventBus.off(H.SelectHover, this._onHover), this._currentMode = y.Mesh, this._store.setSelectMode(this._currentMode);
1635
+ this._handlers && this._handlers.clear(), this._eventBus.off(k.SelectHover, this._onHover), this._currentMode = P.Mesh, this._store.setSelectMode(this._currentMode);
1012
1636
  }
1013
1637
  };
1014
- se = Ft([
1015
- M(),
1016
- q(0, _("EventBus")),
1017
- q(1, G("ISelectHandler")),
1018
- q(2, _("IEditorStore"))
1019
- ], se);
1020
- class Wt {
1021
- /** Доступен ли инструмент при текущем режиме выборки */
1022
- isToolEnabled(e, s) {
1023
- return Pe[s].includes(e);
1024
- }
1025
- /** Получение доступных инструментов для режима выборки*/
1026
- getEnabledTools(e) {
1027
- return Pe[e];
1028
- }
1029
- }
1030
- var zt = Object.getOwnPropertyDescriptor, Nt = (t, e, s, i) => {
1031
- for (var r = i > 1 ? void 0 : i ? zt(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1032
- (n = t[o]) && (r = n(r) || r);
1033
- return r;
1034
- }, Ce = (t, e) => (s, i) => e(s, i, t);
1035
- let ie = class {
1036
- constructor(t, e) {
1037
- this._store = e, this._handlers = new Map(t.map((s) => [s.mode, s])), this._unsubSelected = this._store.onSelectedObjectChange(() => {
1638
+ Be = pr([
1639
+ w(),
1640
+ Ie(0, _("EventBus")),
1641
+ Ie(1, B("ISelectHandler")),
1642
+ Ie(2, _("EditorStore"))
1643
+ ], Be);
1644
+ const mr = (e) => (t, s, r) => {
1645
+ const i = r.value;
1646
+ if (!i)
1647
+ throw new Error("usePolicy can only be applied to method");
1648
+ return r.value = function(...n) {
1649
+ return e(this).check(...n), i.apply(this, n);
1650
+ }, r;
1651
+ }, $t = (e) => (t, s, r) => {
1652
+ const i = r.value;
1653
+ if (!i)
1654
+ throw new Error("useValidator can only be applied to method");
1655
+ return r.value = function(...n) {
1656
+ return e(this).validate(...n), i.apply(this, n);
1657
+ }, r;
1658
+ };
1659
+ var gr = Object.defineProperty, fr = Object.getOwnPropertyDescriptor, Rt = (e, t, s, r) => {
1660
+ for (var i = r > 1 ? void 0 : r ? fr(t, s) : t, n = e.length - 1, o; n >= 0; n--)
1661
+ (o = e[n]) && (i = (r ? o(t, s, i) : o(i)) || i);
1662
+ return r && i && gr(t, s, i), i;
1663
+ }, Pe = (e, t) => (s, r) => t(s, r, e);
1664
+ let me = class {
1665
+ constructor(e, t, s) {
1666
+ this._store = t, this._policy = s, this._handlers = new Map(e.map((r) => [r.mode, r])), this._unsubSelected = this._store.onSelectedObjectChange(() => {
1038
1667
  this._handlers.get(this._currentTool)?.handle();
1039
- }), this._policy = new Wt();
1668
+ });
1040
1669
  }
1041
1670
  /** Текущий выбранный инструмент */
1042
- _currentTool = F.Translate;
1671
+ _currentTool = U.Translate;
1043
1672
  /** Хендлеры, которые управляют инструментами */
1044
1673
  _handlers;
1045
1674
  /** Событие обновления выбора объекта */
1046
1675
  _unsubSelected;
1047
- /** Политика доступности инструментов */
1048
- _policy;
1049
- manage(t) {
1050
- if (this._currentTool === t) return;
1051
- const e = this._store.getSelectMode();
1052
- this._policy.isToolEnabled(t, e) && (this._handlers.get(this._currentTool)?.rollback(), this._currentTool = t, this._store.setToolType(this._currentTool), this._handlers.get(this._currentTool)?.handle());
1053
- }
1054
- /** Освобождает ресурсы менеджера. */
1055
- dispose() {
1056
- this._unsubSelected?.(), this._handlers && this._handlers.clear(), this._currentTool = F.Translate, this._store.setToolType(this._currentTool);
1057
- }
1058
- };
1059
- ie = Nt([
1060
- M(),
1061
- Ce(0, G("IToolHandler")),
1062
- Ce(1, _("IEditorStore"))
1063
- ], ie);
1064
- var Yt = Object.getOwnPropertyDescriptor, $t = (t, e, s, i) => {
1065
- for (var r = i > 1 ? void 0 : i ? Yt(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1066
- (n = t[o]) && (r = n(r) || r);
1067
- return r;
1068
- }, Ut = (t, e) => (s, i) => e(s, i, t);
1069
- let re = class {
1070
- /** Текущий режим редактирования сцены */
1071
- _currentMode = U.AddFigure;
1072
- /** Хендлеры, которые управляют отображением */
1073
- _handlers;
1074
- constructor(t) {
1075
- this._handlers = new Map(t.map((e) => [e.mode, e]));
1076
- }
1077
- /** Установка режима редактирования сцены */
1078
- manage(t, e) {
1079
- t === U.AddFigure ? this._handlers.get(t)?.handle(e) : this._handlers.get(t)?.handle(), this._currentMode = t;
1676
+ /** Тип фичи, за которую отвечает менеджер. */
1677
+ type = E.Tool;
1678
+ manage(e) {
1679
+ this._currentTool !== e && (this._handlers.get(this._currentTool)?.rollback(), this._currentTool = e, this._store.setToolType(this._currentTool), this._handlers.get(this._currentTool)?.handle());
1080
1680
  }
1081
1681
  /** Освобождает ресурсы менеджера. */
1082
1682
  dispose() {
1083
- this._handlers && this._handlers.clear(), this._currentMode = U.AddFigure;
1683
+ this._unsubSelected?.(), this._handlers && this._handlers.clear(), this._currentTool = U.Translate, this._store.setToolType(this._currentTool);
1084
1684
  }
1085
1685
  };
1086
- re = $t([
1087
- M(),
1088
- Ut(0, G("ISceneHandler"))
1089
- ], re);
1090
- var Bt = Object.getOwnPropertyDescriptor, Gt = (t, e, s, i) => {
1091
- for (var r = i > 1 ? void 0 : i ? Bt(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1092
- (n = t[o]) && (r = n(r) || r);
1093
- return r;
1094
- }, Zt = (t, e) => (s, i) => e(s, i, t);
1095
- let oe = class {
1096
- constructor(t) {
1097
- this._api = t;
1686
+ Rt([
1687
+ mr((e) => e._policy)
1688
+ ], me.prototype, "manage", 1);
1689
+ me = Rt([
1690
+ w(),
1691
+ Pe(0, B("IToolHandler")),
1692
+ Pe(1, _("EditorStore")),
1693
+ Pe(2, _("ToolPolicy"))
1694
+ ], me);
1695
+ var vr = Object.getOwnPropertyDescriptor, yr = (e, t, s, r) => {
1696
+ for (var i = r > 1 ? void 0 : r ? vr(t, s) : t, n = e.length - 1, o; n >= 0; n--)
1697
+ (o = e[n]) && (i = o(i) || i);
1698
+ return i;
1699
+ }, br = (e, t) => (s, r) => t(s, r, e);
1700
+ let ke = class {
1701
+ constructor(e) {
1702
+ this._api = e;
1098
1703
  }
1099
1704
  /** Режим отображения. */
1100
- mode = $.Wireframe;
1705
+ mode = K.Wireframe;
1101
1706
  /** Сохраняем предыдущие значения wireframe для отката. */
1102
1707
  _prevWireframe = /* @__PURE__ */ new Map();
1103
1708
  /** Сохраняем исходные цвета материалов для отката */
1104
1709
  _prevColorMesh = /* @__PURE__ */ new Map();
1105
1710
  _prevColorLines = /* @__PURE__ */ new Map();
1106
1711
  /** Цвет ребер для wireframe-режима. */
1107
- _wireColor = new a.Color(65535);
1712
+ _wireColor = new l.Color(65535);
1108
1713
  /** Применяет wireframe-режим к сцене. */
1109
1714
  handle() {
1110
- const t = this._api.getMeshes();
1111
- for (const e of t) {
1112
- const s = Array.isArray(e.material) ? e.material : [e.material];
1113
- for (const i of s) this._enableWireframeOnMaterial(i);
1114
- e.traverse((i) => {
1115
- if (i.isLineSegments) {
1116
- const r = i;
1117
- if (!this._prevColorLines.has(r.material)) {
1118
- const n = r.material;
1119
- this._prevColorLines.set(n, n.color.clone());
1715
+ const e = this._api.getMeshes();
1716
+ for (const t of e) {
1717
+ const s = Array.isArray(t.material) ? t.material : [t.material];
1718
+ for (const r of s) this._enableWireframeOnMaterial(r);
1719
+ t.traverse((r) => {
1720
+ if (r.isLineSegments) {
1721
+ const i = r;
1722
+ if (!this._prevColorLines.has(i.material)) {
1723
+ const o = i.material;
1724
+ this._prevColorLines.set(o, o.color.clone());
1120
1725
  }
1121
- const o = r.material;
1122
- o.color.copy(this._wireColor), o.needsUpdate = !0;
1726
+ const n = i.material;
1727
+ n.color.copy(this._wireColor), n.needsUpdate = !0;
1123
1728
  }
1124
1729
  });
1125
1730
  }
1126
1731
  }
1127
1732
  /** Отключает wireframe-режим и возвращает оригинальные меши. */
1128
1733
  rollback() {
1129
- for (const [t, e] of this._prevWireframe)
1130
- "wireframe" in t && (t.wireframe = e), t.needsUpdate = !0;
1734
+ for (const [e, t] of this._prevWireframe)
1735
+ "wireframe" in e && (e.wireframe = t), e.needsUpdate = !0;
1131
1736
  this._prevWireframe.clear();
1132
- for (const [t, e] of this._prevColorMesh) {
1133
- const s = t;
1134
- s.color?.isColor && s.color.copy(e);
1737
+ for (const [e, t] of this._prevColorMesh) {
1738
+ const s = e;
1739
+ s.color?.isColor && s.color.copy(t);
1135
1740
  }
1136
1741
  this._prevColorMesh.clear();
1137
- for (const [t, e] of this._prevColorLines)
1138
- t.color.copy(e);
1742
+ for (const [e, t] of this._prevColorLines)
1743
+ e.color.copy(t);
1139
1744
  this._prevColorLines.clear();
1140
1745
  }
1141
1746
  /** Освобождает ресурсы хендлера, удаляет слушатели и очищает внутренние данные. */
@@ -1143,107 +1748,161 @@ let oe = class {
1143
1748
  this.rollback();
1144
1749
  }
1145
1750
  /** Изменить цвет, который будет применяться в режиме wireframe. */
1146
- _enableWireframeOnMaterial(t) {
1147
- const e = t;
1148
- "wireframe" in e && !this._prevWireframe.has(t) && (this._prevWireframe.set(t, !!e.wireframe), e.wireframe = !0, t.needsUpdate = !0), e.color?.isColor && (this._prevColorMesh.has(t) || this._prevColorMesh.set(t, e.color.clone()), e.color.copy(this._wireColor));
1751
+ _enableWireframeOnMaterial(e) {
1752
+ const t = e;
1753
+ "wireframe" in t && !this._prevWireframe.has(e) && (this._prevWireframe.set(e, !!t.wireframe), t.wireframe = !0, e.needsUpdate = !0), t.color?.isColor && (this._prevColorMesh.has(e) || this._prevColorMesh.set(e, t.color.clone()), t.color.copy(this._wireColor));
1149
1754
  }
1150
1755
  };
1151
- oe = Gt([
1152
- M(),
1153
- Zt(0, _("RendererApi"))
1154
- ], oe);
1155
- var Xt = Object.getOwnPropertyDescriptor, Kt = (t, e, s, i) => {
1156
- for (var r = i > 1 ? void 0 : i ? Xt(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1157
- (n = t[o]) && (r = n(r) || r);
1158
- return r;
1159
- }, Ae = (t, e) => (s, i) => e(s, i, t);
1160
- let ne = class {
1161
- constructor(t, e) {
1162
- this._api = t, this._store = e;
1756
+ ke = yr([
1757
+ w(),
1758
+ br(0, _("IMeshApi"))
1759
+ ], ke);
1760
+ var Mr = Object.getOwnPropertyDescriptor, xr = (e, t, s, r) => {
1761
+ for (var i = r > 1 ? void 0 : r ? Mr(t, s) : t, n = e.length - 1, o; n >= 0; n--)
1762
+ (o = e[n]) && (i = o(i) || i);
1763
+ return i;
1764
+ }, re = (e, t) => (s, r) => t(s, r, e);
1765
+ let ze = class {
1766
+ constructor(e, t, s, r) {
1767
+ this._sceneApi = e, this._cameraApi = t, this._raycastApi = s, this._store = r, this._cameraApi.enableCameraLayer($), this._hoverLine = Y(this._makeOverlayLine(this._hoverColor)), this._selectLine = Y(this._makeOverlayLine(this._selectColor)), this._sceneApi.addObject(this._hoverLine, $), this._sceneApi.addObject(this._selectLine, $);
1163
1768
  }
1164
1769
  /** Режим, которым управляет хендлер, нужен только менеджеру */
1165
- mode = y.Mesh;
1166
- /** Фигура, на которую навелись в данный момент */
1167
- _hoveredMesh = null;
1168
- /** Фигура, которую выбрали в данный момент */
1169
- _selectedMesh = null;
1770
+ mode = P.Edge;
1771
+ /** Текущее наведённое ребро. */
1772
+ _hoverLine;
1773
+ /** Текущее выбранное ребро. */
1774
+ _selectLine;
1775
+ /** Текущее наведённое ребро из массива `LineSegments` модели. */
1776
+ _hovered = null;
1777
+ /** Текущее выбранное ребро из массива `LineSegments` модели. */
1778
+ _selected = null;
1170
1779
  // Цвета, необходимые для переключения
1171
- /** Цвет ребер для фигуры, на которую навелись */
1172
- _hoverColor = Z;
1173
- /** Цвет ребер для выделенной фигуры */
1174
- _selectColor = X;
1175
- /** Исходные цвета материалов линий для отката */
1176
- _origLineColors = /* @__PURE__ */ new WeakMap();
1177
- handle(t, e) {
1178
- if (this._api.setRaycastMode(this.mode), e === C.Hover) {
1179
- if (!t) {
1180
- this._hoveredMesh && this._hoveredMesh !== this._selectedMesh && this._restoreEdgesColor(this._hoveredMesh), this._hoveredMesh = null;
1780
+ /** Цвет ребра, на которое навелись */
1781
+ _hoverColor = Me;
1782
+ /** Цвет выделенного ребра */
1783
+ _selectColor = xe;
1784
+ /** Обработка текущего режима выборки. */
1785
+ handle(e, t) {
1786
+ if (this._raycastApi.setRaycastMode(this.mode), t === F.Hover) {
1787
+ if (!e) {
1788
+ this._hoverLine.visible = !1, this._hovered = null;
1181
1789
  return;
1182
1790
  }
1183
- const s = t.intersection.object;
1184
- this._hoveredMesh !== s && (this._hoveredMesh && this._hoveredMesh !== this._selectedMesh && this._restoreEdgesColor(this._hoveredMesh), s !== this._selectedMesh && this._paintEdges(s, this._hoverColor), this._hoveredMesh = s);
1791
+ const s = e.intersection.object;
1792
+ if (!s?.isLineSegments) return;
1793
+ const r = s, i = Math.floor((e.intersection.index ?? -1) / 2);
1794
+ if (i < 0) return;
1795
+ this._selected && this._same({ lines: r, seg: i }, this._selected) ? this._hoverLine.visible = !1 : (this._writeWorldSegment(this._hoverLine, r, i), this._hoverLine.visible = !0), this._hovered = { lines: r, seg: i };
1796
+ return;
1185
1797
  }
1186
- if (e === C.Click) {
1187
- if (!t) {
1188
- this._selectedMesh && (this._restoreEdgesColor(this._selectedMesh), this._selectedMesh = null, this._store.setSelectedObject(null));
1798
+ if (t === F.Click) {
1799
+ if (!e) {
1800
+ this._selectLine.visible = !1, this._selected = null, this._store.setSelectedObject(null);
1189
1801
  return;
1190
1802
  }
1191
- const s = t.intersection.object;
1192
- this._selectedMesh && this._selectedMesh !== s && this._restoreEdgesColor(this._selectedMesh), this._paintEdges(s, this._selectColor), this._selectedMesh = s, this._store.setSelectedObject(s);
1803
+ const s = e.intersection.object;
1804
+ if (!s?.isLineSegments) return;
1805
+ const r = s, i = Math.floor((e.intersection.index ?? -1) / 2);
1806
+ if (i < 0) return;
1807
+ this._writeWorldSegment(this._selectLine, r, i), this._centerAndOrientLineOnSegment(this._selectLine, r, i), this._selectLine.visible = !0, this._prepareEdgeMetadata(r, i), this._store.setSelectedObject(this._selectLine), this._selected = { lines: r, seg: i }, this._hovered && this._same(this._hovered, this._selected) && (this._hoverLine.visible = !1);
1193
1808
  }
1194
1809
  }
1810
+ /** Откат текущего режима выборки */
1195
1811
  rollback() {
1196
- this._hoveredMesh && this._restoreEdgesColor(this._hoveredMesh), this._selectedMesh && this._restoreEdgesColor(this._selectedMesh), this._hoveredMesh = this._selectedMesh = null, this._store.setSelectedObject(null);
1812
+ this._hoverLine.visible = !1, this._selectLine.visible = !1, this._hovered = this._selected = null, this._store.setSelectedObject(null);
1197
1813
  }
1198
1814
  /** Освобождает ресурсы хендлера, удаляет слушатели и очищает внутренние данные. */
1199
1815
  dispose() {
1200
- this.rollback();
1816
+ this.rollback(), this._sceneApi.removeFromScene(this._hoverLine), this._sceneApi.removeFromScene(this._selectLine), this._hoverLine.geometry.dispose(), this._hoverLine.material.dispose(), this._selectLine.geometry.dispose(), this._selectLine.material.dispose();
1201
1817
  }
1202
- /**
1203
- * Перекрасить рёбра меша и запомнить оригинальный цвет (один раз на LineSegments).
1818
+ /** Инициализация буферных линий для режима (hover и click).
1819
+ * На весь режим будет использовано 2 глобальных линии на сцене,
1820
+ * использоваться они будут только для обозначения геометрии ребер конкретной фигуры.
1204
1821
  */
1205
- _paintEdges(t, e) {
1206
- t.children.forEach((s) => {
1207
- const i = s;
1208
- if (i.isLineSegments && i.material) {
1209
- const r = i.material;
1210
- this._origLineColors.has(i) || this._origLineColors.set(i, r.color.clone()), r.color.setHex(e), r.needsUpdate = !0;
1211
- }
1212
- });
1822
+ _makeOverlayLine(e) {
1823
+ const t = new l.BufferGeometry();
1824
+ t.setAttribute("position", new l.Float32BufferAttribute(6, 3));
1825
+ const s = new l.LineBasicMaterial({
1826
+ color: e,
1827
+ depthTest: !1,
1828
+ depthWrite: !1,
1829
+ transparent: !0,
1830
+ opacity: 1
1831
+ }), r = new l.Line(t, s);
1832
+ return r.renderOrder = 1e3, r.raycast = () => {
1833
+ }, r.layers.set($), r.visible = !1, r;
1213
1834
  }
1214
- /**
1215
- * Восстановить исходный цвет рёбер меша из WeakMap.
1216
- * Если исходный цвет не сохранён (на всякий случай) ничего не меняем.
1217
- */
1218
- _restoreEdgesColor(t) {
1219
- t.children.forEach((e) => {
1220
- const s = e;
1221
- if (s.isLineSegments && s.material) {
1222
- const i = this._origLineColors.get(s);
1223
- if (i) {
1224
- const r = s.material;
1225
- r.color.copy(i), r.needsUpdate = !0;
1226
- }
1227
- }
1228
- });
1835
+ /** Локальные точки сегмента переводим в target (который висит на сцене) */
1836
+ _writeWorldSegment(e, t, s) {
1837
+ const r = t.geometry.getAttribute("position"), i = s * 2, n = i + 1, o = new l.Vector3(r.getX(i), r.getY(i), r.getZ(i)).applyMatrix4(
1838
+ t.matrixWorld
1839
+ ), c = new l.Vector3(r.getX(n), r.getY(n), r.getZ(n)).applyMatrix4(
1840
+ t.matrixWorld
1841
+ ), u = e.geometry.getAttribute("position");
1842
+ u.setXYZ(0, o.x, o.y, o.z), u.setXYZ(1, c.x, c.y, c.z), u.needsUpdate = !0;
1843
+ }
1844
+ _same(e, t) {
1845
+ return !!e && !!t && e.lines === t.lines && e.seg === t.seg;
1846
+ }
1847
+ /** Центрует `THREE.Line` на сегменте и ориентирует её вдоль ребра */
1848
+ _centerAndOrientLineOnSegment(e, t, s) {
1849
+ const r = t.geometry.getAttribute("position"), i = s * 2, n = i + 1, o = new l.Vector3(r.getX(i), r.getY(i), r.getZ(i)).applyMatrix4(
1850
+ t.matrixWorld
1851
+ ), c = new l.Vector3(r.getX(n), r.getY(n), r.getZ(n)).applyMatrix4(
1852
+ t.matrixWorld
1853
+ ), u = new l.Vector3().subVectors(c, o), d = u.length();
1854
+ if (!isFinite(d) || d === 0) return;
1855
+ const m = new l.Vector3().addVectors(o, c).multiplyScalar(0.5);
1856
+ e.position.copy(m);
1857
+ const p = e.geometry;
1858
+ let g = p.getAttribute("position");
1859
+ (!g || g.count < 2) && (p.setAttribute("position", new l.BufferAttribute(new Float32Array(6), 3)), g = p.getAttribute("position")), g.setXYZ(0, -d / 2, 0, 0), g.setXYZ(1, d / 2, 0, 0), g.needsUpdate = !0, u.normalize();
1860
+ const f = new l.Quaternion().setFromUnitVectors(new l.Vector3(1, 0, 0), u);
1861
+ e.quaternion.copy(f), e.updateMatrixWorld(!0);
1862
+ }
1863
+ /** Запись метаданных выбранного ребра для использования инструментов */
1864
+ _prepareEdgeMetadata(e, t) {
1865
+ const s = Pt(e);
1866
+ if (!s) return;
1867
+ const r = e.geometry.getAttribute("position"), i = t * 2, n = i + 1, o = new l.Vector3(r.getX(i), r.getY(i), r.getZ(i)).applyMatrix4(
1868
+ e.matrixWorld
1869
+ ), c = new l.Vector3(r.getX(n), r.getY(n), r.getZ(n)).applyMatrix4(
1870
+ e.matrixWorld
1871
+ ), u = new l.Matrix4().copy(s.matrixWorld).invert(), d = o.clone().applyMatrix4(u), m = c.clone().applyMatrix4(u), g = s.geometry.getAttribute("position"), f = new l.Vector3(), h = 1e-6, v = [], y = [];
1872
+ for (let O = 0; O < g.count; O++)
1873
+ f.fromBufferAttribute(g, O), f.distanceToSquared(d) < h * h ? v.push(O) : f.distanceToSquared(m) < h * h && y.push(O);
1874
+ const A = new l.Matrix4().copy(e.matrixWorld).invert(), S = o.clone().applyMatrix4(A), x = c.clone().applyMatrix4(A), b = e.geometry.getAttribute("position"), C = new l.Vector3(), M = [], I = [];
1875
+ for (let O = 0; O < b.count; O++)
1876
+ C.fromBufferAttribute(b, O), C.distanceToSquared(S) < h * h ? M.push(O) : C.distanceToSquared(x) < h * h && I.push(O);
1877
+ this._selectLine.userData.edgeInfo = {
1878
+ lines: e,
1879
+ seg: t,
1880
+ mesh: s,
1881
+ aIndices: v,
1882
+ bIndices: y,
1883
+ aEdgeIndices: M,
1884
+ bEdgeIndices: I
1885
+ };
1229
1886
  }
1230
1887
  };
1231
- ne = Kt([
1232
- M(),
1233
- Ae(0, _("RendererApi")),
1234
- Ae(1, _("IEditorStore"))
1235
- ], ne);
1236
- var qt = Object.getOwnPropertyDescriptor, Qt = (t, e, s, i) => {
1237
- for (var r = i > 1 ? void 0 : i ? qt(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1238
- (n = t[o]) && (r = n(r) || r);
1239
- return r;
1240
- }, Ie = (t, e) => (s, i) => e(s, i, t);
1241
- let ae = class {
1242
- constructor(t, e) {
1243
- this._api = t, this._store = e, this._api.enableCameraLayer(T), this._hoverFace = this._makeOverlayFace(this._hoverColor), this._selectFace = this._makeOverlayFace(this._selectColor), this._api.addObject(this._hoverFace, T), this._api.addObject(this._selectFace, T);
1888
+ ze = xr([
1889
+ w(),
1890
+ re(0, _("ISceneApi")),
1891
+ re(1, _("ICameraApi")),
1892
+ re(2, _("IRaycastApi")),
1893
+ re(3, _("EditorStore"))
1894
+ ], ze);
1895
+ var Sr = Object.getOwnPropertyDescriptor, wr = (e, t, s, r) => {
1896
+ for (var i = r > 1 ? void 0 : r ? Sr(t, s) : t, n = e.length - 1, o; n >= 0; n--)
1897
+ (o = e[n]) && (i = o(i) || i);
1898
+ return i;
1899
+ }, ie = (e, t) => (s, r) => t(s, r, e);
1900
+ let Ge = class {
1901
+ constructor(e, t, s, r) {
1902
+ this._cameraApi = e, this._sceneApi = t, this._raycastApi = s, this._store = r, this._cameraApi.enableCameraLayer($), this._hoverFace = Y(this._makeOverlayFace(this._hoverColor)), this._selectFace = Y(this._makeOverlayFace(this._selectColor)), this._sceneApi.addObject(this._hoverFace, $), this._sceneApi.addObject(this._selectFace, $);
1244
1903
  }
1245
1904
  /** Режим, которым управляет хендлер, нужен только менеджеру */
1246
- mode = y.Face;
1905
+ mode = P.Face;
1247
1906
  /** Текущая наведённая грань */
1248
1907
  _hoverFace;
1249
1908
  /** Текущая выбранная грань */
@@ -1258,42 +1917,42 @@ let ae = class {
1258
1917
  _selected = null;
1259
1918
  // Цвета, необходимые для переключения
1260
1919
  /** Цвет грани, на которую навелись */
1261
- _hoverColor = Z;
1920
+ _hoverColor = Me;
1262
1921
  /** Цвет выделенной граней */
1263
- _selectColor = X;
1922
+ _selectColor = xe;
1264
1923
  // Погрешности для поиска треугольников и сборки граней
1265
1924
  /** Погрешность на сравнение нормалей */
1266
1925
  _normalEps = 1e-4;
1267
1926
  /** Погрешность на принадлежность одной плоскости */
1268
1927
  _planeEps = 1e-4;
1269
1928
  /** Обработка текущего режима выборки. */
1270
- handle(t, e) {
1271
- if (this._api.setRaycastMode(this.mode), e === C.Hover) {
1272
- if (!t) {
1929
+ handle(e, t) {
1930
+ if (this._raycastApi.setRaycastMode(this.mode), t === F.Hover) {
1931
+ if (!e) {
1273
1932
  this._hoverFace.visible = !1, this._hovered = null;
1274
1933
  return;
1275
1934
  }
1276
- const s = t.intersection.object;
1935
+ const s = e.intersection.object;
1277
1936
  if (!s?.isMesh) return;
1278
- const i = s, r = t.intersection.faceIndex ?? -1;
1279
- if (r < 0) return;
1280
- const o = this._collectFaceGroup(i, r);
1281
- if (!o) return;
1282
- this._selected && this._same(o, this._selected) ? this._hoverFace.visible = !1 : (this._writeWorldFaceGroup(this._hoverFace, o), this._hoverFace.visible = !0), this._hovered = o;
1937
+ const r = s, i = e.intersection.faceIndex ?? -1;
1938
+ if (i < 0) return;
1939
+ const n = this._collectFaceGroup(r, i);
1940
+ if (!n) return;
1941
+ this._selected && this._same(n, this._selected) ? this._hoverFace.visible = !1 : (this._writeWorldFaceGroup(this._hoverFace, n), this._hoverFace.visible = !0), this._hovered = n;
1283
1942
  return;
1284
1943
  }
1285
- if (e === C.Click) {
1286
- if (!t) {
1944
+ if (t === F.Click) {
1945
+ if (!e) {
1287
1946
  this._selectFace.visible = !1, this._selected = null, this._store.setSelectedObject(null);
1288
1947
  return;
1289
1948
  }
1290
- const s = t.intersection.object;
1949
+ const s = e.intersection.object;
1291
1950
  if (!s?.isMesh) return;
1292
- const i = s, r = t.intersection.faceIndex ?? -1;
1293
- if (r < 0) return;
1294
- const o = this._collectFaceGroup(i, r);
1295
- if (!o) return;
1296
- this._writeWorldFaceGroup(this._selectFace, o), this._centerFaceProxy(this._selectFace), this._selectFace.visible = !0, this._prepareFaceMetadata(o), this._store.setSelectedObject(this._selectFace), this._selected = o, this._hovered && this._same(this._hovered, this._selected) && (this._hoverFace.visible = !1);
1951
+ const r = s, i = e.intersection.faceIndex ?? -1;
1952
+ if (i < 0) return;
1953
+ const n = this._collectFaceGroup(r, i);
1954
+ if (!n) return;
1955
+ this._writeWorldFaceGroup(this._selectFace, n), this._centerFaceProxy(this._selectFace), this._selectFace.visible = !0, this._prepareFaceMetadata(n), this._store.setSelectedObject(this._selectFace), this._selected = n, this._hovered && this._same(this._hovered, this._selected) && (this._hoverFace.visible = !1);
1297
1956
  }
1298
1957
  }
1299
1958
  /** Откат текущего режима выборки */
@@ -1302,235 +1961,318 @@ let ae = class {
1302
1961
  }
1303
1962
  /** Освобождает ресурсы хендлера, удаляет слушатели и очищает внутренние данные. */
1304
1963
  dispose() {
1305
- this.rollback(), this._api.removeObject(this._hoverFace), this._api.removeObject(this._selectFace), this._hoverFace.geometry.dispose(), this._hoverFace.material.dispose(), this._selectFace.geometry.dispose(), this._selectFace.material.dispose();
1964
+ this.rollback(), this._sceneApi.removeFromScene(this._hoverFace), this._sceneApi.removeFromScene(this._selectFace), this._hoverFace.geometry.dispose(), this._hoverFace.material.dispose(), this._selectFace.geometry.dispose(), this._selectFace.material.dispose();
1306
1965
  }
1307
1966
  /**
1308
1967
  * Инициализация overlay mesh для режима (hover и click).
1309
1968
  * На весь режим используются 2 глобальных mesh на сцене,
1310
1969
  * геометрия которых переписывается под текущую грань.
1311
1970
  */
1312
- _makeOverlayFace(t) {
1313
- const e = new a.BufferGeometry(), s = new a.MeshBasicMaterial({
1314
- color: t,
1971
+ _makeOverlayFace(e) {
1972
+ const t = new l.BufferGeometry(), s = new l.MeshBasicMaterial({
1973
+ color: e,
1315
1974
  transparent: !0,
1316
1975
  opacity: 0.35,
1317
1976
  depthTest: !1,
1318
1977
  depthWrite: !1,
1319
- side: a.DoubleSide,
1978
+ side: l.DoubleSide,
1320
1979
  polygonOffset: !0,
1321
1980
  polygonOffsetFactor: -1,
1322
1981
  polygonOffsetUnits: -1
1323
- }), i = new a.Mesh(e, s);
1324
- return i.renderOrder = 1e3, i.layers.set(T), i.visible = !1, i.raycast = () => {
1325
- }, i;
1982
+ }), r = new l.Mesh(t, s);
1983
+ return r.renderOrder = 1e3, r.layers.set($), r.visible = !1, r.raycast = () => {
1984
+ }, r;
1326
1985
  }
1327
1986
  /**
1328
1987
  * Сбор логической грани как связной группы компланарных треугольников.
1329
1988
  * Если geometry неиндексированная — пока возвращаем только стартовый triangle.
1330
1989
  */
1331
- _collectFaceGroup(t, e) {
1332
- const s = t.geometry, i = s.getAttribute("position");
1333
- if (!i) return null;
1334
- const r = s.index;
1335
- if (!r) {
1336
- const E = e * 3, O = e * 3 + 1, A = e * 3 + 2;
1990
+ _collectFaceGroup(e, t) {
1991
+ const s = e.geometry, r = s.getAttribute("position");
1992
+ if (!r) return null;
1993
+ const i = s.index;
1994
+ if (!i) {
1995
+ const b = t * 3, C = t * 3 + 1, M = t * 3 + 2;
1337
1996
  return {
1338
- mesh: t,
1339
- faceIndex: e,
1340
- triangleIndices: [e],
1341
- vertexIndices: [E, O, A],
1342
- proxyVertexMap: [E, O, A]
1997
+ mesh: e,
1998
+ faceIndex: t,
1999
+ triangleIndices: [t],
2000
+ vertexIndices: [b, C, M],
2001
+ proxyVertexMap: [b, C, M]
1343
2002
  };
1344
2003
  }
1345
- const o = Math.floor(r.count / 3);
1346
- if (e < 0 || e >= o) return null;
1347
- const n = this._buildTriangleAdjacency(r, i), [h, l, c] = this._getTriangleIndices(r, e), d = this._readVertex(i, h), g = this._readVertex(i, l), m = this._readVertex(i, c), f = new a.Vector3().subVectors(g, d).cross(new a.Vector3().subVectors(m, d)).normalize(), u = new a.Plane().setFromNormalAndCoplanarPoint(f, d), w = /* @__PURE__ */ new Set(), S = [], j = [e];
1348
- for (; j.length > 0; ) {
1349
- const E = j.pop();
1350
- if (w.has(E)) continue;
1351
- w.add(E);
1352
- const [O, A, k] = this._getTriangleIndices(r, E), x = this._readVertex(i, O), ye = this._readVertex(i, A), Me = this._readVertex(i, k), Ge = new a.Vector3().subVectors(ye, x).cross(new a.Vector3().subVectors(Me, x)).normalize(), Ze = Math.abs(Ge.dot(f)) >= 1 - this._normalEps, Xe = Math.abs(u.distanceToPoint(x)) < this._planeEps && Math.abs(u.distanceToPoint(ye)) < this._planeEps && Math.abs(u.distanceToPoint(Me)) < this._planeEps;
1353
- if (!Ze || !Xe) continue;
1354
- S.push(E);
1355
- const we = n.get(E);
1356
- if (we)
1357
- for (const Se of we)
1358
- w.has(Se) || j.push(Se);
2004
+ const n = Math.floor(i.count / 3);
2005
+ if (t < 0 || t >= n) return null;
2006
+ const o = this._buildTriangleAdjacency(i, r), [c, u, d] = this._getTriangleIndices(i, t), m = this._readVertex(r, c), p = this._readVertex(r, u), g = this._readVertex(r, d), f = new l.Vector3().subVectors(p, m).cross(new l.Vector3().subVectors(g, m)).normalize(), h = new l.Plane().setFromNormalAndCoplanarPoint(f, m), v = /* @__PURE__ */ new Set(), y = [], A = [t];
2007
+ for (; A.length > 0; ) {
2008
+ const b = A.pop();
2009
+ if (v.has(b)) continue;
2010
+ v.add(b);
2011
+ const [C, M, I] = this._getTriangleIndices(i, b), O = this._readVertex(r, C), V = this._readVertex(r, M), D = this._readVertex(r, I), H = new l.Vector3().subVectors(V, O).cross(new l.Vector3().subVectors(D, O)).normalize(), Gt = Math.abs(H.dot(f)) >= 1 - this._normalEps, Wt = Math.abs(h.distanceToPoint(O)) < this._planeEps && Math.abs(h.distanceToPoint(V)) < this._planeEps && Math.abs(h.distanceToPoint(D)) < this._planeEps;
2012
+ if (!Gt || !Wt) continue;
2013
+ y.push(b);
2014
+ const st = o.get(b);
2015
+ if (st)
2016
+ for (const rt of st)
2017
+ v.has(rt) || A.push(rt);
1359
2018
  }
1360
- S.sort((E, O) => E - O);
1361
- const R = /* @__PURE__ */ new Set(), V = [];
1362
- for (const E of S) {
1363
- const [O, A, k] = this._getTriangleIndices(r, E);
1364
- R.add(O), R.add(A), R.add(k), V.push(O, A, k);
2019
+ y.sort((b, C) => b - C);
2020
+ const S = /* @__PURE__ */ new Set(), x = [];
2021
+ for (const b of y) {
2022
+ const [C, M, I] = this._getTriangleIndices(i, b);
2023
+ S.add(C), S.add(M), S.add(I), x.push(C, M, I);
1365
2024
  }
1366
2025
  return {
1367
- mesh: t,
1368
- faceIndex: e,
1369
- triangleIndices: S,
1370
- vertexIndices: Array.from(R),
1371
- proxyVertexMap: V
2026
+ mesh: e,
2027
+ faceIndex: t,
2028
+ triangleIndices: y,
2029
+ vertexIndices: Array.from(S),
2030
+ proxyVertexMap: x
1372
2031
  };
1373
2032
  }
1374
2033
  /** Перезаписывает overlay mesh world-space треугольниками выбранной грани */
1375
- _writeWorldFaceGroup(t, e) {
1376
- const s = e.mesh.geometry, i = s.getAttribute("position"), r = s.index, o = new Float32Array(e.triangleIndices.length * 9);
1377
- let n = 0;
1378
- for (const l of e.triangleIndices) {
1379
- let c, d, g;
1380
- r ? [c, d, g] = this._getTriangleIndices(r, l) : (c = l * 3, d = l * 3 + 1, g = l * 3 + 2);
1381
- const m = this._readVertex(i, c).applyMatrix4(e.mesh.matrixWorld), f = this._readVertex(i, d).applyMatrix4(e.mesh.matrixWorld), u = this._readVertex(i, g).applyMatrix4(e.mesh.matrixWorld);
1382
- o[n++] = m.x, o[n++] = m.y, o[n++] = m.z, o[n++] = f.x, o[n++] = f.y, o[n++] = f.z, o[n++] = u.x, o[n++] = u.y, o[n++] = u.z;
2034
+ _writeWorldFaceGroup(e, t) {
2035
+ const s = t.mesh.geometry, r = s.getAttribute("position"), i = s.index, n = new Float32Array(t.triangleIndices.length * 9);
2036
+ let o = 0;
2037
+ for (const u of t.triangleIndices) {
2038
+ let d, m, p;
2039
+ i ? [d, m, p] = this._getTriangleIndices(i, u) : (d = u * 3, m = u * 3 + 1, p = u * 3 + 2);
2040
+ const g = this._readVertex(r, d).applyMatrix4(t.mesh.matrixWorld), f = this._readVertex(r, m).applyMatrix4(t.mesh.matrixWorld), h = this._readVertex(r, p).applyMatrix4(t.mesh.matrixWorld);
2041
+ n[o++] = g.x, n[o++] = g.y, n[o++] = g.z, n[o++] = f.x, n[o++] = f.y, n[o++] = f.z, n[o++] = h.x, n[o++] = h.y, n[o++] = h.z;
1383
2042
  }
1384
- const h = t.geometry;
1385
- h.setAttribute("position", new a.BufferAttribute(o, 3)), h.setIndex(null), h.computeVertexNormals(), h.computeBoundingBox(), h.computeBoundingSphere();
2043
+ const c = e.geometry;
2044
+ c.setAttribute("position", new l.BufferAttribute(n, 3)), c.setIndex(null), c.computeVertexNormals(), c.computeBoundingBox(), c.computeBoundingSphere();
1386
2045
  }
1387
2046
  /** Сравнение двух логических граней */
1388
- _same(t, e) {
1389
- return !!t && !!e && t.mesh === e.mesh && t.triangleIndices.length === e.triangleIndices.length && t.triangleIndices.every((s, i) => s === e.triangleIndices[i]);
2047
+ _same(e, t) {
2048
+ return !!e && !!t && e.mesh === t.mesh && e.triangleIndices.length === t.triangleIndices.length && e.triangleIndices.every((s, r) => s === t.triangleIndices[r]);
1390
2049
  }
1391
2050
  /** Подготовка метаданных выбранной грани для инструментов */
1392
- _prepareFaceMetadata(t) {
1393
- const { vertexIndexGroups: e, proxyVertexMap: s, lines: i, lineVertexIndexGroups: r } = this._buildFaceVertexGroups(t);
2051
+ _prepareFaceMetadata(e) {
2052
+ const { vertexIndexGroups: t, proxyVertexMap: s, lines: r, lineVertexIndexGroups: i } = this._buildFaceVertexGroups(e);
1394
2053
  this._selectFace.userData.faceInfo = {
1395
- mesh: t.mesh,
1396
- faceIndex: t.faceIndex,
1397
- triangleIndices: t.triangleIndices,
1398
- vertexIndices: t.vertexIndices,
1399
- vertexIndexGroups: e,
2054
+ mesh: e.mesh,
2055
+ faceIndex: e.faceIndex,
2056
+ triangleIndices: e.triangleIndices,
2057
+ vertexIndices: e.vertexIndices,
2058
+ vertexIndexGroups: t,
1400
2059
  proxyVertexMap: s,
1401
- lines: i,
1402
- lineVertexIndexGroups: r
2060
+ lines: r,
2061
+ lineVertexIndexGroups: i
1403
2062
  };
1404
2063
  }
1405
2064
  /**
1406
2065
  * Центрирует proxy-грань, чтобы TransformControls работали с ней как с обычным объектом.
1407
2066
  * После записи world-space вершин переносит геометрию в локальные координаты proxy mesh.
1408
2067
  */
1409
- _centerFaceProxy(t) {
1410
- const e = t.geometry, s = e.getAttribute("position");
2068
+ _centerFaceProxy(e) {
2069
+ const t = e.geometry, s = t.getAttribute("position");
1411
2070
  if (!s || s.count === 0) return;
1412
- const i = new a.Vector3();
1413
- for (let r = 0; r < s.count; r++)
1414
- i.x += s.getX(r), i.y += s.getY(r), i.z += s.getZ(r);
1415
- i.multiplyScalar(1 / s.count);
1416
- for (let r = 0; r < s.count; r++)
1417
- s.setXYZ(r, s.getX(r) - i.x, s.getY(r) - i.y, s.getZ(r) - i.z);
1418
- s.needsUpdate = !0, t.position.copy(i), t.quaternion.identity(), t.scale.set(1, 1, 1), t.updateMatrixWorld(!0), e.computeBoundingBox(), e.computeBoundingSphere();
2071
+ const r = new l.Vector3();
2072
+ for (let i = 0; i < s.count; i++)
2073
+ r.x += s.getX(i), r.y += s.getY(i), r.z += s.getZ(i);
2074
+ r.multiplyScalar(1 / s.count);
2075
+ for (let i = 0; i < s.count; i++)
2076
+ s.setXYZ(i, s.getX(i) - r.x, s.getY(i) - r.y, s.getZ(i) - r.z);
2077
+ s.needsUpdate = !0, e.position.copy(r), e.quaternion.identity(), e.scale.set(1, 1, 1), e.updateMatrixWorld(!0), t.computeBoundingBox(), t.computeBoundingSphere();
1419
2078
  }
1420
2079
  /** Регистрирует ребро треугольника в edge map */
1421
- _pushEdge(t, e, s, i) {
1422
- const r = e < s ? `${e}_${s}` : `${s}_${e}`, o = t.get(r);
1423
- o ? o.push(i) : t.set(r, [i]);
2080
+ _pushEdge(e, t, s, r) {
2081
+ const i = t < s ? `${t}_${s}` : `${s}_${t}`, n = e.get(i);
2082
+ n ? n.push(r) : e.set(i, [r]);
1424
2083
  }
1425
2084
  /** Строит граф соседства треугольников по общим ребрам */
1426
- _buildTriangleAdjacency(t, e) {
1427
- const s = Math.floor(t.count / 3), i = /* @__PURE__ */ new Map(), r = this._buildWeldMap(t, e);
1428
- for (let h = 0; h < s; h++) {
1429
- const [l, c, d] = this._getTriangleIndices(t, h), g = r.get(l), m = r.get(c), f = r.get(d);
1430
- this._pushEdge(i, g, m, h), this._pushEdge(i, m, f, h), this._pushEdge(i, f, g, h);
2085
+ _buildTriangleAdjacency(e, t) {
2086
+ const s = Math.floor(e.count / 3), r = /* @__PURE__ */ new Map(), i = this._buildWeldMap(e, t);
2087
+ for (let c = 0; c < s; c++) {
2088
+ const [u, d, m] = this._getTriangleIndices(e, c), p = i.get(u), g = i.get(d), f = i.get(m);
2089
+ this._pushEdge(r, p, g, c), this._pushEdge(r, g, f, c), this._pushEdge(r, f, p, c);
1431
2090
  }
1432
- const o = /* @__PURE__ */ new Map();
1433
- for (let h = 0; h < s; h++)
1434
- o.set(h, /* @__PURE__ */ new Set());
1435
- for (const h of i.values())
1436
- if (!(h.length < 2))
1437
- for (let l = 0; l < h.length; l++)
1438
- for (let c = 0; c < h.length; c++)
1439
- l !== c && o.get(h[l])?.add(h[c]);
1440
2091
  const n = /* @__PURE__ */ new Map();
1441
- for (const [h, l] of o)
1442
- n.set(h, Array.from(l));
1443
- return n;
2092
+ for (let c = 0; c < s; c++)
2093
+ n.set(c, /* @__PURE__ */ new Set());
2094
+ for (const c of r.values())
2095
+ if (!(c.length < 2))
2096
+ for (let u = 0; u < c.length; u++)
2097
+ for (let d = 0; d < c.length; d++)
2098
+ u !== d && n.get(c[u])?.add(c[d]);
2099
+ const o = /* @__PURE__ */ new Map();
2100
+ for (const [c, u] of n)
2101
+ o.set(c, Array.from(u));
2102
+ return o;
1444
2103
  }
1445
2104
  /** Возвращает индексы трех вершин треугольника */
1446
- _getTriangleIndices(t, e) {
1447
- return [t.getX(e * 3), t.getX(e * 3 + 1), t.getX(e * 3 + 2)];
2105
+ _getTriangleIndices(e, t) {
2106
+ return [e.getX(t * 3), e.getX(t * 3 + 1), e.getX(t * 3 + 2)];
1448
2107
  }
1449
2108
  /** Читает вершину из position buffer в local space geometry */
1450
- _readVertex(t, e) {
1451
- return new a.Vector3(t.getX(e), t.getY(e), t.getZ(e));
2109
+ _readVertex(e, t) {
2110
+ return new l.Vector3(e.getX(t), e.getY(t), e.getZ(t));
1452
2111
  }
1453
2112
  /** Построение ключа вершины по позиции */
1454
- _vertexKey(t, e, s = 1e-6) {
1455
- const i = Math.round(t.getX(e) / s), r = Math.round(t.getY(e) / s), o = Math.round(t.getZ(e) / s);
1456
- return `${i}_${r}_${o}`;
2113
+ _vertexKey(e, t, s = 1e-6) {
2114
+ const r = Math.round(e.getX(t) / s), i = Math.round(e.getY(t) / s), n = Math.round(e.getZ(t) / s);
2115
+ return `${r}_${i}_${n}`;
1457
2116
  }
1458
2117
  /**
1459
2118
  * Строит отображение исходных индексов вершин в "сваренные" ids по координате.
1460
2119
  * Нужно для случаев, когда соседние треугольники визуально делят ребро,
1461
2120
  * но используют разные индексы вершин (например, цилиндрические крышки, UV seams и т.п.).
1462
2121
  */
1463
- _buildWeldMap(t, e) {
1464
- const s = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map();
1465
- let r = 0;
1466
- for (let o = 0; o < t.count; o++) {
1467
- const n = t.getX(o);
1468
- if (i.has(n)) continue;
1469
- const h = this._vertexKey(e, n);
1470
- let l = s.get(h);
1471
- l == null && (l = r++, s.set(h, l)), i.set(n, l);
2122
+ _buildWeldMap(e, t) {
2123
+ const s = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map();
2124
+ let i = 0;
2125
+ for (let n = 0; n < e.count; n++) {
2126
+ const o = e.getX(n);
2127
+ if (r.has(o)) continue;
2128
+ const c = this._vertexKey(t, o);
2129
+ let u = s.get(c);
2130
+ u == null && (u = i++, s.set(c, u)), r.set(o, u);
1472
2131
  }
1473
- return i;
2132
+ return r;
1474
2133
  }
1475
2134
  /** Сбрасывает transform proxy-граням */
1476
- _resetFaceProxyTransform(t) {
1477
- t.position.set(0, 0, 0), t.quaternion.identity(), t.scale.set(1, 1, 1), t.updateMatrixWorld(!0);
1478
- }
1479
- _buildFaceVertexGroups(t) {
1480
- const s = t.mesh.geometry.getAttribute("position"), i = 1e-6, r = new a.Vector3(), o = t.vertexIndices, n = [], h = /* @__PURE__ */ new Map();
1481
- for (const m of o) {
1482
- const f = this._readVertex(s, m), u = [];
1483
- for (let S = 0; S < s.count; S++)
1484
- r.fromBufferAttribute(s, S), r.distanceToSquared(f) < i * i && u.push(S);
1485
- const w = n.length;
1486
- n.push(u);
1487
- for (const S of u)
1488
- h.set(S, w);
2135
+ _resetFaceProxyTransform(e) {
2136
+ e.position.set(0, 0, 0), e.quaternion.identity(), e.scale.set(1, 1, 1), e.updateMatrixWorld(!0);
2137
+ }
2138
+ _buildFaceVertexGroups(e) {
2139
+ const s = e.mesh.geometry.getAttribute("position"), r = 1e-6, i = new l.Vector3(), n = e.vertexIndices, o = [], c = /* @__PURE__ */ new Map();
2140
+ for (const g of n) {
2141
+ const f = this._readVertex(s, g), h = [];
2142
+ for (let y = 0; y < s.count; y++)
2143
+ i.fromBufferAttribute(s, y), i.distanceToSquared(f) < r * r && h.push(y);
2144
+ const v = o.length;
2145
+ o.push(h);
2146
+ for (const y of h)
2147
+ c.set(y, v);
1489
2148
  }
1490
- const l = [];
1491
- for (const m of t.proxyVertexMap) {
1492
- const f = h.get(m);
1493
- l.push(f ?? -1);
2149
+ const u = [];
2150
+ for (const g of e.proxyVertexMap) {
2151
+ const f = c.get(g);
2152
+ u.push(f ?? -1);
1494
2153
  }
1495
- const c = this._findChildLines(t.mesh), d = c ? this._buildLineVertexGroups(t, c) : void 0, g = {
1496
- vertexIndexGroups: n,
1497
- proxyVertexMap: l
2154
+ const d = this._findChildLines(e.mesh), m = d ? this._buildLineVertexGroups(e, d) : void 0, p = {
2155
+ vertexIndexGroups: o,
2156
+ proxyVertexMap: u
1498
2157
  };
1499
- return c && (g.lines = c), d && (g.lineVertexIndexGroups = d), g;
2158
+ return d && (p.lines = d), m && (p.lineVertexIndexGroups = m), p;
1500
2159
  }
1501
- _findChildLines(t) {
1502
- for (const e of t.children)
1503
- if (e.isLineSegments)
1504
- return e;
2160
+ _findChildLines(e) {
2161
+ for (const t of e.children)
2162
+ if (t.isLineSegments)
2163
+ return t;
1505
2164
  return null;
1506
2165
  }
1507
- _buildLineVertexGroups(t, e) {
1508
- const i = e.geometry.getAttribute("position"), o = t.mesh.geometry.getAttribute("position"), n = 1e-6, h = new a.Vector3(), l = e.matrixWorld, c = t.mesh.matrixWorld, d = [];
1509
- for (const g of t.vertexIndices) {
1510
- const m = this._readVertex(o, g).applyMatrix4(c), f = [];
1511
- for (let u = 0; u < i.count; u++)
1512
- h.fromBufferAttribute(i, u).applyMatrix4(l), h.distanceToSquared(m) < n * n && f.push(u);
1513
- d.push(f);
2166
+ _buildLineVertexGroups(e, t) {
2167
+ const r = t.geometry.getAttribute("position"), n = e.mesh.geometry.getAttribute("position"), o = 1e-6, c = new l.Vector3(), u = t.matrixWorld, d = e.mesh.matrixWorld, m = [];
2168
+ for (const p of e.vertexIndices) {
2169
+ const g = this._readVertex(n, p).applyMatrix4(d), f = [];
2170
+ for (let h = 0; h < r.count; h++)
2171
+ c.fromBufferAttribute(r, h).applyMatrix4(u), c.distanceToSquared(g) < o * o && f.push(h);
2172
+ m.push(f);
1514
2173
  }
1515
- return d;
2174
+ return m;
1516
2175
  }
1517
2176
  };
1518
- ae = Qt([
1519
- M(),
1520
- Ie(0, _("RendererApi")),
1521
- Ie(1, _("IEditorStore"))
1522
- ], ae);
1523
- var Jt = Object.getOwnPropertyDescriptor, es = (t, e, s, i) => {
1524
- for (var r = i > 1 ? void 0 : i ? Jt(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1525
- (n = t[o]) && (r = n(r) || r);
1526
- return r;
1527
- }, je = (t, e) => (s, i) => e(s, i, t);
1528
- let he = class {
1529
- constructor(t, e) {
1530
- this._api = t, this._store = e, this._api.enableCameraLayer(T), this._hoverVertex = this._makeOverlayVertex(this._hoverColor), this._selectVertex = this._makeOverlayVertex(this._selectColor), this._api.addObject(this._hoverVertex, T), this._api.addObject(this._selectVertex, T);
2177
+ Ge = wr([
2178
+ w(),
2179
+ ie(0, _("ICameraApi")),
2180
+ ie(1, _("ISceneApi")),
2181
+ ie(2, _("IRaycastApi")),
2182
+ ie(3, _("EditorStore"))
2183
+ ], Ge);
2184
+ var Ar = Object.getOwnPropertyDescriptor, Or = (e, t, s, r) => {
2185
+ for (var i = r > 1 ? void 0 : r ? Ar(t, s) : t, n = e.length - 1, o; n >= 0; n--)
2186
+ (o = e[n]) && (i = o(i) || i);
2187
+ return i;
2188
+ }, pt = (e, t) => (s, r) => t(s, r, e);
2189
+ let We = class {
2190
+ constructor(e, t) {
2191
+ this._api = e, this._store = t;
2192
+ }
2193
+ /** Режим, которым управляет хендлер, нужен только менеджеру */
2194
+ mode = P.Mesh;
2195
+ /** Фигура, на которую навелись в данный момент */
2196
+ _hoveredMesh = null;
2197
+ /** Фигура, которую выбрали в данный момент */
2198
+ _selectedMesh = null;
2199
+ // Цвета, необходимые для переключения
2200
+ /** Цвет ребер для фигуры, на которую навелись */
2201
+ _hoverColor = Me;
2202
+ /** Цвет ребер для выделенной фигуры */
2203
+ _selectColor = xe;
2204
+ /** Исходные цвета материалов линий для отката */
2205
+ _origLineColors = /* @__PURE__ */ new WeakMap();
2206
+ handle(e, t) {
2207
+ if (this._api.setRaycastMode(this.mode), t === F.Hover) {
2208
+ if (!e) {
2209
+ this._hoveredMesh && this._hoveredMesh !== this._selectedMesh && this._restoreEdgesColor(this._hoveredMesh), this._hoveredMesh = null;
2210
+ return;
2211
+ }
2212
+ const s = e.intersection.object;
2213
+ this._hoveredMesh !== s && (this._hoveredMesh && this._hoveredMesh !== this._selectedMesh && this._restoreEdgesColor(this._hoveredMesh), s !== this._selectedMesh && this._paintEdges(s, this._hoverColor), this._hoveredMesh = s);
2214
+ }
2215
+ if (t === F.Click) {
2216
+ if (!e) {
2217
+ this._selectedMesh && (this._restoreEdgesColor(this._selectedMesh), this._selectedMesh = null, this._store.setSelectedObject(null));
2218
+ return;
2219
+ }
2220
+ const s = e.intersection.object;
2221
+ this._selectedMesh && this._selectedMesh !== s && this._restoreEdgesColor(this._selectedMesh), this._paintEdges(s, this._selectColor), this._selectedMesh = s, this._store.setSelectedObject(s);
2222
+ }
2223
+ }
2224
+ rollback() {
2225
+ this._hoveredMesh && this._restoreEdgesColor(this._hoveredMesh), this._selectedMesh && this._restoreEdgesColor(this._selectedMesh), this._hoveredMesh = this._selectedMesh = null, this._store.setSelectedObject(null);
2226
+ }
2227
+ /** Освобождает ресурсы хендлера, удаляет слушатели и очищает внутренние данные. */
2228
+ dispose() {
2229
+ this.rollback();
2230
+ }
2231
+ /**
2232
+ * Перекрасить рёбра меша и запомнить оригинальный цвет (один раз на LineSegments).
2233
+ */
2234
+ _paintEdges(e, t) {
2235
+ e.children.forEach((s) => {
2236
+ const r = s;
2237
+ if (r.isLineSegments && r.material) {
2238
+ const i = r.material;
2239
+ this._origLineColors.has(r) || this._origLineColors.set(r, i.color.clone()), i.color.setHex(t), i.needsUpdate = !0;
2240
+ }
2241
+ });
2242
+ }
2243
+ /**
2244
+ * Восстановить исходный цвет рёбер меша из WeakMap.
2245
+ * Если исходный цвет не сохранён (на всякий случай) — ничего не меняем.
2246
+ */
2247
+ _restoreEdgesColor(e) {
2248
+ e.children.forEach((t) => {
2249
+ const s = t;
2250
+ if (s.isLineSegments && s.material) {
2251
+ const r = this._origLineColors.get(s);
2252
+ if (r) {
2253
+ const i = s.material;
2254
+ i.color.copy(r), i.needsUpdate = !0;
2255
+ }
2256
+ }
2257
+ });
2258
+ }
2259
+ };
2260
+ We = Or([
2261
+ w(),
2262
+ pt(0, _("IRaycastApi")),
2263
+ pt(1, _("EditorStore"))
2264
+ ], We);
2265
+ var Cr = Object.getOwnPropertyDescriptor, Ir = (e, t, s, r) => {
2266
+ for (var i = r > 1 ? void 0 : r ? Cr(t, s) : t, n = e.length - 1, o; n >= 0; n--)
2267
+ (o = e[n]) && (i = o(i) || i);
2268
+ return i;
2269
+ }, ne = (e, t) => (s, r) => t(s, r, e);
2270
+ let Ue = class {
2271
+ constructor(e, t, s, r) {
2272
+ this._cameraApi = e, this._sceneApi = t, this._raycastApi = s, this._store = r, this._cameraApi.enableCameraLayer($), this._hoverVertex = Y(this._makeOverlayVertex(this._hoverColor)), this._selectVertex = Y(this._makeOverlayVertex(this._selectColor)), this._sceneApi.addObject(this._hoverVertex, $), this._sceneApi.addObject(this._selectVertex, $);
1531
2273
  }
1532
2274
  /** Режим, которым управляет хендлер, нужен только менеджеру */
1533
- mode = y.Vertex;
2275
+ mode = P.Vertex;
1534
2276
  _hovered = null;
1535
2277
  _selected = null;
1536
2278
  /** Текущая наведённая вершина. */
@@ -1539,32 +2281,32 @@ let he = class {
1539
2281
  _selectVertex;
1540
2282
  // Цвета, необходимые для переключения
1541
2283
  /** Цвет ребра, на которое навелись */
1542
- _hoverColor = Z;
2284
+ _hoverColor = Me;
1543
2285
  /** Цвет выделенного ребра */
1544
- _selectColor = X;
1545
- handle(t, e) {
1546
- if (this._api.setRaycastMode(this.mode), e === C.Hover) {
1547
- if (!t) {
2286
+ _selectColor = xe;
2287
+ handle(e, t) {
2288
+ if (this._raycastApi.setRaycastMode(this.mode), t === F.Hover) {
2289
+ if (!e) {
1548
2290
  this._hoverVertex.visible = !1, this._hovered = null;
1549
2291
  return;
1550
2292
  }
1551
- const s = t.intersection.object;
2293
+ const s = e.intersection.object;
1552
2294
  if (!s?.isPoints) return;
1553
- const i = s, r = t.intersection.index ?? -1;
1554
- if (r < 0) return;
1555
- this._selected && this._same({ points: i, index: r }, this._selected) ? this._hoverVertex.visible = !1 : (this._writeWorldVertex(this._hoverVertex, i, r), this._hoverVertex.visible = !0);
2295
+ const r = s, i = e.intersection.index ?? -1;
2296
+ if (i < 0) return;
2297
+ this._selected && this._same({ points: r, index: i }, this._selected) ? this._hoverVertex.visible = !1 : (this._writeWorldVertex(this._hoverVertex, r, i), this._hoverVertex.visible = !0);
1556
2298
  return;
1557
2299
  }
1558
- if (e === C.Click) {
1559
- if (!t) {
2300
+ if (t === F.Click) {
2301
+ if (!e) {
1560
2302
  this._selectVertex.visible = !1, this._selected = null, this._store.setSelectedObject(null);
1561
2303
  return;
1562
2304
  }
1563
- const s = t.intersection.object;
2305
+ const s = e.intersection.object;
1564
2306
  if (!s?.isPoints) return;
1565
- const i = s, r = t.intersection.index ?? -1;
1566
- if (r < 0) return;
1567
- this._writeWorldVertex(this._selectVertex, i, r), this._centerVertexOnPoint(this._selectVertex, i, r), this._selectVertex.visible = !0, this._prepareVertexMetadata(i, r), this._store.setSelectedObject(this._selectVertex), this._selected = { points: i, index: r }, this._hovered && this._same(this._hovered, this._selected) && (this._hoverVertex.visible = !1);
2307
+ const r = s, i = e.intersection.index ?? -1;
2308
+ if (i < 0) return;
2309
+ this._writeWorldVertex(this._selectVertex, r, i), this._centerVertexOnPoint(this._selectVertex, r, i), this._selectVertex.visible = !0, this._prepareVertexMetadata(r, i), this._store.setSelectedObject(this._selectVertex), this._selected = { points: r, index: i }, this._hovered && this._same(this._hovered, this._selected) && (this._hoverVertex.visible = !1);
1568
2310
  return;
1569
2311
  }
1570
2312
  }
@@ -1572,83 +2314,85 @@ let he = class {
1572
2314
  this._hoverVertex.visible = !1, this._selectVertex.visible = !1, this._hovered = this._selected = null, this._store.setSelectedObject(null);
1573
2315
  }
1574
2316
  dispose() {
1575
- this.rollback(), this._api.removeObject(this._hoverVertex), this._api.removeObject(this._selectVertex), this._hoverVertex.geometry.dispose(), this._hoverVertex.material.dispose(), this._selectVertex.geometry.dispose(), this._selectVertex.material.dispose();
1576
- }
1577
- _makeOverlayVertex(t, e = lt) {
1578
- const s = new a.BufferGeometry();
1579
- s.setAttribute("position", new a.Float32BufferAttribute([0, 0, 0], 3));
1580
- const i = new a.PointsMaterial({
1581
- color: t,
1582
- size: e,
2317
+ this.rollback(), this._sceneApi.removeFromScene(this._hoverVertex), this._sceneApi.removeFromScene(this._selectVertex), this._hoverVertex.geometry.dispose(), this._hoverVertex.material.dispose(), this._selectVertex.geometry.dispose(), this._selectVertex.material.dispose();
2318
+ }
2319
+ _makeOverlayVertex(e, t = gs) {
2320
+ const s = new l.BufferGeometry();
2321
+ s.setAttribute("position", new l.Float32BufferAttribute([0, 0, 0], 3));
2322
+ const r = new l.PointsMaterial({
2323
+ color: e,
2324
+ size: t,
1583
2325
  sizeAttenuation: !1,
1584
2326
  depthTest: !1,
1585
2327
  depthWrite: !1,
1586
2328
  transparent: !0,
1587
2329
  opacity: 1
1588
- }), r = new a.Points(s, i);
1589
- return r.renderOrder = 1e3, r.raycast = () => {
1590
- }, r.layers.set(T), r.visible = !1, r;
2330
+ }), i = new l.Points(s, r);
2331
+ return i.renderOrder = 1e3, i.raycast = () => {
2332
+ }, i.layers.set($), i.visible = !1, i;
1591
2333
  }
1592
2334
  /** Локальную вершину points переводим в world и пишем в target (прокси-точку) */
1593
- _writeWorldVertex(t, e, s) {
1594
- const i = e.geometry.getAttribute("position"), r = new a.Vector3(
1595
- i.getX(s),
1596
- i.getY(s),
1597
- i.getZ(s)
1598
- ).applyMatrix4(e.matrixWorld), o = t.geometry.getAttribute("position");
1599
- o.setXYZ(0, r.x, r.y, r.z), o.needsUpdate = !0;
2335
+ _writeWorldVertex(e, t, s) {
2336
+ const r = t.geometry.getAttribute("position"), i = new l.Vector3(
2337
+ r.getX(s),
2338
+ r.getY(s),
2339
+ r.getZ(s)
2340
+ ).applyMatrix4(t.matrixWorld), n = e.geometry.getAttribute("position");
2341
+ n.setXYZ(0, i.x, i.y, i.z), n.needsUpdate = !0;
1600
2342
  }
1601
- _same(t, e) {
1602
- return !!t && !!e && t.points === e.points && t.index === e.index;
2343
+ _same(e, t) {
2344
+ return !!e && !!t && e.points === t.points && e.index === t.index;
1603
2345
  }
1604
2346
  /** Готовит метаданные для выбранной вершины и пишет их в _selectVertex.userData */
1605
- _prepareVertexMetadata(t, e) {
1606
- const s = Ye(t);
2347
+ _prepareVertexMetadata(e, t) {
2348
+ const s = Pt(e);
1607
2349
  if (!s) return;
1608
- const i = t.geometry.getAttribute("position"), r = new a.Vector3(
1609
- i.getX(e),
1610
- i.getY(e),
1611
- i.getZ(e)
1612
- ).applyMatrix4(t.matrixWorld), o = new a.Matrix4().copy(s.matrixWorld).invert(), n = r.clone().applyMatrix4(o), l = s.geometry.getAttribute("position"), c = 1e-6, d = c * c, g = new a.Vector3(), m = [];
1613
- for (let w = 0; w < l.count; w++)
1614
- g.fromBufferAttribute(l, w), g.distanceToSquared(n) < d && m.push(w);
1615
- const f = s.children.find((w) => w?.isLineSegments);
1616
- let u = [];
2350
+ const r = e.geometry.getAttribute("position"), i = new l.Vector3(
2351
+ r.getX(t),
2352
+ r.getY(t),
2353
+ r.getZ(t)
2354
+ ).applyMatrix4(e.matrixWorld), n = new l.Matrix4().copy(s.matrixWorld).invert(), o = i.clone().applyMatrix4(n), u = s.geometry.getAttribute("position"), d = 1e-6, m = d * d, p = new l.Vector3(), g = [];
2355
+ for (let v = 0; v < u.count; v++)
2356
+ p.fromBufferAttribute(u, v), p.distanceToSquared(o) < m && g.push(v);
2357
+ const f = s.children.find((v) => v?.isLineSegments);
2358
+ let h = [];
1617
2359
  if (f) {
1618
- const w = new a.Matrix4().copy(f.matrixWorld).invert(), S = r.clone().applyMatrix4(w), j = f.geometry.getAttribute("position"), R = new a.Vector3();
1619
- for (let V = 0; V < j.count; V++)
1620
- R.fromBufferAttribute(j, V), R.distanceToSquared(S) < d && u.push(V);
2360
+ const v = new l.Matrix4().copy(f.matrixWorld).invert(), y = i.clone().applyMatrix4(v), A = f.geometry.getAttribute("position"), S = new l.Vector3();
2361
+ for (let x = 0; x < A.count; x++)
2362
+ S.fromBufferAttribute(A, x), S.distanceToSquared(y) < m && h.push(x);
1621
2363
  }
1622
2364
  this._selectVertex.userData.vertexInfo = {
1623
- points: t,
1624
- index: e,
2365
+ points: e,
2366
+ index: t,
1625
2367
  mesh: s,
1626
- vertexIndices: m,
2368
+ vertexIndices: g,
1627
2369
  lines: f ?? null,
1628
- edgeVertexIndices: u
2370
+ edgeVertexIndices: h
1629
2371
  };
1630
2372
  }
1631
2373
  /** Центрует прокси-вершину на выбранной точке */
1632
- _centerVertexOnPoint(t, e, s) {
1633
- const i = e.geometry.getAttribute("position"), r = new a.Vector3(
1634
- i.getX(s),
1635
- i.getY(s),
1636
- i.getZ(s)
1637
- ).applyMatrix4(e.matrixWorld);
1638
- t.position.copy(r);
1639
- const o = t.geometry;
1640
- let n = o.getAttribute("position");
1641
- (!n || n.count < 1) && (o.setAttribute("position", new a.BufferAttribute(new Float32Array(3), 3)), n = o.getAttribute("position")), n.setXYZ(0, 0, 0, 0), n.needsUpdate = !0, t.quaternion.identity(), t.scale.set(1, 1, 1), t.updateMatrixWorld(!0);
2374
+ _centerVertexOnPoint(e, t, s) {
2375
+ const r = t.geometry.getAttribute("position"), i = new l.Vector3(
2376
+ r.getX(s),
2377
+ r.getY(s),
2378
+ r.getZ(s)
2379
+ ).applyMatrix4(t.matrixWorld);
2380
+ e.position.copy(i);
2381
+ const n = e.geometry;
2382
+ let o = n.getAttribute("position");
2383
+ (!o || o.count < 1) && (n.setAttribute("position", new l.BufferAttribute(new Float32Array(3), 3)), o = n.getAttribute("position")), o.setXYZ(0, 0, 0, 0), o.needsUpdate = !0, e.quaternion.identity(), e.scale.set(1, 1, 1), e.updateMatrixWorld(!0);
1642
2384
  }
1643
2385
  };
1644
- he = es([
1645
- M(),
1646
- je(0, _("RendererApi")),
1647
- je(1, _("IEditorStore"))
1648
- ], he);
1649
- class ve {
1650
- constructor(e, s) {
1651
- this.api = e, this.store = s, this._unsubscribeTransform = this.api.onTransformChange(() => {
2386
+ Ue = Ir([
2387
+ w(),
2388
+ ne(0, _("ICameraApi")),
2389
+ ne(1, _("ISceneApi")),
2390
+ ne(2, _("IRaycastApi")),
2391
+ ne(3, _("EditorStore"))
2392
+ ], Ue);
2393
+ class tt {
2394
+ constructor(t, s) {
2395
+ this.api = t, this.store = s, this._unsubscribeTransform = this.api.onTransformChange(() => {
1652
2396
  this.store.getSelectedObject() && this.store.notifySelectedTransformChange?.();
1653
2397
  });
1654
2398
  }
@@ -1657,8 +2401,8 @@ class ve {
1657
2401
  * Обновляет состояние инструмента под текущее выделение.
1658
2402
  */
1659
2403
  handle() {
1660
- const e = this.store.getSelectedObject();
1661
- this.api.setMode(this.mode), e ? this.api.attach(e) : this.api.detach();
2404
+ const t = this.store.getSelectedObject();
2405
+ this.api.setTransformMode(this.mode), t ? this.api.attachTransform(t) : this.api.detachTransform();
1662
2406
  }
1663
2407
  /**
1664
2408
  * Откатывает локальное состояние инструмента при смене инструмента.
@@ -1666,220 +2410,87 @@ class ve {
1666
2410
  * Вызывается менеджером перед активацией другого хендлера.
1667
2411
  */
1668
2412
  rollback() {
1669
- this.api.detach();
2413
+ this.api.detachTransform();
1670
2414
  }
1671
2415
  /** Освобождение ресурсов хендлера. */
1672
2416
  dispose() {
1673
2417
  this.rollback(), this._unsubscribeTransform && this._unsubscribeTransform();
1674
2418
  }
1675
2419
  }
1676
- var ts = Object.getOwnPropertyDescriptor, ss = (t, e, s, i) => {
1677
- for (var r = i > 1 ? void 0 : i ? ts(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1678
- (n = t[o]) && (r = n(r) || r);
1679
- return r;
1680
- }, Re = (t, e) => (s, i) => e(s, i, t);
1681
- let le = class extends ve {
2420
+ var Pr = Object.getOwnPropertyDescriptor, Lr = (e, t, s, r) => {
2421
+ for (var i = r > 1 ? void 0 : r ? Pr(t, s) : t, n = e.length - 1, o; n >= 0; n--)
2422
+ (o = e[n]) && (i = o(i) || i);
2423
+ return i;
2424
+ }, mt = (e, t) => (s, r) => t(s, r, e);
2425
+ let Ne = class extends tt {
1682
2426
  /** Инструмент, которым управляет хендлер, нужен только менеджеру */
1683
- mode = F.Translate;
1684
- constructor(t, e) {
1685
- super(t, e);
2427
+ mode = U.Rotate;
2428
+ constructor(e, t) {
2429
+ super(e, t);
1686
2430
  }
1687
2431
  };
1688
- le = ss([
1689
- M(),
1690
- Re(0, _("RendererApi")),
1691
- Re(1, _("IEditorStore"))
1692
- ], le);
1693
- var is = Object.getOwnPropertyDescriptor, rs = (t, e, s, i) => {
1694
- for (var r = i > 1 ? void 0 : i ? is(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1695
- (n = t[o]) && (r = n(r) || r);
1696
- return r;
1697
- }, Ve = (t, e) => (s, i) => e(s, i, t);
1698
- let ce = class extends ve {
2432
+ Ne = Lr([
2433
+ w(),
2434
+ mt(0, _("ITransformApi")),
2435
+ mt(1, _("EditorStore"))
2436
+ ], Ne);
2437
+ var Er = Object.getOwnPropertyDescriptor, Tr = (e, t, s, r) => {
2438
+ for (var i = r > 1 ? void 0 : r ? Er(t, s) : t, n = e.length - 1, o; n >= 0; n--)
2439
+ (o = e[n]) && (i = o(i) || i);
2440
+ return i;
2441
+ }, gt = (e, t) => (s, r) => t(s, r, e);
2442
+ let Xe = class extends tt {
1699
2443
  /** Инструмент, которым управляет хендлер, нужен только менеджеру */
1700
- mode = F.Scale;
1701
- constructor(t, e) {
1702
- super(t, e);
2444
+ mode = U.Scale;
2445
+ constructor(e, t) {
2446
+ super(e, t);
1703
2447
  }
1704
2448
  };
1705
- ce = rs([
1706
- M(),
1707
- Ve(0, _("RendererApi")),
1708
- Ve(1, _("IEditorStore"))
1709
- ], ce);
1710
- var os = Object.getOwnPropertyDescriptor, ns = (t, e, s, i) => {
1711
- for (var r = i > 1 ? void 0 : i ? os(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1712
- (n = t[o]) && (r = n(r) || r);
1713
- return r;
1714
- }, ke = (t, e) => (s, i) => e(s, i, t);
1715
- let de = class extends ve {
2449
+ Xe = Tr([
2450
+ w(),
2451
+ gt(0, _("ITransformApi")),
2452
+ gt(1, _("EditorStore"))
2453
+ ], Xe);
2454
+ var Vr = Object.getOwnPropertyDescriptor, Dr = (e, t, s, r) => {
2455
+ for (var i = r > 1 ? void 0 : r ? Vr(t, s) : t, n = e.length - 1, o; n >= 0; n--)
2456
+ (o = e[n]) && (i = o(i) || i);
2457
+ return i;
2458
+ }, ft = (e, t) => (s, r) => t(s, r, e);
2459
+ let Ye = class extends tt {
1716
2460
  /** Инструмент, которым управляет хендлер, нужен только менеджеру */
1717
- mode = F.Rotate;
1718
- constructor(t, e) {
1719
- super(t, e);
1720
- }
1721
- };
1722
- de = ns([
1723
- M(),
1724
- ke(0, _("RendererApi")),
1725
- ke(1, _("IEditorStore"))
1726
- ], de);
1727
- var as = Object.getOwnPropertyDescriptor, hs = (t, e, s, i) => {
1728
- for (var r = i > 1 ? void 0 : i ? as(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1729
- (n = t[o]) && (r = n(r) || r);
1730
- return r;
1731
- }, He = (t, e) => (s, i) => e(s, i, t);
1732
- let _e = class {
1733
- constructor(t, e) {
1734
- this._api = t, this._store = e, this._api.enableCameraLayer(T), this._hoverLine = this._makeOverlayLine(this._hoverColor), this._selectLine = this._makeOverlayLine(this._selectColor), this._api.addObject(this._hoverLine, T), this._api.addObject(this._selectLine, T);
1735
- }
1736
- /** Режим, которым управляет хендлер, нужен только менеджеру */
1737
- mode = y.Edge;
1738
- /** Текущее наведённое ребро. */
1739
- _hoverLine;
1740
- /** Текущее выбранное ребро. */
1741
- _selectLine;
1742
- /** Текущее наведённое ребро из массива `LineSegments` модели. */
1743
- _hovered = null;
1744
- /** Текущее выбранное ребро из массива `LineSegments` модели. */
1745
- _selected = null;
1746
- // Цвета, необходимые для переключения
1747
- /** Цвет ребра, на которое навелись */
1748
- _hoverColor = Z;
1749
- /** Цвет выделенного ребра */
1750
- _selectColor = X;
1751
- /** Обработка текущего режима выборки. */
1752
- handle(t, e) {
1753
- if (this._api.setRaycastMode(this.mode), e === C.Hover) {
1754
- if (!t) {
1755
- this._hoverLine.visible = !1, this._hovered = null;
1756
- return;
1757
- }
1758
- const s = t.intersection.object;
1759
- if (!s?.isLineSegments) return;
1760
- const i = s, r = Math.floor((t.intersection.index ?? -1) / 2);
1761
- if (r < 0) return;
1762
- this._selected && this._same({ lines: i, seg: r }, this._selected) ? this._hoverLine.visible = !1 : (this._writeWorldSegment(this._hoverLine, i, r), this._hoverLine.visible = !0), this._hovered = { lines: i, seg: r };
1763
- return;
1764
- }
1765
- if (e === C.Click) {
1766
- if (!t) {
1767
- this._selectLine.visible = !1, this._selected = null, this._store.setSelectedObject(null);
1768
- return;
1769
- }
1770
- const s = t.intersection.object;
1771
- if (!s?.isLineSegments) return;
1772
- const i = s, r = Math.floor((t.intersection.index ?? -1) / 2);
1773
- if (r < 0) return;
1774
- this._writeWorldSegment(this._selectLine, i, r), this._centerAndOrientLineOnSegment(this._selectLine, i, r), this._selectLine.visible = !0, this._prepareEdgeMetadata(i, r), this._store.setSelectedObject(this._selectLine), this._selected = { lines: i, seg: r }, this._hovered && this._same(this._hovered, this._selected) && (this._hoverLine.visible = !1);
1775
- }
1776
- }
1777
- /** Откат текущего режима выборки */
1778
- rollback() {
1779
- this._hoverLine.visible = !1, this._selectLine.visible = !1, this._hovered = this._selected = null, this._store.setSelectedObject(null);
1780
- }
1781
- /** Освобождает ресурсы хендлера, удаляет слушатели и очищает внутренние данные. */
1782
- dispose() {
1783
- this.rollback(), this._api.removeObject(this._hoverLine), this._api.removeObject(this._selectLine), this._hoverLine.geometry.dispose(), this._hoverLine.material.dispose(), this._selectLine.geometry.dispose(), this._selectLine.material.dispose();
1784
- }
1785
- /** Инициализация буферных линий для режима (hover и click).
1786
- * На весь режим будет использовано 2 глобальных линии на сцене,
1787
- * использоваться они будут только для обозначения геометрии ребер конкретной фигуры.
1788
- */
1789
- _makeOverlayLine(t) {
1790
- const e = new a.BufferGeometry();
1791
- e.setAttribute("position", new a.Float32BufferAttribute(6, 3));
1792
- const s = new a.LineBasicMaterial({
1793
- color: t,
1794
- depthTest: !1,
1795
- depthWrite: !1,
1796
- transparent: !0,
1797
- opacity: 1
1798
- }), i = new a.Line(e, s);
1799
- return i.renderOrder = 1e3, i.raycast = () => {
1800
- }, i.layers.set(T), i.visible = !1, i;
1801
- }
1802
- /** Локальные точки сегмента переводим в target (который висит на сцене) */
1803
- _writeWorldSegment(t, e, s) {
1804
- const i = e.geometry.getAttribute("position"), r = s * 2, o = r + 1, n = new a.Vector3(i.getX(r), i.getY(r), i.getZ(r)).applyMatrix4(
1805
- e.matrixWorld
1806
- ), h = new a.Vector3(i.getX(o), i.getY(o), i.getZ(o)).applyMatrix4(
1807
- e.matrixWorld
1808
- ), l = t.geometry.getAttribute("position");
1809
- l.setXYZ(0, n.x, n.y, n.z), l.setXYZ(1, h.x, h.y, h.z), l.needsUpdate = !0;
1810
- }
1811
- _same(t, e) {
1812
- return !!t && !!e && t.lines === e.lines && t.seg === e.seg;
1813
- }
1814
- /** Центрует `THREE.Line` на сегменте и ориентирует её вдоль ребра */
1815
- _centerAndOrientLineOnSegment(t, e, s) {
1816
- const i = e.geometry.getAttribute("position"), r = s * 2, o = r + 1, n = new a.Vector3(i.getX(r), i.getY(r), i.getZ(r)).applyMatrix4(
1817
- e.matrixWorld
1818
- ), h = new a.Vector3(i.getX(o), i.getY(o), i.getZ(o)).applyMatrix4(
1819
- e.matrixWorld
1820
- ), l = new a.Vector3().subVectors(h, n), c = l.length();
1821
- if (!isFinite(c) || c === 0) return;
1822
- const d = new a.Vector3().addVectors(n, h).multiplyScalar(0.5);
1823
- t.position.copy(d);
1824
- const g = t.geometry;
1825
- let m = g.getAttribute("position");
1826
- (!m || m.count < 2) && (g.setAttribute("position", new a.BufferAttribute(new Float32Array(6), 3)), m = g.getAttribute("position")), m.setXYZ(0, -c / 2, 0, 0), m.setXYZ(1, c / 2, 0, 0), m.needsUpdate = !0, l.normalize();
1827
- const f = new a.Quaternion().setFromUnitVectors(new a.Vector3(1, 0, 0), l);
1828
- t.quaternion.copy(f), t.updateMatrixWorld(!0);
1829
- }
1830
- /** Запись метаданных выбранного ребра для использования инструментов */
1831
- _prepareEdgeMetadata(t, e) {
1832
- const s = Ye(t);
1833
- if (!s) return;
1834
- const i = t.geometry.getAttribute("position"), r = e * 2, o = r + 1, n = new a.Vector3(i.getX(r), i.getY(r), i.getZ(r)).applyMatrix4(
1835
- t.matrixWorld
1836
- ), h = new a.Vector3(i.getX(o), i.getY(o), i.getZ(o)).applyMatrix4(
1837
- t.matrixWorld
1838
- ), l = new a.Matrix4().copy(s.matrixWorld).invert(), c = n.clone().applyMatrix4(l), d = h.clone().applyMatrix4(l), m = s.geometry.getAttribute("position"), f = new a.Vector3(), u = 1e-6, w = [], S = [];
1839
- for (let x = 0; x < m.count; x++)
1840
- f.fromBufferAttribute(m, x), f.distanceToSquared(c) < u * u ? w.push(x) : f.distanceToSquared(d) < u * u && S.push(x);
1841
- const j = new a.Matrix4().copy(t.matrixWorld).invert(), R = n.clone().applyMatrix4(j), V = h.clone().applyMatrix4(j), E = t.geometry.getAttribute("position"), O = new a.Vector3(), A = [], k = [];
1842
- for (let x = 0; x < E.count; x++)
1843
- O.fromBufferAttribute(E, x), O.distanceToSquared(R) < u * u ? A.push(x) : O.distanceToSquared(V) < u * u && k.push(x);
1844
- this._selectLine.userData.edgeInfo = {
1845
- lines: t,
1846
- seg: e,
1847
- mesh: s,
1848
- aIndices: w,
1849
- bIndices: S,
1850
- aEdgeIndices: A,
1851
- bEdgeIndices: k
1852
- };
2461
+ mode = U.Translate;
2462
+ constructor(e, t) {
2463
+ super(e, t);
1853
2464
  }
1854
2465
  };
1855
- _e = hs([
1856
- M(),
1857
- He(0, _("RendererApi")),
1858
- He(1, _("IEditorStore"))
1859
- ], _e);
1860
- var ls = Object.getOwnPropertyDescriptor, cs = (t, e, s, i) => {
1861
- for (var r = i > 1 ? void 0 : i ? ls(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1862
- (n = t[o]) && (r = n(r) || r);
1863
- return r;
1864
- }, ds = (t, e) => (s, i) => e(s, i, t);
1865
- let ue = class {
1866
- constructor(t) {
1867
- this._api = t;
2466
+ Ye = Dr([
2467
+ w(),
2468
+ ft(0, _("ITransformApi")),
2469
+ ft(1, _("EditorStore"))
2470
+ ], Ye);
2471
+ var jr = Object.getOwnPropertyDescriptor, $r = (e, t, s, r) => {
2472
+ for (var i = r > 1 ? void 0 : r ? jr(t, s) : t, n = e.length - 1, o; n >= 0; n--)
2473
+ (o = e[n]) && (i = o(i) || i);
2474
+ return i;
2475
+ }, Rr = (e, t) => (s, r) => t(s, r, e);
2476
+ let ge = class {
2477
+ constructor(e) {
2478
+ this._api = e;
1868
2479
  }
1869
2480
  /** Режим редактирования сцены */
1870
- mode = U.AddFigure;
2481
+ mode = T.AddFigure;
1871
2482
  /** Последняя добавленная фигура, нужно для отката через `ctrl + z`. */
1872
2483
  _lastAddedMesh = null;
1873
2484
  /** Добавление базовых фигур на сцену, которые приписаны в `FigureType`. */
1874
- handle(t) {
1875
- const e = ht[t](), s = e.getAttribute("position");
1876
- s && s.setUsage && s.setUsage(a.DynamicDrawUsage);
1877
- const i = new a.Mesh(e, ze);
1878
- i.layers.enable(J);
1879
- const r = Ue(i.geometry);
1880
- i.add(r);
1881
- const o = $e(i.geometry);
1882
- i.add(o), this._api.addMesh(i), this._lastAddedMesh = i;
2485
+ handle(e) {
2486
+ const t = ms[e](), s = t.getAttribute("position");
2487
+ s && s.setUsage && s.setUsage(l.DynamicDrawUsage);
2488
+ const r = new l.Mesh(t, Ot.clone());
2489
+ r.layers.enable(z);
2490
+ const i = t.index ? t.toNonIndexed() : t, n = N(Et(i));
2491
+ n.layers.enable(z), r.add(n);
2492
+ const o = N(Lt(i));
2493
+ o.layers.enable(z), r.add(o), this._api.addMesh(r), this._lastAddedMesh = r;
1883
2494
  }
1884
2495
  /** Срабатывает только на `ctrl + z`. */
1885
2496
  rollback() {
@@ -1890,26 +2501,26 @@ let ue = class {
1890
2501
  this._lastAddedMesh = null;
1891
2502
  }
1892
2503
  };
1893
- ue = cs([
1894
- M(),
1895
- ds(0, _("RendererApi"))
1896
- ], ue);
1897
- var _s = Object.getOwnPropertyDescriptor, us = (t, e, s, i) => {
1898
- for (var r = i > 1 ? void 0 : i ? _s(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1899
- (n = t[o]) && (r = n(r) || r);
1900
- return r;
1901
- }, Fe = (t, e) => (s, i) => e(s, i, t);
1902
- let pe = class {
1903
- constructor(t, e) {
1904
- this._api = t, this._store = e;
2504
+ ge = $r([
2505
+ w(),
2506
+ Rr(0, _("IMeshApi"))
2507
+ ], ge);
2508
+ var Fr = Object.getOwnPropertyDescriptor, Hr = (e, t, s, r) => {
2509
+ for (var i = r > 1 ? void 0 : r ? Fr(t, s) : t, n = e.length - 1, o; n >= 0; n--)
2510
+ (o = e[n]) && (i = o(i) || i);
2511
+ return i;
2512
+ }, vt = (e, t) => (s, r) => t(s, r, e);
2513
+ let qe = class {
2514
+ constructor(e, t) {
2515
+ this._api = e, this._store = t;
1905
2516
  }
1906
2517
  /** Режим редактирования сцены */
1907
- mode = U.DeleteFigure;
2518
+ mode = T.DeleteFigure;
1908
2519
  /** Последняя удаленная фигура, сохраняем для отката через `ctrl + z` */
1909
2520
  _lastDeletedMesh = null;
1910
2521
  handle() {
1911
- const t = this._store.getSelectedObject();
1912
- bt(t) && (this._api.removeMesh(t), this._store.setSelectedObject(null), this._lastDeletedMesh = t);
2522
+ const e = this._store.getSelectedObject();
2523
+ et(e) && !Vt(e) && (this._api.removeMesh(e), this._store.setSelectedObject(null), this._lastDeletedMesh = e);
1913
2524
  }
1914
2525
  /** Срабатывает только на `ctrl + z`. */
1915
2526
  rollback() {
@@ -1920,147 +2531,311 @@ let pe = class {
1920
2531
  this._lastDeletedMesh = null;
1921
2532
  }
1922
2533
  };
1923
- pe = us([
1924
- M(),
1925
- Fe(0, _("RendererApi")),
1926
- Fe(1, _("IEditorStore"))
1927
- ], pe);
1928
- var ps = Object.getOwnPropertyDescriptor, ms = (t, e, s, i) => {
1929
- for (var r = i > 1 ? void 0 : i ? ps(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1930
- (n = t[o]) && (r = n(r) || r);
1931
- return r;
1932
- }, fs = (t, e) => (s, i) => e(s, i, t);
1933
- let me = class {
1934
- constructor(t) {
1935
- this._renderer = t;
1936
- }
1937
- /** @inheritdoc */
1938
- addMesh(t) {
1939
- this._renderer.addMesh(t);
2534
+ qe = Hr([
2535
+ w(),
2536
+ vt(0, _("IMeshApi")),
2537
+ vt(1, _("EditorStore"))
2538
+ ], qe);
2539
+ class Br {
2540
+ /**
2541
+ * Parses the given 3D object and generates the OBJ output.
2542
+ *
2543
+ * If the 3D object is composed of multiple children and geometry, they are merged into a single mesh in the file.
2544
+ *
2545
+ * @param {Object3D} object - The 3D object to export.
2546
+ * @return {string} The exported OBJ.
2547
+ */
2548
+ parse(t) {
2549
+ let s = "", r = 0, i = 0, n = 0;
2550
+ const o = new W(), c = new St(), u = new W(), d = new qt(), m = [];
2551
+ function p(h) {
2552
+ let v = 0, y = 0, A = 0;
2553
+ const S = h.geometry, x = new Zt(), b = S.getAttribute("position"), C = S.getAttribute("normal"), M = S.getAttribute("uv"), I = S.getIndex();
2554
+ if (s += "o " + h.name + `
2555
+ `, h.material && h.material.name && (s += "usemtl " + h.material.name + `
2556
+ `), b !== void 0)
2557
+ for (let O = 0, V = b.count; O < V; O++, v++)
2558
+ o.fromBufferAttribute(b, O), o.applyMatrix4(h.matrixWorld), s += "v " + o.x + " " + o.y + " " + o.z + `
2559
+ `;
2560
+ if (M !== void 0)
2561
+ for (let O = 0, V = M.count; O < V; O++, A++)
2562
+ d.fromBufferAttribute(M, O), s += "vt " + d.x + " " + d.y + `
2563
+ `;
2564
+ if (C !== void 0) {
2565
+ x.getNormalMatrix(h.matrixWorld);
2566
+ for (let O = 0, V = C.count; O < V; O++, y++)
2567
+ u.fromBufferAttribute(C, O), u.applyMatrix3(x).normalize(), s += "vn " + u.x + " " + u.y + " " + u.z + `
2568
+ `;
2569
+ }
2570
+ if (I !== null)
2571
+ for (let O = 0, V = I.count; O < V; O += 3) {
2572
+ for (let D = 0; D < 3; D++) {
2573
+ const H = I.getX(O + D) + 1;
2574
+ m[D] = r + H + (C || M ? "/" + (M ? i + H : "") + (C ? "/" + (n + H) : "") : "");
2575
+ }
2576
+ s += "f " + m.join(" ") + `
2577
+ `;
2578
+ }
2579
+ else
2580
+ for (let O = 0, V = b.count; O < V; O += 3) {
2581
+ for (let D = 0; D < 3; D++) {
2582
+ const H = O + D + 1;
2583
+ m[D] = r + H + (C || M ? "/" + (M ? i + H : "") + (C ? "/" + (n + H) : "") : "");
2584
+ }
2585
+ s += "f " + m.join(" ") + `
2586
+ `;
2587
+ }
2588
+ r += v, i += A, n += y;
2589
+ }
2590
+ function g(h) {
2591
+ let v = 0;
2592
+ const y = h.geometry, A = h.type, S = y.getAttribute("position");
2593
+ if (s += "o " + h.name + `
2594
+ `, S !== void 0)
2595
+ for (let x = 0, b = S.count; x < b; x++, v++)
2596
+ o.fromBufferAttribute(S, x), o.applyMatrix4(h.matrixWorld), s += "v " + o.x + " " + o.y + " " + o.z + `
2597
+ `;
2598
+ if (A === "Line") {
2599
+ s += "l ";
2600
+ for (let x = 1, b = S.count; x <= b; x++)
2601
+ s += r + x + " ";
2602
+ s += `
2603
+ `;
2604
+ }
2605
+ if (A === "LineSegments")
2606
+ for (let x = 1, b = x + 1, C = S.count; x < C; x += 2, b = x + 1)
2607
+ s += "l " + (r + x) + " " + (r + b) + `
2608
+ `;
2609
+ r += v;
2610
+ }
2611
+ function f(h) {
2612
+ let v = 0;
2613
+ const y = h.geometry, A = y.getAttribute("position"), S = y.getAttribute("color");
2614
+ if (s += "o " + h.name + `
2615
+ `, A !== void 0) {
2616
+ for (let x = 0, b = A.count; x < b; x++, v++)
2617
+ o.fromBufferAttribute(A, x), o.applyMatrix4(h.matrixWorld), s += "v " + o.x + " " + o.y + " " + o.z, S !== void 0 && (c.fromBufferAttribute(S, x), Kt.workingToColorSpace(c, wt), s += " " + c.r + " " + c.g + " " + c.b), s += `
2618
+ `;
2619
+ s += "p ";
2620
+ for (let x = 1, b = A.count; x <= b; x++)
2621
+ s += r + x + " ";
2622
+ s += `
2623
+ `;
2624
+ }
2625
+ r += v;
2626
+ }
2627
+ return t.traverse(function(h) {
2628
+ h.isMesh === !0 && p(h), h.isLine === !0 && g(h), h.isPoints === !0 && f(h);
2629
+ }), s;
1940
2630
  }
1941
- /** @inheritdoc */
1942
- addMeshes(t) {
1943
- for (const e of t)
1944
- this._renderer.addMesh(e);
2631
+ }
2632
+ var kr = Object.getOwnPropertyDescriptor, zr = (e, t, s, r) => {
2633
+ for (var i = r > 1 ? void 0 : r ? kr(t, s) : t, n = e.length - 1, o; n >= 0; n--)
2634
+ (o = e[n]) && (i = o(i) || i);
2635
+ return i;
2636
+ }, yt = (e, t) => (s, r) => t(s, r, e);
2637
+ let fe = class {
2638
+ constructor(e, t) {
2639
+ this._api = e, this._exportStore = t;
1945
2640
  }
1946
- /** @inheritdoc */
1947
- removeMesh(t) {
1948
- this._renderer.removeMesh(t);
2641
+ /** Режим редактирования сцены */
2642
+ mode = T.Export;
2643
+ /** Экспорт всей сцены в ExportStore для последующей загрузки в виде файла. */
2644
+ handle() {
2645
+ const e = this._api.getScene(), t = xs(e), r = new Br().parse(t), i = Date.now();
2646
+ this._exportStore.setResult({
2647
+ format: "obj",
2648
+ filename: `scene-${i}.obj`,
2649
+ mimeType: "text/plain;charset=utf-8",
2650
+ content: r,
2651
+ createdAt: i
2652
+ });
1949
2653
  }
1950
- /** @inheritdoc */
1951
- removeMeshes(t) {
1952
- for (const e of t)
1953
- this._renderer.removeMesh(e);
2654
+ rollback() {
1954
2655
  }
1955
- /** @inheritdoc */
1956
- getMeshes() {
1957
- return this._renderer.getMeshes();
2656
+ /** Освобождает ресурсы хендлера. */
2657
+ dispose() {
2658
+ this._exportStore.clearResult();
1958
2659
  }
1959
- /** @inheritdoc */
1960
- setMode(t) {
1961
- this._renderer.setTransformControlsMode(t);
2660
+ };
2661
+ fe = zr([
2662
+ w(),
2663
+ yt(0, _("ISceneApi")),
2664
+ yt(1, _("ExportStore"))
2665
+ ], fe);
2666
+ var Gr = Object.defineProperty, Wr = Object.getOwnPropertyDescriptor, Ft = (e, t, s, r) => {
2667
+ for (var i = r > 1 ? void 0 : r ? Wr(t, s) : t, n = e.length - 1, o; n >= 0; n--)
2668
+ (o = e[n]) && (i = (r ? o(t, s, i) : o(i)) || i);
2669
+ return r && i && Gr(t, s, i), i;
2670
+ }, bt = (e, t) => (s, r) => t(s, r, e);
2671
+ let J = class {
2672
+ constructor(e, t) {
2673
+ this._api = e, this._validator = t;
1962
2674
  }
1963
- /** @inheritdoc */
1964
- attach(t) {
1965
- this._renderer.attachTransformControls(t);
2675
+ /** Режим редактирования сцены */
2676
+ mode = T.Load;
2677
+ handle(e) {
2678
+ const t = [...this._api.getMeshes()];
2679
+ this._api.removeMeshes(t);
2680
+ const s = Dt(e);
2681
+ this._api.addMeshes(s);
1966
2682
  }
1967
- /** @inheritdoc */
1968
- detach() {
1969
- this._renderer.detachTransformControls();
2683
+ rollback() {
1970
2684
  }
1971
- /** @inheritdoc */
1972
- setRaycastMode(t) {
1973
- this._renderer.setRaycastMode(t);
2685
+ /** Освобождает ресурсы хендлера. */
2686
+ dispose() {
1974
2687
  }
1975
- /** @inheritdoc */
1976
- addObject(t, e) {
1977
- this._renderer.addObject(t, e);
2688
+ };
2689
+ Ft([
2690
+ $t((e) => e._validator)
2691
+ ], J.prototype, "handle", 1);
2692
+ J = Ft([
2693
+ w(),
2694
+ bt(0, _("IMeshApi")),
2695
+ bt(1, _("ObjValidator"))
2696
+ ], J);
2697
+ var Ur = Object.defineProperty, Nr = Object.getOwnPropertyDescriptor, Ht = (e, t, s, r) => {
2698
+ for (var i = r > 1 ? void 0 : r ? Nr(t, s) : t, n = e.length - 1, o; n >= 0; n--)
2699
+ (o = e[n]) && (i = (r ? o(t, s, i) : o(i)) || i);
2700
+ return r && i && Ur(t, s, i), i;
2701
+ }, Mt = (e, t) => (s, r) => t(s, r, e);
2702
+ let Q = class {
2703
+ constructor(e, t) {
2704
+ this._api = e, this._validator = t;
1978
2705
  }
1979
- /** @inheritdoc */
1980
- removeObject(t) {
1981
- this._renderer.removeObject(t);
2706
+ /** Режим редактирования сцены */
2707
+ mode = T.LoadFigure;
2708
+ handle(e) {
2709
+ const t = Dt(e);
2710
+ this._api.addMeshes(t);
1982
2711
  }
1983
- /** @inheritdoc */
1984
- enableCameraLayer(t) {
1985
- this._renderer.enableCameraLayer(t);
2712
+ rollback() {
1986
2713
  }
1987
- /** @inheritdoc */
1988
- onTransformChange(t) {
1989
- return this._renderer.onTransformChange(t);
2714
+ /** Освобождает ресурсы хендлера. */
2715
+ dispose() {
1990
2716
  }
1991
2717
  };
1992
- me = ms([
1993
- M(),
1994
- fs(0, _("EditorRenderer"))
1995
- ], me);
1996
- var gs = Object.getOwnPropertyDescriptor, bs = (t, e, s, i) => {
1997
- for (var r = i > 1 ? void 0 : i ? gs(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1998
- (n = t[o]) && (r = n(r) || r);
1999
- return r;
2000
- }, W = (t, e) => (s, i) => e(s, i, t);
2001
- let fe = class {
2002
- constructor(t, e, s, i, r, o) {
2003
- this._displayManager = t, this._selectManager = e, this._toolManager = s, this._sceneManager = i, this._renderer = r, this._store = o, this.setSelectMode(y.Mesh), this.setToolMode(F.Translate);
2718
+ Ht([
2719
+ $t((e) => e._validator)
2720
+ ], Q.prototype, "handle", 1);
2721
+ Q = Ht([
2722
+ w(),
2723
+ Mt(0, _("IMeshApi")),
2724
+ Mt(1, _("ObjValidator"))
2725
+ ], Q);
2726
+ var Xr = Object.getOwnPropertyDescriptor, Yr = (e, t, s, r) => {
2727
+ for (var i = r > 1 ? void 0 : r ? Xr(t, s) : t, n = e.length - 1, o; n >= 0; n--)
2728
+ (o = e[n]) && (i = o(i) || i);
2729
+ return i;
2730
+ }, Z = (e, t) => (s, r) => t(s, r, e);
2731
+ let Ze = class {
2732
+ constructor(e, t, s, r, i) {
2733
+ this._renderer = e, this._mediator = t, this._store = s, this._exportStore = r, this._controller = i, this.setSelectMode(P.Mesh), this.setToolMode(U.Translate);
2734
+ }
2735
+ setDisplayMode(e) {
2736
+ return this._mediator.send({
2737
+ type: E.Display,
2738
+ payload: [e]
2739
+ });
2004
2740
  }
2005
- setDisplayMode(t) {
2006
- this._displayManager.manage(t);
2741
+ setSelectMode(e) {
2742
+ return this._mediator.send({
2743
+ type: E.Select,
2744
+ payload: [e]
2745
+ });
2746
+ }
2747
+ setToolMode(e) {
2748
+ return this._mediator.send({
2749
+ type: E.Tool,
2750
+ payload: [e]
2751
+ });
2752
+ }
2753
+ addFigure(e) {
2754
+ return this._mediator.send({
2755
+ type: E.Scene,
2756
+ payload: [T.AddFigure, e]
2757
+ });
2758
+ }
2759
+ deleteFigure() {
2760
+ return this._mediator.send({
2761
+ type: E.Scene,
2762
+ payload: [T.DeleteFigure]
2763
+ });
2007
2764
  }
2008
- setSceneMode(t) {
2009
- this._sceneManager.manage(t);
2765
+ loadFigure(e) {
2766
+ return this._mediator.send({
2767
+ type: E.Scene,
2768
+ payload: [T.LoadFigure, e]
2769
+ });
2010
2770
  }
2011
- setSelectMode(t) {
2012
- this._selectManager.manage(t);
2771
+ loadScene(e) {
2772
+ return this._mediator.send({
2773
+ type: E.Scene,
2774
+ payload: [T.Load, e]
2775
+ });
2013
2776
  }
2014
- setToolMode(t) {
2015
- this._toolManager.manage(t);
2777
+ exportScene() {
2778
+ return this._exportStore.clearResult(), {
2779
+ response: this._mediator.send({
2780
+ type: E.Scene,
2781
+ payload: [T.Export]
2782
+ }),
2783
+ result: this._exportStore.getResult()
2784
+ };
2016
2785
  }
2017
2786
  resizeRenderer() {
2018
2787
  this._renderer.resize();
2019
2788
  }
2020
- updateRenderer() {
2021
- this._renderer.loop();
2789
+ /**
2790
+ * Запускает редактор.
2791
+ * Вызывается после создания хаба.
2792
+ */
2793
+ start() {
2794
+ this._controller.start();
2022
2795
  }
2023
- addFigure(t, e) {
2024
- this._sceneManager.manage(t, e);
2796
+ /**
2797
+ * Останавливает редактор.
2798
+ */
2799
+ stop() {
2800
+ this._controller.stop();
2025
2801
  }
2026
2802
  getSelectionStats() {
2027
2803
  return this._store.getSelectionStats();
2028
2804
  }
2029
- onSelectionStatsChange(t) {
2030
- const e = this._store.onSelectedObjectChange(() => {
2031
- t();
2805
+ onSelectionStatsChange(e) {
2806
+ const t = this._store.onSelectedObjectChange(() => {
2807
+ e();
2032
2808
  }), s = this._store.onSelectedTransformChange(() => {
2033
- t();
2809
+ e();
2034
2810
  });
2035
2811
  return () => {
2036
- e(), s();
2812
+ t(), s();
2037
2813
  };
2038
2814
  }
2039
2815
  dispose() {
2040
- this._displayManager.dispose(), this._selectManager.dispose(), this._renderer.dispose();
2816
+ this._mediator.dispose();
2041
2817
  }
2042
2818
  };
2043
- fe = bs([
2044
- M(),
2045
- W(0, _("IDisplayManager")),
2046
- W(1, _("ISelectManager")),
2047
- W(2, _("IToolManager")),
2048
- W(3, _("ISceneManager")),
2049
- W(4, _("EditorRenderer")),
2050
- W(5, _("IEditorStore"))
2051
- ], fe);
2052
- var vs = Object.getOwnPropertyDescriptor, ys = (t, e, s, i) => {
2053
- for (var r = i > 1 ? void 0 : i ? vs(e, s) : e, o = t.length - 1, n; o >= 0; o--)
2054
- (n = t[o]) && (r = n(r) || r);
2055
- return r;
2819
+ Ze = Yr([
2820
+ w(),
2821
+ Z(0, _("Renderer")),
2822
+ Z(1, _("IMediator")),
2823
+ Z(2, _("EditorStore")),
2824
+ Z(3, _("ExportStore")),
2825
+ Z(4, _("IController"))
2826
+ ], Ze);
2827
+ var qr = Object.getOwnPropertyDescriptor, Zr = (e, t, s, r) => {
2828
+ for (var i = r > 1 ? void 0 : r ? qr(t, s) : t, n = e.length - 1, o; n >= 0; n--)
2829
+ (o = e[n]) && (i = o(i) || i);
2830
+ return i;
2056
2831
  };
2057
- let ge = class {
2832
+ let Ke = class {
2058
2833
  /** Текущий режим выборки. */
2059
- _selectMode = y.Mesh;
2834
+ _selectMode = P.Mesh;
2060
2835
  /** Текущий выбранный инструмент. */
2061
- _toolType = F.Translate;
2836
+ _toolType = U.Translate;
2062
2837
  /** Выбранный режим отображения. */
2063
- _displayMode = $.Plane;
2838
+ _displayMode = K.Plane;
2064
2839
  /** Выбранный объект на сцене. */
2065
2840
  _selectedObject = null;
2066
2841
  /** Слушатели событий по изменению выбранного объекта. */
@@ -2068,83 +2843,296 @@ let ge = class {
2068
2843
  /** Слушатели событий трансформации выбранного объекта. */
2069
2844
  _transformListeners = /* @__PURE__ */ new Set();
2070
2845
  constructor() {
2071
- at(this, {}, { autoBind: !0 });
2846
+ At(this, {}, { autoBind: !0 });
2072
2847
  }
2073
- /** @inheritdoc */
2074
2848
  getSelectMode() {
2075
2849
  return this._selectMode;
2076
2850
  }
2077
- /** @inheritdoc */
2078
2851
  getToolType() {
2079
2852
  return this._toolType;
2080
2853
  }
2081
- /** @inheritdoc */
2082
2854
  getDisplayMode() {
2083
2855
  return this._displayMode;
2084
2856
  }
2085
- /** @inheritdoc */
2086
- setSelectMode(t) {
2087
- this._selectMode = t;
2857
+ setSelectMode(e) {
2858
+ this._selectMode = e;
2088
2859
  }
2089
- /** @inheritdoc */
2090
- setToolType(t) {
2091
- this._toolType = t;
2860
+ setToolType(e) {
2861
+ this._toolType = e;
2092
2862
  }
2093
- /** @inheritdoc */
2094
- setDisplayMode(t) {
2095
- this._displayMode = t;
2863
+ setDisplayMode(e) {
2864
+ this._displayMode = e;
2096
2865
  }
2097
- /** @inheritdoc */
2098
2866
  getSelectedObject() {
2099
2867
  return this._selectedObject;
2100
2868
  }
2101
- /** @inheritdoc */
2102
2869
  getSelectionStats() {
2103
- const t = this._selectedObject;
2104
- return t ? vt(t) : null;
2105
- }
2106
- /** @inheritdoc */
2107
- setSelectedObject(t) {
2108
- if (this._selectedObject !== t) {
2109
- this._selectedObject = t;
2110
- for (const e of this._selectedListeners) e(this._selectedObject);
2870
+ const e = this._selectedObject;
2871
+ return e ? ys(e) : null;
2872
+ }
2873
+ setSelectedObject(e) {
2874
+ if (this._selectedObject !== e) {
2875
+ this._selectedObject = e;
2876
+ for (const t of this._selectedListeners) t(this._selectedObject);
2111
2877
  }
2112
2878
  }
2113
- /** @inheritdoc */
2114
- onSelectedObjectChange(t) {
2115
- return this._selectedListeners.add(t), () => this._selectedListeners.delete(t);
2879
+ onSelectedObjectChange(e) {
2880
+ return this._selectedListeners.add(e), () => this._selectedListeners.delete(e);
2116
2881
  }
2117
- /** @inheritdoc */
2118
- onSelectedTransformChange(t) {
2119
- return this._transformListeners.add(t), () => this._transformListeners.delete(t);
2882
+ onSelectedTransformChange(e) {
2883
+ return this._transformListeners.add(e), () => this._transformListeners.delete(e);
2120
2884
  }
2121
- /** @inheritdoc */
2122
2885
  notifySelectedTransformChange() {
2123
- for (const t of this._transformListeners) t();
2886
+ for (const e of this._transformListeners) e();
2124
2887
  }
2125
2888
  };
2126
- ge = ys([
2127
- M()
2128
- ], ge);
2129
- let We = !1;
2130
- const b = ot.createChildContainer();
2131
- function Ms(t) {
2132
- return We || (b.registerInstance("Canvas", t), b.registerSingleton("EventBus", Q), b.registerSingleton("EditorRenderer", ee), b.registerSingleton("RendererApi", me), b.registerSingleton("IDisplayHandler", oe), b.registerSingleton("ISelectHandler", ne), b.registerSingleton("ISelectHandler", ae), b.registerSingleton("ISelectHandler", _e), b.registerSingleton("ISelectHandler", he), b.registerSingleton("IToolHandler", le), b.registerSingleton("IToolHandler", ce), b.registerSingleton("IToolHandler", de), b.registerSingleton("ISceneHandler", ue), b.registerSingleton("ISceneHandler", pe), b.registerSingleton("IDisplayManager", te), b.registerSingleton("ISelectManager", se), b.registerSingleton("IToolManager", ie), b.registerSingleton("ISceneManager", re), b.registerSingleton("EditorHub", fe), b.registerSingleton("IEditorStore", ge), We = !0), b;
2889
+ Ke = Zr([
2890
+ w()
2891
+ ], Ke);
2892
+ class Bt {
2893
+ _result = null;
2894
+ constructor() {
2895
+ At(
2896
+ this,
2897
+ {
2898
+ _result: os.ref
2899
+ },
2900
+ {
2901
+ autoBind: !0
2902
+ }
2903
+ );
2904
+ }
2905
+ get result() {
2906
+ return this._result;
2907
+ }
2908
+ get hasResult() {
2909
+ return this._result !== null;
2910
+ }
2911
+ setResult(t) {
2912
+ this._result = t;
2913
+ }
2914
+ getResult() {
2915
+ return this._result;
2916
+ }
2917
+ clearResult() {
2918
+ this._result = null;
2919
+ }
2920
+ }
2921
+ class kt extends Error {
2922
+ constructor(t, s, r, i) {
2923
+ super(s), this.type = t, this.code = r, this.meta = i, this.name = this._name;
2924
+ }
2925
+ _name = "PolicyException";
2926
+ }
2927
+ class oe extends Error {
2928
+ constructor(t, s, r, i) {
2929
+ super(s), this.type = t, this.code = r, this.meta = i, this.name = this._name;
2930
+ }
2931
+ _name = "ValidationException";
2932
+ }
2933
+ var Kr = Object.getOwnPropertyDescriptor, Jr = (e, t, s, r) => {
2934
+ for (var i = r > 1 ? void 0 : r ? Kr(t, s) : t, n = e.length - 1, o; n >= 0; n--)
2935
+ (o = e[n]) && (i = o(i) || i);
2936
+ return i;
2937
+ }, Qr = (e, t) => (s, r) => t(s, r, e);
2938
+ let Je = class {
2939
+ constructor(e) {
2940
+ this._store = e;
2941
+ }
2942
+ check(e) {
2943
+ const t = this._store.getSelectMode();
2944
+ if (!es[t].includes(e))
2945
+ throw new kt(
2946
+ G.NotAllowed,
2947
+ `Tool ${e} is not allowed`,
2948
+ "TOOL_NOT_ALLOWED"
2949
+ );
2950
+ }
2951
+ };
2952
+ Je = Jr([
2953
+ w(),
2954
+ Qr(0, _("EditorStore"))
2955
+ ], Je);
2956
+ class zt {
2957
+ constructor() {
2958
+ }
2959
+ validate(t) {
2960
+ const s = t.trim();
2961
+ if (!s)
2962
+ throw new oe(
2963
+ G.ValidationError,
2964
+ "File content is empty.",
2965
+ "FILE_CONTENT_EMPTY"
2966
+ );
2967
+ if (!/^v\s+[-+.\deE]+\s+[-+.\deE]+\s+[-+.\deE]+/m.test(s))
2968
+ throw new oe(
2969
+ G.ValidationError,
2970
+ "OBJ content does not contain vertices.",
2971
+ "WRONG_FILE_CONTENT"
2972
+ );
2973
+ if (!/^f\s+/m.test(s))
2974
+ throw new oe(
2975
+ G.ValidationError,
2976
+ "OBJ content does not contain faces.",
2977
+ "WRONG_FILE_CONTENT"
2978
+ );
2979
+ }
2980
+ }
2981
+ var ei = Object.getOwnPropertyDescriptor, ti = (e, t, s, r) => {
2982
+ for (var i = r > 1 ? void 0 : r ? ei(t, s) : t, n = e.length - 1, o; n >= 0; n--)
2983
+ (o = e[n]) && (i = o(i) || i);
2984
+ return i;
2985
+ };
2986
+ let ve = class {
2987
+ handle(e) {
2988
+ try {
2989
+ return e();
2990
+ } catch (t) {
2991
+ return t instanceof kt ? {
2992
+ type: t.type,
2993
+ message: t.message,
2994
+ code: t.code,
2995
+ blocked: !0
2996
+ } : t instanceof oe ? {
2997
+ type: t.type,
2998
+ message: t.message,
2999
+ code: t.code,
3000
+ blocked: !0
3001
+ } : t instanceof Error ? {
3002
+ type: G.Error,
3003
+ message: t.message,
3004
+ code: "UNHANDLED_EXCEPTION",
3005
+ blocked: !0
3006
+ } : {
3007
+ type: G.Error,
3008
+ message: "Unknown exception",
3009
+ code: "UNKNOWN_EXCEPTION",
3010
+ blocked: !0
3011
+ };
3012
+ }
3013
+ }
3014
+ };
3015
+ ve = ti([
3016
+ w()
3017
+ ], ve);
3018
+ var si = Object.getOwnPropertyDescriptor, ri = (e, t, s, r) => {
3019
+ for (var i = r > 1 ? void 0 : r ? si(t, s) : t, n = e.length - 1, o; n >= 0; n--)
3020
+ (o = e[n]) && (i = o(i) || i);
3021
+ return i;
3022
+ }, xt = (e, t) => (s, r) => t(s, r, e);
3023
+ let ye = class {
3024
+ constructor(e, t) {
3025
+ this._middlewares = t, this._managers = new Map(e.map((s) => [s.type, s]));
3026
+ }
3027
+ _managers;
3028
+ send(e) {
3029
+ const t = this._managers.get(e.type);
3030
+ if (!t)
3031
+ return {
3032
+ type: G.Error,
3033
+ message: `Manager for feature "${String(e.type)}" not found`,
3034
+ code: "MANAGER_NOT_FOUND",
3035
+ blocked: !0
3036
+ };
3037
+ const s = () => (t.manage(...e.payload), null);
3038
+ return this._middlewares.reduceRight((i, n) => () => n.handle(i), s)();
3039
+ }
3040
+ dispose() {
3041
+ this._managers && this._managers.clear();
3042
+ }
3043
+ };
3044
+ ye = ri([
3045
+ w(),
3046
+ xt(0, B("IManager")),
3047
+ xt(1, B("IMiddleware"))
3048
+ ], ye);
3049
+ var ii = Object.getOwnPropertyDescriptor, ni = (e, t, s, r) => {
3050
+ for (var i = r > 1 ? void 0 : r ? ii(t, s) : t, n = e.length - 1, o; n >= 0; n--)
3051
+ (o = e[n]) && (i = o(i) || i);
3052
+ return i;
3053
+ }, Le = (e, t) => (s, r) => t(s, r, e);
3054
+ let Qe = class {
3055
+ constructor(e, t, s) {
3056
+ this._renderer = e, this._mediator = t, this._controller = s;
3057
+ }
3058
+ addFigure(e) {
3059
+ return this._mediator.send({
3060
+ type: E.Scene,
3061
+ payload: [T.AddFigure, e]
3062
+ });
3063
+ }
3064
+ loadFigure(e) {
3065
+ return this._mediator.send({
3066
+ type: E.Scene,
3067
+ payload: [T.LoadFigure, e]
3068
+ });
3069
+ }
3070
+ loadScene(e) {
3071
+ return this._mediator.send({
3072
+ type: E.Scene,
3073
+ payload: [T.Load, e]
3074
+ });
3075
+ }
3076
+ resizeRenderer() {
3077
+ this._renderer.resize();
3078
+ }
3079
+ /**
3080
+ * Запускает вьювер.
3081
+ * Вызывается после создания хаба.
3082
+ */
3083
+ start() {
3084
+ this._controller.start();
3085
+ }
3086
+ /**
3087
+ * Останавливает вьювер.
3088
+ */
3089
+ stop() {
3090
+ this._controller.stop();
3091
+ }
3092
+ dispose() {
3093
+ this._mediator.dispose();
3094
+ }
3095
+ };
3096
+ Qe = ni([
3097
+ w(),
3098
+ Le(0, _("Renderer")),
3099
+ Le(1, _("IMediator")),
3100
+ Le(2, _("IController"))
3101
+ ], Qe);
3102
+ let be = !1;
3103
+ const a = Jt.createChildContainer();
3104
+ function oi(e, t) {
3105
+ return be || (a.registerInstance("Canvas", e), a.registerInstance(
3106
+ "RendererConfig",
3107
+ Tt(jt, t)
3108
+ ), a.registerSingleton("EventBus", je), a.registerSingleton("IController", le), a.registerSingleton("Renderer", ae), a.register("IRenderable", { useToken: "Renderer" }), a.register("IRendererAccess", { useToken: "Renderer" }), a.register("IRendererCameraAccess", { useToken: "Renderer" }), a.register("IRendererDomAccess", { useToken: "Renderer" }), a.register("IRendererSceneAccess", { useToken: "Renderer" }), a.registerSingleton("ToolPolicy", Je), a.registerSingleton("ObjValidator", zt), a.registerSingleton("IMeshApi", ce), a.registerSingleton("IControlsStateApi", Ee), a.registerSingleton("IRaycastApi", Te), a.registerSingleton("ITransformApi", Ve), a.registerSingleton("ICameraApi", he), a.registerSingleton("IDomApi", de), a.registerSingleton("ISceneApi", ue), a.registerSingleton("ControlsModule", _e), a.registerSingleton("GizmoModule", De), a.registerSingleton("RaycastModule", $e), a.registerSingleton("SceneModule", Re), a.register("IUpdatableModule", { useToken: "ControlsModule" }), a.register("IRenderableModule", { useToken: "GizmoModule" }), a.register("IRuntimeModule", { useToken: "RaycastModule" }), a.register("IRuntimeModule", { useToken: "SceneModule" }), a.registerSingleton("IDisplayHandler", ke), a.registerSingleton("ISelectHandler", We), a.registerSingleton("ISelectHandler", Ge), a.registerSingleton("ISelectHandler", ze), a.registerSingleton("ISelectHandler", Ue), a.registerSingleton("IToolHandler", Ye), a.registerSingleton("IToolHandler", Xe), a.registerSingleton("IToolHandler", Ne), a.registerSingleton("ISceneHandler", ge), a.registerSingleton("ISceneHandler", qe), a.registerSingleton("ISceneHandler", fe), a.registerSingleton("ISceneHandler", Q), a.registerSingleton("ISceneHandler", J), a.registerSingleton("DisplayManager", He), a.register("IDisplayManager", { useToken: "DisplayManager" }), a.register("IManager", { useToken: "DisplayManager" }), a.registerSingleton("SelectManager", Be), a.register("ISelectManager", { useToken: "SelectManager" }), a.register("IManager", { useToken: "SelectManager" }), a.registerSingleton("ToolManager", me), a.register("IToolManager", { useToken: "ToolManager" }), a.register("IManager", { useToken: "ToolManager" }), a.registerSingleton("SceneManager", pe), a.register("ISceneManager", { useToken: "SceneManager" }), a.register("IManager", { useToken: "SceneManager" }), a.registerSingleton("IMiddleware", ve), a.registerSingleton("IMediator", ye), a.registerSingleton("EditorHub", Ze), a.registerSingleton("EditorStore", Ke), a.registerSingleton("ExportStore", Bt), be = !0), a;
3109
+ }
3110
+ function ai(e, t) {
3111
+ return be || (a.registerInstance("Canvas", e), a.registerInstance(
3112
+ "RendererConfig",
3113
+ Tt(jt, t)
3114
+ ), a.registerSingleton("IController", le), a.registerSingleton("Renderer", ae), a.register("IRenderable", { useToken: "Renderer" }), a.register("IRendererAccess", { useToken: "Renderer" }), a.register("IRendererCameraAccess", { useToken: "Renderer" }), a.register("IRendererDomAccess", { useToken: "Renderer" }), a.register("IRendererSceneAccess", { useToken: "Renderer" }), a.registerSingleton("ObjValidator", zt), a.registerSingleton("IMeshApi", ce), a.registerSingleton("ICameraApi", he), a.registerSingleton("IDomApi", de), a.registerSingleton("ISceneApi", ue), a.registerSingleton("ControlsModule", _e), a.registerSingleton("SceneModule", Fe), a.register("IUpdatableModule", { useToken: "ControlsModule" }), a.register("IRuntimeModule", { useToken: "SceneModule" }), a.registerSingleton("ISceneHandler", ge), a.registerSingleton("ISceneHandler", fe), a.registerSingleton("ISceneHandler", Q), a.registerSingleton("ISceneHandler", J), a.registerSingleton("SceneManager", pe), a.register("ISceneManager", { useToken: "SceneManager" }), a.register("IManager", { useToken: "SceneManager" }), a.registerSingleton("IMiddleware", ve), a.registerSingleton("IMediator", ye), a.registerSingleton("ViewerHub", Qe), a.registerSingleton("ExportStore", Bt), be = !0), a;
2133
3115
  }
2134
- let N = null;
2135
- const Cs = (t) => (N || (N = Ms(t)), N.resolve("EditorHub")), As = () => {
2136
- if (!N)
2137
- throw new Error("EditorHub is not initialized. Call createAppHub(canvas) first.");
2138
- return N.resolve("EditorHub");
3116
+ let R = null;
3117
+ const gi = (e, t) => (R || (R = oi(e, t)), R.resolve("EditorHub")), fi = () => {
3118
+ if (!R)
3119
+ throw new Error("EditorHub is not initialized. Call createEditorHub(canvas) first.");
3120
+ return R.resolve("EditorHub");
3121
+ }, vi = (e, t) => (R || (R = ai(e, t)), R.resolve("ViewerHub")), yi = () => {
3122
+ if (!R)
3123
+ throw new Error("ViewerHub is not initialized. Call createViewerHub(canvas) first.");
3124
+ return R.resolve("ViewerHub");
2139
3125
  };
2140
3126
  export {
2141
- fe as EditorHub,
2142
- ee as EditorRenderer,
2143
- Q as EventBus,
2144
- H as EventTopics,
2145
- Ds as ObjLoader,
2146
- Ls as PreviewRenderer,
2147
- Ne as Renderer,
2148
- Cs as createAppHub,
2149
- As as getAppHub
3127
+ Ze as EditorHub,
3128
+ je as EventBus,
3129
+ k as EventTopics,
3130
+ E as FeatureType,
3131
+ mi as ObjLoader,
3132
+ ae as Renderer,
3133
+ Qe as ViewerHub,
3134
+ gi as createEditorHub,
3135
+ vi as createViewerHub,
3136
+ fi as getEditorHub,
3137
+ yi as getViewerHub
2150
3138
  };