From a646cc1e57a3ff71e2d7bacc8c3618dfd3117527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Mon, 22 Sep 2025 13:50:46 -0500 Subject: [PATCH] feat: mixer buttons --- packages/i18n/strings/en.json | 4 +- .../src/components/MixerScene/index.tsx | 7 +- .../src/components/ScreenshotButton.tsx | 92 +++++++++++ .../HeroSection/components/Options/index.tsx | 82 +--------- .../website/src/core/blitzkit/curateMixer.ts | 33 ++++ .../src/pages/[...locale]/mixer/_index.tsx | 153 +++++++++--------- 6 files changed, 213 insertions(+), 158 deletions(-) create mode 100644 packages/website/src/components/ScreenshotButton.tsx create mode 100644 packages/website/src/core/blitzkit/curateMixer.ts diff --git a/packages/i18n/strings/en.json b/packages/i18n/strings/en.json index c5ca3d70b..5d28cccec 100644 --- a/packages/i18n/strings/en.json +++ b/packages/i18n/strings/en.json @@ -867,7 +867,9 @@ "name": "Mixer", "button": "Mix and match", "description": "Mix tank modules", - "seo_description": "Mix and match hulls, turrets, and guns of tanks in World of Tanks Blitz" + "seo_description": "Mix and match hulls, turrets, and guns of tanks in World of Tanks Blitz", + "screenshot": "Screenshot", + "randomize": "Randomize" }, "guess": { diff --git a/packages/website/src/components/MixerScene/index.tsx b/packages/website/src/components/MixerScene/index.tsx index 80d0fe0da..372293b4f 100644 --- a/packages/website/src/components/MixerScene/index.tsx +++ b/packages/website/src/components/MixerScene/index.tsx @@ -1,14 +1,15 @@ import { OrbitControls } from "@react-three/drei"; import { Canvas } from "@react-three/fiber"; -import { Suspense } from "react"; +import { forwardRef, Suspense } from "react"; import { Lighting } from "../Tankopedia/HeroSection/components/TankSandbox/components/Lighting"; import { SceneProps } from "../Tankopedia/HeroSection/components/TankSandbox/components/SceneProps"; import { MixerFallback } from "./components/MixerFallback"; import { Model } from "./components/Model"; -export function MixerScene() { +export const MixerScene = forwardRef((_, ref) => { return ( ); -} +}); diff --git a/packages/website/src/components/ScreenshotButton.tsx b/packages/website/src/components/ScreenshotButton.tsx new file mode 100644 index 000000000..c5be06dc8 --- /dev/null +++ b/packages/website/src/components/ScreenshotButton.tsx @@ -0,0 +1,92 @@ +import { CameraIcon, CopyIcon, DownloadIcon } from "@radix-ui/react-icons"; +import { + Button, + Flex, + IconButton, + Popover, + type ButtonProps, +} from "@radix-ui/themes"; +import type { RefObject } from "react"; +import { useLocale } from "../hooks/useLocale"; +import { screenshotReadyEvent } from "./Tankopedia/HeroSection/components/TankSandbox/components/SceneProps"; + +interface Props extends ButtonProps { + canvas: RefObject; + name: string; +} + +export function ScreenshotButton({ canvas, name, children, ...props }: Props) { + const { strings } = useLocale(); + + return ( + + + {children ? ( + + ) : ( + + + + )} + + + + + + + + + + + + + + ); +} diff --git a/packages/website/src/components/Tankopedia/HeroSection/components/Options/index.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/Options/index.tsx index 0171aadca..c037df405 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/Options/index.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/Options/index.tsx @@ -6,9 +6,6 @@ import { } from "@blitzkit/core"; import { literals } from "@blitzkit/i18n/src/literals"; import { - CameraIcon, - CopyIcon, - DownloadIcon, EnterFullScreenIcon, ExitFullScreenIcon, EyeOpenIcon, @@ -39,9 +36,9 @@ import { TankopediaDisplay } from "../../../../../stores/tankopediaPersistent/co import type { MaybeSkeletonComponentProps } from "../../../../../types/maybeSkeletonComponentProps"; import type { ThicknessRange } from "../../../../Armor/components/StaticArmor"; import { ModuleButton } from "../../../../ModuleButtons/ModuleButton"; +import { ScreenshotButton } from "../../../../ScreenshotButton"; import { SmallTankIcon } from "../../../../SmallTankIcon"; import { TankSearch } from "../../../../TankSearch"; -import { screenshotReadyEvent } from "../TankSandbox/components/SceneProps"; import { CustomShellButton } from "./components/CustomShellButton"; import { DynamicArmorSwitcher } from "./components/DynamicArmorSwitcher"; import { QuickInputs } from "./components/QuickInputs"; @@ -440,77 +437,12 @@ export function Options({ thicknessRange, canvas, skeleton }: OptionsProps) { - - - - - - - - - - - - - - - - - - + {fullScreenAvailable && ( { + const tankModel = modelDefinitions.models[tank.id]; + const turret = tank.turrets.at(-1)!; + const turretModel = tankModel.turrets[turret.id]; + + return tank.tier >= 10 && !turretModel.yaw; +}); + +export function curateMixer() { + const hull = tanks[Math.floor(Math.random() * tanks.length)]; + const turretTank = tanks[Math.floor(Math.random() * tanks.length)]; + const turret = + turretTank.turrets[Math.floor(Math.random() * turretTank.turrets.length)]; + const gunTank = tanks[Math.floor(Math.random() * tanks.length)]; + const gunTurret = + gunTank.turrets[Math.floor(Math.random() * gunTank.turrets.length)]; + const gun = gunTurret.guns[Math.floor(Math.random() * gunTurret.guns.length)]; + + return { + hull: hull, + turret: { tank: turretTank, turret: turret }, + gun: { + tank: gunTank, + turret: gunTurret, + gun: gun, + }, + }; +} diff --git a/packages/website/src/pages/[...locale]/mixer/_index.tsx b/packages/website/src/pages/[...locale]/mixer/_index.tsx index c8818f799..0a749f97b 100644 --- a/packages/website/src/pages/[...locale]/mixer/_index.tsx +++ b/packages/website/src/pages/[...locale]/mixer/_index.tsx @@ -1,5 +1,5 @@ import { asset } from "@blitzkit/core"; -import { CaretRightIcon } from "@radix-ui/react-icons"; +import { CaretRightIcon, UpdateIcon } from "@radix-ui/react-icons"; import { Box, Button, @@ -12,12 +12,12 @@ import { import { useRef, useState } from "react"; import { MixerScene } from "../../../components/MixerScene"; import { PageWrapper } from "../../../components/PageWrapper"; +import { ScreenshotButton } from "../../../components/ScreenshotButton"; import { TankSearch, type TankSearchProps, } from "../../../components/TankSearch"; -import { awaitableModelDefinitions } from "../../../core/awaitables/modelDefinitions"; -import { awaitableTankDefinitions } from "../../../core/awaitables/tankDefinitions"; +import { curateMixer } from "../../../core/blitzkit/curateMixer"; import { LocaleProvider, useLocale, @@ -26,48 +26,13 @@ import { import { Mixer } from "../../../stores/mixer"; import type { MaybeSkeletonComponentProps } from "../../../types/maybeSkeletonComponentProps"; -const tankDefinitions = await awaitableTankDefinitions; -const modelDefinitions = await awaitableModelDefinitions; -const tanks = Object.values(tankDefinitions.tanks).filter((tank) => { - const tankModel = modelDefinitions.models[tank.id]; - const turret = tank.turrets.at(-1)!; - const turretModel = tankModel.turrets[turret.id]; - - return tank.tier >= 10 && !turretModel.yaw; -}); - export function Page({ locale, skeleton, }: LocaleAcceptorProps & MaybeSkeletonComponentProps) { - const hull = useRef(tanks[Math.floor(Math.random() * tanks.length)]); - const turretTank = useRef(tanks[Math.floor(Math.random() * tanks.length)]); - const turret = useRef( - turretTank.current.turrets[ - Math.floor(Math.random() * turretTank.current.turrets.length) - ] - ); - const gunTank = useRef(tanks[Math.floor(Math.random() * tanks.length)]); - const gunTurret = useRef( - gunTank.current.turrets[ - Math.floor(Math.random() * gunTank.current.turrets.length) - ] - ); - const gun = useRef( - gunTurret.current.guns[ - Math.floor(Math.random() * gunTurret.current.guns.length) - ] - ); + const initial = useRef(curateMixer()); - Mixer.useInitialization({ - hull: hull.current, - turret: { tank: turretTank.current, turret: turret.current }, - gun: { - tank: gunTank.current, - turret: gunTurret.current, - gun: gun.current, - }, - }); + Mixer.useInitialization(initial.current); return ( @@ -141,60 +106,90 @@ function ModuleSeparator() { } function Content({ skeleton }: MaybeSkeletonComponentProps) { - const hullId = Mixer.use((state) => state.hull.id); + const hull = Mixer.use((state) => state.hull); const turretId = Mixer.use((state) => state.turret.tank.id); const gunId = Mixer.use((state) => state.gun.tank.id); + const canvas = useRef(null); + const { strings } = useLocale(); return ( - {!skeleton && } + {!skeleton && } - { - Mixer.mutate((draft) => { - draft.hull = tank; - }); - }} - /> - - { - Mixer.mutate((draft) => { - draft.turret = { - tank, - turret: tank.turrets.at(-1)!, - }; - }); - }} - /> - - { - Mixer.mutate((draft) => { - draft.gun = { - tank, - turret: tank.turrets.at(-1)!, - gun: tank.turrets.at(-1)!.guns.at(-1)!, - }; - }); - }} - /> + + + {strings.website.tools.mixer.screenshot} + + + + + + { + Mixer.mutate((draft) => { + draft.hull = tank; + }); + }} + /> + + { + Mixer.mutate((draft) => { + draft.turret = { + tank, + turret: tank.turrets.at(-1)!, + }; + }); + }} + /> + + { + Mixer.mutate((draft) => { + draft.gun = { + tank, + turret: tank.turrets.at(-1)!, + gun: tank.turrets.at(-1)!.guns.at(-1)!, + }; + }); + }} + /> + );