I have a question about easing

I'm trying to created a smooth draw or lazy draw mode that smooths out the line someone draws. It almost works but the line never gets to the position of the cursor when easing is set low. Is there any way to get it all the way to the cursor when easing is set low?

float x;
float y;
float targetX, targetY;
float easing = 0.05;
float oldx,oldy;
void setup() 
{
     size(600, 600);   
     background( 200 );
     oldx = -1;

}
void draw() 
{ 

}
void mousePressed(){
     if( oldx <0){
          oldx = mouseX;
          oldy = mouseY;
     }
     x = oldx;
     y = oldy;
     point(oldx,oldy);

}
void mouseDragged(){
     x = oldx;
     y = oldy;
     targetX = mouseX;
     float dx = mouseX - x;
     if(abs(dx) > 1) {
          x += dx * easing;
     }
     targetY = mouseY;
     float dy = mouseY - y;
     if(abs(dy) > 1) {
          y += dy * easing;
     }  
     line(oldx,oldy,x,y);
     oldx = x;
     oldy = y;



}
void mouseReleased(){
     oldx = -1;
}    

Answers

  • edited September 2015

    Of course! As soon as the user stops dragging the mouse Processing stops calling the mouseDragged event and so the easing and line drawing will also stop. Just move your easing and rendering code into draw and you should be fine:

    float x, y;
    float easing = 0.05;
    
    void setup() {
        size(600, 600);   
        background(200);
    }
    
    void draw() { 
        if (mousePressed)
            line(x, y, x += (mouseX - x) * easing, y += (mouseY - y) * easing);
        else {
            x = mouseX;
            y = mouseY;
        }
    }
    
  • edited September 2015

    I was afraid of that. In the real situation that would be problematic. I wonder if a while(mousePressed) loop at the end of the mouseDragged would work?

  • edited September 2015

    No, it won't, as all Processing events are called right after the draw() call (in the same thread). Even when mousePressed was set at this moment, your app would only freeze and crash.

    Why would this be problematic?

  • Its problematic because there are many reasons the mouse may be pressed in the real program. It isn't necessarily drawing a line. It might be choosing a color or choosing a clone offset. It would require managing all those modes in the draw function. All the switches I have in the mouse listeners will have to be moved to the draw function and with the different draw modes , its going to get ugly. Right now my draw function is a switch with about 5 or 6 screen modes. Each of those modes are going to have to have mouse switches, because when the mouse is pressed its not necessarily drawing anything.

    I was hoping it was a simple add.

  • _vk_vk
    edited September 2015

    my draw function is a switch with about 5 or 6 screen modes

    so just use mousePressed in proper mode... Drawing mode.

    or make a boolean isDrawing switch it accordingly and say if(mousePressed && isDrawing){//blah}

    and leave other mouse interactions where they are.

  • _vk_vk
    edited September 2015

    The other approach I can think is to use a flag set to true in mousePressed() and to false in mouseReleased() ... wait... this is just another mousePressed field...

    :)

  • edited September 2015 Answer ✓

    I still don't see the problem, just include (as _vk mentioned) the mouse logic in the respective drawing mode.

    Pseudo code:

    void draw() {
    
        switch(CURRENT_STATE) {
    
            case CHOOSE_COLOR_STATE:
                /* ... */
                break;
    
            case CLONE_STATE:
                /* ... */
                break;
    
            case DRAWING_STATE:
                if (mousePressed)
                    line(x, y, x += (mouseX - x) * easing, y += (mouseY - y) * easing);
                else {
                    x = mouseX;
                    y = mouseY;
                }
                break;
    
        }
    
    }
    

    Or use the OOP approach and write a class based state system:

    public abstract class Mode {
    
        public abstract void draw();
    
    }
    
    Mode currentMode;
    Mode drawingMode, chooseColorMode, cloneMode;
    
    void setup() {
    
        size(600, 600);   
        background(200);
    
        chooseColorMode = new Mode() {
            public void draw() {
                /* ... */
            }
        };
        cloneMode = new Mode() {
            public void draw() {
                /* ... */
            }
        };
        drawingMode = new Mode() {
            public float x, y;
            public float easing = 0.05;
            public void draw() {
                if (mousePressed)
                    line(x, y, x += (mouseX - x) * easing, y += (mouseY - y) * easing);
                else {
                    x = mouseX;
                    y = mouseY;
                }
            }
        };
    
        currentMode = drawingMode;
    
    }
    
    void draw() {
    
        currentMode.draw();
    
    }
    

    This is faster (and much cleaner IMHO) than the switch based approach. ;)

  • I like the OOP method also. I'm going to have to redo a lot of stuff, but I guess I should do that anyway. Thanks.

  • No problem! Glad I could help. :)

Sign In or Register to comment.