import { observer } from "mobx-react-lite"; import type { ObjectInstance } from "../types"; import { useEffect, useRef, type RefObject } from "react"; import type { Group } from "three"; import { TransformControls, useHelper } from "@react-three/drei"; import { BoxHelper } from "three"; import type { ThreeEvent } from "@react-three/fiber"; import { state } from "../state"; import { nextSelectionEditMode } from "../state/worldEditorState"; import type { R3 } from "../types/3d"; type ObjectViewProps = { object: ObjectInstance; } export const ObjectView = observer(function ({ object }: ObjectViewProps) { const groupRef = useRef(null); const controlsRef = useRef(null); const isSelected = state.worldEditor.isEnabled && state.worldEditor.selectedObjectId === object.id; useHelper(isSelected ? groupRef : { current: null } as any, BoxHelper, 'white'); const objectType = state.world.getObjectTypeById(object.typeId); if (!objectType) return null; const selectionMode = isSelected ? state.worldEditor.selectedObjectMode : undefined; useEffect(() => { if (!isSelected) return; const controls = controlsRef.current; if (!controls) return; const onDragChanged = (e: { value: boolean }) => { state.worldEditor.setIsDragging(e.value); if (!e.value) { const group = groupRef.current; if (group) state.worldEditor.setObjectTransform( object.id, group.position.toArray(), group.rotation.toArray().slice(0, 3) as R3, group.scale.toArray(), ); } }; controls.addEventListener('dragging-changed', onDragChanged); return () => { controls.removeEventListener('dragging-changed', onDragChanged); state.worldEditor.setIsDragging(false); }; }, [isSelected]); const handleClick = (e: ThreeEvent) => { if (!state.worldEditor.isEnabled) return; if (e.delta > 5) return; e.stopPropagation(); state.worldEditor.setSelectedObject(object.id, nextSelectionEditMode(selectionMode)); }; return (<> { (isSelected && (selectionMode !== undefined) && groupRef.current) && } mode={selectionMode} /> } { objectType.voxels.map((v, idx) => { const vt = state.world.getVoxelTypeById(v.typeId); const color = (v.color ?? vt?.color) ?? 'white'; const opacity = (v.opacity ?? vt?.opacity) ?? 1; return ( ); }) } ); });