@shopware-ag/dive 1.2.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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.cjs CHANGED
@@ -389,11 +389,13 @@ var _DIVECommunication = class _DIVECommunication {
389
389
  return this.registered;
390
390
  }
391
391
  getObjects(payload) {
392
+ if (payload.ids.length === 0) return [];
393
+ const objects = [];
392
394
  this.registered.forEach((object) => {
393
- if (payload.ids && payload.ids.length > 0 && !payload.ids.includes(object.id)) return;
394
- payload.map.set(object.id, object);
395
+ if (!payload.ids.includes(object.id)) return;
396
+ objects.push(object);
395
397
  });
396
- return payload.map;
398
+ return objects;
397
399
  }
398
400
  addObject(payload) {
399
401
  if (this.registered.get(payload.id)) return false;
@@ -647,7 +649,6 @@ var DIVELightRoot = class extends import_three6.Object3D {
647
649
  if (light.visible !== void 0 && light.visible !== null) sceneObject.visible = light.visible;
648
650
  }
649
651
  DeleteLight(light) {
650
- var _a;
651
652
  if (light.id === void 0) {
652
653
  console.warn("LightRoot.DeleteLight: light.id is undefined");
653
654
  return;
@@ -657,9 +658,19 @@ var DIVELightRoot = class extends import_three6.Object3D {
657
658
  console.warn(`LightRoot.DeleteLight: Light with id ${light.id} not found`);
658
659
  return;
659
660
  }
660
- if ("isMoveable" in sceneObject) {
661
- (_a = sceneObject.gizmo) == null ? void 0 : _a.detach();
662
- }
661
+ const findScene = (object) => {
662
+ if (object.parent !== null) {
663
+ return findScene(object.parent);
664
+ }
665
+ ;
666
+ return object;
667
+ };
668
+ const scene = findScene(sceneObject);
669
+ scene.children.find((object) => {
670
+ if ("isTransformControls" in object) {
671
+ object.detach();
672
+ }
673
+ });
663
674
  this.remove(sceneObject);
664
675
  }
665
676
  };
@@ -816,7 +827,6 @@ var DIVEModelRoot = class extends import_three8.Object3D {
816
827
  if (object.visible !== void 0) sceneObject.visible = object.visible;
817
828
  }
818
829
  DeleteModel(object) {
819
- var _a;
820
830
  if (object.id === void 0) {
821
831
  console.warn(`ModelRoot.DeleteModel: object.id is undefined`);
822
832
  return;
@@ -826,9 +836,19 @@ var DIVEModelRoot = class extends import_three8.Object3D {
826
836
  console.warn(`ModelRoot.DeleteModel: Model with id ${object.id} not found`);
827
837
  return;
828
838
  }
829
- if ("isMoveable" in sceneObject) {
830
- (_a = sceneObject.gizmo) == null ? void 0 : _a.detach();
831
- }
839
+ const findScene = (object2) => {
840
+ if (object2.parent !== null) {
841
+ return findScene(object2.parent);
842
+ }
843
+ ;
844
+ return object2;
845
+ };
846
+ const scene = findScene(sceneObject);
847
+ scene.children.find((object2) => {
848
+ if ("isTransformControls" in object2) {
849
+ object2.detach();
850
+ }
851
+ });
832
852
  this.remove(sceneObject);
833
853
  }
834
854
  PlaceOnFloor(object) {
@@ -1141,84 +1161,282 @@ var DIVEMediaCreator = class {
1141
1161
  }
1142
1162
  };
1143
1163
 
1144
- // src/toolbox/select/SelectTool.ts
1164
+ // src/interface/Selectable.ts
1165
+ function isSelectable(object) {
1166
+ return "isSelectable" in object;
1167
+ }
1168
+
1169
+ // src/toolbox/BaseTool.ts
1145
1170
  var import_three15 = require("three");
1146
- var import_Addons3 = require("three/examples/jsm/Addons.js");
1171
+
1172
+ // src/interface/Draggable.ts
1173
+ var isDraggable = (object) => {
1174
+ return "isDraggable" in object;
1175
+ };
1176
+ var findDraggableInterface = (child) => {
1177
+ if (child === void 0) return void 0;
1178
+ if (child.parent === null) {
1179
+ return void 0;
1180
+ }
1181
+ if (isDraggable(child)) {
1182
+ return child;
1183
+ }
1184
+ return findDraggableInterface(child.parent);
1185
+ };
1186
+
1187
+ // src/interface/Hoverable.ts
1188
+ var isHoverable = (object) => {
1189
+ return "isHoverable" in object;
1190
+ };
1191
+ var findHoverableInterface = (child) => {
1192
+ if (child === void 0) return void 0;
1193
+ if (child.parent === null) {
1194
+ return void 0;
1195
+ }
1196
+ if (isHoverable(child)) {
1197
+ return child;
1198
+ }
1199
+ return findHoverableInterface(child.parent);
1200
+ };
1147
1201
 
1148
1202
  // src/toolbox/BaseTool.ts
1149
1203
  var DIVEBaseTool = class {
1150
- constructor() {
1204
+ constructor(scene, controller) {
1205
+ this.POINTER_DRAG_THRESHOLD = 1e-3;
1151
1206
  this.name = "BaseTool";
1207
+ this._canvas = controller.domElement;
1208
+ this._scene = scene;
1209
+ this._controller = controller;
1210
+ this._pointer = new import_three15.Vector2();
1211
+ this._pointerPrimaryDown = false;
1212
+ this._pointerMiddleDown = false;
1213
+ this._pointerSecondaryDown = false;
1214
+ this._lastPointerDown = new import_three15.Vector2();
1215
+ this._lastPointerUp = new import_three15.Vector2();
1216
+ this._raycaster = new import_three15.Raycaster();
1217
+ this._raycaster.layers.mask = PRODUCT_LAYER_MASK | UI_LAYER_MASK;
1218
+ this._intersects = [];
1219
+ this._hovered = null;
1220
+ this._dragging = false;
1221
+ this._dragStart = new import_three15.Vector3();
1222
+ this._dragCurrent = new import_three15.Vector3();
1223
+ this._dragEnd = new import_three15.Vector3();
1224
+ this._dragDelta = new import_three15.Vector3();
1225
+ this._draggable = null;
1226
+ this._dragRaycastOnObjects = null;
1227
+ }
1228
+ get _pointerAnyDown() {
1229
+ return this._pointerPrimaryDown || this._pointerMiddleDown || this._pointerSecondaryDown;
1152
1230
  }
1153
1231
  Activate() {
1154
1232
  }
1155
1233
  Deactivate() {
1156
1234
  }
1157
1235
  onPointerDown(e) {
1236
+ var _a;
1237
+ switch (e.button) {
1238
+ case 0:
1239
+ this._pointerPrimaryDown = true;
1240
+ break;
1241
+ case 1:
1242
+ this._pointerMiddleDown = true;
1243
+ break;
1244
+ case 2:
1245
+ this._pointerSecondaryDown = true;
1246
+ break;
1247
+ }
1248
+ this._lastPointerDown.copy(this._pointer);
1249
+ this._draggable = findDraggableInterface((_a = this._intersects[0]) == null ? void 0 : _a.object) || null;
1250
+ }
1251
+ onDragStart(e) {
1252
+ if (!this._draggable) return;
1253
+ if (this._dragRaycastOnObjects !== null) {
1254
+ this._intersects = this._raycaster.intersectObjects(this._dragRaycastOnObjects, true);
1255
+ }
1256
+ if (this._intersects.length === 0) return;
1257
+ this._dragStart.copy(this._intersects[0].point.clone());
1258
+ this._dragCurrent.copy(this._intersects[0].point.clone());
1259
+ this._dragEnd.copy(this._dragStart.clone());
1260
+ this._dragDelta.set(0, 0, 0);
1261
+ if (this._draggable && this._draggable.onDragStart) {
1262
+ this._draggable.onDragStart({
1263
+ dragStart: this._dragStart,
1264
+ dragCurrent: this._dragCurrent,
1265
+ dragEnd: this._dragEnd,
1266
+ dragDelta: this._dragDelta
1267
+ });
1268
+ this._dragging = true;
1269
+ this._controller.enabled = false;
1270
+ }
1271
+ }
1272
+ onPointerMove(e) {
1273
+ var _a;
1274
+ this._pointer.x = e.offsetX / this._canvas.clientWidth * 2 - 1;
1275
+ this._pointer.y = -(e.offsetY / this._canvas.clientHeight) * 2 + 1;
1276
+ this._raycaster.setFromCamera(this._pointer, this._controller.object);
1277
+ this._intersects = this.raycast(this._scene.children);
1278
+ const hoverable = findHoverableInterface((_a = this._intersects[0]) == null ? void 0 : _a.object);
1279
+ if (this._intersects[0] && hoverable) {
1280
+ if (!this._hovered) {
1281
+ if (hoverable.onPointerEnter) hoverable.onPointerEnter(this._intersects[0]);
1282
+ this._hovered = hoverable;
1283
+ return;
1284
+ }
1285
+ if (this._hovered.uuid !== hoverable.uuid) {
1286
+ if (this._hovered.onPointerLeave) this._hovered.onPointerLeave();
1287
+ if (hoverable.onPointerEnter) hoverable.onPointerEnter(this._intersects[0]);
1288
+ this._hovered = hoverable;
1289
+ return;
1290
+ }
1291
+ if (hoverable.onPointerOver) hoverable.onPointerOver(this._intersects[0]);
1292
+ this._hovered = hoverable;
1293
+ } else {
1294
+ if (this._hovered) {
1295
+ if (this._hovered.onPointerLeave) this._hovered.onPointerLeave();
1296
+ }
1297
+ this._hovered = null;
1298
+ }
1299
+ if (this._pointerAnyDown) {
1300
+ if (!this._dragging) {
1301
+ this.onDragStart(e);
1302
+ }
1303
+ this.onDrag(e);
1304
+ }
1305
+ }
1306
+ onDrag(e) {
1307
+ if (this._dragRaycastOnObjects !== null) {
1308
+ this._intersects = this._raycaster.intersectObjects(this._dragRaycastOnObjects, true);
1309
+ }
1310
+ const intersect = this._intersects[0];
1311
+ if (!intersect) return;
1312
+ this._dragCurrent.copy(intersect.point.clone());
1313
+ this._dragEnd.copy(intersect.point.clone());
1314
+ this._dragDelta.subVectors(this._dragCurrent.clone(), this._dragStart.clone());
1315
+ if (this._draggable && this._draggable.onDrag) {
1316
+ this._draggable.onDrag({
1317
+ dragStart: this._dragStart,
1318
+ dragCurrent: this._dragCurrent,
1319
+ dragEnd: this._dragEnd,
1320
+ dragDelta: this._dragDelta
1321
+ });
1322
+ }
1158
1323
  }
1159
1324
  onPointerUp(e) {
1325
+ if (this.pointerWasDragged() || this._dragging) {
1326
+ if (this._draggable) {
1327
+ this.onDragEnd(e);
1328
+ }
1329
+ } else {
1330
+ this.onClick(e);
1331
+ }
1332
+ switch (e.button) {
1333
+ case 0:
1334
+ this._pointerPrimaryDown = false;
1335
+ break;
1336
+ case 1:
1337
+ this._pointerMiddleDown = false;
1338
+ break;
1339
+ case 2:
1340
+ this._pointerSecondaryDown = false;
1341
+ break;
1342
+ }
1343
+ this._lastPointerUp.copy(this._pointer);
1344
+ }
1345
+ onClick(e) {
1346
+ }
1347
+ onDragEnd(e) {
1348
+ const intersect = this._intersects[0];
1349
+ if (intersect) {
1350
+ this._dragEnd.copy(intersect.point.clone());
1351
+ this._dragCurrent.copy(intersect.point.clone());
1352
+ this._dragDelta.subVectors(this._dragCurrent.clone(), this._dragStart.clone());
1353
+ }
1354
+ if (this._draggable && this._draggable.onDragEnd) {
1355
+ this._draggable.onDragEnd({
1356
+ dragStart: this._dragStart,
1357
+ dragCurrent: this._dragCurrent,
1358
+ dragEnd: this._dragEnd,
1359
+ dragDelta: this._dragDelta
1360
+ });
1361
+ }
1362
+ this._draggable = null;
1363
+ this._dragging = false;
1364
+ this._dragStart.set(0, 0, 0);
1365
+ this._dragCurrent.set(0, 0, 0);
1366
+ this._dragEnd.set(0, 0, 0);
1367
+ this._dragDelta.set(0, 0, 0);
1368
+ this._controller.enabled = true;
1160
1369
  }
1161
1370
  onWheel(e) {
1162
1371
  }
1372
+ raycast(objects) {
1373
+ if (objects !== void 0) return this._raycaster.intersectObjects(objects, true);
1374
+ return this._raycaster.intersectObjects(this._scene.children, true);
1375
+ }
1376
+ pointerWasDragged() {
1377
+ return this._lastPointerDown.distanceTo(this._pointer) > this.POINTER_DRAG_THRESHOLD;
1378
+ }
1163
1379
  };
1164
1380
 
1165
- // src/toolbox/select/SelectTool.ts
1166
- var DIVESelectTool = class extends DIVEBaseTool {
1381
+ // src/toolbox/transform/TransformTool.ts
1382
+ var import_Addons3 = require("three/examples/jsm/Addons");
1383
+ var DIVETransformTool = class extends DIVEBaseTool {
1167
1384
  constructor(scene, controller) {
1168
- super();
1169
- this.name = "SelectTool";
1170
- this.canvas = controller.domElement;
1171
- this.scene = scene;
1172
- this.controller = controller;
1173
- this.raycaster = new import_three15.Raycaster();
1174
- this.raycaster.layers.mask = PRODUCT_LAYER_MASK | HELPER_LAYER_MASK;
1175
- this.gizmo = new import_Addons3.TransformControls(this.controller.object, this.canvas);
1176
- this.gizmo.layers.mask = UI_LAYER_MASK;
1177
- this.gizmo.getRaycaster().layers.mask = UI_LAYER_MASK & this.controller.object.layers.mask;
1178
- this.gizmo.traverse((child) => {
1179
- child.layers.mask = UI_LAYER_MASK;
1180
- });
1181
- this.gizmo.addEventListener("objectChange", () => {
1182
- if (!this.gizmo.object) return;
1183
- if (!("onMove" in this.gizmo.object)) return;
1184
- if (typeof this.gizmo.object.onMove !== "function") return;
1185
- this.gizmo.object.onMove();
1186
- });
1187
- this.controller.object.onSetCameraLayer = (mask) => {
1188
- this.gizmo.getRaycaster().layers.mask = UI_LAYER_MASK & mask;
1189
- };
1190
- this.gizmo.addEventListener("dragging-changed", function(event) {
1191
- controller.enabled = !event.value;
1192
- });
1193
- this.scene.add(this.gizmo);
1385
+ super(scene, controller);
1386
+ this.name = "DIVETransformTool";
1387
+ this._gizmo = new import_Addons3.TransformControls(this._controller.object, this._controller.domElement);
1388
+ this._gizmo.mode = "translate";
1389
+ scene.add(this._gizmo);
1194
1390
  }
1195
1391
  Activate() {
1196
1392
  }
1197
1393
  SetGizmoMode(mode) {
1198
- this.gizmo.setMode(mode);
1394
+ this._gizmo.mode = mode;
1395
+ }
1396
+ // public onPointerDown(e: PointerEvent): void {
1397
+ // super.onPointerDown(e);
1398
+ // // if (this._hovered) {
1399
+ // // this._dragRaycastOnObjects = this._gizmo.gizmoPlane.children;
1400
+ // // }
1401
+ // }
1402
+ // protected raycast(): Intersection[] {
1403
+ // return super.raycast(this._gizmo.gizmoNode.children);
1404
+ // }
1405
+ };
1406
+
1407
+ // src/toolbox/select/SelectTool.ts
1408
+ var DIVESelectTool = class extends DIVETransformTool {
1409
+ constructor(scene, controller) {
1410
+ super(scene, controller);
1411
+ this.name = "SelectTool";
1412
+ }
1413
+ Activate() {
1199
1414
  }
1200
1415
  Select(selectable) {
1201
1416
  if (selectable.onSelect) selectable.onSelect();
1202
1417
  if ("isMoveable" in selectable) {
1203
1418
  const movable = selectable;
1204
- movable.gizmo = this.gizmo;
1205
- this.gizmo.attach(movable);
1419
+ this._gizmo.attach(movable);
1206
1420
  }
1207
1421
  }
1208
1422
  Deselect(selectable) {
1209
1423
  if (selectable.onDeselect) selectable.onDeselect();
1210
- if ("isMoveable" in selectable) selectable.gizmo = null;
1211
- this.gizmo.detach();
1424
+ this._gizmo.detach();
1212
1425
  }
1213
- onPointerUp(e) {
1214
- const pointerPos = new import_three15.Vector2(e.offsetX / this.canvas.clientWidth * 2 - 1, e.offsetY / this.canvas.clientHeight * -2 + 1);
1215
- this.raycaster.setFromCamera(pointerPos, this.controller.object);
1216
- const first = this.raycastFirst();
1426
+ onClick(e) {
1427
+ super.onClick(e);
1428
+ const first = this._raycaster.intersectObjects(this._scene.Root.children, true)[0];
1217
1429
  const selectable = this.findSelectableInterface(first == null ? void 0 : first.object);
1218
1430
  if (!first || !selectable) {
1219
- if (this.gizmo.object) this.Deselect(this.gizmo.object);
1431
+ if (this._gizmo.object) {
1432
+ this.Deselect(this._gizmo.object);
1433
+ }
1220
1434
  return;
1221
1435
  }
1436
+ if (this._gizmo.object) {
1437
+ if (this._gizmo.object.uuid === selectable.uuid) return;
1438
+ this.Deselect(this._gizmo.object);
1439
+ }
1222
1440
  this.Select(selectable);
1223
1441
  }
1224
1442
  findSelectableInterface(child) {
@@ -1226,17 +1444,11 @@ var DIVESelectTool = class extends DIVEBaseTool {
1226
1444
  if (child.parent === null) {
1227
1445
  return void 0;
1228
1446
  }
1229
- if ("isSelectable" in child) {
1447
+ if (isSelectable(child)) {
1230
1448
  return child;
1231
1449
  }
1232
1450
  return this.findSelectableInterface(child.parent);
1233
1451
  }
1234
- raycastFirst() {
1235
- return this.raycastAll()[0];
1236
- }
1237
- raycastAll() {
1238
- return this.raycaster.intersectObjects(this.scene.Root.children, true);
1239
- }
1240
1452
  };
1241
1453
 
1242
1454
  // src/toolbox/Toolbox.ts
@@ -1245,10 +1457,12 @@ var DIVEToolbox = class {
1245
1457
  this.removeListenersCallback = () => {
1246
1458
  };
1247
1459
  this.selectTool = new DIVESelectTool(scene, controller);
1460
+ controller.domElement.addEventListener("pointermove", this.onPointerMove.bind(this));
1248
1461
  controller.domElement.addEventListener("pointerdown", this.onPointerDown.bind(this));
1249
1462
  controller.domElement.addEventListener("pointerup", this.onPointerUp.bind(this));
1250
1463
  controller.domElement.addEventListener("wheel", this.onWheel.bind(this));
1251
1464
  this.removeListenersCallback = () => {
1465
+ controller.domElement.removeEventListener("pointermove", this.onPointerMove.bind(this));
1252
1466
  controller.domElement.removeEventListener("pointerdown", this.onPointerDown.bind(this));
1253
1467
  controller.domElement.removeEventListener("pointerup", this.onPointerUp.bind(this));
1254
1468
  controller.domElement.removeEventListener("wheel", this.onWheel.bind(this));
@@ -1278,6 +1492,9 @@ var DIVEToolbox = class {
1278
1492
  SetGizmoMode(mode) {
1279
1493
  this.selectTool.SetGizmoMode(mode);
1280
1494
  }
1495
+ onPointerMove(e) {
1496
+ this.activeTool.onPointerMove(e);
1497
+ }
1281
1498
  onPointerDown(e) {
1282
1499
  this.activeTool.onPointerDown(e);
1283
1500
  }
@@ -1428,6 +1645,11 @@ function roundExponential(number, decimals = 0) {
1428
1645
  return shift(Math.round(n), -decimals);
1429
1646
  }
1430
1647
 
1648
+ // src/math/signedAngleTo/signedAngleTo.ts
1649
+ function signedAngleTo(vecA, vecB, planeNormal) {
1650
+ return Math.atan2(vecA.clone().cross(vecB).dot(planeNormal), vecB.clone().dot(vecA));
1651
+ }
1652
+
1431
1653
  // src/math/toFixed/toFixedExp.ts
1432
1654
  function toFixedExp(number, decimals = 0) {
1433
1655
  const n = shift(number, +decimals);
@@ -1446,7 +1668,8 @@ var DIVEMath = {
1446
1668
  floorExp,
1447
1669
  roundExp: roundExponential,
1448
1670
  toFixedExp,
1449
- truncateExp
1671
+ truncateExp,
1672
+ signedAngleTo
1450
1673
  };
1451
1674
 
1452
1675
  // src/dive.ts
@@ -1522,6 +1745,11 @@ var DIVE = class {
1522
1745
  this.addResizeObserver();
1523
1746
  }
1524
1747
  this.renderer.StartRenderer(this.scene, this.perspectiveCamera);
1748
+ window.DIVE = {
1749
+ PrintScene: () => {
1750
+ console.log(this.scene);
1751
+ }
1752
+ };
1525
1753
  }
1526
1754
  // methods
1527
1755
  OnResize(width, height) {