fix: use code

This commit is contained in:
TrèsAbhi committed 2026-04-03 14:37:45 -05:00
1 parent 93632a7073
commit 99c95a4c15
1 file changed
+154 -144
@@ -1,13 +1,20 @@
import { ReloadIcon } from "@radix-ui/react-icons"; import { ReloadIcon } from "@radix-ui/react-icons";
import { Card, Flex, IconButton, Text, TextField } from "@radix-ui/themes"; import {
Card,
Code,
Flex,
IconButton,
Text,
TextField,
} from "@radix-ui/themes";
import { Html } from "@react-three/drei"; import { Html } from "@react-three/drei";
import { useRef } from "react"; import { useRef } from "react";
import { radToDeg } from "three/src/math/MathUtils.js"; import { radToDeg } from "three/src/math/MathUtils.js";
import { resolveArmorIndex } from "../../../core/blitzkit/resolveArmorIndex"; import { resolveArmorIndex } from "../../../core/blitzkit/resolveArmorIndex";
import { LocaleProvider, useLocale } from "../../../hooks/useLocale";
import { App } from "../../../stores/app"; import { App } from "../../../stores/app";
import { Duel } from "../../../stores/duel"; import { Duel } from "../../../stores/duel";
import { Tankopedia } from "../../../stores/tankopedia"; import { Tankopedia } from "../../../stores/tankopedia";
import { CopyableCode } from "../../CopyableCode";
import { layerTypeNames } from "./ShotDisplayCard"; import { layerTypeNames } from "./ShotDisplayCard";
import { ArmorType } from "./SpacedArmorScene"; import { ArmorType } from "./SpacedArmorScene";
@@ -15,6 +22,7 @@ export function ArmorPlateDisplay() {
const highlightArmor = Tankopedia.use((state) => state.highlightArmor); const highlightArmor = Tankopedia.use((state) => state.highlightArmor);
const developerMode = App.useDeferred((state) => state.developerMode, false); const developerMode = App.useDeferred((state) => state.developerMode, false);
const input = useRef<HTMLInputElement>(null); const input = useRef<HTMLInputElement>(null);
const { locale } = useLocale();
if (highlightArmor === undefined) return null; if (highlightArmor === undefined) return null;
@@ -24,162 +32,164 @@ export function ArmorPlateDisplay() {
center center
style={{ pointerEvents: highlightArmor.editingPlate ? "auto" : "none" }} style={{ pointerEvents: highlightArmor.editingPlate ? "auto" : "none" }}
> >
<Card <LocaleProvider locale={locale}>
variant="classic" <Card
mb="4" variant="classic"
style={{ mb="4"
whiteSpace: "nowrap", style={{
color: highlightArmor.color, whiteSpace: "nowrap",
transform: "translateY(-50%)", color: highlightArmor.color,
}} transform: "translateY(-50%)",
> }}
<Flex direction="column"> >
<Text weight="bold"> <Flex direction="column">
{layerTypeNames[highlightArmor.type]}{" "} <Text weight="bold">
{highlightArmor.thickness.toFixed(0)} {layerTypeNames[highlightArmor.type]}{" "}
<Text size="1" weight="regular"> {highlightArmor.thickness.toFixed(0)}
mm <Text size="1" weight="regular">
</Text> mm
</Text>
{highlightArmor.type !== ArmorType.External && (
<Text size="2" color="gray">
{highlightArmor.thicknessAngled.toFixed(0)}
<Text size="1">
mm {radToDeg(highlightArmor.angle).toFixed(0)}°
</Text> </Text>
</Text> </Text>
)}
{developerMode && ( {highlightArmor.type !== ArmorType.External && (
<> <Text size="2" color="gray">
<Text mt="2" color="gray" size="2"> {highlightArmor.thicknessAngled.toFixed(0)}
<b>DEV:</b>{" "} <Text size="1">
<CopyableCode mm {radToDeg(highlightArmor.angle).toFixed(0)}°
copy={highlightArmor.name} </Text>
variant="soft"
highContrast
color="gray"
>
{highlightArmor.name}
</CopyableCode>
</Text> </Text>
</> )}
)}
{highlightArmor.editingPlate && ( {developerMode && (
<Flex gap="2" align="center"> <>
<TextField.Root <Text mt="2" color="gray" size="2">
variant="classic" <b>DEV:</b>{" "}
style={{ width: 96 }} <Code variant="soft" highContrast color="gray">
mt="2" {highlightArmor.name}
ref={input} </Code>
key={highlightArmor.name} </Text>
type="number" </>
autoFocus )}
onFocus={(event) => event.target.select()}
onKeyDown={(event) => {
if (!highlightArmor.editingPlate) return;
const index = resolveArmorIndex(highlightArmor.name); {highlightArmor.editingPlate && (
<Flex gap="2" align="center">
if (index === undefined) return; <TextField.Root
variant="classic"
const thickness = event.currentTarget.valueAsNumber; style={{ width: 96 }}
mt="2"
if (isNaN(thickness) || thickness < 0) return; ref={input}
key={highlightArmor.name}
if (event.key === "Enter") { type="number"
input.current?.blur(); autoFocus
onFocus={(event) => event.target.select()}
Tankopedia.mutate((draft) => { onKeyDown={(event) => {
draft.highlightArmor = undefined;
const { protagonist } = Duel.state;
const tank = draft.model;
const turret = tank.turrets[protagonist.turret.id];
const gun = turret.guns[protagonist.gun.id];
const track = tank.tracks[protagonist.track.id];
if (highlightArmor.name.startsWith("hull_")) {
tank.armor!.thickness[index] = thickness;
} else if (highlightArmor.name.startsWith("turret_")) {
turret.armor!.thickness[index] = thickness;
} else if (highlightArmor.name.startsWith("gun_")) {
if (highlightArmor.name.includes("_armor_")) {
gun.armor!.thickness[index] = thickness;
} else {
gun.thickness = thickness;
}
} else if (highlightArmor.name.startsWith("chassis_")) {
track.thickness = thickness;
}
});
} else if (event.key === "Escape") {
input.current?.blur();
Tankopedia.mutate((draft) => {
draft.highlightArmor = undefined;
});
}
}}
onClick={(event) => {
event.stopPropagation();
event.preventDefault();
}}
defaultValue={highlightArmor.thickness.toFixed(0)}
>
<TextField.Slot side="right">mm</TextField.Slot>
</TextField.Root>
<IconButton
mt="2"
color="red"
onClick={() => {
Tankopedia.mutate((draft) => {
if (!highlightArmor.editingPlate) return; if (!highlightArmor.editingPlate) return;
const index = resolveArmorIndex(highlightArmor.name); const index = resolveArmorIndex(highlightArmor.name);
if (index === undefined) return; if (index === undefined) return;
draft.highlightArmor = undefined; const thickness = event.currentTarget.valueAsNumber;
const initialState = Tankopedia.initial;
const { protagonist } = Duel.state;
const tank = draft.model;
const initialTank = initialState.model;
const turret = tank.turrets[protagonist.turret.id];
const initialTurret =
initialTank.turrets[protagonist.turret.id];
const gun = turret.guns[protagonist.gun.id];
const initialGun = initialTurret.guns[protagonist.gun.id];
const track = tank.tracks[protagonist.track.id];
const initialTrack =
initialTank.tracks[protagonist.track.id];
if (highlightArmor.name.startsWith("hull_")) { if (isNaN(thickness) || thickness < 0) return;
tank.armor!.thickness[index] =
initialTank.armor!.thickness[index]; if (event.key === "Enter") {
} else if (highlightArmor.name.startsWith("turret_")) { input.current?.blur();
turret.armor!.thickness[index] =
initialTurret.armor!.thickness[index]; Tankopedia.mutate((draft) => {
} else if (highlightArmor.name.startsWith("gun_")) { draft.highlightArmor = undefined;
if (highlightArmor.name.includes("_armor_")) { const { protagonist } = Duel.state;
gun.armor!.thickness[index] = const tank = draft.model;
initialGun.armor!.thickness[index]; const turret = tank.turrets[protagonist.turret.id];
} else { const gun = turret.guns[protagonist.gun.id];
gun.thickness = initialGun.thickness; const track = tank.tracks[protagonist.track.id];
}
} else if (highlightArmor.name.startsWith("chassis_")) { if (highlightArmor.name.startsWith("hull_")) {
track.thickness = initialTrack.thickness; tank.armor!.thickness[index] = thickness;
} else if (
highlightArmor.name.startsWith("turret_")
) {
turret.armor!.thickness[index] = thickness;
} else if (highlightArmor.name.startsWith("gun_")) {
if (highlightArmor.name.includes("_armor_")) {
gun.armor!.thickness[index] = thickness;
} else {
gun.thickness = thickness;
}
} else if (
highlightArmor.name.startsWith("chassis_")
) {
track.thickness = thickness;
}
});
} else if (event.key === "Escape") {
input.current?.blur();
Tankopedia.mutate((draft) => {
draft.highlightArmor = undefined;
});
} }
}); }}
}} onClick={(event) => {
> event.stopPropagation();
<ReloadIcon /> event.preventDefault();
</IconButton> }}
</Flex> defaultValue={highlightArmor.thickness.toFixed(0)}
)} >
</Flex> <TextField.Slot side="right">mm</TextField.Slot>
</Card> </TextField.Root>
<IconButton
mt="2"
color="red"
onClick={() => {
Tankopedia.mutate((draft) => {
if (!highlightArmor.editingPlate) return;
const index = resolveArmorIndex(highlightArmor.name);
if (index === undefined) return;
draft.highlightArmor = undefined;
const initialState = Tankopedia.initial;
const { protagonist } = Duel.state;
const tank = draft.model;
const initialTank = initialState.model;
const turret = tank.turrets[protagonist.turret.id];
const initialTurret =
initialTank.turrets[protagonist.turret.id];
const gun = turret.guns[protagonist.gun.id];
const initialGun =
initialTurret.guns[protagonist.gun.id];
const track = tank.tracks[protagonist.track.id];
const initialTrack =
initialTank.tracks[protagonist.track.id];
if (highlightArmor.name.startsWith("hull_")) {
tank.armor!.thickness[index] =
initialTank.armor!.thickness[index];
} else if (highlightArmor.name.startsWith("turret_")) {
turret.armor!.thickness[index] =
initialTurret.armor!.thickness[index];
} else if (highlightArmor.name.startsWith("gun_")) {
if (highlightArmor.name.includes("_armor_")) {
gun.armor!.thickness[index] =
initialGun.armor!.thickness[index];
} else {
gun.thickness = initialGun.thickness;
}
} else if (highlightArmor.name.startsWith("chassis_")) {
track.thickness = initialTrack.thickness;
}
});
}}
>
<ReloadIcon />
</IconButton>
</Flex>
)}
</Flex>
</Card>
</LocaleProvider>
</Html> </Html>
</group> </group>
); );