diff --git a/BizHawk.Client.Common/ControllerBinding.cs b/BizHawk.Client.Common/ControllerBinding.cs
index f8027cb3f5..58461651b5 100644
--- a/BizHawk.Client.Common/ControllerBinding.cs
+++ b/BizHawk.Client.Common/ControllerBinding.cs
@@ -132,6 +132,11 @@ namespace BizHawk.Client.Common
}
}
+ public void ApplyAxisConstraints(string constraintClass)
+ {
+ _type.ApplyAxisConstraints(constraintClass,_floatButtons);
+ }
+
///
/// merges pressed logical buttons from the supplied controller, effectively ORing it with the current state
///
diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs
index c6189e4973..668ce2fe54 100644
--- a/BizHawk.Client.EmuHawk/MainForm.cs
+++ b/BizHawk.Client.EmuHawk/MainForm.cs
@@ -427,8 +427,12 @@ namespace BizHawk.Client.EmuHawk
// handle events and dispatch as a hotkey action, or a hotkey button, or an input button
ProcessInput();
Global.ClientControls.LatchFromPhysical(GlobalWin.HotkeyCoalescer);
+
Global.ActiveController.LatchFromPhysical(Global.ControllerInputCoalescer);
+ //TODO - use preferences to apply this
+ Global.ActiveController.ApplyAxisConstraints("Natural Circle");
+
Global.ActiveController.OR_FromLogical(Global.ClickyVirtualPadController);
Global.ActiveController.Overrides(Global.LuaAndAdaptor);
Global.AutoFireController.LatchFromPhysical(Global.ControllerInputCoalescer);
diff --git a/BizHawk.Emulation.Common/Interfaces/IController.cs b/BizHawk.Emulation.Common/Interfaces/IController.cs
index 621b731721..ed6d592e7f 100644
--- a/BizHawk.Emulation.Common/Interfaces/IController.cs
+++ b/BizHawk.Emulation.Common/Interfaces/IController.cs
@@ -17,6 +17,38 @@ namespace BizHawk.Emulation.Common
public class ControllerDefinition
{
+ public void ApplyAxisConstraints(string constraintClass, IDictionary floatButtons)
+ {
+ if (AxisConstraints == null) return;
+
+ foreach (var constraint in AxisConstraints)
+ {
+ if (constraint.Class != constraintClass)
+ continue;
+ switch (constraint.Type)
+ {
+ case AxisConstraintType.Circular:
+ {
+ string xaxis = constraint.Params[0] as string;
+ string yaxis = constraint.Params[1] as string;
+ float range = (float)constraint.Params[2];
+ double xval = floatButtons[xaxis];
+ double yval = floatButtons[yaxis];
+ double length = Math.Sqrt(xval * xval + yval * yval);
+ if (length > range)
+ {
+ double ratio = range / length;
+ xval *= ratio;
+ yval *= ratio;
+ }
+ floatButtons[xaxis] = (float)xval;
+ floatButtons[yaxis] = (float)yval;
+ break;
+ }
+ }
+ }
+ }
+
public struct FloatRange
{
public readonly float Min;
@@ -46,11 +78,24 @@ namespace BizHawk.Emulation.Common
}
}
+ public enum AxisConstraintType
+ {
+ Circular
+ }
+
+ public struct AxisConstraint
+ {
+ public string Class;
+ public AxisConstraintType Type;
+ public object[] Params;
+ }
+
public string Name { get; set; }
public List BoolButtons { get; set; }
public List FloatControls { get; private set; }
public List FloatRanges { get; private set; }
+ public List AxisConstraints { get; private set; }
public ControllerDefinition(ControllerDefinition source)
: this()
@@ -59,6 +104,7 @@ namespace BizHawk.Emulation.Common
BoolButtons.AddRange(source.BoolButtons);
FloatControls.AddRange(source.FloatControls);
FloatRanges.AddRange(source.FloatRanges);
+ AxisConstraints.AddRange(source.AxisConstraints);
}
public ControllerDefinition()
@@ -66,6 +112,7 @@ namespace BizHawk.Emulation.Common
BoolButtons = new List();
FloatControls = new List();
FloatRanges = new List();
+ AxisConstraints = new List();
}
}
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64Input.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64Input.cs
index dce6694d1c..821320c3de 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64Input.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/N64/N64Input.cs
@@ -41,6 +41,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
new[] {127.0f, 0.0f, -128.0f},
new[] {-128.0f, 0.0f, 127.0f},
new[] {127.0f, 0.0f, -128.0f}
+ },
+ AxisConstraints =
+ {
+ new ControllerDefinition.AxisConstraint { Class = "Natural Circle", Type = ControllerDefinition.AxisConstraintType.Circular, Params = new object[] {"P1 X Axis", "P1 Y Axis", 127.0f} }
}
};