@mml-io/3d-web-client-core 0.12.2 → 0.13.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.
@@ -31,7 +31,13 @@ export declare class CameraManager {
|
|
31
31
|
private lerpTarget;
|
32
32
|
private lerpFactor;
|
33
33
|
private lerpDuration;
|
34
|
+
private hasTouchControl;
|
35
|
+
private lastTouchX;
|
36
|
+
private lastTouchY;
|
34
37
|
constructor(targetElement: HTMLElement, collisionsManager: CollisionsManager, initialPhi?: number, initialTheta?: number);
|
38
|
+
private onTouchStart;
|
39
|
+
private onTouchMove;
|
40
|
+
private onTouchEnd;
|
35
41
|
private onMouseDown;
|
36
42
|
private onMouseUp;
|
37
43
|
private onMouseMove;
|
package/build/index.js
CHANGED
@@ -82,6 +82,169 @@ var EventHandlerCollection = class _EventHandlerCollection {
|
|
82
82
|
}
|
83
83
|
};
|
84
84
|
|
85
|
+
// src/input/VirtualJoystick.ts
|
86
|
+
var _VirtualJoystick = class _VirtualJoystick {
|
87
|
+
constructor(attrs) {
|
88
|
+
this.left = false;
|
89
|
+
this.right = false;
|
90
|
+
this.up = false;
|
91
|
+
this.down = false;
|
92
|
+
this.hasDirection = false;
|
93
|
+
this.clearFlags = () => {
|
94
|
+
this.left = false;
|
95
|
+
this.right = false;
|
96
|
+
this.up = false;
|
97
|
+
this.down = false;
|
98
|
+
this.hasDirection = false;
|
99
|
+
this.control.style.left = `${this.width / 2 - this.inner_radius}px`;
|
100
|
+
this.control.style.top = `${this.height / 2 - this.inner_radius}px`;
|
101
|
+
};
|
102
|
+
this.radius = attrs.radius || 50;
|
103
|
+
this.inner_radius = attrs.inner_radius || this.radius / 2;
|
104
|
+
this.anchor = attrs.anchor || "left";
|
105
|
+
this.x = attrs.x || 0;
|
106
|
+
this.y = attrs.y || 0;
|
107
|
+
this.width = attrs.width || this.radius * 2 + this.inner_radius * 2;
|
108
|
+
this.height = attrs.height || this.radius * 2 + this.inner_radius * 2;
|
109
|
+
this.mouse_support = this.checkTouch() || attrs.mouse_support === true;
|
110
|
+
this.initializeJoystick();
|
111
|
+
}
|
112
|
+
static checkForTouch() {
|
113
|
+
try {
|
114
|
+
document.createEvent("TouchEvent");
|
115
|
+
return true;
|
116
|
+
} catch (e) {
|
117
|
+
return false;
|
118
|
+
}
|
119
|
+
}
|
120
|
+
static isTouchOnJoystick(touch) {
|
121
|
+
if (!_VirtualJoystick.JOYSTICK_DIV) {
|
122
|
+
return false;
|
123
|
+
}
|
124
|
+
const divRect = _VirtualJoystick.JOYSTICK_DIV.getBoundingClientRect();
|
125
|
+
return touch.clientX >= divRect.left && touch.clientX <= divRect.right && touch.clientY >= divRect.top && touch.clientY <= divRect.bottom;
|
126
|
+
}
|
127
|
+
checkTouch() {
|
128
|
+
return _VirtualJoystick.checkForTouch();
|
129
|
+
}
|
130
|
+
initializeJoystick() {
|
131
|
+
if (!_VirtualJoystick.JOYSTICK_DIV) {
|
132
|
+
this.div = document.createElement("div");
|
133
|
+
const divStyle = this.div.style;
|
134
|
+
divStyle.display = this.checkTouch() || this.mouse_support ? "visible" : "none";
|
135
|
+
divStyle.position = "fixed";
|
136
|
+
if (this.anchor === "left") {
|
137
|
+
divStyle.left = `${this.x}px`;
|
138
|
+
} else {
|
139
|
+
divStyle.right = `${this.x}px`;
|
140
|
+
}
|
141
|
+
divStyle.bottom = `${this.y}px`;
|
142
|
+
divStyle.width = `${this.width}px`;
|
143
|
+
divStyle.height = `${this.height}px`;
|
144
|
+
divStyle.zIndex = "10000";
|
145
|
+
divStyle.overflow = "hidden";
|
146
|
+
document.body.appendChild(this.div);
|
147
|
+
_VirtualJoystick.JOYSTICK_DIV = this.div;
|
148
|
+
}
|
149
|
+
this.setupBaseAndControl();
|
150
|
+
this.bindEvents();
|
151
|
+
}
|
152
|
+
setupBaseAndControl() {
|
153
|
+
this.base = document.createElement("span");
|
154
|
+
let divStyle = this.base.style;
|
155
|
+
divStyle.width = `${this.radius * 2}px`;
|
156
|
+
divStyle.height = `${this.radius * 2}px`;
|
157
|
+
divStyle.position = "absolute";
|
158
|
+
divStyle.left = `${this.width / 2 - this.radius}px`;
|
159
|
+
divStyle.bottom = `${this.height / 2 - this.radius}px`;
|
160
|
+
divStyle.borderRadius = "50%";
|
161
|
+
divStyle.borderColor = "rgba(200,200,200,0.5)";
|
162
|
+
divStyle.borderWidth = "2px";
|
163
|
+
divStyle.borderStyle = "solid";
|
164
|
+
this.div.appendChild(this.base);
|
165
|
+
this.control = document.createElement("span");
|
166
|
+
divStyle = this.control.style;
|
167
|
+
divStyle.width = `${this.inner_radius * 2}px`;
|
168
|
+
divStyle.height = `${this.inner_radius * 2}px`;
|
169
|
+
divStyle.position = "absolute";
|
170
|
+
divStyle.left = `${this.width / 2 - this.inner_radius}px`;
|
171
|
+
divStyle.bottom = `${this.height / 2 - this.inner_radius}px`;
|
172
|
+
divStyle.borderRadius = "50%";
|
173
|
+
divStyle.backgroundColor = "rgba(200,200,200,0.3)";
|
174
|
+
divStyle.borderWidth = "1px";
|
175
|
+
divStyle.borderColor = "rgba(200,200,200,0.8)";
|
176
|
+
divStyle.borderStyle = "solid";
|
177
|
+
this.div.appendChild(this.control);
|
178
|
+
}
|
179
|
+
bindEvents() {
|
180
|
+
this.div.addEventListener("touchstart", this.handleTouchStart.bind(this), false);
|
181
|
+
this.div.addEventListener("touchmove", this.handleTouchMove.bind(this), false);
|
182
|
+
this.div.addEventListener("touchend", this.clearFlags.bind(this), false);
|
183
|
+
if (this.mouse_support) {
|
184
|
+
this.div.addEventListener("mousedown", this.handleMouseDown.bind(this));
|
185
|
+
this.div.addEventListener("mousemove", this.handleMouseMove.bind(this));
|
186
|
+
this.div.addEventListener("mouseup", this.handleMouseUp.bind(this));
|
187
|
+
}
|
188
|
+
}
|
189
|
+
handleTouchStart(evt) {
|
190
|
+
evt.preventDefault();
|
191
|
+
if (evt.touches) {
|
192
|
+
const touch = evt.touches[0];
|
193
|
+
this.updateControlAndDirection(touch);
|
194
|
+
}
|
195
|
+
}
|
196
|
+
handleTouchMove(evt) {
|
197
|
+
evt.preventDefault();
|
198
|
+
if (evt.touches.length > 0) {
|
199
|
+
const touch = evt.touches[0];
|
200
|
+
this.updateControlAndDirection(touch);
|
201
|
+
}
|
202
|
+
}
|
203
|
+
handleMouseDown(evt) {
|
204
|
+
evt.preventDefault();
|
205
|
+
this.updateControlAndDirection(evt);
|
206
|
+
}
|
207
|
+
handleMouseMove(evt) {
|
208
|
+
if (evt.buttons === 1) {
|
209
|
+
evt.preventDefault();
|
210
|
+
this.updateControlAndDirection(evt);
|
211
|
+
}
|
212
|
+
}
|
213
|
+
handleMouseUp(evt) {
|
214
|
+
this.clearFlags();
|
215
|
+
}
|
216
|
+
updateControlAndDirection(input) {
|
217
|
+
const rect = this.div.getBoundingClientRect();
|
218
|
+
const dx = input.clientX - (rect.left + this.div.offsetWidth / 2);
|
219
|
+
const dy = input.clientY - (rect.top + this.div.offsetHeight / 2);
|
220
|
+
const distance = Math.min(Math.sqrt(dx * dx + dy * dy), this.radius);
|
221
|
+
const angle = Math.atan2(dy, dx);
|
222
|
+
const constrainedX = distance * Math.cos(angle);
|
223
|
+
const constrainedY = distance * Math.sin(angle);
|
224
|
+
this.control.style.left = `${constrainedX + this.width / 2 - this.inner_radius}px`;
|
225
|
+
this.control.style.top = `${constrainedY + this.height / 2 - this.inner_radius}px`;
|
226
|
+
this.up = this.isUp(dx, dy);
|
227
|
+
this.down = this.isDown(dx, dy);
|
228
|
+
this.left = this.isLeft(dx, dy);
|
229
|
+
this.right = this.isRight(dx, dy);
|
230
|
+
this.hasDirection = this.up || this.down || this.left || this.right;
|
231
|
+
}
|
232
|
+
isUp(dx, dy) {
|
233
|
+
return dy < 0 && Math.abs(dx) <= 2 * Math.abs(dy);
|
234
|
+
}
|
235
|
+
isDown(dx, dy) {
|
236
|
+
return dy > 0 && Math.abs(dx) <= 2 * Math.abs(dy);
|
237
|
+
}
|
238
|
+
isLeft(dx, dy) {
|
239
|
+
return dx < 0 && Math.abs(dy) <= 2 * Math.abs(dx);
|
240
|
+
}
|
241
|
+
isRight(dx, dy) {
|
242
|
+
return dx > 0 && Math.abs(dy) <= 2 * Math.abs(dx);
|
243
|
+
}
|
244
|
+
};
|
245
|
+
_VirtualJoystick.JOYSTICK_DIV = null;
|
246
|
+
var VirtualJoystick = _VirtualJoystick;
|
247
|
+
|
85
248
|
// src/tweakpane/tweakPaneActivity.ts
|
86
249
|
var isTweakpaneActive = false;
|
87
250
|
function setTweakpaneActive(status) {
|
@@ -119,6 +282,9 @@ var CameraManager = class {
|
|
119
282
|
this.lerpTarget = new Vector32();
|
120
283
|
this.lerpFactor = 0;
|
121
284
|
this.lerpDuration = 2.1;
|
285
|
+
this.hasTouchControl = false;
|
286
|
+
this.lastTouchX = 0;
|
287
|
+
this.lastTouchY = 0;
|
122
288
|
this.phi = initialPhi;
|
123
289
|
this.targetPhi = initialPhi;
|
124
290
|
this.theta = initialTheta;
|
@@ -126,12 +292,61 @@ var CameraManager = class {
|
|
126
292
|
this.camera = new PerspectiveCamera(this.fov, window.innerWidth / window.innerHeight, 0.1, 400);
|
127
293
|
this.camera.position.set(0, 1.4, -this.initialDistance);
|
128
294
|
this.rayCaster = new Raycaster();
|
295
|
+
this.hasTouchControl = VirtualJoystick.checkForTouch();
|
129
296
|
this.eventHandlerCollection = EventHandlerCollection.create([
|
130
297
|
[targetElement, "mousedown", this.onMouseDown.bind(this)],
|
131
298
|
[document, "mouseup", this.onMouseUp.bind(this)],
|
132
299
|
[document, "mousemove", this.onMouseMove.bind(this)],
|
133
300
|
[targetElement, "wheel", this.onMouseWheel.bind(this)]
|
134
301
|
]);
|
302
|
+
if (this.hasTouchControl) {
|
303
|
+
this.eventHandlerCollection.add(targetElement, "touchstart", this.onTouchStart.bind(this), {
|
304
|
+
passive: false
|
305
|
+
});
|
306
|
+
this.eventHandlerCollection.add(document, "touchmove", this.onTouchMove.bind(this), {
|
307
|
+
passive: false
|
308
|
+
});
|
309
|
+
this.eventHandlerCollection.add(document, "touchend", this.onTouchEnd.bind(this), {
|
310
|
+
passive: false
|
311
|
+
});
|
312
|
+
}
|
313
|
+
}
|
314
|
+
onTouchStart(evt) {
|
315
|
+
Array.from(evt.touches).forEach((touch) => {
|
316
|
+
if (!VirtualJoystick.isTouchOnJoystick(touch)) {
|
317
|
+
this.dragging = true;
|
318
|
+
this.lastTouchX = touch.clientX;
|
319
|
+
this.lastTouchY = touch.clientY;
|
320
|
+
}
|
321
|
+
});
|
322
|
+
}
|
323
|
+
onTouchMove(evt) {
|
324
|
+
if (!this.dragging || getTweakpaneActive()) {
|
325
|
+
return;
|
326
|
+
}
|
327
|
+
evt.preventDefault();
|
328
|
+
const touch = Array.from(evt.touches).find((t) => !VirtualJoystick.isTouchOnJoystick(t));
|
329
|
+
if (touch) {
|
330
|
+
const dx = touch.clientX - this.lastTouchX;
|
331
|
+
const dy = touch.clientY - this.lastTouchY;
|
332
|
+
this.lastTouchX = touch.clientX;
|
333
|
+
this.lastTouchY = touch.clientY;
|
334
|
+
if (this.targetTheta !== null && this.targetPhi !== null) {
|
335
|
+
this.targetTheta += dx * 0.01;
|
336
|
+
this.targetPhi -= dy * 0.01;
|
337
|
+
this.targetPhi = Math.max(this.minPolarAngle, Math.min(this.maxPolarAngle, this.targetPhi));
|
338
|
+
}
|
339
|
+
}
|
340
|
+
}
|
341
|
+
onTouchEnd(evt) {
|
342
|
+
if (this.dragging) {
|
343
|
+
const touchEnded = Array.from(evt.changedTouches).some(
|
344
|
+
(t) => !VirtualJoystick.isTouchOnJoystick(t)
|
345
|
+
);
|
346
|
+
if (touchEnded) {
|
347
|
+
this.dragging = false;
|
348
|
+
}
|
349
|
+
}
|
135
350
|
}
|
136
351
|
onMouseDown() {
|
137
352
|
this.dragging = true;
|
@@ -1795,9 +2010,17 @@ var KeyInputManager = class {
|
|
1795
2010
|
this.shouldCaptureKeyPress = shouldCaptureKeyPress;
|
1796
2011
|
this.keys = /* @__PURE__ */ new Map();
|
1797
2012
|
this.eventHandlerCollection = new EventHandlerCollection();
|
2013
|
+
this.directionJoystick = null;
|
1798
2014
|
this.eventHandlerCollection.add(document, "keydown", this.onKeyDown.bind(this));
|
1799
2015
|
this.eventHandlerCollection.add(document, "keyup", this.onKeyUp.bind(this));
|
1800
2016
|
this.eventHandlerCollection.add(window, "blur", this.handleUnfocus.bind(this));
|
2017
|
+
this.directionJoystick = new VirtualJoystick({
|
2018
|
+
radius: 70,
|
2019
|
+
inner_radius: 20,
|
2020
|
+
x: 70,
|
2021
|
+
y: 0,
|
2022
|
+
mouse_support: false
|
2023
|
+
});
|
1801
2024
|
}
|
1802
2025
|
handleUnfocus(_event) {
|
1803
2026
|
this.keys.clear();
|
@@ -1821,19 +2044,19 @@ var KeyInputManager = class {
|
|
1821
2044
|
return this.keys.get(key) || false;
|
1822
2045
|
}
|
1823
2046
|
isMovementKeyPressed() {
|
1824
|
-
return ["w" /* W */, "a" /* A */, "s" /* S */, "d" /* D */].some((key) => this.isKeyPressed(key));
|
2047
|
+
return ["w" /* W */, "a" /* A */, "s" /* S */, "d" /* D */].some((key) => this.isKeyPressed(key)) || this.directionJoystick.hasDirection;
|
1825
2048
|
}
|
1826
2049
|
get forward() {
|
1827
|
-
return this.isKeyPressed("w" /* W */);
|
2050
|
+
return this.isKeyPressed("w" /* W */) || this.directionJoystick.up;
|
1828
2051
|
}
|
1829
2052
|
get backward() {
|
1830
|
-
return this.isKeyPressed("s" /* S */);
|
2053
|
+
return this.isKeyPressed("s" /* S */) || this.directionJoystick.down;
|
1831
2054
|
}
|
1832
2055
|
get left() {
|
1833
|
-
return this.isKeyPressed("a" /* A */);
|
2056
|
+
return this.isKeyPressed("a" /* A */) || this.directionJoystick.left;
|
1834
2057
|
}
|
1835
2058
|
get right() {
|
1836
|
-
return this.isKeyPressed("d" /* D */);
|
2059
|
+
return this.isKeyPressed("d" /* D */) || this.directionJoystick.right;
|
1837
2060
|
}
|
1838
2061
|
get run() {
|
1839
2062
|
return this.isKeyPressed("shift" /* SHIFT */);
|