""" 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) }