feat: rotation inputs

This commit is contained in:
TrèsAbhi committed 2024-05-04 17:14:08 -05:00
1 parent cebc4392ed
commit a099df5133
4 files changed
+32 -51

No files matched your search

@@ -88,6 +88,7 @@ export function HeroSection() {
</Flex> </Flex>
<div <div
className="tank-sandbox-container"
style={{ style={{
flex: 2, flex: 2,
position: isFullScreen ? 'fixed' : 'relative', position: isFullScreen ? 'fixed' : 'relative',
@@ -36,6 +36,7 @@ import mutateTankopediaPersistent, {
} from '../../../../../../../stores/tankopedia'; } from '../../../../../../../stores/tankopedia';
import { TankSearch } from '../../../../components/TankSearch'; import { TankSearch } from '../../../../components/TankSearch';
import { ENVIRONMENTS } from '../../Lighting'; import { ENVIRONMENTS } from '../../Lighting';
import { RotationInputs } from '../../QuickInputs';
export function Options() { export function Options() {
const mode = useTankopediaPersistent((state) => state.mode); const mode = useTankopediaPersistent((state) => state.mode);
@@ -73,6 +74,8 @@ export function Options() {
return ( return (
<> <>
<RotationInputs />
{mode === 'armor' && ( {mode === 'armor' && (
<Flex <Flex
gap="2" gap="2"
@@ -0,0 +1,11 @@
import { style } from '@vanilla-extract/css';
export const container = style({
display: 'none',
selectors: {
'.tank-sandbox-container:hover &': {
display: 'flex',
},
},
});
@@ -1,3 +1,4 @@
import { CaretSortIcon } from '@radix-ui/react-icons';
import { Flex, TextField } from '@radix-ui/themes'; import { Flex, TextField } from '@radix-ui/themes';
import { use, useEffect, useRef } from 'react'; import { use, useEffect, useRef } from 'react';
import { degToRad, radToDeg } from 'three/src/math/MathUtils'; import { degToRad, radToDeg } from 'three/src/math/MathUtils';
@@ -5,28 +6,22 @@ import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawL
import { modelDefinitions } from '../../../../../../core/blitzkit/modelDefinitions'; import { modelDefinitions } from '../../../../../../core/blitzkit/modelDefinitions';
import { modelTransformEvent } from '../../../../../../core/blitzkit/modelTransform'; import { modelTransformEvent } from '../../../../../../core/blitzkit/modelTransform';
import { useEquipment } from '../../../../../../hooks/useEquipment'; import { useEquipment } from '../../../../../../hooks/useEquipment';
import { useFullScreen } from '../../../../../../hooks/useFullScreen';
import { mutateDuel, useDuel } from '../../../../../../stores/duel'; import { mutateDuel, useDuel } from '../../../../../../stores/duel';
import { useTankopediaPersistent } from '../../../../../../stores/tankopedia'; import * as styles from './index.css';
import { QuickEquipmentButton } from './components/QuickEquipmentButton';
interface RotationInputsProps { export function RotationInputs() {
isFullScreen?: boolean;
}
export function RotationInputs({ isFullScreen }: RotationInputsProps) {
const protagonist = useDuel((state) => state.protagonist!); const protagonist = useDuel((state) => state.protagonist!);
const awaitedModelDefinitions = use(modelDefinitions); const awaitedModelDefinitions = use(modelDefinitions);
const turretYawInput = useRef<HTMLInputElement>(null); const turretYawInput = useRef<HTMLInputElement>(null);
const gunPitchInput = useRef<HTMLInputElement>(null); const gunPitchInput = useRef<HTMLInputElement>(null);
const mode = useTankopediaPersistent((state) => state.mode);
const hasCalibratedShells = useEquipment(103, true);
const hasEnhancedArmor = useEquipment(110);
const tankModelDefinition = awaitedModelDefinitions[protagonist.tank.id]; const tankModelDefinition = awaitedModelDefinitions[protagonist.tank.id];
const turretModelDefinition = const turretModelDefinition =
tankModelDefinition.turrets[protagonist.turret.id]; tankModelDefinition.turrets[protagonist.turret.id];
const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id]; const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id];
const initialGunPitch = tankModelDefinition.turretRotation?.pitch ?? 0; const initialGunPitch = tankModelDefinition.turretRotation?.pitch ?? 0;
const hasImprovedVerticalStabilizer = useEquipment(122); const hasImprovedVerticalStabilizer = useEquipment(122);
const isFullScreen = useFullScreen();
useEffect(() => { useEffect(() => {
turretYawInput.current!.value = radToDeg(protagonist.yaw).toFixed(1); turretYawInput.current!.value = radToDeg(protagonist.yaw).toFixed(1);
@@ -39,19 +34,19 @@ export function RotationInputs({ isFullScreen }: RotationInputsProps) {
return ( return (
<Flex <Flex
justify="center" className={isFullScreen ? undefined : styles.container}
align="center" gap="2"
style={{ style={{
width: 'calc(100% - 16px)', width: 128 + 32,
pointerEvents: 'auto',
position: 'absolute', position: 'absolute',
left: 8, left: '50%',
bottom: isFullScreen ? 80 : 8, top: 16,
pointerEvents: 'none', transform: 'translateX(-50%)',
}} }}
gap="4"
> >
<Flex gap="2" style={{ width: 256, pointerEvents: 'auto' }}>
<TextField.Root <TextField.Root
size="1"
radius="full" radius="full"
style={{ style={{
flex: 1, flex: 1,
@@ -77,9 +72,7 @@ export function RotationInputs({ isFullScreen }: RotationInputsProps) {
state.protagonist!.pitch = pitch; state.protagonist!.pitch = pitch;
state.protagonist!.yaw = yaw; state.protagonist!.yaw = yaw;
}); });
turretYawInput.current!.value = radToDeg(protagonist.yaw).toFixed( turretYawInput.current!.value = radToDeg(protagonist.yaw).toFixed(1);
1,
);
}} }}
onKeyDown={(event) => { onKeyDown={(event) => {
if (event.key === 'Enter') { if (event.key === 'Enter') {
@@ -94,12 +87,13 @@ export function RotationInputs({ isFullScreen }: RotationInputsProps) {
userSelect: 'none', userSelect: 'none',
}} }}
> >
Yaw <CaretSortIcon style={{ transform: 'rotate(90deg)' }} />
</TextField.Slot> </TextField.Slot>
<TextField.Slot style={{ userSelect: 'none' }}>°</TextField.Slot> <TextField.Slot style={{ userSelect: 'none' }}>°</TextField.Slot>
</TextField.Root> </TextField.Root>
<TextField.Root <TextField.Root
size="1"
radius="full" radius="full"
style={{ style={{
flex: 1, flex: 1,
@@ -142,7 +136,7 @@ export function RotationInputs({ isFullScreen }: RotationInputsProps) {
userSelect: 'none', userSelect: 'none',
}} }}
> >
Pitch <CaretSortIcon />
</TextField.Slot> </TextField.Slot>
<TextField.Slot <TextField.Slot
style={{ style={{
@@ -153,33 +147,5 @@ export function RotationInputs({ isFullScreen }: RotationInputsProps) {
</TextField.Slot> </TextField.Slot>
</TextField.Root> </TextField.Root>
</Flex> </Flex>
{mode === 'armor' && (
<Flex gap="4" style={{ pointerEvents: 'auto' }}>
<QuickEquipmentButton
equipment={103}
active={hasCalibratedShells}
onClick={() => {
mutateDuel((draft) => {
draft.antagonist!.equipmentMatrix[0][0] = hasCalibratedShells
? 0
: 1;
});
}}
/>
<QuickEquipmentButton
equipment={110}
active={hasEnhancedArmor}
onClick={() => {
mutateDuel((draft) => {
draft.protagonist!.equipmentMatrix[1][1] = hasEnhancedArmor
? 0
: -1;
});
}}
/>
</Flex>
)}
</Flex>
); );
} }