zone rendering

This commit is contained in:
wass08
2026-01-22 11:44:04 +09:00
parent 68e573f494
commit 36b7117173
4 changed files with 58 additions and 25 deletions
@@ -1,5 +1,5 @@
import { useLayoutEffect } from 'react' import { useLayoutEffect } from "react";
import type * as THREE from 'three' import type * as THREE from "three";
export const sceneRegistry = { export const sceneRegistry = {
// Master lookup: ID -> Object3D // Master lookup: ID -> Object3D
@@ -13,8 +13,9 @@ export const sceneRegistry = {
wall: new Set<string>(), wall: new Set<string>(),
item: new Set<string>(), item: new Set<string>(),
slab: new Set<string>(), slab: new Set<string>(),
zone: new Set<string>(),
}, },
} };
export function useRegistry( export function useRegistry(
id: string, id: string,
@@ -22,19 +23,19 @@ export function useRegistry(
ref: React.RefObject<THREE.Object3D>, ref: React.RefObject<THREE.Object3D>,
) { ) {
useLayoutEffect(() => { useLayoutEffect(() => {
const obj = ref.current const obj = ref.current;
if (!obj) return if (!obj) return;
// 1. Add to master map // 1. Add to master map
sceneRegistry.nodes.set(id, obj) sceneRegistry.nodes.set(id, obj);
// 2. Add to type-specific set // 2. Add to type-specific set
sceneRegistry.byType[type].add(id) sceneRegistry.byType[type].add(id);
// 4. Cleanup when component unmounts // 4. Cleanup when component unmounts
return () => { return () => {
sceneRegistry.nodes.delete(id) sceneRegistry.nodes.delete(id);
sceneRegistry.byType[type].delete(id) sceneRegistry.byType[type].delete(id);
} };
}, [id, type, ref]) }, [id, type, ref]);
} }
@@ -1,12 +1,14 @@
import { type LevelNode, useRegistry } from '@pascal-app/core' import { type LevelNode, useRegistry, useScene } from "@pascal-app/core";
import { useRef } from 'react' import { useRef } from "react";
import type { Group } from 'three' import type { Group } from "three";
import { NodeRenderer } from '../node-renderer' import { useShallow } from "zustand/shallow";
import { NodeRenderer } from "../node-renderer";
import { ZoneRenderer } from "../zone/zone-renderer";
export const LevelRenderer = ({ node }: { node: LevelNode }) => { export const LevelRenderer = ({ node }: { node: LevelNode }) => {
const ref = useRef<Group>(null!) const ref = useRef<Group>(null!);
useRegistry(node.id, node.type, ref) useRegistry(node.id, node.type, ref);
return ( return (
<group ref={ref}> <group ref={ref}>
@@ -17,6 +19,17 @@ export const LevelRenderer = ({ node }: { node: LevelNode }) => {
{node.children.map((childId) => ( {node.children.map((childId) => (
<NodeRenderer key={childId} nodeId={childId} /> <NodeRenderer key={childId} nodeId={childId} />
))} ))}
<LevelZones levelId={node.id} />
</group> </group>
) );
} };
const LevelZones = ({ levelId }: { levelId: LevelNode["id"] }) => {
const zoneIds = useScene(
useShallow((s) =>
s.zoneIds.filter((id) => s.zones[id]?.levelId === levelId),
),
);
return zoneIds.map((zoneId) => <ZoneRenderer key={zoneId} zoneId={zoneId} />);
};
@@ -1,10 +1,12 @@
'use client' "use client";
import { useScene } from '@pascal-app/core' import { useScene } from "@pascal-app/core";
import { NodeRenderer } from './node-renderer' import { NodeRenderer } from "./node-renderer";
export const SceneRenderer = () => { export const SceneRenderer = () => {
const rootNodes = useScene((state) => state.rootNodeIds) const rootNodes = useScene((state) => state.rootNodeIds);
return rootNodes.map((nodeId) => <NodeRenderer key={nodeId} nodeId={nodeId} />) return rootNodes.map((nodeId) => (
} <NodeRenderer key={nodeId} nodeId={nodeId} />
));
};
@@ -0,0 +1,17 @@
import { useRegistry, type Zone } from "@pascal-app/core";
import { useRef } from "react";
import type { Group } from "three";
export const ZoneRenderer = ({ zoneId }: { zoneId: Zone["id"] }) => {
const ref = useRef<Group>(null!);
useRegistry(zoneId, "zone", ref);
return (
<mesh ref={ref}>
{/* <shapeGeometry /> */}
<boxGeometry args={[1, 1, 1]} />
<meshBasicNodeMaterial color="pink" />
</mesh>
);
};