We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpSyntax Questions › Stopping/drawing during a for loop
Page Index Toggle Pages: 1
Stopping/drawing during a for loop (Read 883 times)
Stopping/drawing during a for loop
Nov 17th, 2008, 11:22pm
 
My program uses a for loop to animate color LED's (fading between colors stored in an array), started by clicking a button on my user interface (using the arduino microcontroller).  I have two problems:  first off, I'd like to be able to stop the loop at any time by clicking the mouse on the button again, but during the loop the program ignores any input.  Is there any way to stop a for loop during execution?  Also, I'd like the user interface to change while running the loop, by calling some draw functions from the loop.  However, the UI won't change until the loop is complete, and if I move another window over the program window it will be blank until the loops stops.  I'm using Processing 0156 Beta on a Windows XP machine.  Here's the code:

void Animate()
{
 //toggles the animate button on and off
 N++;
 float stat = pow(X, N);
 DrawAnimateButton(stat);
 
 //load the color data from the file
 int animateArray[] = int(loadStrings("SaveColor.ddd"));
 float Red = 0;                                              //holds the red value
 float Green = 0;                                            //holds the green value
 float Blue = 0;                                             //holds the blue value
 
 float Rdiff = 0;                                            //the calculated values between the initial and final colors
 float Gdiff = 0;  
 float Bdiff = 0;
 float time = 300;                                           //varies the fade time between each stored color
 
 float arrHolder[] = new float[7];                           //temporary storage for the working colors
 
 //increment through successive colors in the array
 for (int i = 0; i < ArrSize - 5; i = i + 3)
 {
   //stops the loop when no more colors are found in the array
   if (animateArray[i] + animateArray[i + 1] + animateArray[i + 2] == 0)
   {
     LEDcontrol('R', 0);
     LEDcontrol('G', 0);
     LEDcontrol('B', 0);
     break;
   }
   
   //load the working colors into the temporary storage
   for (int ind = 0; ind < 6; ind++)
   {
     arrHolder[ind] = animateArray[i + ind];
   }
   
   //find the difference between each successive color
   Rdiff = (arrHolder[3] - (arrHolder[0]));
   Gdiff = (arrHolder[4] - (arrHolder[1]));
   Bdiff = (arrHolder[5] - (arrHolder[2]));
   
   //initialize the colors to the first stored color
   Red = arrHolder[0];
   Green = arrHolder[1];
   Blue = arrHolder[2];
   
   //fades between the two working colors
   for (int a = 0; a < time; a++)
   {
     
     //none of these work.  They should redraw the interface every time the values
     //are incremented, but the interface remains locked out for the duration of the loop.
     DrawColorSample(int(Red), int(Green), int(Blue));
     Rmouse = int(Red);
     Gmouse = int(Green);
     Bmouse = int(Blue);
     DrawGrid();
     
     //sends the current color to the LED array
     if (Red >= 0)
     {
       LEDcontrol('R', Red);
     }
     
     if (Green >= 0)
     {
       LEDcontrol('G', .45 * Green);
     }
     
     if (Blue >= 0)
     {
       LEDcontrol('B', .545 * Blue);
     }
     
     //increments the colors over time from the initial value to the final value
     Red = Red + Rdiff/time;
     Green = Green + Gdiff/time;
     Blue = Blue + Bdiff/time;
   }
 delay(10000);
 }
 //toggle the animate button off after the loop is completed
 N++;
 stat = pow(X, N);
 DrawAnimateButton(stat);
}
Re: Stopping/drawing during a for loop
Reply #1 - Nov 18th, 2008, 4:52pm
 
One big culprit I see is delay(10000);

The problem is that your program is monolithic, leaving no chance to another routine (in the same thread) to be fired.
IIRC, events are queued and their respective functions are called when draw() return.

A way to avoid this problem is to use draw() calls as the running loop of your animation. With the nice side effect to allow updating the screen, as you wish...

A way to do that is to use frameCount variable or a resettable counter. Along with frameRate, it allows to count time: instead of sleeping (call to delay), you check this value and do something when a limit is reached (and nothing otherwise).
You will also use this counter to maintain the index (your variable i), thus updating your animation on each call.

I hope what I wrote makes sense...
Re: Stopping/drawing during a for loop
Reply #2 - Nov 19th, 2008, 7:29am
 
