diff --git a/mono/Assistance/Assistance.csproj b/mono/Assistance/Assistance.csproj
index 2dedccc..e2127d1 100644
--- a/mono/Assistance/Assistance.csproj
+++ b/mono/Assistance/Assistance.csproj
@@ -54,11 +54,16 @@
-
-
+
+ MainWindow.cs
+
+
+
+
+
diff --git a/mono/Assistance/Geometry.cs b/mono/Assistance/Geometry.cs
index f9d248b..e9174cc 100644
--- a/mono/Assistance/Geometry.cs
+++ b/mono/Assistance/Geometry.cs
@@ -1,13 +1,24 @@
using System;
using System.Collections.Generic;
+using System.Linq.Expressions;
namespace Assistance {
public static class Geometry {
- public delegate Point TransformFunc(Point p);
-
public static readonly double precision = 1e-8;
+ public static readonly double precisionSqr = precision*precision;
public static readonly double sqrt2Pi = Math.Sqrt(2.0*Math.PI);
+ public static bool isEqual(double a, double b)
+ { return Math.Abs(b - a) <= precision; }
+ public static bool isGreaterOrEqual(double a, double b)
+ { return b - a <= precision; }
+ public static bool isLessOrEqual(double a, double b)
+ { return isGreaterOrEqual(b, a); }
+ public static bool isLess(double a, double b)
+ { return !isGreaterOrEqual(a, b); }
+ public static bool isGreater(double a, double b)
+ { return !isGreaterOrEqual(b, a); }
+
public static double logNormalDistribuitionUnscaled(double x, double x0, double w) {
return Math.Exp(-0.5*Math.Pow(Math.Log(x/x0)/w, 2.0))/x;
}
@@ -32,29 +43,75 @@ namespace Assistance {
}
}
- public static Point noTransform(Point point) {
- return point;
- }
+ public static class Interpolation {
+ public delegate T HalfFunc(T a, double b);
+ public delegate T FullFunc(T a, T b);
+
+ public static FullFunc add;
+ public static FullFunc sub;
+ public static HalfFunc mul;
+ public static HalfFunc div;
- public static Point transform(List funcs, Point point) {
- Point p = point;
- foreach(TransformFunc func in funcs)
- p = func(p);
- return p;
+ static Interpolation() {
+ { // add
+ ParameterExpression a = Expression.Parameter(typeof(T));
+ ParameterExpression b = Expression.Parameter(typeof(T));
+ add = Expression.Lambda(Expression.Add(a, b), a, b).Compile();
+ }
+ { // sub
+ ParameterExpression a = Expression.Parameter(typeof(T));
+ ParameterExpression b = Expression.Parameter(typeof(T));
+ sub = Expression.Lambda(Expression.Subtract(a, b), a, b).Compile();
+ }
+ { // mul
+ ParameterExpression a = Expression.Parameter(typeof(T));
+ ParameterExpression b = Expression.Parameter(typeof(double));
+ mul = Expression.Lambda(Expression.Multiply(a, b), a, b).Compile();
+ }
+ { // div
+ ParameterExpression a = Expression.Parameter(typeof(T));
+ ParameterExpression b = Expression.Parameter(typeof(double));
+ div = Expression.Lambda(Expression.Divide(a, b), a, b).Compile();
+ }
+ }
+
+ public static T linear(T p0, T p1, double l)
+ { return add(mul(sub(p1, p0), l), p0); }
+
+ public static double spline(T p0, T p1, T t0, T t1, double l) {
+ double ll = l*l;
+ double lll = ll*l;
+ return add( add( mul(p0, ( 2.0*lll - 3.0*ll + 1.0)),
+ mul(p1, (-2.0*lll + 3.0*ll )) ),
+ add( mul(t0, ( lll - 2.0*ll + l )),
+ mul(t1, ( lll - 1.0*ll )) ));
+ }
+
+ public static double splineTangent(T p0, T p1, T t0, T t1, double l) {
+ double ll = l*l;
+ return add( mul(sub(p0, p1), 6.0*(ll - l)),
+ add( mul(t0, ( 3.0*ll - 4.0*l + 1.0)),
+ mul(t1, ( 3.0*ll - 2.0*l )) ));
+ }
}
+
+ public static double interpolationLinear(double p0, double p1, double l)
+ { return (p1 - p0)*l + p0; }
- public static double splinePoint(double p0, double p1, double t0, double t1, double l) {
- return p0*(( 2.0*l - 3.0)*l*l + 1.0)
- + p1*((-2.0*l + 3.0)*l*l )
- + t0*(( l - 2.0)*l*l + l )
- + t1*(( l - 1.0)*l*l );
+ public static double interpolationSpline(double p0, double p1, double t0, double t1, double l) {
+ double ll = l*l;
+ double lll = ll*l;
+ return p0*( 2.0*lll - 3.0*ll + 1.0)
+ + p1*(-2.0*lll + 3.0*ll )
+ + t0*( lll - 2.0*ll + l )
+ + t1*( lll - 1.0*ll );
}
- public static Point splinePoint(Point p0, Point p1, Point t0, Point t1, double l) {
- return p0*(( 2.0*l - 3.0)*l*l + 1.0)
- + p1*((-2.0*l + 3.0)*l*l )
- + t0*(( l - 2.0)*l*l + l )
- + t1*(( l - 1.0)*l*l );
+ public static double interpolationSplineTangent(double p0, double p1, double t0, double t1, double l) {
+ double ll = l*l;
+ return (p0 - p1)*6.0*(ll - l)
+ + t0*( 3.0*ll - 4.0*l + 1.0)
+ + t1*( 3.0*ll - 2.0*l );
}
}
}
diff --git a/mono/Assistance/KeyHistory.cs b/mono/Assistance/KeyHistory.cs
index ea3fdaf..140e9cc 100644
--- a/mono/Assistance/KeyHistory.cs
+++ b/mono/Assistance/KeyHistory.cs
@@ -18,6 +18,12 @@ namespace Assistance {
heldTicks = history.hold(ticks);
}
+ public Holder offset(double timeOffset) {
+ return Geometry.isEqual(timeOffset, 0.0)
+ ? this
+ : new Holder(history, ticks, this.timeOffset + timeOffset);
+ }
+
public KeyState.Holder get(double time) {
long dticks = (long)Math.Ceiling(Timer.frequency*(time + timeOffset));
KeyState state = history.get(ticks + dticks);
@@ -75,7 +81,7 @@ namespace Assistance {
}
private long hold(long ticks) {
- long heldTicks = Math.Max(ticks, current.ticks);
+ long heldTicks = Math.Max(ticks, states[0].ticks);
locks.Insert(findLock(heldTicks) + 1, heldTicks);
return heldTicks;
}
diff --git a/mono/Assistance/Point.cs b/mono/Assistance/Point.cs
index 7814c8b..d3f4f7d 100644
--- a/mono/Assistance/Point.cs
+++ b/mono/Assistance/Point.cs
@@ -24,7 +24,7 @@ namespace Assistance {
{ return a.x*b.x + a.y*b.y; }
public bool isEqual(Point other)
- { return (this - other).lenSqr() <= Geometry.precision*Geometry.precision; }
+ { return (this - other).lenSqr() <= Geometry.precisionSqr; }
public double lenSqr()
{ return x*x + y*y; }
public double len()
@@ -32,7 +32,7 @@ namespace Assistance {
public Point normalize() {
double l = len();
- return l > Geometry.precision*Geometry.precision ? this/l : this;
+ return l > Geometry.precision ? this/l : this;
}
public Point rotate(double angle) {
diff --git a/mono/Assistance/Tool.cs b/mono/Assistance/Tool.cs
index a89a607..d0cc2ca 100644
--- a/mono/Assistance/Tool.cs
+++ b/mono/Assistance/Tool.cs
@@ -9,8 +9,10 @@ namespace Assistance {
Multiline = 4
};
-
- public class InputHandler {
+ public class Tool {
+ public Modifiers getAvailableModifiers()
+ { return Modifiers.None; }
+
public void activate() { }
public void keyPress(Gdk.Key key, InputState state) { }
@@ -25,46 +27,53 @@ namespace Assistance {
public bool paintApply() { return false; }
public void paintCancel() { }
- public void disactivate() { }
- }
+ public void draw(Cairo.Context context) { }
-
- public class InputModifier {
- public InputHandler getNext() { return null; }
-
- public void activate()
- { if (getNext() != null) getNext().activate(); }
-
- public void keyPress(Gdk.Key key, InputState state)
- { if (getNext() != null) getNext().keyPress(key, state); }
- public void keyRelease(Gdk.Key key, InputState state)
- { if (getNext() != null) getNext().keyRelease(key, state); }
- public void buttonPress(Gdk.Device device, uint button, InputState state)
- { if (getNext() != null) getNext().buttonPress(device, button, state); }
- public void buttonRelease(Gdk.Device device, uint button, InputState state)
- { if (getNext() != null) getNext().buttonRelease(device, button, state); }
-
- public bool paintBegin()
- { return getNext() == null ? false : getNext().paintBegin(); }
- public void paintTrackBegin(Track track)
- { if (getNext() != null) getNext().paintTrackBegin(track); }
- public void paintTrackPoint(Track track)
- { if (getNext() != null) getNext().paintTrackPoint(track); }
- public void paintTrackEnd(Track track)
- { if (getNext() != null) getNext().paintTrackEnd(track); }
- public bool paintApply()
- { return getNext() == null ? false : getNext().paintApply(); }
- public void paintCancel()
- { if (getNext() != null) getNext().paintCancel(); }
-
- public void disactivate()
- { if (getNext() != null) getNext().disactivate(); }
- }
-
-
- public class Tool: InputHandler {
- public Modifiers getAvailableModifiers()
- { return Modifiers.None; }
+ public void deactivate() { }
}
}
+/*
+TODO:
+ //////////////////////////////////////////
+ // deprecated
+ //////////////////////////////////////////
+
+ public static readonly Pen pen = new Pen("Dark Green", 3.0);
+ public static readonly Pen penSpecial = new Pen("Blue", 3.0);
+ public static readonly Pen penPreview = new Pen("Dark Green", 1.0, 0.25);
+
+ public void draw(Cairo.Context context, bool preview = false) {
+ if (preview) {
+ if (points.Count < 2)
+ return;
+ context.Save();
+ penPreview.apply(context);
+ context.MoveTo(points[0].point.x, points[0].point.y);
+ for(int i = 1; i < points.Count; ++i)
+ context.LineTo(points[i].point.x, points[i].point.y);
+ context.Stroke();
+ context.Restore();
+ } else {
+ context.Save();
+ pen.apply(context);
+ foreach(TrackPoint p in points) {
+ double t = p.keyState.howLongPressed(Gdk.Key.m)
+ + p.buttonState.howLongPressed(3);
+ double w = p.pressure*pen.width + 5.0*t;
+ context.Arc(p.point.x, p.point.y, 2.0*w, 0.0, 2.0*Math.PI);
+ context.Fill();
+ }
+ context.Restore();
+ }
+ }
+
+ public Rectangle getBounds() {
+ if (points.Count == 0)
+ return new Rectangle();
+ Rectangle bounds = new Rectangle(points[0].point);
+ foreach(TrackPoint p in points)
+ bounds = bounds.expand(p.point);
+ return bounds.inflate(Math.Max(pen.width, penPreview.width) + 2.0);
+ }
+*/
\ No newline at end of file
diff --git a/mono/Assistance/Track.cs b/mono/Assistance/Track.cs
index 8e6cc0c..66cf7b0 100644
--- a/mono/Assistance/Track.cs
+++ b/mono/Assistance/Track.cs
@@ -4,143 +4,256 @@ using Assistance.Drawing;
namespace Assistance {
public class Track {
- public static readonly Pen pen = new Pen("Dark Green", 3.0);
- public static readonly Pen penSpecial = new Pen("Blue", 3.0);
- public static readonly Pen penPreview = new Pen("Dark Green", 1.0, 0.25);
+ public class Owner { }
+
+ public class Handler {
+ public readonly Owner owner;
+ public readonly Track original;
+ public readonly List