feat: prot and anta

This commit is contained in:
TrèsAbhi committed 2024-01-07 13:13:27 -06:00
1 parent 5208cf8678
commit 88a6ab2d95
6 files changed
+480 -412

No files matched your search

@@ -6,8 +6,10 @@ import {
import { Button, Card, Flex, Tabs, Theme } from '@radix-ui/themes';
import { Html } from '@react-three/drei';
import { Canvas } from '@react-three/fiber';
import { Suspense, useEffect, useRef, useState } from 'react';
import { Suspense, use, useEffect, useRef, useState } from 'react';
import { Group } from 'three';
import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits';
import { modelDefinitions } from '../../../../../../core/blitzkrieg/modelDefinitions';
import { theme } from '../../../../../../stitches.config';
import mutateTankopedia, {
TankopediaMode,
@@ -19,19 +21,20 @@ import { RotationInputs } from '../RotationInputs';
import { SceneProps } from '../SceneProps';
import { TankModel } from './components/TankModel';
interface TankDisplayProps {
tankId: number;
turretId: number;
gunId: number;
}
export function TankDisplay({ tankId, turretId, gunId }: TankDisplayProps) {
export function TankDisplay() {
const canvas = useRef<HTMLCanvasElement>(null);
const awaitedModelDefinitions = use(modelDefinitions);
const canvasWrapper = useRef<HTMLDivElement>(null);
const [isFullScreen, setIsFullScreen] = useState(false);
const mode = useTankopedia((state) => state.mode);
const hullContainer = useRef<Group>(null);
const showGrid = useTankopedia((state) => state.model.showGrid);
const protagonist = useTankopedia((state) => {
if (!state.areTanksAssigned) return;
return state.protagonist;
});
if (!protagonist) return null;
function handlePointerDown() {
window.addEventListener('pointermove', handlePointerMove);
@@ -59,6 +62,22 @@ export function TankDisplay({ tankId, turretId, gunId }: TankDisplayProps) {
};
});
useEffect(() => {
const tankModelDefinition = awaitedModelDefinitions[protagonist.tank.id];
const turretModelDefinition =
tankModelDefinition.turrets[protagonist.turret.id];
const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id];
mutateTankopedia((draft) => {
[draft.model.gunPitch, draft.model.turretYaw] = applyPitchYawLimits(
draft.model.gunPitch,
draft.model.turretYaw,
gunModelDefinition.pitch,
turretModelDefinition.yaw,
);
});
}, [protagonist.gun, protagonist.turret]);
return (
<Theme radius={isFullScreen ? 'none' : undefined}>
<Card
@@ -111,12 +130,7 @@ export function TankDisplay({ tankId, turretId, gunId }: TankDisplayProps) {
</Html>
}
>
<TankModel
gunId={gunId}
tankId={tankId}
turretId={turretId}
ref={hullContainer}
/>
<TankModel ref={hullContainer} />
</Suspense>
</Canvas>
</div>
@@ -159,7 +173,7 @@ export function TankDisplay({ tankId, turretId, gunId }: TankDisplayProps) {
</Button>
</Flex>
<RotationInputs gunId={gunId} tankId={tankId} turretId={turretId} />
<RotationInputs />
</Flex>
</Theme>
</Card>
@@ -20,127 +20,127 @@ import { GunContainer } from '../../GunContainer';
import { HullContainer } from '../../HullContainer';
import { TurretContainer } from '../../TurretContainer';
interface TankModelProps {
tankId: number;
turretId: number;
gunId: number;
}
export const TankModel = forwardRef<Group>((_props, ref) => {
// "TypeError: dispatcher.use is not a function"
// const awaitedModelDefinitions = use(modelDefinitions);
const [awaitedModelDefinitions, setAwaitedModelDefinitions] = useState<
ModelDefinitions | undefined
>(undefined);
const protagonist = useTankopedia((state) => {
if (!state.areTanksAssigned) return;
return state.protagonist;
});
export const TankModel = forwardRef<Group, TankModelProps>(
({ tankId, turretId, gunId }, ref) => {
// "TypeError: dispatcher.use is not a function"
// const awaitedModelDefinitions = use(modelDefinitions);
const [awaitedModelDefinitions, setAwaitedModelDefinitions] = useState<
ModelDefinitions | undefined
>(undefined);
const gltf = useLoader(GLTFLoader, `/test/${tankId}.glb`);
const model = useTankopedia((state) => state.model);
const hullContainer = useRef<Group>(null);
const turretContainer = useRef<Group>(null);
const gunContainer = useRef<Group>(null);
if (!protagonist) return null;
useImperativeHandle(ref, () => hullContainer.current!);
useEffect(() => {
(async () => {
setAwaitedModelDefinitions(await modelDefinitions);
})();
}, []);
const gltf = useLoader(GLTFLoader, `/test/${protagonist.tank.id}.glb`);
const model = useTankopedia((state) => state.model);
const hullContainer = useRef<Group>(null);
const turretContainer = useRef<Group>(null);
const gunContainer = useRef<Group>(null);
if (!awaitedModelDefinitions) return null;
useImperativeHandle(ref, () => hullContainer.current!);
useEffect(() => {
(async () => {
setAwaitedModelDefinitions(await modelDefinitions);
})();
}, []);
const tankModelDefinition = awaitedModelDefinitions[tankId];
const turretModelDefinition = tankModelDefinition.turrets[turretId];
const gunModelDefinition = turretModelDefinition.guns[gunId];
const turretOrigin = new Vector3(
tankModelDefinition.turretOrigin[0],
tankModelDefinition.turretOrigin[1],
-tankModelDefinition.turretOrigin[2],
).applyAxisAngle(X_AXIS, Math.PI / 2);
const gunOrigin = new Vector3(
turretModelDefinition.gunOrigin[0],
turretModelDefinition.gunOrigin[1],
-turretModelDefinition.gunOrigin[2],
).applyAxisAngle(X_AXIS, Math.PI / 2);
if (!awaitedModelDefinitions) return null;
return (
<HullContainer
const tankModelDefinition = awaitedModelDefinitions[protagonist.tank.id];
const turretModelDefinition =
tankModelDefinition.turrets[protagonist.turret.id];
const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id];
const turretOrigin = new Vector3(
tankModelDefinition.turretOrigin[0],
tankModelDefinition.turretOrigin[1],
-tankModelDefinition.turretOrigin[2],
).applyAxisAngle(X_AXIS, Math.PI / 2);
const gunOrigin = new Vector3(
turretModelDefinition.gunOrigin[0],
turretModelDefinition.gunOrigin[1],
-turretModelDefinition.gunOrigin[2],
).applyAxisAngle(X_AXIS, Math.PI / 2);
return (
<HullContainer
objects={Object.values(gltf.nodes)}
yaw={model.hullYaw}
ref={hullContainer}
onYawStart={() =>
mutateTankopedia((draft) => {
draft.model.controlsEnabled = false;
})
}
onYawEnd={(yaw) => {
mutateTankopedia((draft) => {
draft.model.controlsEnabled = true;
draft.model.hullYaw = yaw;
});
}}
onTrackStart={() => {
mutateTankopedia((draft) => {
draft.model.controlsEnabled = false;
});
}}
onTrackEnd={() => {
mutateTankopedia((draft) => {
draft.model.controlsEnabled = true;
});
}}
>
<TurretContainer
initialTurretRotation={tankModelDefinition.turretRotation}
gunOrigin={gunOrigin}
ref={turretContainer}
objects={Object.values(gltf.nodes)}
yaw={model.hullYaw}
ref={hullContainer}
model={turretModelDefinition.model}
onYawStart={() =>
mutateTankopedia((draft) => {
draft.model.controlsEnabled = false;
mutateTankopedia((state) => {
state.model.controlsEnabled = false;
})
}
onYawEnd={(yaw) => {
mutateTankopedia((draft) => {
draft.model.controlsEnabled = true;
draft.model.hullYaw = yaw;
});
}}
onTrackStart={() => {
mutateTankopedia((draft) => {
draft.model.controlsEnabled = false;
});
}}
onTrackEnd={() => {
mutateTankopedia((draft) => {
draft.model.controlsEnabled = true;
yawLimits={turretModelDefinition.yaw}
pitchLimits={gunModelDefinition.pitch}
pitch={model.gunPitch}
onYawEnd={(pitch, yaw) => {
mutateTankopedia((state) => {
state.model.controlsEnabled = true;
state.model.gunPitch = pitch;
state.model.turretYaw = yaw;
});
}}
gunContainer={gunContainer}
turretOrigin={turretOrigin}
yaw={model.turretYaw}
>
<TurretContainer
<GunContainer
ref={gunContainer}
initialTurretRotation={tankModelDefinition.turretRotation}
gunOrigin={gunOrigin}
ref={turretContainer}
objects={Object.values(gltf.nodes)}
model={turretModelDefinition.model}
onYawStart={() =>
onPitchStart={() => {
mutateTankopedia((state) => {
state.model.controlsEnabled = false;
})
}
yawLimits={turretModelDefinition.yaw}
});
}}
pitchLimits={gunModelDefinition.pitch}
pitch={model.gunPitch}
onYawEnd={(pitch, yaw) => {
turretContainer={turretContainer}
yaw={model.turretYaw}
onPitchEnd={(pitch, yaw) => {
mutateTankopedia((state) => {
state.model.controlsEnabled = true;
state.model.gunPitch = pitch;
state.model.turretYaw = yaw;
});
}}
gunContainer={gunContainer}
yawLimits={turretModelDefinition.yaw}
gunOrigin={gunOrigin}
pitch={model.gunPitch}
model={gunModelDefinition.model}
objects={Object.values(gltf.nodes)}
turretOrigin={turretOrigin}
yaw={model.turretYaw}
>
<GunContainer
ref={gunContainer}
initialTurretRotation={tankModelDefinition.turretRotation}
onPitchStart={() => {
mutateTankopedia((state) => {
state.model.controlsEnabled = false;
});
}}
pitchLimits={gunModelDefinition.pitch}
turretContainer={turretContainer}
yaw={model.turretYaw}
onPitchEnd={(pitch, yaw) => {
mutateTankopedia((state) => {
state.model.controlsEnabled = true;
state.model.gunPitch = pitch;
state.model.turretYaw = yaw;
});
}}
yawLimits={turretModelDefinition.yaw}
gunOrigin={gunOrigin}
pitch={model.gunPitch}
model={gunModelDefinition.model}
objects={Object.values(gltf.nodes)}
turretOrigin={turretOrigin}
/>
</TurretContainer>
</HullContainer>
);
},
);
/>
</TurretContainer>
</HullContainer>
);
});