Blame mono/Assistance/KeyState.cs

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