2009-05-25 09:01:26 +00:00
/*
* OpenClonk , http : //www.openclonk.org
*
2013-12-17 20:01:09 +00:00
* Copyright ( c ) 2005 - 2009 , RedWolf Design GmbH , http : //www.clonk.de/
2016-04-03 18:18:29 +00:00
* Copyright ( c ) 2009 - 2016 , The OpenClonk Team and contributors
2009-05-25 09:01:26 +00:00
*
2013-12-17 20:01:09 +00:00
* Distributed under the terms of the ISC license ; see accompanying file
* " COPYING " for details .
2009-05-25 09:01:26 +00:00
*
2013-12-17 20:01:09 +00:00
* " Clonk " is a registered trademark of Matthes Bender , used with permission .
* See accompanying file " TRADEMARK " for details .
2009-05-25 09:01:26 +00:00
*
2013-12-17 20:01:09 +00:00
* To redistribute this file separately , substitute the full license texts
* for the above references .
2009-05-25 09:01:26 +00:00
*/
// Input to player control mapping
# ifndef INC_C4PlayerControl
# define INC_C4PlayerControl
2016-04-03 18:07:56 +00:00
# include "gui/C4KeyboardInput.h"
# include "c4group/C4LangStringTable.h"
# include "object/C4Id.h"
# include "platform/C4TimeMilliseconds.h"
2009-12-17 13:06:24 +00:00
# include <list>
2009-05-25 09:01:26 +00:00
2010-09-29 01:44:05 +00:00
const float C4GFX_ZoomStep = 1.1040895f ;
2009-05-25 09:01:26 +00:00
// one control definition, e.g. "Left", "Throw", etc.
class C4PlayerControlDef
2010-03-28 17:58:21 +00:00
{
2011-11-20 20:49:38 +00:00
public :
enum CoordinateSpace // coordinate space for mouse position
{
COS_Game = 0 , // game (landscape) coordinates
COS_Viewport = 1 // viewport (GUI) coordinates
} ;
2015-02-04 18:26:45 +00:00
enum Actions //action to be performed when control is triggered
{
CDA_None = 0 , // do nothing
CDA_Script , // default: Script callback
CDA_Menu , // open player menu (async)
CDA_MenuOK , CDA_MenuCancel , CDA_MenuLeft , CDA_MenuUp , CDA_MenuRight , CDA_MenuDown , // player menu controls (async)
CDA_ObjectMenuTextComplete , // object menu fast-foward through text animation (async)
CDA_ObjectMenuOK , CDA_ObjectMenuOKAll , CDA_ObjectMenuSelect , CDA_ObjectMenuCancel , CDA_ObjectMenuLeft , CDA_ObjectMenuUp , CDA_ObjectMenuRight , CDA_ObjectMenuDown , // object menu controls (sync)
CDA_ZoomIn , CDA_ZoomOut // player viewport control (async)
} ;
2011-11-20 20:49:38 +00:00
2010-03-28 17:58:21 +00:00
private :
StdCopyStrBuf sIdentifier ; // name as seen in script and config
StdCopyStrBuf sGUIName ; // name as displayed to player
StdCopyStrBuf sGUIDesc ; // key description displayed to player in config dialog
bool fGlobal ; // if true, control can be bound to the global player only
bool fIsHoldKey ; // if true, the control can be in down and up state
2015-02-04 18:26:45 +00:00
bool fDefaultDisabled ; // if true, the control is disabled by default and needs to be enabled by script
bool fSendCursorPos ; // if true, x/y parameters will be set by current GUI mouse cursor pos (or GetCursor()-GUI coordinate pos for gamepad)
2010-03-28 17:58:21 +00:00
int32_t iRepeatDelay ; // if >0, the key will generate successive events when held down
int32_t iInitialRepeatDelay ; // delay after which KeyRepeat will be enabled
C4ID idControlExtraData ; // extra data to be passed to script function
2011-11-20 20:49:38 +00:00
CoordinateSpace eCoordSpace ; // coordinate space to be used for mouse coordinates when control is triggered by mouse
2010-03-28 17:58:21 +00:00
Actions eAction ;
public :
2015-02-04 18:26:45 +00:00
C4PlayerControlDef ( ) :
fGlobal ( false ) , fIsHoldKey ( false ) , fDefaultDisabled ( false ) , fSendCursorPos ( false ) ,
idControlExtraData ( C4ID : : None ) , eCoordSpace ( COS_Game ) , eAction ( CDA_Script )
{ }
2010-03-28 17:58:21 +00:00
~ C4PlayerControlDef ( ) { } ;
void CompileFunc ( StdCompiler * pComp ) ;
const char * GetIdentifier ( ) const { return sIdentifier . getData ( ) ; }
const char * GetGUIName ( ) const { return sGUIName . getData ( ) ; }
const char * GetGUIDesc ( ) const { return sGUIDesc . getData ( ) ; }
Actions GetAction ( ) const { return eAction ; }
bool IsHoldKey ( ) const { return fIsHoldKey ; }
C4ID GetExtraData ( ) const { return idControlExtraData ; }
bool IsGlobal ( ) const { return fGlobal ; }
int32_t GetRepeatDelay ( ) const { return iRepeatDelay ; }
int32_t GetInitialRepeatDelay ( ) const { return iInitialRepeatDelay ; }
bool IsDefaultDisabled ( ) const { return fDefaultDisabled ; }
2011-11-20 20:49:38 +00:00
CoordinateSpace GetCoordinateSpace ( ) const { return eCoordSpace ; }
2010-04-10 20:44:00 +00:00
bool IsSendCursorPos ( ) const { return fSendCursorPos ; }
2010-03-28 17:58:21 +00:00
bool operator = = ( const C4PlayerControlDef & cmp ) const ;
bool Execute ( bool fUp , const C4KeyEventData & rKeyExtraData ) ; // key was triggered - execute and return if handled
2014-08-10 18:58:26 +00:00
bool IsSyncObjectMenuControl ( ) const { return eAction > = CDA_ObjectMenuOK & & eAction < = CDA_ObjectMenuDown ; }
bool IsAsync ( ) const { return eAction ! = CDA_None & & eAction ! = CDA_Script & & ! IsSyncObjectMenuControl ( ) ; } // true if to be executed directly when triggered
bool IsSync ( ) const { return eAction = = CDA_Script | | IsSyncObjectMenuControl ( ) ; } // true if to be executed via control queue
2010-03-28 17:58:21 +00:00
bool IsValid ( ) const { return eAction ! = CDA_None ; }
} ;
2009-05-25 09:01:26 +00:00
// CON_* constants are indices into the C4PlayerControlDefs list
enum { CON_None = - 1 } ; // No/undefined control
// list of all known player control definitions
class C4PlayerControlDefs
2010-03-28 17:58:21 +00:00
{
private :
typedef std : : vector < C4PlayerControlDef > DefVecImpl ;
DefVecImpl Defs ;
2011-07-16 09:58:38 +00:00
bool clear_previous ; // if set is merged, all previous control defs are cleared - use
2010-03-28 17:58:21 +00:00
public :
struct CInternalCons
2009-05-25 09:01:26 +00:00
{
2010-05-07 13:57:56 +00:00
int32_t CON_ObjectMenuSelect , CON_ObjectMenuOKAll , CON_ObjectMenuOK , CON_ObjectMenuCancel , CON_CursorPos ;
CInternalCons ( ) : CON_ObjectMenuSelect ( CON_None ) , CON_ObjectMenuOKAll ( CON_None ) , CON_ObjectMenuOK ( CON_None ) , CON_ObjectMenuCancel ( CON_None ) , CON_CursorPos ( CON_None ) { }
2010-03-28 17:58:21 +00:00
} InternalCons ;
2009-05-26 06:10:38 +00:00
2010-03-28 17:58:21 +00:00
void UpdateInternalCons ( ) ;
2009-05-25 09:01:26 +00:00
2010-03-28 17:58:21 +00:00
public :
2011-07-16 09:58:38 +00:00
C4PlayerControlDefs ( ) : clear_previous ( false ) { }
2010-03-28 17:58:21 +00:00
~ C4PlayerControlDefs ( ) { }
void Clear ( ) ;
2009-06-09 23:29:16 +00:00
2010-03-28 17:58:21 +00:00
void CompileFunc ( StdCompiler * pComp ) ;
void MergeFrom ( const C4PlayerControlDefs & Src ) ; // copy all defs from source file; overwrite defs of same name if found
2009-05-26 06:10:38 +00:00
2010-03-28 17:58:21 +00:00
void FinalInit ( ) ; // after all defs have been loaded: register script constants
const C4PlayerControlDef * GetControlByIndex ( int32_t idx ) const ;
int32_t GetControlIndexByIdentifier ( const char * szIdentifier ) const ; // return CON_None for not found
2010-04-20 16:20:24 +00:00
size_t GetCount ( ) const { return Defs . size ( ) ; }
2010-03-28 17:58:21 +00:00
2011-07-16 09:58:38 +00:00
bool operator = = ( const C4PlayerControlDefs & cmp ) const { return Defs = = cmp . Defs & & clear_previous = = cmp . clear_previous ; }
2010-03-28 17:58:21 +00:00
} ;
2009-05-25 09:01:26 +00:00
2009-05-28 00:14:54 +00:00
struct C4PlayerControlRecentKey
2010-03-28 17:58:21 +00:00
{
2009-10-16 14:23:17 +00:00
C4KeyCodeEx pressed_key , matched_key ;
2013-12-04 12:35:07 +00:00
C4TimeMilliseconds tTime ;
C4PlayerControlRecentKey ( const C4KeyCodeEx & pressed_key , const C4KeyCodeEx & matched_key , C4TimeMilliseconds tTime ) : pressed_key ( pressed_key ) , matched_key ( matched_key ) , tTime ( tTime ) { }
2009-10-16 14:23:17 +00:00
bool operator = = ( const C4KeyCodeEx & cmp ) { return pressed_key = = cmp ; } // comparison op for finding items in lists: Search for the pressed key only
2010-03-28 17:58:21 +00:00
} ;
2009-05-28 00:14:54 +00:00
typedef std : : list < C4PlayerControlRecentKey > C4PlayerControlRecentKeyList ;
typedef std : : vector < C4KeyCodeEx > C4KeyCodeExVec ;
2009-05-25 09:01:26 +00:00
// a key/mouse/gamepad assignment to a PlayerControlDef
class C4PlayerControlAssignment
2010-03-28 17:58:21 +00:00
{
2015-02-04 18:26:45 +00:00
public :
// action to be performed on the control upon this key
enum TriggerModes
{
CTM_Default = 0 , // standard behaviour: The control will be triggered
CTM_Hold = 1 < < 0 , // the control will be put into "down"-mode
CTM_Release = 1 < < 1 , // the hold mode of the control will be released
CTM_AlwaysUnhandled = 1 < < 2 , // the key will not block handling of other keys even if it got handled
CTM_HandleDownStatesOnly = 1 < < 3 , // used when an already handled release key is processed to reset down states of overridden keys only
CTM_ClearRecentKeys = 1 < < 4 // if this assignment is triggered, RecentKeys are reset so no more combos can be generated
} ;
2010-03-28 17:58:21 +00:00
private :
// KeyCombo list:
// if size()>1, the control is triggered only if this combo is fulfilled
// used for simultanuous keypresses or sequences
struct KeyComboItem
2009-05-25 09:01:26 +00:00
{
2010-03-28 17:58:21 +00:00
C4KeyCodeEx Key ;
StdCopyStrBuf sKeyName ;
void CompileFunc ( StdCompiler * pComp ) ;
2011-03-30 20:11:47 +00:00
void UpdateKeyName ( ) ;
2013-02-09 00:03:06 +00:00
bool operator = = ( const KeyComboItem & cmp ) const { return Key = = cmp . Key ; }
2010-03-28 17:58:21 +00:00
} ;
typedef std : : vector < KeyComboItem > KeyComboVec ;
KeyComboVec KeyCombo ;
bool fComboIsSequence ; // if true, the keys must be pressed in sequence. Otherwise, they must be pressed simultanuously
2009-05-25 09:01:26 +00:00
2010-03-28 17:58:21 +00:00
// trigger key: key/mouse/gamepad event triggering this assignment. For combinations, the last key of the combo.
C4KeyCodeEx TriggerKey ;
2009-05-25 09:01:26 +00:00
2010-03-28 17:58:21 +00:00
StdCopyStrBuf sControlName ; // name of the control to be executed on this key
2012-10-08 20:29:15 +00:00
StdCopyStrBuf sGUIName ; // name as displayed to player. If empty, name stored in control def should be used.
StdCopyStrBuf sGUIDesc ; // key description displayed to player in config dialog. If empty, name stored in control def should be used.
2012-10-09 20:24:48 +00:00
bool fGUIDisabled ; // whether this key can't be reassigned through the GUI dialogue
2015-02-04 18:26:45 +00:00
bool fOverrideAssignments ; // override all other assignments to the same key?
bool is_inherited ; // set for assignments that were copied from a parent set without modification
bool fRefsResolved ; // set to true after sControlName and sKeyNames have been resolved to runtime values
2012-10-09 21:59:32 +00:00
int32_t iGUIGroup ; // in which this control is grouped in the gui
2010-03-28 17:58:21 +00:00
int32_t iControl ; // the control to be executed on this key, i.e. the resolved sControlName
int32_t iPriority ; // higher priority assignments get handled first
int32_t iTriggerMode ;
2009-05-26 06:10:38 +00:00
2015-02-04 18:26:45 +00:00
const C4PlayerControlAssignment * inherited_assignment ; // valid for assignments that were copied from a parent: source assignment
2009-05-25 09:01:26 +00:00
2010-03-28 17:58:21 +00:00
public :
2015-02-04 18:26:45 +00:00
C4PlayerControlAssignment ( ) :
TriggerKey ( ) , fOverrideAssignments ( false ) , is_inherited ( false ) , fRefsResolved ( false ) ,
iGUIGroup ( 0 ) , iControl ( CON_None ) , iPriority ( 0 ) , iTriggerMode ( CTM_Default ) ,
inherited_assignment ( NULL )
{ }
2010-03-28 17:58:21 +00:00
~ C4PlayerControlAssignment ( ) { }
2009-05-25 09:01:26 +00:00
2010-03-28 17:58:21 +00:00
void CompileFunc ( StdCompiler * pComp ) ;
2011-03-30 20:11:47 +00:00
void CopyKeyFrom ( const C4PlayerControlAssignment & src_assignment ) ;
2010-03-28 17:58:21 +00:00
bool ResolveRefs ( class C4PlayerControlAssignmentSet * pParentSet , C4PlayerControlDefs * pControlDefs ) ; // resolve references between assignments
bool IsComboMatched ( const C4PlayerControlRecentKeyList & DownKeys , const C4PlayerControlRecentKeyList & RecentKeys ) const ; // check if combo is currently fulfilled (assuming TriggerKey is already matched)
2011-03-30 20:11:47 +00:00
void SetInherited ( bool to_val ) { is_inherited = to_val ; }
void SetInheritedAssignment ( const C4PlayerControlAssignment * to_val ) { inherited_assignment = to_val ; }
void ResetKeyToInherited ( ) ;
2011-03-31 14:26:59 +00:00
bool IsKeyChanged ( ) const ;
2011-03-30 20:11:47 +00:00
void SetControlName ( const char * control_name ) { sControlName . Copy ( control_name ) ; }
void SetKey ( const C4KeyCodeEx & key ) ;
2010-03-28 17:58:21 +00:00
bool operator = = ( const C4PlayerControlAssignment & cmp ) const ; // doesn't compare resolved TriggerKey/iControl
bool operator < ( const C4PlayerControlAssignment & cmp ) const { return iPriority > cmp . iPriority ; } // assignments are processed in DESCENDING priority!
const char * GetControlName ( ) const { return sControlName . getData ( ) ; }
int32_t GetControl ( ) const { return iControl ; }
2012-10-08 20:29:15 +00:00
const char * GetGUIName ( const C4PlayerControlDefs & defs ) const ;
const char * GetGUIDesc ( const C4PlayerControlDefs & defs ) const ;
2012-10-09 20:24:48 +00:00
bool IsGUIDisabled ( ) const ;
2012-10-09 21:59:32 +00:00
int32_t GetGUIGroup ( ) const ;
2010-03-28 17:58:21 +00:00
bool IsRefsResolved ( ) const { return fRefsResolved ; }
2012-10-08 18:45:04 +00:00
void ResetRefsResolved ( ) { fRefsResolved = false ; } // Mark references to other assignments as not resolved
2010-03-28 17:58:21 +00:00
bool IsAlwaysUnhandled ( ) const { return ! ! ( iTriggerMode & CTM_AlwaysUnhandled ) ; }
int32_t GetTriggerMode ( ) const { return iTriggerMode ; }
const C4KeyCodeEx & GetTriggerKey ( ) const { return TriggerKey ; }
bool HasCombo ( ) const { return KeyCombo . size ( ) > 1 ; }
bool IsOverrideAssignments ( ) const { return fOverrideAssignments ; }
2011-03-30 20:11:47 +00:00
bool IsInherited ( ) const { return is_inherited ; }
const C4PlayerControlAssignment * GetInheritedAssignment ( ) const { return inherited_assignment ; }
2012-04-17 15:06:16 +00:00
StdStrBuf GetKeysAsString ( bool human_readable , bool short_name ) const ;
2010-03-28 17:58:21 +00:00
} ;
2009-05-26 06:10:38 +00:00
typedef std : : vector < C4PlayerControlAssignment > C4PlayerControlAssignmentVec ;
2009-05-28 00:14:54 +00:00
typedef std : : vector < const C4PlayerControlAssignment * > C4PlayerControlAssignmentPVec ;
2009-05-26 06:10:38 +00:00
2009-05-25 09:01:26 +00:00
// a set of key/mouse/gamepad assignments to all controls
class C4PlayerControlAssignmentSet
2010-03-28 17:58:21 +00:00
{
private :
2011-03-30 20:11:47 +00:00
StdCopyStrBuf sName , sGUIName , sParentSetName ;
const C4PlayerControlAssignmentSet * parent_set ;
2012-10-09 21:59:32 +00:00
C4PlayerControlAssignmentVec Assignments ; // ordered by priority
2011-03-30 20:11:47 +00:00
bool has_keyboard ;
2010-03-28 17:58:21 +00:00
bool has_mouse ;
bool has_gamepad ;
public :
2011-03-30 20:11:47 +00:00
C4PlayerControlAssignmentSet ( ) : parent_set ( NULL ) , has_keyboard ( true ) , has_mouse ( true ) , has_gamepad ( false ) { }
2010-03-28 17:58:21 +00:00
~ C4PlayerControlAssignmentSet ( ) { }
2011-03-30 20:11:47 +00:00
void InitEmptyFromTemplate ( const C4PlayerControlAssignmentSet & template_set ) ; // copy all fields except assignments
2010-03-28 17:58:21 +00:00
void CompileFunc ( StdCompiler * pComp ) ;
bool ResolveRefs ( C4PlayerControlDefs * pControlDefs ) ; // resolve references between assignments
2011-03-31 14:26:59 +00:00
void SortAssignments ( ) ;
2010-03-28 17:58:21 +00:00
2011-03-30 20:11:47 +00:00
enum MergeMode { MM_Normal , MM_LowPrio , MM_Inherit , MM_ConfigOverload } ;
void MergeFrom ( const C4PlayerControlAssignmentSet & Src , MergeMode merge_mode ) ; // take over all assignments defined in Src
C4PlayerControlAssignment * CreateAssignmentForControl ( const char * control_name ) ;
void RemoveAssignmentByControlName ( const char * control_name ) ;
2010-03-28 17:58:21 +00:00
const char * GetName ( ) const { return sName . getData ( ) ; }
2011-03-30 20:11:47 +00:00
const char * GetGUIName ( ) const { return sGUIName . getData ( ) ; }
2010-03-28 17:58:21 +00:00
bool IsWildcardName ( ) const { return IsWildcardString ( sName . getData ( ) ) ; }
2012-10-09 21:59:32 +00:00
C4PlayerControlAssignment * GetAssignmentByIndex ( int32_t index ) ; // assignments are ordered by priority
2010-03-28 17:58:21 +00:00
C4PlayerControlAssignment * GetAssignmentByControlName ( const char * szControlName ) ;
2011-03-30 20:11:47 +00:00
C4PlayerControlAssignment * GetAssignmentByControl ( int32_t control ) ;
2010-03-28 17:58:21 +00:00
void GetAssignmentsByKey ( const C4PlayerControlDefs & rDefs , const C4KeyCodeEx & key , bool fHoldKeysOnly , C4PlayerControlAssignmentPVec * pOutVec , const C4PlayerControlRecentKeyList & DownKeys , const C4PlayerControlRecentKeyList & RecentKeys ) const ; // match only by TriggerKey (last key of Combo) if fHoldKeysOnly
void GetTriggerKeys ( const C4PlayerControlDefs & rDefs , C4KeyCodeExVec * pRegularKeys , C4KeyCodeExVec * pHoldKeys ) const ; // put all trigger keys of keyset into output vectors
bool operator = = ( const C4PlayerControlAssignmentSet & cmp ) const ;
C4Facet GetPicture ( ) const ; // get image to be drawn to represent this control set
// todo
bool HasKeyboard ( ) const { return has_keyboard ; }
bool HasMouse ( ) const { return has_mouse ; }
bool HasGamepad ( ) const { return has_gamepad ; }
int32_t GetLayoutOrder ( ) const { return 0 ; } // returns position on keyboard (increasing from left to right) for viewport sorting
bool IsMouseControlAssigned ( int32_t mouseevent ) const ;
} ;
2009-05-25 09:01:26 +00:00
// list of C4PlayerControlAssignmentSet
class C4PlayerControlAssignmentSets
2010-03-28 17:58:21 +00:00
{
private :
typedef std : : list < C4PlayerControlAssignmentSet > AssignmentSetList ;
AssignmentSetList Sets ;
2011-07-16 09:58:38 +00:00
bool clear_previous ;
2009-05-25 09:01:26 +00:00
2010-03-28 17:58:21 +00:00
public :
2011-07-16 09:58:38 +00:00
C4PlayerControlAssignmentSets ( ) : clear_previous ( false ) { }
2010-03-28 17:58:21 +00:00
~ C4PlayerControlAssignmentSets ( ) { }
void Clear ( ) ;
2009-05-25 09:01:26 +00:00
2010-03-28 17:58:21 +00:00
void CompileFunc ( StdCompiler * pComp ) ;
2011-03-30 20:11:47 +00:00
bool operator = = ( const C4PlayerControlAssignmentSets & cmp ) const ;
2010-03-28 17:58:21 +00:00
bool ResolveRefs ( C4PlayerControlDefs * pControlDefs ) ; // resolve references between assignments
2011-03-31 14:26:59 +00:00
void SortAssignments ( ) ;
2009-05-25 09:01:26 +00:00
2011-03-30 20:11:47 +00:00
void MergeFrom ( const C4PlayerControlAssignmentSets & Src , C4PlayerControlAssignmentSet : : MergeMode merge_mode ) ; // take over all assignments in known sets and new sets defined in Src
C4PlayerControlAssignmentSet * CreateEmptySetByTemplate ( const C4PlayerControlAssignmentSet & template_set ) ;
void RemoveSetByName ( const char * set_name ) ;
2009-05-26 06:10:38 +00:00
2010-03-28 17:58:21 +00:00
C4PlayerControlAssignmentSet * GetSetByName ( const char * szName ) ;
C4PlayerControlAssignmentSet * GetDefaultSet ( ) ;
int32_t GetSetIndex ( const C4PlayerControlAssignmentSet * set ) const ;
C4PlayerControlAssignmentSet * GetSetByIndex ( int32_t index ) ;
2010-04-20 16:20:24 +00:00
size_t GetSetCount ( ) const { return Sets . size ( ) ; }
2010-03-28 17:58:21 +00:00
} ;
2009-05-25 09:01:26 +00:00
// contents of one PlayerControls.txt file
class C4PlayerControlFile
2010-03-28 17:58:21 +00:00
{
private :
C4PlayerControlDefs ControlDefs ;
C4PlayerControlAssignmentSets AssignmentSets ;
public :
void Clear ( ) ;
void CompileFunc ( StdCompiler * pComp ) ;
bool Load ( C4Group & hGroup , const char * szFilename , C4LangStringTable * pLang ) ;
bool Save ( C4Group & hGroup , const char * szFilename ) ;
const C4PlayerControlDefs & GetControlDefs ( ) const { return ControlDefs ; }
const C4PlayerControlAssignmentSets & GetAssignmentSets ( ) const { return AssignmentSets ; }
} ;
2009-05-25 09:01:26 +00:00
// runtime information about a player's control
class C4PlayerControl
2010-03-28 17:58:21 +00:00
{
public :
enum { MaxRecentKeyLookback = 3000 , MaxSequenceKeyDelay = 800 } ; // milliseconds: Time to press key combos
2016-02-15 15:20:37 +00:00
enum ControlState {
CONS_Down = 0 ,
CONS_Up ,
CONS_Moved ,
} ;
2010-03-28 17:58:21 +00:00
private :
C4PlayerControlDefs & ControlDefs ; // shortcut
// owner
int32_t iPlr ;
// async values
C4PlayerControlAssignmentSet * pControlSet ; // the control set used by this player - may be NULL if the player cannot be controlled!
typedef std : : list < C4KeyBinding * > KeyBindingList ;
KeyBindingList KeyBindings ; // keys registered into Game.KeyboardInput
C4PlayerControlRecentKeyList RecentKeys ; // keys pressed recently; for combinations
C4PlayerControlRecentKeyList DownKeys ; // keys currently held down
2010-05-07 13:57:56 +00:00
bool IsCursorPosRequested ; // set to true when a SendCursorPos-control had been issued
2010-03-28 17:58:21 +00:00
public :
// sync values
struct CSync
2009-05-25 09:01:26 +00:00
{
2010-03-28 17:58:21 +00:00
struct ControlDownState
{
Make GetPlayerControlState() query the current controller state
To keep compatibility with scripts which expect only binary buttons,
this adds a third parameter to the function which enables the new
functionality.
Bonus /script to test the controller stick x axis:
Schedule(GetCursor(), "Message(\"%d / %d\", GetPlayerControlState(0, CON_Left, true), GetPlayerControlState(0, CON_Right, true))", 10, 100000000)
Note that the values will be inconsistent if multiple analog sticks are
bound to the same control, as values from one stick will overwrite those
from the other one. This can happen even if you move only one stick.
2016-02-15 23:21:19 +00:00
C4KeyEventData DownState , MovedState ; // control is down if DownState.iStrength>0
int32_t iDownFrame , iMovedFrame ; // frame when control was pressed
2010-03-28 17:58:21 +00:00
bool fDownByUser ; // if true, the key is actually pressed. Otherwise, it's triggered as down by another key
ControlDownState ( const C4KeyEventData & rDownState , int32_t iDownFrame , bool fDownByUser )
2009-05-26 06:10:38 +00:00
: DownState ( rDownState ) , iDownFrame ( iDownFrame ) , fDownByUser ( fDownByUser ) { }
2010-03-28 17:58:21 +00:00
bool IsDown ( ) const { return DownState . iStrength > 0 ; }
ControlDownState ( ) : DownState ( ) , iDownFrame ( 0 ) , fDownByUser ( false ) { }
2009-05-25 09:01:26 +00:00
void CompileFunc ( StdCompiler * pComp ) ;
2010-03-28 17:58:21 +00:00
bool operator = = ( const ControlDownState & cmp ) const ;
} ;
typedef std : : vector < ControlDownState > DownStateVec ;
DownStateVec ControlDownStates ; // indexed by C4PlayerControlID: Down-state of a control. 0=up, 100=down; values inbetween e.g. for gamepad sticks
typedef std : : vector < int32_t > DisableStateVec ;
DisableStateVec ControlDisableStates ; // indexed by C4PlayerControlID: Disable-states of controls. >0 is disabled.
const ControlDownState * GetControlDownState ( int32_t iControl ) const ;
int32_t GetControlDisabled ( int32_t iControl ) const ;
bool IsControlDisabled ( int32_t iControl ) const { return GetControlDisabled ( iControl ) > 0 ; }
void SetControlDownState ( int32_t iControl , const C4KeyEventData & rDownState , int32_t iDownFrame , bool fDownByUser ) ;
Make GetPlayerControlState() query the current controller state
To keep compatibility with scripts which expect only binary buttons,
this adds a third parameter to the function which enables the new
functionality.
Bonus /script to test the controller stick x axis:
Schedule(GetCursor(), "Message(\"%d / %d\", GetPlayerControlState(0, CON_Left, true), GetPlayerControlState(0, CON_Right, true))", 10, 100000000)
Note that the values will be inconsistent if multiple analog sticks are
bound to the same control, as values from one stick will overwrite those
from the other one. This can happen even if you move only one stick.
2016-02-15 23:21:19 +00:00
void SetControlMovedState ( int32_t iControl , const C4KeyEventData & rMovedState , int32_t iMovedFrame ) ;
2010-07-30 20:30:54 +00:00
void ResetControlDownState ( int32_t iControl ) ;
2010-03-28 17:58:21 +00:00
bool SetControlDisabled ( int32_t iControl , int32_t iVal ) ;
void InitDefaults ( const C4PlayerControlDefs & ControlDefs ) ;
2009-05-25 09:01:26 +00:00
void Clear ( ) ;
2010-03-28 17:58:21 +00:00
void CompileFunc ( StdCompiler * pComp ) ;
bool operator = = ( const CSync & cmp ) const ;
} ;
2009-05-25 09:01:26 +00:00
2010-03-28 17:58:21 +00:00
private :
CSync Sync ;
2010-03-26 13:48:28 +00:00
2010-03-28 17:58:21 +00:00
// callbacks from Game.KeyboardInput
2016-02-15 15:20:37 +00:00
bool ProcessKeyEvent ( const C4KeyCodeEx & pressed_key , const C4KeyCodeEx & matched_key , ControlState state , const C4KeyEventData & rKeyExtraData , bool reset_down_states_only = false , bool * clear_recent_keys = NULL ) ;
2010-03-28 17:58:21 +00:00
bool ProcessKeyDown ( const C4KeyCodeEx & pressed_key , const C4KeyCodeEx & matched_key ) ;
2011-11-20 20:49:38 +00:00
bool ProcessKeyUp ( const C4KeyCodeEx & pressed_key , const C4KeyCodeEx & matched_key ) ;
2016-02-15 15:20:37 +00:00
bool ProcessKeyMoved ( const C4KeyCodeEx & pressed_key , const C4KeyCodeEx & matched_key ) ;
2009-05-26 06:10:38 +00:00
2010-03-28 17:58:21 +00:00
// execute single control. return if handled.
2016-02-15 15:20:37 +00:00
bool ExecuteControl ( int32_t iControl , ControlState state , const C4KeyEventData & rKeyExtraData , int32_t iTriggerMode , bool fRepeated , bool fHandleDownStateOnly ) ;
bool ExecuteControlAction ( int32_t iControl , C4PlayerControlDef : : Actions eAction , C4ID idControlExtraData , ControlState state , const C4KeyEventData & rKeyExtraData , bool fRepeated ) ;
bool ExecuteControlScript ( int32_t iControl , C4ID idControlExtraData , ControlState state , const C4KeyEventData & rKeyExtraData , bool fRepeated ) ;
2009-05-26 06:10:38 +00:00
2010-03-28 17:58:21 +00:00
// init
void AddKeyBinding ( const C4KeyCodeEx & key , bool fHoldKey , int32_t idx ) ;
2009-05-26 06:10:38 +00:00
2010-04-10 20:44:00 +00:00
// helper function: get current cursor position of controlling player in GUI coordinates
// used e.g. to open menus at cursor pos
2011-11-20 20:49:38 +00:00
bool GetCurrentPlayerCursorPos ( int32_t * x_out , int32_t * y_out , int32_t * game_x_out , int32_t * game_y_out ) ;
2010-04-10 20:44:00 +00:00
2010-03-28 17:58:21 +00:00
public :
C4PlayerControl ( ) ;
~ C4PlayerControl ( ) { Clear ( ) ; }
void Clear ( ) ;
2009-05-28 00:14:54 +00:00
2010-03-28 17:58:21 +00:00
// first-time init call after player join
// not called again after control set change/savegame resume
// does DefaultDisabled controls
void Init ( ) ;
2009-10-17 15:53:26 +00:00
2010-03-28 17:58:21 +00:00
void CompileFunc ( StdCompiler * pComp ) ;
2009-12-27 18:11:14 +00:00
2010-03-28 17:58:21 +00:00
void RegisterKeyset ( int32_t iPlr , C4PlayerControlAssignmentSet * pKeyset ) ; // register all keys into Game.KeyboardInput creating KeyBindings
2009-12-27 18:11:14 +00:00
2010-03-28 17:58:21 +00:00
bool IsGlobal ( ) const { return iPlr = = - 1 ; }
const CSync : : ControlDownState * GetControlDownState ( int32_t iControl ) const
{ return Sync . GetControlDownState ( iControl ) ; }
2010-03-26 13:48:28 +00:00
2010-03-28 17:58:21 +00:00
// callback from control queue
void ExecuteControlPacket ( const class C4ControlPlayerControl * pCtrl ) ;
// sync execution: Do keyrepeat, etc.
void Execute ( ) ;
// mouse input
bool DoMouseInput ( uint8_t mouse_id , int32_t mouseevent , float game_x , float game_y , float gui_x , float gui_y , bool is_ctrl_down , bool is_shift_down , bool is_alt_down , int wheel_dir ) ;
// control enable/disable
bool SetControlDisabled ( int ctrl , bool is_disabled ) { return Sync . SetControlDisabled ( ctrl , is_disabled ) ; }
bool IsControlDisabled ( int ctrl ) const { return Sync . IsControlDisabled ( ctrl ) ; }
2010-05-07 13:57:56 +00:00
// callback from C4GameControl when the next control packet is finalized
void PrepareInput ( ) ;
2010-03-28 17:58:21 +00:00
} ;
2009-05-25 09:01:26 +00:00
2010-01-25 04:00:59 +00:00
# endif // INC_C4PlayerControl