Feat/map-environment #6
+9
-37
@@ -24,13 +24,16 @@ import { CloudSystem } from "@/world/clouds/CloudSystem";
|
|||||||
import { GeneratedMapNodeInstance } from "@/world/map-generated/GeneratedMapNodeInstance";
|
import { GeneratedMapNodeInstance } from "@/world/map-generated/GeneratedMapNodeInstance";
|
||||||
import { isGeneratedMapModelName } from "@/world/map-generated/generatedMapModelConfig";
|
import { isGeneratedMapModelName } from "@/world/map-generated/generatedMapModelConfig";
|
||||||
import { MapInstancingSystem } from "@/world/map-instancing/MapInstancingSystem";
|
import { MapInstancingSystem } from "@/world/map-instancing/MapInstancingSystem";
|
||||||
import { isInstancedMapNodeName } from "@/world/map-instancing/mapInstancingConfig";
|
|
||||||
import { VegetationSystem } from "@/world/vegetation/VegetationSystem";
|
import { VegetationSystem } from "@/world/vegetation/VegetationSystem";
|
||||||
import { WaterSystem } from "@/world/water/WaterSystem";
|
import { WaterSystem } from "@/world/water/WaterSystem";
|
||||||
import { WorldPlane } from "@/world/WorldPlane";
|
import { WorldPlane } from "@/world/WorldPlane";
|
||||||
import type { SceneLoadingChangeHandler } from "@/types/world/sceneLoading";
|
import type { SceneLoadingChangeHandler } from "@/types/world/sceneLoading";
|
||||||
import { logger } from "@/utils/core/Logger";
|
import { logger } from "@/utils/core/Logger";
|
||||||
import { loadMapSceneData } from "@/utils/map/loadMapSceneData";
|
import { loadMapSceneData } from "@/utils/map/loadMapSceneData";
|
||||||
|
import {
|
||||||
|
getTerrainMapNode,
|
||||||
|
isRuntimeSingleMapNode,
|
||||||
|
} from "@/utils/map/mapRuntimeClassification";
|
||||||
import { logModelLoadError } from "@/utils/three/modelLoadLogger";
|
import { logModelLoadError } from "@/utils/three/modelLoadLogger";
|
||||||
import type { MapNode } from "@/types/editor/editor";
|
import type { MapNode } from "@/types/editor/editor";
|
||||||
import type { OctreeReadyHandler } from "@/types/three/three";
|
import type { OctreeReadyHandler } from "@/types/three/three";
|
||||||
@@ -40,16 +43,6 @@ interface LoadedMapNode {
|
|||||||
modelUrl: string | null;
|
modelUrl: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAP_STRUCTURE_NODE_NAMES = new Set(["Scene", "blocking", "terrain"]);
|
|
||||||
const LITE_MAP_SKIPPED_NODE_NAMES = new Set([
|
|
||||||
"arbre",
|
|
||||||
"buisson",
|
|
||||||
"champdeble",
|
|
||||||
"champdesoja",
|
|
||||||
"champsdetournesol",
|
|
||||||
"sapin",
|
|
||||||
]);
|
|
||||||
|
|
||||||
interface ErrorBoundaryProps {
|
interface ErrorBoundaryProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
fallback: ReactNode;
|
fallback: ReactNode;
|
||||||
@@ -121,7 +114,7 @@ export function GameMap({
|
|||||||
const [terrainNode, setTerrainNode] = useState<MapNode | null>(null);
|
const [terrainNode, setTerrainNode] = useState<MapNode | null>(null);
|
||||||
const [mapLoaded, setMapLoaded] = useState(false);
|
const [mapLoaded, setMapLoaded] = useState(false);
|
||||||
const [settledMapNodeCount, setSettledMapNodeCount] = useState(0);
|
const [settledMapNodeCount, setSettledMapNodeCount] = useState(0);
|
||||||
const mapReady = mapLoaded && settledMapNodeCount >= renderMapNodes.length;
|
const mapReady = mapLoaded;
|
||||||
|
|
||||||
const handleMapNodeSettled = useCallback((index: number) => {
|
const handleMapNodeSettled = useCallback((index: number) => {
|
||||||
if (settledMapNodesRef.current.has(index)) return;
|
if (settledMapNodesRef.current.has(index)) return;
|
||||||
@@ -169,7 +162,9 @@ export function GameMap({
|
|||||||
status: "loading",
|
status: "loading",
|
||||||
});
|
});
|
||||||
|
|
||||||
const visibleMapNodes = sceneData.mapNodes.filter(liteMap);
|
const visibleMapNodes = sceneData.mapNodes.filter(
|
||||||
|
isRuntimeSingleMapNode,
|
||||||
|
);
|
||||||
const skippedMapNodeCount =
|
const skippedMapNodeCount =
|
||||||
sceneData.mapNodes.length - visibleMapNodes.length;
|
sceneData.mapNodes.length - visibleMapNodes.length;
|
||||||
|
|
||||||
@@ -189,7 +184,7 @@ export function GameMap({
|
|||||||
const modelUrl = sceneData.models.get(node.name);
|
const modelUrl = sceneData.models.get(node.name);
|
||||||
return { node, modelUrl: modelUrl ?? null };
|
return { node, modelUrl: modelUrl ?? null };
|
||||||
});
|
});
|
||||||
const loadedTerrainNode = loadedCollisionNodes[0]?.node ?? null;
|
const loadedTerrainNode = getTerrainMapNode(sceneData.mapNodes);
|
||||||
const missingModelCount = loadedMapNodes.filter(
|
const missingModelCount = loadedMapNodes.filter(
|
||||||
(mapNode) => mapNode.modelUrl === null,
|
(mapNode) => mapNode.modelUrl === null,
|
||||||
).length;
|
).length;
|
||||||
@@ -299,29 +294,6 @@ function HiddenMapNode({ onSettled }: { onSettled: () => void }): null {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Temporary development-only map reducer.
|
|
||||||
*
|
|
||||||
* TODO: replace this with a real map performance pass: merged static geometry,
|
|
||||||
* instancing for repeated props, LOD, and/or zone-based loading. For now this
|
|
||||||
* keeps the app usable on local machines by not rendering the densest exported
|
|
||||||
* nodes from map.json.
|
|
||||||
*/
|
|
||||||
function liteMap(node: MapNode): boolean {
|
|
||||||
if (MAP_STRUCTURE_NODE_NAMES.has(node.name)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.type === "Mesh") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
!LITE_MAP_SKIPPED_NODE_NAMES.has(node.name) &&
|
|
||||||
!isInstancedMapNodeName(node.name)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function MapNodeInstance({
|
function MapNodeInstance({
|
||||||
node,
|
node,
|
||||||
modelUrl,
|
modelUrl,
|
||||||
|
|||||||
Reference in New Issue
Block a user