@inweb/viewer-three 26.10.3 → 26.10.5
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.
- package/dist/plugins/loaders/GLTFCloudLoader.js +3 -1
- package/dist/plugins/loaders/GLTFCloudLoader.js.map +1 -1
- package/dist/plugins/loaders/GLTFCloudLoader.min.js +1 -1
- package/dist/plugins/loaders/IFCXLoader.js.map +1 -1
- package/dist/plugins/loaders/IFCXLoader.module.js.map +1 -1
- package/dist/viewer-three.js +11700 -12089
- package/dist/viewer-three.js.map +1 -1
- package/dist/viewer-three.min.js +3 -3
- package/dist/viewer-three.module.js +216 -6
- package/dist/viewer-three.module.js.map +1 -1
- package/lib/Viewer/controls/JoyStickControls.d.ts +44 -0
- package/lib/Viewer/draggers/FlyDragger.d.ts +1 -0
- package/lib/Viewer/draggers/WalkDragger.d.ts +1 -0
- package/package.json +9 -9
- package/plugins/loaders/IFCX/render.js +1 -1
- package/src/Viewer/controls/JoyStickControls.ts +285 -0
- package/src/Viewer/controls/OrbitControls.js +0 -1
- package/src/Viewer/draggers/FlyDragger.ts +13 -0
- package/src/Viewer/draggers/MeasureLineDragger.ts +9 -6
- package/src/Viewer/draggers/WalkDragger.ts +13 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Camera, Controls, Object3D } from "three";
|
|
2
|
+
interface JoyStickControlsEventMap {
|
|
3
|
+
change: {
|
|
4
|
+
type: "change";
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
export declare class JoyStickControls extends Controls<JoyStickControlsEventMap> {
|
|
8
|
+
readonly EYE_HEIGHT = 1.7;
|
|
9
|
+
readonly FAILING_DISTANCE = 2;
|
|
10
|
+
readonly GROUND_FOLLOWING_SPEED = 0.05;
|
|
11
|
+
readonly WALK_SPEED_DELIMITER = 4;
|
|
12
|
+
movementSpeed: number;
|
|
13
|
+
multiplier: number;
|
|
14
|
+
private raycaster;
|
|
15
|
+
private groundObjects;
|
|
16
|
+
private canvas;
|
|
17
|
+
private overlayElement;
|
|
18
|
+
private joyStickCanvas;
|
|
19
|
+
private context;
|
|
20
|
+
private moveClock;
|
|
21
|
+
private camera;
|
|
22
|
+
private joyStickPosition;
|
|
23
|
+
private isActive;
|
|
24
|
+
private readonly MAX_JOYSTICK_DISTANCE;
|
|
25
|
+
private readonly INTERNAL_RADIUS;
|
|
26
|
+
private readonly MAX_MOVE_STICK;
|
|
27
|
+
private readonly EXTERNAL_RADIUS;
|
|
28
|
+
private readonly CANVAS_SIZE;
|
|
29
|
+
private centerX;
|
|
30
|
+
private centerY;
|
|
31
|
+
private pressed;
|
|
32
|
+
constructor(camera: Camera, domElement: HTMLElement, canvasElement: HTMLCanvasElement, groundObjects: Object3D[]);
|
|
33
|
+
dispose(): void;
|
|
34
|
+
private onPointerDown;
|
|
35
|
+
private onPointerMove;
|
|
36
|
+
private onPointerUp;
|
|
37
|
+
private onResize;
|
|
38
|
+
private updateVisibility;
|
|
39
|
+
private updatePosition;
|
|
40
|
+
private draw;
|
|
41
|
+
private updateGroundFollowing;
|
|
42
|
+
update(): void;
|
|
43
|
+
}
|
|
44
|
+
export {};
|
|
@@ -4,6 +4,7 @@ import { FlyControls } from "../controls/FlyControls";
|
|
|
4
4
|
export declare class FlyDragger implements IDragger {
|
|
5
5
|
protected viewer: Viewer;
|
|
6
6
|
controls: FlyControls;
|
|
7
|
+
private joyStickControls;
|
|
7
8
|
constructor(viewer: Viewer);
|
|
8
9
|
dispose(): void;
|
|
9
10
|
updateControls: () => void;
|
|
@@ -4,6 +4,7 @@ import { WalkControls } from "../controls/WalkControls";
|
|
|
4
4
|
export declare class WalkDragger implements IDragger {
|
|
5
5
|
protected viewer: Viewer;
|
|
6
6
|
controls: WalkControls;
|
|
7
|
+
private joyStickControls;
|
|
7
8
|
constructor(viewer: Viewer);
|
|
8
9
|
dispose(): void;
|
|
9
10
|
updateControls: () => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inweb/viewer-three",
|
|
3
|
-
"version": "26.10.
|
|
3
|
+
"version": "26.10.5",
|
|
4
4
|
"description": "JavaScript library for rendering CAD and BIM files in a browser using Three.js",
|
|
5
5
|
"homepage": "https://cloud.opendesign.com/docs/index.html",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -35,18 +35,18 @@
|
|
|
35
35
|
"docs": "typedoc"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@inweb/client": "~26.10.
|
|
39
|
-
"@inweb/eventemitter2": "~26.10.
|
|
40
|
-
"@inweb/markup": "~26.10.
|
|
41
|
-
"@inweb/viewer-core": "~26.10.
|
|
38
|
+
"@inweb/client": "~26.10.5",
|
|
39
|
+
"@inweb/eventemitter2": "~26.10.5",
|
|
40
|
+
"@inweb/markup": "~26.10.5",
|
|
41
|
+
"@inweb/viewer-core": "~26.10.5"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@types/three": "^0.
|
|
44
|
+
"@types/three": "^0.180.0",
|
|
45
45
|
"potree-core": "^2.0.11",
|
|
46
|
-
"three": "^0.
|
|
46
|
+
"three": "^0.180.0"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
|
-
"@types/three": "^0.
|
|
50
|
-
"three": "^0.
|
|
49
|
+
"@types/three": "^0.180.0",
|
|
50
|
+
"three": "^0.180.0"
|
|
51
51
|
}
|
|
52
52
|
}
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
// published under MIT license
|
|
31
31
|
|
|
32
32
|
/* eslint-disable lines-between-class-members */
|
|
33
|
-
/* eslint-disable
|
|
33
|
+
/* eslint-disable no-unused-vars */
|
|
34
34
|
/* eslint-disable prefer-const */
|
|
35
35
|
/* eslint-disable no-useless-catch */
|
|
36
36
|
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2002-2025, Open Design Alliance (the "Alliance").
|
|
3
|
+
// All rights reserved.
|
|
4
|
+
//
|
|
5
|
+
// This software and its documentation and related materials are owned by
|
|
6
|
+
// the Alliance. The software may only be incorporated into application
|
|
7
|
+
// programs owned by members of the Alliance, subject to a signed
|
|
8
|
+
// Membership Agreement and Supplemental Software License Agreement with the
|
|
9
|
+
// Alliance. The structure and organization of this software are the valuable
|
|
10
|
+
// trade secrets of the Alliance and its suppliers. The software is also
|
|
11
|
+
// protected by copyright law and international treaty provisions. Application
|
|
12
|
+
// programs incorporating this software must include the following statement
|
|
13
|
+
// with their copyright notices:
|
|
14
|
+
//
|
|
15
|
+
// This application incorporates Open Design Alliance software pursuant to a
|
|
16
|
+
// license agreement with Open Design Alliance.
|
|
17
|
+
// Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.
|
|
18
|
+
// All rights reserved.
|
|
19
|
+
//
|
|
20
|
+
// By use of this software, its documentation or related materials, you
|
|
21
|
+
// acknowledge and accept the above terms.
|
|
22
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
23
|
+
|
|
24
|
+
// ===================== AI-CODE-FILE ======================
|
|
25
|
+
// Source: Claude Sonnet 4.5
|
|
26
|
+
// Date: 2025-10-07
|
|
27
|
+
// Reviewer: vitaly.ivanov@opendesign.com
|
|
28
|
+
// Issue: CLOUD-5851
|
|
29
|
+
// Notes: Originally AI-generated, modified manually
|
|
30
|
+
// =========================================================
|
|
31
|
+
|
|
32
|
+
import { Camera, Clock, Controls, Vector2, Vector3, Raycaster, Object3D, MathUtils } from "three";
|
|
33
|
+
|
|
34
|
+
interface JoyStickControlsEventMap {
|
|
35
|
+
change: { type: "change" };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export class JoyStickControls extends Controls<JoyStickControlsEventMap> {
|
|
39
|
+
readonly EYE_HEIGHT = 1.7;
|
|
40
|
+
readonly FAILING_DISTANCE = 2;
|
|
41
|
+
readonly GROUND_FOLLOWING_SPEED = 0.05;
|
|
42
|
+
readonly WALK_SPEED_DELIMITER = 4;
|
|
43
|
+
|
|
44
|
+
public movementSpeed = 0.1;
|
|
45
|
+
public multiplier = 3;
|
|
46
|
+
|
|
47
|
+
private raycaster: Raycaster;
|
|
48
|
+
private groundObjects: Object3D[];
|
|
49
|
+
|
|
50
|
+
private canvas: HTMLCanvasElement;
|
|
51
|
+
private overlayElement: HTMLDivElement;
|
|
52
|
+
private joyStickCanvas: HTMLCanvasElement;
|
|
53
|
+
private context: CanvasRenderingContext2D;
|
|
54
|
+
|
|
55
|
+
private moveClock: Clock;
|
|
56
|
+
private camera: Camera;
|
|
57
|
+
|
|
58
|
+
private joyStickPosition: Vector2;
|
|
59
|
+
private isActive: boolean = false;
|
|
60
|
+
|
|
61
|
+
private readonly MAX_JOYSTICK_DISTANCE = 100;
|
|
62
|
+
private readonly INTERNAL_RADIUS = 35;
|
|
63
|
+
private readonly MAX_MOVE_STICK = 40;
|
|
64
|
+
private readonly EXTERNAL_RADIUS = 65;
|
|
65
|
+
private readonly CANVAS_SIZE = 200;
|
|
66
|
+
|
|
67
|
+
private centerX: number;
|
|
68
|
+
private centerY: number;
|
|
69
|
+
private pressed: boolean = false;
|
|
70
|
+
|
|
71
|
+
constructor(camera: Camera, domElement: HTMLElement, canvasElement: HTMLCanvasElement, groundObjects: Object3D[]) {
|
|
72
|
+
super(camera, domElement);
|
|
73
|
+
this.camera = camera;
|
|
74
|
+
this.canvas = canvasElement;
|
|
75
|
+
this.moveClock = new Clock(false);
|
|
76
|
+
this.joyStickPosition = new Vector2(0, 0);
|
|
77
|
+
|
|
78
|
+
this.groundObjects = groundObjects;
|
|
79
|
+
this.raycaster = new Raycaster();
|
|
80
|
+
this.raycaster.near = 0;
|
|
81
|
+
this.raycaster.far = this.EYE_HEIGHT + this.FAILING_DISTANCE;
|
|
82
|
+
|
|
83
|
+
this.centerX = this.CANVAS_SIZE / 2;
|
|
84
|
+
this.centerY = this.CANVAS_SIZE / 2;
|
|
85
|
+
|
|
86
|
+
this.overlayElement = document.createElement("div");
|
|
87
|
+
this.overlayElement.id = "joyStickDiv";
|
|
88
|
+
this.overlayElement.style.background = "rgba(0,0,0,0)";
|
|
89
|
+
this.overlayElement.style.position = "fixed";
|
|
90
|
+
this.overlayElement.style.zIndex = "0";
|
|
91
|
+
this.overlayElement.style.touchAction = "none";
|
|
92
|
+
document.body.appendChild(this.overlayElement);
|
|
93
|
+
|
|
94
|
+
this.joyStickCanvas = document.createElement("canvas");
|
|
95
|
+
this.joyStickCanvas.id = "joyStickCanvas";
|
|
96
|
+
this.joyStickCanvas.width = this.CANVAS_SIZE;
|
|
97
|
+
this.joyStickCanvas.height = this.CANVAS_SIZE;
|
|
98
|
+
this.overlayElement.appendChild(this.joyStickCanvas);
|
|
99
|
+
this.context = this.joyStickCanvas.getContext("2d")!;
|
|
100
|
+
|
|
101
|
+
this.joyStickCanvas.addEventListener("pointerdown", this.onPointerDown);
|
|
102
|
+
document.addEventListener("pointermove", this.onPointerMove);
|
|
103
|
+
document.addEventListener("pointerup", this.onPointerUp);
|
|
104
|
+
|
|
105
|
+
window.addEventListener("resize", this.onResize);
|
|
106
|
+
document.addEventListener("fullscreenchange", this.onResize);
|
|
107
|
+
|
|
108
|
+
this.updateVisibility();
|
|
109
|
+
this.updatePosition();
|
|
110
|
+
this.draw();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
override dispose() {
|
|
114
|
+
this.joyStickCanvas.removeEventListener("pointerdown", this.onPointerDown);
|
|
115
|
+
document.removeEventListener("pointermove", this.onPointerMove);
|
|
116
|
+
document.removeEventListener("pointerup", this.onPointerUp);
|
|
117
|
+
|
|
118
|
+
window.removeEventListener("resize", this.onResize);
|
|
119
|
+
document.removeEventListener("fullscreenchange", this.onResize);
|
|
120
|
+
|
|
121
|
+
this.overlayElement.remove();
|
|
122
|
+
super.dispose();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private onPointerDown = (event: PointerEvent) => {
|
|
126
|
+
event.preventDefault();
|
|
127
|
+
this.pressed = true;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
private onPointerMove = (event: PointerEvent) => {
|
|
131
|
+
event.preventDefault();
|
|
132
|
+
if (!this.pressed) return;
|
|
133
|
+
|
|
134
|
+
let movedX = event.pageX;
|
|
135
|
+
let movedY = event.pageY;
|
|
136
|
+
|
|
137
|
+
if (
|
|
138
|
+
this.joyStickCanvas.offsetParent &&
|
|
139
|
+
(this.joyStickCanvas.offsetParent as HTMLElement).tagName.toUpperCase() === "BODY"
|
|
140
|
+
) {
|
|
141
|
+
movedX -= this.joyStickCanvas.offsetLeft;
|
|
142
|
+
movedY -= this.joyStickCanvas.offsetTop;
|
|
143
|
+
} else if (this.joyStickCanvas.offsetParent) {
|
|
144
|
+
movedX -= (this.joyStickCanvas.offsetParent as HTMLElement).offsetLeft;
|
|
145
|
+
movedY -= (this.joyStickCanvas.offsetParent as HTMLElement).offsetTop;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const x = 100 * ((movedX - this.centerX) / this.MAX_MOVE_STICK);
|
|
149
|
+
const y = 100 * ((movedY - this.centerY) / this.MAX_MOVE_STICK) * -1;
|
|
150
|
+
|
|
151
|
+
const distance = Math.sqrt(x * x + y * y);
|
|
152
|
+
if (distance > 20) {
|
|
153
|
+
this.joyStickPosition.set(x, y);
|
|
154
|
+
this.isActive = true;
|
|
155
|
+
} else {
|
|
156
|
+
this.joyStickPosition.set(0, 0);
|
|
157
|
+
this.isActive = false;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
this.draw();
|
|
161
|
+
this.moveClock.start();
|
|
162
|
+
this.update();
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
private onPointerUp = (event: PointerEvent) => {
|
|
166
|
+
event.preventDefault();
|
|
167
|
+
this.pressed = false;
|
|
168
|
+
this.joyStickPosition.set(0, 0);
|
|
169
|
+
this.isActive = false;
|
|
170
|
+
this.moveClock.stop();
|
|
171
|
+
this.draw();
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
private onResize = () => {
|
|
175
|
+
this.updateVisibility();
|
|
176
|
+
this.updatePosition();
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
private updateVisibility() {
|
|
180
|
+
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
|
181
|
+
const isNarrowScreen = window.innerWidth < 1024;
|
|
182
|
+
|
|
183
|
+
if (isMobile || isNarrowScreen) {
|
|
184
|
+
this.overlayElement.style.display = "block";
|
|
185
|
+
} else {
|
|
186
|
+
this.overlayElement.style.display = "none";
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
private updatePosition() {
|
|
191
|
+
const rect = this.canvas.getBoundingClientRect();
|
|
192
|
+
this.overlayElement.style.top = `${rect.height - this.CANVAS_SIZE}px`;
|
|
193
|
+
this.overlayElement.style.left = `${rect.left}px`;
|
|
194
|
+
this.overlayElement.style.width = `${this.CANVAS_SIZE}px`;
|
|
195
|
+
this.overlayElement.style.height = `${this.CANVAS_SIZE}px`;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private draw() {
|
|
199
|
+
this.context.clearRect(0, 0, this.CANVAS_SIZE, this.CANVAS_SIZE);
|
|
200
|
+
|
|
201
|
+
// Draw external circle
|
|
202
|
+
this.context.beginPath();
|
|
203
|
+
this.context.arc(this.centerX, this.centerY, this.EXTERNAL_RADIUS, 0, 2 * Math.PI, false);
|
|
204
|
+
this.context.lineWidth = 2;
|
|
205
|
+
this.context.strokeStyle = "#35436E";
|
|
206
|
+
this.context.globalAlpha = 0.5;
|
|
207
|
+
this.context.stroke();
|
|
208
|
+
|
|
209
|
+
// Draw internal circle
|
|
210
|
+
let movedX = this.centerX + (this.joyStickPosition.x * this.MAX_MOVE_STICK) / 100;
|
|
211
|
+
let movedY = this.centerY - (this.joyStickPosition.y * this.MAX_MOVE_STICK) / 100;
|
|
212
|
+
|
|
213
|
+
movedX = Math.max(this.MAX_MOVE_STICK, Math.min(this.CANVAS_SIZE - this.MAX_MOVE_STICK, movedX));
|
|
214
|
+
movedY = Math.max(this.MAX_MOVE_STICK, Math.min(this.CANVAS_SIZE - this.MAX_MOVE_STICK, movedY));
|
|
215
|
+
|
|
216
|
+
this.context.beginPath();
|
|
217
|
+
this.context.arc(movedX, movedY, this.INTERNAL_RADIUS, 0, 2 * Math.PI, false);
|
|
218
|
+
this.context.fillStyle = "#35436E";
|
|
219
|
+
this.context.lineWidth = 2;
|
|
220
|
+
this.context.strokeStyle = "#35436E";
|
|
221
|
+
this.context.globalAlpha = 0.5;
|
|
222
|
+
this.context.fill();
|
|
223
|
+
this.context.stroke();
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private updateGroundFollowing() {
|
|
227
|
+
const up = new Vector3().copy(this.camera.up);
|
|
228
|
+
this.raycaster.set(this.camera.position, up.negate());
|
|
229
|
+
|
|
230
|
+
this.raycaster.params = this.raycaster.params = {
|
|
231
|
+
Mesh: {},
|
|
232
|
+
Line: { threshold: 0 },
|
|
233
|
+
Line2: { threshold: 0 },
|
|
234
|
+
LOD: { threshold: 0 },
|
|
235
|
+
Points: { threshold: 0 },
|
|
236
|
+
Sprite: { threshold: 0 },
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
const intersects = this.raycaster.intersectObjects(this.groundObjects, false);
|
|
240
|
+
if (intersects.length > 0) {
|
|
241
|
+
const groundY = intersects[0].point.y;
|
|
242
|
+
const targetY = groundY + this.EYE_HEIGHT;
|
|
243
|
+
|
|
244
|
+
// Smoothly interpolate the camera's y position to the target height
|
|
245
|
+
this.camera.position.y = MathUtils.lerp(this.camera.position.y, targetY, this.GROUND_FOLLOWING_SPEED);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
override update() {
|
|
250
|
+
if (!this.isActive) return;
|
|
251
|
+
|
|
252
|
+
const forwardInput = this.joyStickPosition.y / this.MAX_JOYSTICK_DISTANCE;
|
|
253
|
+
const rightInput = this.joyStickPosition.x / this.MAX_JOYSTICK_DISTANCE;
|
|
254
|
+
|
|
255
|
+
const timeDelta = this.moveClock.getDelta();
|
|
256
|
+
const moveDelta = (timeDelta * this.multiplier * this.movementSpeed) / this.WALK_SPEED_DELIMITER;
|
|
257
|
+
|
|
258
|
+
const forward = new Vector3();
|
|
259
|
+
const sideways = new Vector3();
|
|
260
|
+
|
|
261
|
+
this.camera.getWorldDirection(forward);
|
|
262
|
+
if (this.groundObjects.length > 0) {
|
|
263
|
+
forward.y = 0;
|
|
264
|
+
}
|
|
265
|
+
forward.normalize();
|
|
266
|
+
|
|
267
|
+
sideways.setFromMatrixColumn(this.camera.matrix, 0);
|
|
268
|
+
if (this.groundObjects.length > 0) {
|
|
269
|
+
sideways.y = 0;
|
|
270
|
+
}
|
|
271
|
+
sideways.normalize();
|
|
272
|
+
|
|
273
|
+
if (forwardInput !== 0) {
|
|
274
|
+
this.camera.position.addScaledVector(forward, moveDelta * forwardInput);
|
|
275
|
+
}
|
|
276
|
+
if (rightInput !== 0) {
|
|
277
|
+
this.camera.position.addScaledVector(sideways, moveDelta * rightInput);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (forwardInput !== 0 || rightInput !== 0) {
|
|
281
|
+
if (this.groundObjects.length > 0) this.updateGroundFollowing();
|
|
282
|
+
this.dispatchEvent({ type: "change" });
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
@@ -26,15 +26,21 @@ import { type IDragger } from "@inweb/viewer-core";
|
|
|
26
26
|
|
|
27
27
|
import type { Viewer } from "../Viewer";
|
|
28
28
|
import { FlyControls } from "../controls/FlyControls";
|
|
29
|
+
import { JoyStickControls } from "../controls/JoyStickControls";
|
|
29
30
|
|
|
30
31
|
export class FlyDragger implements IDragger {
|
|
31
32
|
protected viewer: Viewer;
|
|
32
33
|
public controls: FlyControls;
|
|
34
|
+
private joyStickControls: JoyStickControls;
|
|
33
35
|
|
|
34
36
|
constructor(viewer: Viewer) {
|
|
35
37
|
this.controls = new FlyControls(viewer.camera, viewer.canvas);
|
|
36
38
|
this.controls.addEventListener("change", this.controlsChange);
|
|
37
39
|
this.controls.addEventListener("flyspeedchange", this.flyspeedChange);
|
|
40
|
+
|
|
41
|
+
this.joyStickControls = new JoyStickControls(viewer.camera, viewer.canvas, viewer.canvas, []);
|
|
42
|
+
this.joyStickControls.addEventListener("change", this.controlsChange);
|
|
43
|
+
|
|
38
44
|
this.viewer = viewer;
|
|
39
45
|
this.viewer.addEventListener("render", this.viewerRender);
|
|
40
46
|
this.viewer.addEventListener("zoom", this.viewerZoom);
|
|
@@ -49,11 +55,16 @@ export class FlyDragger implements IDragger {
|
|
|
49
55
|
this.controls.removeEventListener("flyspeedchange", this.flyspeedChange);
|
|
50
56
|
this.controls.removeEventListener("change", this.controlsChange);
|
|
51
57
|
this.controls.dispose();
|
|
58
|
+
|
|
59
|
+
this.joyStickControls.removeEventListener("change", this.controlsChange);
|
|
60
|
+
this.joyStickControls.dispose();
|
|
52
61
|
}
|
|
53
62
|
|
|
54
63
|
updateControls = () => {
|
|
55
64
|
const size = this.viewer.extents.getSize(new Vector3());
|
|
56
65
|
this.controls.movementSpeed = Math.min(size.x, size.y, size.z) / 2;
|
|
66
|
+
this.joyStickControls.movementSpeed = this.controls.movementSpeed;
|
|
67
|
+
this.joyStickControls.multiplier = this.controls.multiplier;
|
|
57
68
|
};
|
|
58
69
|
|
|
59
70
|
updateControlsCamera = () => {
|
|
@@ -67,9 +78,11 @@ export class FlyDragger implements IDragger {
|
|
|
67
78
|
|
|
68
79
|
flyspeedChange = (event: any) => {
|
|
69
80
|
this.viewer.emitEvent(event);
|
|
81
|
+
this.joyStickControls.multiplier = this.controls.multiplier;
|
|
70
82
|
};
|
|
71
83
|
|
|
72
84
|
viewerRender = () => {
|
|
85
|
+
this.joyStickControls.update();
|
|
73
86
|
this.controls.update();
|
|
74
87
|
};
|
|
75
88
|
|
|
@@ -367,7 +367,7 @@ class MeasureOverlay {
|
|
|
367
367
|
if (!this.canvas.parentElement) return;
|
|
368
368
|
|
|
369
369
|
this.canvas.parentElement.appendChild(this.container);
|
|
370
|
-
this.resizeObserver.observe(this.canvas
|
|
370
|
+
this.resizeObserver.observe(this.canvas);
|
|
371
371
|
}
|
|
372
372
|
|
|
373
373
|
dispose() {
|
|
@@ -403,13 +403,16 @@ class MeasureOverlay {
|
|
|
403
403
|
this.lines = this.lines.filter((x) => x !== line);
|
|
404
404
|
}
|
|
405
405
|
|
|
406
|
-
resizeContainer = (
|
|
407
|
-
const {
|
|
406
|
+
resizeContainer = () => {
|
|
407
|
+
const { offsetLeft, offsetTop, offsetWidth, offsetHeight } = this.canvas;
|
|
408
408
|
|
|
409
|
-
if (!
|
|
409
|
+
if (!offsetWidth || !offsetHeight) return; // <- invisible canvas, or canvas with parent removed
|
|
410
410
|
|
|
411
|
-
this.container.style.
|
|
412
|
-
this.container.style.
|
|
411
|
+
this.container.style.left = `${offsetLeft}px`;
|
|
412
|
+
this.container.style.top = `${offsetTop}px`;
|
|
413
|
+
|
|
414
|
+
this.container.style.width = `${offsetWidth}px`;
|
|
415
|
+
this.container.style.height = `${offsetHeight}px`;
|
|
413
416
|
};
|
|
414
417
|
}
|
|
415
418
|
|
|
@@ -26,10 +26,12 @@ import { type IDragger } from "@inweb/viewer-core";
|
|
|
26
26
|
|
|
27
27
|
import type { Viewer } from "../Viewer";
|
|
28
28
|
import { WalkControls } from "../controls/WalkControls";
|
|
29
|
+
import { JoyStickControls } from "../controls/JoyStickControls";
|
|
29
30
|
|
|
30
31
|
export class WalkDragger implements IDragger {
|
|
31
32
|
protected viewer: Viewer;
|
|
32
33
|
public controls: WalkControls;
|
|
34
|
+
private joyStickControls: JoyStickControls;
|
|
33
35
|
|
|
34
36
|
constructor(viewer: Viewer) {
|
|
35
37
|
const meshOnlyGround: Mesh[] = [];
|
|
@@ -43,6 +45,10 @@ export class WalkDragger implements IDragger {
|
|
|
43
45
|
this.controls = new WalkControls(viewer.camera, viewer.canvas, meshOnlyGround);
|
|
44
46
|
this.controls.addEventListener("change", this.controlsChange);
|
|
45
47
|
this.controls.addEventListener("walkspeedchange", this.walkspeedChange);
|
|
48
|
+
|
|
49
|
+
this.joyStickControls = new JoyStickControls(viewer.camera, viewer.canvas, viewer.canvas, meshOnlyGround);
|
|
50
|
+
this.joyStickControls.addEventListener("change", this.controlsChange);
|
|
51
|
+
|
|
46
52
|
this.viewer = viewer;
|
|
47
53
|
this.viewer.addEventListener("render", this.viewerRender);
|
|
48
54
|
this.viewer.addEventListener("zoom", this.viewerZoom);
|
|
@@ -57,11 +63,16 @@ export class WalkDragger implements IDragger {
|
|
|
57
63
|
this.controls.removeEventListener("walkspeedchange", this.walkspeedChange);
|
|
58
64
|
this.controls.removeEventListener("change", this.controlsChange);
|
|
59
65
|
this.controls.dispose();
|
|
66
|
+
|
|
67
|
+
this.joyStickControls.removeEventListener("change", this.controlsChange);
|
|
68
|
+
this.joyStickControls.dispose();
|
|
60
69
|
}
|
|
61
70
|
|
|
62
71
|
updateControls = () => {
|
|
63
72
|
const size = this.viewer.extents.getSize(new Vector3());
|
|
64
73
|
this.controls.movementSpeed = Math.min(size.x, size.y, size.z) / 2;
|
|
74
|
+
this.joyStickControls.movementSpeed = this.controls.movementSpeed;
|
|
75
|
+
this.joyStickControls.multiplier = this.controls.multiplier;
|
|
65
76
|
};
|
|
66
77
|
|
|
67
78
|
updateControlsCamera = () => {
|
|
@@ -75,9 +86,11 @@ export class WalkDragger implements IDragger {
|
|
|
75
86
|
|
|
76
87
|
walkspeedChange = (event: any) => {
|
|
77
88
|
this.viewer.emitEvent(event);
|
|
89
|
+
this.joyStickControls.multiplier = this.controls.multiplier;
|
|
78
90
|
};
|
|
79
91
|
|
|
80
92
|
viewerRender = () => {
|
|
93
|
+
this.joyStickControls.update();
|
|
81
94
|
this.controls.update();
|
|
82
95
|
};
|
|
83
96
|
|