AppConfig Persistence Fixes: - Fix constructor to properly handle null localStorage values - Add null check before JSON.parse to prevent errors - Create fresh config copies with spread operator to avoid reference issues - Add better error handling and logging for config loading - Initialize handles array properly React ConfigModal Improvements: - Fix config initialization to get fresh values on render instead of stale module-level values - Separate useEffect hooks for each config property (prevents unnecessary updates) - Fix SegmentedControl string-to-number conversion (locationSnaps now use "0.01", "0.1" format) - Enable/disable logic now properly sets values to 0 when disabled Handle Storage Consolidation: - Create dynamic HandleConfig type with Vec3 for serializable position/rotation/scale - Add handles array to AppConfigType for flexible handle storage - Replace individual localStorage keys with centralized AppConfig storage - Add handle management methods: getHandleConfig, setHandleConfig, removeHandleConfig, getAllHandleConfigs - Update Handle class to read from AppConfig instead of direct localStorage - Update dropMesh to save handles via AppConfig using Vec3 serialization - Convert between BabylonJS Vector3 and serializable Vec3 at conversion points Benefits: - Single source of truth for all configuration - Proper localStorage persistence across page reloads - Dynamic handle creation without code changes - Type-safe configuration with proper JSON serialization - Consolidated storage (one appConfig key instead of multiple handle-* keys) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
85 lines
3.4 KiB
TypeScript
85 lines
3.4 KiB
TypeScript
import {AbstractMesh, Vector3} from "@babylonjs/core";
|
|
import {DiagramManager} from "../diagramManager";
|
|
import {DiagramObject} from "../diagramObject";
|
|
import {MeshTypeEnum} from "../types/meshTypeEnum";
|
|
import {snapAll} from "../../controllers/functions/snapAll";
|
|
import {DiagramEvent, DiagramEventType} from "../types/diagramEntity";
|
|
import {DiagramEventObserverMask} from "../types/diagramEventObserverMask";
|
|
import {DefaultScene} from "../../defaultScene";
|
|
import {appConfigInstance} from "../../util/appConfig";
|
|
import {HandleConfig, Vec3} from "../../util/appConfigType";
|
|
|
|
export function dropMesh(mesh: AbstractMesh,
|
|
grabbedObject: DiagramObject,
|
|
pickPoint: Vector3,
|
|
grabbedMeshType: MeshTypeEnum,
|
|
diagramManager: DiagramManager): boolean {
|
|
if (!mesh) {
|
|
return false;
|
|
}
|
|
let dropped = false;
|
|
const diagramObject = grabbedObject;
|
|
switch (grabbedMeshType) {
|
|
case MeshTypeEnum.ENTITY:
|
|
if (diagramObject) {
|
|
diagramObject.baseTransform.setParent(null);
|
|
snapAll(grabbedObject.baseTransform, pickPoint);
|
|
diagramObject.mesh.computeWorldMatrix(true);
|
|
const event: DiagramEvent =
|
|
{
|
|
type: DiagramEventType.DROP,
|
|
entity: diagramObject.diagramEntity
|
|
}
|
|
diagramManager.onDiagramEventObservable.notifyObservers(event, DiagramEventObserverMask.ALL);
|
|
diagramObject.mesh.computeWorldMatrix(false);
|
|
diagramObject.grabbed = false;
|
|
dropped = true;
|
|
}
|
|
break;
|
|
case MeshTypeEnum.TOOL:
|
|
grabbedObject.baseTransform.setParent(null);
|
|
snapAll(grabbedObject.baseTransform, pickPoint);
|
|
diagramObject.mesh.computeWorldMatrix(true);
|
|
const event: DiagramEvent =
|
|
{
|
|
type: DiagramEventType.DROP,
|
|
entity: diagramObject.diagramEntity
|
|
}
|
|
diagramManager.onDiagramEventObservable.notifyObservers(event, DiagramEventObserverMask.ALL);
|
|
diagramObject.mesh.computeWorldMatrix(false);
|
|
grabbedObject.grabbed = false;
|
|
dropped = true;
|
|
break;
|
|
case MeshTypeEnum.HANDLE:
|
|
mesh.setParent(DefaultScene.Scene.getMeshByName("platform"));
|
|
|
|
// Get existing handle config or create new one
|
|
const existingConfig = appConfigInstance.getHandleConfig(mesh.id);
|
|
|
|
// Convert Vector3 to Vec3 for serialization
|
|
const position: Vec3 = {
|
|
x: mesh.position.x,
|
|
y: mesh.position.y,
|
|
z: mesh.position.z
|
|
};
|
|
const rotation: Vec3 = {
|
|
x: mesh.rotation.x,
|
|
y: mesh.rotation.y,
|
|
z: mesh.rotation.z
|
|
};
|
|
|
|
const handleConfig: HandleConfig = {
|
|
id: mesh.id,
|
|
label: existingConfig?.label || mesh.id, // Preserve label if exists
|
|
position: position,
|
|
rotation: rotation,
|
|
scale: existingConfig?.scale // Preserve scale if exists
|
|
};
|
|
|
|
// Save to AppConfig (which persists to localStorage)
|
|
appConfigInstance.setHandleConfig(handleConfig);
|
|
dropped = true;
|
|
break;
|
|
}
|
|
return dropped;
|
|
} |