UIEntity fixes for the UI.h split: There are segfaults in cos_play, I may have missed a type usage or something

This commit is contained in:
John McCardle 2024-04-18 21:23:49 -04:00
parent 76693acd28
commit 567218cd7b
2 changed files with 107 additions and 9 deletions

View File

@ -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<UIEntity>(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<UIGridPointState>& 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<UIGridPointState> 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 */
};

View File

@ -25,6 +25,12 @@ class UIGrid;
// std::shared_ptr<UIEntity> 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<UIGridPointState>& 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,
};