Migrate from legacy config to new AppConfig singleton system
Remove dual config system and migrate all code to use appConfigInstance. **Phase 1: Update VR Controller Code** - snapAll.ts: Replace getAppConfig() with appConfigInstance.current - Use `rotateSnap > 0` instead of rotationSnapEnabled flag - Use `locationSnap > 0` instead of locationSnapEnabled flag - Remove parseFloat() calls (values already numbers) - groundMeshObserver.ts: Direct property replacement - flyModeEnabled → flyMode - snapTurnSnap → turnSnap (remove parseFloat) - customPhysics.ts: Add enabled checks and update - Add `> 0` checks (was applying unconditionally) - Use locationSnap and rotateSnap directly **Phase 2: Remove Legacy Config Bridge** - vrConfigPanel.ts: Remove syncLegacyConfig() method and all calls - configModal.tsx: Remove legacy localStorage 'config' writes **Phase 3: Cleanup** - appConfig.ts: Remove legacy code (ConfigType, getAppConfig(), setAppConfig()) - Remove unused log import **Benefits:** - Eliminates dual config system confusion - Fixes precision error from string "0" values - Single source of truth via appConfigInstance - Reactive updates via Observable pattern - Cleaner, simpler codebase 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
3cf3d996dc
commit
c66da87401
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "immersive",
|
||||
"private": true,
|
||||
"version": "0.0.8-28",
|
||||
"version": "0.0.8-30",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
|
||||
@ -1,23 +1,23 @@
|
||||
import {TransformNode, Vector3} from "@babylonjs/core";
|
||||
import {getAppConfig} from "../../util/appConfig";
|
||||
import {appConfigInstance} from "../../util/appConfig";
|
||||
import {snapRotateVal} from "../../util/functions/snapRotateVal";
|
||||
import {snapGridVal} from "../../util/functions/snapGridVal";
|
||||
|
||||
export function snapAll(node: TransformNode, pickPoint: Vector3) {
|
||||
const config = getAppConfig();
|
||||
const config = appConfigInstance.current;
|
||||
const transform = new TransformNode('temp', node.getScene());
|
||||
transform.position = pickPoint;
|
||||
node.setParent(transform);
|
||||
if (config.rotationSnapEnabled) {
|
||||
node.rotation = snapRotateVal(node.absoluteRotationQuaternion.toEulerAngles(), parseFloat(config.rotationSnap));
|
||||
if (config.rotateSnap > 0) {
|
||||
node.rotation = snapRotateVal(node.absoluteRotationQuaternion.toEulerAngles(), config.rotateSnap);
|
||||
}
|
||||
if (config.locationSnapEnabled) {
|
||||
transform.position = snapGridVal(transform.absolutePosition, parseFloat(config.locationSnap));
|
||||
if (config.locationSnap > 0) {
|
||||
transform.position = snapGridVal(transform.absolutePosition, config.locationSnap);
|
||||
}
|
||||
|
||||
node.setParent(null);
|
||||
if (config.locationSnapEnabled) {
|
||||
node.position = snapGridVal(node.absolutePosition, parseFloat(config.locationSnap));
|
||||
if (config.locationSnap > 0) {
|
||||
node.position = snapGridVal(node.absolutePosition, config.locationSnap);
|
||||
}
|
||||
|
||||
transform.dispose();
|
||||
|
||||
@ -335,12 +335,10 @@ export class VRConfigPanel {
|
||||
const lastValue = appConfigInstance.current.locationSnap || 0.1;
|
||||
appConfigInstance.setGridSnap(lastValue > 0 ? lastValue : 0.1);
|
||||
this.updateLocationSnapButtonStates(lastValue);
|
||||
this.syncLegacyConfig();
|
||||
} else {
|
||||
// Disable by setting to 0
|
||||
appConfigInstance.setGridSnap(0);
|
||||
this.updateLocationSnapButtonStates(0);
|
||||
this.syncLegacyConfig();
|
||||
}
|
||||
});
|
||||
|
||||
@ -388,7 +386,6 @@ export class VRConfigPanel {
|
||||
if (this._locationSnapEnabled) {
|
||||
appConfigInstance.setGridSnap(snap.value);
|
||||
this.updateLocationSnapButtonStates(snap.value);
|
||||
this.syncLegacyConfig();
|
||||
}
|
||||
});
|
||||
|
||||
@ -457,12 +454,10 @@ export class VRConfigPanel {
|
||||
const lastValue = appConfigInstance.current.rotateSnap || 90;
|
||||
appConfigInstance.setRotateSnap(lastValue > 0 ? lastValue : 90);
|
||||
this.updateRotationSnapButtonStates(lastValue);
|
||||
this.syncLegacyConfig();
|
||||
} else {
|
||||
// Disable by setting to 0
|
||||
appConfigInstance.setRotateSnap(0);
|
||||
this.updateRotationSnapButtonStates(0);
|
||||
this.syncLegacyConfig();
|
||||
}
|
||||
});
|
||||
|
||||
@ -510,7 +505,6 @@ export class VRConfigPanel {
|
||||
if (this._rotationSnapEnabled) {
|
||||
appConfigInstance.setRotateSnap(snap.value);
|
||||
this.updateRotationSnapButtonStates(snap.value);
|
||||
this.syncLegacyConfig();
|
||||
}
|
||||
});
|
||||
|
||||
@ -586,26 +580,4 @@ export class VRConfigPanel {
|
||||
// - Snap turn UI update
|
||||
// - Label rendering mode UI update
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync changes to legacy config for backward compatibility
|
||||
* Legacy config is used by snapAll.ts and other older code
|
||||
*/
|
||||
private syncLegacyConfig(): void {
|
||||
const config = appConfigInstance.current;
|
||||
|
||||
const legacyConfig = {
|
||||
locationSnap: config.locationSnap.toString(),
|
||||
locationSnapEnabled: config.locationSnap > 0,
|
||||
rotationSnap: config.rotateSnap.toString(),
|
||||
rotationSnapEnabled: config.rotateSnap > 0,
|
||||
snapTurnSnap: config.turnSnap.toString(),
|
||||
snapTurnSnapEnabled: config.turnSnap > 0,
|
||||
flyModeEnabled: config.flyMode,
|
||||
labelRenderingMode: config.labelRenderingMode
|
||||
};
|
||||
|
||||
localStorage.setItem('config', JSON.stringify(legacyConfig));
|
||||
this._logger.debug('Synced legacy config', legacyConfig);
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,20 +59,6 @@ export default function ConfigModal({configOpened, closeConfig}) {
|
||||
appConfigInstance.setGridSnap(parseFloat(locationSnap));
|
||||
appConfigInstance.setRotateSnap(parseFloat(rotationSnap));
|
||||
appConfigInstance.setTurnSnap(parseFloat(snapTurnSnap));
|
||||
|
||||
// Also update legacy config for backward compatibility
|
||||
const legacyConfig = {
|
||||
locationSnap: locationSnap,
|
||||
locationSnapEnabled: locationSnapEnabled,
|
||||
rotationSnap: rotationSnap,
|
||||
rotationSnapEnabled: rotationSnapEnabled,
|
||||
snapTurnSnap: snapTurnSnap,
|
||||
snapTurnSnapEnabled: snapTurnSnapEnabled,
|
||||
flyModeEnabled: flyModeEnabled,
|
||||
labelRenderingMode: labelRenderingMode
|
||||
};
|
||||
localStorage.setItem('config', JSON.stringify(legacyConfig));
|
||||
|
||||
}, [locationSnap, locationSnapEnabled, rotationSnap, rotationSnapEnabled, snapTurnSnap, snapTurnSnapEnabled, flyModeEnabled, labelRenderingMode]);
|
||||
return (
|
||||
<Modal onClose={closeConfig} opened={configOpened}>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import {Observable} from "@babylonjs/core";
|
||||
import {AppConfigType, LabelRenderingMode} from "./appConfigType";
|
||||
import log from "loglevel";
|
||||
|
||||
export class AppConfig {
|
||||
public readonly onConfigChangedObservable = new Observable<AppConfigType>();
|
||||
private _currentConfig: AppConfigType;
|
||||
@ -88,42 +88,4 @@ export class AppConfig {
|
||||
|
||||
// Singleton instance for app-wide configuration
|
||||
// Use this instead of creating new AppConfig() instances
|
||||
export const appConfigInstance = new AppConfig();
|
||||
|
||||
let defaultConfig: ConfigType =
|
||||
{
|
||||
locationSnap: '.1',
|
||||
locationSnapEnabled: true,
|
||||
rotationSnap: '90',
|
||||
rotationSnapEnabled: true,
|
||||
flyModeEnabled: true,
|
||||
snapTurnSnap: '45',
|
||||
snapTurnSnapEnabled: false
|
||||
}
|
||||
try {
|
||||
const newConfig = JSON.parse(localStorage.getItem('config'));
|
||||
defaultConfig = {...defaultConfig, ...newConfig};
|
||||
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
|
||||
export type ConfigType = {
|
||||
locationSnap: string,
|
||||
locationSnapEnabled: boolean,
|
||||
rotationSnap: string,
|
||||
rotationSnapEnabled: boolean,
|
||||
flyModeEnabled: boolean,
|
||||
snapTurnSnap: string,
|
||||
snapTurnSnapEnabled: boolean
|
||||
}
|
||||
|
||||
export function getAppConfig(): ConfigType {
|
||||
return defaultConfig;
|
||||
}
|
||||
|
||||
export function setAppConfig(config: ConfigType) {
|
||||
const logger = log.getLogger('setAppConfig');
|
||||
logger.debug('setting config', JSON.stringify(config));
|
||||
localStorage.setItem('config', JSON.stringify(config));
|
||||
}
|
||||
export const appConfigInstance = new AppConfig();
|
||||
@ -3,7 +3,7 @@ import HavokPhysics from "@babylonjs/havok";
|
||||
import {snapGridVal} from "./functions/snapGridVal";
|
||||
import {snapRotateVal} from "./functions/snapRotateVal";
|
||||
import {isDiagramEntity} from "../diagram/functions/isDiagramEntity";
|
||||
import {getAppConfig} from "./appConfig";
|
||||
import {appConfigInstance} from "./appConfig";
|
||||
|
||||
export class CustomPhysics {
|
||||
private readonly scene: Scene;
|
||||
@ -21,6 +21,7 @@ export class CustomPhysics {
|
||||
|
||||
scene.collisionsEnabled = true;
|
||||
scene.onAfterPhysicsObservable.add(() => {
|
||||
const config = appConfigInstance.current;
|
||||
scene.meshes.forEach((mesh) => {
|
||||
if (isDiagramEntity(mesh) && mesh.physicsBody) {
|
||||
const body = mesh.physicsBody;
|
||||
@ -29,18 +30,26 @@ export class CustomPhysics {
|
||||
if (linearVelocity.length() < .1) {
|
||||
|
||||
body.disablePreStep = false;
|
||||
const pos: Vector3 = body.getObjectCenterWorld();
|
||||
const val: Vector3 = snapGridVal(pos,
|
||||
parseFloat(getAppConfig().locationSnap));
|
||||
body.transformNode.position.set(val.x, val.y, val.z);
|
||||
const rot: Quaternion =
|
||||
Quaternion.FromEulerVector(
|
||||
snapRotateVal(body.transformNode.rotationQuaternion.toEulerAngles(),
|
||||
parseFloat(getAppConfig().rotationSnap)))
|
||||
|
||||
body.transformNode.rotationQuaternion.set(
|
||||
rot.x, rot.y, rot.z, rot.w
|
||||
);
|
||||
// Apply location snap if enabled
|
||||
if (config.locationSnap > 0) {
|
||||
const pos: Vector3 = body.getObjectCenterWorld();
|
||||
const val: Vector3 = snapGridVal(pos, config.locationSnap);
|
||||
body.transformNode.position.set(val.x, val.y, val.z);
|
||||
}
|
||||
|
||||
// Apply rotation snap if enabled
|
||||
if (config.rotateSnap > 0) {
|
||||
const rot: Quaternion =
|
||||
Quaternion.FromEulerVector(
|
||||
snapRotateVal(body.transformNode.rotationQuaternion.toEulerAngles(),
|
||||
config.rotateSnap));
|
||||
|
||||
body.transformNode.rotationQuaternion.set(
|
||||
rot.x, rot.y, rot.z, rot.w
|
||||
);
|
||||
}
|
||||
|
||||
scene.onAfterRenderObservable.addOnce(() => {
|
||||
body.disablePreStep = true;
|
||||
});
|
||||
|
||||
@ -4,7 +4,7 @@ import {WebController} from "../../controllers/webController";
|
||||
import {Rigplatform} from "../../controllers/rigplatform";
|
||||
import {DiagramManager} from "../../diagram/diagramManager";
|
||||
import {Spinner} from "../../objects/spinner";
|
||||
import {getAppConfig} from "../appConfig";
|
||||
import {appConfigInstance} from "../appConfig";
|
||||
import {Scene} from "@babylonjs/core";
|
||||
|
||||
|
||||
@ -114,9 +114,9 @@ export async function groundMeshObserver(ground: AbstractMesh,
|
||||
});
|
||||
|
||||
const rig = new Rigplatform(xr, diagramManager);
|
||||
const config = getAppConfig();
|
||||
rig.flyMode = config.flyModeEnabled;
|
||||
rig.turnSnap = parseFloat(config.snapTurnSnap);
|
||||
const config = appConfigInstance.current;
|
||||
rig.flyMode = config.flyMode;
|
||||
rig.turnSnap = config.turnSnap;
|
||||
const webController = new WebController(ground.getScene(), rig, diagramManager);
|
||||
|
||||
// Set XR on diagram manager so toolbox can create exit button
|
||||
|
||||
Loading…
Reference in New Issue
Block a user