"""Status Bar — Bottom bar showing scene info, FPS, and selection."""
from __future__ import annotations
from simvx.core import Control, Vec2
[docs]
class StatusBar(Control):
"""Bottom status bar displaying editor information.
Shows: scene path, modification indicator, FPS, mouse position,
selected node name.
"""
def __init__(self, editor_state=None, **kwargs):
super().__init__(**kwargs)
self.state = editor_state
self.size = Vec2(800, 20)
self.bg_colour = (0.12, 0.12, 0.12, 1.0)
self.text_colour = (0.7, 0.7, 0.7, 1.0)
self.font_size = 11.0
# FPS tracking
self._frame_count = 0
self._fps_timer = 0.0
self._fps = 0.0
# Cached display strings
self._scene_text = "No scene"
self._selection_text = ""
self._mouse_text = "0, 0"
[docs]
def process(self, dt: float):
self._frame_count += 1
self._fps_timer += dt
if self._fps_timer >= 1.0:
self._fps = self._frame_count / self._fps_timer
self._frame_count = 0
self._fps_timer = 0.0
if self.state:
self._scene_text = self.state.get_scene_title()
sel = self.state.selection.primary
self._selection_text = sel.name if sel else ""
# Play state indicator colours
_PLAYING_COLOUR = (0.2, 0.9, 0.2, 1.0)
_PAUSED_COLOUR = (1.0, 0.6, 0.0, 1.0)
def _play_state_text(self) -> tuple[str, tuple] | None:
"""Return (text, colour) for the play state indicator, or None."""
if not self.state:
return None
if self.state.is_playing and self.state.is_paused:
return ("PAUSED", self._PAUSED_COLOUR)
if self.state.is_playing:
return ("PLAYING", self._PLAYING_COLOUR)
return None
[docs]
def draw(self, renderer):
x, y, w, h = self.get_global_rect()
scale = self.font_size / 14.0
# Background
renderer.draw_filled_rect(x, y, w, h, self.bg_colour)
# Top border
renderer.draw_line_coloured(x, y, x + w, y, (0.25, 0.25, 0.25, 1.0))
# Scene path (left)
renderer.draw_text_coloured(
self._scene_text, x + 8, y + 3, scale, self.text_colour)
# Play state indicator (after scene name)
play_info = self._play_state_text()
play_offset = 0.0
if play_info:
text, colour = play_info
scene_w = renderer.text_width(self._scene_text, scale)
px = x + 8 + scene_w + 16
renderer.draw_text_coloured(text, px, y + 3, scale, colour)
play_offset = renderer.text_width(text, scale) + 16
# Selected node (center-left)
if self._selection_text:
scene_w = renderer.text_width(self._scene_text, scale)
sel_x = x + 8 + scene_w + 16 + play_offset
renderer.draw_text_coloured(
f"Selected: {self._selection_text}",
sel_x, y + 3, scale, (0.5, 0.8, 1.0, 1.0))
# FPS (right)
fps_text = f"{self._fps:.0f} FPS"
fps_w = renderer.text_width(fps_text, scale)
renderer.draw_text_coloured(
fps_text, x + w - fps_w - 8, y + 3, scale, self.text_colour)
# Mouse position (center-right)
mouse_w = renderer.text_width(self._mouse_text, scale)
renderer.draw_text_coloured(
self._mouse_text, x + w - fps_w - mouse_w - 30, y + 3,
scale, self.text_colour)
[docs]
def update_mouse_pos(self, mx: float, my: float):
"""Update displayed mouse position."""
self._mouse_text = f"{mx:.0f}, {my:.0f}"