OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4PlayerControl Class Reference

#include <C4PlayerControl.h>

Classes

struct  CSync
 

Public Types

enum  { MaxRecentKeyLookback = 3000, MaxSequenceKeyDelay = 800 }
 
enum  ControlState { CONS_Down = 0, CONS_Up, CONS_Moved }
 

Public Member Functions

 C4PlayerControl ()
 
 ~C4PlayerControl ()
 
void Clear ()
 
void Init ()
 
void CompileFunc (StdCompiler *pComp)
 
void RegisterKeyset (int32_t iPlr, C4PlayerControlAssignmentSet *pKeyset)
 
bool IsGlobal () const
 
const CSync::ControlDownStateGetControlDownState (int32_t iControl) const
 
void ExecuteControlPacket (const class C4ControlPlayerControl *pCtrl)
 
void Execute ()
 
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)
 
bool SetControlDisabled (int ctrl, bool is_disabled)
 
bool IsControlDisabled (int ctrl) const
 
void PrepareInput ()
 

Detailed Description

Definition at line 330 of file C4PlayerControl.h.

Member Enumeration Documentation

anonymous enum
Enumerator
MaxRecentKeyLookback 
MaxSequenceKeyDelay 

Definition at line 333 of file C4PlayerControl.h.

Enumerator
CONS_Down 
CONS_Up 
CONS_Moved 

Definition at line 335 of file C4PlayerControl.h.

Constructor & Destructor Documentation

C4PlayerControl::C4PlayerControl ( )

Definition at line 1373 of file C4PlayerControl.cpp.

1373  : ControlDefs(Game.PlayerControlDefs), iPlr(-1), pControlSet(nullptr), IsCursorPosRequested(false)
1374 {
1375 }
C4Game Game
Definition: C4Globals.cpp:52
C4PlayerControlDefs PlayerControlDefs
Definition: C4Game.h:94
C4PlayerControl::~C4PlayerControl ( )
inline

Definition at line 414 of file C4PlayerControl.h.

References Clear().

414 { Clear(); }

Here is the call graph for this function:

Member Function Documentation

void C4PlayerControl::Clear ( )

Definition at line 1377 of file C4PlayerControl.cpp.

References C4PlayerControl::CSync::Clear(), and NO_OWNER.

Referenced by C4Player::ClearControl(), and ~C4PlayerControl().

1378 {
1379  iPlr = NO_OWNER;
1380  pControlSet = nullptr;
1381  for (KeyBindingList::iterator i = KeyBindings.begin(); i != KeyBindings.end(); ++i) delete *i;
1382  KeyBindings.clear();
1383  RecentKeys.clear();
1384  DownKeys.clear();
1385  Sync.Clear();
1386  IsCursorPosRequested = false;
1387 }
const int NO_OWNER
Definition: C4Constants.h:138

Here is the call graph for this function:

Here is the caller graph for this function:

void C4PlayerControl::CompileFunc ( StdCompiler pComp)

Definition at line 1007 of file C4PlayerControl.cpp.

References C4PlayerControl::CSync::InitDefaults(), mkNamingAdapt(), and StdCompiler::Value().

1008 {
1009  // compile sync values only
1010  CSync DefaultSync;
1011  DefaultSync.InitDefaults(ControlDefs);
1012  pComp->Value(mkNamingAdapt(Sync, "PlayerControl", DefaultSync));
1013 }
StdNamingAdapt< T > mkNamingAdapt(T &&rValue, const char *szName)
Definition: StdAdaptors.h:93
void Value(const T &rStruct)
Definition: StdCompiler.h:171

Here is the call graph for this function:

bool C4PlayerControl::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 
)

Definition at line 1413 of file C4PlayerControl.cpp.

