var facialHair = new Marking(profile.Appearance.FacialHairStyleId,
new[] { facialHairColor });
- if (_markingManager.CanBeApplied(profile.Species, hair, _prototypeManager))
+ if (_markingManager.CanBeApplied(profile.Species, profile.Sex, hair, _prototypeManager))
{
markings.AddBack(MarkingCategories.Hair, hair);
}
- if (_markingManager.CanBeApplied(profile.Species, facialHair, _prototypeManager))
+ if (_markingManager.CanBeApplied(profile.Species, profile.Sex, facialHair, _prototypeManager))
{
markings.AddBack(MarkingCategories.FacialHair, facialHair);
}
}
markings.EnsureSpecies(profile.Species, profile.Appearance.SkinColor, _markingManager, _prototypeManager);
+ markings.EnsureSexes(profile.Sex, _markingManager);
markings.EnsureDefault(
profile.Appearance.SkinColor,
profile.Appearance.EyeColor,
return;
}
- _window.SetState(cast.MarkingSet, cast.Species, cast.SkinColor, cast.CustomBaseLayers);
+ _window.SetState(cast.MarkingSet, cast.Species, cast.Sex, cast.SkinColor, cast.CustomBaseLayers);
}
private void SendMarkingSet(MarkingSet set)
public void SetState(
MarkingSet markings,
string species,
+ Sex sex,
Color skinColor,
Dictionary<HumanoidVisualLayers, CustomBaseLayerInfo> info
)
eyesColor = eyes.Color.Value;
}
- MarkingPickerWidget.SetData(markings, species, skinColor, eyesColor);
+ MarkingPickerWidget.SetData(markings, species, sex, skinColor, eyesColor);
}
private sealed class HumanoidBaseLayerModifier : BoxContainer
private List<MarkingCategories> _markingCategories = Enum.GetValues<MarkingCategories>().ToList();
private string _currentSpecies = SharedHumanoidAppearanceSystem.DefaultSpecies;
+ private Sex _currentSex = Sex.Unsexed;
public Color CurrentSkinColor = Color.White;
public Color CurrentEyeColor = Color.Black;
public Marking? HairMarking;
}
}
- public void SetData(List<Marking> newMarkings, string species, Color skinColor, Color eyeColor)
+ public void SetData(List<Marking> newMarkings, string species, Sex sex, Color skinColor, Color eyeColor)
{
var pointsProto = _prototypeManager
.Index<SpeciesPrototype>(species).MarkingPoints;
}
_currentSpecies = species;
+ _currentSex = sex;
CurrentSkinColor = skinColor;
CurrentEyeColor = eyeColor;
PopulateUsed();
}
- public void SetData(MarkingSet set, string species, Color skinColor, Color eyeColor)
+ public void SetData(MarkingSet set, string species, Sex sex, Color skinColor, Color eyeColor)
{
_currentMarkings = set;
}
_currentSpecies = species;
+ _currentSex = sex;
CurrentSkinColor = skinColor;
CurrentEyeColor = eyeColor;
_selectedUnusedMarking = null;
var markings = IgnoreSpecies
- ? _markingManager.MarkingsByCategory(_selectedMarkingCategory)
- : _markingManager.MarkingsByCategoryAndSpecies(_selectedMarkingCategory, _currentSpecies);
+ ? _markingManager.MarkingsByCategoryAndSex(_selectedMarkingCategory, _currentSex)
+ : _markingManager.MarkingsByCategoryAndSpeciesAndSex(_selectedMarkingCategory, _currentSpecies, _currentSex);
var sortedMarkings = markings.Values.Where(m =>
m.ID.ToLower().Contains(filter.ToLower()) ||
_currentMarkings = new(markingList, speciesPrototype.MarkingPoints, _markingManager, _prototypeManager);
_currentMarkings.EnsureSpecies(species, null, _markingManager);
+ _currentMarkings.EnsureSexes(_currentSex, _markingManager);
+
+ Populate(CMarkingSearch.Text);
+ PopulateUsed();
+ }
+
+ public void SetSex(Sex sex)
+ {
+ _currentSex = sex;
+ var markingList = _currentMarkings.GetForwardEnumerator().ToList();
+
+ var speciesPrototype = _prototypeManager.Index<SpeciesPrototype>(_currentSpecies);
+
+ _currentMarkings = new(markingList, speciesPrototype.MarkingPoints, _markingManager, _prototypeManager);
+ _currentMarkings.EnsureSpecies(_currentSpecies, null, _markingManager);
+ _currentMarkings.EnsureSexes(_currentSex, _markingManager);
Populate(CMarkingSearch.Text);
PopulateUsed();
break;
}
UpdateGenderControls();
+ CMarkings.SetSex(newSex);
IsDirty = true;
}
}
CMarkings.SetData(Profile.Appearance.Markings, Profile.Species,
- Profile.Appearance.SkinColor, Profile.Appearance.EyeColor
+ Profile.Sex, Profile.Appearance.SkinColor, Profile.Appearance.EyeColor
);
}
_markingManager.Markings.TryGetValue(Profile.Appearance.HairStyleId, out var hairProto)
)
{
- if (_markingManager.CanBeApplied(Profile.Species, hairProto, _prototypeManager))
+ if (_markingManager.CanBeApplied(Profile.Species, Profile.Sex, hairProto, _prototypeManager))
{
if (_markingManager.MustMatchSkin(Profile.Species, HumanoidVisualLayers.Hair, out var _, _prototypeManager))
{
_markingManager.Markings.TryGetValue(Profile.Appearance.FacialHairStyleId, out var facialHairProto)
)
{
- if (_markingManager.CanBeApplied(Profile.Species, facialHairProto, _prototypeManager))
+ if (_markingManager.CanBeApplied(Profile.Species, Profile.Sex, facialHairProto, _prototypeManager))
{
if (_markingManager.MustMatchSkin(Profile.Species, HumanoidVisualLayers.Hair, out var _, _prototypeManager))
{
uid,
HumanoidMarkingModifierKey.Key,
new HumanoidMarkingModifierState(component.MarkingSet, component.Species,
+ component.Sex,
component.SkinColor,
component.CustomBaseLayers
));
uid,
HumanoidMarkingModifierKey.Key,
new HumanoidMarkingModifierState(component.MarkingSet, component.Species,
+ component.Sex,
component.SkinColor,
component.CustomBaseLayers
));
uid,
HumanoidMarkingModifierKey.Key,
new HumanoidMarkingModifierState(component.MarkingSet, component.Species,
+ component.Sex,
component.SkinColor,
component.CustomBaseLayers
));
return new(color.RByte, color.GByte, color.BByte);
}
- public static HumanoidCharacterAppearance EnsureValid(HumanoidCharacterAppearance appearance, string species)
+ public static HumanoidCharacterAppearance EnsureValid(HumanoidCharacterAppearance appearance, string species, Sex sex)
{
var hairStyleId = appearance.HairStyleId;
var facialHairStyleId = appearance.FacialHairStyleId;
}
markingSet.EnsureSpecies(species, skinColor, markingManager);
+ markingSet.EnsureSexes(sex, markingManager);
}
return new HumanoidCharacterAppearance(
{
continue;
}
+ res.Add(key, marking);
+ }
+
+ return res;
+ }
+
+ /// <summary>
+ /// Markings by category and sex.
+ /// </summary>
+ /// <param name="category"></param>
+ /// <param name="sex"></param>
+ /// <remarks>
+ /// This is done per category, as enumerating over every single marking by species isn't useful.
+ /// Please make a pull request if you find a use case for that behavior.
+ /// </remarks>
+ /// <returns></returns>
+ public IReadOnlyDictionary<string, MarkingPrototype> MarkingsByCategoryAndSex(MarkingCategories category,
+ Sex sex)
+ {
+ var res = new Dictionary<string, MarkingPrototype>();
+
+ foreach (var (key, marking) in MarkingsByCategory(category))
+ {
+ if (marking.SexRestriction != null && marking.SexRestriction != sex)
+ {
+ continue;
+ }
+
+ res.Add(key, marking);
+ }
+
+ return res;
+ }
+
+ /// <summary>
+ /// Markings by category, species and sex.
+ /// </summary>
+ /// <param name="category"></param>
+ /// <param name="species"></param>
+ /// <param name="sex"></param>
+ /// <remarks>
+ /// This is done per category, as enumerating over every single marking by species isn't useful.
+ /// Please make a pull request if you find a use case for that behavior.
+ /// </remarks>
+ /// <returns></returns>
+ public IReadOnlyDictionary<string, MarkingPrototype> MarkingsByCategoryAndSpeciesAndSex(MarkingCategories category,
+ string species, Sex sex)
+ {
+ var speciesProto = _prototypeManager.Index<SpeciesPrototype>(species);
+ var onlyWhitelisted = _prototypeManager.Index<MarkingPointsPrototype>(speciesProto.MarkingPoints).OnlyWhitelisted;
+ var res = new Dictionary<string, MarkingPrototype>();
+
+ foreach (var (key, marking) in MarkingsByCategory(category))
+ {
+ if (onlyWhitelisted && marking.SpeciesRestrictions == null)
+ {
+ continue;
+ }
+
+ if (marking.SpeciesRestrictions != null && !marking.SpeciesRestrictions.Contains(species))
+ {
+ continue;
+ }
+
+ if (marking.SexRestriction != null && marking.SexRestriction != sex)
+ {
+ continue;
+ }
res.Add(key, marking);
}
/// <param name="marking"></param>
/// <param name="category"></param>
/// <param name="species"></param>
+ /// <param name="sex"></param>
/// <returns></returns>
- public bool IsValidMarking(Marking marking, MarkingCategories category, string species)
+ public bool IsValidMarking(Marking marking, MarkingCategories category, string species, Sex sex)
{
if (!TryGetMarking(marking, out var proto))
{
}
if (proto.MarkingCategory != category ||
- proto.SpeciesRestrictions != null && !proto.SpeciesRestrictions.Contains(species))
+ proto.SpeciesRestrictions != null && !proto.SpeciesRestrictions.Contains(species) ||
+ proto.SexRestriction != null && proto.SexRestriction != sex)
{
return false;
}
}
}
- public bool CanBeApplied(string species, Marking marking, IPrototypeManager? prototypeManager = null)
+ public bool CanBeApplied(string species, Sex sex, Marking marking, IPrototypeManager? prototypeManager = null)
{
IoCManager.Resolve(ref prototypeManager);
{
return false;
}
+
+ if (prototype.SexRestriction != null && prototype.SexRestriction != sex)
+ {
+ return false;
+ }
+
return true;
}
- public bool CanBeApplied(string species, MarkingPrototype prototype, IPrototypeManager? prototypeManager = null)
+ public bool CanBeApplied(string species, Sex sex, MarkingPrototype prototype, IPrototypeManager? prototypeManager = null)
{
IoCManager.Resolve(ref prototypeManager);
{
return false;
}
+
+ if (prototype.SexRestriction != null && prototype.SexRestriction != sex)
+ {
+ return false;
+ }
+
return true;
}
alpha = 1f;
return false;
}
-
+
alpha = sprite.LayerAlpha;
return true;
}
[DataField("speciesRestriction")]
public List<string>? SpeciesRestrictions { get; private set; }
+ [DataField("sexRestriction")]
+ public Sex? SexRestriction { get; private set; }
+
[DataField("followSkinColor")]
public bool FollowSkinColor { get; private set; } = false;
}
}
+ /// <summary>
+ /// Filters markings based on sex and it's restrictions in the marking's prototype from this marking set.
+ /// </summary>
+ /// <param name="sex">The species to filter.</param>
+ /// <param name="markingManager">Marking manager.</param>
+ public void EnsureSexes(Sex sex, MarkingManager? markingManager = null)
+ {
+ IoCManager.Resolve(ref markingManager);
+
+ var toRemove = new List<(MarkingCategories category, string id)>();
+
+ foreach (var (category, list) in Markings)
+ {
+ foreach (var marking in list)
+ {
+ if (!markingManager.TryGetMarking(marking, out var prototype))
+ {
+ toRemove.Add((category, marking.MarkingId));
+ continue;
+ }
+
+ if (prototype.SexRestriction != null && prototype.SexRestriction != sex)
+ {
+ toRemove.Add((category, marking.MarkingId));
+ }
+ }
+ }
+
+ foreach (var remove in toRemove)
+ {
+ Remove(remove.category, remove.id);
+ }
+ }
+
/// <summary>
/// Ensures that all markings in this set are valid.
/// </summary>
var oldSex = humanoid.Sex;
humanoid.Sex = sex;
+ humanoid.MarkingSet.EnsureSexes(sex, _markingManager);
RaiseLocalEvent(uid, new SexChangedEvent(oldSex, sex));
if (sync)
? profile.Appearance.SkinColor.WithAlpha(facialHairAlpha) : profile.Appearance.FacialHairColor;
if (_markingManager.Markings.TryGetValue(profile.Appearance.HairStyleId, out var hairPrototype) &&
- _markingManager.CanBeApplied(profile.Species, hairPrototype, _prototypeManager))
+ _markingManager.CanBeApplied(profile.Species, profile.Sex, hairPrototype, _prototypeManager))
{
AddMarking(uid, profile.Appearance.HairStyleId, hairColor, false);
}
if (_markingManager.Markings.TryGetValue(profile.Appearance.FacialHairStyleId, out var facialHairPrototype) &&
- _markingManager.CanBeApplied(profile.Species, facialHairPrototype, _prototypeManager))
+ _markingManager.CanBeApplied(profile.Species, profile.Sex, facialHairPrototype, _prototypeManager))
{
AddMarking(uid, profile.Appearance.FacialHairStyleId, facialHairColor, false);
}
public HumanoidMarkingModifierState(
MarkingSet markingSet,
string species,
+ Sex sex,
Color skinColor,
Dictionary<HumanoidVisualLayers, CustomBaseLayerInfo> customBaseLayers
)
{
MarkingSet = markingSet;
Species = species;
+ Sex = sex;
SkinColor = skinColor;
CustomBaseLayers = customBaseLayers;
}
public MarkingSet MarkingSet { get; }
public string Species { get; }
+ public Sex Sex { get; }
public Color SkinColor { get; }
public Color EyeColor { get; }
public Color? HairColor { get; }
flavortext = FormattedMessage.RemoveMarkup(FlavorText);
}
- var appearance = HumanoidCharacterAppearance.EnsureValid(Appearance, Species);
+ var appearance = HumanoidCharacterAppearance.EnsureValid(Appearance, Species, Sex);
var prefsUnavailableMode = PreferenceUnavailable switch
{