zone rendering
This commit is contained in:
@@ -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>
|
||||||
|
);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user