References C4MC_Button_LeftDouble, C4MC_Button_LeftDown, C4MC_Button_LeftUp, C4MC_Button_MiddleDouble, C4MC_Button_MiddleDown, C4MC_Button_MiddleUp, C4MC_Button_None, C4MC_Button_RightDouble, C4MC_Button_RightDown, C4MC_Button_RightUp, C4MC_Button_Wheel, C4MC_Button_X1Double, C4MC_Button_X1Down, C4MC_Button_X1Up, C4MC_Button_X2Double, C4MC_Button_X2Down, C4MC_Button_X2Up, C4KeyCodeEx::dwShift, Game, C4KeyEventData::game_x, C4KeyEventData::game_y, C4KeyEventData::iStrength, C4KeyCodeEx::Key, KEY_Mouse(), KEY_MOUSE_ButtonLeft, KEY_MOUSE_ButtonLeftDouble, KEY_MOUSE_ButtonMiddle, KEY_MOUSE_ButtonMiddleDouble, KEY_MOUSE_ButtonRight, KEY_MOUSE_ButtonRightDouble, KEY_MOUSE_ButtonX1, KEY_MOUSE_ButtonX1Double, KEY_MOUSE_ButtonX2, KEY_MOUSE_ButtonX2Double, KEY_MOUSE_Move, KEY_MOUSE_Wheel1Down, KEY_MOUSE_Wheel1Up, C4Game::KeyboardInput, KEYS_Alt, KEYS_Control, KEYS_Shift, C4KeyboardInput::SetLastKeyExtraData(), C4KeyEventData::vp_x, and C4KeyEventData::vp_y.

Referenced by C4MouseControl::DoMoveInput(), and C4MouseControl::Move().

1414 {
1415  // convert moueevent to key code
1416  uint8_t mouseevent_code;
1417  C4KeyCodeEx mouseevent_keycode;
1418  bool is_down = true;
1419  switch (mouseevent)
1420  {
1421  case C4MC_Button_None: mouseevent_code = KEY_MOUSE_Move; break;
1422  case C4MC_Button_LeftUp: is_down = false; // nobreak
1423  case C4MC_Button_LeftDown: mouseevent_code = KEY_MOUSE_ButtonLeft; break;
1424  case C4MC_Button_LeftDouble: mouseevent_code = KEY_MOUSE_ButtonLeftDouble; break;
1425  case C4MC_Button_RightUp: is_down = false; // nobreak
1426  case C4MC_Button_RightDown: mouseevent_code = KEY_MOUSE_ButtonRight; break;
1427  case C4MC_Button_RightDouble: mouseevent_code = KEY_MOUSE_ButtonRightDouble; break;
1428  case C4MC_Button_MiddleUp: is_down = false; // nobreak
1429  case C4MC_Button_MiddleDown: mouseevent_code = KEY_MOUSE_ButtonMiddle; break;
1430  case C4MC_Button_MiddleDouble: mouseevent_code = KEY_MOUSE_ButtonMiddleDouble; break;
1431  case C4MC_Button_X1Up: is_down = false; // nobreak
1432  case C4MC_Button_X1Down: mouseevent_code = KEY_MOUSE_ButtonX1; break;
1433  case C4MC_Button_X1Double: mouseevent_code = KEY_MOUSE_ButtonX1Double; break;
1434  case C4MC_Button_X2Up: is_down = false; // nobreak
1435  case C4MC_Button_X2Down: mouseevent_code = KEY_MOUSE_ButtonX2; break;
1436  case C4MC_Button_X2Double: mouseevent_code = KEY_MOUSE_ButtonX2Double; break;
1437  case C4MC_Button_Wheel:
1438  if (!wheel_dir) return false;
1439  mouseevent_code = (wheel_dir > 0) ? KEY_MOUSE_Wheel1Up : KEY_MOUSE_Wheel1Down; break;
1440  default: assert(false); return false;
1441  }
1442  // compose keycode
1443  if (is_ctrl_down) mouseevent_keycode.dwShift |= KEYS_Control;
1444  if (is_shift_down) mouseevent_keycode.dwShift |= KEYS_Shift;
1445  if (is_alt_down) mouseevent_keycode.dwShift |= KEYS_Alt;
1446  mouseevent_keycode.Key = KEY_Mouse(mouse_id, mouseevent_code);
1447  // first, try processing it as GUI mouse event. if not assigned, process as Game mous event
1448  // TODO: May route this through Game.DoKeyboardInput instead - would allow assignment of mouse events in CustomConfig
1449  // and would get rid of the Game.KeyboardInput.SetLastKeyExtraData-hack
1450  C4KeyEventData mouseevent_data;
1451  mouseevent_data.iStrength = 100*is_down; // TODO: May get pressure from tablet here
1452  mouseevent_data.vp_x = uint32_t(gui_x);
1453  mouseevent_data.vp_y = uint32_t(gui_y);
1454  mouseevent_data.game_x = uint32_t(game_x);
1455  mouseevent_data.game_y = uint32_t(game_y);
1456  Game.KeyboardInput.SetLastKeyExtraData(mouseevent_data); // ProcessKeyDown/Up queries it from there...
1457  bool result;
1458  if (is_down)
1459  result = ProcessKeyDown(mouseevent_keycode, mouseevent_keycode);
1460  else
1461  result = ProcessKeyUp(mouseevent_keycode, mouseevent_keycode);
1462  return result;
1463 }
const int32_t C4MC_Button_MiddleUp
const int32_t C4MC_Button_LeftDown
C4Game Game
Definition: C4Globals.cpp:52
const C4KeyCode KEY_MOUSE_ButtonX1
const int32_t C4MC_Button_RightUp
const int32_t C4MC_Button_X2Down
const C4KeyCode KEY_MOUSE_Wheel1Up
const int32_t C4MC_Button_MiddleDouble
const int32_t C4MC_Button_X1Double
C4KeyCode KEY_Mouse(uint8_t mouse_id, uint8_t mouseevent)
const int32_t C4MC_Button_LeftDouble
const int32_t C4MC_Button_X2Double
const int32_t C4MC_Button_LeftUp
const int32_t C4MC_Button_X1Up
C4KeyboardInput & KeyboardInput
Definition: C4Game.h:98
const C4KeyCode KEY_MOUSE_ButtonLeftDouble
const C4KeyCode KEY_MOUSE_ButtonX1Double
void SetLastKeyExtraData(const C4KeyEventData &data)
const int32_t C4MC_Button_X1Down
const C4KeyCode KEY_MOUSE_ButtonX2
const int32_t C4MC_Button_RightDown
C4KeyCode Key
const C4KeyCode KEY_MOUSE_ButtonX2Double
const C4KeyCode KEY_MOUSE_Move
const int32_t C4MC_Button_Wheel
const C4KeyCode KEY_MOUSE_ButtonRightDouble
const int32_t C4MC_Button_RightDouble
const int32_t C4MC_Button_None
const C4KeyCode KEY_MOUSE_ButtonMiddleDouble
const C4KeyCode KEY_MOUSE_ButtonRight
const int32_t C4MC_Button_MiddleDown
const C4KeyCode KEY_MOUSE_ButtonLeft
const C4KeyCode KEY_MOUSE_ButtonMiddle
const C4KeyCode KEY_MOUSE_Wheel1Down
const int32_t C4MC_Button_X2Up

