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

Member Enumeration Documentation

◆ anonymous enum

anonymous enum
Enumerator
MaxRecentKeyLookback 
MaxSequenceKeyDelay 

Definition at line 328 of file C4PlayerControl.h.

◆ ControlState

Enumerator
CONS_Down 
CONS_Up 
CONS_Moved 

Definition at line 330 of file C4PlayerControl.h.

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

References C4PlayerControlDef::CompileFunc().

409 { Clear(); }
Here is the call graph for this function:

Member Function Documentation

◆ Clear()

void C4PlayerControl::Clear ( )

Definition at line 1359 of file C4PlayerControl.cpp.

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

Referenced by C4Player::ClearControl().

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

References C4Control::Add(), C4ControlPlayerControl::AddControl(), CID_PlrControl, C4PlayerControlAssignment::CTM_ClearRecentKeys, C4PlayerControlAssignment::CTM_HandleDownStatesOnly, C4KeyCodeEx::deviceId, Game, C4KeyEventData::game_x, C4KeyEventData::game_y, C4PlayerList::Get(), C4PlayerControlAssignment::GetControl(), C4KeyboardInput::GetLastKeyExtraData(), C4PlayerControlAssignment::GetTriggerMode(), C4PlayerControl::CSync::InitDefaults(), C4Game::Input, C4PlayerControlDef::IsAsync(), C4PlayerControlDef::IsHoldKey(), C4KeyCodeEx::IsRepeated(), C4PlayerControlDef::IsSendCursorPos(), C4PlayerControlDef::IsValid(), C4KeyCodeEx::Key, Key_GetMouseEvent(), Key_IsGamepad(), Key_IsMouse(), KEY_MOUSE_Button1, KEY_MOUSE_ButtonMax, C4Game::KeyboardInput, mkNamingAdapt(), C4TimeMilliseconds::Now(), C4Player::pGamepad, Players, C4ControlPlayerControl::SetExtraData(), StdCompiler::Value(), C4KeyEventData::vp_x, and C4KeyEventData::vp_y.

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

References C4Player::Cursor, C4KeyCodeEx::FromC4MC(), Game, C4KeyEventData::game_x, C4KeyEventData::game_y, C4PlayerList::Get(), C4MouseControl::GetLastCursorPos(), C4ViewportList::GetViewport(), C4Object::GetX(), C4Object::GetY(), C4Viewport::GetZoom(), C4GUI::GetZoom(), C4PlayerControlAssignmentSet::HasMouse(), C4KeyEventData::iStrength, C4Game::KeyboardInput, C4Viewport::last_game_draw_cgo, MouseControl, Players, C4KeyboardInput::SetLastKeyExtraData(), C4TargetFacet::TargetX, C4TargetFacet::TargetY, Viewports, C4KeyEventData::vp_x, C4KeyEventData::vp_y, C4Facet::X, and C4Facet::Y.

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

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 }
static C4KeyCodeEx FromC4MC(int8_t mouse_id, int32_t button, DWORD param, bool *is_down=nullptr)
C4Game Game
Definition: C4Globals.cpp:52
C4KeyboardInput & KeyboardInput
Definition: C4Game.h:96
void SetLastKeyExtraData(const C4KeyEventData &data)
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.

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

Referenced by C4Player::ExecuteControl().

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 }
Actions GetAction() const
C4Game Game
Definition: C4Globals.cpp:52
size_t GetCount() const
int32_t GetRepeatDelay() const
int32_t GetInitialRepeatDelay() const
int32_t FrameCounter
Definition: C4Game.h:129
C4TimeMilliseconds tTime
C4ID GetExtraData() const
const C4PlayerControlDef * GetControlByIndex(int32_t idx) const
static C4TimeMilliseconds Now()
const ControlDownState * GetControlDownState(int32_t iControl) const
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.

