SendCursorPos controls issue CON_CursorPos (#289)

stable-5.1
Sven Eberhardt 2010-05-07 15:57:56 +02:00
parent f74913b687
commit 65b73b7177
7 changed files with 92 additions and 25 deletions

View File

@ -454,10 +454,18 @@ public func ObjectControl(int plr, int ctrl, int x, int y, int strength, bool re
{
// Cancel usage
CancelUse();
// the x,y pos is wrong because the local coordinates of the clonk have been substracted
x += GetX();
y += GetY();
// use x/y coordinates from last known cursor pos
var plr_cursor_pos = GetPlayerCursorPos(plr);
if (plr_cursor_pos)
{
x = plr_cursor_pos[0];
y = plr_cursor_pos[1];
}
else
{
// Cursor pos unknown? This can't really happen
x = y = 300;
}
CreateRingMenu(nil,x,y,this);
// CreateRingMenu calls SetMenu(this) in the clonk,
// so after this call menu = the created menu

View File

@ -8,6 +8,7 @@
static const CON_Gamepad_Deadzone = 60;
static CON_VC_Players;
static g_player_cursor_pos; // array of [x,y] pos arrays; indexed by player. last cursor pos as sent by CON_CursorPos
// PlayerControlRelease
// Called by engine whenever a control is issued
@ -177,6 +178,14 @@ global func Control2Player(int plr, int ctrl, int x, int y, int strength, bool r
}
StopSelected(plr);
}
// cursor pos info - store in player values
if (ctrl == CON_CursorPos)
{
if (!g_player_cursor_pos) g_player_cursor_pos = CreateArray(plr+1);
g_player_cursor_pos[plr] = [x, y];
return true;
}
/*
if (ctrl == CON_Test)
{
@ -187,6 +196,13 @@ global func Control2Player(int plr, int ctrl, int x, int y, int strength, bool r
return false;
}
/* return info of last sent CON_CursorPos packet for that player as [x, y] */
global func GetPlayerCursorPos(int plr)
{
if (!g_player_cursor_pos) return 0;
return g_player_cursor_pos[plr];
}
global func StopSelected(int plr)
{
var cursor;

View File

@ -30,6 +30,8 @@
# ObjectMenuDown ObjectMenuUp ObjectMenuLeft ObjectMenuRight
# PlayerMenu
#
# CursorPos
#
# Backpack
#
# with Mouse
@ -193,12 +195,14 @@
GUIName=Use
GUIDesc=Use selected or controlled item
Hold=1
SendCursorPos=1
[ControlDef]
Identifier=UseDelayed
GUIName=Use
GUIDesc=Use selected or controlled item
Hold=1
SendCursorPos=1
[ControlDef]
Identifier=CancelUse
@ -215,12 +219,14 @@
GUIName=Use 2
GUIDesc=Use secondary selected or controlled item
Hold=1
SendCursorPos=1
[ControlDef]
Identifier=UseAltDelayed
GUIName=Use 2
GUIDesc=Use secondary selected or controlled item
Hold=1
SendCursorPos=1
[ControlDef]
Identifier=Backpack
@ -232,6 +238,7 @@
Identifier=Grab
GUIName=Grab
GUIDesc=Grab vehicle
SendCursorPos=1
[ControlDef]
Identifier=Ungrab
@ -257,11 +264,13 @@
Identifier=Interact
GUIName=Interact
GUIDesc=Interact with object in landscape
SendCursorPos=1
[ControlDef]
Identifier=Enter
GUIName=Enter
GUIDesc=Go into the building
SendCursorPos=1
[ControlDef]
Identifier=Exit
@ -432,6 +441,10 @@
Identifier=ObjectMenuDown
Action=ObjectMenuDown
# control sent by engine along controls with SendCursorPos=1
[ControlDef]
Identifier=CursorPos
# Extra buttons...
[ControlDef]

View File

@ -30,6 +30,8 @@
#include <C4Network2Stats.h>
#include <C4MouseControl.h>
#include <C4GamePadCon.h>
#include <C4PlayerList.h>
#include <C4Player.h>
#ifdef _MSC_VER
#pragma warning (disable: 4355)
@ -532,6 +534,10 @@ void C4GameControl::PrepareInput()
// add per-controlframe input
::MouseControl.DoMoveInput();
if (Application.pGamePadControl) Application.pGamePadControl->DoAxisInput();
// per-player input
C4Player *plr; int32_t i=0;
while (plr = ::Players.GetLocalByIndex(i++))
plr->Control.PrepareInput();
}
C4GameControl Control;

View File

@ -100,6 +100,7 @@ void C4PlayerControlDefs::UpdateInternalCons()
InternalCons.CON_ObjectMenuOK = GetControlIndexByIdentifier("ObjectMenuOK");
InternalCons.CON_ObjectMenuOKAll = GetControlIndexByIdentifier("ObjectMenuOKAll");
InternalCons.CON_ObjectMenuCancel = GetControlIndexByIdentifier("ObjectMenuCancel");
InternalCons.CON_CursorPos = GetControlIndexByIdentifier("CursorPos");
}
void C4PlayerControlDefs::Clear()
@ -762,24 +763,10 @@ bool C4PlayerControl::ProcessKeyEvent(const C4KeyCodeEx &pressed_key, const C4Ke
if (pControlDef && pControlDef->IsValid() && !Sync.IsControlDisabled(iControlIndex) && (!fUp || pControlDef->IsHoldKey()))
{
// extra data from key or overwrite by current cursor pos if definition requires it
const C4KeyEventData *pKeyExtraData = &rKeyExtraData;
C4KeyEventData CustomKeyExtraData;
if (pControlDef->IsSendCursorPos())
{
CustomKeyExtraData = rKeyExtraData;
if (!GetCurrentPlayerCursorPos(&(CustomKeyExtraData.x), &(CustomKeyExtraData.y)))
{
// no cursor position is known. set it to -1/-1 so scripters get a hint
CustomKeyExtraData.x = CustomKeyExtraData.y = -1;
}
if (!pControlPacket)
pKeyExtraData = &CustomKeyExtraData;
else
pControlPacket->SetExtraData(CustomKeyExtraData);
}
if (pControlDef->IsAsync() && !pControlPacket)
{
if (ExecuteControl(iControlIndex, fUp, *pKeyExtraData, pAssignment->GetTriggerMode(), pressed_key.IsRepeated()))
if (pControlDef->IsSendCursorPos()) IsCursorPosRequested = true; // async cursor pos request - doesn't really make sense to set this flag for async controls
if (ExecuteControl(iControlIndex, fUp, rKeyExtraData, pAssignment->GetTriggerMode(), pressed_key.IsRepeated()))
return true;
}
else
@ -789,8 +776,10 @@ bool C4PlayerControl::ProcessKeyEvent(const C4KeyCodeEx &pressed_key, const C4Ke
if (pressed_key.IsRepeated()) return false;
// sync control has higher priority - no more async execution then
// build a control packet and add control data instead. even for async controls later in chain, as they may be blocked by a sync handler
if (!pControlPacket) pControlPacket = new C4ControlPlayerControl(iPlr, fUp, *pKeyExtraData);
if (!pControlPacket) pControlPacket = new C4ControlPlayerControl(iPlr, fUp, rKeyExtraData);
pControlPacket->AddControl(iControlIndex, pAssignment->GetTriggerMode());
// sync cursor pos request; pos will be added to control before it is synced/executed
if (pControlDef->IsSendCursorPos()) IsCursorPosRequested = true;
}
}
}
@ -1032,7 +1021,7 @@ void C4PlayerControl::Execute()
if (irk != RecentKeys.begin()) RecentKeys.erase(RecentKeys.begin(), irk);
}
C4PlayerControl::C4PlayerControl() : ControlDefs(Game.PlayerControlDefs), iPlr(-1), pControlSet(NULL)
C4PlayerControl::C4PlayerControl() : ControlDefs(Game.PlayerControlDefs), iPlr(-1), pControlSet(NULL), IsCursorPosRequested(false)
{
}
@ -1045,6 +1034,7 @@ void C4PlayerControl::Clear()
RecentKeys.clear();
DownKeys.clear();
Sync.Clear();
IsCursorPosRequested = false;
}
void C4PlayerControl::RegisterKeyset(int32_t iPlr, C4PlayerControlAssignmentSet *pKeyset)
@ -1155,4 +1145,35 @@ bool C4PlayerControl::GetCurrentPlayerCursorPos(int32_t *x_out, int32_t *y_out)
float gui_y = (screen_y - vp->last_game_draw_cgo.Y) / C4GUI::GetZoom() + vp->last_game_draw_cgo.Y;
*x_out = int32_t(gui_x); *y_out = int32_t(gui_y);
return true;
}
void C4PlayerControl::PrepareInput()
{
if (IsCursorPosRequested)
{
int32_t x, y;
// add current cursor pos in GUI coordinates to input
if (GetCurrentPlayerCursorPos(&x, &y))
{
// CON_CursorPos might not have been defined in definition file
if (ControlDefs.InternalCons.CON_CursorPos != CON_None)
{
C4KeyEventData ev;
ev.iStrength = 0;
ev.x = x;
ev.y = y;
C4ControlPlayerControl *pControlPacket = new C4ControlPlayerControl(iPlr, false, ev);
pControlPacket->AddControl(ControlDefs.InternalCons.CON_CursorPos, C4PlayerControlAssignment::CTM_Default);
// make sure it's added at head, because controls that have SendCursorPos=1 set will follow, which will rely
// on the cursor pos being known
Game.Input.AddHead(CID_PlrControl, pControlPacket);
}
}
else
{
// no cursor is known (e.g.: Cursor Clonk dead, etc.). Don't create a control.
// Script will probably fall back to last known cursor pos
}
IsCursorPosRequested = false;
}
}

