Monkey Patch support + Robust callback tracking

McRogueFace needs to accept callable objects (properties on C++ objects)
and also support subclassing (getattr on user objects). Only direct
properties were supported previously, now shadowing a callback by name
will allow custom objects to "just work".
- Added CallbackCache struct and is_python_subclass flag to UIDrawable.h
- Created metaclass for tracking class-level callback changes
- Updated all UI type init functions to detect subclasses
- Modified PyScene.cpp event dispatch to try subclass methods
This commit is contained in:
John McCardle 2026-01-09 21:37:23 -05:00
commit a77ac6c501
14 changed files with 1003 additions and 25 deletions

View file

@ -1,5 +1,6 @@
#include "UIArc.h"
#include "McRFPy_API.h"
#include "PythonObjectCache.h"
#include <cmath>
#include <sstream>
@ -141,6 +142,9 @@ void UIArc::render(sf::Vector2f offset, sf::RenderTarget& target) {
UIDrawable* UIArc::click_at(sf::Vector2f point) {
if (!visible) return nullptr;
// #184: Also check for Python subclass (might have on_click method)
if (!click_callable && !is_python_subclass) return nullptr;
// Calculate distance from center
float dx = point.x - center.x;
float dy = point.y - center.y;
@ -542,5 +546,22 @@ int UIArc::init(PyUIArcObject* self, PyObject* args, PyObject* kwds) {
self->data->name = name;
}
// Register in Python object cache
if (self->data->serial_number == 0) {
self->data->serial_number = PythonObjectCache::getInstance().assignSerial();
PyObject* weakref = PyWeakref_NewRef((PyObject*)self, NULL);
if (weakref) {
PythonObjectCache::getInstance().registerObject(self->data->serial_number, weakref);
Py_DECREF(weakref);
}
}
// #184: Check if this is a Python subclass (for callback method support)
PyObject* arc_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Arc");
if (arc_type) {
self->data->is_python_subclass = (PyObject*)Py_TYPE(self) != arc_type;
Py_DECREF(arc_type);
}
return 0;
}