import logging from typing import Dict, List, Optional from dataclasses import dataclass logger = logging.getLogger(__name__) @dataclass class SceneTemplate: """Data class representing a scene template""" key: str name: str prompt: str negative_extra: str category: str icon: str guidance_scale: float = 7.5 class SceneTemplateManager: """ Manages curated scene templates for background generation. Provides categorized presets that users can select with one click. """ # Scene template definitions TEMPLATES: Dict[str, SceneTemplate] = { # Professional Category "office_modern": SceneTemplate( key="office_modern", name="Modern Office", prompt="modern minimalist office interior, clean white desk, large floor-to-ceiling windows, natural daylight, professional corporate environment, soft shadows, contemporary furniture", negative_extra="messy, cluttered, dark, old", category="Professional", icon="🏢", guidance_scale=7.5 ), "office_executive": SceneTemplate( key="office_executive", name="Executive Suite", prompt="luxurious executive office, mahogany desk, leather chair, city skyline view through windows, warm ambient lighting, bookshelf, elegant professional setting", negative_extra="cheap, cramped, messy", category="Professional", icon="👔", guidance_scale=7.5 ), "studio_white": SceneTemplate( key="studio_white", name="White Studio", prompt="clean white photography studio background, professional lighting setup, seamless white backdrop, soft diffused light, minimal shadows", negative_extra="colored, textured, dirty", category="Professional", icon="📷", guidance_scale=8.0 ), "coworking": SceneTemplate( key="coworking", name="Coworking Space", prompt="modern coworking space, open plan office, plants, exposed brick, industrial chic design, natural light, collaborative environment", negative_extra="empty, dark, boring", category="Professional", icon="💼", guidance_scale=7.0 ), "conference": SceneTemplate( key="conference", name="Conference Room", prompt="modern conference room, large meeting table, glass walls, professional presentation screen, bright corporate lighting, clean minimal design", negative_extra="small, cramped, outdated", category="Professional", icon="🤝", guidance_scale=7.5 ), # Nature Category "beach_sunset": SceneTemplate( key="beach_sunset", name="Sunset Beach", prompt="beautiful tropical beach at golden hour sunset, palm trees silhouette, calm turquoise ocean waves, warm orange and pink sky, soft sand, paradise vacation vibes", negative_extra="storm, rain, crowded, trash", category="Nature", icon="🏖️", guidance_scale=7.0 ), "forest_enchanted": SceneTemplate( key="forest_enchanted", name="Enchanted Forest", prompt="magical enchanted forest, sunlight streaming through tall trees, lush green foliage, mystical atmosphere, morning mist, fairy tale woodland", negative_extra="dead trees, dark, scary, barren", category="Nature", icon="🌲", guidance_scale=7.0 ), "mountain_scenic": SceneTemplate( key="mountain_scenic", name="Mountain Vista", prompt="breathtaking mountain landscape, snow-capped peaks, alpine meadow, clear blue sky, majestic scenic view, pristine nature, peaceful atmosphere", negative_extra="industrial, polluted, crowded", category="Nature", icon="🏔️", guidance_scale=7.5 ), "garden_spring": SceneTemplate( key="garden_spring", name="Spring Garden", prompt="beautiful spring flower garden, colorful blooming flowers, roses and tulips, manicured hedges, sunny day, botanical paradise, fresh and vibrant", negative_extra="dead, winter, wilted, dry", category="Nature", icon="🌸", guidance_scale=7.0 ), "lake_serene": SceneTemplate( key="lake_serene", name="Serene Lake", prompt="peaceful serene lake at dawn, mirror-like water reflection, surrounding mountains, soft morning light, tranquil atmosphere, pristine natural beauty", negative_extra="stormy, polluted, industrial", category="Nature", icon="🏞️", guidance_scale=7.0 ), "cherry_blossom": SceneTemplate( key="cherry_blossom", name="Cherry Blossom", prompt="stunning cherry blossom trees in full bloom, pink sakura petals falling gently, Japanese garden aesthetic, soft spring sunlight, romantic atmosphere", negative_extra="winter, dead, brown, wilted", category="Nature", icon="🌸", guidance_scale=7.0 ), # Urban Category "city_skyline": SceneTemplate( key="city_skyline", name="City Skyline", prompt="modern city skyline at blue hour, impressive skyscrapers, glass buildings reflecting sunset, urban metropolitan view, cinematic atmosphere", negative_extra="slums, dirty, abandoned, ruins", category="Urban", icon="🌆", guidance_scale=7.5 ), "cafe_cozy": SceneTemplate( key="cafe_cozy", name="Cozy Cafe", prompt="warm cozy coffee shop interior, wooden furniture, ambient lighting, exposed brick walls, plants, comfortable atmosphere, artisan cafe vibes", negative_extra="fast food, plastic, harsh lighting", category="Urban", icon="☕", guidance_scale=7.0 ), "street_european": SceneTemplate( key="street_european", name="European Street", prompt="charming European cobblestone street, historic buildings, outdoor cafe, flowers on balconies, warm afternoon light, romantic Paris or Rome vibes", negative_extra="modern, industrial, ugly, dirty", category="Urban", icon="🏛️", guidance_scale=7.0 ), "night_neon": SceneTemplate( key="night_neon", name="Neon Nightlife", prompt="vibrant city nightlife scene, neon lights and signs, urban night atmosphere, colorful reflections on wet street, cyberpunk aesthetic, electric energy", negative_extra="daytime, boring, plain", category="Urban", icon="🌃", guidance_scale=6.5 ), "rooftop_view": SceneTemplate( key="rooftop_view", name="Rooftop Terrace", prompt="luxury rooftop terrace, city panoramic view, modern outdoor furniture, string lights, sunset golden hour, sophisticated urban oasis", negative_extra="cheap, dirty, crowded", category="Urban", icon="🏙️", guidance_scale=7.5 ), # Artistic Category "gradient_soft": SceneTemplate( key="gradient_soft", name="Soft Gradient", prompt="smooth soft gradient background, pastel colors blending beautifully, pink to blue to purple transition, dreamy aesthetic, professional portrait backdrop", negative_extra="harsh, noisy, textured, busy", category="Artistic", icon="🎨", guidance_scale=8.0 ), "abstract_modern": SceneTemplate( key="abstract_modern", name="Modern Abstract", prompt="modern abstract art background, geometric shapes, bold colors, contemporary design, artistic composition, museum gallery aesthetic", negative_extra="realistic, plain, boring", category="Artistic", icon="🖼️", guidance_scale=6.5 ), "vintage_retro": SceneTemplate( key="vintage_retro", name="Vintage Retro", prompt="vintage retro aesthetic background, warm sepia tones, nostalgic 70s vibes, film grain texture, classic photography style, timeless elegance", negative_extra="modern, digital, cold, harsh", category="Artistic", icon="📻", guidance_scale=7.0 ), "watercolor_dream": SceneTemplate( key="watercolor_dream", name="Watercolor Dream", prompt="beautiful watercolor painting background, soft flowing colors, artistic brush strokes, dreamy ethereal atmosphere, delicate artistic aesthetic", negative_extra="digital, sharp, photorealistic", category="Artistic", icon="🖌️", guidance_scale=6.5 ), # Seasonal Category "autumn_foliage": SceneTemplate( key="autumn_foliage", name="Autumn Foliage", prompt="beautiful autumn scenery, vibrant fall foliage, orange red and golden leaves, maple trees, warm sunlight filtering through, cozy seasonal atmosphere", negative_extra="spring, summer, green, snow", category="Seasonal", icon="🍂", guidance_scale=7.0 ), "winter_snow": SceneTemplate( key="winter_snow", name="Winter Wonderland", prompt="magical winter wonderland, fresh white snow covering everything, snow-laden pine trees, soft snowfall, peaceful cold atmosphere, holiday season vibes", negative_extra="summer, green, rain, mud", category="Seasonal", icon="❄️", guidance_scale=7.0 ), "summer_tropical": SceneTemplate( key="summer_tropical", name="Tropical Summer", prompt="vibrant tropical summer scene, lush palm trees, bright sunny day, exotic flowers, paradise vacation destination, warm and inviting atmosphere", negative_extra="winter, cold, snow, gray", category="Seasonal", icon="🌴", guidance_scale=7.0 ), "spring_meadow": SceneTemplate( key="spring_meadow", name="Spring Meadow", prompt="beautiful spring meadow, wildflowers blooming, fresh green grass, butterflies, soft warm sunlight, renewal and new beginnings, pastoral beauty", negative_extra="winter, autumn, dead, dry", category="Seasonal", icon="🌷", guidance_scale=7.0 ), } # Category display order CATEGORIES = ["Professional", "Nature", "Urban", "Artistic", "Seasonal"] def __init__(self): """Initialize the scene template manager""" logger.info(f"SceneTemplateManager initialized with {len(self.TEMPLATES)} templates") def get_all_templates(self) -> Dict[str, SceneTemplate]: """Get all available templates""" return self.TEMPLATES def get_template(self, key: str) -> Optional[SceneTemplate]: """Get a specific template by key""" return self.TEMPLATES.get(key) def get_templates_by_category(self, category: str) -> List[SceneTemplate]: """Get all templates in a specific category""" return [t for t in self.TEMPLATES.values() if t.category == category] def get_categories(self) -> List[str]: """Get list of all categories in display order""" return self.CATEGORIES def get_template_choices_sorted(self) -> List[str]: """ Get template choices formatted for Gradio dropdown. Returns list of display strings sorted A-Z: "🏢 Modern Office" """ display_list = [] for key, template in self.TEMPLATES.items(): display_name = f"{template.icon} {template.name}" display_list.append(display_name) # Sort alphabetically by name (ignoring emoji) display_list.sort(key=lambda x: x.split(' ', 1)[1] if ' ' in x else x) return display_list def get_template_key_from_display(self, display_name: str) -> Optional[str]: """ Get template key from display name. Example: "🏢 Modern Office" -> "office_modern" """ if not display_name: return None for key, template in self.TEMPLATES.items(): if f"{template.icon} {template.name}" == display_name: return key return None def get_prompt_for_template(self, key: str) -> Optional[str]: """Get the prompt string for a template""" template = self.get_template(key) return template.prompt if template else None def get_negative_prompt_for_template( self, key: str, base_negative: str = "blurry, low quality, distorted, people, characters" ) -> str: """Get combined negative prompt for a template""" template = self.get_template(key) if template and template.negative_extra: return f"{base_negative}, {template.negative_extra}" return base_negative def get_guidance_scale_for_template(self, key: str) -> float: """Get the recommended guidance scale for a template""" template = self.get_template(key) return template.guidance_scale if template else 7.5 def build_gallery_html(self) -> str: """ Build HTML for the scene template gallery. Returns HTML string for display in Gradio. """ html_parts = ['