@shopware-ag/dive 1.2.0 → 1.3.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 (39) hide show
  1. package/build/dive.cjs +288 -60
  2. package/build/dive.cjs.map +1 -1
  3. package/build/dive.d.cts +64 -6
  4. package/build/dive.d.ts +64 -6
  5. package/build/dive.js +289 -61
  6. package/build/dive.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/__test__/DIVE.test.ts +2 -0
  9. package/src/com/Communication.ts +6 -3
  10. package/src/com/__test__/Communication.test.ts +3 -6
  11. package/src/com/actions/object/getobjects.ts +2 -2
  12. package/src/dive.ts +7 -0
  13. package/src/gizmo/Gizmo.ts +130 -0
  14. package/src/gizmo/handles/AxisHandle.ts +124 -0
  15. package/src/gizmo/handles/RadialHandle.ts +119 -0
  16. package/src/gizmo/handles/ScaleHandle.ts +152 -0
  17. package/src/gizmo/plane/GizmoPlane.ts +85 -0
  18. package/src/gizmo/rotate/RotateGizmo.ts +95 -0
  19. package/src/gizmo/scale/ScaleGizmo.ts +97 -0
  20. package/src/gizmo/translate/TranslateGizmo.ts +88 -0
  21. package/src/interface/Draggable.ts +34 -0
  22. package/src/interface/Hoverable.ts +33 -0
  23. package/src/interface/Moveable.ts +0 -2
  24. package/src/interface/Selectable.ts +6 -0
  25. package/src/interface/__test__/Interfaces.test.ts +56 -0
  26. package/src/math/index.ts +3 -0
  27. package/src/math/signedAngleTo/__test__/signedAngleTo.test.ts +14 -0
  28. package/src/math/signedAngleTo/signedAngleTo.ts +13 -0
  29. package/src/scene/root/lightroot/LightRoot.ts +17 -3
  30. package/src/scene/root/lightroot/__test__/LightRoot.test.ts +12 -3
  31. package/src/scene/root/modelroot/ModelRoot.ts +17 -3
  32. package/src/scene/root/modelroot/__test__/ModelRoot.test.ts +13 -14
  33. package/src/toolbox/BaseTool.ts +254 -4
  34. package/src/toolbox/Toolbox.ts +6 -0
  35. package/src/toolbox/__test__/BaseTool.test.ts +389 -0
  36. package/src/toolbox/__test__/Toolbox.test.ts +8 -0
  37. package/src/toolbox/select/SelectTool.ts +29 -65
  38. package/src/toolbox/select/__test__/SelectTool.test.ts +57 -25
  39. package/src/toolbox/transform/TransformTool.ts +48 -0
package/build/dive.js CHANGED
@@ -354,11 +354,13 @@ var _DIVECommunication = class _DIVECommunication {
354
354
  return this.registered;
355
355
  }
356
356
  getObjects(payload) {
357
+ if (payload.ids.length === 0) return [];
358
+ const objects = [];
357
359
  this.registered.forEach((object) => {
358
- if (payload.ids && payload.ids.length > 0 && !payload.ids.includes(object.id)) return;
359
- payload.map.set(object.id, object);
360
+ if (!payload.ids.includes(object.id)) return;
361
+ objects.push(object);
360
362
  });
361
- return payload.map;
363
+ return objects;
362
364
  }
