Exit loop on mousePressed

edited August 2014 in Library Questions

I am trying to create a RGB controller program that sends values to an Arduiono Uno to set the colors of an LED strip. The app originally just took the RGB value of the pixel the mouse was clicked on and then sent it to the Arduino. I am now trying to add other modes besides just color selection mode (fade color mode, random color mode, etc).

The issue I am having is that I cannot find a way to break away from my rgb fade function without waiting till it finished the loop. I understand why this is happening with my code but do not know how to have it so that when the mouse is press it breaks from the loop right away. I have looked for example code to achieve this but nothing is working when I apply it to my program.

Any suggestions on this or any other aspect of the code would be appreciated. I have tried to learn many programming languages in the past but typically give up on them do to how complicated it is to create the GUI I want.

import processing.serial.*;  //import serial library
Serial port;   //Create variable for port to represent COM port for communication

//Create new image object for background image
PImage img;    

//used in draw() if loop to determine what mode the program is currently in 
boolean manualMode = true; 
boolean fadeMode = false;

//Variable to hold r,g,b colors
color c;                

//Need float variable for each color to pull r,g,b reading from pixel
float redValue;         
float greenValue;
float blueValue;

//Used in rgbFormat to turn rgb values from get from a float to a string
//so it can be sent as a string over the Serial Port
String red;
String green;
String blue;


//used for fade functions
int [] fadeValues = new int [3];        
String [] fadeString = new String [3];    

int delayTime = 10;



void setup() {

  //Create window to size of background and load background image into window
  size(730, 483);                 
  img = loadImage("beta_controller.jpg");
  image(img, 0, 0);


  //Opens up communications to COM port at 9600 BAUD rate
  println(Serial.list());
  //port = new Serial(this, Serial.list()[2], 57600);
}

void draw() {

  if (manualMode = true) {
    //Create box to show current color.
    //Current color is the color of the last pixel clicked on.
    fill(c);
    rect(22, 436, 680, 32);

    readColor();
    rgbFormat();
    setColor(red, green, blue);
  }

  if (fadeMode == true ) {


    rgbFade();
  }
}



void mousePressed() {
  if ((mouseX > 22) && (mouseX < 22 + 120)
    && (mouseY > 79) && (mouseY < 79 + 75)) {
    manualMode = true;
    fadeMode = false;

    println("Manual Mode Set");
  }
  else if ((mouseX > 167) && (mouseX < 167 + 120)
    && (mouseY > 79) && (mouseY < 79 + 75)) {
    manualMode = false;
    fadeMode = true;

    println("Auto Fade Mode Set");
  }
  else {
    println("ERROR with mousePressed");
  }
}     

//If the mouse is pressed down it gets the color of the pixel the curson is on.
//As long as the mouse is pressed it keeps updating. 
void readColor() {
  if ((mousePressed == true) && (mouseX > 90) && (mouseX < 90 + 540)
    && (mouseY > 168) && (mouseY < 168 + 256)
    || (mousePressed == true) && (mouseX > 22) && (mouseX < 22 + 56)
    && (mouseY > 168) && (mouseY < 168 + 256)
    || (mousePressed == true) && (mouseX > 650 ) && (mouseX < 650 + 56)
    && (mouseY > 168) && (mouseY < 168 + 256)) {
    //Assign R,G,B colors of selected pixel to c variable. 
    c = get(pmouseX, pmouseY);

    //Gets R,G,B values of pixel
    redValue = red(c);
    greenValue = green(c);
    blueValue = blue(c);


    println("red " + redValue + "  green " + greenValue
      + "  blue " + blueValue);
  }
}

//This function gets the rgb values ready to be printed to the serial port.
//It takes the float values returned from the get() function
//then turns them into int to cut of the .0 part of the float.
//Then it converts the values to str to be sent over the serial port.
//everything sent over the serial port is sent as a string.
void rgbFormat() {

  int redHolder = int(redValue);
  int greenHolder = int(greenValue);
  int blueHolder = int(blueValue);

  red = str(redHolder);
  green = str(greenHolder);
  blue = str(blueHolder);
}


