Expand effect engine & ui update (#445)

* update

* update

* update

* .

* .

* .

* update

* .

* .

* .

* .

* update

* .

* update

* .

* update

* update

* update

* update

* update

* update

* .

* update

* update

* update

* .

* .

* .

* Revert "."

This reverts commit 4dd6404b32.

* update

* .

* .

* .

* .

* .

* .

* .

* .

* .

* .

* .

* ...

* .

* .

* .

* .

* .

* .

* .

* .

* .

* update

* update

* update

* remove svg and pic

* colorpicker imgs to base64 to prevent delayed load if not cached

* fix json2python func

* update swirl with rgba

* add double swirl, tune default val in schema, update explanation

* adjust swirl.py

* FileObserver for config checks with timer as fallback (#4)
This commit is contained in:
brindosch
2017-07-30 14:36:23 +02:00
committed by GitHub
parent 5bd020a570
commit 8a794039cf
74 changed files with 3472 additions and 864 deletions

View File

@@ -26,17 +26,25 @@ PyMethodDef Effect::effectMethods[] = {
{"setImage" , Effect::wrapSetImage , METH_VARARGS, "Set a new image to process and determine new led colors."},
{"abort" , Effect::wrapAbort , METH_NOARGS, "Check if the effect should abort execution."},
{"imageShow" , Effect::wrapImageShow , METH_VARARGS, "set current effect image to hyperion core."},
{"imageCanonicalGradient", Effect::wrapImageCanonicalGradient, METH_VARARGS, ""},
{"imageLinearGradient" , Effect::wrapImageLinearGradient , METH_VARARGS, ""},
{"imageConicalGradient" , Effect::wrapImageConicalGradient , METH_VARARGS, ""},
{"imageRadialGradient" , Effect::wrapImageRadialGradient , METH_VARARGS, ""},
{"imageSolidFill" , Effect::wrapImageSolidFill , METH_VARARGS, ""},
{"imageDrawLine" , Effect::wrapImageDrawLine , METH_VARARGS, ""},
{"imageDrawPoint" , Effect::wrapImageDrawPoint , METH_VARARGS, ""},
{"imageDrawRect" , Effect::wrapImageDrawRect , METH_VARARGS, ""},
{"imageDrawPolygon" , Effect::wrapImageDrawPolygon , METH_VARARGS, ""},
{"imageDrawPie" , Effect::wrapImageDrawPie , METH_VARARGS, ""},
{"imageSetPixel" , Effect::wrapImageSetPixel , METH_VARARGS, "set pixel color of image"},
{"imageGetPixel" , Effect::wrapImageGetPixel , METH_VARARGS, "get pixel color of image"},
{"imageSave" , Effect::wrapImageSave , METH_NOARGS, "adds a new background image"},
{"imageMinSize" , Effect::wrapImageMinSize , METH_VARARGS, "sets minimal dimension of background image"},
{"imageMinSize" , Effect::wrapImageMinSize , METH_VARARGS, "sets minimal dimension of background image"},
{"imageWidth" , Effect::wrapImageWidth , METH_NOARGS, "gets image width"},
{"imageHeight" , Effect::wrapImageHeight , METH_NOARGS, "gets image height"},
{"imageCRotate" , Effect::wrapImageCRotate , METH_VARARGS, "rotate the coordinate system by given angle"},
{"imageCOffset" , Effect::wrapImageCOffset , METH_VARARGS, "Add offset to the coordinate system"},
{"imageCShear" , Effect::wrapImageCShear , METH_VARARGS, "Shear of coordinate system by the given horizontal/vertical axis"},
{"imageResetT" , Effect::wrapImageResetT , METH_NOARGS, "Resets all coords modifications (rotate,offset,shear)"},
{NULL, NULL, 0, NULL}
};
@@ -224,6 +232,7 @@ PyObject *Effect::json2python(const QJsonValue &jsonData) const
for (QJsonArray::iterator i = arrayData.begin(); i != arrayData.end(); ++i, ++index)
{
PyObject * obj = json2python(*i);
Py_INCREF(obj);
PyList_SetItem(list, index, obj);
Py_XDECREF(obj);
}
@@ -452,8 +461,76 @@ PyObject* Effect::wrapImageShow(PyObject *self, PyObject *args)
return Py_BuildValue("");
}
PyObject* Effect::wrapImageLinearGradient(PyObject *self, PyObject *args)
{
Effect * effect = getEffect();
PyObject* Effect::wrapImageCanonicalGradient(PyObject *self, PyObject *args)
int argCount = PyTuple_Size(args);
PyObject * bytearray = nullptr;
int startRX = 0;
int startRY = 0;
int startX = 0;
int startY = 0;
int endX, width = effect->_imageSize.width();
int endY, height = effect->_imageSize.height();
int spread = 0;
bool argsOK = false;
if ( argCount == 10 && PyArg_ParseTuple(args, "iiiiiiiiOi", &startRX, &startRY, &width, &height, &startX, &startY, &endX, &endY, &bytearray, &spread) )
{
argsOK = true;
}
if ( argCount == 6 && PyArg_ParseTuple(args, "iiiiOi", &startX, &startY, &endX, &endY, &bytearray, &spread) )
{
argsOK = true;
}
if (argsOK)
{
if (PyByteArray_Check(bytearray))
{
const int length = PyByteArray_Size(bytearray);
const unsigned arrayItemLength = 5;
if (length % arrayItemLength == 0)
{
QRect myQRect(startRX,startRY,width,height);
QLinearGradient gradient(QPoint(startX,startY), QPoint(endX,endY));
char * data = PyByteArray_AS_STRING(bytearray);
for (int idx=0; idx<length; idx+=arrayItemLength)
{
gradient.setColorAt(
((uint8_t)data[idx])/255.0,
QColor(
(uint8_t)(data[idx+1]),
(uint8_t)(data[idx+2]),
(uint8_t)(data[idx+3]),
(uint8_t)(data[idx+4])
));
}
gradient.setSpread(static_cast<QGradient::Spread>(spread));
effect->_painter->fillRect(myQRect, gradient);
return Py_BuildValue("");
}
else
{
PyErr_SetString(PyExc_RuntimeError, "Length of bytearray argument should multiple of 5");
return nullptr;
}
}
else
{
PyErr_SetString(PyExc_RuntimeError, "No bytearray properly defined");
return nullptr;
}
}
return nullptr;
}
PyObject* Effect::wrapImageConicalGradient(PyObject *self, PyObject *args)
{
Effect * effect = getEffect();
@@ -527,30 +604,30 @@ PyObject* Effect::wrapImageRadialGradient(PyObject *self, PyObject *args)
int argCount = PyTuple_Size(args);
PyObject * bytearray = nullptr;
int centerX, centerY, radius, focalX, focalY, focalRadius;
int centerX, centerY, radius, focalX, focalY, focalRadius, spread;
int startX = 0;
int startY = 0;
int width = effect->_imageSize.width();
int height = effect->_imageSize.height();
bool argsOK = false;
if ( argCount == 11 && PyArg_ParseTuple(args, "iiiiiiiiiiO", &startX, &startY, &width, &height, &centerX, &centerY, &radius, &focalX, &focalY, &focalRadius, &bytearray) )
if ( argCount == 12 && PyArg_ParseTuple(args, "iiiiiiiiiiOi", &startX, &startY, &width, &height, &centerX, &centerY, &radius, &focalX, &focalY, &focalRadius, &bytearray, &spread) )
{
argsOK = true;
}
if ( argCount == 8 && PyArg_ParseTuple(args, "iiiiiiiO", &startX, &startY, &width, &height, &centerX, &centerY, &radius, &bytearray) )
}
if ( argCount == 9 && PyArg_ParseTuple(args, "iiiiiiiOi", &startX, &startY, &width, &height, &centerX, &centerY, &radius, &bytearray, &spread) )
{
argsOK = true;
focalX = centerX;
focalY = centerY;
focalRadius = radius;
}
if ( argCount == 7 && PyArg_ParseTuple(args, "iiiiiiO", &centerX, &centerY, &radius, &focalX, &focalY, &focalRadius, &bytearray) )
if ( argCount == 8 && PyArg_ParseTuple(args, "iiiiiiOi", &centerX, &centerY, &radius, &focalX, &focalY, &focalRadius, &bytearray, &spread) )
{
argsOK = true;
}
if ( argCount == 4 && PyArg_ParseTuple(args, "iiiO", &centerX, &centerY, &radius, &bytearray) )
if ( argCount == 5 && PyArg_ParseTuple(args, "iiiOi", &centerX, &centerY, &radius, &bytearray, &spread) )
{
argsOK = true;
focalX = centerX;
@@ -581,7 +658,7 @@ PyObject* Effect::wrapImageRadialGradient(PyObject *self, PyObject *args)
));
}
//gradient.setSpread(QGradient::ReflectSpread);
gradient.setSpread(static_cast<QGradient::Spread>(spread));
effect->_painter->fillRect(myQRect, gradient);
return Py_BuildValue("");
@@ -601,6 +678,160 @@ PyObject* Effect::wrapImageRadialGradient(PyObject *self, PyObject *args)
return nullptr;
}
PyObject* Effect::wrapImageDrawPolygon(PyObject *self, PyObject *args)
{
Effect * effect = getEffect();
PyObject * bytearray = nullptr;
int argCount = PyTuple_Size(args);
int r, g, b;
int a = 255;
bool argsOK = false;
if ( argCount == 5 && PyArg_ParseTuple(args, "Oiiii", &bytearray, &r, &g, &b, &a) )
{
argsOK = true;
}
if ( argCount == 4 && PyArg_ParseTuple(args, "Oiii", &bytearray, &r, &g, &b) )
{
argsOK = true;
}
if (argsOK)
{
if (PyByteArray_Check(bytearray))
{
int length = PyByteArray_Size(bytearray);
if (length % 2 == 0)
{
QVector <QPoint> points;
char * data = PyByteArray_AS_STRING(bytearray);
for (int idx=0; idx<length; idx+=2)
{
points.append(QPoint((int)(data[idx]),(int)(data[idx+1])));
}
QPainter * painter = effect->_painter;
QPen oldPen = painter->pen();
QPen newPen(QColor(r,g,b,a));
painter->setPen(newPen);
painter->setBrush(QBrush(QColor(r,g,b,a), Qt::SolidPattern));
painter->drawPolygon(points);
painter->setPen(oldPen);
return Py_BuildValue("");
}
else
{
PyErr_SetString(PyExc_RuntimeError, "Length of bytearray argument should multiple of 2");
return nullptr;
}
}
else
{
PyErr_SetString(PyExc_RuntimeError, "Argument 1 is not a bytearray");
return nullptr;
}
}
return nullptr;
}
PyObject* Effect::wrapImageDrawPie(PyObject *self, PyObject *args)
{
Effect * effect = getEffect();
PyObject * bytearray = nullptr;
QString brush;
int argCount = PyTuple_Size(args);
int radius, centerX, centerY;
int startAngle = 0;
int spanAngle = 360;
int r = 0;
int g = 0;
int b = 0;
int a = 255;
bool argsOK = false;
if ( argCount == 9 && PyArg_ParseTuple(args, "iiiiiiiii", &centerX, &centerY, &radius, &startAngle, &spanAngle, &r, &g, &b, &a) )
{
argsOK = true;
}
if ( argCount == 8 && PyArg_ParseTuple(args, "iiiiiiii", &centerX, &centerY, &radius, &startAngle, &spanAngle, &r, &g, &b) )
{
argsOK = true;
}
if ( argCount == 7 && PyArg_ParseTuple(args, "iiiiisO", &centerX, &centerY, &radius, &startAngle, &spanAngle, &brush, &bytearray) )
{
argsOK = true;
}
if ( argCount == 5 && PyArg_ParseTuple(args, "iiisO", &centerX, &centerY, &radius, &brush, &bytearray) )
{
argsOK = true;
}
if (argsOK)
{
QPainter * painter = effect->_painter;
startAngle = std::max(std::min(startAngle,360),0);
spanAngle = std::max(std::min(spanAngle,360),-360);
if( argCount == 7 || argCount == 5 )
{
a = 0;
if (PyByteArray_Check(bytearray))
{
int length = PyByteArray_Size(bytearray);
if (length % 5 == 0)
{
QConicalGradient gradient(QPoint(centerX,centerY), startAngle);
char * data = PyByteArray_AS_STRING(bytearray);
for (int idx=0; idx<length; idx+=5)
{
gradient.setColorAt(
((uint8_t)data[idx])/255.0,
QColor(
(uint8_t)(data[idx+1]),
(uint8_t)(data[idx+2]),
(uint8_t)(data[idx+3]),
(uint8_t)(data[idx+4])
));
}
painter->setBrush(gradient);
return Py_BuildValue("");
}
else
{
PyErr_SetString(PyExc_RuntimeError, "Length of bytearray argument should multiple of 5");
return nullptr;
}
}
else
{
PyErr_SetString(PyExc_RuntimeError, "Last argument is not a bytearray");
return nullptr;
}
}
else
{
painter->setBrush(QBrush(QColor(r,g,b,a), Qt::SolidPattern));
}
QPen oldPen = painter->pen();
QPen newPen(QColor(r,g,b,a));
painter->setPen(newPen);
painter->drawPie(centerX - radius, centerY - radius, centerX + radius, centerY + radius, startAngle * 16, spanAngle * 16);
painter->setPen(oldPen);
return Py_BuildValue("");
}
return nullptr;
}
PyObject* Effect::wrapImageSolidFill(PyObject *self, PyObject *args)
{
Effect * effect = getEffect();
@@ -682,6 +913,40 @@ PyObject* Effect::wrapImageDrawLine(PyObject *self, PyObject *args)
return nullptr;
}
PyObject* Effect::wrapImageDrawPoint(PyObject *self, PyObject *args)
{
Effect * effect = getEffect();
int argCount = PyTuple_Size(args);
int r, g, b, x, y;
int a = 255;
int thick = 1;
bool argsOK = false;
if ( argCount == 7 && PyArg_ParseTuple(args, "iiiiiii", &x, &y, &thick, &r, &g, &b, &a) )
{
argsOK = true;
}
if ( argCount == 6 && PyArg_ParseTuple(args, "iiiiii", &x, &y, &thick, &r, &g, &b) )
{
argsOK = true;
}
if (argsOK)
{
QPainter * painter = effect->_painter;
QPen oldPen = painter->pen();
QPen newPen(QColor(r,g,b,a));
newPen.setWidth(thick);
painter->setPen(newPen);
painter->drawPoint(x, y);
painter->setPen(oldPen);
return Py_BuildValue("");
}
return nullptr;
}
PyObject* Effect::wrapImageDrawRect(PyObject *self, PyObject *args)
{
@@ -801,6 +1066,62 @@ PyObject* Effect::wrapImageHeight(PyObject *self, PyObject *args)
return Py_BuildValue("i", effect->_imageSize.height());
}
PyObject* Effect::wrapImageCRotate(PyObject *self, PyObject *args)
{
Effect * effect = getEffect();
int argCount = PyTuple_Size(args);
int angle;
if ( argCount == 1 && PyArg_ParseTuple(args, "i", &angle ) )
{
angle = std::max(std::min(angle,360),0);
effect->_painter->rotate(angle);
return Py_BuildValue("");
}
return nullptr;
}
PyObject* Effect::wrapImageCOffset(PyObject *self, PyObject *args)
{
Effect * effect = getEffect();
int offsetX = 0;
int offsetY = 0;
int argCount = PyTuple_Size(args);
if ( argCount == 2 )
{
PyArg_ParseTuple(args, "ii", &offsetX, &offsetY );
}
effect->_painter->translate(QPoint(offsetX,offsetY));
return Py_BuildValue("");
}
PyObject* Effect::wrapImageCShear(PyObject *self, PyObject *args)
{
Effect * effect = getEffect();
int sh,sv;
int argCount = PyTuple_Size(args);
if ( argCount == 2 && PyArg_ParseTuple(args, "ii", &sh, &sv ))
{
effect->_painter->shear(sh,sv);
return Py_BuildValue("");
}
return nullptr;
}
PyObject* Effect::wrapImageResetT(PyObject *self, PyObject *args)
{
Effect * effect = getEffect();
effect->_painter->resetTransform();
return Py_BuildValue("");
}
Effect * Effect::getEffect()
{
// extract the module from the runtime

View File

@@ -58,18 +58,25 @@ private:
static PyObject* wrapSetImage (PyObject *self, PyObject *args);
static PyObject* wrapAbort (PyObject *self, PyObject *args);
static PyObject* wrapImageShow (PyObject *self, PyObject *args);
static PyObject* wrapImageCanonicalGradient(PyObject *self, PyObject *args);
static PyObject* wrapImageLinearGradient (PyObject *self, PyObject *args);
static PyObject* wrapImageConicalGradient (PyObject *self, PyObject *args);
static PyObject* wrapImageRadialGradient (PyObject *self, PyObject *args);
static PyObject* wrapImageSolidFill (PyObject *self, PyObject *args);
static PyObject* wrapImageDrawLine (PyObject *self, PyObject *args);
static PyObject* wrapImageDrawPoint (PyObject *self, PyObject *args);
static PyObject* wrapImageDrawRect (PyObject *self, PyObject *args);
static PyObject* wrapImageDrawPolygon (PyObject *self, PyObject *args);
static PyObject* wrapImageDrawPie (PyObject *self, PyObject *args);
static PyObject* wrapImageSetPixel (PyObject *self, PyObject *args);
static PyObject* wrapImageGetPixel (PyObject *self, PyObject *args);
static PyObject* wrapImageSave (PyObject *self, PyObject *args);
static PyObject* wrapImageMinSize (PyObject *self, PyObject *args);
static PyObject* wrapImageWidth (PyObject *self, PyObject *args);
static PyObject* wrapImageHeight (PyObject *self, PyObject *args);
static PyObject* wrapImageCRotate (PyObject *self, PyObject *args);
static PyObject* wrapImageCOffset (PyObject *self, PyObject *args);
static PyObject* wrapImageCShear (PyObject *self, PyObject *args);
static PyObject* wrapImageResetT (PyObject *self, PyObject *args);
static Effect * getEffect();
#if PY_MAJOR_VERSION >= 3