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 325 of file C4PlayerControl.h.

Member Enumeration Documentation

anonymous enum
Enumerator
MaxRecentKeyLookback 
MaxSequenceKeyDelay 

Definition at line 328 of file C4PlayerControl.h.

Enumerator
CONS_Down 
CONS_Up 
CONS_Moved 

Definition at line 330 of file C4PlayerControl.h.

Constructor & Destructor Documentation

C4PlayerControl::C4PlayerControl ( )

Definition at line 1357 of file C4PlayerControl.cpp.

1357  : ControlDefs(Game.PlayerControlDefs)
1358 {
1359 }
C4Game Game
Definition: C4Globals.cpp:52
C4PlayerControlDefs PlayerControlDefs
Definition: C4Game.h:92
C4PlayerControl::~C4PlayerControl ( )
inline

Definition at line 409 of file C4PlayerControl.h.

References Clear().

409 { Clear(); }

Here is the call graph for this function:

Member Function Documentation

void C4PlayerControl::Clear ( )

Definition at line 1361 of file C4PlayerControl.cpp.

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

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

1362 {
1363  iPlr = NO_OWNER;
1364  pControlSet = nullptr;
1365  for (auto & KeyBinding : KeyBindings) delete KeyBinding;
1366  KeyBindings.clear();
1367  RecentKeys.clear();
1368  DownKeys.clear();
1369  Sync.Clear();
1370  IsCursorPosRequested = false;
1371 }
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 991 of file C4PlayerControl.cpp.

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

992 {
993  // compile sync values only
994  CSync DefaultSync;
995  DefaultSync.InitDefaults(ControlDefs);
996  pComp->Value(mkNamingAdapt(Sync, "PlayerControl", DefaultSync));
997 }
StdNamingAdapt< T > mkNamingAdapt(T &&rValue, const char *szName)
Definition: StdAdaptors.h:92
void Value(const T &rStruct)
Definition: StdCompiler.h:161

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 1397 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().

1398 {
1399  // convert moueevent to key code
1400  uint8_t mouseevent_code;
1401  C4KeyCodeEx mouseevent_keycode;
1402  bool is_down = true;
1403  switch (mouseevent)
1404  {
1405  case C4MC_Button_None: mouseevent_code = KEY_MOUSE_Move; break;
1406  case C4MC_Button_LeftUp: is_down = false; // nobreak
1407  case C4MC_Button_LeftDown: mouseevent_code = KEY_MOUSE_ButtonLeft; break;
1408  case C4MC_Button_LeftDouble: mouseevent_code = KEY_MOUSE_ButtonLeftDouble; break;
1409  case C4MC_Button_RightUp: is_down = false; // nobreak
1410  case C4MC_Button_RightDown: mouseevent_code = KEY_MOUSE_ButtonRight; break;
1411  case C4MC_Button_RightDouble: mouseevent_code = KEY_MOUSE_ButtonRightDouble; break;
1412  case C4MC_Button_MiddleUp: is_down = false; // nobreak
1413  case C4MC_Button_MiddleDown: mouseevent_code = KEY_MOUSE_ButtonMiddle; break;
1414  case C4MC_Button_MiddleDouble: mouseevent_code = KEY_MOUSE_ButtonMiddleDouble; break;
1415  case C4MC_Button_X1Up: is_down = false; // nobreak
1416  case C4MC_Button_X1Down: mouseevent_code = KEY_MOUSE_ButtonX1; break;
1417  case C4MC_Button_X1Double: mouseevent_code = KEY_MOUSE_ButtonX1Double; break;
1418  case C4MC_Button_X2Up: is_down = false; // nobreak
1419  case C4MC_Button_X2Down: mouseevent_code = KEY_MOUSE_ButtonX2; break;
1420  case C4MC_Button_X2Double: mouseevent_code = KEY_MOUSE_ButtonX2Double; break;
1421  case C4MC_Button_Wheel:
1422  if (!wheel_dir) return false;
1423  mouseevent_code = (wheel_dir > 0) ? KEY_MOUSE_Wheel1Up : KEY_MOUSE_Wheel1Down; break;
1424  default: assert(false); return false;
1425  }
1426  // compose keycode
1427  if (is_ctrl_down) mouseevent_keycode.dwShift |= KEYS_Control;
1428  if (is_shift_down) mouseevent_keycode.dwShift |= KEYS_Shift;
1429  if (is_alt_down) mouseevent_keycode.dwShift |= KEYS_Alt;
1430  mouseevent_keycode.Key = KEY_Mouse(mouse_id, mouseevent_code);
1431  // first, try processing it as GUI mouse event. if not assigned, process as Game mous event
1432  // TODO: May route this through Game.DoKeyboardInput instead - would allow assignment of mouse events in CustomConfig
1433  // and would get rid of the Game.KeyboardInput.SetLastKeyExtraData-hack
1434  C4KeyEventData mouseevent_data;
1435  mouseevent_data.iStrength = 100*is_down; // TODO: May get pressure from tablet here
1436  mouseevent_data.vp_x = uint32_t(gui_x);
1437  mouseevent_data.vp_y = uint32_t(gui_y);
1438  mouseevent_data.game_x = uint32_t(game_x);
1439  mouseevent_data.game_y = uint32_t(game_y);
1440  Game.KeyboardInput.SetLastKeyExtraData(mouseevent_data); // ProcessKeyDown/Up queries it from there...
1441  bool result;
1442  if (is_down)
1443  result = ProcessKeyDown(mouseevent_keycode, mouseevent_keycode);
1444  else
1445  result = ProcessKeyUp(mouseevent_keycode, mouseevent_keycode);
1446  return result;
1447 }
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:96
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 1320 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().

