@planara/core 2.7.1 → 3.0.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 (191) 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/mesh-api.d.ts +30 -0
  5. package/dist/api/modules/mesh-api.d.ts.map +1 -0
  6. package/dist/api/modules/raycast-api.d.ts +28 -0
  7. package/dist/api/modules/raycast-api.d.ts.map +1 -0
  8. package/dist/api/modules/transform-api.d.ts +33 -0
  9. package/dist/api/modules/transform-api.d.ts.map +1 -0
  10. package/dist/api/renderer/camera-api.d.ts +26 -0
  11. package/dist/api/renderer/camera-api.d.ts.map +1 -0
  12. package/dist/api/renderer/dom-api.d.ts +24 -0
  13. package/dist/api/renderer/dom-api.d.ts.map +1 -0
  14. package/dist/api/renderer/scene-api.d.ts +26 -0
  15. package/dist/api/renderer/scene-api.d.ts.map +1 -0
  16. package/dist/constants/colors.d.ts +12 -0
  17. package/dist/constants/colors.d.ts.map +1 -1
  18. package/dist/constants/figure-geometries.d.ts +55 -4
  19. package/dist/constants/figure-geometries.d.ts.map +1 -1
  20. package/dist/constants/layers.d.ts +12 -0
  21. package/dist/constants/layers.d.ts.map +1 -1
  22. package/dist/constants/messages.d.ts +18 -0
  23. package/dist/constants/messages.d.ts.map +1 -0
  24. package/dist/constants/threshold.d.ts +42 -2
  25. package/dist/constants/threshold.d.ts.map +1 -1
  26. package/dist/controllers/renderer-controller.d.ts +74 -0
  27. package/dist/controllers/renderer-controller.d.ts.map +1 -0
  28. package/dist/core/renderer.d.ts +110 -78
  29. package/dist/core/renderer.d.ts.map +1 -1
  30. package/dist/decorators/use-policy.d.ts +5 -0
  31. package/dist/decorators/use-policy.d.ts.map +1 -0
  32. package/dist/errors/policy-error.d.ts +9 -0
  33. package/dist/errors/policy-error.d.ts.map +1 -0
  34. package/dist/events/editor-events.d.ts +2 -6
  35. package/dist/events/editor-events.d.ts.map +1 -1
  36. package/dist/events/event-bus.d.ts +102 -5
  37. package/dist/events/event-bus.d.ts.map +1 -1
  38. package/dist/events/event-topics.d.ts +3 -3
  39. package/dist/events/event-topics.d.ts.map +1 -1
  40. package/dist/handlers/display/wireframe-handler.d.ts +3 -1
  41. package/dist/handlers/display/wireframe-handler.d.ts.map +1 -1
  42. package/dist/handlers/scene/add-figure-scene-handler.d.ts +2 -0
  43. package/dist/handlers/scene/add-figure-scene-handler.d.ts.map +1 -1
  44. package/dist/handlers/scene/delete-figure-scene-handler.d.ts +2 -2
  45. package/dist/handlers/scene/delete-figure-scene-handler.d.ts.map +1 -1
  46. package/dist/handlers/select/edge-select-handler.d.ts +10 -4
  47. package/dist/handlers/select/edge-select-handler.d.ts.map +1 -1
  48. package/dist/handlers/select/face-select-handler.d.ts +65 -6
  49. package/dist/handlers/select/face-select-handler.d.ts.map +1 -1
  50. package/dist/handlers/select/mesh-select-handler.d.ts +5 -3
  51. package/dist/handlers/select/mesh-select-handler.d.ts.map +1 -1
  52. package/dist/handlers/select/vertex-select-handler.d.ts +10 -4
  53. package/dist/handlers/select/vertex-select-handler.d.ts.map +1 -1
  54. package/dist/handlers/tool/base-tool-handler.d.ts +9 -6
  55. package/dist/handlers/tool/base-tool-handler.d.ts.map +1 -1
  56. package/dist/handlers/tool/rotate-tool-handler.d.ts +4 -3
  57. package/dist/handlers/tool/rotate-tool-handler.d.ts.map +1 -1
  58. package/dist/handlers/tool/scale-tool-handler.d.ts +4 -3
  59. package/dist/handlers/tool/scale-tool-handler.d.ts.map +1 -1
  60. package/dist/handlers/tool/translate-tool-handler.d.ts +4 -3
  61. package/dist/handlers/tool/translate-tool-handler.d.ts.map +1 -1
  62. package/dist/hub/app-hub.d.ts +1 -0
  63. package/dist/hub/app-hub.d.ts.map +1 -1
  64. package/dist/hub/editor-hub.d.ts +22 -17
  65. package/dist/hub/editor-hub.d.ts.map +1 -1
  66. package/dist/index.cjs.js +2 -2
  67. package/dist/index.d.ts +15 -8
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.es.js +1750 -1378
  70. package/dist/index.full.d.ts +635 -229
  71. package/dist/index.public.d.ts +653 -147
  72. package/dist/index.umd.js +2 -2
  73. package/dist/interfaces/api/camera-api.d.ts +64 -0
  74. package/dist/interfaces/api/camera-api.d.ts.map +1 -0
  75. package/dist/interfaces/api/controls-state-api.d.ts +63 -0
  76. package/dist/interfaces/api/controls-state-api.d.ts.map +1 -0
  77. package/dist/interfaces/api/dom-api.d.ts +49 -0
  78. package/dist/interfaces/api/dom-api.d.ts.map +1 -0
  79. package/dist/interfaces/api/mesh-api.d.ts +93 -12
  80. package/dist/interfaces/api/mesh-api.d.ts.map +1 -1
  81. package/dist/interfaces/api/raycast-api.d.ts +6 -1
  82. package/dist/interfaces/api/raycast-api.d.ts.map +1 -1
  83. package/dist/interfaces/api/renderer/renderable.d.ts +45 -0
  84. package/dist/interfaces/api/renderer/renderable.d.ts.map +1 -0
  85. package/dist/interfaces/api/renderer/renderer-access.d.ts +34 -0
  86. package/dist/interfaces/api/renderer/renderer-access.d.ts.map +1 -0
  87. package/dist/interfaces/api/renderer/renderer-camera-access.d.ts +37 -0
  88. package/dist/interfaces/api/renderer/renderer-camera-access.d.ts.map +1 -0
  89. package/dist/interfaces/api/renderer/renderer-dom-access.d.ts +51 -0
  90. package/dist/interfaces/api/renderer/renderer-dom-access.d.ts.map +1 -0
  91. package/dist/interfaces/api/renderer/renderer-scene-access.d.ts +45 -0
  92. package/dist/interfaces/api/renderer/renderer-scene-access.d.ts.map +1 -0
  93. package/dist/interfaces/api/renderer-api.d.ts +35 -0
  94. package/dist/interfaces/api/renderer-api.d.ts.map +1 -0
  95. package/dist/interfaces/api/scene-api.d.ts +66 -26
  96. package/dist/interfaces/api/scene-api.d.ts.map +1 -1
  97. package/dist/interfaces/api/transform-api.d.ts +120 -0
  98. package/dist/interfaces/api/transform-api.d.ts.map +1 -0
  99. package/dist/interfaces/command/index.d.ts +9 -0
  100. package/dist/interfaces/command/index.d.ts.map +1 -0
  101. package/dist/interfaces/controller/controller.d.ts +38 -0
  102. package/dist/interfaces/controller/controller.d.ts.map +1 -0
  103. package/dist/interfaces/handler/display-handler.d.ts +9 -1
  104. package/dist/interfaces/handler/display-handler.d.ts.map +1 -1
  105. package/dist/interfaces/handler/handler.d.ts +2 -0
  106. package/dist/interfaces/handler/handler.d.ts.map +1 -1
  107. package/dist/interfaces/handler/scene-handler.d.ts +1 -0
  108. package/dist/interfaces/handler/scene-handler.d.ts.map +1 -1
  109. package/dist/interfaces/handler/select-handler.d.ts +1 -0
  110. package/dist/interfaces/handler/select-handler.d.ts.map +1 -1
  111. package/dist/interfaces/handler/tool-handler.d.ts +1 -0
  112. package/dist/interfaces/handler/tool-handler.d.ts.map +1 -1
  113. package/dist/interfaces/manager/display-manager.d.ts +3 -1
  114. package/dist/interfaces/manager/display-manager.d.ts.map +1 -1
  115. package/dist/interfaces/manager/manager.d.ts +12 -1
  116. package/dist/interfaces/manager/manager.d.ts.map +1 -1
  117. package/dist/interfaces/manager/scene-manager.d.ts +3 -1
  118. package/dist/interfaces/manager/scene-manager.d.ts.map +1 -1
  119. package/dist/interfaces/manager/select-manager.d.ts +3 -1
  120. package/dist/interfaces/manager/select-manager.d.ts.map +1 -1
  121. package/dist/interfaces/manager/tool-manager.d.ts +3 -1
  122. package/dist/interfaces/manager/tool-manager.d.ts.map +1 -1
  123. package/dist/interfaces/mediator/index.d.ts +51 -0
  124. package/dist/interfaces/mediator/index.d.ts.map +1 -0
  125. package/dist/interfaces/middleware/index.d.ts +50 -0
  126. package/dist/interfaces/middleware/index.d.ts.map +1 -0
  127. package/dist/interfaces/module/renderable-module.d.ts +27 -0
  128. package/dist/interfaces/module/renderable-module.d.ts.map +1 -0
  129. package/dist/interfaces/module/runtime-module.d.ts +54 -0
  130. package/dist/interfaces/module/runtime-module.d.ts.map +1 -0
  131. package/dist/interfaces/module/updatable-module.d.ts +48 -0
  132. package/dist/interfaces/module/updatable-module.d.ts.map +1 -0
  133. package/dist/interfaces/policy/index.d.ts +21 -0
  134. package/dist/interfaces/policy/index.d.ts.map +1 -0
  135. package/dist/interfaces/response/index.d.ts +22 -0
  136. package/dist/interfaces/response/index.d.ts.map +1 -0
  137. package/dist/interfaces/store/display-store.d.ts +21 -0
  138. package/dist/interfaces/store/display-store.d.ts.map +1 -0
  139. package/dist/interfaces/store/{editor-store.d.ts → select-store.d.ts} +16 -24
  140. package/dist/interfaces/store/select-store.d.ts.map +1 -0
  141. package/dist/interfaces/store/tool-store.d.ts +27 -0
  142. package/dist/interfaces/store/tool-store.d.ts.map +1 -0
  143. package/dist/interfaces/store/transform-store.d.ts +11 -0
  144. package/dist/interfaces/store/transform-store.d.ts.map +1 -0
  145. package/dist/ioc/container.d.ts.map +1 -1
  146. package/dist/managers/display/display-manager.d.ts +5 -2
  147. package/dist/managers/display/display-manager.d.ts.map +1 -1
  148. package/dist/managers/scene/scene-manager.d.ts +3 -0
  149. package/dist/managers/scene/scene-manager.d.ts.map +1 -1
  150. package/dist/managers/select/select-manager.d.ts +5 -2
  151. package/dist/managers/select/select-manager.d.ts.map +1 -1
  152. package/dist/managers/tool/tool-manager.d.ts +7 -4
  153. package/dist/managers/tool/tool-manager.d.ts.map +1 -1
  154. package/dist/mediator/index.d.ts +14 -0
  155. package/dist/mediator/index.d.ts.map +1 -0
  156. package/dist/middlewares/exception-middleware.d.ts +7 -0
  157. package/dist/middlewares/exception-middleware.d.ts.map +1 -0
  158. package/dist/modules/controls-module.d.ts +58 -0
  159. package/dist/modules/controls-module.d.ts.map +1 -0
  160. package/dist/modules/gizmo-module.d.ts +34 -0
  161. package/dist/modules/gizmo-module.d.ts.map +1 -0
  162. package/dist/modules/raycast-module.d.ts +91 -0
  163. package/dist/modules/raycast-module.d.ts.map +1 -0
  164. package/dist/modules/scene-module.d.ts +32 -0
  165. package/dist/modules/scene-module.d.ts.map +1 -0
  166. package/dist/policy/tool-policy.d.ts +18 -0
  167. package/dist/policy/tool-policy.d.ts.map +1 -0
  168. package/dist/store/index.d.ts +4 -14
  169. package/dist/store/index.d.ts.map +1 -1
  170. package/dist/types/feature/feature-type.d.ts +16 -0
  171. package/dist/types/feature/feature-type.d.ts.map +1 -0
  172. package/dist/types/response/response-type.d.ts +19 -0
  173. package/dist/types/response/response-type.d.ts.map +1 -0
  174. package/dist/types/select/face-group.d.ts +24 -0
  175. package/dist/types/select/face-group.d.ts.map +1 -0
  176. package/package.json +2 -2
  177. package/dist/core/editor-renderer.d.ts +0 -79
  178. package/dist/core/editor-renderer.d.ts.map +0 -1
  179. package/dist/core/preview-renderer.d.ts +0 -16
  180. package/dist/core/preview-renderer.d.ts.map +0 -1
  181. package/dist/interfaces/api/transform-helpers-api.d.ts +0 -26
  182. package/dist/interfaces/api/transform-helpers-api.d.ts.map +0 -1
  183. package/dist/interfaces/policy/tool-availability-policy.d.ts +0 -12
  184. package/dist/interfaces/policy/tool-availability-policy.d.ts.map +0 -1
  185. package/dist/interfaces/store/editor-store.d.ts.map +0 -1
  186. package/dist/policy/tool-availability-policy.d.ts +0 -13
  187. package/dist/policy/tool-availability-policy.d.ts.map +0 -1
  188. package/dist/types/api/editor-api.d.ts +0 -4
  189. package/dist/types/api/editor-api.d.ts.map +0 -1
  190. package/dist/utils/renderer-api.d.ts +0 -43
  191. package/dist/utils/renderer-api.d.ts.map +0 -1
package/dist/index.es.js CHANGED
@@ -1,1053 +1,936 @@
1
1
  import "reflect-metadata";
2
2
  import * as a from "three";
3
- import { Controls as Ue, Vector3 as T, MOUSE as I, TOUCH as R, Quaternion as ve, Spherical as ye, Vector2 as w, Ray as We, Plane as Fe, MathUtils as Ze } from "three";
4
- import { FigureType as S, SelectMode as v, Figure as $e, DisplayMode as V, DEFAULT_TOOL_RULES as Me, ToolType as C, SceneMode as N } from "@planara/types";
5
- import { SymmetricAxesHelper as Be, OrbitWithState as Xe, CameraAxesGizmo as Ge, ModelingTransformControls as Ke } from "@planara/three";
6
- import { injectable as u, inject as h, injectAll as W, container as qe } from "tsyringe";
7
- import { EventEmitter as Qe } from "events";
8
- import { makeAutoObservable as Je } from "mobx";
9
- const et = {
10
- [S.Plane]: () => new a.PlaneGeometry(1, 1, 1, 1),
11
- [S.Cube]: () => new a.BoxGeometry(1, 1, 1, 1, 1, 1),
12
- [S.UVSphere]: () => new a.SphereGeometry(0.5, 32, 16),
13
- [S.Icosphere]: () => new a.IcosahedronGeometry(0.5, 0),
14
- [S.Cylinder]: () => new a.CylinderGeometry(0.5, 0.5, 1, 32, 1, !1),
15
- [S.Cone]: () => new a.ConeGeometry(0.5, 1, 32, 1, !1),
16
- [S.Torus]: () => new a.TorusGeometry(0.5, 0.2, 16, 64),
17
- [S.Circle]: () => new a.CircleGeometry(0.5, 32),
18
- [S.Sphere]: () => new a.SphereGeometry(0.5, 32, 16),
19
- [S.Custom]: function() {
20
- throw new Error("Custom geometry is not generated here.");
21
- }
22
- }, Ie = new a.MeshStandardMaterial({
23
- color: 12566463,
24
- metalness: 0,
25
- roughness: 0.6
26
- }), tt = 8;
27
- class He {
28
- /** Корневой объект сцены */
3
+ import { injectable as d, inject as l, injectAll as D, container as et } from "tsyringe";
4
+ import { FigureType as O, Figure as tt, SelectMode as M, DisplayMode as F, ToolType as j, SceneMode as W, DEFAULT_TOOL_RULES as st } from "@planara/types";
5
+ import { OrbitWithState as rt, ModelingTransformControls as it, CameraAxesGizmo as ot, SymmetricAxesHelper as nt } from "@planara/three";
6
+ import { EventEmitter as at } from "events";
7
+ import { makeAutoObservable as ct } from "mobx";
8
+ var lt = Object.getOwnPropertyDescriptor, ht = (e, t, r, s) => {
9
+ for (var i = s > 1 ? void 0 : s ? lt(t, r) : t, o = e.length - 1, n; o >= 0; o--)
10
+ (n = e[o]) && (i = n(i) || i);
11
+ return i;
12
+ }, _t = (e, t) => (r, s) => t(r, s, e);
13
+ let te = class {
14
+ /**
15
+ * Корневой объект сцены Three.js.
16
+ *
17
+ * @protected
18
+ * @member
19
+ */
29
20
  scene;
30
- /** Камера для сцены */
21
+ /**
22
+ * Камера для сцены Three.js.
23
+ *
24
+ * @protected
25
+ * @member
26
+ */
31
27
  camera;
32
- /** Экземпляр рендерера Three.js */
28
+ /**
29
+ * Экземпляр Three.js WebGLRenderer.
30
+ *
31
+ * @protected
32
+ * @member
33
+ */
33
34
  renderer;
34
- /** HTML-элемент canvas, на котором рендерится сцена */
35
+ /**
36
+ * HTML-элемент canvas, на котором рендерится сцена.
37
+ *
38
+ * @protected
39
+ * @member
40
+ */
35
41
  canvas;
36
- /** Массив моделей на сцене */
37
- meshes = [];
38
42
  /**
39
- * Конструктор рендерера
40
- * @param canvas - HTMLCanvasElement для рендеринга
43
+ * Конструктор рендерера.
44
+ *
45
+ * @param _canvas - HTMLCanvasElement для рендеринга
46
+ *
47
+ * @remarks
48
+ * Инициализирует сцену с тёмным фоном, перспективную камеру
49
+ * (45° FOV, near 0.1, far 1000) и базовое освещение:
50
+ * - `AmbientLight` (0xffffff, 0.5) — общий свет
51
+ * - `DirectionalLight` (0xffffff, 1) — направленный свет
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * const renderer = new Renderer(canvas);
56
+ * ```
57
+ *
58
+ * @public
59
+ * @constructor
41
60
  */
42
61
  constructor(e) {
43
62
  this.canvas = e, this.scene = new a.Scene(), this.scene.background = new a.Color(1710618), this.camera = new a.PerspectiveCamera(
44
63
  45,
45
- e.clientWidth / e.clientHeight,
64
+ this.canvas.clientWidth / this.canvas.clientHeight,
46
65
  0.1,
47
66
  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);
53
- }
54
- /**
55
- * Обновляет размер рендерера и камеры при изменении размеров canvas.
56
- */
57
- resize() {
58
- this.camera.aspect = this.canvas.clientWidth / this.canvas.clientHeight, this.camera.updateProjectionMatrix(), this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
59
- }
60
- /**
61
- * Выполняет рендеринг сцены с текущей камерой.
62
- */
63
- render() {
64
- this.renderer.render(this.scene, this.camera);
65
- }
66
- /**
67
- * Метод для обновления логики рендерера.
68
- */
69
- update() {
70
- }
71
- /**
72
- * Запускает основной цикл рендеринга.
73
- */
74
- loop() {
75
- this.update(), this.render(), requestAnimationFrame(() => this.loop());
76
- }
77
- /**
78
- * Добавление фигуры на сцену.
79
- * @param figure - Данные фигуры: position, normal, uv
80
- */
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, Ie);
85
- return this.scene.add(i), this.meshes.push(i), i;
67
+ ), this.camera.position.set(1, 1, 7), this.renderer = new a.WebGLRenderer({ canvas: this.canvas, antialias: !0 }), this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
68
+ const t = new a.AmbientLight(16777215, 0.5);
69
+ this.scene.add(t);
70
+ const r = new a.DirectionalLight(16777215, 1);
71
+ r.position.set(5, 10, 7), this.scene.add(r);
86
72
  }
87
73
  /**
88
- * Добавляет фигуру в сцену и сохраняет его во внутреннем массиве.
74
+ * Обновляет размер рендерера и пропорции камеры.
89
75
  *
90
- * @param mesh - Фигура для добавления в сцену.
91
- * @internal
92
- */
93
- addMesh(e) {
94
- this.scene && (this.scene.add(e), this.meshes.push(e));
95
- }
96
- /**
97
- * Убирает фигуру со сцены
76
+ * @remarks
77
+ * Вызывается при изменении размеров canvas (например, при ресайзе окна браузера).
98
78
  *
99
- * @param mesh - Фигура для удаления со сцены.
100
- * @internal
101
- */
102
- removeMesh(e) {
103
- this.scene && (this.scene.remove(e), this.meshes = this.meshes.filter((s) => s !== e));
104
- }
105
- /**
106
- * Возвращает список всех фигур, находящихся в сцене.
79
+ * @example
80
+ * ```typescript
81
+ * window.addEventListener('resize', () => renderer.resize());
82
+ * ```
107
83
  *
108
- * @returns Массив текущих фигур.
109
- * @internal
84
+ * @oublic
85
+ * @method
110
86
  */
