From 60dcb279aec1d70d5959681f8973fb1048dd5554 Mon Sep 17 00:00:00 2001 From: Leonid Pershin Date: Sat, 1 Nov 2025 08:51:49 +0300 Subject: [PATCH] Add skin color gene handling to PawnAppearanceData and update skin tone description logic. Enhance AIImages.dll to support special skin tones based on gene definitions, improving character appearance representation. --- Assemblies/AIImages.dll | Bin 112640 -> 114176 bytes Source/AIImages/Models/PawnAppearanceData.cs | 2 + .../Services/AdvancedPromptGenerator.cs | 71 ++++- .../Services/ColorDescriptionService.cs | 258 ++++++++---------- .../Services/PawnDescriptionService.cs | 28 ++ 5 files changed, 209 insertions(+), 150 deletions(-) diff --git a/Assemblies/AIImages.dll b/Assemblies/AIImages.dll index dc6df03043a4d9a06199f328fae626964625bf7d..bbbab5d76224c065c5a1c8be771839006a8fc5dd 100644 GIT binary patch delta 40515 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 delta 38879 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

29K$+Hw6f8N$JRmDyw z^bdS=rO^kaD=ivb*p2DeMIT0Mv^k6EW8InV>%}%KcT!T`U5U7R>5{5C>8B#5(cl%j zxu7jkp+V*Mf{reI81&8DyFfpw`w&mYAw&JP{V9mHmOTqPEAa);g_$dH0kxqUyU0m= z2@J{Ee^^(!9RgFV@26lg9z zT6Hh%3qoc0qTX4xT#v`HnSP3>aRuRF`X!>q;c{q;gvr#|7-A&PK`eO{!%j18AWJeq~{ycHFNZf6SVaW$Eoa+j)KOl5X z>~V)eqoTQh)#9Nf?hjaQ6YaSoIYT4|<8Ib4|E|DsRG~f+*H2 z5Xtg*cKsx%rmePr7(KEjy5{}FkuB%;dLP9M_`hq35Op>M>KY>jOo?GfJYqHaGl55M zMJgBhMvp{wlh0LO)}`F*aksTBZG*?vnHduBb$-gpwG*Ionjl(>EU!4bW?02 zAh}D1-stiRB#4Vq{2eqNv?omgeS)Tgjt?oPeoaZ1heEww# zy$GXYHm0{|Mz$ShHg38%5mtgSJ

k@WyoQaI_Eh?UsY$hiQkO&%$yY0iRU&E7~$V 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 Y*YqdXZ*brXOmCi&(9h5v+A-eoKNRo)-T(jq diff --git a/Source/AIImages/Models/PawnAppearanceData.cs b/Source/AIImages/Models/PawnAppearanceData.cs index 60e5664..a124ce7 100644 --- a/Source/AIImages/Models/PawnAppearanceData.cs +++ b/Source/AIImages/Models/PawnAppearanceData.cs @@ -15,6 +15,7 @@ namespace AIImages.Models public int Age { get; set; } public string BodyType { get; set; } public Color SkinColor { get; set; } + public List SkinColorGeneDefNames { get; set; } public string HairStyle { get; set; } public string HairDefName { get; set; } public Color HairColor { get; set; } @@ -25,6 +26,7 @@ namespace AIImages.Models { Traits = new List(); Apparel = new List(); + SkinColorGeneDefNames = new List(); } } diff --git a/Source/AIImages/Services/AdvancedPromptGenerator.cs b/Source/AIImages/Services/AdvancedPromptGenerator.cs index 342974d..2852531 100644 --- a/Source/AIImages/Services/AdvancedPromptGenerator.cs +++ b/Source/AIImages/Services/AdvancedPromptGenerator.cs @@ -205,12 +205,77 @@ namespace AIImages.Services private string GetSkinToneDescription(PawnAppearanceData data) { - // Этот метод будет использоваться в контексте генерации промптов - // где у нас есть только данные внешности, но не сам Pawn - // Поэтому используем fallback к определению по цвету + // Сначала проверяем специальные гены цвета кожи (зелёная, синяя и т.д.) + if (data.SkinColorGeneDefNames != null && data.SkinColorGeneDefNames.Any()) + { + // Ищем специальные гены (зелёная, синяя, красная и т.д.) + foreach (var geneDefName in data.SkinColorGeneDefNames) + { + string specialSkinTone = GetSpecialGeneSkinTone(geneDefName); + if (!string.IsNullOrEmpty(specialSkinTone)) + return specialSkinTone; + } + } + + // Если нет специальных генов, используем вычисленный RimWorld цвет return ColorDescriptionService.GetSkinToneDescription(data.SkinColor); } + ///

+ /// Получает описание для специальных генов цвета кожи + /// + private string GetSpecialGeneSkinTone(string geneDefName) + { + switch (geneDefName) + { + case "Skin_InkBlack": + return "ink black skin"; + case "Skin_SlateGray": + return "slate gray skin"; + case "Skin_LightGray": + return "light gray skin"; + case "Skin_SheerWhite": + return "sheer white skin"; + case "Skin_Blue": + return "blue skin"; + case "Skin_Purple": + return "purple skin"; + case "Skin_PaleRed": + return "pale red skin"; + case "Skin_DeepRed": + return "deep red skin"; + case "Skin_PaleYellow": + return "pale yellow skin"; + case "Skin_DeepYellow": + return "deep yellow skin"; + case "Skin_Orange": + return "orange skin"; + case "Skin_Green": + return "green skin"; + default: + // Пытаемся определить по названию + if (geneDefName.Contains("Green") || geneDefName.Contains("зел")) + return "green skin"; + if (geneDefName.Contains("Blue") || geneDefName.Contains("син")) + return "blue skin"; + if (geneDefName.Contains("Red") || geneDefName.Contains("красн")) + return "red skin"; + if (geneDefName.Contains("Yellow") || geneDefName.Contains("жёлт")) + return "yellow skin"; + if (geneDefName.Contains("Purple") || geneDefName.Contains("фиолет")) + return "purple skin"; + if (geneDefName.Contains("Orange") || geneDefName.Contains("оранж")) + return "orange skin"; + if (geneDefName.Contains("Black") || geneDefName.Contains("чёрн")) + return "black skin"; + if (geneDefName.Contains("White") || geneDefName.Contains("бел")) + return "white skin"; + if (geneDefName.Contains("Gray") || geneDefName.Contains("Grey") || geneDefName.Contains("сер")) + return "gray skin"; + return null; + } + } + private string GetHairDescription(PawnAppearanceData data) { if (string.IsNullOrEmpty(data.HairDefName)) diff --git a/Source/AIImages/Services/ColorDescriptionService.cs b/Source/AIImages/Services/ColorDescriptionService.cs index 9cb6b90..566f0bc 100644 --- a/Source/AIImages/Services/ColorDescriptionService.cs +++ b/Source/AIImages/Services/ColorDescriptionService.cs @@ -34,21 +34,126 @@ namespace AIImages.Services } /// - /// Получает текстовое описание цвета кожи, сначала проверяя гены, затем используя цвет как fallback + /// Получает текстовое описание цвета кожи + /// Сначала проверяет специальные гены цвета кожи (зелёная, синяя и т.д.), + /// затем использует вычисленный RimWorld цвет кожи /// public static string GetSkinToneDescription(Pawn pawn) { - // Сначала проверяем гены цвета кожи - string geneSkinTone = GetSkinToneFromGenes(pawn); - if (!string.IsNullOrEmpty(geneSkinTone)) + if (pawn?.genes?.GenesListForReading == null) + return GetSkinToneDescription(pawn.story.SkinColor); + + // Ищем активные гены цвета кожи (особенно специальные: зелёная, синяя, красная и т.д.) + var skinColorGenes = pawn + .genes.GenesListForReading.Where(gene => + gene.Active && IsSpecialSkinColorGene(gene.def) + ) + .ToList(); + + // Если есть специальные гены цвета кожи, используем их описание + if (skinColorGenes.Any()) { - return geneSkinTone; + var specialGene = skinColorGenes[0]; + string geneDescription = GetSpecialGeneSkinTone(specialGene.def.defName); + if (!string.IsNullOrEmpty(geneDescription)) + return geneDescription; } - // Fallback к определению по цвету + // Иначе RimWorld уже определил цвет текстуры пешки на основе генов (включая уровень мелатонина) + // Используем этот вычисленный цвет return GetSkinToneDescription(pawn.story.SkinColor); } + /// + /// Проверяет, является ли ген специальным геном цвета кожи (зелёная, синяя, красная и т.д.) + /// + private static bool IsSpecialSkinColorGene(GeneDef geneDef) + { + if (geneDef == null) + return false; + + string geneDefName = geneDef.defName; + + // Специальные цвета: зелёная, синяя, красная, жёлтая, фиолетовая, оранжевая, чёрная, белая, серая + return geneDefName.StartsWith("Skin_") + && ( + geneDefName.Contains("Green") + || geneDefName.Contains("Blue") + || geneDefName.Contains("Red") + || geneDefName.Contains("Yellow") + || geneDefName.Contains("Purple") + || geneDefName.Contains("Orange") + || geneDefName.Contains("Black") + || geneDefName.Contains("White") + || geneDefName.Contains("Gray") + || geneDefName.Contains("Grey") + || geneDefName.Contains("Ink") + || geneDefName.Contains("Slate") + || geneDefName.Contains("Sheer") + || geneDefName.Contains("Pale") + || geneDefName.Contains("Deep") + ); + } + + /// + /// Получает описание для специальных генов цвета кожи + /// + private static string GetSpecialGeneSkinTone(string geneDefName) + { + switch (geneDefName) + { + case "Skin_InkBlack": + return "ink black skin"; + case "Skin_SlateGray": + return "slate gray skin"; + case "Skin_LightGray": + return "light gray skin"; + case "Skin_SheerWhite": + return "sheer white skin"; + case "Skin_Blue": + return "blue skin"; + case "Skin_Purple": + return "purple skin"; + case "Skin_PaleRed": + return "pale red skin"; + case "Skin_DeepRed": + return "deep red skin"; + case "Skin_PaleYellow": + return "pale yellow skin"; + case "Skin_DeepYellow": + return "deep yellow skin"; + case "Skin_Orange": + return "orange skin"; + case "Skin_Green": + return "green skin"; + default: + // Пытаемся определить по названию + if (geneDefName.Contains("Green") || geneDefName.Contains("зел")) + return "green skin"; + if (geneDefName.Contains("Blue") || geneDefName.Contains("син")) + return "blue skin"; + if (geneDefName.Contains("Red") || geneDefName.Contains("красн")) + return "red skin"; + if (geneDefName.Contains("Yellow") || geneDefName.Contains("жёлт")) + return "yellow skin"; + if (geneDefName.Contains("Purple") || geneDefName.Contains("фиолет")) + return "purple skin"; + if (geneDefName.Contains("Orange") || geneDefName.Contains("оранж")) + return "orange skin"; + if (geneDefName.Contains("Black") || geneDefName.Contains("чёрн")) + return "black skin"; + if (geneDefName.Contains("White") || geneDefName.Contains("бел")) + return "white skin"; + if ( + geneDefName.Contains("Gray") + || geneDefName.Contains("Grey") + || geneDefName.Contains("сер") + ) + return "gray skin"; + return null; + } + } + /// /// Получает текстовое описание цвета кожи по RGB цвету (fallback метод) /// @@ -78,147 +183,6 @@ namespace AIImages.Services return "very dark skin"; } - /// - /// Получает текстовое описание цвета кожи по генам - /// - public static string GetSkinToneFromGenes(Pawn pawn) - { - if (pawn?.genes?.GenesListForReading == null) - return null; - - // Ищем активные гены цвета кожи - var skinColorGenes = pawn - .genes.GenesListForReading.Where(gene => - gene.Active && IsSkinColorGene(gene.def.defName) - ) - .ToList(); - - if (!skinColorGenes.Any()) - return null; - - // Берем первый найденный ген (обычно у персонажа один ген цвета кожи) - var skinGene = skinColorGenes[0]; - return GetSkinToneDescriptionFromGene(skinGene.def.defName); - } - - /// - /// Проверяет, является ли ген геном цвета кожи - /// - private static bool IsSkinColorGene(string geneDefName) - { - return geneDefName.StartsWith("Skin_") - || geneDefName.Contains("SkinColor") - || geneDefName.Contains("SkinTone"); - } - - /// - /// Получает описание цвета кожи по названию гена - /// - private static string GetSkinToneDescriptionFromGene(string geneDefName) - { - // Проверяем стандартные гены - string standardGene = GetStandardGeneSkinTone(geneDefName); - if (!string.IsNullOrEmpty(standardGene)) - return standardGene; - - // Проверяем дополнительные гены - string additionalGene = GetAdditionalGeneSkinTone(geneDefName); - if (!string.IsNullOrEmpty(additionalGene)) - return additionalGene; - - // Пытаемся извлечь информацию из названия - return ExtractSkinToneFromGeneName(geneDefName); - } - - /// - /// Получает описание для стандартных генов цвета кожи - /// - private static string GetStandardGeneSkinTone(string geneDefName) - { - switch (geneDefName) - { - case "Skin_InkBlack": - return "ink black skin"; - case "Skin_SlateGray": - return "slate gray skin"; - case "Skin_LightGray": - return "light gray skin"; - case "Skin_SheerWhite": - return "sheer white skin"; - case "Skin_Blue": - return "blue skin"; - case "Skin_Purple": - return "purple skin"; - case "Skin_PaleRed": - return "pale red skin"; - case "Skin_DeepRed": - return "deep red skin"; - case "Skin_PaleYellow": - return "pale yellow skin"; - case "Skin_DeepYellow": - return "deep yellow skin"; - case "Skin_Orange": - return "orange skin"; - case "Skin_Green": - return "green skin"; - default: - return null; - } - } - - /// - /// Получает описание для дополнительных генов цвета кожи - /// - private static string GetAdditionalGeneSkinTone(string geneDefName) - { - switch (geneDefName) - { - case "Skin_Dark": - return "dark skin"; - case "Skin_Light": - return "light skin"; - case "Skin_Medium": - return "medium skin"; - case "Skin_Fair": - return "fair skin"; - case "Skin_Tan": - return "tan skin"; - case "Skin_Olive": - return "olive skin"; - case "Skin_Brown": - return "brown skin"; - default: - return null; - } - } - - /// - /// Извлекает описание цвета кожи из названия гена - /// - private static string ExtractSkinToneFromGeneName(string geneDefName) - { - if (geneDefName.Contains("Black")) - return "black skin"; - if (geneDefName.Contains("White")) - return "white skin"; - if (geneDefName.Contains("Gray") || geneDefName.Contains("Grey")) - return "gray skin"; - if (geneDefName.Contains("Blue")) - return "blue skin"; - if (geneDefName.Contains("Red")) - return "red skin"; - if (geneDefName.Contains("Green")) - return "green skin"; - if (geneDefName.Contains("Yellow")) - return "yellow skin"; - if (geneDefName.Contains("Purple")) - return "purple skin"; - if (geneDefName.Contains("Orange")) - return "orange skin"; - - return null; // Неизвестный ген - } - /// /// Получает описание цвета одежды /// diff --git a/Source/AIImages/Services/PawnDescriptionService.cs b/Source/AIImages/Services/PawnDescriptionService.cs index 0062420..1f1d52b 100644 --- a/Source/AIImages/Services/PawnDescriptionService.cs +++ b/Source/AIImages/Services/PawnDescriptionService.cs @@ -29,6 +29,20 @@ namespace AIImages.Services HairColor = pawn.story.HairColor, }; + // Извлекаем гены цвета кожи + if (pawn.genes?.GenesListForReading != null) + { + var skinColorGenes = pawn + .genes.GenesListForReading + .Where(gene => gene.Active && IsSkinColorGene(gene.def)) + .ToList(); + + foreach (var gene in skinColorGenes) + { + data.SkinColorGeneDefNames.Add(gene.def.defName); + } + } + // Извлекаем черты характера if (pawn.story.traits?.allTraits != null) { @@ -180,5 +194,19 @@ namespace AIImages.Services sb.AppendLine(); } + + /// + /// Проверяет, является ли ген геном цвета кожи + /// + private bool IsSkinColorGene(GeneDef geneDef) + { + if (geneDef == null) + return false; + + string geneDefName = geneDef.defName; + return geneDefName.StartsWith("Skin_") + || geneDefName.Contains("SkinColor") + || geneDefName.Contains("SkinTone"); + } } }