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