From f86a4022ea1d006b1cae0ea4e8209b3e13231a50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Mon, 29 Jul 2024 14:08:52 -0500 Subject: [PATCH] feat: armor toggle buttons --- .../[id]/components/Model/HeroSection.tsx | 59 +++- .../[id]/components/Model/TankSandbox.tsx | 9 +- .../components/Model/components/Options.tsx | 22 +- .../[id]/components/QuickInputs/index.tsx | 6 +- .../[id]/components/Thicknesses.tsx | 130 +++++++++ .../SpacedArmorSceneComponent/index.tsx | 255 +++++++++--------- .../components/StaticArmorScene.tsx | 59 +--- src/components/StaticArmor/index.tsx | 24 +- src/stores/tankopediaPersistent/index.ts | 4 + 9 files changed, 353 insertions(+), 215 deletions(-) create mode 100644 src/app/tools/tankopedia/[id]/components/Thicknesses.tsx diff --git a/src/app/tools/tankopedia/[id]/components/Model/HeroSection.tsx b/src/app/tools/tankopedia/[id]/components/Model/HeroSection.tsx index 06799d6f9..931213969 100644 --- a/src/app/tools/tankopedia/[id]/components/Model/HeroSection.tsx +++ b/src/app/tools/tankopedia/[id]/components/Model/HeroSection.tsx @@ -1,8 +1,11 @@ import { ChevronLeftIcon, MixIcon } from '@radix-ui/react-icons'; import { Box, Button, Flex, Heading, Text } from '@radix-ui/themes'; import Link from 'next/link'; -import { Suspense, useEffect, useState } from 'react'; +import { Suspense, use, useEffect, useMemo, useState } from 'react'; import { classIcons } from '../../../../../../components/ClassIcon'; +import { ThicknessRange } from '../../../../../../components/StaticArmor/components/StaticArmorScene'; +import { modelDefinitions } from '../../../../../../core/blitzkit/modelDefinitions'; +import { tankDefinitions } from '../../../../../../core/blitzkit/tankDefinitions'; import { TIER_ROMAN_NUMERALS } from '../../../../../../core/blitzkit/tankDefinitions/constants'; import { useFullScreen } from '../../../../../../hooks/useFullScreen'; import strings from '../../../../../../lang/en-US.json'; @@ -11,7 +14,11 @@ import { Options } from './components/Options'; import { TankSandbox } from './TankSandbox'; import { TankSandboxLoader } from './TankSandboxLoader'; -export function HeroSection({ id }: { id: number }) { +interface HeroSectionProps { + id: number; +} + +export function HeroSection({ id }: HeroSectionProps) { const protagonist = Duel.use((state) => state.protagonist.tank); const antagonist = Duel.use((state) => state.antagonist.tank); const compareTanks = @@ -27,6 +34,50 @@ export function HeroSection({ id }: { id: number }) { : protagonist.treeType === 'premium' ? 'amber' : undefined; + const awaitedTankDefinitions = use(tankDefinitions); + const awaitedModelDefinitions = use(modelDefinitions); + const tank = awaitedTankDefinitions[id]; + const thicknessRange = useMemo(() => { + const thicknesses = Object.values(awaitedTankDefinitions) + .filter((thisTank) => thisTank.tier === tank.tier) + .map((tank) => ({ + model: awaitedModelDefinitions[tank.id], + id: tank.id, + })) + .filter(Boolean) + .map(({ model, id }) => { + const tankThicknesses = Object.values(model.armor.thickness); + const turretThicknesses = Object.values(model.turrets) + .map((turret) => { + const turretThicknesses = Object.values(turret.armor.thickness); + const gunThicknesses = Object.values(turret.guns) + .map((gun) => Object.values(gun.armor.thickness)) + .flat(); + + return [...turretThicknesses, ...gunThicknesses]; + }) + .flat(); + const totalThicknesses = [...tankThicknesses, ...turretThicknesses]; + + return totalThicknesses; + }) + .flat(); + + const sortedThicknesses = thicknesses.sort((a, b) => a - b); + const quartileIndex = (1 - 2 ** -6) * (sortedThicknesses.length + 1) - 1; + let quartile: number; + + if (Number.isInteger(quartileIndex)) { + quartile = sortedThicknesses[quartileIndex]; + } else { + quartile = + (sortedThicknesses[Math.floor(quartileIndex)] + + sortedThicknesses[Math.ceil(quartileIndex)]) / + 2; + } + + return { quartile } satisfies ThicknessRange; + }, [tank.tier]); useEffect(() => { setDummyLoader(false); @@ -129,11 +180,11 @@ export function HeroSection({ id }: { id: number }) { /> } > - + - + diff --git a/src/app/tools/tankopedia/[id]/components/Model/TankSandbox.tsx b/src/app/tools/tankopedia/[id]/components/Model/TankSandbox.tsx index ffd7a967b..dd66c984f 100644 --- a/src/app/tools/tankopedia/[id]/components/Model/TankSandbox.tsx +++ b/src/app/tools/tankopedia/[id]/components/Model/TankSandbox.tsx @@ -4,6 +4,7 @@ import { Armor } from '../../../../../../components/Armor'; import { ArmorPlateDisplay } from '../../../../../../components/Armor/components/ArmorPlateDisplay'; import { ShotDisplay } from '../../../../../../components/Armor/components/ShotDisplay'; import { StaticArmor } from '../../../../../../components/StaticArmor'; +import { ThicknessRange } from '../../../../../../components/StaticArmor/components/StaticArmorScene'; import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits'; import { modelDefinitions } from '../../../../../../core/blitzkit/modelDefinitions'; import { modelTransformEvent } from '../../../../../../core/blitzkit/modelTransform'; @@ -20,7 +21,11 @@ import { SceneProps } from '../SceneProps'; import { ModelLoader } from './components/ModelLoader'; import { TankModel } from './components/TankModel'; -export function TankSandbox() { +interface TankSandboxProps { + thicknessRange: ThicknessRange; +} + +export function TankSandbox({ thicknessRange }: TankSandboxProps) { const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation(); const canvas = useRef(null); const hasImprovedVerticalStabilizer = useEquipment(122); @@ -165,7 +170,7 @@ export function TankSandbox() { }> {display === TankopediaDisplay.DynamicArmor && } {display === TankopediaDisplay.StaticArmor && ( - + )} diff --git a/src/app/tools/tankopedia/[id]/components/Model/components/Options.tsx b/src/app/tools/tankopedia/[id]/components/Model/components/Options.tsx index 46d1f6d53..61898b218 100644 --- a/src/app/tools/tankopedia/[id]/components/Model/components/Options.tsx +++ b/src/app/tools/tankopedia/[id]/components/Model/components/Options.tsx @@ -22,6 +22,7 @@ import { import { useEffect, useState } from 'react'; import { ModuleButton } from '../../../../../../../components/ModuleButtons/ModuleButton'; import { SmallTankIcon } from '../../../../../../../components/SmallTankIcon'; +import { ThicknessRange } from '../../../../../../../components/StaticArmor/components/StaticArmorScene'; import { resolveNearPenetration } from '../../../../../../../core/blitz/resolveNearPenetration'; import { resolvePenetrationCoefficient } from '../../../../../../../core/blitz/resolvePenetrationCoefficient'; import { asset } from '../../../../../../../core/blitzkit/asset'; @@ -42,9 +43,14 @@ import * as TankopediaPersistent from '../../../../../../../stores/tankopediaPer import { TankopediaDisplay } from '../../../../../../../stores/tankopediaPersistent/constants'; import { TankSearch } from '../../../../components/TankSearch'; import { ENVIRONMENTS } from '../../Lighting'; -import { RotationInputs } from '../../QuickInputs'; +import { QuickInputs } from '../../QuickInputs'; +import { Thicknesses } from '../../Thicknesses'; -export function Options() { +interface OptionsProps { + thicknessRange: ThicknessRange; +} + +export function Options({ thicknessRange }: OptionsProps) { const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation(); const mutateTankopediaPersistent = TankopediaPersistent.useMutation(); const displayRaw = TankopediaPersistent.use((state) => state.display); @@ -113,7 +119,11 @@ export function Options() { )} - + + + {display === TankopediaDisplay.StaticArmor && ( + + )} {display === TankopediaDisplay.DynamicArmor && ( - + - + - + diff --git a/src/app/tools/tankopedia/[id]/components/QuickInputs/index.tsx b/src/app/tools/tankopedia/[id]/components/QuickInputs/index.tsx index 3c04fd8e7..4ee0350e9 100644 --- a/src/app/tools/tankopedia/[id]/components/QuickInputs/index.tsx +++ b/src/app/tools/tankopedia/[id]/components/QuickInputs/index.tsx @@ -9,12 +9,10 @@ import { ModelTransformEventData, } from '../../../../../../core/blitzkit/modelTransform'; import { useEquipment } from '../../../../../../hooks/useEquipment'; -import { useFullScreen } from '../../../../../../hooks/useFullScreen'; import * as Duel from '../../../../../../stores/duel'; -import * as TankopediaPersistent from '../../../../../../stores/tankopediaPersistent'; import * as styles from './index.css'; -export function RotationInputs() { +export function QuickInputs() { const mutateDuel = Duel.useMutation(); const protagonist = Duel.use((state) => state.protagonist); const awaitedModelDefinitions = use(modelDefinitions); @@ -26,8 +24,6 @@ export function RotationInputs() { const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id]; const initialGunPitch = tankModelDefinition.turretRotation?.pitch ?? 0; const hasImprovedVerticalStabilizer = useEquipment(122); - const isFullScreen = useFullScreen(); - const mutateTankopediaPersistent = TankopediaPersistent.useMutation(); useEffect(() => { yawInput.current!.value = radToDeg(protagonist.yaw).toFixed(1); diff --git a/src/app/tools/tankopedia/[id]/components/Thicknesses.tsx b/src/app/tools/tankopedia/[id]/components/Thicknesses.tsx new file mode 100644 index 000000000..33309ec08 --- /dev/null +++ b/src/app/tools/tankopedia/[id]/components/Thicknesses.tsx @@ -0,0 +1,130 @@ +import { EyeClosedIcon, EyeOpenIcon } from '@radix-ui/react-icons'; +import { Box, Flex, Text } from '@radix-ui/themes'; +import { ThicknessRange } from '../../../../../components/StaticArmor/components/StaticArmorScene'; +import * as TankopediaPersistent from '../../../../../stores/tankopediaPersistent'; + +interface ThicknessesProps { + thicknessRange: ThicknessRange; +} + +export function Thicknesses({ thicknessRange }: ThicknessesProps) { + const showExternalModules = TankopediaPersistent.use( + (state) => state.model.visual.showExternalModules, + ); + const showSpacedArmor = TankopediaPersistent.use( + (state) => state.model.visual.showSpacedArmor, + ); + const showCoreArmor = TankopediaPersistent.use( + (state) => state.model.visual.showCoreArmor, + ); + const mutateTankopediaPersistent = TankopediaPersistent.useMutation(); + + return ( + + { + mutateTankopediaPersistent((draft) => { + draft.model.visual.showCoreArmor = + !draft.model.visual.showCoreArmor; + }); + }} + > + + + {thicknessRange.quartile.toFixed(0)} + + + {showCoreArmor ? : } + Core + + + 0 + + + + + + + { + mutateTankopediaPersistent((draft) => { + draft.model.visual.showSpacedArmor = + !draft.model.visual.showSpacedArmor; + }); + }} + > + + + {thicknessRange.quartile.toFixed(0)} + + + {showSpacedArmor ? : } + Spaced + + + 0 + + + + + + + { + mutateTankopediaPersistent((draft) => { + draft.model.visual.showExternalModules = + !draft.model.visual.showExternalModules; + }); + }} + > + + + {showExternalModules ? : } + External + + + + + + + ); +} diff --git a/src/components/Armor/components/SpacedArmorSceneComponent/index.tsx b/src/components/Armor/components/SpacedArmorSceneComponent/index.tsx index 6ee4ed792..b18e94545 100644 --- a/src/components/Armor/components/SpacedArmorSceneComponent/index.tsx +++ b/src/components/Armor/components/SpacedArmorSceneComponent/index.tsx @@ -36,7 +36,6 @@ function to255(value: number) { type SpacedArmorSceneComponentProps = { node: Object3D; thickness: number; - scene: Scene; clip?: Plane; } & ( | { @@ -50,6 +49,7 @@ type SpacedArmorSceneComponentProps = { ( | { static?: false; + scene: Scene; } | { static: true; @@ -88,7 +88,6 @@ const externalModuleColor = new Color(0, 1 / 4, 1 / 2); export function SpacedArmorSceneComponent({ node, thickness, - scene, clip, ...props }: SpacedArmorSceneComponentProps) { @@ -97,6 +96,131 @@ export function SpacedArmorSceneComponent({ const camera = useThree((state) => state.camera); const duelStore = Duel.useStore(); + if (props.static) { + const x = clamp(thickness / props.thicknessRange.quartile, 0, 1); + const y = Math.sqrt(x); + + let color: Color; + let opacity: number; + let renderOrder = 1; + let depthWrite = true; + + switch (props.type) { + case ArmorType.Core: + color = new Color(-((1 - y) ** 2) + 1, -(y ** 2) + 1, 0); + opacity = 1; + break; + + case ArmorType.Spaced: + color = new Color(1 - (7 / 8) * y, 0, 1 - (1 / 8) * y); + opacity = x + 1 / 2; + break; + + case ArmorType.External: + color = externalModuleColor; + opacity = 1 / 8; + renderOrder = 0; + depthWrite = false; + break; + } + + opacity = clamp(opacity, 0, 1); + + const material = useMemo( + () => + new MeshStandardMaterial({ + color, + opacity, + transparent: true, + depthWrite, + ...(clip ? { clippingPlanes: [clip] } : {}), + }), + [], + ); + + /** + * hook inside an if statement?? don't panic! I assure you the static prop + * never mutates :) + */ + useEffect(() => { + function handleHighlightArmor(selectedName?: string) { + if (!props.static) return; + + if (selectedName === undefined) { + // nothing selected, go back to defaults + material.opacity = opacity; + material.transparent = opacity < 1; + material.color = color; + material.depthWrite = props.type !== ArmorType.External; + material.side = FrontSide; + } else if ( + selectedName === props.name || + (props.name.startsWith('chassis_') && + selectedName.startsWith('chassis_')) || + (props.name.startsWith('gun_') && + selectedName.startsWith('gun_') && + !props.name.includes('_armor_') && + !selectedName.includes('_armor_')) + ) { + // this selected, stand out! + material.opacity = 1; + material.transparent = false; + material.color = color; + material.depthWrite = true; + material.side = DoubleSide; + } else { + // something else selected, become background + material.opacity = 1 / 4; + material.transparent = true; + material.color = unselectedColor; + material.depthWrite = props.type !== ArmorType.External; + material.side = FrontSide; + } + } + + const unsubscribe = tankopediaEphemeralStore.subscribe( + (state) => state.highlightArmor?.name, + handleHighlightArmor, + ); + + return unsubscribe; + }, []); + + return jsxTree(node, { + material, + renderOrder, + userData: { + type: props.type, + variant: props.type === ArmorType.External ? props.variant : 'gun', + thickness, + } satisfies ArmorUserData, + + onClick(event) { + event.stopPropagation(); + + const { point } = event; + const cameraNormal = camera.position.clone().sub(point).normalize(); + const surfaceNormal = event + .normal!.clone() + .applyQuaternion(event.object.getWorldQuaternion(new Quaternion())); + const angle = surfaceNormal.angleTo(cameraNormal); + const thicknessAngled = thickness / Math.sin(Math.PI / 2 - angle); + + mutateTankopediaEphemeralStore((draft) => { + draft.highlightArmor = { + type: props.type, + name: props.name, + point, + thickness, + thicknessAngled, + angle, + color: `#${color.getHexString()}`, + }; + }); + }, + }); + } + const shoot = useCallback( async ( point: Vector3, @@ -345,7 +469,7 @@ export function SpacedArmorSceneComponent({ caster.set(lastLayer.point, ricochetNormal); const ricochetIntersections = caster.intersectObjects( - scene.children, + props.scene.children, true, ); const outShot = await shoot( @@ -377,131 +501,6 @@ export function SpacedArmorSceneComponent({ [camera], ); - if (props.static) { - const x = clamp(thickness / props.thicknessRange.quartile, 0, 1); - const y = Math.sqrt(x); - - let color: Color; - let opacity: number; - let renderOrder = 1; - let depthWrite = true; - - switch (props.type) { - case ArmorType.Core: - color = new Color(-((1 - y) ** 2) + 1, -(y ** 2) + 1, 0); - opacity = 1; - break; - - case ArmorType.Spaced: - color = new Color(1 - (7 / 8) * y, 0, 1 - (1 / 8) * y); - opacity = x + 1 / 2; - break; - - case ArmorType.External: - color = externalModuleColor; - opacity = 1 / 8; - renderOrder = 0; - depthWrite = false; - break; - } - - opacity = clamp(opacity, 0, 1); - - const material = useMemo( - () => - new MeshStandardMaterial({ - color, - opacity, - transparent: true, - depthWrite, - ...(clip ? { clippingPlanes: [clip] } : {}), - }), - [], - ); - - /** - * hook inside an if statement?? don't panic! I assure you the static prop - * never mutates :) - */ - useEffect(() => { - function handleHighlightArmor(selectedName?: string) { - if (!props.static) return; - - if (selectedName === undefined) { - // nothing selected, go back to defaults - material.opacity = opacity; - material.transparent = opacity < 1; - material.color = color; - material.depthWrite = props.type !== ArmorType.External; - material.side = FrontSide; - } else if ( - selectedName === props.name || - (props.name.startsWith('chassis_') && - selectedName.startsWith('chassis_')) || - (props.name.startsWith('gun_') && - selectedName.startsWith('gun_') && - !props.name.includes('_armor_') && - !selectedName.includes('_armor_')) - ) { - // this selected, stand out! - material.opacity = 1; - material.transparent = false; - material.color = color; - material.depthWrite = true; - material.side = DoubleSide; - } else { - // something else selected, become background - material.opacity = 1 / 4; - material.transparent = true; - material.color = unselectedColor; - material.depthWrite = props.type !== ArmorType.External; - material.side = FrontSide; - } - } - - const unsubscribe = tankopediaEphemeralStore.subscribe( - (state) => state.highlightArmor?.name, - handleHighlightArmor, - ); - - return unsubscribe; - }, []); - - return jsxTree(node, { - material, - renderOrder, - userData: { - type: props.type, - variant: props.type === ArmorType.External ? props.variant : 'gun', - thickness, - } satisfies ArmorUserData, - - onClick(event) { - event.stopPropagation(); - - const { point } = event; - const cameraNormal = camera.position.clone().sub(point).normalize(); - const surfaceNormal = event - .normal!.clone() - .applyQuaternion(event.object.getWorldQuaternion(new Quaternion())); - const angle = surfaceNormal.angleTo(cameraNormal); - const thicknessAngled = thickness / Math.sin(Math.PI / 2 - angle); - - mutateTankopediaEphemeralStore((draft) => { - draft.highlightArmor = { - type: props.type, - name: props.name, - point, - thickness, - thicknessAngled, - angle, - color: `#${color.getHexString()}`, - }; - }); - }, - }); - } - return ( <> {props.type === ArmorType.Core && diff --git a/src/components/StaticArmor/components/StaticArmorScene.tsx b/src/components/StaticArmor/components/StaticArmorScene.tsx index 6e2c481f0..faace2aa8 100644 --- a/src/components/StaticArmor/components/StaticArmorScene.tsx +++ b/src/components/StaticArmor/components/StaticArmorScene.tsx @@ -1,9 +1,8 @@ -import { memo, useMemo, useRef } from 'react'; -import { Group, Plane, Scene, Vector3 } from 'three'; +import { memo, useRef } from 'react'; +import { Group, Plane, Vector3 } from 'three'; import { correctZYTuple } from '../../../core/blitz/correctZYTuple'; import { nameToArmorId } from '../../../core/blitzkit/nameToArmorId'; import { resolveArmor } from '../../../core/blitzkit/resolveThickness'; -import { TankDefinitions } from '../../../core/blitzkit/tankDefinitions'; import { useArmor } from '../../../hooks/useArmor'; import { useModel } from '../../../hooks/useModel'; import { useModelDefinitions } from '../../../hooks/useModelDefinitions'; @@ -14,8 +13,7 @@ import { ArmorType } from '../../Armor/components/SpacedArmorScene'; import { SpacedArmorSceneComponent } from '../../Armor/components/SpacedArmorSceneComponent'; interface StaticArmorSceneProps { - scene: Scene; - awaitedTankDefinitions: TankDefinitions; + thicknessRange: ThicknessRange; } export interface ThicknessRange { @@ -24,7 +22,7 @@ export interface ThicknessRange { } export const StaticArmorScene = memo( - ({ scene, awaitedTankDefinitions }) => { + ({ thicknessRange }) => { const wrapper = useRef(null); const awaitedTankModelDefinitions = useModelDefinitions(); const turretContainer = useRef(null); @@ -49,50 +47,6 @@ export const StaticArmorScene = memo( gunModelDefinition.mask === undefined ? undefined : gunModelDefinition.mask + hullOrigin.y + turretOrigin.y + gunOrigin.y; - let thisTankThicknesses: number[] = []; - const thicknessRange = useMemo(() => { - const thicknesses = Object.values(awaitedTankDefinitions) - .filter((thisTank) => thisTank.tier === tank.tier) - .map((tank) => ({ - model: awaitedTankModelDefinitions[tank.id], - id: tank.id, - })) - .filter(Boolean) - .map(({ model, id }) => { - const tankThicknesses = Object.values(model.armor.thickness); - const turretThicknesses = Object.values(model.turrets) - .map((turret) => { - const turretThicknesses = Object.values(turret.armor.thickness); - const gunThicknesses = Object.values(turret.guns) - .map((gun) => Object.values(gun.armor.thickness)) - .flat(); - - return [...turretThicknesses, ...gunThicknesses]; - }) - .flat(); - const totalThicknesses = [...tankThicknesses, ...turretThicknesses]; - - if (id === tank.id) thisTankThicknesses = totalThicknesses; - - return totalThicknesses; - }) - .flat(); - - const sortedThicknesses = thicknesses.sort((a, b) => a - b); - const quartileIndex = (1 - 2 ** -6) * (sortedThicknesses.length + 1) - 1; - let quartile: number; - - if (Number.isInteger(quartileIndex)) { - quartile = sortedThicknesses[quartileIndex]; - } else { - quartile = - (sortedThicknesses[Math.floor(quartileIndex)] + - sortedThicknesses[Math.ceil(quartileIndex)]) / - 2; - } - - return { quartile } satisfies ThicknessRange; - }, [tank.tier]); useTankTransform(protagonist, turretContainer, gunContainer); @@ -115,7 +69,6 @@ export const StaticArmorScene = memo( name={node.name} thicknessRange={thicknessRange} static - scene={scene} key={node.uuid} type={spaced ? ArmorType.Spaced : ArmorType.Core} thickness={thickness} @@ -137,7 +90,6 @@ export const StaticArmorScene = memo( name={node.name} thicknessRange={thicknessRange} static - scene={scene} key={node.uuid} type={ArmorType.External} thickness={trackModelDefinition.thickness} @@ -168,7 +120,6 @@ export const StaticArmorScene = memo( name={node.name} thicknessRange={thicknessRange} static - scene={scene} key={node.uuid} type={spaced ? ArmorType.Spaced : ArmorType.Core} thickness={thickness} @@ -203,7 +154,6 @@ export const StaticArmorScene = memo( name={node.name} thicknessRange={thicknessRange} static - scene={scene} type={spaced ? ArmorType.Spaced : ArmorType.Core} thickness={thickness} node={node} @@ -227,7 +177,6 @@ export const StaticArmorScene = memo( name={node.name} thicknessRange={thicknessRange} static - scene={scene} key={node.uuid} type={ArmorType.External} thickness={gunModelDefinition.thickness} diff --git a/src/components/StaticArmor/index.tsx b/src/components/StaticArmor/index.tsx index ebf5b65e8..fbb719bb6 100644 --- a/src/components/StaticArmor/index.tsx +++ b/src/components/StaticArmor/index.tsx @@ -1,18 +1,12 @@ -import { useThree } from '@react-three/fiber'; -import { TankDefinitions } from '../../core/blitzkit/tankDefinitions'; -import { StaticArmorScene } from './components/StaticArmorScene'; +import { + StaticArmorScene, + ThicknessRange, +} from './components/StaticArmorScene'; -export function StaticArmor({ - awaitedTankDefinitions, -}: { - awaitedTankDefinitions: TankDefinitions; -}) { - const scene = useThree((state) => state.scene); +interface StaticArmorProps { + thicknessRange: ThicknessRange; +} - return ( - - ); +export function StaticArmor({ thicknessRange }: StaticArmorProps) { + return ; } diff --git a/src/stores/tankopediaPersistent/index.ts b/src/stores/tankopediaPersistent/index.ts index 3c036d878..643e8a089 100644 --- a/src/stores/tankopediaPersistent/index.ts +++ b/src/stores/tankopediaPersistent/index.ts @@ -22,6 +22,8 @@ export interface TankopediaPersistent { greenPenetration: boolean; showEnvironment: boolean; showSpacedArmor: boolean; + showExternalModules: boolean; + showCoreArmor: boolean; }; }; sort: { @@ -47,6 +49,8 @@ export const { Provider, use, useMutation, useStore } = createNextSafeStore( model: { visual: { showSpacedArmor: true, + showExternalModules: true, + showCoreArmor: true, wireframe: false, opaque: false, environment: ENVIRONMENTS[0],