Blame mono/Assistance/InputModifierTangents.cs

c3ebff
using System;
c3ebff
using System.Collections.Generic;
c3ebff
c3ebff
namespace Assistance {
c3ebff
	public class InputModifierTangents: InputManager.Modifier {
702257
		public struct Tangent {
702257
			public Point position;
702257
			public double pressure;
702257
			public Point tilt;
702257
			
702257
			public Tangent(
702257
				Point position,
702257
				double pressure = 0.0,
702257
				Point tilt = new Point() )
702257
			{
702257
				this.position = position;
702257
				this.pressure = pressure;
702257
				this.tilt = tilt;
702257
			}
702257
		}
702257
	
c3ebff
		public class Modifier: Track.Modifier {
589f9a
			public Modifier(Track.Handler handler):
c3ebff
				base(handler) { }
c3ebff
			
c3ebff
			public InputManager.KeyPoint.Holder holder = null;
702257
			public readonly List<tangent> tangents = new List<tangent>();</tangent></tangent>
c3ebff
			
702257
			public override Track.Point calcPoint(double originalIndex) {
c3ebff
				double frac;
c3ebff
				int i0 = original.floorIndex(originalIndex, out frac);
c3ebff
				int i1 = original.ceilIndex(originalIndex);
702257
				Track.Point p = i0 < 0 ? new Track.Point()
702257
				              : interpolateSpline(
72d2fd
									original[i0],
72d2fd
									original[i1],
72d2fd
									i0 < tangents.Count ? tangents[i0] : new Tangent(),
72d2fd
									i1 < tangents.Count ? tangents[i1] : new Tangent(),
702257
									frac );
7bbf70
				p.originalIndex = originalIndex;
7bbf70
				return p;
c3ebff
			}
c3ebff
		}
c3ebff
702257
		public static Track.Point interpolateSpline(Track.Point p0, Track.Point p1, Tangent t0, Tangent t1, double l) {
702257
			if (l <= Geometry.precision) return p0;
702257
			if (l >= 1.0 - Geometry.precision) return p1;
702257
			return new Track.Point(
702257
				Geometry.interpolationSpline(p0.position, p1.position, t0.position, t1.position, l),
702257
				Geometry.interpolationSpline(p0.pressure, p1.pressure, t0.pressure, t1.pressure, l),
702257
				Geometry.interpolationSpline(p0.tilt, p1.tilt, t0.tilt, t1.tilt, l),
702257
				Geometry.interpolationLinear(p0.originalIndex, p1.originalIndex, l),
702257
				Geometry.interpolationLinear(p0.time, p1.time, l),
702257
				Geometry.interpolationLinear(p0.length, p1.length, l) );
702257
		}
702257
589f9a
		public override void modify(Track track, InputManager.KeyPoint keyPoint, List<track> outTracks) {
c3ebff
			if (track.handler == null) {
c3ebff
				track.handler = new Track.Handler(this, track);
c3ebff
				track.handler.tracks.Add(new Track( new Modifier(track.handler) ));
c3ebff
			}
c3ebff
			
c3ebff
			Track subTrack = track.handler.tracks[0];
c3ebff
			Modifier modifier = (Modifier)subTrack.modifier;
c3ebff
			outTracks.Add(subTrack);
c3ebff
			
72d2fd
			if ( !track.wasChanged
72d2fd
			  && track.count == subTrack.count
72d2fd
			  && track.count == modifier.tangents.Count )
c3ebff
			  	return;
c3ebff
			
72d2fd
			if (!track.wasChanged && subTrack.count == track.count - 1) {
c3ebff
				// add temporary point
702257
				modifier.tangents.Add(new Tangent());
72d2fd
				subTrack.add(track.getLast());
c3ebff
			} else {
c3ebff
				// apply permanent changes
c3ebff
				
c3ebff
				// remove points
72d2fd
				int start = track.count - track.pointsAdded;
c3ebff
				if (start < 0) start = 0;
c3ebff
				if (start > 1) --start;
72d2fd
				subTrack.truncate(start);
0f2bf8
				if (start < modifier.tangents.Count)
c3ebff
					modifier.tangents.RemoveRange(start, modifier.tangents.Count - start);
c3ebff
				
c3ebff
				// add first point
c3ebff
				int index = start;
c3ebff
				if (index == 0) {
702257
					modifier.tangents.Add(new Tangent());
72d2fd
					subTrack.add(track.getLast());
c3ebff
					++index;
c3ebff
				}
c3ebff
				
c3ebff
				// add points with tangents
72d2fd
				if (track.count > 2) {
72d2fd
					while(index < track.count) {
72d2fd
						Track.Point p0 = track[index-1];
72d2fd
						Track.Point p1 = track[index];
72d2fd
						Track.Point p2 = track[index+1];
702257
						double dt = p2.time - p0.time;
702257
						double k = dt > Geometry.precision ? (p1.time - p0.time)/dt : 0.0;
702257
						Tangent tangent = new Tangent(
702257
							(p2.position - p0.position)*k,
702257
							(p2.pressure - p0.pressure)*k,
702257
							(p2.tilt - p0.tilt)*k );
702257
						modifier.tangents.Add(tangent);
72d2fd
						subTrack.add(p1);
c3ebff
						++index;
c3ebff
					}
c3ebff
				}
c3ebff
				
72d2fd
				track.resetCounters();
c3ebff
				
c3ebff
				// release previous key point
589f9a
				if (modifier.holder != null) {
1d3aae
					modifier.holder.Dispose();
1d3aae
					modifier.holder = null;
1d3aae
				}
c3ebff
				
589f9a
				if (track.isFinished()) {
c3ebff
					// finish
702257
					modifier.tangents.Add(new Tangent());
72d2fd
					subTrack.add(track.getLast());
c3ebff
				} else {
c3ebff
					// save key point
c3ebff
					modifier.holder = keyPoint.hold();
c3ebff
				}
c3ebff
			}
c3ebff
		}
c3ebff
	}
c3ebff
}
c3ebff