Replace PyObject_GetAttrString with direct type references
Replace ~230 occurrences of PyObject_GetAttrString(McRFPy_API::mcrf_module, "TypeName") with direct &mcrfpydef::PyXxxType references across 32 source files. Each PyObject_GetAttrString call returns a new reference. When used inline in PyObject_IsInstance(), that reference was immediately leaked. When used for tp_alloc, the reference required careful Py_DECREF management that was often missing on error paths. Direct type references are compile-time constants that never need reference counting, eliminating ~230 potential leak sites and removing ~100 lines of Py_DECREF/Py_XDECREF cleanup code. Also adds extractDrawable() helper in UICollection.cpp to replace repeated 8-way type-check-and-extract chains with a single function call. Closes #267, closes #268 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
348826a0f5
commit
71eb01c950
32 changed files with 249 additions and 944 deletions
|
|
@ -1231,14 +1231,9 @@ PyObject* Entity3D::py_animate(PyEntity3DObject* self, PyObject* args, PyObject*
|
|||
}
|
||||
|
||||
// Create and return a PyAnimation wrapper
|
||||
PyTypeObject* animType = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Animation");
|
||||
if (!animType) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Could not find Animation type");
|
||||
return NULL;
|
||||
}
|
||||
PyTypeObject* animType = &mcrfpydef::PyAnimationType;
|
||||
|
||||
PyAnimationObject* pyAnim = (PyAnimationObject*)animType->tp_alloc(animType, 0);
|
||||
Py_DECREF(animType);
|
||||
|
||||
if (!pyAnim) {
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -390,15 +390,11 @@ PyObject* PyVoxelGrid::get_material(PyVoxelGridObject* self, PyObject* args) {
|
|||
const mcrf::VoxelMaterial& mat = self->data->getMaterial(static_cast<uint8_t>(id));
|
||||
|
||||
// Create color object
|
||||
PyObject* color_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Color");
|
||||
if (!color_type) {
|
||||
return nullptr;
|
||||
}
|
||||
PyObject* color_type = (PyObject*)&mcrfpydef::PyColorType;
|
||||
|
||||
PyObject* color_obj = PyObject_Call(color_type,
|
||||
Py_BuildValue("(iiii)", mat.color.r, mat.color.g, mat.color.b, mat.color.a),
|
||||
nullptr);
|
||||
Py_DECREF(color_type);
|
||||
|
||||
if (!color_obj) {
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -1841,11 +1841,7 @@ int Viewport3D::init(PyViewport3DObject* self, PyObject* args, PyObject* kwds) {
|
|||
}
|
||||
|
||||
// Check if this is a Python subclass (for callback method support)
|
||||
PyObject* viewport3d_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Viewport3D");
|
||||
if (viewport3d_type) {
|
||||
self->data->is_python_subclass = (PyObject*)Py_TYPE(self) != viewport3d_type;
|
||||
Py_DECREF(viewport3d_type);
|
||||
}
|
||||
self->data->is_python_subclass = (PyObject*)Py_TYPE(self) != (PyObject*)&mcrfpydef::PyViewport3DType;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1940,19 +1936,10 @@ static PyObject* Viewport3D_build_terrain(PyViewport3DObject* self, PyObject* ar
|
|||
}
|
||||
|
||||
// Check if heightmap_obj is a PyHeightMapObject
|
||||
// Get the HeightMap type from the module
|
||||
PyObject* heightmap_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "HeightMap");
|
||||
if (!heightmap_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "HeightMap type not found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!PyObject_IsInstance(heightmap_obj, heightmap_type)) {
|
||||
Py_DECREF(heightmap_type);
|
||||
if (!PyObject_IsInstance(heightmap_obj, (PyObject*)&mcrfpydef::PyHeightMapType)) {
|
||||
PyErr_SetString(PyExc_TypeError, "heightmap must be a HeightMap object");
|
||||
return NULL;
|
||||
}
|
||||
Py_DECREF(heightmap_type);
|
||||
|
||||
// Get the TCOD heightmap pointer from the Python object
|
||||
PyHeightMapObject* hm = reinterpret_cast<PyHeightMapObject*>(heightmap_obj);
|
||||
|
|
@ -1987,20 +1974,14 @@ static PyObject* Viewport3D_apply_terrain_colors(PyViewport3DObject* self, PyObj
|
|||
}
|
||||
|
||||
// Validate all three are HeightMap objects
|
||||
PyObject* heightmap_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "HeightMap");
|
||||
if (!heightmap_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "HeightMap type not found");
|
||||
return NULL;
|
||||
}
|
||||
PyObject* heightmap_type = (PyObject*)&mcrfpydef::PyHeightMapType;
|
||||
|
||||
if (!PyObject_IsInstance(r_obj, heightmap_type) ||
|
||||
!PyObject_IsInstance(g_obj, heightmap_type) ||
|
||||
!PyObject_IsInstance(b_obj, heightmap_type)) {
|
||||
Py_DECREF(heightmap_type);
|
||||
PyErr_SetString(PyExc_TypeError, "r_map, g_map, and b_map must all be HeightMap objects");
|
||||
return NULL;
|
||||
}
|
||||
Py_DECREF(heightmap_type);
|
||||
|
||||
// Get the TCOD heightmap pointers
|
||||
PyHeightMapObject* r_hm = reinterpret_cast<PyHeightMapObject*>(r_obj);
|
||||
|
|
@ -2082,18 +2063,10 @@ static PyObject* Viewport3D_apply_heightmap(PyViewport3DObject* self, PyObject*
|
|||
}
|
||||
|
||||
// Validate HeightMap type
|
||||
PyObject* heightmap_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "HeightMap");
|
||||
if (!heightmap_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "HeightMap type not found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!PyObject_IsInstance(hm_obj, heightmap_type)) {
|
||||
Py_DECREF(heightmap_type);
|
||||
if (!PyObject_IsInstance(hm_obj, (PyObject*)&mcrfpydef::PyHeightMapType)) {
|
||||
PyErr_SetString(PyExc_TypeError, "heightmap must be a HeightMap object");
|
||||
return NULL;
|
||||
}
|
||||
Py_DECREF(heightmap_type);
|
||||
|
||||
PyHeightMapObject* hm = reinterpret_cast<PyHeightMapObject*>(hm_obj);
|
||||
if (!hm->heightmap) {
|
||||
|
|
@ -2118,18 +2091,10 @@ static PyObject* Viewport3D_apply_threshold(PyViewport3DObject* self, PyObject*
|
|||
}
|
||||
|
||||
// Validate HeightMap type
|
||||
PyObject* heightmap_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "HeightMap");
|
||||
if (!heightmap_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "HeightMap type not found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!PyObject_IsInstance(hm_obj, heightmap_type)) {
|
||||
Py_DECREF(heightmap_type);
|
||||
if (!PyObject_IsInstance(hm_obj, (PyObject*)&mcrfpydef::PyHeightMapType)) {
|
||||
PyErr_SetString(PyExc_TypeError, "heightmap must be a HeightMap object");
|
||||
return NULL;
|
||||
}
|
||||
Py_DECREF(heightmap_type);
|
||||
|
||||
PyHeightMapObject* hm = reinterpret_cast<PyHeightMapObject*>(hm_obj);
|
||||
if (!hm->heightmap) {
|
||||
|
|
|
|||
|
|
@ -514,8 +514,7 @@ static PyObject* convertDrawableToPython(std::shared_ptr<UIDrawable> drawable) {
|
|||
switch (drawable->derived_type()) {
|
||||
case PyObjectsEnum::UIFRAME:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame");
|
||||
if (!type) return nullptr;
|
||||
type = &mcrfpydef::PyUIFrameType;
|
||||
auto pyObj = (PyUIFrameObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<UIFrame>(drawable);
|
||||
|
|
@ -526,8 +525,7 @@ static PyObject* convertDrawableToPython(std::shared_ptr<UIDrawable> drawable) {
|
|||
}
|
||||
case PyObjectsEnum::UICAPTION:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption");
|
||||
if (!type) return nullptr;
|
||||
type = &mcrfpydef::PyUICaptionType;
|
||||
auto pyObj = (PyUICaptionObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<UICaption>(drawable);
|
||||
|
|
@ -539,8 +537,7 @@ static PyObject* convertDrawableToPython(std::shared_ptr<UIDrawable> drawable) {
|
|||
}
|
||||
case PyObjectsEnum::UISPRITE:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite");
|
||||
if (!type) return nullptr;
|
||||
type = &mcrfpydef::PyUISpriteType;
|
||||
auto pyObj = (PyUISpriteObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<UISprite>(drawable);
|
||||
|
|
@ -551,8 +548,7 @@ static PyObject* convertDrawableToPython(std::shared_ptr<UIDrawable> drawable) {
|
|||
}
|
||||
case PyObjectsEnum::UIGRID:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid");
|
||||
if (!type) return nullptr;
|
||||
type = &mcrfpydef::PyUIGridType;
|
||||
auto pyObj = (PyUIGridObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<UIGrid>(drawable);
|
||||
|
|
@ -563,8 +559,7 @@ static PyObject* convertDrawableToPython(std::shared_ptr<UIDrawable> drawable) {
|
|||
}
|
||||
case PyObjectsEnum::UILINE:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Line");
|
||||
if (!type) return nullptr;
|
||||
type = &mcrfpydef::PyUILineType;
|
||||
auto pyObj = (PyUILineObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<UILine>(drawable);
|
||||
|
|
@ -575,8 +570,7 @@ static PyObject* convertDrawableToPython(std::shared_ptr<UIDrawable> drawable) {
|
|||
}
|
||||
case PyObjectsEnum::UICIRCLE:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Circle");
|
||||
if (!type) return nullptr;
|
||||
type = &mcrfpydef::PyUICircleType;
|
||||
auto pyObj = (PyUICircleObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<UICircle>(drawable);
|
||||
|
|
@ -587,8 +581,7 @@ static PyObject* convertDrawableToPython(std::shared_ptr<UIDrawable> drawable) {
|
|||
}
|
||||
case PyObjectsEnum::UIARC:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Arc");
|
||||
if (!type) return nullptr;
|
||||
type = &mcrfpydef::PyUIArcType;
|
||||
auto pyObj = (PyUIArcObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<UIArc>(drawable);
|
||||
|
|
@ -601,10 +594,6 @@ static PyObject* convertDrawableToPython(std::shared_ptr<UIDrawable> drawable) {
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
if (type) {
|
||||
Py_DECREF(type);
|
||||
}
|
||||
|
||||
return obj ? obj : Py_None;
|
||||
}
|
||||
|
||||
|
|
@ -622,13 +611,9 @@ static PyObject* convertEntityToPython(std::shared_ptr<UIEntity> entity) {
|
|||
}
|
||||
}
|
||||
|
||||
PyTypeObject* type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Entity");
|
||||
if (!type) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
PyTypeObject* type = &mcrfpydef::PyUIEntityType;
|
||||
|
||||
auto pyObj = (PyUIEntityObject*)type->tp_alloc(type, 0);
|
||||
Py_DECREF(type);
|
||||
|
||||
if (!pyObj) {
|
||||
Py_RETURN_NONE;
|
||||
|
|
@ -653,13 +638,9 @@ static PyObject* convertEntity3DToPython(std::shared_ptr<mcrf::Entity3D> entity)
|
|||
}
|
||||
|
||||
// Create a new wrapper
|
||||
PyTypeObject* type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Entity3D");
|
||||
if (!type) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
PyTypeObject* type = &mcrfpydef::PyEntity3DType;
|
||||
|
||||
auto pyObj = (PyEntity3DObject*)type->tp_alloc(type, 0);
|
||||
Py_DECREF(type);
|
||||
|
||||
if (!pyObj) {
|
||||
Py_RETURN_NONE;
|
||||
|
|
|
|||
|
|
@ -1544,7 +1544,7 @@ static void find_in_collection(std::vector<std::shared_ptr<UIDrawable>>* collect
|
|||
switch (drawable->derived_type()) {
|
||||
case PyObjectsEnum::UIFRAME: {
|
||||
auto frame = std::static_pointer_cast<UIFrame>(drawable);
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame");
|
||||
auto type = &mcrfpydef::PyUIFrameType;
|
||||
auto o = (PyUIFrameObject*)type->tp_alloc(type, 0);
|
||||
if (o) {
|
||||
o->data = frame;
|
||||
|
|
@ -1554,7 +1554,7 @@ static void find_in_collection(std::vector<std::shared_ptr<UIDrawable>>* collect
|
|||
}
|
||||
case PyObjectsEnum::UICAPTION: {
|
||||
auto caption = std::static_pointer_cast<UICaption>(drawable);
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption");
|
||||
auto type = &mcrfpydef::PyUICaptionType;
|
||||
auto o = (PyUICaptionObject*)type->tp_alloc(type, 0);
|
||||
if (o) {
|
||||
o->data = caption;
|
||||
|
|
@ -1564,7 +1564,7 @@ static void find_in_collection(std::vector<std::shared_ptr<UIDrawable>>* collect
|
|||
}
|
||||
case PyObjectsEnum::UISPRITE: {
|
||||
auto sprite = std::static_pointer_cast<UISprite>(drawable);
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite");
|
||||
auto type = &mcrfpydef::PyUISpriteType;
|
||||
auto o = (PyUISpriteObject*)type->tp_alloc(type, 0);
|
||||
if (o) {
|
||||
o->data = sprite;
|
||||
|
|
@ -1574,7 +1574,7 @@ static void find_in_collection(std::vector<std::shared_ptr<UIDrawable>>* collect
|
|||
}
|
||||
case PyObjectsEnum::UIGRID: {
|
||||
auto grid = std::static_pointer_cast<UIGrid>(drawable);
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid");
|
||||
auto type = &mcrfpydef::PyUIGridType;
|
||||
auto o = (PyUIGridObject*)type->tp_alloc(type, 0);
|
||||
if (o) {
|
||||
o->data = grid;
|
||||
|
|
@ -1620,7 +1620,7 @@ static void find_in_grid_entities(UIGrid* grid, const std::string& pattern,
|
|||
|
||||
// Entities delegate name to their sprite
|
||||
if (name_matches_pattern(entity->sprite.name, pattern)) {
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Entity");
|
||||
auto type = &mcrfpydef::PyUIEntityType;
|
||||
auto o = (PyUIEntityObject*)type->tp_alloc(type, 0);
|
||||
if (o) {
|
||||
o->data = entity;
|
||||
|
|
@ -1817,15 +1817,12 @@ static bool extract_point(PyObject* obj, int* x, int* y, const char* arg_name) {
|
|||
}
|
||||
|
||||
// Try Vector type
|
||||
PyObject* vector_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
if (vector_type && PyObject_IsInstance(obj, vector_type)) {
|
||||
Py_DECREF(vector_type);
|
||||
if (PyObject_IsInstance(obj, (PyObject*)&mcrfpydef::PyVectorType)) {
|
||||
PyVectorObject* vec = (PyVectorObject*)obj;
|
||||
*x = static_cast<int>(vec->data.x);
|
||||
*y = static_cast<int>(vec->data.y);
|
||||
return true;
|
||||
}
|
||||
Py_XDECREF(vector_type);
|
||||
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%s: expected (x, y) tuple or Vector, got %s",
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include "McRFPy_API.h"
|
||||
#include "GameEngine.h"
|
||||
#include "PyPositionHelper.h"
|
||||
#include "PyVector.h"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
|
@ -262,37 +263,20 @@ PyObject* McRFPy_Automation::_position(PyObject* self, PyObject* args) {
|
|||
y = simulated_mouse_pos.y;
|
||||
}
|
||||
|
||||
// Return a Vector object - get type from module to ensure we use the initialized type
|
||||
auto vector_type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
if (!vector_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Vector type not found in mcrfpy module");
|
||||
return NULL;
|
||||
}
|
||||
PyObject* result = PyObject_CallFunction((PyObject*)vector_type, "ff", (float)x, (float)y);
|
||||
Py_DECREF(vector_type);
|
||||
// Return a Vector object
|
||||
PyObject* result = PyObject_CallFunction((PyObject*)&mcrfpydef::PyVectorType, "ff", (float)x, (float)y);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get screen size - returns Vector object
|
||||
PyObject* McRFPy_Automation::_size(PyObject* self, PyObject* args) {
|
||||
// Get Vector type from module to ensure we use the initialized type
|
||||
auto vector_type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
if (!vector_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Vector type not found in mcrfpy module");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
auto engine = getGameEngine();
|
||||
if (!engine || !engine->getRenderTargetPtr()) {
|
||||
PyObject* result = PyObject_CallFunction((PyObject*)vector_type, "ff", 1024.0f, 768.0f); // Default size
|
||||
Py_DECREF(vector_type);
|
||||
return result;
|
||||
return PyObject_CallFunction((PyObject*)&mcrfpydef::PyVectorType, "ff", 1024.0f, 768.0f); // Default size
|
||||
}
|
||||
|
||||
sf::Vector2u size = engine->getRenderTarget().getSize();
|
||||
PyObject* result = PyObject_CallFunction((PyObject*)vector_type, "ff", (float)size.x, (float)size.y);
|
||||
Py_DECREF(vector_type);
|
||||
return result;
|
||||
return PyObject_CallFunction((PyObject*)&mcrfpydef::PyVectorType, "ff", (float)size.x, (float)size.y);
|
||||
}
|
||||
|
||||
// Check if coordinates are on screen - accepts onScreen(x, y) or onScreen(pos)
|
||||
|
|
|
|||
|
|
@ -216,17 +216,11 @@ PyObject* PyAnimation::start(PyAnimationObject* self, PyObject* args, PyObject*
|
|||
return NULL; // Error already set
|
||||
}
|
||||
|
||||
// Get type objects from the module to ensure they're initialized
|
||||
PyObject* frame_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame");
|
||||
PyObject* caption_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption");
|
||||
PyObject* sprite_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite");
|
||||
PyObject* grid_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid");
|
||||
PyObject* entity_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Entity");
|
||||
|
||||
// Use direct type references (no ref counting needed for static types)
|
||||
bool handled = false;
|
||||
|
||||
// Use PyObject_IsInstance to support inheritance
|
||||
if (frame_type && PyObject_IsInstance(target_obj, frame_type)) {
|
||||
if (PyObject_IsInstance(target_obj, (PyObject*)&mcrfpydef::PyUIFrameType)) {
|
||||
PyUIFrameObject* frame = (PyUIFrameObject*)target_obj;
|
||||
if (frame->data) {
|
||||
self->data->start(frame->data);
|
||||
|
|
@ -234,7 +228,7 @@ PyObject* PyAnimation::start(PyAnimationObject* self, PyObject* args, PyObject*
|
|||
handled = true;
|
||||
}
|
||||
}
|
||||
else if (caption_type && PyObject_IsInstance(target_obj, caption_type)) {
|
||||
else if (PyObject_IsInstance(target_obj, (PyObject*)&mcrfpydef::PyUICaptionType)) {
|
||||
PyUICaptionObject* caption = (PyUICaptionObject*)target_obj;
|
||||
if (caption->data) {
|
||||
self->data->start(caption->data);
|
||||
|
|
@ -242,7 +236,7 @@ PyObject* PyAnimation::start(PyAnimationObject* self, PyObject* args, PyObject*
|
|||
handled = true;
|
||||
}
|
||||
}
|
||||
else if (sprite_type && PyObject_IsInstance(target_obj, sprite_type)) {
|
||||
else if (PyObject_IsInstance(target_obj, (PyObject*)&mcrfpydef::PyUISpriteType)) {
|
||||
PyUISpriteObject* sprite = (PyUISpriteObject*)target_obj;
|
||||
if (sprite->data) {
|
||||
self->data->start(sprite->data);
|
||||
|
|
@ -250,7 +244,7 @@ PyObject* PyAnimation::start(PyAnimationObject* self, PyObject* args, PyObject*
|
|||
handled = true;
|
||||
}
|
||||
}
|
||||
else if (grid_type && PyObject_IsInstance(target_obj, grid_type)) {
|
||||
else if (PyObject_IsInstance(target_obj, (PyObject*)&mcrfpydef::PyUIGridType)) {
|
||||
PyUIGridObject* grid = (PyUIGridObject*)target_obj;
|
||||
if (grid->data) {
|
||||
self->data->start(grid->data);
|
||||
|
|
@ -258,7 +252,7 @@ PyObject* PyAnimation::start(PyAnimationObject* self, PyObject* args, PyObject*
|
|||
handled = true;
|
||||
}
|
||||
}
|
||||
else if (entity_type && PyObject_IsInstance(target_obj, entity_type)) {
|
||||
else if (PyObject_IsInstance(target_obj, (PyObject*)&mcrfpydef::PyUIEntityType)) {
|
||||
// Special handling for Entity since it doesn't inherit from UIDrawable
|
||||
PyUIEntityObject* entity = (PyUIEntityObject*)target_obj;
|
||||
if (entity->data) {
|
||||
|
|
@ -268,13 +262,6 @@ PyObject* PyAnimation::start(PyAnimationObject* self, PyObject* args, PyObject*
|
|||
}
|
||||
}
|
||||
|
||||
// Clean up references
|
||||
Py_XDECREF(frame_type);
|
||||
Py_XDECREF(caption_type);
|
||||
Py_XDECREF(sprite_type);
|
||||
Py_XDECREF(grid_type);
|
||||
Py_XDECREF(entity_type);
|
||||
|
||||
if (!handled) {
|
||||
PyErr_SetString(PyExc_TypeError, "Target must be a Frame, Caption, Sprite, Grid, or Entity (or a subclass of these)");
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -947,19 +947,12 @@ PyObject* PyBSP::to_heightmap(PyBSPObject* self, PyObject* args, PyObject* kwds)
|
|||
}
|
||||
|
||||
// Create HeightMap
|
||||
PyObject* heightmap_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "HeightMap");
|
||||
if (!heightmap_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "HeightMap type not found");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyObject* size_tuple = Py_BuildValue("(ii)", width, height);
|
||||
PyObject* hmap_args = PyTuple_Pack(1, size_tuple);
|
||||
Py_DECREF(size_tuple);
|
||||
|
||||
PyHeightMapObject* hmap = (PyHeightMapObject*)PyObject_Call(heightmap_type, hmap_args, nullptr);
|
||||
PyHeightMapObject* hmap = (PyHeightMapObject*)PyObject_Call((PyObject*)&mcrfpydef::PyHeightMapType, hmap_args, nullptr);
|
||||
Py_DECREF(hmap_args);
|
||||
Py_DECREF(heightmap_type);
|
||||
|
||||
if (!hmap) {
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -53,16 +53,8 @@ PyClickCallable::PyClickCallable()
|
|||
|
||||
void PyClickCallable::call(sf::Vector2f mousepos, std::string button, std::string action)
|
||||
{
|
||||
// Create a Vector object for the position - must fetch the finalized type from the module
|
||||
PyObject* vector_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
if (!vector_type) {
|
||||
std::cerr << "Failed to get Vector type for click callback" << std::endl;
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
return;
|
||||
}
|
||||
PyObject* pos = PyObject_CallFunction(vector_type, "ff", mousepos.x, mousepos.y);
|
||||
Py_DECREF(vector_type);
|
||||
// Create a Vector object for the position
|
||||
PyObject* pos = PyObject_CallFunction((PyObject*)&mcrfpydef::PyVectorType, "ff", mousepos.x, mousepos.y);
|
||||
if (!pos) {
|
||||
std::cerr << "Failed to create Vector object for click callback" << std::endl;
|
||||
PyErr_Print();
|
||||
|
|
@ -203,15 +195,7 @@ void PyHoverCallable::call(sf::Vector2f mousepos)
|
|||
if (target == Py_None || target == NULL) return;
|
||||
|
||||
// Create a Vector object for the position
|
||||
PyObject* vector_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
if (!vector_type) {
|
||||
std::cerr << "Failed to get Vector type for hover callback" << std::endl;
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
return;
|
||||
}
|
||||
PyObject* pos = PyObject_CallFunction(vector_type, "ff", mousepos.x, mousepos.y);
|
||||
Py_DECREF(vector_type);
|
||||
PyObject* pos = PyObject_CallFunction((PyObject*)&mcrfpydef::PyVectorType, "ff", mousepos.x, mousepos.y);
|
||||
if (!pos) {
|
||||
std::cerr << "Failed to create Vector object for hover callback" << std::endl;
|
||||
PyErr_Print();
|
||||
|
|
@ -263,15 +247,7 @@ void PyCellHoverCallable::call(sf::Vector2i cellpos)
|
|||
if (target == Py_None || target == NULL) return;
|
||||
|
||||
// Create a Vector object for the cell position
|
||||
PyObject* vector_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
if (!vector_type) {
|
||||
std::cerr << "Failed to get Vector type for cell hover callback" << std::endl;
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
return;
|
||||
}
|
||||
PyObject* pos = PyObject_CallFunction(vector_type, "ii", cellpos.x, cellpos.y);
|
||||
Py_DECREF(vector_type);
|
||||
PyObject* pos = PyObject_CallFunction((PyObject*)&mcrfpydef::PyVectorType, "ii", cellpos.x, cellpos.y);
|
||||
if (!pos) {
|
||||
std::cerr << "Failed to create Vector object for cell hover callback" << std::endl;
|
||||
PyErr_Print();
|
||||
|
|
|
|||
|
|
@ -52,12 +52,8 @@ PyColor::PyColor(sf::Color target)
|
|||
|
||||
PyObject* PyColor::pyObject()
|
||||
{
|
||||
PyTypeObject* type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Color");
|
||||
if (!type) return nullptr;
|
||||
|
||||
PyColorObject* obj = (PyColorObject*)type->tp_alloc(type, 0);
|
||||
Py_DECREF(type);
|
||||
|
||||
PyColorObject* obj = (PyColorObject*)mcrfpydef::PyColorType.tp_alloc(&mcrfpydef::PyColorType, 0);
|
||||
|
||||
if (obj) {
|
||||
obj->data = data;
|
||||
}
|
||||
|
|
@ -72,14 +68,9 @@ sf::Color PyColor::fromPy(PyObject* obj)
|
|||
}
|
||||
|
||||
// Check if it's already a Color object
|
||||
PyTypeObject* color_type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Color");
|
||||
if (color_type) {
|
||||
bool is_color = PyObject_TypeCheck(obj, color_type);
|
||||
Py_DECREF(color_type);
|
||||
if (is_color) {
|
||||
PyColorObject* self = (PyColorObject*)obj;
|
||||
return self->data;
|
||||
}
|
||||
if (PyObject_TypeCheck(obj, &mcrfpydef::PyColorType)) {
|
||||
PyColorObject* self = (PyColorObject*)obj;
|
||||
return self->data;
|
||||
}
|
||||
|
||||
// Handle tuple or list input
|
||||
|
|
@ -382,9 +373,7 @@ PyObject* PyColor::lerp(PyColorObject* self, PyObject* args)
|
|||
}
|
||||
|
||||
// Validate other color
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Color");
|
||||
if (!PyObject_IsInstance(other_obj, (PyObject*)type)) {
|
||||
Py_DECREF(type);
|
||||
if (!PyObject_IsInstance(other_obj, (PyObject*)&mcrfpydef::PyColorType)) {
|
||||
PyErr_SetString(PyExc_TypeError, "First argument must be a Color");
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -402,8 +391,8 @@ PyObject* PyColor::lerp(PyColorObject* self, PyObject* args)
|
|||
sf::Uint8 a = static_cast<sf::Uint8>(self->data.a + (other->data.a - self->data.a) * t);
|
||||
|
||||
// Create new Color object
|
||||
auto type = &mcrfpydef::PyColorType;
|
||||
PyColorObject* result = (PyColorObject*)type->tp_alloc(type, 0);
|
||||
Py_DECREF(type);
|
||||
|
||||
if (result) {
|
||||
result->data = sf::Color(r, g, b, a);
|
||||
|
|
|
|||
|
|
@ -56,17 +56,12 @@ static PyObject* valueToResult(uint8_t value, PyObject* enum_type) {
|
|||
// Helper: Create a new DiscreteMap object with given dimensions
|
||||
// ============================================================================
|
||||
static PyDiscreteMapObject* CreateNewDiscreteMap(int width, int height) {
|
||||
// Get the DiscreteMap type from the module
|
||||
PyObject* dmap_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "DiscreteMap");
|
||||
if (!dmap_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "DiscreteMap type not found in module");
|
||||
return nullptr;
|
||||
}
|
||||
// Get the DiscreteMap type
|
||||
PyObject* dmap_type = (PyObject*)&mcrfpydef::PyDiscreteMapType;
|
||||
|
||||
// Create size tuple
|
||||
PyObject* size_tuple = Py_BuildValue("(ii)", width, height);
|
||||
if (!size_tuple) {
|
||||
Py_DECREF(dmap_type);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -74,14 +69,12 @@ static PyDiscreteMapObject* CreateNewDiscreteMap(int width, int height) {
|
|||
PyObject* args = PyTuple_Pack(1, size_tuple);
|
||||
Py_DECREF(size_tuple);
|
||||
if (!args) {
|
||||
Py_DECREF(dmap_type);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create the new object
|
||||
PyDiscreteMapObject* new_dmap = (PyDiscreteMapObject*)PyObject_Call(dmap_type, args, nullptr);
|
||||
Py_DECREF(args);
|
||||
Py_DECREF(dmap_type);
|
||||
|
||||
if (!new_dmap) {
|
||||
return nullptr; // Python error already set
|
||||
|
|
@ -94,16 +87,8 @@ static PyDiscreteMapObject* CreateNewDiscreteMap(int width, int height) {
|
|||
// Helper: Validate another DiscreteMap for binary operations
|
||||
// ============================================================================
|
||||
static PyDiscreteMapObject* validateOtherDiscreteMapType(PyObject* other_obj, const char* method_name) {
|
||||
// Get the DiscreteMap type from the module
|
||||
PyObject* dmap_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "DiscreteMap");
|
||||
if (!dmap_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "DiscreteMap type not found in module");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Check if other is a DiscreteMap
|
||||
int is_dmap = PyObject_IsInstance(other_obj, dmap_type);
|
||||
Py_DECREF(dmap_type);
|
||||
int is_dmap = PyObject_IsInstance(other_obj, (PyObject*)&mcrfpydef::PyDiscreteMapType);
|
||||
|
||||
if (is_dmap < 0) {
|
||||
return nullptr; // Error during check
|
||||
|
|
@ -1331,14 +1316,7 @@ PyObject* PyDiscreteMap::from_heightmap(PyTypeObject* type, PyObject* args, PyOb
|
|||
}
|
||||
|
||||
// Validate HeightMap
|
||||
PyObject* hmap_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "HeightMap");
|
||||
if (!hmap_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "HeightMap type not found in module");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int is_hmap = PyObject_IsInstance(hmap_obj, hmap_type);
|
||||
Py_DECREF(hmap_type);
|
||||
int is_hmap = PyObject_IsInstance(hmap_obj, (PyObject*)&mcrfpydef::PyHeightMapType);
|
||||
|
||||
if (is_hmap < 0) {
|
||||
return nullptr;
|
||||
|
|
@ -1507,28 +1485,21 @@ PyObject* PyDiscreteMap::to_heightmap(PyDiscreteMapObject* self, PyObject* args,
|
|||
}
|
||||
|
||||
// Get HeightMap type and create new instance
|
||||
PyObject* hmap_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "HeightMap");
|
||||
if (!hmap_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "HeightMap type not found in module");
|
||||
return nullptr;
|
||||
}
|
||||
PyObject* hmap_type = (PyObject*)&mcrfpydef::PyHeightMapType;
|
||||
|
||||
PyObject* size_tuple = Py_BuildValue("(ii)", self->w, self->h);
|
||||
if (!size_tuple) {
|
||||
Py_DECREF(hmap_type);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyObject* hmap_args = PyTuple_Pack(1, size_tuple);
|
||||
Py_DECREF(size_tuple);
|
||||
if (!hmap_args) {
|
||||
Py_DECREF(hmap_type);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyHeightMapObject* result = (PyHeightMapObject*)PyObject_Call(hmap_type, hmap_args, nullptr);
|
||||
Py_DECREF(hmap_args);
|
||||
Py_DECREF(hmap_type);
|
||||
|
||||
if (!result) {
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@ PyFont::PyFont(std::string filename)
|
|||
|
||||
PyObject* PyFont::pyObject()
|
||||
{
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Font");
|
||||
//PyObject* obj = PyType_GenericAlloc(&mcrfpydef::PyFontType, 0);
|
||||
auto type = &mcrfpydef::PyFontType;
|
||||
PyObject* obj = PyFont::pynew(type, Py_None, Py_None);
|
||||
try {
|
||||
((PyFontObject*)obj)->data = shared_from_this();
|
||||
|
|
|
|||
|
|
@ -1218,17 +1218,12 @@ static PyHeightMapObject* validateOtherHeightMapType(PyObject* other_obj, const
|
|||
// Helper: Create a new HeightMap object with same dimensions
|
||||
static PyHeightMapObject* CreateNewHeightMap(int width, int height)
|
||||
{
|
||||
// Get the HeightMap type from the module
|
||||
PyObject* heightmap_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "HeightMap");
|
||||
if (!heightmap_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "HeightMap type not found in module");
|
||||
return nullptr;
|
||||
}
|
||||
// Get the HeightMap type
|
||||
PyObject* heightmap_type = (PyObject*)&mcrfpydef::PyHeightMapType;
|
||||
|
||||
// Create size tuple
|
||||
PyObject* size_tuple = Py_BuildValue("(ii)", width, height);
|
||||
if (!size_tuple) {
|
||||
Py_DECREF(heightmap_type);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -1236,14 +1231,12 @@ static PyHeightMapObject* CreateNewHeightMap(int width, int height)
|
|||
PyObject* args = PyTuple_Pack(1, size_tuple);
|
||||
Py_DECREF(size_tuple);
|
||||
if (!args) {
|
||||
Py_DECREF(heightmap_type);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create the new object
|
||||
PyHeightMapObject* new_hmap = (PyHeightMapObject*)PyObject_Call(heightmap_type, args, nullptr);
|
||||
Py_DECREF(args);
|
||||
Py_DECREF(heightmap_type);
|
||||
|
||||
if (!new_hmap) {
|
||||
return nullptr; // Python error already set
|
||||
|
|
@ -1981,14 +1974,7 @@ PyObject* PyHeightMap::gradients(PyHeightMapObject* self, PyObject* args, PyObje
|
|||
static PyHeightMapObject* validateOtherHeightMapType(PyObject* other_obj, const char* method_name)
|
||||
{
|
||||
// Check that other is a HeightMap
|
||||
PyObject* heightmap_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "HeightMap");
|
||||
if (!heightmap_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "HeightMap type not found in module");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int is_hmap = PyObject_IsInstance(other_obj, heightmap_type);
|
||||
Py_DECREF(heightmap_type);
|
||||
int is_hmap = PyObject_IsInstance(other_obj, (PyObject*)&mcrfpydef::PyHeightMapType);
|
||||
|
||||
if (is_hmap < 0) {
|
||||
return nullptr; // Error in isinstance check
|
||||
|
|
@ -2326,13 +2312,7 @@ static bool parseNoiseSampleParams(
|
|||
}
|
||||
|
||||
// Validate source is a NoiseSource
|
||||
PyObject* noise_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "NoiseSource");
|
||||
if (!noise_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "NoiseSource type not found in module");
|
||||
return false;
|
||||
}
|
||||
int is_noise = PyObject_IsInstance(source_obj, noise_type);
|
||||
Py_DECREF(noise_type);
|
||||
int is_noise = PyObject_IsInstance(source_obj, (PyObject*)&mcrfpydef::PyNoiseSourceType);
|
||||
|
||||
if (is_noise < 0) return false;
|
||||
if (!is_noise) {
|
||||
|
|
@ -2539,34 +2519,26 @@ static bool collectBSPNodes(
|
|||
return false;
|
||||
}
|
||||
|
||||
PyObject* bspnode_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "BSPNode");
|
||||
if (!bspnode_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "BSPNode type not found in module");
|
||||
return false;
|
||||
}
|
||||
PyObject* bspnode_type = (PyObject*)&mcrfpydef::PyBSPNodeType;
|
||||
|
||||
Py_ssize_t count = PyList_Size(nodes_list);
|
||||
for (Py_ssize_t i = 0; i < count; i++) {
|
||||
PyObject* item = PyList_GetItem(nodes_list, i);
|
||||
int is_node = PyObject_IsInstance(item, bspnode_type);
|
||||
if (is_node < 0) {
|
||||
Py_DECREF(bspnode_type);
|
||||
return false;
|
||||
}
|
||||
if (!is_node) {
|
||||
Py_DECREF(bspnode_type);
|
||||
PyErr_Format(PyExc_TypeError, "%s() nodes[%zd] is not a BSPNode", method_name, i);
|
||||
return false;
|
||||
}
|
||||
|
||||
PyBSPNodeObject* node = (PyBSPNodeObject*)item;
|
||||
if (!PyBSPNode::checkValid(node)) {
|
||||
Py_DECREF(bspnode_type);
|
||||
return false; // Error already set
|
||||
}
|
||||
out_nodes.push_back(node->node);
|
||||
}
|
||||
Py_DECREF(bspnode_type);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2646,13 +2618,7 @@ PyObject* PyHeightMap::add_bsp(PyHeightMapObject* self, PyObject* args, PyObject
|
|||
}
|
||||
|
||||
// Validate bsp is a BSP
|
||||
PyObject* bsp_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "BSP");
|
||||
if (!bsp_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "BSP type not found in module");
|
||||
return nullptr;
|
||||
}
|
||||
int is_bsp = PyObject_IsInstance(bsp_obj, bsp_type);
|
||||
Py_DECREF(bsp_type);
|
||||
int is_bsp = PyObject_IsInstance(bsp_obj, (PyObject*)&mcrfpydef::PyBSPType);
|
||||
|
||||
if (is_bsp < 0) return nullptr;
|
||||
if (!is_bsp) {
|
||||
|
|
@ -2740,13 +2706,7 @@ PyObject* PyHeightMap::multiply_bsp(PyHeightMapObject* self, PyObject* args, PyO
|
|||
}
|
||||
|
||||
// Validate bsp is a BSP
|
||||
PyObject* bsp_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "BSP");
|
||||
if (!bsp_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "BSP type not found in module");
|
||||
return nullptr;
|
||||
}
|
||||
int is_bsp = PyObject_IsInstance(bsp_obj, bsp_type);
|
||||
Py_DECREF(bsp_type);
|
||||
int is_bsp = PyObject_IsInstance(bsp_obj, (PyObject*)&mcrfpydef::PyBSPType);
|
||||
|
||||
if (is_bsp < 0) return nullptr;
|
||||
if (!is_bsp) {
|
||||
|
|
|
|||
|
|
@ -74,14 +74,7 @@ PyObject* PyMouse::get_pos(PyObject* self, void* closure)
|
|||
sf::Vector2i pos = getMousePosition();
|
||||
|
||||
// Return a Vector object
|
||||
auto vector_type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
if (!vector_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Vector type not found in mcrfpy module");
|
||||
return NULL;
|
||||
}
|
||||
PyObject* result = PyObject_CallFunction((PyObject*)vector_type, "ff", (float)pos.x, (float)pos.y);
|
||||
Py_DECREF(vector_type);
|
||||
return result;
|
||||
return PyObject_CallFunction((PyObject*)&mcrfpydef::PyVectorType, "ff", (float)pos.x, (float)pos.y);
|
||||
}
|
||||
|
||||
PyObject* PyMouse::get_left(PyObject* self, void* closure)
|
||||
|
|
|
|||
|
|
@ -76,9 +76,8 @@ void PyMusic::setPosition(float pos)
|
|||
|
||||
PyObject* PyMusic::pyObject()
|
||||
{
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Music");
|
||||
auto type = &mcrfpydef::PyMusicType;
|
||||
PyObject* obj = PyMusic::pynew(type, Py_None, Py_None);
|
||||
Py_DECREF(type);
|
||||
try {
|
||||
((PyMusicObject*)obj)->data = shared_from_this();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -464,28 +464,19 @@ PyObject* PyNoiseSource::sample(PyNoiseSourceObject* self, PyObject* args, PyObj
|
|||
}
|
||||
|
||||
// Create HeightMap
|
||||
PyObject* heightmap_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "HeightMap");
|
||||
if (!heightmap_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "HeightMap type not found in module");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyObject* size_tuple = Py_BuildValue("(ii)", width, height);
|
||||
if (!size_tuple) {
|
||||
Py_DECREF(heightmap_type);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyObject* hmap_args = PyTuple_Pack(1, size_tuple);
|
||||
Py_DECREF(size_tuple);
|
||||
if (!hmap_args) {
|
||||
Py_DECREF(heightmap_type);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyHeightMapObject* hmap = (PyHeightMapObject*)PyObject_Call(heightmap_type, hmap_args, nullptr);
|
||||
PyHeightMapObject* hmap = (PyHeightMapObject*)PyObject_Call((PyObject*)&mcrfpydef::PyHeightMapType, hmap_args, nullptr);
|
||||
Py_DECREF(hmap_args);
|
||||
Py_DECREF(heightmap_type);
|
||||
|
||||
if (!hmap) {
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "McRFPy_Automation.h" // #111 - For simulated mouse position
|
||||
#include "PythonObjectCache.h" // #184 - For subclass callback support
|
||||
#include "McRFPy_API.h" // For Vector type access
|
||||
#include "PyVector.h" // For direct PyVectorType reference
|
||||
#include "PyMouseButton.h" // For MouseButton enum
|
||||
#include "PyInputState.h" // For InputState enum
|
||||
#include <algorithm>
|
||||
|
|
@ -55,16 +56,7 @@ static bool tryCallPythonMethod(UIDrawable* drawable, const char* method_name,
|
|||
|
||||
if (method && PyCallable_Check(method) && method != Py_None) {
|
||||
// Create Vector object for position (matches property callback signature)
|
||||
PyObject* vector_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
if (!vector_type) {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
Py_XDECREF(method);
|
||||
Py_DECREF(pyObj);
|
||||
return false;
|
||||
}
|
||||
PyObject* pos = PyObject_CallFunction(vector_type, "ff", mousepos.x, mousepos.y);
|
||||
Py_DECREF(vector_type);
|
||||
PyObject* pos = PyObject_CallFunction((PyObject*)&mcrfpydef::PyVectorType, "ff", mousepos.x, mousepos.y);
|
||||
if (!pos) {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
|
|
@ -164,16 +156,7 @@ static bool tryCallPythonMethod(UIDrawable* drawable, const char* method_name,
|
|||
|
||||
if (method && PyCallable_Check(method) && method != Py_None) {
|
||||
// Create Vector object for position
|
||||
PyObject* vector_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
if (!vector_type) {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
Py_XDECREF(method);
|
||||
Py_DECREF(pyObj);
|
||||
return false;
|
||||
}
|
||||
PyObject* pos = PyObject_CallFunction(vector_type, "ff", mousepos.x, mousepos.y);
|
||||
Py_DECREF(vector_type);
|
||||
PyObject* pos = PyObject_CallFunction((PyObject*)&mcrfpydef::PyVectorType, "ff", mousepos.x, mousepos.y);
|
||||
if (!pos) {
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "PyTransition.h"
|
||||
#include "PyKey.h"
|
||||
#include "PyInputState.h"
|
||||
#include "PyVector.h"
|
||||
#include <iostream>
|
||||
|
||||
// Static map to store Python scene objects by name
|
||||
|
|
@ -211,11 +212,8 @@ static PyObject* PySceneClass_get_pos(PySceneObject* self, void* closure)
|
|||
}
|
||||
|
||||
// Create a Vector object
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
if (!type) return NULL;
|
||||
PyObject* args = Py_BuildValue("(ff)", self->scene->position.x, self->scene->position.y);
|
||||
PyObject* result = PyObject_CallObject((PyObject*)type, args);
|
||||
Py_DECREF(type);
|
||||
PyObject* result = PyObject_CallObject((PyObject*)&mcrfpydef::PyVectorType, args);
|
||||
Py_DECREF(args);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -425,15 +423,8 @@ void PySceneClass::call_on_resize(PySceneObject* self, sf::Vector2u new_size)
|
|||
PyObject* method = PyObject_GetAttrString((PyObject*)self, "on_resize");
|
||||
if (method && PyCallable_Check(method)) {
|
||||
// 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);
|
||||
PyObject* vector = PyObject_CallObject((PyObject*)&mcrfpydef::PyVectorType, args);
|
||||
Py_DECREF(args);
|
||||
|
||||
if (!vector) {
|
||||
|
|
@ -716,14 +707,11 @@ int McRFPy_API::api_set_current_scene(PyObject* value)
|
|||
if (PyUnicode_Check(value)) {
|
||||
scene_name = PyUnicode_AsUTF8(value);
|
||||
} else {
|
||||
// Check if value is a Scene or Scene subclass - use same pattern as rest of codebase
|
||||
PyObject* scene_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Scene");
|
||||
if (scene_type && PyObject_IsInstance(value, scene_type)) {
|
||||
Py_DECREF(scene_type);
|
||||
// Check if value is a Scene or Scene subclass
|
||||
if (PyObject_IsInstance(value, (PyObject*)&mcrfpydef::PySceneType)) {
|
||||
PySceneObject* scene_obj = (PySceneObject*)value;
|
||||
scene_name = scene_obj->name.c_str();
|
||||
} else {
|
||||
Py_XDECREF(scene_type);
|
||||
PyErr_SetString(PyExc_TypeError, "current_scene must be a Scene object or scene name string");
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,9 +91,8 @@ void PySound::setPitch(float pitch)
|
|||
|
||||
PyObject* PySound::pyObject()
|
||||
{
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sound");
|
||||
auto type = &mcrfpydef::PySoundType;
|
||||
PyObject* obj = PySound::pynew(type, Py_None, Py_None);
|
||||
Py_DECREF(type);
|
||||
try {
|
||||
((PySoundObject*)obj)->data = shared_from_this();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,11 +130,9 @@ PyVector::PyVector(sf::Vector2f target)
|
|||
|
||||
PyObject* PyVector::pyObject()
|
||||
{
|
||||
PyTypeObject* type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
if (!type) return nullptr;
|
||||
|
||||
PyTypeObject* type = &mcrfpydef::PyVectorType;
|
||||
|
||||
PyVectorObject* obj = (PyVectorObject*)type->tp_alloc(type, 0);
|
||||
Py_DECREF(type);
|
||||
|
||||
if (obj) {
|
||||
obj->data = data;
|
||||
|
|
@ -304,7 +302,7 @@ PyVectorObject* PyVector::from_arg(PyObject* args)
|
|||
PyObject* PyVector::add(PyObject* left, PyObject* right)
|
||||
{
|
||||
// Check if both operands are vectors
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
auto type = &mcrfpydef::PyVectorType;
|
||||
|
||||
PyVectorObject* vec1 = nullptr;
|
||||
PyVectorObject* vec2 = nullptr;
|
||||
|
|
@ -326,7 +324,7 @@ PyObject* PyVector::add(PyObject* left, PyObject* right)
|
|||
|
||||
PyObject* PyVector::subtract(PyObject* left, PyObject* right)
|
||||
{
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
auto type = &mcrfpydef::PyVectorType;
|
||||
|
||||
PyVectorObject* vec1 = nullptr;
|
||||
PyVectorObject* vec2 = nullptr;
|
||||
|
|
@ -348,7 +346,7 @@ PyObject* PyVector::subtract(PyObject* left, PyObject* right)
|
|||
|
||||
PyObject* PyVector::multiply(PyObject* left, PyObject* right)
|
||||
{
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
auto type = &mcrfpydef::PyVectorType;
|
||||
|
||||
PyVectorObject* vec = nullptr;
|
||||
double scalar = 0.0;
|
||||
|
|
@ -377,7 +375,7 @@ PyObject* PyVector::multiply(PyObject* left, PyObject* right)
|
|||
|
||||
PyObject* PyVector::divide(PyObject* left, PyObject* right)
|
||||
{
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
auto type = &mcrfpydef::PyVectorType;
|
||||
|
||||
// Only support Vector / scalar
|
||||
if (!PyObject_IsInstance(left, (PyObject*)type) || (!PyFloat_Check(right) && !PyLong_Check(right))) {
|
||||
|
|
@ -402,7 +400,7 @@ PyObject* PyVector::divide(PyObject* left, PyObject* right)
|
|||
|
||||
PyObject* PyVector::negative(PyObject* self)
|
||||
{
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
auto type = &mcrfpydef::PyVectorType;
|
||||
PyVectorObject* vec = (PyVectorObject*)self;
|
||||
|
||||
auto result = (PyVectorObject*)type->tp_alloc(type, 0);
|
||||
|
|
@ -426,7 +424,7 @@ int PyVector::bool_check(PyObject* self)
|
|||
|
||||
PyObject* PyVector::richcompare(PyObject* left, PyObject* right, int op)
|
||||
{
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
auto type = &mcrfpydef::PyVectorType;
|
||||
|
||||
float left_x, left_y, right_x, right_y;
|
||||
|
||||
|
|
@ -509,9 +507,9 @@ PyObject* PyVector::normalize(PyVectorObject* self, PyObject* Py_UNUSED(ignored)
|
|||
{
|
||||
float mag = std::sqrt(self->data.x * self->data.x + self->data.y * self->data.y);
|
||||
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
auto type = &mcrfpydef::PyVectorType;
|
||||
auto result = (PyVectorObject*)type->tp_alloc(type, 0);
|
||||
|
||||
|
||||
if (result) {
|
||||
if (mag > 0.0f) {
|
||||
result->data = sf::Vector2f(self->data.x / mag, self->data.y / mag);
|
||||
|
|
@ -526,9 +524,7 @@ PyObject* PyVector::normalize(PyVectorObject* self, PyObject* Py_UNUSED(ignored)
|
|||
|
||||
PyObject* PyVector::dot(PyVectorObject* self, PyObject* other)
|
||||
{
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
|
||||
if (!PyObject_IsInstance(other, (PyObject*)type)) {
|
||||
if (!PyObject_IsInstance(other, (PyObject*)&mcrfpydef::PyVectorType)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Argument must be a Vector");
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -541,9 +537,7 @@ PyObject* PyVector::dot(PyVectorObject* self, PyObject* other)
|
|||
|
||||
PyObject* PyVector::distance_to(PyVectorObject* self, PyObject* other)
|
||||
{
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
|
||||
if (!PyObject_IsInstance(other, (PyObject*)type)) {
|
||||
if (!PyObject_IsInstance(other, (PyObject*)&mcrfpydef::PyVectorType)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Argument must be a Vector");
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -564,7 +558,7 @@ PyObject* PyVector::angle(PyVectorObject* self, PyObject* Py_UNUSED(ignored))
|
|||
|
||||
PyObject* PyVector::copy(PyVectorObject* self, PyObject* Py_UNUSED(ignored))
|
||||
{
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
auto type = &mcrfpydef::PyVectorType;
|
||||
auto result = (PyVectorObject*)type->tp_alloc(type, 0);
|
||||
|
||||
if (result) {
|
||||
|
|
@ -576,7 +570,7 @@ PyObject* PyVector::copy(PyVectorObject* self, PyObject* Py_UNUSED(ignored))
|
|||
|
||||
PyObject* PyVector::floor(PyVectorObject* self, PyObject* Py_UNUSED(ignored))
|
||||
{
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
auto type = &mcrfpydef::PyVectorType;
|
||||
auto result = (PyVectorObject*)type->tp_alloc(type, 0);
|
||||
|
||||
if (result) {
|
||||
|
|
|
|||
|
|
@ -391,10 +391,8 @@ bool UIArc::hasProperty(const std::string& name) const {
|
|||
// Python API implementation
|
||||
PyObject* UIArc::get_center(PyUIArcObject* self, void* closure) {
|
||||
auto center = self->data->getCenter();
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
if (!type) return NULL;
|
||||
auto type = &mcrfpydef::PyVectorType;
|
||||
PyObject* result = PyObject_CallFunction((PyObject*)type, "ff", center.x, center.y);
|
||||
Py_DECREF(type);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -450,11 +448,10 @@ int UIArc::set_end_angle(PyUIArcObject* self, PyObject* value, void* closure) {
|
|||
|
||||
PyObject* UIArc::get_color(PyUIArcObject* self, void* closure) {
|
||||
auto color = self->data->getColor();
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Color");
|
||||
auto type = &mcrfpydef::PyColorType;
|
||||
PyObject* args = Py_BuildValue("(iiii)", color.r, color.g, color.b, color.a);
|
||||
PyObject* obj = PyObject_CallObject((PyObject*)type, args);
|
||||
Py_DECREF(args);
|
||||
Py_DECREF(type);
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
@ -634,11 +631,7 @@ int UIArc::init(PyUIArcObject* self, PyObject* args, PyObject* kwds) {
|
|||
}
|
||||
|
||||
// #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);
|
||||
}
|
||||
self->data->is_python_subclass = (PyObject*)Py_TYPE(self) != (PyObject*)&mcrfpydef::PyUIArcType;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -255,7 +255,7 @@ int UICaption::set_color_member(PyUICaptionObject* self, PyObject* value, void*
|
|||
auto member_ptr = reinterpret_cast<intptr_t>(closure);
|
||||
//TODO: this logic of (PyColor instance OR tuple -> sf::color) should be encapsulated for reuse
|
||||
int r, g, b, a;
|
||||
if (PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Color") /*(PyObject*)&mcrfpydef::PyColorType)*/))
|
||||
if (PyObject_IsInstance(value, (PyObject*)&mcrfpydef::PyColorType))
|
||||
{
|
||||
// get value from mcrfpy.Color instance
|
||||
auto c = ((PyColorObject*)value)->data;
|
||||
|
|
@ -479,7 +479,7 @@ int UICaption::init(PyUICaptionObject* self, PyObject* args, PyObject* kwds)
|
|||
// Handle font argument
|
||||
std::shared_ptr<PyFont> pyfont = nullptr;
|
||||
if (font && font != Py_None) {
|
||||
if (!PyObject_IsInstance(font, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Font"))) {
|
||||
if (!PyObject_IsInstance(font, (PyObject*)&mcrfpydef::PyFontType)) {
|
||||
PyErr_SetString(PyExc_TypeError, "font must be a mcrfpy.Font instance");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -571,11 +571,7 @@ int UICaption::init(PyUICaptionObject* self, PyObject* args, PyObject* kwds)
|
|||
}
|
||||
|
||||
// #184: Check if this is a Python subclass (for callback method support)
|
||||
PyObject* caption_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption");
|
||||
if (caption_type) {
|
||||
self->data->is_python_subclass = (PyObject*)Py_TYPE(self) != caption_type;
|
||||
Py_DECREF(caption_type);
|
||||
}
|
||||
self->data->is_python_subclass = (PyObject*)Py_TYPE(self) != (PyObject*)&mcrfpydef::PyUICaptionType;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -342,10 +342,8 @@ int UICircle::set_radius(PyUICircleObject* self, PyObject* value, void* closure)
|
|||
|
||||
PyObject* UICircle::get_center(PyUICircleObject* self, void* closure) {
|
||||
sf::Vector2f center = self->data->getCenter();
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
if (!type) return NULL;
|
||||
auto type = &mcrfpydef::PyVectorType;
|
||||
PyObject* result = PyObject_CallFunction((PyObject*)type, "ff", center.x, center.y);
|
||||
Py_DECREF(type);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -362,16 +360,14 @@ int UICircle::set_center(PyUICircleObject* self, PyObject* value, void* closure)
|
|||
|
||||
PyObject* UICircle::get_fill_color(PyUICircleObject* self, void* closure) {
|
||||
sf::Color c = self->data->getFillColor();
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Color");
|
||||
if (!type) return NULL;
|
||||
auto type = &mcrfpydef::PyColorType;
|
||||
PyObject* result = PyObject_CallFunction((PyObject*)type, "iiii", c.r, c.g, c.b, c.a);
|
||||
Py_DECREF(type);
|
||||
return result;
|
||||
}
|
||||
|
||||
int UICircle::set_fill_color(PyUICircleObject* self, PyObject* value, void* closure) {
|
||||
sf::Color color;
|
||||
if (PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Color"))) {
|
||||
if (PyObject_IsInstance(value, (PyObject*)&mcrfpydef::PyColorType)) {
|
||||
auto pyColor = (PyColorObject*)value;
|
||||
color = pyColor->data;
|
||||
} else if (PyTuple_Check(value)) {
|
||||
|
|
@ -391,16 +387,14 @@ int UICircle::set_fill_color(PyUICircleObject* self, PyObject* value, void* clos
|
|||
|
||||
PyObject* UICircle::get_outline_color(PyUICircleObject* self, void* closure) {
|
||||
sf::Color c = self->data->getOutlineColor();
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Color");
|
||||
if (!type) return NULL;
|
||||
auto type = &mcrfpydef::PyColorType;
|
||||
PyObject* result = PyObject_CallFunction((PyObject*)type, "iiii", c.r, c.g, c.b, c.a);
|
||||
Py_DECREF(type);
|
||||
return result;
|
||||
}
|
||||
|
||||
int UICircle::set_outline_color(PyUICircleObject* self, PyObject* value, void* closure) {
|
||||
sf::Color color;
|
||||
if (PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Color"))) {
|
||||
if (PyObject_IsInstance(value, (PyObject*)&mcrfpydef::PyColorType)) {
|
||||
auto pyColor = (PyColorObject*)value;
|
||||
color = pyColor->data;
|
||||
} else if (PyTuple_Check(value)) {
|
||||
|
|
@ -527,7 +521,7 @@ int UICircle::init(PyUICircleObject* self, PyObject* args, PyObject* kwds) {
|
|||
// Set fill color if provided
|
||||
if (fill_color_obj && fill_color_obj != Py_None) {
|
||||
sf::Color color;
|
||||
if (PyObject_IsInstance(fill_color_obj, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Color"))) {
|
||||
if (PyObject_IsInstance(fill_color_obj, (PyObject*)&mcrfpydef::PyColorType)) {
|
||||
color = ((PyColorObject*)fill_color_obj)->data;
|
||||
} else if (PyTuple_Check(fill_color_obj)) {
|
||||
int r, g, b, a = 255;
|
||||
|
|
@ -546,7 +540,7 @@ int UICircle::init(PyUICircleObject* self, PyObject* args, PyObject* kwds) {
|
|||
// Set outline color if provided
|
||||
if (outline_color_obj && outline_color_obj != Py_None) {
|
||||
sf::Color color;
|
||||
if (PyObject_IsInstance(outline_color_obj, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Color"))) {
|
||||
if (PyObject_IsInstance(outline_color_obj, (PyObject*)&mcrfpydef::PyColorType)) {
|
||||
color = ((PyColorObject*)outline_color_obj)->data;
|
||||
} else if (PyTuple_Check(outline_color_obj)) {
|
||||
int r, g, b, a = 255;
|
||||
|
|
@ -596,11 +590,7 @@ int UICircle::init(PyUICircleObject* self, PyObject* args, PyObject* kwds) {
|
|||
}
|
||||
|
||||
// #184: Check if this is a Python subclass (for callback method support)
|
||||
PyObject* circle_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Circle");
|
||||
if (circle_type) {
|
||||
self->data->is_python_subclass = (PyObject*)Py_TYPE(self) != circle_type;
|
||||
Py_DECREF(circle_type);
|
||||
}
|
||||
self->data->is_python_subclass = (PyObject*)Py_TYPE(self) != (PyObject*)&mcrfpydef::PyUICircleType;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ static PyObject* convertDrawableToPython(std::shared_ptr<UIDrawable> drawable) {
|
|||
if (!drawable) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
// Check cache first
|
||||
if (drawable->serial_number != 0) {
|
||||
PyObject* cached = PythonObjectCache::getInstance().lookup(drawable->serial_number);
|
||||
|
|
@ -28,15 +28,14 @@ static PyObject* convertDrawableToPython(std::shared_ptr<UIDrawable> drawable) {
|
|||
return cached; // Already INCREF'd by lookup
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PyTypeObject* type = nullptr;
|
||||
PyObject* obj = nullptr;
|
||||
|
||||
|
||||
switch (drawable->derived_type()) {
|
||||
case PyObjectsEnum::UIFRAME:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame");
|
||||
if (!type) return nullptr;
|
||||
type = &PyUIFrameType;
|
||||
auto pyObj = (PyUIFrameObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<UIFrame>(drawable);
|
||||
|
|
@ -47,8 +46,7 @@ static PyObject* convertDrawableToPython(std::shared_ptr<UIDrawable> drawable) {
|
|||
}
|
||||
case PyObjectsEnum::UICAPTION:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption");
|
||||
if (!type) return nullptr;
|
||||
type = &PyUICaptionType;
|
||||
auto pyObj = (PyUICaptionObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<UICaption>(drawable);
|
||||
|
|
@ -60,8 +58,7 @@ static PyObject* convertDrawableToPython(std::shared_ptr<UIDrawable> drawable) {
|
|||
}
|
||||
case PyObjectsEnum::UISPRITE:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite");
|
||||
if (!type) return nullptr;
|
||||
type = &PyUISpriteType;
|
||||
auto pyObj = (PyUISpriteObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<UISprite>(drawable);
|
||||
|
|
@ -72,8 +69,7 @@ static PyObject* convertDrawableToPython(std::shared_ptr<UIDrawable> drawable) {
|
|||
}
|
||||
case PyObjectsEnum::UIGRID:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid");
|
||||
if (!type) return nullptr;
|
||||
type = &PyUIGridType;
|
||||
auto pyObj = (PyUIGridObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<UIGrid>(drawable);
|
||||
|
|
@ -84,8 +80,7 @@ static PyObject* convertDrawableToPython(std::shared_ptr<UIDrawable> drawable) {
|
|||
}
|
||||
case PyObjectsEnum::UILINE:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Line");
|
||||
if (!type) return nullptr;
|
||||
type = &PyUILineType;
|
||||
auto pyObj = (PyUILineObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<UILine>(drawable);
|
||||
|
|
@ -96,8 +91,7 @@ static PyObject* convertDrawableToPython(std::shared_ptr<UIDrawable> drawable) {
|
|||
}
|
||||
case PyObjectsEnum::UICIRCLE:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Circle");
|
||||
if (!type) return nullptr;
|
||||
type = &PyUICircleType;
|
||||
auto pyObj = (PyUICircleObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<UICircle>(drawable);
|
||||
|
|
@ -108,8 +102,7 @@ static PyObject* convertDrawableToPython(std::shared_ptr<UIDrawable> drawable) {
|
|||
}
|
||||
case PyObjectsEnum::UIARC:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Arc");
|
||||
if (!type) return nullptr;
|
||||
type = &PyUIArcType;
|
||||
auto pyObj = (PyUIArcObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<UIArc>(drawable);
|
||||
|
|
@ -120,8 +113,7 @@ static PyObject* convertDrawableToPython(std::shared_ptr<UIDrawable> drawable) {
|
|||
}
|
||||
case PyObjectsEnum::UIVIEWPORT3D:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Viewport3D");
|
||||
if (!type) return nullptr;
|
||||
type = &PyViewport3DType;
|
||||
auto pyObj = (PyViewport3DObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<mcrf::Viewport3D>(drawable);
|
||||
|
|
@ -134,10 +126,6 @@ static PyObject* convertDrawableToPython(std::shared_ptr<UIDrawable> drawable) {
|
|||
PyErr_SetString(PyExc_TypeError, "Unknown UIDrawable derived type");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (type) {
|
||||
Py_DECREF(type);
|
||||
}
|
||||
|
||||
// Re-register in cache if the object has a serial number
|
||||
// This handles the case where the original Python wrapper was GC'd
|
||||
|
|
@ -153,6 +141,28 @@ static PyObject* convertDrawableToPython(std::shared_ptr<UIDrawable> drawable) {
|
|||
return obj;
|
||||
}
|
||||
|
||||
// Helper to extract shared_ptr<UIDrawable> from any UIDrawable Python subclass.
|
||||
// Returns nullptr without setting an error if the type doesn't match.
|
||||
static std::shared_ptr<UIDrawable> extractDrawable(PyObject* o) {
|
||||
if (PyObject_IsInstance(o, (PyObject*)&PyUIFrameType))
|
||||
return ((PyUIFrameObject*)o)->data;
|
||||
if (PyObject_IsInstance(o, (PyObject*)&PyUICaptionType))
|
||||
return ((PyUICaptionObject*)o)->data;
|
||||
if (PyObject_IsInstance(o, (PyObject*)&PyUISpriteType))
|
||||
return ((PyUISpriteObject*)o)->data;
|
||||
if (PyObject_IsInstance(o, (PyObject*)&PyUIGridType))
|
||||
return ((PyUIGridObject*)o)->data;
|
||||
if (PyObject_IsInstance(o, (PyObject*)&PyUILineType))
|
||||
return ((PyUILineObject*)o)->data;
|
||||
if (PyObject_IsInstance(o, (PyObject*)&PyUICircleType))
|
||||
return ((PyUICircleObject*)o)->data;
|
||||
if (PyObject_IsInstance(o, (PyObject*)&PyUIArcType))
|
||||
return ((PyUIArcObject*)o)->data;
|
||||
if (PyObject_IsInstance(o, (PyObject*)&PyViewport3DType))
|
||||
return ((PyViewport3DObject*)o)->data;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int UICollectionIter::init(PyUICollectionIterObject* self, PyObject* args, PyObject* kwds)
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "UICollection cannot be instantiated: a C++ data source is required.");
|
||||
|
|
@ -250,37 +260,13 @@ int UICollection::setitem(PyUICollectionObject* self, Py_ssize_t index, PyObject
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Type checking - must be a UIDrawable subclass
|
||||
if (!PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame")) &&
|
||||
!PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite")) &&
|
||||
!PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption")) &&
|
||||
!PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid"))) {
|
||||
PyErr_SetString(PyExc_TypeError, "UICollection can only contain Frame, Caption, Sprite, and Grid objects");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get the C++ object from the Python object
|
||||
std::shared_ptr<UIDrawable> new_drawable = nullptr;
|
||||
int old_z_index = (*vec)[index]->z_index; // Preserve the z_index
|
||||
|
||||
if (PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame"))) {
|
||||
PyUIFrameObject* frame = (PyUIFrameObject*)value;
|
||||
new_drawable = frame->data;
|
||||
} else if (PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption"))) {
|
||||
PyUICaptionObject* caption = (PyUICaptionObject*)value;
|
||||
new_drawable = caption->data;
|
||||
} else if (PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite"))) {
|
||||
PyUISpriteObject* sprite = (PyUISpriteObject*)value;
|
||||
new_drawable = sprite->data;
|
||||
} else if (PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid"))) {
|
||||
PyUIGridObject* grid = (PyUIGridObject*)value;
|
||||
new_drawable = grid->data;
|
||||
}
|
||||
|
||||
// Extract drawable from Python object (type-checks internally)
|
||||
std::shared_ptr<UIDrawable> new_drawable = extractDrawable(value);
|
||||
if (!new_drawable) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Failed to extract C++ object from Python object");
|
||||
PyErr_SetString(PyExc_TypeError, "UICollection can only contain Drawable objects");
|
||||
return -1;
|
||||
}
|
||||
int old_z_index = (*vec)[index]->z_index; // Preserve the z_index
|
||||
|
||||
// #122: Clear parent of old element
|
||||
(*vec)[index]->setParent(nullptr);
|
||||
|
|
@ -312,32 +298,8 @@ int UICollection::contains(PyUICollectionObject* self, PyObject* value) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
// Type checking - must be a UIDrawable subclass
|
||||
if (!PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame")) &&
|
||||
!PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite")) &&
|
||||
!PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption")) &&
|
||||
!PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid"))) {
|
||||
// Not a valid type, so it can't be in the collection
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get the C++ object from the Python object
|
||||
std::shared_ptr<UIDrawable> search_drawable = nullptr;
|
||||
|
||||
if (PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame"))) {
|
||||
PyUIFrameObject* frame = (PyUIFrameObject*)value;
|
||||
search_drawable = frame->data;
|
||||
} else if (PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption"))) {
|
||||
PyUICaptionObject* caption = (PyUICaptionObject*)value;
|
||||
search_drawable = caption->data;
|
||||
} else if (PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite"))) {
|
||||
PyUISpriteObject* sprite = (PyUISpriteObject*)value;
|
||||
search_drawable = sprite->data;
|
||||
} else if (PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid"))) {
|
||||
PyUIGridObject* grid = (PyUIGridObject*)value;
|
||||
search_drawable = grid->data;
|
||||
}
|
||||
|
||||
// Extract drawable (returns nullptr for non-drawable types)
|
||||
std::shared_ptr<UIDrawable> search_drawable = extractDrawable(value);
|
||||
if (!search_drawable) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -412,14 +374,11 @@ PyObject* UICollection::inplace_concat(PyUICollectionObject* self, PyObject* oth
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// Type check
|
||||
if (!PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame")) &&
|
||||
!PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite")) &&
|
||||
!PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption")) &&
|
||||
!PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid"))) {
|
||||
// Type check - must be a UIDrawable subclass
|
||||
if (!PyObject_IsInstance(item, (PyObject*)&PyDrawableType)) {
|
||||
Py_DECREF(item);
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"UICollection can only contain Frame, Caption, Sprite, and Grid objects; "
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"UICollection can only contain Drawable objects; "
|
||||
"got %s at index %zd", Py_TYPE(item)->tp_name, i);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -544,20 +503,11 @@ int UICollection::ass_subscript(PyUICollectionObject* self, PyObject* key, PyObj
|
|||
}
|
||||
|
||||
// Type check and extract C++ object
|
||||
std::shared_ptr<UIDrawable> drawable = nullptr;
|
||||
|
||||
if (PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame"))) {
|
||||
drawable = ((PyUIFrameObject*)item)->data;
|
||||
} else if (PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption"))) {
|
||||
drawable = ((PyUICaptionObject*)item)->data;
|
||||
} else if (PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite"))) {
|
||||
drawable = ((PyUISpriteObject*)item)->data;
|
||||
} else if (PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid"))) {
|
||||
drawable = ((PyUIGridObject*)item)->data;
|
||||
} else {
|
||||
std::shared_ptr<UIDrawable> drawable = extractDrawable(item);
|
||||
if (!drawable) {
|
||||
Py_DECREF(item);
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"UICollection can only contain Frame, Caption, Sprite, and Grid objects; "
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"UICollection can only contain Drawable objects; "
|
||||
"got %s at index %zd", Py_TYPE(item)->tp_name, i);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -629,45 +579,22 @@ PySequenceMethods UICollection::sqmethods = {
|
|||
.sq_inplace_repeat = NULL
|
||||
};
|
||||
|
||||
/* Idiomatic way to fetch complete types from the API rather than referencing their PyTypeObject struct
|
||||
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Texture");
|
||||
|
||||
I never identified why `using namespace mcrfpydef;` doesn't solve the segfault issue.
|
||||
The horrible macro in UIDrawable was originally a workaround for this, but as I interact with the types outside of the monster UI.h, a more general (and less icky) solution is required.
|
||||
|
||||
*/
|
||||
|
||||
PyObject* UICollection::append(PyUICollectionObject* self, PyObject* o)
|
||||
{
|
||||
// if not UIDrawable subclass, reject it
|
||||
// self->data->push_back( c++ object inside o );
|
||||
|
||||
// Ensure module is initialized
|
||||
if (!McRFPy_API::mcrf_module) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "mcrfpy module not initialized");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// this would be a great use case for .tp_base
|
||||
if (!PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame")) &&
|
||||
!PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite")) &&
|
||||
!PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption")) &&
|
||||
!PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid")) &&
|
||||
!PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Line")) &&
|
||||
!PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Circle")) &&
|
||||
!PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Arc")) &&
|
||||
!PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Viewport3D"))
|
||||
)
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "Only Frame, Caption, Sprite, Grid, Line, Circle, Arc, and Viewport3D objects can be added to UICollection");
|
||||
// Extract drawable from Python object
|
||||
std::shared_ptr<UIDrawable> drawable = extractDrawable(o);
|
||||
if (!drawable) {
|
||||
PyErr_SetString(PyExc_TypeError, "Only Drawable objects can be added to UICollection");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Calculate z_index for the new element
|
||||
int new_z_index = 0;
|
||||
if (!self->data->empty()) {
|
||||
// Get the z_index of the last element and add 10
|
||||
int last_z = self->data->back()->z_index;
|
||||
if (last_z <= INT_MAX - 10) {
|
||||
new_z_index = last_z + 10;
|
||||
|
|
@ -676,60 +603,20 @@ PyObject* UICollection::append(PyUICollectionObject* self, PyObject* o)
|
|||
}
|
||||
}
|
||||
|
||||
// #122: Get the owner as parent for this drawable
|
||||
std::shared_ptr<UIDrawable> owner_ptr = self->owner.lock();
|
||||
// #183: Remove from old parent (drawable or scene)
|
||||
drawable->removeFromParent();
|
||||
|
||||
// Helper lambda to add drawable with parent tracking
|
||||
auto addDrawable = [&](std::shared_ptr<UIDrawable> drawable) {
|
||||
// #183: Remove from old parent (drawable or scene)
|
||||
drawable->removeFromParent();
|
||||
drawable->z_index = new_z_index;
|
||||
|
||||
drawable->z_index = new_z_index;
|
||||
// #183: Set new parent - either scene or drawable
|
||||
if (!self->scene_name.empty()) {
|
||||
drawable->setParentScene(self->scene_name);
|
||||
} else {
|
||||
std::shared_ptr<UIDrawable> owner_ptr = self->owner.lock();
|
||||
drawable->setParent(owner_ptr);
|
||||
}
|
||||
|
||||
// #183: Set new parent - either scene or drawable
|
||||
if (!self->scene_name.empty()) {
|
||||
// This is a scene's children collection
|
||||
drawable->setParentScene(self->scene_name);
|
||||
} else {
|
||||
// This is a Frame/Grid's children collection
|
||||
drawable->setParent(owner_ptr);
|
||||
}
|
||||
|
||||
self->data->push_back(drawable);
|
||||
};
|
||||
|
||||
if (PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame")))
|
||||
{
|
||||
addDrawable(((PyUIFrameObject*)o)->data);
|
||||
}
|
||||
if (PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption")))
|
||||
{
|
||||
addDrawable(((PyUICaptionObject*)o)->data);
|
||||
}
|
||||
if (PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite")))
|
||||
{
|
||||
addDrawable(((PyUISpriteObject*)o)->data);
|
||||
}
|
||||
if (PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid")))
|
||||
{
|
||||
addDrawable(((PyUIGridObject*)o)->data);
|
||||
}
|
||||
if (PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Line")))
|
||||
{
|
||||
addDrawable(((PyUILineObject*)o)->data);
|
||||
}
|
||||
if (PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Circle")))
|
||||
{
|
||||
addDrawable(((PyUICircleObject*)o)->data);
|
||||
}
|
||||
if (PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Arc")))
|
||||
{
|
||||
addDrawable(((PyUIArcObject*)o)->data);
|
||||
}
|
||||
if (PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Viewport3D")))
|
||||
{
|
||||
addDrawable(((PyViewport3DObject*)o)->data);
|
||||
}
|
||||
self->data->push_back(drawable);
|
||||
|
||||
// Mark scene as needing resort after adding element
|
||||
McRFPy_API::markSceneNeedsSort();
|
||||
|
|
@ -747,83 +634,34 @@ PyObject* UICollection::extend(PyUICollectionObject* self, PyObject* iterable)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// Ensure module is initialized
|
||||
if (!McRFPy_API::mcrf_module) {
|
||||
Py_DECREF(iterator);
|
||||
PyErr_SetString(PyExc_RuntimeError, "mcrfpy module not initialized");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Get current highest z_index
|
||||
int current_z_index = 0;
|
||||
if (!self->data->empty()) {
|
||||
current_z_index = self->data->back()->z_index;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<UIDrawable> owner_ptr = self->owner.lock();
|
||||
|
||||
PyObject* item;
|
||||
while ((item = PyIter_Next(iterator)) != NULL) {
|
||||
// Check if item is a UIDrawable subclass
|
||||
if (!PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame")) &&
|
||||
!PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite")) &&
|
||||
!PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption")) &&
|
||||
!PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid")) &&
|
||||
!PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Line")) &&
|
||||
!PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Circle")) &&
|
||||
!PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Arc")) &&
|
||||
!PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Viewport3D")))
|
||||
{
|
||||
std::shared_ptr<UIDrawable> drawable = extractDrawable(item);
|
||||
if (!drawable) {
|
||||
Py_DECREF(item);
|
||||
Py_DECREF(iterator);
|
||||
PyErr_SetString(PyExc_TypeError, "All items must be Frame, Caption, Sprite, Grid, Line, Circle, Arc, or Viewport3D objects");
|
||||
PyErr_SetString(PyExc_TypeError, "All items must be Drawable objects");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Increment z_index for each new element
|
||||
|
||||
if (current_z_index <= INT_MAX - 10) {
|
||||
current_z_index += 10;
|
||||
} else {
|
||||
current_z_index = INT_MAX;
|
||||
}
|
||||
|
||||
// #122: Get the owner as parent for this drawable
|
||||
std::shared_ptr<UIDrawable> owner_ptr = self->owner.lock();
|
||||
|
||||
// Helper lambda to add drawable with parent tracking
|
||||
auto addDrawable = [&](std::shared_ptr<UIDrawable> drawable) {
|
||||
// #122: Remove from old parent if it has one
|
||||
if (auto old_parent = drawable->getParent()) {
|
||||
drawable->removeFromParent();
|
||||
}
|
||||
drawable->z_index = current_z_index;
|
||||
drawable->setParent(owner_ptr);
|
||||
self->data->push_back(drawable);
|
||||
};
|
||||
|
||||
// Add the item based on its type
|
||||
if (PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame"))) {
|
||||
addDrawable(((PyUIFrameObject*)item)->data);
|
||||
}
|
||||
else if (PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption"))) {
|
||||
addDrawable(((PyUICaptionObject*)item)->data);
|
||||
}
|
||||
else if (PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite"))) {
|
||||
addDrawable(((PyUISpriteObject*)item)->data);
|
||||
}
|
||||
else if (PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid"))) {
|
||||
addDrawable(((PyUIGridObject*)item)->data);
|
||||
}
|
||||
else if (PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Line"))) {
|
||||
addDrawable(((PyUILineObject*)item)->data);
|
||||
}
|
||||
else if (PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Circle"))) {
|
||||
addDrawable(((PyUICircleObject*)item)->data);
|
||||
}
|
||||
else if (PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Arc"))) {
|
||||
addDrawable(((PyUIArcObject*)item)->data);
|
||||
}
|
||||
else if (PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Viewport3D"))) {
|
||||
addDrawable(((PyViewport3DObject*)item)->data);
|
||||
}
|
||||
drawable->removeFromParent();
|
||||
drawable->z_index = current_z_index;
|
||||
drawable->setParent(owner_ptr);
|
||||
self->data->push_back(drawable);
|
||||
|
||||
Py_DECREF(item);
|
||||
}
|
||||
|
|
@ -850,29 +688,11 @@ PyObject* UICollection::remove(PyUICollectionObject* self, PyObject* o)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// Type checking - must be a UIDrawable subclass
|
||||
if (!PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Drawable"))) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"UICollection.remove requires a UI element (Frame, Caption, Sprite, Grid)");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Get the C++ object from the Python object
|
||||
std::shared_ptr<UIDrawable> search_drawable = nullptr;
|
||||
|
||||
if (PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame"))) {
|
||||
search_drawable = ((PyUIFrameObject*)o)->data;
|
||||
} else if (PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption"))) {
|
||||
search_drawable = ((PyUICaptionObject*)o)->data;
|
||||
} else if (PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite"))) {
|
||||
search_drawable = ((PyUISpriteObject*)o)->data;
|
||||
} else if (PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid"))) {
|
||||
search_drawable = ((PyUIGridObject*)o)->data;
|
||||
}
|
||||
|
||||
// Extract drawable from Python object
|
||||
std::shared_ptr<UIDrawable> search_drawable = extractDrawable(o);
|
||||
if (!search_drawable) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"UICollection.remove requires a UI element (Frame, Caption, Sprite, Grid)");
|
||||
"UICollection.remove requires a Drawable object");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -951,29 +771,11 @@ PyObject* UICollection::insert(PyUICollectionObject* self, PyObject* args)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// Type checking - must be a UIDrawable subclass
|
||||
if (!PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Drawable"))) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"UICollection.insert requires a UI element (Frame, Caption, Sprite, Grid)");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Get the C++ object from the Python object
|
||||
std::shared_ptr<UIDrawable> drawable = nullptr;
|
||||
|
||||
if (PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame"))) {
|
||||
drawable = ((PyUIFrameObject*)o)->data;
|
||||
} else if (PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption"))) {
|
||||
drawable = ((PyUICaptionObject*)o)->data;
|
||||
} else if (PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite"))) {
|
||||
drawable = ((PyUISpriteObject*)o)->data;
|
||||
} else if (PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid"))) {
|
||||
drawable = ((PyUIGridObject*)o)->data;
|
||||
}
|
||||
|
||||
// Extract drawable from Python object
|
||||
std::shared_ptr<UIDrawable> drawable = extractDrawable(o);
|
||||
if (!drawable) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"UICollection.insert requires a UI element (Frame, Caption, Sprite, Grid)");
|
||||
"UICollection.insert requires a Drawable object");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1011,30 +813,10 @@ PyObject* UICollection::index_method(PyUICollectionObject* self, PyObject* value
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// Type checking - must be a UIDrawable subclass
|
||||
if (!PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame")) &&
|
||||
!PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite")) &&
|
||||
!PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption")) &&
|
||||
!PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid"))) {
|
||||
PyErr_SetString(PyExc_TypeError, "UICollection.index requires a Frame, Caption, Sprite, or Grid object");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Get the C++ object from the Python object
|
||||
std::shared_ptr<UIDrawable> search_drawable = nullptr;
|
||||
|
||||
if (PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame"))) {
|
||||
search_drawable = ((PyUIFrameObject*)value)->data;
|
||||
} else if (PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption"))) {
|
||||
search_drawable = ((PyUICaptionObject*)value)->data;
|
||||
} else if (PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite"))) {
|
||||
search_drawable = ((PyUISpriteObject*)value)->data;
|
||||
} else if (PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid"))) {
|
||||
search_drawable = ((PyUIGridObject*)value)->data;
|
||||
}
|
||||
|
||||
// Extract drawable from Python object
|
||||
std::shared_ptr<UIDrawable> search_drawable = extractDrawable(value);
|
||||
if (!search_drawable) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Failed to extract C++ object from Python object");
|
||||
PyErr_SetString(PyExc_TypeError, "UICollection.index requires a Drawable object");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1056,28 +838,8 @@ PyObject* UICollection::count(PyUICollectionObject* self, PyObject* value) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// Type checking - must be a UIDrawable subclass
|
||||
if (!PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame")) &&
|
||||
!PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite")) &&
|
||||
!PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption")) &&
|
||||
!PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid"))) {
|
||||
// Not a valid type, so count is 0
|
||||
return PyLong_FromLong(0);
|
||||
}
|
||||
|
||||
// Get the C++ object from the Python object
|
||||
std::shared_ptr<UIDrawable> search_drawable = nullptr;
|
||||
|
||||
if (PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame"))) {
|
||||
search_drawable = ((PyUIFrameObject*)value)->data;
|
||||
} else if (PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption"))) {
|
||||
search_drawable = ((PyUICaptionObject*)value)->data;
|
||||
} else if (PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite"))) {
|
||||
search_drawable = ((PyUISpriteObject*)value)->data;
|
||||
} else if (PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid"))) {
|
||||
search_drawable = ((PyUIGridObject*)value)->data;
|
||||
}
|
||||
|
||||
// Extract drawable (returns nullptr for non-drawable types)
|
||||
std::shared_ptr<UIDrawable> search_drawable = extractDrawable(value);
|
||||
if (!search_drawable) {
|
||||
return PyLong_FromLong(0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -756,12 +756,10 @@ PyObject* UIDrawable::get_grid_pos(PyObject* self, void* closure) {
|
|||
float grid_y = drawable->position.y / cell_size.y;
|
||||
|
||||
// Return as Vector
|
||||
PyObject* vector_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
if (!vector_type) return NULL;
|
||||
PyObject* vector_type = (PyObject*)&mcrfpydef::PyVectorType;
|
||||
|
||||
PyObject* args = Py_BuildValue("(ff)", grid_x, grid_y);
|
||||
PyObject* result = PyObject_CallObject(vector_type, args);
|
||||
Py_DECREF(vector_type);
|
||||
Py_DECREF(args);
|
||||
|
||||
return result;
|
||||
|
|
@ -868,12 +866,10 @@ PyObject* UIDrawable::get_grid_size(PyObject* self, void* closure) {
|
|||
float grid_h = bounds.height / cell_size.y;
|
||||
|
||||
// Return as Vector
|
||||
PyObject* vector_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
if (!vector_type) return NULL;
|
||||
PyObject* vector_type = (PyObject*)&mcrfpydef::PyVectorType;
|
||||
|
||||
PyObject* args = Py_BuildValue("(ff)", grid_w, grid_h);
|
||||
PyObject* result = PyObject_CallObject(vector_type, args);
|
||||
Py_DECREF(vector_type);
|
||||
Py_DECREF(args);
|
||||
|
||||
return result;
|
||||
|
|
@ -1308,8 +1304,7 @@ PyObject* UIDrawable::get_parent(PyObject* self, void* closure) {
|
|||
switch (parent_ptr->derived_type()) {
|
||||
case PyObjectsEnum::UIFRAME:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame");
|
||||
if (!type) return nullptr;
|
||||
type = &mcrfpydef::PyUIFrameType;
|
||||
auto pyObj = (PyUIFrameObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<UIFrame>(parent_ptr);
|
||||
|
|
@ -1320,8 +1315,7 @@ PyObject* UIDrawable::get_parent(PyObject* self, void* closure) {
|
|||
}
|
||||
case PyObjectsEnum::UICAPTION:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption");
|
||||
if (!type) return nullptr;
|
||||
type = &mcrfpydef::PyUICaptionType;
|
||||
auto pyObj = (PyUICaptionObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<UICaption>(parent_ptr);
|
||||
|
|
@ -1333,8 +1327,7 @@ PyObject* UIDrawable::get_parent(PyObject* self, void* closure) {
|
|||
}
|
||||
case PyObjectsEnum::UISPRITE:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite");
|
||||
if (!type) return nullptr;
|
||||
type = &mcrfpydef::PyUISpriteType;
|
||||
auto pyObj = (PyUISpriteObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<UISprite>(parent_ptr);
|
||||
|
|
@ -1345,8 +1338,7 @@ PyObject* UIDrawable::get_parent(PyObject* self, void* closure) {
|
|||
}
|
||||
case PyObjectsEnum::UIGRID:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid");
|
||||
if (!type) return nullptr;
|
||||
type = &mcrfpydef::PyUIGridType;
|
||||
auto pyObj = (PyUIGridObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<UIGrid>(parent_ptr);
|
||||
|
|
@ -1359,9 +1351,6 @@ PyObject* UIDrawable::get_parent(PyObject* self, void* closure) {
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
if (type) {
|
||||
Py_DECREF(type);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
@ -1405,17 +1394,9 @@ int UIDrawable::set_parent(PyObject* self, PyObject* value, void* closure) {
|
|||
}
|
||||
|
||||
// Value must be a Frame, Grid, or Scene (things with children collections)
|
||||
PyTypeObject* frame_type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame");
|
||||
PyTypeObject* grid_type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid");
|
||||
PyTypeObject* scene_type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Scene");
|
||||
|
||||
bool is_frame = frame_type && PyObject_IsInstance(value, (PyObject*)frame_type);
|
||||
bool is_grid = grid_type && PyObject_IsInstance(value, (PyObject*)grid_type);
|
||||
bool is_scene = scene_type && PyObject_IsInstance(value, (PyObject*)scene_type);
|
||||
|
||||
Py_XDECREF(frame_type);
|
||||
Py_XDECREF(grid_type);
|
||||
Py_XDECREF(scene_type);
|
||||
bool is_frame = PyObject_IsInstance(value, (PyObject*)&mcrfpydef::PyUIFrameType);
|
||||
bool is_grid = PyObject_IsInstance(value, (PyObject*)&mcrfpydef::PyUIGridType);
|
||||
bool is_scene = PyObject_IsInstance(value, (PyObject*)&mcrfpydef::PySceneType);
|
||||
|
||||
if (!is_frame && !is_grid && !is_scene) {
|
||||
PyErr_SetString(PyExc_TypeError, "parent must be a Frame, Grid, Scene, or None");
|
||||
|
|
@ -1519,16 +1500,14 @@ PyObject* UIDrawable::get_bounds_py(PyObject* self, void* closure) {
|
|||
|
||||
sf::FloatRect bounds = drawable->get_bounds();
|
||||
|
||||
// Get Vector type from mcrfpy module
|
||||
PyObject* vector_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
if (!vector_type) return NULL;
|
||||
// Get Vector type
|
||||
PyObject* vector_type = (PyObject*)&mcrfpydef::PyVectorType;
|
||||
|
||||
// Create pos vector
|
||||
PyObject* pos_args = Py_BuildValue("(ff)", bounds.left, bounds.top);
|
||||
PyObject* pos = PyObject_CallObject(vector_type, pos_args);
|
||||
Py_DECREF(pos_args);
|
||||
if (!pos) {
|
||||
Py_DECREF(vector_type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1536,7 +1515,6 @@ PyObject* UIDrawable::get_bounds_py(PyObject* self, void* closure) {
|
|||
PyObject* size_args = Py_BuildValue("(ff)", bounds.width, bounds.height);
|
||||
PyObject* size = PyObject_CallObject(vector_type, size_args);
|
||||
Py_DECREF(size_args);
|
||||
Py_DECREF(vector_type);
|
||||
if (!size) {
|
||||
Py_DECREF(pos);
|
||||
return NULL;
|
||||
|
|
@ -1554,16 +1532,14 @@ PyObject* UIDrawable::get_global_bounds_py(PyObject* self, void* closure) {
|
|||
|
||||
sf::FloatRect bounds = drawable->get_global_bounds();
|
||||
|
||||
// Get Vector type from mcrfpy module
|
||||
PyObject* vector_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
if (!vector_type) return NULL;
|
||||
// Get Vector type
|
||||
PyObject* vector_type = (PyObject*)&mcrfpydef::PyVectorType;
|
||||
|
||||
// Create pos vector
|
||||
PyObject* pos_args = Py_BuildValue("(ff)", bounds.left, bounds.top);
|
||||
PyObject* pos = PyObject_CallObject(vector_type, pos_args);
|
||||
Py_DECREF(pos_args);
|
||||
if (!pos) {
|
||||
Py_DECREF(vector_type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1571,7 +1547,6 @@ PyObject* UIDrawable::get_global_bounds_py(PyObject* self, void* closure) {
|
|||
PyObject* size_args = Py_BuildValue("(ff)", bounds.width, bounds.height);
|
||||
PyObject* size = PyObject_CallObject(vector_type, size_args);
|
||||
Py_DECREF(size_args);
|
||||
Py_DECREF(vector_type);
|
||||
if (!size) {
|
||||
Py_DECREF(pos);
|
||||
return NULL;
|
||||
|
|
@ -1976,14 +1951,9 @@ PyObject* UIDrawable_animate_impl(std::shared_ptr<UIDrawable> self, PyObject* ar
|
|||
}
|
||||
|
||||
// Create and return a PyAnimation wrapper
|
||||
PyTypeObject* animType = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Animation");
|
||||
if (!animType) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Could not find Animation type");
|
||||
return NULL;
|
||||
}
|
||||
PyTypeObject* animType = &mcrfpydef::PyAnimationType;
|
||||
|
||||
PyAnimationObject* pyAnim = (PyAnimationObject*)animType->tp_alloc(animType, 0);
|
||||
Py_DECREF(animType);
|
||||
|
||||
if (!pyAnim) {
|
||||
return NULL;
|
||||
|
|
@ -2182,29 +2152,13 @@ PyObject* UIDrawable::py_realign(PyObject* self, PyObject* args) {
|
|||
PyObjectsEnum objtype = PyObjectsEnum::UIFRAME; // Default, will be set by type check
|
||||
|
||||
// Determine the type from the Python object
|
||||
PyObject* frame_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame");
|
||||
PyObject* caption_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption");
|
||||
PyObject* sprite_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite");
|
||||
PyObject* grid_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid");
|
||||
PyObject* line_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Line");
|
||||
PyObject* circle_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Circle");
|
||||
PyObject* arc_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Arc");
|
||||
|
||||
if (PyObject_IsInstance(self, frame_type)) objtype = PyObjectsEnum::UIFRAME;
|
||||
else if (PyObject_IsInstance(self, caption_type)) objtype = PyObjectsEnum::UICAPTION;
|
||||
else if (PyObject_IsInstance(self, sprite_type)) objtype = PyObjectsEnum::UISPRITE;
|
||||
else if (PyObject_IsInstance(self, grid_type)) objtype = PyObjectsEnum::UIGRID;
|
||||
else if (PyObject_IsInstance(self, line_type)) objtype = PyObjectsEnum::UILINE;
|
||||
else if (PyObject_IsInstance(self, circle_type)) objtype = PyObjectsEnum::UICIRCLE;
|
||||
else if (PyObject_IsInstance(self, arc_type)) objtype = PyObjectsEnum::UIARC;
|
||||
|
||||
Py_XDECREF(frame_type);
|
||||
Py_XDECREF(caption_type);
|
||||
Py_XDECREF(sprite_type);
|
||||
Py_XDECREF(grid_type);
|
||||
Py_XDECREF(line_type);
|
||||
Py_XDECREF(circle_type);
|
||||
Py_XDECREF(arc_type);
|
||||
if (PyObject_IsInstance(self, (PyObject*)&mcrfpydef::PyUIFrameType)) objtype = PyObjectsEnum::UIFRAME;
|
||||
else if (PyObject_IsInstance(self, (PyObject*)&mcrfpydef::PyUICaptionType)) objtype = PyObjectsEnum::UICAPTION;
|
||||
else if (PyObject_IsInstance(self, (PyObject*)&mcrfpydef::PyUISpriteType)) objtype = PyObjectsEnum::UISPRITE;
|
||||
else if (PyObject_IsInstance(self, (PyObject*)&mcrfpydef::PyUIGridType)) objtype = PyObjectsEnum::UIGRID;
|
||||
else if (PyObject_IsInstance(self, (PyObject*)&mcrfpydef::PyUILineType)) objtype = PyObjectsEnum::UILINE;
|
||||
else if (PyObject_IsInstance(self, (PyObject*)&mcrfpydef::PyUICircleType)) objtype = PyObjectsEnum::UICIRCLE;
|
||||
else if (PyObject_IsInstance(self, (PyObject*)&mcrfpydef::PyUIArcType)) objtype = PyObjectsEnum::UIARC;
|
||||
|
||||
UIDrawable* drawable = extractDrawable(self, objtype);
|
||||
if (!drawable) return NULL;
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ int UIEntity::init(PyUIEntityObject* self, PyObject* args, PyObject* kwds) {
|
|||
// Handle texture argument
|
||||
std::shared_ptr<PyTexture> texture_ptr = nullptr;
|
||||
if (texture && texture != Py_None) {
|
||||
if (!PyObject_IsInstance(texture, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Texture"))) {
|
||||
if (!PyObject_IsInstance(texture, (PyObject*)&mcrfpydef::PyTextureType)) {
|
||||
PyErr_SetString(PyExc_TypeError, "texture must be a mcrfpy.Texture instance or None");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -220,7 +220,7 @@ int UIEntity::init(PyUIEntityObject* self, PyObject* args, PyObject* kwds) {
|
|||
}
|
||||
|
||||
// Handle grid argument
|
||||
if (grid_obj && !PyObject_IsInstance(grid_obj, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid"))) {
|
||||
if (grid_obj && !PyObject_IsInstance(grid_obj, (PyObject*)&mcrfpydef::PyUIGridType)) {
|
||||
PyErr_SetString(PyExc_TypeError, "grid must be a mcrfpy.Grid instance");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -292,7 +292,7 @@ PyObject* UIEntity::get_spritenumber(PyUIEntityObject* self, void* closure) {
|
|||
}
|
||||
|
||||
PyObject* sfVector2f_to_PyObject(sf::Vector2f vec) {
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
auto type = &mcrfpydef::PyVectorType;
|
||||
auto obj = (PyVectorObject*)type->tp_alloc(type, 0);
|
||||
if (obj) {
|
||||
obj->data = vec;
|
||||
|
|
@ -301,7 +301,7 @@ PyObject* sfVector2f_to_PyObject(sf::Vector2f vec) {
|
|||
}
|
||||
|
||||
PyObject* sfVector2i_to_PyObject(sf::Vector2i vec) {
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
auto type = &mcrfpydef::PyVectorType;
|
||||
auto obj = (PyVectorObject*)type->tp_alloc(type, 0);
|
||||
if (obj) {
|
||||
obj->data = sf::Vector2f(static_cast<float>(vec.x), static_cast<float>(vec.y));
|
||||
|
|
@ -636,11 +636,9 @@ PyObject* UIEntity::get_grid(PyUIEntityObject* self, void* closure)
|
|||
}
|
||||
|
||||
// Return a Python Grid object wrapping the C++ grid
|
||||
PyTypeObject* grid_type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid");
|
||||
if (!grid_type) return nullptr;
|
||||
auto grid_type = &mcrfpydef::PyUIGridType;
|
||||
|
||||
auto pyGrid = (PyUIGridObject*)grid_type->tp_alloc(grid_type, 0);
|
||||
Py_DECREF(grid_type);
|
||||
|
||||
if (pyGrid) {
|
||||
pyGrid->data = self->data->grid;
|
||||
|
|
@ -885,11 +883,7 @@ PyObject* UIEntity::visible_entities(PyUIEntityObject* self, PyObject* args, PyO
|
|||
if (!result) return PyErr_NoMemory();
|
||||
|
||||
// Get Entity type for creating Python objects
|
||||
PyTypeObject* entity_type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Entity");
|
||||
if (!entity_type) {
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
auto entity_type = &mcrfpydef::PyUIEntityType;
|
||||
|
||||
// Iterate through all entities in the grid
|
||||
if (grid->entities) {
|
||||
|
|
@ -908,7 +902,6 @@ PyObject* UIEntity::visible_entities(PyUIEntityObject* self, PyObject* args, PyO
|
|||
auto pyEntity = (PyUIEntityObject*)entity_type->tp_alloc(entity_type, 0);
|
||||
if (!pyEntity) {
|
||||
Py_DECREF(result);
|
||||
Py_DECREF(entity_type);
|
||||
return PyErr_NoMemory();
|
||||
}
|
||||
|
||||
|
|
@ -918,7 +911,6 @@ PyObject* UIEntity::visible_entities(PyUIEntityObject* self, PyObject* args, PyO
|
|||
if (PyList_Append(result, (PyObject*)pyEntity) < 0) {
|
||||
Py_DECREF(pyEntity);
|
||||
Py_DECREF(result);
|
||||
Py_DECREF(entity_type);
|
||||
return NULL;
|
||||
}
|
||||
Py_DECREF(pyEntity); // List now owns the reference
|
||||
|
|
@ -926,7 +918,6 @@ PyObject* UIEntity::visible_entities(PyUIEntityObject* self, PyObject* args, PyO
|
|||
}
|
||||
}
|
||||
|
||||
Py_DECREF(entity_type);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -1308,14 +1299,9 @@ PyObject* UIEntity::animate(PyUIEntityObject* self, PyObject* args, PyObject* kw
|
|||
}
|
||||
|
||||
// Create and return a PyAnimation wrapper
|
||||
PyTypeObject* animType = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Animation");
|
||||
if (!animType) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Could not find Animation type");
|
||||
return NULL;
|
||||
}
|
||||
auto animType = &mcrfpydef::PyAnimationType;
|
||||
|
||||
PyAnimationObject* pyAnim = (PyAnimationObject*)animType->tp_alloc(animType, 0);
|
||||
Py_DECREF(animType);
|
||||
|
||||
if (!pyAnim) {
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -350,15 +350,7 @@ PyObject* UIFrame::get_color_member(PyUIFrameObject* self, void* closure)
|
|||
PyErr_SetString(PyExc_AttributeError, "Invalid attribute");
|
||||
return nullptr;
|
||||
}
|
||||
//PyTypeObject* colorType = &PyColorType;
|
||||
auto colorType = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Color");
|
||||
PyObject* pyColor = colorType->tp_alloc(colorType, 0);
|
||||
if (pyColor == NULL)
|
||||
{
|
||||
std::cout << "failure to allocate mcrfpy.Color / PyColorType" << std::endl;
|
||||
return NULL;
|
||||
}
|
||||
PyColorObject* pyColorObj = reinterpret_cast<PyColorObject*>(pyColor);
|
||||
auto colorType = &mcrfpydef::PyColorType;
|
||||
|
||||
// fetch correct member data
|
||||
sf::Color color;
|
||||
|
|
@ -381,7 +373,7 @@ int UIFrame::set_color_member(PyUIFrameObject* self, PyObject* value, void* clos
|
|||
//TODO: this logic of (PyColor instance OR tuple -> sf::color) should be encapsulated for reuse
|
||||
auto member_ptr = reinterpret_cast<intptr_t>(closure);
|
||||
int r, g, b, a;
|
||||
if (PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Color")))
|
||||
if (PyObject_IsInstance(value, (PyObject*)&mcrfpydef::PyColorType))
|
||||
{
|
||||
sf::Color c = ((PyColorObject*)value)->data;
|
||||
r = c.r; g = c.g; b = c.b; a = c.a;
|
||||
|
|
@ -432,7 +424,7 @@ int UIFrame::set_color_member(PyUIFrameObject* self, PyObject* value, void* clos
|
|||
|
||||
PyObject* UIFrame::get_pos(PyUIFrameObject* self, void* closure)
|
||||
{
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
auto type = &mcrfpydef::PyVectorType;
|
||||
auto obj = (PyVectorObject*)type->tp_alloc(type, 0);
|
||||
if (obj) {
|
||||
auto pos = self->data->box.getPosition();
|
||||
|
|
@ -750,38 +742,27 @@ int UIFrame::init(PyUIFrameObject* self, PyObject* args, PyObject* kwds)
|
|||
if (!child) return -1;
|
||||
|
||||
// Check if it's a UIDrawable (Frame, Caption, Sprite, or Grid)
|
||||
PyObject* frame_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame");
|
||||
PyObject* caption_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption");
|
||||
PyObject* sprite_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite");
|
||||
PyObject* grid_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid");
|
||||
|
||||
if (!PyObject_IsInstance(child, frame_type) &&
|
||||
!PyObject_IsInstance(child, caption_type) &&
|
||||
!PyObject_IsInstance(child, sprite_type) &&
|
||||
!PyObject_IsInstance(child, grid_type)) {
|
||||
if (!PyObject_IsInstance(child, (PyObject*)&mcrfpydef::PyUIFrameType) &&
|
||||
!PyObject_IsInstance(child, (PyObject*)&mcrfpydef::PyUICaptionType) &&
|
||||
!PyObject_IsInstance(child, (PyObject*)&mcrfpydef::PyUISpriteType) &&
|
||||
!PyObject_IsInstance(child, (PyObject*)&mcrfpydef::PyUIGridType)) {
|
||||
Py_DECREF(child);
|
||||
PyErr_SetString(PyExc_TypeError, "children must contain only Frame, Caption, Sprite, or Grid objects");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// Get the shared_ptr and add to children
|
||||
std::shared_ptr<UIDrawable> drawable = nullptr;
|
||||
if (PyObject_IsInstance(child, frame_type)) {
|
||||
if (PyObject_IsInstance(child, (PyObject*)&mcrfpydef::PyUIFrameType)) {
|
||||
drawable = ((PyUIFrameObject*)child)->data;
|
||||
} else if (PyObject_IsInstance(child, caption_type)) {
|
||||
} else if (PyObject_IsInstance(child, (PyObject*)&mcrfpydef::PyUICaptionType)) {
|
||||
drawable = ((PyUICaptionObject*)child)->data;
|
||||
} else if (PyObject_IsInstance(child, sprite_type)) {
|
||||
} else if (PyObject_IsInstance(child, (PyObject*)&mcrfpydef::PyUISpriteType)) {
|
||||
drawable = ((PyUISpriteObject*)child)->data;
|
||||
} else if (PyObject_IsInstance(child, grid_type)) {
|
||||
} else if (PyObject_IsInstance(child, (PyObject*)&mcrfpydef::PyUIGridType)) {
|
||||
drawable = ((PyUIGridObject*)child)->data;
|
||||
}
|
||||
|
||||
// Clean up type references
|
||||
Py_DECREF(frame_type);
|
||||
Py_DECREF(caption_type);
|
||||
Py_DECREF(sprite_type);
|
||||
Py_DECREF(grid_type);
|
||||
|
||||
if (drawable) {
|
||||
drawable->setParent(self->data); // Set parent before adding (enables alignment)
|
||||
self->data->children->push_back(drawable);
|
||||
|
|
@ -812,11 +793,7 @@ int UIFrame::init(PyUIFrameObject* self, PyObject* args, PyObject* kwds)
|
|||
}
|
||||
|
||||
// #184: Check if this is a Python subclass (for callback method support)
|
||||
PyObject* frame_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame");
|
||||
if (frame_type) {
|
||||
self->data->is_python_subclass = (PyObject*)Py_TYPE(self) != frame_type;
|
||||
Py_DECREF(frame_type);
|
||||
}
|
||||
self->data->is_python_subclass = (PyObject*)Py_TYPE(self) != (PyObject*)&mcrfpydef::PyUIFrameType;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -873,7 +873,7 @@ int UIGrid::init(PyUIGridObject* self, PyObject* args, PyObject* kwds) {
|
|||
// Handle texture argument
|
||||
std::shared_ptr<PyTexture> texture_ptr = nullptr;
|
||||
if (textureObj && textureObj != Py_None) {
|
||||
if (!PyObject_IsInstance(textureObj, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Texture"))) {
|
||||
if (!PyObject_IsInstance(textureObj, (PyObject*)&mcrfpydef::PyTextureType)) {
|
||||
PyErr_SetString(PyExc_TypeError, "texture must be a mcrfpy.Texture instance or None");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1139,11 +1139,7 @@ int UIGrid::init(PyUIGridObject* self, PyObject* args, PyObject* kwds) {
|
|||
}
|
||||
|
||||
// #184: Check if this is a Python subclass (for callback method support)
|
||||
PyObject* grid_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid");
|
||||
if (grid_type) {
|
||||
self->data->is_python_subclass = (PyObject*)Py_TYPE(self) != grid_type;
|
||||
Py_DECREF(grid_type);
|
||||
}
|
||||
self->data->is_python_subclass = (PyObject*)Py_TYPE(self) != (PyObject*)&mcrfpydef::PyUIGridType;
|
||||
|
||||
return 0; // Success
|
||||
}
|
||||
|
|
@ -1328,7 +1324,7 @@ PyObject* UIGrid::get_texture(PyUIGridObject* self, void* closure) {
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Texture");
|
||||
auto type = &mcrfpydef::PyTextureType;
|
||||
auto obj = (PyTextureObject*)type->tp_alloc(type, 0);
|
||||
obj->data = texture;
|
||||
return (PyObject*)obj;
|
||||
|
|
@ -1415,17 +1411,16 @@ PyMappingMethods UIGrid::mpmethods = {
|
|||
PyObject* UIGrid::get_fill_color(PyUIGridObject* self, void* closure)
|
||||
{
|
||||
auto& color = self->data->fill_color;
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Color");
|
||||
auto type = &mcrfpydef::PyColorType;
|
||||
PyObject* args = Py_BuildValue("(iiii)", color.r, color.g, color.b, color.a);
|
||||
PyObject* obj = PyObject_CallObject((PyObject*)type, args);
|
||||
Py_DECREF(args);
|
||||
Py_DECREF(type);
|
||||
return obj;
|
||||
}
|
||||
|
||||
int UIGrid::set_fill_color(PyUIGridObject* self, PyObject* value, void* closure)
|
||||
{
|
||||
if (!PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Color"))) {
|
||||
if (!PyObject_IsInstance(value, (PyObject*)&mcrfpydef::PyColorType)) {
|
||||
PyErr_SetString(PyExc_TypeError, "fill_color must be a Color object");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1454,15 +1449,13 @@ PyObject* UIGrid::get_perspective(PyUIGridObject* self, void* closure)
|
|||
}
|
||||
|
||||
// Otherwise, create a new base Entity object
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Entity");
|
||||
auto type = &mcrfpydef::PyUIEntityType;
|
||||
auto o = (PyUIEntityObject*)type->tp_alloc(type, 0);
|
||||
if (o) {
|
||||
o->data = locked;
|
||||
o->weakreflist = NULL;
|
||||
Py_DECREF(type);
|
||||
return (PyObject*)o;
|
||||
}
|
||||
Py_XDECREF(type);
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
|
@ -1476,19 +1469,10 @@ int UIGrid::set_perspective(PyUIGridObject* self, PyObject* value, void* closure
|
|||
}
|
||||
|
||||
// Extract UIEntity from PyObject
|
||||
// Get the Entity type from the module
|
||||
auto entity_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Entity");
|
||||
if (!entity_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Could not get Entity type from mcrfpy module");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!PyObject_IsInstance(value, entity_type)) {
|
||||
Py_DECREF(entity_type);
|
||||
if (!PyObject_IsInstance(value, (PyObject*)&mcrfpydef::PyUIEntityType)) {
|
||||
PyErr_SetString(PyExc_TypeError, "perspective must be a UIEntity or None");
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(entity_type);
|
||||
|
||||
PyUIEntityObject* entity_obj = (PyUIEntityObject*)value;
|
||||
self->data->perspective_entity = entity_obj->data;
|
||||
|
|
@ -2053,14 +2037,7 @@ PyObject* UIGrid::py_apply_threshold(PyUIGridObject* self, PyObject* args, PyObj
|
|||
}
|
||||
|
||||
// Validate source is a HeightMap
|
||||
PyObject* heightmap_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "HeightMap");
|
||||
if (!heightmap_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "HeightMap type not found in module");
|
||||
return nullptr;
|
||||
}
|
||||
bool is_heightmap = PyObject_IsInstance(source_obj, heightmap_type);
|
||||
Py_DECREF(heightmap_type);
|
||||
if (!is_heightmap) {
|
||||
if (!PyObject_IsInstance(source_obj, (PyObject*)&mcrfpydef::PyHeightMapType)) {
|
||||
PyErr_SetString(PyExc_TypeError, "source must be a HeightMap");
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -2140,14 +2117,7 @@ PyObject* UIGrid::py_apply_ranges(PyUIGridObject* self, PyObject* args) {
|
|||
}
|
||||
|
||||
// Validate source is a HeightMap
|
||||
PyObject* heightmap_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "HeightMap");
|
||||
if (!heightmap_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "HeightMap type not found in module");
|
||||
return nullptr;
|
||||
}
|
||||
bool is_heightmap = PyObject_IsInstance(source_obj, heightmap_type);
|
||||
Py_DECREF(heightmap_type);
|
||||
if (!is_heightmap) {
|
||||
if (!PyObject_IsInstance(source_obj, (PyObject*)&mcrfpydef::PyHeightMapType)) {
|
||||
PyErr_SetString(PyExc_TypeError, "source must be a HeightMap");
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -2793,13 +2763,7 @@ void UIGrid::refreshCellCallbackCache(PyObject* pyObj) {
|
|||
// Helper to create typed cell callback arguments: (Vector, MouseButton, InputState)
|
||||
static PyObject* createCellCallbackArgs(sf::Vector2i cell, const std::string& button, const std::string& action) {
|
||||
// Create Vector object for cell position
|
||||
PyObject* vector_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
if (!vector_type) {
|
||||
PyErr_Print();
|
||||
return nullptr;
|
||||
}
|
||||
PyObject* cell_pos = PyObject_CallFunction(vector_type, "ff", (float)cell.x, (float)cell.y);
|
||||
Py_DECREF(vector_type);
|
||||
PyObject* cell_pos = PyObject_CallFunction((PyObject*)&mcrfpydef::PyVectorType, "ff", (float)cell.x, (float)cell.y);
|
||||
if (!cell_pos) {
|
||||
PyErr_Print();
|
||||
return nullptr;
|
||||
|
|
@ -2834,13 +2798,7 @@ static PyObject* createCellCallbackArgs(sf::Vector2i cell, const std::string& bu
|
|||
// #230 - Helper to create cell hover callback arguments: (Vector) only
|
||||
static PyObject* createCellHoverArgs(sf::Vector2i cell) {
|
||||
// Create Vector object for cell position
|
||||
PyObject* vector_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
if (!vector_type) {
|
||||
PyErr_Print();
|
||||
return nullptr;
|
||||
}
|
||||
PyObject* cell_pos = PyObject_CallFunction(vector_type, "ii", cell.x, cell.y);
|
||||
Py_DECREF(vector_type);
|
||||
PyObject* cell_pos = PyObject_CallFunction((PyObject*)&mcrfpydef::PyVectorType, "ii", cell.x, cell.y);
|
||||
if (!cell_pos) {
|
||||
PyErr_Print();
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -83,14 +83,8 @@ sf::Vector2i DijkstraMap::stepFrom(int x, int y, bool* valid) const {
|
|||
bool UIGridPathfinding::ExtractPosition(PyObject* obj, int* x, int* y,
|
||||
UIGrid* expected_grid,
|
||||
const char* arg_name) {
|
||||
// Get types from module to avoid static type instance issues
|
||||
PyObject* entity_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Entity");
|
||||
PyObject* vector_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
|
||||
// Check if it's an Entity
|
||||
if (entity_type && PyObject_IsInstance(obj, entity_type)) {
|
||||
Py_DECREF(entity_type);
|
||||
Py_XDECREF(vector_type);
|
||||
if (PyObject_IsInstance(obj, (PyObject*)&mcrfpydef::PyUIEntityType)) {
|
||||
auto* entity = (PyUIEntityObject*)obj;
|
||||
if (!entity->data) {
|
||||
PyErr_Format(PyExc_RuntimeError,
|
||||
|
|
@ -111,17 +105,14 @@ bool UIGridPathfinding::ExtractPosition(PyObject* obj, int* x, int* y,
|
|||
*y = static_cast<int>(entity->data->position.y);
|
||||
return true;
|
||||
}
|
||||
Py_XDECREF(entity_type);
|
||||
|
||||
// Check if it's a Vector
|
||||
if (vector_type && PyObject_IsInstance(obj, vector_type)) {
|
||||
Py_DECREF(vector_type);
|
||||
if (PyObject_IsInstance(obj, (PyObject*)&mcrfpydef::PyVectorType)) {
|
||||
auto* vec = (PyVectorObject*)obj;
|
||||
*x = static_cast<int>(vec->data.x);
|
||||
*y = static_cast<int>(vec->data.y);
|
||||
return true;
|
||||
}
|
||||
Py_XDECREF(vector_type);
|
||||
|
||||
// Try tuple/list
|
||||
if (PySequence_Check(obj) && PySequence_Size(obj) == 2) {
|
||||
|
|
@ -428,20 +419,13 @@ PyObject* UIGridPathfinding::DijkstraMap_to_heightmap(PyDijkstraMapObject* self,
|
|||
}
|
||||
}
|
||||
|
||||
// Create HeightMap via Python API (same pattern as BSP.to_heightmap)
|
||||
PyObject* hmap_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "HeightMap");
|
||||
if (!hmap_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "HeightMap type not found");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create HeightMap via Python API
|
||||
PyObject* size_tuple = Py_BuildValue("(ii)", width, height);
|
||||
PyObject* hmap_args = PyTuple_Pack(1, size_tuple);
|
||||
Py_DECREF(size_tuple);
|
||||
|
||||
PyHeightMapObject* hmap = (PyHeightMapObject*)PyObject_Call(hmap_type, hmap_args, nullptr);
|
||||
PyHeightMapObject* hmap = (PyHeightMapObject*)PyObject_Call((PyObject*)&mcrfpydef::PyHeightMapType, hmap_args, nullptr);
|
||||
Py_DECREF(hmap_args);
|
||||
Py_DECREF(hmap_type);
|
||||
|
||||
if (!hmap) {
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -17,24 +17,8 @@ PyObject* sfColor_to_PyObject(sf::Color color) {
|
|||
|
||||
// Utility function to convert PyObject* to sf::Color
|
||||
sf::Color PyObject_to_sfColor(PyObject* obj) {
|
||||
// Get the mcrfpy module and Color type
|
||||
PyObject* module = PyImport_ImportModule("mcrfpy");
|
||||
if (!module) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Failed to import mcrfpy module");
|
||||
return sf::Color();
|
||||
}
|
||||
|
||||
PyObject* color_type = PyObject_GetAttrString(module, "Color");
|
||||
Py_DECREF(module);
|
||||
|
||||
if (!color_type) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Failed to get Color type from mcrfpy module");
|
||||
return sf::Color();
|
||||
}
|
||||
|
||||
// Check if it's a mcrfpy.Color object
|
||||
int is_color = PyObject_IsInstance(obj, color_type);
|
||||
Py_DECREF(color_type);
|
||||
int is_color = PyObject_IsInstance(obj, (PyObject*)&mcrfpydef::PyColorType);
|
||||
|
||||
if (is_color == 1) {
|
||||
PyColorObject* color_obj = (PyColorObject*)obj;
|
||||
|
|
@ -110,13 +94,8 @@ PyObject* UIGridPoint::get_entities(PyUIGridPointObject* self, void* closure) {
|
|||
if (static_cast<int>(entity->position.x) == target_x &&
|
||||
static_cast<int>(entity->position.y) == target_y) {
|
||||
// Create Python Entity object for this entity
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Entity");
|
||||
if (!type) {
|
||||
Py_DECREF(list);
|
||||
return NULL;
|
||||
}
|
||||
auto type = &mcrfpydef::PyUIEntityType;
|
||||
auto obj = (PyUIEntityObject*)type->tp_alloc(type, 0);
|
||||
Py_DECREF(type);
|
||||
if (!obj) {
|
||||
Py_DECREF(list);
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -408,9 +408,8 @@ bool UILine::hasProperty(const std::string& name) const {
|
|||
// Python API implementation
|
||||
PyObject* UILine::get_start(PyUILineObject* self, void* closure) {
|
||||
auto vec = self->data->getStart();
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
auto type = &mcrfpydef::PyVectorType;
|
||||
auto obj = (PyVectorObject*)type->tp_alloc(type, 0);
|
||||
Py_DECREF(type);
|
||||
if (obj) {
|
||||
obj->data = vec;
|
||||
}
|
||||
|
|
@ -429,9 +428,8 @@ int UILine::set_start(PyUILineObject* self, PyObject* value, void* closure) {
|
|||
|
||||
PyObject* UILine::get_end(PyUILineObject* self, void* closure) {
|
||||
auto vec = self->data->getEnd();
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
auto type = &mcrfpydef::PyVectorType;
|
||||
auto obj = (PyVectorObject*)type->tp_alloc(type, 0);
|
||||
Py_DECREF(type);
|
||||
if (obj) {
|
||||
obj->data = vec;
|
||||
}
|
||||
|
|
@ -450,11 +448,10 @@ int UILine::set_end(PyUILineObject* self, PyObject* value, void* closure) {
|
|||
|
||||
PyObject* UILine::get_color(PyUILineObject* self, void* closure) {
|
||||
auto color = self->data->getColor();
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Color");
|
||||
auto type = &mcrfpydef::PyColorType;
|
||||
PyObject* args = Py_BuildValue("(iiii)", color.r, color.g, color.b, color.a);
|
||||
PyObject* obj = PyObject_CallObject((PyObject*)type, args);
|
||||
Py_DECREF(args);
|
||||
Py_DECREF(type);
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
@ -660,11 +657,7 @@ int UILine::init(PyUILineObject* self, PyObject* args, PyObject* kwds) {
|
|||
}
|
||||
|
||||
// #184: Check if this is a Python subclass (for callback method support)
|
||||
PyObject* line_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Line");
|
||||
if (line_type) {
|
||||
self->data->is_python_subclass = (PyObject*)Py_TYPE(self) != line_type;
|
||||
Py_DECREF(line_type);
|
||||
}
|
||||
self->data->is_python_subclass = (PyObject*)Py_TYPE(self) != (PyObject*)&mcrfpydef::PyUILineType;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -350,7 +350,7 @@ PyObject* UISprite::get_texture(PyUISpriteObject* self, void* closure)
|
|||
int UISprite::set_texture(PyUISpriteObject* self, PyObject* value, void* closure)
|
||||
{
|
||||
// Check if value is a Texture instance
|
||||
if (!PyObject_IsInstance(value, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Texture"))) {
|
||||
if (!PyObject_IsInstance(value, (PyObject*)&mcrfpydef::PyTextureType)) {
|
||||
PyErr_SetString(PyExc_TypeError, "texture must be a mcrfpy.Texture instance");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -370,7 +370,7 @@ int UISprite::set_texture(PyUISpriteObject* self, PyObject* value, void* closure
|
|||
|
||||
PyObject* UISprite::get_pos(PyUISpriteObject* self, void* closure)
|
||||
{
|
||||
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
||||
auto type = &mcrfpydef::PyVectorType;
|
||||
auto obj = (PyVectorObject*)type->tp_alloc(type, 0);
|
||||
if (obj) {
|
||||
auto pos = self->data->getPosition();
|
||||
|
|
@ -515,9 +515,7 @@ int UISprite::init(PyUISpriteObject* self, PyObject* args, PyObject* kwds)
|
|||
std::shared_ptr<PyTexture> texture_ptr = nullptr;
|
||||
if (snapshot && snapshot != Py_None) {
|
||||
// Check if snapshot is a Frame (most common case)
|
||||
PyObject* frame_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame");
|
||||
if (PyObject_IsInstance(snapshot, frame_type)) {
|
||||
Py_DECREF(frame_type);
|
||||
if (PyObject_IsInstance(snapshot, (PyObject*)&mcrfpydef::PyUIFrameType)) {
|
||||
auto pyframe = (PyUIFrameObject*)snapshot;
|
||||
if (!pyframe->data) {
|
||||
PyErr_SetString(PyExc_ValueError, "Invalid Frame object for snapshot");
|
||||
|
|
@ -547,14 +545,13 @@ int UISprite::init(PyUISpriteObject* self, PyObject* args, PyObject* kwds)
|
|||
texture_ptr = PyTexture::from_rendered(render_tex);
|
||||
sprite_index = 0; // Snapshot is always sprite index 0
|
||||
} else {
|
||||
Py_DECREF(frame_type);
|
||||
PyErr_SetString(PyExc_TypeError, "snapshot must be a Frame instance");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
// Handle texture - allow None or use default (only if no snapshot)
|
||||
else if (texture && texture != Py_None) {
|
||||
if (!PyObject_IsInstance(texture, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Texture"))) {
|
||||
if (!PyObject_IsInstance(texture, (PyObject*)&mcrfpydef::PyTextureType)) {
|
||||
PyErr_SetString(PyExc_TypeError, "texture must be a mcrfpy.Texture instance or None");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -616,11 +613,7 @@ int UISprite::init(PyUISpriteObject* self, PyObject* args, PyObject* kwds)
|
|||
}
|
||||
|
||||
// #184: Check if this is a Python subclass (for callback method support)
|
||||
PyObject* sprite_type = PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite");
|
||||
if (sprite_type) {
|
||||
self->data->is_python_subclass = (PyObject*)Py_TYPE(self) != sprite_type;
|
||||
Py_DECREF(sprite_type);
|
||||
}
|
||||
self->data->is_python_subclass = (PyObject*)Py_TYPE(self) != (PyObject*)&mcrfpydef::PyUISpriteType;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue