SceneWeaver / scene_templates.py
DawnC's picture
Update scene_templates.py
f7dcaec verified
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 = ['<div class="scene-gallery">']
for category in self.CATEGORIES:
templates = self.get_templates_by_category(category)
if not templates:
continue
html_parts.append(f'''
<div class="scene-category">
<h4 class="scene-category-title">{category}</h4>
<div class="scene-grid">
''')
for template in templates:
html_parts.append(f'''
<button class="scene-card" data-template="{template.key}" onclick="selectTemplate('{template.key}')">
<span class="scene-icon">{template.icon}</span>
<span class="scene-name">{template.name}</span>
</button>
''')
html_parts.append('</div></div>')
html_parts.append('</div>')
return ''.join(html_parts)
def get_gallery_css(self) -> str:
"""Get CSS styles for the scene gallery"""
return """
/* Scene Gallery Styles */
.scene-gallery {
margin: 16px 0;
}
.scene-category {
margin-bottom: 20px;
}
.scene-category-title {
font-size: 0.9rem;
font-weight: 600;
color: #475569;
margin-bottom: 12px;
padding-bottom: 8px;
border-bottom: 1px solid #e2e8f0;
}
.scene-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
gap: 8px;
}
.scene-card {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 12px 8px;
background: #f8fafc;
border: 1px solid #e2e8f0;
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease;
min-height: 70px;
}
.scene-card:hover {
background: #dbeafe;
border-color: #3b82f6;
transform: translateY(-2px);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
.scene-card.selected {
background: #dbeafe;
border-color: #3b82f6;
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.3);
}
.scene-icon {
font-size: 1.5rem;
margin-bottom: 4px;
}
.scene-name {
font-size: 0.75rem;
font-weight: 500;
color: #1e293b;
text-align: center;
line-height: 1.2;
}
@media (max-width: 768px) {
.scene-grid {
grid-template-columns: repeat(3, 1fr);
}
}
"""