rework virtual pad analog widget to support n64 and psx simultaneously

This commit is contained in:
zeromus 2015-07-19 21:45:51 -05:00
parent 125a16ec67
commit 0787a3be47
7 changed files with 194 additions and 89 deletions

View File

@ -85,9 +85,9 @@ namespace BizHawk.Client.EmuHawk
{ {
Name = button.Name, Name = button.Name,
Location = UIHelper.Scale(button.Location), Location = UIHelper.Scale(button.Location),
Size = UIHelper.Scale(new Size(button.MaxValue + 79, button.MaxValue + 9)), // TODO: don't use hardcoded values here, at least make them defaults in the AnalogStick object itself Size = UIHelper.Scale(new Size(127 + 79, 127 + 9)),
RangeX = button.MaxValue, RangeX = new float[] { button.MinValue, button.MidValue, button.MaxValue },
RangeY = button.MaxValue // TODO ability to pass in a different Y max RangeY = new float[] { button.MinValueSec, button.MidValueSec, button.MaxValueSec },
}); });
break; break;
case PadSchema.PadInputType.TargetedPair: case PadSchema.PadInputType.TargetedPair:

View File

@ -109,9 +109,9 @@
this.MaxLabel.AutoSize = true; this.MaxLabel.AutoSize = true;
this.MaxLabel.Location = new System.Drawing.Point(138, 72); this.MaxLabel.Location = new System.Drawing.Point(138, 72);
this.MaxLabel.Name = "MaxLabel"; this.MaxLabel.Name = "MaxLabel";
this.MaxLabel.Size = new System.Drawing.Size(27, 13); this.MaxLabel.Size = new System.Drawing.Size(47, 13);
this.MaxLabel.TabIndex = 27; this.MaxLabel.TabIndex = 27;
this.MaxLabel.Text = "Max"; this.MaxLabel.Text = "Range%";
// //
// MaxXNumeric // MaxXNumeric
// //
@ -161,9 +161,8 @@
| System.Windows.Forms.AnchorStyles.Right))); | System.Windows.Forms.AnchorStyles.Right)));
this.AnalogStick.BackColor = System.Drawing.Color.Gray; this.AnalogStick.BackColor = System.Drawing.Color.Gray;
this.AnalogStick.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; this.AnalogStick.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.AnalogStick.ClearCallback = null;
this.AnalogStick.Location = new System.Drawing.Point(3, 3); this.AnalogStick.Location = new System.Drawing.Point(3, 3);
this.AnalogStick.MaxX = 127;
this.AnalogStick.MaxY = 127;
this.AnalogStick.Name = "AnalogStick"; this.AnalogStick.Name = "AnalogStick";
this.AnalogStick.ReadOnly = false; this.AnalogStick.ReadOnly = false;
this.AnalogStick.Size = new System.Drawing.Size(129, 129); this.AnalogStick.Size = new System.Drawing.Size(129, 129);

View File

