ui/scene: lift state signals to allow external access

This commit is contained in:
Johannes Kirschbauer
2025-08-28 22:39:23 +02:00
parent 9275b66bd9
commit 8877f2d451

View File

@@ -38,10 +38,38 @@ function garbageCollectGroup(group: THREE.Group) {
group.clear(); // Clear the group group.clear(); // Clear the group
} }
// Can be imported by others via wrappers below
// Global signal for last clicked machine
const [lastClickedMachine, setLastClickedMachine] = createSignal<string | null>(
null,
);
// Exported so others could also emit the signal if needed
// And for testing purposes
export function emitMachineClick(id: string | null) {
setLastClickedMachine(id);
if (id) {
// Clear after a short delay to allow re-clicking the same machine
setTimeout(() => {
setLastClickedMachine(null);
}, 100);
}
}
/** Hook for components to subscribe */
export function useMachineClick() {
return lastClickedMachine;
}
/*Gloabl signal*/
const [worldMode, setWorldMode] = createSignal<
"default" | "select" | "service" | "create"
>("default");
export { worldMode, setWorldMode };
export function CubeScene(props: { export function CubeScene(props: {
cubesQuery: MachinesQueryResult; cubesQuery: MachinesQueryResult;
onCreate: () => Promise<{ id: string }>; onCreate: () => Promise<{ id: string }>;
onAddService: () => Promise<{ id: string }>;
selectedIds: Accessor<Set<string>>; selectedIds: Accessor<Set<string>>;
onSelect: (v: Set<string>) => void; onSelect: (v: Set<string>) => void;
sceneStore: Accessor<SceneData>; sceneStore: Accessor<SceneData>;
@@ -74,8 +102,6 @@ export function CubeScene(props: {
"grid", "grid",
); );
const [worldMode, setWorldMode] = createSignal<"view" | "create">("view");
const [cursorPosition, setCursorPosition] = createSignal<[number, number]>(); const [cursorPosition, setCursorPosition] = createSignal<[number, number]>();
const [cameraInfo, setCameraInfo] = createSignal({ const [cameraInfo, setCameraInfo] = createSignal({
@@ -222,6 +248,7 @@ export function CubeScene(props: {
controls = new MapControls(camera, renderer.domElement); controls = new MapControls(camera, renderer.domElement);
controls.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled controls.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled
controls.mouseButtons.RIGHT = null; controls.mouseButtons.RIGHT = null;
// controls.rotateSpeed = -0.8;
// controls.enableRotate = false; // controls.enableRotate = false;
controls.minZoom = 1.2; controls.minZoom = 1.2;
controls.maxZoom = 3.5; controls.maxZoom = 3.5;
@@ -370,7 +397,7 @@ export function CubeScene(props: {
); );
// Click handler: // Click handler:
// - Select/deselects a cube in "view" mode // - Select/deselects a cube in mode
// - Creates a new cube in "create" mode // - Creates a new cube in "create" mode
const onClick = (event: MouseEvent) => { const onClick = (event: MouseEvent) => {
if (worldMode() === "create") { if (worldMode() === "create") {
@@ -391,7 +418,7 @@ export function CubeScene(props: {
.finally(() => { .finally(() => {
if (initBase) initBase.visible = false; if (initBase) initBase.visible = false;
setWorldMode("view"); setWorldMode("default");
}); });
} }
@@ -409,8 +436,13 @@ export function CubeScene(props: {
if (intersects.length > 0) { if (intersects.length > 0) {
console.log("Clicked on cube:", intersects); console.log("Clicked on cube:", intersects);
const id = intersects[0].object.userData.id; const id = intersects[0].object.userData.id;
toggleSelection(id);
if (worldMode() === "select") toggleSelection(id);
emitMachineClick(id); // notify subscribers
} else { } else {
emitMachineClick(null);
props.onSelect(new Set<string>()); // Clear selection if clicked outside cubes props.onSelect(new Set<string>()); // Clear selection if clicked outside cubes
} }
}; };
@@ -560,14 +592,15 @@ export function CubeScene(props: {
description="Select machine" description="Select machine"
name="Select" name="Select"
icon="Cursor" icon="Cursor"
onClick={() => setWorldMode("view")} onClick={() =>
selected={worldMode() === "view"} setWorldMode((v) => (v === "select" ? "default" : "select"))
}
selected={worldMode() === "select"}
/> />
<ToolbarButton <ToolbarButton
description="Create new machine" description="Create new machine"
name="new-machine" name="new-machine"
icon="NewMachine" icon="NewMachine"
disabled={positionMode() === "circle"}
onClick={onAddClick} onClick={onAddClick}
selected={worldMode() === "create"} selected={worldMode() === "create"}
/> />
@@ -576,7 +609,10 @@ export function CubeScene(props: {
description="Add new Service" description="Add new Service"
name="modules" name="modules"
icon="Services" icon="Services"
onClick={props.onAddService} selected={worldMode() === "service"}
onClick={() => {
setWorldMode((v) => (v === "service" ? "default" : "service"));
}}
/> />
<ToolbarButton <ToolbarButton
icon="Reload" icon="Reload"