events handlers

This commit is contained in:
wass08
2026-01-16 11:42:10 +09:00
parent d657f4125f
commit 1b954d3416
12 changed files with 135 additions and 266 deletions
@@ -0,0 +1,21 @@
import { BuildingNode, LevelNode, useRegistry } from "@pascal-app/core";
import { useRef } from "react";
import { Group } from "three";
import { NodeRenderer } from "../node-renderer";
export const BuildingRenderer = ({ node }: { node: BuildingNode }) => {
const ref = useRef<Group>(null!);
useRegistry(node.id, node.type, ref);
return (
<group ref={ref}>
{/* <mesh receiveShadow>
<boxGeometry args={[10, 0.1, 10]} />
<meshStandardMaterial color="orange" />
</mesh> */}
{node.children.map((childId) => (
<NodeRenderer key={childId} nodeId={childId} />
))}
</group>
);
};
@@ -4,6 +4,7 @@ import { useGLTF } from "@react-three/drei/core/Gltf";
import { ThreeEvent } from "@react-three/fiber/dist/declarations/src/core/events";
import { useCallback, useRef } from "react";
import { Group } from "three";
import { useNodeEvents } from "../../../hooks/use-node-events";
export const ItemRenderer = ({ node }: { node: ItemNode }) => {
const ref = useRef<Group>(null!);
@@ -15,114 +16,7 @@ export const ItemRenderer = ({ node }: { node: ItemNode }) => {
nodes.cutout.visible = false;
}
// Event handlers
const onPointerDown = useCallback(
(e: ThreeEvent<PointerEvent>) => {
// Only emit events for left-click (button 0)
if (e.button !== 0) return;
const eventData = {
node,
position: [e.point.x, e.point.y, e.point.z] as [number, number, number],
normal: e.face
? ([e.face.normal.x, e.face.normal.y, e.face.normal.z] as [
number,
number,
number
])
: undefined,
stopPropagation: () => e.stopPropagation(),
};
emitter.emit("item:pointerdown", eventData);
},
[node]
);
const onClick = useCallback(
(e: ThreeEvent<PointerEvent>) => {
// Only emit events for left-click (button 0)
if (e.button !== 0) return;
const eventData = {
node,
position: [e.point.x, e.point.y, e.point.z] as [number, number, number],
normal: e.face
? ([e.face.normal.x, e.face.normal.y, e.face.normal.z] as [
number,
number,
number
])
: undefined,
stopPropagation: () => e.stopPropagation(),
};
emitter.emit("item:click", eventData);
},
[node]
);
const onPointerUp = useCallback(
(e: ThreeEvent<PointerEvent>) => {
// Only emit events for left-click (button 0)
if (e.button !== 0) return;
emitter.emit("item:pointerup", {
node,
position: [e.point.x, e.point.y, e.point.z],
normal: e.face
? ([e.face.normal.x, e.face.normal.y, e.face.normal.z] as [
number,
number,
number
])
: undefined,
stopPropagation: () => e.stopPropagation(),
});
},
[node]
);
const onPointerEnter = useCallback(
(e: ThreeEvent<PointerEvent>) => {
emitter.emit("item:enter", {
node,
position: [e.point.x, e.point.y, e.point.z],
normal: e.face
? [e.face.normal.x, e.face.normal.y, e.face.normal.z]
: undefined,
stopPropagation: () => e.stopPropagation(),
});
},
[node]
);
const onPointerLeave = useCallback(
(e: ThreeEvent<PointerEvent>) => {
emitter.emit("item:leave", {
node,
position: [e.point.x, e.point.y, e.point.z],
normal: e.face
? [e.face.normal.x, e.face.normal.y, e.face.normal.z]
: undefined,
stopPropagation: () => e.stopPropagation(),
});
},
[node]
);
const onPointerMove = useCallback(
(e: ThreeEvent<PointerEvent>) => {
emitter.emit("item:move", {
node,
position: [e.point.x, e.point.y, e.point.z],
normal: e.face
? [e.face.normal.x, e.face.normal.y, e.face.normal.z]
: undefined,
stopPropagation: () => e.stopPropagation(),
});
},
[node]
);
const handlers = useNodeEvents(node, "item");
return (
<Clone
@@ -130,12 +24,7 @@ export const ItemRenderer = ({ node }: { node: ItemNode }) => {
object={scene}
position={node.position}
rotation={node.rotation}
onPointerDown={onPointerDown}
onClick={onClick}
onPointerUp={onPointerUp}
onPointerEnter={onPointerEnter}
onPointerLeave={onPointerLeave}
onPointerMove={onPointerMove}
{...handlers}
/>
);
};
@@ -9,10 +9,10 @@ export const LevelRenderer = ({ node }: { node: LevelNode }) => {
useRegistry(node.id, node.type, ref);
return (
<group ref={ref}>
<mesh receiveShadow>
{/* <mesh receiveShadow>
<boxGeometry args={[10, 0.1, 10]} />
<meshStandardMaterial color="orange" />
</mesh>
</mesh> */}
{node.children.map((childId) => (
<NodeRenderer key={childId} nodeId={childId} />
))}
@@ -4,6 +4,7 @@ import { AnyNode, useScene } from "@pascal-app/core";
import { ItemRenderer } from "./item/item-renderer";
import { LevelRenderer } from "./level/level-renderer";
import { WallRenderer } from "./wall/wall-renderer";
import { BuildingRenderer } from "./building/building-renderer";
export const NodeRenderer = ({ nodeId }: { nodeId: AnyNode["id"] }) => {
const node = useScene((state) => state.nodes[nodeId]);
@@ -12,6 +13,7 @@ export const NodeRenderer = ({ nodeId }: { nodeId: AnyNode["id"] }) => {
return (
<>
{node.type === "building" && <BuildingRenderer node={node} />}
{node.type === "level" && <LevelRenderer node={node} />}
{node.type === "item" && <ItemRenderer node={node} />}
{node.type === "wall" && <WallRenderer node={node} />}
@@ -3,132 +3,21 @@ import { ThreeEvent } from "@react-three/fiber";
import { useCallback, useRef } from "react";
import { Mesh } from "three";
import { NodeRenderer } from "../node-renderer";
import { useNodeEvents } from "../../../hooks/use-node-events";
export const WallRenderer = ({ node }: { node: WallNode }) => {
const ref = useRef<Mesh>(null!);
useRegistry(node.id, "wall", ref);
// Event handlers
const onPointerDown = useCallback(
(e: ThreeEvent<PointerEvent>) => {
// Only emit events for left-click (button 0)
if (e.button !== 0) return;
const eventData = {
node,
position: [e.point.x, e.point.y, e.point.z] as [number, number, number],
normal: e.face
? ([e.face.normal.x, e.face.normal.y, e.face.normal.z] as [
number,
number,
number
])
: undefined,
stopPropagation: () => e.stopPropagation(),
};
emitter.emit("wall:pointerdown", eventData);
},
[node]
);
const onClick = useCallback(
(e: ThreeEvent<PointerEvent>) => {
// Only emit events for left-click (button 0)
if (e.button !== 0) return;
const eventData = {
node,
position: [e.point.x, e.point.y, e.point.z] as [number, number, number],
normal: e.face
? ([e.face.normal.x, e.face.normal.y, e.face.normal.z] as [
number,
number,
number
])
: undefined,
stopPropagation: () => e.stopPropagation(),
};
emitter.emit("wall:click", eventData);
},
[node]
);
const onPointerUp = useCallback(
(e: ThreeEvent<PointerEvent>) => {
// Only emit events for left-click (button 0)
if (e.button !== 0) return;
emitter.emit("wall:pointerup", {
node,
position: [e.point.x, e.point.y, e.point.z],
normal: e.face
? ([e.face.normal.x, e.face.normal.y, e.face.normal.z] as [
number,
number,
number
])
: undefined,
stopPropagation: () => e.stopPropagation(),
});
},
[node]
);
const onPointerEnter = useCallback(
(e: ThreeEvent<PointerEvent>) => {
emitter.emit("wall:enter", {
node,
position: [e.point.x, e.point.y, e.point.z],
normal: e.face
? [e.face.normal.x, e.face.normal.y, e.face.normal.z]
: undefined,
stopPropagation: () => e.stopPropagation(),
});
},
[node]
);
const onPointerLeave = useCallback(
(e: ThreeEvent<PointerEvent>) => {
emitter.emit("wall:leave", {
node,
position: [e.point.x, e.point.y, e.point.z],
normal: e.face
? [e.face.normal.x, e.face.normal.y, e.face.normal.z]
: undefined,
stopPropagation: () => e.stopPropagation(),
});
},
[node]
);
const onPointerMove = useCallback(
(e: ThreeEvent<PointerEvent>) => {
emitter.emit("wall:move", {
node,
position: [e.point.x, e.point.y, e.point.z],
normal: e.face
? [e.face.normal.x, e.face.normal.y, e.face.normal.z]
: undefined,
stopPropagation: () => e.stopPropagation(),
});
},
[node]
);
const handlers = useNodeEvents(node, "wall");
return (
<mesh
ref={ref}
castShadow
receiveShadow
onPointerDown={onPointerDown}
onPointerUp={onPointerUp}
onPointerEnter={onPointerEnter}
onPointerLeave={onPointerLeave}
onPointerMove={onPointerMove}
onClick={onClick}
{...handlers}
>
{/* WallSystem will replace this geometry in the next frame */}
<boxGeometry args={[0, 0, 0]} />