Created
February 10, 2010 20:55
-
-
Save splitbrain/300827 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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