1321 {
1322  // sync execution: Do keyrepeat
1323  for (size_t i=0; i<ControlDefs.GetCount(); ++i)
1324  {
1325  const CSync::ControlDownState *pControlDownState = Sync.GetControlDownState(i);
1326  if (pControlDownState && pControlDownState->IsDown())
1327  {
1328  const C4PlayerControlDef *pCtrlDef = ControlDefs.GetControlByIndex(i);
1329  assert(pCtrlDef);
1330  int32_t iCtrlRepeatDelay = pCtrlDef->GetRepeatDelay();
1331  if (iCtrlRepeatDelay)
1332  {
1333  int32_t iFrameDiff = Game.FrameCounter - pControlDownState->iDownFrame;
1334  int32_t iCtrlInitialRepeatDelay = pCtrlDef->GetInitialRepeatDelay();
1335  if (iFrameDiff && iFrameDiff >= iCtrlInitialRepeatDelay)
1336  {
1337  if (!((iFrameDiff-iCtrlInitialRepeatDelay) % iCtrlRepeatDelay))
1338  {
1339  // it's RepeatTime for this key!
1340  ExecuteControlAction(i, pCtrlDef->GetAction(), pCtrlDef->GetExtraData(), CONS_Down, pControlDownState->DownState, true);
1341  }
1342  }
1343  }
1344  }
1345  }
1346  // cleanup old recent keys
1348  C4PlayerControlRecentKeyList::iterator irk;
1349  for (irk = RecentKeys.begin(); irk != RecentKeys.end(); ++irk)
1350  {
1351  C4PlayerControlRecentKey &rk = *irk;
1352  if (rk.tTime + MaxRecentKeyLookback > tNow) break;
1353  }
1354  if (irk != RecentKeys.begin()) RecentKeys.erase(RecentKeys.begin(), irk);
1355 }
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:128
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 1111 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.