363
365
  addObject(payload) {
364
366
  if (this.registered.get(payload.id)) return false;
@@ -612,7 +614,6 @@ var DIVELightRoot = class extends Object3D4 {
612
614
  if (light.visible !== void 0 && light.visible !== null) sceneObject.visible = light.visible;
613
615
  }
614
616
  DeleteLight(light) {
615
- var _a;
616
617
  if (light.id === void 0) {
617
618
  console.warn("LightRoot.DeleteLight: light.id is undefined");
618
619
  return;
@@ -622,9 +623,19 @@ var DIVELightRoot = class extends Object3D4 {
622
623
  console.warn(`LightRoot.DeleteLight: Light with id ${light.id} not found`);
623
624
  return;
624
625
  }
625
- if ("isMoveable" in sceneObject) {
626
- (_a = sceneObject.gizmo) == null ? void 0 : _a.detach();
627
- }
626
+ const findScene = (object) => {
627
+ if (object.parent !== null) {
628
+ return findScene(object.parent);
629
+ }
630
+ ;
631
+ return object;
632
+ };
633
+ const scene = findScene(sceneObject);
634
+ scene.children.find((object) => {
635
+ if ("isTransformControls" in object) {
636
+ object.detach();
637
+ }
638
+ });
628
639
  this.remove(sceneObject);
629
640
  }
630
641
  };
@@ -781,7 +792,6 @@ var DIVEModelRoot = class extends Object3D6 {
781
792
  if (object.visible !== void 0) sceneObject.visible = object.visible;
782
793
  }
783
794
  DeleteModel(object) {
784
- var _a;
785
795
  if (object.id === void 0) {
786
796
  console.warn(`ModelRoot.DeleteModel: object.id is undefined`);
787
797
  return;
@@ -791,9 +801,19 @@ var DIVEModelRoot = class extends Object3D6 {
791
801
  console.warn(`ModelRoot.DeleteModel: Model with id ${object.id} not found`);
792
802
  return;
793
803
  }
794
- if ("isMoveable" in sceneObject) {
795
- (_a = sceneObject.gizmo) == null ? void 0 : _a.detach();
796
- }
804
+ const findScene = (object2) => {
805
+ if (object2.parent !== null) {
806
+ return findScene(object2.parent);
807
+ }
808
+ ;
809
+ return object2;
810
+ };
811
+ const scene = findScene(sceneObject);
812
+ scene.children.find((object2) => {
813
+ if ("isTransformControls" in object2) {
814
+ object2.detach();
815
+ }
816
+ });
797
817
  this.remove(sceneObject);
798
818
  }
799
819
  PlaceOnFloor(object) {
@@ -1106,84 +1126,282 @@ var DIVEMediaCreator = class {
1106
1126
  }
1107
1127
  };
1108
1128
 
1109
- // src/toolbox/select/SelectTool.ts
1110
- import { Raycaster as Raycaster2, Vector2 } from "three";
1111
- import { TransformControls } from "three/examples/jsm/Addons.js";
1129
+ // src/interface/Selectable.ts
1130
+ function isSelectable(object) {
1131
+ return "isSelectable" in object;
1132
+ }
1133
+
1134
+ // src/toolbox/BaseTool.ts
1135
+ import { Raycaster as Raycaster2, Vector2, Vector3 as Vector32 } from "three";
1136
+
1137
+ // src/interface/Draggable.ts
1138
+ var isDraggable = (object) => {
1139
+ return "isDraggable" in object;
1140
+ };
1141
+ var findDraggableInterface = (child) => {
1142
+ if (child === void 0) return void 0;
1143
+ if (child.parent === null) {
1144
+ return void 0;
1145
+ }
1146
+ if (isDraggable(child)) {
1147
+ return child;
1148
+ }
1149
+ return findDraggableInterface(child.parent);
1150
+ };
1151
+
1152
+ // src/interface/Hoverable.ts
1153
+ var isHoverable = (object) => {
1154
+ return "isHoverable" in object;
1155
+ };
1156
+ var findHoverableInterface = (child) => {
1157
+ if (child === void 0) return void 0;
1158
+ if (child.parent === null) {
1159
+ return void 0;
1160
+ }
1161
+ if (isHoverable(child)) {
1162
+ return child;
1163
+ }
1164
+ return findHoverableInterface(child.parent);
1165
+ };
1112
1166
 
1113
1167
  // src/toolbox/BaseTool.ts
1114
1168
  var DIVEBaseTool = class {
1115
- constructor() {
1169
+ constructor(scene, controller) {
1170
+ this.POINTER_DRAG_THRESHOLD = 1e-3;
1116
1171
  this.name = "BaseTool";
1172
+ this._canvas = controller.domElement;
1173
+ this._scene = scene;
1174
+ this._controller = controller;
1175
+ this._pointer = new Vector2();
1176
+ this._pointerPrimaryDown = false;
1177
+ this._pointerMiddleDown = false;
1178
+ this._pointerSecondaryDown = false;
1179
+ this._lastPointerDown = new Vector2();
1180
+ this._lastPointerUp = new Vector2();
1181
+ this._raycaster = new Raycaster2();
1182
+ this._raycaster.layers.mask = PRODUCT_LAYER_MASK | UI_LAYER_MASK;
1183
+ this._intersects = [];
1184
+ this._hovered = null;
1185
+ this._dragging = false;
1186
+ this._dragStart = new Vector32();
1187
+ this._dragCurrent = new Vector32();
1188
+ this._dragEnd = new Vector32();
1189
+ this._dragDelta = new Vector32();
1190
+ this._draggable = null;
1191
+ this._dragRaycastOnObjects = null;
1192
+ }
1193
+ get _pointerAnyDown() {
1194
+ return this._pointerPrimaryDown || this._pointerMiddleDown || this._pointerSecondaryDown;
1117
1195
  }
1118
1196
  Activate() {
1119
1197
  }
1120
1198
  Deactivate() {
1121
1199
  }
1122
1200
  onPointerDown(e) {
1201
+ var _a;
1202
+ switch (e.button) {
1203
+ case 0:
1204
+ this._pointerPrimaryDown = true;
1205
+ break;
1206
+ case 1:
1207
+ this._pointerMiddleDown = true;
1208
+ break;
1209
+ case 2:
1210
+ this._pointerSecondaryDown = true;
1211
+ break;
1212
+ }
1213
+ this._lastPointerDown.copy(this._pointer);
1214
+ this._draggable = findDraggableInterface((_a = this._intersects[0]) == null ? void 0 : _a.object) || null;
1215
+ }
1216
+ onDragStart(e) {
1217
+ if (!this._draggable) return;
1218
+ if (this._dragRaycastOnObjects !== null) {
1219
+ this._intersects = this._raycaster.intersectObjects(this._dragRaycastOnObjects, true);
1220
+ }
1221
+ if (this._intersects.length === 0) return;
1222
+ this._dragStart.copy(this._intersects[0].point.clone());
1223
+ this._dragCurrent.copy(this._intersects[0].point.clone());
1224
+ this._dragEnd.copy(this._dragStart.clone());
1225
+ this._dragDelta.set(0, 0, 0);
1226
+ if (this._draggable && this._draggable.onDragStart) {
1227
+ this._draggable.onDragStart({
1228
+ dragStart: this._dragStart,
1229
+ dragCurrent: this._dragCurrent,
1230
+ dragEnd: this._dragEnd,
1231
+ dragDelta: this._dragDelta
1232
+ });
1233
+ this._dragging = true;
1234
+ this._controller.enabled = false;
1235
+ }
1236
+ }
1237
+ onPointerMove(e) {
1238
+ var _a;
1239
+ this._pointer.x = e.offsetX / this._canvas.clientWidth * 2 - 1;
1240
+ this._pointer.y = -(e.offsetY / this._canvas.clientHeight) * 2 + 1;
1241
+ this._raycaster.setFromCamera(this._pointer, this._controller.object);
1242
+ this._intersects = this.raycast(this._scene.children);
1243
+ const hoverable = findHoverableInterface((_a = this._intersects[0]) == null ? void 0 : _a.object);
1244
+ if (this._intersects[0] && hoverable) {
1245
+ if (!this._hovered) {
1246
+ if (hoverable.onPointerEnter) hoverable.onPointerEnter(this._intersects[0]);
1247
+ this._hovered = hoverable;
1248
+ return;
1249
+ }
1250
+ if (this._hovered.uuid !== hoverable.uuid) {
1251
+ if (this._hovered.onPointerLeave) this._hovered.onPointerLeave();
1252
+ if (hoverable.onPointerEnter) hoverable.onPointerEnter(this._intersects[0]);
1253
+ this._hovered = hoverable;
1254
+ return;
1255
+ }
1256
+ if (hoverable.onPointerOver) hoverable.onPointerOver(this._intersects[0]);
1257
+ this._hovered = hoverable;
1258
+ } else {
1259
+ if (this._hovered) {
1260
+ if (this._hovered.onPointerLeave) this._hovered.onPointerLeave();
1261
+ }
1262
+ this._hovered = null;
1263
+ }
1264
+ if (this._pointerAnyDown) {
1265
+ if (!this._dragging) {
1266
+ this.onDragStart(e);
1267
+ }
1268
+ this.onDrag(e);
1269
+ }
1270
+ }
1271
+ onDrag(e) {
1272
+ if (this._dragRaycastOnObjects !== null) {
1273
+ this._intersects = this._raycaster.intersectObjects(this._dragRaycastOnObjects, true);
1274
+ }
1275
+ const intersect = this._intersects[0];
1276
+ if (!intersect) return;
1277
+ this._dragCurrent.copy(intersect.point.clone());
1278
+ this._dragEnd.copy(intersect.point.clone());
1279
+ this._dragDelta.subVectors(this._dragCurrent.clone(), this._dragStart.clone());
1280
+ if (this._draggable && this._draggable.onDrag) {
1281
+ this._draggable.onDrag({
1282
+ dragStart: this._dragStart,
1283
+ dragCurrent: this._dragCurrent,
1284
+ dragEnd: this._dragEnd,
1285
+ dragDelta: this._dragDelta
1286
+ });
1287
+ }
1123
1288
  }
1124
1289
  onPointerUp(e) {
1290
+ if (this.pointerWasDragged() || this._dragging) {
1291
+ if (this._draggable) {
1292
+ this.onDragEnd(e);
1293
+ }
1294
+ } else {
1295
+ this.onClick(e);
1296
+ }
1297
+ switch (e.button) {
1298
+ case 0:
1299
+ this._pointerPrimaryDown = false;
1300
+ break;
1301
+ case 1:
1302
+ this._pointerMiddleDown = false;
1303
+ break;
1304
+ case 2:
1305
+ this._pointerSecondaryDown = false;
1306
+ break;
1307
+ }
1308
+ this._lastPointerUp.copy(this._pointer);
1309
+ }
1310
+ onClick(e) {
1311
+ }
1312
+ onDragEnd(e) {
1313
+ const intersect = this._intersects[0];
1314
+ if (intersect) {
1315
+ this._dragEnd.copy(intersect.point.clone());
1316
+ this._dragCurrent.copy(intersect.point.clone());
1317
+ this._dragDelta.subVectors(this._dragCurrent.clone(), this._dragStart.clone());
1318
+ }
1319
+ if (this._draggable && this._draggable.onDragEnd) {
1320
+ this._draggable.onDragEnd({
1321
+ dragStart: this._dragStart,
1322
+ dragCurrent: this._dragCurrent,
1323
+ dragEnd: this._dragEnd,
1324
+ dragDelta: this._dragDelta
1325
+ });
1326
+ }
1327
+ this._draggable = null;
1328
+ this._dragging = false;
1329
+ this._dragStart.set(0, 0, 0);
1330
+ this._dragCurrent.set(0, 0, 0);
1331
+ this._dragEnd.set(0, 0, 0);
1332
+ this._dragDelta.set(0, 0, 0);
1333
+ this._controller.enabled = true;
1125
1334
  }
1126
1335
  onWheel(e) {
1127
1336
  }
1337
+ raycast(objects) {
1338
+ if (objects !== void 0) return this._raycaster.intersectObjects(objects, true);
1339
+ return this._raycaster.intersectObjects(this._scene.children, true);
1340
+ }
1341
+ pointerWasDragged() {
1342
+ return this._lastPointerDown.distanceTo(this._pointer) > this.POINTER_DRAG_THRESHOLD;
1343
+ }
1128
1344
  };
1129
1345
 
1130
- // src/toolbox/select/SelectTool.ts
1131
- var DIVESelectTool = class extends DIVEBaseTool {
1346
+ // src/toolbox/transform/TransformTool.ts
1347
+ import { TransformControls } from "three/examples/jsm/Addons";
1348
+ var DIVETransformTool = class extends DIVEBaseTool {
1132
1349
  constructor(scene, controller) {
1133
- super();
1134
- this.name = "SelectTool";
1135
- this.canvas = controller.domElement;
1136
- this.scene = scene;
1137
- this.controller = controller;
1138
- this.raycaster = new Raycaster2();
1139
- this.raycaster.layers.mask = PRODUCT_LAYER_MASK | HELPER_LAYER_MASK;
1140
- this.gizmo = new TransformControls(this.controller.object, this.canvas);
1141
- this.gizmo.layers.mask = UI_LAYER_MASK;
1142
- this.gizmo.getRaycaster().layers.mask = UI_LAYER_MASK & this.controller.object.layers.mask;
1143
- this.gizmo.traverse((child) => {
1144
- child.layers.mask = UI_LAYER_MASK;
1145
- });
1146
- this.gizmo.addEventListener("objectChange", () => {
1147
- if (!this.gizmo.object) return;
1148
- if (!("onMove" in this.gizmo.object)) return;
1149
- if (typeof this.gizmo.object.onMove !== "function") return;
1150
- this.gizmo.object.onMove();
1151
- });
1152
- this.controller.object.onSetCameraLayer = (mask) => {
1153
- this.gizmo.getRaycaster().layers.mask = UI_LAYER_MASK & mask;
1154
- };
1155
- this.gizmo.addEventListener("dragging-changed", function(event) {
1156
- controller.enabled = !event.value;
1157
- });
1158
- this.scene.add(this.gizmo);
1350
+ super(scene, controller);
1351
+ this.name = "DIVETransformTool";
1352
+ this._gizmo = new TransformControls(this._controller.object, this._controller.domElement);
1353
+ this._gizmo.mode = "translate";
1354
+ scene.add(this._gizmo);
1159
1355
  }
1160
1356
  Activate() {
1161
1357
  }
1162
1358
  SetGizmoMode(mode) {
1163
- this.gizmo.setMode(mode);
1359
+ this._gizmo.mode = mode;
1360
+ }
1361
+ // public onPointerDown(e: PointerEvent): void {
1362
+ // super.onPointerDown(e);
1363
+ // // if (this._hovered) {
1364
+ // // this._dragRaycastOnObjects = this._gizmo.gizmoPlane.children;
1365
+ // // }
1366
+ // }
1367
+ // protected raycast(): Intersection[] {
1368
+ // return super.raycast(this._gizmo.gizmoNode.children);
1369
+ // }
1370
+ };
1371
+
1372
+ // src/toolbox/select/SelectTool.ts
1373
+ var DIVESelectTool = class extends DIVETransformTool {
1374
+ constructor(scene, controller) {
1375
+ super(scene, controller);
1376
+ this.name = "SelectTool";
1377
+ }
1378
+ Activate() {
1164
1379
  }
1165
1380
  Select(selectable) {
1166
1381
  if (selectable.onSelect) selectable.onSelect();
1167
1382
  if ("isMoveable" in selectable) {
1168
1383
  const movable = selectable;
1169
- movable.gizmo = this.gizmo;
1170
- this.gizmo.attach(movable);
1384
+ this._gizmo.attach(movable);
1171
1385
  }
1172
1386
  }
1173
1387
  Deselect(selectable) {
1174
1388
  if (selectable.onDeselect) selectable.onDeselect();
1175
- if ("isMoveable" in selectable) selectable.gizmo = null;
1176
- this.gizmo.detach();
1389
+ this._gizmo.detach();
1177
1390
  }
1178
- onPointerUp(e) {
1179
- const pointerPos = new Vector2(e.offsetX / this.canvas.clientWidth * 2 - 1, e.offsetY / this.canvas.clientHeight * -2 + 1);
1180
- this.raycaster.setFromCamera(pointerPos, this.controller.object);
1181
- const first = this.raycastFirst();
1391
+ onClick(e) {
1392
+ super.onClick(e);
1393
+ const first = this._raycaster.intersectObjects(this._scene.Root.children, true)[0];
1182
1394
  const selectable = this.findSelectableInterface(first == null ? void 0 : first.object);
1183
1395
  if (!first || !selectable) {
1184
- if (this.gizmo.object) this.Deselect(this.gizmo.object);
1396
+ if (this._gizmo.object) {
1397
+ this.Deselect(this._gizmo.object);
1398
+ }
1185
1399
  return;
1186
1400
  }
1401
+ if (this._gizmo.object) {
1402
+ if (this._gizmo.object.uuid === selectable.uuid) return;
1403
+ this.Deselect(this._gizmo.object);
1404
+ }
1187
1405
  this.Select(selectable);
1188
1406
  }
1189
1407
  findSelectableInterface(child) {
@@ -1191,17 +1409,11 @@ var DIVESelectTool = class extends DIVEBaseTool {
1191
1409
  if (child.parent === null) {
1192
1410
  return void 0;
1193
1411
  }
1194
- if ("isSelectable" in child) {
1412
+ if (isSelectable(child)) {
1195
1413
  return child;
1196
1414
  }
1197
1415
  return this.findSelectableInterface(child.parent);
1198
1416
  }
1199
- raycastFirst() {
1200
- return this.raycastAll()[0];
1201
- }
1202
- raycastAll() {
1203
- return this.raycaster.intersectObjects(this.scene.Root.children, true);
1204
- }
1205
1417
  };
1206
1418
 
1207
1419
  // src/toolbox/Toolbox.ts
@@ -1210,10 +1422,12 @@ var DIVEToolbox = class {
1210
1422
  this.removeListenersCallback = () => {
1211
1423
  };
1212
1424
  this.selectTool = new DIVESelectTool(scene, controller);
1425
+ controller.domElement.addEventListener("pointermove", this.onPointerMove.bind(this));
1213
1426
  controller.domElement.addEventListener("pointerdown", this.onPointerDown.bind(this));
1214
1427
  controller.domElement.addEventListener("pointerup", this.onPointerUp.bind(this));
1215
1428
  controller.domElement.addEventListener("wheel", this.onWheel.bind(this));
1216
1429
  this.removeListenersCallback = () => {
1430
+ controller.domElement.removeEventListener("pointermove", this.onPointerMove.bind(this));
1217
1431
  controller.domElement.removeEventListener("pointerdown", this.onPointerDown.bind(this));
1218
1432
  controller.domElement.removeEventListener("pointerup", this.onPointerUp.bind(this));
1219
1433
  controller.domElement.removeEventListener("wheel", this.onWheel.bind(this));
@@ -1243,6 +1457,9 @@ var DIVEToolbox = class {
1243
1457
  SetGizmoMode(mode) {
1244
1458
  this.selectTool.SetGizmoMode(mode);
1245
1459
  }
1460
+ onPointerMove(e) {
1461
+ this.activeTool.onPointerMove(e);
1462
+ }
1246
1463
  onPointerDown(e) {
1247
1464
  this.activeTool.onPointerDown(e);
1248
1465
  }
@@ -1393,6 +1610,11 @@ function roundExponential(number, decimals = 0) {
1393
1610
  return shift(Math.round(n), -decimals);
1394
1611
  }
1395
1612
 
1613
+ // src/math/signedAngleTo/signedAngleTo.ts
1614
+ function signedAngleTo(vecA, vecB, planeNormal) {
1615
+ return Math.atan2(vecA.clone().cross(vecB).dot(planeNormal), vecB.clone().dot(vecA));
1616
+ }
1617
+
1396
1618
  // src/math/toFixed/toFixedExp.ts
1397
1619
  function toFixedExp(number, decimals = 0) {
1398
1620
  const n = shift(number, +decimals);
@@ -1411,7 +1633,8 @@ var DIVEMath = {
1411
1633
  floorExp,
1412
1634
  roundExp: roundExponential,
1413
1635
  toFixedExp,
1414
- truncateExp
1636
+ truncateExp,
1637
+ signedAngleTo
1415
1638
  };
1416
1639
 
1417
1640
  // src/dive.ts
@@ -1487,6 +1710,11 @@ var DIVE = class {
1487
1710
  this.addResizeObserver();
1488
1711
  }
1489
1712
  this.renderer.StartRenderer(this.scene, this.perspectiveCamera);
1713
+ window.DIVE = {
1714
+ PrintScene: () => {
1715
+ console.log(this.scene);
1716
+ }
1717
+ };
1490
1718
  }
1491
1719
  // methods
1492
1720
  OnResize(width, height) {