consolidate shape helpers

This commit is contained in:
Brian Beck 2025-11-14 19:33:44 -08:00
parent 507ddf8d49
commit 6473fd6ec3
6 changed files with 77 additions and 123 deletions

View file

@ -0,0 +1,65 @@
import { Suspense } from "react";
import { useGLTF, useTexture } from "@react-three/drei";
import { BASE_URL, shapeTextureToUrl, shapeToUrl } from "../loaders";
import { setupColor } from "../textureUtils";
const FALLBACK_URL = `${BASE_URL}/black.png`;
/**
* Load a .glb file that was converted from a .dts, used for static shapes.
*/
export function useStaticShape(shapeName: string) {
const url = shapeToUrl(shapeName);
return useGLTF(url);
}
export function ShapeTexture({ materialName }: { materialName: string }) {
const url = shapeTextureToUrl(materialName, FALLBACK_URL);
const texture = useTexture(url, (texture) => setupColor(texture));
return <meshStandardMaterial map={texture} side={2} />;
}
export 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 key={node.id} geometry={node.geometry} castShadow receiveShadow>
{node.material ? (
<Suspense
fallback={
// Allow the mesh to render while the texture is still loading;
// show a wireframe placeholder.
<meshStandardMaterial color="gray" wireframe />
}
>
{Array.isArray(node.material) ? (
node.material.map((mat, index) => (
<ShapeTexture key={index} materialName={mat.name} />
))
) : (
<ShapeTexture materialName={node.material.name} />
)}
</Suspense>
) : null}
</mesh>
))}
</>
);
}
export function ShapePlaceholder({ color }: { color: string }) {
return (
<mesh>
<boxGeometry args={[10, 10, 10]} />
<meshStandardMaterial color={color} wireframe />
</mesh>
);
}

View file

@ -22,13 +22,7 @@ function useInterior(interiorFile: string) {
}
function InteriorTexture({ materialName }: { materialName: string }) {
let url = FALLBACK_URL;
try {
url = interiorTextureToUrl(materialName);
} catch (err) {
console.error(err);
}
const url = interiorTextureToUrl(materialName, FALLBACK_URL);
const texture = useTexture(url, (texture) => setupColor(texture));
return <meshStandardMaterial map={texture} side={2} />;

View file

@ -7,49 +7,12 @@ import {
getRotation,
getScale,
} from "../mission";
import { shapeToUrl } from "../loaders";
import { useGLTF } from "@react-three/drei";
import { ShapeModel, ShapePlaceholder } from "./GenericShape";
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 key={node.id} 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;

View file

@ -7,50 +7,13 @@ import {
getRotation,
getScale,
} from "../mission";
import { shapeToUrl } from "../loaders";
import { useGLTF } from "@react-three/drei";
import { ShapeModel, ShapePlaceholder } from "./GenericShape";
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 key={node.id} 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;

View file

@ -7,44 +7,7 @@ import {
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 { 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 key={node.id} 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>
);
}
import { ShapeModel, ShapePlaceholder } from "./GenericShape";
export function TSStatic({ object }: { object: ConsoleObject }) {
const shapeName = getProperty(object, "shapeName").value;

View file

@ -12,6 +12,7 @@ export function getUrlForPath(resourcePath: string, fallbackUrl?: string) {
sourcePath = getSource(resourcePath);
} catch (err) {
if (fallbackUrl) {
console.error(err);
return fallbackUrl;
} else {
throw err;
@ -39,9 +40,14 @@ export function terrainTextureToUrl(name: string) {
return getUrlForPath(`textures/terrain/${name}.png`, `${BASE_URL}/black.png`);
}
export function interiorTextureToUrl(name: string) {
export function interiorTextureToUrl(name: string, fallbackUrl?: string) {
name = name.replace(/\.\d+$/, "");
return getUrlForPath(`textures/${name}.png`);
return getUrlForPath(`textures/${name}.png`, fallbackUrl);
}
export function shapeTextureToUrl(name: string, fallbackUrl?: string) {
name = name.replace(/\.\d+$/, "");
return getUrlForPath(`textures/skins/${name}.png`, fallbackUrl);
}
export function textureToUrl(name: string) {