Camera draging

Hi Folks,

I’ve implemented a analog listener which translates my camera by right mouse click + dragging just like the well known ADSF keys behavior.

But the cam is always jumping to the cursor location first before drag. I would like to scroll around a 2d map but when the cam is always jumping to the mousepos I’m unable to drag the map more then once in a direction.

Hope someone have a solution for that.

[java]
Vector2f mousePos = inputManager.getCursorPosition();
Vector3f location = cam.getWorldCoordinates(mousePos, 0.001f);
Vector3f direction = cam.getWorldCoordinates(mousePos, 0.03f);
direction.subtractLocal(location).normalizeLocal();

        if (MouseDrag) {
            cam.setLocation(new Vector3f(
                    direction.getX() * MouseZoom, 
                    direction.getY() * MouseZoom, 
                    MouseZoom)
                    );
        }

[/java]

Well, you are setting the camera to the mouse position. What did you expect would happen when you did this?

It sounds like you really want to be adding the mouse movement to the camera position instead. So you will have to keep track of how much the mouse has been dragged and then add that to the location.

well, it seems like that, yes. But it is not fully true.

The translation is set to direction.getX(), getY() plus zoomfactor and direction ist the normalized substract of direction.subtractLocal(location).normalizeLocal()

never mind.

I’m sure that I have overseen something here.

For Example: The jme3 “sceneComposer” does behave like that (right mouseclick for drag view), but I have not found the corresponding mouse control code yet.

In fact I would be very happy if I can copy the SceneComposer MouseControl some way, because it is exacly what I’m trying to do right now.

planed Mouse/Cursor Controls:

  • Left-click and drag to rotate the camera around the cam center
  • Right-click and drag to move the cam center
  • Scoll the mouse wheel to zoom in/out the cam center

I know FlyByCamera has a drag to rotate ability. You could just look at that code.

thanks,

the task “drag to rotate” (left click + drag) is completed. Thats not the problem.

I’m talking about dragging the cam. “Right-click and drag to move the cam”, like Jmonkey does in the sceneComposer (right click + drag).

edit: I think I found some hints in the AbstractCameraController.java line#311 onAnalog and the doPanCamera call line#203 from the scene composer src… trying out.

https://code.google.com/p/jmonkeyengine/source/browse/trunk/sdk/jme3-core/src/com/jme3/gde/core/scene/controller/AbstractCameraController.java#311

[SOLVED]

Ok, now it works.
Thanks to the Scene Controller from the SDK I was able to strip down the classes.
Here the implementation for your own use if interested:

