fix more input stuff better

This commit is contained in:
zeromus 2011-07-10 07:39:40 +00:00
parent 2425b3c87a
commit 61f466ca8e
4 changed files with 240 additions and 229 deletions

View File

@ -14,7 +14,6 @@ namespace BizHawk.MultiClient
public static IEmulator Emulator;
public static CoreInputComm CoreInputComm;
public static RomGame Game;
public static Controller ClientControls;
public static Controller SMSControls;
public static Controller PCEControls;
public static Controller GenControls;
@ -29,7 +28,8 @@ namespace BizHawk.MultiClient
public static MultitrackRewiringControllerAdapter MultitrackRewiringControllerAdapter = new MultitrackRewiringControllerAdapter();
//user -> ActiveController -> TurboAdapter(TBD) -> Lua(?) -> MultitrackRewiringControllerAdapter -> MovieInputSourceAdapter -> MovieInputController -> ControllerOutput(1) -> Game
//user -> Input -> ActiveController -> TurboAdapter(TBD) -> Lua(?) -> ..
//.. -> MultitrackRewiringControllerAdapter -> MovieInputSourceAdapter -> MovieInputController -> ControllerOutput(1) -> Game
//(1)->Input Display
//the original source controller, bound to the user, sort of the "input" port for the chain, i think
@ -38,9 +38,15 @@ namespace BizHawk.MultiClient
//the "output" port for the controller chain.
public static IController ControllerOutput;
public static Input.InputCoalescer InputCoalescer;
//input state which has been destined for game controller inputs are coalesced here
public static InputCoalescer ControllerInputCoalescer = new InputCoalescer();
//input state which has been destined for client hotkey consumption are colesced here
public static InputCoalescer HotkeyCoalescer = new InputCoalescer();
public static UD_LR_ControllerAdapter UD_LR_ControllerAdapter = new UD_LR_ControllerAdapter();
public static Controller ClientControls;
public static string GetOutputControllersAsMnemonic()
{
MnemonicsGenerator mg = new MnemonicsGenerator();

View File

@ -14,6 +14,7 @@ namespace BizHawk.MultiClient
private List<string> removeFromForcePressedButtons = new List<string>();
private List<string> programmaticallyPressedButtons = new List<string>();
//look for bindings which are activated by the supplied physical button.
public List<string> SearchBindings(string button)
{
var ret = new List<string>();

View File

@ -1,13 +1,28 @@
using System;
using System.Linq;
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
{
//coalesces events back into instantaneous states
public class InputCoalescer : SimpleController
{
public void Receive(Input.InputEvent ie)
{
bool state = ie.EventType == Input.InputEventType.Press;
Buttons[ie.LogicalButton.ToString()] = state;
//when a button is released, all modified variants of it are released as well
if (!state)
{
var releases = Buttons.Where((kvp) => kvp.Key.Contains("+") && kvp.Key.EndsWith(ie.LogicalButton.Button)).ToArray();
foreach (var kvp in releases)
Buttons[kvp.Key] = false;
}
}
}
public class Input
{
@ -34,16 +49,6 @@ namespace BizHawk.MultiClient
Alt = 262144,
}
//coalesces events back into instantaneous states
public class InputCoalescer : SimpleController
{
public void Receive(Input.InputEvent ie)
{
bool state = ie.EventType == InputEventType.Press;
Buttons[ie.LogicalButton.ToString()] = state;
}
}
public static Input Instance { get; private set; }
Thread UpdateThread;
@ -92,9 +97,6 @@ namespace BizHawk.MultiClient
}
InputCoalescer Coalescer = new InputCoalescer();
WorkingDictionary<string, bool> LastState = new WorkingDictionary<string, bool>();
@ -115,7 +117,8 @@ namespace BizHawk.MultiClient
ModifierKey _Modifiers;
List<InputEvent> _NewEvents = new List<InputEvent>();
//TODO - maybe need clearevents for various purposes? maybe not.
//TODO - maybe need clearevents for various purposes. perhaps when returning from modal dialogs?
Queue<InputEvent> InputEvents = new Queue<InputEvent>();
public InputEvent DequeueEvent()
{
@ -128,13 +131,8 @@ namespace BizHawk.MultiClient
void EnqueueEvent(InputEvent ie)
{
lock (this)
{
InputEvents.Enqueue(ie);
Coalescer.Receive(ie);
}
}
public bool CheckState(string button) { lock (this) return Coalescer.IsPressed(button); }
void UpdateThreadProc()
{
@ -187,14 +185,10 @@ namespace BizHawk.MultiClient
//so i will leave this method here for now..
}
public bool IsPressed(string control)
{
return Instance.CheckState(control);
}
//returns the next Press event, if available. should be useful
public string GetNextPressedButtonOrNull()
{
InputEvent ie = Instance.DequeueEvent();
InputEvent ie = DequeueEvent();
if (ie == null) return null;
if (ie.EventType == InputEventType.Release) return null;
return ie.LogicalButton.ToString();

View File

@ -280,13 +280,10 @@ namespace BizHawk.MultiClient
}
}
bool _HACK_KEY_FF;
bool _HACK_KEY_REWIND;
void SyncThrottle()
{
throttle.signal_unthrottle = unthrottled;
if (_HACK_KEY_FF)
if (Global.ClientControls["Fast Forward"])
throttle.SetSpeedPercent(Global.Config.SpeedPercentAlternate);
else
throttle.SetSpeedPercent(Global.Config.SpeedPercent);
@ -316,8 +313,13 @@ namespace BizHawk.MultiClient
{
for (; ; )
{
//client input-related duties
Input.Instance.Update();
CheckHotkeys();
//handle events and dispatch as a hotkey action, or a hotkey button, or an input button
ProcessInput();
Global.ClientControls.LatchFromPhysical(Global.HotkeyCoalescer);
Global.ActiveController.LatchFromPhysical(Global.ControllerInputCoalescer);
StepRunLoop_Core();
if (!IsNullEmulator())
@ -778,8 +780,9 @@ namespace BizHawk.MultiClient
void RewireInputChain()
{
//insert turbo and lua here?
Global.InputCoalescer = new Input.InputCoalescer();
Global.InputCoalescer.Type = Global.ActiveController.Type;
Global.ControllerInputCoalescer = new InputCoalescer();
Global.ControllerInputCoalescer.Type = Global.ActiveController.Type;
Global.UD_LR_ControllerAdapter.Source = Global.ActiveController;
Global.MultitrackRewiringControllerAdapter.Source = Global.UD_LR_ControllerAdapter;
Global.MovieInputSourceAdapter.Source = Global.MultitrackRewiringControllerAdapter;
@ -968,44 +971,56 @@ namespace BizHawk.MultiClient
UpdateStatusSlots();
}
public void CheckHotkeys()
public void ProcessInput()
{
for(;;)
{
//loop through all available events
var ie = Input.Instance.DequeueEvent();
if(ie == null) break;
//TODO - wonder what happens if we pop up something interactive as a response to one of these hotkeys? may need to purge further processing
//TODO - deal with these later somehow
//look for client control bindings for this key
var triggers = Global.ClientControls.SearchBindings(ie.LogicalButton.ToString());
if (triggers.Count == 0)
{
//no hotkeys or player inputs bound this, so mutate it to an unmodified key
//no hotkeys or player inputs bound this, so mutate it to an unmodified key and assign it for use as a game controller input
//(we have a rule that says: modified events may be used for game controller inputs but not hotkeys)
var mutated_ie = new Input.InputEvent();
mutated_ie.EventType = ie.EventType;
mutated_ie.LogicalButton = ie.LogicalButton;
mutated_ie.LogicalButton.Modifiers = Input.ModifierKey.None;
Global.InputCoalescer.Receive(mutated_ie);
}
foreach(var trigger in triggers)
{
if(trigger == "Fast Forward")
{
_HACK_KEY_FF = ie.EventType == Input.InputEventType.Press;
continue;
}
if (trigger == "Rewind")
{
_HACK_KEY_REWIND = ie.EventType == Input.InputEventType.Press;
continue;
Global.ControllerInputCoalescer.Receive(mutated_ie);
}
if(ie.EventType == Input.InputEventType.Release) continue;
bool handled = false;
if (ie.EventType == Input.InputEventType.Press)
{
foreach (var trigger in triggers)
{
handled |= CheckHotkey(trigger);
}
}
//hotkeys which arent handled as actions get coalesced as pollable buttons
if (!handled)
{
Global.HotkeyCoalescer.Receive(ie);
}
} //foreach event
}
bool CheckHotkey(string trigger)
{
//todo - could have these in a table somehow ?
switch (trigger)
{
default:
return false;
case "ToolBox":
LoadToolBox();
break;
@ -1174,10 +1189,7 @@ namespace BizHawk.MultiClient
} //switch(trigger)
} //foreach triggered hotkey
} //foreach event
return true;
}
void StepRunLoop_Throttle()
@ -1199,7 +1211,7 @@ namespace BizHawk.MultiClient
double frameAdvanceTimestampDelta = (now - FrameAdvanceTimestamp).TotalMilliseconds;
bool frameProgressTimeElapsed = Global.Config.FrameProgressDelayMs < frameAdvanceTimestampDelta;
if (/*Global.ClientControls["Frame Advance"] || PressFrameAdvance*/KeyInput.IsPressed(SlimDX.DirectInput.Key.F))
if (Global.ClientControls["Frame Advance"])
{
//handle the initial trigger of a frame advance
if (FrameAdvanceTimestamp == DateTime.MinValue)
@ -1238,7 +1250,7 @@ namespace BizHawk.MultiClient
runFrame = true;
}
if (Global.Config.RewindEnabled && _HACK_KEY_REWIND || PressRewind)
if (Global.Config.RewindEnabled && Global.ClientControls["Rewind"] || PressRewind)
{
rewindCredits += Global.Config.SpeedPercent;
int rewindTodo = rewindCredits / 100;
@ -1260,7 +1272,7 @@ namespace BizHawk.MultiClient
if (runFrame)
{
runloop_fps++;
bool ff = _HACK_KEY_FF;
bool ff = Global.ClientControls["Fast Forward"];
bool updateFpsString = (runloop_last_ff != ff);
runloop_last_ff = ff;
@ -1284,8 +1296,6 @@ namespace BizHawk.MultiClient
else if (!Global.Config.MuteFrameAdvance)
genSound = true;
Global.ActiveController.LatchFromPhysical(Global.InputCoalescer);
if (UserMovie.GetMovieMode() != MOVIEMODE.INACTIVE)
{
UserMovie.LatchInputFromLog();