feat: armor modes 2

This commit is contained in:
TrèsAbhi committed 2024-09-22 21:27:46 -05:00
1 parent f1410cf321
commit 2b5ffb2b84
12 files changed
+52 -62

No files matched your search

@@ -22,7 +22,7 @@ export function ArmorPlateDisplay() {
(state) => state.highlightArmor, (state) => state.highlightArmor,
); );
const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation(); const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation();
const developerMode = App.useDeferred(false, (state) => state.developerMode); const developerMode = App.useDeferred((state) => state.developerMode, false);
const duelStore = Duel.useStore(); const duelStore = Duel.useStore();
const input = useRef<HTMLInputElement>(null); const input = useRef<HTMLInputElement>(null);
const tankopediaEphemeralStore = TankopediaEphemeral.useStore(); const tankopediaEphemeralStore = TankopediaEphemeral.useStore();
@@ -87,8 +87,8 @@ export const PrimaryArmorScene = memo(() => {
return null; return null;
return ( return (
<group position={hullOrigin}> <group position={hullOrigin} key={node.uuid}>
<group key={node.uuid} position={turretOrigin}> <group position={turretOrigin}>
<PrimaryArmorSceneComponent <PrimaryArmorSceneComponent
key={node.uuid} key={node.uuid}
thickness={thickness} thickness={thickness}
@@ -121,11 +121,8 @@ export const PrimaryArmorScene = memo(() => {
return null; return null;
return ( return (
<group position={hullOrigin}> <group position={hullOrigin} key={node.uuid}>
<group <group position={turretOrigin.clone().add(gunOrigin)}>
key={node.uuid}
position={turretOrigin.clone().add(gunOrigin)}
>
<PrimaryArmorSceneComponent <PrimaryArmorSceneComponent
thickness={thickness} thickness={thickness}
node={node} node={node}
@@ -1,5 +1,5 @@
import { K_HAT } from '@blitzkit/core'; import { J_HAT, K_HAT } from '@blitzkit/core';
import { Box, Text } from '@radix-ui/themes'; import { Box, Flex, Text } from '@radix-ui/themes';
import { Html } from '@react-three/drei'; import { Html } from '@react-three/drei';
import { useFrame } from '@react-three/fiber'; import { useFrame } from '@react-three/fiber';
import { clamp } from 'lodash-es'; import { clamp } from 'lodash-es';
@@ -183,7 +183,7 @@ export function ShotDisplay() {
</Box> </Box>
</Html> </Html>
{/* {[...shot.in.layers, ...(shot.out?.layers ?? [])].map((layer, index) => { {[...shot.in.layers, ...(shot.out?.layers ?? [])].map((layer, index) => {
if (layer.type === null) return null; if (layer.type === null) return null;
const shotStatusColor = const shotStatusColor =
@@ -276,7 +276,7 @@ export function ShotDisplay() {
/> />
</mesh> </mesh>
</group> </group>
)} */} )}
</group> </group>
); );
} }
@@ -1,9 +1,19 @@
import { Flex, Text } from '@radix-ui/themes'; import {
Card,
Flex,
Inset,
Separator,
Text,
type CardProps,
} from '@radix-ui/themes';
import type { ComponentProps } from 'react'; import type { ComponentProps } from 'react';
import { radToDeg } from 'three/src/math/MathUtils.js';
import type { import type {
Shot,
ShotLayer, ShotLayer,
ShotStatus, ShotStatus,
} from '../../../stores/tankopediaEphemeral'; } from '../../../stores/tankopediaEphemeral';
import { shotStatusColors } from './ShotDisplay';
import { ArmorType } from './SpacedArmorScene'; import { ArmorType } from './SpacedArmorScene';
import type { ExternalModuleVariant } from './SpacedArmorSceneComponent'; import type { ExternalModuleVariant } from './SpacedArmorSceneComponent';
@@ -123,8 +123,8 @@ export const SpacedArmorScene = memo<SpacedArmorSceneProps>(({ scene }) => {
return null; return null;
return ( return (
<group position={hullOrigin}> <group position={hullOrigin} key={node.uuid}>
<group key={node.uuid} position={turretOrigin}> <group position={turretOrigin}>
<SpacedArmorSceneComponent <SpacedArmorSceneComponent
scene={scene} scene={scene}
key={node.uuid} key={node.uuid}
@@ -158,11 +158,8 @@ export const SpacedArmorScene = memo<SpacedArmorSceneProps>(({ scene }) => {
return null; return null;
return ( return (
<group position={hullOrigin}> <group position={hullOrigin} key={node.uuid}>
<group <group position={turretOrigin.clone().add(gunOrigin)}>
key={node.uuid}
position={turretOrigin.clone().add(gunOrigin)}
>
<SpacedArmorSceneComponent <SpacedArmorSceneComponent
scene={scene} scene={scene}
type={spaced ? ArmorType.Spaced : ArmorType.Primary} type={spaced ? ArmorType.Spaced : ArmorType.Primary}
@@ -1,7 +1,5 @@
import { EyeClosedIcon, EyeOpenIcon, ReloadIcon } from '@radix-ui/react-icons'; import { EyeClosedIcon, EyeOpenIcon, ReloadIcon } from '@radix-ui/react-icons';
import { Box, Button, Checkbox, Flex, Text } from '@radix-ui/themes'; import { Box, Button, Checkbox, Flex, Text } from '@radix-ui/themes';
import { useArmor } from '../../../../../../hooks/useArmor';
import { Duel } from '../../../../../../stores/duel';
import { TankopediaEphemeral } from '../../../../../../stores/tankopediaEphemeral'; import { TankopediaEphemeral } from '../../../../../../stores/tankopediaEphemeral';
import { TankopediaPersistent } from '../../../../../../stores/tankopediaPersistent'; import { TankopediaPersistent } from '../../../../../../stores/tankopediaPersistent';
import type { ThicknessRange } from '../../../../../Armor/components/StaticArmor'; import type { ThicknessRange } from '../../../../../Armor/components/StaticArmor';
@@ -21,13 +19,10 @@ export function Thicknesses({ thicknessRange }: ThicknessesProps) {
const showPrimaryArmor = TankopediaPersistent.use( const showPrimaryArmor = TankopediaPersistent.use(
(state) => state.showPrimaryArmor, (state) => state.showPrimaryArmor,
); );
const mutateDuel = Duel.useMutation();
const mutateTankopediaPersistent = TankopediaPersistent.useMutation(); const mutateTankopediaPersistent = TankopediaPersistent.useMutation();
const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation(); const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation();
const editStatic = TankopediaEphemeral.use((state) => state.editStatic); const editStatic = TankopediaEphemeral.use((state) => state.editStatic);
const protagonistTank = Duel.use((state) => state.protagonist.tank);
const tankopediaEphemeralStore = TankopediaEphemeral.useStore(); const tankopediaEphemeralStore = TankopediaEphemeral.useStore();
const { hasDynamicArmor } = useArmor(protagonistTank.id);
return ( return (
<Flex <Flex
@@ -53,7 +53,10 @@ interface OptionsProps {
} }
export function Options({ thicknessRange, canvas }: OptionsProps) { export function Options({ thicknessRange, canvas }: OptionsProps) {
const display = TankopediaPersistent.use((state) => state.display); const display = TankopediaPersistent.useDeferred(
(state) => state.display,
TankopediaDisplay.Model,
);
const isFullScreen = useFullScreen(); const isFullScreen = useFullScreen();
const showGrid = TankopediaPersistent.use((state) => state.showGrid); const showGrid = TankopediaPersistent.use((state) => state.showGrid);
const showEnvironment = TankopediaPersistent.use( const showEnvironment = TankopediaPersistent.use(
@@ -45,7 +45,10 @@ export const TankSandbox = forwardRef<HTMLCanvasElement, TankSandboxProps>(
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 display = TankopediaPersistent.use((state) => state.display); const display = TankopediaPersistent.useDeferred(
(state) => state.display,
TankopediaDisplay.Model,
);
const onScreen = useOnScreen(canvas); const onScreen = useOnScreen(canvas);
useImperativeHandle(ref, () => canvas.current!, []); useImperativeHandle(ref, () => canvas.current!, []);
@@ -1,6 +1,6 @@
import { resolveNearPenetration, tankDefinitions } from '@blitzkit/core'; import { resolveNearPenetration, tankDefinitions } from '@blitzkit/core';
import { Box, Flex, Heading, Text } from '@radix-ui/themes'; import { Box, Flex, Heading, Text } from '@radix-ui/themes';
import { Suspense, useEffect, useMemo, useRef, useState } from 'react'; import { Suspense, useEffect, useMemo, useRef } from 'react';
import { NAVBAR_HEIGHT } from '../../../constants/navbar'; import { NAVBAR_HEIGHT } from '../../../constants/navbar';
import { Var } from '../../../core/radix/var'; import { Var } from '../../../core/radix/var';
import { useFullScreen } from '../../../hooks/useFullScreen'; import { useFullScreen } from '../../../hooks/useFullScreen';
@@ -18,7 +18,7 @@ export function HeroSection() {
const isFullScreen = useFullScreen(); const isFullScreen = useFullScreen();
const protagonist = Duel.use((state) => state.protagonist.tank); const protagonist = Duel.use((state) => state.protagonist.tank);
const Icon = classIcons[protagonist.class]; const Icon = classIcons[protagonist.class];
const [dummyLoader, setDummyLoader] = useState(true); // const [dummyLoader, setDummyLoader] = useState(true);
const treeColor = const treeColor =
protagonist.treeType === 'collector' protagonist.treeType === 'collector'
? 'blue' ? 'blue'
@@ -46,7 +46,7 @@ export function HeroSection() {
}, [protagonist]); }, [protagonist]);
useEffect(() => { useEffect(() => {
setDummyLoader(false); // setDummyLoader(false);
}, []); }, []);
return ( return (
@@ -109,19 +109,7 @@ export function HeroSection() {
> >
<Box position="absolute" width="100%" height="100%"> <Box position="absolute" width="100%" height="100%">
<Box width="100%" height="100%"> <Box width="100%" height="100%">
<TankSandboxLoader <Suspense fallback={<TankSandboxLoader id={protagonist.id} />}>
id={protagonist.id}
display={dummyLoader ? 'flex' : 'none'}
/>
<Suspense
fallback={
<TankSandboxLoader
id={protagonist.id}
display={dummyLoader ? 'none' : 'flex'}
/>
}
>
<TankSandbox ref={canvas} thicknessRange={thicknessRange} /> <TankSandbox ref={canvas} thicknessRange={thicknessRange} />
</Suspense> </Suspense>
</Box> </Box>
@@ -1,10 +1,11 @@
import { formatCompact } from '@blitzkit/core'; import { formatCompact } from '@blitzkit/core';
import { useStore } from '@nanostores/react';
import { Flex, Heading, Skeleton, Text } from '@radix-ui/themes'; import { Flex, Heading, Skeleton, Text } from '@radix-ui/themes';
import { memo } from 'react'; import { memo } from 'react';
import { WargamingLoginButton } from '../../../../../../../../../components/Navbar/components/WargamingLoginButton'; import { useTankVotes } from '../../../../../hooks/useTankVotes';
import { useTankVotes } from '../../../../../../../../../hooks/useTankVotes'; import { Duel } from '../../../../../stores/duel';
import * as App from '../../../../../../../../../stores/app'; import { $wargamingLogin } from '../../../../../stores/wargamingLogin';
import * as Duel from '../../../../../../../../../stores/duel'; import { WargamingLoginButton } from '../../../../WargamingLoginButton';
import { StarRow } from './components/StarRow'; import { StarRow } from './components/StarRow';
import { VoteCaster } from './components/VoteCaster'; import { VoteCaster } from './components/VoteCaster';
@@ -12,10 +13,7 @@ export const Votes = memo(
() => { () => {
const id = Duel.use((state) => state.protagonist.tank.id); const id = Duel.use((state) => state.protagonist.tank.id);
const votes = useTankVotes(id); const votes = useTankVotes(id);
const wargaming = App.useDeferred( const wargaming = useStore($wargamingLogin);
undefined,
(state) => state.logins.wargaming,
);
return ( return (
<Flex direction="column" gap="3"> <Flex direction="column" gap="3">
@@ -6,23 +6,22 @@ import {
} from '@blitzkit/core'; } from '@blitzkit/core';
import strings from '@blitzkit/core/lang/en-US.json'; import strings from '@blitzkit/core/lang/en-US.json';
import { ChevronLeftIcon, MixIcon, UpdateIcon } from '@radix-ui/react-icons'; import { ChevronLeftIcon, MixIcon, UpdateIcon } from '@radix-ui/react-icons';
import { Button, Code, Dialog, Flex } from '@radix-ui/themes'; import { Button, Code, Dialog, Flex, Link } from '@radix-ui/themes';
import { useState } from 'react'; import { useState } from 'react';
import { classIcons } from '../../../../../../../components/ClassIcon'; import { tankToDuelMember } from '../../../core/blitzkit/tankToDuelMember';
import { Link } from '../../../../../../../components/Link'; import { App } from '../../../stores/app';
import { ScienceIcon } from '../../../../../../../components/ScienceIcon'; import { Duel } from '../../../stores/duel';
import { tankToDuelMember } from '../../../../../../../core/blitzkit/tankToDuelMember'; import { TankopediaEphemeral } from '../../../stores/tankopediaEphemeral';
import * as App from '../../../../../../../stores/app'; import { classIcons } from '../../ClassIcon';
import * as Duel from '../../../../../../../stores/duel'; import { ScienceIcon } from '../../ScienceIcon';
import * as TankopediaEphemeral from '../../../../../../../stores/tankopediaEphemeral'; import { TankSearch } from '../../TankSearch';
import { TankSearch } from '../../../../components/TankSearch';
import { Listing } from './components/Listing'; import { Listing } from './components/Listing';
const awaitedProvisionDefinitions = await provisionDefinitions; const awaitedProvisionDefinitions = await provisionDefinitions;
const awaitedModelDefinitions = await modelDefinitions; const awaitedModelDefinitions = await modelDefinitions;
export function MetaSection() { export function MetaSection() {
const developerMode = App.useDeferred(false, (state) => state.developerMode); const developerMode = App.useDeferred((state) => state.developerMode, false);
const protagonist = Duel.use((state) => state.protagonist.tank); const protagonist = Duel.use((state) => state.protagonist.tank);
const ClassIcon = classIcons[protagonist.class]; const ClassIcon = classIcons[protagonist.class];
const antagonist = Duel.use((state) => state.antagonist.tank); const antagonist = Duel.use((state) => state.antagonist.tank);
@@ -58,8 +58,8 @@ export function createContextualStore<
} }
function useDeferred<Slice = Type>( function useDeferred<Slice = Type>(
initial: Slice,
selector: (store: Type) => Slice = (state) => state as Slice, selector: (store: Type) => Slice = (state) => state as Slice,
initial: Slice,
) { ) {
const [state, setState] = useState(initial); const [state, setState] = useState(initial);
const trueState = use(selector); const trueState = use(selector);