using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; using BizHawk.Emulation.Common; using System.Drawing; namespace BizHawk.Client.EmuHawk { public partial class VirtualPad : UserControl { private readonly PadSchema _schema; private bool _readOnly; public void UpdateValues() { PadControls.ForEach(c => c.UpdateValues()); } private List PadControls => PadBox.Controls .OfType() .ToList(); public string PadSchemaDisplayName => _schema.DisplayName; public bool ReadOnly { get => _readOnly; set { _readOnly = value; PadControls.ForEach(c => c.ReadOnly = value); } } public VirtualPad(PadSchema schema) { SetStyle(ControlStyles.AllPaintingInWmPaint, true); SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.DoubleBuffer, true); InitializeComponent(); Dock = DockStyle.Top | DockStyle.Left; _schema = schema; } private void VirtualPadControl_Load(object sender, EventArgs e) { static VirtualPadButton GenVirtualPadButton(ButtonSchema button) { var buttonControl = new VirtualPadButton { Name = button.Name, Text = button.Icon != null ? null : button.DisplayName, Location = UIHelper.Scale(button.Location), Image = button.Icon }; if (button.Icon != null && UIHelper.AutoScaleFactorX > 1F && UIHelper.AutoScaleFactorY > 1F) { // When scaling up, unfortunately the icon will look too small, but at least we can make the rest of the button bigger buttonControl.AutoSize = false; buttonControl.Size = UIHelper.Scale(button.Icon.Size) + new Size(6, 6); } return buttonControl; } Size = UIHelper.Scale(_schema.Size); MaximumSize = UIHelper.Scale(_schema.Size); PadBox.Text = _schema.DisplayName; if (_schema.IsConsole) { this.PadBox.ForeColor = SystemColors.HotTrack; } foreach (var controlSchema in _schema.Buttons) { PadBox.Controls.Add(controlSchema switch { ButtonSchema button => GenVirtualPadButton(button), SingleAxisSchema singleAxis => new VirtualPadAnalogButton { Name = singleAxis.Name, DisplayName = singleAxis.DisplayName, Location = UIHelper.Scale(singleAxis.Location), Size = UIHelper.Scale(singleAxis.TargetSize), MinValue = singleAxis.MinValue, MaxValue = singleAxis.MaxValue, Orientation = singleAxis.Orientation }, AnalogSchema analog => new VirtualPadAnalogStick { Name = analog.Name, SecondaryName = analog.SecondaryName, Location = UIHelper.Scale(analog.Location), Size = UIHelper.Scale(new Size(180 + 79, 200 + 9)), RangeX = analog.AxisRange, RangeY = analog.SecondaryAxisRange }, TargetedPairSchema targetedPair => new VirtualPadTargetScreen { Name = targetedPair.Name, Location = UIHelper.Scale(targetedPair.Location), TargetSize = targetedPair.TargetSize, XName = targetedPair.Name, YName = targetedPair.SecondaryName, RangeX = targetedPair.MaxValue, RangeY = targetedPair.MaxValue //TODO split into MaxX and MaxY, and rename VirtualPadTargetScreen.RangeX/RangeY }, DiscManagerSchema discManager => new VirtualPadDiscManager(discManager.SecondaryNames) { Name = discManager.Name, Location = UIHelper.Scale(discManager.Location), Size = UIHelper.Scale(discManager.TargetSize), OwnerEmulator = discManager.OwnerEmulator }, _ => throw new InvalidOperationException() }); } } public void Clear() { PadControls.ForEach(p => p.Clear()); } public void ClearBoolean() { foreach (var p in PadControls.OfType()) { p.Clear(); } } public void Set(IController controller) { PadControls.ForEach(c => c.Set(controller)); } public void SetPrevious(IController previous) { foreach (var c in PadControls.OfType()) { c.SetPrevious(previous); } } public void BumpAnalog(int? x, int? y) { foreach (var a in PadControls.OfType()) { a.Bump(x, y); } foreach (var a in PadControls.OfType()) { a.Bump(x); } foreach (var a in PadControls.OfType()) { a.Bump(x, y); } } } }