draft spatial grid
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
import {
|
||||
emitter,
|
||||
initSpatialGridSync,
|
||||
ItemNode,
|
||||
sceneRegistry,
|
||||
useScene,
|
||||
@@ -32,6 +33,8 @@ import { ToolManager } from "./tools/tool-manager";
|
||||
|
||||
const selectedObjects: Object3D[] = [];
|
||||
|
||||
initSpatialGridSync();
|
||||
|
||||
export default function Editor() {
|
||||
return (
|
||||
<div className="w-full h-full bg-pink-50">
|
||||
|
||||
@@ -6,19 +6,21 @@ import {
|
||||
sceneRegistry,
|
||||
useRegistry,
|
||||
useScene,
|
||||
useSpatialQuery,
|
||||
WallNode,
|
||||
} from "@pascal-app/core";
|
||||
import { useViewer } from "@pascal-app/viewer";
|
||||
import { useFrame } from "@react-three/fiber";
|
||||
import { use, useEffect, useRef } from "react";
|
||||
import { Line, Mesh, Vector3 } from "three";
|
||||
import { BoxGeometry, Line, Mesh, Vector3 } from "three";
|
||||
import { randInt } from "three/src/math/MathUtils.js";
|
||||
|
||||
export const ItemTool: React.FC = () => {
|
||||
const cursorRef = useRef<Mesh>(null);
|
||||
const cursorRef = useRef<Mesh>(null!);
|
||||
const draftItem = useRef<ItemNode | null>(null);
|
||||
const gridPosition = useRef(new Vector3(0, 0, 0));
|
||||
const selectedItem = useEditor((state) => state.selectedItem);
|
||||
const { canPlace } = useSpatialQuery();
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectedItem) {
|
||||
@@ -53,7 +55,7 @@ export const ItemTool: React.FC = () => {
|
||||
);
|
||||
cursorRef.current.position.set(
|
||||
gridPosition.current.x,
|
||||
0.1,
|
||||
0,
|
||||
gridPosition.current.z,
|
||||
);
|
||||
if (draftItem.current) {
|
||||
@@ -62,15 +64,29 @@ export const ItemTool: React.FC = () => {
|
||||
0,
|
||||
gridPosition.current.z,
|
||||
];
|
||||
|
||||
const currentLevelId = useViewer.getState().currentLevelId;
|
||||
if (currentLevelId) {
|
||||
const placeable = canPlace(
|
||||
currentLevelId,
|
||||
[gridPosition.current.x, 0, gridPosition.current.z],
|
||||
selectedItem.dimensions,
|
||||
[0, 0, 0],
|
||||
);
|
||||
console.log(
|
||||
"placeable",
|
||||
placeable,
|
||||
[gridPosition.current.x, 0, gridPosition.current.z],
|
||||
selectedItem.dimensions,
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
const onGridClick = (event: GridEvent) => {
|
||||
const { currentLevelId } = useViewer.getState();
|
||||
|
||||
console.log("oh", currentLevelId, draftItem.current);
|
||||
if (!currentLevelId || !draftItem.current) return;
|
||||
|
||||
console.log("oh");
|
||||
useScene.temporal.getState().resume();
|
||||
useScene.getState().updateNode(draftItem.current.id, {
|
||||
position: [
|
||||
@@ -88,6 +104,17 @@ export const ItemTool: React.FC = () => {
|
||||
emitter.on("grid:move", onGridMove);
|
||||
emitter.on("grid:click", onGridClick);
|
||||
|
||||
const setupBoundingBox = () => {
|
||||
const boxGeometry = new BoxGeometry(
|
||||
selectedItem.dimensions[0],
|
||||
selectedItem.dimensions[1],
|
||||
selectedItem.dimensions[2],
|
||||
);
|
||||
boxGeometry.translate(0, selectedItem.dimensions[1] / 2, 0);
|
||||
cursorRef.current.geometry = boxGeometry;
|
||||
};
|
||||
setupBoundingBox();
|
||||
|
||||
return () => {
|
||||
if (draftItem.current) {
|
||||
useScene.getState().deleteNode(draftItem.current.id);
|
||||
@@ -109,8 +136,8 @@ export const ItemTool: React.FC = () => {
|
||||
return (
|
||||
<group>
|
||||
<mesh ref={cursorRef}>
|
||||
<boxGeometry args={[0.2, 0.2, 0.2]} />
|
||||
<meshStandardMaterial color="red" />
|
||||
<boxGeometry args={[0.1, 0.1, 0.1]} />
|
||||
<meshStandardMaterial color="red" wireframe />
|
||||
</mesh>
|
||||
</group>
|
||||
);
|
||||
|
||||
@@ -5,16 +5,16 @@ export const CATALOG_ITEMS: AssetInput[] = [
|
||||
name: "Couch",
|
||||
thumbnail: "/items/couch-medium/thumbnail.webp",
|
||||
src: "/items/couch-medium/model.glb",
|
||||
scale: [0.4, 0.4, 0.4],
|
||||
dimensions: [4, 2, 2],
|
||||
scale: [0.35, 0.35, 0.35],
|
||||
dimensions: [2, 0.8, 1],
|
||||
},
|
||||
{
|
||||
category: "furniture",
|
||||
name: "Small Couch",
|
||||
thumbnail: "/items/couch-small/thumbnail.webp",
|
||||
src: "/items/couch-small/model.glb",
|
||||
scale: [0.4, 0.4, 0.4],
|
||||
dimensions: [3, 2, 2],
|
||||
scale: [0.35, 0.35, 0.35],
|
||||
dimensions: [1, 0.8, 1],
|
||||
},
|
||||
{
|
||||
category: "furniture",
|
||||
@@ -154,10 +154,10 @@ export const CATALOG_ITEMS: AssetInput[] = [
|
||||
name: "Wall Art",
|
||||
thumbnail: "/items/wall-art-06/thumbnail.webp",
|
||||
src: "/items/wall-art-06/model.glb",
|
||||
offset: [0, 1, 0.15],
|
||||
offset: [0, 0.5, 0],
|
||||
scale: [1, 1, 1],
|
||||
rotation: [0, Math.PI, 0],
|
||||
dimensions: [2, 2, 1],
|
||||
dimensions: [1, 1, 0.1],
|
||||
attachTo: "wall-side",
|
||||
},
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
} from "@pascal-app/core";
|
||||
import { useViewer } from "@pascal-app/viewer";
|
||||
import { create } from "zustand";
|
||||
import { Asset } from "../../../packages/core/src/schema/nodes/item";
|
||||
|
||||
export type Phase = "site" | "structure" | "furnish";
|
||||
|
||||
@@ -54,8 +55,8 @@ type EditorState = {
|
||||
setTool: (tool: Tool | null) => void;
|
||||
catalogCategory: CatalogCategory | null;
|
||||
setCatalogCategory: (category: CatalogCategory | null) => void;
|
||||
selectedItem: AssetInput | null;
|
||||
setSelectedItem: (item: AssetInput) => void;
|
||||
selectedItem: Asset | null;
|
||||
setSelectedItem: (item: Asset) => void;
|
||||
};
|
||||
|
||||
const useEditor = create<EditorState>()((set, get) => ({
|
||||
|
||||
Reference in New Issue
Block a user