FlixelDebugOverlay
View sourceclass
org.flixelgdx.debug.FlixelDebugOverlay
Platform-agnostic controller for the FlixelGDX in-game debugger. This abstract class is the baseline behavior that every FlixelGDX backend can rely on: it owns the visibility flags, keybind handling, hitbox drawing, the pause/camera tools, and the pooled buffers that hold watch values, log entries, and custom tracker blocks.
The class deliberately does not render any UI on its own. Doing so in the core module would pull a heavy GUI dependency into every platform (web/iOS/Android). Instead, backends extend this abstract class and implement FlixelDebugOverlay.drawUI() to render the panels with whatever toolkit suits the platform.
The default install path is:
- Flixel.setDebugMode(boolean) flips debug mode on in your launcher.
- The launcher (or your code) calls Flixel.setDebugOverlay(Supplier<FlixelDebugOverlay>) with the backend-specific factory.
- FlixelGame constructs the overlay during
createand registers it with the logger.
Toggle overlay visibility with FlixelDebugOverlay.toggleKey (default Keybinds.DEFAULT_TOGGLE_KEY). Toggle visual debug (hitboxes) with FlixelDebugOverlay.drawDebugKey (default Keybinds.DEFAULT_DRAW_DEBUG_KEY). In debug mode, FlixelDebugOverlay.pauseKey (default F4) pauses the game; while paused you can inspect the camera with Alt+arrows (FlixelDebugOverlay.cameraCycleLeftKey / FlixelDebugOverlay.cameraCycleRightKey), FlixelDebugOverlay.cameraPanButton pan, and the mouse wheel zoom.
Reduced allocation rate
Strings are the easiest way to allocate yourself into stutters. To avoid that, this class:
- Caches FPS, heap, native and object counters as primitives and only refreshes them every seconds.
- Keeps log entries as
BufferedLogLinerecords pooled across frames; the renderer receives the level, tag, and message via FlixelDebugOverlay.copyLogBuffer(Array<BufferedLogLine>) without producing any markup string. - Refreshes watch entries at 10Hz into reusable FlixelString buffers (FlixelDebugWatchManager.fillWatchEntries(Array<FlixelString>, Array<FlixelString>)).
- Reuses
CachedTrackerBlockinstances across rebuilds.
Constructors
FlixelDebugOverlay()
Constructs the shared debug overlay state. Subclasses should call this before wiring platform UI.
Fields
STATS_UPDATE_INTERVAL
Seconds between automatic refreshes of cached primitive stats while the overlay is visible.
WATCH_REFRESH_INTERVAL
Seconds between watch buffer rebuilds while the overlay is visible.
PERF_SAMPLE_INTERVAL
Seconds between samples written into the performance ring buffers.
PERF_HISTORY_SIZE
Number of samples retained in each performance ring buffer. samples at s gives a rolling window of about six seconds.
toggleKey
Key that toggles overlay visibility. Set to FlixelKey.NONE to disable.
drawDebugKey
Key that toggles bounding-box (hitbox) drawing. Set to FlixelKey.NONE to disable.
pauseKey
Key that pauses/unpauses the game loop (debug mode only). Set to FlixelKey.NONE to disable.
cameraCycleLeftKey
Key that cycles the debug inspect camera left while paused (with Alt). Set to FlixelKey.NONE to disable.
cameraCycleRightKey
Key that cycles the debug inspect camera right while paused (with Alt). Set to FlixelKey.NONE to disable.
cameraPanButton
Mouse button used to pan the debug camera while paused. Set to a negative value to disable.
statsTimer
cachedFps
cachedHeapMegabytes
cachedNativeMegabytes
cachedObjectCount
cachedAssetCount
cachedRenderCalls
Total render-call count snapshotted at the start of each FlixelDebugOverlay.draw() call, after the game's batch has been ended for the frame. Sums the framework's own batch and any batches registered via FlixelDebugManager.trackBatch(FlixelBatch).
perfFrameMs
Frame-time samples in milliseconds (full real-time wall delta).
perfHeapMb
Java heap usage in megabytes per sample.
perfNativeMb
Native (GL/audio) heap usage in megabytes per sample.
perfFps
FPS as reported by libGDX per sample.
perfRenderCalls
Render-call count per sample. Sampled in FlixelDebugOverlay.pushPerfSample(float) after the previous frame's batch has been ended but before the next frame's begin() resets the counter, so it always reflects a complete frame even when the overlay is hidden.
perfHead
Index of the next sample to write (rolls over once the ring is full).
perfCount
Number of valid samples in each perf ring (caps at FlixelDebugOverlay.PERF_HISTORY_SIZE).
watchRefreshTimer
cachedWatchKeys
Cached watch keys refreshed at s; buffers are reused across refreshes.
cachedWatchValues
Cached watch values refreshed at s; buffers are reused across refreshes.
cachedTrackerBlocks
logBuffer
Latest log lines, oldest first; bounded by FlixelLogger.MAX_LOG_ENTRIES.
debugInspectCameraIndex
Methods
getLogListener()
isVisible()
setVisible(boolean)
toggleVisible()
isDrawDebug()
setDrawDebug(boolean)
toggleDrawDebug()
getInspectCameraIndex()
Returns the camera currently selected by Alt+arrow cycling, clamped to a valid index.
forceRefreshOnNextUpdate()
Schedules the next FlixelDebugOverlay.update(float) to refresh stats and watch buffers immediately. Useful when the overlay was just shown or when a backend wants the very first frame to display fresh data.
update(float)
Called every frame from the game loop to handle keybind input and refresh cached stats. Subclasses that need to update their own UI state should override FlixelDebugOverlay.onUpdateUI(float) rather than this method, so the input/state handling stays consistent across backends.
Parameters:
| Name | Description |
|---|---|
elapsed | Seconds since the last frame. |
pushPerfSample(float)
Appends one sample to each performance ring buffer. The buffers are primitive float[] arrays sized at FlixelDebugOverlay.PERF_HISTORY_SIZE, so this method is allocation-free.
The frame-time series always reads Flixel.getRawElapsed() so it reflects actual wall-clock time regardless of the active Flixel.timeScale.
Parameters:
| Name | Description |
|---|---|
elapsed | Scaled elapsed time passed by the update loop (kept for subclass compatibility). |
getPerfHead()
Returns the index immediately after the latest sample (where the next write will go).
getPerfCount()
Returns the number of valid samples in each perf series. Caps at FlixelDebugOverlay.PERF_HISTORY_SIZE.
getPerfFrameMs()
getPerfHeapMb()
getPerfNativeMb()
getPerfFps()
getPerfRenderCalls()
onUpdateUI(float)
Hook for subclass UI state updates that should happen every frame while the overlay is visible.
shouldSuppressDebugRawKeybind(int)
Backends that render a command-line InputText can override this to skip debug hotkeys for keys that would normally type into that field (letters, punctuation, arrows, Enter, and so on). Return false by default so FlixelKeyInputManager.rawJustPressed(int) shortcuts keep working.
Parameters:
| Name | Description |
|---|---|
keycode | FlixelGDX FlixelKey or libGDX Keys key code being handled by a debug binding. |
Returns: true to skip handling this key for debug shortcuts this frame.
onWatchEntriesRefreshed()
Hook fired after FlixelDebugOverlay.cachedWatchKeys and FlixelDebugOverlay.cachedWatchValues have been refilled. Override in renderer subclasses that need to keep a parallel cache (for example a String[] for Dear ImGui calls that only accept String).
onTrackerBlocksRebuilt()
Hook fired after FlixelDebugOverlay.cachedTrackerBlocks has been rebuilt. Override in renderer subclasses that need to keep a parallel cache (for example a String[] for Dear ImGui).
onLogEntryAppended(BufferedLogLine)
Hook fired right after a new FlixelLogEntry has been pushed into FlixelDebugOverlay.logBuffer. The line argument is the pooled buffer that was just populated. Override in renderer subclasses that need to mirror the entry into a parallel cache. Must not retain the reference; the buffer may be recycled once the buffer rolls over.
Parameters:
| Name | Description |
|---|---|
line | The pooled buffer that was just populated. |
isMouseCapturedByUI()
Override to tell the framework's input layer that another UI layer (typically the imgui debug overlay) is currently capturing the mouse. When this returns true, FlixelMouseManager.pressed(int) and the matching justPressed / justReleased helpers will report false for the game's regular input checks, and the debug camera tools / sprite picker also skip their work, so clicking inside (for example) a Dear ImGui window does not bleed through into the game logic. Defaults to false.
The debug overlay's own mouse-driven tools (sprite picker, camera pan) read FlixelMouseManager.rawPressed(int) so they can opt in to "ignore the suppression" while still respecting this hook for the early-exit gate.
Returns: true if a foreground UI element is consuming mouse input this frame.
isKeyboardCapturedByUI()
Override to tell the framework's input layer that another UI layer is currently consuming keyboard input. When this returns true, FlixelKeyInputManager.pressed(int) and the matching justPressed / justReleased helpers will report false for the game's regular input checks, so typing in (for example) a Dear ImGui text field cannot also capture game input and activate game-level actions like ui_accept. Defaults to false.
The debug overlay's own toggle keys (debug overlay toggle, hitbox toggle, pause) read FlixelKeyInputManager.rawJustPressed(int) so they keep working even when this returns true.
Returns: true if a foreground UI element is consuming keyboard input this frame.
drawBoundingBoxes(FlixelCamera[])
Draws bounding boxes for all visible FlixelDebugDrawable instances using each camera's projection. Each object provides its own debug color via FlixelDebugDrawable.getDebugBoundingBoxColor(). Disabled when FlixelDebugOverlay.isDrawDebug() is false.
Parameters:
| Name | Description |
|---|---|
cameras | The game camera array. |
draw()
Draws the overlay UI panels. The base implementation does nothing because the core module intentionally avoids depending on a heavy GUI toolkit (Dear ImGui, scene2d.ui, etc.). Backends override this to render the panels with whatever toolkit suits the platform.
Called from FlixelGame.draw(Batch) after the game stage and bounding boxes have been drawn.
drawUI()
Hook invoked from FlixelDebugOverlay.draw() when the overlay is visible. Each platform backend implements this.
resize(int, int)
Called from FlixelGame.resize(int, int) so backends can keep their renderer state in sync with the window. The base class does not need to do anything.
Parameters:
| Name | Description |
|---|---|
width | New window width in pixels. |
height | New window height in pixels. |
copyLogBuffer(Array<BufferedLogLine>)
Copies the current log buffer into output, oldest first, reusing existing BufferedLogLine slots in output so the renderer does not have to allocate.
Parameters:
| Name | Description |
|---|---|
output | Destination array. Cleared (resized) to match the current buffer size. |
Returns: The number of log lines written.
destroy()
dispose()
Keybinds
class
org.flixelgdx.debug.FlixelDebugOverlay.Keybinds
Default key codes for the debug overlay.
Fields
DEFAULT_TOGGLE_KEY
DEFAULT_DRAW_DEBUG_KEY
DEFAULT_PAUSE_KEY
DEFAULT_DEBUG_CAMERA_CYCLE_LEFT
DEFAULT_DEBUG_CAMERA_CYCLE_RIGHT
BufferedLogLine
class
org.flixelgdx.debug.FlixelDebugOverlay.BufferedLogLine
Buffered, markup-free copy of a FlixelLogEntry. Stored in FlixelDebugOverlay.logBuffer and pooled to avoid per-log allocations when the overlay's renderer reads log lines.
FlixelDebugOverlay.tagStr and FlixelDebugOverlay.messageStr are snapshots taken from the FlixelDebugOverlay.tag and FlixelDebugOverlay.message buffers after each FlixelDebugOverlay.set(...) so renderers that require String (such as Dear ImGui) do not call FlixelString.toString() every frame. They match the copied buffer text, not a live view of any caller-owned CharSequence.
Constructors
BufferedLogLine()
Fields
level
tag
message
tagStr
Stable String reference for the tag, refreshed whenever FlixelDebugOverlay.set(...) runs.
messageStr
Stable String reference for the message, refreshed whenever FlixelDebugOverlay.set(...) runs.
CachedTrackerBlock
class
org.flixelgdx.debug.FlixelDebugOverlay.CachedTrackerBlock
Cached block for a FlixelDebugTrackerEntry (rebuilt every s).