void setColor(String red, String green, String blue) {
  //port.write('c' + red + 'c' + green + 'c' + blue);
}


//This is a fadeFunction I found online.
void rgbFade() {

  // Start off with red.
  fadeValues[0] = 255;
  fadeValues[1] = 0;
  fadeValues[2] = 0;  

  // Choose the colors to increment and decrement.while(stop == false){


  for (int decColor = 0; decColor < 3; decColor += 1) {

    int incColor = decColor == 2 ? 0 : decColor + 1;


    // cross-fade the two colors.

    for (int i = 0; i < 255; i += 1) {


      fadeValues[decColor] -= 1;
      fadeValues[incColor] += 1;

      fadeString [0] = str(fadeValues[0]);
      fadeString [1] = str(fadeValues[1]);
      fadeString [2] = str(fadeValues[2]);


      setColor(fadeString[0], fadeString[1], fadeString[2]);

      println("red " + fadeString[0] + "  green " + fadeString[1]
        + "  blue " + fadeString[2]);  

      delay(delayTime);
    }
  }
}

Answers

  • edited August 2014

    inside of ur loop

    if(mousePressed){
       fadeMode=false; // or what ever it was that stoped the fade thingie
       break; // exits loop
     }
    

    also i belive the delay() is buged i can't remember atm why it should not be used but i remember having issues with it maybe som 1 else can refresh my memory

  • edited August 2014

    Where would you put the if statement? If I put it in the last for loop none of the loops run. Not even once.
    I have tried a few different ways with break and even did a labeled break but didn't get the desired result.

  • You might have better luck if you post an MCVE instead of your whole project. Right now your code contains a bunch of extra stuff that has nothing to do with your problem, which makes it harder to answer your question.

    Your loop is called from the draw() function, which means it's on the same thread as the mousePressed() function. This means you won't be able to interrupt the loop from the mousePressed() function, since the mousePressed() function will only ever be called after the loop completes.

    It also means that you should not be calling the delay() function inside the loop, since you should not call this function from inside the draw() function.

    You'll have to split your loop up across multiple calls to the draw() function.

  • edited August 2014

    Undocumented function delay() isn't bugged! But it's not meant for controlling draw() speed, but other threads!
    Use frameRate() instead. Or create another thread(""), so it won't halt the main "Animation" Thread!

    http://processing.org/reference/frameRate_.html

  • edited August 2014

    The purpose of the delay was not to delay draw() speed it was to delay how often the rgb colors are sent to the Arduino to control how fast the colors are cycling through. Maybe it would be better to take care of that on the Arduino end?

    Splitting the loop up could temporarily relieve the problem but isn't fixing it. Now that I think about it even if I break it up into 1000 pieces it will still have to wait for the delay to finish which will be an issue if the delay is ever set super high.

    It seems as though my concept is deeply flawed from its foundation up and I will probably just scrap it.

  • To understand your problem, you have to understand how threads work.

    The draw() function and the mousePressed() function are called from the same thread. That means that while the draw() function is executing, the mousePressed() function can't start, and vice versa.

    That's why you shouldn't call the delay() function from these functions: it causes your program to become unresponsive as it waits for the delay() function to return. This is a very bad practice.

    To fix your problem, you either need to get rid of your loop completely and instead increment some variable each time the draw() function is called and use that variable as your loop, or you need to use another thread so you can use the delay() function.

  • edited August 2014

    I was originally under the assumption that Processing took care of things such as this for you since it makes no mention of the need for threads in any of the documentation I have been reading. I guess this is simply because it wasn't needed for any examples in the Getting Started with Processing book.

    It also seems like there isn't much information out there about threading in Processing in general. Typically I will get 1000's of google responses when trying to figure out an issue but I am only get a single reference to wiki page about threading with processing.

    It appears that processing only provides a very limit control over threading and to do what I want I am going to have to create my own classes that extend processing thread class or just learn how to do this in java without any help from processing. Both of these currently seem overwhelming so I guess this will just have to be something I deal with.

  • edited August 2014

    I was originally under the assumption that Processing took care of things such as this for you...

    It's not an assumption! Processing's "Animation" Thread takes care of everything!
    It calls back draw() @ 60 FPS by default. And as mentioned, we can change its target FPS via frameRate():
    http://Processing.org/reference/frameRate_.html

    It also seems like there isn't much information out there about threading in Processing in general.

    Processing is a framework API on top of Java. Its official documented API is found below:
    http://Processing.org/reference/

    Everything else, like delay() and threading are undocumented and unsupported.
    Although we can use them anyways at our own risk & peril! :-SS

    Function delay() halts current Thread by specified milliseconds.
    However, Processing's "Animation" Thread got its own FPS-based delay mechanism!
    That's why we should use frameRate() rather than invoking delay(). Except in our own threads!

    ... I am going to have to create my own classes that extend Processing Thread class...

    Class Thread got nothing to do w/ Processing. it's purely a Java thingy!
    Processing got another undocumented function called thread(""), which calls a function over a new Thread!
    Use that if you can't tame your algorithm w/o relying on delay() calls inside draw()! :-\"

  • edited August 2014

    I have already tried to mess with thread("") but couldn't get the desired results.
    As far as eliminating the delay goes, I do not think there is another way to achieve the flow control I want w/o it.

    The only solution I can think of would be to have the modes run in a different thread and then start/stop the threads within the draw() based on the flags set by mousePressed. Actually doing this is above my head so for now I will just remain discouraged and step away for awhile. This is a shame because Processing had me so excited do to how visually based it is, but it seems I have still managed to back myself into a corner.

    I truly appreciate both of you taking time to try to help me out. Programming is the one piece I am missing to fully round out my computer skills and I hope in time Processing can get me over the hump.

  • edited August 2014

    Why did you delete all your posts? Gonna leave us all replying to empty questions??? X(

    I was about to reply. Your problem is that you hadn't learnt that we don't draw directly to a screen,
    but a PGraphics object! Which only at the end of draw() is rendered to the screen!

    Since you're not that much interested anymore, gonna leave my 2 examples w/o any explanations: (~~)


    // forum.processing.org/two/discussion/6889/exit-loop-on-mousepressed
    
    static final color RED = #FF0000, BLUE = #0000FF;
    
    void setup() {
      size(300, 200, JAVA2D);
    }
    
    void draw() {
      background(RED);
      delay(500); // 2 FPS or half second
    
      background(BLUE);
      delay(500); // 2 FPS or half second
    }
    

    // forum.processing.org/two/discussion/6889/exit-loop-on-mousepressed
    
    static final color RED = #FF0000, BLUE = #0000FF;
    
    void setup() {
      size(300, 200, JAVA2D);
      frameRate(2); // 500 ms or half second
    }
    
    void draw() {
      background((frameCount & 1) == 0? BLUE : RED);
    }
    

  • I was originally under the assumption that Processing took care of things such as this for you since it makes no mention of the need for threads in any of the documentation I have been reading. It also seems like there isn't much information out there about threading in Processing in general.

    Processing is great for learning the basics. Threading is not one of the basics.

    I am going to have to create my own classes that extend processing thread class or just learn how to do this in java without any help from processing. Both of these currently seem overwhelming so I guess this will just have to be something I deal with.

    There is no such thing as a "Processing thread". If you take the threading approach (which I don't recommend since you can do this without threading), you would want to use a regular old Java thread inside Processing, or use the thread() function which sets that up for you. Part of being a programmer is taking a problem you don't know how to solve and reading references and examples (both of which you've been given here), asking questions when you don't understand something.

    I have already tried to mess with thread("") but couldn't get the desired results.

    What exactly happened when you tried that? Where is your updated MCVE? This really isn't enough information for anybody to help you.

    As far as eliminating the delay goes, I do not think there is another way to achieve the flow control I want w/o it.

    Like I said, there certainly are other ways to approach this. The "Processing way" would be to not use Threads at all, and to take advantage of the draw() function being called 60 times a second.

    The problem is that you're trying to copy-paste code you found on the internet instead of coming up with your own solution. You've married yourself to a particular approach instead of working with the pieces you already had, which is why this isn't coming together.

Sign In or Register to comment.