|
|
|
@ -214,10 +214,13 @@ export class Player { |
|
|
|
controller.add(debugSphere); |
|
|
|
|
|
|
|
const lineGeometry = new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, 0, -1)]); |
|
|
|
const line = new THREE.Line(lineGeometry); |
|
|
|
line.scale.z = 5; |
|
|
|
const lineMaterial = new THREE.LineBasicMaterial({ color: 0xff0000 }); // White color for the ray
|
|
|
|
const line = new THREE.Line(lineGeometry, lineMaterial); |
|
|
|
line.name = 'controller-ray'; // Give the line a name to find it later
|
|
|
|
line.scale.z = this.maxInteractionDistance; |
|
|
|
controller.add(line); |
|
|
|
|
|
|
|
|
|
|
|
controller.addEventListener('selectstart', () => this._OnVRSelectStart(i)); |
|
|
|
controller.addEventListener('selectend', () => this._OnVRSelectEnd(i)); |
|
|
|
controller.addEventListener('squeezestart', () => this._OnVRSqueezeStart(i)); |
|
|
|
@ -232,6 +235,7 @@ export class Player { |
|
|
|
if (this.currentIntItem && !this.attachedItem) { |
|
|
|
this.attachedItem = this.currentIntItem; |
|
|
|
this.attachedItem.isActive = true; |
|
|
|
console.log("Attaced Item to (VR) ", this.attachedItem.name); |
|
|
|
} else { |
|
|
|
this.isDrawing = true; |
|
|
|
} |
|
|
|
@ -246,9 +250,13 @@ export class Player { |
|
|
|
_OnVRSelectEnd(controllerIndex) { |
|
|
|
// Right controller
|
|
|
|
console.log(`Select End: ${controllerIndex}`); |
|
|
|
if (controllerIndex === 0) { |
|
|
|
this.isDrawing = false; |
|
|
|
if (controllerIndex === 0 && this.attachedItem) { |
|
|
|
this.attachedItem.isActive = false; |
|
|
|
this.attachedItem._removeContentDisplay(); |
|
|
|
this.attachedItem = null; |
|
|
|
console.log("Dettached item from player (VR)"); |
|
|
|
} |
|
|
|
|
|
|
|
// Left controller
|
|
|
|
if (controllerIndex === 1) { |
|
|
|
this.teleporting = false; |
|
|
|
@ -276,36 +284,36 @@ export class Player { |
|
|
|
} |
|
|
|
|
|
|
|
_handleVRJoystick() { |
|
|
|
// Get the gamepad for the left controller (index 1 in your setup)
|
|
|
|
const gamepad = this.vrGamepads[1]; |
|
|
|
|
|
|
|
// You no longer need to check this.vrControllers[1] since the gamepad is null if disconnected.
|
|
|
|
if (!gamepad) return; |
|
|
|
|
|
|
|
// The axes array for a thumbstick is often at index 2 (X) and 3 (Y) for the primary stick.
|
|
|
|
// If the left stick is the primary for movement/teleport, these are the typical indices.
|
|
|
|
// Always check for undefined or use a safe index, just in case.
|
|
|
|
const joystickVertical = gamepad.axes[3]; |
|
|
|
// --- Left Controller (Teleport Distance) ---
|
|
|
|
const leftGamepad = this.vrGamepads[1]; |
|
|
|
if (leftGamepad) { |
|
|
|
const joystickVertical = leftGamepad.axes[3]; |
|
|
|
|
|
|
|
if (joystickVertical !== undefined) { |
|
|
|
// joystickVertical is -1 (forward) to 1 (backward). We want forward to be max distance.
|
|
|
|
// We'll map the [-1, 1] range to our [min, max] distance factor range.
|
|
|
|
|
|
|
|
// 1. Convert [-1, 1] to [0, 1] (Mapping: -1 -> 1, 0 -> 0.5, 1 -> 0)
|
|
|
|
// Since Y is typically -1 forward, using (-Y + 1) / 2 makes full forward (Y=-1) equal to 1.
|
|
|
|
const normalizedValue = (-joystickVertical + 1) / 2; |
|
|
|
|
|
|
|
// 2. Linearly interpolate between min and max factors
|
|
|
|
this.teleportDistanceFactor = this.minTeleportDistanceFactor + normalizedValue * (this.maxTeleportDistanceFactor - this.minTeleportDistanceFactor); |
|
|
|
|
|
|
|
// Optional: Apply a small deadzone to prevent accidental changes when the stick is centered
|
|
|
|
const deadzone = 0.05; |
|
|
|
if (Math.abs(joystickVertical) < deadzone) { |
|
|
|
// If centered, reset to the default factor (e.g., the midpoint of your min/max range)
|
|
|
|
this.teleportDistanceFactor = (this.minTeleportDistanceFactor + this.maxTeleportDistanceFactor) / 2; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// console.log(`Normalized: ${normalizedValue.toFixed(2)}, Factor: ${this.teleportDistanceFactor.toFixed(2)}`);
|
|
|
|
// --- Right Controller (Content Interaction) ---
|
|
|
|
const rightGamepad = this.vrGamepads[0]; |
|
|
|
if (rightGamepad && this.attachedItem && this.attachedItem.content) { |
|
|
|
const joystickVertical = rightGamepad.axes[3]; // Y-axis of the thumbstick
|
|
|
|
const deadzone = 0.5; // Use a larger deadzone to prevent accidental scrolling
|
|
|
|
|
|
|
|
if (joystickVertical < -deadzone) { // Pushed Up
|
|
|
|
if (typeof this.attachedItem.content.scrollUp === 'function') { |
|
|
|
this.attachedItem.content.scrollUp(); |
|
|
|
} |
|
|
|
} else if (joystickVertical > deadzone) { // Pushed Down
|
|
|
|
if (typeof this.attachedItem.content.scrollDown === 'function') { |
|
|
|
this.attachedItem.content.scrollDown(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -453,14 +461,13 @@ export class Player { |
|
|
|
_checkForInteractableItems() { |
|
|
|
|
|
|
|
const ray = new THREE.Raycaster(); |
|
|
|
let isVR = this.vrControllers[0] && this.vrControllers[0].visible; |
|
|
|
let isVR = this.renderer.xr.isPresenting && this.vrControllers[0] && this.vrControllers[0].visible; |
|
|
|
|
|
|
|
if (isVR) { |
|
|
|
// Use right controller for interaction ray
|
|
|
|
const controller = this.vrControllers[0]; |
|
|
|
const controllerMatrix = controller.matrixWorld; |
|
|
|
ray.ray.origin.setFromMatrixPosition(controllerMatrix); |
|
|
|
ray.ray.direction.set(0, 0, -1).applyMatrix4(new THREE.Matrix4().extractRotation(controllerMatrix)); |
|
|
|
controller.getWorldPosition(ray.ray.origin); |
|
|
|
ray.ray.direction.set(0, 0, -1).applyQuaternion(controller.getWorldQuaternion(new THREE.Quaternion())); |
|
|
|
} else { |
|
|
|
// Use camera for desktop interaction ray
|
|
|
|
ray.setFromCamera({ x: 0, y: 0 }, this.camera); |
|
|
|
@ -472,6 +479,12 @@ export class Player { |
|
|
|
|
|
|
|
const intersects = ray.intersectObjects(itemObj, true); |
|
|
|
|
|
|
|
// Update ray visualization
|
|
|
|
const controllerRay = this.vrControllers[0]?.getObjectByName('controller-ray'); |
|
|
|
if (controllerRay) { |
|
|
|
controllerRay.visible = isVR; |
|
|
|
} |
|
|
|
|
|
|
|
if (intersects.length > 0) { |
|
|
|
let intersectedObject = intersects[0].object; |
|
|
|
|
|
|
|
@ -563,14 +576,15 @@ export class Player { |
|
|
|
} |
|
|
|
|
|
|
|
if (this.enableInput) { |
|
|
|
if (this.attachedItem) { |
|
|
|
if (this.attachedItem && !this.renderer.xr.isPresenting) { // Only lock camera for desktop
|
|
|
|
this._lockCameraForAttachedItem(); |
|
|
|
} else if (!this.renderer.xr.isPresenting) { // Only update movement if not in VR
|
|
|
|
this._updatePlayerMovement(delta); |
|
|
|
} |
|
|
|
this._checkForInteractableItems(); |
|
|
|
} |
|
|
|
|
|
|
|
this._checkForInteractableItems(); |
|
|
|
|
|
|
|
this.input.mouseDelta.x = 0; |
|
|
|
this.input.mouseDelta.y = 0; |
|
|
|
} |
|
|
|
|