feat: Add ImGui-based developer console overlay

Integrates Dear ImGui for an in-game debug console that replaces the
blocking Python REPL. Press ~ (grave/tilde) to toggle the console.

Features:
- Python code execution without blocking the game loop
- Output capture with color coding (yellow=input, red=errors, gray=output)
- Expression results show repr() automatically
- Command history navigation with up/down arrows
- Word wrapping for long output lines
- Auto-scroll that doesn't fight manual scrolling
- mcrfpy.setDevConsole(bool) API to disable for shipping

Technical changes:
- Update imgui submodule to v1.89.9 (stable)
- Update imgui-sfml submodule to 2.6.x branch (SFML 2.x compatible)
- Add ImGui sources to CMakeLists.txt with OpenGL dependency
- Integrate ImGui lifecycle into GameEngine
- Add ImGuiConsole class for console overlay

closes #36, closes #65, closes #75

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
John McCardle 2025-11-26 20:03:58 -05:00
commit 3f6ea4fe33
9 changed files with 405 additions and 10 deletions

View file

@ -9,6 +9,7 @@
#include "PyWindow.h"
#include "PySceneObject.h"
#include "GameEngine.h"
#include "ImGuiConsole.h"
#include "UI.h"
#include "UILine.h"
#include "UICircle.h"
@ -202,6 +203,16 @@ static PyMethodDef mcrfpyMethods[] = {
MCRF_RETURNS("dict: Performance data with keys: frame_time (last frame duration in seconds), avg_frame_time (average frame time), fps (frames per second), draw_calls (number of draw calls), ui_elements (total UI element count), visible_elements (visible element count), current_frame (frame counter), runtime (total runtime in seconds)")
)},
{"setDevConsole", McRFPy_API::_setDevConsole, METH_VARARGS,
MCRF_FUNCTION(setDevConsole,
MCRF_SIG("(enabled: bool)", "None"),
MCRF_DESC("Enable or disable the developer console overlay."),
MCRF_ARGS_START
MCRF_ARG("enabled", "True to enable the console (default), False to disable")
MCRF_RETURNS("None")
MCRF_NOTE("When disabled, the grave/tilde key will not open the console. Use this to ship games without debug features.")
)},
{NULL, NULL, 0, NULL}
};
@ -1195,6 +1206,16 @@ PyObject* McRFPy_API::_getMetrics(PyObject* self, PyObject* args) {
return dict;
}
PyObject* McRFPy_API::_setDevConsole(PyObject* self, PyObject* args) {
int enabled;
if (!PyArg_ParseTuple(args, "p", &enabled)) { // "p" for boolean predicate
return NULL;
}
ImGuiConsole::setEnabled(enabled);
Py_RETURN_NONE;
}
// Exception handling implementation
void McRFPy_API::signalPythonException() {
// Check if we should exit on exception (consult config via game)