Use inheritance for AxisConstraints

This commit is contained in:
YoshiRulz 2020-06-26 08:42:10 +10:00
parent 15906af6e4
commit 1e67fc1d4b
No known key found for this signature in database
GPG Key ID: C4DE31C245353FB7
3 changed files with 42 additions and 45 deletions

View File

@ -97,7 +97,7 @@ namespace BizHawk.Emulation.Common
/// For instance, a N64 controller's analog range is actually larger than the amount allowed by the plastic that artificially constrains it to lower values
/// Axis constraints provide a way to technically allow the full range but have a user option to constrain down to typical values that a real control would have
/// </summary>
public readonly AxisConstraint? Constraint;
public readonly AxisConstraint Constraint;
public Range<float> FloatRange => ((float) Min).RangeTo(Max);
@ -115,7 +115,7 @@ namespace BizHawk.Emulation.Common
public readonly Range<int> Range;
public AxisSpec(Range<int> range, int mid, bool isReversed = false, AxisConstraint? constraint = null)
public AxisSpec(Range<int> range, int mid, bool isReversed = false, AxisConstraint constraint = null)
{
Constraint = constraint;
IsReversed = isReversed;
@ -132,37 +132,17 @@ namespace BizHawk.Emulation.Common
public void ApplyAxisConstraints(string constraintClass, IDictionary<string, int> axes)
{
if (!Axes.HasContraints) return;
foreach (var kvp in Axes)
{
if (kvp.Value.Constraint == null) continue;
var constraint = kvp.Value.Constraint.Value;
if (constraint.Class != constraintClass) continue;
switch (constraint.Type)
var constraint = kvp.Value.Constraint;
if (constraint == null || constraint.Class != constraintClass) continue;
switch (constraint)
{
case AxisConstraintType.Circular:
{
string xAxis = constraint.Params[0] as string ?? "";
string yAxis = constraint.Params[1] as string ?? "";
float range = (float)constraint.Params[2];
if (!axes.ContainsKey(xAxis)) break;
if (!axes.ContainsKey(yAxis)) break;
double xVal = axes[xAxis];
double yVal = axes[yAxis];
double length = Math.Sqrt((xVal * xVal) + (yVal * yVal));
if (length > range)
{
double ratio = range / length;
xVal *= ratio;
yVal *= ratio;
}
axes[xAxis] = (int) xVal;
axes[yAxis] = (int) yVal;
break;
}
case CircularAxisConstraint circular:
var xAxis = kvp.Key;
var yAxis = circular.PairedAxis;
(axes[xAxis], axes[yAxis]) = circular.ApplyTo(axes[xAxis], axes[yAxis]);
break;
}
}
}
@ -177,16 +157,38 @@ namespace BizHawk.Emulation.Common
LeftAndDown = 3
}
public enum AxisConstraintType
public interface AxisConstraint
{
Circular
public string Class { get; }
public string PairedAxis { get; }
}
public struct AxisConstraint
public sealed class CircularAxisConstraint : AxisConstraint
{
public string Class;
public AxisConstraintType Type;
public object[] Params;
public string Class { get; }
private readonly float Magnitude;
public string PairedAxis { get; }
public CircularAxisConstraint(string @class, string pairedAxis, float magnitude)
{
Class = @class;
Magnitude = magnitude;
PairedAxis = pairedAxis;
}
public (int X, int Y) ApplyTo(int rawX, int rawY)
{
var xVal = (double) rawX;
var yVal = (double) rawY;
var length = Math.Sqrt(xVal * xVal + yVal * yVal);
var ratio = Magnitude / length;
return ratio < 1.0
? ((int) (xVal * ratio), (int) (yVal * ratio))
: ((int) xVal, (int) yVal);
}
}
/// <summary>

View File

@ -407,7 +407,7 @@ namespace BizHawk.Emulation.Common
/// </summary>
/// <param name="constraint">pass only for one axis in a pair, by convention the X axis</param>
/// <returns>identical reference to <paramref name="def"/>; the object is mutated</returns>
public static ControllerDefinition AddAxis(this ControllerDefinition def, string name, Range<int> range, int mid, bool isReversed = false, AxisConstraint? constraint = null)
public static ControllerDefinition AddAxis(this ControllerDefinition def, string name, Range<int> range, int mid, bool isReversed = false, AxisConstraint constraint = null)
{
def.Axes.Add(name, new AxisSpec(range, mid, isReversed, constraint));
return def;
@ -419,7 +419,7 @@ namespace BizHawk.Emulation.Common
/// </summary>
/// <param name="nameFormat">format string e.g. <c>"P1 Left {0}"</c> (will be used to interpolate <c>"X"</c> and <c>"Y"</c>)</param>
/// <returns>identical reference to <paramref name="def"/>; the object is mutated</returns>
public static ControllerDefinition AddXYPair(this ControllerDefinition def, string nameFormat, AxisPairOrientation pDir, Range<int> rangeX, int midX, Range<int> rangeY, int midY, AxisConstraint? constraint = null)
public static ControllerDefinition AddXYPair(this ControllerDefinition def, string nameFormat, AxisPairOrientation pDir, Range<int> rangeX, int midX, Range<int> rangeY, int midY, AxisConstraint constraint = null)
=> def.AddAxis(string.Format(nameFormat, "X"), rangeX, midX, ((byte) pDir & 2) != 0, constraint)
.AddAxis(string.Format(nameFormat, "Y"), rangeY, midY, ((byte) pDir & 1) != 0);
@ -429,7 +429,7 @@ namespace BizHawk.Emulation.Common
/// </summary>
/// <param name="nameFormat">format string e.g. <c>"P1 Left {0}"</c> (will be used to interpolate <c>"X"</c> and <c>"Y"</c>)</param>
/// <returns>identical reference to <paramref name="def"/>; the object is mutated</returns>
public static ControllerDefinition AddXYPair(this ControllerDefinition def, string nameFormat, AxisPairOrientation pDir, Range<int> rangeBoth, int midBoth, AxisConstraint? constraint = null)
public static ControllerDefinition AddXYPair(this ControllerDefinition def, string nameFormat, AxisPairOrientation pDir, Range<int> rangeBoth, int midBoth, AxisConstraint constraint = null)
=> def.AddXYPair(nameFormat, pDir, rangeBoth, midBoth, rangeBoth, midBoth, constraint);
/// <summary>

View File

@ -40,12 +40,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
AxisPairOrientation.RightAndUp,
(-128).RangeTo(127),
0,
new AxisConstraint
{
Class = "Natural Circle",
Type = AxisConstraintType.Circular,
Params = new object[] { $"P{player} X Axis", $"P{player} Y Axis", 127.0f }
}
new CircularAxisConstraint("Natural Circle", $"P{player} Y Axis", 127.0f)
);
}