Spaces:
Sleeping
Sleeping
| """ | |
| UI Tools | |
| 2D overlay elements for text, bars, and HUD components | |
| """ | |
| from typing import Dict, Any, Optional | |
| from backend.storage import storage | |
| def render_text_on_screen( | |
| scene_id: str, | |
| text: str, | |
| x: float = 50.0, | |
| y: float = 10.0, | |
| font_size: int = 24, | |
| color: str = "#ffffff", | |
| text_id: Optional[str] = None, | |
| font_family: str = "Arial", | |
| text_align: str = "center", | |
| background_color: Optional[str] = None, | |
| padding: int = 8 | |
| ) -> Dict[str, Any]: | |
| """ | |
| Render text on the screen as a 2D overlay. | |
| Args: | |
| scene_id: ID of the scene | |
| text: The text to display | |
| x: Horizontal position in percentage (0=left edge, 50=center, 100=right edge) | |
| y: Vertical position in percentage (0=top edge, 50=center, 100=bottom edge) | |
| font_size: Font size in pixels (default: 24) | |
| color: Text color as hex (default: "#ffffff") | |
| text_id: Optional unique identifier for this text element (for updates/removal) | |
| font_family: CSS font family (default: "Arial") | |
| text_align: Text alignment - "left", "center", "right" (default: "center") | |
| background_color: Optional background color (e.g., "#000000" for black box behind text) | |
| padding: Padding around text in pixels when background is set (default: 8) | |
| Returns: | |
| Dictionary with text element info and message | |
| """ | |
| scene = storage.get(scene_id) | |
| if not scene: | |
| raise ValueError(f"Scene '{scene_id}' not found") | |
| if "ui_elements" not in scene: | |
| scene["ui_elements"] = [] | |
| # Generate ID if not provided | |
| if not text_id: | |
| text_id = f"text_{len([e for e in scene['ui_elements'] if e.get('element_type') == 'text'])}" | |
| # Remove existing element with same ID (update behavior) | |
| scene["ui_elements"] = [e for e in scene["ui_elements"] if e.get("id") != text_id] | |
| # Clamp position values | |
| x = max(0.0, min(100.0, x)) | |
| y = max(0.0, min(100.0, y)) | |
| text_element = { | |
| "id": text_id, | |
| "element_type": "text", | |
| "text": text, | |
| "x": x, | |
| "y": y, | |
| "font_size": font_size, | |
| "color": color, | |
| "font_family": font_family, | |
| "text_align": text_align, | |
| "background_color": background_color, | |
| "padding": padding, | |
| "visible": True | |
| } | |
| scene["ui_elements"].append(text_element) | |
| storage.save(scene) | |
| return { | |
| "scene_id": scene_id, | |
| "text_id": text_id, | |
| "message": f"Rendered text '{text[:30]}{'...' if len(text) > 30 else ''}' at ({x}%, {y}%)", | |
| "text_element": text_element | |
| } | |
| def render_bar_on_screen( | |
| scene_id: str, | |
| x: float = 10.0, | |
| y: float = 10.0, | |
| width: float = 200.0, | |
| height: float = 20.0, | |
| value: float = 100.0, | |
| max_value: float = 100.0, | |
| bar_color: str = "#00ff00", | |
| background_color: str = "#333333", | |
| border_color: Optional[str] = "#ffffff", | |
| bar_id: Optional[str] = None, | |
| label: Optional[str] = None, | |
| show_value: bool = False | |
| ) -> Dict[str, Any]: | |
| """ | |
| Render a progress/health bar on the screen as a 2D overlay. | |
| Args: | |
| scene_id: ID of the scene | |
| x: Horizontal position in percentage (0=left edge, 50=center, 100=right edge) | |
| y: Vertical position in percentage (0=top edge, 50=center, 100=bottom edge) | |
| width: Bar width in pixels (default: 200) | |
| height: Bar height in pixels (default: 20) | |
| value: Current value (default: 100) | |
| max_value: Maximum value (default: 100) | |
| bar_color: Fill color for the bar (default: "#00ff00" green) | |
| background_color: Background color (default: "#333333" dark gray) | |
| border_color: Optional border color (default: "#ffffff" white) | |
| bar_id: Optional unique identifier for this bar (for updates/removal) | |
| label: Optional label text above the bar | |
| show_value: Show numeric value on the bar (default: False) | |
| Returns: | |
| Dictionary with bar element info and message | |
| """ | |
| scene = storage.get(scene_id) | |
| if not scene: | |
| raise ValueError(f"Scene '{scene_id}' not found") | |
| if "ui_elements" not in scene: | |
| scene["ui_elements"] = [] | |
| # Generate ID if not provided | |
| if not bar_id: | |
| bar_id = f"bar_{len([e for e in scene['ui_elements'] if e.get('element_type') == 'bar'])}" | |
| # Remove existing element with same ID (update behavior) | |
| scene["ui_elements"] = [e for e in scene["ui_elements"] if e.get("id") != bar_id] | |
| # Clamp values | |
| x = max(0.0, min(100.0, x)) | |
| y = max(0.0, min(100.0, y)) | |
| value = max(0.0, min(max_value, value)) | |
| percentage = (value / max_value) * 100.0 if max_value > 0 else 0.0 | |
| bar_element = { | |
| "id": bar_id, | |
| "element_type": "bar", | |
| "x": x, | |
| "y": y, | |
| "width": width, | |
| "height": height, | |
| "value": value, | |
| "max_value": max_value, | |
| "percentage": percentage, | |
| "bar_color": bar_color, | |
| "background_color": background_color, | |
| "border_color": border_color, | |
| "label": label, | |
| "show_value": show_value, | |
| "visible": True | |
| } | |
| scene["ui_elements"].append(bar_element) | |
| storage.save(scene) | |
| label_str = f"'{label}' " if label else "" | |
| return { | |
| "scene_id": scene_id, | |
| "bar_id": bar_id, | |
| "message": f"Rendered {label_str}bar at ({x}%, {y}%) - {value}/{max_value} ({percentage:.0f}%)", | |
| "bar_element": bar_element | |
| } | |
| def remove_ui_element(scene_id: str, element_id: str) -> Dict[str, Any]: | |
| """ | |
| Remove a UI element from the screen. | |
| Args: | |
| scene_id: ID of the scene | |
| element_id: ID of the UI element to remove (text_id or bar_id) | |
| Returns: | |
| Dictionary with confirmation message | |
| """ | |
| scene = storage.get(scene_id) | |
| if not scene: | |
| raise ValueError(f"Scene '{scene_id}' not found") | |
| if "ui_elements" not in scene or not scene["ui_elements"]: | |
| raise ValueError("Scene has no UI elements") | |
| original_count = len(scene["ui_elements"]) | |
| scene["ui_elements"] = [e for e in scene["ui_elements"] if e.get("id") != element_id] | |
| if len(scene["ui_elements"]) == original_count: | |
| raise ValueError(f"UI element '{element_id}' not found") | |
| storage.save(scene) | |
| return { | |
| "scene_id": scene_id, | |
| "message": f"Removed UI element '{element_id}'", | |
| "element_id": element_id | |
| } | |
| def get_ui_elements(scene_id: str) -> Dict[str, Any]: | |
| """ | |
| Get all UI elements in the scene. | |
| Args: | |
| scene_id: ID of the scene | |
| Returns: | |
| Dictionary with all UI elements | |
| """ | |
| scene = storage.get(scene_id) | |
| if not scene: | |
| raise ValueError(f"Scene '{scene_id}' not found") | |
| ui_elements = scene.get("ui_elements", []) | |
| return { | |
| "scene_id": scene_id, | |
| "ui_elements": ui_elements, | |
| "count": len(ui_elements) | |
| } | |