Spaces:
Sleeping
Sleeping
| """ | |
| 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() | |