View File

@ -93,8 +93,8 @@ private:
public:
struct CInternalCons
{
int32_t CON_ObjectMenuSelect, CON_ObjectMenuOKAll, CON_ObjectMenuOK, CON_ObjectMenuCancel;
CInternalCons() : CON_ObjectMenuSelect(CON_None), CON_ObjectMenuOKAll(CON_None), CON_ObjectMenuOK(CON_None), CON_ObjectMenuCancel(CON_None) {}
int32_t CON_ObjectMenuSelect, CON_ObjectMenuOKAll, CON_ObjectMenuOK, CON_ObjectMenuCancel, CON_CursorPos;
CInternalCons() : CON_ObjectMenuSelect(CON_None), CON_ObjectMenuOKAll(CON_None), CON_ObjectMenuOK(CON_None), CON_ObjectMenuCancel(CON_None), CON_CursorPos(CON_None) {}
} InternalCons;
void UpdateInternalCons();
@ -290,6 +290,7 @@ private:
KeyBindingList KeyBindings; // keys registered into Game.KeyboardInput
C4PlayerControlRecentKeyList RecentKeys; // keys pressed recently; for combinations
C4PlayerControlRecentKeyList DownKeys; // keys currently held down
bool IsCursorPosRequested; // set to true when a SendCursorPos-control had been issued
public:
// sync values
@ -376,6 +377,8 @@ public:
bool SetControlDisabled(int ctrl, bool is_disabled) { return Sync.SetControlDisabled(ctrl, is_disabled); }
bool IsControlDisabled(int ctrl) const { return Sync.IsControlDisabled(ctrl); }
// callback from C4GameControl when the next control packet is finalized
void PrepareInput();
};

View File

@ -315,7 +315,7 @@ void C4PacketList::Add(C4PacketType eType, C4PacketBase *pPkt)
void C4PacketList::AddHead(C4PacketType eType, C4PacketBase *pPkt)
{
Add(new C4IDPacket(eType, pPkt));
AddHead(new C4IDPacket(eType, pPkt));
}
void C4PacketList::Take(C4PacketList &List)