Can I change the colour of a drawable made from SVG? Or is there a way to draw it tinted?
Bruce
Can I change the colour of a drawable made from SVG? Or is there a way to draw it tinted?
Bruce
Here you go.
Drawable* d = ...;
DrawableFinder df;
DrawableShape* ds = df.findShape(d, "nameofshape");
if (ds)
ds->setFill(whatever);
[code]
/**
*
#ifndef drawwalk_h
#define drawwalk_h
#include “…/JuceLibraryCode/JuceHeader.h”
#include
typedef bool DWCallback(Drawable* d, void* ctx);
class DrawableWalker
{
public:
DrawableWalker() { _init(); }
DrawableWalker(Drawable* d) { _init(); _d = d; }
void drawable(Drawable* d) { _d = d; }
void setShapeCb(DWCallback* cb, void* ctx)
{
_shapeCb = cb;
_shapeCbCtx = ctx;
}
void setCompositeCb(DWCallback* cb, void* ctx)
{
_compositeCb = cb;
_compositeCbCtx = ctx;
}
void walk()
{
_walk(_d);
}
private:
bool _walk(Drawable* d)
{
bool res = true;
if (d)
{
if (_shapeCb)
{
DrawableShape* ds = dynamic_cast<DrawableShape*>(d);
if (ds)
res = (*_shapeCb)(d, _shapeCbCtx);
}
if (_compositeCb)
{
DrawableComposite* dc = dynamic_cast<DrawableComposite*>(d);
if (dc)
res = (*_compositeCb)(d, _compositeCbCtx);
}
if (res)
{
int n = d->getNumChildComponents();
for (int i = 0; i < n; ++i)
{
Drawable* c = (Drawable*)d->getChildComponent(i);
res = _walk(c);
if (!res) break;
}
}
}
return res;
}
void _init()
{
_d = 0;
_shapeCb = 0;
_shapeCbCtx = 0;
_compositeCb = 0;
_compositeCbCtx = 0;
}
Drawable* _d;
DWCallback* _shapeCb;
void* _shapeCbCtx;
DWCallback* _compositeCb;
void* _compositeCbCtx;
};
class DrawableFinder
{
public:
typedef std::vector<Drawable*> drawListT;
DrawableFinder() { _init(); }
DrawableShape* findShape(Drawable* d, const String& name)
{
_shape = 0;
_shapeName = name;
_w.drawable(d);
_w.walk();
return _shape;
}
Drawable* find(Drawable* d, const String& name)
{
// find any
_shape = 0;
_shapeName = name;
_composite = 0;
_compositeName = name;
_w.drawable(d);
_w.walk();
if (_shape)
return _shape;
return _composite;
}
void findAll(Drawable* d, drawListT& list)
{
_drawList = &list;
_w.drawable(d);
_w.walk();
_drawList = 0;
}
private:
void _init()
{
_drawList = 0;
_w.setShapeCb(_shapeCallback, this);
_w.setCompositeCb(_compositeCallback, this);
}
bool allCallback(Drawable* d)
{
bool res = false;
if (_drawList)
{
String name = d->getName();
const char* p = name.getCharPointer();
// allow name if all alpha
if (p && *p)
{
// start with upper case
bool ok = *p >= 'A' && *p <= 'Z';
if (ok)
{
_drawList->push_back(d);
res = true;
}
}
}
return res;
}
bool shapeCallback(Drawable* d)
{
bool res = true; // continue;
if (!allCallback(d) &&
_shapeName.length() > 0 && d->getName() == _shapeName)
{
// found it!
_shape = (DrawableShape*)d;
res = false; // stop!
}
return res;
}
bool compositeCallback(Drawable* d)
{
bool res = true; // continue;
if (!allCallback(d) &&
_compositeName.length() > 0 && d->getName() == _compositeName)
{
_composite = (DrawableComposite*)d;
res = false; // stop!
}
return res;
}
static bool _shapeCallback(Drawable* d, void* ctx)
{
DrawableFinder* self = (DrawableFinder*)ctx;
return self->shapeCallback(d);
}
static bool _compositeCallback(Drawable* d, void* ctx)
{
DrawableFinder* self = (DrawableFinder*)ctx;
return self->compositeCallback(d);
}
String _compositeName;
DrawableComposite* _composite;
String _shapeName;
DrawableShape* _shape;
DrawableWalker _w;
drawListT* _drawList;
};
#endif // drawwalk_h[/code]
What I do is edit my SVGs “id=” field to a known name, then find them at runtime.
Awesome, thanks Hugh.
Edit: (your code reminds me of OpenSceneGraph’s per-node callbacks. Nice stuff!)