1112 {
1113  // callback from control queue. Execute controls in packet until one of them gets processed
1114  // assume async packets always as not processed to ensure sync safety (usually, sync commands should better not ovberride async commands anyway)
1115  bool fHandleDownStateOnly = false;
1116  for (C4ControlPlayerControl::ControlItemVec::const_iterator i = pCtrl->GetControlItems().begin(); i != pCtrl->GetControlItems().end(); ++i)
1117  {
1118  const C4ControlPlayerControl::ControlItem &rItem = *i;
1119  const C4PlayerControlDef *pCtrlDef = ControlDefs.GetControlByIndex(rItem.iControl);
1120  if (pCtrlDef)
1121  {
1122  if (Config.General.DebugRec)
1123  {
1124  if (pCtrlDef->IsSync())
1125  {
1126  AddDbgRec(RCT_PlrCom, &rItem.iControl, sizeof(rItem.iControl));
1127  }
1128  }
1129  if (ExecuteControl(rItem.iControl, pCtrl->GetState(), pCtrl->GetExtraData(), rItem.iTriggerMode, false, fHandleDownStateOnly))
1130  if (pCtrlDef->IsSync())
1131  {
1132  if (pCtrl->GetState() == CONS_Up)
1133  {
1134  // control processed. however, for key releases, overriden keys are released silently so following down events aren't handled as key repeats
1135  // note this does not affect CTM_Hold/CTM_Release, because they ignore release controls anyway
1136  fHandleDownStateOnly = true;
1137  }
1138  else
1139  {
1140  break;
1141  }
1142  }
1143  }
1144  }
1145 }
C4Config Config
Definition: C4Config.cpp:833
C4ConfigGeneral General
Definition: C4Config.h:251
bool IsSync() const
const C4PlayerControlDef * GetControlByIndex(int32_t idx) const
void AddDbgRec(C4RecordChunkType eType, const void *pData, int iSize)
Definition: C4Record.cpp:32
int32_t DebugRec
Definition: C4Config.h:60

Here is the call graph for this function:

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

Definition at line 422 of file C4PlayerControl.h.

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

Definition at line 985 of file C4PlayerControl.cpp.

Referenced by C4Player::Init().

986 {
987  // defaultdisabled controls
988  Sync.InitDefaults(ControlDefs);
989 }
void InitDefaults(const C4PlayerControlDefs &ControlDefs)

Here is the caller graph for this function:

bool C4PlayerControl::IsControlDisabled ( int  ctrl) const
inline

Definition at line 436 of file C4PlayerControl.h.

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

Definition at line 421 of file C4PlayerControl.h.

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

Definition at line 1479 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().

1480 {
1481  if (IsCursorPosRequested)
1482  {
1483  int32_t x, y, game_x, game_y;
1484  // add current cursor pos in GUI coordinates to input
1485  if (GetCurrentPlayerCursorPos(&x, &y, &game_x, &game_y))
1486  {
1487  // CON_CursorPos might not have been defined in definition file
1488  if (ControlDefs.InternalCons.CON_CursorPos != CON_None)
1489  {
1490  C4KeyEventData ev;
1491  ev.iStrength = 0;
1492  ev.vp_x = x; ev.vp_y = y;
1493  ev.game_x = game_x; ev.game_y = game_y;
1494  C4ControlPlayerControl *pControlPacket = new C4ControlPlayerControl(iPlr, CONS_Down, ev);
1496  // make sure it's added at head, because controls that have SendCursorPos=1 set will follow, which will rely
1497  // on the cursor pos being known
1498  Game.Input.AddHead(CID_PlrControl, pControlPacket);
1499  }
1500  }
1501  else
1502  {
1503  // no cursor is known (e.g.: Cursor Clonk dead, etc.). Don't create a control.
1504  // Script will probably fall back to last known cursor pos
1505  }
1506  IsCursorPosRequested = false;
1507  }
1508 }
C4Game Game
Definition: C4Globals.cpp:52
struct C4PlayerControlDefs::CInternalCons InternalCons
C4Control & Input
Definition: C4Game.h:82
DECLARE_C4CONTROL_VIRTUALS void AddControl(int32_t iControl, int32_t iTriggerMode)
Definition: C4Control.h:225
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 1373 of file C4PlayerControl.cpp.

References C4PlayerControlAssignmentSet::GetTriggerKeys().

Referenced by C4Player::InitControl().

1374 {
1375  // setup
1376  pControlSet = pKeyset;
1377  this->iPlr = iPlr;
1378  // register all keys into Game.KeyboardInput creating KeyBindings
1379  if (pControlSet)
1380  {
1381  C4KeyCodeExVec RegularKeys, HoldKeys;
1382  pControlSet->GetTriggerKeys(ControlDefs, &RegularKeys, &HoldKeys);
1383  int32_t idx=0;
1384  for (C4KeyCodeExVec::const_iterator i = RegularKeys.begin(); i != RegularKeys.end(); ++i) AddKeyBinding(*i, false, idx++);
1385  for (C4KeyCodeExVec::const_iterator i = HoldKeys.begin(); i != HoldKeys.end(); ++i) AddKeyBinding(*i, true, idx++);
1386  }
1387 }
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 435 of file C4PlayerControl.h.

435 { 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: