analog input support. this is bad code and should all be reverted as soon as possible.

binds (along with sensitivity, deadzone, flip customization) are not supported yet.  to test out, try using the first two axes of dinput joystick #5 on N64 player #1
This commit is contained in:
goyuken 2013-07-18 16:18:17 +00:00
parent e88691152d
commit 3169968858
9 changed files with 154 additions and 20 deletions

View File

@ -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}
}
};

View File

@ -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}
}
};

View File

@ -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},
}
};

View File

@ -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<ControllerDefinition.FloatRange l, float Min, float Mid, float Max)
{
l.Add(new ControllerDefinition.FloatRange(Min, Mid, Max);
}
}
*/
public class ControllerDefinition
{
public struct FloatRange
{
public readonly float Min;
public readonly float Max;
/// <summary>
/// default position
/// </summary>
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<string> BoolButtons = new List<string>();
public List<string> FloatControls = new List<string>();
public List<FloatRange> FloatRanges = new List<FloatRange>();
/// <summary>
/// copy
/// </summary>

View File

@ -10,9 +10,22 @@ namespace BizHawk.MultiClient
private readonly WorkingDictionary<string, List<string>> bindings = new WorkingDictionary<string, List<string>>();
private readonly WorkingDictionary<string, bool> buttons = new WorkingDictionary<string, bool>();
private readonly WorkingDictionary<string, float> FloatButtons = new WorkingDictionary<string, float>();
private readonly Dictionary<string, ControllerDefinition.FloatRange> FloatRanges = new WorkingDictionary<string, ControllerDefinition.FloatRange>();
private readonly Dictionary<string, string> FloatBinds = new Dictionary<string, string>();
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;
}
}
}
/// <summary>

View File

@ -87,6 +87,13 @@ namespace BizHawk.MultiClient
return;
}
public IEnumerable<Tuple<string, float>> GetFloats()
{
var pis = typeof(JoystickState).GetProperties();
foreach (var pi in pis)
yield return new Tuple<string, float>(pi.Name, 10.0f * (float)(int)pi.GetValue(state, null));
}
/// <summary>FOR DEBUGGING ONLY</summary>
public JoystickState GetInternalState()
{

View File

@ -163,6 +163,7 @@ namespace BizHawk.MultiClient
private readonly WorkingDictionary<string, bool> LastState = new WorkingDictionary<string, bool>();
private readonly WorkingDictionary<string, bool> UnpressState = new WorkingDictionary<string, bool>();
private readonly HashSet<string> IgnoreKeys = new HashSet<string>(new[] { "LeftShift", "RightShift", "LeftControl", "RightControl", "LeftAlt", "RightAlt" });
private readonly List<Tuple<string, float>> FloatValues = new List<Tuple<string, float>>();
void HandleButton(string button, bool newState)
{
@ -254,6 +255,16 @@ namespace BizHawk.MultiClient
}
}
public List<Tuple<string, float>> GetFloats()
{
List<Tuple<string, float>> FloatValuesCopy;
lock (FloatValues)
{
FloatValuesCopy = new List<Tuple<string, float>>(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<string, float>(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;

View File

@ -1928,6 +1928,9 @@ namespace BizHawk.MultiClient
}
} //foreach event
// also handle floats
Global.ControllerInputCoalescer.AcceptNewFloats(Input.Instance.GetFloats());
}
private void ClearAutohold()

View File

@ -101,9 +101,10 @@ namespace BizHawk.MultiClient
public ControllerDefinition Type { get; set; }
protected WorkingDictionary<string, bool> Buttons = new WorkingDictionary<string, bool>();
protected WorkingDictionary<string, float> Floats = new WorkingDictionary<string, float>();
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<KeyValuePair<string, bool>> BoolButtons()
@ -118,6 +119,12 @@ namespace BizHawk.MultiClient
Buttons[button] = source[button];
}
}
public void AcceptNewFloats(IEnumerable<Tuple<string, float>> NewValues)
{
foreach (var sv in NewValues)
Floats[sv.Item1] = sv.Item2;
}
}
public class ORAdapter : IController