Add ImGui Scene Explorer (F4) for runtime object inspection (#136)

New Features:
- Scene Explorer window (F4) displays hierarchical tree of all scenes
- Shows UIDrawable hierarchy with type, name, and visibility status
- Click scene name to switch active scene
- Double-click drawables to toggle visibility
- Displays Python repr() for cached objects, enabling custom class debugging
- Entity display within Grid nodes

Bug Fixes:
- Fix PythonObjectCache re-registration: when retrieving objects from
  collections, newly created Python wrappers are now re-registered in
  the cache. Previously, inline-created objects (e.g.,
  scene.children.append(Frame(...))) would lose their cache entry when
  the temporary Python object was GC'd, causing repeated wrapper
  allocation on each access.
- Fix console focus stealing: removed aggressive focus reclaim that
  caused title bar flashing when clicking in Scene Explorer

Infrastructure:
- Add GameEngine::getSceneNames() to expose scene list for explorer
- Scene Explorer uses same enabled flag as console (ImGuiConsole::isEnabled())

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
John McCardle 2026-01-21 23:26:33 -05:00
commit 5e45ab015c
7 changed files with 378 additions and 3 deletions

View file

@ -130,6 +130,18 @@ PyObject* UIEntityCollection::getitem(PyUIEntityCollectionObject* self, Py_ssize
o->data = std::static_pointer_cast<UIEntity>(target);
o->weakreflist = NULL;
// Re-register in cache if the entity has a serial number
// This handles the case where the original Python wrapper was GC'd
// but the C++ object persists (e.g., inline-created objects added to collections)
if (target->serial_number != 0) {
PyObject* weakref = PyWeakref_NewRef((PyObject*)o, NULL);
if (weakref) {
PythonObjectCache::getInstance().registerObject(target->serial_number, weakref);
Py_DECREF(weakref);
}
}
return (PyObject*)o;
}