OpenClonk
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, DWORD flags)
 
bool SetControlDisabled (int ctrl, bool is_disabled)
 
bool IsControlDisabled (int ctrl) const
 
void PrepareInput ()
 

Detailed Description

Definition at line 324 of file C4PlayerControl.h.

Member Enumeration Documentation

◆ anonymous enum

anonymous enum
Enumerator
MaxRecentKeyLookback 
MaxSequenceKeyDelay 

Definition at line 327 of file C4PlayerControl.h.

327 { MaxRecentKeyLookback = 3000, MaxSequenceKeyDelay = 800 }; // milliseconds: Time to press key combos

◆ ControlState

Enumerator
CONS_Down 
CONS_Up 
CONS_Moved 

Definition at line 329 of file C4PlayerControl.h.

329  {
330  CONS_Down = 0,
331  CONS_Up,
332  CONS_Moved,
333  };

Constructor & Destructor Documentation

◆ C4PlayerControl()

C4PlayerControl::C4PlayerControl ( )

Definition at line 1355 of file C4PlayerControl.cpp.

1355  : ControlDefs(Game.PlayerControlDefs)
1356 {
1357 }
C4Game Game
Definition: C4Globals.cpp:52
C4PlayerControlDefs PlayerControlDefs
Definition: C4Game.h:92

◆ ~C4PlayerControl()

C4PlayerControl::~C4PlayerControl ( )
inline

Definition at line 408 of file C4PlayerControl.h.

408 { Clear(); }

References Clear().

Here is the call graph for this function:

Member Function Documentation

◆ Clear()

void C4PlayerControl::Clear ( )

Definition at line 1359 of file C4PlayerControl.cpp.

1360 {
1361  iPlr = NO_OWNER;
1362  pControlSet = nullptr;
1363  for (auto & KeyBinding : KeyBindings) delete KeyBinding;
1364  KeyBindings.clear();
1365  RecentKeys.clear();
1366  DownKeys.clear();
1367  Sync.Clear();
1368  IsCursorPosRequested = false;
1369 }
const int NO_OWNER
Definition: C4Constants.h:137

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

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

Here is the call graph for this function:
Here is the caller graph for this function:

◆ CompileFunc()

void C4PlayerControl::CompileFunc ( StdCompiler pComp)

Definition at line 989 of file C4PlayerControl.cpp.

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

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

Here is the call graph for this function:

◆ DoMouseInput()

bool C4PlayerControl::DoMouseInput ( uint8_t  mouse_id,
int32_t  mouseevent,
float  game_x,
float  game_y,
float  gui_x,
float  gui_y,
DWORD  flags 
)

Definition at line 1395 of file C4PlayerControl.cpp.

1396 {
1397  // convert moueevent to key code
1398  bool is_down;
1399  C4KeyCodeEx mouseevent_keycode = C4KeyCodeEx::FromC4MC(mouse_id, mouseevent, modifier_flags, &is_down);
1400  // first, try processing it as GUI mouse event. if not assigned, process as Game mous event
1401  // TODO: May route this through Game.DoKeyboardInput instead - would allow assignment of mouse events in CustomConfig
1402  // and would get rid of the Game.KeyboardInput.SetLastKeyExtraData-hack
1403  C4KeyEventData mouseevent_data;
1404  mouseevent_data.iStrength = 100*is_down; // TODO: May get pressure from tablet here
1405  mouseevent_data.vp_x = uint32_t(gui_x);
1406  mouseevent_data.vp_y = uint32_t(gui_y);
1407  mouseevent_data.game_x = uint32_t(game_x);
1408  mouseevent_data.game_y = uint32_t(game_y);
1409  Game.KeyboardInput.SetLastKeyExtraData(mouseevent_data); // ProcessKeyDown/Up queries it from there...
1410  bool result;
1411  if (is_down)
1412  result = ProcessKeyDown(mouseevent_keycode, mouseevent_keycode);
1413  else
1414  result = ProcessKeyUp(mouseevent_keycode, mouseevent_keycode);
1415  return result;
1416 }
C4KeyboardInput & KeyboardInput
Definition: C4Game.h:96
void SetLastKeyExtraData(const C4KeyEventData &data)
static C4KeyCodeEx FromC4MC(int8_t mouse_id, int32_t button, DWORD param, bool *is_down=nullptr)

References C4KeyCodeEx::FromC4MC(), Game, C4KeyEventData::game_x, C4KeyEventData::game_y, C4KeyEventData::iStrength, C4Game::KeyboardInput, C4KeyboardInput::SetLastKeyExtraData(), C4KeyEventData::vp_x, and C4KeyEventData::vp_y.

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

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Execute()

