refine input event system and binding logic to allow more natural use of modifier keys as hotkeys

This commit is contained in:
zeromus 2012-11-09 20:03:59 +00:00
parent e13e3257c1
commit 9053ac5b67
5 changed files with 90 additions and 41 deletions

View File

@ -109,7 +109,7 @@ namespace BizHawk.MultiClient
{ {
return Button.GetHashCode() ^ Modifiers.GetHashCode(); return Button.GetHashCode() ^ Modifiers.GetHashCode();
} }
public static bool operator==(LogicalButton lhs, LogicalButton rhs) public static bool operator ==(LogicalButton lhs, LogicalButton rhs)
{ {
return lhs.Button == rhs.Button && lhs.Modifiers == rhs.Modifiers; return lhs.Button == rhs.Button && lhs.Modifiers == rhs.Modifiers;
} }
@ -130,6 +130,7 @@ namespace BizHawk.MultiClient
WorkingDictionary<string, object> ModifierState = new WorkingDictionary<string, object>(); WorkingDictionary<string, object> ModifierState = new WorkingDictionary<string, object>();
WorkingDictionary<string, bool> LastState = new WorkingDictionary<string, bool>(); WorkingDictionary<string, bool> LastState = new WorkingDictionary<string, bool>();
WorkingDictionary<string, bool> UnpressState = new WorkingDictionary<string, bool>();
HashSet<string> IgnoreKeys = new HashSet<string>(new[] { "LeftShift", "RightShift", "LeftControl", "RightControl", "LeftAlt", "RightAlt" }); HashSet<string> IgnoreKeys = new HashSet<string>(new[] { "LeftShift", "RightShift", "LeftControl", "RightControl", "LeftAlt", "RightAlt" });
void HandleButton(string button, bool newState) void HandleButton(string button, bool newState)
@ -137,11 +138,28 @@ namespace BizHawk.MultiClient
if (EnableIgnoreModifiers && IgnoreKeys.Contains(button)) return; if (EnableIgnoreModifiers && IgnoreKeys.Contains(button)) return;
if (LastState[button] && newState) return; if (LastState[button] && newState) return;
if (!LastState[button] && !newState) return; if (!LastState[button] && !newState) return;
if (UnpressState.ContainsKey(button))
{
if (newState) return;
Console.WriteLine("Removing Unpress {0} with newState {1}", button, newState);
UnpressState.Remove(button);
LastState[button] = false;
return;
}
//dont generate events for things like Ctrl+LeftControl
ModifierKey mods = _Modifiers;
if (button == "LeftShift") mods &= ~ModifierKey.Shift;
if (button == "RightShift") mods &= ~ModifierKey.Shift;
if (button == "LeftControl") mods &= ~ModifierKey.Control;
if (button == "RightControl") mods &= ~ModifierKey.Control;
if (button == "LeftAlt") mods &= ~ModifierKey.Alt;
if (button == "RightAlt") mods &= ~ModifierKey.Alt;
var ie = new InputEvent(); var ie = new InputEvent();
ie.EventType = newState ? InputEventType.Press : InputEventType.Release; ie.EventType = newState ? InputEventType.Press : InputEventType.Release;
ie.LogicalButton = new LogicalButton(button, _Modifiers); ie.LogicalButton = new LogicalButton(button, mods);
_NewEvents.Add(ie);
LastState[button] = newState; LastState[button] = newState;
//track the pressed events with modifiers that we send so that we can send corresponding unpresses with modifiers //track the pressed events with modifiers that we send so that we can send corresponding unpresses with modifiers
@ -153,21 +171,23 @@ namespace BizHawk.MultiClient
//so, i am adding it as of 11-sep-2011 //so, i am adding it as of 11-sep-2011
if (newState) if (newState)
{ {
ModifierState[button] = ie.LogicalButton; ModifierState[button] = ie.LogicalButton;
} }
else else
{ {
if (ModifierState[button] != null) if (ModifierState[button] != null)
{ {
LogicalButton alreadyReleased = ie.LogicalButton; LogicalButton alreadyReleased = ie.LogicalButton;
ie = new InputEvent(); var ieModified = new InputEvent();
ie.LogicalButton = (LogicalButton)ModifierState[button]; ieModified.LogicalButton = (LogicalButton)ModifierState[button];
ie.EventType = InputEventType.Release; ieModified.EventType = InputEventType.Release;
if(ie.LogicalButton != alreadyReleased) if (ieModified.LogicalButton != alreadyReleased)
_NewEvents.Add(ie); _NewEvents.Add(ieModified);
} }
ModifierState[button] = null; ModifierState[button] = null;
} }
_NewEvents.Add(ie);
} }
ModifierKey _Modifiers; ModifierKey _Modifiers;
@ -182,7 +202,7 @@ namespace BizHawk.MultiClient
} }
} }
Queue<InputEvent> InputEvents = new Queue<InputEvent>(); Queue<InputEvent> InputEvents = new Queue<InputEvent>();
public InputEvent DequeueEvent() public InputEvent DequeueEvent()
{ {
lock (this) lock (this)
@ -205,15 +225,15 @@ namespace BizHawk.MultiClient
for (; ; ) for (; ; )
{ {
KeyInput.Update(); KeyInput.Update();
GamePad.UpdateAll(); GamePad.UpdateAll();
GamePad360.UpdateAll(); GamePad360.UpdateAll();
_Modifiers = KeyInput.GetModifierKeysAsKeys(); _Modifiers = KeyInput.GetModifierKeysAsKeys();
_NewEvents.Clear(); _NewEvents.Clear();
//analyze keys //analyze keys
var bleh = new HashSet<Key>(); var bleh = new HashSet<Key>();
foreach(var k in KeyInput.State.PressedKeys) foreach (var k in KeyInput.State.PressedKeys)
bleh.Add(k); bleh.Add(k);
foreach (var k in KeyInput.State.AllKeys) foreach (var k in KeyInput.State.AllKeys)
if (bleh.Contains(k)) if (bleh.Contains(k))
@ -221,22 +241,22 @@ namespace BizHawk.MultiClient
else else
HandleButton(k.ToString(), false); HandleButton(k.ToString(), false);
//analyze xinput //analyze xinput
for (int i = 0; i < GamePad360.Devices.Count; i++) for (int i = 0; i < GamePad360.Devices.Count; i++)
{ {
var pad = GamePad360.Devices[i]; var pad = GamePad360.Devices[i];
string xname = "X" + (i + 1) + " "; string xname = "X" + (i + 1) + " ";
for (int b = 0; b < pad.NumButtons; b++) for (int b = 0; b < pad.NumButtons; b++)
HandleButton(xname + pad.ButtonName(b), pad.Pressed(b)); HandleButton(xname + pad.ButtonName(b), pad.Pressed(b));
} }
//analyze joysticks //analyze joysticks
for (int i = 0; i < GamePad.Devices.Count; i++) for (int i = 0; i < GamePad.Devices.Count; i++)
{ {
var pad = GamePad.Devices[i]; var pad = GamePad.Devices[i];
string jname = "J" + (i + 1) + " "; string jname = "J" + (i + 1) + " ";
for (int b = 0; b < pad.NumButtons; b++) for (int b = 0; b < pad.NumButtons; b++)
HandleButton(jname + pad.ButtonName(b), pad.Pressed(b)); HandleButton(jname + pad.ButtonName(b), pad.Pressed(b));
} }
@ -264,12 +284,41 @@ namespace BizHawk.MultiClient
} }
//returns the next Press event, if available. should be useful //returns the next Press event, if available. should be useful
public string GetNextPressedButtonOrNull() public string GetNextBindEvent()
{ {
InputEvent ie = DequeueEvent(); if (InputEvents.Count == 0) return null;
if (ie == null) return null;
if (ie.EventType == InputEventType.Release) return null; //we only listen to releases for input binding, because we need to distinguish releases of pure modifierkeys from modified keys
return ie.LogicalButton.ToString(); //if you just pressed ctrl, wanting to bind ctrl, we'd see: pressed:ctrl, unpressed:ctrl
//if you just pressed ctrl+c, wanting to bind ctrl+c, we'd see: pressed:ctrl, pressed:ctrl+c, unpressed:ctrl+c, unpressed:ctrl
//so its the first unpress we need to listen for
while (InputEvents.Count != 0)
{
var ie = DequeueEvent();
//as a special perk, we'll accept escape immediately
if (ie.EventType == InputEventType.Press && ie.LogicalButton.Button == "Escape")
goto ACCEPT;
if (ie.EventType == InputEventType.Press) continue;
ACCEPT:
Console.WriteLine("Bind Event: {0} ", ie);
foreach (var kvp in LastState)
if (kvp.Value)
{
Console.WriteLine("Unpressing " + kvp.Key);
UnpressState[kvp.Key] = true;
}
InputEvents.Clear();
return ie.LogicalButton.ToString();
}
return null;
} }
//controls whether modifier keys will be ignored as key press events //controls whether modifier keys will be ignored as key press events

View File

@ -97,14 +97,14 @@ namespace BizHawk.MultiClient
protected override void OnShown(EventArgs e) protected override void OnShown(EventArgs e)
{ {
Input.Instance.EnableIgnoreModifiers = true; //Input.Instance.EnableIgnoreModifiers = true;
base.OnShown(e); base.OnShown(e);
} }
protected override void OnClosed(EventArgs e) protected override void OnClosed(EventArgs e)
{ {
base.OnClosed(e); base.OnClosed(e);
Input.Instance.EnableIgnoreModifiers = false; //Input.Instance.EnableIgnoreModifiers = false;
} }
private void SetAutoTab(bool setting) private void SetAutoTab(bool setting)

View File

@ -122,14 +122,14 @@ namespace BizHawk.MultiClient
protected override void OnShown(EventArgs e) protected override void OnShown(EventArgs e)
{ {
Input.Instance.EnableIgnoreModifiers = true; //Input.Instance.EnableIgnoreModifiers = true;
base.OnShown(e); base.OnShown(e);
} }
protected override void OnClosed(EventArgs e) protected override void OnClosed(EventArgs e)
{ {
base.OnClosed(e); base.OnClosed(e);
Input.Instance.EnableIgnoreModifiers = false; //Input.Instance.EnableIgnoreModifiers = false;
} }
private void IDB_SAVE_Click(object sender, EventArgs e) private void IDB_SAVE_Click(object sender, EventArgs e)

View File

@ -68,14 +68,14 @@ namespace BizHawk.MultiClient
protected override void OnShown(EventArgs e) protected override void OnShown(EventArgs e)
{ {
Input.Instance.EnableIgnoreModifiers = true; //Input.Instance.EnableIgnoreModifiers = true;
base.OnShown(e); base.OnShown(e);
} }
protected override void OnClosed(EventArgs e) protected override void OnClosed(EventArgs e)
{ {
base.OnClosed(e); base.OnClosed(e);
Input.Instance.EnableIgnoreModifiers = false; //Input.Instance.EnableIgnoreModifiers = false;
} }
private void Do(string platform) private void Do(string platform)

View File

@ -90,7 +90,7 @@ namespace BizHawk.MultiClient
//Input.Update(); //Input.Update();
//zero: ??? what is this all about ??? //zero: ??? what is this all about ???
wasPressed = Input.Instance.GetNextPressedButtonOrNull(); wasPressed = Input.Instance.GetNextBindEvent();
} }
protected override void OnLeave(EventArgs e) protected override void OnLeave(EventArgs e)
@ -115,7 +115,7 @@ namespace BizHawk.MultiClient
private void ReadKeys() private void ReadKeys()
{ {
Input.Instance.Update(); Input.Instance.Update();
string TempBindingStr = Input.Instance.GetNextPressedButtonOrNull(); string TempBindingStr = Input.Instance.GetNextBindEvent();
if (wasPressed != "" && TempBindingStr == wasPressed) if (wasPressed != "" && TempBindingStr == wasPressed)
{ {
return; return;