@shopware-ag/dive 1.0.7 → 1.0.9

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 (97) hide show
  1. package/package.json +6 -3
  2. package/src/__test__/DIVE.test.ts +244 -0
  3. package/src/animation/AnimationSystem.ts +14 -0
  4. package/src/animation/__test__/AnimationSystem.test.ts +19 -0
  5. package/src/axiscamera/AxisCamera.ts +50 -0
  6. package/src/axiscamera/__test__/AxisCamera.test.ts +41 -0
  7. package/src/camera/PerspectiveCamera.ts +43 -0
  8. package/src/camera/__test__/PerspectiveCamera.test.ts +27 -0
  9. package/src/com/Communication.ts +382 -0
  10. package/src/com/__test__/Communication.test.ts +612 -0
  11. package/src/com/actions/camera/getcameratransform.ts +9 -0
  12. package/src/com/actions/camera/movecamera.ts +15 -0
  13. package/src/com/actions/camera/resetcamera.ts +4 -0
  14. package/src/com/actions/camera/setcameralayer.ts +4 -0
  15. package/src/com/actions/camera/setcameratransform.ts +9 -0
  16. package/src/com/actions/camera/zoomcamera.ts +4 -0
  17. package/src/com/actions/index.ts +41 -0
  18. package/src/com/actions/media/generatemedia.ts +15 -0
  19. package/src/com/actions/object/addobject.ts +6 -0
  20. package/src/com/actions/object/deleteobject.ts +6 -0
  21. package/src/com/actions/object/getallobjects.ts +6 -0
  22. package/src/com/actions/object/getobjects.ts +6 -0
  23. package/src/com/actions/object/model/modelloaded.ts +4 -0
  24. package/src/com/actions/object/model/placeonfloor.ts +4 -0
  25. package/src/com/actions/object/selectobject.ts +6 -0
  26. package/src/com/actions/object/updateobject.ts +6 -0
  27. package/src/com/actions/scene/getallscenedata.ts +23 -0
  28. package/src/com/actions/scene/setbackground.ts +4 -0
  29. package/src/com/actions/scene/updatescene.ts +9 -0
  30. package/src/com/actions/toolbox/select/setgizmomode.ts +4 -0
  31. package/src/com/index.ts +4 -0
  32. package/src/com/types.ts +30 -0
  33. package/src/constant/AxisHelperColors.ts +7 -0
  34. package/src/constant/GridColors.ts +2 -0
  35. package/src/constant/VisibilityLayerMask.ts +5 -0
  36. package/src/controls/OrbitControls.ts +145 -0
  37. package/src/controls/__test__/OrbitControls.test.ts +181 -0
  38. package/src/grid/Grid.ts +22 -0
  39. package/src/grid/__test__/Grid.test.ts +19 -0
  40. package/src/helper/applyMixins/__test__/applyMixins.test.ts +27 -0
  41. package/src/helper/applyMixins/applyMixins.ts +15 -0
  42. package/src/helper/getObjectDelta/__test__/getObjectDelta.spec.ts +152 -0
  43. package/src/helper/getObjectDelta/getObjectDelta.ts +101 -0
  44. package/src/interface/Moveable.ts +13 -0
  45. package/src/interface/Rotatable.ts +10 -0
  46. package/src/interface/Scalable.ts +10 -0
  47. package/src/interface/Selectable.ts +11 -0
  48. package/src/interface/__test__/Interfaces.test.ts +13 -0
  49. package/src/light/AmbientLight.ts +29 -0
  50. package/src/light/PointLight.ts +63 -0
  51. package/src/light/SceneLight.ts +60 -0
  52. package/src/light/__test__/AmbientLight.test.ts +44 -0
  53. package/src/light/__test__/PointLight.test.ts +98 -0
  54. package/src/light/__test__/SceneLight.test.ts +122 -0
  55. package/src/loadingmanager/LoadingManager.ts +44 -0
  56. package/src/loadingmanager/__test__/LoadingManager.test.ts +52 -0
  57. package/src/math/__test__/DIVEMath.test.ts +12 -0
  58. package/src/math/ceil/__test__/ceilExp.test.ts +12 -0
  59. package/src/math/ceil/ceilExp.ts +6 -0
  60. package/src/math/floor/__test__/floorExp.test.ts +14 -0
  61. package/src/math/floor/floorExp.ts +6 -0
  62. package/src/math/helper/__test__/shift.test.ts +12 -0
  63. package/src/math/helper/shift.ts +4 -0
  64. package/src/math/index.ts +19 -0
  65. package/src/math/round/__test__/roundExp.test.ts +14 -0
  66. package/src/math/round/roundExp.ts +7 -0
  67. package/src/math/toFixed/__test__/toFixedExp.test.ts +14 -0
  68. package/src/math/toFixed/toFixedExp.ts +6 -0
  69. package/src/math/truncate/__test__/truncateExp.test.ts +14 -0
  70. package/src/math/truncate/truncateExp.ts +6 -0
  71. package/src/mediacreator/MediaCreator.ts +65 -0
  72. package/src/mediacreator/__test__/MediaCreator.test.ts +113 -0
  73. package/src/model/Model.ts +72 -0
  74. package/src/model/__test__/Model.test.ts +163 -0
  75. package/src/primitive/floor/Floor.ts +34 -0
  76. package/src/primitive/floor/__test__/Floor.test.ts +21 -0
  77. package/src/renderer/Renderer.ts +165 -0
  78. package/src/renderer/__test__/Renderer.test.ts +169 -0
  79. package/src/scene/Scene.ts +49 -0
  80. package/src/scene/__test__/Scene.test.ts +70 -0
  81. package/src/scene/root/Root.ts +107 -0
  82. package/src/scene/root/__test__/Root.test.ts +129 -0
  83. package/src/scene/root/lightroot/LightRoot.ts +84 -0
  84. package/src/scene/root/lightroot/__test__/LightRoot.test.ts +137 -0
  85. package/src/scene/root/modelroot/ModelRoot.ts +82 -0
  86. package/src/scene/root/modelroot/__test__/ModelRoot.test.ts +185 -0
  87. package/src/toolbox/BaseTool.ts +18 -0
  88. package/src/toolbox/Toolbox.ts +76 -0
  89. package/src/toolbox/__test__/Toolbox.test.ts +109 -0
  90. package/src/toolbox/select/SelectTool.ts +123 -0
  91. package/src/toolbox/select/__test__/SelectTool.test.ts +190 -0
  92. package/build/dive.cjs +0 -1551
  93. package/build/dive.cjs.map +0 -1
  94. package/build/dive.d.cts +0 -558
  95. package/build/dive.d.ts +0 -558
  96. package/build/dive.js +0 -1516
  97. package/build/dive.js.map +0 -1