I'm trying to grasp the concepts here, I'm still fairly new to programming so excuse my ignorance.  When you say to use draw() calls, do you mean that I need to somehow put the animation code into the draw() function?  I did actually try that, and the same thing happened.  I'm not entirely sure how to go about using the frameCount variable to iterate my loop, is it possible you could provide a simple code example of how this might be done?  I appreciate the help, thanks!
Re: Stopping/drawing during a for loop
Reply #3 - Nov 19th, 2008, 8:09am
 
OK, I will try and illustrate my ideas, recycling a simple sketch I have.
Something like your code:
Code:
int rMove = +5;
int slowDown = 1;
int minRadius = 5, maxRadius = 100;
int radius = minRadius;
int xPos = 200;
int yPos = 200;
color c1 = #005599, c2 = #00AA99;

void setup()
{
size(400, 400);
}

void keyPressed()
{
exit();
}

void draw()
{
background(240);
fill(lerpColor(c1, c2, (float) radius / (float) maxRadius));

rMove = -rMove;
for (int radius = minRadius; radius <= maxRadius && radius >= minRadius; radius += rMove)
{
ellipse(xPos, yPos, radius, radius);
delay(1000);
}
}

It doesn't work, we see nothing moving, only a pulsating circle.

Now, if I change the draw code to:
Code:
void draw()
{
background(240);
fill(lerpColor(c1, c2, (float) radius / (float) maxRadius));

ellipse(xPos, yPos, radius, radius);
if (frameCount % slowDown == 0)
{
radius += rMove;
if (radius > maxRadius)
rMove = -1;
else if (radius < minRadius)
rMove = +1;
}
}

it is much better, or at least close of what I wanted to do... (there is a strange start up).
If you increase slowDown, you control the speed. We don't spend much time in the draw routine, and the keyPressed routine is active.
Re: Stopping/drawing during a for loop
Reply #4 - Nov 20th, 2008, 7:08am
 
Thought you might like to know, your concept worked great!  It was a bit of a struggle for me to convert the code to work from draw(), but once I figured it out the animation works perfectly.  Here's the final code:

 if (stat < 0)
 {    
   int animateArray[] = int(loadStrings("SaveColor.ddd"));  //load the color data from the file
   
   for (int in = 0; in < 7; in++)
   {
     arrHolder[in] = 0;
   }
   if (index < 48)
   {
     
     //load the working colors into the temporary storage
     if (refreshCount % time == 0)
     {
     
       arrHolder[0] = animateArray[index];
       arrHolder[1] = animateArray[index + 1];
       arrHolder[2] = animateArray[index + 2];
       arrHolder[3] = animateArray[index + 3];
       arrHolder[4] = animateArray[index + 4];
       arrHolder[5] = animateArray[index + 5];
       
       
       //find the difference between each successive color
       Rdiff = (arrHolder[3] - (arrHolder[0]));
       Gdiff = (arrHolder[4] - (arrHolder[1]));
       Bdiff = (arrHolder[5] - (arrHolder[2]));      
     
       //initialize the colors to the first stored color
       Red = arrHolder[0];
       Green = arrHolder[1];
       Blue = arrHolder[2];
     }
     
     //fades between the two working colors
     if (refreshCount <= time * 16)
     {
       
       DrawColorSample(int(Red), int(Green), int(Blue));
       Rmouse = int(Red);
       Gmouse = int(Green);
       Bmouse = int(Blue);
       DrawGrid();
       
       //sends the current color to the LED array
     
       LEDcontrol('R', .5 * Red);
       delay(10);    
       LEDcontrol('G', .45 * Green);
       delay(10);    
       LEDcontrol('B', .545 * Blue);
       delay(10);    
     
       //increments the colors over time from the initial value to the final value
       Red = abs(Red + Rdiff/time);
       Green = abs(Green + Gdiff/time);
       Blue = abs(Blue + Bdiff/time);
       refreshCount++;
       //println(refreshCount);
     }
     if (refreshCount % time == 0)
     {
     index = index + 3;
     }
     if (index == 48)
     {
       index = 0;
       refreshCount = 0;
     }
     //println(index);
   }
 }  
Re: Stopping/drawing during a for loop
Reply #5 - Nov 20th, 2008, 4:11pm
 
Thanks for the update! Glad I could help.
Page Index Toggle Pages: 1