98 lines
2.4 KiB
TypeScript
98 lines
2.4 KiB
TypeScript
import type { HierarchicalMapNode, MapNode } from "@/types/map/mapScene";
|
|
|
|
export interface ParsedMapNodes {
|
|
mapNodes: MapNode[];
|
|
mapTree: HierarchicalMapNode | HierarchicalMapNode[];
|
|
}
|
|
|
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
return typeof value === "object" && value !== null;
|
|
}
|
|
|
|
function isVector3Tuple(value: unknown): value is [number, number, number] {
|
|
return (
|
|
Array.isArray(value) &&
|
|
value.length === 3 &&
|
|
value.every((item) => typeof item === "number" && Number.isFinite(item))
|
|
);
|
|
}
|
|
|
|
function isMapNode(value: unknown): value is MapNode {
|
|
if (!isRecord(value)) {
|
|
return false;
|
|
}
|
|
|
|
return (
|
|
(value.id === undefined || typeof value.id === "string") &&
|
|
typeof value.name === "string" &&
|
|
typeof value.type === "string" &&
|
|
isVector3Tuple(value.position) &&
|
|
isVector3Tuple(value.rotation) &&
|
|
isVector3Tuple(value.scale)
|
|
);
|
|
}
|
|
|
|
function isHierarchicalMapNode(value: unknown): value is HierarchicalMapNode {
|
|
if (!isMapNode(value)) {
|
|
return false;
|
|
}
|
|
|
|
if ("role" in value && value.role !== undefined && value.role !== "group") {
|
|
return false;
|
|
}
|
|
|
|
if (!("children" in value)) {
|
|
return true;
|
|
}
|
|
|
|
return (
|
|
value.children === undefined ||
|
|
(Array.isArray(value.children) &&
|
|
value.children.every(isHierarchicalMapNode))
|
|
);
|
|
}
|
|
|
|
function flattenMapNode(node: HierarchicalMapNode, path: number[]): MapNode[] {
|
|
const mapNode: MapNode = {
|
|
...(node.id ? { id: node.id } : {}),
|
|
name: node.name,
|
|
type: node.type,
|
|
position: node.position,
|
|
rotation: node.rotation,
|
|
scale: node.scale,
|
|
sourcePath: path,
|
|
};
|
|
const childNodes =
|
|
node.children?.flatMap((child, index) =>
|
|
flattenMapNode(child, [...path, index]),
|
|
) ?? [];
|
|
|
|
if (node.role === "group" || node.type === "Mesh") {
|
|
return childNodes;
|
|
}
|
|
|
|
return [mapNode, ...childNodes];
|
|
}
|
|
|
|
export function parseMapNodes(value: unknown): MapNode[] {
|
|
return parseMapData(value).mapNodes;
|
|
}
|
|
|
|
export function parseMapData(value: unknown): ParsedMapNodes {
|
|
if (Array.isArray(value) && value.every(isHierarchicalMapNode)) {
|
|
return {
|
|
mapNodes: value.flatMap((node, index) => flattenMapNode(node, [index])),
|
|
mapTree: value,
|
|
};
|
|
}
|
|
|
|
if (isHierarchicalMapNode(value)) {
|
|
return {
|
|
mapNodes: flattenMapNode(value, []),
|
|
mapTree: value,
|
|
};
|
|
}
|
|
|
|
throw new Error("Invalid map node data");
|
|
}
|