feat: code split

This commit is contained in:
TrèsAbhi committed 2024-01-04 13:06:40 -06:00
1 parent 2cf0bda352
commit 0a4e696bc1
15 files changed
+308 -121

No files matched your search

@@ -3,15 +3,16 @@ import { useThree } from '@react-three/fiber';
import { RefObject, useEffect, useRef } from 'react';
import { Box3, Object3D } from 'three';
import { OrbitControls as OrbitControlsClass } from 'three-stdlib';
import { useTankopedia } from '../../../../../stores/tankopedia';
interface ControlsProps {
enabled: boolean;
fit: RefObject<Object3D>;
}
export function Controls({ enabled, fit }: ControlsProps) {
export function Controls({ fit }: ControlsProps) {
const camera = useThree((state) => state.camera);
const orbitControls = useRef<OrbitControlsClass>(null);
const enabled = useTankopedia((state) => state.model.controlsEnabled);
useEffect(() => {
const box = new Box3().setFromObject(fit.current!);
@@ -0,0 +1,126 @@
import { useLoader } from '@react-three/fiber';
import { forwardRef, use, useImperativeHandle, useRef } from 'react';
import { Group, Vector3 } from 'three';
import { GLTFLoader } from 'three-stdlib';
import { X_AXIS } from '../../../../../constants/axis';
import { modelDefinitions } from '../../../../../core/blitzkrieg/modelDefinitions';
import mutateTankopedia, {
useTankopedia,
} from '../../../../../stores/tankopedia';
import { GunContainer } from './GunContainer';
import { HullContainer } from './HullContainer';
import { TurretContainer } from './TurretContainer';
interface ModelProps {
tankId: number;
gunId: number;
turretId: number;
}
export const Model = forwardRef<Group, ModelProps>(
({ gunId, tankId, turretId }, ref) => {
const awaitedModelDefinitions = use(modelDefinitions);
const model = useTankopedia((state) => state.model);
const gltf = useLoader(GLTFLoader, `/test/${tankId}.glb`);
const gunContainer = useRef<Group>(null);
const hullContainer = useRef<Group>(null);
const turretContainer = useRef<Group>(null);
useImperativeHandle(ref, () => hullContainer.current!);
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);
return (
<HullContainer
objects={gltf.scene.children[0].children}
yaw={model.hullYaw}
ref={hullContainer}
onYawStart={() =>
mutateTankopedia((state) => {
state.model.controlsEnabled = false;
})
}
onYawEnd={(yaw) => {
mutateTankopedia((state) => {
state.model.controlsEnabled = true;
state.model.hullYaw = yaw;
});
}}
onTrackStart={() => {
mutateTankopedia((state) => {
state.model.controlsEnabled = false;
});
}}
onTrackEnd={() => {
mutateTankopedia((state) => {
state.model.controlsEnabled = true;
});
}}
>
<TurretContainer
initialTurretRotation={tankModelDefinition.turretRotation}
gunOrigin={gunOrigin}
ref={turretContainer}
objects={gltf.scene.children[0].children}
model={turretModelDefinition.model}
onYawStart={() =>
mutateTankopedia((state) => {
state.model.controlsEnabled = false;
})
}
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}
>
<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={gltf.scene.children[0].children}
turretOrigin={turretOrigin}
/>
</TurretContainer>
</HullContainer>
);
},
);
@@ -0,0 +1,150 @@
import { Flex, TextField } from '@radix-ui/themes';
import { clamp } from 'lodash';
import { use, useEffect, useRef } from 'react';
import { modelDefinitions } from '../../../../../core/blitzkrieg/modelDefinitions';
import { normalizeAnglePI } from '../../../../../core/math/normalizeAngle180';
import mutateTankopedia, {
useTankopedia,
} from '../../../../../stores/tankopedia';
interface RotationInputsProps {
tankId: number;
gunId: number;
turretId: number;
}
export function RotationInputs({
tankId,
gunId,
turretId,
}: RotationInputsProps) {
const model = useTankopedia((state) => state.model);
const awaitedModelDefinitions = use(modelDefinitions);
const turretYawInput = useRef<HTMLInputElement>(null);
const hullYawInput = useRef<HTMLInputElement>(null);
const gunPitchInput = useRef<HTMLInputElement>(null);
const tankModelDefinition = awaitedModelDefinitions[tankId];
const turretModelDefinition = tankModelDefinition.turrets[turretId];
const gunModelDefinition = turretModelDefinition.guns[gunId];
useEffect(() => {
hullYawInput.current!.value = `${-Math.round(
model.hullYaw * (180 / Math.PI),
)}`;
}, [model.hullYaw]);
useEffect(() => {
turretYawInput.current!.value = `${-Math.round(
model.turretYaw * (180 / Math.PI),
)}`;
}, [model.turretYaw]);
useEffect(() => {
gunPitchInput.current!.value = `${-Math.round(
model.gunPitch * (180 / Math.PI),
)}`;
}, [model.gunPitch]);
return (
<Flex
gap="2"
align="center"
style={{
position: 'absolute',
left: 16,
bottom: 16,
}}
>
<TextField.Root
variant="surface"
style={{
width: 115,
}}
>
<TextField.Slot>Hull</TextField.Slot>
<TextField.Input
defaultValue={Math.round(model.hullYaw * (180 / Math.PI))}
onBlur={() => {
const normalized = normalizeAnglePI(
-Number(hullYawInput.current?.value) * (Math.PI / 180),
);
mutateTankopedia((state) => {
state.model.hullYaw = normalized;
});
hullYawInput.current!.value = `${Math.round(normalized)}`;
}}
onKeyDown={(event) => {
if (event.key === 'Enter') {
hullYawInput.current?.blur();
}
}}
onFocus={() => hullYawInput.current?.focus()}
ref={hullYawInput}
style={{ textAlign: 'right' }}
/>
<TextField.Slot>°</TextField.Slot>
</TextField.Root>
<TextField.Root
variant="surface"
style={{
width: 115,
}}
>
<TextField.Slot>Turret</TextField.Slot>
<TextField.Input
defaultValue={Math.round(model.turretYaw * (180 / Math.PI))}
onBlur={() => {
const normalized = normalizeAnglePI(
-Number(turretYawInput.current?.value) * (Math.PI / 180),
);
mutateTankopedia((state) => {
state.model.turretYaw = normalized;
});
turretYawInput.current!.value = `${Math.round(normalized)}`;
}}
onKeyDown={(event) => {
if (event.key === 'Enter') {
turretYawInput.current?.blur();
}
}}
onFocus={() => turretYawInput.current?.focus()}
ref={turretYawInput}
style={{ textAlign: 'right' }}
/>
<TextField.Slot>°</TextField.Slot>
</TextField.Root>
<TextField.Root
variant="surface"
style={{
width: 115,
}}
>
<TextField.Slot>Gun</TextField.Slot>
<TextField.Input
defaultValue={-Math.round(model.gunPitch * (180 / Math.PI))}
onBlur={() => {
const clamped = clamp(
Number(gunPitchInput.current?.value),
gunModelDefinition.pitch.min,
gunModelDefinition.pitch.max,
);
mutateTankopedia((state) => {
state.model.gunPitch = -clamped * (Math.PI / 180);
});
gunPitchInput.current!.value = `${Math.round(clamped)}`;
}}
onKeyDown={(event) => {
if (event.key === 'Enter') {
gunPitchInput.current?.blur();
}
}}
onFocus={() => gunPitchInput.current?.focus()}
ref={gunPitchInput}
style={{ textAlign: 'right' }}
/>
<TextField.Slot>°</TextField.Slot>
</TextField.Root>
</Flex>
);
}