From 9a241c99d7d04248ebfeb81397049fe4d76a1238 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Sat, 17 Jan 2026 10:38:17 -0500 Subject: [PATCH 1/2] Version bump: 0.2.1-prerelease-7drl2026 (baa7ee3) -> 0.2.2-prerelease-7drl2026 --- src/McRogueFaceVersion.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/McRogueFaceVersion.h b/src/McRogueFaceVersion.h index 9051aeb..76d9877 100644 --- a/src/McRogueFaceVersion.h +++ b/src/McRogueFaceVersion.h @@ -1,4 +1,4 @@ #pragma once // McRogueFace version string (#164) -#define MCRFPY_VERSION "0.2.1-prerelease-7drl2026" +#define MCRFPY_VERSION "0.2.2-prerelease-7drl2026" From 09fa4f4665f78086ab2b9ad0f51989741b7d6fe9 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Sat, 17 Jan 2026 23:37:56 -0500 Subject: [PATCH 2/2] emove `register_keyboard(callable)` from scene - all callbacks are standard attributes now. on_resize now returns a vector --- src/GameEngine.cpp | 2 +- src/McRFPy_API.h | 2 +- src/PySceneObject.cpp | 65 +++++++++++++++---------------------------- src/PySceneObject.h | 5 ++-- 4 files changed, 27 insertions(+), 47 deletions(-) diff --git a/src/GameEngine.cpp b/src/GameEngine.cpp index 8a4c619..0427ab7 100644 --- a/src/GameEngine.cpp +++ b/src/GameEngine.cpp @@ -421,7 +421,7 @@ void GameEngine::processEvent(const sf::Event& event) updateViewport(); // Notify Python scenes about the resize - McRFPy_API::triggerResize(event.size.width, event.size.height); + McRFPy_API::triggerResize(sf::Vector2u(event.size.width, event.size.height)); } else if (event.type == sf::Event::KeyPressed || event.type == sf::Event::MouseButtonPressed || event.type == sf::Event::MouseWheelScrolled) actionType = "start"; diff --git a/src/McRFPy_API.h b/src/McRFPy_API.h index 3c7408d..d5587f3 100644 --- a/src/McRFPy_API.h +++ b/src/McRFPy_API.h @@ -79,7 +79,7 @@ public: // Scene lifecycle management for Python Scene objects static void triggerSceneChange(const std::string& from_scene, const std::string& to_scene); static void updatePythonScenes(float dt); - static void triggerResize(int width, int height); + static void triggerResize(sf::Vector2u new_size); static void triggerKeyEvent(const std::string& key, const std::string& action); // #151: Module-level scene property accessors diff --git a/src/PySceneObject.cpp b/src/PySceneObject.cpp index 8104c2a..e943fbf 100644 --- a/src/PySceneObject.cpp +++ b/src/PySceneObject.cpp @@ -136,35 +136,6 @@ static PyObject* PySceneClass_get_children(PySceneObject* self, void* closure) return result; } -PyObject* PySceneClass::register_keyboard(PySceneObject* self, PyObject* args) -{ - PyObject* callable; - if (!PyArg_ParseTuple(args, "O", &callable)) { - return NULL; - } - - if (!PyCallable_Check(callable)) { - PyErr_SetString(PyExc_TypeError, "Argument must be callable"); - return NULL; - } - - // Store the callable - Py_INCREF(callable); - - // Get the current scene and set its key_callable - GameEngine* game = McRFPy_API::game; - if (game) { - // We need to be on the right scene first - std::string old_scene = game->scene; - game->scene = self->name; - game->currentScene()->key_callable = std::make_unique(callable); - game->scene = old_scene; - } - - Py_DECREF(callable); - Py_RETURN_NONE; -} - // on_key property getter static PyObject* PySceneClass_get_on_key(PySceneObject* self, void* closure) { @@ -458,11 +429,30 @@ void PySceneClass::call_update(PySceneObject* self, float dt) } } -void PySceneClass::call_on_resize(PySceneObject* self, int width, int height) +void PySceneClass::call_on_resize(PySceneObject* self, sf::Vector2u new_size) { PyObject* method = PyObject_GetAttrString((PyObject*)self, "on_resize"); if (method && PyCallable_Check(method)) { - PyObject* result = PyObject_CallFunction(method, "ii", width, height); + // Create a Vector object to pass + auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector"); + if (!type) { + PyErr_Print(); + Py_DECREF(method); + return; + } + PyObject* args = Py_BuildValue("(ff)", (float)new_size.x, (float)new_size.y); + PyObject* vector = PyObject_CallObject((PyObject*)type, args); + Py_DECREF(type); + Py_DECREF(args); + + if (!vector) { + PyErr_Print(); + Py_DECREF(method); + return; + } + + PyObject* result = PyObject_CallFunctionObjArgs(method, vector, NULL); + Py_DECREF(vector); if (result) { Py_DECREF(result); } else { @@ -536,15 +526,6 @@ PyMethodDef PySceneClass::methods[] = { MCRF_RETURNS("None") MCRF_NOTE("Deactivates the current scene and activates this one. Lifecycle callbacks (on_exit, on_enter) are triggered.") )}, - {"register_keyboard", (PyCFunction)register_keyboard, METH_VARARGS, - MCRF_METHOD(SceneClass, register_keyboard, - MCRF_SIG("(callback: callable)", "None"), - MCRF_DESC("Register a keyboard event handler function."), - MCRF_ARGS_START - MCRF_ARG("callback", "Function that receives (key: str, pressed: bool) when keyboard events occur") - MCRF_RETURNS("None") - MCRF_NOTE("Alternative to setting on_key property. Handler is called for both key press and release events.") - )}, {"realign", (PyCFunction)PySceneClass_realign, METH_NOARGS, MCRF_METHOD(SceneClass, realign, MCRF_SIG("()", "None"), @@ -596,14 +577,14 @@ void McRFPy_API::updatePythonScenes(float dt) } // Helper function to trigger resize events on Python scenes -void McRFPy_API::triggerResize(int width, int height) +void McRFPy_API::triggerResize(sf::Vector2u new_size) { GameEngine* game = McRFPy_API::game; if (!game) return; // Only notify the active scene if (python_scenes.count(game->scene) > 0) { - PySceneClass::call_on_resize(python_scenes[game->scene], width, height); + PySceneClass::call_on_resize(python_scenes[game->scene], new_size); } } diff --git a/src/PySceneObject.h b/src/PySceneObject.h index 9e9f189..487a656 100644 --- a/src/PySceneObject.h +++ b/src/PySceneObject.h @@ -27,7 +27,6 @@ public: // Scene methods static PyObject* activate(PySceneObject* self, PyObject* args, PyObject* kwds); - static PyObject* register_keyboard(PySceneObject* self, PyObject* args); // Properties static PyObject* get_name(PySceneObject* self, void* closure); @@ -38,7 +37,7 @@ public: static void call_on_exit(PySceneObject* self); static void call_on_key(PySceneObject* self, const std::string& key, const std::string& action); static void call_update(PySceneObject* self, float dt); - static void call_on_resize(PySceneObject* self, int width, int height); + static void call_on_resize(PySceneObject* self, sf::Vector2u new_size); // #183: Lookup scene by name (returns new reference or nullptr) static PyObject* get_scene_by_name(const std::string& name); @@ -77,7 +76,7 @@ namespace mcrfpydef { " on_exit(): Called when scene is deactivated (another scene activates).\n" " on_key(key: str, action: str): Called for keyboard events (subclass method).\n" " update(dt: float): Called every frame with delta time in seconds.\n" - " on_resize(width: int, height: int): Called when window is resized.\n\n" + " on_resize(new_size: Vector): Called when window is resized.\n\n" "Example:\n" " # Basic usage (replacing module functions):\n" " scene = mcrfpy.Scene('main_menu')\n"