mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 12:09:51 +02:00
feat: functional armor type toggling
This commit is contained in:
1 parent
0aca2dab6c
commit
c4b5baf6cc
6 files changed
+52
-33
No files matched your search
@@ -70,9 +70,6 @@ export function Options({ thicknessRange }: OptionsProps) {
|
|||||||
const wireframe = TankopediaPersistent.use(
|
const wireframe = TankopediaPersistent.use(
|
||||||
(state) => state.model.visual.wireframe,
|
(state) => state.model.visual.wireframe,
|
||||||
);
|
);
|
||||||
const showSpacedArmor = TankopediaPersistent.use(
|
|
||||||
(state) => state.model.visual.showSpacedArmor,
|
|
||||||
);
|
|
||||||
const opaque = TankopediaPersistent.use((state) => state.model.visual.opaque);
|
const opaque = TankopediaPersistent.use((state) => state.model.visual.opaque);
|
||||||
const fullScreenAvailable = useFullscreenAvailability();
|
const fullScreenAvailable = useFullscreenAvailability();
|
||||||
const environment = TankopediaPersistent.use(
|
const environment = TankopediaPersistent.use(
|
||||||
@@ -537,24 +534,10 @@ export function Options({ thicknessRange }: OptionsProps) {
|
|||||||
</DropdownMenu.Trigger>
|
</DropdownMenu.Trigger>
|
||||||
|
|
||||||
<DropdownMenu.Content>
|
<DropdownMenu.Content>
|
||||||
{display !== TankopediaDisplay.Model && (
|
{display === TankopediaDisplay.DynamicArmor && (
|
||||||
<>
|
<>
|
||||||
<DropdownMenu.Label>Armor</DropdownMenu.Label>
|
<DropdownMenu.Label>Armor</DropdownMenu.Label>
|
||||||
|
|
||||||
<DropdownMenu.CheckboxItem
|
|
||||||
checked={showSpacedArmor}
|
|
||||||
onCheckedChange={(checked) => {
|
|
||||||
mutateTankopediaPersistent((draft) => {
|
|
||||||
draft.model.visual.showSpacedArmor = checked;
|
|
||||||
});
|
|
||||||
mutateTankopediaEphemeral((draft) => {
|
|
||||||
draft.shot = undefined;
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Spaced armor
|
|
||||||
</DropdownMenu.CheckboxItem>
|
|
||||||
|
|
||||||
<DropdownMenu.CheckboxItem
|
<DropdownMenu.CheckboxItem
|
||||||
checked={greenPenetration}
|
checked={greenPenetration}
|
||||||
onCheckedChange={(checked) => {
|
onCheckedChange={(checked) => {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { EyeClosedIcon, EyeOpenIcon } from '@radix-ui/react-icons';
|
import { EyeClosedIcon, EyeOpenIcon } from '@radix-ui/react-icons';
|
||||||
import { Box, Flex, Text } from '@radix-ui/themes';
|
import { Box, Flex, Text } from '@radix-ui/themes';
|
||||||
import { ThicknessRange } from '../../../../../components/StaticArmor/components/StaticArmorScene';
|
import { ThicknessRange } from '../../../../../components/StaticArmor/components/StaticArmorScene';
|
||||||
|
import * as TankopediaEphemeral from '../../../../../stores/tankopediaEphemeral';
|
||||||
import * as TankopediaPersistent from '../../../../../stores/tankopediaPersistent';
|
import * as TankopediaPersistent from '../../../../../stores/tankopediaPersistent';
|
||||||
|
|
||||||
interface ThicknessesProps {
|
interface ThicknessesProps {
|
||||||
@@ -18,6 +19,7 @@ export function Thicknesses({ thicknessRange }: ThicknessesProps) {
|
|||||||
(state) => state.model.visual.showCoreArmor,
|
(state) => state.model.visual.showCoreArmor,
|
||||||
);
|
);
|
||||||
const mutateTankopediaPersistent = TankopediaPersistent.useMutation();
|
const mutateTankopediaPersistent = TankopediaPersistent.useMutation();
|
||||||
|
const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
@@ -25,7 +27,7 @@ export function Thicknesses({ thicknessRange }: ThicknessesProps) {
|
|||||||
right="0"
|
right="0"
|
||||||
top="50%"
|
top="50%"
|
||||||
mr="4"
|
mr="4"
|
||||||
style={{ transform: 'translateY(-50%)' }}
|
style={{ transform: 'translateY(-50%)', userSelect: 'none' }}
|
||||||
direction="column"
|
direction="column"
|
||||||
gap="2"
|
gap="2"
|
||||||
align="end"
|
align="end"
|
||||||
@@ -39,6 +41,9 @@ export function Thicknesses({ thicknessRange }: ThicknessesProps) {
|
|||||||
draft.model.visual.showCoreArmor =
|
draft.model.visual.showCoreArmor =
|
||||||
!draft.model.visual.showCoreArmor;
|
!draft.model.visual.showCoreArmor;
|
||||||
});
|
});
|
||||||
|
mutateTankopediaEphemeral((draft) => {
|
||||||
|
draft.highlightArmor = undefined;
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Flex direction="column" align="end" justify="between">
|
<Flex direction="column" align="end" justify="between">
|
||||||
@@ -73,6 +78,9 @@ export function Thicknesses({ thicknessRange }: ThicknessesProps) {
|
|||||||
draft.model.visual.showSpacedArmor =
|
draft.model.visual.showSpacedArmor =
|
||||||
!draft.model.visual.showSpacedArmor;
|
!draft.model.visual.showSpacedArmor;
|
||||||
});
|
});
|
||||||
|
mutateTankopediaEphemeral((draft) => {
|
||||||
|
draft.highlightArmor = undefined;
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Flex direction="column" align="end" justify="between">
|
<Flex direction="column" align="end" justify="between">
|
||||||
@@ -106,6 +114,9 @@ export function Thicknesses({ thicknessRange }: ThicknessesProps) {
|
|||||||
draft.model.visual.showExternalModules =
|
draft.model.visual.showExternalModules =
|
||||||
!draft.model.visual.showExternalModules;
|
!draft.model.visual.showExternalModules;
|
||||||
});
|
});
|
||||||
|
mutateTankopediaEphemeral((draft) => {
|
||||||
|
draft.highlightArmor = undefined;
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Flex direction="column" align="end" justify="between">
|
<Flex direction="column" align="end" justify="between">
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ export function CoreArmorSceneComponent({
|
|||||||
explosionRadius: { value: null },
|
explosionRadius: { value: null },
|
||||||
greenPenetration: { value: null },
|
greenPenetration: { value: null },
|
||||||
opaque: { value: null },
|
opaque: { value: null },
|
||||||
useSpacedArmor: { value: null },
|
|
||||||
|
|
||||||
inverseProjectionMatrix: { value: null },
|
inverseProjectionMatrix: { value: null },
|
||||||
resolution: { value: new Vector2() },
|
resolution: { value: new Vector2() },
|
||||||
@@ -80,7 +79,6 @@ export function CoreArmorSceneComponent({
|
|||||||
) {
|
) {
|
||||||
material.uniforms.greenPenetration.value = visual.greenPenetration;
|
material.uniforms.greenPenetration.value = visual.greenPenetration;
|
||||||
material.uniforms.opaque.value = visual.opaque || visual.wireframe;
|
material.uniforms.opaque.value = visual.opaque || visual.wireframe;
|
||||||
material.uniforms.useSpacedArmor.value = visual.showSpacedArmor;
|
|
||||||
material.wireframe = visual.wireframe;
|
material.wireframe = visual.wireframe;
|
||||||
}
|
}
|
||||||
async function handleProtagonistEquipmentChange(
|
async function handleProtagonistEquipmentChange(
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ uniform float damage;
|
|||||||
uniform float explosionRadius;
|
uniform float explosionRadius;
|
||||||
uniform bool greenPenetration;
|
uniform bool greenPenetration;
|
||||||
uniform bool opaque;
|
uniform bool opaque;
|
||||||
uniform bool useSpacedArmor;
|
|
||||||
uniform mat4 inverseProjectionMatrix;
|
uniform mat4 inverseProjectionMatrix;
|
||||||
|
|
||||||
uniform highp sampler2D spacedArmorBuffer;
|
uniform highp sampler2D spacedArmorBuffer;
|
||||||
@@ -49,7 +48,7 @@ void main() {
|
|||||||
float coreArmorDistance = depthToDistance(gl_FragCoord.z);
|
float coreArmorDistance = depthToDistance(gl_FragCoord.z);
|
||||||
float distanceFromSpacedArmor = coreArmorDistance - spacedArmorDistance;
|
float distanceFromSpacedArmor = coreArmorDistance - spacedArmorDistance;
|
||||||
|
|
||||||
if (canSplash && useSpacedArmor && isUnderSpacedArmor) {
|
if (canSplash && isUnderSpacedArmor) {
|
||||||
float spacedArmorThickness = spacedArmorBufferFragment.r * penetration;
|
float spacedArmorThickness = spacedArmorBufferFragment.r * penetration;
|
||||||
float finalDamage = 0.5 * damage * (1.0 - distanceFromSpacedArmor / explosionRadius) - 1.1 * (finalThickness + spacedArmorThickness);
|
float finalDamage = 0.5 * damage * (1.0 - distanceFromSpacedArmor / explosionRadius) - 1.1 * (finalThickness + spacedArmorThickness);
|
||||||
|
|
||||||
@@ -58,7 +57,7 @@ void main() {
|
|||||||
} else {
|
} else {
|
||||||
float remainingPenetration = penetration;
|
float remainingPenetration = penetration;
|
||||||
|
|
||||||
if (useSpacedArmor && isUnderSpacedArmor) {
|
if (isUnderSpacedArmor) {
|
||||||
float spacedArmorThickness = spacedArmorBufferFragment.r * penetration;
|
float spacedArmorThickness = spacedArmorBufferFragment.r * penetration;
|
||||||
remainingPenetration -= spacedArmorThickness;
|
remainingPenetration -= spacedArmorThickness;
|
||||||
|
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ export function SpacedArmorSceneComponent({
|
|||||||
if (selectedName === undefined) {
|
if (selectedName === undefined) {
|
||||||
// nothing selected, go back to defaults
|
// nothing selected, go back to defaults
|
||||||
material.opacity = opacity;
|
material.opacity = opacity;
|
||||||
material.transparent = opacity < 1;
|
// material.transparent = opacity < 1;
|
||||||
material.color = color;
|
material.color = color;
|
||||||
material.depthWrite = props.type !== ArmorType.External;
|
material.depthWrite = props.type !== ArmorType.External;
|
||||||
material.side = FrontSide;
|
material.side = FrontSide;
|
||||||
@@ -164,14 +164,14 @@ export function SpacedArmorSceneComponent({
|
|||||||
) {
|
) {
|
||||||
// this selected, stand out!
|
// this selected, stand out!
|
||||||
material.opacity = 1;
|
material.opacity = 1;
|
||||||
material.transparent = false;
|
// material.transparent = false;
|
||||||
material.color = color;
|
material.color = color;
|
||||||
material.depthWrite = true;
|
material.depthWrite = true;
|
||||||
material.side = DoubleSide;
|
material.side = DoubleSide;
|
||||||
} else {
|
} else {
|
||||||
// something else selected, become background
|
// something else selected, become background
|
||||||
material.opacity = 1 / 4;
|
material.opacity = 1 / 4;
|
||||||
material.transparent = true;
|
// material.transparent = true;
|
||||||
material.color = unselectedColor;
|
material.color = unselectedColor;
|
||||||
material.depthWrite = props.type !== ArmorType.External;
|
material.depthWrite = props.type !== ArmorType.External;
|
||||||
material.side = FrontSide;
|
material.side = FrontSide;
|
||||||
@@ -188,7 +188,7 @@ export function SpacedArmorSceneComponent({
|
|||||||
|
|
||||||
return jsxTree(node, {
|
return jsxTree(node, {
|
||||||
material,
|
material,
|
||||||
renderOrder,
|
// renderOrder,
|
||||||
userData: {
|
userData: {
|
||||||
type: props.type,
|
type: props.type,
|
||||||
variant: props.type === ArmorType.External ? props.variant : 'gun',
|
variant: props.type === ArmorType.External ? props.variant : 'gun',
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { useModel } from '../../../hooks/useModel';
|
|||||||
import { useModelDefinitions } from '../../../hooks/useModelDefinitions';
|
import { useModelDefinitions } from '../../../hooks/useModelDefinitions';
|
||||||
import { useTankTransform } from '../../../hooks/useTankTransform';
|
import { useTankTransform } from '../../../hooks/useTankTransform';
|
||||||
import * as Duel from '../../../stores/duel';
|
import * as Duel from '../../../stores/duel';
|
||||||
|
import * as TankopediaPersistent from '../../../stores/tankopediaPersistent';
|
||||||
import { ModelTankWrapper } from '../../Armor/components/ModelTankWrapper';
|
import { ModelTankWrapper } from '../../Armor/components/ModelTankWrapper';
|
||||||
import { ArmorType } from '../../Armor/components/SpacedArmorScene';
|
import { ArmorType } from '../../Armor/components/SpacedArmorScene';
|
||||||
import { SpacedArmorSceneComponent } from '../../Armor/components/SpacedArmorSceneComponent';
|
import { SpacedArmorSceneComponent } from '../../Armor/components/SpacedArmorSceneComponent';
|
||||||
@@ -47,6 +48,15 @@ export const StaticArmorScene = memo<StaticArmorSceneProps>(
|
|||||||
gunModelDefinition.mask === undefined
|
gunModelDefinition.mask === undefined
|
||||||
? undefined
|
? undefined
|
||||||
: gunModelDefinition.mask + hullOrigin.y + turretOrigin.y + gunOrigin.y;
|
: gunModelDefinition.mask + hullOrigin.y + turretOrigin.y + gunOrigin.y;
|
||||||
|
const showCoreArmor = TankopediaPersistent.use(
|
||||||
|
(state) => state.model.visual.showCoreArmor,
|
||||||
|
);
|
||||||
|
const showSpacedArmor = TankopediaPersistent.use(
|
||||||
|
(state) => state.model.visual.showSpacedArmor,
|
||||||
|
);
|
||||||
|
const showExternalModules = TankopediaPersistent.use(
|
||||||
|
(state) => state.model.visual.showExternalModules,
|
||||||
|
);
|
||||||
|
|
||||||
useTankTransform(protagonist, turretContainer, gunContainer);
|
useTankTransform(protagonist, turretContainer, gunContainer);
|
||||||
|
|
||||||
@@ -62,7 +72,13 @@ export const StaticArmorScene = memo<StaticArmorSceneProps>(
|
|||||||
armorId,
|
armorId,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!isVisible || thickness === undefined) return null;
|
if (
|
||||||
|
!isVisible ||
|
||||||
|
thickness === undefined ||
|
||||||
|
(!showCoreArmor && !spaced) ||
|
||||||
|
(!showSpacedArmor && spaced)
|
||||||
|
)
|
||||||
|
return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SpacedArmorSceneComponent
|
<SpacedArmorSceneComponent
|
||||||
@@ -83,7 +99,7 @@ export const StaticArmorScene = memo<StaticArmorSceneProps>(
|
|||||||
const isTrack = node.name.startsWith('chassis_track_');
|
const isTrack = node.name.startsWith('chassis_track_');
|
||||||
const isVisible = isWheel || isTrack;
|
const isVisible = isWheel || isTrack;
|
||||||
|
|
||||||
if (!isVisible) return null;
|
if (!isVisible || !showExternalModules) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SpacedArmorSceneComponent
|
<SpacedArmorSceneComponent
|
||||||
@@ -111,7 +127,13 @@ export const StaticArmorScene = memo<StaticArmorSceneProps>(
|
|||||||
armorId,
|
armorId,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!isVisible || thickness === undefined) return null;
|
if (
|
||||||
|
!isVisible ||
|
||||||
|
thickness === undefined ||
|
||||||
|
(!showCoreArmor && !spaced) ||
|
||||||
|
(!showSpacedArmor && spaced)
|
||||||
|
)
|
||||||
|
return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<group position={hullOrigin}>
|
<group position={hullOrigin}>
|
||||||
@@ -142,7 +164,13 @@ export const StaticArmorScene = memo<StaticArmorSceneProps>(
|
|||||||
armorId,
|
armorId,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!isVisible || thickness === undefined) return null;
|
if (
|
||||||
|
!isVisible ||
|
||||||
|
thickness === undefined ||
|
||||||
|
(!showCoreArmor && !spaced) ||
|
||||||
|
(!showSpacedArmor && spaced)
|
||||||
|
)
|
||||||
|
return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<group position={hullOrigin}>
|
<group position={hullOrigin}>
|
||||||
@@ -170,7 +198,7 @@ export const StaticArmorScene = memo<StaticArmorSceneProps>(
|
|||||||
: node.name === gunString;
|
: node.name === gunString;
|
||||||
const isVisible = isCurrentGun;
|
const isVisible = isCurrentGun;
|
||||||
|
|
||||||
if (!isVisible) return null;
|
if (!isVisible || !showExternalModules) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SpacedArmorSceneComponent
|
<SpacedArmorSceneComponent
|
||||||
|
|||||||
Reference in new issue
Block a user