From cae574cbda7b61761a8f426591c15b6365ea5700 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Wed, 30 Aug 2023 12:32:35 +1000 Subject: [PATCH] Add tile entity occlusion (#14626) --- .../Movement/Systems/FloorOcclusionSystem.cs | 55 +++++++++++++++++++ .../Movement/Systems/FloorOcclusionSystem.cs | 8 +++ .../Components/FloorOccluderComponent.cs | 12 ++++ .../Components/FloorOcclusionComponent.cs | 19 +++++++ .../Systems/SharedFloorOcclusionSystem.cs | 53 ++++++++++++++++++ .../Prototypes/Entities/Mobs/Species/base.yml | 1 + Resources/Prototypes/Entities/Tiles/water.yml | 4 +- Resources/Prototypes/Shaders/shaders.yml | 6 ++ Resources/Textures/Shaders/hcut.swsl | 13 +++++ 9 files changed, 168 insertions(+), 3 deletions(-) create mode 100644 Content.Client/Movement/Systems/FloorOcclusionSystem.cs create mode 100644 Content.Server/Movement/Systems/FloorOcclusionSystem.cs create mode 100644 Content.Shared/Movement/Components/FloorOccluderComponent.cs create mode 100644 Content.Shared/Movement/Components/FloorOcclusionComponent.cs create mode 100644 Content.Shared/Movement/Systems/SharedFloorOcclusionSystem.cs create mode 100644 Resources/Textures/Shaders/hcut.swsl diff --git a/Content.Client/Movement/Systems/FloorOcclusionSystem.cs b/Content.Client/Movement/Systems/FloorOcclusionSystem.cs new file mode 100644 index 0000000000..27ba99b3aa --- /dev/null +++ b/Content.Client/Movement/Systems/FloorOcclusionSystem.cs @@ -0,0 +1,55 @@ +using Content.Shared.Movement.Components; +using Content.Shared.Movement.Systems; +using Robust.Client.GameObjects; +using Robust.Client.Graphics; +using Robust.Shared.Prototypes; + +namespace Content.Client.Movement.Systems; + +public sealed class FloorOcclusionSystem : SharedFloorOcclusionSystem +{ + [Dependency] private readonly IPrototypeManager _proto = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnOcclusionStartup); + SubscribeLocalEvent(OnOcclusionAuto); + } + + private void OnOcclusionAuto(EntityUid uid, FloorOcclusionComponent component, ref AfterAutoHandleStateEvent args) + { + SetEnabled(uid, component, component.Enabled); + } + + private void OnOcclusionStartup(EntityUid uid, FloorOcclusionComponent component, ComponentStartup args) + { + if (component.Enabled && TryComp(uid, out var sprite)) + SetShader(sprite, true); + } + + protected override void SetEnabled(EntityUid uid, FloorOcclusionComponent component, bool enabled) + { + if (component.Enabled == enabled) + return; + + base.SetEnabled(uid, component, enabled); + + if (!TryComp(uid, out var sprite)) + return; + + SetShader(sprite, enabled); + } + + private void SetShader(SpriteComponent sprite, bool enabled) + { + if (enabled) + { + sprite.PostShader = _proto.Index("HorizontalCut").Instance(); + } + else + { + sprite.PostShader = null; + } + } +} diff --git a/Content.Server/Movement/Systems/FloorOcclusionSystem.cs b/Content.Server/Movement/Systems/FloorOcclusionSystem.cs new file mode 100644 index 0000000000..9597070af2 --- /dev/null +++ b/Content.Server/Movement/Systems/FloorOcclusionSystem.cs @@ -0,0 +1,8 @@ +using Content.Shared.Movement.Systems; + +namespace Content.Server.Movement.Systems; + +public sealed class FloorOcclusionSystem : SharedFloorOcclusionSystem +{ + +} diff --git a/Content.Shared/Movement/Components/FloorOccluderComponent.cs b/Content.Shared/Movement/Components/FloorOccluderComponent.cs new file mode 100644 index 0000000000..b9409a8198 --- /dev/null +++ b/Content.Shared/Movement/Components/FloorOccluderComponent.cs @@ -0,0 +1,12 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Movement.Components; + +/// +/// Applies floor occlusion to any that intersect us. +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class FloorOccluderComponent : Component +{ + +} diff --git a/Content.Shared/Movement/Components/FloorOcclusionComponent.cs b/Content.Shared/Movement/Components/FloorOcclusionComponent.cs new file mode 100644 index 0000000000..aa9a1ced55 --- /dev/null +++ b/Content.Shared/Movement/Components/FloorOcclusionComponent.cs @@ -0,0 +1,19 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Movement.Components; + +/// +/// Applies an occlusion shader to this entity if it's colliding with a +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)] +public sealed partial class FloorOcclusionComponent : Component +{ + /// + /// Is the shader currently enabled. + /// + [ViewVariables(VVAccess.ReadWrite), DataField("enabled"), AutoNetworkedField] + public bool Enabled; + + [DataField("colliding")] + public List Colliding = new(); +} diff --git a/Content.Shared/Movement/Systems/SharedFloorOcclusionSystem.cs b/Content.Shared/Movement/Systems/SharedFloorOcclusionSystem.cs new file mode 100644 index 0000000000..9d27ea42c6 --- /dev/null +++ b/Content.Shared/Movement/Systems/SharedFloorOcclusionSystem.cs @@ -0,0 +1,53 @@ +using Content.Shared.Movement.Components; +using Robust.Shared.Physics.Events; + +namespace Content.Shared.Movement.Systems; + +/// +/// Applies an occlusion shader for any relevant entities. +/// +public abstract class SharedFloorOcclusionSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnStartCollide); + SubscribeLocalEvent(OnEndCollide); + } + + private void OnStartCollide(EntityUid uid, FloorOccluderComponent component, ref StartCollideEvent args) + { + var other = args.OtherEntity; + + if (!TryComp(other, out var occlusion) || + occlusion.Colliding.Contains(uid)) + { + return; + } + + SetEnabled(other, occlusion, true); + occlusion.Colliding.Add(uid); + } + + private void OnEndCollide(EntityUid uid, FloorOccluderComponent component, ref EndCollideEvent args) + { + var other = args.OtherEntity; + + if (!TryComp(other, out var occlusion)) + return; + + occlusion.Colliding.Remove(uid); + + if (occlusion.Colliding.Count == 0) + SetEnabled(other, occlusion, false); + } + + protected virtual void SetEnabled(EntityUid uid, FloorOcclusionComponent component, bool enabled) + { + if (component.Enabled == enabled) + return; + + component.Enabled = enabled; + Dirty(uid, component); + } +} diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index 5dfe46021f..60c1989aa2 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -5,6 +5,7 @@ id: BaseMobOrganic noSpawn: true components: + - type: FloorOcclusion - type: LagCompensation - type: RangedDamageSound soundGroups: diff --git a/Resources/Prototypes/Entities/Tiles/water.yml b/Resources/Prototypes/Entities/Tiles/water.yml index bb93e1a43d..45079c0a37 100644 --- a/Resources/Prototypes/Entities/Tiles/water.yml +++ b/Resources/Prototypes/Entities/Tiles/water.yml @@ -7,9 +7,7 @@ snap: - Wall components: - - type: StepTrigger - requiredTriggeredSpeed: 0 - intersectRatio: 0.1 + - type: FloorOccluder - type: Transform anchored: true - type: SyncSprite diff --git a/Resources/Prototypes/Shaders/shaders.yml b/Resources/Prototypes/Shaders/shaders.yml index f6da3b8774..7e165e47c1 100644 --- a/Resources/Prototypes/Shaders/shaders.yml +++ b/Resources/Prototypes/Shaders/shaders.yml @@ -76,3 +76,9 @@ id: PaperStamp kind: source path: "/Textures/Shaders/paperstamp.swsl" + +# Simple horizontal cut +- type: shader + id: HorizontalCut + kind: source + path: "/Textures/Shaders/hcut.swsl" diff --git a/Resources/Textures/Shaders/hcut.swsl b/Resources/Textures/Shaders/hcut.swsl new file mode 100644 index 0000000000..e2b1fea11a --- /dev/null +++ b/Resources/Textures/Shaders/hcut.swsl @@ -0,0 +1,13 @@ +light_mode unshaded; + +const highp float c = 0.3; +const highp float alphaModifier = 0.2; +uniform bool below = true; + +void fragment() +{ + highp vec4 tex = zTexture(UV); + highp float modifier = (UV.y > c ^^ !below) ? 1 : alphaModifier; + + COLOR = vec4(tex.x, tex.y, tex.z, tex.w * modifier); +}