using System.Collections.Generic; using System.Linq; using System.Text; using AIImages.Models; using RimWorld; using Verse; namespace AIImages.Services { /// /// Продвинутый генератор промптов для Stable Diffusion /// public class AdvancedPromptGenerator : IPromptGeneratorService { private static readonly Dictionary TraitToMood = new Dictionary< string, string > { { "Kind", "warm smile, gentle expression, friendly eyes" }, { "Bloodlust", "intense gaze, fierce expression, aggressive posture" }, { "Psychopath", "cold eyes, emotionless face, calculating expression" }, { "Pessimist", "sad eyes, worried expression, downcast gaze" }, { "Optimist", "bright smile, hopeful expression, cheerful demeanor" }, { "Nervous", "anxious expression, tense posture, worried eyes" }, { "Careful", "focused expression, attentive gaze, composed posture" }, { "Brave", "confident expression, determined gaze, strong posture" }, { "Wimp", "fearful eyes, nervous expression, timid posture" }, { "Greedy", "cunning expression, calculating eyes, sly smile" }, { "Jealous", "envious gaze, bitter expression, tense face" }, { "Ascetic", "serene expression, calm demeanor, peaceful eyes" }, { "Beautiful", "stunning features, attractive appearance, graceful" }, { "Ugly", "rough features, weathered appearance" }, { "Pretty", "attractive features, pleasant appearance, charming" }, }; private static readonly Dictionary ArtStylePrompts = new Dictionary< ArtStyle, string > { { ArtStyle.Realistic, "photorealistic, hyperrealistic, realistic photo, photography" }, { ArtStyle.SemiRealistic, "semi-realistic, detailed illustration, realistic art" }, { ArtStyle.Anime, "anime style, manga style, anime character" }, { ArtStyle.ConceptArt, "concept art, digital art, artstation, professional concept design" }, { ArtStyle.DigitalPainting, "digital painting, painterly, brush strokes, artistic" }, { ArtStyle.OilPainting, "oil painting, traditional painting, canvas, fine art" }, { ArtStyle.Sketch, "pencil sketch, hand drawn, sketch art, line art" }, { ArtStyle.CellShaded, "cell shaded, flat colors, toon shading, stylized" }, }; private static readonly Dictionary ShotTypePrompts = new Dictionary< ShotType, string > { { ShotType.Portrait, "portrait, head and shoulders" }, { ShotType.HalfBody, "half body shot, waist up" }, { ShotType.FullBody, "full body, full length" }, { ShotType.CloseUp, "close up, face focus, detailed face" }, { ShotType.ThreeQuarter, "three-quarter view, 3/4 view" }, }; public string GeneratePositivePrompt( PawnAppearanceData appearanceData, StableDiffusionSettings settings ) { if (appearanceData == null) return "portrait of a person"; StringBuilder prompt = new StringBuilder(); // 1. Художественный стиль if (ArtStylePrompts.TryGetValue(settings.ArtStyle, out string stylePrompt)) { prompt.Append(stylePrompt); prompt.Append(", "); } // 2. Тип кадра if (ShotTypePrompts.TryGetValue(settings.ShotType, out string shotPrompt)) { prompt.Append(shotPrompt); prompt.Append(" of "); } // 3. Базовое описание (возраст и пол) prompt.Append(GetAgeAndGenderDescription(appearanceData)); prompt.Append(", "); // 4. Тип тела string bodyType = GetBodyTypeDescription(appearanceData.BodyType); if (!string.IsNullOrEmpty(bodyType)) { prompt.Append(bodyType); prompt.Append(", "); } // 5. Цвет кожи string skinTone = ColorDescriptionService.GetSkinToneDescription( appearanceData.SkinColor ); prompt.Append(skinTone); prompt.Append(", "); // 6. Волосы string hairDescription = GetHairDescription(appearanceData); if (!string.IsNullOrEmpty(hairDescription)) { prompt.Append(hairDescription); prompt.Append(", "); } // 7. Настроение и выражение на основе черт характера string moodDescription = GetMoodFromTraits(appearanceData.Traits); if (!string.IsNullOrEmpty(moodDescription)) { prompt.Append(moodDescription); prompt.Append(", "); } // 8. Одежда string apparelDescription = GetApparelDescription(appearanceData.Apparel); if (!string.IsNullOrEmpty(apparelDescription)) { prompt.Append(apparelDescription); prompt.Append(", "); } // 9. Базовый пользовательский промпт (если указан) if (!string.IsNullOrEmpty(settings.PositivePrompt)) { prompt.Append(settings.PositivePrompt); prompt.Append(", "); } // 10. Качественные теги prompt.Append(GetQualityTags(settings.ArtStyle)); return prompt.ToString().Trim().TrimEnd(','); } public string GenerateNegativePrompt(StableDiffusionSettings settings) { StringBuilder negativePrompt = new StringBuilder(); // Базовые негативные промпты negativePrompt.Append( "ugly, deformed, low quality, blurry, bad anatomy, worst quality, " ); negativePrompt.Append( "mutated, disfigured, bad proportions, extra limbs, missing limbs, " ); // Специфичные для стиля негативы if ( settings.ArtStyle == ArtStyle.Realistic || settings.ArtStyle == ArtStyle.SemiRealistic ) { negativePrompt.Append("cartoon, anime, painting, drawing, illustration, "); } else if (settings.ArtStyle == ArtStyle.Anime) { negativePrompt.Append("realistic, photo, photography, 3d, "); } // Пользовательский негативный промпт if (!string.IsNullOrEmpty(settings.NegativePrompt)) { negativePrompt.Append(settings.NegativePrompt); } return negativePrompt.ToString().Trim().TrimEnd(','); } public string GetFullPromptDescription( PawnAppearanceData appearanceData, StableDiffusionSettings settings ) { StringBuilder description = new StringBuilder(); description.AppendLine("=== Positive Prompt ==="); description.AppendLine(GeneratePositivePrompt(appearanceData, settings)); description.AppendLine(); description.AppendLine("=== Negative Prompt ==="); description.AppendLine(GenerateNegativePrompt(settings)); description.AppendLine(); description.AppendLine("=== Technical Parameters ==="); description.AppendLine($"Steps: {settings.Steps}"); description.AppendLine($"CFG Scale: {settings.CfgScale}"); description.AppendLine($"Size: {settings.Width}x{settings.Height}"); description.AppendLine($"Sampler: {settings.Sampler}"); description.AppendLine( $"Seed: {(settings.Seed == -1 ? "Random" : settings.Seed.ToString())}" ); return description.ToString(); } private string GetAgeAndGenderDescription(PawnAppearanceData data) { string ageGroup = data.Age switch { < 18 => "young", < 25 => "young adult", < 35 => "adult", < 50 => "middle-aged", < 65 => "mature", _ => "elderly", }; string genderLabel = data.Gender switch { Gender.Male => "man", Gender.Female => "woman", _ => "person", }; return $"{ageGroup} {genderLabel}"; } private string GetBodyTypeDescription(string bodyType) { if (string.IsNullOrEmpty(bodyType)) return ""; return bodyType.ToLower() switch { "thin" => "slender build, lean physique", "hulk" => "muscular build, strong physique, athletic body", "fat" => "heavyset build, stocky physique", "female" => "feminine build", "male" => "masculine build", _ => "average build", }; } private string GetHairDescription(PawnAppearanceData data) { if (string.IsNullOrEmpty(data.HairStyle)) return ""; StringBuilder hair = new StringBuilder(); // Цвет волос string hairColor = ColorDescriptionService.GetHairColorDescription(data.HairColor); hair.Append(hairColor); hair.Append(" "); // Стиль прически (упрощаем сложные названия) string style = data .HairStyle.ToLower() .Replace("_", " ") .Replace("shaved", "very short") .Replace("mohawk", "mohawk hairstyle"); hair.Append(style); hair.Append(" hair"); return hair.ToString(); } private string GetMoodFromTraits(List traits) { if (traits == null || !traits.Any()) return "neutral expression"; // Ищем черты, которые влияют на внешний вид foreach (var trait in traits) { string traitDefName = trait.def.defName; if (TraitToMood.TryGetValue(traitDefName, out string mood)) { return mood; } } return "calm expression"; } private string GetApparelDescription(List apparel) { if (apparel == null || !apparel.Any()) return "simple clothes"; StringBuilder apparelDesc = new StringBuilder("wearing "); // Берем топ 5 наиболее заметных предметов одежды var visibleApparel = apparel.Take(5).ToList(); List items = new List(); foreach (var item in visibleApparel) { StringBuilder itemDesc = new StringBuilder(); // Цвет (если не белый) if (item.Color != UnityEngine.Color.white) { string colorDesc = ColorDescriptionService.GetApparelColorDescription( item.Color ); itemDesc.Append(colorDesc); itemDesc.Append(" "); } // Материал if (!string.IsNullOrEmpty(item.Material)) { itemDesc.Append(item.Material.ToLower()); itemDesc.Append(" "); } // Название предмета itemDesc.Append(item.Label.ToLower()); items.Add(itemDesc.ToString()); } apparelDesc.Append(string.Join(", ", items)); return apparelDesc.ToString(); } private string GetQualityTags(ArtStyle style) { var baseTags = "highly detailed, professional, masterpiece, best quality"; if (style == ArtStyle.Realistic || style == ArtStyle.SemiRealistic) { return $"{baseTags}, professional photography, 8k uhd, dslr, high quality, sharp focus"; } else if (style == ArtStyle.Anime) { return $"{baseTags}, anime masterpiece, high resolution, vibrant colors"; } else if (style == ArtStyle.ConceptArt) { return $"{baseTags}, trending on artstation, professional digital art"; } else { return baseTags; } } } }