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
{
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
}
2017-04-14 19:59:01 +00:00
public ControllerDefinition Definition = > _type ;
2013-12-30 01:58:44 +00:00
2017-04-15 20:37:30 +00:00
public bool IsPressed ( string button )
2011-08-09 22:13:57 +00:00
{
2014-01-08 03:53:53 +00:00
return _buttons [ button ] ;
2011-08-09 22:13:57 +00:00
}
2016-12-14 20:12:16 +00:00
public float GetFloat ( string name )
{
return _floatButtons [ name ] ;
}
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 > ( ) ;
private ControllerDefinition _type ;
/// <summary>don't do this</summary>
2019-11-15 00:18:46 +00:00
public void ForceType ( ControllerDefinition newType ) { _type = newType ; }
2016-12-14 20:12:16 +00:00
2017-05-09 12:21:38 +00:00
public bool this [ string button ] = > IsPressed ( button ) ;
2016-12-14 20:12:16 +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 )
{
2017-05-09 12:21:38 +00:00
return ( from kvp in _bindings from boundButton in kvp . Value where boundButton = = 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 )
{
2019-11-15 00:18:46 +00:00
return _bindings
. SelectMany ( kvp = > kvp . Value )
. Any ( boundButton = > boundButton = = button ) ;
2012-12-02 15:18:28 +00:00
}
2015-03-10 02:55:55 +00:00
public void NormalizeFloats ( IController controller )
2011-08-09 22:13:57 +00:00
{
2014-01-08 03:53:53 +00:00
foreach ( var kvp in _floatBinds )
2013-07-18 16:18:17 +00:00
{
2015-03-10 02:55:55 +00:00
var input = _floatButtons [ kvp . Key ] ;
2019-11-15 00:18:46 +00:00
string outKey = kvp . Key ;
2013-07-24 00:08:50 +00:00
float multiplier = kvp . Value . Mult ;
2019-11-15 00:18:46 +00:00
float deadZone = kvp . Value . Deadzone ;
if ( _floatRanges . TryGetValue ( outKey , out var 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
2019-11-15 00:18:46 +00:00
// first, modify for deadZone
float absInput = Math . Abs ( input ) ;
float zeroPoint = deadZone * 10000.0f ;
if ( absInput < zeroPoint )
2013-07-29 23:39:37 +00:00
{
2019-11-15 00:18:46 +00:00
input = 0.0f ;
2013-07-29 23:39:37 +00:00
}
2019-11-15 00:18:46 +00:00
else
{
absInput - = zeroPoint ;
absInput * = 10000.0f ;
absInput / = 10000.0f - zeroPoint ;
input = absInput * Math . Sign ( input ) ;
}
2013-07-29 23:39:37 +00:00
2017-04-14 19:59:01 +00:00
// zero 09-mar-2015 - not sure if adding + 1 here is correct.. but... maybe?
2019-12-30 22:28:48 +00:00
float output = 0 ;
if ( range . Max < range . Min )
{
output = ( ( ( input * multiplier ) + 10000.0f ) * ( range . Min - range . Max + 1 ) / 20000.0f ) + range . Max ;
}
else
{
output = ( ( ( input * multiplier ) + 10000.0f ) * ( range . Max - range . Min + 1 ) / 20000.0f ) + range . Min ;
}
2014-05-17 00:06:20 +00:00
2019-11-15 00:18:46 +00:00
// zero 09-mar-2015 - at this point, we should only have integers, since that's all 100% of consoles ever see
2017-04-14 19:59:01 +00:00
// if this becomes a problem we can add flags to the range and update GUIs to be able to display floats
2015-03-10 03:34:24 +00:00
output = ( int ) output ;
2019-11-15 00:18:46 +00:00
float lowerBound = Math . Min ( range . Min , range . Max ) ;
float upperBound = Math . Max ( range . Min , range . Max ) ;
2014-05-17 00:06:20 +00:00
2019-11-15 00:18:46 +00:00
if ( output < lowerBound )
2014-01-08 03:53:53 +00:00
{
2019-11-15 00:18:46 +00:00
output = lowerBound ;
2014-01-08 03:53:53 +00:00
}
2019-11-15 00:18:46 +00:00
if ( output > upperBound )
2014-01-08 03:53:53 +00:00
{
2019-11-15 00:18:46 +00:00
output = upperBound ;
2014-01-08 03:53:53 +00:00
}
2019-11-15 00:18:46 +00:00
_floatButtons [ outKey ] = output ;
2013-07-18 16:18:17 +00:00
}
}
2011-08-09 22:13:57 +00:00
}
2015-03-10 02:55:55 +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 )
{
_buttons . Clear ( ) ;
foreach ( var kvp in _bindings )
{
_buttons [ kvp . Key ] = false ;
2019-11-15 00:18:46 +00:00
foreach ( var button in kvp . Value )
2015-03-10 02:55:55 +00:00
{
2019-11-15 00:18:46 +00:00
if ( controller . IsPressed ( button ) )
2015-03-10 02:55:55 +00:00
{
_buttons [ kvp . Key ] = true ;
}
}
}
foreach ( var kvp in _floatBinds )
{
var input = controller . GetFloat ( kvp . Value . Value ) ;
2019-11-15 00:18:46 +00:00
string outKey = kvp . Key ;
if ( _floatRanges . ContainsKey ( outKey ) )
2015-03-10 02:55:55 +00:00
{
2019-11-15 00:18:46 +00:00
_floatButtons [ outKey ] = input ;
2015-03-10 02:55:55 +00:00
}
}
2017-04-14 19:59:01 +00:00
// it's not sure where this should happen, so for backwards compatibility.. do it every time
2015-03-10 02:55:55 +00:00
NormalizeFloats ( controller ) ;
}
2014-05-17 19:35:47 +00:00
public void ApplyAxisConstraints ( string constraintClass )
{
2017-05-09 18:19:55 +00:00
_type . ApplyAxisConstraints ( constraintClass , _floatButtons ) ;
2014-05-17 19:35:47 +00:00
}
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)
2016-12-12 18:30:32 +00:00
if ( controller . Definition ! = null )
2013-12-30 01:58:44 +00:00
{
2016-12-12 18:30:32 +00:00
foreach ( var button in controller . Definition . 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 )
{
2016-12-14 20:12:16 +00:00
_buttons [ button ] = controller . IsPressed ( button ) ;
2014-03-29 21:12:04 +00:00
}
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 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
}
2019-11-15 00:18:46 +00:00
var controlBindings = controlString . Split ( ',' ) ;
foreach ( var control in controlBindings )
2013-12-30 01:58:44 +00:00
{
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
}
2019-11-15 00:18:46 +00:00
public List < string > PressedButtons = > _buttons
. Where ( kvp = > kvp . Value )
. Select ( kvp = > kvp . Key )
. ToList ( ) ;
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 ;
2019-11-15 00:18:46 +00:00
Definition = definition ;
2015-02-22 18:02:56 +00:00
_emulator = emulator ;
}
private readonly IEmulator _emulator ;
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 , int > _buttonStarts = new WorkingDictionary < string , int > ( ) ;
private bool _autofire = true ;
2011-08-09 22:13:57 +00:00
2019-11-15 00:18:46 +00:00
public bool Autofire
{
get = > false ;
set = > _autofire = value ;
}
2011-08-09 22:13:57 +00:00
public int On { get ; set ; }
public int Off { get ; set ; }
2019-11-15 00:18:46 +00:00
public ControllerDefinition Definition { get ; }
2016-12-14 20:12:16 +00:00
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 ( ) ;
}
2019-12-31 22:24:46 +00:00
/// <exception cref="NotImplementedException">always</exception>
2017-04-14 19:59:01 +00:00
public float GetFloat ( string name )
{
throw new NotImplementedException ( ) ;
}
2011-06-19 23:39:25 +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
{
2017-04-14 19:59:01 +00:00
foreach ( var boundBtn in kvp . Value )
2011-08-10 00:34:33 +00:00
{
2017-04-14 19:59:01 +00:00
if ( _buttons [ kvp . Key ] = = false & & controller . IsPressed ( boundBtn ) )
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 ;
2019-11-15 00:18:46 +00:00
foreach ( var button in kvp . Value )
2011-07-10 02:14:58 +00:00
{
2019-11-15 00:18:46 +00:00
if ( controller . IsPressed ( 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-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
{
2019-11-15 00:18:46 +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
2019-11-15 00:18:46 +00:00
public List < string > PressedButtons = > _buttons
. Where ( kvp = > kvp . Value )
. Select ( kvp = > kvp . Key )
. ToList ( ) ;
2011-06-19 23:39:25 +00:00
}
2011-01-14 03:38:26 +00:00
}