From 88cc37a6af298feb1a5ef2669f280e1de439f068 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Mon, 1 Jan 2024 21:17:22 -0600 Subject: [PATCH] feat: hull rotation --- src/app/tools/tankopedia/[id]/page.tsx | 290 +++++++++++++++++-------- 1 file changed, 205 insertions(+), 85 deletions(-) diff --git a/src/app/tools/tankopedia/[id]/page.tsx b/src/app/tools/tankopedia/[id]/page.tsx index 0878a2cea..b0b7cfbe7 100644 --- a/src/app/tools/tankopedia/[id]/page.tsx +++ b/src/app/tools/tankopedia/[id]/page.tsx @@ -53,7 +53,8 @@ export default function Page({ params }: { params: { id: string } }) { const [crew, setCrew] = useState(100); const [mode, setMode] = useState('model'); const versusTankSearchInput = useRef(null); - const model = useRef(null); + const hullContainer = useRef(null); + const turretContainer = useRef(null); const [versusTankSearchResults, setVersusTankSearchResults] = useState< number[] >([]); @@ -73,8 +74,10 @@ export default function Page({ params }: { params: { id: string } }) { ).applyAxisAngle(new Vector3(1, 0, 0), Math.PI / 2); const gunOrigin = new Vector3(...turret.gunOrigin); const [turretRotation, setTurretRotation] = useState(0); + const [hullRotation, setHullRotation] = useState(0); const [orbitControlsEnabled, setOrbitControlsEnabled] = useState(true); const turretRotationInput = useRef(null); + const hullRotationInput = useRef(null); const gunRotationInput = useRef(null); useEffect(() => { @@ -97,6 +100,11 @@ export default function Page({ params }: { params: { id: string } }) { turretRotation * (180 / Math.PI), )}`; }, [turretRotation]); + useEffect(() => { + hullRotationInput.current!.value = `${Math.round( + hullRotation * (180 / Math.PI), + )}`; + }); return ( @@ -134,7 +142,7 @@ export default function Page({ params }: { params: { id: string } }) { onPointerDown={(event) => event.preventDefault()} camera={{ fov: 20, position: [4, 0, -16] }} > - + @@ -153,57 +161,24 @@ export default function Page({ params }: { params: { id: string } }) { /> - + {gltf.scene.children[0].children.map((child) => { const isHull = child.name === 'hull'; - const isTurret = child.name.startsWith('turret_'); - const isMantlet = - child.name.startsWith('gun_') && - child.name.endsWith('_mask'); - const isGun = child.name.startsWith('gun_') && !isMantlet; - const isVisible = - isHull || - child.name.startsWith('chassis_track_') || - child.name.startsWith('chassis_wheel_') || - (child.name.startsWith('turret_') && - child.name === - `turret_${turret.model - .toString() - .padStart(2, '0')}`) || - (child.name.startsWith('gun_') && - child.name === - `gun_${gun.model.toString().padStart(2, '0')}`) || - child.name === - `gun_${gun.model.toString().padStart(2, '0')}_mask`; + const isWheel = child.name.startsWith('chassis_wheel_'); + const isTrack = child.name.startsWith('chassis_track_'); + const isVisible = isHull || isWheel || isTrack; let draftTurretRotation = 0; - const position = child.position.clone(); - const rotation = new Vector3().setFromEuler( - child.rotation, - ); - - if (!isVisible) return null; - - if (isTurret || isMantlet) { - position - .sub(turretOrigin) - .applyAxisAngle(new Vector3(0, 0, 1), turretRotation) - .add(turretOrigin); - rotation.add(new Vector3(0, 0, turretRotation)); - } else if (isGun) { - position - .sub(turretOrigin) - .applyAxisAngle(new Vector3(0, 0, 1), turretRotation) - .add(turretOrigin); - rotation.add(new Vector3(0, 0, turretRotation)); - } function handlePointerDown( event: ThreeEvent, ) { - if (isTurret) { + if (isHull) { event.stopPropagation(); - draftTurretRotation = turretRotation; + draftTurretRotation = hullRotation; setOrbitControlsEnabled(false); window.addEventListener( @@ -223,7 +198,125 @@ export default function Page({ params }: { params: { id: string } }) { event.movementX * rotationSpeed; draftTurretRotation += deltaTurretRotation; - if (isTurret) { + if (hullContainer.current) { + hullContainer.current.rotation.z = + draftTurretRotation; + } + } + function handlePointerUp(event: PointerEvent) { + setOrbitControlsEnabled(true); + setHullRotation(normalizeAngle180(draftTurretRotation)); + + window.removeEventListener( + 'pointermove', + handlePointerMove, + ); + window.removeEventListener( + 'pointerup', + handlePointerUp, + ); + } + + return ( + + ); + })} + + + {gltf.scene.children[0].children.map((child) => { + const isTurret = child.name.startsWith('turret_'); + const isCurrentTurret = + isTurret && + child.name === + `turret_${turret.model + .toString() + .padStart(2, '0')}`; + const isMantlet = + child.name.startsWith('gun_') && + child.name.endsWith('_mask'); + const isCurrentMantlet = + child.name === + `gun_${gun.model.toString().padStart(2, '0')}_mask`; + const isGun = + child.name.startsWith('gun_') && !isMantlet; + const isCurrentGun = + isGun && + child.name === + `gun_${gun.model.toString().padStart(2, '0')}`; + const isVisible = + isCurrentTurret || isCurrentGun || isCurrentMantlet; + let draftTurretRotation = 0; + const position = child.position.clone(); + const rotation = new Vector3().setFromEuler( + child.rotation, + ); + + if (!isVisible) return null; + + if (isTurret || isMantlet) { + position + .sub(turretOrigin) + .applyAxisAngle( + new Vector3(0, 0, 1), + turretRotation, + ) + .add(turretOrigin); + rotation.add(new Vector3(0, 0, turretRotation)); + } else if (isGun) { + position + .sub(turretOrigin) + .applyAxisAngle( + new Vector3(0, 0, 1), + turretRotation, + ) + .add(turretOrigin); + rotation.add(new Vector3(0, 0, turretRotation)); + } + + function handlePointerDown( + event: ThreeEvent, + ) { + if (isTurret) { + event.stopPropagation(); + + draftTurretRotation = turretRotation; + + setOrbitControlsEnabled(false); + window.addEventListener( + 'pointermove', + handlePointerMove, + ); + window.addEventListener( + 'pointerup', + handlePointerUp, + ); + } + } + function handlePointerMove(event: PointerEvent) { + event.stopPropagation(); + event.preventDefault(); + + const rotationSpeed = + (2 * Math.PI) / canvas.current!.width; + const deltaTurretRotation = + event.movementX * rotationSpeed; + draftTurretRotation += deltaTurretRotation; + if (turretObject3D.current) { turretObject3D.current.position .sub(turretOrigin) @@ -260,48 +353,48 @@ export default function Page({ params }: { params: { id: string } }) { draftTurretRotation; } } - } - function handlePointerUp(event: PointerEvent) { - setOrbitControlsEnabled(true); - setTurretRotation( - normalizeAngle180(draftTurretRotation), - ); + function handlePointerUp(event: PointerEvent) { + setOrbitControlsEnabled(true); + setTurretRotation( + normalizeAngle180(draftTurretRotation), + ); - window.removeEventListener( - 'pointermove', - handlePointerMove, - ); - window.removeEventListener( - 'pointerup', - handlePointerUp, - ); - } + window.removeEventListener( + 'pointermove', + handlePointerMove, + ); + window.removeEventListener( + 'pointerup', + handlePointerUp, + ); + } - return ( - - ); - })} + return ( + + ); + })} + @@ -322,6 +415,33 @@ export default function Page({ params }: { params: { id: string } }) { bottom: 16, }} > + + Hull + { + setHullRotation( + normalizeAngle180( + Number(hullRotationInput.current?.value) * + (Math.PI / 180), + ), + ); + }} + onKeyDown={(event) => { + if (event.key === 'Enter') { + hullRotationInput.current?.blur(); + } + }} + ref={hullRotationInput} + style={{ textAlign: 'right' }} + /> + ° + +