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