2011-01-11 02:55:51 +00:00
using System ;
using System.Collections.Generic ;
2011-08-29 03:28:34 +00:00
using System.Linq ;
2011-01-11 02:55:51 +00:00
2013-11-04 00:36:15 +00:00
using BizHawk.Common ;
2013-11-04 01:39:19 +00:00
using BizHawk.Emulation.Common ;
2013-11-04 00:36:15 +00:00
2013-10-27 07:54:00 +00:00
namespace BizHawk.Client.Common
2011-01-11 02:55:51 +00:00
{
2011-06-19 23:39:25 +00:00
public class Controller : IController
{
2014-01-08 03:53:53 +00:00
private readonly WorkingDictionary < string , List < string > > _bindings = new WorkingDictionary < string , List < string > > ( ) ;
private readonly WorkingDictionary < string , bool > _buttons = new WorkingDictionary < string , bool > ( ) ;
private readonly WorkingDictionary < string , float > _floatButtons = new WorkingDictionary < string , float > ( ) ;
private readonly Dictionary < string , ControllerDefinition . FloatRange > _floatRanges = new WorkingDictionary < string , ControllerDefinition . FloatRange > ( ) ;
private readonly Dictionary < string , Config . AnalogBind > _floatBinds = new Dictionary < string , Config . AnalogBind > ( ) ;
2013-07-18 16:18:17 +00:00
2014-01-08 03:53:53 +00:00
private ControllerDefinition _type ;
2013-07-18 16:18:17 +00:00
2011-07-24 20:37:10 +00:00
public Controller ( ControllerDefinition definition )
{
2013-12-30 01:58:44 +00:00
_type = definition ;
for ( int i = 0 ; i < _type . FloatControls . Count ; i + + )
2013-07-18 16:18:17 +00:00
{
2014-01-08 03:53:53 +00:00
_floatButtons [ _type . FloatControls [ i ] ] = _type . FloatRanges [ i ] . Mid ;
_floatRanges [ _type . FloatControls [ i ] ] = _type . FloatRanges [ i ] ;
2013-07-18 16:18:17 +00:00
}
2011-07-24 20:37:10 +00:00
}
2013-12-30 01:58:44 +00:00
public ControllerDefinition Type { get { return _type ; } }
2012-10-26 18:51:08 +00:00
/// <summary>don't do this</summary>
2013-12-30 01:58:44 +00:00
public void ForceType ( ControllerDefinition newtype ) { _type = newtype ; }
2011-08-09 22:13:57 +00:00
public bool this [ string button ] { get { return IsPressed ( button ) ; } }
public bool IsPressed ( string button )
{
2014-01-08 03:53:53 +00:00
return _buttons [ button ] ;
2011-08-09 22:13:57 +00:00
}
2014-04-28 00:39:40 +00:00
public bool AnyPressed
{
get
{
if ( _buttons . Any ( x = > x . Value ) )
{
return true ;
}
return _floatButtons . Any ( x = > x . Value ! = 0 ) ;
}
}
2014-01-08 03:53:53 +00:00
public float GetFloat ( string name ) { return _floatButtons [ name ] ; }
2011-08-09 22:13:57 +00:00
2013-12-30 01:58:44 +00:00
// Looks for bindings which are activated by the supplied physical button.
2011-08-09 22:13:57 +00:00
public List < string > SearchBindings ( string button )
{
2014-01-08 03:53:53 +00:00
return ( from kvp in _bindings from bound_button in kvp . Value where bound_button = = button select kvp . Key ) . ToList ( ) ;
2011-08-09 22:13:57 +00:00
}
2013-12-30 01:58:44 +00:00
// Searches bindings for the controller and returns true if this binding is mapped somewhere in this controller
2012-12-02 15:18:28 +00:00
public bool HasBinding ( string button )
{
2014-01-08 03:53:53 +00:00
return _bindings . SelectMany ( kvp = > kvp . Value ) . Any ( boundButton = > boundButton = = button ) ;
2012-12-02 15:18:28 +00:00
}
2011-08-09 22:13:57 +00:00
/// <summary>
/// uses the bindings to latch our own logical button state from the source controller's button state (which are assumed to be the physical side of the binding).
/// this will clobber any existing data (use OR_* or other functions to layer in additional input sources)
/// </summary>
public void LatchFromPhysical ( IController controller )
{
2014-01-08 03:53:53 +00:00
_buttons . Clear ( ) ;
2013-10-28 02:11:24 +00:00
2014-01-08 03:53:53 +00:00
foreach ( var kvp in _bindings )
2011-08-09 22:13:57 +00:00
{
2014-01-08 03:53:53 +00:00
_buttons [ kvp . Key ] = false ;
2011-08-09 22:13:57 +00:00
foreach ( var bound_button in kvp . Value )
{
2013-07-18 16:18:17 +00:00
if ( controller [ bound_button ] )
2013-12-30 01:58:44 +00:00
{
2014-01-08 03:53:53 +00:00
_buttons [ kvp . Key ] = true ;
2013-12-30 01:58:44 +00:00
}
2011-08-09 22:13:57 +00:00
}
}
2013-10-28 02:11:24 +00:00
2014-01-08 03:53:53 +00:00
foreach ( var kvp in _floatBinds )
2013-07-18 16:18:17 +00:00
{
2014-01-08 03:53:53 +00:00
var input = controller . GetFloat ( kvp . Value . Value ) ;
2013-07-24 02:14:25 +00:00
string outkey = kvp . Key ;
2013-07-24 00:08:50 +00:00
float multiplier = kvp . Value . Mult ;
2013-07-29 23:39:37 +00:00
float deadzone = kvp . Value . Deadzone ;
2013-07-18 16:18:17 +00:00
ControllerDefinition . FloatRange range ;
2014-01-08 03:53:53 +00:00
if ( _floatRanges . TryGetValue ( outkey , out range ) )
2013-07-18 16:18:17 +00:00
{
// input range is assumed to be -10000,0,10000
2013-07-29 23:39:37 +00:00
// first, modify for deadzone
{
float absinput = Math . Abs ( input ) ;
float zeropoint = deadzone * 10000.0f ;
if ( absinput < zeropoint )
2014-01-08 03:53:53 +00:00
{
2013-07-29 23:39:37 +00:00
input = 0.0f ;
2014-01-08 03:53:53 +00:00
}
2013-07-29 23:39:37 +00:00
else
{
absinput - = zeropoint ;
absinput * = 10000.0f ;
2014-01-08 03:53:53 +00:00
absinput / = 10000.0f - zeropoint ;
2013-07-29 23:39:37 +00:00
input = absinput * Math . Sign ( input ) ;
}
}
2014-01-08 03:53:53 +00:00
var output = ( input * multiplier + 10000.0f ) * ( range . Max - range . Min ) / 20000.0f + range . Min ;
2014-05-17 00:06:20 +00:00
float lbound = Math . Min ( range . Min , range . Max ) ;
float ubound = Math . Max ( range . Min , range . Max ) ;
if ( output < lbound )
2014-01-08 03:53:53 +00:00
{
2014-05-17 00:06:20 +00:00
output = lbound ;
2014-01-08 03:53:53 +00:00
}
2014-05-17 00:06:20 +00:00
if ( output > ubound )
2014-01-08 03:53:53 +00:00
{
2014-05-17 00:06:20 +00:00
output = ubound ;
2014-01-08 03:53:53 +00:00
}
_floatButtons [ outkey ] = output ;
2013-07-18 16:18:17 +00:00
}
}
2011-08-09 22:13:57 +00:00
}
2014-05-17 19:35:47 +00:00
public void ApplyAxisConstraints ( string constraintClass )
{
_type . ApplyAxisConstraints ( constraintClass , _floatButtons ) ;
}
2011-08-09 22:13:57 +00:00
/// <summary>
/// merges pressed logical buttons from the supplied controller, effectively ORing it with the current state
/// </summary>
public void OR_FromLogical ( IController controller )
{
2012-10-26 18:51:08 +00:00
// change: or from each button that the other input controller has
2013-12-30 01:58:44 +00:00
// foreach (string button in type.BoolButtons)
2012-10-26 18:51:08 +00:00
if ( controller . Type ! = null )
2013-12-30 01:58:44 +00:00
{
foreach ( var button in controller . Type . BoolButtons )
2011-08-09 22:13:57 +00:00
{
2012-10-26 18:51:08 +00:00
if ( controller . IsPressed ( button ) )
{
2014-01-08 03:53:53 +00:00
_buttons [ button ] = true ;
2012-10-26 18:51:08 +00:00
}
2011-08-09 22:13:57 +00:00
}
2013-12-30 01:58:44 +00:00
}
2011-08-09 22:13:57 +00:00
}
2014-03-29 21:12:04 +00:00
public void Overrides ( OverrideAdaptor controller )
{
foreach ( var button in controller . Overrides )
{
_buttons [ button ] = controller [ button ] ;
}
2014-05-21 03:25:41 +00:00
foreach ( var button in controller . FloatOverrides )
{
_floatButtons [ button ] = controller . GetFloat ( button ) ;
}
2014-03-29 21:12:04 +00:00
foreach ( var button in controller . InversedButtons )
{
_buttons [ button ] ^ = true ;
}
}
2011-08-09 22:13:57 +00:00
public void BindButton ( string button , string control )
{
2014-01-08 03:53:53 +00:00
_bindings [ button ] . Add ( control ) ;
2011-08-09 22:13:57 +00:00
}
public void BindMulti ( string button , string controlString )
{
if ( string . IsNullOrEmpty ( controlString ) )
2013-12-30 01:58:44 +00:00
{
2011-08-09 22:13:57 +00:00
return ;
2013-12-30 01:58:44 +00:00
}
var controlbindings = controlString . Split ( ',' ) ;
foreach ( var control in controlbindings )
{
2014-01-08 03:53:53 +00:00
_bindings [ button ] . Add ( control . Trim ( ) ) ;
2013-12-30 01:58:44 +00:00
}
2011-08-09 22:13:57 +00:00
}
2013-10-27 17:47:54 +00:00
public void BindFloat ( string button , Config . AnalogBind bind )
2013-07-24 02:14:25 +00:00
{
2014-01-08 03:53:53 +00:00
_floatBinds [ button ] = bind ;
2013-07-24 02:14:25 +00:00
}
2012-09-10 17:49:33 +00:00
/// <summary>
/// Returns a list of all keys mapped and the name of the button they are mapped to
/// </summary>
public List < KeyValuePair < string , string > > MappingList ( )
{
2014-01-08 03:53:53 +00:00
return ( from key in _bindings from binding in key . Value select new KeyValuePair < string , string > ( binding , key . Key ) ) . ToList ( ) ;
2012-09-10 17:49:33 +00:00
}
2012-09-14 21:31:00 +00:00
public List < string > PressedButtons
{
get
{
2014-01-08 03:53:53 +00:00
return ( from button in _buttons where button . Value select button . Key ) . ToList ( ) ;
2012-09-14 21:31:00 +00:00
}
}
2012-09-10 17:49:33 +00:00
}
2011-08-09 22:13:57 +00:00
public class AutofireController : IController
{
2015-02-22 18:02:56 +00:00
public AutofireController ( ControllerDefinition definition , IEmulator emulator )
{
On = Global . Config . AutofireOn < 1 ? 0 : Global . Config . AutofireOn ;
Off = Global . Config . AutofireOff < 1 ? 0 : Global . Config . AutofireOff ;
_type = definition ;
_emulator = emulator ;
}
private readonly IEmulator _emulator ;
2014-01-08 03:53:53 +00:00
private readonly ControllerDefinition _type ;
private readonly WorkingDictionary < string , List < string > > _bindings = new WorkingDictionary < string , List < string > > ( ) ;
private readonly WorkingDictionary < string , bool > _buttons = new WorkingDictionary < string , bool > ( ) ;
private readonly WorkingDictionary < string , int > _buttonStarts = new WorkingDictionary < string , int > ( ) ;
private bool _autofire = true ;
2011-08-09 22:13:57 +00:00
2014-01-08 03:53:53 +00:00
public bool Autofire { get { return false ; } set { _autofire = value ; } }
2011-08-09 22:13:57 +00:00
public int On { get ; set ; }
public int Off { get ; set ; }
2014-01-08 03:53:53 +00:00
public ControllerDefinition Type { get { return _type ; } }
2011-07-24 20:37:10 +00:00
public bool this [ string button ] { get { return IsPressed ( button ) ; } }
2011-08-08 23:35:13 +00:00
public bool IsPressed ( string button )
{
2014-01-08 03:53:53 +00:00
if ( _autofire )
2011-08-08 23:35:13 +00:00
{
2015-02-22 18:02:56 +00:00
var a = ( _emulator . Frame - _buttonStarts [ button ] ) % ( On + Off ) ;
2014-01-08 03:53:53 +00:00
return a < On & & _buttons [ button ] ;
2011-08-08 23:35:13 +00:00
}
2014-07-03 18:17:09 +00:00
return _buttons [ button ] ;
2011-08-08 23:35:13 +00:00
}
2014-08-16 14:33:09 +00:00
public void ClearStarts ( )
{
_buttonStarts . Clear ( ) ;
}
2011-07-24 20:37:10 +00:00
public float GetFloat ( string name ) { throw new NotImplementedException ( ) ; }
2011-06-19 23:39:25 +00:00
2013-12-30 01:58:44 +00:00
// look for bindings which are activated by the supplied physical button.
2011-07-09 22:09:39 +00:00
public List < string > SearchBindings ( string button )
{
2014-01-08 03:53:53 +00:00
return ( from kvp in _bindings from bound_button in kvp . Value where bound_button = = button select kvp . Key ) . ToList ( ) ;
2011-07-09 22:09:39 +00:00
}
2011-07-24 20:23:27 +00:00
/// <summary>
2011-08-04 02:47:05 +00:00
/// uses the bindings to latch our own logical button state from the source controller's button state (which are assumed to be the physical side of the binding).
/// this will clobber any existing data (use OR_* or other functions to layer in additional input sources)
2011-07-24 20:23:27 +00:00
/// </summary>
2011-07-10 02:14:58 +00:00
public void LatchFromPhysical ( IController controller )
{
2014-01-08 03:53:53 +00:00
foreach ( var kvp in _bindings )
2011-08-10 00:34:33 +00:00
{
foreach ( var bound_button in kvp . Value )
{
2014-01-08 03:53:53 +00:00
if ( _buttons [ kvp . Key ] = = false & & controller [ bound_button ] )
2013-12-30 01:58:44 +00:00
{
2015-02-22 18:02:56 +00:00
_buttonStarts [ kvp . Key ] = _emulator . Frame ;
2013-12-30 01:58:44 +00:00
}
2011-08-10 00:34:33 +00:00
}
}
2014-01-08 03:53:53 +00:00
_buttons . Clear ( ) ;
foreach ( var kvp in _bindings )
2011-07-10 02:14:58 +00:00
{
2014-01-08 03:53:53 +00:00
_buttons [ kvp . Key ] = false ;
2011-07-10 02:14:58 +00:00
foreach ( var bound_button in kvp . Value )
{
2011-08-09 22:13:57 +00:00
if ( controller [ bound_button ] )
2011-08-10 00:34:33 +00:00
{
2014-01-08 03:53:53 +00:00
_buttons [ kvp . Key ] = true ;
2011-08-10 00:34:33 +00:00
}
2011-07-10 02:14:58 +00:00
}
}
}
2011-07-24 20:23:27 +00:00
/// <summary>
/// merges pressed logical buttons from the supplied controller, effectively ORing it with the current state
/// </summary>
public void OR_FromLogical ( IController controller )
{
2014-01-08 03:53:53 +00:00
foreach ( var button in _type . BoolButtons . Where ( controller . IsPressed ) )
2011-07-24 20:23:27 +00:00
{
2014-01-08 03:53:53 +00:00
_buttons [ button ] = true ;
2013-12-30 01:58:44 +00:00
Console . WriteLine ( button ) ;
2011-07-24 20:23:27 +00:00
}
}
2011-06-19 23:39:25 +00:00
public void BindButton ( string button , string control )
{
2014-01-08 03:53:53 +00:00
_bindings [ button ] . Add ( control ) ;
2011-06-19 23:39:25 +00:00
}
public void BindMulti ( string button , string controlString )
{
2015-02-22 18:02:56 +00:00
if ( ! string . IsNullOrEmpty ( controlString ) )
2013-10-28 02:11:24 +00:00
{
2013-12-30 01:58:44 +00:00
var controlbindings = controlString . Split ( ',' ) ;
foreach ( var control in controlbindings )
2013-10-28 02:11:24 +00:00
{
2014-01-08 03:53:53 +00:00
_bindings [ button ] . Add ( control . Trim ( ) ) ;
2013-10-28 02:11:24 +00:00
}
}
2011-06-19 23:39:25 +00:00
}
2011-08-29 03:28:34 +00:00
public void IncrementStarts ( )
{
2014-01-08 03:53:53 +00:00
foreach ( var key in _buttonStarts . Keys . ToArray ( ) )
2013-12-30 01:58:44 +00:00
{
2014-01-08 03:53:53 +00:00
_buttonStarts [ key ] + + ;
2013-12-30 01:58:44 +00:00
}
2011-08-29 03:28:34 +00:00
}
2012-09-14 21:31:00 +00:00
public List < string > PressedButtons
{
get
{
2014-01-08 03:53:53 +00:00
return ( from button in _buttons where button . Value select button . Key ) . ToList ( ) ;
2012-09-14 21:31:00 +00:00
}
}
2011-06-19 23:39:25 +00:00
}
2011-01-14 03:38:26 +00:00
}