working ceiling items

This commit is contained in:
wass08
2026-01-28 06:55:56 +09:00
parent 6bd34762e5
commit e27028a29a
4 changed files with 116 additions and 11 deletions
@@ -1,5 +1,6 @@
import {
type CeilingEvent,
type CeilingNode,
emitter,
type GridEvent,
ItemNode,
@@ -112,7 +113,7 @@ export const ItemTool: React.FC = () => {
const draftItem = useRef<ItemNode | null>(null)
const gridPosition = useRef(new Vector3(0, 0, 0))
const selectedItem = useEditor((state) => state.selectedItem)
const { canPlaceOnFloor, canPlaceOnWall } = useSpatialQuery()
const { canPlaceOnFloor, canPlaceOnWall, canPlaceOnCeiling } = useSpatialQuery()
const isOnWall = useRef(false)
const isOnCeiling = useRef(false)
@@ -129,7 +130,18 @@ export const ItemTool: React.FC = () => {
if (currentLevelId && draftItem.current) {
let placeable = true
if (draftItem.current.asset.attachTo === 'ceiling') {
placeable = isOnCeiling.current && !!currentCeilingId
if (!isOnCeiling.current || !currentCeilingId) {
placeable = false
} else {
const result = canPlaceOnCeiling(
currentCeilingId as CeilingNode['id'],
[gridPosition.current.x, gridPosition.current.y, gridPosition.current.z],
draftItem.current.asset.dimensions,
draftItem.current.rotation,
[draftItem.current.id],
)
placeable = result.valid
}
} else if (draftItem.current.asset.attachTo) {
if (!isOnWall.current || !currentWallId) {
placeable = false
@@ -541,7 +553,7 @@ export const ItemTool: React.FC = () => {
emitter.off('ceiling:leave', onCeilingLeave)
window.removeEventListener('keydown', onKeyDown)
}
}, [selectedItem, canPlaceOnFloor, canPlaceOnWall])
}, [selectedItem, canPlaceOnFloor, canPlaceOnWall, canPlaceOnCeiling])
useFrame((_, delta) => {
if (draftItem.current && !isOnWall.current && !isOnCeiling.current) {
@@ -1,7 +1,8 @@
import { CeilingNode } from "@pascal-app/core";
import { useViewer } from "@pascal-app/viewer";
import { Square } from "lucide-react";
import { TreeNodeWrapper } from "./tree-node";
import { useState } from "react";
import { TreeNode, TreeNodeWrapper } from "./tree-node";
import { TreeNodeActions } from "./tree-node-actions";
interface CeilingTreeNodeProps {
@@ -10,6 +11,7 @@ interface CeilingTreeNodeProps {
}
export function CeilingTreeNode({ node, depth }: CeilingTreeNodeProps) {
const [expanded, setExpanded] = useState(false);
const isSelected = useViewer((state) => state.selection.selectedIds.includes(node.id));
const isHovered = useViewer((state) => state.hoveredId === node.id);
const setSelection = useViewer((state) => state.setSelection);
@@ -35,16 +37,20 @@ export function CeilingTreeNode({ node, depth }: CeilingTreeNodeProps) {
icon={<Square className="w-3.5 h-3.5" />}
label={node.name || `Ceiling (${area}m²)`}
depth={depth}
hasChildren={false}
expanded={false}
onToggle={() => {}}
hasChildren={node.children.length > 0}
expanded={expanded}
onToggle={() => setExpanded(!expanded)}
onClick={handleClick}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
isSelected={isSelected}
isHovered={isHovered}
actions={<TreeNodeActions node={node} />}
/>
>
{node.children.map((childId) => (
<TreeNode key={childId} nodeId={childId} depth={depth + 1} />
))}
</TreeNodeWrapper>
);
}