diff --git a/src/McRFPy_API.cpp b/src/McRFPy_API.cpp index e5621f0..9f4a013 100644 --- a/src/McRFPy_API.cpp +++ b/src/McRFPy_API.cpp @@ -56,7 +56,7 @@ PyObject* PyInit_mcrfpy() using namespace mcrfpydef; PyTypeObject* pytypes[] = { /*SFML exposed types*/ - &PyColorType, /*&PyLinkedColorType,*/ &PyFontType, &PyTextureType, + &PyColorType, /*&PyLinkedColorType,*/ &PyFontType, &PyTextureType, &PyVectorType, /*UI widgets*/ &PyUICaptionType, &PyUISpriteType, &PyUIFrameType, &PyUIEntityType, &PyUIGridType, diff --git a/src/PyVector.cpp b/src/PyVector.cpp new file mode 100644 index 0000000..9438b42 --- /dev/null +++ b/src/PyVector.cpp @@ -0,0 +1,113 @@ +#include "PyVector.h" + +PyGetSetDef PyVector::getsetters[] = { + {"x", (getter)PyVector::get_member, (setter)PyVector::set_member, "X/horizontal component", (void*)0}, + {"y", (getter)PyVector::get_member, (setter)PyVector::set_member, "Y/vertical component", (void*)1}, + {NULL} +}; + +PyVector::PyVector(sf::Vector2f target) +:data(target) {} + +PyObject* PyVector::pyObject() +{ + PyObject* obj = PyType_GenericAlloc(&mcrfpydef::PyVectorType, 0); + Py_INCREF(obj); + PyVectorObject* self = (PyVectorObject*)obj; + self->data = data; + return obj; +} + +sf::Vector2f PyVector::fromPy(PyObject* obj) +{ + PyVectorObject* self = (PyVectorObject*)obj; + return self->data; +} + +sf::Vector2f PyVector::fromPy(PyVectorObject* self) +{ + return self->data; +} + +Py_hash_t PyVector::hash(PyObject* obj) +{ + auto self = (PyVectorObject*)obj; + Py_hash_t value = 0; + value += self->data.x; + value << 8; value += self->data.y; + + return value; +} + +PyObject* PyVector::repr(PyObject* obj) +{ + PyVectorObject* self = (PyVectorObject*)obj; + std::ostringstream ss; + sf::Vector2f v = self->data; + ss << ""; + + std::string repr_str = ss.str(); + return PyUnicode_DecodeUTF8(repr_str.c_str(), repr_str.size(), "replace"); +} + + +int PyVector::init(PyVectorObject* self, PyObject* args, PyObject* kwds) +{ + using namespace mcrfpydef; + static const char* keywords[] = { "x", "y", nullptr }; + PyObject* leader; + double x=0, y=0; + if (!PyArg_ParseTupleAndKeywords, args, kwds, "|Of", leader, &y) + { + //PyErr_SetString(PyExc_TypeError, "mcrfpy.Vector requires a 2-tuple or two numeric values"); + return 0; + } + + // if the "r" arg is already a vector, yoink that color value + if (PyObject_IsInstance(leader, (PyObject*)&PyVectorType)) + { + self->data = ((PyVectorObject*)leader)->data; + return 0; + } + // else if the "r" arg is a 3-tuple, initialize to (r, g, b, 255) + // (if the "r" arg is a 4-tuple, initialize to (r, g, b, a)) + else if (PyTuple_Check(leader)) + { + if (PyTuple_Size(leader) != 2) + { + PyErr_SetString(PyExc_TypeError, "Invalid tuple length: mcrfpy.Vector requires a 2-tuple"); + return -1; + } + x = PyFloat_AsDouble(PyTuple_GetItem(leader, 0)); + y = PyFloat_AsDouble(PyTuple_GetItem(leader, 1)); + + self->data = sf::Vector2f(x, y); + } + // else - + else if (!PyFloat_Check(leader) && !(PyLong_Check(leader))) + { + PyErr_SetString(PyExc_TypeError, "mcrfpy.Vector requires a 2-tuple or two numeric values"); + return -1; + } + if (PyFloat_Check(leader)) x = PyFloat_AsDouble(leader); + else x = PyLong_AsDouble(leader); + self->data = sf::Vector2f(x, y); + return 0; +} + +PyObject* PyVector::pynew(PyTypeObject* type, PyObject* args, PyObject* kwds) +{ + return (PyObject*)type->tp_alloc(type, 0); +} + +PyObject* PyVector::get_member(PyObject* obj, void* closure) +{ + // TODO + return Py_None; +} + +int PyVector::set_member(PyObject* obj, PyObject* value, void* closure) +{ + // TODO + return 0; +} diff --git a/src/PyVector.h b/src/PyVector.h new file mode 100644 index 0000000..6ea0622 --- /dev/null +++ b/src/PyVector.h @@ -0,0 +1,42 @@ +#pragma once +#include "Common.h" +#include "Python.h" + +typedef struct { + PyObject_HEAD + sf::Vector2f data; +} PyVectorObject; + +class PyVector +{ +public: + sf::Vector2f data; + PyVector(sf::Vector2f); + PyVector(); + PyObject* pyObject(); + static sf::Vector2f fromPy(PyObject*); + static sf::Vector2f fromPy(PyVectorObject*); + static PyObject* repr(PyObject*); + static Py_hash_t hash(PyObject*); + static int init(PyVectorObject*, PyObject*, PyObject*); + static PyObject* pynew(PyTypeObject* type, PyObject* args=NULL, PyObject* kwds=NULL); + static PyObject* get_member(PyObject*, void*); + static int set_member(PyObject*, PyObject*, void*); + + static PyGetSetDef getsetters[]; +}; + +namespace mcrfpydef { + static PyTypeObject PyVectorType = { + .tp_name = "mcrfpy.Vector", + .tp_basicsize = sizeof(PyVectorObject), + .tp_itemsize = 0, + .tp_repr = PyVector::repr, + .tp_hash = PyVector::hash, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = PyDoc_STR("SFML Vector Object"), + .tp_getset = PyVector::getsetters, + .tp_init = (initproc)PyVector::init, + .tp_new = PyVector::pynew, + }; +} diff --git a/src/UI.h b/src/UI.h index f0f64db..1a47a40 100644 --- a/src/UI.h +++ b/src/UI.h @@ -12,6 +12,7 @@ #include "PyTexture.h" #include "PyColor.h" //#include "PyLinkedColor.h" +#include "PyVector.h" enum PyObjectsEnum : int { @@ -587,6 +588,17 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c return 0; } + static PyObject* PyUICaption_get_vec_member(PyUICaptionObject* self, void* closure) + { + return PyVector(self->data->text.getPosition()).pyObject(); + } + + static int PyUICaption_set_vec_member(PyUICaptionObject* self, PyObject* value, void* closure) + { + self->data->text.setPosition(PyVector::fromPy(value)); + return 0; + } + static PyObject* PyUICaption_get_color_member(PyUICaptionObject* self, void* closure) { // validate closure (should be impossible to be wrong, but it's thorough) @@ -730,6 +742,7 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c static PyGetSetDef PyUICaption_getsetters[] = { {"x", (getter)PyUICaption_get_float_member, (setter)PyUICaption_set_float_member, "X coordinate of top-left corner", (void*)0}, {"y", (getter)PyUICaption_get_float_member, (setter)PyUICaption_set_float_member, "Y coordinate of top-left corner", (void*)1}, + {"pos", (getter)PyUICaption_get_vec_member, (setter)PyUICaption_set_vec_member, "(x, y) vector", (void*)0}, //{"w", (getter)PyUIFrame_get_float_member, (setter)PyUIFrame_set_float_member, "width of the rectangle", (void*)2}, //{"h", (getter)PyUIFrame_get_float_member, (setter)PyUIFrame_set_float_member, "height of the rectangle", (void*)3}, {"outline", (getter)PyUICaption_get_float_member, (setter)PyUICaption_set_float_member, "Thickness of the border", (void*)4},