""" In-memory storage for game scenes """ from typing import Dict, Optional, Any from datetime import datetime class Storage: """Simple in-memory storage for game scenes using plain dictionaries""" def __init__(self): self._scenes: Dict[str, Dict[str, Any]] = {} def save(self, scene: Dict[str, Any]) -> Dict[str, Any]: """Save or update a scene""" if not isinstance(scene, dict): raise ValueError("Scene must be a dictionary") if "scene_id" not in scene: raise ValueError("Scene must have a 'scene_id' key") # Update timestamp scene["updated_at"] = datetime.utcnow().isoformat() self._scenes[scene["scene_id"]] = scene return scene def get(self, scene_id: str) -> Optional[Dict[str, Any]]: """Retrieve a scene by ID""" return self._scenes.get(scene_id) def delete(self, scene_id: str) -> bool: """Delete a scene""" if scene_id in self._scenes: del self._scenes[scene_id] return True return False def list_all(self) -> list[Dict[str, Any]]: """List all scenes""" return list(self._scenes.values()) def exists(self, scene_id: str) -> bool: """Check if scene exists""" return scene_id in self._scenes # Global storage instance storage = Storage() # Initialize with an impressive default Welcome Scene for HuggingFace Spaces def initialize_default_scene(): """Create a visually impressive Welcome Scene on startup""" from backend.game_models import ( create_scene, create_light, create_environment, create_vector3, create_game_object, create_material ) # Create lights using Three.js best practices: # - Ambient: Low intensity (~0.1-0.2) to fake light bounce without washing out scene # - Directional: Main sun light with warm color for outdoor feel # - Secondary directional: Fill light from opposite side to soften shadows # - Point lights: Distributed around arena for even coverage lights = [ # Main directional light (sun) - warm sunset color, positioned for dramatic shadows create_light( name="Sun", light_type="directional", color="#ffd4a3", # Warm sunlight (less saturated orange) intensity=1.5, position=create_vector3(10, 20, 10), cast_shadow=True, ), # Fill light - cooler blue from opposite side to balance shadows create_light( name="FillLight", light_type="directional", color="#a3c4ff", # Cool blue fill intensity=0.4, position=create_vector3(-10, 15, -5), ), # Ambient light - very low intensity to simulate indirect light bounce create_light( name="Ambient", light_type="ambient", color="#404060", # Slightly blue-ish for natural feel intensity=0.2, ), # === Arena Point Lights (distributed for even coverage) === # Center light - main arena illumination create_light( name="ArenaCenter", light_type="point", color="#ffffff", # Neutral white intensity=1.0, position=create_vector3(0, 10, 0), distance=30, ), # Corner lights - warm tones for cozy feel create_light( name="ArenaCornerNE", light_type="point", color="#ffcc88", # Warm intensity=0.6, position=create_vector3(8, 6, 8), distance=20, ), create_light( name="ArenaCornerNW", light_type="point", color="#ffcc88", # Warm intensity=0.6, position=create_vector3(-8, 6, 8), distance=20, ), create_light( name="ArenaCornerSE", light_type="point", color="#88ccff", # Cool blue intensity=0.5, position=create_vector3(8, 6, -8), distance=20, ), create_light( name="ArenaCornerSW", light_type="point", color="#88ccff", # Cool blue intensity=0.5, position=create_vector3(-8, 6, -8), distance=20, ), ] # Create environment with sunset preset env = create_environment( lighting_preset="sunset", background_color="#1a0a20", # Dark purple (will be overridden by skybox) ) # Hugging Face emoji model at center (animated + unlit for true colors) objects = [ create_game_object( object_type="model", name="HuggingFace", position=create_vector3(0, 1.5, 0), scale=create_vector3(3, 3, 3), model_path="Norod78/huggingface_emoji.glb", metadata={"animate": True, "baseY": 1.5, "unlit": True}, ), ] # Create scene with starter objects scene = create_scene( name="Welcome to GCP", description="AI-powered 3D scene builder - Try 'add a red sphere' or 'set lighting to night'", world_width=25, world_height=10, world_depth=25, objects=objects, lights=lights, environment=env, ) # Use a predictable scene ID for easy linking scene["scene_id"] = "welcome" # Add skybox configuration (sunset preset) scene["skybox"] = { "preset": "sunset", "turbidity": 8, "rayleigh": 2, "elevation": 5, "azimuth": 180 } # Save to storage storage.save(scene) print(f"✓ Initialized Welcome Scene (ID: welcome)") print(f" - 25x25 world with sunset skybox") print(f" - Hugging Face emoji model at center (unlit)") print(f" - 8-light setup: Sun + Fill + Ambient + 5 arena point lights") print(f" - FPS physics controller ready") # Initialize on module load initialize_default_scene()