Попытка сделать адекватный градиент (#3195)
This commit is contained in:
parent
c38d90ee53
commit
c286124224
45 changed files with 1595 additions and 4011 deletions
|
|
@ -23,29 +23,15 @@ public sealed class DisplacementMapSystem : EntitySystem
|
|||
Entity<SpriteComponent> sprite,
|
||||
int index,
|
||||
object key,
|
||||
out string displacementKey,
|
||||
ShaderInstance? shaderOverride = null) // Sunrise-Edit
|
||||
out string displacementKey)
|
||||
{
|
||||
displacementKey = $"{key}-displacement";
|
||||
|
||||
if (key.ToString() is null)
|
||||
return false;
|
||||
|
||||
// Sunrise-Start
|
||||
// sprite.Comp.LayerSetShader(index, data.ShaderOverride);
|
||||
// TODO: костыль пиздец, когда появится возможность устанавливать 2 шейдера на один леер - удалить эту хуйню
|
||||
if (data.ShaderOverride != null)
|
||||
{
|
||||
if (shaderOverride != null)
|
||||
{
|
||||
shaderOverride.SetParameter("useDisplacement", true);
|
||||
shaderOverride.SetParameter("displacementSize", 127);
|
||||
sprite.Comp.LayerSetShader(index, shaderOverride);
|
||||
}
|
||||
else
|
||||
sprite.Comp.LayerSetShader(index, data.ShaderOverride);
|
||||
}
|
||||
// Sunrise-End
|
||||
sprite.Comp.LayerSetShader(index, data.ShaderOverride);
|
||||
|
||||
_sprite.RemoveLayer(sprite.AsNullable(), displacementKey, false);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,19 @@
|
|||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Client._Sunrise.MarkingEffectsClient;
|
||||
using Content.Client.DisplacementMap;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared._Sunrise;
|
||||
using Content.Shared._Sunrise.MarkingEffects;
|
||||
using Content.Shared.DisplacementMap;
|
||||
using Content.Shared.Humanoid.Markings;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Preferences;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Graphics; //Sunrise
|
||||
using Robust.Shared.Maths; //Sunrise
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Log; //Lua: for debug logging
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
|
|
@ -185,25 +184,14 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
|||
var hairColor = _markingManager.MustMatchSkin(profile.Species, HumanoidVisualLayers.Hair, out var hairAlpha, _prototypeManager)
|
||||
? profile.Appearance.SkinColor.WithAlpha(hairAlpha)
|
||||
: profile.Appearance.HairColor;
|
||||
|
||||
var hairMarkingEffects = profile.Appearance.HairMarkingEffect != null
|
||||
? new List<MarkingEffect> { profile.Appearance.HairMarkingEffect }
|
||||
: new List<MarkingEffect>();
|
||||
|
||||
var hair = new Marking(profile.Appearance.HairStyleId,
|
||||
new[] { hairColor },
|
||||
hairMarkingEffects);
|
||||
|
||||
var facialHairMarkingEffects = profile.Appearance.FacialHairMarkingEffect != null
|
||||
? new List<MarkingEffect> { profile.Appearance.FacialHairMarkingEffect }
|
||||
: new List<MarkingEffect>();
|
||||
new[] { hairColor });
|
||||
|
||||
var facialHairColor = _markingManager.MustMatchSkin(profile.Species, HumanoidVisualLayers.FacialHair, out var facialHairAlpha, _prototypeManager)
|
||||
? profile.Appearance.SkinColor.WithAlpha(facialHairAlpha)
|
||||
: profile.Appearance.FacialHairColor;
|
||||
var facialHair = new Marking(profile.Appearance.FacialHairStyleId,
|
||||
new[] { facialHairColor },
|
||||
facialHairMarkingEffects);
|
||||
new[] { facialHairColor });
|
||||
|
||||
if (_markingManager.CanBeApplied(profile.Species, profile.Sex, hair, _prototypeManager))
|
||||
{
|
||||
|
|
@ -249,6 +237,20 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
|||
humanoid.Width = profile.Appearance.Width; // Sunrise
|
||||
humanoid.Height = profile.Appearance.Height; // Sunrise
|
||||
|
||||
//Sunrise start Copy hair/facial hair gradient settings for preview
|
||||
humanoid.HairGradientEnabled = profile.Appearance.HairGradientEnabled;
|
||||
humanoid.HairGradientSecondaryColor = profile.Appearance.HairGradientSecondaryColor;
|
||||
humanoid.HairGradientDirection = profile.Appearance.HairGradientDirection;
|
||||
humanoid.FacialHairGradientEnabled = profile.Appearance.FacialHairGradientEnabled;
|
||||
humanoid.FacialHairGradientSecondaryColor = profile.Appearance.FacialHairGradientSecondaryColor;
|
||||
humanoid.FacialHairGradientDirection = profile.Appearance.FacialHairGradientDirection;
|
||||
humanoid.AllMarkingsGradientEnabled = profile.Appearance.AllMarkingsGradientEnabled;
|
||||
humanoid.AllMarkingsGradientSecondaryColor = profile.Appearance.AllMarkingsGradientSecondaryColor;
|
||||
humanoid.AllMarkingsGradientDirection = profile.Appearance.AllMarkingsGradientDirection;
|
||||
// Set cached hair colors for gradient shader
|
||||
humanoid.CachedHairColor = hairColor;
|
||||
humanoid.CachedFacialHairColor = facialHairColor; //Sunrise end
|
||||
|
||||
UpdateSprite((uid, humanoid, Comp<SpriteComponent>(uid)));
|
||||
}
|
||||
|
||||
|
|
@ -273,7 +275,7 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
|||
{
|
||||
if (_markingManager.TryGetMarking(marking, out var markingPrototype))
|
||||
{
|
||||
ApplyMarking(markingPrototype, marking.MarkingColors, marking.Visible, entity, marking.MarkingEffects); // Sunrise-Edit
|
||||
ApplyMarking(markingPrototype, marking.MarkingColors, marking.Visible, entity);
|
||||
//if (markingPrototype.BodyPart == HumanoidVisualLayers.UndergarmentTop)
|
||||
// applyUndergarmentTop = false;
|
||||
//else if (markingPrototype.BodyPart == HumanoidVisualLayers.UndergarmentBottom)
|
||||
|
|
@ -365,8 +367,7 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
|||
public void ApplyMarking(MarkingPrototype markingPrototype, // Sunrise-Edit
|
||||
IReadOnlyList<Color>? colors,
|
||||
bool visible,
|
||||
Entity<HumanoidAppearanceComponent, SpriteComponent> entity,
|
||||
IReadOnlyList<MarkingEffect>? markingEffects = null)
|
||||
Entity<HumanoidAppearanceComponent, SpriteComponent> entity)
|
||||
{
|
||||
var humanoid = entity.Comp1;
|
||||
var sprite = entity.Comp2;
|
||||
|
|
@ -405,37 +406,49 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
|||
continue;
|
||||
}
|
||||
|
||||
// Sunrise-Edit-Start
|
||||
// // Okay so if the marking prototype is modified but we load old marking data this may no longer be valid
|
||||
// // and we need to check the index is correct.
|
||||
// // So if that happens just default to white?
|
||||
// if (colors != null && j < colors.Count)
|
||||
// {
|
||||
// _sprite.LayerSetColor((entity.Owner, sprite), layerId, colors[j]);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// _sprite.LayerSetColor((entity.Owner, sprite), layerId, Color.White);
|
||||
// }
|
||||
//Sunrise start Hair/FacialHair gradient support
|
||||
var isHair = markingPrototype.BodyPart == HumanoidVisualLayers.Hair;
|
||||
var isFacialHair = markingPrototype.BodyPart == HumanoidVisualLayers.FacialHair;
|
||||
|
||||
ShaderInstance? shaderOverride = null;
|
||||
|
||||
|
||||
if (markingEffects != null && j < markingEffects.Count && markingEffects[j].Type != MarkingEffectType.Color)
|
||||
if (isHair && humanoid.HairGradientEnabled)
|
||||
{
|
||||
float texWidth = sprite.AllLayers.Max(x => x.PixelSize.X);
|
||||
float texHeight = sprite.AllLayers.Max(x => x.PixelSize.Y);
|
||||
var shaderName = markingEffects[j].Type.ToString();
|
||||
var instance = _prototypeManager.Index<ShaderPrototype>(shaderName).InstanceUnique();
|
||||
shaderOverride = instance;
|
||||
|
||||
instance.ApplyShaderParams(markingEffects[j], new Vector2(texWidth, texHeight));
|
||||
|
||||
sprite.LayerSetShader(layerId, instance);
|
||||
Log.Debug($"Applying hair gradient: enabled={humanoid.HairGradientEnabled}, secondaryColor={humanoid.HairGradientSecondaryColor}, direction={humanoid.HairGradientDirection}"); //Lua: debug
|
||||
var inst = _prototypeManager.Index<ShaderPrototype>("HairGradient").InstanceUnique();
|
||||
var baseCol = (colors != null && j < colors.Count)
|
||||
? colors[j]
|
||||
: (humanoid.CachedHairColor ?? Color.White);
|
||||
inst.SetParameter("color1", new Vector3(baseCol.R, baseCol.G, baseCol.B));
|
||||
inst.SetParameter("color2", new Vector3(humanoid.HairGradientSecondaryColor.R, humanoid.HairGradientSecondaryColor.G, humanoid.HairGradientSecondaryColor.B));
|
||||
inst.SetParameter("direction", (float) humanoid.HairGradientDirection);
|
||||
sprite.LayerSetShader(layerId, inst, "HairGradient");
|
||||
_sprite.LayerSetColor((entity.Owner, sprite), layerId, Color.White);
|
||||
}
|
||||
else if (isFacialHair && humanoid.FacialHairGradientEnabled)
|
||||
{
|
||||
var inst2 = _prototypeManager.Index<ShaderPrototype>("HairGradient").InstanceUnique();
|
||||
var baseCol2 = (colors != null && j < colors.Count)
|
||||
? colors[j]
|
||||
: (humanoid.CachedFacialHairColor ?? Color.White);
|
||||
inst2.SetParameter("color1", new Vector3(baseCol2.R, baseCol2.G, baseCol2.B));
|
||||
inst2.SetParameter("color2", new Vector3(humanoid.FacialHairGradientSecondaryColor.R, humanoid.FacialHairGradientSecondaryColor.G, humanoid.FacialHairGradientSecondaryColor.B));
|
||||
inst2.SetParameter("direction", (float) humanoid.FacialHairGradientDirection);
|
||||
sprite.LayerSetShader(layerId, inst2, "HairGradient");
|
||||
_sprite.LayerSetColor((entity.Owner, sprite), layerId, Color.White);
|
||||
}
|
||||
else if (humanoid.AllMarkingsGradientEnabled && markingPrototype.BodyPart != HumanoidVisualLayers.Head && markingPrototype.BodyPart != HumanoidVisualLayers.HeadTop && markingPrototype.BodyPart != HumanoidVisualLayers.HeadSide)
|
||||
{
|
||||
// Apply gradient to any marking if enabled globally (excluding skin/base-like head parts)
|
||||
var instG = _prototypeManager.Index<ShaderPrototype>("HairGradient").InstanceUnique();
|
||||
var baseColor = (colors != null && j < colors.Count) ? colors[j] : Color.White;
|
||||
instG.SetParameter("color1", new Vector3(baseColor.R, baseColor.G, baseColor.B));
|
||||
instG.SetParameter("color2", new Vector3(humanoid.AllMarkingsGradientSecondaryColor.R, humanoid.AllMarkingsGradientSecondaryColor.G, humanoid.AllMarkingsGradientSecondaryColor.B));
|
||||
instG.SetParameter("direction", (float) humanoid.AllMarkingsGradientDirection);
|
||||
sprite.LayerSetShader(layerId, instG, "HairGradient");
|
||||
_sprite.LayerSetColor((entity.Owner, sprite), layerId, Color.White);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Sunrise end Default color application
|
||||
if (colors != null && j < colors.Count)
|
||||
{
|
||||
_sprite.LayerSetColor((entity.Owner, sprite), layerId, colors[j]);
|
||||
|
|
@ -443,17 +456,13 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
|||
else
|
||||
{
|
||||
_sprite.LayerSetColor((entity.Owner, sprite), layerId, Color.White);
|
||||
}
|
||||
} //Sunrise
|
||||
}
|
||||
//Sunrise-Edit-End
|
||||
|
||||
var displacementData = GetMarkingDisplacement(entity.Owner, markingPrototype.BodyPart, humanoid);
|
||||
if (displacementData != null && markingPrototype.CanBeDisplaced)
|
||||
{
|
||||
// TODO: в шейдер нужно ещё вставлять displacementSize, сейчас в нём хардкод 127
|
||||
|
||||
// TODO: костыль пиздец, когда появится возможность устанавливать 2 шейдера на один леер - удалить эту хуйню (shaderOverride)
|
||||
_displacement.TryAddDisplacement(displacementData, (entity.Owner, sprite), targetLayer + j + 1, layerId, out _, shaderOverride); // Sunrise-Edit
|
||||
_displacement.TryAddDisplacement(displacementData, (entity.Owner, sprite), targetLayer + j + 1, layerId, out _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -547,7 +556,7 @@ public sealed class HumanoidAppearanceSystem : SharedHumanoidAppearanceSystem
|
|||
foreach (var marking in markingList)
|
||||
{
|
||||
if (_markingManager.TryGetMarking(marking, out var markingPrototype) && markingPrototype.BodyPart == layer)
|
||||
ApplyMarking(markingPrototype, marking.MarkingColors, marking.Visible, (ent, ent.Comp, sprite), marking.MarkingEffects); // Sunrise-Edit
|
||||
ApplyMarking(markingPrototype, marking.MarkingColors, marking.Visible, (ent, ent.Comp, sprite));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,11 +17,9 @@
|
|||
<ItemList Name="MarkingList" VerticalExpand="True" />
|
||||
</ScrollContainer>
|
||||
|
||||
<!-- Sunrise-Edit -->
|
||||
<!-- Color sliders -->
|
||||
<BoxContainer Name="ColorSelectorContainer" HorizontalExpand="True" />
|
||||
<!-- <ScrollContainer MinHeight="200" HorizontalExpand="True"> -->
|
||||
<!-- <BoxContainer Name="ColorSelectorContainer" HorizontalExpand="True" /> -->
|
||||
<!-- </ScrollContainer> -->
|
||||
<ScrollContainer MinHeight="200" HorizontalExpand="True">
|
||||
<BoxContainer Name="ColorSelectorContainer" HorizontalExpand="True" />
|
||||
</ScrollContainer>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using System.Linq;
|
||||
using Content.Client._Sunrise.UserInterface.Controls;
|
||||
using Content.Shared._Sunrise.MarkingEffects;
|
||||
using Content.Shared.Humanoid.Markings;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
|
|
@ -235,40 +235,24 @@ public sealed partial class SingleMarkingPicker : BoxContainer
|
|||
ColorSelectorContainer.DisposeAllChildren();
|
||||
ColorSelectorContainer.RemoveAllChildren();
|
||||
|
||||
if (marking.MarkingColors.Count != proto.Sprites.Count ||
|
||||
marking.MarkingEffects.Count != proto.Sprites.Count)
|
||||
if (marking.MarkingColors.Count != proto.Sprites.Count)
|
||||
{
|
||||
marking = new Marking(marking.MarkingId, proto.Sprites.Count);
|
||||
}
|
||||
|
||||
for (var i = 0; i < marking.MarkingColors.Count; i++)
|
||||
{
|
||||
MarkingEffect selectorColor;
|
||||
var selectorType = MarkingEffectType.Color;
|
||||
if(marking.MarkingEffects == null)
|
||||
selectorColor = new ColorMarkingEffect(marking.MarkingColors[i]);
|
||||
else
|
||||
{
|
||||
selectorColor = marking.MarkingEffects[i];
|
||||
selectorType = marking.MarkingEffects[i].Type;
|
||||
}
|
||||
|
||||
var selector = new MarkingEffectSelectorSliders(selectorColor)
|
||||
var selector = new CustomColorSelectorSliders()
|
||||
{
|
||||
HorizontalExpand = true
|
||||
};
|
||||
// selector.Color = marking.MarkingColors[i];
|
||||
selector.CurrentType = selectorType;
|
||||
selector.Color = marking.MarkingColors[i];
|
||||
|
||||
var colorIndex = i;
|
||||
selector.OnColorChanged += color =>
|
||||
{
|
||||
var newCol = color.Colors["base"];
|
||||
if (marking.MarkingColors[colorIndex] != newCol)
|
||||
marking.SetColor(colorIndex, newCol);
|
||||
|
||||
if(marking.MarkingEffects?[colorIndex].Equals(color) != true)
|
||||
marking.SetMarkingEffect(colorIndex, color.Clone());
|
||||
if (marking.MarkingColors[colorIndex] != color)
|
||||
marking.SetColor(colorIndex, color);
|
||||
|
||||
OnColorChanged!((_slot, marking));
|
||||
};
|
||||
|
|
@ -298,11 +282,6 @@ public sealed partial class SingleMarkingPicker : BoxContainer
|
|||
_markings[Slot].SetColor(i, oldMarking.MarkingColors[i]);
|
||||
}
|
||||
|
||||
for (var i = 0; i < _markings[Slot].MarkingEffects.Count && i < oldMarking.MarkingEffects.Count; i++)
|
||||
{
|
||||
_markings[Slot].SetMarkingEffect(i, oldMarking.MarkingEffects[i]); // Sunrise-Edit
|
||||
}
|
||||
|
||||
PopulateColors();
|
||||
|
||||
OnMarkingSelect!((_slot, id));
|
||||
|
|
|
|||
|
|
@ -127,9 +127,43 @@
|
|||
<BoxContainer Name="RgbSkinColorContainer" Visible="False" Orientation="Vertical" HorizontalExpand="True"></BoxContainer>
|
||||
</BoxContainer>
|
||||
<!-- Hair -->
|
||||
<BoxContainer Margin="10" Orientation="Horizontal">
|
||||
<humanoid:SingleMarkingPicker Name="HairStylePicker" Category="Hair" />
|
||||
<humanoid:SingleMarkingPicker Name="FacialHairPicker" Category="FacialHair" />
|
||||
<BoxContainer Margin="10" Orientation="Vertical"> <!-- Sunrise Horizontal<Vertical -->
|
||||
<BoxContainer Orientation="Horizontal">
|
||||
<humanoid:SingleMarkingPicker Name="HairStylePicker" Category="Hair" />
|
||||
<humanoid:SingleMarkingPicker Name="FacialHairPicker" Category="FacialHair" />
|
||||
</BoxContainer> <!-- Sunrise start -->
|
||||
<!-- Hair gradient controls -->
|
||||
<BoxContainer Margin="10 5 0 0" Orientation="Vertical">
|
||||
<Label Text="{Loc 'humanoid-profile-editor-hair-gradient-label'}" />
|
||||
<BoxContainer Orientation="Horizontal" SeparationOverride="5" HorizontalExpand="True">
|
||||
<CheckBox Name="HairGradientToggle" Text="{Loc 'humanoid-profile-editor-hair-gradient-enable'}" VerticalAlignment="Center" />
|
||||
<ColorSelectorSliders Name="HairGradientSecondColorSelector" MinSize="280 0" HorizontalExpand="True" />
|
||||
<Label Text="{Loc 'humanoid-profile-editor-hair-gradient-direction'}" VerticalAlignment="Center" />
|
||||
<OptionButton Name="HairGradientDirectionSelector" MinSize="160 24" VerticalAlignment="Center" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<!-- Facial hair gradient controls -->
|
||||
<BoxContainer Margin="10 5 0 0" Orientation="Vertical">
|
||||
<Label Text="{Loc 'humanoid-profile-editor-facialhair-gradient-label'}" />
|
||||
<BoxContainer Orientation="Horizontal" SeparationOverride="5" HorizontalExpand="True">
|
||||
<CheckBox Name="FacialHairGradientToggle" Text="{Loc 'humanoid-profile-editor-hair-gradient-enable'}" VerticalAlignment="Center" />
|
||||
<ColorSelectorSliders Name="FacialHairGradientSecondColorSelector" MinSize="280 0" HorizontalExpand="True" />
|
||||
<Label Text="{Loc 'humanoid-profile-editor-hair-gradient-direction'}" VerticalAlignment="Center" />
|
||||
<OptionButton Name="FacialHairGradientDirectionSelector" MinSize="160 24" VerticalAlignment="Center" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<!-- Global markings gradient controls (except skin) -->
|
||||
<BoxContainer Margin="10 5 0 0" Orientation="Vertical">
|
||||
<Label Text="{Loc 'humanoid-profile-editor-allmarkings-gradient-label'}" />
|
||||
<BoxContainer Orientation="Horizontal" SeparationOverride="5" HorizontalExpand="True">
|
||||
<CheckBox Name="AllMarkingsGradientToggle" Text="{Loc 'humanoid-profile-editor-hair-gradient-enable'}" VerticalAlignment="Center" />
|
||||
<ColorSelectorSliders Name="AllMarkingsGradientSecondColorSelector" MinSize="280 0" HorizontalExpand="True" />
|
||||
<Label Text="{Loc 'humanoid-profile-editor-hair-gradient-direction'}" VerticalAlignment="Center" />
|
||||
<OptionButton Name="AllMarkingsGradientDirectionSelector" MinSize="160 24" VerticalAlignment="Center" />
|
||||
</BoxContainer>
|
||||
</BoxContainer> <!-- Sunrise end -->
|
||||
</BoxContainer>
|
||||
<!-- Eyes -->
|
||||
<BoxContainer Margin="10" Orientation="Vertical">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Log;
|
||||
using Content.Client.Humanoid;
|
||||
using Content.Client.Lobby.UI.Loadouts;
|
||||
using Content.Client.Lobby.UI.Roles;
|
||||
|
|
@ -10,7 +11,6 @@ using Content.Client.Sprite;
|
|||
using Content.Client.Stylesheets;
|
||||
using Content.Client.UserInterface.Systems.Guidebook;
|
||||
using Content.Shared._Sunrise;
|
||||
using Content.Shared._Sunrise.MarkingEffects;
|
||||
using Content.Shared._Sunrise.SunriseCCVars;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Clothing;
|
||||
|
|
@ -253,6 +253,10 @@ namespace Content.Client.Lobby.UI
|
|||
|
||||
#endregion
|
||||
|
||||
// Sunrise: Инициализируем градиентные контролы ПЕРЕД RefreshSpecies
|
||||
InitializeHairGradientControls(); //Sunrise
|
||||
InitializeAllMarkingsGradientControls(); //Sunrise
|
||||
|
||||
RefreshSpecies();
|
||||
|
||||
SpeciesButton.OnItemSelected += args =>
|
||||
|
|
@ -329,29 +333,6 @@ namespace Content.Client.Lobby.UI
|
|||
|
||||
#region Hair
|
||||
|
||||
// sunrise gradient edit start
|
||||
|
||||
HairStylePicker.OnExtendedColorChanged += newColor =>
|
||||
{
|
||||
if (Profile is null)
|
||||
return;
|
||||
Profile = Profile.WithCharacterAppearance(
|
||||
Profile.Appearance.WithHairExtendedColor(newColor.marking.MarkingEffects[0]));
|
||||
UpdateCMarkingsHair();
|
||||
ReloadPreview();
|
||||
};
|
||||
|
||||
FacialHairPicker.OnExtendedColorChanged += newColor =>
|
||||
{
|
||||
if (Profile is null)
|
||||
return;
|
||||
Profile = Profile.WithCharacterAppearance(
|
||||
Profile.Appearance.WithFacialHairExtendedColor(newColor.marking.MarkingEffects[0]));
|
||||
UpdateCMarkingsFacialHair();
|
||||
ReloadPreview();
|
||||
};
|
||||
|
||||
// sunrise gradient edit end
|
||||
|
||||
HairStylePicker.OnMarkingSelect += newStyle =>
|
||||
{
|
||||
|
|
@ -366,9 +347,8 @@ namespace Content.Client.Lobby.UI
|
|||
{
|
||||
if (Profile is null)
|
||||
return;
|
||||
var newExtended = newColor.marking.MarkingEffects[0].Clone();
|
||||
Profile = Profile.WithCharacterAppearance(
|
||||
Profile.Appearance.WithHairColor(newColor.marking.MarkingColors[0], newExtended)); // sunrise gradient edit
|
||||
Profile.Appearance.WithHairColor(newColor.marking.MarkingColors[0]));
|
||||
UpdateCMarkingsHair();
|
||||
ReloadPreview();
|
||||
};
|
||||
|
|
@ -386,9 +366,8 @@ namespace Content.Client.Lobby.UI
|
|||
{
|
||||
if (Profile is null)
|
||||
return;
|
||||
var newExtended = newColor.marking.MarkingEffects[0].Clone();
|
||||
Profile = Profile.WithCharacterAppearance(
|
||||
Profile.Appearance.WithFacialHairColor(newColor.marking.MarkingColors[0], newExtended)); // sunrise gradient edit
|
||||
Profile.Appearance.WithFacialHairColor(newColor.marking.MarkingColors[0]));
|
||||
UpdateCMarkingsFacialHair();
|
||||
ReloadPreview();
|
||||
};
|
||||
|
|
@ -716,7 +695,7 @@ namespace Content.Client.Lobby.UI
|
|||
SpeciesButton.Clear();
|
||||
_species.Clear();
|
||||
|
||||
_species.AddRange(_prototypeManager.EnumeratePrototypes<SpeciesPrototype>().Where(o => o.RoundStart));
|
||||
_species.AddRange(_prototypeManager.EnumeratePrototypes<SpeciesPrototype>().Where(o => o.RoundStart).OrderBy(s => Loc.GetString(s.Name))); //Lua: Сортировка рас по алфавиту
|
||||
var speciesIds = _species.Select(o => o.ID).ToList();
|
||||
|
||||
for (var i = 0; i < _species.Count; i++)
|
||||
|
|
@ -892,6 +871,7 @@ namespace Content.Client.Lobby.UI
|
|||
UpdateHairPickers();
|
||||
UpdateCMarkingsHair();
|
||||
UpdateCMarkingsFacialHair();
|
||||
UpdateGradientControls(); //Sunrise: Ensure gradient controls are updated
|
||||
|
||||
RefreshAntags();
|
||||
RefreshJobs();
|
||||
|
|
@ -1741,19 +1721,13 @@ namespace Content.Client.Lobby.UI
|
|||
{
|
||||
return;
|
||||
}
|
||||
var hairMarking = Profile.Appearance.HairStyleId == HairStyles.DefaultHairStyle
|
||||
? new List<Marking>()
|
||||
: new() { new(Profile.Appearance.HairStyleId, new List<Color>() { Profile.Appearance.HairColor }) };
|
||||
|
||||
var hairMarking = CreateHairMarkings(
|
||||
Profile.Appearance.HairStyleId,
|
||||
HairStyles.DefaultHairStyle,
|
||||
Profile.Appearance.HairColor,
|
||||
Profile.Appearance.HairMarkingEffect);
|
||||
|
||||
var facialHairMarking = CreateHairMarkings(
|
||||
Profile.Appearance.FacialHairStyleId,
|
||||
HairStyles.DefaultFacialHairStyle,
|
||||
Profile.Appearance.FacialHairColor,
|
||||
Profile.Appearance.FacialHairMarkingEffect);
|
||||
|
||||
var facialHairMarking = Profile.Appearance.FacialHairStyleId == HairStyles.DefaultFacialHairStyle
|
||||
? new List<Marking>()
|
||||
: new() { new(Profile.Appearance.FacialHairStyleId, new List<Color>() { Profile.Appearance.FacialHairColor }) };
|
||||
|
||||
HairStylePicker.UpdateData(
|
||||
hairMarking,
|
||||
|
|
@ -1763,29 +1737,9 @@ namespace Content.Client.Lobby.UI
|
|||
facialHairMarking,
|
||||
Profile.Species,
|
||||
1);
|
||||
}
|
||||
|
||||
private static List<Marking> CreateHairMarkings(
|
||||
string styleId,
|
||||
string defaultStyleId,
|
||||
Color color,
|
||||
MarkingEffect? effect)
|
||||
{
|
||||
if (styleId == defaultStyleId)
|
||||
return new List<Marking>();
|
||||
|
||||
var effects = effect is { } ext
|
||||
? new List<MarkingEffect> { ext.Clone() }
|
||||
: null;
|
||||
|
||||
return new List<Marking>()
|
||||
{
|
||||
new(
|
||||
styleId,
|
||||
new[] { color },
|
||||
effects
|
||||
)
|
||||
};
|
||||
// Sunrise start: Apply gradient toggles to UI controls if they exist
|
||||
UpdateGradientControls(); //Sunrise end
|
||||
}
|
||||
|
||||
private void UpdateCMarkingsHair()
|
||||
|
|
@ -1817,10 +1771,7 @@ namespace Content.Client.Lobby.UI
|
|||
{
|
||||
Markings.HairMarking = new (
|
||||
Profile.Appearance.HairStyleId,
|
||||
new List<Color>() { hairColor.Value },
|
||||
Profile.Appearance.HairMarkingEffect is { } hairExt
|
||||
? new List<MarkingEffect> { hairExt.Clone() }
|
||||
: null);
|
||||
new List<Color>() { hairColor.Value });
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1856,10 +1807,7 @@ namespace Content.Client.Lobby.UI
|
|||
{
|
||||
Markings.FacialHairMarking = new(
|
||||
Profile.Appearance.FacialHairStyleId,
|
||||
new List<Color>() { facialHairColor.Value },
|
||||
Profile.Appearance.FacialHairMarkingEffect is { } facialExt
|
||||
? new List<MarkingEffect> { facialExt.Clone() }
|
||||
: null);
|
||||
new List<Color>() { facialHairColor.Value });
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2035,5 +1983,190 @@ namespace Content.Client.Lobby.UI
|
|||
|
||||
CBodyTypesButton.Select(_bodyTypes.FindIndex(x => x.ID == Profile.BodyType));
|
||||
}
|
||||
|
||||
//Sunrise start - Hair gradient initialization methods
|
||||
private void InitializeHairGradientControls()
|
||||
{
|
||||
// Initialize hair gradient direction selector
|
||||
HairGradientDirectionSelector.AddItem(Loc.GetString("humanoid-profile-editor-hair-gradient-dir-bottom-top"), 0);
|
||||
HairGradientDirectionSelector.AddItem(Loc.GetString("humanoid-profile-editor-hair-gradient-dir-top-bottom"), 1);
|
||||
HairGradientDirectionSelector.AddItem(Loc.GetString("humanoid-profile-editor-hair-gradient-dir-left-right"), 2);
|
||||
HairGradientDirectionSelector.AddItem(Loc.GetString("humanoid-profile-editor-hair-gradient-dir-right-left"), 3);
|
||||
|
||||
// Initialize facial hair gradient direction selector
|
||||
FacialHairGradientDirectionSelector.AddItem(Loc.GetString("humanoid-profile-editor-hair-gradient-dir-bottom-top"), 0);
|
||||
FacialHairGradientDirectionSelector.AddItem(Loc.GetString("humanoid-profile-editor-hair-gradient-dir-top-bottom"), 1);
|
||||
FacialHairGradientDirectionSelector.AddItem(Loc.GetString("humanoid-profile-editor-hair-gradient-dir-left-right"), 2);
|
||||
FacialHairGradientDirectionSelector.AddItem(Loc.GetString("humanoid-profile-editor-hair-gradient-dir-right-left"), 3);
|
||||
|
||||
// Hair gradient toggle
|
||||
HairGradientToggle.OnToggled += args =>
|
||||
{
|
||||
if (Profile is null)
|
||||
return;
|
||||
Profile = Profile.WithCharacterAppearance(
|
||||
Profile.Appearance.WithHairGradientEnabled(args.Pressed));
|
||||
SetDirty();
|
||||
ReloadPreview();
|
||||
};
|
||||
|
||||
// Hair gradient secondary color
|
||||
HairGradientSecondColorSelector.OnColorChanged += newColor =>
|
||||
{
|
||||
if (Profile is null)
|
||||
return;
|
||||
Profile = Profile.WithCharacterAppearance(
|
||||
Profile.Appearance.WithHairGradientSecondaryColor(newColor));
|
||||
SetDirty();
|
||||
ReloadPreview();
|
||||
};
|
||||
|
||||
// Hair gradient direction
|
||||
HairGradientDirectionSelector.OnItemSelected += args =>
|
||||
{
|
||||
if (Profile is null)
|
||||
return;
|
||||
HairGradientDirectionSelector.SelectId(args.Id);
|
||||
Profile = Profile.WithCharacterAppearance(
|
||||
Profile.Appearance.WithHairGradientDirection(args.Id));
|
||||
SetDirty();
|
||||
ReloadPreview();
|
||||
};
|
||||
|
||||
// Facial hair gradient toggle
|
||||
FacialHairGradientToggle.OnToggled += args =>
|
||||
{
|
||||
if (Profile is null)
|
||||
return;
|
||||
Profile = Profile.WithCharacterAppearance(
|
||||
Profile.Appearance.WithFacialHairGradientEnabled(args.Pressed));
|
||||
SetDirty();
|
||||
ReloadPreview();
|
||||
};
|
||||
|
||||
// Facial hair gradient secondary color
|
||||
FacialHairGradientSecondColorSelector.OnColorChanged += newColor =>
|
||||
{
|
||||
if (Profile is null)
|
||||
return;
|
||||
Profile = Profile.WithCharacterAppearance(
|
||||
Profile.Appearance.WithFacialHairGradientSecondaryColor(newColor));
|
||||
SetDirty();
|
||||
ReloadPreview();
|
||||
};
|
||||
|
||||
// Facial hair gradient direction
|
||||
FacialHairGradientDirectionSelector.OnItemSelected += args =>
|
||||
{
|
||||
if (Profile is null)
|
||||
return;
|
||||
FacialHairGradientDirectionSelector.SelectId(args.Id);
|
||||
Profile = Profile.WithCharacterAppearance(
|
||||
Profile.Appearance.WithFacialHairGradientDirection(args.Id));
|
||||
SetDirty();
|
||||
ReloadPreview();
|
||||
};
|
||||
}
|
||||
|
||||
private void InitializeAllMarkingsGradientControls()
|
||||
{
|
||||
// Initialize all markings gradient direction selector
|
||||
AllMarkingsGradientDirectionSelector.AddItem(Loc.GetString("humanoid-profile-editor-hair-gradient-dir-bottom-top"), 0);
|
||||
AllMarkingsGradientDirectionSelector.AddItem(Loc.GetString("humanoid-profile-editor-hair-gradient-dir-top-bottom"), 1);
|
||||
AllMarkingsGradientDirectionSelector.AddItem(Loc.GetString("humanoid-profile-editor-hair-gradient-dir-left-right"), 2);
|
||||
AllMarkingsGradientDirectionSelector.AddItem(Loc.GetString("humanoid-profile-editor-hair-gradient-dir-right-left"), 3);
|
||||
|
||||
// All markings gradient toggle
|
||||
AllMarkingsGradientToggle.OnToggled += args =>
|
||||
{
|
||||
if (Profile is null)
|
||||
return;
|
||||
Profile = Profile.WithCharacterAppearance(
|
||||
Profile.Appearance.WithAllMarkingsGradientEnabled(args.Pressed));
|
||||
SetDirty();
|
||||
ReloadPreview();
|
||||
};
|
||||
|
||||
// All markings gradient secondary color
|
||||
AllMarkingsGradientSecondColorSelector.OnColorChanged += newColor =>
|
||||
{
|
||||
if (Profile is null)
|
||||
return;
|
||||
Profile = Profile.WithCharacterAppearance(
|
||||
Profile.Appearance.WithAllMarkingsGradientSecondaryColor(newColor));
|
||||
SetDirty();
|
||||
ReloadPreview();
|
||||
};
|
||||
|
||||
// All markings gradient direction
|
||||
AllMarkingsGradientDirectionSelector.OnItemSelected += args =>
|
||||
{
|
||||
if (Profile is null)
|
||||
return;
|
||||
AllMarkingsGradientDirectionSelector.SelectId(args.Id);
|
||||
Profile = Profile.WithCharacterAppearance(
|
||||
Profile.Appearance.WithAllMarkingsGradientDirection(args.Id));
|
||||
SetDirty();
|
||||
ReloadPreview();
|
||||
};
|
||||
}
|
||||
|
||||
private void UpdateGradientControls()
|
||||
{
|
||||
if (Profile == null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
// Hair gradient controls
|
||||
if (HairGradientToggle != null)
|
||||
{
|
||||
HairGradientToggle.Pressed = Profile.Appearance.HairGradientEnabled;
|
||||
}
|
||||
if (HairGradientSecondColorSelector != null)
|
||||
{
|
||||
HairGradientSecondColorSelector.Color = Profile.Appearance.HairGradientSecondaryColor;
|
||||
}
|
||||
if (HairGradientDirectionSelector != null)
|
||||
{
|
||||
HairGradientDirectionSelector.SelectId(Profile.Appearance.HairGradientDirection);
|
||||
}
|
||||
|
||||
// Facial hair gradient controls
|
||||
if (FacialHairGradientToggle != null)
|
||||
{
|
||||
FacialHairGradientToggle.Pressed = Profile.Appearance.FacialHairGradientEnabled;
|
||||
}
|
||||
if (FacialHairGradientSecondColorSelector != null)
|
||||
{
|
||||
FacialHairGradientSecondColorSelector.Color = Profile.Appearance.FacialHairGradientSecondaryColor;
|
||||
}
|
||||
if (FacialHairGradientDirectionSelector != null)
|
||||
{
|
||||
FacialHairGradientDirectionSelector.SelectId(Profile.Appearance.FacialHairGradientDirection);
|
||||
}
|
||||
|
||||
// All markings gradient controls
|
||||
if (AllMarkingsGradientToggle != null)
|
||||
{
|
||||
AllMarkingsGradientToggle.Pressed = Profile.Appearance.AllMarkingsGradientEnabled;
|
||||
}
|
||||
if (AllMarkingsGradientSecondColorSelector != null)
|
||||
{
|
||||
AllMarkingsGradientSecondColorSelector.Color = Profile.Appearance.AllMarkingsGradientSecondaryColor;
|
||||
}
|
||||
if (AllMarkingsGradientDirectionSelector != null)
|
||||
{
|
||||
AllMarkingsGradientDirectionSelector.SelectId(Profile.Appearance.AllMarkingsGradientDirection);
|
||||
}
|
||||
|
||||
Logger.Debug($"Sunrise: Градиентные контролы обновлены - Hair: {Profile.Appearance.HairGradientEnabled}, FacialHair: {Profile.Appearance.FacialHairGradientEnabled}, AllMarkings: {Profile.Appearance.AllMarkingsGradientEnabled}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error($"Sunrise: Ошибка при обновлении градиентных контролов: {ex}");
|
||||
}
|
||||
}
|
||||
//Sunrise end
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
using Content.Client._Sunrise.UserInterface.Controls;
|
||||
using Content.Shared._Sunrise.MarkingEffects;
|
||||
using Robust.Client.UserInterface;
|
||||
|
||||
namespace Content.Client._Sunrise.MarkingEffectsClient;
|
||||
|
||||
public sealed class ColorMarkingEffectUiBuilder : IMarkingEffectUiBuilder
|
||||
{
|
||||
public void BuildUI(MarkingEffect effect, MarkingEffectSelectorSliders parent)
|
||||
{
|
||||
if (effect is not ColorMarkingEffect)
|
||||
return;
|
||||
|
||||
parent.CreateSelector(type: MarkingEffectType.Color);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
using Content.Client._Sunrise.UserInterface.Controls;
|
||||
using Content.Shared._Sunrise.MarkingEffects;
|
||||
|
||||
namespace Content.Client._Sunrise.MarkingEffectsClient;
|
||||
|
||||
public sealed class GradientMarkingEffectUiBuilder : IMarkingEffectUiBuilder
|
||||
{
|
||||
private const float ToIntScaling = 100;
|
||||
|
||||
private const int OffsetMin = -200;
|
||||
private const int OffsetMax = 100;
|
||||
|
||||
private const int SizeMin = 30;
|
||||
private const int SizeMax = 100;
|
||||
|
||||
private const int RotationMin = 0;
|
||||
private const int RotationMax = 360;
|
||||
|
||||
public void BuildUI(MarkingEffect effect, MarkingEffectSelectorSliders parent)
|
||||
{
|
||||
if (effect is not GradientMarkingEffect gradient)
|
||||
return;
|
||||
|
||||
parent.CreateSelector(type: MarkingEffectType.Gradient);
|
||||
parent.CreateSelector("gradient", MarkingEffectType.Gradient);
|
||||
|
||||
parent.CreateSlider(Loc.GetString("marking-effect-gradient-parameter-offset"),
|
||||
(int)(gradient.Offset.Y * ToIntScaling), OffsetMin, OffsetMax,
|
||||
v => gradient.Offset.Y = v / ToIntScaling
|
||||
);
|
||||
parent.CreateSlider(Loc.GetString("marking-effect-gradient-parameter-size"),
|
||||
(int)(gradient.Size.Y * ToIntScaling), SizeMin, SizeMax,
|
||||
v => gradient.Size.Y = v / ToIntScaling);
|
||||
parent.CreateSlider(Loc.GetString("marking-effect-gradient-parameter-rotation"),
|
||||
(int)gradient.Rotation, RotationMin, RotationMax,
|
||||
v => gradient.Rotation = v);
|
||||
|
||||
parent.CreateToggle(Loc.GetString("marking-effect-gradient-parameter-pixelation"),
|
||||
gradient.Pixelated,
|
||||
v => gradient.Pixelated = v);
|
||||
parent.CreateToggle(Loc.GetString("marking-effect-gradient-parameter-mirror"),
|
||||
gradient.Mirrored,
|
||||
v => gradient.Mirrored = v);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
using Content.Client._Sunrise.UserInterface.Controls;
|
||||
using Content.Shared._Sunrise.MarkingEffects;
|
||||
using Robust.Client.UserInterface;
|
||||
|
||||
namespace Content.Client._Sunrise.MarkingEffectsClient;
|
||||
|
||||
public interface IMarkingEffectUiBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Builds UI elements to customize <see cref="MarkingEffect"/>
|
||||
/// </summary>
|
||||
void BuildUI(MarkingEffect effect, MarkingEffectSelectorSliders parent);
|
||||
}
|
||||
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
using System.Numerics;
|
||||
using Content.Shared._Sunrise.MarkingEffects;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
|
||||
namespace Content.Client._Sunrise.MarkingEffectsClient;
|
||||
|
||||
public static class MarkingEffectShaders
|
||||
{
|
||||
|
||||
public static Vector3 ColorToVec(Color col)
|
||||
{
|
||||
return new Vector3(col.R, col.G, col.B);
|
||||
}
|
||||
|
||||
public static void ApplyShaderParams(this ShaderInstance instance, MarkingEffect color, Vector2 texScale)
|
||||
{
|
||||
instance.SetParameter("useDisplacement", false);
|
||||
|
||||
switch (color.Type)
|
||||
{
|
||||
case MarkingEffectType.Gradient:
|
||||
if (color is not GradientMarkingEffect gradient)
|
||||
return;
|
||||
|
||||
// Safely get colors with fallback for old imported characters
|
||||
var baseColor = gradient.Colors.TryGetValue("base", out var bColor) ? bColor : Color.White;
|
||||
var gradientColor = gradient.Colors.TryGetValue("gradient", out var gColor) ? gColor : baseColor;
|
||||
|
||||
instance.SetParameter("color1", ColorToVec(baseColor));
|
||||
instance.SetParameter("color2", ColorToVec(gradientColor));
|
||||
instance.SetParameter("texScale", texScale);
|
||||
instance.SetParameter("offset", gradient.Offset);
|
||||
instance.SetParameter("size", gradient.Size);
|
||||
instance.SetParameter("rotation", gradient.Rotation);
|
||||
instance.SetParameter("pixelated", gradient.Pixelated);
|
||||
instance.SetParameter("mirrored", gradient.Mirrored);
|
||||
break;
|
||||
case MarkingEffectType.RoughGradient:
|
||||
if (color is not RoughGradientMarkingEffect roughGradient)
|
||||
return;
|
||||
|
||||
// Safely get colors with fallback for old imported characters
|
||||
var baseColor2 = roughGradient.Colors.TryGetValue("base", out var bColor2) ? bColor2 : Color.White;
|
||||
var gradientColor2 = roughGradient.Colors.TryGetValue("gradient", out var gColor2) ? gColor2 : baseColor2;
|
||||
|
||||
instance.SetParameter("color1", ColorToVec(baseColor2));
|
||||
instance.SetParameter("color2", ColorToVec(gradientColor2));
|
||||
instance.SetParameter("horizontal", roughGradient.Horizontal);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
using Content.Client._Sunrise.UserInterface.Controls;
|
||||
using Content.Shared._Sunrise.MarkingEffects;
|
||||
using Robust.Client.UserInterface;
|
||||
|
||||
namespace Content.Client._Sunrise.MarkingEffectsClient;
|
||||
|
||||
public sealed class RoughGradientMarkingEffectUiBuilder : IMarkingEffectUiBuilder
|
||||
{
|
||||
public void BuildUI(MarkingEffect effect, MarkingEffectSelectorSliders parent)
|
||||
{
|
||||
if (effect is not RoughGradientMarkingEffect rough)
|
||||
return;
|
||||
|
||||
parent.CreateSelector(type: MarkingEffectType.RoughGradient);
|
||||
parent.CreateSelector("gradient", type: MarkingEffectType.RoughGradient);
|
||||
|
||||
parent.CreateToggle(Loc.GetString("marking-effect-roughgradient-parameter-horizontal"),
|
||||
rough.Horizontal,
|
||||
val => rough.Horizontal = val);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +1,32 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Numerics;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.ColorNaming;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Content.Client._Sunrise.UserInterface.Controls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
// condensed version of the original ColorSlider set
|
||||
public sealed class CustomColorSelectorSliders : Control
|
||||
{
|
||||
[Dependency] private readonly ILocalizationManager _localization = default!;
|
||||
|
||||
public Color Color
|
||||
{
|
||||
get => _currentColor;
|
||||
set
|
||||
{
|
||||
_currentColor = value;
|
||||
_colorData = GetStrategy().ToColorData(value);
|
||||
|
||||
UpdateAllSliders();
|
||||
switch (SelectorType)
|
||||
{
|
||||
case ColorSelectorType.Rgb:
|
||||
_colorData = new Vector4(_currentColor.R, _currentColor.G, _currentColor.B, _currentColor.A);
|
||||
break;
|
||||
case ColorSelectorType.Hsv:
|
||||
_colorData = Color.ToHsv(value);
|
||||
break;
|
||||
}
|
||||
Update();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -32,12 +35,18 @@ public sealed class CustomColorSelectorSliders : Control
|
|||
get => _currentType;
|
||||
set
|
||||
{
|
||||
switch ((_currentType, value))
|
||||
{
|
||||
case (ColorSelectorType.Rgb, ColorSelectorType.Hsv):
|
||||
_colorData = Color.ToHsv(Color);
|
||||
break;
|
||||
case (ColorSelectorType.Hsv, ColorSelectorType.Rgb):
|
||||
_colorData = new Vector4(_currentColor.R, _currentColor.G, _currentColor.B, _currentColor.A);
|
||||
break;
|
||||
}
|
||||
_currentType = value;
|
||||
_typeSelector.Select(_types.IndexOf(value));
|
||||
_colorData = GetStrategy().ToColorData(_currentColor);
|
||||
|
||||
UpdateType();
|
||||
UpdateAllSliders();
|
||||
Update();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -53,12 +62,9 @@ public sealed class CustomColorSelectorSliders : Control
|
|||
}
|
||||
|
||||
public Action<Color>? OnColorChanged;
|
||||
public Action<Color>? OnColorReleased;
|
||||
|
||||
private readonly static HsvSliderStrategy _hsvStrategy = new();
|
||||
private readonly static RgbSliderStrategy _rgbStrategy = new();
|
||||
|
||||
private const float AlphaDivisor = 100.0f;
|
||||
|
||||
private bool _updating = false;
|
||||
private Color _currentColor = Color.White;
|
||||
private Vector4 _colorData;
|
||||
private ColorSelectorType _currentType = ColorSelectorType.Rgb;
|
||||
|
|
@ -80,8 +86,6 @@ public sealed class CustomColorSelectorSliders : Control
|
|||
private Label _middleSliderLabel = new();
|
||||
private Label _bottomSliderLabel = new();
|
||||
private Label _alphaSliderLabel = new();
|
||||
//Sunrise-Edit
|
||||
// private Label _colorDescriptionLabel = new();
|
||||
|
||||
private OptionButton _typeSelector;
|
||||
private List<ColorSelectorType> _types = new();
|
||||
|
|
@ -90,13 +94,11 @@ public sealed class CustomColorSelectorSliders : Control
|
|||
private ColorSelectorStyleBox _middleStyle;
|
||||
private ColorSelectorStyleBox _bottomStyle;
|
||||
|
||||
|
||||
public CustomColorSelectorSliders() : this(ColorSelectorType.Rgb){} // Sunrise-Edit
|
||||
|
||||
|
||||
public CustomColorSelectorSliders(ColorSelectorType type = ColorSelectorType.Rgb, string? label = null) // Sunrise-Edit
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
_topColorSlider = new ColorableSlider
|
||||
{
|
||||
HorizontalExpand = true,
|
||||
|
|
@ -128,10 +130,15 @@ public sealed class CustomColorSelectorSliders : Control
|
|||
MaxValue = 1.0f,
|
||||
};
|
||||
|
||||
_topColorSlider.OnValueChanged += r => { OnSliderValueChanged(ColorSliderOrder.Top); };
|
||||
_middleColorSlider.OnValueChanged += r => { OnSliderValueChanged(ColorSliderOrder.Middle); };
|
||||
_bottomColorSlider.OnValueChanged += r => { OnSliderValueChanged(ColorSliderOrder.Bottom); };
|
||||
_alphaSlider.OnValueChanged += r => { OnSliderValueChanged(ColorSliderOrder.Alpha); };
|
||||
_topColorSlider.OnValueChanged += _ => { OnColorSet(); };
|
||||
_middleColorSlider.OnValueChanged += _ => { OnColorSet(); };
|
||||
_bottomColorSlider.OnValueChanged += _ => { OnColorSet(); };
|
||||
_alphaSlider.OnValueChanged += _ => { OnColorSet(); };
|
||||
|
||||
_topColorSlider.OnReleased += _ => { OnColorSet(true); };
|
||||
_middleColorSlider.OnReleased += _ => { OnColorSet(true); };
|
||||
_bottomColorSlider.OnReleased += _ => { OnColorSet(true); };
|
||||
_alphaSlider.OnReleased += _ => { OnColorSet(true); };
|
||||
|
||||
_topInputBox = new SpinBox
|
||||
{
|
||||
|
|
@ -157,10 +164,25 @@ public sealed class CustomColorSelectorSliders : Control
|
|||
};
|
||||
_alphaInputBox.InitDefaultButtons();
|
||||
|
||||
_topInputBox.ValueChanged += value => { OnInputBoxValueChanged(value, ColorSliderOrder.Top); };
|
||||
_middleInputBox.ValueChanged += value => { OnInputBoxValueChanged(value, ColorSliderOrder.Middle); };
|
||||
_bottomInputBox.ValueChanged += value => { OnInputBoxValueChanged(value, ColorSliderOrder.Bottom); };
|
||||
_alphaInputBox.ValueChanged += value => { OnInputBoxValueChanged(value, ColorSliderOrder.Alpha); };
|
||||
_topInputBox.ValueChanged += value =>
|
||||
{
|
||||
_topColorSlider.Value = value.Value / GetColorValueDivisor(ColorSliderOrder.Top);
|
||||
};
|
||||
|
||||
_middleInputBox.ValueChanged += value =>
|
||||
{
|
||||
_middleColorSlider.Value = value.Value / GetColorValueDivisor(ColorSliderOrder.Middle);
|
||||
};
|
||||
|
||||
_bottomInputBox.ValueChanged += value =>
|
||||
{
|
||||
_bottomColorSlider.Value = value.Value / GetColorValueDivisor(ColorSliderOrder.Bottom);
|
||||
};
|
||||
|
||||
_alphaInputBox.ValueChanged += value =>
|
||||
{
|
||||
_alphaSlider.Value = value.Value / GetColorValueDivisor(ColorSliderOrder.Alpha);
|
||||
};
|
||||
|
||||
_alphaSliderLabel.Text = Loc.GetString("color-selector-sliders-alpha");
|
||||
|
||||
|
|
@ -177,9 +199,6 @@ public sealed class CustomColorSelectorSliders : Control
|
|||
_typeSelector.Select(args.Id);
|
||||
};
|
||||
|
||||
//Sunrise-Edit
|
||||
// _colorDescriptionLabel.Text = ColorNaming.Describe(_currentColor, _localization);
|
||||
|
||||
// TODO: Maybe some engine widgets could be laid out in XAML?
|
||||
|
||||
var rootBox = new BoxContainer
|
||||
|
|
@ -247,113 +266,168 @@ public sealed class CustomColorSelectorSliders : Control
|
|||
Color = _currentColor;
|
||||
}
|
||||
|
||||
private ColorSliderStrategy GetStrategy()
|
||||
{
|
||||
return SelectorType switch
|
||||
{
|
||||
ColorSelectorType.Rgb => _rgbStrategy,
|
||||
ColorSelectorType.Hsv => _hsvStrategy,
|
||||
_ => throw new ArgumentOutOfRangeException(),
|
||||
};
|
||||
}
|
||||
|
||||
private (Slider slider, SpinBox inputBox) GetSliderByOrder(ColorSliderOrder order)
|
||||
{
|
||||
return order switch
|
||||
{
|
||||
ColorSliderOrder.Top => (_topColorSlider, _topInputBox),
|
||||
ColorSliderOrder.Middle => (_middleColorSlider, _middleInputBox),
|
||||
ColorSliderOrder.Bottom => (_bottomColorSlider, _bottomInputBox),
|
||||
ColorSliderOrder.Alpha => (_alphaSlider, _alphaInputBox),
|
||||
_ => throw new ArgumentOutOfRangeException(),
|
||||
};
|
||||
}
|
||||
|
||||
private float GetColorValueDivisor(ColorSliderOrder order)
|
||||
{
|
||||
return order == ColorSliderOrder.Alpha
|
||||
? AlphaDivisor
|
||||
: GetStrategy().GetColorValueDivisor(order);
|
||||
}
|
||||
|
||||
private void UpdateType()
|
||||
{
|
||||
var strategy = GetStrategy();
|
||||
var labels = strategy.GetSliderLabelTexts();
|
||||
_topSliderLabel.Text = labels.top;
|
||||
_middleSliderLabel.Text = labels.middle;
|
||||
_bottomSliderLabel.Text = labels.bottom;
|
||||
(string topLabel, string middleLabel, string bottomLabel) labels = GetSliderLabels();
|
||||
|
||||
_topStyle.ConfigureSlider(strategy.TopSliderStyle);
|
||||
_middleStyle.ConfigureSlider(strategy.MiddleSliderStyle);
|
||||
_bottomStyle.ConfigureSlider(strategy.BottomSliderStyle);
|
||||
_topSliderLabel.Text = labels.topLabel;
|
||||
_middleSliderLabel.Text = labels.middleLabel;
|
||||
_bottomSliderLabel.Text = labels.bottomLabel;
|
||||
|
||||
bool hsv = SelectorType == ColorSelectorType.Hsv;
|
||||
_topStyle.ConfigureSlider( hsv ? ColorSelectorStyleBox.ColorSliderPreset.Hue : ColorSelectorStyleBox.ColorSliderPreset.Red);
|
||||
_middleStyle.ConfigureSlider( hsv ? ColorSelectorStyleBox.ColorSliderPreset.Saturation : ColorSelectorStyleBox.ColorSliderPreset.Green);
|
||||
_bottomStyle.ConfigureSlider( hsv ? ColorSelectorStyleBox.ColorSliderPreset.Value : ColorSelectorStyleBox.ColorSliderPreset.Blue);
|
||||
}
|
||||
|
||||
private void UpdateSlider(ColorSliderOrder order)
|
||||
private void Update()
|
||||
{
|
||||
var (slider, inputBox) = GetSliderByOrder(order);
|
||||
var divisor = GetColorValueDivisor(order);
|
||||
// This code is a mess of UI events causing stack overflows. Also, updating one slider triggers all sliders to
|
||||
// update, which due to rounding errors causes them to actually change values, specifically for HSV sliders.
|
||||
if (_updating)
|
||||
return;
|
||||
|
||||
var dataValue = order switch
|
||||
{
|
||||
ColorSliderOrder.Top => _colorData.X,
|
||||
ColorSliderOrder.Middle => _colorData.Y,
|
||||
ColorSliderOrder.Bottom => _colorData.Z,
|
||||
ColorSliderOrder.Alpha => _colorData.W,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(order))
|
||||
};
|
||||
|
||||
slider.SetValueWithoutEvent(dataValue);
|
||||
inputBox.OverrideValue((int)(dataValue * divisor));
|
||||
}
|
||||
|
||||
private void UpdateSliderVisuals()
|
||||
{
|
||||
_updating = true;
|
||||
_topStyle.SetBaseColor(_colorData);
|
||||
_middleStyle.SetBaseColor(_colorData);
|
||||
_bottomStyle.SetBaseColor(_colorData);
|
||||
}
|
||||
|
||||
private void UpdateAllSliders()
|
||||
{
|
||||
UpdateSliderVisuals();
|
||||
UpdateSlider(ColorSliderOrder.Top);
|
||||
UpdateSlider(ColorSliderOrder.Middle);
|
||||
UpdateSlider(ColorSliderOrder.Bottom);
|
||||
UpdateSlider(ColorSliderOrder.Alpha);
|
||||
switch (SelectorType)
|
||||
{
|
||||
case ColorSelectorType.Rgb:
|
||||
_topColorSlider.Value = _colorData.X;
|
||||
_middleColorSlider.Value = _colorData.Y;
|
||||
_bottomColorSlider.Value = _colorData.Z;
|
||||
|
||||
_topInputBox.Value = (int)(_colorData.X * 255.0f);
|
||||
_middleInputBox.Value = (int)(_colorData.Y * 255.0f);
|
||||
_bottomInputBox.Value = (int)(_colorData.Z * 255.0f);
|
||||
|
||||
break;
|
||||
case ColorSelectorType.Hsv:
|
||||
// dumb workaround because the formula for
|
||||
// HSV calculation results in a negative
|
||||
// number in any value past 300 degrees
|
||||
if (_colorData.X > 0)
|
||||
{
|
||||
_topColorSlider.Value = _colorData.X;
|
||||
_topInputBox.Value = (int)(_colorData.X * 360.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
_topInputBox.Value = (int)(_topColorSlider.Value * 360.0f);
|
||||
}
|
||||
|
||||
_middleColorSlider.Value = _colorData.Y;
|
||||
_bottomColorSlider.Value = _colorData.Z;
|
||||
|
||||
_middleInputBox.Value = (int)(_colorData.Y * 100.0f);
|
||||
_bottomInputBox.Value = (int)(_colorData.Z * 100.0f);
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
_alphaSlider.Value = Color.A;
|
||||
_alphaInputBox.Value = (int)(Color.A * 100.0f);
|
||||
_updating = false;
|
||||
}
|
||||
|
||||
private bool IsSpinBoxValid(int value, ColorSliderOrder ordering)
|
||||
{
|
||||
var divisor = GetColorValueDivisor(ordering);
|
||||
var channelValue = value / divisor;
|
||||
if (value < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return channelValue >= 0.0f && channelValue <= 1.0f;
|
||||
if (ordering == ColorSliderOrder.Alpha)
|
||||
{
|
||||
return value <= 100;
|
||||
}
|
||||
|
||||
switch (SelectorType)
|
||||
{
|
||||
case ColorSelectorType.Rgb:
|
||||
return value <= byte.MaxValue;
|
||||
case ColorSelectorType.Hsv:
|
||||
switch (ordering)
|
||||
{
|
||||
case ColorSliderOrder.Top:
|
||||
return value <= 360;
|
||||
default:
|
||||
return value <= 100;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void OnInputBoxValueChanged(ValueChangedEventArgs args, ColorSliderOrder order)
|
||||
private (string, string, string) GetSliderLabels()
|
||||
{
|
||||
var (slider, _) = GetSliderByOrder(order);
|
||||
var value = args.Value / GetColorValueDivisor(order);
|
||||
switch (SelectorType)
|
||||
{
|
||||
case ColorSelectorType.Rgb:
|
||||
return (
|
||||
Loc.GetString("color-selector-sliders-red"),
|
||||
Loc.GetString("color-selector-sliders-green"),
|
||||
Loc.GetString("color-selector-sliders-blue")
|
||||
);
|
||||
case ColorSelectorType.Hsv:
|
||||
return (
|
||||
Loc.GetString("color-selector-sliders-hue"),
|
||||
Loc.GetString("color-selector-sliders-saturation"),
|
||||
Loc.GetString("color-selector-sliders-value")
|
||||
);
|
||||
}
|
||||
|
||||
// We are intentionally triggering the slider OnValueChanged event here.
|
||||
// This is so that the color data values of the sliders are updated accordingly.
|
||||
slider.Value = value;
|
||||
return ("ERR", "ERR", "ERR");
|
||||
}
|
||||
|
||||
private void OnSliderValueChanged(ColorSliderOrder order)
|
||||
private float GetColorValueDivisor(ColorSliderOrder order)
|
||||
{
|
||||
_colorData = new Vector4(
|
||||
_topColorSlider.Value,
|
||||
_middleColorSlider.Value,
|
||||
_bottomColorSlider.Value,
|
||||
_alphaSlider.Value);
|
||||
if (order == ColorSliderOrder.Alpha)
|
||||
{
|
||||
return 100.0f;
|
||||
}
|
||||
|
||||
_currentColor = GetStrategy().FromColorData(_colorData);
|
||||
OnColorChanged?.Invoke(_currentColor);
|
||||
switch (SelectorType)
|
||||
{
|
||||
case ColorSelectorType.Rgb:
|
||||
return 255.0f;
|
||||
case ColorSelectorType.Hsv:
|
||||
switch (order)
|
||||
{
|
||||
case ColorSliderOrder.Top:
|
||||
return 360.0f;
|
||||
default:
|
||||
return 100.0f;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateSliderVisuals();
|
||||
UpdateSlider(order);
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
private void OnColorSet(bool release = false)
|
||||
{
|
||||
// stack overflow otherwise due to value sets
|
||||
if (_updating)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_colorData = new Vector4(_topColorSlider.Value, _middleColorSlider.Value, _bottomColorSlider.Value, _alphaSlider.Value);
|
||||
|
||||
_currentColor = SelectorType switch
|
||||
{
|
||||
ColorSelectorType.Hsv => Color.FromHsv(_colorData),
|
||||
_ => new Color(_colorData.X, _colorData.Y, _colorData.Z, _colorData.W)
|
||||
};
|
||||
|
||||
Update();
|
||||
if (release)
|
||||
OnColorReleased?.Invoke(_currentColor);
|
||||
else
|
||||
OnColorChanged?.Invoke(_currentColor);
|
||||
}
|
||||
|
||||
private enum ColorSliderOrder
|
||||
|
|
@ -369,121 +443,4 @@ public sealed class CustomColorSelectorSliders : Control
|
|||
Rgb,
|
||||
Hsv,
|
||||
}
|
||||
|
||||
private abstract class ColorSliderStrategy
|
||||
{
|
||||
/// <summary>
|
||||
/// The style preset used by the top slider.
|
||||
/// </summary>
|
||||
public abstract ColorSelectorStyleBox.ColorSliderPreset TopSliderStyle { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The style preset used by the middle slider.
|
||||
/// </summary>
|
||||
public abstract ColorSelectorStyleBox.ColorSliderPreset MiddleSliderStyle { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The style preset used by the bottom slider.
|
||||
/// </summary>
|
||||
public abstract ColorSelectorStyleBox.ColorSliderPreset BottomSliderStyle { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Color to a Vector4 representation of its components.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Each value in the Vector4 must be between 0.0f and 1.0f; this is used in the
|
||||
/// context of slider values, which are between these ranges.
|
||||
/// </remarks>
|
||||
/// <param name="color">A Color to convert into Vector4 slider values.</param>
|
||||
/// <returns>A Vector4 representation of a Color's slider values.</returns>
|
||||
public abstract Vector4 ToColorData(Color color);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Vector4 representation of color slider values into a Color.
|
||||
/// </summary>
|
||||
/// <param name="colorData">A Vector4 representation of color slider values.</param>
|
||||
/// <returns>A color generated from slider values.</returns>
|
||||
public abstract Color FromColorData(Vector4 colorData);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a color component divisor for the given slider.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is used for converting slider values to/from color component values.
|
||||
/// For example, in RGB coloration, each channel ranges from 0 to 255,
|
||||
/// so if you had a slider value of 0.2, you would multiply 0.2 * 255 = 51
|
||||
/// for the "channel" value.
|
||||
///
|
||||
/// This does not apply to the Alpha channel, as the Alpha channel
|
||||
/// always uses the same divisor; this is defined in ColorSelectorSliders.
|
||||
/// </remarks>
|
||||
/// <param name="order">The slider to retrieve a divisor for.</param>
|
||||
/// <returns>The divisor for the given slider.</returns>
|
||||
public abstract float GetColorValueDivisor(ColorSliderOrder order);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a label text string for the first three color sliders.
|
||||
/// </summary>
|
||||
/// <returns>Label text strings for the top, middle, and bottom sliders.</returns>
|
||||
public abstract (string top, string middle, string bottom) GetSliderLabelTexts();
|
||||
}
|
||||
|
||||
private sealed class RgbSliderStrategy : ColorSliderStrategy
|
||||
{
|
||||
private const float ChannelMaxValue = byte.MaxValue;
|
||||
|
||||
public override ColorSelectorStyleBox.ColorSliderPreset TopSliderStyle
|
||||
=> ColorSelectorStyleBox.ColorSliderPreset.Red;
|
||||
public override ColorSelectorStyleBox.ColorSliderPreset MiddleSliderStyle
|
||||
=> ColorSelectorStyleBox.ColorSliderPreset.Green;
|
||||
public override ColorSelectorStyleBox.ColorSliderPreset BottomSliderStyle
|
||||
=> ColorSelectorStyleBox.ColorSliderPreset.Blue;
|
||||
|
||||
public override Vector4 ToColorData(Color color) => new(color.R, color.G, color.B, color.A);
|
||||
public override Color FromColorData(Vector4 colorData)
|
||||
=> new(colorData.X, colorData.Y, colorData.Z, colorData.W);
|
||||
|
||||
public override float GetColorValueDivisor(ColorSliderOrder order) => ChannelMaxValue;
|
||||
|
||||
public override (string top, string middle, string bottom) GetSliderLabelTexts()
|
||||
{
|
||||
return (
|
||||
Loc.GetString("color-selector-sliders-red"),
|
||||
Loc.GetString("color-selector-sliders-green"),
|
||||
Loc.GetString("color-selector-sliders-blue"));
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class HsvSliderStrategy : ColorSliderStrategy
|
||||
{
|
||||
private const float HueMaxValue = 360.0f;
|
||||
private const float SliderMaxValue = 100.0f;
|
||||
|
||||
public override ColorSelectorStyleBox.ColorSliderPreset TopSliderStyle
|
||||
=> ColorSelectorStyleBox.ColorSliderPreset.Hue;
|
||||
public override ColorSelectorStyleBox.ColorSliderPreset MiddleSliderStyle
|
||||
=> ColorSelectorStyleBox.ColorSliderPreset.Saturation;
|
||||
public override ColorSelectorStyleBox.ColorSliderPreset BottomSliderStyle
|
||||
=> ColorSelectorStyleBox.ColorSliderPreset.Value;
|
||||
|
||||
public override Vector4 ToColorData(Color color) => Color.ToHsv(color);
|
||||
public override Color FromColorData(Vector4 colorData) => Color.FromHsv(colorData);
|
||||
|
||||
public override float GetColorValueDivisor(ColorSliderOrder order)
|
||||
{
|
||||
return order switch
|
||||
{
|
||||
ColorSliderOrder.Top => HueMaxValue,
|
||||
_ => SliderMaxValue,
|
||||
};
|
||||
}
|
||||
|
||||
public override (string top, string middle, string bottom) GetSliderLabelTexts()
|
||||
{
|
||||
return (
|
||||
Loc.GetString("color-selector-sliders-hue"),
|
||||
Loc.GetString("color-selector-sliders-saturation"),
|
||||
Loc.GetString("color-selector-sliders-value"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,242 +0,0 @@
|
|||
using Content.Client._Sunrise.MarkingEffectsClient;
|
||||
using Content.Shared._Sunrise.MarkingEffects;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
|
||||
namespace Content.Client._Sunrise.UserInterface.Controls;
|
||||
|
||||
public sealed class MarkingEffectSelectorSliders : Control
|
||||
{
|
||||
private MarkingEffect Effect { get; set; }
|
||||
|
||||
private static readonly Dictionary<MarkingEffectType, IMarkingEffectUiBuilder> UiBuilders = new()
|
||||
{
|
||||
{ MarkingEffectType.Color, new ColorMarkingEffectUiBuilder() },
|
||||
{ MarkingEffectType.Gradient, new GradientMarkingEffectUiBuilder() },
|
||||
{ MarkingEffectType.RoughGradient, new RoughGradientMarkingEffectUiBuilder() },
|
||||
};
|
||||
|
||||
private readonly Dictionary<string, CustomColorSelectorSliders> _colorSelectors = new();
|
||||
|
||||
private readonly OptionButton _typeSelector;
|
||||
private readonly List<MarkingEffectType> _types = new();
|
||||
|
||||
private MarkingEffectType _currentType;
|
||||
|
||||
private readonly BoxContainer _selectorsContainer;
|
||||
private readonly BoxContainer _slidersContainer;
|
||||
private readonly BoxContainer _toggleContainer;
|
||||
|
||||
public Action<MarkingEffect>? OnColorChanged;
|
||||
|
||||
public MarkingEffectType CurrentType
|
||||
{
|
||||
get => _currentType;
|
||||
set
|
||||
{
|
||||
if (_currentType == value)
|
||||
return;
|
||||
|
||||
_currentType = value;
|
||||
Populate(_currentType);
|
||||
}
|
||||
}
|
||||
|
||||
public MarkingEffectSelectorSliders(MarkingEffect? defaultEffect = null)
|
||||
{
|
||||
defaultEffect ??= ColorMarkingEffect.White;
|
||||
|
||||
_typeSelector = new OptionButton();
|
||||
_typeSelector.HorizontalExpand = true;
|
||||
foreach (var type in Enum.GetValues<MarkingEffectType>())
|
||||
{
|
||||
_typeSelector.AddItem(Loc.GetString($"marking-effect-type-{type.ToString().ToLower()}"));
|
||||
_types.Add(type);
|
||||
}
|
||||
|
||||
_typeSelector.OnItemSelected += args =>
|
||||
{
|
||||
CurrentType = _types[args.Id];
|
||||
_typeSelector.Select(args.Id);
|
||||
OnColorsChanged();
|
||||
};
|
||||
|
||||
var rootBox = new BoxContainer
|
||||
{ Orientation = BoxContainer.LayoutOrientation.Vertical };
|
||||
AddChild(rootBox);
|
||||
|
||||
var headerBox = new BoxContainer();
|
||||
rootBox.AddChild(headerBox);
|
||||
headerBox.AddChild(_typeSelector);
|
||||
|
||||
var bodyBox = new BoxContainer
|
||||
{ Orientation = BoxContainer.LayoutOrientation.Vertical };
|
||||
rootBox.AddChild(bodyBox);
|
||||
|
||||
_selectorsContainer = new BoxContainer();
|
||||
bodyBox.AddChild(_selectorsContainer);
|
||||
|
||||
_slidersContainer = new BoxContainer
|
||||
{ Orientation = BoxContainer.LayoutOrientation.Vertical };
|
||||
bodyBox.AddChild(_slidersContainer);
|
||||
|
||||
_toggleContainer = new BoxContainer();
|
||||
bodyBox.AddChild(_toggleContainer);
|
||||
|
||||
|
||||
_currentType = defaultEffect.Type;
|
||||
_typeSelector.TrySelect(_types.IndexOf(_currentType));
|
||||
Effect = defaultEffect;
|
||||
Populate(_currentType, defaultEffect);
|
||||
}
|
||||
|
||||
public CustomColorSelectorSliders CreateSelector(string key = "base", MarkingEffectType type = MarkingEffectType.Color)
|
||||
{
|
||||
var colorSelector = new CustomColorSelectorSliders(
|
||||
CustomColorSelectorSliders.ColorSelectorType.Hsv,
|
||||
Loc.GetString($"marking-effect-{type.ToString().ToLower()}-color-{key}"));
|
||||
|
||||
colorSelector.HorizontalExpand = true;
|
||||
colorSelector.HorizontalAlignment = HAlignment.Stretch;
|
||||
|
||||
if (Effect.Colors.TryGetValue(key, out var defaultColor))
|
||||
colorSelector.Color = defaultColor;
|
||||
|
||||
colorSelector.OnColorChanged += _ => OnColorsChanged();
|
||||
|
||||
_colorSelectors.Add(key, colorSelector);
|
||||
|
||||
var selectorContainer = new BoxContainer
|
||||
{
|
||||
HorizontalExpand = true,
|
||||
HorizontalAlignment = HAlignment.Stretch,
|
||||
};
|
||||
|
||||
_selectorsContainer.AddChild(selectorContainer);
|
||||
selectorContainer.AddChild(colorSelector);
|
||||
|
||||
return colorSelector;
|
||||
}
|
||||
|
||||
public void CreateSlider(string label,
|
||||
int defaultValue,
|
||||
int minValue,
|
||||
int maxValue,
|
||||
Action<float> onValueChanged)
|
||||
{
|
||||
var slider = new Slider
|
||||
{
|
||||
HorizontalExpand = true,
|
||||
VerticalAlignment = VAlignment.Center,
|
||||
};
|
||||
|
||||
slider.MinValue = minValue;
|
||||
slider.MaxValue = maxValue;
|
||||
slider.Value = defaultValue;
|
||||
|
||||
var sliderContainer = new BoxContainer();
|
||||
|
||||
var sliderLabel = new Label();
|
||||
sliderLabel.Text = label;
|
||||
|
||||
var spinBox = new SpinBox
|
||||
{
|
||||
IsValid = value => IsSpinBoxValid(value, minValue, maxValue)
|
||||
};
|
||||
spinBox.InitDefaultButtons();
|
||||
spinBox.Value = defaultValue;
|
||||
|
||||
|
||||
|
||||
sliderContainer.AddChild(sliderLabel);
|
||||
sliderContainer.AddChild(slider);
|
||||
sliderContainer.AddChild(spinBox);
|
||||
_slidersContainer.AddChild(sliderContainer);
|
||||
|
||||
BindSlider(slider, spinBox, onValueChanged);
|
||||
}
|
||||
|
||||
private void BindSlider(Slider slider, SpinBox spinBox, Action<float> setValue)
|
||||
{
|
||||
slider.OnReleased += val =>
|
||||
{
|
||||
setValue(val.Value);
|
||||
spinBox.Value = (int)(val.Value);
|
||||
OnColorsChanged();
|
||||
};
|
||||
|
||||
spinBox.ValueChanged += val =>
|
||||
{
|
||||
setValue(val.Value);
|
||||
slider.SetValueWithoutEvent(val.Value);
|
||||
OnColorsChanged();
|
||||
};
|
||||
}
|
||||
|
||||
public void CreateToggle(string label, bool defaultValue, Action<bool> onValueChanged)
|
||||
{
|
||||
var button = new Button
|
||||
{
|
||||
Text = label,
|
||||
ToggleMode = true,
|
||||
Pressed = defaultValue,
|
||||
HorizontalExpand = true,
|
||||
};
|
||||
|
||||
button.OnToggled += _ => OnColorsChanged();
|
||||
|
||||
_toggleContainer.AddChild(button);
|
||||
|
||||
BindToggle(button, onValueChanged);
|
||||
}
|
||||
|
||||
private void BindToggle(Button toggle, Action<bool> setValue)
|
||||
{
|
||||
toggle.OnToggled += val =>
|
||||
{
|
||||
setValue(val.Pressed);
|
||||
OnColorsChanged();
|
||||
};
|
||||
}
|
||||
|
||||
private bool IsSpinBoxValid(int value, float min, float max)
|
||||
{
|
||||
return (value >= min) && (value <= max);
|
||||
}
|
||||
|
||||
private void OnColorsChanged()
|
||||
{
|
||||
foreach (var (key, selector) in _colorSelectors)
|
||||
{
|
||||
Effect.Colors[key] = selector.Color;
|
||||
}
|
||||
|
||||
OnColorChanged?.Invoke(Effect);
|
||||
}
|
||||
|
||||
private void Populate(MarkingEffectType type, MarkingEffect? defaultEffect = null)
|
||||
{
|
||||
_colorSelectors.Clear();
|
||||
_selectorsContainer.DisposeAllChildren();
|
||||
_slidersContainer.DisposeAllChildren();
|
||||
_toggleContainer.DisposeAllChildren();
|
||||
|
||||
Logger.Debug($"{defaultEffect}");
|
||||
|
||||
defaultEffect ??= type switch
|
||||
{
|
||||
MarkingEffectType.Color => ColorMarkingEffect.White,
|
||||
MarkingEffectType.Gradient => new GradientMarkingEffect(),
|
||||
MarkingEffectType.RoughGradient => new RoughGradientMarkingEffect(),
|
||||
_ => ColorMarkingEffect.White,
|
||||
};
|
||||
|
||||
Effect = defaultEffect;
|
||||
|
||||
if (UiBuilders.TryGetValue(type, out var builder))
|
||||
builder.BuildUI(Effect, this);
|
||||
else
|
||||
Logger.Warning($"No UI builder for marking effect: {type}");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Server.Database;
|
||||
using Content.Shared._Sunrise.MarkingEffects;
|
||||
using Content.Shared.GameTicking;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Preferences;
|
||||
|
|
@ -55,12 +54,8 @@ namespace Content.IntegrationTests.Tests.Preferences
|
|||
Color.Azure,
|
||||
Color.Beige,
|
||||
new (),
|
||||
MarkingEffectType.Color,
|
||||
null,
|
||||
MarkingEffectType.Color,
|
||||
null,
|
||||
1,
|
||||
1)
|
||||
1.0f,
|
||||
1.0f)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,62 +0,0 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Gradient : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "facial_hair_color_type",
|
||||
table: "profile",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "facial_hair_extended_color",
|
||||
table: "profile",
|
||||
type: "text",
|
||||
nullable: false,
|
||||
defaultValue: "");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "hair_color_type",
|
||||
table: "profile",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "hair_extended_color",
|
||||
table: "profile",
|
||||
type: "text",
|
||||
nullable: false,
|
||||
defaultValue: "");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "facial_hair_color_type",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "facial_hair_extended_color",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "hair_color_type",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "hair_extended_color",
|
||||
table: "profile");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Postgres
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class GradientFields : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "hair_gradient_enabled",
|
||||
table: "profile",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "hair_gradient_secondary_color",
|
||||
table: "profile",
|
||||
type: "text",
|
||||
nullable: false,
|
||||
defaultValue: "#FFFFFF");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "hair_gradient_direction",
|
||||
table: "profile",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "facial_hair_gradient_enabled",
|
||||
table: "profile",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "facial_hair_gradient_secondary_color",
|
||||
table: "profile",
|
||||
type: "text",
|
||||
nullable: false,
|
||||
defaultValue: "#FFFFFF");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "facial_hair_gradient_direction",
|
||||
table: "profile",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "all_markings_gradient_enabled",
|
||||
table: "profile",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "all_markings_gradient_secondary_color",
|
||||
table: "profile",
|
||||
type: "text",
|
||||
nullable: false,
|
||||
defaultValue: "#FFFFFF");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "all_markings_gradient_direction",
|
||||
table: "profile",
|
||||
type: "integer",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "hair_gradient_enabled",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "hair_gradient_secondary_color",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "hair_gradient_direction",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "facial_hair_gradient_enabled",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "facial_hair_gradient_secondary_color",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "facial_hair_gradient_direction",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "all_markings_gradient_enabled",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "all_markings_gradient_secondary_color",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "all_markings_gradient_direction",
|
||||
table: "profile");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1008,15 +1008,6 @@ namespace Content.Server.Database.Migrations.Postgres
|
|||
.HasColumnType("text")
|
||||
.HasColumnName("facial_hair_color");
|
||||
|
||||
b.Property<int>("FacialHairColorType")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("facial_hair_color_type");
|
||||
|
||||
b.Property<string>("FacialHairExtendedColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("facial_hair_extended_color");
|
||||
|
||||
b.Property<string>("FacialHairName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
|
|
@ -1037,15 +1028,6 @@ namespace Content.Server.Database.Migrations.Postgres
|
|||
.HasColumnType("text")
|
||||
.HasColumnName("hair_color");
|
||||
|
||||
b.Property<int>("HairColorType")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("hair_color_type");
|
||||
|
||||
b.Property<string>("HairExtendedColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("hair_extended_color");
|
||||
|
||||
b.Property<string>("HairName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
|
|
@ -1099,6 +1081,45 @@ namespace Content.Server.Database.Migrations.Postgres
|
|||
.HasColumnType("real")
|
||||
.HasColumnName("width");
|
||||
|
||||
b.Property<bool>("AllMarkingsGradientEnabled")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("all_markings_gradient_enabled");
|
||||
|
||||
b.Property<string>("AllMarkingsGradientSecondaryColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("all_markings_gradient_secondary_color");
|
||||
|
||||
b.Property<int>("AllMarkingsGradientDirection")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("all_markings_gradient_direction");
|
||||
|
||||
b.Property<bool>("FacialHairGradientEnabled")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("facial_hair_gradient_enabled");
|
||||
|
||||
b.Property<string>("FacialHairGradientSecondaryColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("facial_hair_gradient_secondary_color");
|
||||
|
||||
b.Property<int>("FacialHairGradientDirection")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("facial_hair_gradient_direction");
|
||||
|
||||
b.Property<bool>("HairGradientEnabled")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("hair_gradient_enabled");
|
||||
|
||||
b.Property<string>("HairGradientSecondaryColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("hair_gradient_secondary_color");
|
||||
|
||||
b.Property<int>("HairGradientDirection")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("hair_gradient_direction");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_profile");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,62 +0,0 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Gradient : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "facial_hair_color_type",
|
||||
table: "profile",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "facial_hair_extended_color",
|
||||
table: "profile",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: "");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "hair_color_type",
|
||||
table: "profile",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "hair_extended_color",
|
||||
table: "profile",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: "");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "facial_hair_color_type",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "facial_hair_extended_color",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "hair_color_type",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "hair_extended_color",
|
||||
table: "profile");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,8 +11,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
[DbContext(typeof(SqliteServerDbContext))]
|
||||
[Migration("20250724212307_Gradient")]
|
||||
partial class Gradient
|
||||
[Migration("20250910035429_GradientFields")]
|
||||
partial class GradientFields
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
|
|
@ -136,6 +136,10 @@ namespace Content.Server.Database.Migrations.Sqlite
|
|||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("admin_log_id");
|
||||
|
||||
b.Property<long>("CurTime")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("cur_time");
|
||||
|
||||
b.Property<DateTime>("Date")
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("date");
|
||||
|
|
@ -827,6 +831,19 @@ namespace Content.Server.Database.Migrations.Sqlite
|
|||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("age");
|
||||
|
||||
b.Property<int>("AllMarkingsGradientDirection")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("all_markings_gradient_direction");
|
||||
|
||||
b.Property<bool>("AllMarkingsGradientEnabled")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("all_markings_gradient_enabled");
|
||||
|
||||
b.Property<string>("AllMarkingsGradientSecondaryColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("all_markings_gradient_secondary_color");
|
||||
|
||||
b.Property<string>("BodyType")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
|
|
@ -847,14 +864,18 @@ namespace Content.Server.Database.Migrations.Sqlite
|
|||
.HasColumnType("TEXT")
|
||||
.HasColumnName("facial_hair_color");
|
||||
|
||||
b.Property<int>("FacialHairColorType")
|
||||
b.Property<int>("FacialHairGradientDirection")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("facial_hair_color_type");
|
||||
.HasColumnName("facial_hair_gradient_direction");
|
||||
|
||||
b.Property<string>("FacialHairExtendedColor")
|
||||
b.Property<bool>("FacialHairGradientEnabled")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("facial_hair_gradient_enabled");
|
||||
|
||||
b.Property<string>("FacialHairGradientSecondaryColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("facial_hair_extended_color");
|
||||
.HasColumnName("facial_hair_gradient_secondary_color");
|
||||
|
||||
b.Property<string>("FacialHairName")
|
||||
.IsRequired()
|
||||
|
|
@ -876,20 +897,28 @@ namespace Content.Server.Database.Migrations.Sqlite
|
|||
.HasColumnType("TEXT")
|
||||
.HasColumnName("hair_color");
|
||||
|
||||
b.Property<int>("HairColorType")
|
||||
b.Property<int>("HairGradientDirection")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("hair_color_type");
|
||||
.HasColumnName("hair_gradient_direction");
|
||||
|
||||
b.Property<string>("HairExtendedColor")
|
||||
b.Property<bool>("HairGradientEnabled")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("hair_gradient_enabled");
|
||||
|
||||
b.Property<string>("HairGradientSecondaryColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("hair_extended_color");
|
||||
.HasColumnName("hair_gradient_secondary_color");
|
||||
|
||||
b.Property<string>("HairName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("hair_name");
|
||||
|
||||
b.Property<float>("Height")
|
||||
.HasColumnType("REAL")
|
||||
.HasColumnName("height");
|
||||
|
||||
b.Property<byte[]>("Markings")
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("markings");
|
||||
|
|
@ -930,6 +959,10 @@ namespace Content.Server.Database.Migrations.Sqlite
|
|||
.HasColumnType("TEXT")
|
||||
.HasColumnName("voice");
|
||||
|
||||
b.Property<float>("Width")
|
||||
.HasColumnType("REAL")
|
||||
.HasColumnName("width");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("PK_profile");
|
||||
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Content.Server.Database.Migrations.Sqlite
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class GradientFields : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "all_markings_gradient_direction",
|
||||
table: "profile",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "all_markings_gradient_enabled",
|
||||
table: "profile",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "all_markings_gradient_secondary_color",
|
||||
table: "profile",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: "#FFFFFF");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "facial_hair_gradient_direction",
|
||||
table: "profile",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "facial_hair_gradient_enabled",
|
||||
table: "profile",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "facial_hair_gradient_secondary_color",
|
||||
table: "profile",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: "#FFFFFF");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "hair_gradient_direction",
|
||||
table: "profile",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "hair_gradient_enabled",
|
||||
table: "profile",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "hair_gradient_secondary_color",
|
||||
table: "profile",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: "#FFFFFF");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "all_markings_gradient_direction",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "all_markings_gradient_enabled",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "all_markings_gradient_secondary_color",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "facial_hair_gradient_direction",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "facial_hair_gradient_enabled",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "facial_hair_gradient_secondary_color",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "hair_gradient_direction",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "hair_gradient_enabled",
|
||||
table: "profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "hair_gradient_secondary_color",
|
||||
table: "profile");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -933,6 +933,19 @@ namespace Content.Server.Database.Migrations.Sqlite
|
|||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("age");
|
||||
|
||||
b.Property<int>("AllMarkingsGradientDirection")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("all_markings_gradient_direction");
|
||||
|
||||
b.Property<bool>("AllMarkingsGradientEnabled")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("all_markings_gradient_enabled");
|
||||
|
||||
b.Property<string>("AllMarkingsGradientSecondaryColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("all_markings_gradient_secondary_color");
|
||||
|
||||
b.Property<string>("BodyType")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
|
|
@ -953,14 +966,18 @@ namespace Content.Server.Database.Migrations.Sqlite
|
|||
.HasColumnType("TEXT")
|
||||
.HasColumnName("facial_hair_color");
|
||||
|
||||
b.Property<int>("FacialHairColorType")
|
||||
b.Property<int>("FacialHairGradientDirection")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("facial_hair_color_type");
|
||||
.HasColumnName("facial_hair_gradient_direction");
|
||||
|
||||
b.Property<string>("FacialHairExtendedColor")
|
||||
b.Property<bool>("FacialHairGradientEnabled")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("facial_hair_gradient_enabled");
|
||||
|
||||
b.Property<string>("FacialHairGradientSecondaryColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("facial_hair_extended_color");
|
||||
.HasColumnName("facial_hair_gradient_secondary_color");
|
||||
|
||||
b.Property<string>("FacialHairName")
|
||||
.IsRequired()
|
||||
|
|
@ -982,14 +999,18 @@ namespace Content.Server.Database.Migrations.Sqlite
|
|||
.HasColumnType("TEXT")
|
||||
.HasColumnName("hair_color");
|
||||
|
||||
b.Property<int>("HairColorType")
|
||||
b.Property<int>("HairGradientDirection")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("hair_color_type");
|
||||
.HasColumnName("hair_gradient_direction");
|
||||
|
||||
b.Property<string>("HairExtendedColor")
|
||||
b.Property<bool>("HairGradientEnabled")
|
||||
.HasColumnType("INTEGER")
|
||||
.HasColumnName("hair_gradient_enabled");
|
||||
|
||||
b.Property<string>("HairGradientSecondaryColor")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT")
|
||||
.HasColumnName("hair_extended_color");
|
||||
.HasColumnName("hair_gradient_secondary_color");
|
||||
|
||||
b.Property<string>("HairName")
|
||||
.IsRequired()
|
||||
|
|
|
|||
|
|
@ -422,14 +422,23 @@ namespace Content.Server.Database
|
|||
public string HairColor { get; set; } = null!;
|
||||
public string FacialHairName { get; set; } = null!;
|
||||
public string FacialHairColor { get; set; } = null!;
|
||||
// sunrise gradient start
|
||||
public int HairColorType { get; set; } = 0;
|
||||
public string HairExtendedColor { get; set; } = null!;
|
||||
public int FacialHairColorType { get; set; } = 0;
|
||||
public string FacialHairExtendedColor { get; set; } = null!;
|
||||
// sunrise gradient end
|
||||
public string EyeColor { get; set; } = null!;
|
||||
public string SkinColor { get; set; } = null!;
|
||||
|
||||
// Sunrise: Hair gradient fields
|
||||
public bool HairGradientEnabled { get; set; } = false;
|
||||
public string HairGradientSecondaryColor { get; set; } = "#FFFFFF";
|
||||
public int HairGradientDirection { get; set; } = 0;
|
||||
|
||||
// Sunrise: Facial hair gradient fields
|
||||
public bool FacialHairGradientEnabled { get; set; } = false;
|
||||
public string FacialHairGradientSecondaryColor { get; set; } = "#FFFFFF";
|
||||
public int FacialHairGradientDirection { get; set; } = 0;
|
||||
|
||||
// Sunrise: All markings gradient fields
|
||||
public bool AllMarkingsGradientEnabled { get; set; } = false;
|
||||
public string AllMarkingsGradientSecondaryColor { get; set; } = "#FFFFFF";
|
||||
public int AllMarkingsGradientDirection { get; set; } = 0;
|
||||
public int SpawnPriority { get; set; } = 0;
|
||||
public List<Job> Jobs { get; } = new();
|
||||
public List<Antag> Antags { get; } = new();
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ namespace Content.Server.Database
|
|||
options.ConfigureWarnings(x =>
|
||||
{
|
||||
x.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning);
|
||||
x.Ignore(Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.PendingModelChangesWarning); //Lua: Игнорируем предупреждение о pending changes
|
||||
#if DEBUG
|
||||
// for tests
|
||||
x.Ignore(CoreEventId.SensitiveDataLoggingEnabledWarning);
|
||||
|
|
|
|||
|
|
@ -8,9 +8,8 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Administration.Managers;
|
||||
using Content.Shared._Sunrise.MarkingEffects;
|
||||
using Content.Shared._Sunrise.MentorHelp;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared._Sunrise.MentorHelp;
|
||||
using Content.Shared.Construction.Prototypes;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Humanoid;
|
||||
|
|
@ -25,6 +24,7 @@ using Robust.Shared.Network;
|
|||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
|
||||
namespace Content.Server.Database
|
||||
{
|
||||
public abstract class ServerDbBase
|
||||
|
|
@ -207,6 +207,9 @@ namespace Content.Server.Database
|
|||
|
||||
private static HumanoidCharacterProfile ConvertProfiles(Profile profile)
|
||||
{
|
||||
// Debug logging for gradient load
|
||||
Console.WriteLine($"Sunrise: Loading gradient settings from DB - Hair: {profile.HairGradientEnabled}, FacialHair: {profile.FacialHairGradientEnabled}, AllMarkings: {profile.AllMarkingsGradientEnabled}");
|
||||
|
||||
var jobs = profile.Jobs.ToDictionary(j => new ProtoId<JobPrototype>(j.JobName), j => (JobPriority) j.Priority);
|
||||
var antags = profile.Antags.Select(a => new ProtoId<AntagPrototype>(a.AntagName));
|
||||
var traits = profile.Traits.Select(t => new ProtoId<TraitPrototype>(t.TraitName));
|
||||
|
|
@ -285,15 +288,21 @@ namespace Content.Server.Database
|
|||
Color.FromHex(profile.EyeColor),
|
||||
Color.FromHex(profile.SkinColor),
|
||||
markings,
|
||||
//sunrise gradient start
|
||||
(MarkingEffectType)profile.HairColorType,
|
||||
MarkingEffect.Parse(profile.HairExtendedColor),
|
||||
(MarkingEffectType)profile.FacialHairColorType,
|
||||
MarkingEffect.Parse(profile.FacialHairExtendedColor),
|
||||
//sunrise gradient end
|
||||
profile.Width,
|
||||
profile.Height
|
||||
),
|
||||
)
|
||||
{
|
||||
// Sunrise: Load gradient settings from database
|
||||
HairGradientEnabled = profile.HairGradientEnabled,
|
||||
HairGradientSecondaryColor = Color.FromHex(profile.HairGradientSecondaryColor ?? "#FFFFFF"),
|
||||
HairGradientDirection = profile.HairGradientDirection,
|
||||
FacialHairGradientEnabled = profile.FacialHairGradientEnabled,
|
||||
FacialHairGradientSecondaryColor = Color.FromHex(profile.FacialHairGradientSecondaryColor ?? "#FFFFFF"),
|
||||
FacialHairGradientDirection = profile.FacialHairGradientDirection,
|
||||
AllMarkingsGradientEnabled = profile.AllMarkingsGradientEnabled,
|
||||
AllMarkingsGradientSecondaryColor = Color.FromHex(profile.AllMarkingsGradientSecondaryColor ?? "#FFFFFF"),
|
||||
AllMarkingsGradientDirection = profile.AllMarkingsGradientDirection
|
||||
},
|
||||
spawnPriority,
|
||||
jobs,
|
||||
(PreferenceUnavailableMode) profile.PreferenceUnavailable,
|
||||
|
|
@ -328,14 +337,22 @@ namespace Content.Server.Database
|
|||
profile.HairColor = appearance.HairColor.ToHex();
|
||||
profile.FacialHairName = appearance.FacialHairStyleId;
|
||||
profile.FacialHairColor = appearance.FacialHairColor.ToHex();
|
||||
// sunrise gradient start
|
||||
profile.HairColorType = (int)appearance.HairMarkingEffectType;
|
||||
profile.HairExtendedColor = appearance.HairMarkingEffect?.ToString() ?? "";
|
||||
profile.FacialHairColorType = (int)appearance.FacialHairMarkingEffectType;
|
||||
profile.FacialHairExtendedColor = appearance.FacialHairMarkingEffect?.ToString() ?? "";
|
||||
// sunrise gradient end
|
||||
profile.EyeColor = appearance.EyeColor.ToHex();
|
||||
profile.SkinColor = appearance.SkinColor.ToHex();
|
||||
|
||||
// Sunrise: Save gradient settings to database
|
||||
profile.HairGradientEnabled = appearance.HairGradientEnabled;
|
||||
profile.HairGradientSecondaryColor = appearance.HairGradientSecondaryColor.ToHex();
|
||||
profile.HairGradientDirection = appearance.HairGradientDirection;
|
||||
profile.FacialHairGradientEnabled = appearance.FacialHairGradientEnabled;
|
||||
profile.FacialHairGradientSecondaryColor = appearance.FacialHairGradientSecondaryColor.ToHex();
|
||||
profile.FacialHairGradientDirection = appearance.FacialHairGradientDirection;
|
||||
profile.AllMarkingsGradientEnabled = appearance.AllMarkingsGradientEnabled;
|
||||
profile.AllMarkingsGradientSecondaryColor = appearance.AllMarkingsGradientSecondaryColor.ToHex();
|
||||
profile.AllMarkingsGradientDirection = appearance.AllMarkingsGradientDirection;
|
||||
|
||||
// Debug logging for gradient save
|
||||
Console.WriteLine($"Sunrise: Saving gradient settings - Hair: {appearance.HairGradientEnabled}, FacialHair: {appearance.FacialHairGradientEnabled}, AllMarkings: {appearance.AllMarkingsGradientEnabled}");
|
||||
profile.SpawnPriority = (int) humanoid.SpawnPriority;
|
||||
profile.Markings = markings;
|
||||
profile.Slot = slot;
|
||||
|
|
|
|||
|
|
@ -131,6 +131,45 @@ public sealed partial class HumanoidAppearanceComponent : Component
|
|||
/// </summary>
|
||||
[DataField]
|
||||
public Dictionary<string, Dictionary<Sex, Dictionary<HumanoidVisualLayers, DisplacementData>>> BodyTypeSexMarkingsDisplacement = new();
|
||||
|
||||
//Sunrise start Hair/Fur gradient settings (client-applied shader parameters)
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool HairGradientEnabled = false;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public Color HairGradientSecondaryColor = Color.White;
|
||||
|
||||
/// <summary>
|
||||
/// 0 = bottom->top, 1 = top->bottom, 2 = left->right, 3 = right->left
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public int HairGradientDirection = 0;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool FacialHairGradientEnabled = false;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public Color FacialHairGradientSecondaryColor = Color.White;
|
||||
|
||||
/// <summary>
|
||||
/// 0 = bottom->top, 1 = top->bottom, 2 = left->right, 3 = right->left
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public int FacialHairGradientDirection = 0; //Sunrise end
|
||||
|
||||
// Sunrise start Global gradient for all markings (except skin/base layers)
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool AllMarkingsGradientEnabled = false;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public Color AllMarkingsGradientSecondaryColor = Color.White;
|
||||
|
||||
/// <summary>
|
||||
/// 0 = bottom->top, 1 = top->bottom, 2 = left->right, 3 = right->left
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public int AllMarkingsGradientDirection = 0;
|
||||
// Sunrise end
|
||||
}
|
||||
|
||||
[DataDefinition]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System.Linq;
|
||||
using Content.Shared._Sunrise.MarkingEffects;
|
||||
using System.Numerics;
|
||||
using Content.Shared.Humanoid.Markings;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
|
|
@ -25,22 +24,6 @@ public sealed partial class HumanoidCharacterAppearance : ICharacterAppearance,
|
|||
[DataField]
|
||||
public Color FacialHairColor { get; set; } = Color.Black;
|
||||
|
||||
// sunrise gradient edit start
|
||||
|
||||
[DataField]
|
||||
public MarkingEffectType HairMarkingEffectType { get; set; } = MarkingEffectType.Color;
|
||||
|
||||
[DataField]
|
||||
public MarkingEffect? HairMarkingEffect { get; set; }
|
||||
|
||||
[DataField]
|
||||
public MarkingEffectType FacialHairMarkingEffectType { get; set; } = MarkingEffectType.Color;
|
||||
|
||||
[DataField]
|
||||
public MarkingEffect? FacialHairMarkingEffect { get; set; }
|
||||
|
||||
// sunrise gradient edit end
|
||||
|
||||
[DataField]
|
||||
public Color EyeColor { get; set; } = Color.Black;
|
||||
|
||||
|
|
@ -50,6 +33,45 @@ public sealed partial class HumanoidCharacterAppearance : ICharacterAppearance,
|
|||
[DataField]
|
||||
public List<Marking> Markings { get; set; } = new();
|
||||
|
||||
//Sunrise start Hair/Fur gradient settings
|
||||
[DataField]
|
||||
public bool HairGradientEnabled { get; set; } = false;
|
||||
|
||||
[DataField]
|
||||
public Color HairGradientSecondaryColor { get; set; } = Color.White;
|
||||
|
||||
/// <summary>
|
||||
/// 0 = bottom->top, 1 = top->bottom, 2 = left->right, 3 = right->left
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int HairGradientDirection { get; set; } = 0;
|
||||
|
||||
[DataField]
|
||||
public bool FacialHairGradientEnabled { get; set; } = false;
|
||||
|
||||
[DataField]
|
||||
public Color FacialHairGradientSecondaryColor { get; set; } = Color.White;
|
||||
|
||||
/// <summary>
|
||||
/// 0 = bottom->top, 1 = top->bottom, 2 = left->right, 3 = right->left
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int FacialHairGradientDirection { get; set; } = 0; //Sunrise end
|
||||
|
||||
// Sunrise start Global gradient for all markings (except skin)
|
||||
[DataField]
|
||||
public bool AllMarkingsGradientEnabled { get; set; } = false;
|
||||
|
||||
[DataField]
|
||||
public Color AllMarkingsGradientSecondaryColor { get; set; } = Color.White;
|
||||
|
||||
/// <summary>
|
||||
/// 0 = bottom->top, 1 = top->bottom, 2 = left->right, 3 = right->left
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int AllMarkingsGradientDirection { get; set; } = 0;
|
||||
// Sunrise end
|
||||
|
||||
[DataField]
|
||||
public float Width { get; set; } = 1f; //Sunrise
|
||||
|
||||
|
|
@ -63,12 +85,6 @@ public sealed partial class HumanoidCharacterAppearance : ICharacterAppearance,
|
|||
Color eyeColor,
|
||||
Color skinColor,
|
||||
List<Marking> markings,
|
||||
//sunrise gradient start
|
||||
MarkingEffectType hairMarkingEffectType,
|
||||
MarkingEffect? hairMarkingEffect,
|
||||
MarkingEffectType facialHairMarkingEffectType,
|
||||
MarkingEffect? facialHairMarkingEffect,
|
||||
//sunrise gradient end
|
||||
float width, //Sunrise
|
||||
float height) //Sunrise
|
||||
{
|
||||
|
|
@ -79,89 +95,313 @@ public sealed partial class HumanoidCharacterAppearance : ICharacterAppearance,
|
|||
EyeColor = ClampColor(eyeColor);
|
||||
SkinColor = ClampColor(skinColor);
|
||||
Markings = markings;
|
||||
//sunrise gradient start
|
||||
HairMarkingEffectType = hairMarkingEffectType;
|
||||
HairMarkingEffect = hairMarkingEffect;
|
||||
FacialHairMarkingEffectType = facialHairMarkingEffectType;
|
||||
FacialHairMarkingEffect = facialHairMarkingEffect;
|
||||
Width = width; //Sunrise
|
||||
Height = height; //Sunrise
|
||||
//sunrise gradient end
|
||||
}
|
||||
|
||||
public HumanoidCharacterAppearance(HumanoidCharacterAppearance other) :
|
||||
this(other.HairStyleId,
|
||||
other.HairColor,
|
||||
other.FacialHairStyleId,
|
||||
other.FacialHairColor,
|
||||
other.EyeColor,
|
||||
other.SkinColor,
|
||||
new(other.Markings),
|
||||
other.HairMarkingEffectType,
|
||||
other.HairMarkingEffect,
|
||||
other.FacialHairMarkingEffectType,
|
||||
other.FacialHairMarkingEffect,
|
||||
other.Width,
|
||||
other.Height) // sunrise gradient edit
|
||||
this(other.HairStyleId, other.HairColor, other.FacialHairStyleId, other.FacialHairColor, other.EyeColor, other.SkinColor, new(other.Markings), other.Width, other.Height)
|
||||
{
|
||||
|
||||
HairGradientEnabled = other.HairGradientEnabled; //Sunrise start
|
||||
HairGradientSecondaryColor = ClampColor(other.HairGradientSecondaryColor);
|
||||
HairGradientDirection = other.HairGradientDirection;
|
||||
FacialHairGradientEnabled = other.FacialHairGradientEnabled;
|
||||
FacialHairGradientSecondaryColor = ClampColor(other.FacialHairGradientSecondaryColor);
|
||||
FacialHairGradientDirection = other.FacialHairGradientDirection;
|
||||
AllMarkingsGradientEnabled = other.AllMarkingsGradientEnabled;
|
||||
AllMarkingsGradientSecondaryColor = ClampColor(other.AllMarkingsGradientSecondaryColor);
|
||||
AllMarkingsGradientDirection = other.AllMarkingsGradientDirection; //Sunrise end
|
||||
}
|
||||
|
||||
public HumanoidCharacterAppearance WithHairStyleName(string newName)
|
||||
{
|
||||
return new(newName, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings, HairMarkingEffectType, HairMarkingEffect, FacialHairMarkingEffectType, FacialHairMarkingEffect, Width, Height); // sunrise gradient edit
|
||||
return new(newName, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings, Width, Height) //Sunrise start
|
||||
{
|
||||
HairGradientEnabled = HairGradientEnabled,
|
||||
HairGradientSecondaryColor = HairGradientSecondaryColor,
|
||||
HairGradientDirection = HairGradientDirection,
|
||||
FacialHairGradientEnabled = FacialHairGradientEnabled,
|
||||
FacialHairGradientSecondaryColor = FacialHairGradientSecondaryColor,
|
||||
FacialHairGradientDirection = FacialHairGradientDirection,
|
||||
AllMarkingsGradientEnabled = AllMarkingsGradientEnabled,
|
||||
AllMarkingsGradientSecondaryColor = AllMarkingsGradientSecondaryColor,
|
||||
AllMarkingsGradientDirection = AllMarkingsGradientDirection
|
||||
}; //Sunrise end
|
||||
}
|
||||
|
||||
public HumanoidCharacterAppearance WithHairColor(Color newColor, MarkingEffect? newExtendedColor = null)
|
||||
public HumanoidCharacterAppearance WithHairColor(Color newColor)
|
||||
{
|
||||
return new(HairStyleId, newColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings, newExtendedColor?.Type ?? HairMarkingEffectType, newExtendedColor ?? HairMarkingEffect, FacialHairMarkingEffectType, FacialHairMarkingEffect, Width, Height); // sunrise gradient edit
|
||||
return new(HairStyleId, newColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings, Width, Height) //Sunrise start
|
||||
{
|
||||
HairGradientEnabled = HairGradientEnabled,
|
||||
HairGradientSecondaryColor = HairGradientSecondaryColor,
|
||||
HairGradientDirection = HairGradientDirection,
|
||||
FacialHairGradientEnabled = FacialHairGradientEnabled,
|
||||
FacialHairGradientSecondaryColor = FacialHairGradientSecondaryColor,
|
||||
FacialHairGradientDirection = FacialHairGradientDirection,
|
||||
AllMarkingsGradientEnabled = AllMarkingsGradientEnabled,
|
||||
AllMarkingsGradientSecondaryColor = AllMarkingsGradientSecondaryColor,
|
||||
AllMarkingsGradientDirection = AllMarkingsGradientDirection
|
||||
}; //Sunrise end
|
||||
}
|
||||
|
||||
public HumanoidCharacterAppearance WithFacialHairStyleName(string newName)
|
||||
{
|
||||
return new(HairStyleId, HairColor, newName, FacialHairColor, EyeColor, SkinColor, Markings, HairMarkingEffectType, HairMarkingEffect, FacialHairMarkingEffectType, FacialHairMarkingEffect, Width, Height);
|
||||
return new(HairStyleId, HairColor, newName, FacialHairColor, EyeColor, SkinColor, Markings, Width, Height) //Sunrise start
|
||||
{
|
||||
HairGradientEnabled = HairGradientEnabled,
|
||||
HairGradientSecondaryColor = HairGradientSecondaryColor,
|
||||
HairGradientDirection = HairGradientDirection,
|
||||
FacialHairGradientEnabled = FacialHairGradientEnabled,
|
||||
FacialHairGradientSecondaryColor = FacialHairGradientSecondaryColor,
|
||||
FacialHairGradientDirection = FacialHairGradientDirection,
|
||||
AllMarkingsGradientEnabled = AllMarkingsGradientEnabled,
|
||||
AllMarkingsGradientSecondaryColor = AllMarkingsGradientSecondaryColor,
|
||||
AllMarkingsGradientDirection = AllMarkingsGradientDirection
|
||||
}; //Sunrise end
|
||||
}
|
||||
|
||||
public HumanoidCharacterAppearance WithFacialHairColor(Color newColor, MarkingEffect? newFacialExtendedColor = null)
|
||||
public HumanoidCharacterAppearance WithFacialHairColor(Color newColor)
|
||||
{
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, newColor, EyeColor, SkinColor, Markings, HairMarkingEffectType, HairMarkingEffect, newFacialExtendedColor?.Type ?? FacialHairMarkingEffectType, newFacialExtendedColor ?? FacialHairMarkingEffect, Width, Height); // sunrise gradient edit
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, newColor, EyeColor, SkinColor, Markings, Width, Height) //Sunrise start
|
||||
{
|
||||
HairGradientEnabled = HairGradientEnabled,
|
||||
HairGradientSecondaryColor = HairGradientSecondaryColor,
|
||||
HairGradientDirection = HairGradientDirection,
|
||||
FacialHairGradientEnabled = FacialHairGradientEnabled,
|
||||
FacialHairGradientSecondaryColor = FacialHairGradientSecondaryColor,
|
||||
FacialHairGradientDirection = FacialHairGradientDirection,
|
||||
AllMarkingsGradientEnabled = AllMarkingsGradientEnabled,
|
||||
AllMarkingsGradientSecondaryColor = AllMarkingsGradientSecondaryColor,
|
||||
AllMarkingsGradientDirection = AllMarkingsGradientDirection
|
||||
}; //Sunrise end
|
||||
}
|
||||
|
||||
public HumanoidCharacterAppearance WithEyeColor(Color newColor)
|
||||
{
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, newColor, SkinColor, Markings, HairMarkingEffectType, HairMarkingEffect, FacialHairMarkingEffectType, FacialHairMarkingEffect, Width, Height); // sunrise gradient edit
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, newColor, SkinColor, Markings, Width, Height) //Sunrise start
|
||||
{
|
||||
HairGradientEnabled = HairGradientEnabled,
|
||||
HairGradientSecondaryColor = HairGradientSecondaryColor,
|
||||
HairGradientDirection = HairGradientDirection,
|
||||
FacialHairGradientEnabled = FacialHairGradientEnabled,
|
||||
FacialHairGradientSecondaryColor = FacialHairGradientSecondaryColor,
|
||||
FacialHairGradientDirection = FacialHairGradientDirection,
|
||||
AllMarkingsGradientEnabled = AllMarkingsGradientEnabled,
|
||||
AllMarkingsGradientSecondaryColor = AllMarkingsGradientSecondaryColor,
|
||||
AllMarkingsGradientDirection = AllMarkingsGradientDirection
|
||||
}; //Sunrise end
|
||||
}
|
||||
|
||||
public HumanoidCharacterAppearance WithSkinColor(Color newColor)
|
||||
{
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, newColor, Markings, HairMarkingEffectType, HairMarkingEffect, FacialHairMarkingEffectType, FacialHairMarkingEffect, Width, Height); // sunrise gradient edit
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, newColor, Markings, Width, Height) //Sunrise start
|
||||
{
|
||||
HairGradientEnabled = HairGradientEnabled,
|
||||
HairGradientSecondaryColor = HairGradientSecondaryColor,
|
||||
HairGradientDirection = HairGradientDirection,
|
||||
FacialHairGradientEnabled = FacialHairGradientEnabled,
|
||||
FacialHairGradientSecondaryColor = FacialHairGradientSecondaryColor,
|
||||
FacialHairGradientDirection = FacialHairGradientDirection,
|
||||
AllMarkingsGradientEnabled = AllMarkingsGradientEnabled,
|
||||
AllMarkingsGradientSecondaryColor = AllMarkingsGradientSecondaryColor,
|
||||
AllMarkingsGradientDirection = AllMarkingsGradientDirection
|
||||
}; //Sunrise end
|
||||
}
|
||||
|
||||
public HumanoidCharacterAppearance WithMarkings(List<Marking> newMarkings)
|
||||
{
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, newMarkings, HairMarkingEffectType, HairMarkingEffect, FacialHairMarkingEffectType, FacialHairMarkingEffect, Width, Height); // sunrise gradient edit
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, newMarkings, Width, Height) //Sunrise start
|
||||
{
|
||||
HairGradientEnabled = HairGradientEnabled,
|
||||
HairGradientSecondaryColor = HairGradientSecondaryColor,
|
||||
HairGradientDirection = HairGradientDirection,
|
||||
FacialHairGradientEnabled = FacialHairGradientEnabled,
|
||||
FacialHairGradientSecondaryColor = FacialHairGradientSecondaryColor,
|
||||
FacialHairGradientDirection = FacialHairGradientDirection,
|
||||
AllMarkingsGradientEnabled = AllMarkingsGradientEnabled,
|
||||
AllMarkingsGradientSecondaryColor = AllMarkingsGradientSecondaryColor,
|
||||
AllMarkingsGradientDirection = AllMarkingsGradientDirection
|
||||
}; //Sunrise end
|
||||
}
|
||||
|
||||
// sunrise gradient edit start
|
||||
public HumanoidCharacterAppearance WithHairExtendedColor(MarkingEffect? newExtendedColor)
|
||||
//Sunrise start Hair gradient methods
|
||||
public HumanoidCharacterAppearance WithHairGradientEnabled(bool enabled)
|
||||
{
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings, newExtendedColor?.Type ?? MarkingEffectType.Color, newExtendedColor, FacialHairMarkingEffectType, FacialHairMarkingEffect, Width, Height); // sunrise gradient edit
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings, Width, Height)
|
||||
{
|
||||
HairGradientEnabled = enabled,
|
||||
HairGradientSecondaryColor = HairGradientSecondaryColor,
|
||||
HairGradientDirection = HairGradientDirection,
|
||||
FacialHairGradientEnabled = FacialHairGradientEnabled,
|
||||
FacialHairGradientSecondaryColor = FacialHairGradientSecondaryColor,
|
||||
FacialHairGradientDirection = FacialHairGradientDirection,
|
||||
AllMarkingsGradientEnabled = AllMarkingsGradientEnabled,
|
||||
AllMarkingsGradientSecondaryColor = AllMarkingsGradientSecondaryColor,
|
||||
AllMarkingsGradientDirection = AllMarkingsGradientDirection
|
||||
};
|
||||
}
|
||||
public HumanoidCharacterAppearance WithFacialHairExtendedColor(MarkingEffect? newFacialExtendedColor)
|
||||
|
||||
public HumanoidCharacterAppearance WithHairGradientSecondaryColor(Color color)
|
||||
{
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings, HairMarkingEffectType, HairMarkingEffect, newFacialExtendedColor?.Type ?? MarkingEffectType.Color, newFacialExtendedColor, Width, Height); // sunrise gradient edit
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings, Width, Height)
|
||||
{
|
||||
HairGradientEnabled = HairGradientEnabled,
|
||||
HairGradientSecondaryColor = ClampColor(color),
|
||||
HairGradientDirection = HairGradientDirection,
|
||||
FacialHairGradientEnabled = FacialHairGradientEnabled,
|
||||
FacialHairGradientSecondaryColor = FacialHairGradientSecondaryColor,
|
||||
FacialHairGradientDirection = FacialHairGradientDirection,
|
||||
AllMarkingsGradientEnabled = AllMarkingsGradientEnabled,
|
||||
AllMarkingsGradientSecondaryColor = AllMarkingsGradientSecondaryColor,
|
||||
AllMarkingsGradientDirection = AllMarkingsGradientDirection
|
||||
};
|
||||
}
|
||||
|
||||
public HumanoidCharacterAppearance WithHairGradientDirection(int direction)
|
||||
{
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings, Width, Height)
|
||||
{
|
||||
HairGradientEnabled = HairGradientEnabled,
|
||||
HairGradientSecondaryColor = HairGradientSecondaryColor,
|
||||
HairGradientDirection = direction,
|
||||
FacialHairGradientEnabled = FacialHairGradientEnabled,
|
||||
FacialHairGradientSecondaryColor = FacialHairGradientSecondaryColor,
|
||||
FacialHairGradientDirection = FacialHairGradientDirection,
|
||||
AllMarkingsGradientEnabled = AllMarkingsGradientEnabled,
|
||||
AllMarkingsGradientSecondaryColor = AllMarkingsGradientSecondaryColor,
|
||||
AllMarkingsGradientDirection = AllMarkingsGradientDirection
|
||||
};
|
||||
}
|
||||
|
||||
public HumanoidCharacterAppearance WithFacialHairGradientEnabled(bool enabled)
|
||||
{
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings, Width, Height)
|
||||
{
|
||||
HairGradientEnabled = HairGradientEnabled,
|
||||
HairGradientSecondaryColor = HairGradientSecondaryColor,
|
||||
HairGradientDirection = HairGradientDirection,
|
||||
FacialHairGradientEnabled = enabled,
|
||||
FacialHairGradientSecondaryColor = FacialHairGradientSecondaryColor,
|
||||
FacialHairGradientDirection = FacialHairGradientDirection,
|
||||
AllMarkingsGradientEnabled = AllMarkingsGradientEnabled,
|
||||
AllMarkingsGradientSecondaryColor = AllMarkingsGradientSecondaryColor,
|
||||
AllMarkingsGradientDirection = AllMarkingsGradientDirection
|
||||
};
|
||||
}
|
||||
|
||||
public HumanoidCharacterAppearance WithFacialHairGradientSecondaryColor(Color color)
|
||||
{
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings, Width, Height)
|
||||
{
|
||||
HairGradientEnabled = HairGradientEnabled,
|
||||
HairGradientSecondaryColor = HairGradientSecondaryColor,
|
||||
HairGradientDirection = HairGradientDirection,
|
||||
FacialHairGradientEnabled = FacialHairGradientEnabled,
|
||||
FacialHairGradientSecondaryColor = ClampColor(color),
|
||||
FacialHairGradientDirection = FacialHairGradientDirection,
|
||||
AllMarkingsGradientEnabled = AllMarkingsGradientEnabled,
|
||||
AllMarkingsGradientSecondaryColor = AllMarkingsGradientSecondaryColor,
|
||||
AllMarkingsGradientDirection = AllMarkingsGradientDirection
|
||||
};
|
||||
}
|
||||
|
||||
public HumanoidCharacterAppearance WithFacialHairGradientDirection(int direction)
|
||||
{
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings, Width, Height)
|
||||
{
|
||||
HairGradientEnabled = HairGradientEnabled,
|
||||
HairGradientSecondaryColor = HairGradientSecondaryColor,
|
||||
HairGradientDirection = HairGradientDirection,
|
||||
FacialHairGradientEnabled = FacialHairGradientEnabled,
|
||||
FacialHairGradientSecondaryColor = FacialHairGradientSecondaryColor,
|
||||
FacialHairGradientDirection = direction,
|
||||
AllMarkingsGradientEnabled = AllMarkingsGradientEnabled,
|
||||
AllMarkingsGradientSecondaryColor = AllMarkingsGradientSecondaryColor,
|
||||
AllMarkingsGradientDirection = AllMarkingsGradientDirection
|
||||
};
|
||||
}
|
||||
|
||||
public HumanoidCharacterAppearance WithAllMarkingsGradientEnabled(bool enabled)
|
||||
{
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings, Width, Height)
|
||||
{
|
||||
HairGradientEnabled = HairGradientEnabled,
|
||||
HairGradientSecondaryColor = HairGradientSecondaryColor,
|
||||
HairGradientDirection = HairGradientDirection,
|
||||
FacialHairGradientEnabled = FacialHairGradientEnabled,
|
||||
FacialHairGradientSecondaryColor = FacialHairGradientSecondaryColor,
|
||||
FacialHairGradientDirection = FacialHairGradientDirection,
|
||||
AllMarkingsGradientEnabled = enabled,
|
||||
AllMarkingsGradientSecondaryColor = AllMarkingsGradientSecondaryColor,
|
||||
AllMarkingsGradientDirection = AllMarkingsGradientDirection
|
||||
};
|
||||
}
|
||||
|
||||
public HumanoidCharacterAppearance WithAllMarkingsGradientSecondaryColor(Color color)
|
||||
{
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings, Width, Height)
|
||||
{
|
||||
HairGradientEnabled = HairGradientEnabled,
|
||||
HairGradientSecondaryColor = HairGradientSecondaryColor,
|
||||
HairGradientDirection = HairGradientDirection,
|
||||
FacialHairGradientEnabled = FacialHairGradientEnabled,
|
||||
FacialHairGradientSecondaryColor = FacialHairGradientSecondaryColor,
|
||||
FacialHairGradientDirection = FacialHairGradientDirection,
|
||||
AllMarkingsGradientEnabled = AllMarkingsGradientEnabled,
|
||||
AllMarkingsGradientSecondaryColor = ClampColor(color),
|
||||
AllMarkingsGradientDirection = AllMarkingsGradientDirection
|
||||
};
|
||||
}
|
||||
|
||||
public HumanoidCharacterAppearance WithAllMarkingsGradientDirection(int direction)
|
||||
{
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings, Width, Height)
|
||||
{
|
||||
HairGradientEnabled = HairGradientEnabled,
|
||||
HairGradientSecondaryColor = HairGradientSecondaryColor,
|
||||
HairGradientDirection = HairGradientDirection,
|
||||
FacialHairGradientEnabled = FacialHairGradientEnabled,
|
||||
FacialHairGradientSecondaryColor = FacialHairGradientSecondaryColor,
|
||||
FacialHairGradientDirection = FacialHairGradientDirection,
|
||||
AllMarkingsGradientEnabled = AllMarkingsGradientEnabled,
|
||||
AllMarkingsGradientSecondaryColor = AllMarkingsGradientSecondaryColor,
|
||||
AllMarkingsGradientDirection = direction
|
||||
};
|
||||
}
|
||||
// sunrise gradient edit end
|
||||
|
||||
public HumanoidCharacterAppearance WithWidth(float newWidth)
|
||||
{
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings, HairMarkingEffectType, HairMarkingEffect, FacialHairMarkingEffectType, FacialHairMarkingEffect, newWidth, Height);
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings, newWidth, Height)
|
||||
{
|
||||
HairGradientEnabled = HairGradientEnabled,
|
||||
HairGradientSecondaryColor = HairGradientSecondaryColor,
|
||||
HairGradientDirection = HairGradientDirection,
|
||||
FacialHairGradientEnabled = FacialHairGradientEnabled,
|
||||
FacialHairGradientSecondaryColor = FacialHairGradientSecondaryColor,
|
||||
FacialHairGradientDirection = FacialHairGradientDirection,
|
||||
AllMarkingsGradientEnabled = AllMarkingsGradientEnabled,
|
||||
AllMarkingsGradientSecondaryColor = AllMarkingsGradientSecondaryColor,
|
||||
AllMarkingsGradientDirection = AllMarkingsGradientDirection
|
||||
};
|
||||
}
|
||||
|
||||
public HumanoidCharacterAppearance WithHeight(float newHeight)
|
||||
{
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings, HairMarkingEffectType, HairMarkingEffect, FacialHairMarkingEffectType, FacialHairMarkingEffect, Width, newHeight);
|
||||
return new(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings, Width, newHeight)
|
||||
{
|
||||
HairGradientEnabled = HairGradientEnabled,
|
||||
HairGradientSecondaryColor = HairGradientSecondaryColor,
|
||||
HairGradientDirection = HairGradientDirection,
|
||||
FacialHairGradientEnabled = FacialHairGradientEnabled,
|
||||
FacialHairGradientSecondaryColor = FacialHairGradientSecondaryColor,
|
||||
FacialHairGradientDirection = FacialHairGradientDirection,
|
||||
AllMarkingsGradientEnabled = AllMarkingsGradientEnabled,
|
||||
AllMarkingsGradientSecondaryColor = AllMarkingsGradientSecondaryColor,
|
||||
AllMarkingsGradientDirection = AllMarkingsGradientDirection
|
||||
};
|
||||
}
|
||||
//Sunrise end
|
||||
|
||||
public static HumanoidCharacterAppearance DefaultWithSpecies(string species)
|
||||
{
|
||||
|
|
@ -185,12 +425,6 @@ public sealed partial class HumanoidCharacterAppearance : ICharacterAppearance,
|
|||
Color.Black,
|
||||
skinColor,
|
||||
new (),
|
||||
// sunrise gradient edit start
|
||||
MarkingEffectType.Color,
|
||||
null,
|
||||
MarkingEffectType.Color,
|
||||
null,
|
||||
// sunrise gradient edit end
|
||||
speciesPrototype.DefaultWidth, //Sunrise
|
||||
speciesPrototype.DefaultHeight //Sunrise
|
||||
);
|
||||
|
|
@ -209,40 +443,76 @@ public sealed partial class HumanoidCharacterAppearance : ICharacterAppearance,
|
|||
{
|
||||
var random = IoCManager.Resolve<IRobustRandom>();
|
||||
var markingManager = IoCManager.Resolve<MarkingManager>();
|
||||
var hairStyles = markingManager.MarkingsByCategoryAndSpecies(MarkingCategories.Hair, species).Keys.ToList();
|
||||
var facialHairStyles = markingManager.MarkingsByCategoryAndSpecies(MarkingCategories.FacialHair, species).Keys.ToList();
|
||||
|
||||
var newHairStyle = hairStyles.Count > 0
|
||||
? random.Pick(hairStyles)
|
||||
: HairStyles.DefaultHairStyle.Id;
|
||||
var newFacialHairStyle = HairStyles.DefaultFacialHairStyle;
|
||||
var newHairStyle = HairStyles.DefaultHairStyle;
|
||||
List<Marking> newMarkings = [];
|
||||
|
||||
var newFacialHairStyle = facialHairStyles.Count == 0 || sex == Sex.Female
|
||||
? HairStyles.DefaultFacialHairStyle.Id
|
||||
: random.Pick(facialHairStyles);
|
||||
// grab a completely random color.
|
||||
var baseColor = new Color(random.NextFloat(1), random.NextFloat(1), random.NextFloat(1), 1);
|
||||
|
||||
var newHairColor = random.Pick(HairStyles.RealisticHairColors);
|
||||
newHairColor = newHairColor
|
||||
.WithRed(RandomizeColor(newHairColor.R))
|
||||
.WithGreen(RandomizeColor(newHairColor.G))
|
||||
.WithBlue(RandomizeColor(newHairColor.B));
|
||||
|
||||
// TODO: Add random markings
|
||||
|
||||
var newEyeColor = random.Pick(RealisticEyeColors);
|
||||
// create a new color palette based on BaseColor. roll to determine what type of palette it is.
|
||||
// personally I think this should be weighted, but I can't be bothered to implement that.
|
||||
List<Color> colorPalette = [];
|
||||
switch (random.Next(3))
|
||||
{
|
||||
case 0:
|
||||
colorPalette = GetSplitComplementaries(baseColor);
|
||||
break;
|
||||
case 1:
|
||||
colorPalette = GetTriadicComplementaries(baseColor);
|
||||
break;
|
||||
case 2:
|
||||
colorPalette = GetOneComplementary(baseColor);
|
||||
break;
|
||||
}
|
||||
|
||||
// grab the species skin coloration type.
|
||||
var skinType = IoCManager.Resolve<IPrototypeManager>().Index<SpeciesPrototype>(species).SkinColoration;
|
||||
|
||||
var newSkinColor = new Color(random.NextFloat(1), random.NextFloat(1), random.NextFloat(1), 1);
|
||||
// declare some defaults. ensures that the hair and eyes on hues-colored species don't match the skin or one another.
|
||||
var newSkinColor = colorPalette[0];
|
||||
var newHairColor = colorPalette[1];
|
||||
var newEyeColor = colorPalette[2];
|
||||
|
||||
// now we do some color logic.
|
||||
switch (skinType)
|
||||
{
|
||||
// if the species is HumanToned:
|
||||
case HumanoidSkinColor.HumanToned:
|
||||
newSkinColor = Humanoid.SkinColor.HumanSkinTone(random.Next(0, 101));
|
||||
// quantize the randomized skin color to the nearest acceptable HumanToned color.
|
||||
var tone = Math.Round(Humanoid.SkinColor.HumanSkinToneFromColor(newSkinColor));
|
||||
newSkinColor = Humanoid.SkinColor.HumanSkinTone((int)tone);
|
||||
|
||||
// pick a random realistic hair color from the list and randomize it juuuuust a little bit.
|
||||
newHairColor = random.Pick(HairStyles.RealisticHairColors);
|
||||
newHairColor = newHairColor
|
||||
.WithRed(RandomizeColor(newHairColor.R))
|
||||
.WithGreen(RandomizeColor(newHairColor.G))
|
||||
.WithBlue(RandomizeColor(newHairColor.B));
|
||||
|
||||
// and pick a random realistic eye color from the list.
|
||||
newEyeColor = random.Pick(RealisticEyeColors);
|
||||
|
||||
// we're also going to crush the other colors down to the skin's luminosity so markings don't appear too bright on darker skin.
|
||||
colorPalette[1] = SquashToSkinLuminosity(newSkinColor, colorPalette[1]);
|
||||
colorPalette[2] = SquashToSkinLuminosity(newSkinColor, colorPalette[2]);
|
||||
break;
|
||||
|
||||
// if the species is Hues toned: it's fine the way it is.
|
||||
case HumanoidSkinColor.Hues:
|
||||
break;
|
||||
|
||||
// if the species is TintedHues toned: tint them hues.
|
||||
case HumanoidSkinColor.TintedHues:
|
||||
newSkinColor = Humanoid.SkinColor.ValidTintedHuesSkinTone(newSkinColor);
|
||||
|
||||
// we're also going to crush the other colors down to valid TintedHues skin colors.
|
||||
colorPalette[1] = Humanoid.SkinColor.ValidTintedHuesSkinTone(colorPalette[1]);
|
||||
colorPalette[2] = Humanoid.SkinColor.ValidTintedHuesSkinTone(colorPalette[2]);
|
||||
break;
|
||||
|
||||
// if the species is VoxFeathers toned: confine the skin color to vox limits. Bright colors are otherwise fine, so leave the marking colors alone.
|
||||
case HumanoidSkinColor.VoxFeathers:
|
||||
newSkinColor = Humanoid.SkinColor.ProportionalVoxColor(newSkinColor);
|
||||
break;
|
||||
|
|
@ -251,18 +521,151 @@ public sealed partial class HumanoidCharacterAppearance : ICharacterAppearance,
|
|||
break;
|
||||
}
|
||||
|
||||
// now we loop through every extant marking category,
|
||||
foreach (var category in Enum.GetValues<MarkingCategories>())
|
||||
{
|
||||
// grab a list of markings in that category for that species,
|
||||
var markings = markingManager.MarkingsByCategoryAndSpecies(category, species).Keys.ToList();
|
||||
var markingProtos = markingManager.MarkingsByCategoryAndSpecies(category, species).Values.ToList();
|
||||
|
||||
// if it's facial hair, there are entries in the category, and the character is not female, assign a random one. else bald
|
||||
if (category == MarkingCategories.FacialHair)
|
||||
{
|
||||
newFacialHairStyle = markings.Count == 0 || sex == Sex.Female ? HairStyles.DefaultFacialHairStyle : random.Pick(markings);
|
||||
}
|
||||
|
||||
// if it's hair, and there are hair styles, roll one. else bald
|
||||
else if (category == MarkingCategories.Hair)
|
||||
{
|
||||
newHairStyle = markings.Count > 0 ? random.Pick(markings) : HairStyles.DefaultHairStyle;
|
||||
}
|
||||
|
||||
// for every other category,
|
||||
else if (markings.Count > 0)
|
||||
{
|
||||
// roll a die. currently a 1 in 3 chance per category, except Tails, which are 1 in 2 (because of the effect they have on the silhouettes of spiders and moths.)
|
||||
int diceRoll;
|
||||
if (category == MarkingCategories.Tail)
|
||||
diceRoll = random.Next(2);
|
||||
else
|
||||
diceRoll = random.Next(3);
|
||||
|
||||
if (diceRoll == 0)
|
||||
{
|
||||
MarkingPrototype? lastMarking = null;
|
||||
|
||||
// roll to see how many markings from that category will be added. currently a maximum of 2.
|
||||
var loops = random.Next(2) + 1;
|
||||
|
||||
// add a marking (loops) times
|
||||
for (var i = 0; i < loops; i++)
|
||||
{
|
||||
// pick a random marking from the list
|
||||
var protoToAdd = random.Pick(markingProtos);
|
||||
var markingToAdd = protoToAdd.AsMarking();
|
||||
Color markingColor;
|
||||
|
||||
// prevent duplicates:
|
||||
if (lastMarking != null && lastMarking == protoToAdd)
|
||||
continue;
|
||||
|
||||
// set gauze to white.
|
||||
// side note, I really hate that gauze isn't its own category. please fix that so that i can make this not suck as much.
|
||||
// or, like, give it its own color rules. or something.
|
||||
if (markingToAdd.MarkingId.Contains("gauze", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
markingToAdd.SetColor(Color.White);
|
||||
newMarkings.Add(markingToAdd);
|
||||
lastMarking = protoToAdd;
|
||||
continue;
|
||||
}
|
||||
|
||||
// select a random color from our two secondary colors. if our marking is a Tail, add the skin color as well, otherwise lizards always look a little odd.
|
||||
// this will also make moths and spiders look less interesting on average, but I don't want a hardcoded exception for lizards.
|
||||
if (category == MarkingCategories.Tail)
|
||||
markingColor = random.Pick(colorPalette);
|
||||
else
|
||||
markingColor = random.Pick(colorPalette.Skip(0).ToList());
|
||||
|
||||
// set the marking to that color
|
||||
markingToAdd.SetColor(markingColor);
|
||||
|
||||
// otherwise, add it to the final list.
|
||||
newMarkings.Add(markingToAdd);
|
||||
lastMarking = protoToAdd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Sunrise start
|
||||
var speciesPrototype = IoCManager.Resolve<IPrototypeManager>().Index<SpeciesPrototype>(species);
|
||||
var newWidth = random.NextFloat(speciesPrototype.MinWidth, speciesPrototype.MaxWidth);
|
||||
var newHeight = random.NextFloat(speciesPrototype.MinHeight, speciesPrototype.MaxHeight);
|
||||
//Sunrise end
|
||||
|
||||
return new HumanoidCharacterAppearance(newHairStyle, newHairColor, newFacialHairStyle, newHairColor, newEyeColor, newSkinColor, new (), MarkingEffectType.Color, null, MarkingEffectType.Color, null, newWidth, newHeight);
|
||||
// at the end of all that, we should have new values for each of these, so we set the character appearance to these new values.
|
||||
return new HumanoidCharacterAppearance(newHairStyle, newHairColor, newFacialHairStyle, newHairColor, newEyeColor, newSkinColor, newMarkings, newWidth, newHeight); // Sunrise edit
|
||||
|
||||
// helper functions:
|
||||
float RandomizeColor(float channel)
|
||||
{
|
||||
return MathHelper.Clamp01(channel + random.Next(-25, 25) / 100f);
|
||||
}
|
||||
|
||||
List<Color> GetComplementaryColors(Color color, double angle)
|
||||
{
|
||||
var hsl = Color.ToHsl(color);
|
||||
|
||||
var hVal = hsl.X + angle;
|
||||
hVal = hVal >= 0.360 ? hVal - 0.360 : hVal;
|
||||
var positiveHSL = new Vector4((float)hVal, hsl.Y, hsl.Z, hsl.W);
|
||||
|
||||
var hVal1 = hsl.X - angle;
|
||||
hVal1 = hVal1 <= 0 ? hVal1 + 0.360 : hVal1;
|
||||
var negativeHSL = new Vector4((float)hVal1, hsl.Y, hsl.Z, hsl.W);
|
||||
|
||||
var c0 = Color.FromHsl(positiveHSL);
|
||||
var c1 = Color.FromHsl(negativeHSL);
|
||||
|
||||
var palette = new List<Color> { color, c0, c1 };
|
||||
return palette;
|
||||
}
|
||||
|
||||
// return a list of triadic complementary colors
|
||||
List<Color> GetTriadicComplementaries(Color color)
|
||||
{
|
||||
return GetComplementaryColors(color, 0.120);
|
||||
}
|
||||
|
||||
// return a list of split complementary colors
|
||||
List<Color> GetSplitComplementaries(Color color)
|
||||
{
|
||||
return GetComplementaryColors(color, 0.150);
|
||||
}
|
||||
|
||||
// return a list containing the base color and two copies of a single complemenary color
|
||||
List<Color> GetOneComplementary(Color color)
|
||||
{
|
||||
return GetComplementaryColors(color, 0.180);
|
||||
}
|
||||
|
||||
Color SquashToSkinLuminosity(Color skinColor, Color toSquash)
|
||||
{
|
||||
var skinColorHSL = Color.ToHsl(skinColor);
|
||||
var toSquashHSL = Color.ToHsl(toSquash);
|
||||
|
||||
// check if the skin color is as dark as or darker than the marking color:
|
||||
if (toSquashHSL.Z <= skinColorHSL.Z)
|
||||
{
|
||||
// if it is, don't fuck with it
|
||||
return toSquash;
|
||||
}
|
||||
|
||||
// otherwise, create a new color with the H, S, and A of toSquash, but the L of skinColor
|
||||
var newColor = new Vector4(toSquashHSL.X, toSquashHSL.Y, skinColorHSL.Z, toSquashHSL.W);
|
||||
return Color.FromHsl(newColor);
|
||||
}
|
||||
}
|
||||
|
||||
public static Color ClampColor(Color color)
|
||||
|
|
@ -333,24 +736,6 @@ public sealed partial class HumanoidCharacterAppearance : ICharacterAppearance,
|
|||
markingSet.FilterSponsor(sponsorPrototypes, markingManager); // Sunrise-Sponsors
|
||||
}
|
||||
|
||||
// sunrise gradient start
|
||||
MarkingEffect? hairExtendedColor = null;
|
||||
if (appearance.HairMarkingEffect != null)
|
||||
{
|
||||
hairExtendedColor = appearance.HairMarkingEffect;
|
||||
foreach (var (key, value) in hairExtendedColor.Colors)
|
||||
hairExtendedColor.Colors[key] = ClampColor(value);
|
||||
}
|
||||
|
||||
MarkingEffect? facialHairExtendedColor = null;
|
||||
if (appearance.FacialHairMarkingEffect != null)
|
||||
{
|
||||
facialHairExtendedColor = appearance.FacialHairMarkingEffect;
|
||||
foreach (var (key, value) in facialHairExtendedColor.Colors)
|
||||
facialHairExtendedColor.Colors[key] = ClampColor(value);
|
||||
}
|
||||
// sunrise gradient end
|
||||
|
||||
return new HumanoidCharacterAppearance(
|
||||
hairStyleId,
|
||||
hairColor,
|
||||
|
|
@ -359,13 +744,10 @@ public sealed partial class HumanoidCharacterAppearance : ICharacterAppearance,
|
|||
eyeColor,
|
||||
skinColor,
|
||||
markingSet.GetForwardEnumerator().ToList(),
|
||||
appearance.HairMarkingEffectType,
|
||||
hairExtendedColor,
|
||||
appearance.FacialHairMarkingEffectType,
|
||||
facialHairExtendedColor,
|
||||
width,
|
||||
height);
|
||||
}
|
||||
|
||||
public bool MemberwiseEquals(ICharacterAppearance maybeOther)
|
||||
{
|
||||
if (maybeOther is not HumanoidCharacterAppearance other) return false;
|
||||
|
|
@ -376,12 +758,15 @@ public sealed partial class HumanoidCharacterAppearance : ICharacterAppearance,
|
|||
if (!EyeColor.Equals(other.EyeColor)) return false;
|
||||
if (!SkinColor.Equals(other.SkinColor)) return false;
|
||||
if (!Markings.SequenceEqual(other.Markings)) return false;
|
||||
// sunrise gradient edit start
|
||||
if (!HairMarkingEffectType.Equals(other.HairMarkingEffectType)) return false;
|
||||
if (!Equals(HairMarkingEffect, other.HairMarkingEffect)) return false;
|
||||
if (!FacialHairMarkingEffectType.Equals(other.FacialHairMarkingEffectType)) return false;
|
||||
if (!Equals(FacialHairMarkingEffect, other.FacialHairMarkingEffect)) return false;
|
||||
// sunrise gradient edit end
|
||||
if (HairGradientEnabled != other.HairGradientEnabled) return false; //Sunrise start
|
||||
if (!HairGradientSecondaryColor.Equals(other.HairGradientSecondaryColor)) return false;
|
||||
if (HairGradientDirection != other.HairGradientDirection) return false;
|
||||
if (FacialHairGradientEnabled != other.FacialHairGradientEnabled) return false;
|
||||
if (!FacialHairGradientSecondaryColor.Equals(other.FacialHairGradientSecondaryColor)) return false;
|
||||
if (FacialHairGradientDirection != other.FacialHairGradientDirection) return false;
|
||||
if (AllMarkingsGradientEnabled != other.AllMarkingsGradientEnabled) return false;
|
||||
if (!AllMarkingsGradientSecondaryColor.Equals(other.AllMarkingsGradientSecondaryColor)) return false;
|
||||
if (AllMarkingsGradientDirection != other.AllMarkingsGradientDirection) return false; //Sunrise end
|
||||
if (Width != other.Width) return false; //Sunrise
|
||||
if (Height != other.Height) return false; //Sunrise
|
||||
return true;
|
||||
|
|
@ -398,11 +783,15 @@ public sealed partial class HumanoidCharacterAppearance : ICharacterAppearance,
|
|||
EyeColor.Equals(other.EyeColor) &&
|
||||
SkinColor.Equals(other.SkinColor) &&
|
||||
Markings.SequenceEqual(other.Markings) &&
|
||||
// sunrise gradient edit start
|
||||
HairMarkingEffectType.Equals(other.HairMarkingEffectType) &&
|
||||
Equals(HairMarkingEffect, other.HairMarkingEffect) &&
|
||||
FacialHairMarkingEffectType.Equals(other.FacialHairMarkingEffectType) &&
|
||||
Equals(FacialHairMarkingEffect, other.FacialHairMarkingEffect) &&
|
||||
HairGradientEnabled == other.HairGradientEnabled && //Sunrise start
|
||||
HairGradientSecondaryColor.Equals(other.HairGradientSecondaryColor) &&
|
||||
HairGradientDirection == other.HairGradientDirection &&
|
||||
FacialHairGradientEnabled == other.FacialHairGradientEnabled &&
|
||||
FacialHairGradientSecondaryColor.Equals(other.FacialHairGradientSecondaryColor) &&
|
||||
FacialHairGradientDirection == other.FacialHairGradientDirection &&
|
||||
AllMarkingsGradientEnabled == other.AllMarkingsGradientEnabled &&
|
||||
AllMarkingsGradientSecondaryColor.Equals(other.AllMarkingsGradientSecondaryColor) &&
|
||||
AllMarkingsGradientDirection == other.AllMarkingsGradientDirection && //Sunrise end
|
||||
Width == other.Width && //starlight
|
||||
Height == other.Height;
|
||||
}
|
||||
|
|
@ -414,7 +803,12 @@ public sealed partial class HumanoidCharacterAppearance : ICharacterAppearance,
|
|||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings, new Vector2(Width, Height));
|
||||
var h1 = HashCode.Combine(HairStyleId, HairColor, FacialHairStyleId, FacialHairColor, EyeColor, SkinColor, Markings); //Sunrise start
|
||||
var h2 = HashCode.Combine(HairGradientEnabled, HairGradientSecondaryColor, HairGradientDirection);
|
||||
var h3 = HashCode.Combine(FacialHairGradientEnabled, FacialHairGradientSecondaryColor, FacialHairGradientDirection);
|
||||
var h4 = HashCode.Combine(AllMarkingsGradientEnabled, AllMarkingsGradientSecondaryColor, AllMarkingsGradientDirection);
|
||||
var h5 = HashCode.Combine(Width, Height);
|
||||
return HashCode.Combine(h1, h2, h3, h4, h5); //Sunrise end
|
||||
}
|
||||
|
||||
public HumanoidCharacterAppearance Clone()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System.Linq;
|
||||
using Content.Shared._Sunrise.MarkingEffects;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
|
|
@ -13,32 +12,20 @@ namespace Content.Shared.Humanoid.Markings
|
|||
[DataField("markingColor")]
|
||||
private List<Color> _markingColors = new();
|
||||
|
||||
// sunrise gradient edit start
|
||||
[DataField("markingEffects")]
|
||||
public List<MarkingEffect> MarkingEffects = new();
|
||||
// sunrise gradient edit end
|
||||
|
||||
|
||||
private Marking()
|
||||
{
|
||||
}
|
||||
|
||||
public Marking(string markingId,
|
||||
List<Color> markingColors,
|
||||
List<MarkingEffect>? markingEffects = null)
|
||||
List<Color> markingColors)
|
||||
{
|
||||
MarkingId = markingId;
|
||||
_markingColors = markingColors;
|
||||
MarkingEffects = markingEffects ?? new(); // sunrise gradient edit
|
||||
}
|
||||
|
||||
public Marking(string markingId,
|
||||
IReadOnlyList<Color> markingColors,
|
||||
IReadOnlyList<MarkingEffect>? markingEffects = null)
|
||||
: this(
|
||||
markingId,
|
||||
new List<Color>(markingColors),
|
||||
markingEffects is not null ? new List<MarkingEffect>(markingEffects) : new List<MarkingEffect>())
|
||||
IReadOnlyList<Color> markingColors)
|
||||
: this(markingId, new List<Color>(markingColors))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -47,11 +34,7 @@ namespace Content.Shared.Humanoid.Markings
|
|||
MarkingId = markingId;
|
||||
List<Color> colors = new();
|
||||
for (int i = 0; i < colorCount; i++)
|
||||
{
|
||||
colors.Add(Color.White);
|
||||
MarkingEffects.Add(ColorMarkingEffect.White);
|
||||
}
|
||||
|
||||
_markingColors = colors;
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +42,6 @@ namespace Content.Shared.Humanoid.Markings
|
|||
{
|
||||
MarkingId = other.MarkingId;
|
||||
_markingColors = new(other.MarkingColors);
|
||||
MarkingEffects = other.MarkingEffects.Select(e => e.Clone()).ToList();
|
||||
Visible = other.Visible;
|
||||
Forced = other.Forced;
|
||||
}
|
||||
|
|
@ -99,20 +81,6 @@ namespace Content.Shared.Humanoid.Markings
|
|||
}
|
||||
}
|
||||
|
||||
public void SetMarkingEffect(int colorIndex, MarkingEffect effect)
|
||||
{
|
||||
if(MarkingEffects.Count > colorIndex && colorIndex >= 0)
|
||||
MarkingEffects[colorIndex] = effect;
|
||||
}
|
||||
|
||||
public void SetMarkingEffect(MarkingEffect effect)
|
||||
{
|
||||
for (int i = 0; i < MarkingEffects.Count; i++)
|
||||
{
|
||||
MarkingEffects[i] = effect;
|
||||
}
|
||||
}
|
||||
|
||||
public int CompareTo(Marking? marking)
|
||||
{
|
||||
if (marking == null)
|
||||
|
|
@ -154,53 +122,28 @@ namespace Content.Shared.Humanoid.Markings
|
|||
// doesn't seem to have compatible interfaces? this 'works'
|
||||
// for now but should eventually be improved so that this can,
|
||||
// in fact just be serialized through a convenient interface
|
||||
public new string ToString()
|
||||
new public string ToString()
|
||||
{
|
||||
// reserved character
|
||||
string sanitizedName = this.MarkingId.Replace('@', '_');
|
||||
List<string> colorStringList = new();
|
||||
foreach (Color color in _markingColors)
|
||||
colorStringList.Add(color.ToHex());
|
||||
|
||||
var colorStringList = _markingColors.Select(c => c.ToHex()).ToList();
|
||||
if (MarkingEffects == null || MarkingEffects.Count == 0)
|
||||
return $"{sanitizedName}@{string.Join(',', colorStringList)}";
|
||||
|
||||
var extColorsList = MarkingEffects.Select(ext => ext.ToString());
|
||||
|
||||
var extColorsString = string.Join(";", extColorsList);
|
||||
return $"{sanitizedName}@{string.Join(',', colorStringList)}@{extColorsString}";
|
||||
return $"{sanitizedName}@{String.Join(',', colorStringList)}";
|
||||
}
|
||||
|
||||
public static Marking? ParseFromDbString(string input)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
if (input.Length == 0)
|
||||
return null;
|
||||
|
||||
var split = input.Split('@');
|
||||
if (split.Length < 2)
|
||||
return null;
|
||||
if (split.Length != 2) return null;
|
||||
List<Color> colorList = new();
|
||||
foreach (string color in split[1].Split(','))
|
||||
colorList.Add(Color.FromHex(color));
|
||||
|
||||
var name = split[0];
|
||||
var colorsRaw = split[1];
|
||||
|
||||
var colorList = new List<Color>();
|
||||
foreach (var colorHex in colorsRaw.Split(','))
|
||||
{
|
||||
colorList.Add(Color.FromHex(colorHex));
|
||||
}
|
||||
|
||||
if (split.Length == 2)
|
||||
return new Marking(name, colorList);
|
||||
|
||||
var extColorsRaw = split[2];
|
||||
var markingEffects = new List<MarkingEffect>();
|
||||
|
||||
foreach (var extColorStr in extColorsRaw.Split(';'))
|
||||
{
|
||||
var parsed = MarkingEffect.Parse(extColorStr);
|
||||
if (parsed != null)
|
||||
markingEffects.Add(parsed);
|
||||
}
|
||||
|
||||
return new Marking(name, colorList, markingEffects);
|
||||
return new Marking(split[0], colorList);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ using System.Linq;
|
|||
using Content.Shared._Sunrise;
|
||||
using Content.Shared._Sunrise.TTS;
|
||||
using System.Numerics;
|
||||
using Content.Shared._Sunrise.MarkingEffects;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Decals;
|
||||
using Content.Shared.Examine;
|
||||
|
|
@ -199,6 +198,20 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
|||
targetHumanoid.Width = sourceHumanoid.Width; //Sunrise
|
||||
targetHumanoid.Height = sourceHumanoid.Height; //Sunrise
|
||||
|
||||
//Sunrise start: Copy gradient settings
|
||||
targetHumanoid.HairGradientEnabled = sourceHumanoid.HairGradientEnabled;
|
||||
targetHumanoid.HairGradientSecondaryColor = sourceHumanoid.HairGradientSecondaryColor;
|
||||
targetHumanoid.HairGradientDirection = sourceHumanoid.HairGradientDirection;
|
||||
targetHumanoid.FacialHairGradientEnabled = sourceHumanoid.FacialHairGradientEnabled;
|
||||
targetHumanoid.FacialHairGradientSecondaryColor = sourceHumanoid.FacialHairGradientSecondaryColor;
|
||||
targetHumanoid.FacialHairGradientDirection = sourceHumanoid.FacialHairGradientDirection;
|
||||
targetHumanoid.AllMarkingsGradientEnabled = sourceHumanoid.AllMarkingsGradientEnabled;
|
||||
targetHumanoid.AllMarkingsGradientSecondaryColor = sourceHumanoid.AllMarkingsGradientSecondaryColor;
|
||||
targetHumanoid.AllMarkingsGradientDirection = sourceHumanoid.AllMarkingsGradientDirection;
|
||||
targetHumanoid.CachedHairColor = sourceHumanoid.CachedHairColor;
|
||||
targetHumanoid.CachedFacialHairColor = sourceHumanoid.CachedFacialHairColor;
|
||||
//Sunrise end
|
||||
|
||||
SetSex(target, sourceHumanoid.Sex, false, targetHumanoid);
|
||||
SetGender((target, targetHumanoid), sourceHumanoid.Gender);
|
||||
|
||||
|
|
@ -470,13 +483,13 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
|||
if (_markingManager.Markings.TryGetValue(profile.Appearance.HairStyleId, out var hairPrototype) &&
|
||||
_markingManager.CanBeApplied(profile.Species, profile.Sex, hairPrototype, _proto))
|
||||
{
|
||||
AddMarking(uid, profile.Appearance.HairStyleId, hairColor, false, markingEffect: profile.Appearance.HairMarkingEffect);
|
||||
AddMarking(uid, profile.Appearance.HairStyleId, hairColor, false);
|
||||
}
|
||||
|
||||
if (_markingManager.Markings.TryGetValue(profile.Appearance.FacialHairStyleId, out var facialHairPrototype) &&
|
||||
_markingManager.CanBeApplied(profile.Species, profile.Sex, facialHairPrototype, _proto))
|
||||
{
|
||||
AddMarking(uid, profile.Appearance.FacialHairStyleId, facialHairColor, false, markingEffect: profile.Appearance.FacialHairMarkingEffect);
|
||||
AddMarking(uid, profile.Appearance.FacialHairStyleId, facialHairColor, false);
|
||||
}
|
||||
|
||||
humanoid.MarkingSet.EnsureSpecies(profile.Species, profile.Appearance.SkinColor, _markingManager, _proto);
|
||||
|
|
@ -508,6 +521,20 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
|||
humanoid.Width = profile.Appearance.Width; //Sunrise
|
||||
humanoid.Height = profile.Appearance.Height; //Sunrise
|
||||
|
||||
//Sunrise start: Load gradient settings from profile
|
||||
humanoid.HairGradientEnabled = profile.Appearance.HairGradientEnabled;
|
||||
humanoid.HairGradientSecondaryColor = profile.Appearance.HairGradientSecondaryColor;
|
||||
humanoid.HairGradientDirection = profile.Appearance.HairGradientDirection;
|
||||
humanoid.FacialHairGradientEnabled = profile.Appearance.FacialHairGradientEnabled;
|
||||
humanoid.FacialHairGradientSecondaryColor = profile.Appearance.FacialHairGradientSecondaryColor;
|
||||
humanoid.FacialHairGradientDirection = profile.Appearance.FacialHairGradientDirection;
|
||||
humanoid.AllMarkingsGradientEnabled = profile.Appearance.AllMarkingsGradientEnabled;
|
||||
humanoid.AllMarkingsGradientSecondaryColor = profile.Appearance.AllMarkingsGradientSecondaryColor;
|
||||
humanoid.AllMarkingsGradientDirection = profile.Appearance.AllMarkingsGradientDirection;
|
||||
// Set cached hair colors for gradient shader
|
||||
humanoid.CachedHairColor = hairColor;
|
||||
humanoid.CachedFacialHairColor = facialHairColor; //Sunrise end
|
||||
|
||||
Dirty(uid, humanoid);
|
||||
}
|
||||
|
||||
|
|
@ -520,7 +547,7 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
|||
/// <param name="sync">Whether to immediately sync this marking or not</param>
|
||||
/// <param name="forced">If this marking was forced (ignores marking points)</param>
|
||||
/// <param name="humanoid">Humanoid component of the entity</param>
|
||||
public void AddMarking(EntityUid uid, string marking, Color? color = null, bool sync = true, bool forced = false, HumanoidAppearanceComponent? humanoid = null, MarkingEffect? markingEffect = null)
|
||||
public void AddMarking(EntityUid uid, string marking, Color? color = null, bool sync = true, bool forced = false, HumanoidAppearanceComponent? humanoid = null)
|
||||
{
|
||||
if (!Resolve(uid, ref humanoid)
|
||||
|| !_markingManager.Markings.TryGetValue(marking, out var prototype))
|
||||
|
|
@ -535,8 +562,6 @@ public abstract class SharedHumanoidAppearanceSystem : EntitySystem
|
|||
for (var i = 0; i < prototype.Sprites.Count; i++)
|
||||
{
|
||||
markingObject.SetColor(i, color.Value);
|
||||
if(markingEffect != null)
|
||||
markingObject.SetMarkingEffect(i, markingEffect);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,62 +0,0 @@
|
|||
using System.Linq;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._Sunrise.MarkingEffects;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class ColorMarkingEffect : MarkingEffect
|
||||
{
|
||||
public override MarkingEffectType Type => MarkingEffectType.Color;
|
||||
|
||||
public Color GetColor()
|
||||
=> Colors.TryGetValue("base", out var col) ? col : Color.White;
|
||||
|
||||
#region Constructors
|
||||
|
||||
public ColorMarkingEffect(Color color) : base(color) { }
|
||||
public static ColorMarkingEffect White => new(Color.White);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Parsers
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
Dictionary<string, string> dict = new();
|
||||
|
||||
var color = GetColor();
|
||||
dict.Add($"color.base", color.ToHex());
|
||||
|
||||
var result = string.Join(",", dict.Select(kvp => $"{kvp.Key}={kvp.Value}"));
|
||||
return $"{Type.ToString()}=={result}";
|
||||
}
|
||||
|
||||
public static ColorMarkingEffect? Parse(Dictionary<string, string> dict)
|
||||
{
|
||||
var color = Color.White;
|
||||
|
||||
foreach (var (type, value) in dict)
|
||||
{
|
||||
if (type == "color.base")
|
||||
color = Color.TryFromHex(value) ?? Color.White;
|
||||
}
|
||||
|
||||
return new ColorMarkingEffect(color);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Other methods
|
||||
public override ColorMarkingEffect Clone()
|
||||
{
|
||||
return new ColorMarkingEffect(Colors["base"]);
|
||||
}
|
||||
|
||||
public override bool Equals(MarkingEffect? maybeOther)
|
||||
{
|
||||
if (maybeOther is not ColorMarkingEffect other)
|
||||
return false;
|
||||
|
||||
return DictionaryEquals(Colors, other.Colors);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._Sunrise.MarkingEffects;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class GradientMarkingEffect : MarkingEffect
|
||||
{
|
||||
public override MarkingEffectType Type => MarkingEffectType.Gradient;
|
||||
|
||||
public Vector2 Offset = new(0, -190/100f);
|
||||
public Vector2 Size = new(1, 33/100f);
|
||||
public float Rotation = 0;
|
||||
public float Speed = 1;
|
||||
public bool Pixelated = true;
|
||||
public bool Mirrored = false;
|
||||
|
||||
#region Parsing
|
||||
public override string ToString()
|
||||
{
|
||||
var dict = new Dictionary<string, string>();
|
||||
|
||||
dict.Add("offset", ParamToString(Offset));
|
||||
dict.Add("size", ParamToString(Size));
|
||||
dict.Add("rotation", ParamToString(Rotation));
|
||||
dict.Add("speed", ParamToString(Speed));
|
||||
dict.Add("pixelated", ParamToString(Pixelated));
|
||||
dict.Add("mirrored", ParamToString(Mirrored));
|
||||
|
||||
foreach (var (k, v) in Colors)
|
||||
dict.Add($"color.{k}", $"{v.ToHex()}");
|
||||
|
||||
var result = string.Join(",", dict.Select(kvp => $"{kvp.Key}={kvp.Value}"));
|
||||
return $"{Type.ToString()}=={result}";
|
||||
}
|
||||
|
||||
public static GradientMarkingEffect? Parse(Dictionary<string, string> dict)
|
||||
{
|
||||
var colors = new Dictionary<string, Color>();
|
||||
|
||||
var offset = new Vector2(0, -190/100f);
|
||||
var size = new Vector2(1, 33/100f);
|
||||
var rotation = 0f;
|
||||
var speed = 1f;
|
||||
var pixelated = true;
|
||||
var mirrored = false;
|
||||
|
||||
foreach (var (type, value) in dict)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case "offset":
|
||||
TryParseParam(value, out offset);
|
||||
break;
|
||||
case "size":
|
||||
TryParseParam(value, out size);
|
||||
break;
|
||||
case "rotation":
|
||||
TryParseParam(value, out rotation);
|
||||
break;
|
||||
case "speed":
|
||||
TryParseParam(value, out speed);
|
||||
break;
|
||||
case "pixelated":
|
||||
TryParseParam(value, out pixelated);
|
||||
break;
|
||||
case "mirrored":
|
||||
TryParseParam(value, out mirrored);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if (type.StartsWith("color."))
|
||||
colors[type["color.".Length..]] = Color.TryFromHex(value) ?? Color.White;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure both base and gradient colors are present for compatibility
|
||||
if (!colors.ContainsKey("base"))
|
||||
colors["base"] = Color.White;
|
||||
if (!colors.ContainsKey("gradient"))
|
||||
colors["gradient"] = colors["base"]; // Use base color as fallback
|
||||
|
||||
return new GradientMarkingEffect(colors, offset, size, rotation, speed, pixelated, mirrored);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public GradientMarkingEffect()
|
||||
{
|
||||
Colors = new Dictionary<string, Color>()
|
||||
{
|
||||
{ "base", Color.White },
|
||||
{ "gradient", Color.White }
|
||||
};
|
||||
}
|
||||
|
||||
public GradientMarkingEffect(Color color)
|
||||
{
|
||||
Colors = new Dictionary<string, Color>
|
||||
{
|
||||
{"base", color },
|
||||
{"gradient", color }
|
||||
};
|
||||
}
|
||||
|
||||
public GradientMarkingEffect(Dictionary<string, Color> colors,
|
||||
Vector2 offset,
|
||||
Vector2 size,
|
||||
float rotation,
|
||||
float speed,
|
||||
bool pixelated,
|
||||
bool mirrored)
|
||||
{
|
||||
Colors = colors;
|
||||
Offset = offset;
|
||||
Size = size;
|
||||
Rotation = rotation;
|
||||
Speed = speed;
|
||||
Pixelated = pixelated;
|
||||
Mirrored = mirrored;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Other methods
|
||||
public override GradientMarkingEffect Clone()
|
||||
{
|
||||
return new GradientMarkingEffect(new(Colors), new(Offset.X, Offset.Y), new(Size.X, Size.Y), Rotation, Speed, Pixelated, Mirrored);
|
||||
}
|
||||
|
||||
public override bool Equals(MarkingEffect? maybeOther)
|
||||
{
|
||||
if (maybeOther is not GradientMarkingEffect other)
|
||||
return false;
|
||||
|
||||
return DictionaryEquals(Colors, other.Colors)
|
||||
&& Offset.Equals(other.Offset)
|
||||
&& Size.Equals(other.Size)
|
||||
&& Rotation.Equals(other.Rotation)
|
||||
&& Speed.Equals(other.Speed)
|
||||
&& Pixelated.Equals(other.Pixelated)
|
||||
&& Mirrored.Equals(other.Mirrored);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._Sunrise.MarkingEffects;
|
||||
|
||||
[ImplicitDataDefinitionForInheritors, Serializable, NetSerializable]
|
||||
public abstract partial class MarkingEffect
|
||||
{
|
||||
public abstract MarkingEffectType Type { get; }
|
||||
public Dictionary<string, Color> Colors;
|
||||
|
||||
public abstract override string ToString();
|
||||
public abstract MarkingEffect Clone();
|
||||
public abstract bool Equals(MarkingEffect? other);
|
||||
|
||||
#region Constructors
|
||||
|
||||
protected MarkingEffect()
|
||||
{
|
||||
Colors = new Dictionary<string, Color>
|
||||
{
|
||||
{ "base", Color.White }
|
||||
};
|
||||
}
|
||||
|
||||
protected MarkingEffect(Color color)
|
||||
{
|
||||
Colors = new Dictionary<string, Color>
|
||||
{
|
||||
{ "base", color }
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Parsers
|
||||
|
||||
protected static Dictionary<string, string>? ParseToDict(string input)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
return null;
|
||||
|
||||
var spl = input.Split("==");
|
||||
if (spl.Length > 1)
|
||||
input = spl[1];
|
||||
|
||||
var lines = input.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||
|
||||
if (lines.Length == 0)
|
||||
return null;
|
||||
|
||||
return lines
|
||||
.Select(line => line.Split('=', 2))
|
||||
.Where(parts => parts.Length == 2 && !string.IsNullOrWhiteSpace(parts[0]) && !string.IsNullOrWhiteSpace(parts[1]))
|
||||
.ToDictionary(parts => parts[0], parts => parts[1]);
|
||||
}
|
||||
|
||||
public static MarkingEffect? Parse(string input)
|
||||
{
|
||||
var pair = input.Split("==");
|
||||
|
||||
if (pair.Length != 2 || !Enum.TryParse<MarkingEffectType>(pair[0], true, out var type))
|
||||
return null;
|
||||
|
||||
var dict = ParseToDict(input);
|
||||
|
||||
if (dict == null)
|
||||
return null;
|
||||
|
||||
return MarkingEffectTypes.TypeParsers.TryGetValue(type, out var parser) ? parser(dict) : null;
|
||||
}
|
||||
|
||||
public static string ParamToString<T>(T param)
|
||||
{
|
||||
if (param == null)
|
||||
return "";
|
||||
|
||||
return param switch
|
||||
{
|
||||
null => "",
|
||||
float f => f.ToString(CultureInfo.InvariantCulture),
|
||||
bool b => b.ToString(),
|
||||
Vector2 v => Vector2ToString(v),
|
||||
_ => "",
|
||||
};
|
||||
}
|
||||
|
||||
public static bool TryParseParam<T>(string input, out T param)
|
||||
{
|
||||
param = default!;
|
||||
|
||||
if (typeof(T) == typeof(float))
|
||||
{
|
||||
if (!float.TryParse(input, CultureInfo.InvariantCulture, out var floatResult))
|
||||
return false;
|
||||
|
||||
param = (T)(object)floatResult;
|
||||
}
|
||||
else if (typeof(T) == typeof(bool))
|
||||
{
|
||||
if (!bool.TryParse(input, out var boolResult))
|
||||
return false;
|
||||
|
||||
param = (T)(object)boolResult;
|
||||
}
|
||||
else if (typeof(T) == typeof(Vector2))
|
||||
param = (T)(object)ParseVector2(input);
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Static methods
|
||||
|
||||
public static Vector2 ParseVector2(string str)
|
||||
{
|
||||
str = str.Trim('(', ')');
|
||||
var parts = str.Split('=');
|
||||
|
||||
if (parts.Length != 2
|
||||
|| !float.TryParse(parts[0], CultureInfo.InvariantCulture, out var x)
|
||||
|| !float.TryParse(parts[1], CultureInfo.InvariantCulture, out var y))
|
||||
return new(0, 0);
|
||||
|
||||
return new Vector2(x, y);
|
||||
}
|
||||
|
||||
public static bool DictionaryEquals<TKey, TValue>(
|
||||
Dictionary<TKey, TValue>? a,
|
||||
Dictionary<TKey, TValue>? b)
|
||||
where TKey : notnull
|
||||
{
|
||||
if (a == b)
|
||||
return true;
|
||||
if (a == null || b == null)
|
||||
return false;
|
||||
|
||||
return a.Count == b.Count && !a.Except(b).Any();
|
||||
}
|
||||
|
||||
public static string Vector2ToString(Vector2 v)
|
||||
{
|
||||
return $"({v.X.ToString(CultureInfo.InvariantCulture)}={v.Y.ToString(CultureInfo.InvariantCulture)})";
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
namespace Content.Shared._Sunrise.MarkingEffects;
|
||||
|
||||
// какой-то прям костыль, надо как-то по-другому парсер реализовать
|
||||
|
||||
public enum MarkingEffectType
|
||||
{
|
||||
Color,
|
||||
Gradient,
|
||||
RoughGradient,
|
||||
}
|
||||
|
||||
public static class MarkingEffectTypes
|
||||
{
|
||||
public static readonly Dictionary<MarkingEffectType, Func<Dictionary<string, string>, MarkingEffect?>> TypeParsers = new()
|
||||
{
|
||||
{ MarkingEffectType.Color, ColorMarkingEffect.Parse },
|
||||
{ MarkingEffectType.Gradient, GradientMarkingEffect.Parse },
|
||||
{ MarkingEffectType.RoughGradient, RoughGradientMarkingEffect.Parse },
|
||||
};
|
||||
}
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._Sunrise.MarkingEffects;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class RoughGradientMarkingEffect : MarkingEffect
|
||||
{
|
||||
public override MarkingEffectType Type => MarkingEffectType.RoughGradient;
|
||||
|
||||
public bool Horizontal = false;
|
||||
|
||||
#region Parsing
|
||||
public override string ToString()
|
||||
{
|
||||
var dict = new Dictionary<string, string>();
|
||||
|
||||
dict.Add("horizontal", ParamToString(Horizontal));
|
||||
|
||||
foreach (var (k, v) in Colors)
|
||||
dict.Add($"color.{k}", $"{v.ToHex()}");
|
||||
|
||||
var result = string.Join(",", dict.Select(kvp => $"{kvp.Key}={kvp.Value}"));
|
||||
return $"{Type.ToString()}=={result}";
|
||||
}
|
||||
|
||||
public static RoughGradientMarkingEffect? Parse(Dictionary<string, string> dict)
|
||||
{
|
||||
var colors = new Dictionary<string, Color>();
|
||||
|
||||
var horizontal = false;
|
||||
|
||||
foreach (var (type, value) in dict)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case "horizontal":
|
||||
TryParseParam(value, out horizontal);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if (type.StartsWith("color."))
|
||||
colors[type["color.".Length..]] = Color.TryFromHex(value) ?? Color.White;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure both base and gradient colors are present for compatibility
|
||||
if (!colors.ContainsKey("base"))
|
||||
colors["base"] = Color.White;
|
||||
if (!colors.ContainsKey("gradient"))
|
||||
colors["gradient"] = colors["base"]; // Use base color as fallback
|
||||
|
||||
return new RoughGradientMarkingEffect(colors, horizontal);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
public RoughGradientMarkingEffect()
|
||||
{
|
||||
Colors = new Dictionary<string, Color>()
|
||||
{
|
||||
{ "base", Color.White },
|
||||
{ "gradient", Color.White }
|
||||
};
|
||||
}
|
||||
|
||||
public RoughGradientMarkingEffect(Color color)
|
||||
{
|
||||
Colors = new Dictionary<string, Color>
|
||||
{
|
||||
{"base", color },
|
||||
{"gradient", color }
|
||||
};
|
||||
}
|
||||
|
||||
public RoughGradientMarkingEffect(Dictionary<string, Color> colors, bool horizontal)
|
||||
{
|
||||
Colors = colors;
|
||||
Horizontal = horizontal;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Other methods
|
||||
public override RoughGradientMarkingEffect Clone()
|
||||
{
|
||||
return new RoughGradientMarkingEffect(new(Colors), Horizontal);
|
||||
}
|
||||
|
||||
public override bool Equals(MarkingEffect? maybeOther)
|
||||
{
|
||||
if (maybeOther is not RoughGradientMarkingEffect other)
|
||||
return false;
|
||||
|
||||
return DictionaryEquals(Colors, other.Colors)
|
||||
&& Equals(Horizontal, other.Horizontal);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# Sunrise Hair gradient UI
|
||||
humanoid-profile-editor-hair-gradient-label = Hair gradient
|
||||
humanoid-profile-editor-hair-gradient-enable = Enable gradient
|
||||
humanoid-profile-editor-hair-gradient-direction = Direction
|
||||
humanoid-profile-editor-hair-gradient-dir-bottom-top = Bottom to top
|
||||
humanoid-profile-editor-hair-gradient-dir-top-bottom = Top to bottom
|
||||
humanoid-profile-editor-hair-gradient-dir-left-right = Left to right
|
||||
humanoid-profile-editor-hair-gradient-dir-right-left = Right to left
|
||||
|
||||
humanoid-profile-editor-facialhair-gradient-label = Facial hair gradient
|
||||
|
||||
# Sunrise All markings gradient
|
||||
humanoid-profile-editor-allmarkings-gradient-label = All markings gradient
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# Sunrise Hair gradient UI
|
||||
humanoid-profile-editor-hair-gradient-label = Градиент волос
|
||||
humanoid-profile-editor-hair-gradient-enable = Включить градиент
|
||||
humanoid-profile-editor-hair-gradient-direction = Направление
|
||||
humanoid-profile-editor-hair-gradient-dir-bottom-top = Снизу вверх
|
||||
humanoid-profile-editor-hair-gradient-dir-top-bottom = Сверху вниз
|
||||
humanoid-profile-editor-hair-gradient-dir-left-right = Слева направо
|
||||
humanoid-profile-editor-hair-gradient-dir-right-left = Справа налево
|
||||
|
||||
humanoid-profile-editor-facialhair-gradient-label = Градиент растительности на лице
|
||||
|
||||
# Sunrise All markings gradient
|
||||
humanoid-profile-editor-allmarkings-gradient-label = Градиент всех маркингов
|
||||
|
|
@ -105,4 +105,4 @@ marking-HairAppleJack = Эппл Джек (NEW)
|
|||
marking-HairPinkiePie = Пинки Пай (NEW)
|
||||
marking-HairRarity = Рарити (NEW)
|
||||
marking-HairAqua = Аква (NEW)
|
||||
marking-HairBairdAndBangs = Коса с чёлкой (NEW)
|
||||
marking-HairBairdAndBangs = Коса с чёлкой (NEW)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
marking-effect-type-color = Без эффекта
|
||||
marking-effect-type-color = Стандартный
|
||||
marking-effect-color-color-base = Цвет
|
||||
marking-effect-type-gradient = Градиент
|
||||
marking-effect-gradient-color-base = Начало
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
hideLayersOnEquip:
|
||||
- Hair
|
||||
- Snout
|
||||
# MARKINGS START
|
||||
# MARKINGS START
|
||||
bodyTypeMarkingsDisplacement:
|
||||
body-fat-m:
|
||||
Hair:
|
||||
|
|
@ -556,7 +556,7 @@
|
|||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
- type: HumanoidAppearance
|
||||
# MARKINGS START
|
||||
# MARKINGS START
|
||||
bodyTypeMarkingsDisplacement:
|
||||
body-fat-m:
|
||||
Hair:
|
||||
|
|
@ -1070,4 +1070,4 @@
|
|||
sizeMaps:
|
||||
32:
|
||||
sprite: _Sunrise/Mobs/Species/Human/Distrofik/displacement.rsi
|
||||
state: back
|
||||
state: back
|
||||
13
Resources/Prototypes/_Sunrise/Shaders/shaders.yml
Normal file
13
Resources/Prototypes/_Sunrise/Shaders/shaders.yml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# © SUNRISE, Contributor: UnilTan
|
||||
# Licensed under SUNRISE CLA
|
||||
# Full text: https://github.com/space-sunrise/space-station-14/blob/master/CLA.txt
|
||||
# Hair/fur linear gradient used in customization
|
||||
- type: shader
|
||||
id: HairGradient
|
||||
kind: source
|
||||
path: "/Textures/_Sunrise/Shaders/hair_linear_gradient.swsl"
|
||||
params:
|
||||
color1: 1, 0, 0
|
||||
color2: 1, 1, 1
|
||||
direction: 0
|
||||
light_mode: shaded
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
- type: shader
|
||||
- type: shader
|
||||
id: NVDDisplay
|
||||
kind: source
|
||||
path: "/Textures/_Sunrise/Shaders/NVDDisplay.swsl"
|
||||
|
|
@ -34,13 +34,3 @@
|
|||
NightVisionBoost: 2.0
|
||||
NightVisionThreshold: 0.3
|
||||
BlueTintIntensity: 0.6
|
||||
|
||||
- type: shader
|
||||
id: Gradient
|
||||
kind: source
|
||||
path: "/Textures/_Sunrise/Shaders/gradient.swsl"
|
||||
|
||||
- type: shader
|
||||
id: RoughGradient
|
||||
kind: source
|
||||
path: "/Textures/_Sunrise/Shaders/gradient_rough.swsl"
|
||||
|
|
|
|||
|
|
@ -1,66 +0,0 @@
|
|||
uniform highp vec3 color1;
|
||||
uniform highp vec3 color2;
|
||||
uniform highp vec2 texScale;
|
||||
uniform highp vec2 offset;
|
||||
uniform highp vec2 size;
|
||||
uniform highp float rotation;
|
||||
uniform bool pixelated;
|
||||
uniform bool mirrored;
|
||||
|
||||
// DISPLACEMENT START
|
||||
uniform sampler2D displacementMap;
|
||||
uniform highp float displacementSize;
|
||||
uniform highp vec4 displacementUV;
|
||||
varying highp vec2 displacementUVOut;
|
||||
|
||||
void vertex() {
|
||||
if(useDisplacement == true) {
|
||||
displacementUVOut = mix(displacementUV.xy, displacementUV.zw, tCoord2);
|
||||
}
|
||||
}
|
||||
|
||||
uniform bool useDisplacement;
|
||||
// DISPLACEMENT END
|
||||
|
||||
highp float mirror(highp float x) {
|
||||
return mix(x, abs(fract(x) * 2.0 - 1.0), float(mirrored));
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
highp vec4 color = texture2D(TEXTURE, UV);
|
||||
|
||||
highp vec2 uv = UV2;
|
||||
highp float rad = radians(rotation);
|
||||
highp vec2 center = vec2(0.5);
|
||||
uv -= center;
|
||||
|
||||
highp float cos_a = cos(rad);
|
||||
highp float sin_a = sin(rad);
|
||||
highp mat2 rot = mat2(
|
||||
cos_a, -sin_a,
|
||||
sin_a, cos_a
|
||||
);
|
||||
|
||||
if (pixelated) {
|
||||
uv = floor(uv * texScale) / texScale;
|
||||
}
|
||||
|
||||
uv = rot * uv;
|
||||
uv += center;
|
||||
|
||||
highp float t = mirror(uv.y / size.y + offset.y);
|
||||
t = clamp(t, 0.0, 1.0);
|
||||
|
||||
highp vec3 gradient = mix(color2, color1, t);
|
||||
|
||||
// DISPLACEMENT START
|
||||
if(useDisplacement == true) {
|
||||
highp vec4 displacementSample = texture2D(displacementMap, displacementUVOut);
|
||||
highp vec2 displacementValue = (displacementSample.xy - vec2(128.0 / 255.0)) / (1.0 - 128.0 / 255.0);
|
||||
color = zTexture(UV + displacementValue * TEXTURE_PIXEL_SIZE * displacementSize * vec2(1.0, -1.0));
|
||||
color.a *= displacementSample.a;
|
||||
}
|
||||
// DISPLACEMENT END
|
||||
|
||||
COLOR = color * vec4(gradient, 1);
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
uniform highp vec3 color1;
|
||||
uniform highp vec3 color2;
|
||||
uniform bool horizontal;
|
||||
|
||||
// DISPLACEMENT START
|
||||
uniform sampler2D displacementMap;
|
||||
uniform highp float displacementSize;
|
||||
uniform highp vec4 displacementUV;
|
||||
varying highp vec2 displacementUVOut;
|
||||
|
||||
void vertex() {
|
||||
if(useDisplacement == true) {
|
||||
displacementUVOut = mix(displacementUV.xy, displacementUV.zw, tCoord2);
|
||||
}
|
||||
}
|
||||
|
||||
uniform bool useDisplacement;
|
||||
// DISPLACEMENT END
|
||||
|
||||
highp float find_bound(bool forward, bool horizontal) {
|
||||
highp float step = horizontal ? TEXTURE_PIXEL_SIZE.x : TEXTURE_PIXEL_SIZE.y;
|
||||
highp float current = horizontal ? UV.x : UV.y;
|
||||
|
||||
const highp int MAX_ITERATIONS = 256;
|
||||
highp int iterations = 0;
|
||||
|
||||
highp vec4 result = texture2D(TEXTURE, UV);
|
||||
|
||||
while ((forward ? current < 1.0 : current > 0.0) && result.a > 0.0 && iterations < MAX_ITERATIONS) {
|
||||
current += forward ? step : -step;
|
||||
iterations++;
|
||||
|
||||
highp vec2 probeUV = UV;
|
||||
if (horizontal)
|
||||
probeUV.x = current;
|
||||
else
|
||||
probeUV.y = current;
|
||||
|
||||
result = texture2D(TEXTURE, probeUV);
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
|
||||
void fragment() {
|
||||
highp vec4 color = texture2D(TEXTURE, UV);
|
||||
|
||||
highp float a = find_bound(false, horizontal);
|
||||
highp float b = find_bound(true, horizontal);
|
||||
|
||||
highp float diff = max(0.001, b - a);
|
||||
highp float pos = horizontal ? UV.x : UV.y;
|
||||
|
||||
highp float norm = clamp((pos - a) / diff, 0.0, 1.0);
|
||||
highp vec3 gradient = mix(color2, color1, norm);
|
||||
|
||||
// DISPLACEMENT START
|
||||
if(useDisplacement == true) {
|
||||
highp vec4 displacementSample = texture2D(displacementMap, displacementUVOut);
|
||||
highp vec2 displacementValue = (displacementSample.xy - vec2(128.0 / 255.0)) / (1.0 - 128.0 / 255.0);
|
||||
color = zTexture(UV + displacementValue * TEXTURE_PIXEL_SIZE * displacementSize * vec2(1.0, -1.0));
|
||||
color.a *= displacementSample.a;
|
||||
}
|
||||
// DISPLACEMENT END
|
||||
|
||||
COLOR = vec4(color.rgb * gradient, color.a);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// Linear gradient tint shader for sprite layers (hair/fur).
|
||||
// Blends between two colors along a chosen axis and multiplies original texture RGB (no grayscale), preserving alpha.
|
||||
//
|
||||
// direction:
|
||||
// 0 = bottom -> top (vertical)
|
||||
// 1 = top -> bottom (vertical)
|
||||
// 2 = left -> right (horizontal)
|
||||
// 3 = right -> left (horizontal)
|
||||
|
||||
|
||||
uniform highp vec3 color1;
|
||||
uniform highp vec3 color2;
|
||||
uniform highp float direction;
|
||||
|
||||
void fragment()
|
||||
{
|
||||
// Sample the sprite normally (texture atlas UV)
|
||||
highp vec4 base = zTexture(UV);
|
||||
|
||||
// Compute gradient coordinate t in [0,1] using quad-local UV (UV2),
|
||||
// so it spans exactly across the drawn sprite region, not the whole atlas.
|
||||
highp float t = 0.0;
|
||||
if (direction < 0.5) // bottom -> top
|
||||
t = UV2.y;
|
||||
else if (direction < 1.5) // top -> bottom
|
||||
t = 1.0 - UV2.y;
|
||||
else if (direction < 2.5) // left -> right
|
||||
t = UV2.x;
|
||||
else // right -> left
|
||||
t = 1.0 - UV2.x;
|
||||
|
||||
highp float tt = clamp(t, 0.0, 1.0);
|
||||
|
||||
// Создаем градиентный цвет: переходим от color1 к color2
|
||||
highp vec3 gradColor = mix(color1, color2, tt);
|
||||
|
||||
// Применяем градиентный цвет к оригинальной текстуре
|
||||
// Текстура волос умножается на градиентный цвет напрямую
|
||||
highp vec3 finalRgb = base.rgb * gradColor;
|
||||
COLOR = vec4(finalRgb, base.a);
|
||||
}
|
||||
|
||||
|
||||
7
runall.bat
Normal file
7
runall.bat
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
set PDIR=%~dp0
|
||||
cd %PDIR%Bin\Content.Server
|
||||
start Content.Server.exe
|
||||
cd %PDIR%Bin\Content.Client
|
||||
start Content.Client.exe
|
||||
cd %PDIR%
|
||||
set PDIR=
|
||||
Loading…
Add table
Reference in a new issue