|
|
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; }
|
|
|
38c95c |
public double howLongPressed(T value)
|
|
|
38c95c |
{ return howLongPressed(find(value), ticks, timeOffset); }
|
|
|
38c95c |
|
|
|
38c95c |
public static double howLongPressed(KeyState<t> state, long ticks, double timeOffset) {</t>
|
|
|
c66393 |
return state == null ? 0.0
|
|
|
c66393 |
: Math.Max(Timer.step, (ticks - state.ticks)*Timer.step + timeOffset);
|
|
|
c66393 |
}
|
|
|
c66393 |
}
|
|
|
a6a507 |
|
|
|
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 |
|