UIEntity::init() stored self->data->self = (PyObject*)self with
Py_INCREF(self), creating a reference cycle that prevented entities
from ever being freed. The matching Py_DECREF never existed.
Fix: Remove the `self` field from UIEntity entirely. Replace all
read sites (iter next, getitem, get_perspective, entities_in_radius)
with PythonObjectCache lookups using serial_number, which uses weak
references and doesn't prevent garbage collection.
Also adds tp_dealloc to PyUIEntityType to properly clean up the
shared_ptr and weak references when the Python wrapper is freed.
Closes#266, closes#275
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add ensureGridstate() helper that unconditionally checks gridstate size
against current grid dimensions and resizes if mismatched. Replace all
lazy-init guards (size == 0) with ensureGridstate() calls.
Previously, gridstate was only initialized when empty. When an entity
moved to a differently-sized grid, gridstate kept the old size, causing
heap buffer overflows when updateVisibility() or at() iterated using the
new grid's dimensions.
Also adds spatial_hash.remove() calls in set_grid() before removing
entities from old grids, and replaces PyObject_GetAttrString type lookup
with direct &mcrfpydef::PyUIGridType reference.
Closes#258, closes#259, closes#260, closes#261, closes#262,
closes#263, closes#274, closes#276, closes#278
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All 27 PyTypeObject declarations in namespace mcrfpydef headers changed
from `static` to `inline` (C++17), ensuring a single global instance
across translation units. This fixes the root cause of stale-type-pointer
segfaults where only the McRFPy_API.cpp copy was PyType_Ready'd.
Replaced ~20 PyTypeCache call sites and 2 PyRAII::PyTypeRef lookups with
direct &mcrfpydef::Type references. Deleted PyTypeCache.h/.cpp,
PyObjectUtils.h, and PyRAII.h (all were workarounds for the static bug).
228/228 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>