fill() colours all children of SVG

Hi all, I'm trying to randomly colour the children of an SVG, similarly to the getChild example found here.

My issue is that the call to fill() changes the colour of all child elements instead of the one intended. I have included the xml from the svg file. This was created in illustrator with these settings:

SVG OUTPUT SETTINGS:
SVG Profiles: SVG 1.1
Type: Convert to Outline
Image Location: Embed

Advanced Options:
CSS Properties: Presentation Attributes
Decimal Places: 1
Encoding Unicode(UTF-8)
Responsive

I have tried svg 1.0, I've tried having the pieces(children) on indiviual layers or all on one layer and nothing seems to make a difference. My best guess is that it is an svg output issue.

Any help is appreciated. Thankyou.

SVG xml: http://pastebin.com/exjabwAE

Code:

PShape img, meatus, head, dGlans, mGlans, fGlans, tBones, tMeat, tongue, 
  lips, teethDirt, teeth, gums, uvula, dThroat, mThroat, fThroat, mouthInner;
PVector pos;

void setup() { 
  size(800, 800);
  pos = new PVector(0, 0);
  img = loadShape("WholeImageIII.svg");

  meatus     = img.getChild("dickSlit");
  head       = img.getChild("dickhead");
  dGlans     = img.getChild("deepGlans");
  mGlans     = img.getChild("midGlans");
  fGlans     = img.getChild("foreGlans");
  tBones     = img.getChild("toungueBones");
  tMeat      = img.getChild("tongueMeat");
  tongue     = img.getChild("tongue");
  lips       = img.getChild("lips");
  teethDirt  = img.getChild("teethDirt");
  teeth      = img.getChild("teeth");
  gums       = img.getChild("gums");
  uvula      = img.getChild("uvula");
  dThroat    = img.getChild("deepThroat");
  mThroat    = img.getChild("midThroat");
  fThroat    = img.getChild("foreThroat");
  mouthInner = img.getChild("mouthInner");
}

void draw() { 
  background(255);
  shape(img, pos.x, pos.y); //draw image

  if (mousePressed) { //randomises the colour of the children
    lips.disableStyle();
    fill(random(255), random(255), random(255));
    noStroke();
    shape(lips, pos.x, pos.y);

    head.disableStyle();
    fill(random(255), random(255), random(255));
    noStroke();
    shape(head, pos.x, pos.y);

    teeth.disableStyle();
    fill(random(255), random(255), random(255));
    noStroke();
    shape(teeth, pos.x, pos.y);

    tongue.disableStyle();
    fill(random(255), random(255), random(255));
    noStroke();
    shape(tongue, pos.x, pos.y);
  }
  shape(mouthInner, pos.x, pos.y);
  shape(fThroat, pos.x, pos.y);
  shape(mThroat, pos.x, pos.y);
  shape(dThroat, pos.x, pos.y);
  shape(uvula, pos.x, pos.y);
  shape(gums, pos.x, pos.y);
  shape(teeth, pos.x, pos.y);
  shape(teethDirt, pos.x, pos.y);
  shape(lips, pos.x, pos.y);
  shape(tongue, pos.x, pos.y);
  shape(tMeat, pos.x, pos.y);
  shape(tBones, pos.x, pos.y);
  shape(fGlans, pos.x, pos.y);
  shape(mGlans, pos.x, pos.y);
  shape(dGlans, pos.x, pos.y);
  shape(head, pos.x, pos.y);
  shape(meatus, pos.x, pos.y); //draws the child
}

void keyPressed() { 
  meatus.enableStyle(); //reenables the css stylesheet
  head.enableStyle();
  dGlans.enableStyle();
  mGlans.enableStyle();
  fGlans .enableStyle();
  tBones.enableStyle();
  tMeat .enableStyle();
  tongue.enableStyle();
  lips .enableStyle();
  teethDirt.enableStyle();
  teeth.enableStyle();
  gums.enableStyle();
  uvula.enableStyle();
  dThroat.enableStyle();
  mThroat.enableStyle();
  fThroat.enableStyle();
  mouthInner.enableStyle();
}

