redo some of client input and hotkey handling

This commit is contained in:
zeromus 2011-07-09 22:09:39 +00:00
parent 003b7ebebf
commit 9355bc0f2e
8 changed files with 379 additions and 472 deletions

View File

@ -14,6 +14,20 @@ namespace BizHawk.MultiClient
private List<string> removeFromForcePressedButtons = new List<string>();
private List<string> programmaticallyPressedButtons = new List<string>();
public List<string> SearchBindings(string button)
{
var ret = new List<string>();
foreach (var kvp in bindings)
{
foreach (var bound_button in kvp.Value)
{
if (bound_button == button)
ret.Add(kvp.Key);
}
}
return ret;
}
public Controller(ControllerDefinition definition)
{
type = definition;
@ -67,6 +81,7 @@ namespace BizHawk.MultiClient
return false;
}
//zeromus - TODO - this is gross!!!
if (Global.Config.AllowUD_LR == false)
{
string prefix;
@ -93,7 +108,7 @@ namespace BizHawk.MultiClient
bool sticky = stickyButtons[button];
foreach (var control in bindings[button])
if (Input.IsPressed(control))
if (Input.Instance.IsPressed(control))
return sticky ? false : true;
return sticky ? true : false;

View File

@ -1,143 +1,187 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Forms;
using SlimDX.DirectInput;
//maybe todo - split into an event processor class (which can grab events from the main input class and be used to step through them independently)
namespace BizHawk.MultiClient
{
public static class Input
public class Input
{
public static Input Instance { get; private set; }
Thread UpdateThread;
private Input()
{
UpdateThread = new Thread(UpdateThreadProc);
UpdateThread.IsBackground = true;
UpdateThread.Start();
}
public static void Initialize()
{
KeyInput.Initialize();
GamePad.Initialize();
Instance = new Input();
}
public static void Update()
public enum InputEventType
{
KeyInput.Update();
GamePad.UpdateAll();
Press, Release
}
public static bool IsPressed(string control)
public struct LogicalButton
{
if (Global.Config.AcceptBackgroundInput == false && Form.ActiveForm == null)
return false; // application isn't active and background input is disabled
// Check joystick first, its easier
if (control.StartsWith("J1 ")) return GetGamePad(0, control.Substring(3));
if (control.StartsWith("J2 ")) return GetGamePad(1, control.Substring(3));
if (control.StartsWith("J3 ")) return GetGamePad(2, control.Substring(3));
if (control.StartsWith("J4 ")) return GetGamePad(3, control.Substring(3));
// Keyboard time.
// Keyboard bindings are significantly less free-form than they were previously.
// They are no longer just a list of keys which must be pressed simultaneously.
// Bindings are assumed to be in the form of 0, 1, 2, or 3 modifiers (Ctrl, Alt, Shift),
// plus one non-modifier key, which is at the end.
// It is not possible to bind to two non-modifier keys together as a chorded hotkey.
int lastCombinerPosition = control.LastIndexOf('+');
if (lastCombinerPosition < 0)
{
// No modifiers in this key binding.
// Verify that no modifiers are currently pressed.
if (KeyInput.CtrlModifier || KeyInput.ShiftModifier || KeyInput.AltModifier)
return false;
Key k = (Key) Enum.Parse(typeof (Key), control, true);
return KeyInput.IsPressed(k);
}
// 1 or more modifiers present in binding. First, lets identify the non-modifier key and check if it's pressed.
string nonModifierString = control.Substring(lastCombinerPosition+1);
Key nonModifierKey = (Key)Enum.Parse(typeof(Key), nonModifierString, true);
if (KeyInput.IsPressed(nonModifierKey) == false)
return false; // non-modifier key isn't pressed anyway, exit out
// non-modifier key IS pressed, now we need to ensure the modifiers match exactly
if (control.Contains("Ctrl+") ^ KeyInput.CtrlModifier) return false;
if (control.Contains("Shift+") ^ KeyInput.ShiftModifier) return false;
if (control.Contains("Alt+") ^ KeyInput.AltModifier) return false;
// You have passed all my tests, you may consider yourself pressed.
// Man, I'm winded.
return true;
}
private static bool IsPressedSingle(string control)
{
if (string.IsNullOrEmpty(control))
return false;
if (control.StartsWith("J1 ")) return GetGamePad(0, control.Substring(3));
if (control.StartsWith("J2 ")) return GetGamePad(1, control.Substring(3));
if (control.StartsWith("J3 ")) return GetGamePad(2, control.Substring(3));
if (control.StartsWith("J4 ")) return GetGamePad(3, control.Substring(3));
if (control.Contains("RightShift"))
control = control.Replace("RightShift", "LeftShift");
if (control.Contains("RightControl"))
control = control.Replace("RightControl", "LeftControl");
if (control.Contains("RightAlt"))
control = control.Replace("RightAlt", "LeftAlt");
if (control.Contains("Ctrl"))
control = control.Replace("Ctrl", "LeftControl");
if (control.Contains("Shift") && control != "LeftShift")
control = control.Replace("Shift", "LeftShift");
if (control.Contains("Control") && control.Trim() != "LeftControl")
control = control.Replace("Control", "LeftControl");
if (control.Contains("Ctrl") && control.Trim() != "LeftControl")
control = control.Replace("Control", "LeftControl");
if (control.Contains("Alt") && control != "LeftAlt")
control = control.Replace("Alt", "LeftAlt");
Key k = (Key)Enum.Parse(typeof(Key), control, true);
return KeyInput.IsPressed(k);
}
private static bool GetGamePad(int index, string control)
{
if (index >= GamePad.Devices.Count)
return false;
if (control == "Up") return GamePad.Devices[index].Up;
if (control == "Down") return GamePad.Devices[index].Down;
if (control == "Left") return GamePad.Devices[index].Left;
if (control == "Right") return GamePad.Devices[index].Right;
if (control.StartsWith("B"))
public LogicalButton(string button, Keys modifiers)
{
int buttonIndex = int.Parse(control.Substring(1)) - 1;
if (buttonIndex >= GamePad.Devices[index].Buttons.Length)
return false;
return GamePad.Devices[index].Buttons[buttonIndex];
Button = button;
Modifiers = modifiers;
}
public string Button;
public Keys Modifiers;
public override string ToString()
{
string ret = "";
if ((Modifiers & Keys.Control) != 0) ret += "Ctrl+";
if ((Modifiers & Keys.Alt) != 0) ret += "Alt+";
if ((Modifiers & Keys.Shift) != 0) ret += "Shift+";
ret += Button;
return ret;
}
}
public class InputEvent
{
public LogicalButton LogicalButton;
public InputEventType EventType;
}
//coalesces events back into instantaneous states
class InputCoalescer
{
public void Receive(InputEvent ie)
{
bool state = ie.EventType == InputEventType.Press;
State[ie.LogicalButton.ToString()] = state;
LogicalButton unmodified = ie.LogicalButton;
unmodified.Modifiers = Keys.None;
UnmodifiedState[unmodified.ToString()] = state;
}
return false;
public WorkingDictionary<string, bool> State = new WorkingDictionary<string, bool>();
public WorkingDictionary<string, bool> UnmodifiedState = new WorkingDictionary<string, bool>();
}
public static string GetPressedKey()
InputCoalescer Coalescer = new InputCoalescer();
WorkingDictionary<string, bool> LastState = new WorkingDictionary<string, bool>();
HashSet<string> Ignore = new HashSet<string>(new[] { "LeftShift", "RightShift" });
void HandleButton(string button, bool newState)
{
// Poll Joystick input
for (int j = 0; j < GamePad.Devices.Count; j++)
if (Ignore.Contains(button)) return;
if (LastState[button] && newState) return;
if (!LastState[button] && !newState) return;
var ie = new InputEvent();
ie.EventType = newState ? InputEventType.Press : InputEventType.Release;
ie.LogicalButton = new LogicalButton(button, _Modifiers);
_NewEvents.Add(ie);
LastState[button] = newState;
}
Keys _Modifiers;
List<InputEvent> _NewEvents = new List<InputEvent>();
//TODO - maybe need clearevents for various purposes? maybe not.
Queue<InputEvent> InputEvents = new Queue<InputEvent>();
public InputEvent DequeueEvent()
{
lock (this)
{
if (GamePad.Devices[j].Up) return "J" + (j+1) + " Up";
if (GamePad.Devices[j].Down) return "J" + (j+1) + " Down";
if (GamePad.Devices[j].Left) return "J" + (j+1) + " Left";
if (GamePad.Devices[j].Right) return "J" + (j+1) + " Right";
var buttons = GamePad.Devices[j].Buttons;
for (int b=0; b<buttons.Length; b++)
{
if (buttons[b])
return "J" + (j+1) + " B" + (b+1);
}
if (InputEvents.Count == 0) return null;
else return InputEvents.Dequeue();
}
}
void EnqueueEvent(InputEvent ie)
{
lock (this)
{
InputEvents.Enqueue(ie);
Coalescer.Receive(ie);
}
}
return KeyInput.GetPressedKey();
public bool CheckState(string button) { lock (this) return Coalescer.State[button]; }
public bool CheckStateUnmodified(string button) { lock (this) return Coalescer.UnmodifiedState[button]; }
void UpdateThreadProc()
{
for(;;)
{
KeyInput.Update();
GamePad.UpdateAll();
_Modifiers = KeyInput.GetModifierKeysAsKeys();
_NewEvents.Clear();
//analyze keys
foreach (var key in KeyInput.State.PressedKeys) HandleButton(key.ToString(), true);
foreach (var key in KeyInput.State.ReleasedKeys) HandleButton(key.ToString(), false);
//analyze joysticks
for (int i = 0; i < GamePad.Devices.Count; i++)
{
var pad = GamePad.Devices[i];
string jname = "J" + (i + 1) + " ";
HandleButton(jname + "Up", pad.Up);
HandleButton(jname + "Down", pad.Down);
HandleButton(jname + "Left", pad.Left);
HandleButton(jname + "Right", pad.Right);
for (int b = 0; b < pad.Buttons.Length; b++)
HandleButton(jname + "B" + (b + 1), pad.Buttons[b]);
}
bool swallow = (Global.Config.AcceptBackgroundInput == false && Form.ActiveForm == null);
foreach (var ie in _NewEvents)
{
//events are swallowed in some cases:
if (ie.EventType == InputEventType.Press && swallow)
{ }
else
EnqueueEvent(ie);
}
//arbitrary selection of polling frequency:
Thread.Sleep(10);
}
}
public void Update()
{
//TODO - for some reason, we may want to control when the next event processing step happens
//so i will leave this method here for now..
}
public bool IsPressed(string control)
{
return Instance.CheckState(control);
}
public string GetNextPressedButtonOrNull()
{
InputEvent ie = Instance.DequeueEvent();
if (ie == null) return null;
if (ie.EventType == InputEventType.Release) return null;
return ie.LogicalButton.ToString();
}
}
}

View File

@ -113,6 +113,15 @@ namespace BizHawk.MultiClient
}
}
public static System.Windows.Forms.Keys GetModifierKeysAsKeys()
{
System.Windows.Forms.Keys ret = System.Windows.Forms.Keys.None;
if (ShiftModifier) ret |= System.Windows.Forms.Keys.Shift;
if (CtrlModifier) ret |= System.Windows.Forms.Keys.Control;
if (AltModifier) ret |= System.Windows.Forms.Keys.Alt;
return ret;
}
public static string GetModifierKeys()
{
StringBuilder sb = new StringBuilder(16);

View File

@ -314,7 +314,7 @@ namespace BizHawk.MultiClient
{
for (; ; )
{
Input.Update();
Input.Instance.Update();
CheckHotkeys();
StepRunLoop_Core();
@ -956,27 +956,198 @@ namespace BizHawk.MultiClient
[System.Security.SuppressUnmanagedCodeSecurity, DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern bool PeekMessage(out Message msg, IntPtr hWnd, UInt32 msgFilterMin, UInt32 msgFilterMax, UInt32 flags);
void OnSelectSlot(int num)
{
SaveSlot = num;
SaveSlotSelectedMessage();
UpdateStatusSlots();
}
public void CheckHotkeys()
{
if (Global.ClientControls["ToolBox"])
for(;;)
{
LoadToolBox();
Global.ClientControls.UnpressButton("ToolBox");
}
var ie = Input.Instance.DequeueEvent();
if(ie == null) break;
if (Global.ClientControls["Quick Save State"])
{
if (!IsNullEmulator())
SaveState("QuickSave" + SaveSlot.ToString());
Global.ClientControls.UnpressButton("Quick Save State");
}
//TODO - wonder what happens if we pop up something interactive as a response to one of these hotkeys? may need to purge further processing
if (Global.ClientControls["Quick Load State"])
{
if (!IsNullEmulator())
LoadState("QuickSave" + SaveSlot.ToString());
Global.ClientControls.UnpressButton("Quick Load State");
}
//TODO - deal with these later somehow
if(ie.EventType == Input.InputEventType.Release) return;
var triggers = Global.ClientControls.SearchBindings(ie.LogicalButton.ToString());
foreach(var trigger in triggers)
{
//todo - could have these in a table somehow ?
switch (trigger)
{
case "ToolBox":
LoadToolBox();
break;
case "Quick Save State":
if (!IsNullEmulator())
SaveState("QuickSave" + SaveSlot.ToString());
break;
case "Quick Load State":
if (!IsNullEmulator())
LoadState("QuickSave" + SaveSlot.ToString());
break;
case "Unthrottle":
unthrottled ^= true;
Global.RenderPanel.AddMessage("Unthrottled: " + unthrottled);
break;
case "Hard Reset":
LoadRom(CurrentlyOpenRom);
break;
case "Screenshot":
TakeScreenshot();
break;
case "SaveSlot0": if (!IsNullEmulator()) SaveState("QuickSave0"); break;
case "SaveSlot1": if (!IsNullEmulator()) SaveState("QuickSave1"); break;
case "SaveSlot2": if (!IsNullEmulator()) SaveState("QuickSave2"); break;
case "SaveSlot3": if (!IsNullEmulator()) SaveState("QuickSave3"); break;
case "SaveSlot4": if (!IsNullEmulator()) SaveState("QuickSave4"); break;
case "SaveSlot5": if (!IsNullEmulator()) SaveState("QuickSave5"); break;
case "SaveSlot6": if (!IsNullEmulator()) SaveState("QuickSave6"); break;
case "SaveSlot7": if (!IsNullEmulator()) SaveState("QuickSave7"); break;
case "SaveSlot8": if (!IsNullEmulator()) SaveState("QuickSave8"); break;
case "SaveSlot9": if (!IsNullEmulator()) SaveState("QuickSave9"); break;
case "LoadSlot0": if (!IsNullEmulator()) LoadState("QuickSave0"); break;
case "LoadSlot1": if (!IsNullEmulator()) LoadState("QuickSave1"); break;
case "LoadSlot2": if (!IsNullEmulator()) LoadState("QuickSave2"); break;
case "LoadSlot3": if (!IsNullEmulator()) LoadState("QuickSave3"); break;
case "LoadSlot4": if (!IsNullEmulator()) LoadState("QuickSave4"); break;
case "LoadSlot5": if (!IsNullEmulator()) LoadState("QuickSave5"); break;
case "LoadSlot6": if (!IsNullEmulator()) LoadState("QuickSave6"); break;
case "LoadSlot7": if (!IsNullEmulator()) LoadState("QuickSave7"); break;
case "LoadSlot8": if (!IsNullEmulator()) LoadState("QuickSave8"); break;
case "LoadSlot9": if (!IsNullEmulator()) LoadState("QuickSave9"); break;
case "SelectSlot0": OnSelectSlot(0); break;
case "SelectSlot1": OnSelectSlot(1); break;
case "SelectSlot2": OnSelectSlot(2); break;
case "SelectSlot3": OnSelectSlot(3); break;
case "SelectSlot4": OnSelectSlot(4); break;
case "SelectSlot5": OnSelectSlot(5); break;
case "SelectSlot6": OnSelectSlot(6); break;
case "SelectSlot7": OnSelectSlot(7); break;
case "SelectSlot8": OnSelectSlot(8); break;
case "SelectSlot9": OnSelectSlot(9); break;
case "Toggle Fullscreen": ToggleFullscreen(); break;
case "Save Named State": SaveStateAs(); break;
case "Load Named State": LoadStateAs(); break;
case "Previous Slot": PreviousSlot(); break;
case "Next Slot": NextSlot(); break;
case "Ram Watch": LoadRamWatch(); break;
case "Ram Search": LoadRamSearch(); break;
case "Ram Poke":
{
RamPoke r = new RamPoke();
r.Show();
break;
}
case "Hex Editor": LoadHexEditor(); break;
case "Lua Console":
{
var window = new BizHawk.MultiClient.tools.LuaWindow();
window.Show();
break;
}
case "Cheats": LoadCheatsWindow(); break;
case "Open ROM":
{
OpenROM();
break;
}
case "Close ROM": CloseROM(); break;
case "Display FPS": ToggleFPS(); break;
case "Display FrameCounter": ToggleFrameCounter(); break;
case "Display LagCounter": ToggleLagCounter(); break;
case "Display Input": ToggleInputDisplay(); break;
case "Toggle Read Only": ToggleReadOnly(); break;
case "Play Movie":
{
PlayMovie();
break;
}
case "Record Movie":
{
RecordMovie();
break;
}
case "Stop Movie": StopUserMovie(); break;
case "Play Beginning": PlayMovieFromBeginning(); break;
case "Volume Up": VolumeUp(); break;
case "Volume Down": VolumeDown(); break;
case "Soft Reset": SoftReset(); break;
case "Toggle MultiTrack":
{
Global.MainForm.UserMovie.MultiTrack.IsActive = !Global.MainForm.UserMovie.MultiTrack.IsActive;
if (Global.MainForm.UserMovie.MultiTrack.IsActive)
{
Global.RenderPanel.AddMessage("MultiTrack Enabled");
Global.RenderPanel.MT = "Recording None";
}
else
Global.RenderPanel.AddMessage("MultiTrack Disabled");
Global.MainForm.UserMovie.MultiTrack.RecordAll = false;
Global.MainForm.UserMovie.MultiTrack.CurrentPlayer = 0;
break;
}
case "Increment Player":
{
Global.MainForm.UserMovie.MultiTrack.CurrentPlayer++;
Global.MainForm.UserMovie.MultiTrack.RecordAll = false;
if (Global.MainForm.UserMovie.MultiTrack.CurrentPlayer > 5) //TODO: Replace with console's maximum or current maximum players??!
{
Global.MainForm.UserMovie.MultiTrack.CurrentPlayer = 1;
}
Global.RenderPanel.MT = "Recording Player " + Global.MainForm.UserMovie.MultiTrack.CurrentPlayer.ToString();
break;
}
case "Decrement Player":
{
Global.MainForm.UserMovie.MultiTrack.CurrentPlayer--;
Global.MainForm.UserMovie.MultiTrack.RecordAll = false;
if (Global.MainForm.UserMovie.MultiTrack.CurrentPlayer < 1)
{
Global.MainForm.UserMovie.MultiTrack.CurrentPlayer = 5;//TODO: Replace with console's maximum or current maximum players??!
}
Global.RenderPanel.MT = "Recording Player " + Global.MainForm.UserMovie.MultiTrack.CurrentPlayer.ToString();
break;
}
case "Record All":
{
Global.MainForm.UserMovie.MultiTrack.CurrentPlayer = 0;
Global.MainForm.UserMovie.MultiTrack.RecordAll = true;
Global.RenderPanel.MT = "Recording All";
break;
}
case "Record None":
{
Global.MainForm.UserMovie.MultiTrack.CurrentPlayer = 0;
Global.MainForm.UserMovie.MultiTrack.RecordAll = false;
Global.RenderPanel.MT = "Recording None";
break;
}
} //switch(trigger)
} //foreach triggered hotkey
} //foreach event
//the pause hotkey is ignored when we are frame advancing
if (!Global.ClientControls.IsPressed("Frame Advance"))
@ -991,258 +1162,6 @@ namespace BizHawk.MultiClient
}
}
if (Global.ClientControls.IsPressed("Unthrottle"))
{
Global.ClientControls.UnpressButton("Unthrottle");
unthrottled ^= true;
Global.RenderPanel.AddMessage("Unthrottled: " + unthrottled);
}
if (Global.ClientControls["Hard Reset"])
{
Global.ClientControls.UnpressButton("Hard Reset");
LoadRom(CurrentlyOpenRom);
}
if (Global.ClientControls["Screenshot"])
{
Global.ClientControls.UnpressButton("Screenshot");
TakeScreenshot();
}
for (int i = 0; i < 10; i++)
{
if (Global.ClientControls["SaveSlot" + i.ToString()])
{
if (!IsNullEmulator())
SaveState("QuickSave" + i.ToString());
Global.ClientControls.UnpressButton("LoadSlot" + i.ToString());
Global.ClientControls.UnpressButton("SaveSlot" + i.ToString());
}
}
for (int i = 0; i < 10; i++)
{
if (Global.ClientControls["LoadSlot" + i.ToString()])
{
if (!IsNullEmulator())
LoadState("QuickSave" + i.ToString());
Global.ClientControls.UnpressButton("LoadSlot" + i.ToString());
Global.ClientControls.UnpressButton("SaveSlot" + i.ToString());
}
}
for (int i = 0; i < 10; i++)
{
if (Global.ClientControls["SelectSlot" + i.ToString()])
{
SaveSlot = i;
SaveSlotSelectedMessage();
UpdateStatusSlots();
Global.ClientControls.UnpressButton("SelectSlot" + i.ToString());
}
}
if (Global.ClientControls["Toggle Fullscreen"])
{
Global.ClientControls.UnpressButton("Toggle Fullscreen");
ToggleFullscreen();
}
if (Global.ClientControls["Save Named State"])
{
SaveStateAs();
Global.ClientControls.UnpressButton("Save Named State");
}
if (Global.ClientControls["Load Named State"])
{
LoadStateAs();
Global.ClientControls.UnpressButton("Load Named State");
}
if (Global.ClientControls["Previous Slot"])
{
PreviousSlot();
Global.ClientControls.UnpressButton("Previous Slot");
}
if (Global.ClientControls["Next Slot"])
{
NextSlot();
Global.ClientControls.UnpressButton("Next Slot");
}
if (Global.ClientControls["Ram Watch"])
{
LoadRamWatch();
Global.ClientControls.UnpressButton("Ram Watch");
}
if (Global.ClientControls["Ram Search"])
{
LoadRamSearch();
Global.ClientControls.UnpressButton("Ram Search");
}
if (Global.ClientControls["Ram Poke"])
{
RamPoke r = new RamPoke();
r.Show();
Global.ClientControls.UnpressButton("Ram Poke");
}
if (Global.ClientControls["Hex Editor"])
{
LoadHexEditor();
Global.ClientControls.UnpressButton("Hex Editor");
}
if (Global.ClientControls["Lua Console"])
{
var window = new BizHawk.MultiClient.tools.LuaWindow();
window.Show();
Global.ClientControls.UnpressButton("Lua Console");
}
if (Global.ClientControls["Cheats"])
{
LoadCheatsWindow();
Global.ClientControls.UnpressButton("Cheats");
}
if (Global.ClientControls["Open ROM"])
{
OpenROM();
Global.ClientControls.UnpressButton("Open ROM");
}
if (Global.ClientControls["Close ROM"])
{
CloseROM();
Global.ClientControls.UnpressButton("Close ROM");
}
//"Display LagCounter", "Display Input"}
if (Global.ClientControls["Display FPS"])
{
ToggleFPS();
Global.ClientControls.UnpressButton("Display FPS");
}
if (Global.ClientControls["Display FrameCounter"])
{
ToggleFrameCounter();
Global.ClientControls.UnpressButton("Display FrameCounter");
}
if (Global.ClientControls["Display LagCounter"])
{
ToggleLagCounter();
Global.ClientControls.UnpressButton("Display LagCounter");
}
if (Global.ClientControls["Display Input"])
{
ToggleInputDisplay();
Global.ClientControls.UnpressButton("Display Input");
}
if (Global.ClientControls["Toggle Read Only"])
{
ToggleReadOnly();
Global.ClientControls.UnpressButton("Toggle Read Only");
}
if (Global.ClientControls["Play Movie"])
{
PlayMovie();
Global.ClientControls.UnpressButton("Play Movie");
}
if (Global.ClientControls["Record Movie"])
{
RecordMovie();
Global.ClientControls.UnpressButton("Record Movie");
}
if (Global.ClientControls["Stop Movie"])
{
StopUserMovie();
Global.ClientControls.UnpressButton("Stop Movie");
}
if (Global.ClientControls["Play Beginning"])
{
PlayMovieFromBeginning();
Global.ClientControls.UnpressButton("Play Beginning");
}
if (Global.ClientControls["Volume Up"])
{
VolumeUp();
Global.ClientControls.UnpressButton("Volume Up");
}
if (Global.ClientControls["Volume Down"])
{
VolumeDown();
Global.ClientControls.UnpressButton("Volume Down");
}
if (Global.ClientControls["Soft Reset"])
{
SoftReset();
Global.ClientControls.UnpressButton("Soft Reset");
}
if (Global.ClientControls["Toggle MultiTrack"])
{
Global.MainForm.UserMovie.MultiTrack.IsActive = !Global.MainForm.UserMovie.MultiTrack.IsActive;
if (Global.MainForm.UserMovie.MultiTrack.IsActive)
{
Global.RenderPanel.AddMessage("MultiTrack Enabled");
Global.RenderPanel.MT = "Recording None";
}
else
Global.RenderPanel.AddMessage("MultiTrack Disabled");
Global.MainForm.UserMovie.MultiTrack.RecordAll = false;
Global.MainForm.UserMovie.MultiTrack.CurrentPlayer = 0;
Global.ClientControls.UnpressButton("Toggle MultiTrack");
}
if (Global.ClientControls["Increment Player"])
{
Global.MainForm.UserMovie.MultiTrack.CurrentPlayer++;
Global.MainForm.UserMovie.MultiTrack.RecordAll = false;
if (Global.MainForm.UserMovie.MultiTrack.CurrentPlayer > 5) //TODO: Replace with console's maximum or current maximum players??!
{
Global.MainForm.UserMovie.MultiTrack.CurrentPlayer = 1;
}
Global.ClientControls.UnpressButton("Increment Player");
Global.RenderPanel.MT = "Recording Player " + Global.MainForm.UserMovie.MultiTrack.CurrentPlayer.ToString();
}
if (Global.ClientControls["Decrement Player"])
{
Global.MainForm.UserMovie.MultiTrack.CurrentPlayer--;
Global.MainForm.UserMovie.MultiTrack.RecordAll = false;
if (Global.MainForm.UserMovie.MultiTrack.CurrentPlayer < 1)
{
Global.MainForm.UserMovie.MultiTrack.CurrentPlayer = 5;//TODO: Replace with console's maximum or current maximum players??!
}
Global.ClientControls.UnpressButton("Decrement Player");
Global.RenderPanel.MT = "Recording Player " + Global.MainForm.UserMovie.MultiTrack.CurrentPlayer.ToString();
}
if (Global.ClientControls["Record All"])
{
Global.MainForm.UserMovie.MultiTrack.CurrentPlayer = 0;
Global.MainForm.UserMovie.MultiTrack.RecordAll = true;
Global.ClientControls.UnpressButton("Record All");
Global.RenderPanel.MT = "Recording All";
}
if (Global.ClientControls["Record None"])
{
Global.MainForm.UserMovie.MultiTrack.CurrentPlayer = 0;
Global.MainForm.UserMovie.MultiTrack.RecordAll = false;
Global.ClientControls.UnpressButton("Record None");
Global.RenderPanel.MT = "Recording None";
}
}
void StepRunLoop_Throttle()

View File

@ -55,8 +55,10 @@ namespace BizHawk.MultiClient
{
pos = 0;
timer.Start();
Input.Update();
wasPressed = Input.GetPressedKey();
//Input.Update();
//zero: ??? what is this all about ???
wasPressed = Input.Instance.GetNextPressedButtonOrNull();
}
protected override void OnLeave(EventArgs e)
@ -73,8 +75,8 @@ namespace BizHawk.MultiClient
private void ReadKeys()
{
Input.Update();
string TempBindingStr = Input.GetPressedKey();
Input.Instance.Update();
string TempBindingStr = Input.Instance.GetNextPressedButtonOrNull();
if (wasPressed != "" && TempBindingStr == wasPressed) return;
if (TempBindingStr != null)
{

View File

@ -85,7 +85,6 @@
<Compile Include="7z\SevenZipExtractorAsynchronous.cs" />
<Compile Include="7z\SevenZipSfx.cs" />
<Compile Include="7z\StreamWrappers.cs" />
<Compile Include="Dictionaries.cs" />
<Compile Include="InputConfigBase.cs">
<SubType>Form</SubType>
</Compile>

View File

@ -1,81 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace BizHawk
{
/// <summary>
/// a Dictionary-of-lists with key K and values List&lt;V&gt;
/// </summary>
[Serializable]
public class Bag<K, V> : BagBase<K, V, Dictionary<K, List<V>>, List<V>> { }
/// <summary>
/// a Dictionary-of-lists with key K and values List&lt;V&gt;
/// </summary>
[Serializable]
public class SortedBag<K, V> : BagBase<K, V, SortedDictionary<K, List<V>>, List<V>> { }
/// <summary>
/// A dictionary that creates new values on the fly as necessary so that any key you need will be defined.
/// </summary>
/// <typeparam name="K">dictionary keys</typeparam>
/// <typeparam name="V">dictionary values</typeparam>
public class WorkingDictionary<K, V> : Dictionary<K, V> where V : new() {
public new V this[K key] {
get {
V temp;
if(!TryGetValue(key, out temp))
temp = this[key] = new V();
return temp;
}
set { base[key] = value; }
}
}
/// <summary>
/// base class for Bag and SortedBag
/// </summary>
/// <typeparam name="K">dictionary keys</typeparam>
/// <typeparam name="V">list values</typeparam>
/// <typeparam name="D">dictionary type</typeparam>
/// <typeparam name="L">list type</typeparam>
[Serializable]
public class BagBase<K, V, D, L> : IEnumerable<V>
where D : IDictionary<K, L>, new()
where L : IList<V>, IEnumerable<V>, new() {
D dictionary = new D();
public void Add(K key, V val) {
this[key].Add(val);
}
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
public IEnumerator<V> GetEnumerator() {
foreach(L lv in dictionary.Values)
foreach(V v in lv)
yield return v;
}
public IEnumerable KeyValuePairEnumerator { get { return dictionary; } }
/// <summary>
/// the list of keys contained herein
/// </summary>
public IList<K> Keys { get { return new List<K>(dictionary.Keys); } }
public L this[K key] {
get {
L slot;
if(!dictionary.TryGetValue(key, out slot))
dictionary[key] = slot = new L();
return slot;
}
set {
dictionary[key] = value;
}
}
}
}

View File

@ -538,7 +538,7 @@ namespace BizHawk
break;
}
break;
//it is conceivable that you will need this. you wouldnt be able to conceive of why, though. obscure message loop flakiness when exceptions are thrown from the message loop...
//obscure message loop flakiness when exceptions are thrown from the message loop...
case (int)WindowsMessage.WM_SETFOCUS:
if (SelectedIndices.Count > 0 && SelectedIndices[0] >= VirtualListSize)
messageProcessed = true;