diff --git a/BizHawk.Emulation/Consoles/Atari/7800/Atari7800Control.cs b/BizHawk.Emulation/Consoles/Atari/7800/Atari7800Control.cs index b060e1c89e..6b4c23f5fb 100644 --- a/BizHawk.Emulation/Consoles/Atari/7800/Atari7800Control.cs +++ b/BizHawk.Emulation/Consoles/Atari/7800/Atari7800Control.cs @@ -48,6 +48,14 @@ namespace BizHawk.Emulation "P2 Paddle", "P3 Paddle", "P4 Paddle" + }, + FloatRanges = + { + // what is the center point supposed to be here? + new[] {0.0f, 0.0f, 700000.0f}, + new[] {0.0f, 0.0f, 700000.0f}, + new[] {0.0f, 0.0f, 700000.0f}, + new[] {0.0f, 0.0f, 700000.0f} } }; public static ControllerDefinition Keypad = new ControllerDefinition @@ -103,6 +111,12 @@ namespace BizHawk.Emulation { "P1 Driving", "P2 Driving" + }, + FloatRanges = + { + new[] {0.0f, 0.0f, 3.0f}, + new[] {0.0f, 0.0f, 3.0f}, + new[] {0.0f, 0.0f, 3.0f} } }; public static ControllerDefinition BoosterGrip = new ControllerDefinition @@ -159,6 +173,14 @@ namespace BizHawk.Emulation { "P1 VPos", "P1 HPos", "P2 VPos", "P2 HPos" + }, + FloatRanges = + { + // how many scanlines are there again?? + new[] {0.0f, 0.0f, 240.0f}, + new[] {0.0f, 0.0f, 319.0f}, + new[] {0.0f, 0.0f, 240.0f}, + new[] {0.0f, 0.0f, 319.0f} } }; diff --git a/BizHawk.Emulation/Consoles/Nintendo/N64/N64.cs b/BizHawk.Emulation/Consoles/Nintendo/N64/N64.cs index aee3013cef..da62f0d7aa 100644 --- a/BizHawk.Emulation/Consoles/Nintendo/N64/N64.cs +++ b/BizHawk.Emulation/Consoles/Nintendo/N64/N64.cs @@ -49,6 +49,17 @@ namespace BizHawk.Emulation.Consoles.Nintendo.N64 "P2 X Axis", "P2 Y Axis", "P3 X Axis", "P3 Y Axis", "P4 X Axis", "P4 Y Axis" + }, + FloatRanges = + { + new[] {-128.0f, 0.0f, 127.0f}, + new[] {-128.0f, 0.0f, 127.0f}, + new[] {-128.0f, 0.0f, 127.0f}, + new[] {-128.0f, 0.0f, 127.0f}, + new[] {-128.0f, 0.0f, 127.0f}, + new[] {-128.0f, 0.0f, 127.0f}, + new[] {-128.0f, 0.0f, 127.0f}, + new[] {-128.0f, 0.0f, 127.0f} } }; diff --git a/BizHawk.Emulation/Consoles/Sony/PSP/PSP.cs b/BizHawk.Emulation/Consoles/Sony/PSP/PSP.cs index f4cb4cbc7b..ecbaeccbd8 100644 --- a/BizHawk.Emulation/Consoles/Sony/PSP/PSP.cs +++ b/BizHawk.Emulation/Consoles/Sony/PSP/PSP.cs @@ -18,6 +18,11 @@ namespace BizHawk.Emulation.Consoles.Sony.PSP FloatControls = { "Stick X", "Stick Y" + }, + FloatRanges = // TODO + { + new[] {-1.0f, 0.0f, 1.0f}, + new[] {-1.0f, 0.0f, 1.0f}, } }; diff --git a/BizHawk.Emulation/Interfaces/IController.cs b/BizHawk.Emulation/Interfaces/IController.cs index cfdedc8091..e61434d45d 100644 --- a/BizHawk.Emulation/Interfaces/IController.cs +++ b/BizHawk.Emulation/Interfaces/IController.cs @@ -1,12 +1,49 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace BizHawk { + // doesn't do what is desired + // http://connect.microsoft.com/VisualStudio/feedback/details/459307/extension-add-methods-are-not-considered-in-c-collection-initializers + /* + public static class UltimateMagic + { + public static void Add(this List + /// default position + /// + public readonly float Mid; + public FloatRange(float Min, float Mid, float Max) + { + this.Min = Min; + this.Mid = Mid; + this.Max = Max; + } + // for terse construction + public static implicit operator FloatRange(float[] f) + { + if (f.Length != 3) + throw new ArgumentException(); + return new FloatRange(f[0], f[1], f[2]); + } + } + public string Name; public List BoolButtons = new List(); public List FloatControls = new List(); + public List FloatRanges = new List(); /// /// copy /// diff --git a/BizHawk.MultiClient/Input/ControllerBinding.cs b/BizHawk.MultiClient/Input/ControllerBinding.cs index 6a1b9827dd..55406e1552 100644 --- a/BizHawk.MultiClient/Input/ControllerBinding.cs +++ b/BizHawk.MultiClient/Input/ControllerBinding.cs @@ -10,9 +10,22 @@ namespace BizHawk.MultiClient private readonly WorkingDictionary> bindings = new WorkingDictionary>(); private readonly WorkingDictionary buttons = new WorkingDictionary(); + private readonly WorkingDictionary FloatButtons = new WorkingDictionary(); + + private readonly Dictionary FloatRanges = new WorkingDictionary(); + + private readonly Dictionary FloatBinds = new Dictionary(); + public Controller(ControllerDefinition definition) { type = definition; + for (int i = 0; i < type.FloatControls.Count; i++) + { + FloatButtons[type.FloatControls[i]] = type.FloatRanges[i].Mid; + FloatRanges[type.FloatControls[i]] = type.FloatRanges[i]; + } + FloatBinds.Add("J5 X", "P1 X Axis"); + FloatBinds.Add("J5 Y", "P1 Y Axis"); } public ControllerDefinition Type { get { return type; } } @@ -24,9 +37,7 @@ namespace BizHawk.MultiClient return buttons[button]; } - // the default state of an unpressed float is assumed to be zero. - // so always return zero here, until we add a float binding infrastructure to Controller - public float GetFloat(string name) { return 0.0f; } + public float GetFloat(string name) { return FloatButtons[name]; } public void UpdateControls(int frame) { } //look for bindings which are activated by the supplied physical button. @@ -72,10 +83,22 @@ namespace BizHawk.MultiClient buttons[kvp.Key] = false; foreach (var bound_button in kvp.Value) { - if(controller[bound_button]) + if (controller[bound_button]) buttons[kvp.Key] = true; } } + foreach (var kvp in FloatBinds) + { + float input = controller.GetFloat(kvp.Key); + string outkey = kvp.Value; + ControllerDefinition.FloatRange range; + if (FloatRanges.TryGetValue(outkey, out range)) + { + // input range is assumed to be -10000,0,10000 + // this is where deadzone, axis flip, sensitivity would be implemented + FloatButtons[outkey] = (input + 10000.0f) * (range.Max - range.Min) / 20000.0f + range.Min; + } + } } /// diff --git a/BizHawk.MultiClient/Input/GamePad.cs b/BizHawk.MultiClient/Input/GamePad.cs index c1968a7525..c5065a140b 100644 --- a/BizHawk.MultiClient/Input/GamePad.cs +++ b/BizHawk.MultiClient/Input/GamePad.cs @@ -87,6 +87,13 @@ namespace BizHawk.MultiClient return; } + public IEnumerable> GetFloats() + { + var pis = typeof(JoystickState).GetProperties(); + foreach (var pi in pis) + yield return new Tuple(pi.Name, 10.0f * (float)(int)pi.GetValue(state, null)); + } + /// FOR DEBUGGING ONLY public JoystickState GetInternalState() { diff --git a/BizHawk.MultiClient/Input/Input.cs b/BizHawk.MultiClient/Input/Input.cs index 22f88e612d..b3a30445e7 100644 --- a/BizHawk.MultiClient/Input/Input.cs +++ b/BizHawk.MultiClient/Input/Input.cs @@ -163,6 +163,7 @@ namespace BizHawk.MultiClient private readonly WorkingDictionary LastState = new WorkingDictionary(); private readonly WorkingDictionary UnpressState = new WorkingDictionary(); private readonly HashSet IgnoreKeys = new HashSet(new[] { "LeftShift", "RightShift", "LeftControl", "RightControl", "LeftAlt", "RightAlt" }); + private readonly List> FloatValues = new List>(); void HandleButton(string button, bool newState) { @@ -254,6 +255,16 @@ namespace BizHawk.MultiClient } } + public List> GetFloats() + { + List> FloatValuesCopy; + lock (FloatValues) + { + FloatValuesCopy = new List>(FloatValues); + } + return FloatValuesCopy; + } + #if WINDOWS void UpdateThreadProc() { @@ -276,23 +287,31 @@ namespace BizHawk.MultiClient else HandleButton(k.ToString(), false); - //analyze xinput - for (int i = 0; i < GamePad360.Devices.Count; i++) + lock (FloatValues) { - var pad = GamePad360.Devices[i]; - string xname = "X" + (i + 1) + " "; - for (int b = 0; b < pad.NumButtons; b++) - HandleButton(xname + pad.ButtonName(b), pad.Pressed(b)); - } + FloatValues.Clear(); - //analyze joysticks - for (int i = 0; i < GamePad.Devices.Count; i++) - { - var pad = GamePad.Devices[i]; - string jname = "J" + (i + 1) + " "; + //analyze xinput + for (int i = 0; i < GamePad360.Devices.Count; i++) + { + var pad = GamePad360.Devices[i]; + string xname = "X" + (i + 1) + " "; + for (int b = 0; b < pad.NumButtons; b++) + HandleButton(xname + pad.ButtonName(b), pad.Pressed(b)); + } + + //analyze joysticks + for (int i = 0; i < GamePad.Devices.Count; i++) + { + var pad = GamePad.Devices[i]; + string jname = "J" + (i + 1) + " "; + + for (int b = 0; b < pad.NumButtons; b++) + HandleButton(jname + pad.ButtonName(b), pad.Pressed(b)); + foreach (var sv in pad.GetFloats()) + FloatValues.Add(new Tuple(jname + sv.Item1, sv.Item2)); + } - for (int b = 0; b < pad.NumButtons; b++) - HandleButton(jname + pad.ButtonName(b), pad.Pressed(b)); } bool swallow = !Global.MainForm.AllowInput; diff --git a/BizHawk.MultiClient/MainForm.cs b/BizHawk.MultiClient/MainForm.cs index dc72deeea5..499bf43885 100644 --- a/BizHawk.MultiClient/MainForm.cs +++ b/BizHawk.MultiClient/MainForm.cs @@ -1928,6 +1928,9 @@ namespace BizHawk.MultiClient } } //foreach event + + // also handle floats + Global.ControllerInputCoalescer.AcceptNewFloats(Input.Instance.GetFloats()); } private void ClearAutohold() diff --git a/BizHawk.MultiClient/movie/InputAdapters.cs b/BizHawk.MultiClient/movie/InputAdapters.cs index 2484d69a95..26351ec336 100644 --- a/BizHawk.MultiClient/movie/InputAdapters.cs +++ b/BizHawk.MultiClient/movie/InputAdapters.cs @@ -101,9 +101,10 @@ namespace BizHawk.MultiClient public ControllerDefinition Type { get; set; } protected WorkingDictionary Buttons = new WorkingDictionary(); + protected WorkingDictionary Floats = new WorkingDictionary(); public virtual bool this[string button] { get { return Buttons[button]; } set { Buttons[button] = value; } } public virtual bool IsPressed(string button) { return this[button]; } - public float GetFloat(string name) { return 0.0f; } //TODO + public float GetFloat(string name) { return Floats[name]; } public void UpdateControls(int frame) { } public IEnumerable> BoolButtons() @@ -118,6 +119,12 @@ namespace BizHawk.MultiClient Buttons[button] = source[button]; } } + + public void AcceptNewFloats(IEnumerable> NewValues) + { + foreach (var sv in NewValues) + Floats[sv.Item1] = sv.Item2; + } } public class ORAdapter : IController