From 344e7caa81962694e8fa1b08beec77301d0b3558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Thu, 27 Nov 2025 13:05:08 -0600 Subject: [PATCH] feat: overhead lighting --- .../HeroSection/components/Options/index.tsx | 16 +++++ .../TankSandbox/components/Lighting.tsx | 71 ++++++++++--------- .../src/stores/tankopediaPersistent/index.ts | 2 + 3 files changed, 55 insertions(+), 34 deletions(-) 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 59fdca5a6..a9659776d 100644 --- a/packages/website/src/components/Tankopedia/HeroSection/components/Options/index.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/Options/index.tsx @@ -12,6 +12,7 @@ import { EyeOpenIcon, ShadowInnerIcon, ShadowNoneIcon, + SunIcon, } from "@radix-ui/react-icons"; import { Button, @@ -73,6 +74,7 @@ export function Options({ thicknessRange, canvas, skeleton }: OptionsProps) { const { strings, unwrap } = useLocale(); const revealed = Tankopedia.use((state) => state.revealed); const disturbed = Tankopedia.use((state) => state.disturbed); + const highGraphics = TankopediaPersistent.use((state) => state.highGraphics); return ( <> @@ -349,6 +351,20 @@ export function Options({ thicknessRange, canvas, skeleton }: OptionsProps) { + { + TankopediaPersistent.mutate((draft) => { + draft.highGraphics = !draft.highGraphics; + }); + }} + color={highGraphics ? undefined : "gray"} + variant={highGraphics ? "solid" : "surface"} + > + + + (null!); const t0 = useRef(0); @@ -17,6 +26,7 @@ export function Lighting() { const display = Tankopedia.use((state) => state.display); const requestedDisplay = Tankopedia.use((state) => state.requestedDisplay); const animationTime = useRef(REVEAL_ANIMATION_TIME); + const highGraphics = TankopediaPersistent.use((state) => state.highGraphics); useEffect(() => { Tankopedia.mutate((draft) => { @@ -35,9 +45,7 @@ export function Lighting() { const t = 0.5 * Math.sin(Math.PI * (x + 0.5)) + 0.5; for (const child of wrapper.current.children) { - if (child instanceof HemisphereLight) { - child.intensity = HEMISPHERE_INTENSITY * t; - } else if (child instanceof SpotLight) { + if (child instanceof SpotLight) { child.angle = ANGLE * t; } } @@ -60,34 +68,29 @@ export function Lighting() { return ( - + {times(LIGHTS_COUNT, (index) => { + const x = index / (LIGHTS_COUNT - 1); + const theta = 2 * Math.PI * (index / LIGHTS_COUNT) + THETA_OFFSET; + const position = [ + LIGHT_DISTANCE * Math.sin(theta), + lerp(LIGHT_HEIGHT_0, LIGHT_HEIGHT_1, x), + LIGHT_DISTANCE * Math.cos(theta), + ] as const; + const intensity = lerp(INTENSITY_0, INTENSITY_1, x); - - - + return ( + + ); + })} ); } diff --git a/packages/website/src/stores/tankopediaPersistent/index.ts b/packages/website/src/stores/tankopediaPersistent/index.ts index 1b1cc2839..ced9cf380 100644 --- a/packages/website/src/stores/tankopediaPersistent/index.ts +++ b/packages/website/src/stores/tankopediaPersistent/index.ts @@ -15,6 +15,7 @@ export interface TankopediaPersistent { showPrimaryArmor: boolean; recentlyViewed: number[]; hideTankModelUnderArmor: boolean; + highGraphics: boolean; sort: { by: TankopediaSortBy; @@ -33,6 +34,7 @@ export const TankopediaPersistent = new Varuna( showExternalModules: true, showPrimaryArmor: true, recentlyViewed: [], + highGraphics: true, sort: { by: "meta.none", direction: "ascending",