References C4Player::ActivateMenuMain(), AddDbgRec(), C4GFX_ZoomStep, C4Id2Def(), C4VInt(), C4VNull, C4PropList::Call(), C4PlayerControlDef::CDA_Menu, C4PlayerControlDef::CDA_MenuCancel, C4PlayerControlDef::CDA_MenuDown, C4PlayerControlDef::CDA_MenuLeft, C4PlayerControlDef::CDA_MenuOK, C4PlayerControlDef::CDA_MenuRight, C4PlayerControlDef::CDA_MenuUp, C4PlayerControlDef::CDA_ObjectMenuCancel, C4PlayerControlDef::CDA_ObjectMenuDown, C4PlayerControlDef::CDA_ObjectMenuLeft, C4PlayerControlDef::CDA_ObjectMenuOK, C4PlayerControlDef::CDA_ObjectMenuOKAll, C4PlayerControlDef::CDA_ObjectMenuRight, C4PlayerControlDef::CDA_ObjectMenuSelect, C4PlayerControlDef::CDA_ObjectMenuTextComplete, C4PlayerControlDef::CDA_ObjectMenuUp, C4PlayerControlDef::CDA_Script, C4PlayerControlDef::CDA_ZoomIn, C4PlayerControlDef::CDA_ZoomOut, C4Viewport::ChangeZoom(), COM_MenuClose, COM_MenuDown, COM_MenuEnter, COM_MenuEnterAll, COM_MenuLeft, COM_MenuRight, COM_MenuSelect, COM_MenuShowText, COM_MenuUp, Config, C4Menu::Control(), C4PlayerControlDef::COS_Viewport, C4Player::CountControl(), C4PlayerControlAssignment::CTM_AlwaysUnhandled, C4PlayerControlAssignment::CTM_HandleDownStatesOnly, C4PlayerControlAssignment::CTM_Hold, C4PlayerControlAssignment::CTM_Release, C4Player::Cursor, C4ConfigGeneral::DebugRec, C4Player::Eliminated, C4Game::FrameCounter, Game, C4KeyEventData::game_x, C4KeyEventData::game_y, C4Config::General, C4PlayerList::Get(), C4PlayerControlDef::GetAction(), C4Value::getBool(), C4ControlPlayerControl::GetControlItems(), C4PlayerControlDef::GetCoordinateSpace(), C4PlayerControlDef::GetExtraData(), C4ControlPlayerControl::GetExtraData(), C4AulScriptEngine::GetPropList(), C4ControlPlayerControl::GetState(), C4ViewportList::GetViewport(), C4ControlPlayerControl::ControlItem::iControl, C4Menu::IsActive(), C4PlayerControl::CSync::ControlDownState::IsDown(), C4PlayerControlDef::IsGlobal(), C4PlayerControlDef::IsHoldKey(), C4PlayerControlDef::IsSync(), C4Menu::IsTextProgressing(), C4KeyEventData::iStrength, C4ControlPlayerControl::ControlItem::iTriggerMode, C4KeyEventData::KeyPos_None, C4Player::Menu, C4Object::Menu, C4Player::PCID_DirectCom, Players, PSF_PlayerControl, RCT_PlrCom, ScriptEngine, C4Player::ShowStartup, C4Menu::TryClose(), Viewports, C4KeyEventData::vp_x, and C4KeyEventData::vp_y.

Referenced by C4ControlPlayerSelect::C4ControlPlayerSelect().

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:833
C4ConfigGeneral General
Definition: C4Config.h:251
void AddDbgRec(C4RecordChunkType eType, const void *pData, int iSize)
Definition: C4Record.cpp:32
int32_t DebugRec
Definition: C4Config.h:60
bool IsSync() const
const C4PlayerControlDef * GetControlByIndex(int32_t idx) const
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetControlDownState()

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

Definition at line 422 of file C4PlayerControl.h.

References C4PlayerControlDef::Execute(), and C4PlayerControl::CSync::GetControlDownState().

423  { return Sync.GetControlDownState(iControl); }
const ControlDownState * GetControlDownState(int32_t iControl) const
Here is the call graph for this function:

◆ Init()

void C4PlayerControl::Init ( )

Definition at line 983 of file C4PlayerControl.cpp.

Referenced by C4Player::Init().

984 {
985  // defaultdisabled controls
986  Sync.InitDefaults(ControlDefs);
987 }
void InitDefaults(const C4PlayerControlDefs &ControlDefs)
Here is the caller graph for this function:

◆ IsControlDisabled()

bool C4PlayerControl::IsControlDisabled ( int  ctrl) const
inline

Definition at line 436 of file C4PlayerControl.h.

References C4PlayerControl::CSync::IsControlDisabled().

436 { return Sync.IsControlDisabled(ctrl); }
bool IsControlDisabled(int32_t iControl) const
Here is the call graph for this function:

◆ IsGlobal()

bool C4PlayerControl::IsGlobal ( ) const
inline

Definition at line 421 of file C4PlayerControl.h.

421 { return iPlr==-1; }

◆ PrepareInput()

void C4PlayerControl::PrepareInput ( )

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

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 }
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:

◆ RegisterKeyset()

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

Definition at line 1371 of file C4PlayerControl.cpp.

References FormatString(), C4PlayerControlAssignmentSet::GetTriggerKeys(), KEYSCOPE_Control, and C4CustomKey::PRIO_PlrControl.

Referenced by C4Player::InitControl().

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 }
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:

◆ SetControlDisabled()

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

Definition at line 435 of file C4PlayerControl.h.

References C4PlayerControl::CSync::SetControlDisabled().

435 { return Sync.SetControlDisabled(ctrl, is_disabled); }
bool SetControlDisabled(int32_t iControl, int32_t iVal)
Here is the call graph for this function:

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