diff --git a/Content.Client/Clothing/ClientClothingSystem.cs b/Content.Client/Clothing/ClientClothingSystem.cs index 22d639fc2f..81220e650d 100644 --- a/Content.Client/Clothing/ClientClothingSystem.cs +++ b/Content.Client/Clothing/ClientClothingSystem.cs @@ -60,26 +60,15 @@ public sealed class ClientClothingSystem : ClothingSystem private void OnAppearanceUpdate(EntityUid uid, InventoryComponent component, ref AppearanceChangeEvent args) { // May need to update jumpsuit stencils if the sex changed. Also required to properly set the stencil on init - // when sex is first loaded from the profile. - if (!TryComp(uid, out SpriteComponent? sprite) || !sprite.LayerMapTryGet(HumanoidVisualLayers.StencilMask, out var layer)) + // This is when sex is first loaded from the profile. + + if (!TryComp(uid, out SpriteComponent? sprite) || + !TryComp(uid, out HumanoidAppearanceComponent? humanoid) || + !_inventorySystem.TryGetSlotEntity(uid, "jumpsuit", out var suit, component) || + !TryComp(suit, out ClothingComponent? clothing)) return; - if (!TryComp(uid, out HumanoidAppearanceComponent? humanoid) - || humanoid.Sex != Sex.Female - || !_inventorySystem.TryGetSlotEntity(uid, "jumpsuit", out var suit, component) - || !TryComp(suit, out ClothingComponent? clothing)) - { - sprite.LayerSetVisible(layer, false); - return; - } - - sprite.LayerSetState(layer, clothing.FemaleMask switch - { - FemaleClothingMask.NoMask => "female_none", - FemaleClothingMask.UniformTop => "female_top", - _ => "female_full", - }); - sprite.LayerSetVisible(layer, true); + SetGenderedMask(sprite, humanoid, clothing); } private void OnGetVisuals(EntityUid uid, ClothingComponent item, GetEquipmentVisualsEvent args) @@ -225,20 +214,12 @@ public sealed class ClientClothingSystem : ClothingSystem return; } - if (slot == "jumpsuit" && sprite.LayerMapTryGet(HumanoidVisualLayers.StencilMask, out var suitLayer)) + if (slot == "jumpsuit") { - if (TryComp(equipee, out HumanoidAppearanceComponent? humanoid) && humanoid.Sex == Sex.Female) - { - sprite.LayerSetState(suitLayer, clothingComponent.FemaleMask switch - { - FemaleClothingMask.NoMask => "female_none", - FemaleClothingMask.UniformTop => "female_top", - _ => "female_full", - }); - sprite.LayerSetVisible(suitLayer, true); - } - else - sprite.LayerSetVisible(suitLayer, false); + if (!TryComp(equipee, out HumanoidAppearanceComponent? humanoid)) + return; + + SetGenderedMask(sprite, humanoid, clothingComponent); } if (!_inventorySystem.TryGetSlot(equipee, slot, out var slotDef, inventory)) @@ -315,4 +296,49 @@ public sealed class ClientClothingSystem : ClothingSystem RaiseLocalEvent(equipment, new EquipmentVisualsUpdatedEvent(equipee, slot, revealedLayers), true); } + + + /// + /// Sets a sprite's gendered mask based on gender (obviously). + /// + /// Sprite to modify + /// Humanoid, to get gender from + /// Clothing component, to get mask sprite type + private static void SetGenderedMask(SpriteComponent sprite, HumanoidAppearanceComponent humanoid, ClothingComponent clothing) + { + if (!sprite.LayerMapTryGet(HumanoidVisualLayers.StencilMask, out var layer)) + return; + + ClothingMask? mask = null; + var prefix = ""; + + switch (humanoid.Sex) + { + case Sex.Male: + mask = clothing.MaleMask; + prefix = "male_"; + break; + case Sex.Female: + mask = clothing.FemaleMask; + prefix = "female_"; + break; + case Sex.Unsexed: + mask = clothing.UnisexMask; + prefix = "unisex_"; + break; + } + + if (mask != null) + { + sprite.LayerSetState(layer, mask switch + { + ClothingMask.NoMask => $"{prefix}none", + ClothingMask.UniformTop => $"{prefix}top", + _ => $"{prefix}full", + }); + sprite.LayerSetVisible(layer, true); + } + else + sprite.LayerSetVisible(layer, false); + } } diff --git a/Content.Shared/Clothing/Components/ClothingComponent.cs b/Content.Shared/Clothing/Components/ClothingComponent.cs index 3f6925fd24..a748e2348e 100644 --- a/Content.Shared/Clothing/Components/ClothingComponent.cs +++ b/Content.Shared/Clothing/Components/ClothingComponent.cs @@ -53,9 +53,17 @@ public sealed class ClothingComponent : Component [DataField("sprite")] public string? RsiPath; + [ViewVariables(VVAccess.ReadWrite)] + [DataField("maleMask")] + public ClothingMask MaleMask = ClothingMask.UniformFull; + [ViewVariables(VVAccess.ReadWrite)] [DataField("femaleMask")] - public FemaleClothingMask FemaleMask = FemaleClothingMask.UniformFull; + public ClothingMask FemaleMask = ClothingMask.UniformFull; + + [ViewVariables(VVAccess.ReadWrite)] + [DataField("unisexMask")] + public ClothingMask UnisexMask = ClothingMask.UniformFull; public string? InSlot; } @@ -71,7 +79,7 @@ public sealed class ClothingComponentState : ComponentState } } -public enum FemaleClothingMask : byte +public enum ClothingMask : byte { NoMask = 0, UniformFull, diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index 96ba3c4261..173256ec5c 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -111,16 +111,16 @@ # sprite refactor when state: l_leg - shader: StencilMask - map: [ "enum.HumanoidVisualLayers.StencilMask" ] + map: ["enum.HumanoidVisualLayers.StencilMask"] sprite: Mobs/Customization/masking_helpers.rsi - state: female_full + state: unisex_full visible: false - - map: [ "jumpsuit" ] - - map: [ "enum.HumanoidVisualLayers.LHand" ] - - map: [ "enum.HumanoidVisualLayers.RHand" ] - - map: [ "enum.HumanoidVisualLayers.LFoot" ] - - map: [ "enum.HumanoidVisualLayers.RFoot" ] - - map: [ "enum.HumanoidVisualLayers.Handcuffs" ] + - map: ["jumpsuit"] + - map: ["enum.HumanoidVisualLayers.LFoot"] + - map: ["enum.HumanoidVisualLayers.RFoot"] + - map: ["enum.HumanoidVisualLayers.LHand"] + - map: ["enum.HumanoidVisualLayers.RHand"] + - map: ["enum.HumanoidVisualLayers.Handcuffs"] color: "#ffffff" sprite: Objects/Misc/handcuffs.rsi state: body-overlay-2 @@ -334,16 +334,16 @@ sprite: Mobs/Species/Human/parts.rsi state: l_leg - shader: StencilMask - map: [ "enum.HumanoidVisualLayers.StencilMask" ] + map: ["enum.HumanoidVisualLayers.StencilMask"] sprite: Mobs/Customization/masking_helpers.rsi - state: female_full + state: unisex_full visible: false - - map: [ "jumpsuit" ] - - map: [ "enum.HumanoidVisualLayers.LHand" ] - - map: [ "enum.HumanoidVisualLayers.RHand" ] - - map: [ "enum.HumanoidVisualLayers.LFoot" ] - - map: [ "enum.HumanoidVisualLayers.RFoot" ] - - map: [ "enum.HumanoidVisualLayers.Handcuffs" ] + - map: ["jumpsuit"] + - map: ["enum.HumanoidVisualLayers.LFoot"] + - map: ["enum.HumanoidVisualLayers.RFoot"] + - map: ["enum.HumanoidVisualLayers.LHand"] + - map: ["enum.HumanoidVisualLayers.RHand"] + - map: ["enum.HumanoidVisualLayers.Handcuffs"] color: "#ffffff" sprite: Objects/Misc/handcuffs.rsi state: body-overlay-2 diff --git a/Resources/Prototypes/Entities/Mobs/Species/vox.yml b/Resources/Prototypes/Entities/Mobs/Species/vox.yml index c4f957f799..be6e170c41 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/vox.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/vox.yml @@ -37,7 +37,7 @@ # sprite: Mobs/Species/Vox/parts.rsi # state: l_leg #- shader: StencilMask - # map: [ "enum.HumanoidVisualLayers.StencilMask" ] + # map: [ "enum.HumanoidVisualLayers.FemaleStencilMask" ] # sprite: Mobs/Customization/masking_helpers.rsi # state: female_full # visible: false diff --git a/Resources/Textures/Mobs/Customization/masking_helpers.rsi/female_none.png b/Resources/Textures/Mobs/Customization/masking_helpers.rsi/female_none.png new file mode 100644 index 0000000000..44e0c1358d Binary files /dev/null and b/Resources/Textures/Mobs/Customization/masking_helpers.rsi/female_none.png differ diff --git a/Resources/Textures/Mobs/Customization/masking_helpers.rsi/full.png b/Resources/Textures/Mobs/Customization/masking_helpers.rsi/full.png new file mode 100644 index 0000000000..f78008f58a Binary files /dev/null and b/Resources/Textures/Mobs/Customization/masking_helpers.rsi/full.png differ diff --git a/Resources/Textures/Mobs/Customization/masking_helpers.rsi/male_full.png b/Resources/Textures/Mobs/Customization/masking_helpers.rsi/male_full.png new file mode 100644 index 0000000000..f78008f58a Binary files /dev/null and b/Resources/Textures/Mobs/Customization/masking_helpers.rsi/male_full.png differ diff --git a/Resources/Textures/Mobs/Customization/masking_helpers.rsi/male_none.png b/Resources/Textures/Mobs/Customization/masking_helpers.rsi/male_none.png new file mode 100644 index 0000000000..44e0c1358d Binary files /dev/null and b/Resources/Textures/Mobs/Customization/masking_helpers.rsi/male_none.png differ diff --git a/Resources/Textures/Mobs/Customization/masking_helpers.rsi/male_top.png b/Resources/Textures/Mobs/Customization/masking_helpers.rsi/male_top.png new file mode 100644 index 0000000000..a96eb3c294 Binary files /dev/null and b/Resources/Textures/Mobs/Customization/masking_helpers.rsi/male_top.png differ diff --git a/Resources/Textures/Mobs/Customization/masking_helpers.rsi/meta.json b/Resources/Textures/Mobs/Customization/masking_helpers.rsi/meta.json index 35abe29aa4..090804c6e8 100644 --- a/Resources/Textures/Mobs/Customization/masking_helpers.rsi/meta.json +++ b/Resources/Textures/Mobs/Customization/masking_helpers.rsi/meta.json @@ -1 +1,56 @@ -{"version":1,"size":{"x":32,"y":32},"license":"CC-BY-SA-3.0","copyright":"Discord PJB#3005","states":[{"name":"female_full","directions":4},{"name":"female_top","directions":4},{"name":"none"}]} \ No newline at end of file +{ + "version": 1, + "size": { "x": 32, "y": 32 }, + "license": "CC-BY-SA-3.0", + "copyright": "Discord PJB#3005", + "states": [ + { + "name": "female_full", + "directions": 4 + }, + { + "name": "female_none", + "directions": 1 + }, + { + "name": "female_top", + "directions": 4 + }, + { + "name": "male_full", + "directions": 4 + }, + { + "name": "male_none", + "directions": 1 + }, + { + "name": "male_top", + "directions": 4 + }, + { + "name": "unisex_full", + "directions": 4 + }, + { + "name": "unisex_none", + "directions": 1 + }, + { + "name": "unisex_top", + "directions": 4 + }, + { + "name": "full", + "directions": 4 + }, + { + "name": "none", + "directions": 1 + }, + { + "name": "top", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Mobs/Customization/masking_helpers.rsi/top.png b/Resources/Textures/Mobs/Customization/masking_helpers.rsi/top.png new file mode 100644 index 0000000000..f78008f58a Binary files /dev/null and b/Resources/Textures/Mobs/Customization/masking_helpers.rsi/top.png differ diff --git a/Resources/Textures/Mobs/Customization/masking_helpers.rsi/unisex_full.png b/Resources/Textures/Mobs/Customization/masking_helpers.rsi/unisex_full.png new file mode 100644 index 0000000000..1b69c04a7a Binary files /dev/null and b/Resources/Textures/Mobs/Customization/masking_helpers.rsi/unisex_full.png differ diff --git a/Resources/Textures/Mobs/Customization/masking_helpers.rsi/unisex_none.png b/Resources/Textures/Mobs/Customization/masking_helpers.rsi/unisex_none.png new file mode 100644 index 0000000000..44e0c1358d Binary files /dev/null and b/Resources/Textures/Mobs/Customization/masking_helpers.rsi/unisex_none.png differ diff --git a/Resources/Textures/Mobs/Customization/masking_helpers.rsi/unisex_top.png b/Resources/Textures/Mobs/Customization/masking_helpers.rsi/unisex_top.png new file mode 100644 index 0000000000..44e0c1358d Binary files /dev/null and b/Resources/Textures/Mobs/Customization/masking_helpers.rsi/unisex_top.png differ