Answers

  • edited February 2017

    @SnailPropulsionLabs --

    Here is an example of a previous sketch that loops through the children of an SVG and assigns each one a random color:

    The key thing in this approach is loop over the range for( int i=0; i<shape.getChildCount(); i++ ) and each time access shape.getChild(i) before rendering each shape with a given fill.

  • Thanks for the suggestion, I tried to implement that but it still appears to be applying each colour to all children of the svg.

    I looked at the xml of the bot.svg image and then re-output my image to try and match the path structure as closely as possible hoping that was the difference, no luck. New xml here.

    It looks like there is multicoloured flashes so all the colours are being applied, just to every child on every loop instead of selectively.

    Current sketch version:

    PShape img, meatus, head, dGlans, mGlans, fGlans, tBones, tMeat, tongue, temp, 
      lips, teethDirt, teeth, gums, uvula, dThroat, mThroat, fThroat, mouthInner;
    PVector pos;
    boolean clicked = false;
    
    void setup() { 
      size(800, 800);
      pos = new PVector(0, 0);
      img = loadShape("WholeImageIV.svg");
    
      meatus     = img.getChild("dickSlit");
      head       = img.getChild("dickhead");
      dGlans     = img.getChild("deepGlans");
      mGlans     = img.getChild("midGlans");
      fGlans     = img.getChild("foreGlans");
      tBones     = img.getChild("toungueBones");
      tMeat      = img.getChild("tongueMeat");
      tongue     = img.getChild("tongue");
      lips       = img.getChild("lips");
      teethDirt  = img.getChild("teethDirt");
      teeth      = img.getChild("teeth");
      gums       = img.getChild("gums");
      uvula      = img.getChild("uvula");
      dThroat    = img.getChild("deepThroat");
      mThroat    = img.getChild("midThroat");
      fThroat    = img.getChild("foreThroat");
      mouthInner = img.getChild("mouthInner");
    }
    
    void draw() { 
      background(255);
      shape(img, pos.x, pos.y); //draw image
      if (clicked) img.disableStyle();
    
      if (mousePressed && !clicked) { //randomises the colour of the children
        clicked = !clicked;
        for (int i = 0; i < img.getChildCount(); i++)
        {      
    
          temp = img.getChild(i);
          fill(random(255), random(255), random(255));
          shape(temp, 0, 0);
        }
      }
    }
    
    void mouseReleased() {
      clicked = !clicked;
    }
    
    void keyPressed() { 
      img.enableStyle(); //reenables the css stylesheet
    }
    
  • I've found that it seems to be the last colour called before the mouse is released is then used to colour the entire image.

    In the new version below i've tried to separate concerns by having individual color variables for each child and changing the fill using them but i'm still getting the colour overlap issue as before. So I now know this isn't an svg issue, it seems to be a loop or order issue which still has me perplexed as to what i've done wrong.

    PShape img, meatus, head, dGlans, mGlans, fGlans, tBones, tMeat, tongue, temp, 
      lips, teethDirt, teeth, gums, uvula, dThroat, mThroat, fThroat, mouthInner;
    PVector pos;
    boolean clicked = false;
    color cMeatus, cHead, cDGlans, cMGlans, cFGlans, cTBones, cTMeat, cTongue, 
      cLips, cTeethDirt, cTeeth, cGums, cUvula, cDThroat, cMThroat, cFThroat, cMouthInner;
    
    void setup() { 
      size(800, 800);
      pos = new PVector(0, 0);
      img = loadShape("WholeImageIV.svg");
    
      meatus     = img.getChild("dickSlit");
      head       = img.getChild("dickhead");
      dGlans     = img.getChild("deepGlans");
      mGlans     = img.getChild("midGlans");
      fGlans     = img.getChild("foreGlans");
      tBones     = img.getChild("toungueBones");
      tMeat      = img.getChild("tongueMeat");
      tongue     = img.getChild("tongue");
      lips       = img.getChild("lips");
      teethDirt  = img.getChild("teethDirt");
      teeth      = img.getChild("teeth");
      gums       = img.getChild("gums");
      uvula      = img.getChild("uvula");
      dThroat    = img.getChild("deepThroat");
      mThroat    = img.getChild("midThroat");
      fThroat    = img.getChild("foreThroat");
      mouthInner = img.getChild("mouthInner");
    
      //frameRate(5);
    }
    
    void draw() { 
      background(100);
      img.enableStyle();
      shape(img, 0, 0);
      noStroke();
    
      img.disableStyle();
      if (keyPressed) interaction(key);
    
      shape(mouthInner, pos.x, pos.y);
    
      shape(tongue, pos.x, pos.y);
    
    
      println("M: " + cMouthInner + " T: " + cTongue);
    }
    
    color colourChange() { 
      println("colour changed");
      return color(random(255), random(255), random(255));
    }
    
    void interaction(int section) { 
      int tempSection = section;
    
      switch(tempSection) {
    
      case '1':
        mouthInner.disableStyle();
        fill(cMouthInner = colourChange());
        shape(mouthInner, pos.x, pos.y);
    
      case '2':
        tongue.disableStyle();
        fill(cTongue = colourChange());
        shape(tongue, pos.x, pos.y);
      }
    }
    
  • edited March 2017 Answer ✓

    Solution: Make it object oriented, then the objects hold their own colour information. Credit goes to Wootai on reddit for the oop suggestion.

    Main Tab:

    PShape source;
    PVector pos;
    boolean clicked = false;
    child meatus, head, dGlans, mGlans, fGlans, tBones, tMeat, tongue, 
      lips, teethDirt, teeth, gums, uvula, dThroat, mThroat, fThroat, mouthInner;
    
    void setup() { 
      size(800, 800);
      pos = new PVector(0, 0);
      source = loadShape("WholeImageIV.svg");
    
      meatus     = new child(source.getChild("dickSlit"), pos, color(158, 20, 80));
      head       = new child(source.getChild("dickhead"), pos, color(237, 30, 121));
      dGlans     = new child(source.getChild("DeepGlans"), pos, color(46, 49, 146));
      mGlans     = new child(source.getChild("midGlans"), pos, color(0, 113, 188));
      fGlans     = new child(source.getChild("ForeGlans"), pos, color(41, 171, 226));
      tBones     = new child(source.getChild("toungueBones"), pos, color(140, 198, 63));
      tMeat      = new child(source.getChild("tongueMeat"), pos, color(237, 30, 121));
      tongue     = new child(source.getChild("tongue"), pos, color(158, 20, 80));
      lips       = new child(source.getChild("lips"), pos, color(41, 171, 226));
      teethDirt  = new child(source.getChild("teethDirt"), pos, color(171, 128, 61));
      teeth      = new child(source.getChild("teeth"), pos, color(227, 170, 81));
      gums       = new child(source.getChild("gums"), pos, color(193, 39, 45));
      uvula      = new child(source.getChild("uvula"), pos, color(158, 20, 80));
      dThroat    = new child(source.getChild("deepThroat"), pos, color(102, 13, 52));
      mThroat    = new child(source.getChild("midThroat"), pos, color(158, 19, 78));
      fThroat    = new child(source.getChild("foreThroat"), pos, color(201, 26, 53));
      mouthInner = new child(source.getChild("mouthInner"), pos, color(237, 30, 121));
    
      noLoop();
      noStroke();
    }
    
    void draw() { 
      background(100);
    
      mouthInner.draw();
      fThroat.draw();
      mThroat.draw();  
      dThroat.draw();   
      uvula.draw();     
      gums.draw();
      teeth.draw();
      teethDirt.draw();
      lips.draw();
      tongue.draw();
      tMeat.draw(); 
      tBones.draw(); 
      fGlans.draw();
      mGlans.draw(); 
      dGlans.draw(); 
      head.draw();  
      meatus.draw();
    }
    
    void keyReleased() {
      interaction(key);
    }
    
    void interaction(int section) {
      switch(section) {
    
      case '1':
        println("1");
        mouthInner.colourChange();
        redraw();
        break;
    
      case '2':
        fThroat.colourChange();
        redraw();
        break;
    
      case '3':
        mThroat.colourChange();  
        redraw();
        break;
    
      case '4':
        dThroat.colourChange();   
        redraw();
        break;
    
      case '5':
        uvula.colourChange();     
        redraw();
        break;
    
      case '6':
        gums.colourChange();
        redraw();
        break;
    
      case '7':
        teeth.colourChange();
        redraw();
        break;
    
      case '8':
        teethDirt.colourChange();
        redraw();
        break;
    
      case '9':
        lips.colourChange();
        redraw();
        break;
    
      case '0':
        tongue.colourChange();
        redraw();
        break;
    
      case 'q':
        tMeat.colourChange();
        redraw();
        break;
    
      case 'w':
        tBones.colourChange();
        redraw();
        break;
    
      case 'e':
        fGlans.colourChange();
        redraw();
        break;
    
      case 'r':
        mGlans.colourChange();
        redraw();
        break;
    
      case 't':
        dGlans.colourChange();
        redraw();
        break;
    
      case 'y':
        head.colourChange();
        redraw();
        break;
    
      case 'u':
        meatus.colourChange();
        redraw();
        break;
      }
    }
    

    Child Tab:

    class child 
    {
      PShape child;
      PVector pos;
      color c;
    
      child(PShape child, PVector pos, color c) 
      {
        this.pos = new PVector(pos.x, pos.y);
        this.c = c;
        this.child = child;
      }
    
      void draw() {
        child.disableStyle();
        fill(c);
        println("before");
        shape(child, pos.x, pos.y);
        println("after");
      }
    
      void colourChange() {
        c = color(random(255), random(255), random(255));
      }
    }
    
Sign In or Register to comment.