Here is the call graph for this function:

Here is the caller graph for this function:

void C4PlayerControl::Execute ( )

Definition at line 1336 of file C4PlayerControl.cpp.

References CONS_Down, C4PlayerControl::CSync::ControlDownState::DownState, C4Game::FrameCounter, Game, C4PlayerControlDef::GetAction(), C4PlayerControlDef::GetExtraData(), C4PlayerControlDef::GetInitialRepeatDelay(), C4PlayerControlDef::GetRepeatDelay(), C4PlayerControl::CSync::ControlDownState::iDownFrame, C4PlayerControl::CSync::ControlDownState::IsDown(), MaxRecentKeyLookback, C4TimeMilliseconds::Now(), and C4PlayerControlRecentKey::tTime.

Referenced by C4Player::ExecuteControl().

1337 {
1338  // sync execution: Do keyrepeat
1339  for (size_t i=0; i<ControlDefs.GetCount(); ++i)
1340  {
1341  const CSync::ControlDownState *pControlDownState = Sync.GetControlDownState(i);
1342  if (pControlDownState && pControlDownState->IsDown())
1343  {
1344  const C4PlayerControlDef *pCtrlDef = ControlDefs.GetControlByIndex(i);
1345  assert(pCtrlDef);
1346  int32_t iCtrlRepeatDelay = pCtrlDef->GetRepeatDelay();
1347  if (iCtrlRepeatDelay)
1348  {
1349  int32_t iFrameDiff = Game.FrameCounter - pControlDownState->iDownFrame;
1350  int32_t iCtrlInitialRepeatDelay = pCtrlDef->GetInitialRepeatDelay();
1351  if (iFrameDiff && iFrameDiff >= iCtrlInitialRepeatDelay)
1352  {
1353  if (!((iFrameDiff-iCtrlInitialRepeatDelay) % iCtrlRepeatDelay))
1354  {
1355  // it's RepeatTime for this key!
1356  ExecuteControlAction(i, pCtrlDef->GetAction(), pCtrlDef->GetExtraData(), CONS_Down, pControlDownState->DownState, true);
1357  }
1358  }
1359  }
1360  }
1361  }
1362  // cleanup old recent keys
1364  C4PlayerControlRecentKeyList::iterator irk;
1365  for (irk = RecentKeys.begin(); irk != RecentKeys.end(); ++irk)
1366  {
1367  C4PlayerControlRecentKey &rk = *irk;
1368  if (rk.tTime + MaxRecentKeyLookback > tNow) break;
1369  }
1370  if (irk != RecentKeys.begin()) RecentKeys.erase(RecentKeys.begin(), irk);
1371 }
C4Game Game
Definition: C4Globals.cpp:52
const ControlDownState * GetControlDownState(int32_t iControl) const
const C4PlayerControlDef * GetControlByIndex(int32_t idx) const
C4ID GetExtraData() const
int32_t FrameCounter
Definition: C4Game.h:130
C4TimeMilliseconds tTime
Actions GetAction() const
size_t GetCount() const
int32_t GetInitialRepeatDelay() const
static C4TimeMilliseconds Now()
int32_t GetRepeatDelay() const