void C4PlayerControl::Execute ( )

Definition at line 1318 of file C4PlayerControl.cpp.

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

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

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ExecuteControlPacket()

void C4PlayerControl::ExecuteControlPacket ( const class C4ControlPlayerControl pCtrl)

Definition at line 1109 of file C4PlayerControl.cpp.

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

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.

Here is the call graph for this function:

◆ GetControlDownState()

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

Definition at line 421 of file C4PlayerControl.h.

422  { return Sync.GetControlDownState(iControl); }

◆ Init()

void C4PlayerControl::Init ( )

Definition at line 983 of file C4PlayerControl.cpp.

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

Referenced by C4Player::Init().

Here is the caller graph for this function:

◆ IsControlDisabled()

bool C4PlayerControl::IsControlDisabled ( int  ctrl) const
inline

Definition at line 435 of file C4PlayerControl.h.

435 { return Sync.IsControlDisabled(ctrl); }
bool IsControlDisabled(int32_t iControl) const

◆ IsGlobal()

bool C4PlayerControl::IsGlobal ( ) const
inline

Definition at line 420 of file C4PlayerControl.h.

420 { return iPlr==-1; }

◆ PrepareInput()

void C4PlayerControl::PrepareInput ( )

Definition at line 1448 of file C4PlayerControl.cpp.

1449 {
1450  if (IsCursorPosRequested)
1451  {
1452  int32_t x, y, game_x, game_y;
1453  // add current cursor pos in GUI coordinates to input
1454  if (GetCurrentPlayerCursorPos(&x, &y, &game_x, &game_y))
1455  {
1456  // CON_CursorPos might not have been defined in definition file
1457  if (ControlDefs.InternalCons.CON_CursorPos != CON_None)
1458  {
1459  C4KeyEventData ev;
1460  ev.iStrength = 0;
1461  ev.vp_x = x; ev.vp_y = y;
1462  ev.game_x = game_x; ev.game_y = game_y;
1463  C4ControlPlayerControl *pControlPacket = new C4ControlPlayerControl(iPlr, CONS_Down, ev);
1465  // make sure it's added at head, because controls that have SendCursorPos=1 set will follow, which will rely
1466  // on the cursor pos being known
1467  Game.Input.AddHead(CID_PlrControl, pControlPacket);
1468  }
1469  }
1470  else
1471  {
1472  // no cursor is known (e.g.: Cursor Clonk dead, etc.). Don't create a control.
1473  // Script will probably fall back to last known cursor pos
1474  }
1475  IsCursorPosRequested = false;
1476  }
1477 }
@ CID_PlrControl
Definition: C4PacketBase.h:163
@ CON_None
void AddHead(C4PacketType eType, C4ControlPacket *pCtrl)
Definition: C4Control.h:81
DECLARE_C4CONTROL_VIRTUALS void AddControl(int32_t iControl, int32_t iTriggerMode)
Definition: C4Control.h:225
C4Control & Input
Definition: C4Game.h:82
struct C4PlayerControlDefs::CInternalCons InternalCons

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

Here is the call graph for this function:
Here is the caller graph for this function:

◆ RegisterKeyset()

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

Definition at line 1371 of file C4PlayerControl.cpp.

1372 {
1373  // setup
1374  pControlSet = pKeyset;
1375  this->iPlr = iPlr;
1376  // register all keys into Game.KeyboardInput creating KeyBindings
1377  if (pControlSet)
1378  {
1379  C4KeyCodeExVec RegularKeys, HoldKeys;
1380  pControlSet->GetTriggerKeys(ControlDefs, &RegularKeys, &HoldKeys);
1381  int32_t idx=0;
1382  for (C4KeyCodeExVec::const_iterator i = RegularKeys.begin(); i != RegularKeys.end(); ++i) AddKeyBinding(*i, false, idx++);
1383  for (C4KeyCodeExVec::const_iterator i = HoldKeys.begin(); i != HoldKeys.end(); ++i) AddKeyBinding(*i, true, idx++);
1384  }
1385 }
std::vector< C4KeyCodeEx > C4KeyCodeExVec
void GetTriggerKeys(const C4PlayerControlDefs &rDefs, C4KeyCodeExVec *pRegularKeys, C4KeyCodeExVec *pHoldKeys) const

References C4PlayerControlAssignmentSet::GetTriggerKeys().

Referenced by C4Player::InitControl().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetControlDisabled()

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

Definition at line 434 of file C4PlayerControl.h.

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