1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2005-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 // Input to player control mapping
17 
18 #ifndef INC_C4PlayerControl
19 #define INC_C4PlayerControl
20 
21 #include "gui/C4KeyboardInput.h"
22 #include "c4group/C4LangStringTable.h"
23 #include "object/C4Id.h"
24 #include "platform/C4TimeMilliseconds.h"
25 
26 const float C4GFX_ZoomStep = 1.1040895f;
27 
28 // one control definition, e.g. "Left", "Throw", etc.
29 class C4PlayerControlDef
30 {
31 public:
32 	enum CoordinateSpace // coordinate space for mouse position
33 	{
34 		COS_Game = 0,     // game (landscape) coordinates
35 		COS_Viewport = 1  // viewport (GUI) coordinates
36 	};
37 	enum Actions //action to be performed when control is triggered
38 	{
39 		CDA_None = 0,          // do nothing
40 		CDA_Script,          // default: Script callback
41 		CDA_Menu,            // open player menu (async)
42 		CDA_MenuOK, CDA_MenuCancel, CDA_MenuLeft, CDA_MenuUp, CDA_MenuRight, CDA_MenuDown, // player menu controls (async)
43 		CDA_ObjectMenuTextComplete, // object menu fast-foward through text animation (async)
44 		CDA_ObjectMenuOK, CDA_ObjectMenuOKAll, CDA_ObjectMenuSelect, CDA_ObjectMenuCancel, CDA_ObjectMenuLeft, CDA_ObjectMenuUp, CDA_ObjectMenuRight, CDA_ObjectMenuDown, // object menu controls (sync)
45 		CDA_ZoomIn, CDA_ZoomOut // player viewport control (async)
46 	};
47 
48 private:
49 	StdCopyStrBuf sIdentifier; // name as seen in script and config
50 	StdCopyStrBuf sGUIName;    // name as displayed to player
51 	StdCopyStrBuf sGUIDesc;    // key description displayed to player in config dialog
52 	bool fGlobal{false};             // if true, control can be bound to the global player only
53 	bool fIsHoldKey{false};          // if true, the control can be in down and up state
54 	bool fDefaultDisabled{false};    // if true, the control is disabled by default and needs to be enabled by script
55 	bool fSendCursorPos{false};      // if true, x/y parameters will be set by current GUI mouse cursor pos (or GetCursor()-GUI coordinate pos for gamepad)
56 	int32_t iRepeatDelay;     // if >0, the key will generate successive events when held down
57 	int32_t iInitialRepeatDelay; // delay after which KeyRepeat will be enabled
58 	C4ID idControlExtraData;  // extra data to be passed to script function
59 	CoordinateSpace eCoordSpace{COS_Game}; // coordinate space to be used for mouse coordinates when control is triggered by mouse
60 	Actions eAction{CDA_Script};
61 
62 public:
C4PlayerControlDef()63 	C4PlayerControlDef() :
64 		idControlExtraData(C4ID::None)
65 	{}
66 	~C4PlayerControlDef() = default;
67 
68 	void CompileFunc(StdCompiler *pComp);
69 
GetIdentifier()70 	const char *GetIdentifier() const { return sIdentifier.getData(); }
GetGUIName()71 	const char *GetGUIName() const { return sGUIName.getData(); }
GetGUIDesc()72 	const char *GetGUIDesc() const { return sGUIDesc.getData(); }
GetAction()73 	Actions GetAction() const { return eAction; }
IsHoldKey()74 	bool IsHoldKey() const { return fIsHoldKey; }
GetExtraData()75 	C4ID GetExtraData() const { return idControlExtraData; }
IsGlobal()76 	bool IsGlobal() const { return fGlobal; }
GetRepeatDelay()77 	int32_t GetRepeatDelay() const { return iRepeatDelay; }
GetInitialRepeatDelay()78 	int32_t GetInitialRepeatDelay() const { return iInitialRepeatDelay; }
IsDefaultDisabled()79 	bool IsDefaultDisabled() const { return fDefaultDisabled; }
GetCoordinateSpace()80 	CoordinateSpace GetCoordinateSpace() const { return eCoordSpace; }
IsSendCursorPos()81 	bool IsSendCursorPos() const { return fSendCursorPos; }
82 
83 	bool operator ==(const C4PlayerControlDef &cmp) const;
84 
85 	bool Execute(bool fUp, const C4KeyEventData &rKeyExtraData); // key was triggered - execute and return if handled
IsSyncObjectMenuControl()86 	bool IsSyncObjectMenuControl() const { return eAction>=CDA_ObjectMenuOK && eAction<=CDA_ObjectMenuDown; }
IsAsync()87 	bool IsAsync() const { return eAction != CDA_None && eAction != CDA_Script && !IsSyncObjectMenuControl(); } // true if to be executed directly when triggered
IsSync()88 	bool IsSync() const { return eAction == CDA_Script || IsSyncObjectMenuControl(); } // true if to be executed via control queue
IsValid()89 	bool IsValid() const { return eAction != CDA_None; }
90 };
91 
92 // CON_* constants are indices into the C4PlayerControlDefs list
93 enum { CON_None = -1 }; // No/undefined control
94 
95 // list of all known player control definitions
96 class C4PlayerControlDefs
97 {
98 private:
99 	typedef std::vector<C4PlayerControlDef> DefVecImpl;
100 	DefVecImpl Defs;
101 	bool clear_previous{false}; // if set is merged, all previous control defs are cleared - use
102 
103 public:
104 	struct CInternalCons
105 	{
106 		int32_t CON_ObjectMenuSelect{CON_None}, CON_ObjectMenuOKAll{CON_None}, CON_ObjectMenuOK{CON_None}, CON_ObjectMenuCancel{CON_None}, CON_CursorPos{CON_None};
107 		CInternalCons() = default;
108 	} InternalCons;
109 
110 	void UpdateInternalCons();
111 
112 public:
113 	C4PlayerControlDefs() = default;
114 	~C4PlayerControlDefs() = default;
115 	void Clear();
116 
117 	void CompileFunc(StdCompiler *pComp);
118 	void MergeFrom(const C4PlayerControlDefs &Src); // copy all defs from source file; overwrite defs of same name if found
119 
120 	void FinalInit(); // after all defs have been loaded: register script constants
121 
122 	const C4PlayerControlDef *GetControlByIndex(int32_t idx) const;
123 	int32_t GetControlIndexByIdentifier(const char *szIdentifier) const; // return CON_None for not found
GetCount()124 	size_t GetCount() const { return Defs.size(); }
125 
126 	bool operator ==(const C4PlayerControlDefs &cmp) const { return Defs == cmp.Defs && clear_previous == cmp.clear_previous; }
127 };
128 
129 struct C4PlayerControlRecentKey
130 {
131 	C4KeyCodeEx pressed_key, matched_key;
132 	C4TimeMilliseconds tTime;
C4PlayerControlRecentKeyC4PlayerControlRecentKey133 	C4PlayerControlRecentKey(const C4KeyCodeEx &pressed_key, const C4KeyCodeEx &matched_key, C4TimeMilliseconds tTime) : pressed_key(pressed_key), matched_key(matched_key), tTime(tTime) {}
134 	bool operator ==(const C4KeyCodeEx &cmp) { return pressed_key==cmp; } // comparison op for finding items in lists: Search for the pressed key only
135 };
136 
137 typedef std::list<C4PlayerControlRecentKey> C4PlayerControlRecentKeyList;
138 
139 typedef std::vector<C4KeyCodeEx> C4KeyCodeExVec;
140 
141 // a key/mouse/gamepad assignment to a PlayerControlDef
142 class C4PlayerControlAssignment
143 {
144 public:
145 	// action to be performed on the control upon this key
146 	enum TriggerModes
147 	{
148 		CTM_Default = 0,              // standard behaviour: The control will be triggered
149 		CTM_Hold = 1 << 0,        // the control will be put into "down"-mode
150 		CTM_Release = 1 << 1,        // the hold mode of the control will be released
151 		CTM_AlwaysUnhandled = 1 << 2,  // the key will not block handling of other keys even if it got handled
152 		CTM_HandleDownStatesOnly = 1 << 3, // used when an already handled release key is processed to reset down states of overridden keys only
153 		CTM_ClearRecentKeys = 1 << 4  // if this assignment is triggered, RecentKeys are reset so no more combos can be generated
154 	};
155 
156 private:
157 	// KeyCombo list:
158 	// if size()>1, the control is triggered only if this combo is fulfilled
159 	// used for simultanuous keypresses or sequences
160 	struct KeyComboItem
161 	{
162 		C4KeyCodeEx Key;
163 		StdCopyStrBuf sKeyName;
164 		void CompileFunc(StdCompiler *pComp);
165 		void UpdateKeyName();
166 		bool operator ==(const KeyComboItem &cmp) const { return Key==cmp.Key; }
167 	};
168 	typedef std::vector<KeyComboItem> KeyComboVec;
169 	KeyComboVec KeyCombo;
170 	bool fComboIsSequence; // if true, the keys must be pressed in sequence. Otherwise, they must be pressed simultanuously
171 
172 	// trigger key: key/mouse/gamepad event triggering this assignment. For combinations, the last key of the combo.
173 	C4KeyCodeEx TriggerKey;
174 
175 	StdCopyStrBuf sControlName; // name of the control to be executed on this key
176 	StdCopyStrBuf sGUIName;    // name as displayed to player. If empty, name stored in control def should be used.
177 	StdCopyStrBuf sGUIDesc;    // key description displayed to player in config dialog. If empty, name stored in control def should be used.
178 	bool fGUIDisabled;   // whether this key can't be reassigned through the GUI dialogue
179 	bool fOverrideAssignments{false};  // override all other assignments to the same key?
180 	bool is_inherited{false}; // set for assignments that were copied from a parent set without modification
181 	bool fRefsResolved{false}; // set to true after sControlName and sKeyNames have been resolved to runtime values
182 	int32_t iGUIGroup{0};  // in which this control is grouped in the gui
183 	int32_t iControl{CON_None}; // the control to be executed on this key, i.e. the resolved sControlName
184 	int32_t iPriority{0};          // higher priority assignments get handled first
185 	int32_t iTriggerMode{CTM_Default};
186 
187 	const C4PlayerControlAssignment *inherited_assignment{nullptr}; // valid for assignments that were copied from a parent: source assignment
188 
189 public:
C4PlayerControlAssignment()190 	C4PlayerControlAssignment() :
191 		TriggerKey()
192 	{}
193 	~C4PlayerControlAssignment() = default;
194 
195 	void CompileFunc(StdCompiler *pComp);
196 	void CopyKeyFrom(const C4PlayerControlAssignment &src_assignment);
197 	bool ResolveRefs(class C4PlayerControlAssignmentSet *pParentSet, C4PlayerControlDefs *pControlDefs); // resolve references between assignments
198 	bool IsComboMatched(const C4PlayerControlRecentKeyList &DownKeys, const C4PlayerControlRecentKeyList &RecentKeys) const; // check if combo is currently fulfilled (assuming TriggerKey is already matched)
SetInherited(bool to_val)199 	void SetInherited(bool to_val) { is_inherited = to_val; }
SetInheritedAssignment(const C4PlayerControlAssignment * to_val)200 	void SetInheritedAssignment(const C4PlayerControlAssignment *to_val) { inherited_assignment = to_val; }
201 	void ResetKeyToInherited();
202 	bool IsKeyChanged() const;
SetControlName(const char * control_name)203 	void SetControlName(const char *control_name) { sControlName.Copy(control_name); }
204 	void SetKey(const C4KeyCodeEx &key);
205 
206 	bool operator ==(const C4PlayerControlAssignment &cmp) const; // doesn't compare resolved TriggerKey/iControl
207 	bool operator <(const C4PlayerControlAssignment &cmp) const { return iPriority > cmp.iPriority; } // assignments are processed in DESCENDING priority!
GetControlName()208 	const char *GetControlName() const { return sControlName.getData(); }
GetControl()209 	int32_t GetControl() const { return iControl; }
210 	const char *GetGUIName(const C4PlayerControlDefs &defs) const;
211 	const char *GetGUIDesc(const C4PlayerControlDefs &defs) const;
212 	bool IsGUIDisabled() const;
213 	int32_t GetGUIGroup() const;
IsRefsResolved()214 	bool IsRefsResolved() const { return fRefsResolved; }
ResetRefsResolved()215 	void ResetRefsResolved() { fRefsResolved = false; } // Mark references to other assignments as not resolved
IsAlwaysUnhandled()216 	bool IsAlwaysUnhandled() const { return !!(iTriggerMode & CTM_AlwaysUnhandled); }
GetTriggerMode()217 	int32_t GetTriggerMode() const { return iTriggerMode; }
GetTriggerKey()218 	const C4KeyCodeEx &GetTriggerKey() const { return TriggerKey; }
HasCombo()219 	bool HasCombo() const { return KeyCombo.size()>1; }
IsOverrideAssignments()220 	bool IsOverrideAssignments() const { return fOverrideAssignments; }
IsInherited()221 	bool IsInherited() const { return is_inherited; }
GetInheritedAssignment()222 	const C4PlayerControlAssignment *GetInheritedAssignment() const { return inherited_assignment; }
223 	StdStrBuf GetKeysAsString(bool human_readable, bool short_name) const;
224 };
225 
226 typedef std::vector<C4PlayerControlAssignment> C4PlayerControlAssignmentVec;
227 typedef std::vector<const C4PlayerControlAssignment *> C4PlayerControlAssignmentPVec;
228 
229 
230 // a set of key/mouse/gamepad assignments to all controls
231 class C4PlayerControlAssignmentSet
232 {
233 private:
234 	StdCopyStrBuf sName, sGUIName, sParentSetName;
235 	const C4PlayerControlAssignmentSet *parent_set{nullptr};
236 	C4PlayerControlAssignmentVec Assignments; // ordered by priority
237 
238 	bool has_keyboard{true};
239 	bool has_mouse{true};
240 	bool has_gamepad{false};
241 
242 public:
243 	C4PlayerControlAssignmentSet() = default;
244 	~C4PlayerControlAssignmentSet() = default;
245 	void InitEmptyFromTemplate(const C4PlayerControlAssignmentSet &template_set); // copy all fields except assignments
246 
247 	void CompileFunc(StdCompiler *pComp);
248 	bool ResolveRefs(C4PlayerControlDefs *pControlDefs); // resolve references between assignments
249 	void SortAssignments();
250 
251 	enum MergeMode { MM_Normal, MM_LowPrio, MM_Inherit, MM_ConfigOverload };
252 
253 	void MergeFrom(const C4PlayerControlAssignmentSet &Src, MergeMode merge_mode); // take over all assignments defined in Src
254 	C4PlayerControlAssignment *CreateAssignmentForControl(const char *control_name);
255 	void RemoveAssignmentByControlName(const char *control_name);
256 
GetName()257 	const char *GetName() const { return sName.getData(); }
GetGUIName()258 	const char *GetGUIName() const { return sGUIName.getData(); }
IsWildcardName()259 	bool IsWildcardName() const { return IsWildcardString(sName.getData()); }
260 
261 	C4PlayerControlAssignment *GetAssignmentByIndex(int32_t index); // assignments are ordered by priority
262 	C4PlayerControlAssignment *GetAssignmentByControlName(const char *szControlName);
263 	C4PlayerControlAssignment *GetAssignmentByControl(int32_t control);
264 	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
265 	void GetTriggerKeys(const C4PlayerControlDefs &rDefs, C4KeyCodeExVec *pRegularKeys, C4KeyCodeExVec *pHoldKeys) const; // put all trigger keys of keyset into output vectors
266 
267 	bool operator ==(const C4PlayerControlAssignmentSet &cmp) const;
268 
269 	C4Facet GetPicture() const; // get image to be drawn to represent this control set
270 	// todo
HasKeyboard()271 	bool HasKeyboard() const { return has_keyboard; }
HasMouse()272 	bool HasMouse() const { return has_mouse; }
HasGamepad()273 	bool HasGamepad() const { return has_gamepad; }
GetLayoutOrder()274 	int32_t GetLayoutOrder() const { return 0; } // returns position on keyboard (increasing from left to right) for viewport sorting
275 	bool IsMouseControlAssigned(int32_t mouseevent) const;
276 };
277 
278 // list of C4PlayerControlAssignmentSet
279 class C4PlayerControlAssignmentSets
280 {
281 private:
282 	typedef std::list<C4PlayerControlAssignmentSet> AssignmentSetList;
283 	AssignmentSetList Sets;
284 	bool clear_previous{false};
285 
286 public:
287 	C4PlayerControlAssignmentSets() = default;
288 	~C4PlayerControlAssignmentSets() = default;
289 	void Clear();
290 
291 	void CompileFunc(StdCompiler *pComp);
292 	bool operator ==(const C4PlayerControlAssignmentSets &cmp) const;
293 	bool ResolveRefs(C4PlayerControlDefs *pControlDefs); // resolve references between assignments
294 	void SortAssignments();
295 
296 	void MergeFrom(const C4PlayerControlAssignmentSets &Src, C4PlayerControlAssignmentSet::MergeMode merge_mode); // take over all assignments in known sets and new sets defined in Src
297 
298 	C4PlayerControlAssignmentSet *CreateEmptySetByTemplate(const C4PlayerControlAssignmentSet &template_set);
299 	void RemoveSetByName(const char *set_name);
300 
301 	C4PlayerControlAssignmentSet *GetSetByName(const char *szName);
302 	C4PlayerControlAssignmentSet *GetDefaultSet();
303 	int32_t GetSetIndex(const C4PlayerControlAssignmentSet *set) const;
304 	C4PlayerControlAssignmentSet *GetSetByIndex(int32_t index);
GetSetCount()305 	size_t GetSetCount() const { return Sets.size(); }
306 };
307 
308 // contents of one PlayerControls.txt file
309 class C4PlayerControlFile
310 {
311 private:
312 	C4PlayerControlDefs ControlDefs;
313 	C4PlayerControlAssignmentSets AssignmentSets;
314 public:
315 	void Clear();
316 	void CompileFunc(StdCompiler *pComp);
317 	bool Load(C4Group &hGroup, const char *szFilename, C4LangStringTable *pLang);
318 	bool Save(C4Group &hGroup, const char *szFilename);
319 
GetControlDefs()320 	const C4PlayerControlDefs &GetControlDefs() const { return ControlDefs; }
GetAssignmentSets()321 	const C4PlayerControlAssignmentSets &GetAssignmentSets() const { return AssignmentSets; }
322 };
323 
324 // runtime information about a player's control
325 class C4PlayerControl
326 {
327 public:
328 	enum { MaxRecentKeyLookback = 3000, MaxSequenceKeyDelay = 800 }; // milliseconds: Time to press key combos
329 
330 	enum ControlState {
331 		CONS_Down = 0,
332 		CONS_Up,
333 		CONS_Moved,
334 	};
335 
336 private:
337 	C4PlayerControlDefs &ControlDefs; // shortcut
338 
339 	// owner
340 	int32_t iPlr{-1};
341 
342 	// async values
343 	C4PlayerControlAssignmentSet *pControlSet{nullptr}; // the control set used by this player - may be nullptr if the player cannot be controlled!
344 	typedef std::list<C4KeyBinding *> KeyBindingList;
345 	KeyBindingList KeyBindings;     // keys registered into Game.KeyboardInput
346 	C4PlayerControlRecentKeyList RecentKeys;           // keys pressed recently; for combinations
347 	C4PlayerControlRecentKeyList DownKeys;         // keys currently held down
348 	bool IsCursorPosRequested{false};                     // set to true when a SendCursorPos-control had been issued
349 
350 public:
351 	// sync values
352 	struct CSync
353 	{
354 		struct ControlDownState
355 		{
356 			C4KeyEventData DownState, MovedState; // control is down if DownState.iStrength>0
357 			int32_t iDownFrame{0}, iMovedFrame; // frame when control was pressed
358 			bool fDownByUser{false};  // if true, the key is actually pressed. Otherwise, it's triggered as down by another key
ControlDownStateCSync::ControlDownState359 			ControlDownState(const C4KeyEventData &rDownState, int32_t iDownFrame, bool fDownByUser)
360 					: DownState(rDownState), iDownFrame(iDownFrame), fDownByUser(fDownByUser) {}
IsDownCSync::ControlDownState361 			bool IsDown() const { return DownState.iStrength>0; }
362 
ControlDownStateCSync::ControlDownState363 			ControlDownState() : DownState() {}
364 			void CompileFunc(StdCompiler *pComp);
365 			bool operator ==(const ControlDownState &cmp) const;
366 		};
367 		typedef std::vector<ControlDownState> DownStateVec;
368 		DownStateVec ControlDownStates;           // indexed by C4PlayerControlID: Down-state of a control. 0=up, 100=down; values inbetween e.g. for gamepad sticks
369 		typedef std::vector<int32_t> DisableStateVec;
370 		DisableStateVec ControlDisableStates;        // indexed by C4PlayerControlID: Disable-states of controls. >0 is disabled.
371 
372 		const ControlDownState *GetControlDownState(int32_t iControl) const;
373 		int32_t GetControlDisabled(int32_t iControl) const;
IsControlDisabledCSync374 		bool IsControlDisabled(int32_t iControl) const { return GetControlDisabled(iControl)>0; }
375 		void SetControlDownState(int32_t iControl, const C4KeyEventData &rDownState, int32_t iDownFrame, bool fDownByUser);
376 		void SetControlMovedState(int32_t iControl, const C4KeyEventData &rMovedState, int32_t iMovedFrame);
377 		void ResetControlDownState(int32_t iControl);
378 		bool SetControlDisabled(int32_t iControl, int32_t iVal);
379 
380 		void InitDefaults(const C4PlayerControlDefs &ControlDefs);
381 		void Clear();
382 		void CompileFunc(StdCompiler *pComp);
383 		bool operator ==(const CSync &cmp) const;
384 	};
385 
386 private:
387 	CSync Sync;
388 
389 	// callbacks from Game.KeyboardInput
390 	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=nullptr);
391 	bool ProcessKeyDown(const C4KeyCodeEx &pressed_key, const C4KeyCodeEx &matched_key);
392 	bool ProcessKeyUp(const C4KeyCodeEx &pressed_key, const C4KeyCodeEx &matched_key);
393 	bool ProcessKeyMoved(const C4KeyCodeEx &pressed_key, const C4KeyCodeEx &matched_key);
394 
395 	// execute single control. return if handled.
396 	bool ExecuteControl(int32_t iControl, ControlState state, const C4KeyEventData &rKeyExtraData, int32_t iTriggerMode, bool fRepeated, bool fHandleDownStateOnly);
397 	bool ExecuteControlAction(int32_t iControl, C4PlayerControlDef::Actions eAction, C4ID idControlExtraData, ControlState state, const C4KeyEventData &rKeyExtraData, bool fRepeated);
398 	bool ExecuteControlScript(int32_t iControl, C4ID idControlExtraData, ControlState state, const C4KeyEventData &rKeyExtraData, bool fRepeated);
399 
400 	// init
401 	void AddKeyBinding(const C4KeyCodeEx &key, bool fHoldKey, int32_t idx);
402 
403 	// helper function: get current cursor position of controlling player in GUI coordinates
404 	// used e.g. to open menus at cursor pos
405 	bool GetCurrentPlayerCursorPos(int32_t *x_out, int32_t *y_out, int32_t *game_x_out, int32_t *game_y_out);
406 
407 public:
408 	C4PlayerControl();
~C4PlayerControl()409 	~C4PlayerControl() { Clear(); }
410 	void Clear();
411 
412 	// first-time init call after player join
413 	// not called again after control set change/savegame resume
414 	// does DefaultDisabled controls
415 	void Init();
416 
417 	void CompileFunc(StdCompiler *pComp);
418 
419 	void RegisterKeyset(int32_t iPlr, C4PlayerControlAssignmentSet *pKeyset); // register all keys into Game.KeyboardInput creating KeyBindings
420 
IsGlobal()421 	bool IsGlobal() const { return iPlr==-1; }
GetControlDownState(int32_t iControl)422 	const CSync::ControlDownState *GetControlDownState(int32_t iControl) const
423 	{ return Sync.GetControlDownState(iControl); }
424 
425 	// callback from control queue
426 	void ExecuteControlPacket(const class C4ControlPlayerControl *pCtrl);
427 
428 	// sync execution: Do keyrepeat, etc.
429 	void Execute();
430 
431 	// mouse input
432 	bool DoMouseInput(uint8_t mouse_id, int32_t mouseevent, float game_x, float game_y, float gui_x, float gui_y, DWORD flags);
433 
434 	// control enable/disable
SetControlDisabled(int ctrl,bool is_disabled)435 	bool SetControlDisabled(int ctrl, bool is_disabled) { return Sync.SetControlDisabled(ctrl, is_disabled); }
IsControlDisabled(int ctrl)436 	bool IsControlDisabled(int ctrl) const { return Sync.IsControlDisabled(ctrl); }
437 
438 	// callback from C4GameControl when the next control packet is finalized
439 	void PrepareInput();
440 
441 };
442 
443 
444 #endif // INC_C4PlayerControl
445