From e88188cd6dde74591defa464013b0e84c0739c7f Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Tue, 28 Apr 2026 16:22:08 +0900 Subject: [PATCH] wip --- packages/frontend/src/pages/room.vue | 64 ++++++------------- .../frontend/src/world/room/controller.ts | 10 +-- packages/frontend/src/world/room/engine.ts | 12 ++-- packages/frontend/src/world/utility.ts | 49 -------------- 4 files changed, 25 insertions(+), 110 deletions(-) diff --git a/packages/frontend/src/pages/room.vue b/packages/frontend/src/pages/room.vue index 163b10ac74..59c06213e4 100644 --- a/packages/frontend/src/pages/room.vue +++ b/packages/frontend/src/pages/room.vue @@ -59,15 +59,9 @@ SPDX-License-Identifier: AGPL-3.0-only -
-
-
-
-
-
-
-
-
+
+
+
@@ -218,20 +212,17 @@ const resolutionRaw = prefer.model('world.resolution'); const resolutionAutoValue = computed(() => deviceKind !== 'desktop' ? 0.5 : 1); const resolution = computed(() => resolutionRaw.value ?? resolutionAutoValue.value); -const useVirtualJoystick = isTouchUsing && (deviceKind === 'smartphone' || deviceKind === 'tablet'); -//const useVirtualJoystick = true; +//const useVirtualJoystick = isTouchUsing && (deviceKind === 'smartphone' || deviceKind === 'tablet'); +const useVirtualJoystick = true; const wasdVec = { x: 0, y: 0 }; const pointerVec = { x: 0, y: 0 }; let isDashing = false; const joyStickRadiusPx = 100; -const joyStickLeftEl = useTemplateRef('joyStickLeftEl'); -const joyStickRightEl = useTemplateRef('joyStickRightEl'); -const joyStickLeftVec = ref({ x: 0, y: 0 }); -const joyStickRightVec = ref({ x: 0, y: 0 }); -const joyStickLeftStartPos = ref<{ x: number; y: number } | null>(null); -const joyStickRightStartPos = ref<{ x: number; y: number } | null>(null); +const joyStickEl = useTemplateRef('joyStickEl'); +const joyStickVec = ref({ x: 0, y: 0 }); +const joyStickStartPos = ref<{ x: number; y: number } | null>(null); const data = localStorage.getItem('roomData') != null ? JSON.parse(localStorage.getItem('roomData')!) : { heya: { @@ -322,30 +313,18 @@ onMounted(async () => { // } //}); - if (joyStickLeftEl.value != null && joyStickRightEl.value != null) { - const joyStickLeft = new Joystick(joyStickLeftEl.value!, { radiusPx: joyStickRadiusPx }); - joyStickLeft.on('start', (vector) => { - joyStickLeftStartPos.value = vector; + if (joyStickEl.value != null) { + const joyStick = new Joystick(joyStickEl.value!, { radiusPx: joyStickRadiusPx }); + joyStick.on('start', (vector) => { + joyStickStartPos.value = vector; }); - joyStickLeft.on('end', () => { - joyStickLeftStartPos.value = null; + joyStick.on('end', () => { + joyStickStartPos.value = null; }); - joyStickLeft.on('updateVector', (vector) => { - joyStickLeftVec.value = vector; + joyStick.on('updateVector', (vector) => { + joyStickVec.value = vector; controller.setCameraJoystickMoveVector(vector); }); - - const joyStickRight = new Joystick(joyStickRightEl.value!, { radiusPx: joyStickRadiusPx }); - joyStickRight.on('start', (vector) => { - joyStickRightStartPos.value = vector; - }); - joyStickRight.on('end', () => { - joyStickRightStartPos.value = null; - }); - joyStickRight.on('updateVector', (vector) => { - joyStickRightVec.value = vector; - controller.setCameraJoystickRotateVector(vector); - }); } canvas.value!.addEventListener('keydown', (ev) => { @@ -700,20 +679,15 @@ definePage(() => ({ } } -.joySticks { - display: flex; - width: 100%; -} - -.joyStickLeft, .joyStickRight { +.joyStick { position: relative; - flex: 1; + width: 50%; height: 100px; box-sizing: border-box; padding: 8px; } -.joyStickLeft::before, .joyStickRight::before { +.joyStick::before { content: ''; display: block; width: 100%; diff --git a/packages/frontend/src/world/room/controller.ts b/packages/frontend/src/world/room/controller.ts index 47708d78f9..3bb90124c9 100644 --- a/packages/frontend/src/world/room/controller.ts +++ b/packages/frontend/src/world/room/controller.ts @@ -185,6 +185,7 @@ export class RoomController { private onCanvasPointerdown(ev: PointerEvent) { this.pointerDownPosition = { x: ev.offsetX, y: ev.offsetY }; + this.canvas!.setPointerCapture(ev.pointerId); } private onCanvasPointerup(ev: PointerEvent) { @@ -201,6 +202,7 @@ export class RoomController { } } this.pointerDownPosition = null; + this.canvas!.releasePointerCapture(ev.pointerId); } public async reset(roomState?: RoomState | null, options?: RoomControllerOptions | null, canvas?: HTMLCanvasElement | null) { @@ -256,14 +258,6 @@ export class RoomController { } } - public setCameraJoystickRotateVector(vec: { x: number; y: number }) { - if (this.worker != null) { - this.worker.postMessage({ type: 'call', fn: 'cameraJoystickRotate', args: [vec] }); - } else if (this.engine != null) { - this.engine.cameraJoystickRotate(vec); - } - } - public enterEditMode() { if (this.worker != null) { this.worker.postMessage({ type: 'call', fn: 'enterEditMode' }); diff --git a/packages/frontend/src/world/room/engine.ts b/packages/frontend/src/world/room/engine.ts index f5b89e5ffa..e06c591dd0 100644 --- a/packages/frontend/src/world/room/engine.ts +++ b/packages/frontend/src/world/room/engine.ts @@ -14,7 +14,7 @@ import * as BABYLON from '@babylonjs/core'; import { registerBuiltInLoaders } from '@babylonjs/loaders/dynamic'; import { EventEmitter } from 'eventemitter3'; -import { TIME_MAP, scaleMorph, camelToKebab, cm, WORLD_SCALE, getMeshesBoundingBox, Timer, getYRotationDirection, FreeCameraVirtualJoystickInput, FreeCameraManualInput } from '../utility.js'; +import { TIME_MAP, scaleMorph, camelToKebab, cm, WORLD_SCALE, getMeshesBoundingBox, Timer, getYRotationDirection, FreeCameraManualInput } from '../utility.js'; import { getObjectDef } from './object-defs.js'; import { findMaterial, ModelManager, SYSTEM_HEYA_MESH_NAMES, SYSTEM_MESH_NAMES } from './utility.js'; import { SimpleHeyaManager } from './heya.js'; @@ -301,9 +301,9 @@ export class RoomEngine extends EventEmitter { this.camera.inputs.clear(); if (options.useVirtualJoystick) { - this.camera.inputs.add(new FreeCameraVirtualJoystickInput({ + this.camera.inputs.add(new FreeCameraManualInput({ moveSensitivity: 0.015 * WORLD_SCALE, - rotationSensitivity: 0.01, + rotationSensitivity: 0.0005, })); this.camera.inertia = 0.75; } else { @@ -612,11 +612,7 @@ export class RoomEngine extends EventEmitter { } public cameraJoystickMove(vector: { x: number; y: number; }) { - (this.camera.inputs.attached.joystick as FreeCameraVirtualJoystickInput).setJoystickMoveVector(vector); - } - - public cameraJoystickRotate(vector: { x: number; y: number; }) { - (this.camera.inputs.attached.joystick as FreeCameraVirtualJoystickInput).setJoystickRotationVector(vector); + (this.camera.inputs.attached.manual as FreeCameraManualInput).setMoveVector(vector); } public selectObject(objectId: string | null) { diff --git a/packages/frontend/src/world/utility.ts b/packages/frontend/src/world/utility.ts index 2990168f0f..45b414f531 100644 --- a/packages/frontend/src/world/utility.ts +++ b/packages/frontend/src/world/utility.ts @@ -618,55 +618,6 @@ export function getRgb(hex: string | number): [number, number, number] | null { return m.map(x => parseInt(x, 16) / 255) as [number, number, number]; } -export class FreeCameraVirtualJoystickInput implements BABYLON.ICameraInput { - public camera: BABYLON.FreeCamera; - private moveSensitivity: number; - private rotationSensitivity: number; - private moveVector = BABYLON.Vector3.Zero(); - private rotationVecX = 0; - private rotationVecY = 0; - - constructor(options: { - moveSensitivity?: number; - rotationSensitivity?: number; - }) { - this.moveSensitivity = options.moveSensitivity ?? 0.01; - this.rotationSensitivity = options.rotationSensitivity ?? 0.01; - } - - getClassName = () => this.constructor.name; - - getSimpleName = () => 'joystick'; - - attachControl(noPreventDefault) { - } - - detachControl() { - } - - public setJoystickMoveVector(vec: { x: number; y: number }) { - this.moveVector = new BABYLON.Vector3(vec.x, 0, -vec.y).scale(this.moveSensitivity); - } - - public setJoystickRotationVector(vec: { x: number; y: number }) { - let directionAdjust = 1; - if (this.camera.getScene().useRightHandedSystem) directionAdjust *= -1; - if (this.camera.parent && this.camera.parent._getWorldMatrixDeterminant() < 0) directionAdjust *= -1; - - this.rotationVecX = vec.y * this.rotationSensitivity * directionAdjust; - this.rotationVecY = vec.x * this.rotationSensitivity * directionAdjust; - } - - checkInputs() { - this.camera.cameraRotation.y += this.rotationVecY; - this.camera.cameraRotation.x += this.rotationVecX; - - this.camera.cameraDirection.addInPlace( - BABYLON.Vector3.TransformCoordinates(this.moveVector, BABYLON.Matrix.RotationY(this.camera.rotation.y)), - ); - } -} - export class FreeCameraManualInput implements BABYLON.ICameraInput { public camera: BABYLON.FreeCamera; private moveSensitivity: number;