mirror of
https://github.com/exogen/t2-mapper.git
synced 2026-07-15 16:34:49 +00:00
set up static shape components
This commit is contained in:
parent
beade00727
commit
d925585a34
7 changed files with 243 additions and 3 deletions
13
package-lock.json
generated
13
package-lock.json
generated
|
|
@ -16,6 +16,7 @@
|
||||||
"next": "^15.5.2",
|
"next": "^15.5.2",
|
||||||
"react": "^19.1.1",
|
"react": "^19.1.1",
|
||||||
"react-dom": "^19.1.1",
|
"react-dom": "^19.1.1",
|
||||||
|
"react-error-boundary": "^6.0.0",
|
||||||
"three": "^0.180.0",
|
"three": "^0.180.0",
|
||||||
"unzipper": "^0.12.3"
|
"unzipper": "^0.12.3"
|
||||||
},
|
},
|
||||||
|
|
@ -2220,6 +2221,18 @@
|
||||||
"react": "^19.1.1"
|
"react": "^19.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-error-boundary": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-gdlJjD7NWr0IfkPlaREN2d9uUZUlksrfOx7SX62VRerwXbMY6ftGCIZua1VG1aXFNOimhISsTq+Owp725b9SiA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.12.5"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.13.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-reconciler": {
|
"node_modules/react-reconciler": {
|
||||||
"version": "0.31.0",
|
"version": "0.31.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.31.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.31.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
"next": "^15.5.2",
|
"next": "^15.5.2",
|
||||||
"react": "^19.1.1",
|
"react": "^19.1.1",
|
||||||
"react-dom": "^19.1.1",
|
"react-dom": "^19.1.1",
|
||||||
|
"react-error-boundary": "^6.0.0",
|
||||||
"three": "^0.180.0",
|
"three": "^0.180.0",
|
||||||
"unzipper": "^0.12.3"
|
"unzipper": "^0.12.3"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
79
src/components/Item.tsx
Normal file
79
src/components/Item.tsx
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
import { Suspense, useMemo } from "react";
|
||||||
|
import { ErrorBoundary } from "react-error-boundary";
|
||||||
|
import {
|
||||||
|
ConsoleObject,
|
||||||
|
getPosition,
|
||||||
|
getProperty,
|
||||||
|
getRotation,
|
||||||
|
getScale,
|
||||||
|
} from "../mission";
|
||||||
|
import { shapeToUrl } from "../loaders";
|
||||||
|
import { useGLTF } from "@react-three/drei";
|
||||||
|
|
||||||
|
const dataBlockToShapeName = {
|
||||||
|
RepairPack: "pack_upgrade_repair.dts",
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a .glb file that was converted from a .dts, used for static shapes.
|
||||||
|
*/
|
||||||
|
function useStaticShape(shapeName: string) {
|
||||||
|
const url = shapeToUrl(shapeName);
|
||||||
|
return useGLTF(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ShapeModel({ shapeName }: { shapeName: string }) {
|
||||||
|
const { nodes } = useStaticShape(shapeName);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{Object.entries(nodes)
|
||||||
|
.filter(
|
||||||
|
([name, node]: [string, any]) =>
|
||||||
|
!node.material || !node.material.name.match(/\.\d+$/)
|
||||||
|
)
|
||||||
|
.map(([name, node]: [string, any]) => (
|
||||||
|
<mesh geometry={node.geometry} castShadow receiveShadow>
|
||||||
|
<meshStandardMaterial color="cyan" wireframe />
|
||||||
|
</mesh>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ShapePlaceholder({ color }: { color: string }) {
|
||||||
|
return (
|
||||||
|
<mesh>
|
||||||
|
<boxGeometry args={[10, 10, 10]} />
|
||||||
|
<meshStandardMaterial color={color} wireframe />
|
||||||
|
</mesh>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Item({ object }: { object: ConsoleObject }) {
|
||||||
|
const dataBlock = getProperty(object, "dataBlock").value;
|
||||||
|
|
||||||
|
const [z, y, x] = useMemo(() => getPosition(object), [object]);
|
||||||
|
const [scaleX, scaleY, scaleZ] = useMemo(() => getScale(object), [object]);
|
||||||
|
const q = useMemo(() => getRotation(object, true), [object]);
|
||||||
|
|
||||||
|
const shapeName = dataBlockToShapeName[dataBlock];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<group
|
||||||
|
quaternion={q}
|
||||||
|
position={[x - 1024, y, z - 1024]}
|
||||||
|
scale={[-scaleX, scaleY, -scaleZ]}
|
||||||
|
>
|
||||||
|
{shapeName ? (
|
||||||
|
<ErrorBoundary fallback={<ShapePlaceholder color="red" />}>
|
||||||
|
<Suspense fallback={<ShapePlaceholder color="yellow" />}>
|
||||||
|
<ShapeModel shapeName={shapeName} />
|
||||||
|
</Suspense>
|
||||||
|
</ErrorBoundary>
|
||||||
|
) : (
|
||||||
|
<ShapePlaceholder color="orange" />
|
||||||
|
)}
|
||||||
|
</group>
|
||||||
|
);
|
||||||
|
}
|
||||||
80
src/components/StaticShape.tsx
Normal file
80
src/components/StaticShape.tsx
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
import { Suspense, useMemo } from "react";
|
||||||
|
import { ErrorBoundary } from "react-error-boundary";
|
||||||
|
import {
|
||||||
|
ConsoleObject,
|
||||||
|
getPosition,
|
||||||
|
getProperty,
|
||||||
|
getRotation,
|
||||||
|
getScale,
|
||||||
|
} from "../mission";
|
||||||
|
import { shapeToUrl } from "../loaders";
|
||||||
|
import { useGLTF } from "@react-three/drei";
|
||||||
|
|
||||||
|
const dataBlockToShapeName = {
|
||||||
|
StationInventory: "station_inv_human.dts",
|
||||||
|
SensorLargePulse: "sensor_pulse_large.dts",
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a .glb file that was converted from a .dts, used for static shapes.
|
||||||
|
*/
|
||||||
|
function useStaticShape(shapeName: string) {
|
||||||
|
const url = shapeToUrl(shapeName);
|
||||||
|
return useGLTF(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ShapeModel({ shapeName }: { shapeName: string }) {
|
||||||
|
const { nodes } = useStaticShape(shapeName);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{Object.entries(nodes)
|
||||||
|
.filter(
|
||||||
|
([name, node]: [string, any]) =>
|
||||||
|
!node.material || !node.material.name.match(/\.\d+$/)
|
||||||
|
)
|
||||||
|
.map(([name, node]: [string, any]) => (
|
||||||
|
<mesh geometry={node.geometry} castShadow receiveShadow>
|
||||||
|
<meshStandardMaterial color="cyan" wireframe />
|
||||||
|
</mesh>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ShapePlaceholder({ color }: { color: string }) {
|
||||||
|
return (
|
||||||
|
<mesh>
|
||||||
|
<boxGeometry args={[10, 10, 10]} />
|
||||||
|
<meshStandardMaterial color={color} wireframe />
|
||||||
|
</mesh>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function StaticShape({ object }: { object: ConsoleObject }) {
|
||||||
|
const dataBlock = getProperty(object, "dataBlock").value;
|
||||||
|
|
||||||
|
const [z, y, x] = useMemo(() => getPosition(object), [object]);
|
||||||
|
const [scaleX, scaleY, scaleZ] = useMemo(() => getScale(object), [object]);
|
||||||
|
const q = useMemo(() => getRotation(object, true), [object]);
|
||||||
|
|
||||||
|
const shapeName = dataBlockToShapeName[dataBlock];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<group
|
||||||
|
quaternion={q}
|
||||||
|
position={[x - 1024, y, z - 1024]}
|
||||||
|
scale={[-scaleX, scaleY, -scaleZ]}
|
||||||
|
>
|
||||||
|
{shapeName ? (
|
||||||
|
<ErrorBoundary fallback={<ShapePlaceholder color="red" />}>
|
||||||
|
<Suspense fallback={<ShapePlaceholder color="yellow" />}>
|
||||||
|
<ShapeModel shapeName={shapeName} />
|
||||||
|
</Suspense>
|
||||||
|
</ErrorBoundary>
|
||||||
|
) : (
|
||||||
|
<ShapePlaceholder color="orange" />
|
||||||
|
)}
|
||||||
|
</group>
|
||||||
|
);
|
||||||
|
}
|
||||||
56
src/components/TSStatic.tsx
Normal file
56
src/components/TSStatic.tsx
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
import { Suspense, useMemo } from "react";
|
||||||
|
import { ErrorBoundary } from "react-error-boundary";
|
||||||
|
import {
|
||||||
|
ConsoleObject,
|
||||||
|
getPosition,
|
||||||
|
getProperty,
|
||||||
|
getRotation,
|
||||||
|
getScale,
|
||||||
|
} from "../mission";
|
||||||
|
import { shapeToUrl } from "../loaders";
|
||||||
|
import { useGLTF } from "@react-three/drei";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a .glb file that was converted from a .dts, used for static shapes.
|
||||||
|
*/
|
||||||
|
function useStaticShape(shapeName: string) {
|
||||||
|
const url = shapeToUrl(shapeName);
|
||||||
|
return useGLTF(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ShapeModel({ shapeName }: { shapeName: string }) {
|
||||||
|
const { scene } = useStaticShape(shapeName);
|
||||||
|
|
||||||
|
return <primitive object={scene} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ShapePlaceholder({ color }: { color: string }) {
|
||||||
|
return (
|
||||||
|
<mesh>
|
||||||
|
<boxGeometry args={[10, 10, 10]} />
|
||||||
|
<meshStandardMaterial color={color} wireframe />
|
||||||
|
</mesh>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function TSStatic({ object }: { object: ConsoleObject }) {
|
||||||
|
const shapeName = getProperty(object, "shapeName").value;
|
||||||
|
|
||||||
|
const [z, y, x] = useMemo(() => getPosition(object), [object]);
|
||||||
|
const [scaleX, scaleY, scaleZ] = useMemo(() => getScale(object), [object]);
|
||||||
|
const q = useMemo(() => getRotation(object, true), [object]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<group
|
||||||
|
quaternion={q}
|
||||||
|
position={[x - 1024, y, z - 1024]}
|
||||||
|
scale={[-scaleX, scaleY, -scaleZ]}
|
||||||
|
>
|
||||||
|
<ErrorBoundary fallback={<ShapePlaceholder color="red" />}>
|
||||||
|
<Suspense fallback={<ShapePlaceholder color="yellow" />}>
|
||||||
|
<ShapeModel shapeName={shapeName} />
|
||||||
|
</Suspense>
|
||||||
|
</ErrorBoundary>
|
||||||
|
</group>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -5,14 +5,20 @@ import { SimGroup } from "./SimGroup";
|
||||||
import { InteriorInstance } from "./InteriorInstance";
|
import { InteriorInstance } from "./InteriorInstance";
|
||||||
import { Sky } from "./Sky";
|
import { Sky } from "./Sky";
|
||||||
import { Sun } from "./Sun";
|
import { Sun } from "./Sun";
|
||||||
|
import { TSStatic } from "./TSStatic";
|
||||||
|
import { StaticShape } from "./StaticShape";
|
||||||
|
import { Item } from "./Item";
|
||||||
|
|
||||||
const componentMap = {
|
const componentMap = {
|
||||||
SimGroup,
|
|
||||||
TerrainBlock,
|
|
||||||
WaterBlock,
|
|
||||||
InteriorInstance,
|
InteriorInstance,
|
||||||
|
Item,
|
||||||
|
SimGroup,
|
||||||
Sky,
|
Sky,
|
||||||
|
StaticShape,
|
||||||
Sun,
|
Sun,
|
||||||
|
TerrainBlock,
|
||||||
|
TSStatic,
|
||||||
|
WaterBlock,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function renderObject(object: ConsoleObject, key: string | number) {
|
export function renderObject(object: ConsoleObject, key: string | number) {
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,11 @@ export function interiorToUrl(name: string) {
|
||||||
return difUrl.replace(/\.dif$/i, ".gltf");
|
return difUrl.replace(/\.dif$/i, ".gltf");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function shapeToUrl(name: string) {
|
||||||
|
const difUrl = getUrlForPath(`shapes/${name}`);
|
||||||
|
return difUrl.replace(/\.dts$/i, ".glb");
|
||||||
|
}
|
||||||
|
|
||||||
export function terrainTextureToUrl(name: string) {
|
export function terrainTextureToUrl(name: string) {
|
||||||
name = name.replace(/^terrain\./, "");
|
name = name.replace(/^terrain\./, "");
|
||||||
return getUrlForPath(`textures/terrain/${name}.png`, `${BASE_URL}/black.png`);
|
return getUrlForPath(`textures/terrain/${name}.png`, `${BASE_URL}/black.png`);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue