mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 12:09:51 +02:00
feat: armor modes 2
This commit is contained in:
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}
|
||||||
|
|||||||
-5
@@ -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(
|
||||||
|
|||||||
+4
-1
@@ -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);
|
||||||
|
|||||||
Reference in new issue
Block a user