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