mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-11-14 21:26:08 +01:00
feat: prot and anta
This commit is contained in:
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>
|
||||
);
|
||||
});
|
||||
Reference in new issue
Block a user