Polar Coord

- Add polar coordinates to VirtualPadAnalogStick
- Update N64 pad Schema as VirtualPadAnalogStick is a bit larger
- Add Clamp method to NumberExtensions (allows a IComparable<T> value to be restriced between 2 specified other values)
This commit is contained in:
Hathor86 2016-01-23 16:16:19 +01:00
parent c0421965f1
commit f145f3cc68
6 changed files with 178 additions and 72 deletions

View File

@ -85,7 +85,7 @@ namespace BizHawk.Client.EmuHawk
{
Name = button.Name,
Location = UIHelper.Scale(button.Location),
Size = UIHelper.Scale(new Size(127 + 79, 127 + 9)),
Size = UIHelper.Scale(new Size(180 + 79, 200 + 9)),
RangeX = new float[] { button.MinValue, button.MidValue, button.MaxValue },
RangeY = new float[] { button.MinValueSec, button.MidValueSec, button.MaxValueSec },
});

View File

@ -35,18 +35,24 @@
this.MaxLabel = new System.Windows.Forms.Label();
this.MaxXNumeric = new System.Windows.Forms.NumericUpDown();
this.MaxYNumeric = new System.Windows.Forms.NumericUpDown();
this.rLabel = new System.Windows.Forms.Label();
this.manualR = new System.Windows.Forms.NumericUpDown();
this.manualTheta = new System.Windows.Forms.NumericUpDown();
this.thetaLabel = new System.Windows.Forms.Label();
this.AnalogStick = new BizHawk.Client.EmuHawk.AnalogStickPanel();
((System.ComponentModel.ISupportInitialize)(this.ManualX)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.ManualY)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.MaxXNumeric)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.MaxYNumeric)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.manualR)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.manualTheta)).BeginInit();
this.SuspendLayout();
//
// XLabel
//
this.XLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.XLabel.AutoSize = true;
this.XLabel.Location = new System.Drawing.Point(138, 7);
this.XLabel.Location = new System.Drawing.Point(187, 7);
this.XLabel.Name = "XLabel";
this.XLabel.Size = new System.Drawing.Size(14, 13);
this.XLabel.TabIndex = 23;
@ -55,7 +61,7 @@
// ManualX
//
this.ManualX.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.ManualX.Location = new System.Drawing.Point(156, 3);
this.ManualX.Location = new System.Drawing.Point(205, 3);
this.ManualX.Maximum = new decimal(new int[] {
127,
0,
@ -69,14 +75,13 @@
this.ManualX.Name = "ManualX";
this.ManualX.Size = new System.Drawing.Size(44, 20);
this.ManualX.TabIndex = 24;
this.ManualX.ValueChanged += new System.EventHandler(this.ManualX_ValueChanged);
this.ManualX.KeyUp += new System.Windows.Forms.KeyEventHandler(this.ManualX_KeyUp);
this.ManualX.KeyUp += new System.Windows.Forms.KeyEventHandler(this.ManualXY_ValueChanged);
//
// YLabel
//
this.YLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.YLabel.AutoSize = true;
this.YLabel.Location = new System.Drawing.Point(138, 33);
this.YLabel.Location = new System.Drawing.Point(187, 33);
this.YLabel.Name = "YLabel";
this.YLabel.Size = new System.Drawing.Size(14, 13);
this.YLabel.TabIndex = 26;
@ -85,7 +90,7 @@
// ManualY
//
this.ManualY.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.ManualY.Location = new System.Drawing.Point(156, 29);
this.ManualY.Location = new System.Drawing.Point(205, 29);
this.ManualY.Maximum = new decimal(new int[] {
127,
0,
@ -100,14 +105,13 @@
this.ManualY.RightToLeft = System.Windows.Forms.RightToLeft.No;
this.ManualY.Size = new System.Drawing.Size(44, 20);
this.ManualY.TabIndex = 25;
this.ManualY.ValueChanged += new System.EventHandler(this.ManualY_ValueChanged);
this.ManualY.KeyUp += new System.Windows.Forms.KeyEventHandler(this.ManualY_KeyUp);
this.ManualY.KeyUp += new System.Windows.Forms.KeyEventHandler(this.ManualXY_ValueChanged);
//
// MaxLabel
//
this.MaxLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.MaxLabel.AutoSize = true;
this.MaxLabel.Location = new System.Drawing.Point(138, 72);
this.MaxLabel.Location = new System.Drawing.Point(205, 107);
this.MaxLabel.Name = "MaxLabel";
this.MaxLabel.Size = new System.Drawing.Size(47, 13);
this.MaxLabel.TabIndex = 27;
@ -116,7 +120,7 @@
// MaxXNumeric
//
this.MaxXNumeric.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.MaxXNumeric.Location = new System.Drawing.Point(138, 89);
this.MaxXNumeric.Location = new System.Drawing.Point(205, 124);
this.MaxXNumeric.Maximum = new decimal(new int[] {
127,
0,
@ -130,13 +134,13 @@
this.MaxXNumeric.Name = "MaxXNumeric";
this.MaxXNumeric.Size = new System.Drawing.Size(44, 20);
this.MaxXNumeric.TabIndex = 28;
this.MaxXNumeric.ValueChanged += new System.EventHandler(this.MaxXNumeric_ValueChanged);
this.MaxXNumeric.KeyUp += new System.Windows.Forms.KeyEventHandler(this.MaxXNumeric_KeyUp);
this.MaxXNumeric.ValueChanged += new System.EventHandler(this.MaxManualXY_ValueChanged);
this.MaxXNumeric.KeyUp += new System.Windows.Forms.KeyEventHandler(this.MaxManualXY_ValueChanged);
//
// MaxYNumeric
//
this.MaxYNumeric.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.MaxYNumeric.Location = new System.Drawing.Point(138, 112);
this.MaxYNumeric.Location = new System.Drawing.Point(205, 147);
this.MaxYNumeric.Maximum = new decimal(new int[] {
127,
0,
@ -151,21 +155,71 @@
this.MaxYNumeric.RightToLeft = System.Windows.Forms.RightToLeft.No;
this.MaxYNumeric.Size = new System.Drawing.Size(44, 20);
this.MaxYNumeric.TabIndex = 29;
this.MaxYNumeric.ValueChanged += new System.EventHandler(this.MaxYNumeric_ValueChanged);
this.MaxYNumeric.KeyUp += new System.Windows.Forms.KeyEventHandler(this.MaxYNumeric_KeyUp);
this.MaxYNumeric.ValueChanged += new System.EventHandler(this.MaxManualXY_ValueChanged);
this.MaxYNumeric.KeyUp += new System.Windows.Forms.KeyEventHandler(this.MaxManualXY_ValueChanged);
//
// rLabel
//
this.rLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.rLabel.AutoSize = true;
this.rLabel.Location = new System.Drawing.Point(167, 60);
this.rLabel.Name = "rLabel";
this.rLabel.Size = new System.Drawing.Size(26, 13);
this.rLabel.TabIndex = 30;
this.rLabel.Text = "Ray";
//
// manualR
//
this.manualR.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.manualR.DecimalPlaces = 2;
this.manualR.Location = new System.Drawing.Point(193, 58);
this.manualR.Maximum = new decimal(new int[] {
182,
0,
0,
0});
this.manualR.Name = "manualR";
this.manualR.Size = new System.Drawing.Size(56, 20);
this.manualR.TabIndex = 31;
//
// manualTheta
//
this.manualTheta.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.manualTheta.DecimalPlaces = 2;
this.manualTheta.Location = new System.Drawing.Point(193, 84);
this.manualTheta.Maximum = new decimal(new int[] {
360,
0,
0,
0});
this.manualTheta.Minimum = new decimal(new int[] {
360,
0,
0,
-2147483648});
this.manualTheta.Name = "manualTheta";
this.manualTheta.Size = new System.Drawing.Size(56, 20);
this.manualTheta.TabIndex = 33;
//
// thetaLabel
//
this.thetaLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.thetaLabel.AutoSize = true;
this.thetaLabel.Location = new System.Drawing.Point(167, 86);
this.thetaLabel.Name = "thetaLabel";
this.thetaLabel.Size = new System.Drawing.Size(20, 13);
this.thetaLabel.TabIndex = 32;
this.thetaLabel.Text = "θ °";
//
// AnalogStick
//
this.AnalogStick.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.AnalogStick.BackColor = System.Drawing.Color.Gray;
this.AnalogStick.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.AnalogStick.ClearCallback = null;
this.AnalogStick.Location = new System.Drawing.Point(3, 3);
this.AnalogStick.Name = "AnalogStick";
this.AnalogStick.ReadOnly = false;
this.AnalogStick.Size = new System.Drawing.Size(129, 129);
this.AnalogStick.Size = new System.Drawing.Size(164, 164);
this.AnalogStick.TabIndex = 0;
this.AnalogStick.X = 0;
this.AnalogStick.Y = 0;
@ -176,6 +230,10 @@
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.manualTheta);
this.Controls.Add(this.thetaLabel);
this.Controls.Add(this.manualR);
this.Controls.Add(this.rLabel);
this.Controls.Add(this.MaxYNumeric);
this.Controls.Add(this.MaxXNumeric);
this.Controls.Add(this.MaxLabel);
@ -185,12 +243,14 @@
this.Controls.Add(this.XLabel);
this.Controls.Add(this.AnalogStick);
this.Name = "VirtualPadAnalogStick";
this.Size = new System.Drawing.Size(204, 136);
this.Size = new System.Drawing.Size(253, 172);
this.Load += new System.EventHandler(this.VirtualPadAnalogStick_Load);
((System.ComponentModel.ISupportInitialize)(this.ManualX)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.ManualY)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.MaxXNumeric)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.MaxYNumeric)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.manualR)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.manualTheta)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
@ -206,5 +266,9 @@
private System.Windows.Forms.Label MaxLabel;
private System.Windows.Forms.NumericUpDown MaxXNumeric;
private System.Windows.Forms.NumericUpDown MaxYNumeric;
private System.Windows.Forms.Label rLabel;
private System.Windows.Forms.NumericUpDown manualR;
private System.Windows.Forms.NumericUpDown manualTheta;
private System.Windows.Forms.Label thetaLabel;
}
}

View File

@ -5,18 +5,34 @@ using System.Windows.Forms;
using BizHawk.Emulation.Common;
using BizHawk.Client.Common;
using System.Windows;
using BizHawk.Common.NumberExtensions;
namespace BizHawk.Client.EmuHawk
{
public partial class VirtualPadAnalogStick : UserControl, IVirtualPadControl
{
#region Fields
private bool _programmaticallyUpdatingNumerics;
private bool _readonly;
private EventHandler manualXYValueChangedEventHandler;
private EventHandler polarNumericChangedEventHandler;
#endregion
public VirtualPadAnalogStick()
{
InitializeComponent();
AnalogStick.ClearCallback = ClearCallback;
manualXYValueChangedEventHandler = new EventHandler(ManualXY_ValueChanged);
polarNumericChangedEventHandler = new EventHandler(PolarNumeric_Changed);
ManualX.ValueChanged += manualXYValueChangedEventHandler;
ManualY.ValueChanged += manualXYValueChangedEventHandler;
manualR.ValueChanged += polarNumericChangedEventHandler;
manualTheta.ValueChanged += polarNumericChangedEventHandler;
}
public float[] RangeX = new float[] { -128f, 0.0f, 127f };
@ -64,6 +80,8 @@ namespace BizHawk.Client.EmuHawk
{
ManualX.Value = 0;
ManualY.Value = 0;
manualR.Value = 0;
manualTheta.Value = 0;
//see HOOMOO
Global.AutofireStickyXORAdapter.SetSticky(AnalogStick.XName, false);
Global.StickyXORAdapter.Unset(AnalogStick.XName);
@ -95,12 +113,16 @@ namespace BizHawk.Client.EmuHawk
MaxLabel.Enabled =
MaxXNumeric.Enabled =
MaxYNumeric.Enabled =
manualR.Enabled =
rLabel.Enabled =
manualTheta.Enabled =
thetaLabel.Enabled =
!value;
AnalogStick.ReadOnly =
AnalogStick.ReadOnly =
_readonly =
value;
Refresh();
}
}
@ -130,24 +152,30 @@ namespace BizHawk.Client.EmuHawk
AnalogStick.SetPrevious(previous);
}
private void ManualX_ValueChanged(object sender, EventArgs e)
private void ManualXY_ValueChanged(object sender, EventArgs e)
{
SetAnalogControlFromNumerics();
}
private void ManualX_KeyUp(object sender, KeyEventArgs e)
private void MaxManualXY_ValueChanged(object sender, EventArgs e)
{
SetAnalogControlFromNumerics();
SetAnalogMaxFromNumerics();
}
private void ManualY_KeyUp(object sender, KeyEventArgs e)
private void PolarNumeric_Changed(object sender, EventArgs e)
{
SetAnalogControlFromNumerics();
}
ManualX.ValueChanged -= manualXYValueChangedEventHandler;
ManualY.ValueChanged -= manualXYValueChangedEventHandler;
private void ManualY_ValueChanged(object sender, EventArgs e)
{
SetAnalogControlFromNumerics();
ManualX.Value = Math.Ceiling(manualR.Value * (decimal)Math.Cos(Math.PI * (double)manualTheta.Value / 180)).Clamp(-127, 127);
ManualY.Value = Math.Ceiling(manualR.Value * (decimal)Math.Sin(Math.PI * (double)manualTheta.Value / 180)).Clamp(-127, 127);
AnalogStick.X = (int)ManualX.Value;
AnalogStick.Y = (int)ManualY.Value;
AnalogStick.HasValue = true;
AnalogStick.Refresh();
ManualX.ValueChanged += manualXYValueChangedEventHandler;
ManualY.ValueChanged += manualXYValueChangedEventHandler;
}
private void SetAnalogControlFromNumerics()
@ -188,6 +216,15 @@ namespace BizHawk.Client.EmuHawk
ManualY.Value = 0;
}
}
manualR.ValueChanged -= polarNumericChangedEventHandler;
manualTheta.ValueChanged -= polarNumericChangedEventHandler;
manualR.Value = (decimal)Math.Sqrt(Math.Pow(AnalogStick.X, 2) + Math.Pow(AnalogStick.Y, 2));
manualTheta.Value = (decimal)(Math.Atan2(AnalogStick.Y, AnalogStick.X) * (180 / Math.PI));
manualR.ValueChanged += polarNumericChangedEventHandler;
manualTheta.ValueChanged += polarNumericChangedEventHandler;
}
private void AnalogStick_MouseDown(object sender, MouseEventArgs e)
@ -210,26 +247,6 @@ namespace BizHawk.Client.EmuHawk
}
}
private void MaxXNumeric_ValueChanged(object sender, EventArgs e)
{
SetAnalogMaxFromNumerics();
}
private void MaxXNumeric_KeyUp(object sender, KeyEventArgs e)
{
SetAnalogMaxFromNumerics();
}
private void MaxYNumeric_ValueChanged(object sender, EventArgs e)
{
SetAnalogMaxFromNumerics();
}
private void MaxYNumeric_KeyUp(object sender, KeyEventArgs e)
{
SetAnalogMaxFromNumerics();
}
private void SetAnalogMaxFromNumerics()
{
if (!_programmaticallyUpdatingNumerics)

View File

@ -123,8 +123,8 @@ namespace BizHawk.Client.EmuHawk
//dont count on this working. it's never been tested.
//but it kind of must be, or else nothing here would work...
public float ScaleX = 0.5f;
public float ScaleY = 0.5f;
public float ScaleX = 0.60f;
public float ScaleY = 0.60f;
int MinX { get { return (int)(RangeX[0]); } }
int MinY { get { return (int)(RangeY[0]); } }
@ -252,7 +252,7 @@ namespace BizHawk.Client.EmuHawk
unchecked
{
// Background
e.Graphics.Clear(Color.Black);
e.Graphics.Clear(Color.LightGray);
e.Graphics.FillRectangle(GrayBrush, PixelMinX, PixelMinY, PixelMaxX - PixelMinX, PixelMaxY- PixelMinY);
e.Graphics.FillEllipse(ReadOnly ? OffWhiteBrush : WhiteBrush, PixelMinX, PixelMinY, PixelMaxX - PixelMinX - 2, PixelMaxY - PixelMinY - 3);

View File

@ -26,7 +26,7 @@ namespace BizHawk.Client.EmuHawk
return new PadSchema
{
IsConsole = false,
DefaultSize = new Size(220, 316),
DefaultSize = new Size(275, 316),
Buttons = new[]
{
new PadSchema.ButtonScema
@ -34,7 +34,7 @@ namespace BizHawk.Client.EmuHawk
Name = "P" + controller + " DPad U",
DisplayName = "",
Icon = Properties.Resources.BlueUp,
Location = new Point(24, 195),
Location = new Point(24, 230),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonScema
@ -42,7 +42,7 @@ namespace BizHawk.Client.EmuHawk
Name = "P" + controller + " DPad D",
DisplayName = "",
Icon = Properties.Resources.BlueDown,
Location = new Point(24, 216),
Location = new Point(24, 251),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonScema
@ -50,7 +50,7 @@ namespace BizHawk.Client.EmuHawk
Name = "P" + controller + " DPad L",
DisplayName = "",
Icon = Properties.Resources.Back,
Location = new Point(3, 207),
Location = new Point(3, 242),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonScema
@ -58,77 +58,77 @@ namespace BizHawk.Client.EmuHawk
Name = "P" + controller + " DPad R",
DisplayName = "",
Icon = Properties.Resources.Forward,
Location = new Point(45, 207),
Location = new Point(45, 242),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonScema
{
Name = "P" + controller + " L",
DisplayName = "L",
Location = new Point(3, 150),
Location = new Point(3, 185),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonScema
{
Name = "P" + controller + " R",
DisplayName = "R",
Location = new Point(191, 150),
Location = new Point(191, 185),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonScema
{
Name = "P" + controller + " Z",
DisplayName = "Z",
Location = new Point(81, 234),
Location = new Point(81, 269),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonScema
{
Name = "P" + controller + " Start",
DisplayName = "S",
Location = new Point(81, 211),
Location = new Point(81, 246),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonScema
{
Name = "P" + controller + " B",
DisplayName = "B",
Location = new Point(127, 211),
Location = new Point(127, 246),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonScema
{
Name = "P" + controller + " A",
DisplayName = "A",
Location = new Point(138, 234),
Location = new Point(138, 269),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonScema
{
Name = "P" + controller + " C Up",
Icon = Properties.Resources.YellowUp,
Location = new Point(173, 175),
Location = new Point(173, 210),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonScema
{
Name = "P" + controller + " C Down",
Icon = Properties.Resources.YellowDown,
Location = new Point(173, 196),
Location = new Point(173, 231),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonScema
{
Name = "P" + controller + " C Left",
Icon = Properties.Resources.YellowLeft,
Location = new Point(152, 189),
Location = new Point(152, 221),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonScema
{
Name = "P" + controller + " C Right",
Icon = Properties.Resources.YellowRight,
Location = new Point(194, 189),
Location = new Point(194, 221),
Type = PadSchema.PadInputType.Boolean
},
new PadSchema.ButtonScema

View File

@ -1,4 +1,5 @@
using System.Linq;
using System;
using System.Linq;
namespace BizHawk.Common.NumberExtensions
{
@ -106,5 +107,29 @@ namespace BizHawk.Common.NumberExtensions
{
return a - (b * (int)System.Math.Floor((float)a / b));
}
/// <summary>
/// Force the value to be stricly between min and max (both exclued)
/// </summary>
/// <typeparam name="T">Anything that implements <see cref="IComparable{T}"/></typeparam>
/// <param name="val">Value that will be clamped</param>
/// <param name="min">Minimum allowed</param>
/// <param name="max">Maximum allowed</param>
/// <returns>The value if strictly between min and max; otherwise min (or max depending of what is passed)</returns>
public static T Clamp<T>(this T val, T min, T max) where T : IComparable<T>
{
if(val.CompareTo(min) < 0)
{
return min;
}
else if(val.CompareTo(max) > 0)
{
return max;
}
else
{
return val;
}
}
}
}