Blame mono/Assistance/KeyState.cs

c66393
using System;
c66393
c66393
namespace Assistance {
c66393
	public class KeyState<t> where T: IComparable, new() {</t>
c66393
		public struct Holder {
c66393
			public KeyState<t> state;</t>
c66393
			public long ticks;
c66393
			public double timeOffset;
c66393
			
c66393
			public Holder(KeyState<t> state, long ticks = 0, double timeOffset = 0.0) {</t>
c66393
				this.state = state;
c66393
				this.ticks = ticks;
c66393
				this.timeOffset = timeOffset;
c66393
			}
c66393
			
c66393
			public KeyState<t> find(T value)</t>
c66393
				{ return state == null ? null : state.find(value); }
c66393
			public bool isEmpty
c66393
				{ get { return state == null || state.isEmpty; } }
c66393
			public bool isPressed(T value)
c66393
				{ return find(value) != null; }
c66393
			public double howLongPressed(T value) {
c66393
				KeyState<t> state = find(value);</t>
c66393
				return state == null ? 0.0
c66393
				     : Math.Max(Timer.step, (ticks - state.ticks)*Timer.step + timeOffset);
c66393
			}
c66393
		}
c66393
	
c66393
		public static readonly T none = new T();
c66393
		public static readonly KeyState<t> empty = new KeyState<t>();</t></t>
c66393
		
c66393
		public readonly KeyState<t> previous;</t>
c66393
		public readonly long ticks;
c66393
		public readonly T value;
c66393
c66393
		public KeyState(): this(null, 0, none) { }
c66393
c66393
		private KeyState(KeyState<t> previous, long ticks, T value) {</t>
c66393
			this.previous = previous;
c66393
			this.ticks = ticks;
c66393
			this.value = value;
c66393
		}
c66393
		
c66393
		public KeyState<t> find(T value) {</t>
c66393
			if (value.CompareTo(none) == 0)
c66393
				return null;
c66393
			if (value.CompareTo(this.value) == 0)
c66393
				return this;
c66393
			if (previous == null)
c66393
				return null;
c66393
			return previous.find(value);
c66393
		}
c66393
		
c66393
		private KeyState<t> makeChainWithout(KeyState<t> ks) {</t></t>
c66393
			if (this == ks || previous == null) return previous;
c66393
			return new KeyState<t>(previous.makeChainWithout(ks), ticks, value);</t>
c66393
		}
c66393
		
c66393
		public KeyState<t> change(bool press, T value, long ticks) {</t>
c66393
			if (value.CompareTo(none) == 0)
c66393
				return this;
c66393
			if (ticks <= this.ticks)
c66393
				ticks = this.ticks + 1;
c66393
c66393
			KeyState<t> p = find(value);</t>
c66393
			if (press) {
c66393
				if (p != null) return this;
c66393
				return new KeyState<t>(isEmpty ? null : this, ticks, value);</t>
c66393
			}
c66393
c66393
			if (p == null) return this;
c66393
			KeyState<t> chain = makeChainWithout(p);</t>
c66393
			return chain == null ? new KeyState<t>() : chain;</t>
c66393
		}
c66393
		
c66393
		public bool isEmpty
c66393
			{ get { return value.CompareTo(none) == 0 && (previous == null || previous.isEmpty); } }
c66393
		public bool isPressed(T value)
c66393
			{ return find(value) != null; }
c66393
c66393
		public KeyState<t> press(T value, long ticks)</t>
c66393
			{ return change(true, value, ticks); }
c66393
		public KeyState<t> release(T value, long ticks)</t>
c66393
			{ return change(false, value, ticks); }
c66393
	}
c66393
}
c66393