refine input event system and binding logic to allow more natural use of modifier keys as hotkeys
This commit is contained in:
parent
e13e3257c1
commit
9053ac5b67
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue