mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 03:59:50 +02:00
feat: transiton and reveal
This commit is contained in:
1 parent
b67fd5b58c
commit
778efb2372
6 files changed
+75
-11
No files matched your search
+1
-1
@@ -15,7 +15,7 @@ type ThicknessesProps = MaybeSkeletonComponentProps & {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function Thicknesses({ thicknessRange, skeleton }: ThicknessesProps) {
|
export function Thicknesses({ thicknessRange, skeleton }: ThicknessesProps) {
|
||||||
const display = Tankopedia.use((state) => state.display);
|
const display = Tankopedia.use((state) => state.requestedDisplay);
|
||||||
const showExternalModules = TankopediaPersistent.use(
|
const showExternalModules = TankopediaPersistent.use(
|
||||||
(state) => state.showExternalModules
|
(state) => state.showExternalModules
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export function Options({ thicknessRange, canvas, skeleton }: OptionsProps) {
|
|||||||
const hasCustomShell = Tankopedia.use(
|
const hasCustomShell = Tankopedia.use(
|
||||||
(state) => state.customShell !== undefined
|
(state) => state.customShell !== undefined
|
||||||
);
|
);
|
||||||
const display = Tankopedia.use((state) => state.display);
|
const display = Tankopedia.use((state) => state.requestedDisplay);
|
||||||
const isFullScreen = useFullScreen();
|
const isFullScreen = useFullScreen();
|
||||||
const advancedHighlighting = TankopediaPersistent.use(
|
const advancedHighlighting = TankopediaPersistent.use(
|
||||||
(state) => state.advancedHighlighting
|
(state) => state.advancedHighlighting
|
||||||
@@ -388,7 +388,7 @@ export function Options({ thicknessRange, canvas, skeleton }: OptionsProps) {
|
|||||||
onValueChange={(value) => {
|
onValueChange={(value) => {
|
||||||
Tankopedia.mutate((draft) => {
|
Tankopedia.mutate((draft) => {
|
||||||
draft.disturbed = true;
|
draft.disturbed = true;
|
||||||
draft.display = Number(value);
|
draft.requestedDisplay = Number(value);
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
+62
-3
@@ -1,13 +1,70 @@
|
|||||||
|
import { useFrame, useThree } from "@react-three/fiber";
|
||||||
|
import { useEffect, useRef } from "react";
|
||||||
|
import { HemisphereLight, SpotLight, type Group } from "three";
|
||||||
|
import { clamp } from "three/src/math/MathUtils.js";
|
||||||
|
import { Tankopedia } from "../../../../../../stores/tankopedia";
|
||||||
import { HelpingSpotLight } from "../../../../../HelpingSpotLight";
|
import { HelpingSpotLight } from "../../../../../HelpingSpotLight";
|
||||||
|
|
||||||
|
const ANGLE = Math.PI / 3;
|
||||||
|
const HEMISPHERE_INTENSITY = 4;
|
||||||
|
const REVEAL_ANIMATION_TIME = 5;
|
||||||
|
const TRANSITION_ANIMATION_TIME = 0.5;
|
||||||
|
|
||||||
export function Lighting() {
|
export function Lighting() {
|
||||||
|
const wrapper = useRef<Group>(null!);
|
||||||
|
const t0 = useRef(0);
|
||||||
|
const clock = useThree((state) => state.clock);
|
||||||
|
const display = Tankopedia.use((state) => state.display);
|
||||||
|
const requestedDisplay = Tankopedia.use((state) => state.requestedDisplay);
|
||||||
|
const animationTime = useRef(REVEAL_ANIMATION_TIME);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
Tankopedia.mutate((draft) => {
|
||||||
|
draft.revealed = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
t0.current = clock.elapsedTime - REVEAL_ANIMATION_TIME;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useFrame(({ clock, invalidate }) => {
|
||||||
|
const x = clamp(
|
||||||
|
(clock.elapsedTime - t0.current) / animationTime.current,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
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) {
|
||||||
|
child.angle = ANGLE * t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x < 2) invalidate();
|
||||||
|
|
||||||
|
if (x === 2 && display !== requestedDisplay) {
|
||||||
|
Tankopedia.mutate((draft) => {
|
||||||
|
draft.display = requestedDisplay;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (requestedDisplay === display) return;
|
||||||
|
|
||||||
|
t0.current = clock.elapsedTime;
|
||||||
|
animationTime.current = TRANSITION_ANIMATION_TIME;
|
||||||
|
}, [requestedDisplay]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<group ref={wrapper}>
|
||||||
<hemisphereLight
|
<hemisphereLight
|
||||||
position={[0, 1, 0]}
|
position={[0, 1, 0]}
|
||||||
color="#dadaff"
|
color="#dadaff"
|
||||||
groundColor="#856331"
|
groundColor="#856331"
|
||||||
intensity={4}
|
intensity={0}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<HelpingSpotLight
|
<HelpingSpotLight
|
||||||
@@ -18,6 +75,7 @@ export function Lighting() {
|
|||||||
castShadow
|
castShadow
|
||||||
color="#ffffff"
|
color="#ffffff"
|
||||||
decay={0}
|
decay={0}
|
||||||
|
angle={0}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<HelpingSpotLight
|
<HelpingSpotLight
|
||||||
@@ -28,7 +86,8 @@ export function Lighting() {
|
|||||||
castShadow
|
castShadow
|
||||||
color="#ffffff"
|
color="#ffffff"
|
||||||
decay={0}
|
decay={0}
|
||||||
|
angle={0}
|
||||||
/>
|
/>
|
||||||
</>
|
</group>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
+7
-2
@@ -59,7 +59,10 @@ export function TankModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function onPointerDown(event: ThreeEvent<PointerEvent>) {
|
function onPointerDown(event: ThreeEvent<PointerEvent>) {
|
||||||
if (isTrack && Tankopedia.state.display === TankopediaDisplay.Model) {
|
if (
|
||||||
|
isTrack &&
|
||||||
|
Tankopedia.state.requestedDisplay === TankopediaDisplay.Model
|
||||||
|
) {
|
||||||
position.set(event.clientX, event.clientY);
|
position.set(event.clientX, event.clientY);
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
@@ -106,7 +109,9 @@ export function TankModel() {
|
|||||||
const isTurret = node.name.startsWith("turret_");
|
const isTurret = node.name.startsWith("turret_");
|
||||||
const isCurrentTurret =
|
const isCurrentTurret =
|
||||||
node.name ===
|
node.name ===
|
||||||
`turret_${turretModelDefinition.model_id.toString().padStart(2, "0")}`;
|
`turret_${turretModelDefinition.model_id
|
||||||
|
.toString()
|
||||||
|
.padStart(2, "0")}`;
|
||||||
const isVisible = isCurrentTurret;
|
const isVisible = isCurrentTurret;
|
||||||
const position = new Vector2();
|
const position = new Vector2();
|
||||||
const delta = new Vector2();
|
const delta = new Vector2();
|
||||||
|
|||||||
+1
-3
@@ -5,7 +5,6 @@ import {
|
|||||||
useEffect,
|
useEffect,
|
||||||
useImperativeHandle,
|
useImperativeHandle,
|
||||||
useRef,
|
useRef,
|
||||||
useState,
|
|
||||||
} from "react";
|
} from "react";
|
||||||
import { Fog } from "three";
|
import { Fog } from "three";
|
||||||
import { applyPitchYawLimits } from "../../../../../core/blitz/applyPitchYawLimits";
|
import { applyPitchYawLimits } from "../../../../../core/blitz/applyPitchYawLimits";
|
||||||
@@ -49,8 +48,7 @@ export const TankSandbox = forwardRef<HTMLCanvasElement, TankSandboxProps>(
|
|||||||
const turretModelDefinition =
|
const turretModelDefinition =
|
||||||
tankModelDefinition.turrets[protagonistTurret.id];
|
tankModelDefinition.turrets[protagonistTurret.id];
|
||||||
const gunModelDefinition = turretModelDefinition.guns[protagonistGun.id];
|
const gunModelDefinition = turretModelDefinition.guns[protagonistGun.id];
|
||||||
const rawDisplay = Tankopedia.use((state) => state.display);
|
const display = Tankopedia.use((state) => state.requestedDisplay);
|
||||||
const [display, setDisplay] = useState(rawDisplay);
|
|
||||||
const hideTankModelUnderArmor = TankopediaPersistent.use(
|
const hideTankModelUnderArmor = TankopediaPersistent.use(
|
||||||
(state) => state.hideTankModelUnderArmor
|
(state) => state.hideTankModelUnderArmor
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ interface Tankopedia {
|
|||||||
);
|
);
|
||||||
xpMultiplier: (typeof XP_MULTIPLIERS)[number];
|
xpMultiplier: (typeof XP_MULTIPLIERS)[number];
|
||||||
customShell?: ShellDefinition;
|
customShell?: ShellDefinition;
|
||||||
|
requestedDisplay: TankopediaDisplay;
|
||||||
display: TankopediaDisplay;
|
display: TankopediaDisplay;
|
||||||
statSearch?: string;
|
statSearch?: string;
|
||||||
}
|
}
|
||||||
@@ -114,5 +115,6 @@ export const Tankopedia = new Varuna<Tankopedia, ModelDefinition>((model) => ({
|
|||||||
skills: createDefaultSkills(skillDefinitions),
|
skills: createDefaultSkills(skillDefinitions),
|
||||||
model,
|
model,
|
||||||
xpMultiplier: 1,
|
xpMultiplier: 1,
|
||||||
|
requestedDisplay: TankopediaDisplay.Model,
|
||||||
display: TankopediaDisplay.Model,
|
display: TankopediaDisplay.Model,
|
||||||
}));
|
}));
|
||||||
Reference in new issue
Block a user