From c4d5a497d4e306bf4330af08fc6464a9f94ce609 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Mon, 28 Aug 2023 05:44:26 -0400 Subject: [PATCH] Color container type for Python working. I still need to implement UIFrame using it. --- src/McRFPy_API.cpp | 111 ++------------------- src/UI.cpp | 23 ++++- src/UI.h | 238 ++++++++++++++++++++++---------------------- src/UITestScene.cpp | 27 ++--- 4 files changed, 159 insertions(+), 240 deletions(-) diff --git a/src/McRFPy_API.cpp b/src/McRFPy_API.cpp index 0cf93ba..8bad78f 100644 --- a/src/McRFPy_API.cpp +++ b/src/McRFPy_API.cpp @@ -20,6 +20,7 @@ bool McRFPy_API::do_camfollow; EntityManager McRFPy_API::entities; static PyMethodDef mcrfpyMethods[] = { + {"createMenu", McRFPy_API::_createMenu, METH_VARARGS, "Create a new uimenu (name_str, x, y, w, h)"}, @@ -95,6 +96,7 @@ static PyMethodDef mcrfpyMethods[] = { {"createEntity", McRFPy_API::_createEntity, METH_VARARGS, ""}, //{"listEntities", McRFPy_API::_listEntities, METH_VARARGS, ""}, {"refreshFov", McRFPy_API::_refreshFov, METH_VARARGS, ""}, + {"camFollow", McRFPy_API::_camFollow, METH_VARARGS, ""}, {NULL, NULL, 0, NULL} @@ -105,95 +107,6 @@ static PyModuleDef mcrfpyModule = { NULL, NULL, NULL, NULL }; -// -// Point class dump -// - -// Point class example - - class Point -{ -public: - float x, y; - float magnitude() { - return std::sqrt(x*x + y*y); - } -}; - - - -static PyObject* PyPoint_new(PyTypeObject* type, PyObject* args, PyObject* kwds) -{ - Point* self; - self = (Point*)type->tp_alloc(type, 0); - if (self != nullptr) - { - self->x = 0.0f; - self->y = 0.0f; - } - return (PyObject*)self; -} - - -// Method to initialize the Point object -static int PyPoint_init(Point* self, PyObject* args, PyObject* kwds) -{ - static const char* keywords[] = { "x", "y", nullptr }; - float x = 0.0f, y = 0.0f; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ff", const_cast(keywords), &x, &y)) - { - return -1; - } - - self->x = x; - self->y = y; - - return 0; -} - -// Method to calculate the magnitude of the Point -static PyObject* PyPoint_magnitude(Point* self) -{ - float mag = self->magnitude(); - return PyFloat_FromDouble(mag); -} - -static PyMethodDef PyPoint_methods[] = { - {"magnitude", (PyCFunction)PyPoint_magnitude, METH_NOARGS, - "Vector length, or distance from origin."}, - {NULL, NULL, 0, NULL} -}; - -static PyMemberDef PyPoint_members[] = { - {"x", T_FLOAT, offsetof(Point, x), 0}, - {"y", T_FLOAT, offsetof(Point, y), 0}, - {NULL} -}; - - -static PyTypeObject PyPointType = { - .tp_name = "mcrfpy.Point", - .tp_basicsize = sizeof(Point), - //.tp_itemsize = 0, - //.tp_dealloc = NULL, - //.tp_repr = NULL, - //.tp_hash = NULL, - //.tp_iter - //.tp_iternext - .tp_flags = Py_TPFLAGS_DEFAULT, - //.tp_doc = PyDoc_STR("Custom point object. (x, y)"), - //.tp_methods = PyPoint_methods, - .tp_members = PyPoint_members, - //.tp_init = (initproc)PyPoint_init, - //.tp_new = PyPoint_new, //PyType_GenericNew ? -}; - - -// -// End Dump -// - // Module initializer fn, passed to PyImport_AppendInittab PyObject* PyInit_mcrfpy() { @@ -201,31 +114,19 @@ PyObject* PyInit_mcrfpy() if (m == NULL) { - std::cout << "ohno, module didn't ):\n"; return NULL; } - /* // This code runs, but Python segfaults when accessing the UIFrame type. std::cout << "Adding UIFrame object to module\n"; - Py_INCREF(&mcrfpydef::PyUIFrameType); - if (PyModule_AddObject(m, "UIFrame", (PyObject *) & mcrfpydef::PyUIFrameType) < 0) + PyModule_AddType(m, &mcrfpydef::PyColorType); + if (PyModule_AddType(m, &mcrfpydef::PyUIFrameType) < 0) { - std::cout << "Failed to add UIFrame object\n"; + std::cout << "Error adding UIFrame type to module; aborting" << std::endl; Py_DECREF(&mcrfpydef::PyUIFrameType); - //return NULL; - } - std::cout << "Returning module\n"; - */ - - Py_INCREF(&PyPointType); - if (PyModule_AddObject(m, "Point", (PyObject *) &PyPointType) < 0) { - std::cout << "ohno, couldn't add\n"; - Py_DECREF(&PyPointType); - Py_DECREF(m); return NULL; } - + return m; } diff --git a/src/UI.cpp b/src/UI.cpp index 08db2a5..6e36a9c 100644 --- a/src/UI.cpp +++ b/src/UI.cpp @@ -7,15 +7,30 @@ void UIDrawable::render() //std::cout << "Rendering base UIDrawable\n"; render(sf::Vector2f()); } +UIFrame::UIFrame(): +x(0), y(0), w(0), h(0), outline(0), fillColor(0,0,0,255), outlineColor(0,0,0,0) +{} + +UIFrame::UIFrame(float _x, float _y, float _w, float _h): +x(_x), y(_y), w(_w), h(_h), outline(0), fillColor(0,0,0,255), outlineColor(0,0,0,0) +{} void UIFrame::render(sf::Vector2f offset) { - //std::cout << "Rendering UIFrame w/ offset\n"; - box.move(offset); + //std::cout << "Rendering UIFrame w/ offset " << offset.x << ", " << offset.y << "\n"; + //std::cout << "position = " << x << ", " << y << "\n"; + //box.move(offset); + //Resources::game->getWindow().draw(box); + //box.move(-offset); + sf::RectangleShape box = sf::RectangleShape(sf::Vector2f(w,h)); + sf::Vector2f pos = sf::Vector2f(x, y); + box.setPosition(offset + pos); + box.setFillColor(fillColor); + box.setOutlineColor(outlineColor); + box.setOutlineThickness(outline); Resources::game->getWindow().draw(box); - box.move(-offset); for (auto drawable : children) { - drawable->render(offset + box.getPosition()); + drawable->render(offset + pos); } } diff --git a/src/UI.h b/src/UI.h index d6e650e..d5bec87 100644 --- a/src/UI.h +++ b/src/UI.h @@ -17,9 +17,16 @@ public: class UIFrame: public UIDrawable { public: - sf::RectangleShape box; + UIFrame(float, float, float, float); + UIFrame(); + //sf::RectangleShape box; + + //Simulate RectangleShape + sf::Color fillColor, outlineColor; + float x, y, w, h, outline; std::vector children; void render(sf::Vector2f) override final; + void move(sf::Vector2f); }; class UICaption: public UIDrawable @@ -39,7 +46,112 @@ public: }; namespace mcrfpydef { + + // Color Definitions + // struct, members, new, set_member, PyTypeObject + typedef struct { + PyObject_HEAD + sf::Color color; + } PyColorObject; + + static PyMemberDef PyColor_members[] + { + {"r", T_BYTE, offsetof(PyColorObject, color.r), 0}, + {"g", T_BYTE, offsetof(PyColorObject, color.g), 0}, + {"b", T_BYTE, offsetof(PyColorObject, color.b), 0}, + {"a", T_BYTE, offsetof(PyColorObject, color.a), 0}, + {NULL} + }; + + static PyObject* PyColor_new(PyTypeObject* type, PyObject* args, PyObject* kwds) + { + PyColorObject* self = (PyColorObject*)type->tp_alloc(type, 0); + if (self != NULL) + { + self->color.r = 0; + self->color.g = 0; + self->color.b = 0; + self->color.a = 255; + } + return (PyObject*) self; + } + + static PyObject* PyColor_get_member(PyColorObject* self, void* closure) + { + auto member_ptr = reinterpret_cast(closure); + if (member_ptr == offsetof(PyColorObject, color.r)) + return PyLong_FromLong(self->color.r); + else if (member_ptr == offsetof(PyColorObject, color.g)) + return PyLong_FromLong(self->color.g); + else if (member_ptr == offsetof(PyColorObject, color.b)) + return PyLong_FromLong(self->color.b); + else if (member_ptr == offsetof(PyColorObject, color.a)) + return PyLong_FromLong(self->color.a); + else + { + PyErr_SetString(PyExc_AttributeError, "Invalid attribute"); + return nullptr; + } + } + + static int PyColor_set_member(PyColorObject* self, PyObject* value, void* closure) + { + if (PyLong_Check(value)) + { + long int_val = PyLong_AsLong(value); + if (int_val < 0) + int_val = 0; + else if (int_val > 255) + int_val = 255; + auto member_ptr = reinterpret_cast(closure); + if (member_ptr == offsetof(PyColorObject, color.r)) + self->color.r = static_cast(int_val); + else if (member_ptr == offsetof(PyColorObject, color.g)) + self->color.g = static_cast(int_val); + else if (member_ptr == offsetof(PyColorObject, color.b)) + self->color.b = static_cast(int_val); + else if (member_ptr == offsetof(PyColorObject, color.a)) + self->color.a = static_cast(int_val); + } + else + { + PyErr_SetString(PyExc_TypeError, "Value must be an integer."); + return -1; + } + return 0; + } + + static PyGetSetDef PyColor_getsetters[] = { + {"r", (getter)PyColor_get_member, (setter)PyColor_set_member, "Red component", (void*)offsetof(PyColorObject, color.r)}, + {"g", (getter)PyColor_get_member, (setter)PyColor_set_member, "Green component", (void*)offsetof(PyColorObject, color.g)}, + {"b", (getter)PyColor_get_member, (setter)PyColor_set_member, "Blue component", (void*)offsetof(PyColorObject, color.b)}, + {"a", (getter)PyColor_get_member, (setter)PyColor_set_member, "Alpha component", (void*)offsetof(PyColorObject, color.a)}, + {NULL} + }; + + static PyTypeObject PyColorType = { + //PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "mcrfpy.Color", + .tp_basicsize = sizeof(PyColorObject), + .tp_itemsize = 0, + //.tp_dealloc = [](PyObject* obj) { Py_TYPE(obj)->tp_free(obj); }, + //.tp_repr = (reprfunc)PyUIFrame_repr, + //.tp_hash = NULL, + //.tp_iter + //.tp_iternext + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = PyDoc_STR("SFML Color object (RGBA)"), + //.tp_methods = PyUIFrame_methods, + //.tp_members = PyColor_members, + .tp_getset = PyColor_getsetters, + //.tp_base = NULL, + //.tp_init = (initproc)PyUIFrame_init, + .tp_new = PyColor_new, //PyType_GenericNew ? + }; + + // UIFrame Definitions + // new, init, repr, set_size, methods, members, PyTypeObject static PyObject* PyUIFrame_new(PyTypeObject* type, PyObject* args, PyObject* kwds) { @@ -80,9 +192,9 @@ namespace mcrfpydef { static PyObject* PyUIFrame_setSize(UIFrame* self, PyObject* args) { - float w, h; - if (!PyArg_ParseTuple(args, "ff", &w, &h)) return (PyObject*)-1; - self->box.setSize(sf::Vector2f(w, h)); + //float w, h; + if (!PyArg_ParseTuple(args, "ff", &self->w, &self->h)) return (PyObject*)-1; + //self->box.setSize(sf::Vector2f(w, h)); Py_INCREF(Py_None); //return PyFloat_FromDouble(mag); return Py_None; @@ -103,7 +215,6 @@ namespace mcrfpydef { static PyTypeObject PyUIFrameType = { //PyVarObject_HEAD_INIT(NULL, 0) - //.tp_base = NULL, .tp_name = "mcrfpy.UIFrame", .tp_basicsize = sizeof(UIFrame), .tp_itemsize = 0, @@ -114,123 +225,12 @@ namespace mcrfpydef { //.tp_iternext .tp_flags = Py_TPFLAGS_DEFAULT, .tp_doc = PyDoc_STR("Custom UIFrame object"), - //.tp_methods = PyUIFrame_methods, + .tp_methods = PyUIFrame_methods, //.tp_members = PyUIFrame_members, + //.tp_base = NULL, .tp_init = (initproc)PyUIFrame_init, .tp_new = PyUIFrame_new, //PyType_GenericNew ? }; - // module - /* - static PyModuleDef ui_module = { - PyModuleDef_HEAD_INIT, - .m_name = "ui", - .m_size = -1, - }; - PyMODINIT_FUNC PyInit_my_module(void) { - PyObject* module = PyModule_Create(&my_module); - if (module == NULL) { - return NULL; - } - - if (PyType_Ready(&MyType_Type) < 0) { - return NULL; - } - - Py_INCREF(&MyType_Type); - PyModule_AddObject(module, "UIFrame", (PyObject*)&MyType_Type); - return module; - } - */ - - // Point class example - - class Point -{ -public: - float x, y; - float magnitude() { - return std::sqrt(x*x + y*y); - } -}; - - - -static PyObject* PyPoint_new(PyTypeObject* type, PyObject* args, PyObject* kwds) -{ - Point* self; - self = (Point*)type->tp_alloc(type, 0); - if (self != nullptr) - { - self->x = 0.0f; - self->y = 0.0f; - } - return (PyObject*)self; -} - - -// Method to initialize the Point object -static int PyPoint_init(Point* self, PyObject* args, PyObject* kwds) -{ - static const char* keywords[] = { "x", "y", nullptr }; - float x = 0.0f, y = 0.0f; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ff", const_cast(keywords), &x, &y)) - { - return -1; - } - - self->x = x; - self->y = y; - - return 0; -} - -// Method to calculate the magnitude of the Point -static PyObject* PyPoint_magnitude(Point* self) -{ - float mag = self->magnitude(); - return PyFloat_FromDouble(mag); -} - -static PyMethodDef PyPoint_methods[] = { - {"magnitude", (PyCFunction)PyPoint_magnitude, METH_NOARGS, - "Vector length, or distance from origin."}, - {NULL, NULL, 0, NULL} -}; - -static PyMemberDef PyPoint_members[] = { - {"x", T_FLOAT, offsetof(Point, x), 0}, - {"y", T_FLOAT, offsetof(Point, y), 0}, - {NULL} -}; - - -static PyTypeObject PyPointType = { - .tp_name = "mcrfpy.Point", - .tp_basicsize = sizeof(Point), - //.tp_itemsize = 0, - //.tp_dealloc = NULL, - //.tp_repr = NULL, - //.tp_hash = NULL, - //.tp_iter - //.tp_iternext - .tp_flags = Py_TPFLAGS_DEFAULT, - //.tp_doc = PyDoc_STR("Custom point object. (x, y)"), - //.tp_methods = PyPoint_methods, - //.tp_members = PyPoint_members, - //.tp_init = (initproc)PyPoint_init, - //.tp_new = PyPoint_new, //PyType_GenericNew ? -}; - -/* -static PyModuleDef PyPointModule = { - PyModuleDef_HEAD_INIT, - .m_name = "point", - .m_doc = "Custom point module.", - .m_size = -1, - //.m_methods = PyPoint_methods, -}; -*/ -} \ No newline at end of file +} diff --git a/src/UITestScene.cpp b/src/UITestScene.cpp index 6c27bee..e21784b 100644 --- a/src/UITestScene.cpp +++ b/src/UITestScene.cpp @@ -14,21 +14,24 @@ UITestScene::UITestScene(GameEngine* g) : Scene(g) // Create a UI element or three? - e1 = UIFrame(); - e1.box.setPosition(100, 150); - e1.box.setSize(sf::Vector2f(400,400)); - e1.box.setFillColor(sf::Color(255, 0, 0)); + e1 = UIFrame(100,150,400,400); + //e1.box.setPosition(100, 150); + //e1.box.setSize(sf::Vector2f(400,400)); + //e1.box.setFillColor(sf::Color(255, 0, 0)); + e1.fillColor = sf::Color(255,0,0); - e1a = UIFrame(); - e1a.box.setPosition(50, 50); - e1a.box.setSize(sf::Vector2f(200,200)); - e1a.box.setFillColor(sf::Color(0, 255, 0)); + e1a = UIFrame(50,50,200,200); + //e1a.box.setPosition(50, 50); + //e1a.box.setSize(sf::Vector2f(200,200)); + //e1a.box.setFillColor(sf::Color(0, 255, 0)); + e1a.fillColor = sf::Color(0, 255, 0); e1.children.push_back(&e1a); - e1aa = UIFrame(); - e1aa.box.setPosition(5, 5); - e1aa.box.setSize(sf::Vector2f(100,100)); - e1aa.box.setFillColor(sf::Color(0, 0, 255)); + e1aa = UIFrame(5,5,100,100); + //e1aa.box.setPosition(5, 5); + //e1aa.box.setSize(sf::Vector2f(100,100)); + //e1aa.box.setFillColor(sf::Color(0, 0, 255)); + e1aa.fillColor = sf::Color(0, 0, 255); e1a.children.push_back(&e1aa); e2 = UICaption();