Implementation Main app
[java]
// …
public class Main extends SimpleApplication {
private StartScreenControl startScreenControl;
private SceneCameraController camController;
// …

//Somewere in your App Initialisation Method(s)
// …
inputManager.addMapping(“MouseAxisX”, new MouseAxisTrigger(MouseInput.AXIS_X, false));
inputManager.addMapping(“MouseAxisY”, new MouseAxisTrigger(MouseInput.AXIS_Y, false));
inputManager.addMapping(“MouseAxisX-”, new MouseAxisTrigger(MouseInput.AXIS_X, true));
inputManager.addMapping(“MouseAxisY-”, new MouseAxisTrigger(MouseInput.AXIS_Y, true));
inputManager.addMapping(“MouseWheel”, new MouseAxisTrigger(MouseInput.AXIS_WHEEL, false));
inputManager.addMapping(“MouseWheel-”, new MouseAxisTrigger(MouseInput.AXIS_WHEEL, true));
inputManager.addMapping(“MouseButtonLeft”, new MouseButtonTrigger(0));
inputManager.addMapping(“MouseButtonMiddle”, new MouseButtonTrigger(2));
inputManager.addMapping(“MouseButtonRight”, new MouseButtonTrigger(1));
// …

// Somewhere in your Initialisation procedure
// …
camController = new SceneCameraController(cam, inputManager);
inputManager.addRawInputListener(camController);
inputManager.addListener(camController, “MouseAxisX”, “MouseAxisY”, “MouseAxisX-”, “MouseAxisY-”, “MouseWheel”, “MouseWheel-”, “MouseButtonLeft”, “MouseButtonMiddle”, “MouseButtonRight”);
// …
[/java]

Classes Needed:

Abstract Cam Control
[java]
package mygame;

import com.jme3.app.Application;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.input.InputManager;
import com.jme3.input.KeyInput;
import com.jme3.input.RawInputListener;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.event.JoyAxisEvent;
import com.jme3.input.event.JoyButtonEvent;
import com.jme3.input.event.KeyInputEvent;
import com.jme3.input.event.MouseButtonEvent;
import com.jme3.input.event.MouseMotionEvent;
import com.jme3.input.event.TouchEvent;
import com.jme3.renderer.Camera;
import com.jme3.math.Vector3f;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;

public abstract class AbstractCameraController extends AbstractAppState implements ActionListener, AnalogListener, RawInputListener {

protected Camera cam;
protected InputManager inputManager;
protected Quaternion rot = new Quaternion();
protected Vector3f vector = new Vector3f(0, 0, 5);
protected Vector3f focus = new Vector3f();
protected boolean leftMouse, rightMouse, middleMouse;
protected int mouseX = 0;
protected int mouseY = 0;
protected boolean moved = false;
protected boolean movedR = false;
protected boolean buttonDownL = false;
protected boolean buttonDownR = false;
protected boolean buttonDownM = false;
protected boolean checkClickL = false;
protected boolean checkClickR = false;
protected boolean checkClickM = false;
protected boolean checkReleaseL = false;
protected boolean checkReleaseR = false;
protected boolean checkReleaseM = false;
protected boolean checkDragged = false;
protected boolean checkDraggedR = false;
protected boolean checkReleaseLeft = false;
protected boolean checkReleaseRight = false;
protected boolean shiftModifier = false;

public AbstractCameraController(Camera cam, InputManager inputManager) {
    this.cam = cam;
    this.inputManager = inputManager;
}

/*
 * methods to move camera
 */
protected void doRotateCamera(Vector3f axis, float amount) {
    if (axis.equals(cam.getLeft())) {
        float elevation = -FastMath.asin(cam.getDirection().y);
        amount = Math.min(Math.max(elevation + amount, -FastMath.HALF_PI), FastMath.HALF_PI) - elevation;
    }
    rot.fromAngleAxis(amount, axis);
    cam.getLocation().subtract(focus, vector);
    rot.mult(vector, vector);
    focus.add(vector, cam.getLocation());

    Quaternion curRot = cam.getRotation().clone();
    cam.setRotation(rot.mult(curRot));
}

protected void doPanCamera(float left, float up) {
    cam.getLeft().mult(left, vector);
    vector.scaleAdd(up, cam.getUp(), vector);
    vector.multLocal(cam.getLocation().distance(focus));
    cam.setLocation(cam.getLocation().add(vector));
    focus.addLocal(vector);
}

protected void doMoveCamera(float forward) {
    cam.getDirection().mult(forward, vector);
    cam.setLocation(cam.getLocation().add(vector));
}

protected void doZoomCamera(float amount) {
    amount = cam.getLocation().distance(focus) * amount;
    float dist = cam.getLocation().distance(focus);
    amount = dist - Math.max(0f, dist - amount);
    Vector3f loc = cam.getLocation().clone();
    loc.scaleAdd(amount, cam.getDirection(), loc);
    cam.setLocation(loc);

    if (cam.isParallelProjection()) {
        float aspect = (float) cam.getWidth() / cam.getHeight();
        float h = FastMath.tan(45f * FastMath.DEG_TO_RAD * .5f) * dist;
        float w = h * aspect;
        cam.setFrustum(-1000, 1000, -w, w, h, -h);
    }
}

@Override
public void onAction(String name, boolean isPressed, float tpf) {
    if ("MouseButtonLeft".equals(name)) {
        if (isPressed) {
            if (!buttonDownL) { // mouse clicked
                checkClickL = true;
                checkReleaseL = false;
            }
        } else {
            if (buttonDownL) { // mouse released
                checkReleaseL = true;
                checkClickL = false;
            }
        }
        buttonDownL = isPressed;
    }
    if ("MouseButtonRight".equals(name)) {
        if (isPressed) {
            if (!buttonDownR) { // mouse clicked
                checkClickR = true;
                checkReleaseR = false;
            }
        } else {
            if (buttonDownR) { // mouse released
                checkReleaseR = true;
                checkClickR = false;
            }
        }
        buttonDownR = isPressed;
    }
    if ("MouseButtonMiddle".equals(name)) {
        if (isPressed) {
            if (!buttonDownM) { // mouse clicked
                checkClickM = true;
                checkReleaseM = false;
            }
        } else {
            if (buttonDownM) { // mouse released
                checkReleaseM = true;
                checkClickM = false;
            }
        }
        buttonDownM = isPressed;
    }
}

public abstract boolean useCameraControls();

@Override
public void onAnalog(String name, float value, float tpf) {
    switch (name) {
        case "MouseAxisX":
            moved = true;
            movedR = true;
            if ((buttonDownL && useCameraControls()) || (buttonDownM && !shiftModifier)) {
                doRotateCamera(Vector3f.UNIT_Y, -value * 2.5f);
            }
            if ((buttonDownR && useCameraControls()) || (buttonDownM && shiftModifier)) {
                doPanCamera(value * 2.5f, 0);
            }
            break;
        case "MouseAxisY":
            moved = true;
            movedR = true;
            if ((buttonDownL && useCameraControls()) || (buttonDownM && !shiftModifier)) {
                doRotateCamera(cam.getLeft(), -value * 2.5f);
            }
            if ((buttonDownR && useCameraControls()) || (buttonDownM && shiftModifier)) {
                doPanCamera(0, -value * 2.5f);
            }
            break;
        case "MouseAxisX-":
            moved = true;
            movedR = true;
            if ((buttonDownL && useCameraControls()) || (buttonDownM && !shiftModifier)) {
                doRotateCamera(Vector3f.UNIT_Y, value * 2.5f);
            }
            if ((buttonDownR && useCameraControls()) || (buttonDownM && shiftModifier)) {
                doPanCamera(-value * 2.5f, 0);
            }
            break;
        case "MouseAxisY-":
            moved = true;
            movedR = true;
            if ((buttonDownL && useCameraControls()) || (buttonDownM && !shiftModifier)) {
                doRotateCamera(cam.getLeft(), value * 2.5f);
            }
            if ((buttonDownR && useCameraControls()) || (buttonDownM && shiftModifier)) {
                doPanCamera(0, value * 2.5f);
            }
            break;
        case "MouseWheel":
            doZoomCamera(.1f);
            break;
        case "MouseWheel-":
            doZoomCamera(-.1f);
            break;
    }
}

@Override
public void beginInput() {
}

@Override
public void endInput() {
}

@Override
public void onJoyAxisEvent(JoyAxisEvent evt) {
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}

@Override
public void onJoyButtonEvent(JoyButtonEvent evt) {
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}

@Override
public void onMouseMotionEvent(MouseMotionEvent evt) {
    mouseX = evt.getX();
    mouseY = evt.getY();
}

@Override
public void onMouseButtonEvent(MouseButtonEvent evt) {
}

@Override
public void onKeyEvent(KeyInputEvent evt) {
    if (evt.isPressed()) {
        if (KeyInput.KEY_LSHIFT == evt.getKeyCode()) {
            shiftModifier = true;
        }
    } else if (evt.isReleased()) {
        if (KeyInput.KEY_LSHIFT == evt.getKeyCode()) {
            shiftModifier = false;
        }
    }

}

@Override
public void onTouchEvent(TouchEvent evt) {
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
/**
 * APPSTATE*
 */
private boolean appInit = false;

@Override
public void initialize(AppStateManager asm, Application aplctn) {
    appInit = true;
}

@Override
public boolean isInitialized() {
    return appInit;
}

@Override
public void stateAttached(AppStateManager asm) {
}

@Override
public void stateDetached(AppStateManager asm) {
}

@Override
public void update(float f) {
    if (moved) {
        // moved, check for drags
        if (checkReleaseL || checkReleaseR || checkReleaseM) {
            // drag released
            if (checkReleaseL) {
                checkDragged(0, false);
            }
            if (checkReleaseR) {
                checkDragged(1, false);
            }
            if (checkReleaseM) {
                checkDragged(2, false);
            }
            checkReleaseL = false;
            checkReleaseR = false;
            checkReleaseM = false;
        } else {
            if (buttonDownL) {
                checkDragged(0, true);
            } else if (buttonDownR) {
                checkDragged(1, true);
            } else if (buttonDownM) {
                checkDragged(2, true);
            } else {
                checkMoved(); // no dragging, just moved
            }
        }

        moved = false;
    } else {
        // not moved, check for just clicks
        if (checkClickL) {
            checkClick(0, true);
            checkClickL = false;
        }
        if (checkReleaseL) {
            checkClick(0, false);
            checkReleaseL = false;
        }
        if (checkClickR) {
            checkClick(1, true);
            checkClickR = false;
        }
        if (checkReleaseR) {
            checkClick(1, false);
            checkReleaseR = false;
        }
        if (checkClickM) {
            checkClick(2, true);
            checkClickM = false;
        }
        if (checkReleaseM) {
            checkClick(2, false);
            checkReleaseM = false;
        }
    }

    /*
     * if (checkDragged || checkDraggedR) { if (checkDragged) {
     * checkDragged(0); checkReleaseLeft = false; checkDragged = false;
     * checkClick = false; checkClickR = false; } if (checkDraggedR) {
     * checkDragged(1); checkReleaseRight = false; checkDraggedR = false;
     * checkClick = false; checkClickR = false; } } else { if (checkClick) {
     * checkClick(0, checkReleaseLeft); checkReleaseLeft = false; checkClick
     * = false; checkDragged = false; checkDraggedR = false; } if
     * (checkClickR) { checkClick(1, checkReleaseRight); checkReleaseRight =
     * false; checkClickR = false; checkDragged = false; checkDraggedR =
     * false; } }
     */
}

/**
 * mouse clicked, not dragged
 *
 * @param pressed true if pressed, false if released
 */
protected abstract void checkClick(int button, boolean pressed);

/**
 * Mouse dragged while button is depressed
 */
protected void checkDragged(int button, boolean pressed) {
    // override in sub classes
}

/**
 * The mouse moved, no dragging or buttons pressed
 */
protected void checkMoved() {
    // override in subclasses
}

}
[/java]

Scene Cam Control
[java]
package mygame;

import com.jme3.app.Application;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.input.InputManager;
import com.jme3.input.KeyInput;
import com.jme3.input.RawInputListener;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.event.JoyAxisEvent;
import com.jme3.input.event.JoyButtonEvent;
import com.jme3.input.event.KeyInputEvent;
import com.jme3.input.event.MouseButtonEvent;
import com.jme3.input.event.MouseMotionEvent;
import com.jme3.input.event.TouchEvent;
import com.jme3.renderer.Camera;
import com.jme3.math.Vector3f;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;

public abstract class AbstractCameraController extends AbstractAppState implements ActionListener, AnalogListener, RawInputListener {

protected Camera cam;
protected InputManager inputManager;
protected Quaternion rot = new Quaternion();
protected Vector3f vector = new Vector3f(0, 0, 5);
protected Vector3f focus = new Vector3f();
protected boolean leftMouse, rightMouse, middleMouse;
protected int mouseX = 0;
protected int mouseY = 0;
protected boolean moved = false;
protected boolean movedR = false;
protected boolean buttonDownL = false;
protected boolean buttonDownR = false;
protected boolean buttonDownM = false;
protected boolean checkClickL = false;
protected boolean checkClickR = false;
protected boolean checkClickM = false;
protected boolean checkReleaseL = false;
protected boolean checkReleaseR = false;
protected boolean checkReleaseM = false;
protected boolean checkDragged = false;
protected boolean checkDraggedR = false;
protected boolean checkReleaseLeft = false;
protected boolean checkReleaseRight = false;
protected boolean shiftModifier = false;

public AbstractCameraController(Camera cam, InputManager inputManager) {
    this.cam = cam;
    this.inputManager = inputManager;
}

/*
 * methods to move camera
 */
protected void doRotateCamera(Vector3f axis, float amount) {
    if (axis.equals(cam.getLeft())) {
        float elevation = -FastMath.asin(cam.getDirection().y);
        amount = Math.min(Math.max(elevation + amount, -FastMath.HALF_PI), FastMath.HALF_PI) - elevation;
    }
    rot.fromAngleAxis(amount, axis);
    cam.getLocation().subtract(focus, vector);
    rot.mult(vector, vector);
    focus.add(vector, cam.getLocation());

    Quaternion curRot = cam.getRotation().clone();
    cam.setRotation(rot.mult(curRot));
}

protected void doPanCamera(float left, float up) {
    cam.getLeft().mult(left, vector);
    vector.scaleAdd(up, cam.getUp(), vector);
    vector.multLocal(cam.getLocation().distance(focus));
    cam.setLocation(cam.getLocation().add(vector));
    focus.addLocal(vector);
}

protected void doMoveCamera(float forward) {
    cam.getDirection().mult(forward, vector);
    cam.setLocation(cam.getLocation().add(vector));
}

protected void doZoomCamera(float amount) {
    amount = cam.getLocation().distance(focus) * amount;
    float dist = cam.getLocation().distance(focus);
    amount = dist - Math.max(0f, dist - amount);
    Vector3f loc = cam.getLocation().clone();
    loc.scaleAdd(amount, cam.getDirection(), loc);
    cam.setLocation(loc);

    if (cam.isParallelProjection()) {
        float aspect = (float) cam.getWidth() / cam.getHeight();
        float h = FastMath.tan(45f * FastMath.DEG_TO_RAD * .5f) * dist;
        float w = h * aspect;
        cam.setFrustum(-1000, 1000, -w, w, h, -h);
    }
}

@Override
public void onAction(String name, boolean isPressed, float tpf) {
    if ("MouseButtonLeft".equals(name)) {
        if (isPressed) {
            if (!buttonDownL) { // mouse clicked
                checkClickL = true;
                checkReleaseL = false;
            }
        } else {
            if (buttonDownL) { // mouse released
                checkReleaseL = true;
                checkClickL = false;
            }
        }
        buttonDownL = isPressed;
    }
    if ("MouseButtonRight".equals(name)) {
        if (isPressed) {
            if (!buttonDownR) { // mouse clicked
                checkClickR = true;
                checkReleaseR = false;
            }
        } else {
            if (buttonDownR) { // mouse released
                checkReleaseR = true;
                checkClickR = false;
            }
        }
        buttonDownR = isPressed;
    }
    if ("MouseButtonMiddle".equals(name)) {
        if (isPressed) {
            if (!buttonDownM) { // mouse clicked
                checkClickM = true;
                checkReleaseM = false;
            }
        } else {
            if (buttonDownM) { // mouse released
                checkReleaseM = true;
                checkClickM = false;
            }
        }
        buttonDownM = isPressed;
    }
}

public abstract boolean useCameraControls();

@Override
public void onAnalog(String name, float value, float tpf) {
    switch (name) {
        case "MouseAxisX":
            moved = true;
            movedR = true;
            if ((buttonDownL && useCameraControls()) || (buttonDownM && !shiftModifier)) {
                doRotateCamera(Vector3f.UNIT_Y, -value * 2.5f);
            }
            if ((buttonDownR && useCameraControls()) || (buttonDownM && shiftModifier)) {
                doPanCamera(value * 2.5f, 0);
            }
            break;
        case "MouseAxisY":
            moved = true;
            movedR = true;
            if ((buttonDownL && useCameraControls()) || (buttonDownM && !shiftModifier)) {
                doRotateCamera(cam.getLeft(), -value * 2.5f);
            }
            if ((buttonDownR && useCameraControls()) || (buttonDownM && shiftModifier)) {
                doPanCamera(0, -value * 2.5f);
            }
            break;
        case "MouseAxisX-":
            moved = true;
            movedR = true;
            if ((buttonDownL && useCameraControls()) || (buttonDownM && !shiftModifier)) {
                doRotateCamera(Vector3f.UNIT_Y, value * 2.5f);
            }
            if ((buttonDownR && useCameraControls()) || (buttonDownM && shiftModifier)) {
                doPanCamera(-value * 2.5f, 0);
            }
            break;
        case "MouseAxisY-":
            moved = true;
            movedR = true;
            if ((buttonDownL && useCameraControls()) || (buttonDownM && !shiftModifier)) {
                doRotateCamera(cam.getLeft(), value * 2.5f);
            }
            if ((buttonDownR && useCameraControls()) || (buttonDownM && shiftModifier)) {
                doPanCamera(0, value * 2.5f);
            }
            break;
        case "MouseWheel":
            doZoomCamera(.1f);
            break;
        case "MouseWheel-":
            doZoomCamera(-.1f);
            break;
    }
}

@Override
public void beginInput() {
}

@Override
public void endInput() {
}

@Override
public void onJoyAxisEvent(JoyAxisEvent evt) {
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}

@Override
public void onJoyButtonEvent(JoyButtonEvent evt) {
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}

@Override
public void onMouseMotionEvent(MouseMotionEvent evt) {
    mouseX = evt.getX();
    mouseY = evt.getY();
}

@Override
public void onMouseButtonEvent(MouseButtonEvent evt) {
}

@Override
public void onKeyEvent(KeyInputEvent evt) {
    if (evt.isPressed()) {
        if (KeyInput.KEY_LSHIFT == evt.getKeyCode()) {
            shiftModifier = true;
        }
    } else if (evt.isReleased()) {
        if (KeyInput.KEY_LSHIFT == evt.getKeyCode()) {
            shiftModifier = false;
        }
    }

}

@Override
public void onTouchEvent(TouchEvent evt) {
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
/**
 * APPSTATE*
 */
private boolean appInit = false;

@Override
public void initialize(AppStateManager asm, Application aplctn) {
    appInit = true;
}

@Override
public boolean isInitialized() {
    return appInit;
}

@Override
public void stateAttached(AppStateManager asm) {
}

@Override
public void stateDetached(AppStateManager asm) {
}

@Override
public void update(float f) {
    if (moved) {
        // moved, check for drags
        if (checkReleaseL || checkReleaseR || checkReleaseM) {
            // drag released
            if (checkReleaseL) {
                checkDragged(0, false);
            }
            if (checkReleaseR) {
                checkDragged(1, false);
            }
            if (checkReleaseM) {
                checkDragged(2, false);
            }
            checkReleaseL = false;
            checkReleaseR = false;
            checkReleaseM = false;
        } else {
            if (buttonDownL) {
                checkDragged(0, true);
            } else if (buttonDownR) {
                checkDragged(1, true);
            } else if (buttonDownM) {
                checkDragged(2, true);
            } else {
                checkMoved(); // no dragging, just moved
            }
        }

        moved = false;
    } else {
        // not moved, check for just clicks
        if (checkClickL) {
            checkClick(0, true);
            checkClickL = false;
        }
        if (checkReleaseL) {
            checkClick(0, false);
            checkReleaseL = false;
        }
        if (checkClickR) {
            checkClick(1, true);
            checkClickR = false;
        }
        if (checkReleaseR) {
            checkClick(1, false);
            checkReleaseR = false;
        }
        if (checkClickM) {
            checkClick(2, true);
            checkClickM = false;
        }
        if (checkReleaseM) {
            checkClick(2, false);
            checkReleaseM = false;
        }
    }

    /*
     * if (checkDragged || checkDraggedR) { if (checkDragged) {
     * checkDragged(0); checkReleaseLeft = false; checkDragged = false;
     * checkClick = false; checkClickR = false; } if (checkDraggedR) {
     * checkDragged(1); checkReleaseRight = false; checkDraggedR = false;
     * checkClick = false; checkClickR = false; } } else { if (checkClick) {
     * checkClick(0, checkReleaseLeft); checkReleaseLeft = false; checkClick
     * = false; checkDragged = false; checkDraggedR = false; } if
     * (checkClickR) { checkClick(1, checkReleaseRight); checkReleaseRight =
     * false; checkClickR = false; checkDragged = false; checkDraggedR =
     * false; } }
     */
}

/**
 * mouse clicked, not dragged
 *
 * @param pressed true if pressed, false if released
 */
protected abstract void checkClick(int button, boolean pressed);

/**
 * Mouse dragged while button is depressed
 */
protected void checkDragged(int button, boolean pressed) {
    // override in sub classes
}

/**
 * The mouse moved, no dragging or buttons pressed
 */
protected void checkMoved() {
    // override in subclasses
}

}
[/java]