Refactor HUD action handling and improve input callback setup

This commit is contained in:
Sam 2025-11-08 20:17:33 -06:00
parent 36d13a53a0
commit 6d5ea1ae10

View File

@ -27,6 +27,16 @@ class SimulationEngine:
self._init_ui()
self.running = True
# HUD action handlers registry for extensibility
self._hud_action_handlers = {
'toggle_pause': self.simulation_core.toggle_pause,
'step_forward': self.simulation_core.step,
'toggle_sprint': self.simulation_core.toggle_sprint_mode,
'viewport_resized': self._update_simulation_view,
'set_speed': self.simulation_core.set_speed_multiplier,
'set_custom_tps': self.simulation_core.set_tps,
}
def _profile_single_tick(self):
"""Profile a single tick for performance analysis."""
profiler = cProfile.Profile()
@ -83,11 +93,7 @@ class SimulationEngine:
self.input_handler.default_tps = DEFAULT_TPS
# Set up action callbacks for input handler
self.input_handler.set_action_callback('toggle_pause', self.simulation_core.toggle_pause)
self.input_handler.set_action_callback('step_forward', self.simulation_core.step)
self.input_handler.set_action_callback('set_speed', self.simulation_core.set_speed_multiplier)
self.input_handler.set_action_callback('set_custom_tps', self.simulation_core.set_tps)
self.input_handler.set_action_callback('toggle_sprint', self.simulation_core.toggle_sprint_mode)
self._setup_input_handler_callbacks()
# Setup renderer
self.renderer = Renderer(self.sim_view)
@ -112,6 +118,19 @@ class SimulationEngine:
# Update input handler simulation view rect
self.input_handler.update_sim_view_rect(self.sim_view_rect)
def _setup_input_handler_callbacks(self):
"""Set up action callbacks for input handler."""
callbacks = {
'toggle_pause': self.simulation_core.toggle_pause,
'step_forward': self.simulation_core.step,
'set_speed': self.simulation_core.set_speed_multiplier,
'set_custom_tps': self.simulation_core.set_tps,
'toggle_sprint': self.simulation_core.toggle_sprint_mode,
}
for action, callback in callbacks.items():
self.input_handler.set_action_callback(action, callback)
def _count_cells(self):
"""Count cells in the simulation."""
# Import locally to avoid circular import
@ -142,7 +161,7 @@ class SimulationEngine:
# Process HUD events and window events
for event in events:
hud_action = self.hud.process_event(event)
self._handle_hud_actions(hud_action)
self._process_hud_action(hud_action)
if event.type == pygame.VIDEORESIZE:
self._handle_window_resize(event)
@ -170,8 +189,8 @@ class SimulationEngine:
self.input_handler.update_selected_objects()
# Render frame
self._update(deltatime)
self._render()
self._update_frame(deltatime)
self._render_frame()
def _sync_input_and_timing(self):
"""Synchronize input handler state with simulation core timing."""
@ -189,6 +208,73 @@ class SimulationEngine:
# Sync speed multiplier
self.input_handler.speed_multiplier = timing_state.speed_multiplier
def _update_frame(self, deltatime):
"""Update camera and input state."""
keys = pygame.key.get_pressed()
self.input_handler.update_camera(keys, deltatime)
def _render_frame(self):
"""Render the complete frame."""
self.screen.fill(BLACK)
self.renderer.clear_screen()
# Render simulation world
self._render_simulation_world()
# Update and render UI
self._update_and_render_ui()
# Render HUD overlays
self._render_hud_overlays()
pygame.display.flip()
self.clock.tick(MAX_FPS)
def _render_simulation_world(self):
"""Render the simulation world if not dragging splitter."""
if not self.hud.dragging_splitter:
self.renderer.draw_grid(self.simulation_core.camera, self.input_handler.show_grid)
self.renderer.render_world(self.simulation_core.world, self.simulation_core.camera)
self.renderer.render_interaction_radius(
self.simulation_core.world,
self.simulation_core.camera,
self.input_handler.selected_objects,
self.input_handler.show_interaction_radius
)
self.renderer.render_selection_rectangle(
self.input_handler.get_selection_rect(),
self.sim_view_rect
)
self.renderer.render_selected_objects_outline(
self.input_handler.selected_objects,
self.simulation_core.camera
)
self.screen.blit(self.sim_view, (self.sim_view_rect.left, self.sim_view_rect.top))
def _update_and_render_ui(self):
"""Update UI elements and render them."""
# Update HUD displays with simulation core state
self.hud.update_simulation_controls(self.simulation_core)
# Draw UI elements
self.hud.manager.draw_ui(self.screen)
self.hud.draw_splitters(self.screen)
def _render_hud_overlays(self):
"""Render HUD overlay elements."""
self.hud.render_fps(self.screen, self.clock)
self.hud.render_tps(self.screen, self.simulation_core.state.actual_tps)
self.hud.render_selected_objects_info(self.screen, self.input_handler.selected_objects)
self.hud.render_legend(self.screen, self.input_handler.show_legend)
self.hud.render_pause_indicator(self.screen, self.simulation_core.timing.state.is_paused)
# Render neural network visualization for selected object
if self.input_handler.selected_objects:
self.hud.render_neural_network_visualization(
self.screen,
self.input_handler.selected_objects[0]
)
def _handle_window_resize(self, event):
"""Handle window resize event."""
self.window_width, self.window_height = event.w, event.h
@ -199,26 +285,41 @@ class SimulationEngine:
self._update_simulation_view()
self.hud.update_layout(self.window_width, self.window_height)
def _process_hud_action(self, action):
"""Process a single HUD action using the handler registry."""
if not action:
return
def _handle_hud_actions(self, action):
"""Handle actions from HUD simulation controls by forwarding to simulation core."""
if action == 'toggle_pause':
self.simulation_core.toggle_pause()
elif action == 'step_forward':
self.simulation_core.step()
elif action == 'toggle_sprint':
self.simulation_core.toggle_sprint_mode()
elif isinstance(action, tuple) and action[0] == 'set_speed':
self.simulation_core.set_speed_multiplier(action[1])
elif isinstance(action, tuple) and action[0] == 'set_custom_tps':
self.simulation_core.set_tps(action[1])
elif isinstance(action, tuple) and action[0] == 'reset_tps_display':
# Reset TPS display to current value
# Handle simple actions directly
if action in self._hud_action_handlers:
self._hud_action_handlers[action]()
return
# Handle parameterized actions
if isinstance(action, tuple) and len(action) >= 2:
action_type, param = action[0], action[1]
if action_type == 'set_speed':
self.simulation_core.set_speed_multiplier(param)
elif action_type == 'set_custom_tps':
self.simulation_core.set_tps(param)
elif action_type == 'reset_tps_display':
self._reset_tps_display()
def _reset_tps_display(self):
"""Reset TPS display to current simulation value."""
if self.hud.custom_tps_entry:
self.hud.custom_tps_entry.set_text(str(int(self.simulation_core.timing.state.tps)))
elif action == 'viewport_resized':
# Update simulation viewport when panels are resized
self._update_simulation_view()
current_tps = int(self.simulation_core.timing.state.tps)
self.hud.custom_tps_entry.set_text(str(current_tps))
def register_hud_action(self, action_name: str, handler):
"""Register a new HUD action handler for extensibility.
Args:
action_name: Name of the HUD action
handler: Callable that handles the action
"""
self._hud_action_handlers[action_name] = handler
def _handle_sprint_mode(self):
"""Handle sprint mode by running multiple simulation ticks quickly."""
@ -241,56 +342,4 @@ class SimulationEngine:
pygame.display.flip()
self.clock.tick(MAX_FPS)
def _update(self, deltatime):
"""Update camera based on input."""
keys = pygame.key.get_pressed()
self.input_handler.update_camera(keys, deltatime)
def _render(self):
"""Render the simulation frame."""
self.screen.fill(BLACK)
self.renderer.clear_screen()
if not self.hud.dragging_splitter:
# Render world
self.renderer.draw_grid(self.simulation_core.camera, self.input_handler.show_grid)
self.renderer.render_world(self.simulation_core.world, self.simulation_core.camera)
self.renderer.render_interaction_radius(
self.simulation_core.world,
self.simulation_core.camera,
self.input_handler.selected_objects,
self.input_handler.show_interaction_radius
)
self.renderer.render_selection_rectangle(
self.input_handler.get_selection_rect(),
self.sim_view_rect
)
self.renderer.render_selected_objects_outline(
self.input_handler.selected_objects,
self.simulation_core.camera
)
self.screen.blit(self.sim_view, (self.sim_view_rect.left, self.sim_view_rect.top))
# Update HUD displays with simulation core state
self.hud.update_simulation_controls(self.simulation_core)
# Draw UI elements
self.hud.manager.draw_ui(self.screen)
self.hud.draw_splitters(self.screen)
# Render HUD overlays
self.hud.render_fps(self.screen, self.clock)
self.hud.render_tps(self.screen, self.simulation_core.state.actual_tps)
self.hud.render_selected_objects_info(self.screen, self.input_handler.selected_objects)
self.hud.render_legend(self.screen, self.input_handler.show_legend)
self.hud.render_pause_indicator(self.screen, self.simulation_core.timing.state.is_paused)
# Render neural network visualization for selected object
if self.input_handler.selected_objects:
self.hud.render_neural_network_visualization(
self.screen,
self.input_handler.selected_objects[0]
)
pygame.display.flip()
self.clock.tick(MAX_FPS)