[Feat] Тонкие спрайты снова в строю (#102)
* Revert "Hair Overhaul (#19298)"
This reverts commit 9491f322de.
# Conflicts:
# Resources/Textures/Mobs/Customization/human_hair.rsi/a.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/afro.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/afro2.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/bigafro.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/cornrows2.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/emofringe.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/keanu.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/long.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/long2.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/long3.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/meta.json
# Resources/Textures/Mobs/Customization/human_hair.rsi/modern.png
# Resources/Textures/Mobs/Customization/human_hair.rsi/quiff.png
* add: возврат системы тонкоспрайтов
* fix: небольшие фиксы после реверта причесок
* add: старые текстуры для slim бодитайпа
* fix: фикс причесок после апстрима
This commit is contained in:
@@ -5,12 +5,14 @@ using Content.Shared.Clothing;
|
||||
using Content.Shared.Clothing.Components;
|
||||
using Content.Shared.Clothing.EntitySystems;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Inventory.Events;
|
||||
using Content.Shared.Item;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations;
|
||||
using Robust.Shared.Utility;
|
||||
using static Robust.Client.GameObjects.SpriteComponent;
|
||||
@@ -28,30 +30,31 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
/// </summary>
|
||||
private static readonly Dictionary<string, string> TemporarySlotMap = new()
|
||||
{
|
||||
{"head", "HELMET"},
|
||||
{"eyes", "EYES"},
|
||||
{"ears", "EARS"},
|
||||
{"mask", "MASK"},
|
||||
{"outerClothing", "OUTERCLOTHING"},
|
||||
{Jumpsuit, "INNERCLOTHING"},
|
||||
{"neck", "NECK"},
|
||||
{"back", "BACKPACK"},
|
||||
{"belt", "BELT"},
|
||||
{"gloves", "HAND"},
|
||||
{"shoes", "FEET"},
|
||||
{"id", "IDCARD"},
|
||||
{"pocket1", "POCKET1"},
|
||||
{"pocket2", "POCKET2"},
|
||||
{"suitstorage", "SUITSTORAGE"},
|
||||
{ "head", "HELMET" },
|
||||
{ "eyes", "EYES" },
|
||||
{ "ears", "EARS" },
|
||||
{ "mask", "MASK" },
|
||||
{ "outerClothing", "OUTERCLOTHING" },
|
||||
{ Jumpsuit, "INNERCLOTHING" },
|
||||
{ "neck", "NECK" },
|
||||
{ "back", "BACKPACK" },
|
||||
{ "belt", "BELT" },
|
||||
{ "gloves", "HAND" },
|
||||
{ "shoes", "FEET" },
|
||||
{ "id", "IDCARD" },
|
||||
{ "pocket1", "POCKET1" },
|
||||
{ "pocket2", "POCKET2" },
|
||||
{ "suitstorage", "SUITSTORAGE" },
|
||||
//WHITE EDIT
|
||||
{"socks", "SOCKS"},
|
||||
{"underweart", "UNDERWEART"},
|
||||
{"underwearb", "UNDERWEARB"},
|
||||
{ "socks", "SOCKS" },
|
||||
{ "underweart", "UNDERWEART" },
|
||||
{ "underwearb", "UNDERWEARB" },
|
||||
// WHITE EDIT
|
||||
};
|
||||
|
||||
[Dependency] private readonly IResourceCache _cache = default!;
|
||||
[Dependency] private readonly InventorySystem _inventorySystem = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -99,8 +102,13 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
// if that returned nothing, attempt to find generic data
|
||||
if (layers == null && !item.ClothingVisuals.TryGetValue(args.Slot, out layers))
|
||||
{
|
||||
if (!TryComp(args.Equipee, out HumanoidAppearanceComponent? humanoid))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// No generic data either. Attempt to generate defaults from the item's RSI & item-prefixes
|
||||
if (!TryGetDefaultVisuals(uid, item, args.Slot, inventory.SpeciesId, out layers))
|
||||
if (!TryGetDefaultVisuals(uid, item, args.Slot, inventory.SpeciesId, humanoid, out layers))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -126,7 +134,12 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
/// <remarks>
|
||||
/// Useful for lazily adding clothing sprites without modifying yaml. And for backwards compatibility.
|
||||
/// </remarks>
|
||||
private bool TryGetDefaultVisuals(EntityUid uid, ClothingComponent clothing, string slot, string? speciesId,
|
||||
private bool TryGetDefaultVisuals(
|
||||
EntityUid uid,
|
||||
ClothingComponent clothing,
|
||||
string slot,
|
||||
string? speciesId,
|
||||
HumanoidAppearanceComponent humanoid,
|
||||
[NotNullWhen(true)] out List<PrototypeLayerData>? layers)
|
||||
{
|
||||
layers = null;
|
||||
@@ -138,14 +151,12 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
else if (TryComp(uid, out SpriteComponent? sprite))
|
||||
rsi = sprite.BaseRSI;
|
||||
|
||||
if (rsi == null || rsi.Path == null)
|
||||
if (rsi?.Path == null)
|
||||
return false;
|
||||
|
||||
var correctedSlot = slot;
|
||||
TemporarySlotMap.TryGetValue(correctedSlot, out correctedSlot);
|
||||
|
||||
|
||||
|
||||
var state = $"equipped-{correctedSlot}";
|
||||
|
||||
if (clothing.EquippedPrefix != null)
|
||||
@@ -154,6 +165,13 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
if (clothing.EquippedState != null)
|
||||
state = $"{clothing.EquippedState}";
|
||||
|
||||
// body type specific
|
||||
var bodyTypeProto = _prototypeManager.Index<BodyTypePrototype>(humanoid.BodyType);
|
||||
if (rsi.TryGetState($"{state}-{bodyTypeProto.Name}", out _))
|
||||
{
|
||||
state = $"{state}-{bodyTypeProto.Name}";
|
||||
}
|
||||
|
||||
// species specific
|
||||
if (speciesId != null && rsi.TryGetState($"{state}-{speciesId}", out _))
|
||||
{
|
||||
@@ -164,10 +182,13 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
return false;
|
||||
}
|
||||
|
||||
var layer = new PrototypeLayerData();
|
||||
layer.RsiPath = rsi.Path.ToString();
|
||||
layer.State = state;
|
||||
layers = new() { layer };
|
||||
var layer = new PrototypeLayerData
|
||||
{
|
||||
RsiPath = rsi.Path.ToString(),
|
||||
State = state
|
||||
};
|
||||
|
||||
layers = new List<PrototypeLayerData> { layer };
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -189,7 +210,7 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
&& TryComp(uid, out SpriteComponent? sprite)
|
||||
&& sprite.LayerMapTryGet(HumanoidVisualLayers.StencilMask, out var maskLayer))
|
||||
{
|
||||
sprite.LayerSetVisible(maskLayer, false);
|
||||
sprite.LayerSetVisible(maskLayer, false);
|
||||
}
|
||||
|
||||
if (!TryComp(uid, out InventorySlotsComponent? inventorySlots))
|
||||
@@ -204,6 +225,7 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
{
|
||||
component.RemoveLayer(layer);
|
||||
}
|
||||
|
||||
revealedLayers.Clear();
|
||||
}
|
||||
|
||||
@@ -226,12 +248,17 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
RenderEquipment(args.Equipee, uid, args.Slot, clothingComponent: component);
|
||||
}
|
||||
|
||||
private void RenderEquipment(EntityUid equipee, EntityUid equipment, string slot,
|
||||
InventoryComponent? inventory = null, SpriteComponent? sprite = null, ClothingComponent? clothingComponent = null,
|
||||
private void RenderEquipment(
|
||||
EntityUid equipee,
|
||||
EntityUid equipment,
|
||||
string slot,
|
||||
InventoryComponent? inventory = null,
|
||||
SpriteComponent? sprite = null,
|
||||
ClothingComponent? clothingComponent = null,
|
||||
InventorySlotsComponent? inventorySlots = null)
|
||||
{
|
||||
if (!Resolve(equipee, ref inventory, ref sprite, ref inventorySlots) ||
|
||||
!Resolve(equipment, ref clothingComponent, false))
|
||||
!Resolve(equipment, ref clothingComponent, false))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -250,11 +277,12 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
{
|
||||
sprite.RemoveLayer(key);
|
||||
}
|
||||
|
||||
revealedLayers.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
revealedLayers = new();
|
||||
revealedLayers = new HashSet<string>();
|
||||
inventorySlots.VisualLayerKeys[slot] = revealedLayers;
|
||||
}
|
||||
|
||||
@@ -276,7 +304,9 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
{
|
||||
if (!revealedLayers.Add(key))
|
||||
{
|
||||
Logger.Warning($"Duplicate key for clothing visuals: {key}. Are multiple components attempting to modify the same layer? Equipment: {ToPrettyString(equipment)}");
|
||||
Logger.Warning(
|
||||
$"Duplicate key for clothing visuals: {key}. Are multiple components attempting to modify the same layer? Equipment: {ToPrettyString(equipment)}");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -315,12 +345,10 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
RaiseLocalEvent(equipment, new EquipmentVisualsUpdatedEvent(equipee, slot, revealedLayers), true);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets a sprite's gendered mask based on gender (obviously).
|
||||
/// </summary>
|
||||
/// <param name="sprite">Sprite to modify</param>
|
||||
/// <param name="humanoid">Humanoid, to get gender from</param>
|
||||
/// <param name="clothing">Clothing component, to get mask sprite type</param>
|
||||
private void SetGenderedMask(EntityUid uid, SpriteComponent sprite, ClothingComponent clothing)
|
||||
{
|
||||
@@ -330,7 +358,12 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
ClothingMask mask;
|
||||
string prefix;
|
||||
|
||||
switch (CompOrNull<HumanoidAppearanceComponent>(uid)?.Sex)
|
||||
if (!TryComp(uid, out HumanoidAppearanceComponent? humanoid))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (humanoid.Sex)
|
||||
{
|
||||
case Sex.Male:
|
||||
mask = clothing.MaleMask;
|
||||
@@ -338,7 +371,8 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
break;
|
||||
case Sex.Female:
|
||||
mask = clothing.FemaleMask;
|
||||
prefix = "female_";
|
||||
var bodyTypeProto = _prototypeManager.Index<BodyTypePrototype>(humanoid.BodyType!);
|
||||
prefix = bodyTypeProto.Name != "body-normal" ? $"female_{bodyTypeProto.Name}_" : "female_";
|
||||
break;
|
||||
default:
|
||||
mask = clothing.UnisexMask;
|
||||
@@ -348,10 +382,11 @@ public sealed class ClientClothingSystem : ClothingSystem
|
||||
|
||||
sprite.LayerSetState(layer, mask switch
|
||||
{
|
||||
ClothingMask.NoMask => $"{prefix}none",
|
||||
ClothingMask.NoMask => $"{prefix}none",
|
||||
ClothingMask.UniformTop => $"{prefix}top",
|
||||
_ => $"{prefix}full",
|
||||
_ => $"{prefix}full",
|
||||
});
|
||||
|
||||
sprite.LayerSetVisible(layer, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,9 +42,8 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||
component.BaseLayers.Clear();
|
||||
|
||||
// add default species layers
|
||||
var speciesProto = _prototypeManager.Index(component.Species);
|
||||
var baseSprites = _prototypeManager.Index<HumanoidSpeciesBaseSpritesPrototype>(speciesProto.SpriteSet);
|
||||
foreach (var (key, id) in baseSprites.Sprites)
|
||||
var bodyTypeProto = _prototypeManager.Index<BodyTypePrototype>(component.BodyType);
|
||||
foreach (var (key, id) in bodyTypeProto.Sprites)
|
||||
{
|
||||
oldLayers.Remove(key);
|
||||
if (!component.CustomBaseLayers.ContainsKey(key))
|
||||
@@ -108,13 +107,17 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||
/// This should not be used if the entity is owned by the server. The server will otherwise
|
||||
/// override this with the appearance data it sends over.
|
||||
/// </remarks>
|
||||
public override void LoadProfile(EntityUid uid, HumanoidCharacterProfile profile, HumanoidAppearanceComponent? humanoid = null)
|
||||
public override void LoadProfile(
|
||||
EntityUid uid,
|
||||
HumanoidCharacterProfile profile,
|
||||
HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (!Resolve(uid, ref humanoid))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
humanoid.BodyType = profile.BodyType;
|
||||
var customBaseLayers = new Dictionary<HumanoidVisualLayers, CustomBaseLayerInfo>();
|
||||
|
||||
var speciesPrototype = _prototypeManager.Index<SpeciesPrototype>(profile.Species);
|
||||
@@ -142,15 +145,19 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||
//markings.RemoveCategory(MarkingCategories.FacialHair);
|
||||
|
||||
// We need to ensure hair before applying it or coloring can try depend on markings that can be invalid
|
||||
var hairColor = _markingManager.MustMatchSkin(profile.Species, HumanoidVisualLayers.Hair, out var hairAlpha, _prototypeManager)
|
||||
var hairColor = _markingManager.MustMatchSkin(profile.BodyType, HumanoidVisualLayers.Hair, out var hairAlpha,
|
||||
_prototypeManager)
|
||||
? profile.Appearance.SkinColor.WithAlpha(hairAlpha)
|
||||
: profile.Appearance.HairColor;
|
||||
|
||||
var hair = new Marking(profile.Appearance.HairStyleId,
|
||||
new[] { hairColor });
|
||||
|
||||
var facialHairColor = _markingManager.MustMatchSkin(profile.Species, HumanoidVisualLayers.FacialHair, out var facialHairAlpha, _prototypeManager)
|
||||
var facialHairColor = _markingManager.MustMatchSkin(profile.BodyType, HumanoidVisualLayers.FacialHair,
|
||||
out var facialHairAlpha, _prototypeManager)
|
||||
? profile.Appearance.SkinColor.WithAlpha(facialHairAlpha)
|
||||
: profile.Appearance.FacialHairColor;
|
||||
|
||||
var facialHair = new Marking(profile.Appearance.FacialHairStyleId,
|
||||
new[] { facialHairColor });
|
||||
|
||||
@@ -158,6 +165,7 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||
{
|
||||
markings.AddBack(MarkingCategories.Hair, hair);
|
||||
}
|
||||
|
||||
if (_markingManager.CanBeApplied(profile.Species, profile.Sex, facialHair, _prototypeManager))
|
||||
{
|
||||
markings.AddBack(MarkingCategories.FacialHair, facialHair);
|
||||
@@ -172,10 +180,13 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||
profile.Appearance.EyeColor,
|
||||
markings
|
||||
);
|
||||
|
||||
markings.AddBack(prototype.MarkingCategory, new Marking(marking.MarkingId, markingColors));
|
||||
}
|
||||
|
||||
markings.EnsureSpecies(profile.Species, profile.Appearance.SkinColor, _markingManager, _prototypeManager);
|
||||
markings.EnsureSpecies(profile.Species, profile.BodyType, profile.Appearance.SkinColor, _markingManager,
|
||||
_prototypeManager);
|
||||
|
||||
markings.EnsureSexes(profile.Sex, _markingManager);
|
||||
markings.EnsureDefault(
|
||||
profile.Appearance.SkinColor,
|
||||
@@ -190,6 +201,7 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||
humanoid.CustomBaseLayers = customBaseLayers;
|
||||
humanoid.Sex = profile.Sex;
|
||||
humanoid.Gender = profile.Gender;
|
||||
humanoid.BodyType = profile.BodyType;
|
||||
humanoid.Age = profile.Age;
|
||||
humanoid.Species = profile.Species;
|
||||
humanoid.SkinColor = profile.Appearance.SkinColor;
|
||||
@@ -261,7 +273,9 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||
spriteComp.RemoveLayer(index);
|
||||
}
|
||||
}
|
||||
private void ApplyMarking(MarkingPrototype markingPrototype,
|
||||
|
||||
private void ApplyMarking(
|
||||
MarkingPrototype markingPrototype,
|
||||
IReadOnlyList<Color>? colors,
|
||||
bool visible,
|
||||
HumanoidAppearanceComponent humanoid,
|
||||
@@ -274,7 +288,7 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||
|
||||
visible &= !IsHidden(humanoid, markingPrototype.BodyPart);
|
||||
visible &= humanoid.BaseLayers.TryGetValue(markingPrototype.BodyPart, out var setting)
|
||||
&& setting.AllowsMarkings;
|
||||
&& setting.AllowsMarkings;
|
||||
|
||||
for (var j = 0; j < markingPrototype.Sprites.Count; j++)
|
||||
{
|
||||
@@ -315,7 +329,12 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||
}
|
||||
}
|
||||
|
||||
public override void SetSkinColor(EntityUid uid, Color skinColor, bool sync = true, bool verify = true, HumanoidAppearanceComponent? humanoid = null)
|
||||
public override void SetSkinColor(
|
||||
EntityUid uid,
|
||||
Color skinColor,
|
||||
bool sync = true,
|
||||
bool verify = true,
|
||||
HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (!Resolve(uid, ref humanoid) || humanoid.SkinColor == skinColor)
|
||||
return;
|
||||
@@ -366,7 +385,8 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
||||
{
|
||||
foreach (var marking in markingList)
|
||||
{
|
||||
if (_markingManager.TryGetMarking(marking, out var markingPrototype) && markingPrototype.BodyPart == layer)
|
||||
if (_markingManager.TryGetMarking(marking, out var markingPrototype) &&
|
||||
markingPrototype.BodyPart == layer)
|
||||
ApplyMarking(markingPrototype, marking.MarkingColors, marking.Visible, humanoid, sprite);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public sealed class HumanoidMarkingModifierBoundUserInterface : BoundUserInterfa
|
||||
return;
|
||||
}
|
||||
|
||||
_window.SetState(cast.MarkingSet, cast.Species, cast.Sex, cast.SkinColor, cast.CustomBaseLayers);
|
||||
_window.SetState(cast.MarkingSet, cast.Species, cast.Sex, cast.BodyType, cast.SkinColor, cast.CustomBaseLayers);
|
||||
}
|
||||
|
||||
private void SendMarkingSet(MarkingSet set)
|
||||
|
||||
@@ -59,10 +59,12 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
||||
string? state = _protoMan.HasIndex<HumanoidSpeciesSpriteLayer>(modifier.Text) ? modifier.Text : null;
|
||||
OnLayerInfoModified?.Invoke(layer, new CustomBaseLayerInfo(state, modifier.Color));
|
||||
}
|
||||
|
||||
public void SetState(
|
||||
MarkingSet markings,
|
||||
string species,
|
||||
Sex sex,
|
||||
string bodyType,
|
||||
Color skinColor,
|
||||
Dictionary<HumanoidVisualLayers, CustomBaseLayerInfo> info
|
||||
)
|
||||
@@ -84,7 +86,7 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
||||
eyesColor = eyes.Color.Value;
|
||||
}
|
||||
|
||||
MarkingPickerWidget.SetData(markings, species, sex, skinColor, eyesColor);
|
||||
MarkingPickerWidget.SetData(markings, species, sex, bodyType, skinColor, eyesColor);
|
||||
}
|
||||
|
||||
private sealed class HumanoidBaseLayerModifier : BoxContainer
|
||||
@@ -95,7 +97,9 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
||||
private BoxContainer _infoBox;
|
||||
|
||||
public bool Enabled => _enable.Pressed;
|
||||
|
||||
public string Text => _lineEdit.Text;
|
||||
|
||||
public Color Color => _colorSliders.Color;
|
||||
|
||||
public Action? OnStateChanged;
|
||||
@@ -109,6 +113,7 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
||||
MinWidth = 250,
|
||||
HorizontalExpand = true
|
||||
};
|
||||
|
||||
AddChild(labelBox);
|
||||
|
||||
labelBox.AddChild(new Label
|
||||
@@ -116,6 +121,7 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
||||
HorizontalExpand = true,
|
||||
Text = layer.ToString()
|
||||
});
|
||||
|
||||
_enable = new CheckBox
|
||||
{
|
||||
Text = "Enable",
|
||||
@@ -128,6 +134,7 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
||||
Orientation = LayoutOrientation.Vertical,
|
||||
Visible = false
|
||||
};
|
||||
|
||||
_enable.OnToggled += args =>
|
||||
{
|
||||
_infoBox.Visible = args.Pressed;
|
||||
@@ -135,7 +142,7 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
||||
};
|
||||
|
||||
var lineEditBox = new BoxContainer();
|
||||
lineEditBox.AddChild(new Label { Text = "Prototype id: "});
|
||||
lineEditBox.AddChild(new Label { Text = "Prototype id: " });
|
||||
|
||||
// TODO: This line edit should really be an options / dropdown selector, not text.
|
||||
_lineEdit = new() { MinWidth = 200 };
|
||||
|
||||
@@ -40,6 +40,7 @@ public sealed partial class MarkingPicker : Control
|
||||
private List<MarkingCategories> _markingCategories = Enum.GetValues<MarkingCategories>().ToList();
|
||||
|
||||
private string _currentSpecies = SharedHumanoidAppearanceSystem.DefaultSpecies;
|
||||
private string _currentBodyType = SharedHumanoidAppearanceSystem.DefaultBodyType;
|
||||
private Sex _currentSex = Sex.Unsexed;
|
||||
public Color CurrentSkinColor = Color.White;
|
||||
public Color CurrentEyeColor = Color.Black;
|
||||
@@ -83,7 +84,7 @@ public sealed partial class MarkingPicker : Control
|
||||
}
|
||||
}
|
||||
|
||||
public void SetData(List<Marking> newMarkings, string species, Sex sex, Color skinColor, Color eyeColor)
|
||||
public void SetData(List<Marking> newMarkings, string species, Sex sex, string bodyType, Color skinColor, Color eyeColor)
|
||||
{
|
||||
var pointsProto = _prototypeManager
|
||||
.Index<SpeciesPrototype>(species).MarkingPoints;
|
||||
@@ -91,7 +92,7 @@ public sealed partial class MarkingPicker : Control
|
||||
|
||||
if (!IgnoreSpecies)
|
||||
{
|
||||
_currentMarkings.EnsureSpecies(species, skinColor, _markingManager); // should be validated server-side but it can't hurt
|
||||
_currentMarkings.EnsureSpecies(species, bodyType, skinColor, _markingManager); // should be validated server-side but it can't hurt
|
||||
}
|
||||
|
||||
_currentSpecies = species;
|
||||
@@ -103,13 +104,13 @@ public sealed partial class MarkingPicker : Control
|
||||
PopulateUsed();
|
||||
}
|
||||
|
||||
public void SetData(MarkingSet set, string species, Sex sex, Color skinColor, Color eyeColor)
|
||||
public void SetData(MarkingSet set, string species, Sex sex, string bodyType, Color skinColor, Color eyeColor)
|
||||
{
|
||||
_currentMarkings = set;
|
||||
|
||||
if (!IgnoreSpecies)
|
||||
{
|
||||
_currentMarkings.EnsureSpecies(species, skinColor, _markingManager); // should be validated server-side but it can't hurt
|
||||
_currentMarkings.EnsureSpecies(species, bodyType, skinColor, _markingManager); // should be validated server-side but it can't hurt
|
||||
}
|
||||
|
||||
_currentSpecies = species;
|
||||
@@ -234,7 +235,7 @@ public sealed partial class MarkingPicker : Control
|
||||
|
||||
if (!IgnoreSpecies)
|
||||
{
|
||||
_currentMarkings.EnsureSpecies(_currentSpecies, null, _markingManager);
|
||||
_currentMarkings.EnsureSpecies(_currentSpecies, _currentBodyType, null, _markingManager);
|
||||
}
|
||||
|
||||
// walk backwards through the list for visual purposes
|
||||
@@ -338,7 +339,7 @@ public sealed partial class MarkingPicker : Control
|
||||
var speciesPrototype = _prototypeManager.Index<SpeciesPrototype>(species);
|
||||
|
||||
_currentMarkings = new(markingList, speciesPrototype.MarkingPoints, _markingManager, _prototypeManager);
|
||||
_currentMarkings.EnsureSpecies(species, null, _markingManager);
|
||||
_currentMarkings.EnsureSpecies(species, _currentBodyType, null, _markingManager);
|
||||
_currentMarkings.EnsureSexes(_currentSex, _markingManager);
|
||||
|
||||
Populate(CMarkingSearch.Text);
|
||||
@@ -353,7 +354,7 @@ public sealed partial class MarkingPicker : Control
|
||||
var speciesPrototype = _prototypeManager.Index<SpeciesPrototype>(_currentSpecies);
|
||||
|
||||
_currentMarkings = new(markingList, speciesPrototype.MarkingPoints, _markingManager, _prototypeManager);
|
||||
_currentMarkings.EnsureSpecies(_currentSpecies, null, _markingManager);
|
||||
_currentMarkings.EnsureSpecies(_currentSpecies, _currentBodyType, null, _markingManager);
|
||||
_currentMarkings.EnsureSexes(_currentSex, _markingManager);
|
||||
|
||||
Populate(CMarkingSearch.Text);
|
||||
|
||||
@@ -75,6 +75,12 @@
|
||||
<Control HorizontalExpand="True"/>
|
||||
<OptionButton Name="CSpeciesButton" HorizontalAlignment="Right" />
|
||||
</BoxContainer>
|
||||
<!-- Body Type -->
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<Label Text="{Loc 'humanoid-profile-editor-body-type-label'}"/>
|
||||
<Control HorizontalExpand="True"/>
|
||||
<OptionButton Name="CBodyTypesButton" HorizontalAlignment="Right" />
|
||||
</BoxContainer>
|
||||
<!-- Age -->
|
||||
<BoxContainer HorizontalExpand="True">
|
||||
<Label Text="{Loc 'humanoid-profile-editor-age-label'}" />
|
||||
|
||||
@@ -14,13 +14,11 @@ using Content.Shared.GameTicking;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Markings;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Preferences;
|
||||
using Content.Shared.Roles;
|
||||
using Content.Shared.StatusIcon;
|
||||
using Content.Shared.Traits;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
@@ -29,10 +27,8 @@ using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Client.Utility;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
using static Robust.Client.UserInterface.Controls.BoxContainer;
|
||||
@@ -44,7 +40,7 @@ namespace Content.Client.Preferences.UI
|
||||
{
|
||||
public HighlightedContainer()
|
||||
{
|
||||
PanelOverride = new StyleBoxFlat()
|
||||
PanelOverride = new StyleBoxFlat
|
||||
{
|
||||
BackgroundColor = new Color(25, 25, 25),
|
||||
ContentMarginTopOverride = 10,
|
||||
@@ -110,6 +106,7 @@ namespace Content.Client.Preferences.UI
|
||||
private readonly List<SpeciesPrototype> _speciesList;
|
||||
private readonly List<AntagPreferenceSelector> _antagPreferences;
|
||||
private readonly List<TraitPreferenceSelector> _traitPreferences;
|
||||
private List<BodyTypePrototype> _bodyTypesList = new();
|
||||
|
||||
private SpriteView _previewSpriteView => CSpriteView;
|
||||
private Button _previewRotateLeftButton => CSpriteRotateLeft;
|
||||
@@ -177,6 +174,14 @@ namespace Content.Client.Preferences.UI
|
||||
|
||||
#endregion Sex
|
||||
|
||||
#region Body Type
|
||||
|
||||
CBodyTypesButton.OnItemSelected += OnBodyTypeSelected;
|
||||
|
||||
UpdateBodyTypes();
|
||||
|
||||
#endregion Body Type
|
||||
|
||||
#region Age
|
||||
|
||||
_ageEdit.OnTextChanged += args =>
|
||||
@@ -845,6 +850,7 @@ namespace Content.Client.Preferences.UI
|
||||
CMarkings.SetSpecies(newSpecies); // Repopulate the markings tab as well.
|
||||
UpdateSexControls(); // update sex for new species
|
||||
RebuildSpriteView(); // they might have different inv so we need a new dummy
|
||||
UpdateBodyTypes();
|
||||
IsDirty = true;
|
||||
_needUpdatePreview = true;
|
||||
}
|
||||
@@ -903,6 +909,38 @@ namespace Content.Client.Preferences.UI
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBodyTypeSelected(OptionButton.ItemSelectedEventArgs args)
|
||||
{
|
||||
args.Button.SelectId(args.Id);
|
||||
SetBodyType(_bodyTypesList[args.Id].ID);
|
||||
}
|
||||
|
||||
private void UpdateBodyTypes()
|
||||
{
|
||||
if (Profile is null)
|
||||
return;
|
||||
|
||||
CBodyTypesButton.Clear();
|
||||
var species = _prototypeManager.Index<SpeciesPrototype>(Profile.Species);
|
||||
var sex = Profile.Sex;
|
||||
_bodyTypesList = EntitySystem.Get<HumanoidAppearanceSystem>().GetValidBodyTypes(species, sex);
|
||||
|
||||
for (var i = 0; i < _bodyTypesList.Count; i++)
|
||||
{
|
||||
CBodyTypesButton.AddItem(Loc.GetString(_bodyTypesList[i].Name), i);
|
||||
}
|
||||
|
||||
// If current body type is not valid.
|
||||
if (!_bodyTypesList.Select(proto => proto.ID).Contains(Profile.BodyType))
|
||||
{
|
||||
// Then replace it with a first valid body type.
|
||||
SetBodyType(_bodyTypesList.First().ID);
|
||||
}
|
||||
|
||||
CBodyTypesButton.Select(_bodyTypesList.FindIndex(x => x.ID == Profile.BodyType));
|
||||
IsDirty = true;
|
||||
}
|
||||
|
||||
private bool IsDirty
|
||||
{
|
||||
get => _isDirty;
|
||||
@@ -1025,7 +1063,7 @@ namespace Content.Client.Preferences.UI
|
||||
}
|
||||
|
||||
CMarkings.SetData(Profile.Appearance.Markings, Profile.Species,
|
||||
Profile.Sex, Profile.Appearance.SkinColor, Profile.Appearance.EyeColor
|
||||
Profile.Sex, Profile.BodyType, Profile.Appearance.SkinColor, Profile.Appearance.EyeColor
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1090,13 +1128,13 @@ namespace Content.Client.Preferences.UI
|
||||
var hairMarking = Profile.Appearance.HairStyleId switch
|
||||
{
|
||||
HairStyles.DefaultHairStyle => new List<Marking>(),
|
||||
_ => new() { new(Profile.Appearance.HairStyleId, new List<Color>() { Profile.Appearance.HairColor }) },
|
||||
_ => new() { new(Profile.Appearance.HairStyleId, new List<Color> { Profile.Appearance.HairColor }) },
|
||||
};
|
||||
|
||||
var facialHairMarking = Profile.Appearance.FacialHairStyleId switch
|
||||
{
|
||||
HairStyles.DefaultFacialHairStyle => new List<Marking>(),
|
||||
_ => new() { new(Profile.Appearance.FacialHairStyleId, new List<Color>() { Profile.Appearance.FacialHairColor }) },
|
||||
_ => new() { new(Profile.Appearance.FacialHairStyleId, new List<Color> { Profile.Appearance.FacialHairColor }) },
|
||||
};
|
||||
|
||||
_hairPicker.UpdateData(
|
||||
@@ -1124,7 +1162,7 @@ namespace Content.Client.Preferences.UI
|
||||
{
|
||||
if (_markingManager.CanBeApplied(Profile.Species, Profile.Sex, hairProto, _prototypeManager))
|
||||
{
|
||||
if (_markingManager.MustMatchSkin(Profile.Species, HumanoidVisualLayers.Hair, out var _, _prototypeManager))
|
||||
if (_markingManager.MustMatchSkin(Profile.BodyType, HumanoidVisualLayers.Hair, out _, _prototypeManager))
|
||||
{
|
||||
hairColor = Profile.Appearance.SkinColor;
|
||||
}
|
||||
@@ -1136,7 +1174,7 @@ namespace Content.Client.Preferences.UI
|
||||
}
|
||||
if (hairColor != null)
|
||||
{
|
||||
CMarkings.HairMarking = new (Profile.Appearance.HairStyleId, new List<Color>() { hairColor.Value });
|
||||
CMarkings.HairMarking = new (Profile.Appearance.HairStyleId, new List<Color> { hairColor.Value });
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1159,7 +1197,7 @@ namespace Content.Client.Preferences.UI
|
||||
{
|
||||
if (_markingManager.CanBeApplied(Profile.Species, Profile.Sex, facialHairProto, _prototypeManager))
|
||||
{
|
||||
if (_markingManager.MustMatchSkin(Profile.Species, HumanoidVisualLayers.Hair, out var _, _prototypeManager))
|
||||
if (_markingManager.MustMatchSkin(Profile.BodyType, HumanoidVisualLayers.Hair, out _, _prototypeManager))
|
||||
{
|
||||
facialHairColor = Profile.Appearance.SkinColor;
|
||||
}
|
||||
@@ -1171,7 +1209,7 @@ namespace Content.Client.Preferences.UI
|
||||
}
|
||||
if (facialHairColor != null)
|
||||
{
|
||||
CMarkings.FacialHairMarking = new (Profile.Appearance.FacialHairStyleId, new List<Color>() { facialHairColor.Value });
|
||||
CMarkings.FacialHairMarking = new (Profile.Appearance.FacialHairStyleId, new List<Color> { facialHairColor.Value });
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1237,6 +1275,7 @@ namespace Content.Client.Preferences.UI
|
||||
|
||||
//WD-EDIT
|
||||
UpdateTTSVoicesControls();
|
||||
UpdateBodyTypes();
|
||||
//WD-EDIT
|
||||
|
||||
_preferenceUnavailableButton.SelectId((int) Profile.PreferenceUnavailable);
|
||||
@@ -1299,6 +1338,14 @@ namespace Content.Client.Preferences.UI
|
||||
|
||||
return allowedSpecies;
|
||||
}
|
||||
|
||||
private void SetBodyType(string newBodyType)
|
||||
{
|
||||
Profile = Profile?.WithBodyType(newBodyType);
|
||||
IsDirty = true;
|
||||
_needUpdatePreview = true;
|
||||
}
|
||||
|
||||
//WD EDIT END
|
||||
|
||||
private void UpdateJobPriorities()
|
||||
@@ -1337,7 +1384,7 @@ namespace Content.Client.Preferences.UI
|
||||
|
||||
Options.OnItemSelected += args => Options.Select(args.Id);
|
||||
|
||||
_requirementsLabel = new Label()
|
||||
_requirementsLabel = new Label
|
||||
{
|
||||
Text = Loc.GetString("role-timer-locked"),
|
||||
Visible = true,
|
||||
@@ -1345,7 +1392,7 @@ namespace Content.Client.Preferences.UI
|
||||
StyleClasses = {StyleBase.StyleClassLabelSubText},
|
||||
};
|
||||
|
||||
_lockStripe = new StripeBack()
|
||||
_lockStripe = new StripeBack
|
||||
{
|
||||
Visible = false,
|
||||
HorizontalExpand = true,
|
||||
@@ -1369,7 +1416,7 @@ namespace Content.Client.Preferences.UI
|
||||
Options.AddItem(Loc.GetString(text), value);
|
||||
}
|
||||
|
||||
var titleLabel = new Label()
|
||||
var titleLabel = new Label
|
||||
{
|
||||
Margin = new Thickness(5f, 0, 5f, 0),
|
||||
Text = title,
|
||||
|
||||
Reference in New Issue
Block a user