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(
702257
									original.points[i0],
702257
									original.points[i1],
702257
									tangents[i0],
702257
									tangents[i1],
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
			
c3ebff
			if ( !track.isChanged
c3ebff
			  && track.points.Count == subTrack.points.Count
c3ebff
			  && track.points.Count == modifier.tangents.Count )
c3ebff
			  	return;
c3ebff
			
c3ebff
			if (!track.isChanged && subTrack.points.Count == track.points.Count - 1) {
c3ebff
				// add temporary point
702257
				modifier.tangents.Add(new Tangent());
c3ebff
				subTrack.points.Add(track.getLast());
c3ebff
				++subTrack.wayPointsAdded;
c3ebff
			} else {
c3ebff
				// apply permanent changes
c3ebff
				
c3ebff
				// remove points
c3ebff
				int start = track.points.Count - track.wayPointsAdded;
c3ebff
				if (start < 0) start = 0;
c3ebff
				if (start > 1) --start;
0f2bf8
				if (start < subTrack.points.Count) {
c3ebff
					subTrack.wayPointsRemoved += subTrack.points.Count - start;
0f2bf8
					subTrack.points.RemoveRange(start, subTrack.points.Count - start);
c3ebff
				}
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());
c3ebff
					subTrack.points.Add(track.getLast());
c3ebff
					++index;
c3ebff
				}
c3ebff
				
c3ebff
				// add points with tangents
c3ebff
				if (track.points.Count > 2) {
c3ebff
					while(index < track.points.Count - 1) {
702257
						Track.Point p0 = track.points[index-1];
702257
						Track.Point p1 = track.points[index];
702257
						Track.Point p2 = track.points[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);
702257
						subTrack.points.Add(p1);
c3ebff
						++index;
c3ebff
					}
c3ebff
				}
c3ebff
				
c3ebff
				track.wayPointsRemoved = 0;
c3ebff
				track.wayPointsAdded = 0;
c3ebff
				subTrack.wayPointsAdded += index - start;
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());
c3ebff
					subTrack.points.Add(track.getLast());
c3ebff
					++subTrack.wayPointsAdded;
c3ebff
				} else {
c3ebff
					// save key point
c3ebff
					modifier.holder = keyPoint.hold();
c3ebff
				}
c3ebff
			}
c3ebff
		}
c3ebff
	}
c3ebff
}
c3ebff