@ -17,32 +17,33 @@ namespace BizHawk.Client.EmuHawk
{ {
InitializeComponent(); InitializeComponent();
AnalogStick.ClearCallback = ClearCallback; AnalogStick.ClearCallback = ClearCallback;
RangeX = 127;
RangeY = 127;
} }
public int RangeX { get; set; } public float[] RangeX = new float[] { -128f, 0.0f, 127f };
public int RangeY { get; set; } public float[] RangeY = new float[] { -128f, 0.0f, 127f };
private void VirtualPadAnalogStick_Load(object sender, EventArgs e) private void VirtualPadAnalogStick_Load(object sender, EventArgs e)
{ {
AnalogStick.Name = Name; AnalogStick.Name = Name;
AnalogStick.XName = Name; AnalogStick.XName = Name;
AnalogStick.YName = Name.Replace("X", "Y"); // TODO: allow schema to dictate this but this is a convenient default AnalogStick.YName = Name.Replace("X", "Y"); // TODO: allow schema to dictate this but this is a convenient default
AnalogStick.MaxX = RangeX; AnalogStick.SetRangeX(RangeX);
AnalogStick.MaxY = RangeY; AnalogStick.SetRangeY(RangeY);
ManualX.Minimum = AnalogStick.MinX; ManualX.Minimum = (decimal)RangeX[0];
ManualX.Maximum = AnalogStick.MaxX; ManualX.Maximum = (decimal)RangeX[2];
ManualY.Minimum = AnalogStick.MinY; ManualY.Minimum = (decimal)RangeX[0];
ManualY.Maximum = AnalogStick.MaxY; ManualY.Maximum = (decimal)RangeX[2];
MaxXNumeric.Maximum = RangeX; MaxXNumeric.Minimum = 1;
MaxXNumeric.Value = RangeX; MaxXNumeric.Maximum = 100;
MaxXNumeric.Value = 100;
MaxYNumeric.Maximum = RangeY; MaxYNumeric.Minimum = 1;
MaxYNumeric.Value = RangeY; // Note: these trigger change events that change the analog stick too MaxYNumeric.Maximum = 100;
MaxYNumeric.Value = 100; // Note: these trigger change events that change the analog stick too
} }
#region IVirtualPadControl Implementation #region IVirtualPadControl Implementation
@ -233,8 +234,8 @@ namespace BizHawk.Client.EmuHawk
{ {
if (!_programmaticallyUpdatingNumerics) if (!_programmaticallyUpdatingNumerics)
{ {
AnalogStick.MaxX = (int)MaxXNumeric.Value; //blehh,... this damn feature
AnalogStick.MaxY = (int)MaxYNumeric.Value; AnalogStick.SetUserRange((float)MaxXNumeric.Value, (float)MaxYNumeric.Value);
} }
} }
} }

View File

