Fix Fly Mode and Snap Turn not applying at runtime in VR

Add Observable subscription to Rigplatform so Fly Mode and Snap Turn
settings take effect immediately when changed in the VR config panel,
instead of only applying after exiting and re-entering XR.

Changes to src/controllers/rigplatform.ts:
- Import Observer, appConfigInstance, and AppConfigType
- Add _configObserver property to track subscription
- Add _subscribeToConfigChanges() method in constructor
- Subscribe to onConfigChangedObservable to update flyMode and turnSnap
- Add dispose() method to clean up observer and controllers
- Log config changes for debugging

Changes to src/menus/vrConfigPanel.ts:
- Remove unused index parameter in forEach loop

Root cause: Settings were only applied once at Rigplatform initialization
in groundMeshObserver.ts. Config changes during VR session were saving to
localStorage but not updating the running Rigplatform instance.

Result: Fly Mode and Snap Turn now update in real-time when changed in VR.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Michael Mainguy 2025-11-18 15:27:08 -06:00
parent 5091ca0bab
commit 0e318e7cc7
2 changed files with 46 additions and 2 deletions

View File

@ -1,4 +1,4 @@
import {Angle, Mesh, Quaternion, Scene, Vector3, WebXRDefaultExperience} from "@babylonjs/core"; import {Angle, Mesh, Observer, Quaternion, Scene, Vector3, WebXRDefaultExperience} from "@babylonjs/core";
import {RightController} from "./rightController"; import {RightController} from "./rightController";
import {LeftController} from "./leftController"; import {LeftController} from "./leftController";
import log from "loglevel"; import log from "loglevel";
@ -8,6 +8,8 @@ import {DefaultScene} from "../defaultScene";
import {ControllerEvent} from "./types/controllerEvent"; import {ControllerEvent} from "./types/controllerEvent";
import {ControllerEventType} from "./types/controllerEventType"; import {ControllerEventType} from "./types/controllerEventType";
import {controllerObservable} from "./controllers"; import {controllerObservable} from "./controllers";
import {appConfigInstance} from "../util/appConfig";
import {AppConfigType} from "../util/appConfigType";
const RIGHT = "right"; const RIGHT = "right";
const LEFT = "left"; const LEFT = "left";
@ -34,6 +36,7 @@ export class Rigplatform {
private _turnVelocity: number = 0; private _turnVelocity: number = 0;
private _registered = false; private _registered = false;
private _yRotation: number = 0; private _yRotation: number = 0;
private _configObserver: Observer<AppConfigType>;
constructor( constructor(
xr: WebXRDefaultExperience, xr: WebXRDefaultExperience,
@ -49,6 +52,26 @@ export class Rigplatform {
this._fixRotation(); this._fixRotation();
this._initializeControllers(); this._initializeControllers();
this._registerVelocityObserver(); this._registerVelocityObserver();
this._subscribeToConfigChanges();
}
/**
* Subscribe to config changes to update flyMode and turnSnap at runtime
*/
private _subscribeToConfigChanges(): void {
this._configObserver = appConfigInstance.onConfigChangedObservable.add((config) => {
// Update fly mode if changed
if (config.flyMode !== this._flyMode) {
this.flyMode = config.flyMode;
this._logger.debug('Fly mode updated from config:', config.flyMode);
}
// Update turn snap if changed
if (config.turnSnap !== this.turnSnap) {
this.turnSnap = config.turnSnap;
this._logger.debug('Turn snap updated from config:', config.turnSnap);
}
});
} }
private _flyMode: boolean = true; private _flyMode: boolean = true;
@ -215,4 +238,25 @@ export class Rigplatform {
} }
}, -1, false, this, false); }, -1, false, this, false);
} }
/**
* Clean up resources and observers
*/
public dispose(): void {
// Remove config observer
if (this._configObserver) {
appConfigInstance.onConfigChangedObservable.remove(this._configObserver);
this._configObserver = null;
}
// Clean up controllers
if (this._rightController) {
this._rightController = null;
}
if (this._leftController) {
this._leftController = null;
}
this._logger.debug('Rigplatform disposed');
}
} }

View File

@ -374,7 +374,7 @@ export class VRConfigPanel {
]; ];
// Create button for each snap value // Create button for each snap value
snapValues.forEach((snap, index) => { snapValues.forEach((snap) => {
const isSelected = this._locationSnapEnabled && Math.abs(currentSnap - snap.value) < 0.001; const isSelected = this._locationSnapEnabled && Math.abs(currentSnap - snap.value) < 0.001;
const btn = Button.CreateSimpleButton(`locationSnap_${snap.value}`, snap.label); const btn = Button.CreateSimpleButton(`locationSnap_${snap.value}`, snap.label);