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-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
{
private ControllerDefinition type ;
2013-04-15 02:14:14 +00:00
private readonly WorkingDictionary < string , List < string > > bindings = new WorkingDictionary < string , List < string > > ( ) ;
private readonly WorkingDictionary < string , bool > buttons = new WorkingDictionary < string , bool > ( ) ;
2011-07-24 20:37:10 +00:00
2013-07-18 16:18:17 +00:00
private readonly WorkingDictionary < string , float > FloatButtons = new WorkingDictionary < string , float > ( ) ;
private readonly Dictionary < string , ControllerDefinition . FloatRange > FloatRanges = new WorkingDictionary < string , ControllerDefinition . FloatRange > ( ) ;
2013-10-27 17:47:54 +00:00
private readonly Dictionary < string , Config . AnalogBind > FloatBinds = new Dictionary < string , Config . AnalogBind > ( ) ;
2013-07-18 16:18:17 +00:00
2011-07-24 20:37:10 +00:00
public Controller ( ControllerDefinition definition )
{
type = definition ;
2013-07-18 16:18:17 +00:00
for ( int i = 0 ; i < type . FloatControls . Count ; i + + )
{
FloatButtons [ type . FloatControls [ i ] ] = type . FloatRanges [ i ] . Mid ;
FloatRanges [ type . FloatControls [ i ] ] = type . FloatRanges [ i ] ;
}
2011-07-24 20:37:10 +00:00
}
2011-08-09 22:13:57 +00:00
public ControllerDefinition Type { get { return type ; } }
2012-10-26 18:51:08 +00:00
/// <summary>don't do this</summary>
2013-04-15 02:14:14 +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 )
{
return buttons [ button ] ;
}
2013-07-18 16:18:17 +00:00
public float GetFloat ( string name ) { return FloatButtons [ name ] ; }
2011-08-09 22:13:57 +00:00
public void UpdateControls ( int frame ) { }
//look for bindings which are activated by the supplied physical button.
public List < string > SearchBindings ( string button )
{
2013-10-27 17:47:54 +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
}
2012-12-02 15:18:28 +00:00
//Searches bindings for the controller and returns true if this binding is mapped somewhere in this controller
public bool HasBinding ( string button )
{
2013-10-27 17:47:54 +00:00
return bindings . SelectMany ( kvp = > kvp . Value ) . Any ( bound_button = > bound_button = = 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 )
{
buttons . Clear ( ) ;
2013-10-28 02:11:24 +00:00
2011-08-09 22:13:57 +00:00
foreach ( var kvp in bindings )
{
buttons [ kvp . Key ] = false ;
foreach ( var bound_button in kvp . Value )
{
2013-07-18 16:18:17 +00:00
if ( controller [ bound_button ] )
2011-08-09 22:13:57 +00:00
buttons [ kvp . Key ] = true ;
}
}
2013-10-28 02:11:24 +00:00
2013-07-18 16:18:17 +00:00
foreach ( var kvp in FloatBinds )
{
2013-07-24 02:14:25 +00:00
float input = controller . GetFloat ( kvp . Value . Value ) ;
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 ;
if ( FloatRanges . TryGetValue ( outkey , out range ) )
{
// 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 )
input = 0.0f ;
else
{
absinput - = zeropoint ;
absinput * = 10000.0f ;
absinput / = ( 10000.0f - zeropoint ) ;
input = absinput * Math . Sign ( input ) ;
}
}
2013-07-24 02:14:25 +00:00
float output = ( input * multiplier + 10000.0f ) * ( range . Max - range . Min ) / 20000.0f + range . Min ;
if ( output < range . Min ) output = range . Min ;
if ( output > range . Max ) output = range . Max ;
FloatButtons [ outkey ] = output ;
2013-07-18 16:18:17 +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
//foreach (string button in type.BoolButtons)
if ( controller . Type ! = null )
foreach ( string 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 ) )
{
buttons [ button ] = true ;
}
2011-08-09 22:13:57 +00:00
}
}
public void BindButton ( string button , string control )
{
bindings [ button ] . Add ( control ) ;
}
public void BindMulti ( string button , string controlString )
{
if ( string . IsNullOrEmpty ( controlString ) )
return ;
string [ ] controlbindings = controlString . Split ( ',' ) ;
foreach ( string control in controlbindings )
bindings [ button ] . Add ( control . Trim ( ) ) ;
}
2013-10-27 17:47:54 +00:00
public void BindFloat ( string button , Config . AnalogBind bind )
2013-07-24 02:14:25 +00:00
{
FloatBinds [ button ] = bind ;
}
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>
/// <returns></returns>
public List < KeyValuePair < string , string > > MappingList ( )
{
2013-10-27 17:47:54 +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
{
2013-04-15 02:14:14 +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
{
2013-10-27 17:47:54 +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 > ( ) ;
2011-08-29 03:28:34 +00:00
public WorkingDictionary < string , int > buttonStarts = new WorkingDictionary < string , int > ( ) ;
2011-08-09 22:13:57 +00:00
private bool autofire = true ;
public bool Autofire { get { return false ; } set { autofire = value ; } }
public int On { get ; set ; }
public int Off { get ; set ; }
public AutofireController ( ControllerDefinition definition )
{
On = Global . Config . AutofireOn < 1 ? 0 : Global . Config . AutofireOn ;
Off = Global . Config . AutofireOff < 1 ? 0 : Global . Config . AutofireOff ;
type = definition ;
}
2011-07-24 20:37:10 +00:00
public ControllerDefinition Type { get { return type ; } }
public bool this [ string button ] { get { return IsPressed ( button ) ; } }
2011-08-08 23:35:13 +00:00
public bool IsPressed ( string button )
{
if ( autofire )
{
2013-10-28 02:11:24 +00:00
int a = ( Global . Emulator . Frame - buttonStarts [ button ] ) % ( On + Off ) ;
2011-08-09 22:13:57 +00:00
if ( a < On )
2013-10-28 02:11:24 +00:00
{
2011-08-08 23:35:13 +00:00
return buttons [ button ] ;
2013-10-28 02:11:24 +00:00
}
2011-08-08 23:35:13 +00:00
else
2013-10-28 02:11:24 +00:00
{
2011-08-08 23:35:13 +00:00
return false ;
2013-10-28 02:11:24 +00:00
}
2011-08-08 23:35:13 +00:00
}
else
2013-10-28 02:11:24 +00:00
{
2011-08-08 23:35:13 +00:00
return buttons [ button ] ;
2013-10-28 02:11:24 +00:00
}
2011-08-08 23:35:13 +00:00
}
2011-07-24 20:37:10 +00:00
public float GetFloat ( string name ) { throw new NotImplementedException ( ) ; }
public void UpdateControls ( int frame ) { }
2011-06-19 23:39:25 +00:00
2011-07-10 07:39:40 +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 )
{
2013-10-27 17:47:54 +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 )
{
2011-08-10 00:34:33 +00:00
foreach ( var kvp in bindings )
{
foreach ( var bound_button in kvp . Value )
{
2013-04-15 02:14:14 +00:00
if ( buttons [ kvp . Key ] = = false & & controller [ bound_button ] )
2013-10-20 18:02:43 +00:00
buttonStarts [ kvp . Key ] = Global . Emulator . Frame ;
2011-08-10 00:34:33 +00:00
}
}
2011-08-04 02:47:05 +00:00
buttons . Clear ( ) ;
2011-07-10 02:14:58 +00:00
foreach ( var kvp in bindings )
{
2011-07-24 20:37:10 +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
{
2011-07-24 20:37:10 +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 )
{
foreach ( string button in type . BoolButtons )
{
if ( controller . IsPressed ( button ) )
2011-08-04 02:47:05 +00:00
{
2011-07-24 20:37:10 +00:00
buttons [ button ] = true ;
2011-08-04 02:47:05 +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 )
{
bindings [ button ] . Add ( control ) ;
}
public void BindMulti ( string button , string controlString )
{
2013-10-28 02:11:24 +00:00
if ( ! String . IsNullOrEmpty ( controlString ) )
{
string [ ] controlbindings = controlString . Split ( ',' ) ;
foreach ( string control in controlbindings )
{
bindings [ button ] . Add ( control . Trim ( ) ) ;
}
}
2011-06-19 23:39:25 +00:00
}
2011-08-29 03:28:34 +00:00
public void IncrementStarts ( )
{
foreach ( var key in buttonStarts . Keys . ToArray ( ) ) buttonStarts [ key ] + + ;
}
2012-09-14 21:31:00 +00:00
public List < string > PressedButtons
{
get
{
2013-04-15 02:14:14 +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
}