@ -1,9 +1,11 @@
using System.Drawing; using System;
using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
using BizHawk.Client.Common; using BizHawk.Client.Common;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using System;
//Just because this code was mostly rewritten, dont think it isnt still awful
namespace BizHawk.Client.EmuHawk namespace BizHawk.Client.EmuHawk
{ {
@ -48,31 +50,140 @@ namespace BizHawk.Client.EmuHawk
private IController _previous = null; private IController _previous = null;
public int MaxX float UserRangePercentageX = 100, UserRangePercentageY = 100;
public void SetUserRange(float rx, float ry)
{ {
get { return _maxX; } UserRangePercentageX = rx;
set UserRangePercentageY = ry;
{ Rerange();
_maxX = value; Refresh();
CheckMax();
}
} }
public int MaxY public void SetRangeX(float[] range)
{ {
get { return _maxY; } for (int i = 0; i < 3; i++) ActualRangeX[i] = range[i];
set Rerange();
{
_maxY = value;
CheckMax();
}
} }
private int _maxX = 127; public void SetRangeY(float[] range)
private int _maxY = 127; {
for (int i = 0; i < 3; i++) ActualRangeY[i] = range[i];
Rerange();
}
public int MinX { get { return 0 - MaxX - 1; } } public float[] RangeX = new float[] { -128f, 0.0f, 127f };
public int MinY { get { return 0 - MaxY - 1; } } public float[] RangeY = new float[] { -128f, 0.0f, 127f };
public float[] ActualRangeX = new float[] { -128f, 0.0f, 127f };
public float[] ActualRangeY = new float[] { -128f, 0.0f, 127f };
float flipx = 1, flipy = 1;
void Rerange()
{
//baseline:
//Array.Copy(ActualRangeX, RangeX, 3);
//Array.Copy(ActualRangeY, RangeY, 3);
float rx = ActualRangeX[2] - ActualRangeX[0];
float ry = ActualRangeY[2] - ActualRangeY[0];
float midx = rx / 2 + ActualRangeX[0];
float midy = ry / 2 + ActualRangeY[0];
rx *= UserRangePercentageX / 100;
ry *= UserRangePercentageY / 100;
float minx = midx - rx / 2;
float maxx = minx + rx;
float miny = midy - ry / 2;
float maxy = miny + ry;
if (minx > maxx)
{
float temp = minx;
minx = maxx;
maxx = temp;
flipx = -1;
}
if (miny > maxy)
{
float temp = miny;
miny = maxy;
maxy = temp;
flipy = -1;
}
//Range?[1] isn't really used
RangeX[0] = minx;
RangeX[2] = maxx;
RangeY[0] = miny;
RangeY[2] = maxy;
Clamp();
}
//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;
int MinX { get { return (int)(RangeX[0]); } }
int MinY { get { return (int)(RangeY[0]); } }
int MaxX { get { return (int)(RangeX[2]); } }
int MaxY { get { return (int)(RangeY[2]); } }
int RangeSizeX { get { return (int)(MaxX - MinX + 1); } }
int RangeSizeY { get { return (int)(MaxY - MinY + 1); } }
int PixelSizeX { get { return (int)(RangeSizeX * ScaleX); } }
int PixelSizeY { get { return (int)(RangeSizeY * ScaleY); } }
int PixelMinX { get { return (Size.Width - PixelSizeX) / 2; } }
int PixelMinY { get { return (Size.Height - PixelSizeY) / 2; } }
int PixelMidX { get { return PixelMinX + PixelSizeX / 2; } }
int PixelMidY { get { return PixelMinY + PixelSizeY / 2; } }
int PixelMaxX { get { return PixelMinX + PixelSizeX - 1; } }
int PixelMaxY { get { return PixelMinY + PixelSizeY - 1; } }
private int RealToGfxX(int val)
{
int v = val;
if (flipx == -1)
v = (MaxX - val) + MinX;
v = (int)(((float)v - MinX) * ScaleX);
v += PixelMinX;
return v;
}
private int RealToGfxY(int val)
{
int v = val;
if (flipy == -1)
v = (MaxY - val) + MinY;
v = (int)(((float)v - MinY) * ScaleY);
v += PixelMinY;
return v;
}
private int GfxToRealX(int val)
{
val -= PixelMinX;
float v = ((float)val / ScaleX + MinX);
if (v < MinX) v = MinX;
if (v > MaxX) v = MaxX;
if (flipx == -1)
v = (MaxX - v) + MinX;
return (int)v;
}
private int GfxToRealY(int val)
{
val -= PixelMinY;
float v;
v = ((float)val / ScaleY + MinY);
if (v < MinX) v = MinX;
if (v > MaxX) v = MaxX;
if(flipy == -1)
v = (MaxY - v) + MinY;
return (int)v;
}
private readonly Brush WhiteBrush = Brushes.White; private readonly Brush WhiteBrush = Brushes.White;
private readonly Brush GrayBrush = Brushes.LightGray; private readonly Brush GrayBrush = Brushes.LightGray;
@ -98,7 +209,7 @@ namespace BizHawk.Client.EmuHawk
public AnalogStickPanel() public AnalogStickPanel()
{ {
Size = new Size(MaxX + 1, MaxY + 1); Size = new Size(PixelSizeX + 1, PixelSizeY + 1);
SetStyle(ControlStyles.AllPaintingInWmPaint, true); SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true); SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
@ -126,30 +237,6 @@ namespace BizHawk.Client.EmuHawk
} }
} }
private int RealToGfx(int val)
{
return (val + MaxX) / 2;
}
private int GfxToReal(int val, bool isX) // isX is a hack
{
var max = isX ? MaxX : MaxY;
var min = isX ? MinX : MinY;
var ret = (val * 2);
if (ret > max)
{
ret = max;
}
if (ret < min)
{
ret = min;
}
return ret;
}
private void SetAnalog() private void SetAnalog()
{ {
var xn = HasValue ? X : (int?)null; var xn = HasValue ? X : (int?)null;
@ -160,35 +247,33 @@ namespace BizHawk.Client.EmuHawk
Refresh(); Refresh();
} }
private int MidX { get { return (int)((MaxX + 0.5) / 2); } }
private int MidY { get { return (int)((MaxY + 0.5) / 2); } }
private void AnalogControlPanel_Paint(object sender, PaintEventArgs e) private void AnalogControlPanel_Paint(object sender, PaintEventArgs e)
{ {
unchecked unchecked
{ {
// Background // Background
e.Graphics.Clear(Color.Black); e.Graphics.Clear(Color.Black);
e.Graphics.FillRectangle(GrayBrush, 0, 0, MaxX, MaxY);
e.Graphics.FillEllipse(ReadOnly ? OffWhiteBrush : WhiteBrush, 0, 0, MaxX - 1, MaxY - 3); e.Graphics.FillRectangle(GrayBrush, PixelMinX, PixelMinY, PixelMaxX - PixelMinX, PixelMaxY- PixelMinY);
e.Graphics.DrawEllipse(BlackPen, 0, 0, MaxX - 1, MaxY - 3); e.Graphics.FillEllipse(ReadOnly ? OffWhiteBrush : WhiteBrush, PixelMinX, PixelMinY, PixelMaxX - PixelMinX - 2, PixelMaxY - PixelMinY - 3);
e.Graphics.DrawLine(BlackPen, MidX, 0, MidX, MaxY); e.Graphics.DrawEllipse(BlackPen, PixelMinX, PixelMinY, PixelMaxX - PixelMinX - 2, PixelMaxY - PixelMinY - 3);
e.Graphics.DrawLine(BlackPen, 0, MidY, MaxX, MidY); e.Graphics.DrawLine(BlackPen, PixelMidX, 0, PixelMidX, PixelMaxY);
e.Graphics.DrawLine(BlackPen, 0, PixelMidY, PixelMaxX, PixelMidY);
// Previous frame // Previous frame
if (_previous != null) if (_previous != null)
{ {
var pX = (int)_previous.GetFloat(XName); var pX = (int)_previous.GetFloat(XName);
var pY = (int)_previous.GetFloat(YName); var pY = (int)_previous.GetFloat(YName);
e.Graphics.DrawLine(GrayPen, MidX, MidY, RealToGfx(pX), MaxY - RealToGfx(pY)); e.Graphics.DrawLine(GrayPen, PixelMidX, PixelMidY, RealToGfxX(pX), RealToGfxY(pY));
e.Graphics.DrawImage(GrayDot, RealToGfx(pX) - 3, MaxY - RealToGfx(pY) - 3); e.Graphics.DrawImage(GrayDot, RealToGfxX(pX) - 3, RealToGfxY(MaxY) - RealToGfxY(pY) - 3);
} }
// Line // Line
if (HasValue) if (HasValue)
{ {
e.Graphics.DrawLine(BluePen, MidX, MidY, RealToGfx(X), MaxY - RealToGfx(Y)); e.Graphics.DrawLine(BluePen, PixelMidX, PixelMidY, RealToGfxX(X), RealToGfxY(Y));
e.Graphics.DrawImage(ReadOnly ? GrayDot : Dot, RealToGfx(X) - 3, MaxY - RealToGfx(Y) - 3); e.Graphics.DrawImage(ReadOnly ? GrayDot : Dot, RealToGfxX(X) - 3, RealToGfxY(Y) - 3);
} }
} }
} }
@ -199,8 +284,9 @@ namespace BizHawk.Client.EmuHawk
{ {
if (e.Button == MouseButtons.Left) if (e.Button == MouseButtons.Left)
{ {
X = GfxToReal(e.X - MidX, true); X = GfxToRealX(e.X);
Y = GfxToReal(-(e.Y - MidY), false); Y = GfxToRealY(e.Y);
Clamp();
HasValue = true; HasValue = true;
SetAnalog(); SetAnalog();
} }
@ -237,8 +323,9 @@ namespace BizHawk.Client.EmuHawk
{ {
if (e.Button == MouseButtons.Left) if (e.Button == MouseButtons.Left)
{ {
X = GfxToReal(e.X - MidX, true); X = GfxToRealX(e.X);
Y = GfxToReal(-(e.Y - MidY), false); Y = GfxToRealY(e.Y);
Clamp();
HasValue = true; HasValue = true;
} }
if (e.Button == MouseButtons.Right) if (e.Button == MouseButtons.Right)
@ -282,12 +369,13 @@ namespace BizHawk.Client.EmuHawk
{ {
X = xval; X = xval;
Y = yval; Y = yval;
Clamp();
HasValue = true; HasValue = true;
Refresh(); Refresh();
} }
private void CheckMax() private void Clamp()
{ {
if (X > MaxX) if (X > MaxX)
{ {
@ -306,8 +394,6 @@ namespace BizHawk.Client.EmuHawk
{ {
Y = MinY; Y = MinY;
} }
Refresh();
} }
} }
} }

View File

@ -134,7 +134,12 @@ namespace BizHawk.Client.EmuHawk
new PadSchema.ButtonScema new PadSchema.ButtonScema
{ {
Name = "P" + controller + " X Axis", Name = "P" + controller + " X Axis",
MinValue = -128,
MidValue = 0,
MaxValue = 127, MaxValue = 127,
MinValueSec = 127,
MidValueSec = 0,
MaxValueSec = -128,
DisplayName = "", DisplayName = "",
Location = new Point(6, 14), Location = new Point(6, 14),
Type = PadSchema.PadInputType.AnalogStick Type = PadSchema.PadInputType.AnalogStick

View File

@ -164,7 +164,12 @@ namespace BizHawk.Client.EmuHawk
new PadSchema.ButtonScema new PadSchema.ButtonScema
{ {
Name = "P" + controller + " LStick X", Name = "P" + controller + " LStick X",
MaxValue = 127, MinValue = 0,
MidValue = 128,
MaxValue = 255,
MinValueSec = 0,
MidValueSec = 128,
MaxValueSec = 255,
DisplayName = "", DisplayName = "",
Location = new Point(3, 120), Location = new Point(3, 120),
Type = PadSchema.PadInputType.AnalogStick Type = PadSchema.PadInputType.AnalogStick
@ -172,7 +177,12 @@ namespace BizHawk.Client.EmuHawk
new PadSchema.ButtonScema new PadSchema.ButtonScema
{ {
Name = "P" + controller + " RStick X", Name = "P" + controller + " RStick X",
MaxValue = 127, MinValue = 0,
MidValue = 128,
MaxValue = 255,
MinValueSec = 0,
MidValueSec = 128,
MaxValueSec = 255,
DisplayName = "", DisplayName = "",
Location = new Point(210, 120), Location = new Point(210, 120),
Type = PadSchema.PadInputType.AnalogStick Type = PadSchema.PadInputType.AnalogStick

View File

@ -31,7 +31,11 @@ namespace BizHawk.Client.EmuHawk
public Size TargetSize { get; set; } // Specifically for TargetedPair, specifies the screen size public Size TargetSize { get; set; } // Specifically for TargetedPair, specifies the screen size
public string[] SecondaryNames { get; set; } // Any other buttons necessary to operate (such as the Y axis) public string[] SecondaryNames { get; set; } // Any other buttons necessary to operate (such as the Y axis)
public int MaxValue { get; set; } // For non-boolean values, specifies the maximum value the button allows public int MaxValue { get; set; } // For non-boolean values, specifies the maximum value the button allows
public int MidValue { get; set; } // For non-boolean values, specifies the mid (zero) value for the button
public int MinValue { get; set; } // For non-boolean values, specifies the minimum value the button allows public int MinValue { get; set; } // For non-boolean values, specifies the minimum value the button allows
public int MaxValueSec { get; set; }
public int MidValueSec { get; set; }
public int MinValueSec { get; set; }
public object OwnerEmulator { get; set; } public object OwnerEmulator { get; set; }
} }
} }