Implement unified panel styling system with consistent colors and dimensions
This commit is contained in:
parent
50eafcf808
commit
074d6fdb3c
@ -42,6 +42,22 @@ HUD_MARGIN = 10
|
|||||||
LINE_HEIGHT = 20
|
LINE_HEIGHT = 20
|
||||||
SELECTION_THRESHOLD = 3 # pixels
|
SELECTION_THRESHOLD = 3 # pixels
|
||||||
|
|
||||||
|
# Unified Panel Styling System (based on tree widget design)
|
||||||
|
PANEL_BACKGROUND_COLOR = (30, 30, 40) # Dark blue-gray background
|
||||||
|
PANEL_SELECTED_COLOR = (50, 100, 150) # Blue highlight for selected elements
|
||||||
|
PANEL_HOVER_COLOR = (60, 60, 80) # Dark blue highlight for interactive elements
|
||||||
|
PANEL_TEXT_COLOR = (200, 200, 200) # Light gray text
|
||||||
|
PANEL_ICON_COLOR = (150, 150, 150) # Medium gray icons
|
||||||
|
PANEL_BORDER_COLOR = (220, 220, 220) # Light gray borders/dividers
|
||||||
|
|
||||||
|
# Panel spacing and dimensions
|
||||||
|
PANEL_DIVIDER_WIDTH = 0 # No divider lines between panels
|
||||||
|
PANEL_BORDER_WIDTH = 2 # Border width for emphasis elements
|
||||||
|
PANEL_INTERNAL_PADDING = 8 # Standard padding inside panels
|
||||||
|
PANEL_TIGHT_SPACING = 4 # Tight spacing between components
|
||||||
|
PANEL_NODE_HEIGHT = 20 # Height for list/grid items
|
||||||
|
PANEL_INDENTATION = 20 # Indentation per hierarchy level
|
||||||
|
|
||||||
# Simulation settings
|
# Simulation settings
|
||||||
FOOD_SPAWNING = True
|
FOOD_SPAWNING = True
|
||||||
FOOD_OBJECTS_COUNT = 500
|
FOOD_OBJECTS_COUNT = 500
|
||||||
|
|||||||
@ -136,7 +136,6 @@ class InputHandler:
|
|||||||
local_x = mouse_x - inspector_rect.x
|
local_x = mouse_x - inspector_rect.x
|
||||||
local_y = mouse_y - inspector_rect.y
|
local_y = mouse_y - inspector_rect.y
|
||||||
event.pos = (local_x, local_y)
|
event.pos = (local_x, local_y)
|
||||||
print("Passing event to tree widget")
|
|
||||||
self.hud.tree_widget.handle_event(event)
|
self.hud.tree_widget.handle_event(event)
|
||||||
else:
|
else:
|
||||||
# Fallback: always zoom if no HUD reference
|
# Fallback: always zoom if no HUD reference
|
||||||
|
|||||||
@ -269,9 +269,11 @@ class SimulationEngine:
|
|||||||
# Update tree widget
|
# Update tree widget
|
||||||
self.hud.update_tree_widget(deltatime)
|
self.hud.update_tree_widget(deltatime)
|
||||||
|
|
||||||
|
# Draw panel backgrounds first (before pygame_gui UI)
|
||||||
|
self.hud.render_panel_backgrounds(self.screen)
|
||||||
|
|
||||||
# Draw UI elements
|
# Draw UI elements
|
||||||
self.hud.manager.draw_ui(self.screen)
|
self.hud.manager.draw_ui(self.screen)
|
||||||
self.hud.draw_splitters(self.screen)
|
|
||||||
|
|
||||||
# Render tree widget
|
# Render tree widget
|
||||||
self.hud.render_tree_widget(self.screen)
|
self.hud.render_tree_widget(self.screen)
|
||||||
|
|||||||
107
ui/hud.py
107
ui/hud.py
@ -10,9 +10,26 @@ from pygame_gui.elements import UIPanel, UIButton, UITextEntryLine, UILabel
|
|||||||
from ui.tree_widget import TreeWidget
|
from ui.tree_widget import TreeWidget
|
||||||
import math
|
import math
|
||||||
|
|
||||||
|
# Custom HUD colors (preserving existing functionality)
|
||||||
DARK_GRAY = (40, 40, 40)
|
DARK_GRAY = (40, 40, 40)
|
||||||
DARKER_GRAY = (25, 25, 25)
|
DARKER_GRAY = (25, 25, 25)
|
||||||
|
|
||||||
|
|
||||||
|
def create_panel_style(manager: pygame_gui.UIManager) -> dict:
|
||||||
|
"""Create unified styling dictionary for panels."""
|
||||||
|
return {
|
||||||
|
'panel_background': PANEL_BACKGROUND_COLOR,
|
||||||
|
'border_color': PANEL_BORDER_COLOR,
|
||||||
|
'text_color': PANEL_TEXT_COLOR,
|
||||||
|
'internal_padding': PANEL_INTERNAL_PADDING,
|
||||||
|
'border_width': PANEL_BORDER_WIDTH
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def render_panel_divider(surface: pygame.Surface, rect: pygame.Rect):
|
||||||
|
"""Render a thin divider line between panels."""
|
||||||
|
pygame.draw.rect(surface, PANEL_BORDER_COLOR, rect, PANEL_DIVIDER_WIDTH)
|
||||||
|
|
||||||
# Panel visibility constants
|
# Panel visibility constants
|
||||||
SHOW_CONTROL_BAR = True
|
SHOW_CONTROL_BAR = True
|
||||||
SHOW_INSPECTOR_PANEL = True
|
SHOW_INSPECTOR_PANEL = True
|
||||||
@ -50,13 +67,16 @@ class HUD:
|
|||||||
self.world = None # Will be set when world is available
|
self.world = None # Will be set when world is available
|
||||||
self._last_tree_selection = None # Track last selection to avoid unnecessary updates
|
self._last_tree_selection = None # Track last selection to avoid unnecessary updates
|
||||||
|
|
||||||
|
# Initialize unified panel styling
|
||||||
|
self.panel_style = create_panel_style(self.manager)
|
||||||
|
|
||||||
self._create_panels()
|
self._create_panels()
|
||||||
self._create_simulation_controls()
|
self._create_simulation_controls()
|
||||||
|
|
||||||
def _create_panels(self):
|
def _create_panels(self):
|
||||||
self.panels = []
|
self.panels = []
|
||||||
|
|
||||||
# Top control bar
|
# Top control bar - full width, positioned at top
|
||||||
if SHOW_CONTROL_BAR:
|
if SHOW_CONTROL_BAR:
|
||||||
self.control_bar = UIPanel(
|
self.control_bar = UIPanel(
|
||||||
relative_rect=pygame.Rect(0, 0, self.screen_width, self.control_bar_height),
|
relative_rect=pygame.Rect(0, 0, self.screen_width, self.control_bar_height),
|
||||||
@ -67,34 +87,35 @@ class HUD:
|
|||||||
else:
|
else:
|
||||||
self.control_bar = None
|
self.control_bar = None
|
||||||
|
|
||||||
# Left inspector with tree widget
|
# Calculate vertical position for side panels (edge-to-edge with control bar)
|
||||||
|
side_panel_top = self.control_bar_height if SHOW_CONTROL_BAR else 0
|
||||||
|
side_panel_height = self.screen_height - side_panel_top
|
||||||
|
|
||||||
|
# Left inspector panel - edge-to-edge with control bar, no gap
|
||||||
if SHOW_INSPECTOR_PANEL:
|
if SHOW_INSPECTOR_PANEL:
|
||||||
# Create a container panel for the inspector
|
|
||||||
self.inspector_panel = UIPanel(
|
self.inspector_panel = UIPanel(
|
||||||
relative_rect=pygame.Rect(
|
relative_rect=pygame.Rect(
|
||||||
0, self.control_bar_height if SHOW_CONTROL_BAR else 0,
|
0, side_panel_top, # Start right at control bar edge
|
||||||
self.inspector_width,
|
self.inspector_width,
|
||||||
self.screen_height - (self.control_bar_height if SHOW_CONTROL_BAR else 0)
|
side_panel_height # Extend to bottom edge
|
||||||
),
|
),
|
||||||
manager=self.manager,
|
manager=self.manager,
|
||||||
object_id="#inspector_panel",
|
object_id="#inspector_panel",
|
||||||
)
|
)
|
||||||
self.panels.append(self.inspector_panel)
|
self.panels.append(self.inspector_panel)
|
||||||
|
|
||||||
# Tree widget will be created when world is available
|
|
||||||
self.tree_widget = None
|
self.tree_widget = None
|
||||||
else:
|
else:
|
||||||
self.inspector_panel = None
|
self.inspector_panel = None
|
||||||
self.tree_widget = None
|
self.tree_widget = None
|
||||||
|
|
||||||
# Right properties
|
# Right properties panel - edge-to-edge with control bar, no gap
|
||||||
if SHOW_PROPERTIES_PANEL:
|
if SHOW_PROPERTIES_PANEL:
|
||||||
self.properties_panel = UIPanel(
|
self.properties_panel = UIPanel(
|
||||||
relative_rect=pygame.Rect(
|
relative_rect=pygame.Rect(
|
||||||
self.screen_width - self.properties_width,
|
self.screen_width - self.properties_width, # Precisely at right edge
|
||||||
self.control_bar_height if SHOW_CONTROL_BAR else 0,
|
side_panel_top, # Align with control bar
|
||||||
self.properties_width,
|
self.properties_width,
|
||||||
self.screen_height - (self.control_bar_height if SHOW_CONTROL_BAR else 0)
|
side_panel_height # Extend to bottom edge
|
||||||
),
|
),
|
||||||
manager=self.manager,
|
manager=self.manager,
|
||||||
object_id="#properties_panel",
|
object_id="#properties_panel",
|
||||||
@ -103,13 +124,16 @@ class HUD:
|
|||||||
else:
|
else:
|
||||||
self.properties_panel = None
|
self.properties_panel = None
|
||||||
|
|
||||||
# Bottom console
|
# Bottom console panel - edge-to-edge with side panels, no gap
|
||||||
if SHOW_CONSOLE_PANEL:
|
if SHOW_CONSOLE_PANEL:
|
||||||
|
console_left = self.inspector_width if SHOW_INSPECTOR_PANEL else 0
|
||||||
|
console_width = self.screen_width - console_left - (self.properties_width if SHOW_PROPERTIES_PANEL else 0)
|
||||||
|
|
||||||
self.console_panel = UIPanel(
|
self.console_panel = UIPanel(
|
||||||
relative_rect=pygame.Rect(
|
relative_rect=pygame.Rect(
|
||||||
self.inspector_width if SHOW_INSPECTOR_PANEL else 0,
|
console_left, # Start right at inspector edge
|
||||||
self.screen_height - self.console_height,
|
self.screen_height - self.console_height, # Exactly at bottom edge
|
||||||
self.screen_width - (self.inspector_width if SHOW_INSPECTOR_PANEL else 0) - (self.properties_width if SHOW_PROPERTIES_PANEL else 0),
|
console_width, # Fill space between side panels
|
||||||
self.console_height
|
self.console_height
|
||||||
),
|
),
|
||||||
manager=self.manager,
|
manager=self.manager,
|
||||||
@ -139,17 +163,55 @@ class HUD:
|
|||||||
self.tree_widget.select_entities(selected_objects)
|
self.tree_widget.select_entities(selected_objects)
|
||||||
self._last_tree_selection = current_selection
|
self._last_tree_selection = current_selection
|
||||||
|
|
||||||
|
def render_panel_backgrounds(self, screen: pygame.Surface):
|
||||||
|
"""Render panel backgrounds with consistent colors before UI elements."""
|
||||||
|
|
||||||
|
# Render control bar background to match inspector panel
|
||||||
|
if SHOW_CONTROL_BAR and self.control_bar:
|
||||||
|
control_bg_rect = pygame.Rect(
|
||||||
|
0, 0,
|
||||||
|
self.screen_width,
|
||||||
|
self.control_bar_height
|
||||||
|
)
|
||||||
|
pygame.draw.rect(screen, PANEL_BACKGROUND_COLOR, control_bg_rect)
|
||||||
|
|
||||||
|
# Render console panel background to match inspector panel
|
||||||
|
if SHOW_CONSOLE_PANEL and self.console_panel:
|
||||||
|
console_bg_rect = pygame.Rect(
|
||||||
|
self.console_panel.rect.x,
|
||||||
|
self.console_panel.rect.y,
|
||||||
|
self.console_panel.rect.width,
|
||||||
|
self.console_panel.rect.height
|
||||||
|
)
|
||||||
|
pygame.draw.rect(screen, PANEL_BACKGROUND_COLOR, console_bg_rect)
|
||||||
|
|
||||||
|
# Render properties panel background to match inspector panel
|
||||||
|
if SHOW_PROPERTIES_PANEL and self.properties_panel:
|
||||||
|
properties_bg_rect = pygame.Rect(
|
||||||
|
self.properties_panel.rect.x,
|
||||||
|
self.properties_panel.rect.y,
|
||||||
|
self.properties_panel.rect.width,
|
||||||
|
self.properties_panel.rect.height
|
||||||
|
)
|
||||||
|
pygame.draw.rect(screen, PANEL_BACKGROUND_COLOR, properties_bg_rect)
|
||||||
|
|
||||||
|
def render_panel_dividers(self, screen: pygame.Surface):
|
||||||
|
"""Render consistent panel sliders with proper rendering order."""
|
||||||
|
|
||||||
|
# Render consistent panel sliders
|
||||||
|
self.draw_splitters(screen)
|
||||||
|
|
||||||
def _create_simulation_controls(self):
|
def _create_simulation_controls(self):
|
||||||
"""Create simulation control buttons in the control bar."""
|
"""Create simulation control buttons in the control bar."""
|
||||||
if not self.control_bar:
|
if not self.control_bar:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Button layout constants
|
# Button layout constants (using standardized spacing)
|
||||||
button_width = 40
|
button_width = 40
|
||||||
button_height = 32
|
button_height = 32
|
||||||
button_spacing = 8
|
button_spacing = PANEL_TIGHT_SPACING # Using standardized tight spacing
|
||||||
start_x = 20
|
start_x = PANEL_INTERNAL_PADDING # Using standardized internal padding
|
||||||
start_y = 8
|
start_y = PANEL_TIGHT_SPACING # Using standardized tight spacing
|
||||||
|
|
||||||
# Play/Pause button
|
# Play/Pause button
|
||||||
self.play_pause_button = UIButton(
|
self.play_pause_button = UIButton(
|
||||||
@ -444,8 +506,8 @@ class HUD:
|
|||||||
self.update_layout(self.screen_width, self.screen_height)
|
self.update_layout(self.screen_width, self.screen_height)
|
||||||
|
|
||||||
def draw_splitters(self, screen):
|
def draw_splitters(self, screen):
|
||||||
# Draw draggable splitters for visual feedback
|
# Draw draggable splitters for visual feedback with consistent styling
|
||||||
indicator_color = (220, 220, 220)
|
indicator_color = PANEL_ICON_COLOR # Use standardized icon color for consistency
|
||||||
indicator_size = 6 # Length of indicator line
|
indicator_size = 6 # Length of indicator line
|
||||||
indicator_gap = 4 # Gap between indicator lines
|
indicator_gap = 4 # Gap between indicator lines
|
||||||
indicator_count = 3 # Number of indicator lines
|
indicator_count = 3 # Number of indicator lines
|
||||||
@ -985,3 +1047,6 @@ class HUD:
|
|||||||
# Create a surface for the tree widget area
|
# Create a surface for the tree widget area
|
||||||
tree_surface = screen.subsurface(self.inspector_panel.rect)
|
tree_surface = screen.subsurface(self.inspector_panel.rect)
|
||||||
self.tree_widget.draw(tree_surface)
|
self.tree_widget.draw(tree_surface)
|
||||||
|
|
||||||
|
# Render panel dividers for visual consistency
|
||||||
|
self.render_panel_dividers(screen)
|
||||||
|
|||||||
@ -6,6 +6,7 @@ Provides extensible tree structure for entity inspection.
|
|||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from typing import List, Optional, Dict, Any
|
from typing import List, Optional, Dict, Any
|
||||||
import pygame
|
import pygame
|
||||||
|
from config.constants import PANEL_NODE_HEIGHT, PANEL_INDENTATION
|
||||||
|
|
||||||
|
|
||||||
class TreeNode(ABC):
|
class TreeNode(ABC):
|
||||||
@ -18,7 +19,7 @@ class TreeNode(ABC):
|
|||||||
self.is_expanded = False
|
self.is_expanded = False
|
||||||
self.is_selected = False
|
self.is_selected = False
|
||||||
self.depth = 0 if parent is None else parent.depth + 1
|
self.depth = 0 if parent is None else parent.depth + 1
|
||||||
self.rect = pygame.Rect(0, 0, 0, 20) # Will be updated during layout
|
self.rect = pygame.Rect(0, 0, 0, PANEL_NODE_HEIGHT) # Will be updated during layout
|
||||||
|
|
||||||
def add_child(self, child: 'TreeNode') -> None:
|
def add_child(self, child: 'TreeNode') -> None:
|
||||||
"""Add a child node to this node."""
|
"""Add a child node to this node."""
|
||||||
@ -77,7 +78,7 @@ class TreeNode(ABC):
|
|||||||
|
|
||||||
def get_indent(self) -> int:
|
def get_indent(self) -> int:
|
||||||
"""Get the indentation width for this node."""
|
"""Get the indentation width for this node."""
|
||||||
return self.depth * 20
|
return self.depth * PANEL_INDENTATION
|
||||||
|
|
||||||
|
|
||||||
class SimulationNode(TreeNode):
|
class SimulationNode(TreeNode):
|
||||||
|
|||||||
@ -8,6 +8,10 @@ import pygame_gui
|
|||||||
from pygame_gui.core import UIElement
|
from pygame_gui.core import UIElement
|
||||||
from typing import List, Optional, Tuple, Any
|
from typing import List, Optional, Tuple, Any
|
||||||
from ui.inspector_tree import TreeNode, SimulationNode, TreeSelectionManager
|
from ui.inspector_tree import TreeNode, SimulationNode, TreeSelectionManager
|
||||||
|
from config.constants import (
|
||||||
|
PANEL_BACKGROUND_COLOR, PANEL_SELECTED_COLOR, PANEL_HOVER_COLOR,
|
||||||
|
PANEL_TEXT_COLOR, PANEL_ICON_COLOR, PANEL_NODE_HEIGHT, PANEL_INDENTATION
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TreeWidget(UIElement):
|
class TreeWidget(UIElement):
|
||||||
@ -29,14 +33,14 @@ class TreeWidget(UIElement):
|
|||||||
# Selection management
|
# Selection management
|
||||||
self.selection_manager = TreeSelectionManager()
|
self.selection_manager = TreeSelectionManager()
|
||||||
|
|
||||||
# Visual properties
|
# Visual properties (using standardized panel styling)
|
||||||
self.node_height = 20
|
self.node_height = PANEL_NODE_HEIGHT
|
||||||
self.expand_collapse_width = 20
|
self.expand_collapse_width = PANEL_INDENTATION
|
||||||
self.icon_size = 8
|
self.icon_size = 8
|
||||||
self.text_color = (200, 200, 200)
|
self.text_color = PANEL_TEXT_COLOR
|
||||||
self.selected_color = (50, 100, 150)
|
self.selected_color = PANEL_SELECTED_COLOR
|
||||||
self.hover_color = (60, 60, 80)
|
self.hover_color = PANEL_HOVER_COLOR
|
||||||
self.expand_icon_color = (150, 150, 150)
|
self.expand_icon_color = PANEL_ICON_COLOR
|
||||||
|
|
||||||
# Interaction state
|
# Interaction state
|
||||||
self.hovered_node: Optional[TreeNode] = None
|
self.hovered_node: Optional[TreeNode] = None
|
||||||
@ -253,7 +257,7 @@ class TreeWidget(UIElement):
|
|||||||
"""Draw the tree widget."""
|
"""Draw the tree widget."""
|
||||||
# Create a clipping surface for the tree area
|
# Create a clipping surface for the tree area
|
||||||
tree_surface = pygame.Surface((self.rect.width, self.rect.height))
|
tree_surface = pygame.Surface((self.rect.width, self.rect.height))
|
||||||
tree_surface.fill((30, 30, 40)) # Background color
|
tree_surface.fill(PANEL_BACKGROUND_COLOR) # Using standardized background color
|
||||||
|
|
||||||
# Set up clipping rect to prevent rendering outside bounds
|
# Set up clipping rect to prevent rendering outside bounds
|
||||||
clip_rect = pygame.Rect(0, 0, self.rect.width, self.rect.height)
|
clip_rect = pygame.Rect(0, 0, self.rect.width, self.rect.height)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user