@@ -0,0 +1,107 @@
1
+ import { Object3D } from "three";
2
+ import DIVELightRoot from "./lightroot/LightRoot.ts";
3
+ import DIVEModelRoot from "./modelroot/ModelRoot.ts";
4
+ import { COMLight, COMModel, COMEntity } from "../../com/types.ts";
5
+ import DIVEFloor from "../../primitive/floor/Floor.ts";
6
+ import DIVEGrid from "../../grid/Grid.ts";
7
+
8
+ /**
9
+ * A basic scene node to hold grid, floor and all lower level roots.
10
+ *
11
+ * @module
12
+ */
13
+
14
+ export default class DIVERoot extends Object3D {
15
+ private lightRoot: DIVELightRoot;
16
+ private modelRoot: DIVEModelRoot;
17
+ private floor: DIVEFloor;
18
+ private grid: DIVEGrid;
19
+
20
+ public get Floor(): DIVEFloor {
21
+ return this.floor;
22
+ }
23
+
24
+ public get Grid(): DIVEGrid {
25
+ return this.grid;
26
+ }
27
+
28
+ constructor() {
29
+ super();
30
+ this.name = "Root";
31
+
32
+ this.lightRoot = new DIVELightRoot();
33
+ this.add(this.lightRoot);
34
+ this.modelRoot = new DIVEModelRoot();
35
+ this.add(this.modelRoot);
36
+ this.floor = new DIVEFloor();
37
+ this.add(this.floor);
38
+ this.grid = new DIVEGrid();
39
+ this.add(this.grid);
40
+ }
41
+
42
+ public GetSceneObject(object: Partial<COMEntity>): Object3D | undefined {
43
+ switch (object.entityType) {
44
+ case "pov": {
45
+ return undefined;
46
+ }
47
+ case "light": {
48
+ return this.lightRoot.GetLight(object as COMLight);
49
+ }
50
+ case "model": {
51
+ return this.modelRoot.GetModel(object as COMModel);
52
+ }
53
+ }
54
+ }
55
+
56
+ public AddSceneObject(object: COMEntity): void {
57
+ switch (object.entityType) {
58
+ case "pov": {
59
+ break;
60
+ }
61
+ case "light": {
62
+ this.lightRoot.UpdateLight(object as COMLight);
63
+ break;
64
+ }
65
+ case "model": {
66
+ this.modelRoot.UpdateModel(object as COMModel);
67
+ break;
68
+ }
69
+ }
70
+ }
71
+
72
+ public UpdateSceneObject(object: Partial<COMEntity>): void {
73
+ switch (object.entityType) {
74
+ case "pov": {
75
+ break;
76
+ }
77
+ case "light": {
78
+ this.lightRoot.UpdateLight(object as COMLight);
79
+ break;
80
+ }
81
+ case "model": {
82
+ this.modelRoot.UpdateModel(object as COMModel);
83
+ break;
84
+ }
85
+ }
86
+ }
87
+
88
+ public DeleteSceneObject(object: Partial<COMEntity>): void {
89
+ switch (object.entityType) {
90
+ case "pov": {
91
+ break;
92
+ }
93
+ case "light": {
94
+ this.lightRoot.DeleteLight(object as COMLight);
95
+ break;
96
+ }
97
+ case "model": {
98
+ this.modelRoot.DeleteModel(object as COMModel);
99
+ break;
100
+ }
101
+ }
102
+ }
103
+
104
+ public PlaceOnFloor(object: Partial<COMModel>): void {
105
+ this.modelRoot.PlaceOnFloor(object);
106
+ }
107
+ }
@@ -0,0 +1,129 @@
1
+ import { COMLight, COMModel, COMPov } from '../../../com';
2
+ import DIVERoot from '../Root';
3
+
4
+ const mock_UpdateLight = jest.fn();
5
+ const mock_UpdateModel = jest.fn();
6
+ const mock_GetLight = jest.fn();
7
+ const mock_GetModel = jest.fn();
8
+ const mock_DeleteLight = jest.fn();
9
+ const mock_DeleteModel = jest.fn();
10
+ const mock_PlaceOnFloor = jest.fn();
11
+
12
+ jest.mock('../../../primitive/floor/Floor', () => {
13
+ return jest.fn(function () {
14
+ this.isObject3D = true;
15
+ this.parent = null;
16
+ this.dispatchEvent = jest.fn();
17
+ this.removeFromParent = jest.fn();
18
+ return this;
19
+ });
20
+ });
21
+
22
+ jest.mock('../../../grid/Grid', () => {
23
+ return jest.fn(function () {
24
+ this.isObject3D = true;
25
+ this.parent = null;
26
+ this.dispatchEvent = jest.fn();
27
+ this.removeFromParent = jest.fn();
28
+ return this;
29
+ });
30
+ });
31
+
32
+ jest.mock('../lightroot/LightRoot', () => {
33
+ return jest.fn(function () {
34
+ this.isObject3D = true;
35
+ this.parent = null;
36
+ this.dispatchEvent = jest.fn();
37
+ this.UpdateLight = mock_UpdateLight;
38
+ this.DeleteLight = mock_DeleteLight;
39
+ this.GetLight = mock_GetLight;
40
+ this.removeFromParent = jest.fn();
41
+ return this;
42
+ });
43
+ });
44
+
45
+ jest.mock('../modelroot/ModelRoot', () => {
46
+ return jest.fn(function () {
47
+ this.isObject3D = true;
48
+ this.parent = null;
49
+ this.dispatchEvent = jest.fn();
50
+ this.UpdateModel = mock_UpdateModel;
51
+ this.DeleteModel = mock_DeleteModel;
52
+ this.PlaceOnFloor = mock_PlaceOnFloor;
53
+ this.GetModel = mock_GetModel;
54
+ this.removeFromParent = jest.fn();
55
+ return this;
56
+ });
57
+ });
58
+
59
+ describe('DIVE/scene/root/DIVERoot', () => {
60
+ afterEach(() => {
61
+ jest.clearAllMocks();
62
+ });
63
+
64
+ it('should instantiate', () => {
65
+ const root = new DIVERoot();
66
+ expect(root).toBeDefined();
67
+ expect(root.children).toHaveLength(4);
68
+ });
69
+
70
+ it('should have Floor', () => {
71
+ const root = new DIVERoot();
72
+ expect(root.Floor).toBeDefined();
73
+ });
74
+
75
+ it('should have Grid', () => {
76
+ const root = new DIVERoot();
77
+ expect(root.Grid).toBeDefined();
78
+ });
79
+
80
+ it('should add object', () => {
81
+ const root = new DIVERoot();
82
+ root.AddSceneObject({ entityType: 'light' } as COMLight);
83
+ expect(mock_UpdateLight).toHaveBeenCalledTimes(1);
84
+
85
+ root.AddSceneObject({ entityType: 'model' } as COMModel);
86
+ expect(mock_UpdateModel).toHaveBeenCalledTimes(1);
87
+
88
+ expect(() => root.AddSceneObject({ entityType: 'pov' } as COMPov)).not.toThrow();
89
+ });
90
+
91
+ it('should update object', () => {
92
+ const root = new DIVERoot();
93
+
94
+ root.UpdateSceneObject({ entityType: 'light' });
95
+ expect(mock_UpdateLight).toHaveBeenCalledTimes(1);
96
+
97
+ root.UpdateSceneObject({ entityType: 'model' });
98
+ expect(mock_UpdateModel).toHaveBeenCalledTimes(1);
99
+
100
+ expect(() => root.UpdateSceneObject({ entityType: 'pov' })).not.toThrow();
101
+ });
102
+
103
+ it('should delete object', () => {
104
+ const root = new DIVERoot();
105
+
106
+ root.DeleteSceneObject({ entityType: 'light' });
107
+ expect(mock_DeleteLight).toHaveBeenCalledTimes(1);
108
+
109
+ root.DeleteSceneObject({ entityType: 'model' });
110
+ expect(mock_DeleteModel).toHaveBeenCalledTimes(1);
111
+
112
+ expect(() => root.DeleteSceneObject({ entityType: 'pov' })).not.toThrow();
113
+ });
114
+
115
+ it('should place model on floor', () => {
116
+ const root = new DIVERoot();
117
+ root.PlaceOnFloor({ entityType: 'model' });
118
+ expect(mock_PlaceOnFloor).toHaveBeenCalledTimes(1);
119
+ });
120
+
121
+ it('should get scene object', () => {
122
+ const scene = new DIVERoot();
123
+ scene.GetSceneObject({ entityType: 'model' });
124
+ expect(mock_GetModel).toHaveBeenCalledTimes(1);
125
+ scene.GetSceneObject({ entityType: 'light' });
126
+ expect(mock_GetLight).toHaveBeenCalledTimes(1);
127
+ expect(scene.GetSceneObject({ entityType: 'pov' })).toBeUndefined();
128
+ });
129
+ });
@@ -0,0 +1,84 @@
1
+ import { Color, Object3D } from "three";
2
+ import { type COMLight } from "../../../com/types.ts";
3
+ import DIVEAmbientLight from "../../../light/AmbientLight.ts";
4
+ import DIVEPointLight from "../../../light/PointLight.ts";
5
+ import type { DIVEMoveable } from "../../../interface/Moveable.ts";
6
+ import DIVESceneLight from "../../../light/SceneLight.ts";
7
+
8
+ /**
9
+ * A basic scene node to hold all lights.
10
+ *
11
+ * @module
12
+ */
13
+
14
+ export default class DIVELightRoot extends Object3D {
15
+ constructor() {
16
+ super();
17
+ this.name = "LightRoot";
18
+ }
19
+
20
+ public GetLight(object: Partial<COMLight>): Object3D | undefined {
21
+ if (object.id === undefined) {
22
+ console.warn('LightRoot.GetLight: object.id is undefined')
23
+ return undefined;
24
+ }
25
+ return this.children.find(object3D => object3D.userData.id === object.id);
26
+ }
27
+
28
+ public UpdateLight(light: Partial<COMLight>): void {
29
+ // update scene here for light
30
+ if (light.id === undefined) {
31
+ console.warn(`LightRoot.UpdateLight: light.id is undefined`)
32
+ return;
33
+ }
34
+
35
+ let sceneObject = this.children.find(object3D => object3D.userData.id === light.id);
36
+ if (!sceneObject) {
37
+ switch (light.type) {
38
+ case 'scene': {
39
+ sceneObject = new DIVESceneLight();
40
+ break;
41
+ }
42
+ case 'ambient': {
43
+ sceneObject = new DIVEAmbientLight();
44
+ break;
45
+ }
46
+ case 'point': {
47
+ sceneObject = new DIVEPointLight();
48
+ break;
49
+ }
50
+ default: {
51
+ console.warn(`LightRoot.UpdateLight: Unknown light type: ${light.type}`);
52
+ return;
53
+ }
54
+ }
55
+ sceneObject.userData.id = light.id;
56
+ this.add(sceneObject);
57
+ }
58
+
59
+ if (light.name !== undefined && light.name !== null) sceneObject.name = light.name;
60
+ if (light.position !== undefined && light.position !== null) sceneObject.position.set(light.position.x, light.position.y, light.position.z);
61
+ if (light.intensity !== undefined && light.intensity !== null) (sceneObject as (DIVEAmbientLight | DIVEPointLight)).SetIntensity(light.intensity);
62
+ if (light.enabled !== undefined && light.enabled !== null) (sceneObject as (DIVEAmbientLight | DIVEPointLight)).SetEnabled(light.enabled);
63
+ if (light.color !== undefined && light.color !== null) (sceneObject as (DIVEAmbientLight | DIVEPointLight)).SetColor(new Color(light.color));
64
+ }
65
+
66
+ public DeleteLight(light: Partial<COMLight>): void {
67
+ if (light.id === undefined) {
68
+ console.warn('LightRoot.DeleteLight: light.id is undefined')
69
+ return;
70
+ }
71
+
72
+ const sceneObject = this.children.find(object3D => object3D.userData.id === light.id);
73
+ if (!sceneObject) {
74
+ console.warn(`LightRoot.DeleteLight: Light with id ${light.id} not found`);
75
+ return;
76
+ }
77
+
78
+ if ('isMoveable' in sceneObject) {
79
+ (sceneObject as unknown as DIVEMoveable).gizmo?.detach();
80
+ }
81
+
82
+ this.remove(sceneObject);
83
+ }
84
+ }
@@ -0,0 +1,137 @@
1
+ import { TransformControls } from 'three/examples/jsm/Addons';
2
+ import { COMLight } from '../../../../com';
3
+ import { DIVEMoveable } from '../../../../interface/Moveable';
4
+ import DIVELightRoot from '../LightRoot';
5
+
6
+ const mock_SetPosition = jest.fn();
7
+ const mock_SetIntensity = jest.fn();
8
+ const mock_SetEnabled = jest.fn();
9
+ const mock_SetColor = jest.fn();
10
+
11
+ jest.mock('../../../../light/AmbientLight.ts', () => {
12
+ return jest.fn(function () {
13
+ this.isObject3D = true;
14
+ this.parent = null;
15
+ this.dispatchEvent = jest.fn();
16
+ this.position = {
17
+ set: mock_SetPosition,
18
+ }
19
+ this.SetIntensity = mock_SetIntensity;
20
+ this.SetEnabled = mock_SetEnabled;
21
+ this.SetColor = mock_SetColor;
22
+ this.userData = {
23
+ id: undefined,
24
+ }
25
+ this.removeFromParent = jest.fn();
26
+ return this;
27
+ });
28
+ });
29
+
30
+ jest.mock('../../../../light/PointLight.ts', () => {
31
+ return jest.fn(function () {
32
+ this.isObject3D = true;
33
+ this.parent = null;
34
+ this.dispatchEvent = jest.fn();
35
+ this.position = {
36
+ set: mock_SetPosition,
37
+ }
38
+ this.SetIntensity = mock_SetIntensity;
39
+ this.SetEnabled = mock_SetEnabled;
40
+ this.SetColor = mock_SetColor;
41
+ this.userData = {
42
+ id: undefined,
43
+ }
44
+ this.removeFromParent = jest.fn();
45
+ return this;
46
+ });
47
+ });
48
+
49
+ const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(() => { });
50
+
51
+ describe('dive/scene/root/lightroot/DIVELightRoot', () => {
52
+ beforeEach(() => {
53
+ consoleWarnSpy.mockClear();
54
+ });
55
+
56
+ it('should instantiate', () => {
57
+ const lightRoot = new DIVELightRoot();
58
+ expect(lightRoot).toBeDefined();
59
+ });
60
+
61
+ it('should not add incorrect light without id', () => {
62
+ const lightRoot = new DIVELightRoot();
63
+ expect(() => lightRoot.UpdateLight({ id: undefined })).not.toThrow();
64
+ expect(consoleWarnSpy).toHaveBeenCalled();
65
+ expect(lightRoot.children).toHaveLength(0);
66
+ });
67
+
68
+ it('should not add incorrect light', () => {
69
+ const lightRoot = new DIVELightRoot();
70
+ expect(() => lightRoot.UpdateLight(({ id: 'test_id', name: 'test', type: 'this not a real light type' }) as unknown as COMLight)).not.toThrow();
71
+ expect(consoleWarnSpy).toHaveBeenCalled();
72
+ expect(lightRoot.children).toHaveLength(0);
73
+ });
74
+
75
+ it('should update basic scene light', () => {
76
+ const lightRoot = new DIVELightRoot();
77
+ lightRoot.UpdateLight({ id: 'test_id', type: 'scene', name: 'test', position: undefined, enabled: true });
78
+ expect(lightRoot.children).toHaveLength(1);
79
+ expect(lightRoot.children[0].userData.id).toBe('test_id');
80
+ });
81
+
82
+ it('should update basic ambient light', () => {
83
+ const lightRoot = new DIVELightRoot();
84
+ lightRoot.UpdateLight({ id: 'test_id', type: 'ambient', position: undefined });
85
+ expect(lightRoot.children).toHaveLength(1);
86
+ expect(lightRoot.children[0].userData.id).toBe('test_id');
87
+ });
88
+
89
+ it('should update basic point light', () => {
90
+ const lightRoot = new DIVELightRoot();
91
+ lightRoot.UpdateLight({ id: 'test_id', type: 'point', position: undefined });
92
+ expect(lightRoot.children).toHaveLength(1);
93
+ expect(lightRoot.children[0].userData.id).toBe('test_id');
94
+ });
95
+
96
+ it('should update configured light', () => {
97
+ const lightRoot = new DIVELightRoot();
98
+ lightRoot.UpdateLight({ id: 'test_id', type: 'point', position: { x: 1, y: 2, z: 3 }, intensity: 0.5, color: 0x123456 });
99
+ expect(consoleWarnSpy).not.toHaveBeenCalled();
100
+ expect(lightRoot.children).toHaveLength(1);
101
+ expect(lightRoot.children[0].userData.id).toBe('test_id');
102
+ expect(mock_SetIntensity).toHaveBeenCalledTimes(1);
103
+ expect(mock_SetColor).toHaveBeenCalledTimes(1);
104
+ expect(mock_SetPosition).toHaveBeenCalledTimes(1);
105
+ });
106
+
107
+ it('should get light', () => {
108
+ const lightRoot = new DIVELightRoot();
109
+ expect(() => lightRoot.GetLight({ id: undefined })).not.toThrow();
110
+ expect(lightRoot.GetLight({ id: 'test_id' })).toBeUndefined();
111
+ lightRoot.UpdateLight({ id: 'test_id', type: 'point', position: { x: 1, y: 2, z: 3 }, intensity: 0.5, color: 0x123456 });
112
+ expect(consoleWarnSpy).toHaveBeenCalled();
113
+ expect(lightRoot.GetLight({ id: 'test_id' })).toBeDefined();
114
+ });
115
+
116
+ it('should delete light', () => {
117
+ const lightRoot = new DIVELightRoot();
118
+ expect(() => lightRoot.DeleteLight({ id: undefined })).not.toThrow();
119
+
120
+ expect(() => lightRoot.DeleteLight({ id: 'test_id' })).not.toThrow();
121
+
122
+ lightRoot.UpdateLight({ id: 'test_id', type: 'point', position: { x: 1, y: 2, z: 3 }, intensity: 0.5, color: 0x123456 });
123
+ expect(() => lightRoot.DeleteLight({ id: 'test_id' })).not.toThrow();
124
+
125
+ lightRoot.UpdateLight({ id: 'test_id', type: 'point', position: { x: 1, y: 2, z: 3 }, intensity: 0.5, color: 0x123456 });
126
+ (lightRoot.children[0] as unknown as DIVEMoveable).isMoveable = true;
127
+ expect(() => lightRoot.DeleteLight({ id: 'test_id' })).not.toThrow();
128
+
129
+ lightRoot.UpdateLight({ id: 'test_id', type: 'point', position: { x: 1, y: 2, z: 3 }, intensity: 0.5, color: 0x123456 });
130
+ (lightRoot.children[0] as unknown as DIVEMoveable).isMoveable = true;
131
+ (lightRoot.children[0] as unknown as DIVEMoveable).gizmo = {
132
+ detach: jest.fn(),
133
+ } as unknown as TransformControls;
134
+ expect(() => lightRoot.DeleteLight({ id: 'test_id' })).not.toThrow();
135
+ expect(lightRoot.children).toHaveLength(0);
136
+ });
137
+ });
@@ -0,0 +1,82 @@
1
+ import { Object3D } from "three";
2
+ import { COMModel } from "../../../com/types.ts";
3
+ import Model from "../../../model/Model.ts";
4
+ import DIVELoadingManager from "../../../loadingmanager/LoadingManager.ts";
5
+ import DIVECommunication from "../../../com/Communication.ts";
6
+ import type { DIVEMoveable } from "../../../interface/Moveable.ts";
7
+
8
+ /**
9
+ * A basic scene node to hold all models.
10
+ *
11
+ * @module
12
+ */
13
+ export default class DIVEModelRoot extends Object3D {
14
+ private loadingManager: DIVELoadingManager;
15
+
16
+ constructor() {
17
+ super();
18
+ this.name = "ModelRoot";
19
+
20
+ this.loadingManager = new DIVELoadingManager();
21
+ }
22
+
23
+ public GetModel(object: Partial<COMModel>): Object3D | undefined {
24
+ if (object.id === undefined) {
25
+ console.warn('ModelRoot.GetModel: object.id is undefined')
26
+ return undefined;
27
+ }
28
+ return this.children.find(object3D => object3D.userData.id === object.id);
29
+ }
30
+
31
+ public UpdateModel(object: Partial<COMModel>): void {
32
+ if (object.id === undefined) {
33
+ console.warn('ModelRoot.UpdateModel: object.id is undefined')
34
+ return;
35
+ }
36
+
37
+ let sceneObject = this.children.find(object3D => object3D.userData.id === object.id);
38
+ if (!sceneObject && object.uri !== undefined) {
39
+ const model = new Model();
40
+ sceneObject = model;
41
+ sceneObject.userData.id = object.id;
42
+ this.add(sceneObject);
43
+
44
+ this.loadingManager.LoadGLTF(object.uri).then((gltf) => {
45
+ model.SetModel(gltf);
46
+ DIVECommunication.get(object.id!)?.PerformAction('MODEL_LOADED', { id: object.id! });
47
+ });
48
+ }
49
+
50
+ if (object.position !== undefined) (sceneObject as Model).SetPosition(object.position);
51
+ if (object.rotation !== undefined) (sceneObject as Model).SetRotation(object.rotation);
52
+ if (object.scale !== undefined) (sceneObject as Model).SetScale(object.scale);
53
+ }
54
+
55
+ public DeleteModel(object: Partial<COMModel>): void {
56
+ if (object.id === undefined) {
57
+ console.warn(`ModelRoot.DeleteModel: object.id is undefined`)
58
+ return;
59
+ }
60
+
61
+ const sceneObject = this.children.find(object3D => object3D.userData.id === object.id);
62
+ if (!sceneObject) {
63
+ console.warn(`ModelRoot.DeleteModel: Model with id ${object.id} not found`);
64
+ return;
65
+ }
66
+
67
+ if ('isMoveable' in sceneObject) {
68
+ (sceneObject as unknown as DIVEMoveable).gizmo?.detach();
69
+ }
70
+
71
+ this.remove(sceneObject);
72
+ }
73
+
74
+ public PlaceOnFloor(object: Partial<COMModel>): void {
75
+ if (object.id === undefined) console.warn('ModelRoot.PlaceOnFloor: object.id is undefined');
76
+
77
+ const sceneObject = this.children.find(object3D => object3D.userData.id === object.id);
78
+ if (!sceneObject) return;
79
+
80
+ (sceneObject as Model).PlaceOnFloor();
81
+ }
82
+ }