diff --git a/Assemblies/AIImages.dll b/Assemblies/AIImages.dll index dc6df03..bbbab5d 100644 Binary files a/Assemblies/AIImages.dll and b/Assemblies/AIImages.dll differ 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"); + } } }