111
- getMeshes() {
112
- return this.meshes;
87
+ resize() {
88
+ this.camera.aspect = this.canvas.clientWidth / this.canvas.clientHeight, this.camera.updateProjectionMatrix(), this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
113
89
  }
114
90
  /**
115
- * Добавляет объект в сцену и (опционально) выставляет ему слой.
116
- *
117
- * @param obj - Объект, который нужно добавить в сцену.
118
- * @param layer - (Опц.) Номер слоя, который следует установить объекту перед добавлением.
91
+ * Выполняет рендеринг текущего кадра.
119
92
  *
120
93
  * @remarks
121
- * Если рендерер уже диспоузнут (scene отсутствует), метод тихо завершится.
122
- * Слой задаётся через `obj.layers.set(layer)`, после чего объект добавляется в `this.scene`.
123
- *
124
- * @example
125
- * // Добавить оверлей на слой подсветок:
126
- * add(overlayLine, OVERLAY_LAYER);
94
+ * Рендерит сцену с текущей камерой.
95
+ * Вызывается автоматически в цикле `loop()`.
127
96
  *
128
- * @internal
97
+ * @public
98
+ * @method
129
99
  */
130
- addObject(e, s) {
131
- this.scene && (typeof s == "number" && e.layers.set(s), this.scene.add(e));
100
+ render() {
101
+ this.renderer.render(this.scene, this.camera);
132
102
  }
133
103
  /**
134
- * Удаляет объект из сцены (или из его родителя, если он есть).
135
- *
136
- * @param obj - Объект, который необходимо удалить.
104
+ * Обновляет состояние рендерера перед рендерингом.
137
105
  *
138
106
  * @remarks
139
- * Если у объекта есть `parent`, он будет удалён из родителя. Иначе — метод попытается
140
- * удалить его напрямую из `this.scene`. В рамках данного API метод не отвечает за
141
- * освобождение GPU-ресурсов; освобождайте геометрию/материалы отдельно при необходимости.
142
- *
143
- * @example
144
- * // Снять оверлей со сцены:
145
- * removeObject(overlayLine);
107
+ * Пустой метод, предназначен для переопределения в наследниках
108
+ * (например, для обновления контролов камеры).
146
109
  *
147
- * @internal
110
+ * @protected
111
+ * @method
112
+ * @virtual
148
113
  */
149
- removeObject(e) {
150
- this.scene && (e.parent ? e.parent.remove(e) : this.scene.remove(e));
114
+ update() {
151
115
  }
152
116
  /**
153
- * Включает указанный слой у активной камеры.
154
- *
155
- * @param layer - Номер слоя, который требуется сделать видимым для камеры.
117
+ * Запускает основной цикл рендеринга.
156
118
  *
157
119
  * @remarks
158
- * Полезно для показа служебных оверлеев (например, подсветки) на отдельном слое.
159
- * Метод не изменяет слои Raycaster — ими должен управлять другой слой API (например, IRaycastAPI).
120
+ * Вызывает `update()` и `render()` каждый кадр с помощью `requestAnimationFrame`.
121
+ * **Важно:** вызывать метод только один раз.
160
122
  *
161
123
  * @example
162
- * // Убедиться, что камера видит слой оверлеев:
163
- * enableCameraLayer(OVERLAY_LAYER);
124
+ * ```typescript
125
+ * renderer.loop();
126
+ * ```
164
127
  *
165
- * @internal
128
+ * @public
129
+ * @method
166
130
  */
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 st = Object.getOwnPropertyDescriptor, it = (t, e, s, i) => {
176
- for (var r = i > 1 ? void 0 : i ? st(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 G = class {
181
- _emitter;
182
- constructor() {
183
- this._emitter = new Qe();
184
- }
185
- /** Публикация события */
186
- emit(t, e) {
187
- this._emitter.emit(t, e);
188
- }
189
- /** Подписка на событие */
190
- on(t, e) {
191
- this._emitter.on(t, e);
192
- }
193
- /** Отписка от события */
194
- off(t, e) {
195
- this._emitter.off(t, e);
196
- }
197
- };
198
- G = it([
199
- u()
200
- ], G);
201
- var H = /* @__PURE__ */ ((t) => (t.SelectHover = "select.hover", t.SelectClick = "select.click", t.ToolSelect = "tool.select", t))(H || {});
202
- const rt = 0.03, ot = 0.05, ke = 0, nt = 1, at = 2, L = 31, F = 16776960, Z = 16755200, ht = 2236962, lt = 2236962, ct = (t) => !!t && t.isMesh, Ve = (t) => {
203
- let e = t;
204
- for (; e; ) {
205
- if (e.isMesh) return e;
206
- e = e.parent;
131
+ loop() {
132
+ this.update(), this.render(), requestAnimationFrame(() => this.loop());
207
133
  }
208
- return null;
209
- }, Ne = (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: lt,
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(at), i.renderOrder = 1e3, i.visible = !1, i;
222
- }, Ye = (t) => {
223
- const e = new a.EdgesGeometry(t), s = new a.LineSegments(
224
- e,
225
- new a.LineBasicMaterial({ color: ht, linewidth: 1 })
226
- );
227
- return s.layers.set(nt), s;
228
- }, dt = (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 _t = Object.getOwnPropertyDescriptor, pt = (t, e, s, i) => {
235
- for (var r = i > 1 ? void 0 : i ? _t(e, s) : e, o = t.length - 1, n; o >= 0; o--)
236
- (n = t[o]) && (r = n(r) || r);
237
- return r;
238
- }, Ee = (t, e) => (s, i) => e(s, i, t);
239
- let K = class extends He {
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 Be(6);
245
- this.scene.add(i), this._orbit = new Xe(this.camera, this.renderer.domElement), this._orbit.enableDamping = !0, this._orbit.dampingFactor = 0.05, this._cameraGizmo = new Ge(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 Ke(this.camera, this.renderer.domElement), this._transformHelper = this._transform.getHelper(), this.scene.add(this._transformHelper), this._isEventListenersAdded || this._initMouseListeners();
134
+ getCamera() {
135
+ return this.camera;
251
136
  }
252
- /** Orbit-контроллер для управления камерой */
253
- _orbit;
254
- /** Transform-контроллер для редактирования */
255
- _transform;
256
- _transformHelper;
257
- /** Raycast для получения событий наведения/клика по модели*/
258
- _raycaster;
259
- /** Курсор мыши */
260
- _mouse;
261
- /** Были ли инициализированы обработчики событий (hover/click) */
262
- _isEventListenersAdded = !1;
263
- /**
264
- * Последняя модель на которую наводились,
265
- * необходима для отправки только уникальных событий в event bus
266
- */
267
- _lastHovered = null;
268
- /** Gizmo для управления отображением perspective camera */
269
- _cameraGizmo;
270
- _transformListeners = /* @__PURE__ */ new Set();
271
- /**
272
- * Обновление состояния рендерера.
273
- */
274
- update() {
275
- this._orbit.update();
137
+ getRenderer() {
138
+ return this.renderer;
276
139
  }
277
- /** Добавление фигуры на сцену */
278
- addFigure(t) {
279
- const e = super.addFigure(t);
280
- e.layers.enable(ke);
281
- const s = Ye(e.geometry);
282
- e.add(s);
283
- const i = Ne(e.geometry);
284
- return e.add(i), e;
140
+ getCanvas() {
141
+ return this.canvas;
285
142
  }
286
- /**
287
- * Смена отображения `TransformControls` в зависимости от типа инструмента.
288
- * @param mode - тип инструмента для отображения `TransformControls`.
289
- * @internal
290
- */
291
- setTransformControlsMode(t) {
292
- this._transform.setMode(t);
143
+ getDomElement() {
144
+ return this.renderer.domElement;
293
145
  }
294
- /**
295
- * Добавление `TransformControls` к объекту.
296
- * @param object - объект, к которому добавляются `TransformControls`.
297
- * @internal
298
- */
299
- attachTransformControls(t) {
300
- this._transform.attach(t);
146
+ getScene() {
147
+ return this.scene;
301
148
  }
302
149
  /**
303
- * Удаление `TransformControls` с последнего выбранного объекта.
304
- * @internal
150
+ * Освобождает ресурсы рендерера.
151
+ *
152
+ * @remarks
153
+ * Удаляет ссылки на сцену, камеру и canvas, вызывает `dispose()` у WebGLRenderer.
154
+ * Вызывается при уничтожении редактора IOC-контейнером.
155
+ *
156
+ * @public
157
+ * @method
305
158
  */
306
- detachTransformControls() {
307
- this._transform.detach();
159
+ dispose() {
160
+ this.scene = null, this.camera = null, this.renderer?.dispose(), this.canvas = null;
308
161
  }
162
+ };
163
+ te = ht([
164
+ d(),
165
+ _t(0, l("Canvas"))
166
+ ], te);
167
+ class Js {
168
+ /** Позиции вершин */
169
+ _positions = [];
170
+ /** Нормали вершин */
171
+ _normals = [];
172
+ /** UV-координаты (опционально) */
173
+ _uvs = [];
174
+ // Временные поля для парсинга файла
175
+ _tmpPositions = [];
176
+ _tmpNormals = [];
177
+ _tmpUVs = [];
309
178
  /**
310
- * Подписывает слушателя на изменения трансформации текущего объекта.
311
- * @internal
179
+ * Загружает OBJ-модель в Figure
180
+ * @param objContent - Строка содержимого .obj файла
312
181
  */
313
- onTransformChange(t) {
314
- return this._transformListeners.add(t), () => this._transformListeners.delete(t);
182
+ load(t) {
183
+ const r = t.split(`
184
+ `);
185
+ for (const i of r) {
186
+ if (!i.trim() || i.startsWith("#")) continue;
187
+ const o = i.trim().split(/\s+/);
188
+ switch (o[0]) {
189
+ case "v":
190
+ this._tmpPositions.push(o.slice(1).map(Number));
191
+ break;
192
+ case "vn":
193
+ this._tmpNormals.push(o.slice(1).map(Number));
194
+ break;
195
+ case "vt":
196
+ this._tmpUVs.push(o.slice(1).map(Number));
197
+ break;
198
+ case "f":
199
+ this.processFaceLine(o);
200
+ break;
201
+ }
202
+ }
203
+ const s = {
204
+ type: O.Custom,
205
+ position: this._positions,
206
+ ...this._normals.length > 0 && { normal: this._normals },
207
+ ...this._uvs.length > 0 && { uv: this._uvs }
208
+ };
209
+ return new tt(s);
315
210
  }
316
211
  /**
317
- * Настройка режимов для `Raycaster`.
318
- * @internal
212
+ * Обрабатывает строку face (f) и разворачивает индексы в массивы для рендеринга
319
213
  */
320
- setRaycastMode(t) {
321
- const e = this._raycaster;
322
- switch (e.params.Line.threshold = 0, e.params.Points.threshold = 0, t) {
323
- case v.Mesh:
324
- case v.Face:
325
- e.layers.set(0);
326
- break;
327
- case v.Edge:
328
- e.layers.set(1), e.params.Line.threshold = rt;
329
- break;
330
- case v.Vertex:
331
- e.layers.set(2), e.params.Points.threshold = ot;
332
- break;
214
+ processFaceLine(t) {
215
+ for (let r = 1; r < t.length; r++) {
216
+ const s = t[r];
217
+ if (!s) continue;
218
+ const [i, o, n] = s.split("/"), c = i ? parseInt(i, 10) : void 0, _ = o ? parseInt(o, 10) : void 0, u = n ? parseInt(n, 10) : void 0;
219
+ if (c !== void 0) {
220
+ const p = this._tmpPositions[c - 1];
221
+ p && this._positions.push(...p);
222
+ }
223
+ if (_ !== void 0) {
224
+ const p = this._tmpUVs[_ - 1];
225
+ p && this._uvs.push(...p);
226
+ }
227
+ if (u !== void 0) {
228
+ const p = this._tmpNormals[u - 1];
229
+ p && this._normals.push(...p);
230
+ }
333
231
  }
334
232
  }
335
- dispose() {
336
- this._isEventListenersAdded && (this.canvas.removeEventListener("mousemove", this._handleMouseMove, !1), this.canvas.removeEventListener("click", this._handleMouseClick, !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", () => {
337
- this._orbit.enabled = !this._transform.dragging;
338
- }), this._transformListeners.clear(), this._isEventListenersAdded = !1), this._orbit?.dispose(), this._transform?.dispose(), this._transformHelper?.parent && this._transformHelper.parent.remove(this._transformHelper), this._lastHovered = null, super.dispose();
339
- }
340
- render() {
341
- super.render(), this._cameraGizmo.render(this.canvas.width, this.canvas.height);
342
- }
343
- /** Инициализация обработчиков событий на hover/click */
344
- _initMouseListeners() {
345
- this.canvas.addEventListener("mousemove", this._handleMouseMove, !1), this.canvas.addEventListener("click", this._handleMouseClick, !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", () => {
346
- this._orbit.enabled = !this._transform.dragging;
347
- }), this._transform.addEventListener("objectChange", () => {
348
- for (const t of this._transformListeners) t();
349
- }), this._isEventListenersAdded = !0;
350
- }
351
- /** Обработчик события для hover */
352
- _handleMouseMove = (t) => {
353
- this._processRaycastEvent(t, H.SelectHover, !0);
354
- };
355
- /** Обработчик события на click */
356
- _handleMouseClick = (t) => {
357
- this._processRaycastEvent(t, H.SelectClick, !1);
358
- };
359
- /** Вспомогательный метод для получения модели, которую выбрали и отправки события в event bus */
360
- _processRaycastEvent(t, e, s) {
361
- if (this._orbit.isInteracting || this._transform.dragging) return;
362
- const i = this._canvas.getBoundingClientRect();
363
- this._mouse.x = (t.clientX - i.left) / i.width * 2 - 1, this._mouse.y = -((t.clientY - i.top) / i.height) * 2 + 1, this._raycaster.setFromCamera(this._mouse, this.camera);
364
- const o = this._raycaster.intersectObjects(this.meshes, !0)[0] ?? null, n = o?.object ?? null;
365
- s ? n !== this._lastHovered && (this.meshes.forEach((c) => c.userData.isHit = !1), n && (n.userData.isHit = !0), this._lastHovered = n, this._bus.emit(e, o ? { intersection: o } : null)) : this._bus.emit(e, o ? { intersection: o } : null);
366
- }
367
- };
368
- K = pt([
369
- u(),
370
- Ee(0, h("Canvas")),
371
- Ee(1, h("EventBus"))
372
- ], K);
373
- const we = { type: "change" }, ue = { type: "start" }, ze = { type: "end" }, U = new We(), Se = new Fe(), ut = Math.cos(70 * Ze.DEG2RAD), p = new T(), g = 2 * Math.PI, l = {
374
- NONE: -1,
375
- ROTATE: 0,
376
- DOLLY: 1,
377
- PAN: 2,
378
- TOUCH_ROTATE: 3,
379
- TOUCH_PAN: 4,
380
- TOUCH_DOLLY_PAN: 5,
381
- TOUCH_DOLLY_ROTATE: 6
382
- }, B = 1e-6;
383
- class mt extends Ue {
233
+ }
234
+ var dt = Object.getOwnPropertyDescriptor, ut = (e, t, r, s) => {
235
+ for (var i = s > 1 ? void 0 : s ? dt(t, r) : t, o = e.length - 1, n; o >= 0; o--)
236
+ (n = e[o]) && (i = n(i) || i);
237
+ return i;
238
+ }, B = (e, t) => (r, s) => t(r, s, e);
239
+ let se = class {
384
240
  /**
385
- * Constructs a new controls instance.
241
+ * Конструктор контроллера.
386
242
  *
387
- * @param {Object3D} object - The object that is managed by the controls.
388
- * @param {?HTMLElement} domElement - The HTML element used for event listeners.
389
- */
390
- constructor(e, s = null) {
391
- super(e, s), this.state = l.NONE, this.target = new T(), this.cursor = new T(), 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: I.ROTATE, MIDDLE: I.DOLLY, RIGHT: I.PAN }, this.touches = { ONE: R.ROTATE, TWO: R.DOLLY_PAN }, this.target0 = this.target.clone(), this.position0 = this.object.position.clone(), this.zoom0 = this.object.zoom, this._domElementKeyEvents = null, this._lastPosition = new T(), this._lastQuaternion = new ve(), this._lastTargetPosition = new T(), this._quat = new ve().setFromUnitVectors(e.up, new T(0, 1, 0)), this._quatInverse = this._quat.clone().invert(), this._spherical = new ye(), this._sphericalDelta = new ye(), this._scale = 1, this._panOffset = new T(), this._rotateStart = new w(), this._rotateEnd = new w(), this._rotateDelta = new w(), this._panStart = new w(), this._panEnd = new w(), this._panDelta = new w(), this._dollyStart = new w(), this._dollyEnd = new w(), this._dollyDelta = new w(), this._dollyDirection = new T(), this._mouse = new w(), this._performCursorZoom = !1, this._pointers = [], this._pointerPositions = {}, this._controlActive = !1, this._onPointerMove = gt.bind(this), this._onPointerDown = ft.bind(this), this._onPointerUp = bt.bind(this), this._onContextMenu = Pt.bind(this), this._onMouseWheel = Mt.bind(this), this._onKeyDown = Et.bind(this), this._onTouchStart = wt.bind(this), this._onTouchMove = St.bind(this), this._onMouseDown = vt.bind(this), this._onMouseMove = yt.bind(this), this._interceptControlDown = Ot.bind(this), this._interceptControlUp = Tt.bind(this), this.domElement !== null && this.connect(this.domElement), this.update();
392
- }
393
- connect(e) {
394
- 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";
395
- }
396
- disconnect() {
397
- 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";
398
- }
399
- dispose() {
400
- this.disconnect();
401
- }
402
- /**
403
- * Get the current vertical rotation, in radians.
243
+ * @param _updatable - модули, требующие обновления каждый кадр
244
+ * @param _renderable - модули, требующие кастомного рендеринга
245
+ * @param _runtime - модули, требующие инициализации
246
+ * @param _renderer - рендерер (должен реализовывать `IRenderable`)
404
247
  *
405
- * @return {number} The current vertical rotation, in radians.
248
+ * @internal
249
+ * @constructor
406
250
  */
407
- getPolarAngle() {
408
- return this._spherical.phi;
251
+ constructor(e, t, r, s) {
252
+ this._updatable = e, this._renderable = t, this._runtime = r, this._renderer = s;
409
253
  }
410
254
  /**
411
- * Get the current horizontal rotation, in radians.
255
+ * ID анимационного цикла (для остановки)
412
256
  *
413
- * @return {number} The current horizontal rotation, in radians.
257
+ * @private
258
+ * @member
414
259
  */
415
- getAzimuthalAngle() {
416
- return this._spherical.theta;
260
+ _animationId = null;
261
+ start() {
262
+ const e = [...this._runtime, ...this._updatable, ...this._renderable];
263
+ new Set(e).forEach((t) => t.init()), this._loop();
417
264
  }
418
265
  /**
419
- * Returns the distance from the camera to the target.
266
+ * Внутренний анимационный цикл.
420
267
  *
421
- * @return {number} The distance from the camera to the target.
268
+ * @remarks
269
+ * Каждый кадр:
270
+ * 1. Обновляет модули (`update()`)
271
+ * 2. Рендерит сцену
272
+ * 3. Рендерит дополнительные модули (`render()`)
273
+ *
274
+ * @private
275
+ * @method
422
276
  */
423
- getDistance() {
424
- return this.object.position.distanceTo(this.target);
277
+ _loop() {
278
+ this._updatable.forEach((e) => e.update()), this._renderer.render(), this._renderable.forEach((e) => e.render()), this._animationId = requestAnimationFrame(() => this._loop());
279
+ }
280
+ stop() {
281
+ this._animationId && (cancelAnimationFrame(this._animationId), this._animationId = null);
425
282
  }
426
283
  /**
427
- * Adds key event listeners to the given DOM element.
428
- * `window` is a recommended argument for using this method.
284
+ * Освобождает ресурсы контроллера.
429
285
  *
430
- * @param {HTMLElement} domElement - The DOM element
286
+ * @public
287
+ * @method
431
288
  */
432
- listenToKeyEvents(e) {
433
- e.addEventListener("keydown", this._onKeyDown), this._domElementKeyEvents = e;
289
+ dispose() {
290
+ this._animationId = null;
434
291
  }
435
- /**
436
- * Removes the key event listener previously defined with `listenToKeyEvents()`.
437
- */
438
- stopListenToKeyEvents() {
439
- this._domElementKeyEvents !== null && (this._domElementKeyEvents.removeEventListener("keydown", this._onKeyDown), this._domElementKeyEvents = null);
292
+ };
293
+ se = ut([
294
+ d(),
295
+ B(0, D("IUpdatableModule")),
296
+ B(1, D("IRenderableModule")),
297
+ B(2, D("IRuntimeModule")),
298
+ B(3, l("IRenderable"))
299
+ ], se);
300
+ var pt = Object.getOwnPropertyDescriptor, mt = (e, t, r, s) => {
301
+ for (var i = s > 1 ? void 0 : s ? pt(t, r) : t, o = e.length - 1, n; o >= 0; o--)
302
+ (n = e[o]) && (i = n(i) || i);
303
+ return i;
304
+ }, gt = (e, t) => (r, s) => t(r, s, e);
305
+ let re = class {
306
+ /** @constructor */
307
+ constructor(e) {
308
+ this._sceneModule = e;
440
309
  }
441
- /**
442
- * Save the current state of the controls. This can later be recovered with `reset()`.
443
- */
444
- saveState() {
445
- this.target0.copy(this.target), this.position0.copy(this.object.position), this.zoom0 = this.object.zoom;
310
+ addMesh(e) {
311
+ this._sceneModule.addMesh(e);
446
312
  }
447
- /**
448
- * Reset the controls to their state from either the last time the `saveState()`
449
- * was called, or the initial state.
450
- */
451
- reset() {
452
- this.target.copy(this.target0), this.object.position.copy(this.position0), this.object.zoom = this.zoom0, this.object.updateProjectionMatrix(), this.dispatchEvent(we), this.update(), this.state = l.NONE;
453
- }
454
- update(e = null) {
455
- const s = this.object.position;
456
- p.copy(s).sub(this.target), p.applyQuaternion(this._quat), this._spherical.setFromVector3(p), this.autoRotate && this.state === l.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);
457
- let i = this.minAzimuthAngle, r = this.maxAzimuthAngle;
458
- isFinite(i) && isFinite(r) && (i < -Math.PI ? i += g : i > Math.PI && (i -= g), r < -Math.PI ? r += g : r > Math.PI && (r -= g), 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);
459
- let o = !1;
460
- if (this.zoomToCursor && this._performCursorZoom || this.object.isOrthographicCamera)
461
- this._spherical.radius = this._clampDistance(this._spherical.radius);
462
- else {
463
- const n = this._spherical.radius;
464
- this._spherical.radius = this._clampDistance(this._spherical.radius * this._scale), o = n != this._spherical.radius;
465
- }
466
- if (p.setFromSpherical(this._spherical), p.applyQuaternion(this._quatInverse), s.copy(this.target).add(p), 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) {
467
- let n = null;
468
- if (this.object.isPerspectiveCamera) {
469
- const c = p.length();
470
- n = this._clampDistance(c * this._scale);
471
- const _ = c - n;
472
- this.object.position.addScaledVector(this._dollyDirection, _), this.object.updateMatrixWorld(), o = !!_;
473
- } else if (this.object.isOrthographicCamera) {
474
- const c = new T(this._mouse.x, this._mouse.y, 0);
475
- c.unproject(this.object);
476
- const _ = this.object.zoom;
477
- this.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom / this._scale)), this.object.updateProjectionMatrix(), o = _ !== this.object.zoom;
478
- const m = new T(this._mouse.x, this._mouse.y, 0);
479
- m.unproject(this.object), this.object.position.sub(m).add(c), this.object.updateMatrixWorld(), n = p.length();
480
- } else
481
- console.warn("WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled."), this.zoomToCursor = !1;
482
- n !== null && (this.screenSpacePanning ? this.target.set(0, 0, -1).transformDirection(this.object.matrix).multiplyScalar(n).add(this.object.position) : (U.origin.copy(this.object.position), U.direction.set(0, 0, -1).transformDirection(this.object.matrix), Math.abs(this.object.up.dot(U.direction)) < ut ? this.object.lookAt(this.target) : (Se.setFromNormalAndCoplanarPoint(this.object.up, this.target), U.intersectPlane(Se, this.target))));
483
- } else if (this.object.isOrthographicCamera) {
484
- const n = this.object.zoom;
485
- 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);
486
- }
487
- return this._scale = 1, this._performCursorZoom = !1, o || this._lastPosition.distanceToSquared(this.object.position) > B || 8 * (1 - this._lastQuaternion.dot(this.object.quaternion)) > B || this._lastTargetPosition.distanceToSquared(this.target) > B ? (this.dispatchEvent(we), this._lastPosition.copy(this.object.position), this._lastQuaternion.copy(this.object.quaternion), this._lastTargetPosition.copy(this.target), !0) : !1;
313
+ addMeshes(e) {
314
+ this._sceneModule.addMeshes(e);
488
315
  }
489
- _getAutoRotationAngle(e) {
490
- return e !== null ? g / 60 * this.autoRotateSpeed * e : g / 60 / 60 * this.autoRotateSpeed;
316
+ removeMesh(e) {
317
+ this._sceneModule.removeMesh(e);
491
318
  }
492
- _getZoomScale(e) {
493
- const s = Math.abs(e * 0.01);
494
- return Math.pow(0.95, this.zoomSpeed * s);
319
+ removeMeshes(e) {
320
+ this._sceneModule.removeMeshes(e);
495
321
  }
496
- _rotateLeft(e) {
497
- this._sphericalDelta.theta -= e;
322
+ getMeshes() {
323
+ return this._sceneModule.getMeshes();
498
324
  }
499
- _rotateUp(e) {
500
- this._sphericalDelta.phi -= e;
325
+ };
326
+ re = mt([
327
+ d(),
328
+ gt(0, l("SceneModule"))
329
+ ], re);
330
+ var vt = Object.getOwnPropertyDescriptor, ft = (e, t, r, s) => {
331
+ for (var i = s > 1 ? void 0 : s ? vt(t, r) : t, o = e.length - 1, n; o >= 0; o--)
332
+ (n = e[o]) && (i = n(i) || i);
333
+ return i;
334
+ }, Mt = (e, t) => (r, s) => t(r, s, e);
335
+ let ie = class {
336
+ /** @constructor */
337
+ constructor(e) {
338
+ this._raycastModule = e;
501
339
  }
502
- _panLeft(e, s) {
503
- p.setFromMatrixColumn(s, 0), p.multiplyScalar(-e), this._panOffset.add(p);
340
+ setRaycastMode(e) {
341
+ this._raycastModule.setRaycastMode(e);
504
342
  }
505
- _panUp(e, s) {
506
- this.screenSpacePanning === !0 ? p.setFromMatrixColumn(s, 1) : (p.setFromMatrixColumn(s, 0), p.crossVectors(this.object.up, p)), p.multiplyScalar(e), this._panOffset.add(p);
343
+ };
344
+ ie = ft([
345
+ d(),
346
+ Mt(0, l("RaycastModule"))
347
+ ], ie);
348
+ var yt = Object.getOwnPropertyDescriptor, bt = (e, t, r, s) => {
349
+ for (var i = s > 1 ? void 0 : s ? yt(t, r) : t, o = e.length - 1, n; o >= 0; o--)
350
+ (n = e[o]) && (i = n(i) || i);
351
+ return i;
352
+ }, St = (e, t) => (r, s) => t(r, s, e);
353
+ let oe = class {
354
+ /** @constructor */
355
+ constructor(e) {
356
+ this._controlsModule = e;
507
357
  }
508
- // deltaX and deltaY are in pixels; right and down are positive
509
- _pan(e, s) {
510
- const i = this.domElement;
511
- if (this.object.isPerspectiveCamera) {
512
- const r = this.object.position;
513
- p.copy(r).sub(this.target);
514
- let o = p.length();
515
- 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);
516
- } 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);
358
+ attachTransform(e) {
359
+ this._controlsModule.attachTransform(e);
517
360
  }
518
- _dollyOut(e) {
519
- 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);
361
+ detachTransform() {
362
+ this._controlsModule.detachTransform();
520
363
  }
521
- _dollyIn(e) {
522
- 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);
364
+ setTransformMode(e) {
365
+ this._controlsModule.setTransformMode(e);
523
366
  }
524
- _updateZoomParameters(e, s) {
525
- if (!this.zoomToCursor)
526
- return;
527
- this._performCursorZoom = !0;
528
- const i = this.domElement.getBoundingClientRect(), r = e - i.left, o = s - i.top, n = i.width, c = i.height;
529
- this._mouse.x = r / n * 2 - 1, this._mouse.y = -(o / c) * 2 + 1, this._dollyDirection.set(this._mouse.x, this._mouse.y, 1).unproject(this.object).sub(this.object.position).normalize();
367
+ onTransformChange(e) {
368
+ return this._controlsModule.onTransformChange(e);
530
369
  }
531
- _clampDistance(e) {
532
- return Math.max(this.minDistance, Math.min(this.maxDistance, e));
370
+ };
371
+ oe = bt([
372
+ d(),
373
+ St(0, l("ControlsModule"))
374
+ ], oe);
375
+ var At = Object.getOwnPropertyDescriptor, wt = (e, t, r, s) => {
376
+ for (var i = s > 1 ? void 0 : s ? At(t, r) : t, o = e.length - 1, n; o >= 0; o--)
377
+ (n = e[o]) && (i = n(i) || i);
378
+ return i;
379
+ }, xt = (e, t) => (r, s) => t(r, s, e);
380
+ let ne = class {
381
+ constructor(e) {
382
+ this._cameraAccessApi = e;
533
383
  }
534
- //
535
- // event callbacks - update the object state
536
- //
537
- _handleMouseDownRotate(e) {
538
- this._rotateStart.set(e.clientX, e.clientY);
384
+ getCamera() {
385
+ return this._cameraAccessApi.getCamera();
539
386
  }
540
- _handleMouseDownDolly(e) {
541
- this._updateZoomParameters(e.clientX, e.clientX), this._dollyStart.set(e.clientX, e.clientY);
387
+ enableCameraLayer(e) {
388
+ this._cameraAccessApi.getCamera().layers.enable(e);
542
389
  }
543
- _handleMouseDownPan(e) {
544
- this._panStart.set(e.clientX, e.clientY);
390
+ disableCameraLayer(e) {
391
+ this._cameraAccessApi.getCamera().layers.disable(e);
545
392
  }
546
- _handleMouseMoveRotate(e) {
547
- this._rotateEnd.set(e.clientX, e.clientY), this._rotateDelta.subVectors(this._rotateEnd, this._rotateStart).multiplyScalar(this.rotateSpeed);
548
- const s = this.domElement;
549
- this._rotateLeft(g * this._rotateDelta.x / s.clientHeight), this._rotateUp(g * this._rotateDelta.y / s.clientHeight), this._rotateStart.copy(this._rotateEnd), this.update();
393
+ };
394
+ ne = wt([
395
+ d(),
396
+ xt(0, l("IRendererCameraAccess"))
397
+ ], ne);
398
+ var Ot = Object.getOwnPropertyDescriptor, Ct = (e, t, r, s) => {
399
+ for (var i = s > 1 ? void 0 : s ? Ot(t, r) : t, o = e.length - 1, n; o >= 0; o--)
400
+ (n = e[o]) && (i = n(i) || i);
401
+ return i;
402
+ }, It = (e, t) => (r, s) => t(r, s, e);
403
+ let ae = class {
404
+ constructor(e) {
405
+ this._domAccessApi = e;
550
406
  }
551
- _handleMouseMoveDolly(e) {
552
- 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();
407
+ getCanvas() {
408
+ return this._domAccessApi.getCanvas();
553
409
  }
554
- _handleMouseMovePan(e) {
555
- 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();
410
+ getDomElement() {
411
+ return this._domAccessApi.getDomElement();
556
412
  }
557
- _handleMouseWheel(e) {
558
- 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();
413
+ };
414
+ ae = Ct([
415
+ d(),
416
+ It(0, l("IRendererDomAccess"))
417
+ ], ae);
418
+ var Pt = Object.getOwnPropertyDescriptor, Lt = (e, t, r, s) => {
419
+ for (var i = s > 1 ? void 0 : s ? Pt(t, r) : t, o = e.length - 1, n; o >= 0; o--)
420
+ (n = e[o]) && (i = n(i) || i);
421
+ return i;
422
+ }, Et = (e, t) => (r, s) => t(r, s, e);
423
+ let ce = class {
424
+ constructor(e) {
425
+ this._sceneAccessApi = e;
559
426
  }
560
- _handleKeyDown(e) {
561
- let s = !1;
562
- switch (e.code) {
563
- case this.keys.UP:
564
- e.ctrlKey || e.metaKey || e.shiftKey ? this.enableRotate && this._rotateUp(g * this.keyRotateSpeed / this.domElement.clientHeight) : this.enablePan && this._pan(0, this.keyPanSpeed), s = !0;
565
- break;
566
- case this.keys.BOTTOM:
567
- e.ctrlKey || e.metaKey || e.shiftKey ? this.enableRotate && this._rotateUp(-g * this.keyRotateSpeed / this.domElement.clientHeight) : this.enablePan && this._pan(0, -this.keyPanSpeed), s = !0;
568
- break;
569
- case this.keys.LEFT:
570
- e.ctrlKey || e.metaKey || e.shiftKey ? this.enableRotate && this._rotateLeft(g * this.keyRotateSpeed / this.domElement.clientHeight) : this.enablePan && this._pan(this.keyPanSpeed, 0), s = !0;
571
- break;
572
- case this.keys.RIGHT:
573
- e.ctrlKey || e.metaKey || e.shiftKey ? this.enableRotate && this._rotateLeft(-g * this.keyRotateSpeed / this.domElement.clientHeight) : this.enablePan && this._pan(-this.keyPanSpeed, 0), s = !0;
574
- break;
575
- }
576
- s && (e.preventDefault(), this.update());
577
- }
578
- _handleTouchStartRotate(e) {
579
- if (this._pointers.length === 1)
580
- this._rotateStart.set(e.pageX, e.pageY);
581
- else {
582
- const s = this._getSecondPointerPosition(e), i = 0.5 * (e.pageX + s.x), r = 0.5 * (e.pageY + s.y);
583
- this._rotateStart.set(i, r);
584
- }
427
+ getScene() {
428
+ return this._sceneAccessApi.getScene();
585
429
  }
586
- _handleTouchStartPan(e) {
587
- if (this._pointers.length === 1)
588
- this._panStart.set(e.pageX, e.pageY);
589
- else {
590
- const s = this._getSecondPointerPosition(e), i = 0.5 * (e.pageX + s.x), r = 0.5 * (e.pageY + s.y);
591
- this._panStart.set(i, r);
592
- }
430
+ addToScene(e) {
431
+ this._sceneAccessApi.getScene().add(e);
593
432
  }
594
- _handleTouchStartDolly(e) {
595
- const s = this._getSecondPointerPosition(e), i = e.pageX - s.x, r = e.pageY - s.y, o = Math.sqrt(i * i + r * r);
596
- this._dollyStart.set(0, o);
433
+ removeFromScene(e) {
434
+ this._sceneAccessApi.getScene().remove(e);
597
435
  }
598
- _handleTouchStartDollyPan(e) {
599
- this.enableZoom && this._handleTouchStartDolly(e), this.enablePan && this._handleTouchStartPan(e);
436
+ addObject(e, t) {
437
+ const r = this._sceneAccessApi.getScene();
438
+ r && (typeof t == "number" && e.layers.set(t), r.add(e));
600
439
  }
601
- _handleTouchStartDollyRotate(e) {
602
- this.enableZoom && this._handleTouchStartDolly(e), this.enableRotate && this._handleTouchStartRotate(e);
440
+ };
441
+ ce = Lt([
442
+ d(),
443
+ Et(0, l("IRendererSceneAccess"))
444
+ ], ce);
445
+ var Tt = Object.getOwnPropertyDescriptor, Dt = (e, t, r, s) => {
446
+ for (var i = s > 1 ? void 0 : s ? Tt(t, r) : t, o = e.length - 1, n; o >= 0; o--)
447
+ (n = e[o]) && (i = n(i) || i);
448
+ return i;
449
+ }, Vt = (e, t) => (r, s) => t(r, s, e);
450
+ let le = class {
451
+ /** @constructor */
452
+ constructor(e) {
453
+ this._controlsModule = e;
603
454
  }
604
- _handleTouchMoveRotate(e) {
605
- if (this._pointers.length == 1)
606
- this._rotateEnd.set(e.pageX, e.pageY);
607
- else {
608
- const i = this._getSecondPointerPosition(e), r = 0.5 * (e.pageX + i.x), o = 0.5 * (e.pageY + i.y);
609
- this._rotateEnd.set(r, o);
610
- }
611
- this._rotateDelta.subVectors(this._rotateEnd, this._rotateStart).multiplyScalar(this.rotateSpeed);
612
- const s = this.domElement;
613
- this._rotateLeft(g * this._rotateDelta.x / s.clientHeight), this._rotateUp(g * this._rotateDelta.y / s.clientHeight), this._rotateStart.copy(this._rotateEnd);
614
- }
615
- _handleTouchMovePan(e) {
616
- if (this._pointers.length === 1)
617
- this._panEnd.set(e.pageX, e.pageY);
618
- else {
619
- const s = this._getSecondPointerPosition(e), i = 0.5 * (e.pageX + s.x), r = 0.5 * (e.pageY + s.y);
620
- this._panEnd.set(i, r);
621
- }
622
- this._panDelta.subVectors(this._panEnd, this._panStart).multiplyScalar(this.panSpeed), this._pan(this._panDelta.x, this._panDelta.y), this._panStart.copy(this._panEnd);
455
+ isOrbitInteracting() {
456
+ return this._controlsModule.isOrbitInteracting();
623
457
  }
624
- _handleTouchMoveDolly(e) {
625
- const s = this._getSecondPointerPosition(e), i = e.pageX - s.x, r = e.pageY - s.y, o = Math.sqrt(i * i + r * r);
626
- 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);
627
- const n = (e.pageX + s.x) * 0.5, c = (e.pageY + s.y) * 0.5;
628
- this._updateZoomParameters(n, c);
458
+ isTransformDragging() {
459
+ return this._controlsModule.isTransformDragging();
629
460
  }
630
- _handleTouchMoveDollyPan(e) {
631
- this.enableZoom && this._handleTouchMoveDolly(e), this.enablePan && this._handleTouchMovePan(e);
461
+ };
462
+ le = Dt([
463
+ d(),
464
+ Vt(0, l("ControlsModule"))
465
+ ], le);
466
+ var $t = Object.getOwnPropertyDescriptor, jt = (e, t, r, s) => {
467
+ for (var i = s > 1 ? void 0 : s ? $t(t, r) : t, o = e.length - 1, n; o >= 0; o--)
468
+ (n = e[o]) && (i = n(i) || i);
469
+ return i;
470
+ }, K = (e, t) => (r, s) => t(r, s, e);
471
+ let he = class {
472
+ constructor(e, t, r) {
473
+ this._cameraApi = e, this._domApi = t, this._sceneApi = r;
632
474
  }
633
- _handleTouchMoveDollyRotate(e) {
634
- this.enableZoom && this._handleTouchMoveDolly(e), this.enableRotate && this._handleTouchMoveRotate(e);
475
+ /** Orbit-контроллер для управления камерой */
476
+ _orbit = null;
477
+ /** Transform-контроллер для редактирования */
478
+ _transform = null;
479
+ _transformHelper = null;
480
+ _transformListeners = /* @__PURE__ */ new Set();
481
+ /** Были ли инициализированы обработчики событий (hover/click) */
482
+ _isEventListenersAdded = !1;
483
+ init() {
484
+ this._orbit = new rt(this._cameraApi.getCamera(), this._domApi.getDomElement()), this._orbit.enableDamping = !0, this._orbit.dampingFactor = 0.05, this._transform = new it(
485
+ this._cameraApi.getCamera(),
486
+ this._domApi.getDomElement()
487
+ ), this._transformHelper = this._transform.getHelper(), this._sceneApi.addToScene(this._transformHelper), this._initMouseListeners();
635
488
  }
636
- // pointers
637
- _addPointer(e) {
638
- this._pointers.push(e.pointerId);
489
+ attachTransform(e) {
490
+ this._transform?.attach(e);
639
491
  }
640
- _removePointer(e) {
641
- delete this._pointerPositions[e.pointerId];
642
- for (let s = 0; s < this._pointers.length; s++)
643
- if (this._pointers[s] == e.pointerId) {
644
- this._pointers.splice(s, 1);
645
- return;
646
- }
492
+ detachTransform() {
493
+ this._transform?.detach();
647
494
  }
648
- _isTrackingPointer(e) {
649
- for (let s = 0; s < this._pointers.length; s++)
650
- if (this._pointers[s] == e.pointerId) return !0;
651
- return !1;
495
+ update() {
496
+ this._orbit?.update();
652
497
  }
653
- _trackPointer(e) {
654
- let s = this._pointerPositions[e.pointerId];
655
- s === void 0 && (s = new w(), this._pointerPositions[e.pointerId] = s), s.set(e.pageX, e.pageY);
498
+ setTransformMode(e) {
499
+ this._transform?.setMode(e);
656
500
  }
657
- _getSecondPointerPosition(e) {
658
- const s = e.pointerId === this._pointers[0] ? this._pointers[1] : this._pointers[0];
659
- return this._pointerPositions[s];
501
+ onTransformChange(e) {
502
+ return this._transformListeners.add(e), () => this._transformListeners.delete(e);
660
503
  }
661
- //
662
- _customWheelEvent(e) {
663
- const s = e.deltaMode, i = {
664
- clientX: e.clientX,
665
- clientY: e.clientY,
666
- deltaY: e.deltaY
667
- };
668
- switch (s) {
669
- case 1:
670
- i.deltaY *= 16;
671
- break;
672
- case 2:
673
- i.deltaY *= 100;
674
- break;
504
+ isOrbitInteracting() {
505
+ return !!this._orbit?.isInteracting;
506
+ }
507
+ isTransformDragging() {
508
+ return !!this._transform?.dragging;
509
+ }
510
+ /** Освобождает ресурсы модуля */
511
+ dispose() {
512
+ if (this._isEventListenersAdded) {
513
+ const e = this._domApi.getCanvas();
514
+ if (!this._transform || !this._orbit) return;
515
+ e.removeEventListener("pointerdown", (t) => this._transform?.pointerDown(t)), e.removeEventListener("pointermove", (t) => this._transform?.pointerMove(t)), e.removeEventListener("pointerup", (t) => this._transform?.pointerUp(t)), e.removeEventListener("pointerleave", () => this._transform?.pointerHover(null)), this._transform.removeEventListener("dragging-changed", () => {
516
+ this._orbit.enabled = !this._transform?.dragging;
517
+ }), this._transformListeners.clear(), this._isEventListenersAdded = !1;
675
518
  }
676
- return e.ctrlKey && !this._controlActive && (i.deltaY *= 10), i;
519
+ this._orbit?.dispose(), this._orbit = null, this._transform?.dispose(), this._transform = null, this._transformHelper?.parent && this._transformHelper.parent.remove(this._transformHelper);
677
520
  }
678
- }
679
- function ft(t) {
680
- 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)));
681
- }
682
- function gt(t) {
683
- this.enabled !== !1 && (t.pointerType === "touch" ? this._onTouchMove(t) : this._onMouseMove(t));
684
- }
685
- function bt(t) {
686
- switch (this._removePointer(t), this._pointers.length) {
687
- case 0:
688
- this.domElement.releasePointerCapture(t.pointerId), this.domElement.removeEventListener("pointermove", this._onPointerMove), this.domElement.removeEventListener("pointerup", this._onPointerUp), this.dispatchEvent(ze), this.state = l.NONE;
689
- break;
690
- case 1:
691
- const e = this._pointers[0], s = this._pointerPositions[e];
692
- this._onTouchStart({ pointerId: e, pageX: s.x, pageY: s.y });
693
- break;
521
+ /** Инициализация обработчиков событий на hover/click */
522
+ _initMouseListeners() {
523
+ const e = this._domApi.getCanvas();
524
+ !this._transform || !this._orbit || (e.addEventListener("pointerdown", (t) => this._transform?.pointerDown(t)), e.addEventListener("pointermove", (t) => this._transform?.pointerMove(t)), e.addEventListener("pointerup", (t) => this._transform?.pointerUp(t)), e.addEventListener("pointerleave", () => this._transform?.pointerHover(null)), this._transform.addEventListener("dragging-changed", () => {
525
+ this._orbit.enabled = !this._transform?.dragging;
526
+ }), this._transform.addEventListener("objectChange", () => {
527
+ for (const t of this._transformListeners) t();
528
+ }), this._isEventListenersAdded = !0);
694
529
  }
695
- }
696
- function vt(t) {
697
- let e;
698
- switch (t.button) {
699
- case 0:
700
- e = this.mouseButtons.LEFT;
701
- break;
702
- case 1:
703
- e = this.mouseButtons.MIDDLE;
704
- break;
705
- case 2:
706
- e = this.mouseButtons.RIGHT;
707
- break;
708
- default:
709
- e = -1;
710
- }
711
- switch (e) {
712
- case I.DOLLY:
713
- if (this.enableZoom === !1) return;
714
- this._handleMouseDownDolly(t), this.state = l.DOLLY;
715
- break;
716
- case I.ROTATE:
717
- if (t.ctrlKey || t.metaKey || t.shiftKey) {
718
- if (this.enablePan === !1) return;
719
- this._handleMouseDownPan(t), this.state = l.PAN;
720
- } else {
721
- if (this.enableRotate === !1) return;
722
- this._handleMouseDownRotate(t), this.state = l.ROTATE;
723
- }
724
- break;
725
- case I.PAN:
726
- if (t.ctrlKey || t.metaKey || t.shiftKey) {
727
- if (this.enableRotate === !1) return;
728
- this._handleMouseDownRotate(t), this.state = l.ROTATE;
729
- } else {
730
- if (this.enablePan === !1) return;
731
- this._handleMouseDownPan(t), this.state = l.PAN;
732
- }
733
- break;
734
- default:
735
- this.state = l.NONE;
530
+ };
531
+ he = jt([
532
+ d(),
533
+ K(0, l("ICameraApi")),
534
+ K(1, l("IDomApi")),
535
+ K(2, l("ISceneApi"))
536
+ ], he);
537
+ var Ht = Object.getOwnPropertyDescriptor, Rt = (e, t, r, s) => {
538
+ for (var i = s > 1 ? void 0 : s ? Ht(t, r) : t, o = e.length - 1, n; o >= 0; o--)
539
+ (n = e[o]) && (i = n(i) || i);
540
+ return i;
541
+ }, Q = (e, t) => (r, s) => t(r, s, e);
542
+ let _e = class {
543
+ constructor(e, t, r) {
544
+ this._cameraApi = e, this._domApi = t, this._rendererApi = r;
736
545
  }
737
- this.state !== l.NONE && this.dispatchEvent(ue);
738
- }
739
- function yt(t) {
740
- switch (this.state) {
741
- case l.ROTATE:
742
- if (this.enableRotate === !1) return;
743
- this._handleMouseMoveRotate(t);
744
- break;
745
- case l.DOLLY:
746
- if (this.enableZoom === !1) return;
747
- this._handleMouseMoveDolly(t);
748
- break;
749
- case l.PAN:
750
- if (this.enablePan === !1) return;
751
- this._handleMouseMovePan(t);
752
- break;
546
+ /** Gizmo для управления отображением perspective camera */
547
+ _cameraGizmo = null;
548
+ init() {
549
+ const e = this._cameraApi.getCamera(), t = this._rendererApi.getRenderer();
550
+ this._cameraGizmo = new ot(t, e, {
551
+ size: 96,
552
+ // Размер квадрата
553
+ margin: 36
554
+ // Отступы по сторонам (снизу и справа)
555
+ });
753
556
  }
754
- }
755
- function Mt(t) {
756
- this.enabled === !1 || this.enableZoom === !1 || this.state !== l.NONE || (t.preventDefault(), this.dispatchEvent(ue), this._handleMouseWheel(this._customWheelEvent(t)), this.dispatchEvent(ze));
757
- }
758
- function Et(t) {
759
- this.enabled !== !1 && this._handleKeyDown(t);
760
- }
761
- function wt(t) {
762
- switch (this._trackPointer(t), this._pointers.length) {
763
- case 1:
764
- switch (this.touches.ONE) {
765
- case R.ROTATE:
766
- if (this.enableRotate === !1) return;
767
- this._handleTouchStartRotate(t), this.state = l.TOUCH_ROTATE;
768
- break;
769
- case R.PAN:
770
- if (this.enablePan === !1) return;
771
- this._handleTouchStartPan(t), this.state = l.TOUCH_PAN;
772
- break;
773
- default:
774
- this.state = l.NONE;
775
- }
776
- break;
777
- case 2:
778
- switch (this.touches.TWO) {
779
- case R.DOLLY_PAN:
780
- if (this.enableZoom === !1 && this.enablePan === !1) return;
781
- this._handleTouchStartDollyPan(t), this.state = l.TOUCH_DOLLY_PAN;
782
- break;
783
- case R.DOLLY_ROTATE:
784
- if (this.enableZoom === !1 && this.enableRotate === !1) return;
785
- this._handleTouchStartDollyRotate(t), this.state = l.TOUCH_DOLLY_ROTATE;
786
- break;
787
- default:
788
- this.state = l.NONE;
789
- }
790
- break;
791
- default:
792
- this.state = l.NONE;
557
+ render() {
558
+ const e = this._domApi.getCanvas();
559
+ this._cameraGizmo?.render(e.width, e.height);
793
560
  }
794
- this.state !== l.NONE && this.dispatchEvent(ue);
795
- }
796
- function St(t) {
797
- switch (this._trackPointer(t), this.state) {
798
- case l.TOUCH_ROTATE:
799
- if (this.enableRotate === !1) return;
800
- this._handleTouchMoveRotate(t), this.update();
801
- break;
802
- case l.TOUCH_PAN:
803
- if (this.enablePan === !1) return;
804
- this._handleTouchMovePan(t), this.update();
805
- break;
806
- case l.TOUCH_DOLLY_PAN:
807
- if (this.enableZoom === !1 && this.enablePan === !1) return;
808
- this._handleTouchMoveDollyPan(t), this.update();
809
- break;
810
- case l.TOUCH_DOLLY_ROTATE:
811
- if (this.enableZoom === !1 && this.enableRotate === !1) return;
812
- this._handleTouchMoveDollyRotate(t), this.update();
813
- break;
814
- default:
815
- this.state = l.NONE;
561
+ /** Освобождение ресурсов модуля */
562
+ dispose() {
563
+ this._cameraGizmo?.dispose(), this._cameraGizmo = null;
816
564
  }
817
- }
818
- function Pt(t) {
819
- this.enabled !== !1 && t.preventDefault();
820
- }
821
- function Ot(t) {
822
- t.key === "Control" && (this._controlActive = !0, this.domElement.getRootNode().addEventListener("keyup", this._interceptControlUp, { passive: !0, capture: !0 }));
823
- }
824
- function Tt(t) {
825
- t.key === "Control" && (this._controlActive = !1, this.domElement.getRootNode().removeEventListener("keyup", this._interceptControlUp, { passive: !0, capture: !0 }));
826
- }
827
- class Es extends He {
828
- /** Orbit-контроллер для управления камерой */
829
- _orbit;
830
- constructor(e) {
831
- super(e), this.camera.position.set(1, 1, 7), this.camera.lookAt(0, 0, 0), this._orbit = new mt(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;
565
+ };
566
+ _e = Rt([
567
+ d(),
568
+ Q(0, l("ICameraApi")),
569
+ Q(1, l("IDomApi")),
570
+ Q(2, l("IRendererAccess"))
571
+ ], _e);
572
+ var V = /* @__PURE__ */ ((e) => (e.SelectHover = "select.hover", e.SelectClick = "select.click", e))(V || {});
573
+ const Ft = 0.03, Wt = 0.05, k = 0, Ue = 1, Xe = 2, x = 31;
574
+ var kt = Object.getOwnPropertyDescriptor, Gt = (e, t, r, s) => {
575
+ for (var i = s > 1 ? void 0 : s ? kt(t, r) : t, o = e.length - 1, n; o >= 0; o--)
576
+ (n = e[o]) && (i = n(i) || i);
577
+ return i;
578
+ }, R = (e, t) => (r, s) => t(r, s, e);
579
+ let de = class {
580
+ constructor(e, t, r, s, i) {
581
+ this._domApi = e, this._cameraApi = t, this._meshApi = r, this._controlsState = s, this._bus = i;
832
582
  }
833
583
  /**
834
- * Обновление состояния рендерера.
584
+ * Raycast для получения событий наведения/клика по модели
585
+ *
586
+ * @private
587
+ * @member
835
588
  */
836
- update() {
837
- this._orbit?.update();
838
- }
839
- }
840
- class ws {
841
- /** Позиции вершин */
842
- _positions = [];
843
- /** Нормали вершин */
844
- _normals = [];
845
- /** UV-координаты (опционально) */
846
- _uvs = [];
847
- // Временные поля для парсинга файла
848
- _tmpPositions = [];
849
- _tmpNormals = [];
850
- _tmpUVs = [];
589
+ _raycaster;
851
590
  /**
852
- * Загружает OBJ-модель в Figure
853
- * @param objContent - Строка содержимого .obj файла
591
+ * Курсор мыши
592
+ *
593
+ * @private
594
+ * @member
854
595
  */
855
- load(e) {
856
- const s = e.split(`
857
- `);
858
- for (const r of s) {
859
- if (!r.trim() || r.startsWith("#")) continue;
860
- const o = r.trim().split(/\s+/);
861
- switch (o[0]) {
862
- case "v":
863
- this._tmpPositions.push(o.slice(1).map(Number));
864
- break;
865
- case "vn":
866
- this._tmpNormals.push(o.slice(1).map(Number));
867
- break;
868
- case "vt":
869
- this._tmpUVs.push(o.slice(1).map(Number));
870
- break;
871
- case "f":
872
- this.processFaceLine(o);
873
- break;
596
+ _mouse;
597
+ /**
598
+ * Ключ последней модели, на которую наводились,
599
+ * необходим для отправки только уникальных событий в event bus
600
+ *
601
+ * @private
602
+ * @member
603
+ */
604
+ _lastHoverKey = null;
605
+ /**
606
+ * Текуший режим для raycaster
607
+ *
608
+ * @private
609
+ * @member
610
+ */
611
+ _currentRaycastMode = M.Mesh;
612
+ /**
613
+ * Были ли инициализированы обработчики событий (hover/click)
614
+ *
615
+ * @private
616
+ * @member
617
+ */
618
+ _isEventListenersAdded = !1;
619
+ init() {
620
+ this._raycaster = new a.Raycaster(), this._mouse = new a.Vector2(), this._applyRaycastParamsByMode(), this._isEventListenersAdded || (this._initMouseListeners(), this._isEventListenersAdded = !0);
621
+ }
622
+ setRaycastMode(e) {
623
+ if (this._currentRaycastMode === e) return;
624
+ const t = this._raycaster;
625
+ t.params.Line.threshold = 0, t.params.Points.threshold = 0, this._currentRaycastMode = e, this._lastHoverKey = null, this._applyRaycastParamsByMode();
626
+ }
627
+ /** Применяет параметры raycaster в зависимости от текущего режима */
628
+ _applyRaycastParamsByMode() {
629
+ const e = this._raycaster;
630
+ switch (e.params.Line.threshold = 0, e.params.Points.threshold = 0, this._currentRaycastMode) {
631
+ case M.Mesh:
632
+ case M.Face:
633
+ e.layers.set(k);
634
+ break;
635
+ case M.Edge:
636
+ e.layers.set(Ue), e.params.Line.threshold = Ft;
637
+ break;
638
+ case M.Vertex:
639
+ e.layers.set(Xe), e.params.Points.threshold = Wt;
640
+ break;
641
+ }
642
+ }
643
+ /** Возвращает ближайшее пересечение по текущему положению курсора */
644
+ _getHitIntersection(e) {
645
+ const t = this._controlsState.isOrbitInteracting() || this._controlsState.isTransformDragging(), r = this._domApi.getCanvas(), s = this._cameraApi.getCamera(), i = this._meshApi.getMeshes();
646
+ if (t) return;
647
+ const o = r.getBoundingClientRect();
648
+ this._mouse.x = (e.clientX - o.left) / o.width * 2 - 1, this._mouse.y = -((e.clientY - o.top) / o.height) * 2 + 1, this._raycaster.setFromCamera(this._mouse, s);
649
+ const n = this._raycaster.intersectObjects(i, !0)[0] ?? null;
650
+ if (this._currentRaycastMode === M.Mesh || this._currentRaycastMode === M.Face)
651
+ return n;
652
+ const c = this._raycaster.layers.mask;
653
+ this._raycaster.layers.set(k);
654
+ const _ = this._raycaster.intersectObjects(i, !0)[0] ?? null;
655
+ return this._raycaster.layers.mask = c, this._getVisibleHit(n, _);
656
+ }
657
+ // Hover сравнивается не только по object, но и по режимному ключу попадания.
658
+ // Это нужно для Face/Edge/Vertex режимов, где разные элементы могут принадлежать одному и тому же Object3D.
659
+ /** Вспомогательный метод для получения модели, которую выбрали и отправки события в event bus */
660
+ _processRaycastEvent(e, t, r) {
661
+ const s = this._getHitIntersection(e), i = this._meshApi.getMeshes();
662
+ if (s === void 0) return;
663
+ const o = s?.object ?? null;
664
+ if (r) {
665
+ if (!s) {
666
+ i.forEach((c) => c.userData.isHit = !1), this._lastHoverKey = null, this._bus.emit(t, null);
667
+ return;
874
668
  }
669
+ const n = this._makeHoverKey(s);
670
+ n !== this._lastHoverKey && (i.forEach((c) => c.userData.isHit = !1), o && (o.userData.isHit = !0), this._lastHoverKey = n, this._bus.emit(t, { intersection: s }));
671
+ return;
875
672
  }
876
- const i = {
877
- type: S.Custom,
878
- position: this._positions,
879
- ...this._normals.length > 0 && { normal: this._normals },
880
- ...this._uvs.length > 0 && { uv: this._uvs }
881
- };
882
- return new $e(i);
673
+ s && this._bus.emit(t, { intersection: s });
883
674
  }
884
- /**
885
- * Обрабатывает строку face (f) и разворачивает индексы в массивы для рендеринга
675
+ /** Поиск видимой части меша
676
+ * необходимо это для того, чтобы отправлять только видимые элементы модели, а не все попадания
886
677
  */
887
- processFaceLine(e) {
888
- for (let s = 1; s < e.length; s++) {
889
- const i = e[s];
890
- if (!i) continue;
891
- const [r, o, n] = i.split("/"), c = r ? parseInt(r, 10) : void 0, _ = o ? parseInt(o, 10) : void 0, m = n ? parseInt(n, 10) : void 0;
892
- if (c !== void 0) {
893
- const f = this._tmpPositions[c - 1];
894
- f && this._positions.push(...f);
895
- }
896
- if (_ !== void 0) {
897
- const f = this._tmpUVs[_ - 1];
898
- f && this._uvs.push(...f);
899
- }
900
- if (m !== void 0) {
901
- const f = this._tmpNormals[m - 1];
902
- f && this._normals.push(...f);
903
- }
678
+ _getVisibleHit(e, t, r = 1e-4) {
679
+ return e ? t ? e.distance <= t.distance + r ? e : null : e : null;
680
+ }
681
+ /** Строит ключ hover-пересечения с учетом текущего режима выборки */
682
+ _makeHoverKey(e) {
683
+ if (!e) return null;
684
+ const t = e.object.uuid;
685
+ switch (this._currentRaycastMode) {
686
+ case M.Face:
687
+ return `${t}:face:${e.faceIndex ?? -1}`;
688
+ case M.Edge:
689
+ return `${t}:edge:${Math.floor((e.index ?? -1) / 2)}`;
690
+ case M.Vertex:
691
+ return `${t}:vertex:${e.index ?? -1}`;
692
+ case M.Mesh:
693
+ default:
694
+ return `${t}:mesh`;
904
695
  }
905
696
  }
906
- }
907
- var Lt = Object.getOwnPropertyDescriptor, Dt = (t, e, s, i) => {
908
- for (var r = i > 1 ? void 0 : i ? Lt(e, s) : e, o = t.length - 1, n; o >= 0; o--)
909
- (n = t[o]) && (r = n(r) || r);
910
- return r;
911
- }, Pe = (t, e) => (s, i) => e(s, i, t);
912
- let q = class {
913
- constructor(t, e) {
914
- this._store = e, this._handlers = new Map(t.map((s) => [s.mode, s]));
697
+ /** Обработчик события для hover */
698
+ _handleMouseMove = (e) => {
699
+ this._processRaycastEvent(e, V.SelectHover, !0);
700
+ };
701
+ /** Обработчик события на click */
702
+ _handleMouseClick = (e) => {
703
+ this._processRaycastEvent(e, V.SelectClick, !1);
704
+ };
705
+ /** Обработчик двойного клика */
706
+ _handleDoubleClick = (e) => {
707
+ const t = this._getHitIntersection(e);
708
+ t !== void 0 && (t || this._bus.emit(V.SelectClick, null));
709
+ };
710
+ /** Обработчик ухода курсора с canvas */
711
+ _handleMouseLeave = () => {
712
+ this._lastHoverKey = null, this._bus.emit(V.SelectHover, null);
713
+ };
714
+ /** Инициализация обработчиков событий на hover/click */
715
+ _initMouseListeners() {
716
+ const e = this._domApi.getCanvas();
717
+ 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;
718
+ }
719
+ _removeMouseListeners() {
720
+ const e = this._domApi.getCanvas();
721
+ e.removeEventListener("mousemove", this._handleMouseMove), e.removeEventListener("click", this._handleMouseClick), e.removeEventListener("dblclick", this._handleDoubleClick), e.removeEventListener("mouseleave", this._handleMouseLeave);
722
+ }
723
+ dispose() {
724
+ this._removeMouseListeners(), this._isEventListenersAdded = !1, this._lastHoverKey = null;
725
+ }
726
+ };
727
+ de = Gt([
728
+ d(),
729
+ R(0, l("IDomApi")),
730
+ R(1, l("ICameraApi")),
731
+ R(2, l("IMeshApi")),
732
+ R(3, l("IControlsStateApi")),
733
+ R(4, l("EventBus"))
734
+ ], de);
735
+ var Bt = Object.getOwnPropertyDescriptor, zt = (e, t, r, s) => {
736
+ for (var i = s > 1 ? void 0 : s ? Bt(t, r) : t, o = e.length - 1, n; o >= 0; o--)
737
+ (n = e[o]) && (i = n(i) || i);
738
+ return i;
739
+ }, Nt = (e, t) => (r, s) => t(r, s, e);
740
+ let ue = class {
741
+ constructor(e) {
742
+ this._api = e;
743
+ }
744
+ /** Объекты редактора, участвующие в raycast и редактировании */
745
+ _meshes = [];
746
+ /** Сетка сцены */
747
+ _grid = null;
748
+ /** Оси сцены */
749
+ _axes = null;
750
+ /** Базовый свет сцены */
751
+ _light = null;
752
+ init() {
753
+ this._grid = new a.GridHelper(10, 10), this._grid.position.y = -1e-3, this._api.addToScene(this._grid), this._axes = new nt(6), this._api.addToScene(this._axes), this._light = new a.HemisphereLight(16777215, 4473924, 0.6), this._api.addToScene(this._light);
754
+ }
755
+ getMeshes() {
756
+ return this._meshes;
757
+ }
758
+ addMesh(e) {
759
+ this._meshes.includes(e) || (this._meshes.push(e), this._api.addToScene(e));
760
+ }
761
+ removeMesh(e) {
762
+ const t = this._meshes.indexOf(e);
763
+ t >= 0 && this._meshes.splice(t, 1), this._api.removeFromScene(e);
764
+ }
765
+ addMeshes(e) {
766
+ for (const t of e)
767
+ this.addMesh(t);
768
+ }
769
+ removeMeshes(e) {
770
+ for (const t of e)
771
+ this.removeMesh(t);
772
+ }
773
+ /** Освобождает ресурсы модуля */
774
+ dispose() {
775
+ for (const e of this._meshes)
776
+ this._api.removeFromScene(e);
777
+ 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);
778
+ }
779
+ };
780
+ ue = zt([
781
+ d(),
782
+ Nt(0, l("ISceneApi"))
783
+ ], ue);
784
+ var P = /* @__PURE__ */ ((e) => (e[e.Display = 0] = "Display", e[e.Scene = 1] = "Scene", e[e.Select = 2] = "Select", e[e.Tool = 3] = "Tool", e))(P || {}), Ut = Object.getOwnPropertyDescriptor, Xt = (e, t, r, s) => {
785
+ for (var i = s > 1 ? void 0 : s ? Ut(t, r) : t, o = e.length - 1, n; o >= 0; o--)
786
+ (n = e[o]) && (i = n(i) || i);
787
+ return i;
788
+ }, Re = (e, t) => (r, s) => t(r, s, e);
789
+ let pe = class {
790
+ constructor(e, t) {
791
+ this._store = t, this._handlers = new Map(e.map((r) => [r.mode, r]));
915
792
  }
916
793
  /** Текущий режим отображения */
917
- _currentMode = V.Plane;
794
+ _currentMode = F.Plane;
918
795
  /** Хендлеры, которые управляют отображением */
919
796
  _handlers;
797
+ /** Тип фичи, за которую отвечает менеджер. */
798
+ type = P.Display;
920
799
  /** Установка режима отображения */
921
- manage(t) {
922
- t !== this._currentMode && (this._handlers.get(this._currentMode)?.rollback(), t !== V.Plane && this._handlers.get(t)?.handle(), this._currentMode = t, this._store.setDisplayMode(this._currentMode));
800
+ manage(e) {
801
+ e !== this._currentMode && (this._handlers.get(this._currentMode)?.rollback(), e !== F.Plane && this._handlers.get(e)?.handle(), this._currentMode = e, this._store.setDisplayMode(this._currentMode));
923
802
  }
924
803
  /** Освобождает ресурсы менеджера. */
925
804
  dispose() {
926
- this._handlers && this._handlers.clear(), this._currentMode = V.Plane, this._store.setDisplayMode(this._currentMode);
805
+ this._handlers && this._handlers.clear(), this._currentMode = F.Plane, this._store.setDisplayMode(this._currentMode);
927
806
  }
928
807
  };
929
- q = Dt([
930
- u(),
931
- Pe(0, W("IDisplayHandler")),
932
- Pe(1, h("IEditorStore"))
933
- ], q);
934
- var P = /* @__PURE__ */ ((t) => (t.Hover = "hover", t.Click = "click", t))(P || {}), Ct = Object.getOwnPropertyDescriptor, At = (t, e, s, i) => {
935
- for (var r = i > 1 ? void 0 : i ? Ct(e, s) : e, o = t.length - 1, n; o >= 0; o--)
936
- (n = t[o]) && (r = n(r) || r);
937
- return r;
938
- }, X = (t, e) => (s, i) => e(s, i, t);
939
- let Q = class {
940
- constructor(t, e, s) {
941
- 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);
808
+ pe = Xt([
809
+ d(),
810
+ Re(0, D("IDisplayHandler")),
811
+ Re(1, l("EditorStore"))
812
+ ], pe);
813
+ var C = /* @__PURE__ */ ((e) => (e.Hover = "hover", e.Click = "click", e))(C || {}), Yt = Object.getOwnPropertyDescriptor, Zt = (e, t, r, s) => {
814
+ for (var i = s > 1 ? void 0 : s ? Yt(t, r) : t, o = e.length - 1, n; o >= 0; o--)
815
+ (n = e[o]) && (i = n(i) || i);
816
+ return i;
817
+ }, J = (e, t) => (r, s) => t(r, s, e);
818
+ let me = class {
819
+ constructor(e, t, r) {
820
+ this._eventBus = e, this._store = r, this._handlers = new Map(t.map((s) => [s.mode, s])), this._eventBus.on(V.SelectHover, this._onHover), this._eventBus.on(V.SelectClick, this._onClick);
942
821
  }
943
822
  /** Текущий режим выборки */
944
- _currentMode = v.Mesh;
823
+ _currentMode = M.Mesh;
945
824
  /** Хендлеры, которые управляют выборкой */
946
825
  _handlers;
826
+ /** Тип фичи, за которую отвечает менеджер. */
827
+ type = P.Select;
947
828
  /** Переключает режим выбора */
948
- manage(t) {
949
- t !== this._currentMode && (this._handlers.get(this._currentMode)?.rollback(), this._currentMode = t, this._store.setSelectMode(this._currentMode));
829
+ manage(e) {
830
+ e !== this._currentMode && (this._handlers.get(this._currentMode)?.rollback(), this._currentMode = e, this._store.setSelectMode(this._currentMode));
950
831
  }
951
832
  /** Обработчик события наведения на модель */
952
- _onHover = (t) => {
953
- this._handlers.get(this._currentMode)?.handle(t, P.Hover);
833
+ _onHover = (e) => {
834
+ this._handlers.get(this._currentMode)?.handle(e, C.Hover);
954
835
  };
955
836
  /** Обработчик события клика на модель */
956
- _onClick = (t) => {
957
- this._handlers.get(this._currentMode)?.handle(t, P.Click);
837
+ _onClick = (e) => {
838
+ this._handlers.get(this._currentMode)?.handle(e, C.Click);
958
839
  };
959
840
  /** Освобождает ресурсы менеджера. */
960
841
  dispose() {
961
- this._handlers && this._handlers.clear(), this._eventBus.off(H.SelectHover, this._onHover), this._currentMode = v.Mesh, this._store.setSelectMode(this._currentMode);
842
+ this._handlers && this._handlers.clear(), this._eventBus.off(V.SelectHover, this._onHover), this._currentMode = M.Mesh, this._store.setSelectMode(this._currentMode);
962
843
  }
963
844
  };
964
- Q = At([
965
- u(),
966
- X(0, h("EventBus")),
967
- X(1, W("ISelectHandler")),
968
- X(2, h("IEditorStore"))
969
- ], Q);
970
- class xt {
971
- /** Доступен ли инструмент при текущем режиме выборки */
972
- isToolEnabled(e, s) {
973
- return Me[s].includes(e);
974
- }
975
- /** Получение доступных инструментов для режима выборки*/
976
- getEnabledTools(e) {
977
- return Me[e];
978
- }
979
- }
980
- var Rt = Object.getOwnPropertyDescriptor, jt = (t, e, s, i) => {
981
- for (var r = i > 1 ? void 0 : i ? Rt(e, s) : e, o = t.length - 1, n; o >= 0; o--)
982
- (n = t[o]) && (r = n(r) || r);
983
- return r;
984
- }, Oe = (t, e) => (s, i) => e(s, i, t);
985
- let J = class {
986
- constructor(t, e) {
987
- this._store = e, this._handlers = new Map(t.map((s) => [s.mode, s])), this._unsubSelected = this._store.onSelectedObjectChange(() => {
845
+ me = Zt([
846
+ d(),
847
+ J(0, l("EventBus")),
848
+ J(1, D("ISelectHandler")),
849
+ J(2, l("EditorStore"))
850
+ ], me);
851
+ const qt = (e) => (t, r, s) => {
852
+ const i = s.value;
853
+ if (!i)
854
+ throw new Error("usePolicy can only be applied to method");
855
+ return s.value = function(...o) {
856
+ return e(this).check(...o), i.apply(this, o);
857
+ }, s;
858
+ };
859
+ var Kt = Object.defineProperty, Qt = Object.getOwnPropertyDescriptor, Ye = (e, t, r, s) => {
860
+ for (var i = s > 1 ? void 0 : s ? Qt(t, r) : t, o = e.length - 1, n; o >= 0; o--)
861
+ (n = e[o]) && (i = (s ? n(t, r, i) : n(i)) || i);
862
+ return s && i && Kt(t, r, i), i;
863
+ }, ee = (e, t) => (r, s) => t(r, s, e);
864
+ let Y = class {
865
+ constructor(e, t, r) {
866
+ this._store = t, this._policy = r, this._handlers = new Map(e.map((s) => [s.mode, s])), this._unsubSelected = this._store.onSelectedObjectChange(() => {
988
867
  this._handlers.get(this._currentTool)?.handle();
989
- }), this._policy = new xt();
868
+ });
990
869
  }
991
870
  /** Текущий выбранный инструмент */
992
- _currentTool = C.Translate;
871
+ _currentTool = j.Translate;
993
872
  /** Хендлеры, которые управляют инструментами */
994
873
  _handlers;
995
874
  /** Событие обновления выбора объекта */
996
875
  _unsubSelected;
997
- /** Политика доступности инструментов */
998
- _policy;
999
- manage(t) {
1000
- if (this._currentTool === t) return;
1001
- const e = this._store.getSelectMode();
1002
- 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());
876
+ /** Тип фичи, за которую отвечает менеджер. */
877
+ type = P.Tool;
878
+ manage(e) {
879
+ this._currentTool !== e && (this._handlers.get(this._currentTool)?.rollback(), this._currentTool = e, this._store.setToolType(this._currentTool), this._handlers.get(this._currentTool)?.handle());
1003
880
  }
1004
881
  /** Освобождает ресурсы менеджера. */
1005
882
  dispose() {
1006
- this._unsubSelected?.(), this._handlers && this._handlers.clear(), this._currentTool = C.Translate, this._store.setToolType(this._currentTool);
883
+ this._unsubSelected?.(), this._handlers && this._handlers.clear(), this._currentTool = j.Translate, this._store.setToolType(this._currentTool);
1007
884
  }
1008
885
  };
1009
- J = jt([
1010
- u(),
1011
- Oe(0, W("IToolHandler")),
1012
- Oe(1, h("IEditorStore"))
1013
- ], J);
1014
- var It = Object.getOwnPropertyDescriptor, Ht = (t, e, s, i) => {
1015
- for (var r = i > 1 ? void 0 : i ? It(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1016
- (n = t[o]) && (r = n(r) || r);
1017
- return r;
1018
- }, kt = (t, e) => (s, i) => e(s, i, t);
1019
- let ee = class {
886
+ Ye([
887
+ qt((e) => e._policy)
888
+ ], Y.prototype, "manage", 1);
889
+ Y = Ye([
890
+ d(),
891
+ ee(0, D("IToolHandler")),
892
+ ee(1, l("EditorStore")),
893
+ ee(2, l("ToolPolicy"))
894
+ ], Y);
895
+ var Jt = Object.getOwnPropertyDescriptor, es = (e, t, r, s) => {
896
+ for (var i = s > 1 ? void 0 : s ? Jt(t, r) : t, o = e.length - 1, n; o >= 0; o--)
897
+ (n = e[o]) && (i = n(i) || i);
898
+ return i;
899
+ }, ts = (e, t) => (r, s) => t(r, s, e);
900
+ let ge = class {
1020
901
  /** Текущий режим редактирования сцены */
1021
- _currentMode = N.AddFigure;
902
+ _currentMode = W.AddFigure;
1022
903
  /** Хендлеры, которые управляют отображением */
1023
904
  _handlers;
1024
- constructor(t) {
1025
- this._handlers = new Map(t.map((e) => [e.mode, e]));
905
+ /** Тип фичи, за которую отвечает менеджер. */
906
+ type = P.Scene;
907
+ constructor(e) {
908
+ this._handlers = new Map(e.map((t) => [t.mode, t]));
1026
909
  }
1027
910
  /** Установка режима редактирования сцены */
1028
- manage(t, e) {
1029
- t === N.AddFigure ? this._handlers.get(t)?.handle(e) : this._handlers.get(t)?.handle(), this._currentMode = t;
911
+ manage(e, t) {
912
+ e === W.AddFigure ? this._handlers.get(e)?.handle(t) : this._handlers.get(e)?.handle(), this._currentMode = e;
1030
913
  }
1031
914
  /** Освобождает ресурсы менеджера. */
1032
915
  dispose() {
1033
- this._handlers && this._handlers.clear(), this._currentMode = N.AddFigure;
916
+ this._handlers && this._handlers.clear(), this._currentMode = W.AddFigure;
1034
917
  }
1035
918
  };
1036
- ee = Ht([
1037
- u(),
1038
- kt(0, W("ISceneHandler"))
1039
- ], ee);
1040
- var Vt = Object.getOwnPropertyDescriptor, Nt = (t, e, s, i) => {
1041
- for (var r = i > 1 ? void 0 : i ? Vt(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1042
- (n = t[o]) && (r = n(r) || r);
1043
- return r;
1044
- }, Yt = (t, e) => (s, i) => e(s, i, t);
1045
- let te = class {
1046
- constructor(t) {
1047
- this._api = t;
919
+ ge = es([
920
+ d(),
921
+ ts(0, D("ISceneHandler"))
922
+ ], ge);
923
+ var ss = Object.getOwnPropertyDescriptor, rs = (e, t, r, s) => {
924
+ for (var i = s > 1 ? void 0 : s ? ss(t, r) : t, o = e.length - 1, n; o >= 0; o--)
925
+ (n = e[o]) && (i = n(i) || i);
926
+ return i;
927
+ }, is = (e, t) => (r, s) => t(r, s, e);
928
+ let ve = class {
929
+ constructor(e) {
930
+ this._api = e;
1048
931
  }
1049
932
  /** Режим отображения. */
1050
- mode = V.Wireframe;
933
+ mode = F.Wireframe;
1051
934
  /** Сохраняем предыдущие значения wireframe для отката. */
1052
935
  _prevWireframe = /* @__PURE__ */ new Map();
1053
936
  /** Сохраняем исходные цвета материалов для отката */
@@ -1057,18 +940,18 @@ let te = class {
1057
940
  _wireColor = new a.Color(65535);
1058
941
  /** Применяет wireframe-режим к сцене. */
1059
942
  handle() {
1060
- const t = this._api.getMeshes();
1061
- for (const e of t) {
1062
- const s = Array.isArray(e.material) ? e.material : [e.material];
1063
- for (const i of s) this._enableWireframeOnMaterial(i);
1064
- e.traverse((i) => {
1065
- if (i.isLineSegments) {
1066
- const r = i;
1067
- if (!this._prevColorLines.has(r.material)) {
1068
- const n = r.material;
943
+ const e = this._api.getMeshes();
944
+ for (const t of e) {
945
+ const r = Array.isArray(t.material) ? t.material : [t.material];
946
+ for (const s of r) this._enableWireframeOnMaterial(s);
947
+ t.traverse((s) => {
948
+ if (s.isLineSegments) {
949
+ const i = s;
950
+ if (!this._prevColorLines.has(i.material)) {
951
+ const n = i.material;
1069
952
  this._prevColorLines.set(n, n.color.clone());
1070
953
  }
1071
- const o = r.material;
954
+ const o = i.material;
1072
955
  o.color.copy(this._wireColor), o.needsUpdate = !0;
1073
956
  }
1074
957
  });
@@ -1076,16 +959,16 @@ let te = class {
1076
959
  }
1077
960
  /** Отключает wireframe-режим и возвращает оригинальные меши. */
1078
961
  rollback() {
1079
- for (const [t, e] of this._prevWireframe)
1080
- "wireframe" in t && (t.wireframe = e), t.needsUpdate = !0;
962
+ for (const [e, t] of this._prevWireframe)
963
+ "wireframe" in e && (e.wireframe = t), e.needsUpdate = !0;
1081
964
  this._prevWireframe.clear();
1082
- for (const [t, e] of this._prevColorMesh) {
1083
- const s = t;
1084
- s.color?.isColor && s.color.copy(e);
965
+ for (const [e, t] of this._prevColorMesh) {
966
+ const r = e;
967
+ r.color?.isColor && r.color.copy(t);
1085
968
  }
1086
969
  this._prevColorMesh.clear();
1087
- for (const [t, e] of this._prevColorLines)
1088
- t.color.copy(e);
970
+ for (const [e, t] of this._prevColorLines)
971
+ e.color.copy(t);
1089
972
  this._prevColorLines.clear();
1090
973
  }
1091
974
  /** Освобождает ресурсы хендлера, удаляет слушатели и очищает внутренние данные. */
@@ -1093,57 +976,58 @@ let te = class {
1093
976
  this.rollback();
1094
977
  }
1095
978
  /** Изменить цвет, который будет применяться в режиме wireframe. */
1096
- _enableWireframeOnMaterial(t) {
1097
- const e = t;
1098
- "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));
979
+ _enableWireframeOnMaterial(e) {
980
+ const t = e;
981
+ "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));
1099
982
  }
1100
983
  };
1101
- te = Nt([
1102
- u(),
1103
- Yt(0, h("RendererApi"))
1104
- ], te);
1105
- var zt = Object.getOwnPropertyDescriptor, Ut = (t, e, s, i) => {
1106
- for (var r = i > 1 ? void 0 : i ? zt(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1107
- (n = t[o]) && (r = n(r) || r);
1108
- return r;
1109
- }, Te = (t, e) => (s, i) => e(s, i, t);
1110
- let se = class {
1111
- constructor(t, e) {
1112
- this._api = t, this._store = e;
984
+ ve = rs([
985
+ d(),
986
+ is(0, l("IMeshApi"))
987
+ ], ve);
988
+ const Z = 16776960, q = 16755200, os = 2236962, ns = 2236962;
989
+ var as = Object.getOwnPropertyDescriptor, cs = (e, t, r, s) => {
990
+ for (var i = s > 1 ? void 0 : s ? as(t, r) : t, o = e.length - 1, n; o >= 0; o--)
991
+ (n = e[o]) && (i = n(i) || i);
992
+ return i;
993
+ }, Fe = (e, t) => (r, s) => t(r, s, e);
994
+ let fe = class {
995
+ constructor(e, t) {
996
+ this._api = e, this._store = t;
1113
997
  }
1114
998
  /** Режим, которым управляет хендлер, нужен только менеджеру */
1115
- mode = v.Mesh;
999
+ mode = M.Mesh;
1116
1000
  /** Фигура, на которую навелись в данный момент */
1117
1001
  _hoveredMesh = null;
1118
1002
  /** Фигура, которую выбрали в данный момент */
1119
1003
  _selectedMesh = null;
1120
1004
  // Цвета, необходимые для переключения
1121
1005
  /** Цвет ребер для фигуры, на которую навелись */
1122
- _hoverColor = F;
1006
+ _hoverColor = Z;
1123
1007
  /** Цвет ребер для выделенной фигуры */
1124
- _selectColor = Z;
1008
+ _selectColor = q;
1125
1009
  /** Исходные цвета материалов линий для отката */
1126
1010
  _origLineColors = /* @__PURE__ */ new WeakMap();
1127
- handle(t, e) {
1128
- if (this._api.setRaycastMode(this.mode), e === P.Hover) {
1129
- if (!t) {
1011
+ handle(e, t) {
1012
+ if (this._api.setRaycastMode(this.mode), t === C.Hover) {
1013
+ if (!e) {
1130
1014
  this._hoveredMesh && this._hoveredMesh !== this._selectedMesh && this._restoreEdgesColor(this._hoveredMesh), this._hoveredMesh = null;
1131
1015
  return;
1132
1016
  }
1133
- const s = t.intersection.object;
1134
- this._hoveredMesh !== s && (this._hoveredMesh && this._hoveredMesh !== this._selectedMesh && this._restoreEdgesColor(this._hoveredMesh), s !== this._selectedMesh && this._paintEdges(s, this._hoverColor), this._hoveredMesh = s);
1017
+ const r = e.intersection.object;
1018
+ this._hoveredMesh !== r && (this._hoveredMesh && this._hoveredMesh !== this._selectedMesh && this._restoreEdgesColor(this._hoveredMesh), r !== this._selectedMesh && this._paintEdges(r, this._hoverColor), this._hoveredMesh = r);
1135
1019
  }
1136
- if (e === P.Click) {
1137
- if (!t) {
1020
+ if (t === C.Click) {
1021
+ if (!e) {
1138
1022
  this._selectedMesh && (this._restoreEdgesColor(this._selectedMesh), this._selectedMesh = null, this._store.setSelectedObject(null));
1139
1023
  return;
1140
1024
  }
1141
- const s = t.intersection.object;
1142
- this._selectedMesh && this._selectedMesh !== s && this._restoreEdgesColor(this._selectedMesh), this._paintEdges(s, this._selectColor), this._selectedMesh = s, this._store.setSelectedObject(s);
1025
+ const r = e.intersection.object;
1026
+ this._selectedMesh && this._selectedMesh !== r && this._restoreEdgesColor(this._selectedMesh), this._paintEdges(r, this._selectColor), this._selectedMesh = r, this._store.setSelectedObject(r);
1143
1027
  }
1144
1028
  }
1145
1029
  rollback() {
1146
- this._hoveredMesh && this._restoreEdgesColor(this._hoveredMesh), this._selectedMesh && this._restoreEdgesColor(this._selectedMesh), this._hoveredMesh = this._selectedMesh = null;
1030
+ this._hoveredMesh && this._restoreEdgesColor(this._hoveredMesh), this._selectedMesh && this._restoreEdgesColor(this._selectedMesh), this._hoveredMesh = this._selectedMesh = null, this._store.setSelectedObject(null);
1147
1031
  }
1148
1032
  /** Освобождает ресурсы хендлера, удаляет слушатели и очищает внутренние данные. */
1149
1033
  dispose() {
@@ -1152,12 +1036,12 @@ let se = class {
1152
1036
  /**
1153
1037
  * Перекрасить рёбра меша и запомнить оригинальный цвет (один раз на LineSegments).
1154
1038
  */
1155
- _paintEdges(t, e) {
1156
- t.children.forEach((s) => {
1157
- const i = s;
1158
- if (i.isLineSegments && i.material) {
1159
- const r = i.material;
1160
- this._origLineColors.has(i) || this._origLineColors.set(i, r.color.clone()), r.color.setHex(e), r.needsUpdate = !0;
1039
+ _paintEdges(e, t) {
1040
+ e.children.forEach((r) => {
1041
+ const s = r;
1042
+ if (s.isLineSegments && s.material) {
1043
+ const i = s.material;
1044
+ this._origLineColors.has(s) || this._origLineColors.set(s, i.color.clone()), i.color.setHex(t), i.needsUpdate = !0;
1161
1045
  }
1162
1046
  });
1163
1047
  }
@@ -1165,72 +1049,413 @@ let se = class {
1165
1049
  * Восстановить исходный цвет рёбер меша из WeakMap.
1166
1050
  * Если исходный цвет не сохранён (на всякий случай) — ничего не меняем.
1167
1051
  */
1168
- _restoreEdgesColor(t) {
1169
- t.children.forEach((e) => {
1170
- const s = e;
1171
- if (s.isLineSegments && s.material) {
1172
- const i = this._origLineColors.get(s);
1173
- if (i) {
1174
- const r = s.material;
1175
- r.color.copy(i), r.needsUpdate = !0;
1052
+ _restoreEdgesColor(e) {
1053
+ e.children.forEach((t) => {
1054
+ const r = t;
1055
+ if (r.isLineSegments && r.material) {
1056
+ const s = this._origLineColors.get(r);
1057
+ if (s) {
1058
+ const i = r.material;
1059
+ i.color.copy(s), i.needsUpdate = !0;
1176
1060
  }
1177
1061
  }
1178
1062
  });
1179
1063
  }
1180
1064
  };
1181
- se = Ut([
1182
- u(),
1183
- Te(0, h("RendererApi")),
1184
- Te(1, h("IEditorStore"))
1185
- ], se);
1186
- var Wt = Object.getOwnPropertyDescriptor, Ft = (t, e, s, i) => {
1187
- for (var r = i > 1 ? void 0 : i ? Wt(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1188
- (n = t[o]) && (r = n(r) || r);
1189
- return r;
1190
- }, Zt = (t, e) => (s, i) => e(s, i, t);
1191
- let ie = class {
1192
- constructor(t) {
1193
- this._api = t;
1065
+ fe = cs([
1066
+ d(),
1067
+ Fe(0, l("IRaycastApi")),
1068
+ Fe(1, l("EditorStore"))
1069
+ ], fe);
1070
+ var ls = Object.getOwnPropertyDescriptor, hs = (e, t, r, s) => {
1071
+ for (var i = s > 1 ? void 0 : s ? ls(t, r) : t, o = e.length - 1, n; o >= 0; o--)
1072
+ (n = e[o]) && (i = n(i) || i);
1073
+ return i;
1074
+ }, z = (e, t) => (r, s) => t(r, s, e);
1075
+ let Me = class {
1076
+ constructor(e, t, r, s) {
1077
+ this._cameraApi = e, this._sceneApi = t, this._raycastApi = r, this._store = s, this._cameraApi.enableCameraLayer(x), this._hoverFace = this._makeOverlayFace(this._hoverColor), this._selectFace = this._makeOverlayFace(this._selectColor), this._sceneApi.addObject(this._hoverFace, x), this._sceneApi.addObject(this._selectFace, x);
1194
1078
  }
1195
1079
  /** Режим, которым управляет хендлер, нужен только менеджеру */
1196
- mode = v.Face;
1080
+ mode = M.Face;
1197
1081
  /** Текущая наведённая грань */
1198
- _hovered = null;
1082
+ _hoverFace;
1199
1083
  /** Текущая выбранная грань */
1084
+ _selectFace;
1085
+ // Группы треугольников, которые образуют грань
1086
+ //
1087
+ // !!NB:
1088
+ // Все грани фигур состоят из треугольников, их объединение даст необходимую грань
1089
+ /** Текущая группа треугольников для наведённой грани */
1090
+ _hovered = null;
1091
+ /** Текущая группа треугольников для выбранной грани */
1200
1092
  _selected = null;
1201
1093
  // Цвета, необходимые для переключения
1202
1094
  /** Цвет грани, на которую навелись */
1203
- _hoverColor = F;
1095
+ _hoverColor = Z;
1204
1096
  /** Цвет выделенной граней */
1205
- _selectColor = Z;
1206
- /** Изначальный цвет граней у модели, перед наложением эффектов*/
1207
- _defaultColor = 2236962;
1208
- handle(t, e) {
1209
- this._api.setRaycastMode(this.mode), e === P.Hover && console.log(t), e === P.Click && console.log(t);
1097
+ _selectColor = q;
1098
+ // Погрешности для поиска треугольников и сборки граней
1099
+ /** Погрешность на сравнение нормалей */
1100
+ _normalEps = 1e-4;
1101
+ /** Погрешность на принадлежность одной плоскости */
1102
+ _planeEps = 1e-4;
1103
+ /** Обработка текущего режима выборки. */
1104
+ handle(e, t) {
1105
+ if (this._raycastApi.setRaycastMode(this.mode), t === C.Hover) {
1106
+ if (!e) {
1107
+ this._hoverFace.visible = !1, this._hovered = null;
1108
+ return;
1109
+ }
1110
+ const r = e.intersection.object;
1111
+ if (!r?.isMesh) return;
1112
+ const s = r, i = e.intersection.faceIndex ?? -1;
1113
+ if (i < 0) return;
1114
+ const o = this._collectFaceGroup(s, i);
1115
+ if (!o) return;
1116
+ this._selected && this._same(o, this._selected) ? this._hoverFace.visible = !1 : (this._writeWorldFaceGroup(this._hoverFace, o), this._hoverFace.visible = !0), this._hovered = o;
1117
+ return;
1118
+ }
1119
+ if (t === C.Click) {
1120
+ if (!e) {
1121
+ this._selectFace.visible = !1, this._selected = null, this._store.setSelectedObject(null);
1122
+ return;
1123
+ }
1124
+ const r = e.intersection.object;
1125
+ if (!r?.isMesh) return;
1126
+ const s = r, i = e.intersection.faceIndex ?? -1;
1127
+ if (i < 0) return;
1128
+ const o = this._collectFaceGroup(s, i);
1129
+ if (!o) return;
1130
+ 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);
1131
+ }
1210
1132
  }
1133
+ /** Откат текущего режима выборки */
1211
1134
  rollback() {
1212
- throw new Error("Method not implemented.");
1135
+ this._hoverFace.visible = !1, this._selectFace.visible = !1, this._resetFaceProxyTransform(this._selectFace), this._resetFaceProxyTransform(this._hoverFace), this._hovered = this._selected = null, this._store.setSelectedObject(null);
1213
1136
  }
1214
1137
  /** Освобождает ресурсы хендлера, удаляет слушатели и очищает внутренние данные. */
1215
1138
  dispose() {
1216
- throw new Error("Method not implemented.");
1139
+ 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();
1140
+ }
1141
+ /**
1142
+ * Инициализация overlay mesh для режима (hover и click).
1143
+ * На весь режим используются 2 глобальных mesh на сцене,
1144
+ * геометрия которых переписывается под текущую грань.
1145
+ */
1146
+ _makeOverlayFace(e) {
1147
+ const t = new a.BufferGeometry(), r = new a.MeshBasicMaterial({
1148
+ color: e,
1149
+ transparent: !0,
1150
+ opacity: 0.35,
1151
+ depthTest: !1,
1152
+ depthWrite: !1,
1153
+ side: a.DoubleSide,
1154
+ polygonOffset: !0,
1155
+ polygonOffsetFactor: -1,
1156
+ polygonOffsetUnits: -1
1157
+ }), s = new a.Mesh(t, r);
1158
+ return s.renderOrder = 1e3, s.layers.set(x), s.visible = !1, s.raycast = () => {
1159
+ }, s;
1160
+ }
1161
+ /**
1162
+ * Сбор логической грани как связной группы компланарных треугольников.
1163
+ * Если geometry неиндексированная — пока возвращаем только стартовый triangle.
1164
+ */
1165
+ _collectFaceGroup(e, t) {
1166
+ const r = e.geometry, s = r.getAttribute("position");
1167
+ if (!s) return null;
1168
+ const i = r.index;
1169
+ if (!i) {
1170
+ const S = t * 3, w = t * 3 + 1, I = t * 3 + 2;
1171
+ return {
1172
+ mesh: e,
1173
+ faceIndex: t,
1174
+ triangleIndices: [t],
1175
+ vertexIndices: [S, w, I],
1176
+ proxyVertexMap: [S, w, I]
1177
+ };
1178
+ }
1179
+ const o = Math.floor(i.count / 3);
1180
+ if (t < 0 || t >= o) return null;
1181
+ const n = this._buildTriangleAdjacency(i, s), [c, _, u] = this._getTriangleIndices(i, t), p = this._readVertex(s, c), f = this._readVertex(s, _), g = this._readVertex(s, u), v = new a.Vector3().subVectors(f, p).cross(new a.Vector3().subVectors(g, p)).normalize(), m = new a.Plane().setFromNormalAndCoplanarPoint(v, p), y = /* @__PURE__ */ new Set(), b = [], L = [t];
1182
+ for (; L.length > 0; ) {
1183
+ const S = L.pop();
1184
+ if (y.has(S)) continue;
1185
+ y.add(S);
1186
+ const [w, I, $] = this._getTriangleIndices(i, S), A = this._readVertex(s, w), Ve = this._readVertex(s, I), $e = this._readVertex(s, $), Ke = new a.Vector3().subVectors(Ve, A).cross(new a.Vector3().subVectors($e, A)).normalize(), Qe = Math.abs(Ke.dot(v)) >= 1 - this._normalEps, Je = Math.abs(m.distanceToPoint(A)) < this._planeEps && Math.abs(m.distanceToPoint(Ve)) < this._planeEps && Math.abs(m.distanceToPoint($e)) < this._planeEps;
1187
+ if (!Qe || !Je) continue;
1188
+ b.push(S);
1189
+ const je = n.get(S);
1190
+ if (je)
1191
+ for (const He of je)
1192
+ y.has(He) || L.push(He);
1193
+ }
1194
+ b.sort((S, w) => S - w);
1195
+ const E = /* @__PURE__ */ new Set(), T = [];
1196
+ for (const S of b) {
1197
+ const [w, I, $] = this._getTriangleIndices(i, S);
1198
+ E.add(w), E.add(I), E.add($), T.push(w, I, $);
1199
+ }
1200
+ return {
1201
+ mesh: e,
1202
+ faceIndex: t,
1203
+ triangleIndices: b,
1204
+ vertexIndices: Array.from(E),
1205
+ proxyVertexMap: T
1206
+ };
1207
+ }
1208
+ /** Перезаписывает overlay mesh world-space треугольниками выбранной грани */
1209
+ _writeWorldFaceGroup(e, t) {
1210
+ const r = t.mesh.geometry, s = r.getAttribute("position"), i = r.index, o = new Float32Array(t.triangleIndices.length * 9);
1211
+ let n = 0;
1212
+ for (const _ of t.triangleIndices) {
1213
+ let u, p, f;
1214
+ i ? [u, p, f] = this._getTriangleIndices(i, _) : (u = _ * 3, p = _ * 3 + 1, f = _ * 3 + 2);
1215
+ const g = this._readVertex(s, u).applyMatrix4(t.mesh.matrixWorld), v = this._readVertex(s, p).applyMatrix4(t.mesh.matrixWorld), m = this._readVertex(s, f).applyMatrix4(t.mesh.matrixWorld);
1216
+ o[n++] = g.x, o[n++] = g.y, o[n++] = g.z, o[n++] = v.x, o[n++] = v.y, o[n++] = v.z, o[n++] = m.x, o[n++] = m.y, o[n++] = m.z;
1217
+ }
1218
+ const c = e.geometry;
1219
+ c.setAttribute("position", new a.BufferAttribute(o, 3)), c.setIndex(null), c.computeVertexNormals(), c.computeBoundingBox(), c.computeBoundingSphere();
1220
+ }
1221
+ /** Сравнение двух логических граней */
1222
+ _same(e, t) {
1223
+ return !!e && !!t && e.mesh === t.mesh && e.triangleIndices.length === t.triangleIndices.length && e.triangleIndices.every((r, s) => r === t.triangleIndices[s]);
1224
+ }
1225
+ /** Подготовка метаданных выбранной грани для инструментов */
1226
+ _prepareFaceMetadata(e) {
1227
+ const { vertexIndexGroups: t, proxyVertexMap: r, lines: s, lineVertexIndexGroups: i } = this._buildFaceVertexGroups(e);
1228
+ this._selectFace.userData.faceInfo = {
1229
+ mesh: e.mesh,
1230
+ faceIndex: e.faceIndex,
1231
+ triangleIndices: e.triangleIndices,
1232
+ vertexIndices: e.vertexIndices,
1233
+ vertexIndexGroups: t,
1234
+ proxyVertexMap: r,
1235
+ lines: s,
1236
+ lineVertexIndexGroups: i
1237
+ };
1238
+ }
1239
+ /**
1240
+ * Центрирует proxy-грань, чтобы TransformControls работали с ней как с обычным объектом.
1241
+ * После записи world-space вершин переносит геометрию в локальные координаты proxy mesh.
1242
+ */
1243
+ _centerFaceProxy(e) {
1244
+ const t = e.geometry, r = t.getAttribute("position");
1245
+ if (!r || r.count === 0) return;
1246
+ const s = new a.Vector3();
1247
+ for (let i = 0; i < r.count; i++)
1248
+ s.x += r.getX(i), s.y += r.getY(i), s.z += r.getZ(i);
1249
+ s.multiplyScalar(1 / r.count);
1250
+ for (let i = 0; i < r.count; i++)
1251
+ r.setXYZ(i, r.getX(i) - s.x, r.getY(i) - s.y, r.getZ(i) - s.z);
1252
+ r.needsUpdate = !0, e.position.copy(s), e.quaternion.identity(), e.scale.set(1, 1, 1), e.updateMatrixWorld(!0), t.computeBoundingBox(), t.computeBoundingSphere();
1253
+ }
1254
+ /** Регистрирует ребро треугольника в edge map */
1255
+ _pushEdge(e, t, r, s) {
1256
+ const i = t < r ? `${t}_${r}` : `${r}_${t}`, o = e.get(i);
1257
+ o ? o.push(s) : e.set(i, [s]);
1258
+ }
1259
+ /** Строит граф соседства треугольников по общим ребрам */
1260
+ _buildTriangleAdjacency(e, t) {
1261
+ const r = Math.floor(e.count / 3), s = /* @__PURE__ */ new Map(), i = this._buildWeldMap(e, t);
1262
+ for (let c = 0; c < r; c++) {
1263
+ const [_, u, p] = this._getTriangleIndices(e, c), f = i.get(_), g = i.get(u), v = i.get(p);
1264
+ this._pushEdge(s, f, g, c), this._pushEdge(s, g, v, c), this._pushEdge(s, v, f, c);
1265
+ }
1266
+ const o = /* @__PURE__ */ new Map();
1267
+ for (let c = 0; c < r; c++)
1268
+ o.set(c, /* @__PURE__ */ new Set());
1269
+ for (const c of s.values())
1270
+ if (!(c.length < 2))
1271
+ for (let _ = 0; _ < c.length; _++)
1272
+ for (let u = 0; u < c.length; u++)
1273
+ _ !== u && o.get(c[_])?.add(c[u]);
1274
+ const n = /* @__PURE__ */ new Map();
1275
+ for (const [c, _] of o)
1276
+ n.set(c, Array.from(_));
1277
+ return n;
1278
+ }
1279
+ /** Возвращает индексы трех вершин треугольника */
1280
+ _getTriangleIndices(e, t) {
1281
+ return [e.getX(t * 3), e.getX(t * 3 + 1), e.getX(t * 3 + 2)];
1282
+ }
1283
+ /** Читает вершину из position buffer в local space geometry */
1284
+ _readVertex(e, t) {
1285
+ return new a.Vector3(e.getX(t), e.getY(t), e.getZ(t));
1286
+ }
1287
+ /** Построение ключа вершины по позиции */
1288
+ _vertexKey(e, t, r = 1e-6) {
1289
+ const s = Math.round(e.getX(t) / r), i = Math.round(e.getY(t) / r), o = Math.round(e.getZ(t) / r);
1290
+ return `${s}_${i}_${o}`;
1291
+ }
1292
+ /**
1293
+ * Строит отображение исходных индексов вершин в "сваренные" ids по координате.
1294
+ * Нужно для случаев, когда соседние треугольники визуально делят ребро,
1295
+ * но используют разные индексы вершин (например, цилиндрические крышки, UV seams и т.п.).
1296
+ */
1297
+ _buildWeldMap(e, t) {
1298
+ const r = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map();
1299
+ let i = 0;
1300
+ for (let o = 0; o < e.count; o++) {
1301
+ const n = e.getX(o);
1302
+ if (s.has(n)) continue;
1303
+ const c = this._vertexKey(t, n);
1304
+ let _ = r.get(c);
1305
+ _ == null && (_ = i++, r.set(c, _)), s.set(n, _);
1306
+ }
1307
+ return s;
1308
+ }
1309
+ /** Сбрасывает transform proxy-граням */
1310
+ _resetFaceProxyTransform(e) {
1311
+ e.position.set(0, 0, 0), e.quaternion.identity(), e.scale.set(1, 1, 1), e.updateMatrixWorld(!0);
1312
+ }
1313
+ _buildFaceVertexGroups(e) {
1314
+ const r = e.mesh.geometry.getAttribute("position"), s = 1e-6, i = new a.Vector3(), o = e.vertexIndices, n = [], c = /* @__PURE__ */ new Map();
1315
+ for (const g of o) {
1316
+ const v = this._readVertex(r, g), m = [];
1317
+ for (let b = 0; b < r.count; b++)
1318
+ i.fromBufferAttribute(r, b), i.distanceToSquared(v) < s * s && m.push(b);
1319
+ const y = n.length;
1320
+ n.push(m);
1321
+ for (const b of m)
1322
+ c.set(b, y);
1323
+ }
1324
+ const _ = [];
1325
+ for (const g of e.proxyVertexMap) {
1326
+ const v = c.get(g);
1327
+ _.push(v ?? -1);
1328
+ }
1329
+ const u = this._findChildLines(e.mesh), p = u ? this._buildLineVertexGroups(e, u) : void 0, f = {
1330
+ vertexIndexGroups: n,
1331
+ proxyVertexMap: _
1332
+ };
1333
+ return u && (f.lines = u), p && (f.lineVertexIndexGroups = p), f;
1334
+ }
1335
+ _findChildLines(e) {
1336
+ for (const t of e.children)
1337
+ if (t.isLineSegments)
1338
+ return t;
1339
+ return null;
1340
+ }
1341
+ _buildLineVertexGroups(e, t) {
1342
+ const s = t.geometry.getAttribute("position"), o = e.mesh.geometry.getAttribute("position"), n = 1e-6, c = new a.Vector3(), _ = t.matrixWorld, u = e.mesh.matrixWorld, p = [];
1343
+ for (const f of e.vertexIndices) {
1344
+ const g = this._readVertex(o, f).applyMatrix4(u), v = [];
1345
+ for (let m = 0; m < s.count; m++)
1346
+ c.fromBufferAttribute(s, m).applyMatrix4(_), c.distanceToSquared(g) < n * n && v.push(m);
1347
+ p.push(v);
1348
+ }
1349
+ return p;
1217
1350
  }
1218
1351
  };
1219
- ie = Ft([
1220
- u(),
1221
- Zt(0, h("RendererApi"))
1222
- ], ie);
1223
- var $t = Object.getOwnPropertyDescriptor, Bt = (t, e, s, i) => {
1224
- for (var r = i > 1 ? void 0 : i ? $t(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1225
- (n = t[o]) && (r = n(r) || r);
1226
- return r;
1227
- }, Le = (t, e) => (s, i) => e(s, i, t);
1228
- let re = class {
1229
- constructor(t, e) {
1230
- this._api = t, this._store = e, this._api.enableCameraLayer(L), this._hoverVertex = this._makeOverlayVertex(this._hoverColor), this._selectVertex = this._makeOverlayVertex(this._selectColor), this._api.addObject(this._hoverVertex, L), this._api.addObject(this._selectVertex, L);
1352
+ Me = hs([
1353
+ d(),
1354
+ z(0, l("ICameraApi")),
1355
+ z(1, l("ISceneApi")),
1356
+ z(2, l("IRaycastApi")),
1357
+ z(3, l("EditorStore"))
1358
+ ], Me);
1359
+ const _s = {
1360
+ /**
1361
+ * Плоскость (PlaneGeometry)
1362
+ * @returns Плоскость размером 1x1 с одной сегментацией
1363
+ */
1364
+ [O.Plane]: () => new a.PlaneGeometry(1, 1, 1, 1),
1365
+ /**
1366
+ * Куб (BoxGeometry)
1367
+ * @returns Куб размером 1x1x1 с одной сегментацией по каждой оси
1368
+ */
1369
+ [O.Cube]: () => new a.BoxGeometry(1, 1, 1, 1, 1, 1),
1370
+ /**
1371
+ * Ультра-сфера (SphereGeometry) с гладкой поверхностью
1372
+ * @returns Сфера радиусом 0.5, 32 сегмента по ширине, 16 по высоте
1373
+ */
1374
+ [O.UVSphere]: () => new a.SphereGeometry(0.5, 32, 16),
1375
+ /**
1376
+ * Икосфера (IcosahedronGeometry) — сфера из треугольников
1377
+ * @returns Икосфера радиусом 0.5, уровень детализации 0
1378
+ */
1379
+ [O.Icosphere]: () => new a.IcosahedronGeometry(0.5, 0),
1380
+ /**
1381
+ * Цилиндр (CylinderGeometry)
1382
+ * @returns Цилиндр радиусом 0.5, высотой 1, 32 сегмента
1383
+ */
1384
+ [O.Cylinder]: () => new a.CylinderGeometry(0.5, 0.5, 1, 32, 1, !1),
1385
+ /**
1386
+ * Конус (ConeGeometry)
1387
+ * @returns Конус радиусом 0.5, высотой 1, 32 сегмента
1388
+ */
1389
+ [O.Cone]: () => new a.ConeGeometry(0.5, 1, 32, 1, !1),
1390
+ /**
1391
+ * Тор (TorusGeometry)
1392
+ * @returns Тор радиусом 0.5, толщиной 0.2, 16 сегментов по радиусу, 64 по трубке
1393
+ */
1394
+ [O.Torus]: () => new a.TorusGeometry(0.5, 0.2, 16, 64),
1395
+ /**
1396
+ * Круг (CircleGeometry)
1397
+ * @returns Круг радиусом 0.5, 32 сегмента
1398
+ */
1399
+ [O.Circle]: () => new a.CircleGeometry(0.5, 32),
1400
+ /**
1401
+ * Сфера (SphereGeometry) — алиас для UVSphere
1402
+ * @returns Сфера радиусом 0.5, 32 сегмента по ширине, 16 по высоте
1403
+ */
1404
+ [O.Sphere]: () => new a.SphereGeometry(0.5, 32, 16),
1405
+ /**
1406
+ * Кастомная геометрия (не реализовано в фабрике)
1407
+ * @throws {Error} Всегда выбрасывает ошибку
1408
+ */
1409
+ [O.Custom]: function() {
1410
+ throw new Error("Custom geometry is not generated here.");
1411
+ }
1412
+ }, ds = new a.MeshStandardMaterial({
1413
+ color: 12566463,
1414
+ metalness: 0,
1415
+ roughness: 0.6
1416
+ }), us = 8, ps = (e) => !!e && e.isMesh, Ze = (e) => {
1417
+ let t = e;
1418
+ for (; t; ) {
1419
+ if (t.isMesh) return t;
1420
+ t = t.parent;
1421
+ }
1422
+ return null;
1423
+ }, ms = (e) => {
1424
+ const t = new a.BufferGeometry();
1425
+ t.setAttribute("position", e.getAttribute("position")), t.computeBoundingSphere(), t.computeBoundingBox();
1426
+ const r = new a.PointsMaterial({
1427
+ color: ns,
1428
+ size: 6,
1429
+ sizeAttenuation: !1,
1430
+ depthTest: !1,
1431
+ depthWrite: !1,
1432
+ transparent: !0,
1433
+ opacity: 0.9
1434
+ }), s = new a.Points(t, r);
1435
+ return s.layers.set(Xe), s.renderOrder = 1e3, s.visible = !1, s;
1436
+ }, gs = (e) => {
1437
+ const t = new a.EdgesGeometry(e), r = new a.LineSegments(
1438
+ t,
1439
+ new a.LineBasicMaterial({ color: os, linewidth: 1 })
1440
+ );
1441
+ return r.layers.set(Ue), r;
1442
+ }, vs = (e) => {
1443
+ const t = { x: e.position.x, y: e.position.y, z: e.position.z }, r = { x: e.rotation.x, y: e.rotation.y, z: e.rotation.z }, s = { x: e.scale.x, y: e.scale.y, z: e.scale.z }, i = new a.Box3().setFromObject(e), o = new a.Vector3();
1444
+ i.getSize(o);
1445
+ const n = { x: o.x, y: o.y, z: o.z };
1446
+ return { position: t, rotation: r, scale: s, size: n };
1447
+ };
1448
+ var fs = Object.getOwnPropertyDescriptor, Ms = (e, t, r, s) => {
1449
+ for (var i = s > 1 ? void 0 : s ? fs(t, r) : t, o = e.length - 1, n; o >= 0; o--)
1450
+ (n = e[o]) && (i = n(i) || i);
1451
+ return i;
1452
+ }, N = (e, t) => (r, s) => t(r, s, e);
1453
+ let ye = class {
1454
+ constructor(e, t, r, s) {
1455
+ this._cameraApi = e, this._sceneApi = t, this._raycastApi = r, this._store = s, this._cameraApi.enableCameraLayer(x), this._hoverVertex = this._makeOverlayVertex(this._hoverColor), this._selectVertex = this._makeOverlayVertex(this._selectColor), this._sceneApi.addObject(this._hoverVertex, x), this._sceneApi.addObject(this._selectVertex, x);
1231
1456
  }
1232
1457
  /** Режим, которым управляет хендлер, нужен только менеджеру */
1233
- mode = v.Vertex;
1458
+ mode = M.Vertex;
1234
1459
  _hovered = null;
1235
1460
  _selected = null;
1236
1461
  /** Текущая наведённая вершина. */
@@ -1239,116 +1464,118 @@ let re = class {
1239
1464
  _selectVertex;
1240
1465
  // Цвета, необходимые для переключения
1241
1466
  /** Цвет ребра, на которое навелись */
1242
- _hoverColor = F;
1467
+ _hoverColor = Z;
1243
1468
  /** Цвет выделенного ребра */
1244
- _selectColor = Z;
1245
- handle(t, e) {
1246
- if (this._api.setRaycastMode(this.mode), e === P.Hover) {
1247
- if (!t) {
1469
+ _selectColor = q;
1470
+ handle(e, t) {
1471
+ if (this._raycastApi.setRaycastMode(this.mode), t === C.Hover) {
1472
+ if (!e) {
1248
1473
  this._hoverVertex.visible = !1, this._hovered = null;
1249
1474
  return;
1250
1475
  }
1251
- const s = t.intersection.object;
1252
- if (!s?.isPoints) return;
1253
- const i = s, r = t.intersection.index ?? -1;
1254
- if (r < 0) return;
1255
- this._selected && this._same({ points: i, index: r }, this._selected) ? this._hoverVertex.visible = !1 : (this._writeWorldVertex(this._hoverVertex, i, r), this._hoverVertex.visible = !0);
1476
+ const r = e.intersection.object;
1477
+ if (!r?.isPoints) return;
1478
+ const s = r, i = e.intersection.index ?? -1;
1479
+ if (i < 0) return;
1480
+ this._selected && this._same({ points: s, index: i }, this._selected) ? this._hoverVertex.visible = !1 : (this._writeWorldVertex(this._hoverVertex, s, i), this._hoverVertex.visible = !0);
1256
1481
  return;
1257
1482
  }
1258
- if (e === P.Click) {
1259
- if (!t) {
1483
+ if (t === C.Click) {
1484
+ if (!e) {
1260
1485
  this._selectVertex.visible = !1, this._selected = null, this._store.setSelectedObject(null);
1261
1486
  return;
1262
1487
  }
1263
- const s = t.intersection.object;
1264
- if (!s?.isPoints) return;
1265
- const i = s, r = t.intersection.index ?? -1;
1266
- if (r < 0) return;
1267
- 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);
1488
+ const r = e.intersection.object;
1489
+ if (!r?.isPoints) return;
1490
+ const s = r, i = e.intersection.index ?? -1;
1491
+ if (i < 0) return;
1492
+ this._writeWorldVertex(this._selectVertex, s, i), this._centerVertexOnPoint(this._selectVertex, s, i), this._selectVertex.visible = !0, this._prepareVertexMetadata(s, i), this._store.setSelectedObject(this._selectVertex), this._selected = { points: s, index: i }, this._hovered && this._same(this._hovered, this._selected) && (this._hoverVertex.visible = !1);
1268
1493
  return;
1269
1494
  }
1270
1495
  }
1271
1496
  rollback() {
1272
- this._hoverVertex.visible = !1, this._selectVertex.visible = !1, this._hovered = this._selected = null;
1497
+ this._hoverVertex.visible = !1, this._selectVertex.visible = !1, this._hovered = this._selected = null, this._store.setSelectedObject(null);
1273
1498
  }
1274
1499
  dispose() {
1275
- 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();
1276
- }
1277
- _makeOverlayVertex(t, e = tt) {
1278
- const s = new a.BufferGeometry();
1279
- s.setAttribute("position", new a.Float32BufferAttribute([0, 0, 0], 3));
1280
- const i = new a.PointsMaterial({
1281
- color: t,
1282
- size: e,
1500
+ 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();
1501
+ }
1502
+ _makeOverlayVertex(e, t = us) {
1503
+ const r = new a.BufferGeometry();
1504
+ r.setAttribute("position", new a.Float32BufferAttribute([0, 0, 0], 3));
1505
+ const s = new a.PointsMaterial({
1506
+ color: e,
1507
+ size: t,
1283
1508
  sizeAttenuation: !1,
1284
1509
  depthTest: !1,
1285
1510
  depthWrite: !1,
1286
1511
  transparent: !0,
1287
1512
  opacity: 1
1288
- }), r = new a.Points(s, i);
1289
- return r.renderOrder = 1e3, r.raycast = () => {
1290
- }, r.layers.set(L), r.visible = !1, r;
1513
+ }), i = new a.Points(r, s);
1514
+ return i.renderOrder = 1e3, i.raycast = () => {
1515
+ }, i.layers.set(x), i.visible = !1, i;
1291
1516
  }
1292
1517
  /** Локальную вершину points переводим в world и пишем в target (прокси-точку) */
1293
- _writeWorldVertex(t, e, s) {
1294
- const i = e.geometry.getAttribute("position"), r = new a.Vector3(
1295
- i.getX(s),
1296
- i.getY(s),
1297
- i.getZ(s)
1298
- ).applyMatrix4(e.matrixWorld), o = t.geometry.getAttribute("position");
1299
- o.setXYZ(0, r.x, r.y, r.z), o.needsUpdate = !0;
1518
+ _writeWorldVertex(e, t, r) {
1519
+ const s = t.geometry.getAttribute("position"), i = new a.Vector3(
1520
+ s.getX(r),
1521
+ s.getY(r),
1522
+ s.getZ(r)
1523
+ ).applyMatrix4(t.matrixWorld), o = e.geometry.getAttribute("position");
1524
+ o.setXYZ(0, i.x, i.y, i.z), o.needsUpdate = !0;
1300
1525
  }
1301
- _same(t, e) {
1302
- return !!t && !!e && t.points === e.points && t.index === e.index;
1526
+ _same(e, t) {
1527
+ return !!e && !!t && e.points === t.points && e.index === t.index;
1303
1528
  }
1304
1529
  /** Готовит метаданные для выбранной вершины и пишет их в _selectVertex.userData */
1305
- _prepareVertexMetadata(t, e) {
1306
- const s = Ve(t);
1307
- if (!s) return;
1308
- const i = t.geometry.getAttribute("position"), r = new a.Vector3(
1309
- i.getX(e),
1310
- i.getY(e),
1311
- i.getZ(e)
1312
- ).applyMatrix4(t.matrixWorld), o = new a.Matrix4().copy(s.matrixWorld).invert(), n = r.clone().applyMatrix4(o), _ = s.geometry.getAttribute("position"), m = 1e-6, f = m * m, D = new a.Vector3(), b = [];
1313
- for (let M = 0; M < _.count; M++)
1314
- D.fromBufferAttribute(_, M), D.distanceToSquared(n) < f && b.push(M);
1315
- const O = s.children.find((M) => M?.isLineSegments);
1316
- let y = [];
1317
- if (O) {
1318
- const M = new a.Matrix4().copy(O.matrixWorld).invert(), Y = r.clone().applyMatrix4(M), k = O.geometry.getAttribute("position"), z = new a.Vector3();
1319
- for (let A = 0; A < k.count; A++)
1320
- z.fromBufferAttribute(k, A), z.distanceToSquared(Y) < f && y.push(A);
1530
+ _prepareVertexMetadata(e, t) {
1531
+ const r = Ze(e);
1532
+ if (!r) return;
1533
+ const s = e.geometry.getAttribute("position"), i = new a.Vector3(
1534
+ s.getX(t),
1535
+ s.getY(t),
1536
+ s.getZ(t)
1537
+ ).applyMatrix4(e.matrixWorld), o = new a.Matrix4().copy(r.matrixWorld).invert(), n = i.clone().applyMatrix4(o), _ = r.geometry.getAttribute("position"), u = 1e-6, p = u * u, f = new a.Vector3(), g = [];
1538
+ for (let y = 0; y < _.count; y++)
1539
+ f.fromBufferAttribute(_, y), f.distanceToSquared(n) < p && g.push(y);
1540
+ const v = r.children.find((y) => y?.isLineSegments);
1541
+ let m = [];
1542
+ if (v) {
1543
+ const y = new a.Matrix4().copy(v.matrixWorld).invert(), b = i.clone().applyMatrix4(y), L = v.geometry.getAttribute("position"), E = new a.Vector3();
1544
+ for (let T = 0; T < L.count; T++)
1545
+ E.fromBufferAttribute(L, T), E.distanceToSquared(b) < p && m.push(T);
1321
1546
  }
1322
1547
  this._selectVertex.userData.vertexInfo = {
1323
- points: t,
1324
- index: e,
1325
- mesh: s,
1326
- vertexIndices: b,
1327
- lines: O ?? null,
1328
- edgeVertexIndices: y
1548
+ points: e,
1549
+ index: t,
1550
+ mesh: r,
1551
+ vertexIndices: g,
1552
+ lines: v ?? null,
1553
+ edgeVertexIndices: m
1329
1554
  };
1330
1555
  }
1331
1556
  /** Центрует прокси-вершину на выбранной точке */
1332
- _centerVertexOnPoint(t, e, s) {
1333
- const i = e.geometry.getAttribute("position"), r = new a.Vector3(
1334
- i.getX(s),
1335
- i.getY(s),
1336
- i.getZ(s)
1337
- ).applyMatrix4(e.matrixWorld);
1338
- t.position.copy(r);
1339
- const o = t.geometry;
1557
+ _centerVertexOnPoint(e, t, r) {
1558
+ const s = t.geometry.getAttribute("position"), i = new a.Vector3(
1559
+ s.getX(r),
1560
+ s.getY(r),
1561
+ s.getZ(r)
1562
+ ).applyMatrix4(t.matrixWorld);
1563
+ e.position.copy(i);
1564
+ const o = e.geometry;
1340
1565
  let n = o.getAttribute("position");
1341
- (!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);
1566
+ (!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, e.quaternion.identity(), e.scale.set(1, 1, 1), e.updateMatrixWorld(!0);
1342
1567
  }
1343
1568
  };
1344
- re = Bt([
1345
- u(),
1346
- Le(0, h("RendererApi")),
1347
- Le(1, h("IEditorStore"))
1348
- ], re);
1349
- class me {
1350
- constructor(e, s) {
1351
- this.api = e, this.store = s, this._unsubscribeTransform = this.api.onTransformChange(() => {
1569
+ ye = Ms([
1570
+ d(),
1571
+ N(0, l("ICameraApi")),
1572
+ N(1, l("ISceneApi")),
1573
+ N(2, l("IRaycastApi")),
1574
+ N(3, l("EditorStore"))
1575
+ ], ye);
1576
+ class De {
1577
+ constructor(t, r) {
1578
+ this.api = t, this.store = r, this._unsubscribeTransform = this.api.onTransformChange(() => {
1352
1579
  this.store.getSelectedObject() && this.store.notifySelectedTransformChange?.();
1353
1580
  });
1354
1581
  }
@@ -1357,8 +1584,8 @@ class me {
1357
1584
  * Обновляет состояние инструмента под текущее выделение.
1358
1585
  */
1359
1586
  handle() {
1360
- const e = this.store.getSelectedObject();
1361
- this.api.setMode(this.mode), e ? this.api.attach(e) : this.api.detach();
1587
+ const t = this.store.getSelectedObject();
1588
+ this.api.setTransformMode(this.mode), t ? this.api.attachTransform(t) : this.api.detachTransform();
1362
1589
  }
1363
1590
  /**
1364
1591
  * Откатывает локальное состояние инструмента при смене инструмента.
@@ -1366,75 +1593,75 @@ class me {
1366
1593
  * Вызывается менеджером перед активацией другого хендлера.
1367
1594
  */
1368
1595
  rollback() {
1369
- this.api.detach();
1596
+ this.api.detachTransform();
1370
1597
  }
1371
1598
  /** Освобождение ресурсов хендлера. */
1372
1599
  dispose() {
1373
1600
  this.rollback(), this._unsubscribeTransform && this._unsubscribeTransform();
1374
1601
  }
1375
1602
  }
1376
- var Xt = Object.getOwnPropertyDescriptor, Gt = (t, e, s, i) => {
1377
- for (var r = i > 1 ? void 0 : i ? Xt(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1378
- (n = t[o]) && (r = n(r) || r);
1379
- return r;
1380
- }, De = (t, e) => (s, i) => e(s, i, t);
1381
- let oe = class extends me {
1603
+ var ys = Object.getOwnPropertyDescriptor, bs = (e, t, r, s) => {
1604
+ for (var i = s > 1 ? void 0 : s ? ys(t, r) : t, o = e.length - 1, n; o >= 0; o--)
1605
+ (n = e[o]) && (i = n(i) || i);
1606
+ return i;
1607
+ }, We = (e, t) => (r, s) => t(r, s, e);
1608
+ let be = class extends De {
1382
1609
  /** Инструмент, которым управляет хендлер, нужен только менеджеру */
1383
- mode = C.Translate;
1384
- constructor(t, e) {
1385
- super(t, e);
1610
+ mode = j.Translate;
1611
+ constructor(e, t) {
1612
+ super(e, t);
1386
1613
  }
1387
1614
  };
1388
- oe = Gt([
1389
- u(),
1390
- De(0, h("RendererApi")),
1391
- De(1, h("IEditorStore"))
1392
- ], oe);
1393
- var Kt = Object.getOwnPropertyDescriptor, qt = (t, e, s, i) => {
1394
- for (var r = i > 1 ? void 0 : i ? Kt(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1395
- (n = t[o]) && (r = n(r) || r);
1396
- return r;
1397
- }, Ce = (t, e) => (s, i) => e(s, i, t);
1398
- let ne = class extends me {
1615
+ be = bs([
1616
+ d(),
1617
+ We(0, l("ITransformApi")),
1618
+ We(1, l("EditorStore"))
1619
+ ], be);
1620
+ var Ss = Object.getOwnPropertyDescriptor, As = (e, t, r, s) => {
1621
+ for (var i = s > 1 ? void 0 : s ? Ss(t, r) : t, o = e.length - 1, n; o >= 0; o--)
1622
+ (n = e[o]) && (i = n(i) || i);
1623
+ return i;
1624
+ }, ke = (e, t) => (r, s) => t(r, s, e);
1625
+ let Se = class extends De {
1399
1626
  /** Инструмент, которым управляет хендлер, нужен только менеджеру */
1400
- mode = C.Scale;
1401
- constructor(t, e) {
1402
- super(t, e);
1627
+ mode = j.Scale;
1628
+ constructor(e, t) {
1629
+ super(e, t);
1403
1630
  }
1404
1631
  };
1405
- ne = qt([
1406
- u(),
1407
- Ce(0, h("RendererApi")),
1408
- Ce(1, h("IEditorStore"))
1409
- ], ne);
1410
- var Qt = Object.getOwnPropertyDescriptor, Jt = (t, e, s, i) => {
1411
- for (var r = i > 1 ? void 0 : i ? Qt(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1412
- (n = t[o]) && (r = n(r) || r);
1413
- return r;
1414
- }, Ae = (t, e) => (s, i) => e(s, i, t);
1415
- let ae = class extends me {
1632
+ Se = As([
1633
+ d(),
1634
+ ke(0, l("ITransformApi")),
1635
+ ke(1, l("EditorStore"))
1636
+ ], Se);
1637
+ var ws = Object.getOwnPropertyDescriptor, xs = (e, t, r, s) => {
1638
+ for (var i = s > 1 ? void 0 : s ? ws(t, r) : t, o = e.length - 1, n; o >= 0; o--)
1639
+ (n = e[o]) && (i = n(i) || i);
1640
+ return i;
1641
+ }, Ge = (e, t) => (r, s) => t(r, s, e);
1642
+ let Ae = class extends De {
1416
1643
  /** Инструмент, которым управляет хендлер, нужен только менеджеру */
1417
- mode = C.Rotate;
1418
- constructor(t, e) {
1419
- super(t, e);
1644
+ mode = j.Rotate;
1645
+ constructor(e, t) {
1646
+ super(e, t);
1420
1647
  }
1421
1648
  };
1422
- ae = Jt([
1423
- u(),
1424
- Ae(0, h("RendererApi")),
1425
- Ae(1, h("IEditorStore"))
1426
- ], ae);
1427
- var es = Object.getOwnPropertyDescriptor, ts = (t, e, s, i) => {
1428
- for (var r = i > 1 ? void 0 : i ? es(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1429
- (n = t[o]) && (r = n(r) || r);
1430
- return r;
1431
- }, xe = (t, e) => (s, i) => e(s, i, t);
1432
- let he = class {
1433
- constructor(t, e) {
1434
- this._api = t, this._store = e, this._api.enableCameraLayer(L), this._hoverLine = this._makeOverlayLine(this._hoverColor), this._selectLine = this._makeOverlayLine(this._selectColor), this._api.addObject(this._hoverLine, L), this._api.addObject(this._selectLine, L);
1649
+ Ae = xs([
1650
+ d(),
1651
+ Ge(0, l("ITransformApi")),
1652
+ Ge(1, l("EditorStore"))
1653
+ ], Ae);
1654
+ var Os = Object.getOwnPropertyDescriptor, Cs = (e, t, r, s) => {
1655
+ for (var i = s > 1 ? void 0 : s ? Os(t, r) : t, o = e.length - 1, n; o >= 0; o--)
1656
+ (n = e[o]) && (i = n(i) || i);
1657
+ return i;
1658
+ }, U = (e, t) => (r, s) => t(r, s, e);
1659
+ let we = class {
1660
+ constructor(e, t, r, s) {
1661
+ this._sceneApi = e, this._cameraApi = t, this._raycastApi = r, this._store = s, this._cameraApi.enableCameraLayer(x), this._hoverLine = this._makeOverlayLine(this._hoverColor), this._selectLine = this._makeOverlayLine(this._selectColor), this._sceneApi.addObject(this._hoverLine, x), this._sceneApi.addObject(this._selectLine, x);
1435
1662
  }
1436
1663
  /** Режим, которым управляет хендлер, нужен только менеджеру */
1437
- mode = v.Edge;
1664
+ mode = M.Edge;
1438
1665
  /** Текущее наведённое ребро. */
1439
1666
  _hoverLine;
1440
1667
  /** Текущее выбранное ребро. */
@@ -1445,141 +1672,143 @@ let he = class {
1445
1672
  _selected = null;
1446
1673
  // Цвета, необходимые для переключения
1447
1674
  /** Цвет ребра, на которое навелись */
1448
- _hoverColor = F;
1675
+ _hoverColor = Z;
1449
1676
  /** Цвет выделенного ребра */
1450
- _selectColor = Z;
1677
+ _selectColor = q;
1451
1678
  /** Обработка текущего режима выборки. */
1452
- handle(t, e) {
1453
- if (this._api.setRaycastMode(this.mode), e === P.Hover) {
1454
- if (!t) {
1679
+ handle(e, t) {
1680
+ if (this._raycastApi.setRaycastMode(this.mode), t === C.Hover) {
1681
+ if (!e) {
1455
1682
  this._hoverLine.visible = !1, this._hovered = null;
1456
1683
  return;
1457
1684
  }
1458
- const s = t.intersection.object;
1459
- if (!s?.isLineSegments) return;
1460
- const i = s, r = Math.floor((t.intersection.index ?? -1) / 2);
1461
- if (r < 0) return;
1462
- 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 };
1685
+ const r = e.intersection.object;
1686
+ if (!r?.isLineSegments) return;
1687
+ const s = r, i = Math.floor((e.intersection.index ?? -1) / 2);
1688
+ if (i < 0) return;
1689
+ this._selected && this._same({ lines: s, seg: i }, this._selected) ? this._hoverLine.visible = !1 : (this._writeWorldSegment(this._hoverLine, s, i), this._hoverLine.visible = !0), this._hovered = { lines: s, seg: i };
1463
1690
  return;
1464
1691
  }
1465
- if (e === P.Click) {
1466
- if (!t) {
1692
+ if (t === C.Click) {
1693
+ if (!e) {
1467
1694
  this._selectLine.visible = !1, this._selected = null, this._store.setSelectedObject(null);
1468
1695
  return;
1469
1696
  }
1470
- const s = t.intersection.object;
1471
- if (!s?.isLineSegments) return;
1472
- const i = s, r = Math.floor((t.intersection.index ?? -1) / 2);
1473
- if (r < 0) return;
1474
- 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);
1697
+ const r = e.intersection.object;
1698
+ if (!r?.isLineSegments) return;
1699
+ const s = r, i = Math.floor((e.intersection.index ?? -1) / 2);
1700
+ if (i < 0) return;
1701
+ this._writeWorldSegment(this._selectLine, s, i), this._centerAndOrientLineOnSegment(this._selectLine, s, i), this._selectLine.visible = !0, this._prepareEdgeMetadata(s, i), this._store.setSelectedObject(this._selectLine), this._selected = { lines: s, seg: i }, this._hovered && this._same(this._hovered, this._selected) && (this._hoverLine.visible = !1);
1475
1702
  }
1476
1703
  }
1477
1704
  /** Откат текущего режима выборки */
1478
1705
  rollback() {
1479
- this._hoverLine.visible = !1, this._selectLine.visible = !1, this._hovered = this._selected = null;
1706
+ this._hoverLine.visible = !1, this._selectLine.visible = !1, this._hovered = this._selected = null, this._store.setSelectedObject(null);
1480
1707
  }
1481
1708
  /** Освобождает ресурсы хендлера, удаляет слушатели и очищает внутренние данные. */
1482
1709
  dispose() {
1483
- 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();
1710
+ 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();
1484
1711
  }
1485
1712
  /** Инициализация буферных линий для режима (hover и click).
1486
1713
  * На весь режим будет использовано 2 глобальных линии на сцене,
1487
1714
  * использоваться они будут только для обозначения геометрии ребер конкретной фигуры.
1488
1715
  */
1489
- _makeOverlayLine(t) {
1490
- const e = new a.BufferGeometry();
1491
- e.setAttribute("position", new a.Float32BufferAttribute(6, 3));
1492
- const s = new a.LineBasicMaterial({
1493
- color: t,
1716
+ _makeOverlayLine(e) {
1717
+ const t = new a.BufferGeometry();
1718
+ t.setAttribute("position", new a.Float32BufferAttribute(6, 3));
1719
+ const r = new a.LineBasicMaterial({
1720
+ color: e,
1494
1721
  depthTest: !1,
1495
1722
  depthWrite: !1,
1496
1723
  transparent: !0,
1497
1724
  opacity: 1
1498
- }), i = new a.Line(e, s);
1499
- return i.renderOrder = 1e3, i.raycast = () => {
1500
- }, i.layers.set(L), i.visible = !1, i;
1725
+ }), s = new a.Line(t, r);
1726
+ return s.renderOrder = 1e3, s.raycast = () => {
1727
+ }, s.layers.set(x), s.visible = !1, s;
1501
1728
  }
1502
1729
  /** Локальные точки сегмента переводим в target (который висит на сцене) */
1503
- _writeWorldSegment(t, e, s) {
1504
- 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(
1505
- e.matrixWorld
1506
- ), c = new a.Vector3(i.getX(o), i.getY(o), i.getZ(o)).applyMatrix4(
1507
- e.matrixWorld
1508
- ), _ = t.geometry.getAttribute("position");
1730
+ _writeWorldSegment(e, t, r) {
1731
+ const s = t.geometry.getAttribute("position"), i = r * 2, o = i + 1, n = new a.Vector3(s.getX(i), s.getY(i), s.getZ(i)).applyMatrix4(
1732
+ t.matrixWorld
1733
+ ), c = new a.Vector3(s.getX(o), s.getY(o), s.getZ(o)).applyMatrix4(
1734
+ t.matrixWorld
1735
+ ), _ = e.geometry.getAttribute("position");
1509
1736
  _.setXYZ(0, n.x, n.y, n.z), _.setXYZ(1, c.x, c.y, c.z), _.needsUpdate = !0;
1510
1737
  }
1511
- _same(t, e) {
1512
- return !!t && !!e && t.lines === e.lines && t.seg === e.seg;
1738
+ _same(e, t) {
1739
+ return !!e && !!t && e.lines === t.lines && e.seg === t.seg;
1513
1740
  }
1514
1741
  /** Центрует `THREE.Line` на сегменте и ориентирует её вдоль ребра */
1515
- _centerAndOrientLineOnSegment(t, e, s) {
1516
- 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(
1517
- e.matrixWorld
1518
- ), c = new a.Vector3(i.getX(o), i.getY(o), i.getZ(o)).applyMatrix4(
1519
- e.matrixWorld
1520
- ), _ = new a.Vector3().subVectors(c, n), m = _.length();
1521
- if (!isFinite(m) || m === 0) return;
1522
- const f = new a.Vector3().addVectors(n, c).multiplyScalar(0.5);
1523
- t.position.copy(f);
1524
- const D = t.geometry;
1525
- let b = D.getAttribute("position");
1526
- (!b || b.count < 2) && (D.setAttribute("position", new a.BufferAttribute(new Float32Array(6), 3)), b = D.getAttribute("position")), b.setXYZ(0, -m / 2, 0, 0), b.setXYZ(1, m / 2, 0, 0), b.needsUpdate = !0, _.normalize();
1527
- const O = new a.Quaternion().setFromUnitVectors(new a.Vector3(1, 0, 0), _);
1528
- t.quaternion.copy(O), t.updateMatrixWorld(!0);
1529
- }
1530
- /** Запись метаданных выбранного ребра для использования инструментов */
1531
- _prepareEdgeMetadata(t, e) {
1532
- const s = Ve(t);
1533
- if (!s) return;
1534
- 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(
1742
+ _centerAndOrientLineOnSegment(e, t, r) {
1743
+ const s = t.geometry.getAttribute("position"), i = r * 2, o = i + 1, n = new a.Vector3(s.getX(i), s.getY(i), s.getZ(i)).applyMatrix4(
1535
1744
  t.matrixWorld
1536
- ), c = new a.Vector3(i.getX(o), i.getY(o), i.getZ(o)).applyMatrix4(
1745
+ ), c = new a.Vector3(s.getX(o), s.getY(o), s.getZ(o)).applyMatrix4(
1537
1746
  t.matrixWorld
1538
- ), _ = new a.Matrix4().copy(s.matrixWorld).invert(), m = n.clone().applyMatrix4(_), f = c.clone().applyMatrix4(_), b = s.geometry.getAttribute("position"), O = new a.Vector3(), y = 1e-6, M = [], Y = [];
1539
- for (let E = 0; E < b.count; E++)
1540
- O.fromBufferAttribute(b, E), O.distanceToSquared(m) < y * y ? M.push(E) : O.distanceToSquared(f) < y * y && Y.push(E);
1541
- const k = new a.Matrix4().copy(t.matrixWorld).invert(), z = n.clone().applyMatrix4(k), A = c.clone().applyMatrix4(k), fe = t.geometry.getAttribute("position"), $ = new a.Vector3(), ge = [], be = [];
1542
- for (let E = 0; E < fe.count; E++)
1543
- $.fromBufferAttribute(fe, E), $.distanceToSquared(z) < y * y ? ge.push(E) : $.distanceToSquared(A) < y * y && be.push(E);
1747
+ ), _ = new a.Vector3().subVectors(c, n), u = _.length();
1748
+ if (!isFinite(u) || u === 0) return;
1749
+ const p = new a.Vector3().addVectors(n, c).multiplyScalar(0.5);
1750
+ e.position.copy(p);
1751
+ const f = e.geometry;
1752
+ let g = f.getAttribute("position");
1753
+ (!g || g.count < 2) && (f.setAttribute("position", new a.BufferAttribute(new Float32Array(6), 3)), g = f.getAttribute("position")), g.setXYZ(0, -u / 2, 0, 0), g.setXYZ(1, u / 2, 0, 0), g.needsUpdate = !0, _.normalize();
1754
+ const v = new a.Quaternion().setFromUnitVectors(new a.Vector3(1, 0, 0), _);
1755
+ e.quaternion.copy(v), e.updateMatrixWorld(!0);
1756
+ }
1757
+ /** Запись метаданных выбранного ребра для использования инструментов */
1758
+ _prepareEdgeMetadata(e, t) {
1759
+ const r = Ze(e);
1760
+ if (!r) return;
1761
+ const s = e.geometry.getAttribute("position"), i = t * 2, o = i + 1, n = new a.Vector3(s.getX(i), s.getY(i), s.getZ(i)).applyMatrix4(
1762
+ e.matrixWorld
1763
+ ), c = new a.Vector3(s.getX(o), s.getY(o), s.getZ(o)).applyMatrix4(
1764
+ e.matrixWorld
1765
+ ), _ = new a.Matrix4().copy(r.matrixWorld).invert(), u = n.clone().applyMatrix4(_), p = c.clone().applyMatrix4(_), g = r.geometry.getAttribute("position"), v = new a.Vector3(), m = 1e-6, y = [], b = [];
1766
+ for (let A = 0; A < g.count; A++)
1767
+ v.fromBufferAttribute(g, A), v.distanceToSquared(u) < m * m ? y.push(A) : v.distanceToSquared(p) < m * m && b.push(A);
1768
+ const L = new a.Matrix4().copy(e.matrixWorld).invert(), E = n.clone().applyMatrix4(L), T = c.clone().applyMatrix4(L), S = e.geometry.getAttribute("position"), w = new a.Vector3(), I = [], $ = [];
1769
+ for (let A = 0; A < S.count; A++)
1770
+ w.fromBufferAttribute(S, A), w.distanceToSquared(E) < m * m ? I.push(A) : w.distanceToSquared(T) < m * m && $.push(A);
1544
1771
  this._selectLine.userData.edgeInfo = {
1545
- lines: t,
1546
- seg: e,
1547
- mesh: s,
1548
- aIndices: M,
1549
- bIndices: Y,
1550
- aEdgeIndices: ge,
1551
- bEdgeIndices: be
1772
+ lines: e,
1773
+ seg: t,
1774
+ mesh: r,
1775
+ aIndices: y,
1776
+ bIndices: b,
1777
+ aEdgeIndices: I,
1778
+ bEdgeIndices: $
1552
1779
  };
1553
1780
  }
1554
1781
  };
1555
- he = ts([
1556
- u(),
1557
- xe(0, h("RendererApi")),
1558
- xe(1, h("IEditorStore"))
1559
- ], he);
1560
- var ss = Object.getOwnPropertyDescriptor, is = (t, e, s, i) => {
1561
- for (var r = i > 1 ? void 0 : i ? ss(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1562
- (n = t[o]) && (r = n(r) || r);
1563
- return r;
1564
- }, rs = (t, e) => (s, i) => e(s, i, t);
1565
- let le = class {
1566
- constructor(t) {
1567
- this._api = t;
1782
+ we = Cs([
1783
+ d(),
1784
+ U(0, l("ISceneApi")),
1785
+ U(1, l("ICameraApi")),
1786
+ U(2, l("IRaycastApi")),
1787
+ U(3, l("EditorStore"))
1788
+ ], we);
1789
+ var Is = Object.getOwnPropertyDescriptor, Ps = (e, t, r, s) => {
1790
+ for (var i = s > 1 ? void 0 : s ? Is(t, r) : t, o = e.length - 1, n; o >= 0; o--)
1791
+ (n = e[o]) && (i = n(i) || i);
1792
+ return i;
1793
+ }, Ls = (e, t) => (r, s) => t(r, s, e);
1794
+ let xe = class {
1795
+ constructor(e) {
1796
+ this._api = e;
1568
1797
  }
1569
1798
  /** Режим редактирования сцены */
1570
- mode = N.AddFigure;
1799
+ mode = W.AddFigure;
1571
1800
  /** Последняя добавленная фигура, нужно для отката через `ctrl + z`. */
1572
1801
  _lastAddedMesh = null;
1573
1802
  /** Добавление базовых фигур на сцену, которые приписаны в `FigureType`. */
1574
- handle(t) {
1575
- const e = et[t](), s = e.getAttribute("position");
1576
- s && s.setUsage && s.setUsage(a.DynamicDrawUsage);
1577
- const i = new a.Mesh(e, Ie);
1578
- i.layers.enable(ke);
1579
- const r = Ye(i.geometry);
1580
- i.add(r);
1581
- const o = Ne(i.geometry);
1582
- i.add(o), this._api.addMesh(i), this._lastAddedMesh = i;
1803
+ handle(e) {
1804
+ const t = _s[e](), r = t.getAttribute("position");
1805
+ r && r.setUsage && r.setUsage(a.DynamicDrawUsage);
1806
+ const s = new a.Mesh(t, ds);
1807
+ s.layers.enable(k);
1808
+ const i = t.index ? t.toNonIndexed() : t, o = gs(i);
1809
+ o.layers.enable(k), s.add(o);
1810
+ const n = ms(i);
1811
+ n.layers.enable(k), s.add(n), this._api.addMesh(s), this._lastAddedMesh = s;
1583
1812
  }
1584
1813
  /** Срабатывает только на `ctrl + z`. */
1585
1814
  rollback() {
@@ -1590,26 +1819,26 @@ let le = class {
1590
1819
  this._lastAddedMesh = null;
1591
1820
  }
1592
1821
  };
1593
- le = is([
1594
- u(),
1595
- rs(0, h("RendererApi"))
1596
- ], le);
1597
- var os = Object.getOwnPropertyDescriptor, ns = (t, e, s, i) => {
1598
- for (var r = i > 1 ? void 0 : i ? os(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1599
- (n = t[o]) && (r = n(r) || r);
1600
- return r;
1601
- }, Re = (t, e) => (s, i) => e(s, i, t);
1602
- let ce = class {
1603
- constructor(t, e) {
1604
- this._api = t, this._store = e;
1822
+ xe = Ps([
1823
+ d(),
1824
+ Ls(0, l("IMeshApi"))
1825
+ ], xe);
1826
+ var Es = Object.getOwnPropertyDescriptor, Ts = (e, t, r, s) => {
1827
+ for (var i = s > 1 ? void 0 : s ? Es(t, r) : t, o = e.length - 1, n; o >= 0; o--)
1828
+ (n = e[o]) && (i = n(i) || i);
1829
+ return i;
1830
+ }, Be = (e, t) => (r, s) => t(r, s, e);
1831
+ let Oe = class {
1832
+ constructor(e, t) {
1833
+ this._api = e, this._store = t;
1605
1834
  }
1606
1835
  /** Режим редактирования сцены */
1607
- mode = N.DeleteFigure;
1836
+ mode = W.DeleteFigure;
1608
1837
  /** Последняя удаленная фигура, сохраняем для отката через `ctrl + z` */
1609
1838
  _lastDeletedMesh = null;
1610
1839
  handle() {
1611
- const t = this._store.getSelectedObject();
1612
- ct(t) && (this._api.removeMesh(t), this._store.setSelectedObject(null), this._lastDeletedMesh = t);
1840
+ const e = this._store.getSelectedObject();
1841
+ ps(e) && (this._api.removeMesh(e), this._store.setSelectedObject(null), this._lastDeletedMesh = e);
1613
1842
  }
1614
1843
  /** Срабатывает только на `ctrl + z`. */
1615
1844
  rollback() {
@@ -1620,147 +1849,209 @@ let ce = class {
1620
1849
  this._lastDeletedMesh = null;
1621
1850
  }
1622
1851
  };
1623
- ce = ns([
1624
- u(),
1625
- Re(0, h("RendererApi")),
1626
- Re(1, h("IEditorStore"))
1627
- ], ce);
1628
- var as = Object.getOwnPropertyDescriptor, hs = (t, e, s, i) => {
1629
- for (var r = i > 1 ? void 0 : i ? as(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1630
- (n = t[o]) && (r = n(r) || r);
1631
- return r;
1632
- }, ls = (t, e) => (s, i) => e(s, i, t);
1633
- let de = class {
1634
- constructor(t) {
1635
- this._renderer = t;
1636
- }
1637
- /** @inheritdoc */
1638
- addMesh(t) {
1639
- this._renderer.addMesh(t);
1640
- }
1641
- /** @inheritdoc */
1642
- addMeshes(t) {
1643
- for (const e of t)
1644
- this._renderer.addMesh(e);
1645
- }
1646
- /** @inheritdoc */
1647
- removeMesh(t) {
1648
- this._renderer.removeMesh(t);
1649
- }
1650
- /** @inheritdoc */
1651
- removeMeshes(t) {
1652
- for (const e of t)
1653
- this._renderer.removeMesh(e);
1654
- }
1655
- /** @inheritdoc */
1656
- getMeshes() {
1657
- return this._renderer.getMeshes();
1658
- }
1659
- /** @inheritdoc */
1660
- setMode(t) {
1661
- this._renderer.setTransformControlsMode(t);
1662
- }
1663
- /** @inheritdoc */
1664
- attach(t) {
1665
- this._renderer.attachTransformControls(t);
1666
- }
1667
- /** @inheritdoc */
1668
- detach() {
1669
- this._renderer.detachTransformControls();
1670
- }
1671
- /** @inheritdoc */
1672
- setRaycastMode(t) {
1673
- this._renderer.setRaycastMode(t);
1674
- }
1675
- /** @inheritdoc */
1676
- addObject(t, e) {
1677
- this._renderer.addObject(t, e);
1678
- }
1679
- /** @inheritdoc */
1680
- removeObject(t) {
1681
- this._renderer.removeObject(t);
1682
- }
1683
- /** @inheritdoc */
1684
- enableCameraLayer(t) {
1685
- this._renderer.enableCameraLayer(t);
1686
- }
1687
- /** @inheritdoc */
1688
- onTransformChange(t) {
1689
- return this._renderer.onTransformChange(t);
1690
- }
1691
- };
1692
- de = hs([
1693
- u(),
1694
- ls(0, h("EditorRenderer"))
1695
- ], de);
1696
- var cs = Object.getOwnPropertyDescriptor, ds = (t, e, s, i) => {
1697
- for (var r = i > 1 ? void 0 : i ? cs(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1698
- (n = t[o]) && (r = n(r) || r);
1699
- return r;
1700
- }, x = (t, e) => (s, i) => e(s, i, t);
1701
- let _e = class {
1702
- constructor(t, e, s, i, r, o) {
1703
- this._displayManager = t, this._selectManager = e, this._toolManager = s, this._sceneManager = i, this._renderer = r, this._store = o, this.setSelectMode(v.Mesh), this.setToolMode(C.Translate);
1852
+ Oe = Ts([
1853
+ d(),
1854
+ Be(0, l("IMeshApi")),
1855
+ Be(1, l("EditorStore"))
1856
+ ], Oe);
1857
+ var Ds = Object.getOwnPropertyDescriptor, Vs = (e, t, r, s) => {
1858
+ for (var i = s > 1 ? void 0 : s ? Ds(t, r) : t, o = e.length - 1, n; o >= 0; o--)
1859
+ (n = e[o]) && (i = n(i) || i);
1860
+ return i;
1861
+ }, X = (e, t) => (r, s) => t(r, s, e);
1862
+ let Ce = class {
1863
+ constructor(e, t, r, s) {
1864
+ this._renderer = e, this._mediator = t, this._store = r, this._controller = s, this.setSelectMode(M.Mesh), this.setToolMode(j.Translate);
1865
+ }
1866
+ setDisplayMode(e) {
1867
+ return this._mediator.send({
1868
+ type: P.Display,
1869
+ payload: [e]
1870
+ });
1704
1871
  }
1705
- setDisplayMode(t) {
1706
- this._displayManager.manage(t);
1872
+ setSceneMode(e) {
1873
+ return this._mediator.send({
1874
+ type: P.Scene,
1875
+ payload: [e]
1876
+ });
1707
1877
  }
1708
- setSceneMode(t) {
1709
- this._sceneManager.manage(t);
1878
+ setSelectMode(e) {
1879
+ return this._mediator.send({
1880
+ type: P.Select,
1881
+ payload: [e]
1882
+ });
1710
1883
  }
1711
- setSelectMode(t) {
1712
- this._selectManager.manage(t);
1884
+ setToolMode(e) {
1885
+ return this._mediator.send({
1886
+ type: P.Tool,
1887
+ payload: [e]
1888
+ });
1713
1889
  }
1714
- setToolMode(t) {
1715
- this._toolManager.manage(t);
1890
+ addFigure(e, t) {
1891
+ return this._mediator.send({
1892
+ type: P.Scene,
1893
+ payload: [e, t]
1894
+ });
1716
1895
  }
1717
1896
  resizeRenderer() {
1718
1897
  this._renderer.resize();
1719
1898
  }
1720
- updateRenderer() {
1721
- this._renderer.loop();
1899
+ /**
1900
+ * Запускает редактор.
1901
+ * Вызывается после создания хаба.
1902
+ */
1903
+ start() {
1904
+ this._controller.start();
1722
1905
  }
1723
- addFigure(t, e) {
1724
- this._sceneManager.manage(t, e);
1906
+ /**
1907
+ * Останавливает редактор.
1908
+ */
1909
+ stop() {
1910
+ this._controller.stop();
1725
1911
  }
1726
1912
  getSelectionStats() {
1727
1913
  return this._store.getSelectionStats();
1728
1914
  }
1729
- onSelectionStatsChange(t) {
1730
- const e = this._store.onSelectedObjectChange(() => {
1731
- t();
1732
- }), s = this._store.onSelectedTransformChange(() => {
1733
- t();
1915
+ onSelectionStatsChange(e) {
1916
+ const t = this._store.onSelectedObjectChange(() => {
1917
+ e();
1918
+ }), r = this._store.onSelectedTransformChange(() => {
1919
+ e();
1734
1920
  });
1735
1921
  return () => {
1736
- e(), s();
1922
+ t(), r();
1737
1923
  };
1738
1924
  }
1739
1925
  dispose() {
1740
- this._displayManager.dispose(), this._selectManager.dispose(), this._renderer.dispose();
1926
+ this._mediator.dispose();
1741
1927
  }
1742
1928
  };
1743
- _e = ds([
1744
- u(),
1745
- x(0, h("IDisplayManager")),
1746
- x(1, h("ISelectManager")),
1747
- x(2, h("IToolManager")),
1748
- x(3, h("ISceneManager")),
1749
- x(4, h("EditorRenderer")),
1750
- x(5, h("IEditorStore"))
1751
- ], _e);
1752
- var _s = Object.getOwnPropertyDescriptor, ps = (t, e, s, i) => {
1753
- for (var r = i > 1 ? void 0 : i ? _s(e, s) : e, o = t.length - 1, n; o >= 0; o--)
1754
- (n = t[o]) && (r = n(r) || r);
1755
- return r;
1929
+ Ce = Vs([
1930
+ d(),
1931
+ X(0, l("Renderer")),
1932
+ X(1, l("IMediator")),
1933
+ X(2, l("EditorStore")),
1934
+ X(3, l("IController"))
1935
+ ], Ce);
1936
+ var $s = Object.getOwnPropertyDescriptor, js = (e, t, r, s) => {
1937
+ for (var i = s > 1 ? void 0 : s ? $s(t, r) : t, o = e.length - 1, n; o >= 0; o--)
1938
+ (n = e[o]) && (i = n(i) || i);
1939
+ return i;
1756
1940
  };
1757
- let pe = class {
1941
+ let Ie = class {
1942
+ /**
1943
+ * Внутренний эмиттер событий Node.js.
1944
+ *
1945
+ * @private
1946
+ * @member
1947
+ */
1948
+ _emitter;
1949
+ /** @constructor */
1950
+ constructor() {
1951
+ this._emitter = new at();
1952
+ }
1953
+ /**
1954
+ * Публикует событие в шину.
1955
+ *
1956
+ * @param event - название события (из `EventTopics`)
1957
+ * @param payload - данные события (тип зависит от события)
1958
+ *
1959
+ * @typeParam K - ключ события из `EditorEvents`
1960
+ *
1961
+ * @remarks
1962
+ * Все подписчики, зарегистрированные на это событие, получат payload.
1963
+ *
1964
+ * @example
1965
+ * ```typescript
1966
+ * // Публикация события клика
1967
+ * eventBus.emit(EventTopics.SelectClick, { intersection: hit });
1968
+ *
1969
+ * // Публикация события сброса выделения
1970
+ * eventBus.emit(EventTopics.SelectClick, null);
1971
+ * ```
1972
+ *
1973
+ * @public
1974
+ * @method
1975
+ */
1976
+ emit(e, t) {
1977
+ this._emitter.emit(e, t);
1978
+ }
1979
+ /**
1980
+ * Подписывается на событие.
1981
+ *
1982
+ * @param event - название события (из `EventTopics`)
1983
+ * @param listener - функция-обработчик, получающая payload
1984
+ *
1985
+ * @typeParam K - ключ события из `EditorEvents`
1986
+ *
1987
+ * @remarks
1988
+ * **Важно:** для предотвращения утечек памяти необходимо отписываться от событий
1989
+ * в `dispose()` методах компонентов.
1990
+ *
1991
+ * @example
1992
+ * ```typescript
1993
+ * // Подписка на событие hover
1994
+ * this._eventBus.on(EventTopics.SelectHover, (payload) => {
1995
+ * if (payload) {
1996
+ * this._handleHover(payload.intersection);
1997
+ * } else {
1998
+ * this._clearHover();
1999
+ * }
2000
+ * });
2001
+ * ```
2002
+ *
2003
+ * @public
2004
+ * @method
2005
+ */
2006
+ on(e, t) {
2007
+ this._emitter.on(e, t);
2008
+ }
2009
+ /**
2010
+ * Отписывается от события.
2011
+ *
2012
+ * @param event - название события (из `EventTopics`)
2013
+ * @param listener - функция-обработчик, которую нужно отписать
2014
+ *
2015
+ * @typeParam K - ключ события из `EditorEvents`
2016
+ *
2017
+ * @remarks
2018
+ * Для корректной отписки необходимо передать ту же самую функцию,
2019
+ * которая использовалась при подписке.
2020
+ *
2021
+ * @example
2022
+ * ```typescript
2023
+ * // Сохранение ссылки на обработчик
2024
+ * private _handleClick = (payload) => { ... };
2025
+ *
2026
+ * // Подписка
2027
+ * eventBus.on(EventTopics.SelectClick, this._handleClick);
2028
+ *
2029
+ * // Отписка (в dispose)
2030
+ * eventBus.off(EventTopics.SelectClick, this._handleClick);
2031
+ * ```
2032
+ *
2033
+ * @public
2034
+ * @method
2035
+ */
2036
+ off(e, t) {
2037
+ this._emitter.off(e, t);
2038
+ }
2039
+ };
2040
+ Ie = js([
2041
+ d()
2042
+ ], Ie);
2043
+ var Hs = Object.getOwnPropertyDescriptor, Rs = (e, t, r, s) => {
2044
+ for (var i = s > 1 ? void 0 : s ? Hs(t, r) : t, o = e.length - 1, n; o >= 0; o--)
2045
+ (n = e[o]) && (i = n(i) || i);
2046
+ return i;
2047
+ };
2048
+ let Pe = class {
1758
2049
  /** Текущий режим выборки. */
1759
- _selectMode = v.Mesh;
2050
+ _selectMode = M.Mesh;
1760
2051
  /** Текущий выбранный инструмент. */
1761
- _toolType = C.Translate;
2052
+ _toolType = j.Translate;
1762
2053
  /** Выбранный режим отображения. */
1763
- _displayMode = V.Plane;
2054
+ _displayMode = F.Plane;
1764
2055
  /** Выбранный объект на сцене. */
1765
2056
  _selectedObject = null;
1766
2057
  /** Слушатели событий по изменению выбранного объекта. */
@@ -1768,83 +2059,164 @@ let pe = class {
1768
2059
  /** Слушатели событий трансформации выбранного объекта. */
1769
2060
  _transformListeners = /* @__PURE__ */ new Set();
1770
2061
  constructor() {
1771
- Je(this, {}, { autoBind: !0 });
2062
+ ct(this, {}, { autoBind: !0 });
1772
2063
  }
1773
- /** @inheritdoc */
1774
2064
  getSelectMode() {
1775
2065
  return this._selectMode;
1776
2066
  }
1777
- /** @inheritdoc */
1778
2067
  getToolType() {
1779
2068
  return this._toolType;
1780
2069
  }
1781
- /** @inheritdoc */
1782
2070
  getDisplayMode() {
1783
2071
  return this._displayMode;
1784
2072
  }
1785
- /** @inheritdoc */
1786
- setSelectMode(t) {
1787
- this._selectMode = t;
2073
+ setSelectMode(e) {
2074
+ this._selectMode = e;
1788
2075
  }
1789
- /** @inheritdoc */
1790
- setToolType(t) {
1791
- this._toolType = t;
2076
+ setToolType(e) {
2077
+ this._toolType = e;
1792
2078
  }
1793
- /** @inheritdoc */
1794
- setDisplayMode(t) {
1795
- this._displayMode = t;
2079
+ setDisplayMode(e) {
2080
+ this._displayMode = e;
1796
2081
  }
1797
- /** @inheritdoc */
1798
2082
  getSelectedObject() {
1799
2083
  return this._selectedObject;
1800
2084
  }
1801
- /** @inheritdoc */
1802
2085
  getSelectionStats() {
1803
- const t = this._selectedObject;
1804
- return t ? dt(t) : null;
1805
- }
1806
- /** @inheritdoc */
1807
- setSelectedObject(t) {
1808
- if (this._selectedObject !== t) {
1809
- this._selectedObject = t;
1810
- for (const e of this._selectedListeners) e(this._selectedObject);
2086
+ const e = this._selectedObject;
2087
+ return e ? vs(e) : null;
2088
+ }
2089
+ setSelectedObject(e) {
2090
+ if (this._selectedObject !== e) {
2091
+ this._selectedObject = e;
2092
+ for (const t of this._selectedListeners) t(this._selectedObject);
1811
2093
  }
1812
2094
  }
1813
- /** @inheritdoc */
1814
- onSelectedObjectChange(t) {
1815
- return this._selectedListeners.add(t), () => this._selectedListeners.delete(t);
2095
+ onSelectedObjectChange(e) {
2096
+ return this._selectedListeners.add(e), () => this._selectedListeners.delete(e);
1816
2097
  }
1817
- /** @inheritdoc */
1818
- onSelectedTransformChange(t) {
1819
- return this._transformListeners.add(t), () => this._transformListeners.delete(t);
2098
+ onSelectedTransformChange(e) {
2099
+ return this._transformListeners.add(e), () => this._transformListeners.delete(e);
1820
2100
  }
1821
- /** @inheritdoc */
1822
2101
  notifySelectedTransformChange() {
1823
- for (const t of this._transformListeners) t();
2102
+ for (const e of this._transformListeners) e();
1824
2103
  }
1825
2104
  };
1826
- pe = ps([
1827
- u()
1828
- ], pe);
1829
- let je = !1;
1830
- const d = qe.createChildContainer();
1831
- function us(t) {
1832
- return je || (d.registerInstance("Canvas", t), d.registerSingleton("EventBus", G), d.registerSingleton("EditorRenderer", K), d.registerSingleton("RendererApi", de), d.registerSingleton("IDisplayHandler", te), d.registerSingleton("ISelectHandler", se), d.registerSingleton("ISelectHandler", ie), d.registerSingleton("ISelectHandler", he), d.registerSingleton("ISelectHandler", re), d.registerSingleton("IToolHandler", oe), d.registerSingleton("IToolHandler", ne), d.registerSingleton("IToolHandler", ae), d.registerSingleton("ISceneHandler", le), d.registerSingleton("ISceneHandler", ce), d.registerSingleton("IDisplayManager", q), d.registerSingleton("ISelectManager", Q), d.registerSingleton("IToolManager", J), d.registerSingleton("ISceneManager", ee), d.registerSingleton("EditorHub", _e), d.registerSingleton("IEditorStore", pe), je = !0), d;
2105
+ Pe = Rs([
2106
+ d()
2107
+ ], Pe);
2108
+ var G = /* @__PURE__ */ ((e) => (e.ToolNotAllowed = "TOOL_NOT_ALLOWED", e.Success = "SUCCESS", e.NoChange = "NO_CHANGE", e.Error = "ERROR", e))(G || {});
2109
+ class qe extends Error {
2110
+ constructor(t, r, s, i) {
2111
+ super(r), this.type = t, this.code = s, this.meta = i, this.name = this._name;
2112
+ }
2113
+ _name = "PolicyException";
2114
+ }
2115
+ var Fs = Object.getOwnPropertyDescriptor, Ws = (e, t, r, s) => {
2116
+ for (var i = s > 1 ? void 0 : s ? Fs(t, r) : t, o = e.length - 1, n; o >= 0; o--)
2117
+ (n = e[o]) && (i = n(i) || i);
2118
+ return i;
2119
+ }, ks = (e, t) => (r, s) => t(r, s, e);
2120
+ let Le = class {
2121
+ constructor(e) {
2122
+ this._store = e;
2123
+ }
2124
+ check(e) {
2125
+ const t = this._store.getSelectMode();
2126
+ if (!st[t].includes(e))
2127
+ throw new qe(
2128
+ G.ToolNotAllowed,
2129
+ `Tool ${e} is not allowed`,
2130
+ "TOOL_NOT_ALLOWED"
2131
+ );
2132
+ }
2133
+ };
2134
+ Le = Ws([
2135
+ d(),
2136
+ ks(0, l("EditorStore"))
2137
+ ], Le);
2138
+ var Gs = Object.getOwnPropertyDescriptor, Bs = (e, t, r, s) => {
2139
+ for (var i = s > 1 ? void 0 : s ? Gs(t, r) : t, o = e.length - 1, n; o >= 0; o--)
2140
+ (n = e[o]) && (i = n(i) || i);
2141
+ return i;
2142
+ };
2143
+ let Ee = class {
2144
+ handle(e) {
2145
+ try {
2146
+ return e();
2147
+ } catch (t) {
2148
+ return t instanceof qe ? {
2149
+ type: t.type,
2150
+ message: t.message,
2151
+ code: t.code,
2152
+ blocked: !0
2153
+ } : t instanceof Error ? {
2154
+ type: G.Error,
2155
+ message: t.message,
2156
+ code: "UNHANDLED_EXCEPTION",
2157
+ blocked: !0
2158
+ } : {
2159
+ type: G.Error,
2160
+ message: "Unknown exception",
2161
+ code: "UNKNOWN_EXCEPTION",
2162
+ blocked: !0
2163
+ };
2164
+ }
2165
+ }
2166
+ };
2167
+ Ee = Bs([
2168
+ d()
2169
+ ], Ee);
2170
+ var zs = Object.getOwnPropertyDescriptor, Ns = (e, t, r, s) => {
2171
+ for (var i = s > 1 ? void 0 : s ? zs(t, r) : t, o = e.length - 1, n; o >= 0; o--)
2172
+ (n = e[o]) && (i = n(i) || i);
2173
+ return i;
2174
+ }, ze = (e, t) => (r, s) => t(r, s, e);
2175
+ let Te = class {
2176
+ constructor(e, t) {
2177
+ this._middlewares = t, this._managers = new Map(e.map((r) => [r.type, r]));
2178
+ }
2179
+ _managers;
2180
+ send(e) {
2181
+ const t = this._managers.get(e.type);
2182
+ if (!t)
2183
+ return {
2184
+ type: G.Error,
2185
+ message: `Manager for feature "${String(e.type)}" not found`,
2186
+ code: "MANAGER_NOT_FOUND",
2187
+ blocked: !0
2188
+ };
2189
+ const r = () => (t.manage(...e.payload), null);
2190
+ return this._middlewares.reduceRight((i, o) => () => o.handle(i), r)();
2191
+ }
2192
+ dispose() {
2193
+ this._managers && this._managers.clear();
2194
+ }
2195
+ };
2196
+ Te = Ns([
2197
+ d(),
2198
+ ze(0, D("IManager")),
2199
+ ze(1, D("IMiddleware"))
2200
+ ], Te);
2201
+ let Ne = !1;
2202
+ const h = et.createChildContainer();
2203
+ function Us(e) {
2204
+ return Ne || (h.registerInstance("Canvas", e), h.registerSingleton("EventBus", Ie), h.registerSingleton("IController", se), h.registerSingleton("Renderer", te), h.register("IRenderable", { useToken: "Renderer" }), h.register("IRendererAccess", { useToken: "Renderer" }), h.register("IRendererCameraAccess", { useToken: "Renderer" }), h.register("IRendererDomAccess", { useToken: "Renderer" }), h.register("IRendererSceneAccess", { useToken: "Renderer" }), h.registerSingleton("ToolPolicy", Le), h.registerSingleton("IMeshApi", re), h.registerSingleton("IControlsStateApi", le), h.registerSingleton("IRaycastApi", ie), h.registerSingleton("ITransformApi", oe), h.registerSingleton("ICameraApi", ne), h.registerSingleton("IDomApi", ae), h.registerSingleton("ISceneApi", ce), h.registerSingleton("ControlsModule", he), h.registerSingleton("GizmoModule", _e), h.registerSingleton("RaycastModule", de), h.registerSingleton("SceneModule", ue), h.register("IUpdatableModule", { useToken: "ControlsModule" }), h.register("IRenderableModule", { useToken: "GizmoModule" }), h.register("IRuntimeModule", { useToken: "RaycastModule" }), h.register("IRuntimeModule", { useToken: "SceneModule" }), h.registerSingleton("IDisplayHandler", ve), h.registerSingleton("ISelectHandler", fe), h.registerSingleton("ISelectHandler", Me), h.registerSingleton("ISelectHandler", we), h.registerSingleton("ISelectHandler", ye), h.registerSingleton("IToolHandler", be), h.registerSingleton("IToolHandler", Se), h.registerSingleton("IToolHandler", Ae), h.registerSingleton("ISceneHandler", xe), h.registerSingleton("ISceneHandler", Oe), h.registerSingleton("DisplayManager", pe), h.register("IDisplayManager", { useToken: "DisplayManager" }), h.register("IManager", { useToken: "DisplayManager" }), h.registerSingleton("SelectManager", me), h.register("ISelectManager", { useToken: "SelectManager" }), h.register("IManager", { useToken: "SelectManager" }), h.registerSingleton("ToolManager", Y), h.register("IToolManager", { useToken: "ToolManager" }), h.register("IManager", { useToken: "ToolManager" }), h.registerSingleton("SceneManager", ge), h.register("ISceneManager", { useToken: "SceneManager" }), h.register("IManager", { useToken: "SceneManager" }), h.registerSingleton("IMiddleware", Ee), h.registerSingleton("IMediator", Te), h.registerSingleton("EditorHub", Ce), h.registerSingleton("EditorStore", Pe), Ne = !0), h;
1833
2205
  }
1834
- let j = null;
1835
- const Ss = (t) => (j || (j = us(t)), j.resolve("EditorHub")), Ps = () => {
1836
- if (!j)
2206
+ let H = null;
2207
+ const er = (e) => (H || (H = Us(e)), H.resolve("EditorHub")), tr = () => {
2208
+ if (!H)
1837
2209
  throw new Error("EditorHub is not initialized. Call createAppHub(canvas) first.");
1838
- return j.resolve("EditorHub");
2210
+ return H.resolve("EditorHub");
1839
2211
  };
1840
2212
  export {
1841
- _e as EditorHub,
1842
- K as EditorRenderer,
1843
- G as EventBus,
1844
- H as EventTopics,
1845
- ws as ObjLoader,
1846
- Es as PreviewRenderer,
1847
- He as Renderer,
1848
- Ss as createAppHub,
1849
- Ps as getAppHub
2213
+ Ce as EditorHub,
2214
+ Ie as EventBus,
2215
+ V as EventTopics,
2216
+ P as FeatureType,
2217
+ Js as ObjLoader,
2218
+ te as Renderer,
2219
+ G as ResponseType,
2220
+ er as createAppHub,
2221
+ tr as getAppHub
1850
2222
  };