Skip to content

Instantly share code, notes, and snippets.

@splitbrain
Created February 10, 2010 20:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save splitbrain/300827 to your computer and use it in GitHub Desktop.
Save splitbrain/300827 to your computer and use it in GitHub Desktop.
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JOptionPane;
import processing.core.PApplet;
public class MousePath extends PApplet {
public static void main(String args[]) {
Frame f = new Frame("MousePath © Anatoly Zenkov (anatolyzenkov.com), Andreas Gohr (splitbrain.org)");
GraphicsEnvironment e = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] screens = e.getScreenDevices();
int w = 0;
int h = 0;
for(int i=0; i<screens.length; i++){
w += screens[i].getDisplayMode().getWidth();
h = max(h,screens[i].getDisplayMode().getHeight());
}
JOptionPane.showMessageDialog(null,
"Keep the next window open to record your mouse movements.\n"+
"Use the following keys to control the behaviour:\n\n"+
" S - Save the current image as TIF in the current directory\n"+
" R - Clean the image and restart the recording\n"+
" C - Toggle between color and B/W mode\n"+
" D - Toggle dots on movement pauses\n"+
" L - Toggle speed dependent line thickness\n"+
" A - Toggle automatic image saving every 15 minutes\n"+
" P - Pause recording\n\n"+
"© Anatoly Zenkov (anatolyzenkov.com)\n"+
" modified by Andreas Gohr (splitbrain.org)",
"MousePath",JOptionPane.PLAIN_MESSAGE);
float scale = Math.min((float) w, 1280) / (float) w;
f.setSize((int) (w * scale), (int) (h * scale));
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
f.setResizable(false);
f.setVisible(true);
f.setLayout(new BorderLayout());
MousePath p = new MousePath();
f.add(p, BorderLayout.CENTER);
p.setWidth(w);
p.setHeight(h);
p.setScale(scale);
p.init();
}
private float _width;
private float _height;
private float _scale;
private float _radius;
private boolean _stops;
private boolean _color;
private boolean _stroke;
private boolean _auto;
private boolean _pause;
private Point _prevP;
private Point _newP;
private Point _stopP;
private int _pseudopid;
private float _time;
public MousePath() {
this.start();
}
public void setWidth(int width){
this._width = (float) width;
}
public void setHeight(int height){
this._height = (float) height;
}
public void setScale(float scale){
this._scale = (float) scale;
}
public void setup() {
_stops = true;
_color = true;
_stroke = false;
_auto = false;
_pause = false;
_time = millis();
_pseudopid = (int) random(0,10000);
size((int) (_width * _scale), (int) (_height * _scale));
_newP = MouseInfo.getPointerInfo().getLocation() ;
_prevP = _newP;
_stopP = _newP;
stroke(random(10,240),random(10,240),random(10,240),random(180,230));
strokeWeight(.2f);
frameRate(50);
smooth();
background(255);
}
public void draw() {
int dx, dy, d;
if(_pause) return;
_newP = MouseInfo.getPointerInfo().getLocation() ;
if(_auto && (millis() - _time) > 900000){ // 900k ms = 15 min
this.saveImage();
_time = millis();
}
// calculate distance to last measure
if(_stroke){
dx = _newP.x - _prevP.x;
dy = _newP.y - _prevP.y;
d = dx * dx + dy * dy;
if(d > 2000) d = 2000;
strokeWeight(0.2f + d/2000f);
}
line(_newP.x * _scale, _newP.y * _scale, _prevP.x * _scale, _prevP.y * _scale);
_prevP = _newP;
strokeWeight(0.2f);
// calculate distance to last stop
dx = _newP.x - _stopP.x;
dy = _newP.y - _stopP.y;
d = dx * dx + dy * dy;
if (d < 20) {
_radius += 0.1;
}else{
// if we stopped long enough...
if(_radius > 15) {
// change colors
if(_color){
fill(random(10,240),random(10,240),random(10,240), 200f * max(0f, 1f - sqrt(_radius) / 20));
stroke(random(10,240),random(10,240),random(10,240),random(180,230));
}else{
fill(255, 200f * max(0f, 1f - sqrt(_radius) / 20));
stroke(0);
}
// draw dots
if(_stops){
ellipse(_stopP.x * _scale, _stopP.y * _scale, _radius * .5f, _radius * .5f);
fill(0);
ellipse(_stopP.x * _scale, _stopP.y * _scale, sqrt(_radius), sqrt(_radius));
noFill();
}
}
_stopP = _newP;
_radius = 0;
}
}
public void saveImage() {
String n = "mousePath-";
n += nf(_pseudopid,4);
n += "-";
n += nf(year(),4);
n += nf(month(),2);
n += nf(day(),2);
n += ".";
n += nf(hour(), 2);
n += nf(minute(), 2);
n += nf(second(), 2);
n += ".tif";
save(n);
status("Saved image to '"+n+"'");
}
public void keyReleased() {
if (key == 's' || key == 'S') {
this.saveImage();
return;
}
if (key == 'r' || key == 'R') {
background(255);
}
if (key == 'd' || key == 'D') {
_stops = !_stops;
if(_stops){
status("Stop circles enabled");
}else{
status("Stop circles disabled");
}
}
if (key == 'c' || key == 'C') {
_color = !_color;
if(_color){
status("Color enabled");
}else{
status("Color disabled");
}
}
if (key == 'l' || key == 'L') {
_stroke = !_stroke;
if(_stroke){
status("Line thickness enabled");
}else{
status("Line thickness disabled");
}
}
if (key == 'a' || key == 'A') {
_auto = !_auto;
if(_auto){
status("Automatic image saving enabled");
}else{
status("Automatic image saving disabled");
}
}
if (key == 'p' || key == 'P') {
_pause = !_pause;
if(_pause){
status("Recording paused");
}else{
status("Recording resumed");
}
}
}
private static final long serialVersionUID = 1L;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment