Debug Overlay

the engine’s built-in on-screen diagnostic HUD.

▶ Run in browser

Tags: debug

Debug is the engine’s diagnostic switchboard and Debug.create_node() builds the node that draws it. Add that node to any scene, last so it draws over everything else, and the overlay is available in the running game:

self.add_child(Debug.create_node())
Debug.enabled = True    # start with it on; it is off by default

F3 toggles the overlay (Debug.toggle() does the same from code) and F4 steps through its feature presets. It opens on the profiler alone: frame rate, per-phase timings, node and control counts and a frame-time graph. Each press then adds to it: the bounding box of every control, coloured by state (red disabled, blue focused, green hovered); the same boxes for interactive controls only; all boxes again with a label on each control near the cursor; a rolling log of input events and where they landed. One more press shows nothing, and the next starts over. While it is off the overlay draws nothing.

The scene under it is an ordinary panel of buttons, a disabled button and a dropdown, which keep working normally beneath the overlay: click them with the event log showing to watch each press and the control it reached.

The labels read name (Type), and name is whatever the control was given with name=. A control given none is named after its class, so every button would read Button (Button); naming the controls is what makes the overlay say which one is under the cursor:

Button("Click Me", name="ClickMe")

Source

 1"""Debug Overlay: the engine's built-in on-screen diagnostic HUD.
 2
 3`Debug` is the engine's diagnostic switchboard and `Debug.create_node()` builds
 4the node that draws it. Add that node to any scene, last so it draws over
 5everything else, and the overlay is available in the running game:
 6
 7    self.add_child(Debug.create_node())
 8    Debug.enabled = True    # start with it on; it is off by default
 9
10F3 toggles the overlay (`Debug.toggle()` does the same from code) and F4 steps
11through its feature presets. It opens on the profiler alone: frame rate,
12per-phase timings, node and control counts and a frame-time graph. Each press
13then adds to it: the bounding box of every control, coloured by state (red
14disabled, blue focused, green hovered); the same boxes for interactive controls
15only; all boxes again with a label on each control near the cursor; a rolling
16log of input events and where they landed. One more press shows nothing, and
17the next starts over. While it is off the overlay draws nothing.
18
19The scene under it is an ordinary panel of buttons, a disabled button and a
20dropdown, which keep working normally beneath the overlay: click them with
21the event log showing to watch each press and the control it reached.
22
23The labels read `name (Type)`, and `name` is whatever the control was given
24with `name=`. A control given none is named after its class, so every button
25would read `Button (Button)`; naming the controls is what makes the overlay
26say which one is under the cursor:
27
28    Button("Click Me", name="ClickMe")
29"""
30
31from simvx.core import Anchor, Button, Debug, DropDown, HBoxContainer, Label, Node, Panel, VBoxContainer
32from simvx.graphics import App
33
34
35class DebugDemo(Node):
36    def on_ready(self):
37        panel = self.add_child(Panel(name="RootPanel", anchor=Anchor.TOP_LEFT, inset=50, size=(400, 300)))
38        column = panel.add_child(VBoxContainer(name="Column", anchor=Anchor.FULL_RECT, inset=10))
39        column.add_child(Label("Debug Overlay Demo", name="Title", font_size=20))
40        self.status = column.add_child(Label("Click a button", name="Status"))
41        for text, name in (("Click Me", "ClickMe"), ("Another Button", "Another")):
42            column.add_child(Button(text, name=name, on_press=lambda text=text: self._clicked(text)))
43        disabled = column.add_child(Button("Disabled", name="DisabledBtn"))
44        disabled.disabled = True
45        column.add_child(DropDown(items=["Option A", "Option B", "Option C"], name="Choice"))
46        row = column.add_child(HBoxContainer(name="SmallButtons"))
47        for i in range(3):
48            row.add_child(Button(f"Btn {i}", name=f"SmallBtn{i}", on_press=lambda i=i: self._clicked(f"Btn {i}")))
49
50        # Example help overlay: not part of the technique shown.
51        help_row = self.add_child(HBoxContainer(name="Help", anchor=Anchor.BOTTOM_RIGHT, inset=16))
52        help_row.add_child(Button("F3: toggle overlay", name="ToggleOverlay", on_press=Debug.toggle))
53        help_row.add_child(Label("F4: cycle features", name="CycleHint"))
54        # An anchored container keeps its default 100-pixel width rather than its
55        # content's, which pushes a right-anchored row off the screen; fit it by hand.
56        help_row.autosize_to_content()
57
58        self.add_child(Debug.create_node())
59        Debug.enabled = True
60
61    def _clicked(self, text):
62        self.status.text = f"Clicked: {text}"
63
64
65if __name__ == "__main__":
66    App(title="Debug Overlay", width=1280, height=720).run(DebugDemo())