Build runs again. PyColor objects are being instantiated, with bugs and no test of color changing

This commit is contained in:
John McCardle 2024-03-26 23:02:00 -04:00
parent 1601fc7fab
commit 13a4ddf41b
3 changed files with 159 additions and 14 deletions

View File

@ -8,11 +8,19 @@ PyGetSetDef PyColor::getsetters[] = {
{NULL} {NULL}
}; };
PyColor::PyColor(_PyColorData d)
{
data = d;
if (data.index == PyColor::SELF_OWNED) data.index = PyColor::BORROWED; // I think this is a bad idea, but the alternatives come with their own mess
}
PyColor::PyColor(sf::Color* target, std::weak_ptr<UIDrawable> parent, int index) PyColor::PyColor(sf::Color* target, std::weak_ptr<UIDrawable> parent, int index)
{ {
data.index = index; data.index = index;
data.parent = parent; data.parent = parent;
data.target = target; data.target = target;
data.setter = NULL;
data.getter = NULL;
} }
PyColor::PyColor(sf::Color target) PyColor::PyColor(sf::Color target)
@ -20,6 +28,18 @@ PyColor::PyColor(sf::Color target)
data.index = PyColor::SELF_OWNED; data.index = PyColor::SELF_OWNED;
data.parent = std::weak_ptr<UIDrawable>(); data.parent = std::weak_ptr<UIDrawable>();
data.target = new sf::Color; data.target = new sf::Color;
data.setter = NULL;
data.getter = NULL;
}
PyColor::PyColor(sf::Color (*getter)(), void (*setter)(sf::Color), std::weak_ptr<UIDrawable> parent, int index)
{
data.index = index;
data.parent = parent;
data.target = NULL;
data.setter = setter;
data.getter = getter;
} }
PyColor::~PyColor() PyColor::~PyColor()
@ -31,32 +51,123 @@ PyColor::~PyColor()
PyObject* PyColor::pyObject() PyObject* PyColor::pyObject()
{ {
PyObject* obj = PyType_GenericAlloc(&mcrfpydef::PyColorType, 0); PyObject* obj = PyType_GenericAlloc(&mcrfpydef::PyColorType, 0);
((PyColorObject*)obj->data = data; PyColorObject* self = (PyColorObject*)obj;
self->data = data;
if (data.index == PyColor::SELF_OWNED) self->data.index = PyColor::BORROWED;
return obj; return obj;
} }
PyColor PyColor::fromPy(PyObject* obj)
{
PyColorObject* self = (PyColorObject*)obj;
return PyColor(self->data);
}
PyColor PyColor::fromPy(PyColorObject* self)
{
return PyColor(self->data);
}
void PyColor::set(sf::Color color)
{
auto ptr = data.parent.lock();
if (ptr || data.index == PyColor::SELF_OWNED)
{
if (data.setter)
data.setter(color);
else
*data.target = color;
}
}
sf::Color PyColor::get()
{
auto ptr = data.parent.lock();
if (ptr || data.index == PyColor::SELF_OWNED)
{
if (data.getter)
return data.getter();
else
return *(data.target);
}
return sf::Color(0, 0, 0, 0);
}
bool PyColor::alive()
{
if (data.index == PyColor::SELF_OWNED) return true;
return !data.parent.lock();
}
std::string PyColor::field()
{
switch (data.index)
{
case PyColor::SELF_OWNED:
return "None";
break;
case 0:
return "fill";
break;
case 1:
return "outline";
break;
case 2:
return "background";
break;
default:
return "unknown";
break;
}
}
std::string PyColor::mode()
{
if (data.index == PyColor::SELF_OWNED) return "self-owned value";
else if (data.index == PyColor::BORROWED) return "self-owned value (borrowed)";
else if (data.getter || data.setter)
{
if (alive()) return "callback passthrough";
else return "callback passthrough (dangling; parent dead)";
}
else if (alive()) return "linked pointer";
else return "linked pointer (dangling; parent dead)";
}
Py_hash_t PyColor::hash(PyObject* obj) Py_hash_t PyColor::hash(PyObject* obj)
{ {
auto self = (PyColorObject*)obj; auto self = (PyColorObject*)obj;
Py_hash_t value = 0; Py_hash_t value = 0;
auto ptr = self.data.parent.lock(); auto ptr = self->data.parent.lock();
if (ptr || self->data.index == PyColor::SELF_OWNED) if (ptr || self->data.index == PyColor::SELF_OWNED)
{ {
value += self->data.target.r; value += self->data.target->r;
value << 8; value += self->data.target.g; value << 8; value += self->data.target->g;
value << 8; value += self->data.target.b; value << 8; value += self->data.target->b;
value << 8; value += self->data.target.a; value << 8; value += self->data.target->a;
} }
if (ptr) if (ptr)
{ {
//value << (sizeof(*UIDrawable) * 8);
value << (sizeof(*UIDrawable) * 8); value += reinterpret_cast<Py_hash_t>(&ptr);
value += reinterpret_cast<Py_hash_t>(ptr);
} }
return value; return value;
} }
PyObject* PyColor::repr(PyObject* obj)
{
PyColorObject* self = (PyColorObject*)obj;
std::ostringstream ss;
PyColor color = PyColor(self->data);
sf::Color c = color.get();
ss << "<Color (" << c.r << ", " << c.g << ", " << c.b << ", " << c.a << ") " << color.mode() << ">";
std::string repr_str = ss.str();
return PyUnicode_DecodeUTF8(repr_str.c_str(), repr_str.size(), "replace");
}
int PyColor::init(PyColorObject* self, PyObject* args, PyObject* kwds) int PyColor::init(PyColorObject* self, PyObject* args, PyObject* kwds)
{ {
static const char* keywords[] = { "r", "g", "b", "a", nullptr }; static const char* keywords[] = { "r", "g", "b", "a", nullptr };
@ -67,3 +178,13 @@ PyObject* PyColor::pynew(PyTypeObject* type, PyObject* args, PyObject* kwds)
{ {
return (PyObject*)type->tp_alloc(type, 0); return (PyObject*)type->tp_alloc(type, 0);
} }
PyObject* PyColor::get_member(PyObject* obj, void* closure)
{
return Py_None;
}
int PyColor::set_member(PyObject* obj, PyObject* value, void* closure)
{
return 0;
}

View File

@ -9,6 +9,8 @@ typedef struct {
sf::Color* target; // color target to set/get sf::Color* target; // color target to set/get
std::weak_ptr<UIDrawable> parent; // lifetime management: parent must still exist std::weak_ptr<UIDrawable> parent; // lifetime management: parent must still exist
int index; // specific to the parent class, which color is it? int index; // specific to the parent class, which color is it?
sf::Color(*getter)();
void(*setter)(sf::Color);
} _PyColorData; } _PyColorData;
typedef struct { typedef struct {
@ -21,16 +23,27 @@ class PyColor
private: private:
_PyColorData data; _PyColorData data;
static const int SELF_OWNED = -1; static const int SELF_OWNED = -1;
static const int BORROWED = -2;
PyColor(_PyColorData); // private constructor / for operations transferring between C++ and Python
public: public:
PyColor(sf::Color* target, std::weak_ptr<UIDrawable> parent, int index); // linked constructor PyColor(sf::Color* target, std::weak_ptr<UIDrawable> parent, int index); // linked constructor
PyColor(sf::Color target); // simple color container PyColor(sf::Color target); // simple color container
void set(sf::Color); PyColor(sf::Color (*)(), void (*)(sf::Color), std::weak_ptr<UIDrawable>, int);
sf::Color get(); ~PyColor();
void set(sf::Color); // change target value, behavior determined by the mode
sf::Color get(); // retrieve target value, behavior determined by the mode
PyObject* pyParent(); // UIDrawable derived parent object or None
std::string field(); // interpret the index as a field's name on UIDrawable
std::string mode(); // "value" for SELF_OWNED, "linked" for pointer, and "passthrough" for callbacks
bool alive(); // true if SELF_OWNED or parent still exists
PyObject* pyObject(); PyObject* pyObject();
static PyColor fromPy(PyObject*);
static PyColor fromPy(PyColorObject*);
static PyObject* repr(PyObject*);
static Py_hash_t hash(PyObject*); static Py_hash_t hash(PyObject*);
static int init(PyColorObject*, PyObject*, PyObject*); static int init(PyColorObject*, PyObject*, PyObject*);
static PyObject* pynew(PyTypeObject* type, PyObject* args=NULL, PyObject* kwds=NULL); static PyObject* pynew(PyTypeObject* type, PyObject* args=NULL, PyObject* kwds=NULL);
static PyObject* get_member(PyObject*, void*); static PyObject* get_member(PyObject*, void*);
static int set_member(PyObject*, PyObject*, void*); static int set_member(PyObject*, PyObject*, void*);
@ -81,6 +94,7 @@ namespace mcrfpydef {
.tp_name = "mcrfpy.Color", .tp_name = "mcrfpy.Color",
.tp_basicsize = sizeof(PyColorObject), .tp_basicsize = sizeof(PyColorObject),
.tp_itemsize = 0, .tp_itemsize = 0,
.tp_repr = PyColor::repr,
.tp_hash = PyColor::hash, .tp_hash = PyColor::hash,
.tp_flags = Py_TPFLAGS_DEFAULT, .tp_flags = Py_TPFLAGS_DEFAULT,
.tp_doc = PyDoc_STR("SFML Color Object"), .tp_doc = PyDoc_STR("SFML Color Object"),

View File

@ -617,7 +617,8 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c
} }
// initialize new mcrfpy.Color instance // initialize new mcrfpy.Color instance
pyColorObj->data = std::make_shared<sf::Color>(color); //pyColorObj->data = std::make_shared<sf::Color>(color);
PyColor::fromPy(pyColorObj).set(color);
return pyColor; return pyColor;
} }
@ -630,11 +631,15 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c
if (PyObject_IsInstance(value, (PyObject*)&PyColorType)) if (PyObject_IsInstance(value, (PyObject*)&PyColorType))
{ {
// get value from mcrfpy.Color instance // get value from mcrfpy.Color instance
/*
PyColorObject* color = reinterpret_cast<PyColorObject*>(value); PyColorObject* color = reinterpret_cast<PyColorObject*>(value);
r = color->data->r; r = color->data->r;
g = color->data->g; g = color->data->g;
b = color->data->b; b = color->data->b;
a = color->data->a; a = color->data->a;
*/
sf::Color c = PyColor::fromPy(value).get();
r = c.r; g = c.g; b = c.b; a = c.a;
} }
else if (!PyTuple_Check(value) || PyTuple_Size(value) < 3 || PyTuple_Size(value) > 4) else if (!PyTuple_Check(value) || PyTuple_Size(value) < 3 || PyTuple_Size(value) > 4)
{ {
@ -901,7 +906,8 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c
} }
// initialize new mcrfpy.Color instance // initialize new mcrfpy.Color instance
pyColorObj->data = std::make_shared<sf::Color>(color); //pyColorObj->data = std::make_shared<sf::Color>(color);
PyColor::fromPy(pyColorObj).set(color);
return pyColor; return pyColor;
} }
@ -914,12 +920,16 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c
if (PyObject_IsInstance(value, (PyObject*)&PyColorType)) if (PyObject_IsInstance(value, (PyObject*)&PyColorType))
{ {
// get value from mcrfpy.Color instance // get value from mcrfpy.Color instance
/*
PyColorObject* color = reinterpret_cast<PyColorObject*>(value); PyColorObject* color = reinterpret_cast<PyColorObject*>(value);
r = color->data->r; r = color->data->r;
g = color->data->g; g = color->data->g;
b = color->data->b; b = color->data->b;
a = color->data->a; a = color->data->a;
std::cout << "using color: " << r << " " << g << " " << b << " " << a << std::endl; std::cout << "using color: " << r << " " << g << " " << b << " " << a << std::endl;
*/
sf::Color c = PyColor::fromPy(value).get();
r = c.r; g = c.g; b = c.b; a = c.a;
} }
else if (!PyTuple_Check(value) || PyTuple_Size(value) < 3 || PyTuple_Size(value) > 4) else if (!PyTuple_Check(value) || PyTuple_Size(value) < 3 || PyTuple_Size(value) > 4)
{ {