Here is the call graph for this function:

Here is the caller graph for this function:

void C4PlayerControl::ExecuteControlPacket ( const class C4ControlPlayerControl pCtrl)

Definition at line 1127 of file C4PlayerControl.cpp.

References AddDbgRec(), Config, CONS_Up, C4ConfigGeneral::DebugRec, C4Config::General, C4ControlPlayerControl::GetControlItems(), C4ControlPlayerControl::GetExtraData(), C4ControlPlayerControl::GetState(), C4ControlPlayerControl::ControlItem::iControl, C4PlayerControlDef::IsSync(), C4ControlPlayerControl::ControlItem::iTriggerMode, and RCT_PlrCom.

1128 {
1129  // callback from control queue. Execute controls in packet until one of them gets processed
1130  // assume async packets always as not processed to ensure sync safety (usually, sync commands should better not ovberride async commands anyway)
1131  bool fHandleDownStateOnly = false;
1132  for (C4ControlPlayerControl::ControlItemVec::const_iterator i = pCtrl->GetControlItems().begin(); i != pCtrl->GetControlItems().end(); ++i)
1133  {
1134  const C4ControlPlayerControl::ControlItem &rItem = *i;
1135  const C4PlayerControlDef *pCtrlDef = ControlDefs.GetControlByIndex(rItem.iControl);
1136  if (pCtrlDef)
1137  {
1138  if (Config.General.DebugRec)
1139  {
1140  if (pCtrlDef->IsSync())
1141  {
1142  AddDbgRec(RCT_PlrCom, &rItem.iControl, sizeof(rItem.iControl));
1143  }
1144  }
1145  if (ExecuteControl(rItem.iControl, pCtrl->GetState(), pCtrl->GetExtraData(), rItem.iTriggerMode, false, fHandleDownStateOnly))
1146  if (pCtrlDef->IsSync())
1147  {
1148  if (pCtrl->GetState() == CONS_Up)
1149  {
1150  // control processed. however, for key releases, overriden keys are released silently so following down events aren't handled as key repeats
1151  // note this does not affect CTM_Hold/CTM_Release, because they ignore release controls anyway
1152  fHandleDownStateOnly = true;
1153  }
1154  else
1155  {
1156  break;
1157  }
1158  }
1159  }
1160  }
1161 }
C4Config Config
Definition: C4Config.cpp:837
C4ConfigGeneral General
Definition: C4Config.h:252
bool IsSync() const
const C4PlayerControlDef * GetControlByIndex(int32_t idx) const
void AddDbgRec(C4RecordChunkType eType, const void *pData, int iSize)
Definition: C4Record.cpp:36
int32_t DebugRec
Definition: C4Config.h:61

Here is the call graph for this function:

const CSync::ControlDownState* C4PlayerControl::GetControlDownState ( int32_t  iControl) const
inline

Definition at line 427 of file C4PlayerControl.h.

428  { return Sync.GetControlDownState(iControl); }
const ControlDownState * GetControlDownState(int32_t iControl) const
void C4PlayerControl::Init ( )

Definition at line 1001 of file C4PlayerControl.cpp.

Referenced by C4Player::Init().

1002 {
1003  // defaultdisabled controls
1004  Sync.InitDefaults(ControlDefs);
1005 }
void InitDefaults(const C4PlayerControlDefs &ControlDefs)

Here is the caller graph for this function:

bool C4PlayerControl::IsControlDisabled ( int  ctrl) const
inline

Definition at line 441 of file C4PlayerControl.h.

