mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 02:37:05 +02:00
feat: complete transition
This commit is contained in:
1 parent
cd4fa366a0
commit
1427f61c52
6 files changed
+41
-15
No files matched your search
@@ -67,7 +67,9 @@ export const PrimaryArmorScene = memo(() => {
|
||||
<group ref={turretContainer}>
|
||||
{armorNodes.map((node) => {
|
||||
const isCurrentTurret = node.name.startsWith(
|
||||
`turret_${turretModelDefinition.model_id.toString().padStart(2, "0")}`
|
||||
`turret_${turretModelDefinition.model_id
|
||||
.toString()
|
||||
.padStart(2, "0")}`
|
||||
);
|
||||
const isVisible = isCurrentTurret;
|
||||
const armorId = nameToArmorId(node.name);
|
||||
|
||||
+12
-1
@@ -4,6 +4,7 @@ import {
|
||||
resolvePenetrationCoefficient,
|
||||
} from "@blitzkit/core";
|
||||
import { invalidate, useFrame } from "@react-three/fiber";
|
||||
import type { QuicklimeEvent } from "quicklime";
|
||||
import { useEffect } from "react";
|
||||
import {
|
||||
MeshBasicMaterial,
|
||||
@@ -21,6 +22,7 @@ import { jsxTree } from "../../../../core/blitzkit/jsxTree";
|
||||
import { Duel, type EquipmentMatrix } from "../../../../stores/duel";
|
||||
import { Tankopedia } from "../../../../stores/tankopedia";
|
||||
import { TankopediaPersistent } from "../../../../stores/tankopediaPersistent";
|
||||
import { transitionEvent } from "../../../Tankopedia/HeroSection/components/TankSandbox/components/Lighting";
|
||||
import fragmentShader from "./shaders/fragment.glsl?raw";
|
||||
import vertexShader from "./shaders/vertex.glsl?raw";
|
||||
import { spacedArmorRenderTarget } from "./target";
|
||||
@@ -72,6 +74,8 @@ export function PrimaryArmorSceneComponent({
|
||||
resolution: { value: new Vector2() },
|
||||
spacedArmorBuffer: { value: null },
|
||||
spacedArmorDepth: { value: null },
|
||||
|
||||
opacity: { value: 0 },
|
||||
},
|
||||
]),
|
||||
});
|
||||
@@ -154,6 +158,10 @@ export function PrimaryArmorSceneComponent({
|
||||
if (!noInvalidate) invalidate();
|
||||
}
|
||||
|
||||
function handleTransitionEvent(event: QuicklimeEvent<number>) {
|
||||
material.uniforms.opacity.value = event.data;
|
||||
}
|
||||
|
||||
handleShellChange();
|
||||
handleGreenPenetrationChange(TankopediaPersistent.state.greenPenetration);
|
||||
handleAdvancedHighlightingChange(
|
||||
@@ -164,6 +172,8 @@ export function PrimaryArmorSceneComponent({
|
||||
handleProtagonistEquipmentChange(Duel.state.protagonist.equipmentMatrix);
|
||||
handleAntagonistEquipmentChange(Duel.state.antagonist.equipmentMatrix);
|
||||
|
||||
transitionEvent.on(handleTransitionEvent);
|
||||
|
||||
const unsubscribes = [
|
||||
Duel.on((state) => state.antagonist.shell, handleShellChange),
|
||||
Tankopedia.on((state) => state.customShell, handleShellChange),
|
||||
@@ -184,12 +194,13 @@ export function PrimaryArmorSceneComponent({
|
||||
(state) => state.antagonist.equipmentMatrix,
|
||||
(equipment) => handleAntagonistEquipmentChange(equipment)
|
||||
),
|
||||
() => transitionEvent.off(handleTransitionEvent),
|
||||
];
|
||||
|
||||
return () => {
|
||||
unsubscribes.forEach((unsubscribe) => unsubscribe());
|
||||
};
|
||||
});
|
||||
}, []);
|
||||
|
||||
useFrame(({ gl, camera }) => {
|
||||
gl.getSize(material.uniforms.resolution.value).multiplyScalar(
|
||||
|
||||
+2
-5
@@ -1,12 +1,9 @@
|
||||
precision mediump float;
|
||||
|
||||
#define USE_FOG
|
||||
|
||||
#include <fog_pars_fragment>
|
||||
|
||||
varying vec3 vNormal;
|
||||
varying vec3 vViewPosition;
|
||||
|
||||
uniform float opacity;
|
||||
uniform float thickness;
|
||||
uniform float penetration;
|
||||
uniform float caliber;
|
||||
@@ -119,5 +116,5 @@ void main() {
|
||||
gl_FragColor = vec4(baseColor, (1.0 - penetrationChance) * alpha);
|
||||
}
|
||||
|
||||
#include <fog_fragment>
|
||||
gl_FragColor.a *= opacity;
|
||||
}
|
||||
-6
@@ -1,9 +1,5 @@
|
||||
precision mediump float;
|
||||
|
||||
#define USE_FOG
|
||||
|
||||
#include <fog_pars_vertex>
|
||||
|
||||
varying vec3 vNormal;
|
||||
varying vec3 vViewPosition;
|
||||
|
||||
@@ -14,6 +10,4 @@ void main() {
|
||||
vNormal = normalMatrix * normal;
|
||||
|
||||
gl_Position = projectionMatrix * mvPosition;
|
||||
|
||||
#include <fog_vertex>
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
} from "../../../core/blitzkit/modelTransform";
|
||||
import { discardClippingPlane } from "../../../core/three/discardClippingPlane";
|
||||
import { Tankopedia } from "../../../stores/tankopedia";
|
||||
import { transitionEvent } from "../../Tankopedia/HeroSection/components/TankSandbox/components/Lighting";
|
||||
import { ArmorType } from "./SpacedArmorScene";
|
||||
import type {
|
||||
ArmorUserData,
|
||||
@@ -108,10 +109,11 @@ export function StaticArmorSceneComponent({
|
||||
() =>
|
||||
new MeshBasicMaterial({
|
||||
color,
|
||||
opacity,
|
||||
transparent: opacity < 1,
|
||||
transparent: true,
|
||||
depthWrite,
|
||||
...(props.clip ? { clippingPlanes: [props.clip] } : {}),
|
||||
opacity: 0,
|
||||
userData: { opacity0: opacity },
|
||||
}),
|
||||
[thickness]
|
||||
);
|
||||
@@ -121,6 +123,8 @@ export function StaticArmorSceneComponent({
|
||||
color: color
|
||||
.clone()
|
||||
.multiplyScalar(props.type === ArmorType.Spaced ? 2 ** 2 : 2 ** -1),
|
||||
opacity: 0,
|
||||
transparent: true,
|
||||
}),
|
||||
[thickness]
|
||||
);
|
||||
@@ -163,11 +167,22 @@ export function StaticArmorSceneComponent({
|
||||
surfaceMaterial.needsUpdate = true;
|
||||
}
|
||||
|
||||
function handleTransitionEvent(event: QuicklimeEvent<number>) {
|
||||
surfaceMaterial.opacity = surfaceMaterial.userData.opacity0 * event.data;
|
||||
outlineMaterial.opacity = event.data;
|
||||
|
||||
surfaceMaterial.transparent = surfaceMaterial.opacity < 1;
|
||||
outlineMaterial.transparent = outlineMaterial.opacity < 1;
|
||||
}
|
||||
|
||||
transitionEvent.on(handleTransitionEvent);
|
||||
|
||||
const unsubscribes = [
|
||||
Tankopedia.on(
|
||||
(state) => state.highlightArmor?.name,
|
||||
handleHighlightArmor
|
||||
),
|
||||
() => transitionEvent.off(handleTransitionEvent),
|
||||
];
|
||||
|
||||
if (props.clip) {
|
||||
|
||||
+7
@@ -1,5 +1,6 @@
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import { times } from "lodash-es";
|
||||
import { Quicklime } from "quicklime";
|
||||
import { useEffect, useRef } from "react";
|
||||
import { SpotLight, type Group } from "three";
|
||||
import { clamp, degToRad, lerp } from "three/src/math/MathUtils.js";
|
||||
@@ -19,6 +20,8 @@ const LIGHT_HEIGHT_1 = 10;
|
||||
const INTENSITY_0 = 60;
|
||||
const INTENSITY_1 = 30;
|
||||
|
||||
export const transitionEvent = new Quicklime<number>(0);
|
||||
|
||||
export function Lighting() {
|
||||
const wrapper = useRef<Group>(null!);
|
||||
const t0 = useRef(0);
|
||||
@@ -50,6 +53,10 @@ export function Lighting() {
|
||||
);
|
||||
const t = (0.5 * Math.sin(Math.PI * (x + 0.5)) + 0.5) ** 2;
|
||||
|
||||
if (t !== transitionEvent.last) {
|
||||
transitionEvent.dispatch(t);
|
||||
}
|
||||
|
||||
for (const child of wrapper.current.children) {
|
||||
if (child instanceof SpotLight) {
|
||||
child.angle = ANGLE * t;
|
||||
|
||||
Reference in new issue
Block a user