mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-27 12:39:49 +01:00
feat: togglable spaced armor
This commit is contained in:
1 parent
b15e73e3a8
commit
191d6133b2
5 files changed
+36
-4
No files matched your search
@@ -8,6 +8,7 @@ import { Button, DropdownMenu, Flex } from '@radix-ui/themes';
|
|||||||
import { RefObject } from 'react';
|
import { RefObject } from 'react';
|
||||||
import { Pose, poseEvent } from '../../../../../../../core/blitzkrieg/pose';
|
import { Pose, poseEvent } from '../../../../../../../core/blitzkrieg/pose';
|
||||||
import mutateTankopediaPersistent, {
|
import mutateTankopediaPersistent, {
|
||||||
|
mutateTankopediaTemporary,
|
||||||
useTankopediaPersistent,
|
useTankopediaPersistent,
|
||||||
} from '../../../../../../../stores/tankopedia';
|
} from '../../../../../../../stores/tankopedia';
|
||||||
import { ENVIRONMENTS } from '../../Lighting';
|
import { ENVIRONMENTS } from '../../Lighting';
|
||||||
@@ -30,6 +31,9 @@ export function Options({ isFullScreen, canvasWrapper }: OptionsProps) {
|
|||||||
const wireframe = useTankopediaPersistent(
|
const wireframe = useTankopediaPersistent(
|
||||||
(state) => state.model.visual.wireframe,
|
(state) => state.model.visual.wireframe,
|
||||||
);
|
);
|
||||||
|
const showSpacedArmor = useTankopediaPersistent(
|
||||||
|
(state) => state.model.visual.showSpacedArmor,
|
||||||
|
);
|
||||||
const opaque = useTankopediaPersistent((state) => state.model.visual.opaque);
|
const opaque = useTankopediaPersistent((state) => state.model.visual.opaque);
|
||||||
const fullScreenAvailable =
|
const fullScreenAvailable =
|
||||||
typeof document !== 'undefined' && document.fullscreenEnabled;
|
typeof document !== 'undefined' && document.fullscreenEnabled;
|
||||||
@@ -81,6 +85,20 @@ export function Options({ isFullScreen, canvasWrapper }: OptionsProps) {
|
|||||||
<DropdownMenu.Content>
|
<DropdownMenu.Content>
|
||||||
<DropdownMenu.Label>Armor</DropdownMenu.Label>
|
<DropdownMenu.Label>Armor</DropdownMenu.Label>
|
||||||
|
|
||||||
|
<DropdownMenu.CheckboxItem
|
||||||
|
checked={showSpacedArmor}
|
||||||
|
onCheckedChange={(checked) => {
|
||||||
|
mutateTankopediaPersistent((draft) => {
|
||||||
|
draft.model.visual.showSpacedArmor = checked;
|
||||||
|
});
|
||||||
|
mutateTankopediaTemporary((draft) => {
|
||||||
|
draft.shot = undefined;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Spaced armor
|
||||||
|
</DropdownMenu.CheckboxItem>
|
||||||
|
|
||||||
<DropdownMenu.CheckboxItem
|
<DropdownMenu.CheckboxItem
|
||||||
checked={greenPenetration}
|
checked={greenPenetration}
|
||||||
onCheckedChange={(checked) => {
|
onCheckedChange={(checked) => {
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ export function CoreArmorSceneComponent({
|
|||||||
explosionRadius: { value: null },
|
explosionRadius: { value: null },
|
||||||
greenPenetration: { value: null },
|
greenPenetration: { value: null },
|
||||||
opaque: { value: null },
|
opaque: { value: null },
|
||||||
|
useSpacedArmor: { value: null },
|
||||||
|
|
||||||
resolution: { value: new Vector2() },
|
resolution: { value: new Vector2() },
|
||||||
spacedArmorBuffer: { value: null },
|
spacedArmorBuffer: { value: null },
|
||||||
@@ -75,6 +76,7 @@ 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(
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ 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 highp sampler2D spacedArmorBuffer;
|
uniform highp sampler2D spacedArmorBuffer;
|
||||||
uniform highp sampler2D spacedArmorDepth;
|
uniform highp sampler2D spacedArmorDepth;
|
||||||
@@ -49,7 +50,7 @@ void main() {
|
|||||||
float coreArmorDistance = depthToDistance(gl_FragCoord.z);
|
float coreArmorDistance = depthToDistance(gl_FragCoord.z);
|
||||||
float distanceFromSpacedArmor = coreArmorDistance - spacedArmorDistance;
|
float distanceFromSpacedArmor = coreArmorDistance - spacedArmorDistance;
|
||||||
|
|
||||||
if (isUnderSpacedArmor) {
|
if (useSpacedArmor && isUnderSpacedArmor) {
|
||||||
float spacedArmorThickness = spacedArmorBufferFragment.r * penetration;
|
float spacedArmorThickness = spacedArmorBufferFragment.r * penetration;
|
||||||
remainingPenetration -= spacedArmorThickness;
|
remainingPenetration -= spacedArmorThickness;
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { useDuel } from '../../../../stores/duel';
|
|||||||
import {
|
import {
|
||||||
Shot,
|
Shot,
|
||||||
ShotLayerBase,
|
ShotLayerBase,
|
||||||
|
useTankopediaPersistent,
|
||||||
useTankopediaTemporary,
|
useTankopediaTemporary,
|
||||||
} from '../../../../stores/tankopedia';
|
} from '../../../../stores/tankopedia';
|
||||||
import { ArmorType } from '../SpacedArmorScene';
|
import { ArmorType } from '../SpacedArmorScene';
|
||||||
@@ -115,12 +116,20 @@ export function SpacedArmorSceneComponent({
|
|||||||
pushLogs(shellNormal, filterIntersections(event.intersections), 0);
|
pushLogs(shellNormal, filterIntersections(event.intersections), 0);
|
||||||
|
|
||||||
function filterIntersections(intersectionsRaw: Intersection[]) {
|
function filterIntersections(intersectionsRaw: Intersection[]) {
|
||||||
const intersectionsAll = intersectionsRaw.filter(
|
const showSpacedArmor =
|
||||||
|
useTankopediaPersistent.getState().model.visual.showSpacedArmor;
|
||||||
|
const intersectionsTyped = intersectionsRaw.filter(
|
||||||
({ object }) => object.userData.type !== undefined,
|
({ object }) => object.userData.type !== undefined,
|
||||||
) as ArmorMeshIntersection[];
|
) as ArmorMeshIntersection[];
|
||||||
const intersectionsWithDuplicates = intersectionsAll.slice(
|
const intersectionsFiltered = intersectionsTyped.filter(
|
||||||
|
({ object }) =>
|
||||||
|
showSpacedArmor
|
||||||
|
? true
|
||||||
|
: object.userData.type === ArmorType.Core,
|
||||||
|
);
|
||||||
|
const intersectionsWithDuplicates = intersectionsFiltered.slice(
|
||||||
0,
|
0,
|
||||||
intersectionsAll.findIndex(
|
intersectionsFiltered.findIndex(
|
||||||
({ object }) => object.userData.type === ArmorType.Core,
|
({ object }) => object.userData.type === ArmorType.Core,
|
||||||
) + 1,
|
) + 1,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ export interface TankopediaPersistent {
|
|||||||
showGrid: boolean;
|
showGrid: boolean;
|
||||||
greenPenetration: boolean;
|
greenPenetration: boolean;
|
||||||
showEnvironment: boolean;
|
showEnvironment: boolean;
|
||||||
|
showSpacedArmor: boolean;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
sort: {
|
sort: {
|
||||||
@@ -123,6 +124,7 @@ export const useTankopediaPersistent = create<TankopediaPersistent>()(
|
|||||||
subscribeWithSelector<TankopediaPersistent>(() => ({
|
subscribeWithSelector<TankopediaPersistent>(() => ({
|
||||||
model: {
|
model: {
|
||||||
visual: {
|
visual: {
|
||||||
|
showSpacedArmor: true,
|
||||||
wireframe: false,
|
wireframe: false,
|
||||||
opaque: false,
|
opaque: false,
|
||||||
environment: ENVIRONMENTS[0],
|
environment: ENVIRONMENTS[0],
|
||||||
|
|||||||
Reference in new issue
Block a user