Fix humanoid appearance error (#13721)
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
using Content.Shared.Ghost;
|
||||||
using Content.Shared.Humanoid;
|
using Content.Shared.Humanoid;
|
||||||
using Content.Shared.Humanoid.Markings;
|
using Content.Shared.Humanoid.Markings;
|
||||||
using Content.Shared.Humanoid.Prototypes;
|
using Content.Shared.Humanoid.Prototypes;
|
||||||
@@ -86,28 +87,31 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
|||||||
HumanoidAppearanceComponent component,
|
HumanoidAppearanceComponent component,
|
||||||
SpriteComponent sprite,
|
SpriteComponent sprite,
|
||||||
HumanoidVisualLayers key,
|
HumanoidVisualLayers key,
|
||||||
string protoId,
|
string? protoId,
|
||||||
bool sexMorph = false,
|
bool sexMorph = false,
|
||||||
Color? color = null)
|
Color? color = null)
|
||||||
{
|
{
|
||||||
|
var layerIndex = sprite.LayerMapReserveBlank(key);
|
||||||
|
var layer = sprite[layerIndex];
|
||||||
|
layer.Visible = !IsHidden(component, key);
|
||||||
|
|
||||||
|
if (color != null)
|
||||||
|
layer.Color = color.Value;
|
||||||
|
|
||||||
|
if (protoId == null)
|
||||||
|
return;
|
||||||
|
|
||||||
if (sexMorph)
|
if (sexMorph)
|
||||||
protoId = HumanoidVisualLayersExtension.GetSexMorph(key, component.Sex, protoId);
|
protoId = HumanoidVisualLayersExtension.GetSexMorph(key, component.Sex, protoId);
|
||||||
|
|
||||||
var proto = _prototypeManager.Index<HumanoidSpeciesSpriteLayer>(protoId);
|
var proto = _prototypeManager.Index<HumanoidSpeciesSpriteLayer>(protoId);
|
||||||
component.BaseLayers[key] = proto;
|
component.BaseLayers[key] = proto;
|
||||||
|
|
||||||
var layerIndex = sprite.LayerMapReserveBlank(key);
|
if (proto.MatchSkin)
|
||||||
var layer = sprite[layerIndex];
|
layer.Color = component.SkinColor.WithAlpha(proto.LayerAlpha);
|
||||||
|
|
||||||
if (color != null)
|
|
||||||
layer.Color = color.Value;
|
|
||||||
else if (proto.MatchSkin)
|
|
||||||
layer.Color = proto.MatchSkin ? component.SkinColor.WithAlpha(proto.LayerAlpha) : Color.White;
|
|
||||||
|
|
||||||
if (proto.BaseSprite != null)
|
if (proto.BaseSprite != null)
|
||||||
sprite.LayerSetSprite(layerIndex, proto.BaseSprite);
|
sprite.LayerSetSprite(layerIndex, proto.BaseSprite);
|
||||||
|
|
||||||
layer.Visible = !IsHidden(component, key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
using Content.Shared.Humanoid;
|
using Content.Shared.Humanoid;
|
||||||
using Content.Shared.Humanoid.Markings;
|
using Content.Shared.Humanoid.Markings;
|
||||||
|
using Content.Shared.Humanoid.Prototypes;
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
using Robust.Client.UserInterface.CustomControls;
|
using Robust.Client.UserInterface.CustomControls;
|
||||||
using Robust.Client.UserInterface.XAML;
|
using Robust.Client.UserInterface.XAML;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
using static Content.Shared.Humanoid.HumanoidAppearanceState;
|
using static Content.Shared.Humanoid.HumanoidAppearanceState;
|
||||||
|
|
||||||
namespace Content.Client.Humanoid;
|
namespace Content.Client.Humanoid;
|
||||||
@@ -18,12 +20,14 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
|||||||
public Action<MarkingSet>? OnMarkingColorChange;
|
public Action<MarkingSet>? OnMarkingColorChange;
|
||||||
public Action<MarkingSet>? OnMarkingRankChange;
|
public Action<MarkingSet>? OnMarkingRankChange;
|
||||||
public Action<HumanoidVisualLayers, CustomBaseLayerInfo?>? OnLayerInfoModified;
|
public Action<HumanoidVisualLayers, CustomBaseLayerInfo?>? OnLayerInfoModified;
|
||||||
|
private readonly IPrototypeManager _protoMan = default!;
|
||||||
|
|
||||||
private readonly Dictionary<HumanoidVisualLayers, HumanoidBaseLayerModifier> _modifiers = new();
|
private readonly Dictionary<HumanoidVisualLayers, HumanoidBaseLayerModifier> _modifiers = new();
|
||||||
|
|
||||||
public HumanoidMarkingModifierWindow()
|
public HumanoidMarkingModifierWindow()
|
||||||
{
|
{
|
||||||
RobustXamlLoader.Load(this);
|
RobustXamlLoader.Load(this);
|
||||||
|
_protoMan = IoCManager.Resolve<IPrototypeManager>();
|
||||||
|
|
||||||
foreach (var layer in Enum.GetValues<HumanoidVisualLayers>())
|
foreach (var layer in Enum.GetValues<HumanoidVisualLayers>())
|
||||||
{
|
{
|
||||||
@@ -31,14 +35,7 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
|||||||
BaseLayersContainer.AddChild(modifier);
|
BaseLayersContainer.AddChild(modifier);
|
||||||
_modifiers.Add(layer, modifier);
|
_modifiers.Add(layer, modifier);
|
||||||
|
|
||||||
modifier.OnStateChanged += delegate
|
modifier.OnStateChanged += () => OnStateChanged(layer, modifier);
|
||||||
{
|
|
||||||
OnLayerInfoModified!(
|
|
||||||
layer,
|
|
||||||
modifier.Enabled
|
|
||||||
? new CustomBaseLayerInfo(modifier.State, modifier.Color)
|
|
||||||
: null);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MarkingPickerWidget.OnMarkingAdded += set => OnMarkingAdded!(set);
|
MarkingPickerWidget.OnMarkingAdded += set => OnMarkingAdded!(set);
|
||||||
@@ -52,6 +49,18 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
|||||||
MarkingPickerWidget.IgnoreSpecies = MarkingForced.Pressed;
|
MarkingPickerWidget.IgnoreSpecies = MarkingForced.Pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnStateChanged(HumanoidVisualLayers layer, HumanoidBaseLayerModifier modifier)
|
||||||
|
{
|
||||||
|
if (!modifier.Enabled)
|
||||||
|
{
|
||||||
|
OnLayerInfoModified?.Invoke(layer, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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, Color skinColor, Dictionary<HumanoidVisualLayers, CustomBaseLayerInfo> info)
|
public void SetState(MarkingSet markings, string species, Color skinColor, Dictionary<HumanoidVisualLayers, CustomBaseLayerInfo> info)
|
||||||
{
|
{
|
||||||
MarkingPickerWidget.SetData(markings, species, skinColor);
|
MarkingPickerWidget.SetData(markings, species, skinColor);
|
||||||
@@ -64,7 +73,7 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier.SetState(true, layerInfo.ID, layerInfo.Color ?? Color.White);
|
modifier.SetState(true, layerInfo.ID ?? string.Empty, layerInfo.Color ?? Color.White);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +85,7 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
|||||||
private BoxContainer _infoBox;
|
private BoxContainer _infoBox;
|
||||||
|
|
||||||
public bool Enabled => _enable.Pressed;
|
public bool Enabled => _enable.Pressed;
|
||||||
public string State => _lineEdit.Text;
|
public string Text => _lineEdit.Text;
|
||||||
public Color Color => _colorSliders.Color;
|
public Color Color => _colorSliders.Color;
|
||||||
|
|
||||||
public Action? OnStateChanged;
|
public Action? OnStateChanged;
|
||||||
@@ -117,7 +126,9 @@ public sealed partial class HumanoidMarkingModifierWindow : DefaultWindow
|
|||||||
|
|
||||||
var lineEditBox = new BoxContainer();
|
var lineEditBox = new BoxContainer();
|
||||||
lineEditBox.AddChild(new Label { Text = "Prototype id: "});
|
lineEditBox.AddChild(new Label { Text = "Prototype id: "});
|
||||||
_lineEdit = new();
|
|
||||||
|
// TODO: This line edit should really be an options / dropdown selector, not text.
|
||||||
|
_lineEdit = new() { MinWidth = 200 };
|
||||||
_lineEdit.OnTextEntered += args => OnStateChanged!();
|
_lineEdit.OnTextEntered += args => OnStateChanged!();
|
||||||
lineEditBox.AddChild(_lineEdit);
|
lineEditBox.AddChild(_lineEdit);
|
||||||
_infoBox.AddChild(lineEditBox);
|
_infoBox.AddChild(lineEditBox);
|
||||||
|
|||||||
@@ -114,9 +114,9 @@ public sealed class HumanoidAppearanceState : ComponentState
|
|||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public readonly struct CustomBaseLayerInfo
|
public readonly struct CustomBaseLayerInfo
|
||||||
{
|
{
|
||||||
public CustomBaseLayerInfo(string id, Color? color = null)
|
public CustomBaseLayerInfo(string? id, Color? color = null)
|
||||||
{
|
{
|
||||||
DebugTools.Assert(IoCManager.Resolve<IPrototypeManager>().HasIndex<HumanoidSpeciesSpriteLayer>(id));
|
DebugTools.Assert(id == null || IoCManager.Resolve<IPrototypeManager>().HasIndex<HumanoidSpeciesSpriteLayer>(id));
|
||||||
ID = id;
|
ID = id;
|
||||||
Color = color;
|
Color = color;
|
||||||
}
|
}
|
||||||
@@ -124,11 +124,11 @@ public sealed class HumanoidAppearanceState : ComponentState
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// ID of this custom base layer. Must be a <see cref="HumanoidSpeciesSpriteLayer"/>.
|
/// ID of this custom base layer. Must be a <see cref="HumanoidSpeciesSpriteLayer"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("id", customTypeSerializer: typeof(PrototypeIdSerializer<HumanoidSpeciesSpriteLayer>), required: true)]
|
[DataField("id", customTypeSerializer: typeof(PrototypeIdSerializer<HumanoidSpeciesSpriteLayer>))]
|
||||||
public string ID { init; get; }
|
public string? ID { init; get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Color of this custom base layer. Null implies skin colour.
|
/// Color of this custom base layer. Null implies skin colour if the corresponding <see cref="HumanoidSpeciesSpriteLayer"/> is set to match skin.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("color")]
|
[DataField("color")]
|
||||||
public Color? Color { init; get; }
|
public Color? Color { init; get; }
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
|||||||
/// <param name="id">The ID of the sprite to use. See <see cref="HumanoidSpeciesSpriteLayer"/>.</param>
|
/// <param name="id">The ID of the sprite to use. See <see cref="HumanoidSpeciesSpriteLayer"/>.</param>
|
||||||
/// <param name="sync">Whether to synchronize this to the humanoid mob, or not.</param>
|
/// <param name="sync">Whether to synchronize this to the humanoid mob, or not.</param>
|
||||||
/// <param name="humanoid">Humanoid component of the entity</param>
|
/// <param name="humanoid">Humanoid component of the entity</param>
|
||||||
public void SetBaseLayerId(EntityUid uid, HumanoidVisualLayers layer, string id, bool sync = true,
|
public void SetBaseLayerId(EntityUid uid, HumanoidVisualLayers layer, string? id, bool sync = true,
|
||||||
HumanoidAppearanceComponent? humanoid = null)
|
HumanoidAppearanceComponent? humanoid = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref humanoid))
|
if (!Resolve(uid, ref humanoid))
|
||||||
@@ -192,7 +192,10 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
|||||||
if (!Resolve(uid, ref humanoid))
|
if (!Resolve(uid, ref humanoid))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
humanoid.CustomBaseLayers[layer] = humanoid.CustomBaseLayers[layer] with { Color = color };
|
if (humanoid.CustomBaseLayers.TryGetValue(layer, out var info))
|
||||||
|
humanoid.CustomBaseLayers[layer] = info with { Color = color };
|
||||||
|
else
|
||||||
|
humanoid.CustomBaseLayers[layer] = new(null, color);
|
||||||
|
|
||||||
if (sync)
|
if (sync)
|
||||||
Dirty(humanoid);
|
Dirty(humanoid);
|
||||||
|
|||||||
Reference in New Issue
Block a user