441 { return Sync.IsControlDisabled(ctrl); }
bool IsControlDisabled(int32_t iControl) const
bool C4PlayerControl::IsGlobal ( ) const
inline

Definition at line 426 of file C4PlayerControl.h.

426 { return iPlr==-1; }
void C4PlayerControl::PrepareInput ( )

Definition at line 1495 of file C4PlayerControl.cpp.

References C4ControlPlayerControl::AddControl(), C4Control::AddHead(), CID_PlrControl, C4PlayerControlDefs::CInternalCons::CON_CursorPos, CON_None, CONS_Down, C4PlayerControlAssignment::CTM_Default, Game, C4KeyEventData::game_x, C4KeyEventData::game_y, C4Game::Input, C4PlayerControlDefs::InternalCons, C4KeyEventData::iStrength, C4KeyEventData::vp_x, and C4KeyEventData::vp_y.

Referenced by C4GameControl::PrepareInput().

1496 {
1497  if (IsCursorPosRequested)
1498  {
1499  int32_t x, y, game_x, game_y;
1500  // add current cursor pos in GUI coordinates to input
1501  if (GetCurrentPlayerCursorPos(&x, &y, &game_x, &game_y))
1502  {
1503  // CON_CursorPos might not have been defined in definition file
1504  if (ControlDefs.InternalCons.CON_CursorPos != CON_None)
1505  {
1506  C4KeyEventData ev;
1507  ev.iStrength = 0;
1508  ev.vp_x = x; ev.vp_y = y;
1509  ev.game_x = game_x; ev.game_y = game_y;
1510  C4ControlPlayerControl *pControlPacket = new C4ControlPlayerControl(iPlr, CONS_Down, ev);
1512  // make sure it's added at head, because controls that have SendCursorPos=1 set will follow, which will rely
1513  // on the cursor pos being known
1514  Game.Input.AddHead(CID_PlrControl, pControlPacket);
1515  }
1516  }
1517  else
1518  {
1519  // no cursor is known (e.g.: Cursor Clonk dead, etc.). Don't create a control.
1520  // Script will probably fall back to last known cursor pos
1521  }
1522  IsCursorPosRequested = false;
1523  }
1524 }
C4Game Game
Definition: C4Globals.cpp:52
struct C4PlayerControlDefs::CInternalCons InternalCons
C4Control & Input
Definition: C4Game.h:84
DECLARE_C4CONTROL_VIRTUALS void AddControl(int32_t iControl, int32_t iTriggerMode)
Definition: C4Control.h:230
void AddHead(C4PacketType eType, C4ControlPacket *pCtrl)
Definition: C4Control.h:81

Here is the call graph for this function:

Here is the caller graph for this function:

void C4PlayerControl::RegisterKeyset ( int32_t  iPlr,
C4PlayerControlAssignmentSet pKeyset 
)

Definition at line 1389 of file C4PlayerControl.cpp.

References C4PlayerControlAssignmentSet::GetTriggerKeys().

Referenced by C4Player::InitControl().

1390 {
1391  // setup
1392  pControlSet = pKeyset;
1393  this->iPlr = iPlr;
1394  // register all keys into Game.KeyboardInput creating KeyBindings
1395  if (pControlSet)
1396  {
1397  C4KeyCodeExVec RegularKeys, HoldKeys;
1398  pControlSet->GetTriggerKeys(ControlDefs, &RegularKeys, &HoldKeys);
1399  int32_t idx=0;
1400  for (C4KeyCodeExVec::const_iterator i = RegularKeys.begin(); i != RegularKeys.end(); ++i) AddKeyBinding(*i, false, idx++);
1401  for (C4KeyCodeExVec::const_iterator i = HoldKeys.begin(); i != HoldKeys.end(); ++i) AddKeyBinding(*i, true, idx++);
1402  }
1403 }
void GetTriggerKeys(const C4PlayerControlDefs &rDefs, C4KeyCodeExVec *pRegularKeys, C4KeyCodeExVec *pHoldKeys) const
std::vector< C4KeyCodeEx > C4KeyCodeExVec

Here is the call graph for this function:

Here is the caller graph for this function:

bool C4PlayerControl::SetControlDisabled ( int  ctrl,
bool  is_disabled 
)
inline

Definition at line 440 of file C4PlayerControl.h.

440 { return Sync.SetControlDisabled(ctrl, is_disabled); }
bool SetControlDisabled(int32_t iControl, int32_t iVal)

The documentation for this class was generated from the following files: