Addressing issues with PyColor by splitting behavior off into PyLinkedColor
This commit is contained in:
parent
13a4ddf41b
commit
41509dfe96
|
@ -0,0 +1,144 @@
|
||||||
|
#include "PyLinkedColor.h"
|
||||||
|
|
||||||
|
PyGetSetDef PyLinkedColor::getsetters[] = {
|
||||||
|
{"r", (getter)PyLinkedColor::get_member, (setter)PyLinkedColor::set_member, "Red component", (void*)0},
|
||||||
|
{"g", (getter)PyLinkedColor::get_member, (setter)PyLinkedColor::set_member, "Green component", (void*)1},
|
||||||
|
{"b", (getter)PyLinkedColor::get_member, (setter)PyLinkedColor::set_member, "Blue component", (void*)2},
|
||||||
|
{"a", (getter)PyLinkedColor::get_member, (setter)PyLinkedColor::set_member, "Alpha component", (void*)3},
|
||||||
|
{NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
PyLinkedColor::PyLinkedColor(_PyLinkedColorData d)
|
||||||
|
{
|
||||||
|
data = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyLinkedColor::PyLinkedColor(sf::Color (*getter)(), void (*setter)(sf::Color), std::weak_ptr<UIDrawable> parent, int index)
|
||||||
|
{
|
||||||
|
data.index = index;
|
||||||
|
data.parent = parent;
|
||||||
|
data.setter = setter;
|
||||||
|
data.getter = getter;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* PyLinkedColor::pyObject()
|
||||||
|
{
|
||||||
|
PyObject* obj = PyType_GenericAlloc(&mcrfpydef::PyLinkedColorType, 0);
|
||||||
|
PyLinkedColorObject* self = (PyLinkedColorObject*)obj;
|
||||||
|
self->data = data;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyLinkedColor PyLinkedColor::fromPy(PyObject* obj)
|
||||||
|
{
|
||||||
|
PyLinkedColorObject* self = (PyLinkedColorObject*)obj;
|
||||||
|
return PyLinkedColor(self->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyLinkedColor PyLinkedColor::fromPy(PyLinkedColorObject* self)
|
||||||
|
{
|
||||||
|
return PyLinkedColor(self->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PyLinkedColor::set(sf::Color color)
|
||||||
|
{
|
||||||
|
auto ptr = data.parent.lock();
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
if (data.setter)
|
||||||
|
data.setter(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sf::Color PyLinkedColor::get()
|
||||||
|
{
|
||||||
|
auto ptr = data.parent.lock();
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
if (data.getter)
|
||||||
|
return data.getter();
|
||||||
|
}
|
||||||
|
return sf::Color(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PyLinkedColor::alive()
|
||||||
|
{
|
||||||
|
return !data.parent.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PyLinkedColor::field()
|
||||||
|
{
|
||||||
|
switch (data.index)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return "fill";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
return "outline";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
return "background";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_hash_t PyLinkedColor::hash(PyObject* obj)
|
||||||
|
{
|
||||||
|
auto self = (PyLinkedColorObject*)obj;
|
||||||
|
Py_hash_t value = 0;
|
||||||
|
auto ptr = self->data.parent.lock();
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
auto color = PyLinkedColor(self->data);
|
||||||
|
auto c = linkedcolor.get();
|
||||||
|
value += c.r;
|
||||||
|
value << 8; value += c.g;
|
||||||
|
value << 8; value += c.b;
|
||||||
|
value << 8; value += c.a;
|
||||||
|
}
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
//value << (sizeof(*UIDrawable) * 8);
|
||||||
|
value += reinterpret_cast<Py_hash_t>(&ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* PyLinkedColor::repr(PyObject* obj)
|
||||||
|
{
|
||||||
|
PyLinkedColorObject* self = (PyLinkedColorObject*)obj;
|
||||||
|
std::ostringstream ss;
|
||||||
|
PyLinkedColor color = PyLinkedColor(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 PyLinkedColor::init(PyLinkedColorObject* self, PyObject* args, PyObject* kwds)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
static const char* keywords[] = { "r", "g", "b", "a", nullptr };
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* PyLinkedColor::pynew(PyTypeObject* type, PyObject* args, PyObject* kwds)
|
||||||
|
{
|
||||||
|
return (PyObject*)type->tp_alloc(type, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* PyLinkedColor::get_member(PyObject* obj, void* closure)
|
||||||
|
{
|
||||||
|
return Py_None; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
int PyLinkedColor::set_member(PyObject* obj, PyObject* value, void* closure)
|
||||||
|
{
|
||||||
|
return 0; // TODO
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
#pragma once
|
||||||
|
#include "Common.h"
|
||||||
|
#include "Python.h"
|
||||||
|
|
||||||
|
class PyLinkedColor;
|
||||||
|
class UIDrawable; // forward declare for pointer
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
std::weak_ptr<UIDrawable> parent; // lifetime management: parent must still exist
|
||||||
|
int index; // specific to the parent class, which color is it?
|
||||||
|
sf::Color(*getter)();
|
||||||
|
void(*setter)(sf::Color);
|
||||||
|
} _PyLinkedColorData;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
_PyLinkedColorData data;
|
||||||
|
} PyLinkedColorObject;
|
||||||
|
|
||||||
|
class PyLinkedColor
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
_PyLinkedColorData data;
|
||||||
|
PyColor(_PyColorData); // private constructor / for operations transferring between C++ and Python
|
||||||
|
|
||||||
|
public:
|
||||||
|
PyLinkedColor(sf::Color (*)(), void (*)(sf::Color), std::weak_ptr<UIDrawable>, int);
|
||||||
|
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
|
||||||
|
bool alive(); // true if SELF_OWNED or parent still exists
|
||||||
|
PyObject* pyObject();
|
||||||
|
static PyLinkedColor fromPy(PyObject*);
|
||||||
|
static PyLinkedColor fromPy(PyLinkedColorObject*);
|
||||||
|
static PyObject* repr(PyObject*);
|
||||||
|
static Py_hash_t hash(PyObject*);
|
||||||
|
static int init(PyLinkedColorObject*, 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 PyLinkedColorType = {
|
||||||
|
.tp_name = "mcrfpy.LinkedColor",
|
||||||
|
.tp_basicsize = sizeof(PyLinkedColorObject),
|
||||||
|
.tp_itemsize = 0,
|
||||||
|
.tp_repr = PyLinkedColor::repr,
|
||||||
|
.tp_hash = PyLinkedColor::hash,
|
||||||
|
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||||
|
.tp_doc = PyDoc_STR("SFML Color Object - Linked to UIDrawable Field"),
|
||||||
|
.tp_getset = PyLinkedColor::getsetters,
|
||||||
|
.tp_init = (initproc)PyLinkedColor::init,
|
||||||
|
.tp_new = PyLinkedColor::pynew,
|
||||||
|
};
|
||||||
|
}
|
34
src/UI.h
34
src/UI.h
|
@ -8,6 +8,7 @@
|
||||||
#include "PyCallable.h"
|
#include "PyCallable.h"
|
||||||
#include "PyTexture.h"
|
#include "PyTexture.h"
|
||||||
#include "PyColor.h"
|
#include "PyColor.h"
|
||||||
|
#include "PyLinkedColor.h"
|
||||||
|
|
||||||
enum PyObjectsEnum : int
|
enum PyObjectsEnum : int
|
||||||
{
|
{
|
||||||
|
@ -594,33 +595,44 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: manually calling tp_alloc to create a PyColorObject seems like an antipattern
|
// TODO: manually calling tp_alloc to create a PyColorObject seems like an antipattern
|
||||||
PyTypeObject* colorType = &PyColorType;
|
/*
|
||||||
PyObject* pyColor = colorType->tp_alloc(colorType, 0);
|
PyTypeObject* colorType = &PyLinkedColorType;
|
||||||
|
PyObject* pyColor = colorType->tp_alloc(colorLinkedType, 0);
|
||||||
if (pyColor == NULL)
|
if (pyColor == NULL)
|
||||||
{
|
{
|
||||||
std::cout << "failure to allocate mcrfpy.Color / PyColorType" << std::endl;
|
std::cout << "failure to allocate mcrfpy.LinkedColor / PyLinkedColorType" << std::endl;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
PyColorObject* pyColorObj = reinterpret_cast<PyColorObject*>(pyColor);
|
PyColorObject* pyColorObj = reinterpret_cast<PyLinkedColorObject*>(pyColor);
|
||||||
|
*/
|
||||||
|
|
||||||
// fetch correct member data
|
// fetch correct member data
|
||||||
sf::Color color;
|
//sf::Color color;
|
||||||
|
sf::Color (*cgetter)();
|
||||||
|
void (*csetter)(sf::Color);
|
||||||
if (member_ptr == 0)
|
if (member_ptr == 0)
|
||||||
{
|
{
|
||||||
color = self->data->text.getFillColor();
|
//color = self->data->text.getFillColor();
|
||||||
//return Py_BuildValue("(iii)", color.r, color.g, color.b);
|
//return Py_BuildValue("(iii)", color.r, color.g, color.b);
|
||||||
|
csetter = &self->data->text.setFillColor;
|
||||||
|
cgetter = &self->data->text.getFillColor;
|
||||||
}
|
}
|
||||||
else if (member_ptr == 1)
|
else if (member_ptr == 1)
|
||||||
{
|
{
|
||||||
color = self->data->text.getOutlineColor();
|
//color = self->data->text.getOutlineColor();
|
||||||
//return Py_BuildValue("(iii)", color.r, color.g, color.b);
|
//return Py_BuildValue("(iii)", color.r, color.g, color.b);
|
||||||
|
csetter = &self->data->text.setOutlineColor;
|
||||||
|
cgetter = &self->data->text.getOutlineColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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);
|
//PyLinkedColor::fromPy(pyColorObj).set(color);
|
||||||
|
auto linkedcolor = PyLinkedColor(getter, setter, self->data, member_ptr);
|
||||||
|
//linkedcolor.set(color); // don't need to set a linked color!
|
||||||
|
|
||||||
return pyColor;
|
//return pyColor;
|
||||||
|
return linkedcolor.pyObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int PyUICaption_set_color_member(PyUICaptionObject* self, PyObject* value, void* closure)
|
static int PyUICaption_set_color_member(PyUICaptionObject* self, PyObject* value, void* closure)
|
||||||
|
@ -628,7 +640,7 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c
|
||||||
auto member_ptr = reinterpret_cast<long>(closure);
|
auto member_ptr = reinterpret_cast<long>(closure);
|
||||||
//TODO: this logic of (PyColor instance OR tuple -> sf::color) should be encapsulated for reuse
|
//TODO: this logic of (PyColor instance OR tuple -> sf::color) should be encapsulated for reuse
|
||||||
int r, g, b, a;
|
int r, g, b, a;
|
||||||
if (PyObject_IsInstance(value, (PyObject*)&PyColorType))
|
if (PyObject_IsInstance(value, (PyObject*)&PyLinkedColorType))
|
||||||
{
|
{
|
||||||
// get value from mcrfpy.Color instance
|
// get value from mcrfpy.Color instance
|
||||||
/*
|
/*
|
||||||
|
@ -638,7 +650,7 @@ static int PyUIDrawable_set_click(PyUIGridObject* self, PyObject* value, void* c
|
||||||
b = color->data->b;
|
b = color->data->b;
|
||||||
a = color->data->a;
|
a = color->data->a;
|
||||||
*/
|
*/
|
||||||
sf::Color c = PyColor::fromPy(value).get();
|
sf::Color c = PyLinkedColor::fromPy(value).get();
|
||||||
r = c.r; g = c.g; b = c.b; a = c.a;
|
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)
|
||||||
|
|
Loading…
Reference in New Issue