ui/scene: clean up initBase
This commit is contained in:
@@ -71,7 +71,6 @@ export function CubeScene(props: {
|
|||||||
setMachinePos: (machineId: string, pos: [number, number]) => void;
|
setMachinePos: (machineId: string, pos: [number, number]) => void;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
}) {
|
}) {
|
||||||
// sceneData.cubesQuer
|
|
||||||
let container: HTMLDivElement;
|
let container: HTMLDivElement;
|
||||||
let scene: THREE.Scene;
|
let scene: THREE.Scene;
|
||||||
let camera: THREE.PerspectiveCamera;
|
let camera: THREE.PerspectiveCamera;
|
||||||
@@ -80,6 +79,7 @@ export function CubeScene(props: {
|
|||||||
let controls: MapControls;
|
let controls: MapControls;
|
||||||
// Raycaster for clicking
|
// Raycaster for clicking
|
||||||
const raycaster = new THREE.Raycaster();
|
const raycaster = new THREE.Raycaster();
|
||||||
|
let initBase: THREE.Mesh | undefined;
|
||||||
|
|
||||||
let needsRender = false; // Flag to control rendering
|
let needsRender = false; // Flag to control rendering
|
||||||
|
|
||||||
@@ -172,6 +172,7 @@ export function CubeScene(props: {
|
|||||||
// Add the machine to the store
|
// Add the machine to the store
|
||||||
// Adding it triggers a reactive update
|
// Adding it triggers a reactive update
|
||||||
props.setMachinePos(id, position);
|
props.setMachinePos(id, position);
|
||||||
|
occupiedPositions.add(keyFromPos(position));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -184,7 +185,12 @@ export function CubeScene(props: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderScene() {
|
function renderScene() {
|
||||||
if (!isAnimating) return;
|
if (!isAnimating) {
|
||||||
|
console.warn("Not animating!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log("Rendering scene...", initBase.position);
|
||||||
|
|
||||||
needsRender = false;
|
needsRender = false;
|
||||||
|
|
||||||
frameCount++;
|
frameCount++;
|
||||||
@@ -222,7 +228,6 @@ export function CubeScene(props: {
|
|||||||
const key = keyFromPos(pos);
|
const key = keyFromPos(pos);
|
||||||
|
|
||||||
if (!occupiedPositions.has(key)) {
|
if (!occupiedPositions.has(key)) {
|
||||||
occupiedPositions.add(key);
|
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -451,8 +456,6 @@ export function CubeScene(props: {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
let initBase: THREE.Mesh;
|
|
||||||
|
|
||||||
const grid = new THREE.GridHelper(1000, 1000 / 1, 0xe1edef, 0xe1edef);
|
const grid = new THREE.GridHelper(1000, 1000 / 1, 0xe1edef, 0xe1edef);
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
@@ -589,6 +592,16 @@ export function CubeScene(props: {
|
|||||||
BASE_SIZE,
|
BASE_SIZE,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Important create CubeBase depends on sharedBaseGeometry
|
||||||
|
initBase = createCubeBase(
|
||||||
|
[1, BASE_HEIGHT / 2, 1],
|
||||||
|
1,
|
||||||
|
CREATE_BASE_COLOR,
|
||||||
|
CREATE_BASE_EMISSIVE,
|
||||||
|
);
|
||||||
|
|
||||||
|
scene.add(initBase);
|
||||||
|
|
||||||
// const spherical = new THREE.Spherical();
|
// const spherical = new THREE.Spherical();
|
||||||
// spherical.setFromVector3(camera.position);
|
// spherical.setFromVector3(camera.position);
|
||||||
|
|
||||||
@@ -618,18 +631,14 @@ export function CubeScene(props: {
|
|||||||
// - 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") {
|
||||||
if (initBase) {
|
setWorldMode("view");
|
||||||
scene.remove(initBase); // Remove the base mesh after adding cube
|
|
||||||
setWorldMode("view");
|
|
||||||
|
|
||||||
// res.result.then(() => {
|
// res.result.then(() => {
|
||||||
// props.cubesQuery.refetch();
|
// props.cubesQuery.refetch();
|
||||||
|
|
||||||
// positionMap.set("sara", pos);
|
// positionMap.set("sara", pos);
|
||||||
// addCube("sara");
|
// addCube("sara");
|
||||||
// });
|
// });
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const rect = renderer.domElement.getBoundingClientRect();
|
const rect = renderer.domElement.getBoundingClientRect();
|
||||||
@@ -673,6 +682,8 @@ export function CubeScene(props: {
|
|||||||
requestRenderIfNotRequested();
|
requestRenderIfNotRequested();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
renderer.domElement.addEventListener("mousemove", onMouseMove);
|
||||||
|
|
||||||
window.addEventListener("resize", handleResize);
|
window.addEventListener("resize", handleResize);
|
||||||
// For debugging,
|
// For debugging,
|
||||||
// TODO: Remove in production
|
// TODO: Remove in production
|
||||||
@@ -689,6 +700,7 @@ export function CubeScene(props: {
|
|||||||
// Stop animation loop
|
// Stop animation loop
|
||||||
isAnimating = false;
|
isAnimating = false;
|
||||||
renderer.domElement.removeEventListener("click", onClick);
|
renderer.domElement.removeEventListener("click", onClick);
|
||||||
|
renderer.domElement.removeEventListener("mousemove", onMouseMove);
|
||||||
window.removeEventListener("resize", handleResize);
|
window.removeEventListener("resize", handleResize);
|
||||||
|
|
||||||
if (initBase) {
|
if (initBase) {
|
||||||
@@ -841,38 +853,60 @@ export function CubeScene(props: {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const onHover = (inside: boolean) => (event: MouseEvent) => {
|
const onHover = (inside: boolean) => (event: MouseEvent) => {
|
||||||
// Hover over the plus button, shows a preview of the base mesh
|
const pos = nextGridPos();
|
||||||
const currentCubes = cubes();
|
if (!initBase) return;
|
||||||
if (currentCubes.length > 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!initBase) {
|
initBase.position.set(pos[0], BASE_HEIGHT / 2, pos[1]);
|
||||||
// Create initial base mesh if it doesn't exist
|
|
||||||
initBase = createCubeBase(
|
requestRenderIfNotRequested();
|
||||||
[0, BASE_HEIGHT / 2, 0],
|
|
||||||
1,
|
|
||||||
CREATE_BASE_COLOR,
|
|
||||||
CREATE_BASE_EMISSIVE,
|
|
||||||
); // Emissive color
|
|
||||||
}
|
|
||||||
if (inside) {
|
|
||||||
scene.add(initBase);
|
|
||||||
} else {
|
|
||||||
scene.remove(initBase);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onAddClick = (event: MouseEvent) => {
|
const onAddClick = (event: MouseEvent) => {
|
||||||
setPositionMode("grid");
|
setPositionMode("grid");
|
||||||
setWorldMode("create");
|
setWorldMode("create");
|
||||||
};
|
};
|
||||||
|
const onMouseMove = (event: MouseEvent) => {
|
||||||
|
if (worldMode() !== "create") return;
|
||||||
|
|
||||||
|
const rect = renderer.domElement.getBoundingClientRect();
|
||||||
|
const mouse = new THREE.Vector2(
|
||||||
|
((event.clientX - rect.left) / rect.width) * 2 - 1,
|
||||||
|
-((event.clientY - rect.top) / rect.height) * 2 + 1,
|
||||||
|
);
|
||||||
|
raycaster.setFromCamera(mouse, camera);
|
||||||
|
const intersects = raycaster.intersectObject(floor);
|
||||||
|
if (intersects.length > 0) {
|
||||||
|
const point = intersects[0].point;
|
||||||
|
// Snap to grid
|
||||||
|
const snapped = new THREE.Vector3(
|
||||||
|
Math.round(point.x / GRID_SIZE) * GRID_SIZE,
|
||||||
|
0,
|
||||||
|
Math.round(point.z / GRID_SIZE) * GRID_SIZE,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
Math.abs(initBase.position.x - snapped.x) > 0.01 ||
|
||||||
|
Math.abs(initBase.position.z - snapped.z) > 0.01
|
||||||
|
) {
|
||||||
|
// Only request render if the position actually changed
|
||||||
|
initBase.position.set(snapped.x, 0, snapped.z);
|
||||||
|
setCursorPosition([snapped.x, snapped.z]); // Update next position for cube creation
|
||||||
|
requestRenderIfNotRequested();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div class="cubes-scene-container" ref={(el) => (container = el)} />
|
<div class="cubes-scene-container" ref={(el) => (container = el)} />
|
||||||
<div class="toolbar-container">
|
<div class="toolbar-container">
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
|
<ToolbarButton
|
||||||
|
name="Select"
|
||||||
|
icon="Cursor"
|
||||||
|
onClick={() => setWorldMode("view")}
|
||||||
|
selected={worldMode() === "view"}
|
||||||
|
/>
|
||||||
<ToolbarButton
|
<ToolbarButton
|
||||||
name="new-machine"
|
name="new-machine"
|
||||||
icon="NewMachine"
|
icon="NewMachine"
|
||||||
|
|||||||
Reference in New Issue
Block a user