Drawable Colour


#1

Can I change the colour of a drawable made from SVG? Or is there a way to draw it tinted?

Bruce


#2

Here you go.

Drawable* d = ...; DrawableFinder df; DrawableShape* ds = df.findShape(d, "nameofshape"); if (ds) ds->setFill(whatever);

[code]
/**
*

  • Portions Copyright © 2013 Voidware Ltd. All Rights Reserved.
  • This file contains Original Code and/or Modifications of Original Code as
  • defined in and that are subject to the Voidware Public Source Licence version
  • 1.0 (the ‘Licence’). You may not use this file except in compliance with the
  • Licence or with expressly written permission from Voidware. Please obtain a
  • copy of the Licence at http://www.voidware.com/legal/vpsl1.txt and read it
  • before using this file.
  • The Original Code and all software distributed under the Licence are
  • distributed on an ‘AS IS’ basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
  • OR IMPLIED, AND VOIDWARE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING
  • WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  • PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  • Please see the Licence for the specific language governing rights and
  • limitations under the Licence.
    */

#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.


#3

Awesome, thanks Hugh.

Edit: (your code reminds me of OpenSceneGraph’s per-node callbacks. Nice stuff!)