|
|
""" |
|
|
Data models for GCP - Game Context Protocol |
|
|
Using plain dictionaries for simplicity and clarity. |
|
|
""" |
|
|
from typing import Optional, Literal, Dict, Any, List |
|
|
from datetime import datetime |
|
|
import uuid |
|
|
|
|
|
|
|
|
|
|
|
ObjectType = Literal["cube", "sphere", "cylinder", "plane", "cone", "torus", "model"] |
|
|
LightType = Literal["ambient", "directional", "point", "spot", "hemisphere"] |
|
|
LightingPreset = Literal["day", "night", "sunset", "studio"] |
|
|
CameraMode = Literal["fps", "orbit", "top_down", "free"] |
|
|
MaterialType = Literal["standard", "basic", "phong", "toon"] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def create_vector3(x: float = 0.0, y: float = 0.0, z: float = 0.0) -> Dict[str, float]: |
|
|
"""Create a 3D vector for position, rotation, or scale.""" |
|
|
return {"x": x, "y": y, "z": z} |
|
|
|
|
|
|
|
|
def create_material( |
|
|
type: MaterialType = "standard", |
|
|
color: str = "#ffffff", |
|
|
metalness: float = 0.5, |
|
|
roughness: float = 0.5, |
|
|
opacity: float = 1.0, |
|
|
wireframe: bool = False |
|
|
) -> Dict[str, Any]: |
|
|
"""Create material properties.""" |
|
|
return { |
|
|
"type": type, |
|
|
"color": color, |
|
|
"metalness": metalness, |
|
|
"roughness": roughness, |
|
|
"opacity": opacity, |
|
|
"wireframe": wireframe |
|
|
} |
|
|
|
|
|
|
|
|
def create_game_object( |
|
|
object_type: ObjectType = "cube", |
|
|
name: Optional[str] = None, |
|
|
position: Optional[Dict[str, float]] = None, |
|
|
rotation: Optional[Dict[str, float]] = None, |
|
|
scale: Optional[Dict[str, float]] = None, |
|
|
material: Optional[Dict[str, Any]] = None, |
|
|
model_path: Optional[str] = None, |
|
|
metadata: Optional[Dict[str, Any]] = None |
|
|
) -> Dict[str, Any]: |
|
|
"""Create a 3D game object.""" |
|
|
return { |
|
|
"id": str(uuid.uuid4()), |
|
|
"name": name, |
|
|
"type": object_type, |
|
|
"position": position or create_vector3(), |
|
|
"rotation": rotation or create_vector3(), |
|
|
"scale": scale or create_vector3(1, 1, 1), |
|
|
"material": material or create_material(), |
|
|
"model_path": model_path, |
|
|
"metadata": metadata or {}, |
|
|
"created_at": datetime.utcnow().isoformat() |
|
|
} |
|
|
|
|
|
|
|
|
def create_light( |
|
|
light_type: LightType = "directional", |
|
|
name: Optional[str] = None, |
|
|
color: str = "#ffffff", |
|
|
intensity: float = 1.0, |
|
|
position: Optional[Dict[str, float]] = None, |
|
|
target: Optional[Dict[str, float]] = None, |
|
|
cast_shadow: bool = True, |
|
|
ground_color: Optional[str] = None, |
|
|
distance: Optional[float] = None, |
|
|
decay: float = 2.0 |
|
|
) -> Dict[str, Any]: |
|
|
""" |
|
|
Create a light source. |
|
|
|
|
|
Args: |
|
|
light_type: Type of light (ambient, directional, point, spot, hemisphere) |
|
|
name: Light name for identification |
|
|
color: Light color in hex format (sky color for hemisphere) |
|
|
intensity: Light intensity (0.0-2.0 typical, higher for specific effects) |
|
|
position: Light position in 3D space |
|
|
target: Target position for directional/spot lights |
|
|
cast_shadow: Whether the light casts shadows (directional/spot only) |
|
|
ground_color: Ground color for hemisphere lights (defaults to darker version of color) |
|
|
distance: Maximum range for point/spot lights (0 = infinite) |
|
|
decay: Light falloff rate for point/spot (2.0 = physically correct) |
|
|
""" |
|
|
light = { |
|
|
"id": str(uuid.uuid4()), |
|
|
"name": name, |
|
|
"type": light_type, |
|
|
"color": color, |
|
|
"intensity": intensity, |
|
|
"position": position or create_vector3(10, 10, 10), |
|
|
"target": target, |
|
|
"cast_shadow": cast_shadow, |
|
|
} |
|
|
|
|
|
|
|
|
if light_type == "hemisphere": |
|
|
light["ground_color"] = ground_color or "#444444" |
|
|
|
|
|
|
|
|
if light_type in ["point", "spot"]: |
|
|
if distance is not None: |
|
|
light["distance"] = distance |
|
|
light["decay"] = decay |
|
|
|
|
|
return light |
|
|
|
|
|
|
|
|
def create_environment( |
|
|
background_color: str = "#87CEEB", |
|
|
fog_enabled: bool = False, |
|
|
fog_color: str = "#ffffff", |
|
|
fog_near: float = 10.0, |
|
|
fog_far: float = 100.0, |
|
|
ambient_light_intensity: float = 0.5, |
|
|
lighting_preset: LightingPreset = "day" |
|
|
) -> Dict[str, Any]: |
|
|
"""Create environment settings.""" |
|
|
return { |
|
|
"background_color": background_color, |
|
|
"fog_enabled": fog_enabled, |
|
|
"fog_color": fog_color, |
|
|
"fog_near": fog_near, |
|
|
"fog_far": fog_far, |
|
|
"ambient_light_intensity": ambient_light_intensity, |
|
|
"lighting_preset": lighting_preset |
|
|
} |
|
|
|
|
|
|
|
|
def create_player( |
|
|
position: Optional[Dict[str, float]] = None, |
|
|
rotation: Optional[Dict[str, float]] = None, |
|
|
camera_mode: CameraMode = "orbit", |
|
|
movement_speed: float = 5.0, |
|
|
look_sensitivity: float = 0.002 |
|
|
) -> Dict[str, Any]: |
|
|
"""Create player/camera configuration.""" |
|
|
return { |
|
|
"position": position or create_vector3(0, 5, 10), |
|
|
"rotation": rotation or create_vector3(), |
|
|
"camera_mode": camera_mode, |
|
|
"movement_speed": movement_speed, |
|
|
"look_sensitivity": look_sensitivity |
|
|
} |
|
|
|
|
|
|
|
|
def create_player_config( |
|
|
move_speed: float = 8.0, |
|
|
jump_force: float = 5.0, |
|
|
mouse_sensitivity: float = 0.002, |
|
|
invert_y: bool = False, |
|
|
gravity: float = -9.82, |
|
|
player_height: float = 1.7, |
|
|
player_radius: float = 0.3, |
|
|
eye_height: float = 1.6, |
|
|
player_mass: float = 80.0, |
|
|
linear_damping: float = 0.0, |
|
|
movement_acceleration: float = 0.0, |
|
|
air_control: float = 1.0, |
|
|
camera_fov: float = 75.0, |
|
|
min_pitch: float = -89.0, |
|
|
max_pitch: float = 89.0 |
|
|
) -> Dict[str, Any]: |
|
|
""" |
|
|
Create player controller configuration for FPS mode. |
|
|
|
|
|
Args: |
|
|
move_speed: Horizontal movement speed in units/second |
|
|
jump_force: Initial upward velocity for jumps in m/s |
|
|
mouse_sensitivity: Mouse look sensitivity multiplier |
|
|
invert_y: Whether to invert vertical mouse look |
|
|
gravity: World gravity in m/s² (negative = downward) |
|
|
player_height: Player collision capsule height in meters |
|
|
player_radius: Player collision capsule radius in meters |
|
|
eye_height: Camera height from player feet in meters |
|
|
player_mass: Player body mass in kg |
|
|
linear_damping: Air resistance (0.0-1.0, higher = more friction) |
|
|
movement_acceleration: Acceleration time (0.0=instant, higher=slower) |
|
|
air_control: Movement control while airborne (0.0-1.0) |
|
|
camera_fov: Field of view in degrees (typical: 60-90) |
|
|
min_pitch: Minimum vertical look angle in degrees (looking down) |
|
|
max_pitch: Maximum vertical look angle in degrees (looking up) |
|
|
|
|
|
Returns: |
|
|
Dictionary with player controller configuration |
|
|
""" |
|
|
return { |
|
|
"move_speed": move_speed, |
|
|
"jump_force": jump_force, |
|
|
"mouse_sensitivity": mouse_sensitivity, |
|
|
"invert_y": invert_y, |
|
|
"gravity": gravity, |
|
|
"player_height": player_height, |
|
|
"player_radius": player_radius, |
|
|
"eye_height": eye_height, |
|
|
"player_mass": player_mass, |
|
|
"linear_damping": linear_damping, |
|
|
"movement_acceleration": movement_acceleration, |
|
|
"air_control": air_control, |
|
|
"camera_fov": camera_fov, |
|
|
"min_pitch": min_pitch, |
|
|
"max_pitch": max_pitch |
|
|
} |
|
|
|
|
|
|
|
|
def create_scene( |
|
|
name: str = "Untitled Scene", |
|
|
description: Optional[str] = None, |
|
|
world_width: float = 100.0, |
|
|
world_height: float = 100.0, |
|
|
world_depth: float = 100.0, |
|
|
objects: Optional[List[Dict[str, Any]]] = None, |
|
|
lights: Optional[List[Dict[str, Any]]] = None, |
|
|
environment: Optional[Dict[str, Any]] = None, |
|
|
player: Optional[Dict[str, Any]] = None, |
|
|
show_grid: bool = False, |
|
|
grid_size: float = 100.0, |
|
|
grid_divisions: int = 20, |
|
|
tags: Optional[List[str]] = None |
|
|
) -> Dict[str, Any]: |
|
|
"""Create a complete 3D scene.""" |
|
|
now = datetime.utcnow().isoformat() |
|
|
return { |
|
|
"scene_id": str(uuid.uuid4()), |
|
|
"name": name, |
|
|
"description": description, |
|
|
"world_width": world_width, |
|
|
"world_height": world_height, |
|
|
"world_depth": world_depth, |
|
|
"objects": objects or [], |
|
|
"lights": lights or [], |
|
|
"environment": environment or create_environment(), |
|
|
"player": player or create_player(), |
|
|
"show_grid": show_grid, |
|
|
"grid_size": grid_size, |
|
|
"grid_divisions": grid_divisions, |
|
|
"tags": tags or [], |
|
|
"created_at": now, |
|
|
"updated_at": now |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def validate_vector3(v: Dict[str, float]) -> bool: |
|
|
"""Check if a dict is a valid Vector3.""" |
|
|
return isinstance(v, dict) and all(k in v for k in ["x", "y", "z"]) |
|
|
|
|
|
|
|
|
def validate_lighting_preset(preset: str) -> bool: |
|
|
"""Check if a string is a valid lighting preset.""" |
|
|
return preset in ["day", "night", "sunset", "studio"] |
|
|
|
|
|
|
|
|
def validate_object_type(obj_type: str) -> bool: |
|
|
"""Check if a string is a valid object type.""" |
|
|
return obj_type in ["cube", "sphere", "cylinder", "plane", "cone", "torus", "model"] |
|
|
|