Files
La-Fabrik/src/world/vegetation/useVegetationData.ts
T
Tom Boullay 439f9c1dad
🔍 Lint / 🪄 Check lint (pull_request) Has been cancelled
🔍 Lint / 🎨 Check format (pull_request) Has been cancelled
🔍 Lint / 🔎 Typecheck (pull_request) Has been cancelled
📊 Quality / 🔒 Security Audit (pull_request) Has been cancelled
📊 Quality / 📋 Dependency Freshness (pull_request) Has been cancelled
📊 Quality / 📦 Bundle Size (pull_request) Has been cancelled
🔍 Lint / 🏗 Build (pull_request) Has been cancelled
feat: add VegetationSystem with InstancedMesh rendering
2026-05-14 00:16:00 +02:00

85 lines
2.0 KiB
TypeScript

import { useEffect, useState } from "react";
import type { MapNode } from "@/types/editor/editor";
import type { Vector3Tuple } from "@/types/three/three";
import { getMapNodes, loadMapSceneData } from "@/utils/map/loadMapSceneData";
import {
VEGETATION_MAX_INSTANCES,
VEGETATION_TYPES,
type VegetationType,
} from "@/world/vegetation/vegetationConfig";
export interface VegetationInstance {
position: Vector3Tuple;
rotation: Vector3Tuple;
scale: Vector3Tuple;
}
export type VegetationData = Map<VegetationType, VegetationInstance[]>;
function mapNodeToInstance(node: MapNode): VegetationInstance {
return {
position: node.position,
rotation: node.rotation,
scale: node.scale,
};
}
function extractVegetationData(mapNodes: MapNode[]): VegetationData {
const data: VegetationData = new Map();
for (const [type, config] of Object.entries(VEGETATION_TYPES)) {
if (!config.enabled) continue;
const instances = mapNodes
.filter((node) => node.name === config.mapName)
.slice(0, VEGETATION_MAX_INSTANCES)
.map(mapNodeToInstance);
if (instances.length > 0) {
data.set(type as VegetationType, instances);
}
}
return data;
}
export function useVegetationData(): {
data: VegetationData | null;
isLoading: boolean;
} {
const [data, setData] = useState<VegetationData | null>(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
let cancelled = false;
async function load() {
const cachedNodes = getMapNodes();
if (cachedNodes) {
if (!cancelled) {
setData(extractVegetationData(cachedNodes));
setIsLoading(false);
}
return;
}
await loadMapSceneData();
const nodes = getMapNodes();
if (!cancelled && nodes) {
setData(extractVegetationData(nodes));
setIsLoading(false);
}
}
load();
return () => {
cancelled = true;
};
}, []);
return { data, isLoading };
}