From 567218cd7bb58c87fd980166010752a0e913ef2d Mon Sep 17 00:00:00 2001 From: John McCardle Date: Thu, 18 Apr 2024 21:23:49 -0400 Subject: [PATCH] UIEntity fixes for the UI.h split: There are segfaults in cos_play, I may have missed a type usage or something --- src/UIEntity.cpp | 89 ++++++++++++++++++++++++++++++++++++++++++++++-- src/UIEntity.h | 27 +++++++++++---- 2 files changed, 107 insertions(+), 9 deletions(-) diff --git a/src/UIEntity.cpp b/src/UIEntity.cpp index abfb8b9..57aeeae 100644 --- a/src/UIEntity.cpp +++ b/src/UIEntity.cpp @@ -1,5 +1,6 @@ #include "UIEntity.h" #include "UIGrid.h" +#include "McRFPy_API.h" UIEntity::UIEntity() {} // this will not work lol. TODO remove default constructor by finding the shared pointer inits that use it @@ -19,8 +20,11 @@ PyObject* UIEntity::at(PyUIEntityObject* self, PyObject* o) { PyErr_SetString(PyExc_ValueError, "Entity cannot access surroundings because it is not associated with a grid"); return NULL; } - + /* PyUIGridPointStateObject* obj = (PyUIGridPointStateObject*)((&mcrfpydef::PyUIGridPointStateType)->tp_alloc(&mcrfpydef::PyUIGridPointStateType, 0)); + */ + auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "GridPointState"); + auto obj = (PyUIGridPointStateObject*)type->tp_alloc(type, 0); //auto target = std::static_pointer_cast(target); obj->data = &(self->data->gridstate[y + self->data->grid->grid_x * x]); obj->grid = self->data->grid; @@ -46,7 +50,7 @@ int UIEntity::init(PyUIEntityObject* self, PyObject* args, PyObject* kwds) { // // Set Texture // - if (texture != NULL && !PyObject_IsInstance(texture, (PyObject*)&mcrfpydef::PyTextureType)){ + if (texture != NULL && !PyObject_IsInstance(texture, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Texture"))){ PyErr_SetString(PyExc_TypeError, "texture must be a mcrfpy.Texture instance"); return -1; } /*else if (texture != NULL) // this section needs to go; texture isn't optional and isn't managed by the UI objects anymore @@ -58,7 +62,7 @@ int UIEntity::init(PyUIEntityObject* self, PyObject* args, PyObject* kwds) { // default tex? }*/ - if (grid != NULL && !PyObject_IsInstance(grid, (PyObject*)&mcrfpydef::PyUIGridType)) { + if (grid != NULL && !PyObject_IsInstance(grid, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid"))) { PyErr_SetString(PyExc_TypeError, "grid must be a mcrfpy.Grid instance"); return -1; } @@ -80,3 +84,82 @@ int UIEntity::init(PyUIEntityObject* self, PyObject* args, PyObject* kwds) { } return 0; } + + + +PyObject* UIEntity::get_spritenumber(PyUIEntityObject* self, void* closure) { + return PyLong_FromDouble(self->data->sprite.getSpriteIndex()); +} + +PyObject* sfVector2f_to_PyObject(sf::Vector2f vector) { + return Py_BuildValue("(ff)", vector.x, vector.y); +} + +sf::Vector2f PyObject_to_sfVector2f(PyObject* obj) { + float x, y; + if (!PyArg_ParseTuple(obj, "ff", &x, &y)) { + return sf::Vector2f(); // TODO / reconsider this default: Return default vector on parse error + } + return sf::Vector2f(x, y); +} + +// TODO - deprecate / remove this helper +PyObject* UIGridPointState_to_PyObject(const UIGridPointState& state) { + return PyObject_New(PyObject, (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "GridPointState")); +} + +PyObject* UIGridPointStateVector_to_PyList(const std::vector& vec) { + PyObject* list = PyList_New(vec.size()); + if (!list) return PyErr_NoMemory(); + + for (size_t i = 0; i < vec.size(); ++i) { + PyObject* obj = UIGridPointState_to_PyObject(vec[i]); + if (!obj) { // Cleanup on failure + Py_DECREF(list); + return NULL; + } + PyList_SET_ITEM(list, i, obj); // This steals a reference to obj + } + + return list; +} + +PyObject* UIEntity::get_position(PyUIEntityObject* self, void* closure) { + return sfVector2f_to_PyObject(self->data->position); +} + +int UIEntity::set_position(PyUIEntityObject* self, PyObject* value, void* closure) { + self->data->position = PyObject_to_sfVector2f(value); + return 0; +} + +PyObject* UIEntity::get_gridstate(PyUIEntityObject* self, void* closure) { + // Assuming a function to convert std::vector to PyObject* list + return UIGridPointStateVector_to_PyList(self->data->gridstate); +} + +int UIEntity::set_spritenumber(PyUIEntityObject* self, PyObject* value, void* closure) { + int val; + if (PyLong_Check(value)) + val = PyLong_AsLong(value); + else + { + PyErr_SetString(PyExc_TypeError, "Value must be an integer."); + return -1; + } + //self->data->sprite.sprite_index = val; + self->data->sprite.setSpriteIndex(val); // todone - I don't like ".sprite.sprite" in this stack of UIEntity.UISprite.sf::Sprite + return 0; +} + +PyMethodDef UIEntity::methods[] = { + {"at", (PyCFunction)UIEntity::at, METH_O}, + {NULL, NULL, 0, NULL} +}; + +PyGetSetDef UIEntity::getsetters[] = { + {"position", (getter)UIEntity::get_position, (setter)UIEntity::set_position, "Entity position", NULL}, + {"gridstate", (getter)UIEntity::get_gridstate, NULL, "Grid point states for the entity", NULL}, + {"sprite_number", (getter)UIEntity::get_spritenumber, (setter)UIEntity::set_spritenumber, "Sprite number (index) on the texture on the display", NULL}, + {NULL} /* Sentinel */ +}; diff --git a/src/UIEntity.h b/src/UIEntity.h index 1f37aa6..da14cb2 100644 --- a/src/UIEntity.h +++ b/src/UIEntity.h @@ -25,6 +25,12 @@ class UIGrid; // std::shared_ptr data; //} PyUIEntityObject; +// helper methods with no namespace requirement +static PyObject* sfVector2f_to_PyObject(sf::Vector2f vector); +static sf::Vector2f PyObject_to_sfVector2f(PyObject* obj); +static PyObject* UIGridPointState_to_PyObject(const UIGridPointState& state); +static PyObject* UIGridPointStateVector_to_PyList(const std::vector& vec); + // TODO: make UIEntity a drawable class UIEntity//: public UIDrawable { @@ -41,9 +47,18 @@ public: static PyObject* at(PyUIEntityObject* self, PyObject* o); static int init(PyUIEntityObject* self, PyObject* args, PyObject* kwds); + + static PyObject* get_position(PyUIEntityObject* self, void* closure); + static int set_position(PyUIEntityObject* self, PyObject* value, void* closure); + static PyObject* get_gridstate(PyUIEntityObject* self, void* closure); + static PyObject* get_spritenumber(PyUIEntityObject* self, void* closure); + static int set_spritenumber(PyUIEntityObject* self, PyObject* value, void* closure); + static PyMethodDef methods[]; + static PyGetSetDef getsetters[]; }; namespace mcrfpydef { +/* //TODO: add this method to class scope; move implementation to .cpp file; reconsider for moving to "UIBase.h/.cpp" // TODO: sf::Vector2f convenience functions here might benefit from a PyVectorObject much like PyColorObject // Utility function to convert sf::Vector2f to PyObject* @@ -128,7 +143,7 @@ static int PyUIEntity_set_spritenumber(PyUIEntityObject* self, PyObject* value, } //TODO: add this method to class scope; move implementation to .cpp file -/* + static PyObject* PyUIEntity_at(PyUIEntityObject* self, PyObject* o) { int x, y; @@ -149,7 +164,7 @@ static PyObject* PyUIEntity_at(PyUIEntityObject* self, PyObject* o) obj->entity = self->data; return (PyObject*)obj; } -*/ + //TODO: add this static array to class scope; move implementation to .cpp file static PyMethodDef PyUIEntity_methods[] = { @@ -163,13 +178,13 @@ static PyGetSetDef PyUIEntity_getsetters[] = { {"position", (getter)PyUIEntity_get_position, (setter)PyUIEntity_set_position, "Entity position", NULL}, {"gridstate", (getter)PyUIEntity_get_gridstate, NULL, "Grid point states for the entity", NULL}, {"sprite_number", (getter)PyUIEntity_get_spritenumber, (setter)PyUIEntity_set_spritenumber, "Sprite number (index) on the texture on the display", NULL}, - {NULL} /* Sentinel */ + {NULL} // Sentinel }; //TODO: add this method to class scope; forward declaration not required after .h/.cpp split //static int PyUIEntity_init(PyUIEntityObject*, PyObject*, PyObject*); // forward declare - +*/ // Define the PyTypeObject for UIEntity static PyTypeObject PyUIEntityType = { //PyVarObject_HEAD_INIT(NULL, 0) @@ -179,8 +194,8 @@ static PyTypeObject PyUIEntityType = { // Methods omitted for brevity .tp_flags = Py_TPFLAGS_DEFAULT, .tp_doc = "UIEntity objects", - .tp_methods = PyUIEntity_methods, - .tp_getset = PyUIEntity_getsetters, + .tp_methods = UIEntity::methods, + .tp_getset = UIEntity::getsetters, .tp_init = (initproc)UIEntity::init, .tp_new = PyType_GenericNew, };