2014-06-22 13:58:12 +00:00
using System ;
using System.Collections.Generic ;
using System.Drawing ;
using System.Linq ;
2014-06-24 00:26:35 +00:00
using System.Reflection ;
2014-06-22 13:58:12 +00:00
using System.Windows.Forms ;
using BizHawk.Client.Common ;
namespace BizHawk.Client.EmuHawk
{
public partial class VirtualpadTool : Form , IToolForm
{
private int _defaultWidth ;
private int _defaultHeight ;
2014-06-29 03:14:40 +00:00
private bool _readOnly ;
2014-06-22 13:58:12 +00:00
2014-06-22 15:05:37 +00:00
private List < VirtualPad > Pads
2014-06-22 13:58:12 +00:00
{
get
{
return ControllerBox . Controls
2014-06-22 15:05:37 +00:00
. OfType < VirtualPad > ( )
2014-06-22 13:58:12 +00:00
. ToList ( ) ;
}
}
2014-06-27 01:45:30 +00:00
public bool Readonly
2014-06-26 20:36:33 +00:00
{
get
{
2014-06-27 01:45:30 +00:00
return _readOnly ;
}
set
{
_readOnly = value ;
Pads . ForEach ( p = > p . ReadOnly = value ) ;
2014-06-26 20:36:33 +00:00
}
}
2014-06-22 13:58:12 +00:00
public VirtualpadTool ( )
{
InitializeComponent ( ) ;
2014-06-22 15:05:37 +00:00
Closing + = ( o , e ) = > SaveConfigSettings ( ) ;
TopMost = Global . Config . VirtualPadSettings . TopMost ;
2014-06-22 13:58:12 +00:00
}
private void VirtualpadTool_Load ( object sender , EventArgs e )
{
_defaultWidth = Size . Width ;
_defaultHeight = Size . Height ;
if ( Global . Config . VirtualPadSettings . UseWindowPosition )
{
Location = Global . Config . VirtualPadSettings . WindowPosition ;
}
if ( Global . Config . VirtualPadSettings . UseWindowPosition )
{
Size = Global . Config . VirtualPadSettings . WindowSize ;
}
CreatePads ( ) ;
}
public void ClearVirtualPadHolds ( )
{
2014-06-24 16:36:19 +00:00
Pads . ForEach ( pad = > pad . Clear ( ) ) ;
2014-06-22 13:58:12 +00:00
}
2014-06-29 23:43:31 +00:00
public void BumpAnalogValue ( int? x , int? y ) // TODO: multi-player
2014-06-22 13:58:12 +00:00
{
2014-06-29 23:43:31 +00:00
Pads . ForEach ( pad = > pad . BumpAnalog ( x , y ) ) ;
2014-06-22 13:58:12 +00:00
}
private void CreatePads ( )
{
ControllerBox . Controls . Clear ( ) ;
2014-06-24 00:26:35 +00:00
var schemaType = Assembly
. GetExecutingAssembly ( )
. GetTypes ( )
. Where ( t = > typeof ( IVirtualPadSchema )
. IsAssignableFrom ( t ) & & t . GetCustomAttributes ( false )
. OfType < SchemaAttributes > ( )
. Any ( ) )
. FirstOrDefault ( t = > t . GetCustomAttributes ( false )
. OfType < SchemaAttributes > ( )
. First ( ) . SystemId = = Global . Emulator . SystemId ) ;
if ( schemaType ! = null )
2014-06-22 13:58:12 +00:00
{
2014-06-30 17:14:02 +00:00
var padschemas = ( Activator . CreateInstance ( schemaType ) as IVirtualPadSchema ) . GetPadSchemas ( ) ;
2014-06-30 18:28:55 +00:00
if ( VersionInfo . DeveloperBuild )
{
CheckPads ( padschemas , Global . Emulator . ControllerDefinition ) ;
}
2014-06-30 17:14:02 +00:00
var pads = padschemas . Select ( s = > new VirtualPad ( s ) ) ;
2014-06-27 17:02:46 +00:00
2014-06-26 21:09:14 +00:00
if ( pads . Any ( ) )
{
ControllerBox . Controls . AddRange ( pads . Reverse ( ) . ToArray ( ) ) ;
}
2014-06-22 13:58:12 +00:00
}
}
2014-06-30 17:14:02 +00:00
private void CheckPads ( IEnumerable < PadSchema > schemas , BizHawk . Emulation . Common . ControllerDefinition def )
{
HashSet < string > analogs = new HashSet < string > ( def . FloatControls ) ;
HashSet < string > bools = new HashSet < string > ( def . BoolButtons ) ;
foreach ( var schema in schemas )
{
foreach ( var button in schema . Buttons )
{
HashSet < string > searchset = null ;
switch ( button . Type )
{
case PadSchema . PadInputType . AnalogStick :
case PadSchema . PadInputType . FloatSingle :
case PadSchema . PadInputType . TargetedPair :
// analog
searchset = analogs ;
break ;
case PadSchema . PadInputType . Boolean :
searchset = bools ;
break ;
}
if ( ! searchset . Contains ( button . Name ) )
{
MessageBox . Show ( this ,
string . Format ( "Schema warning: Schema entry '{0}':'{1}' will not correspond to any control in definition '{2}'" , schema . DisplayName , button . Name , def . Name ) ,
"Dev Warning" ) ;
}
}
}
}
2014-06-22 15:05:37 +00:00
private void SaveConfigSettings ( )
{
Global . Config . VirtualPadSettings . Wndx = Location . X ;
Global . Config . VirtualPadSettings . Wndy = Location . Y ;
Global . Config . VirtualPadSettings . Width = Right - Left ;
Global . Config . VirtualPadSettings . Height = Bottom - Top ;
}
2014-06-22 13:58:12 +00:00
private void RefreshFloatingWindowControl ( )
{
Owner = Global . Config . VirtualPadSettings . FloatingWindow ? null : GlobalWin . MainForm ;
}
#region IToolForm Implementation
public bool AskSave ( ) { return true ; }
public bool UpdateBefore { get { return false ; } }
public void Restart ( )
{
if ( ! IsHandleCreated | | IsDisposed )
{
return ;
}
CreatePads ( ) ;
}
public void UpdateValues ( )
{
if ( ! IsHandleCreated | | IsDisposed )
{
return ;
}
2014-06-29 14:42:20 +00:00
Pads . ForEach ( p = > p . SetPrevious ( null ) ) ; // Not the cleanest way to clear this every frame
if ( Global . MovieSession . Movie . IsPlaying & & ! Global . MovieSession . Movie . IsFinished )
2014-06-22 13:58:12 +00:00
{
2014-06-27 01:45:30 +00:00
Readonly = true ;
2014-06-24 17:12:20 +00:00
Pads . ForEach ( p = > p . Set ( Global . MovieSession . CurrentInput ) ) ;
2014-06-22 13:58:12 +00:00
}
2014-06-26 20:07:07 +00:00
else
{
2014-06-29 14:42:20 +00:00
if ( Global . MovieSession . Movie . IsRecording )
{
Pads . ForEach ( p = > p . SetPrevious ( Global . MovieSession . PreviousFrame ) ) ;
}
2014-06-27 01:45:30 +00:00
Readonly = false ;
2014-06-26 20:07:07 +00:00
}
2014-06-24 16:36:19 +00:00
2014-06-26 20:37:44 +00:00
if ( ! Readonly & & ! Global . Config . VirtualPadSticky )
2014-06-26 20:36:33 +00:00
{
Pads . ForEach ( pad = > pad . Clear ( ) ) ;
}
2014-07-04 15:15:08 +00:00
Pads . ForEach ( pad = > pad . Refresh ( ) ) ;
2014-06-22 13:58:12 +00:00
}
#endregion
#region Events
#region Menu
private void OptionsSubMenu_DropDownOpened ( object sender , EventArgs e )
{
AutoloadMenuItem . Checked = Global . Config . AutoloadVirtualPad ;
SaveWindowPositionMenuItem . Checked = Global . Config . VirtualPadSettings . SaveWindowPosition ;
AlwaysOnTopMenuItem . Checked = Global . Config . VirtualPadSettings . TopMost ;
FloatingWindowMenuItem . Checked = Global . Config . VirtualPadSettings . FloatingWindow ;
}
private void AutoloadMenuItem_Click ( object sender , EventArgs e )
{
Global . Config . AutoloadVirtualPad ^ = true ;
}
private void SaveWindowPositionMenuItem_Click ( object sender , EventArgs e )
{
Global . Config . VirtualPadSettings . SaveWindowPosition ^ = true ;
}
private void AlwaysOnTopMenuItem_Click ( object sender , EventArgs e )
{
Global . Config . VirtualPadSettings . TopMost ^ = true ;
TopMost = Global . Config . VirtualPadSettings . TopMost ;
}
private void FloatingWindowMenuItem_Click ( object sender , EventArgs e )
{
Global . Config . VirtualPadSettings . FloatingWindow ^ = true ;
RefreshFloatingWindowControl ( ) ;
}
private void RestoreDefaultSettingsMenuItem_Click ( object sender , EventArgs e )
{
Size = new Size ( _defaultWidth , _defaultHeight ) ;
Global . Config . VirtualPadSettings . SaveWindowPosition = true ;
Global . Config . VirtualPadSettings . TopMost = TopMost = false ;
Global . Config . VirtualPadSettings . FloatingWindow = false ;
Global . Config . VirtualPadMultiplayerMode = false ;
}
private void ExitMenuItem_Click ( object sender , EventArgs e )
{
Close ( ) ;
}
2014-06-22 15:05:37 +00:00
private void PadsSubMenu_DropDownOpened ( object sender , EventArgs e )
{
2014-06-26 20:24:30 +00:00
StickyMenuItem . Checked = Global . Config . VirtualPadSticky ;
2014-06-22 15:05:37 +00:00
}
2014-06-22 13:58:12 +00:00
private void ClearAllMenuItem_Click ( object sender , EventArgs e )
{
ClearVirtualPadHolds ( ) ;
}
2014-06-22 15:05:37 +00:00
private void StickyMenuItem_Click ( object sender , EventArgs e )
{
2014-06-26 20:24:30 +00:00
Global . Config . VirtualPadSticky ^ = true ;
2014-06-22 15:05:37 +00:00
}
2014-06-29 21:16:33 +00:00
private void PadBoxContextMenu_Opening ( object sender , System . ComponentModel . CancelEventArgs e )
{
StickyContextMenuItem . Checked = Global . Config . VirtualPadSticky ;
}
2014-06-22 13:58:12 +00:00
#endregion
#endregion
}
}