mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-22 19:19:52 +02:00
feat: dynamic model defs
This commit is contained in:
1 parent
3889c0f75d
commit
8ba56069c4
18 files changed
+127
-57
No files matched your search
@@ -1,7 +1,11 @@
|
||||
import { Card, Code, Flex, Text } from '@radix-ui/themes';
|
||||
import { Card, Code, Flex, Text, TextField } from '@radix-ui/themes';
|
||||
import { Html } from '@react-three/drei';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { radToDeg } from 'three/src/math/MathUtils';
|
||||
import { ModelArmor } from '../../../core/blitzkit/modelDefinitions';
|
||||
import { resolveArmorIndex } from '../../../core/blitzkit/resolveArmorIndex';
|
||||
import * as App from '../../../stores/app';
|
||||
import * as Duel from '../../../stores/duel';
|
||||
import * as TankopediaEphemeral from '../../../stores/tankopediaEphemeral';
|
||||
import { layerTypeNames } from './ShotDisplayCard';
|
||||
import { ArmorType } from './SpacedArmorScene';
|
||||
@@ -10,7 +14,14 @@ export function ArmorPlateDisplay() {
|
||||
const highlightArmor = TankopediaEphemeral.use(
|
||||
(state) => state.highlightArmor,
|
||||
);
|
||||
const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation();
|
||||
const developerMode = App.use((state) => state.developerMode);
|
||||
const devThicknessInput = useRef<HTMLInputElement>(null);
|
||||
const duelStore = Duel.useStore();
|
||||
|
||||
useEffect(() => {
|
||||
devThicknessInput.current?.focus();
|
||||
});
|
||||
|
||||
if (highlightArmor === undefined) return null;
|
||||
|
||||
@@ -42,9 +53,60 @@ export function ArmorPlateDisplay() {
|
||||
</Text>
|
||||
)}
|
||||
{developerMode && (
|
||||
<Text mt="2" color="gray" size="2">
|
||||
<b>DEV:</b> <Code>{highlightArmor.name}</Code>
|
||||
</Text>
|
||||
<>
|
||||
<Text mt="2" color="gray" size="2">
|
||||
<b>DEV:</b> <Code>{highlightArmor.name}</Code>
|
||||
</Text>
|
||||
<TextField.Root
|
||||
type="number"
|
||||
style={{ width: 96 }}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === 'Enter') {
|
||||
devThicknessInput.current?.blur();
|
||||
mutateTankopediaEphemeral((draft) => {
|
||||
draft.highlightArmor = undefined;
|
||||
const { protagonist } = duelStore.getState();
|
||||
let armor: ModelArmor;
|
||||
|
||||
if (highlightArmor.name.startsWith('hull_')) {
|
||||
armor = draft.model.armor;
|
||||
} else if (highlightArmor.name.startsWith('turret_')) {
|
||||
armor =
|
||||
draft.model.turrets[protagonist.turret.id].armor;
|
||||
} else if (highlightArmor.name.startsWith('gun_')) {
|
||||
armor =
|
||||
draft.model.turrets[protagonist.turret.id].guns[
|
||||
protagonist.gun.id
|
||||
].armor;
|
||||
} else return;
|
||||
|
||||
const index = resolveArmorIndex(highlightArmor.name);
|
||||
|
||||
if (index === undefined) return;
|
||||
|
||||
const input = event.currentTarget.valueAsNumber;
|
||||
|
||||
if (!isNaN(input)) {
|
||||
armor.thickness[index] = input;
|
||||
}
|
||||
});
|
||||
} else if (event.key === 'Escape') {
|
||||
devThicknessInput.current?.blur();
|
||||
mutateTankopediaEphemeral((draft) => {
|
||||
draft.highlightArmor = undefined;
|
||||
});
|
||||
}
|
||||
}}
|
||||
key={highlightArmor.name}
|
||||
defaultValue={highlightArmor.thickness.toFixed(0)}
|
||||
mt="1"
|
||||
autoFocus
|
||||
ref={devThicknessInput}
|
||||
size="1"
|
||||
>
|
||||
<TextField.Slot side="right">mm</TextField.Slot>
|
||||
</TextField.Root>
|
||||
</>
|
||||
)}
|
||||
</Flex>
|
||||
</Card>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { correctZYTuple } from '../../../core/blitz/correctZYTuple';
|
||||
import { nameToArmorId } from '../../../core/blitzkit/nameToArmorId';
|
||||
import { resolveArmor } from '../../../core/blitzkit/resolveThickness';
|
||||
import { useArmor } from '../../../hooks/useArmor';
|
||||
import { useModelDefinitions } from '../../../hooks/useModelDefinitions';
|
||||
import { useTankModelDefinition } from '../../../hooks/useTankModelDefinition';
|
||||
import { useTankTransform } from '../../../hooks/useTankTransform';
|
||||
import * as Duel from '../../../stores/duel';
|
||||
import * as TankopediaPersistent from '../../../stores/tankopediaPersistent';
|
||||
@@ -13,7 +13,6 @@ import { PrimaryArmorSceneComponent } from './PrimaryArmorSceneComponent';
|
||||
|
||||
export const PrimaryArmorScene = memo(() => {
|
||||
const wrapper = useRef<Group>(null);
|
||||
const modelDefinitions = useModelDefinitions();
|
||||
const turretContainer = useRef<Group>(null);
|
||||
const gunContainer = useRef<Group>(null);
|
||||
const protagonist = Duel.use((draft) => draft.protagonist);
|
||||
@@ -23,7 +22,7 @@ export const PrimaryArmorScene = memo(() => {
|
||||
const gun = Duel.use((state) => state.protagonist.gun);
|
||||
const armorGltf = useArmor(tank.id);
|
||||
const armorNodes = Object.values(armorGltf.nodes);
|
||||
const tankModelDefinition = modelDefinitions[tank.id];
|
||||
const tankModelDefinition = useTankModelDefinition();
|
||||
const trackModelDefinition = tankModelDefinition.tracks[track.id];
|
||||
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
||||
const gunModelDefinition = turretModelDefinition.guns[gun.id];
|
||||
@@ -32,6 +31,12 @@ export const PrimaryArmorScene = memo(() => {
|
||||
const gunOrigin = correctZYTuple(turretModelDefinition.gunOrigin);
|
||||
const tankopediaPersistentStore = TankopediaPersistent.useStore();
|
||||
|
||||
console.log(
|
||||
tankModelDefinition.armor,
|
||||
turretModelDefinition.armor,
|
||||
gunModelDefinition.armor,
|
||||
);
|
||||
|
||||
useTankTransform(protagonist, turretContainer, gunContainer);
|
||||
|
||||
return (
|
||||
|
||||
@@ -5,7 +5,7 @@ import { nameToArmorId } from '../../../core/blitzkit/nameToArmorId';
|
||||
import { resolveArmor } from '../../../core/blitzkit/resolveThickness';
|
||||
import { useArmor } from '../../../hooks/useArmor';
|
||||
import { useModel } from '../../../hooks/useModel';
|
||||
import { useModelDefinitions } from '../../../hooks/useModelDefinitions';
|
||||
import { useTankModelDefinition } from '../../../hooks/useTankModelDefinition';
|
||||
import { useTankTransform } from '../../../hooks/useTankTransform';
|
||||
import * as Duel from '../../../stores/duel';
|
||||
import { ModelTankWrapper } from './ModelTankWrapper';
|
||||
@@ -23,7 +23,6 @@ interface SpacedArmorSceneProps {
|
||||
|
||||
export const SpacedArmorScene = memo<SpacedArmorSceneProps>(({ scene }) => {
|
||||
const wrapper = useRef<Group>(null);
|
||||
const modelDefinitions = useModelDefinitions();
|
||||
const turretContainer = useRef<Group>(null);
|
||||
const gunContainer = useRef<Group>(null);
|
||||
const protagonist = Duel.use((draft) => draft.protagonist);
|
||||
@@ -35,7 +34,7 @@ export const SpacedArmorScene = memo<SpacedArmorSceneProps>(({ scene }) => {
|
||||
const { gltf: modelGltf } = useModel(tank.id);
|
||||
const armorNodes = Object.values(armorGltf.nodes);
|
||||
const modelNodes = Object.values(modelGltf.nodes);
|
||||
const tankModelDefinition = modelDefinitions[tank.id];
|
||||
const tankModelDefinition = useTankModelDefinition();
|
||||
const trackModelDefinition = tankModelDefinition.tracks[track.id];
|
||||
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
||||
const gunModelDefinition = turretModelDefinition.guns[gun.id];
|
||||
|
||||
@@ -92,9 +92,9 @@ export function SpacedArmorSceneComponent({
|
||||
...props
|
||||
}: SpacedArmorSceneComponentProps) {
|
||||
const tankopediaEphemeralStore = TankopediaEphemeral.useStore();
|
||||
const duelStore = Duel.useStore();
|
||||
const mutateTankopediaEphemeralStore = TankopediaEphemeral.useMutation();
|
||||
const camera = useThree((state) => state.camera);
|
||||
const duelStore = Duel.useStore();
|
||||
|
||||
if (props.static) {
|
||||
const x = clamp(thickness / props.thicknessRange.quartile, 0, 1);
|
||||
@@ -134,7 +134,7 @@ export function SpacedArmorSceneComponent({
|
||||
depthWrite,
|
||||
...(clip ? { clippingPlanes: [clip] } : {}),
|
||||
}),
|
||||
[],
|
||||
[thickness],
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -182,7 +182,7 @@ export function SpacedArmorSceneComponent({
|
||||
);
|
||||
|
||||
return unsubscribe;
|
||||
}, []);
|
||||
}, [thickness]);
|
||||
|
||||
return jsxTree(node, {
|
||||
material,
|
||||
|
||||
@@ -5,7 +5,7 @@ import { nameToArmorId } from '../../../core/blitzkit/nameToArmorId';
|
||||
import { resolveArmor } from '../../../core/blitzkit/resolveThickness';
|
||||
import { useArmor } from '../../../hooks/useArmor';
|
||||
import { useModel } from '../../../hooks/useModel';
|
||||
import { useModelDefinitions } from '../../../hooks/useModelDefinitions';
|
||||
import { useTankModelDefinition } from '../../../hooks/useTankModelDefinition';
|
||||
import { useTankTransform } from '../../../hooks/useTankTransform';
|
||||
import * as Duel from '../../../stores/duel';
|
||||
import * as TankopediaPersistent from '../../../stores/tankopediaPersistent';
|
||||
@@ -25,7 +25,6 @@ export interface ThicknessRange {
|
||||
export const StaticArmorScene = memo<StaticArmorSceneProps>(
|
||||
({ thicknessRange }) => {
|
||||
const wrapper = useRef<Group>(null);
|
||||
const awaitedTankModelDefinitions = useModelDefinitions();
|
||||
const turretContainer = useRef<Group>(null);
|
||||
const gunContainer = useRef<Group>(null);
|
||||
const protagonist = Duel.use((draft) => draft.protagonist);
|
||||
@@ -37,7 +36,7 @@ export const StaticArmorScene = memo<StaticArmorSceneProps>(
|
||||
const { gltf: modelGltf } = useModel(tank.id);
|
||||
const armorNodes = Object.values(armorGltf.nodes);
|
||||
const modelNodes = Object.values(modelGltf.nodes);
|
||||
const tankModelDefinition = awaitedTankModelDefinitions[tank.id];
|
||||
const tankModelDefinition = useTankModelDefinition();
|
||||
const trackModelDefinition = tankModelDefinition.tracks[track.id];
|
||||
const turretModelDefinition = tankModelDefinition.turrets[turret.id];
|
||||
const gunModelDefinition = turretModelDefinition.guns[gun.id];
|
||||
@@ -58,6 +57,8 @@ export const StaticArmorScene = memo<StaticArmorSceneProps>(
|
||||
(state) => state.model.visual.showExternalModules,
|
||||
);
|
||||
|
||||
console.log('yeah');
|
||||
|
||||
useTankTransform(protagonist, turretContainer, gunContainer);
|
||||
|
||||
return (
|
||||
|
||||
Reference in new issue
Block a user