package advanced.gestureSound.input;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.mt4j.components.MTComponent;
import org.mt4j.input.IMTInputEventListener;
import org.mt4j.input.inputData.AbstractCursorInputEvt;
import org.mt4j.input.inputData.InputCursor;
import org.mt4j.input.inputData.MTFingerInputEvt;
import org.mt4j.input.inputData.MTInputEvent;
import org.mt4j.input.inputSources.AbstractInputSource;
import org.mt4j.sceneManagement.AbstractScene;
import org.mt4j.util.math.Vector3D;
import advanced.gestureSound.Geometry;
import advanced.gestureSound.U;
import advanced.gestureSound.gestures.qualities.Curvature;
import processing.core.PApplet;
public class InputDelegate extends MTComponent {
List<FadeOut> tickings;
final PApplet p;
public InputDelegate(PApplet pApplet, final AbstractScene scene) {
super(pApplet);
p = pApplet;
tickings = new ArrayList<FadeOut>();
// TODO Auto-generated constructor stub
scene.getCanvas().addInputListener(new IMTInputEventListener() {
//@Override
public boolean processInputEvent(final MTInputEvent inEvt){
if(inEvt instanceof AbstractCursorInputEvt){
AbstractCursorInputEvt posEvt = (AbstractCursorInputEvt)inEvt;
if (posEvt.hasTarget() && posEvt.getTargetComponent().equals(scene.getCanvas())){
final InputCursor m = posEvt.getCursor();
if (posEvt.getId() == AbstractCursorInputEvt.INPUT_ENDED) {
trailOff(inEvt, m);
}
else {
fireInputEvent(inEvt);
}
}
}
else {
fireInputEvent(inEvt);
}
return false;
}
});
}
public void trailOff(final MTInputEvent inEvt, final InputCursor m) {
final AbstractCursorInputEvt posEvt = (AbstractCursorInputEvt)inEvt;
m.getEvents().remove(posEvt);
/** bezel curve stuff **/
List<AbstractCursorInputEvt> past = m.getEvents();
int n= m.getEvents(1000).size();
int sizeofpast = m.getEvents().size();
n = Math.min(n, sizeofpast-1);
final Point2D[] s = new Point2D[n+1];
final double cX = past.get(sizeofpast-1).getPosX();
final double cY = past.get(sizeofpast-1).getPosY();
for (int i=0;i<n+1;i++) {
AbstractCursorInputEvt p = past.get(sizeofpast-i-1);
double x = cX-p.getPosX();//(cX-p.getPosX())+cX;//onward into the future!
double y = cY-p.getPosY();//(cY-p.getPosY())+cY;//onward into the future!
s[i] = new Point2D.Double(x,y);
//System.out.println("Adding point: "+x+","+y);
}
Point2D p0,p1,p2;
float curve = 0f;
float damp = 0f;
for (int i=0;i<10;i++) {
p0 = Geometry.evalBezier(s,0.0+i/20);
p1 = Geometry.evalBezier(s,0.2+i/20);
p2 = Geometry.evalBezier(s,0.4+i/20);
damp += m.getVelocityVector(i*100).length();
curve += (float) Curvature.findCurvature(p0.getX(),p0.getY(),p1.getX(),p1.getY(),p2.getX(),p2.getY());
}
/** that was way more complicated than it needed to be. oh well. **/
final float curvature = curve/20;
final float dampening = damp/(30+damp);
//System.out.println("Curavture: "+curvature);
tickings.add(new FadeOut() {
int i=0;
float currentX = (float) posEvt.getPosX();
float currentY = (float) posEvt.getPosY();
Vector3D currentVec = m.getVelocityVector();
float ourCurvature = curvature;
public void tick() {
synchronized(m.getEvents()) {
if (currentVec.length() < 1) {
m.getEvents().add(posEvt);
fireInputEvent(posEvt);
done();
return;
}
AbstractCursorInputEvt evt = m.getPreviousEvent();
evt = predictNext(m);
m.getEvents().add(evt);
// System.out.println("Sending evt: " + evt + " Stats: "
// + evt.getId() + " " + evt.getPosX() + " "
// + evt.getPosY() + " " + evt.getWhen());
fireInputEvent(evt);
i++;
}
}
public AbstractCursorInputEvt predictNext(InputCursor m) {
AbstractCursorInputEvt evt = m.getPreviousEvent();
currentVec.rotateZ(-ourCurvature);
Vector3D out = currentVec.getAdded(new Vector3D(currentX, currentY));
currentVec = currentVec.getScaled(dampening);
currentX = out.x;
currentY = out.y;
//if we go out of the bounds, bounce back like you'd expect.
if (currentX < 0 || currentX > p.width || currentY < 0 || currentY > p.height) {
if (currentX < 0) {
System.out.println("Bounce LR! "+currentVec.angleBetween(Vector3D.Y_AXIS));
currentVec.rotateAroundAxisLocal(new Vector3D(0,-1), 2*currentVec.angleBetween(new Vector3D(0,-1)));
}
else if (currentX > p.width) {
System.out.println("Bounce LR! "+currentVec.angleBetween(Vector3D.Y_AXIS));
currentVec.rotateAroundAxisLocal(Vector3D.Y_AXIS, 2*currentVec.angleBetween(Vector3D.Y_AXIS));
}
else if (currentY < 0) {
System.out.println("Bounce TB! "+currentVec.angleBetween(Vector3D.X_AXIS));
currentVec.rotateAroundAxisLocal(Vector3D.X_AXIS, 2*currentVec.angleBetween(Vector3D.X_AXIS));
}
else {
System.out.println("Bounce TB! "+currentVec.angleBetween(Vector3D.X_AXIS));
currentVec.rotateZ(-2*currentVec.angleBetween(Vector3D.X_AXIS));
}
currentVec = currentVec.getScaled(0.7f);//dampen bounces
currentX = U.minmax(currentX, 0, p.width);
currentY = U.minmax(currentY, 0, p.height);
}
return new MTFingerInputEvt((AbstractInputSource) evt
.getSource(), evt.getTargetComponent(), currentX
, currentY , evt.getId() + 2, m);
}
});
}
public abstract class FadeOut {
public boolean done = false;
public abstract void tick();
public void done() {
done = true;
}
}
public void tick() {
Iterator i = tickings.iterator();
FadeOut f;
while (i.hasNext()) {
f=(FadeOut) i.next();
f.tick();
if (f.done){
i.remove();
}
}
}
}