mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-14 02:27:40 -04:00
CWE Directory Reorganization
Rearrange directory structure of CWE to be loosely equivalent to the H'uru Plasma repository. Part 1: Movement of directories and files.
This commit is contained in:
1138
Sources/Plasma/PubUtilLib/plInputCore/plAvatarInputInterface.cpp
Normal file
1138
Sources/Plasma/PubUtilLib/plInputCore/plAvatarInputInterface.cpp
Normal file
File diff suppressed because it is too large
Load Diff
268
Sources/Plasma/PubUtilLib/plInputCore/plAvatarInputInterface.h
Normal file
268
Sources/Plasma/PubUtilLib/plInputCore/plAvatarInputInterface.h
Normal file
@ -0,0 +1,268 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// plAvatarInputInterface //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef plAvatarInputInterface_inc
|
||||
#define plAvatarInputInterface_inc
|
||||
|
||||
#include "plInputInterface.h"
|
||||
#include "../pnInputCore/plInputMap.h"
|
||||
|
||||
#include "hsTemplates.h"
|
||||
|
||||
#include "hsGeometry3.h"
|
||||
#include "hsUtils.h"
|
||||
|
||||
|
||||
//// Class Definition ////////////////////////////////////////////////////////
|
||||
|
||||
class plInputEventMsg;
|
||||
class plMouseEventMsg;
|
||||
class plKeyMap;
|
||||
class plMouseMap;
|
||||
class plKey;
|
||||
class hsStream;
|
||||
class hsResMgr;
|
||||
class plAvatarInputMap;
|
||||
class plPipeline;
|
||||
class plAvatarInputInterface;
|
||||
|
||||
//// Little Input Map Helpers ////////////////////////////////////////////////
|
||||
|
||||
class plAvatarInputMap
|
||||
{
|
||||
protected:
|
||||
|
||||
plAvatarInputInterface *fInterface;
|
||||
|
||||
public:
|
||||
|
||||
plAvatarInputMap();
|
||||
virtual ~plAvatarInputMap();
|
||||
virtual char *GetName() = 0;
|
||||
virtual hsBool IsBasic() { return false; }
|
||||
|
||||
plMouseMap *fMouseMap;
|
||||
UInt32 fButtonState;
|
||||
};
|
||||
|
||||
// Basic avatar mappings, for when the avatar is in "suspended input" mode.
|
||||
class plSuspendedMovementMap : public plAvatarInputMap
|
||||
{
|
||||
public:
|
||||
plSuspendedMovementMap();
|
||||
virtual char *GetName() { return "Suspended Movement"; }
|
||||
};
|
||||
|
||||
// The above, plus movement
|
||||
class plBasicControlMap : public plSuspendedMovementMap
|
||||
{
|
||||
public:
|
||||
plBasicControlMap();
|
||||
virtual char *GetName() { return "Basic"; }
|
||||
virtual hsBool IsBasic() { return true; }
|
||||
|
||||
};
|
||||
// The above, plus movement
|
||||
class plBasicThirdPersonControlMap : public plBasicControlMap
|
||||
{
|
||||
public:
|
||||
plBasicThirdPersonControlMap();
|
||||
virtual char *GetName() { return "Basic Third Person"; }
|
||||
};
|
||||
|
||||
class plLadderControlMap : public plSuspendedMovementMap
|
||||
{
|
||||
public:
|
||||
plLadderControlMap();
|
||||
virtual char *GetName() { return "LadderClimb"; }
|
||||
};
|
||||
|
||||
class plLadderMountMap : public plSuspendedMovementMap
|
||||
{
|
||||
public:
|
||||
plLadderMountMap();
|
||||
virtual char *GetName() { return "Ladder Mount"; }
|
||||
};
|
||||
|
||||
class plLadderDismountMap : public plSuspendedMovementMap
|
||||
{
|
||||
public:
|
||||
plLadderDismountMap();
|
||||
virtual char *GetName() { return "Ladder Dismount"; }
|
||||
};
|
||||
|
||||
|
||||
class plBasicFirstPersonControlMap : public plBasicControlMap
|
||||
{
|
||||
public:
|
||||
plBasicFirstPersonControlMap();
|
||||
virtual char *GetName() { return "Basic First Person"; }
|
||||
};
|
||||
|
||||
// Mouse walk mode
|
||||
class pl3rdWalkMap : public plAvatarInputMap
|
||||
{
|
||||
public:
|
||||
pl3rdWalkMap();
|
||||
virtual ~pl3rdWalkMap();
|
||||
};
|
||||
|
||||
class pl3rdWalkForwardMap : public pl3rdWalkMap
|
||||
{
|
||||
public:
|
||||
pl3rdWalkForwardMap();
|
||||
virtual char *GetName() { return "Walking Forward"; }
|
||||
};
|
||||
|
||||
class pl3rdWalkBackwardMap : public pl3rdWalkMap
|
||||
{
|
||||
public:
|
||||
pl3rdWalkBackwardMap();
|
||||
virtual char *GetName() { return "Walking Backward"; }
|
||||
};
|
||||
|
||||
class pl3rdWalkBackwardLBMap : public pl3rdWalkMap
|
||||
{
|
||||
public:
|
||||
pl3rdWalkBackwardLBMap();
|
||||
virtual char *GetName() { return "Walking Backward (LB)"; }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class plAvatarInputInterface : public plInputInterface
|
||||
{
|
||||
protected:
|
||||
|
||||
UInt32 fCurrentCursor;
|
||||
hsScalar fCursorOpacity, fCursorTimeout, fCursorFadeDelay;
|
||||
|
||||
plAvatarInputMap *fInputMap;
|
||||
|
||||
static plAvatarInputInterface *fInstance;
|
||||
|
||||
virtual hsBool IHandleCtrlCmd( plCtrlCmd *cmd );
|
||||
|
||||
// Gets called once per IUpdate(), just like normal IEval()s
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty );
|
||||
|
||||
void IDeactivateCommand(plMouseInfo *info);
|
||||
void IChangeInputMaps(plAvatarInputMap *newMap);
|
||||
void ISetSuspendMovementMode();
|
||||
void ISetBasicMode();
|
||||
void ISetMouseWalkMode(ControlEventCode code);
|
||||
void ISetLadderMap();
|
||||
void ISetPreLadderMap();
|
||||
void ISetPostLadderMap();
|
||||
|
||||
hsBool IHasControlFlag(int f) const { return fControlFlags.IsBitSet(f); }
|
||||
void IClearControlFlag(int which) { fControlFlags.ClearBit( which ); }
|
||||
|
||||
hsBool CursorInBox(plMouseEventMsg* pMsg, hsPoint4 box);
|
||||
void ClearMouseCursor();
|
||||
void DisableMouseInput() { fMouseDisabled = true; }
|
||||
void EnableMouseInput() { fMouseDisabled = false; }
|
||||
|
||||
void Reset();
|
||||
|
||||
void RequestCursorToWorldPos(hsScalar xPos, hsScalar yPos, int ID);
|
||||
|
||||
hsBitVector fControlFlags;
|
||||
hsBool fMouseDisabled;
|
||||
|
||||
plPipeline* fPipe;
|
||||
int fCursorState;
|
||||
int fCursorPriority;
|
||||
hsBool f3rdPerson;
|
||||
|
||||
public:
|
||||
|
||||
plAvatarInputInterface();
|
||||
virtual ~plAvatarInputInterface();
|
||||
|
||||
void CameraInThirdPerson(hsBool state);
|
||||
|
||||
// Always return true, since the cursor should be representing how we control the avatar
|
||||
virtual hsBool HasInterestingCursorID( void ) const { return true; }
|
||||
virtual UInt32 GetPriorityLevel( void ) const { return kAvatarInputPriority; }
|
||||
virtual UInt32 GetCurrentCursorID( void ) const { return fCurrentCursor; }
|
||||
virtual hsScalar GetCurrentCursorOpacity( void ) const { return fCursorOpacity; }
|
||||
char* GetInputMapName() { return fInputMap ? fInputMap->GetName() : ""; }
|
||||
|
||||
virtual hsBool InterpretInputEvent( plInputEventMsg *pMsg );
|
||||
virtual void MissedInputEvent( plInputEventMsg *pMsg );
|
||||
|
||||
virtual hsBool MsgReceive( plMessage *msg );
|
||||
|
||||
virtual void Init( plInputInterfaceMgr *manager );
|
||||
virtual void Shutdown( void );
|
||||
|
||||
virtual void RestoreDefaultKeyMappings( void );
|
||||
virtual void ClearKeyMap();
|
||||
|
||||
// [dis/en]able mouse commands for avatar movement
|
||||
void SuspendMouseMovement();
|
||||
void EnableMouseMovement();
|
||||
void EnableJump(hsBool val);
|
||||
void EnableForwardMovement(hsBool val);
|
||||
void EnableControl(hsBool val, ControlEventCode code);
|
||||
void ClearLadderMode();
|
||||
void SetLadderMode();
|
||||
void ForceAlwaysRun(hsBool val);
|
||||
|
||||
void SetControlFlag(int f, hsBool val = true) { fControlFlags.SetBit(f, val); }
|
||||
|
||||
void SetCursorFadeDelay( hsScalar delay ) { fCursorFadeDelay = delay; }
|
||||
|
||||
hsBool IsEnterChatModeBound();
|
||||
|
||||
static plAvatarInputInterface *GetInstance( void ) { return fInstance; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif plAvatarInputInterface_inc
|
293
Sources/Plasma/PubUtilLib/plInputCore/plDInputDevice.cpp
Normal file
293
Sources/Plasma/PubUtilLib/plInputCore/plDInputDevice.cpp
Normal file
@ -0,0 +1,293 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
// plDInputDevice.cpp
|
||||
|
||||
#include "hsConfig.h"
|
||||
#include "hsWindows.h"
|
||||
|
||||
#include "plDInputDevice.h"
|
||||
#include "plgDispatch.h"
|
||||
#include "../plMessage/plInputEventMsg.h"
|
||||
#define DIRECTINPUT_VERSION 0x0800
|
||||
#include <dinput.h>
|
||||
//
|
||||
//
|
||||
//
|
||||
// plDInputDevice
|
||||
//
|
||||
//
|
||||
|
||||
plDInputDevice::plDInputDevice() :
|
||||
fX(0.5),
|
||||
fY(0.5)
|
||||
{
|
||||
}
|
||||
|
||||
plDInputDevice::~plDInputDevice()
|
||||
{
|
||||
}
|
||||
|
||||
void plDInputDevice::Update(DIDEVICEOBJECTDATA* js)
|
||||
{
|
||||
switch(js->uAppData)
|
||||
{
|
||||
case A_CONTROL_MOVE:
|
||||
{
|
||||
int i = (int)(js->dwData);
|
||||
if (i <= -1)
|
||||
{
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
pMsg->SetControlCode( B_CONTROL_MOVE_FORWARD );
|
||||
pMsg->SetControlActivated( true );
|
||||
plgDispatch::MsgSend( pMsg );
|
||||
}
|
||||
else
|
||||
if (i >= 1)
|
||||
{
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
pMsg->SetControlCode( B_CONTROL_MOVE_BACKWARD );
|
||||
pMsg->SetControlActivated( true );
|
||||
plgDispatch::MsgSend( pMsg );
|
||||
}
|
||||
else
|
||||
if (i == 0)
|
||||
{
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
pMsg->SetControlCode( B_CONTROL_MOVE_BACKWARD );
|
||||
pMsg->SetControlActivated( false );
|
||||
plgDispatch::MsgSend( pMsg );
|
||||
plControlEventMsg* pMsg2 = TRACKED_NEW plControlEventMsg;
|
||||
pMsg2->SetControlCode( B_CONTROL_MOVE_FORWARD );
|
||||
pMsg2->SetControlActivated( false );
|
||||
plgDispatch::MsgSend( pMsg2 );
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case A_CONTROL_TURN:
|
||||
{
|
||||
int i = (int)(js->dwData);
|
||||
float f = ((float)i) * 0.001f;
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
pMsg->SetControlCode( A_CONTROL_TURN );
|
||||
if (f <= 0.02 && f >= -0.02)
|
||||
pMsg->SetControlActivated( false );
|
||||
else
|
||||
pMsg->SetControlActivated( true );
|
||||
pMsg->SetControlPct(f);
|
||||
plgDispatch::MsgSend( pMsg );
|
||||
}
|
||||
break;
|
||||
case B_CONTROL_ACTION:
|
||||
{
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
pMsg->SetControlCode( B_CONTROL_ACTION );
|
||||
pMsg->SetControlActivated(js->dwData & 0x80);
|
||||
plgDispatch::MsgSend(pMsg);
|
||||
}
|
||||
break;
|
||||
case B_CONTROL_MODIFIER_FAST:
|
||||
{
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
pMsg->SetControlCode( B_CONTROL_MODIFIER_FAST );
|
||||
pMsg->SetControlActivated(js->dwData & 0x80);
|
||||
plgDispatch::MsgSend(pMsg);
|
||||
}
|
||||
break;
|
||||
case B_CONTROL_JUMP:
|
||||
{
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
pMsg->SetControlCode( B_CONTROL_JUMP );
|
||||
pMsg->SetControlActivated(js->dwData & 0x80);
|
||||
plgDispatch::MsgSend(pMsg);
|
||||
}
|
||||
break;
|
||||
case B_CONTROL_STRAFE_LEFT:
|
||||
{
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
pMsg->SetControlCode( B_CONTROL_STRAFE_LEFT );
|
||||
pMsg->SetControlActivated(js->dwData & 0x80);
|
||||
plgDispatch::MsgSend(pMsg);
|
||||
}
|
||||
break;
|
||||
case B_CONTROL_STRAFE_RIGHT:
|
||||
{
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
pMsg->SetControlCode( B_CONTROL_STRAFE_RIGHT);
|
||||
pMsg->SetControlActivated(js->dwData & 0x80);
|
||||
plgDispatch::MsgSend(pMsg);
|
||||
}
|
||||
break;
|
||||
case B_CONTROL_EQUIP:
|
||||
{
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
pMsg->SetControlCode( B_CONTROL_EQUIP );
|
||||
pMsg->SetControlActivated(js->dwData & 0x80);
|
||||
plgDispatch::MsgSend(pMsg);
|
||||
}
|
||||
break;
|
||||
case B_CONTROL_DROP:
|
||||
{
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
pMsg->SetControlCode( B_CONTROL_DROP );
|
||||
pMsg->SetControlActivated(js->dwData & 0x80);
|
||||
plgDispatch::MsgSend(pMsg);
|
||||
}
|
||||
break;
|
||||
case B_CONTROL_MOVE_FORWARD:
|
||||
{
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
pMsg->SetControlCode( B_CONTROL_MOVE_FORWARD );
|
||||
pMsg->SetControlActivated(js->dwData & 0x80);
|
||||
plgDispatch::MsgSend(pMsg);
|
||||
}
|
||||
break;
|
||||
case B_CONTROL_MOVE_BACKWARD:
|
||||
{
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
pMsg->SetControlCode( B_CONTROL_MOVE_BACKWARD );
|
||||
pMsg->SetControlActivated(js->dwData & 0x80);
|
||||
plgDispatch::MsgSend(pMsg);
|
||||
}
|
||||
break;
|
||||
case B_CONTROL_ROTATE_RIGHT:
|
||||
{
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
pMsg->SetControlCode( B_CONTROL_ROTATE_RIGHT);
|
||||
pMsg->SetControlActivated(js->dwData & 0x80);
|
||||
plgDispatch::MsgSend(pMsg);
|
||||
}
|
||||
break;
|
||||
case B_CONTROL_ROTATE_LEFT:
|
||||
{
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
pMsg->SetControlCode( B_CONTROL_ROTATE_LEFT );
|
||||
pMsg->SetControlActivated(js->dwData & 0x80);
|
||||
plgDispatch::MsgSend(pMsg);
|
||||
}
|
||||
break;
|
||||
case B_CONTROL_TURN_TO:
|
||||
{
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
pMsg->SetControlCode( B_CONTROL_TURN_TO );
|
||||
pMsg->SetControlActivated(js->dwData & 0x80);
|
||||
plgDispatch::MsgSend(pMsg);
|
||||
}
|
||||
break;
|
||||
case B_CAMERA_RECENTER:
|
||||
{
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
pMsg->SetControlCode( B_CAMERA_RECENTER );
|
||||
pMsg->SetControlActivated(js->dwData & 0x80);
|
||||
plgDispatch::MsgSend(pMsg);
|
||||
}
|
||||
break;
|
||||
|
||||
case A_CONTROL_MOUSE_X:
|
||||
{
|
||||
int i = (int)(js->dwData);
|
||||
float f = ((float)i) * 0.001f;
|
||||
if (f <= 0.02 && f >= -0.02)
|
||||
{
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
pMsg->SetControlActivated( false );
|
||||
pMsg->SetControlCode(B_CAMERA_ROTATE_DOWN);
|
||||
pMsg->SetControlPct(0);
|
||||
plgDispatch::MsgSend( pMsg );
|
||||
plControlEventMsg* pMsg2 = TRACKED_NEW plControlEventMsg;
|
||||
pMsg2->SetControlActivated( false );
|
||||
pMsg2->SetControlCode(B_CAMERA_ROTATE_UP);
|
||||
pMsg2->SetControlPct(0);
|
||||
plgDispatch::MsgSend( pMsg2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
pMsg->SetControlActivated( true );
|
||||
if (f < 0)
|
||||
pMsg->SetControlCode(B_CAMERA_ROTATE_DOWN);
|
||||
else
|
||||
pMsg->SetControlCode(B_CAMERA_ROTATE_UP);
|
||||
|
||||
pMsg->SetControlPct(f);
|
||||
plgDispatch::MsgSend( pMsg );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case A_CONTROL_MOUSE_Y:
|
||||
{
|
||||
int i = (int)(js->dwData);
|
||||
float f = ((float)i) * 0.001f;
|
||||
if (f <= 0.02 && f >= -0.02)
|
||||
{
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
pMsg->SetControlActivated( false );
|
||||
pMsg->SetControlCode(B_CAMERA_ROTATE_RIGHT);
|
||||
pMsg->SetControlPct(0);
|
||||
plgDispatch::MsgSend( pMsg );
|
||||
plControlEventMsg* pMsg2 = TRACKED_NEW plControlEventMsg;
|
||||
pMsg2->SetControlActivated( false );
|
||||
pMsg2->SetControlCode(B_CAMERA_ROTATE_LEFT);
|
||||
pMsg2->SetControlPct(0);
|
||||
plgDispatch::MsgSend( pMsg2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
pMsg->SetControlActivated( true );
|
||||
if (f < 0)
|
||||
pMsg->SetControlCode(B_CAMERA_ROTATE_RIGHT);
|
||||
else
|
||||
pMsg->SetControlCode(B_CAMERA_ROTATE_LEFT);
|
||||
|
||||
pMsg->SetControlPct(f);
|
||||
plgDispatch::MsgSend( pMsg );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
66
Sources/Plasma/PubUtilLib/plInputCore/plDInputDevice.h
Normal file
66
Sources/Plasma/PubUtilLib/plInputCore/plDInputDevice.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
// plDInputDevice.h
|
||||
|
||||
#ifndef PL_DINPUT_DEVICE_H
|
||||
#define PL_DINPUT_DEVICE_H
|
||||
|
||||
#include "plInputDevice.h"
|
||||
|
||||
struct DIDEVICEOBJECTDATA;
|
||||
|
||||
class plDInputDevice : public plInputDevice
|
||||
{
|
||||
public:
|
||||
plDInputDevice();
|
||||
~plDInputDevice();
|
||||
|
||||
const char* GetInputName() { return "DInput"; }
|
||||
|
||||
virtual void Update(DIDEVICEOBJECTDATA* js);
|
||||
|
||||
protected:
|
||||
hsScalar fX,fY;
|
||||
};
|
||||
|
||||
|
||||
#endif // PL_INPUT_DEVICE_H
|
357
Sources/Plasma/PubUtilLib/plInputCore/plDebugInputInterface.cpp
Normal file
357
Sources/Plasma/PubUtilLib/plInputCore/plDebugInputInterface.cpp
Normal file
@ -0,0 +1,357 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// plDebugInputInterface //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsConfig.h"
|
||||
#include "hsWindows.h"
|
||||
#include "hsTypes.h"
|
||||
#include "plDebugInputInterface.h"
|
||||
|
||||
#include "plInputInterfaceMgr.h"
|
||||
#include "plInputManager.h"
|
||||
#include "plInputDevice.h"
|
||||
|
||||
#include "../plMessage/plInputIfaceMgrMsg.h"
|
||||
#include "../plMessage/plInputEventMsg.h"
|
||||
#include "../pnKeyedObject/plKey.h"
|
||||
#include "../pnInputCore/plKeyMap.h"
|
||||
|
||||
#include "plgDispatch.h"
|
||||
#include "plPipeline.h"
|
||||
#include "hsConfig.h"
|
||||
|
||||
|
||||
plDebugInputInterface *plDebugInputInterface::fInstance = nil;
|
||||
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
plDebugInputInterface::plDebugInputInterface()
|
||||
{
|
||||
fInstance = this;
|
||||
|
||||
// Add our control codes to our control map. Do NOT add the key bindings yet.
|
||||
// Note: HERE is where you specify the actions for each command, i.e. net propagate and so forth.
|
||||
// This part basically declares us master of the bindings for these commands.
|
||||
|
||||
// IF YOU ARE LOOKING TO CHANGE THE DEFAULT KEY BINDINGS, DO NOT LOOK HERE. GO TO
|
||||
// RestoreDefaultKeyMappings()!!!!
|
||||
|
||||
#ifndef PLASMA_EXTERNAL_RELEASE
|
||||
// fControlMap->AddCode( B_CONTROL_MODIFIER_FAST, kControlFlagNormal | kControlFlagNoRepeat );
|
||||
fControlMap->AddCode( B_CAMERA_DRIVE_SPEED_UP, kControlFlagNormal );
|
||||
fControlMap->AddCode( B_CAMERA_DRIVE_SPEED_DOWN, kControlFlagNormal );
|
||||
fControlMap->AddCode( B_CAMERA_MOVE_FORWARD, kControlFlagNormal | kControlFlagNoRepeat );
|
||||
fControlMap->AddCode( B_CAMERA_MOVE_BACKWARD, kControlFlagNormal | kControlFlagNoRepeat );
|
||||
fControlMap->AddCode( B_CAMERA_MOVE_LEFT, kControlFlagNormal | kControlFlagNoRepeat );
|
||||
fControlMap->AddCode( B_CAMERA_MOVE_RIGHT, kControlFlagNormal | kControlFlagNoRepeat );
|
||||
fControlMap->AddCode( B_CAMERA_MOVE_UP, kControlFlagNormal | kControlFlagNoRepeat );
|
||||
fControlMap->AddCode( B_CAMERA_MOVE_DOWN, kControlFlagNormal | kControlFlagNoRepeat );
|
||||
// fControlMap->AddCode( B_TOGGLE_DRIVE_MODE, kControlFlagNormal | kControlFlagNoRepeat | kControlFlagShift );
|
||||
#endif
|
||||
|
||||
// IF YOU ARE LOOKING TO CHANGE THE DEFAULT KEY BINDINGS, DO NOT LOOK HERE. GO TO
|
||||
// RestoreDefaultKeyMappings()!!!!
|
||||
}
|
||||
|
||||
plDebugInputInterface::~plDebugInputInterface()
|
||||
{
|
||||
fInstance = nil;
|
||||
}
|
||||
|
||||
//// Init/Shutdown ///////////////////////////////////////////////////////////
|
||||
|
||||
void plDebugInputInterface::Init( plInputInterfaceMgr *manager )
|
||||
{
|
||||
plInputInterface::Init( manager );
|
||||
}
|
||||
|
||||
void plDebugInputInterface::Shutdown( void )
|
||||
{
|
||||
}
|
||||
|
||||
//// RestoreDefaultKeyMappings ///////////////////////////////////////////////
|
||||
|
||||
void plDebugInputInterface::RestoreDefaultKeyMappings( void )
|
||||
{
|
||||
if( fControlMap == nil )
|
||||
return;
|
||||
|
||||
fControlMap->UnmapAllBindings();
|
||||
|
||||
#ifndef PLASMA_EXTERNAL_RELEASE
|
||||
// fControlMap->BindKey( KEY_SHIFT, B_CONTROL_MODIFIER_FAST );
|
||||
fControlMap->BindKey( plShiftKeyCombo( KEY_EQUAL ), B_CAMERA_DRIVE_SPEED_UP );
|
||||
fControlMap->BindKey( plShiftKeyCombo( KEY_DASH ), B_CAMERA_DRIVE_SPEED_DOWN );
|
||||
fControlMap->BindKey( KEY_W, B_CAMERA_MOVE_FORWARD );
|
||||
fControlMap->BindKey( KEY_S, B_CAMERA_MOVE_BACKWARD );
|
||||
fControlMap->BindKey( KEY_A, B_CAMERA_MOVE_LEFT );
|
||||
fControlMap->BindKey( KEY_D, B_CAMERA_MOVE_RIGHT );
|
||||
fControlMap->BindKey( KEY_I, B_CAMERA_MOVE_UP );
|
||||
fControlMap->BindKey( KEY_K, B_CAMERA_MOVE_DOWN );
|
||||
// fControlMap->BindKey( KEY_C, B_TOGGLE_DRIVE_MODE );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//// IEval ///////////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool plDebugInputInterface::IEval( double secs, hsScalar del, UInt32 dirty )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//// MsgReceive //////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool plDebugInputInterface::MsgReceive( plMessage *msg )
|
||||
{
|
||||
return plInputInterface::MsgReceive(msg);
|
||||
}
|
||||
|
||||
//// cursorinbox /////////////////////////////////////////////////////
|
||||
hsBool plDebugInputInterface::CursorInBox(plMouseEventMsg* pMsg, hsPoint4 box)
|
||||
{
|
||||
return ( pMsg->GetXPos() >= box.fX && pMsg->GetXPos() <= box.fY && pMsg->GetYPos() >= box.fZ && pMsg->GetYPos() <= box.fW );
|
||||
}
|
||||
|
||||
|
||||
//// InterpretInputEvent /////////////////////////////////////////////////////
|
||||
|
||||
hsBool plDebugInputInterface::InterpretInputEvent( plInputEventMsg *pMsg )
|
||||
{
|
||||
hsBool handled = false;
|
||||
|
||||
plMouseEventMsg* pMouseMsg = plMouseEventMsg::ConvertNoRef(pMsg);
|
||||
if (pMouseMsg)
|
||||
{
|
||||
// check for button presses...
|
||||
if (fButtonState & kLeftButtonDown)
|
||||
{
|
||||
fButtonState |= kLeftButtonRepeat;
|
||||
}
|
||||
if (fButtonState & kRightButtonDown)
|
||||
{
|
||||
fButtonState |= kRightButtonRepeat;
|
||||
}
|
||||
if (pMouseMsg->GetButton() == kLeftButtonDown)
|
||||
{
|
||||
fButtonState |= kLeftButtonDown;
|
||||
}
|
||||
if (pMouseMsg->GetButton() == kLeftButtonUp)
|
||||
{
|
||||
fButtonState &= ~kLeftButtonDown;
|
||||
fButtonState &= ~kLeftButtonRepeat;
|
||||
}
|
||||
if (pMouseMsg->GetButton() == kRightButtonDown)
|
||||
{
|
||||
fButtonState |= kRightButtonDown;
|
||||
}
|
||||
if (pMouseMsg->GetButton() == kRightButtonUp)
|
||||
{
|
||||
fButtonState &= ~kRightButtonDown;
|
||||
fButtonState &= ~kRightButtonRepeat;
|
||||
}
|
||||
|
||||
|
||||
for (int i=0; i < fMouseMap.fMap.Count(); i++)
|
||||
{
|
||||
// is this control already set?
|
||||
if (fControlFlags.IsBitSet(fMouseMap.fMap[i]->fCode))
|
||||
{
|
||||
// can we disable this control?
|
||||
hsBool disable = false;
|
||||
|
||||
// can we disable this control based on a button?
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagLeftButton && !(fButtonState & kLeftButtonDown))
|
||||
disable = true;
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagRightButton && !(fButtonState & kRightButtonDown))
|
||||
disable = true;
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagLeftButtonEx && (fButtonState & kLeftButtonRepeat))
|
||||
disable = true;
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagRightButtonEx && (fButtonState & kRightButtonRepeat))
|
||||
disable = true;
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagLeftButtonEx && !(fButtonState & kLeftButtonDown))
|
||||
disable = true;
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagRightButtonEx && !(fButtonState & kRightButtonDown))
|
||||
disable = true;
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagLeftButtonRepeat && !(fButtonState & kLeftButtonDown))
|
||||
disable = true;
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagRightButtonRepeat && !(fButtonState & kRightButtonDown))
|
||||
disable = true;
|
||||
|
||||
// can we disable this control based on the cursor position?
|
||||
if (!CursorInBox(pMouseMsg, fMouseMap.fMap[i]->fBox) && fMouseMap.fMap[i]->fControlFlags & kControlFlagBoxDisable)
|
||||
disable = true;
|
||||
|
||||
if (disable)
|
||||
{
|
||||
plCtrlCmd* pCmd = TRACKED_NEW plCtrlCmd( this );
|
||||
pCmd->fNetPropagateToPlayers = fMouseMap.fMap[i]->fControlFlags & kControlFlagNetPropagate;
|
||||
pCmd->fControlActivated = false;
|
||||
pCmd->fControlCode = fMouseMap.fMap[i]->fCode;
|
||||
fControlFlags.ClearBit(pCmd->fControlCode);
|
||||
fMessageQueue->Append(pCmd);
|
||||
handled = true;
|
||||
continue;
|
||||
}
|
||||
// is it a range control? If so we need to re-send the command
|
||||
|
||||
if ((fMouseMap.fMap[i]->fControlFlags & kControlFlagRangePos) || (fMouseMap.fMap[i]->fControlFlags & kControlFlagRangeNeg))
|
||||
{
|
||||
plCtrlCmd* pCmd = TRACKED_NEW plCtrlCmd( this );
|
||||
pCmd->fControlActivated = true;
|
||||
pCmd->fControlCode = fMouseMap.fMap[i]->fCode;
|
||||
hsScalar pct = 0.0f;
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagRangePos)
|
||||
{
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagXAxisEvent)
|
||||
pct = hsABS((fMouseMap.fMap[i]->fBox.fX - pMouseMsg->GetXPos()) / (fMouseMap.fMap[i]->fBox.fY - fMouseMap.fMap[i]->fBox.fX));
|
||||
else
|
||||
pct = hsABS((fMouseMap.fMap[i]->fBox.fZ - pMouseMsg->GetYPos()) / (fMouseMap.fMap[i]->fBox.fW - fMouseMap.fMap[i]->fBox.fZ));
|
||||
}
|
||||
else
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagRangeNeg)
|
||||
{
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagXAxisEvent)
|
||||
pct = hsABS((fMouseMap.fMap[i]->fBox.fY - pMouseMsg->GetXPos()) / (fMouseMap.fMap[i]->fBox.fY - fMouseMap.fMap[i]->fBox.fX));
|
||||
else
|
||||
pct = hsABS((fMouseMap.fMap[i]->fBox.fW - pMouseMsg->GetYPos()) / (fMouseMap.fMap[i]->fBox.fW - fMouseMap.fMap[i]->fBox.fZ));
|
||||
}
|
||||
pCmd->fPct = pct;
|
||||
if (pct == 1.0f || pct == -1.0f)
|
||||
{
|
||||
delete pCmd;
|
||||
break;
|
||||
}
|
||||
pCmd->fNetPropagateToPlayers = fMouseMap.fMap[i]->fControlFlags & kControlFlagNetPropagate;
|
||||
fMessageQueue->Append(pCmd);
|
||||
}
|
||||
}
|
||||
else // if it is an 'always if in box' command see if it's not in the box
|
||||
if ( (fMouseMap.fMap[i]->fControlFlags & kControlFlagInBox) && (!CursorInBox(pMouseMsg, fMouseMap.fMap[i]->fBox)) )
|
||||
{
|
||||
plCtrlCmd* pCmd = TRACKED_NEW plCtrlCmd( this );
|
||||
pCmd->fControlActivated = false;
|
||||
pCmd->fControlCode = fMouseMap.fMap[i]->fCode;
|
||||
pCmd->fNetPropagateToPlayers = fMouseMap.fMap[i]->fControlFlags & kControlFlagNetPropagate;
|
||||
fMessageQueue->Append(pCmd);
|
||||
continue;
|
||||
}
|
||||
else // the control is not set, see if we should set it.
|
||||
{
|
||||
// is the cursor in the appropriate box?
|
||||
if (CursorInBox(pMouseMsg, fMouseMap.fMap[i]->fBox))
|
||||
{
|
||||
// do we require a button?
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagLeftButton && !(fButtonState & kLeftButtonDown))
|
||||
continue;
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagRightButton && !(fButtonState & kRightButtonDown))
|
||||
continue;
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagLeftButtonEx && (fButtonState & kLeftButtonRepeat))
|
||||
continue;
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagRightButtonEx && (fButtonState & kRightButtonRepeat))
|
||||
continue;
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagLeftButtonRepeat && !(fButtonState & kLeftButtonRepeat))
|
||||
continue;
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagRightButtonRepeat && !(fButtonState & kRightButtonRepeat))
|
||||
continue;
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagLeftButtonEx && !(fButtonState & kLeftButtonDown))
|
||||
continue;
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagRightButtonEx && !(fButtonState & kLeftButtonDown))
|
||||
continue;
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagLeftButtonUp && !(pMouseMsg->GetButton() == kLeftButtonUp))
|
||||
continue;
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagRightButtonUp && !(pMouseMsg->GetButton() == kRightButtonUp))
|
||||
continue;
|
||||
|
||||
// okay, we're in the box and either we don't require a button or our button is pressed.
|
||||
// so set the command as 'enabled'
|
||||
// UNLESS it has kControlFlagInBox, which means we want it sent every frame it is in the box
|
||||
if (!(fMouseMap.fMap[i]->fControlFlags & kControlFlagInBox))
|
||||
fControlFlags.SetBit(fMouseMap.fMap[i]->fCode);
|
||||
// issue the command
|
||||
plCtrlCmd* pCmd = TRACKED_NEW plCtrlCmd( this );
|
||||
pCmd->fControlActivated = true;
|
||||
pCmd->fControlCode = fMouseMap.fMap[i]->fCode;
|
||||
pCmd->fNetPropagateToPlayers = fMouseMap.fMap[i]->fControlFlags & kControlFlagNetPropagate;
|
||||
|
||||
// figure out what percent (if any)
|
||||
hsScalar pct = 0.0f;
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagRangePos)
|
||||
{
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagXAxisEvent)
|
||||
pct = hsABS((fMouseMap.fMap[i]->fBox.fX - pMouseMsg->GetXPos()) / (fMouseMap.fMap[i]->fBox.fY - fMouseMap.fMap[i]->fBox.fX));
|
||||
else
|
||||
pct = hsABS((fMouseMap.fMap[i]->fBox.fZ - pMouseMsg->GetYPos()) / (fMouseMap.fMap[i]->fBox.fW - fMouseMap.fMap[i]->fBox.fZ));
|
||||
}
|
||||
else
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagRangeNeg)
|
||||
{
|
||||
if (fMouseMap.fMap[i]->fControlFlags & kControlFlagXAxisEvent)
|
||||
pct = hsABS((fMouseMap.fMap[i]->fBox.fY - pMouseMsg->GetXPos()) / (fMouseMap.fMap[i]->fBox.fY - fMouseMap.fMap[i]->fBox.fX));
|
||||
else
|
||||
pct = hsABS((fMouseMap.fMap[i]->fBox.fW - pMouseMsg->GetYPos()) / (fMouseMap.fMap[i]->fBox.fW - fMouseMap.fMap[i]->fBox.fZ));
|
||||
}
|
||||
pCmd->fPct = pct;
|
||||
if (pct == 1.0f || pct == -1.0f)
|
||||
{
|
||||
delete pCmd;
|
||||
break;
|
||||
}
|
||||
|
||||
// and add it to the list
|
||||
fMessageQueue->Append(pCmd);
|
||||
handled = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// plDebugInputInterface //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _plDebugInputInterface_h
|
||||
#define _plDebugInputInterface_h
|
||||
|
||||
#include "plInputInterface.h"
|
||||
#include "../pnInputCore/plInputMap.h"
|
||||
|
||||
|
||||
//// Class Definition ////////////////////////////////////////////////////////
|
||||
|
||||
class plMouseEventMsg;
|
||||
|
||||
class plDebugInputInterface : public plInputInterface
|
||||
{
|
||||
protected:
|
||||
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty );
|
||||
hsBool CursorInBox(plMouseEventMsg* pMsg, hsPoint4 box);
|
||||
|
||||
plMouseMap fMouseMap;
|
||||
UInt32 fButtonState;
|
||||
hsBitVector fControlFlags;
|
||||
|
||||
static plDebugInputInterface *fInstance;
|
||||
|
||||
public:
|
||||
|
||||
plDebugInputInterface();
|
||||
virtual ~plDebugInputInterface();
|
||||
|
||||
// Always return false,
|
||||
virtual hsBool HasInterestingCursorID( void ) const { return false; }
|
||||
virtual UInt32 GetPriorityLevel( void ) const { return kDebugCmdPrioity; }
|
||||
virtual void RestoreDefaultKeyMappings( void );
|
||||
virtual UInt32 GetCurrentCursorID( void ) const { return 0; }
|
||||
|
||||
virtual hsBool InterpretInputEvent( plInputEventMsg *pMsg );
|
||||
|
||||
virtual hsBool MsgReceive( plMessage *msg );
|
||||
|
||||
virtual void Init( plInputInterfaceMgr *manager );
|
||||
virtual void Shutdown( void );
|
||||
|
||||
static plDebugInputInterface *GetInstance( void ) { return fInstance; }
|
||||
};
|
||||
|
||||
|
||||
#endif //_plDebugInputInterface_h
|
56
Sources/Plasma/PubUtilLib/plInputCore/plInputCoreCreatable.h
Normal file
56
Sources/Plasma/PubUtilLib/plInputCore/plInputCoreCreatable.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
|
||||
#ifndef plInputCoreCreatable_inc
|
||||
#define plInputCoreCreatable_inc
|
||||
|
||||
#include "../pnFactory/plCreator.h"
|
||||
|
||||
#include "plInputManager.h"
|
||||
|
||||
REGISTER_CREATABLE(plInputManager);
|
||||
|
||||
#include "plInputInterfaceMgr.h"
|
||||
|
||||
REGISTER_CREATABLE(plInputInterfaceMgr);
|
||||
|
||||
#endif // plInputCoreCreatable_inc
|
932
Sources/Plasma/PubUtilLib/plInputCore/plInputDevice.cpp
Normal file
932
Sources/Plasma/PubUtilLib/plInputCore/plInputDevice.cpp
Normal file
@ -0,0 +1,932 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
// plInputDevice.cpp
|
||||
//#include "STRING"
|
||||
|
||||
#include "hsConfig.h"
|
||||
#include "hsWindows.h"
|
||||
|
||||
#include "plInputDevice.h"
|
||||
#include "plInputManager.h"
|
||||
#include "plAvatarInputInterface.h"
|
||||
#include "../plMessage/plInputEventMsg.h"
|
||||
#include "../pnMessage/plTimeMsg.h"
|
||||
#include "hsUtils.h"
|
||||
#include "plgDispatch.h"
|
||||
|
||||
#include "../plPipeline/plPlates.h"
|
||||
#include "../plPipeline/plDebugText.h"
|
||||
#include "../plGImage/plMipmap.h"
|
||||
|
||||
#include "hsWindows.h"
|
||||
#include "../NucleusLib/inc/plPipeline.h"
|
||||
|
||||
// The resolution that uses the base size of the cursor.
|
||||
// All other resolutions will scale the cursor size to keep the same physical size.
|
||||
#define BASE_WIDTH 1024
|
||||
#define BASE_HEIGHT 768
|
||||
|
||||
plKeyboardDevice* plKeyboardDevice::fInstance = nil;
|
||||
bool plKeyboardDevice::fKeyboardState[256];
|
||||
hsBool plKeyboardDevice::fIgnoreCapsLock = false;
|
||||
hsBool plKeyboardDevice::fKeyIsDeadKey = false;
|
||||
|
||||
plKeyboardDevice::plKeyboardDevice() :
|
||||
fShiftKeyDown(false),
|
||||
fCapsLockKeyDown(false),
|
||||
fAltKeyDown(false),
|
||||
fCtrlKeyDown(false),
|
||||
fCapsLockLock(false),
|
||||
fPrevNumLockOn(false),
|
||||
fControlMode(STANDARD_MODE)
|
||||
{
|
||||
fInstance = this;
|
||||
fStartedUpWithNumLockOn = ((GetKeyState(VK_NUMLOCK) & 1) != 0);
|
||||
InitKeyboardState();
|
||||
}
|
||||
|
||||
plKeyboardDevice::~plKeyboardDevice()
|
||||
{
|
||||
if (fStartedUpWithNumLockOn)
|
||||
ForceNumLock(true);
|
||||
}
|
||||
|
||||
void plKeyboardDevice::InitKeyboardState()
|
||||
{
|
||||
static bool initialized = false;
|
||||
if (!initialized)
|
||||
{
|
||||
for (unsigned int i = 0; i < 256; ++i)
|
||||
plKeyboardDevice::fKeyboardState[i] = false;
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void plKeyboardDevice::ReleaseAllKeys()
|
||||
{
|
||||
// send a key-up message for all "normal" keys
|
||||
for (unsigned int i = 0; i < 256; ++i)
|
||||
{
|
||||
if ((i == KEY_SHIFT) || (i == KEY_CTRL) || (i == KEY_CAPSLOCK))
|
||||
continue; // these are handled slightly differently
|
||||
|
||||
if (fKeyboardState[i])
|
||||
{
|
||||
fKeyboardState[i] = false;
|
||||
|
||||
// fake a key-up command
|
||||
plKeyEventMsg* pMsg = TRACKED_NEW plKeyEventMsg;
|
||||
pMsg->SetKeyCode( (plKeyDef)i );
|
||||
pMsg->SetKeyDown( false );
|
||||
pMsg->SetShiftKeyDown( fShiftKeyDown );
|
||||
pMsg->SetCtrlKeyDown( fCtrlKeyDown );
|
||||
pMsg->SetCapsLockKeyDown( fCapsLockLock );
|
||||
pMsg->SetRepeat( false );
|
||||
plgDispatch::MsgSend( pMsg );
|
||||
}
|
||||
}
|
||||
|
||||
// send key messages for shift and ctrl if necessary because the keys above need to have
|
||||
// the proper states of the shift and ctrl keys sent with their messages, and our internal
|
||||
// flags for these keys need to be cleared. We don't send a key-up message for caps lock
|
||||
// because it doesn't really operate like every other key on the keyboard
|
||||
if (fKeyboardState[KEY_SHIFT])
|
||||
{
|
||||
fKeyboardState[KEY_SHIFT] = false;
|
||||
fShiftKeyDown = false;
|
||||
|
||||
plKeyEventMsg* pMsg = TRACKED_NEW plKeyEventMsg;
|
||||
pMsg->SetKeyCode( KEY_SHIFT );
|
||||
pMsg->SetKeyDown( false );
|
||||
pMsg->SetShiftKeyDown( false );
|
||||
pMsg->SetCtrlKeyDown( false );
|
||||
pMsg->SetCapsLockKeyDown( fCapsLockLock );
|
||||
pMsg->SetRepeat( false );
|
||||
plgDispatch::MsgSend( pMsg );
|
||||
}
|
||||
if (fKeyboardState[KEY_CTRL])
|
||||
{
|
||||
fKeyboardState[KEY_CTRL] = false;
|
||||
fCtrlKeyDown = false;
|
||||
|
||||
plKeyEventMsg* pMsg = TRACKED_NEW plKeyEventMsg;
|
||||
pMsg->SetKeyCode( KEY_CTRL );
|
||||
pMsg->SetKeyDown( false );
|
||||
pMsg->SetShiftKeyDown( false );
|
||||
pMsg->SetCtrlKeyDown( false );
|
||||
pMsg->SetCapsLockKeyDown( fCapsLockLock );
|
||||
pMsg->SetRepeat( false );
|
||||
plgDispatch::MsgSend( pMsg );
|
||||
}
|
||||
}
|
||||
|
||||
hsBool plKeyboardDevice::IsCapsLockKeyOn()
|
||||
{
|
||||
return fCapsLockLock;
|
||||
}
|
||||
|
||||
void plKeyboardDevice::Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
void plKeyboardDevice::ForceNumLock(hsBool on)
|
||||
{
|
||||
if (on != ((GetKeyState(VK_NUMLOCK) & 1) != 0))
|
||||
{
|
||||
OSVERSIONINFO info;
|
||||
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
GetVersionEx(&info);
|
||||
if (info.dwPlatformId == VER_PLATFORM_WIN32_NT)
|
||||
{
|
||||
keybd_event( VK_NUMLOCK, 0, KEYEVENTF_EXTENDEDKEY | 0, 0 );
|
||||
keybd_event( VK_NUMLOCK, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt8 keyState[256];
|
||||
GetKeyboardState(keyState);
|
||||
keyState[VK_NUMLOCK] = keyState[VK_NUMLOCK] ^ 1;
|
||||
SetKeyboardState(keyState);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //HS_BUILD_FOR_WIN32
|
||||
|
||||
void plKeyboardDevice::HandleKeyEvent(plOSMsg message, plKeyDef key, bool bKeyDown, hsBool bKeyRepeat)
|
||||
{
|
||||
// update the internal keyboard state
|
||||
unsigned int keyCode = (unsigned int)key;
|
||||
if ((key >= 0) && (key < 256))
|
||||
fKeyboardState[key] = bKeyDown;
|
||||
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
if (key == VK_NUMLOCK && bKeyDown)
|
||||
{
|
||||
ForceNumLock(false);
|
||||
}
|
||||
#endif // HS_BUILD_FOR_WIN32
|
||||
|
||||
if (key == KEY_SHIFT)
|
||||
{
|
||||
fShiftKeyDown = bKeyDown;
|
||||
// return;
|
||||
}
|
||||
if (key == KEY_CTRL)
|
||||
{
|
||||
fCtrlKeyDown = bKeyDown;
|
||||
// return;
|
||||
}
|
||||
if (key == KEY_CAPSLOCK)
|
||||
{
|
||||
// Keyboards toggle the light on key-down, so I'm going with that.
|
||||
if (bKeyDown && !bKeyRepeat)
|
||||
{
|
||||
fCapsLockLock = !fCapsLockLock;
|
||||
plAvatarInputInterface::GetInstance()->ForceAlwaysRun(fCapsLockLock);
|
||||
}
|
||||
}
|
||||
|
||||
// send a key event...
|
||||
plKeyEventMsg* pMsg = TRACKED_NEW plKeyEventMsg;
|
||||
pMsg->SetKeyCode( key );
|
||||
pMsg->SetKeyDown( bKeyDown );
|
||||
pMsg->SetShiftKeyDown( fShiftKeyDown );
|
||||
pMsg->SetCtrlKeyDown( fCtrlKeyDown );
|
||||
pMsg->SetCapsLockKeyDown( fCapsLockLock );
|
||||
pMsg->SetRepeat(bKeyRepeat);
|
||||
plgDispatch::MsgSend( pMsg );
|
||||
}
|
||||
|
||||
void plKeyboardDevice::HandleWindowActivate(bool bActive, HWND hWnd)
|
||||
{
|
||||
if (bActive)
|
||||
{
|
||||
fCtrlKeyDown = false;
|
||||
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
{
|
||||
fPrevNumLockOn = ((GetKeyState(VK_NUMLOCK) & 1) != 0);
|
||||
ForceNumLock(false);
|
||||
hsBool oldLock = fCapsLockLock;
|
||||
fCapsLockLock = (GetKeyState(KEY_CAPSLOCK) & 1) != 0;
|
||||
if (fCapsLockLock != oldLock)
|
||||
plAvatarInputInterface::GetInstance()->ForceAlwaysRun(fCapsLockLock);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
ReleaseAllKeys(); // send key-up events for everything since we're losing focus
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
{
|
||||
if (fPrevNumLockOn)
|
||||
ForceNumLock(true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//// KeyEventToChar //////////////////////////////////////////////////////////
|
||||
// Translate a Plasma key event to an actual char
|
||||
char plKeyboardDevice::KeyEventToChar( plKeyEventMsg *msg )
|
||||
{
|
||||
short code = msg->GetKeyCode();
|
||||
char c = 0;
|
||||
unsigned char *kbState = TRACKED_NEW unsigned char[256];
|
||||
unsigned char *buffer = TRACKED_NEW unsigned char[256];
|
||||
UINT scanCode;
|
||||
int retVal;
|
||||
|
||||
buffer[0] = 0;
|
||||
|
||||
switch( code )
|
||||
{
|
||||
case KEY_A:
|
||||
case KEY_B:
|
||||
case KEY_C:
|
||||
case KEY_D:
|
||||
case KEY_E:
|
||||
case KEY_F:
|
||||
case KEY_G:
|
||||
case KEY_H:
|
||||
case KEY_I:
|
||||
case KEY_J:
|
||||
case KEY_K:
|
||||
case KEY_L:
|
||||
case KEY_M:
|
||||
case KEY_N:
|
||||
case KEY_O:
|
||||
case KEY_P:
|
||||
case KEY_Q:
|
||||
case KEY_R:
|
||||
case KEY_S:
|
||||
case KEY_T:
|
||||
case KEY_U:
|
||||
case KEY_V:
|
||||
case KEY_W:
|
||||
case KEY_X:
|
||||
case KEY_Y:
|
||||
case KEY_Z:
|
||||
case KEY_1:
|
||||
case KEY_2:
|
||||
case KEY_3:
|
||||
case KEY_4:
|
||||
case KEY_5:
|
||||
case KEY_6:
|
||||
case KEY_7:
|
||||
case KEY_8:
|
||||
case KEY_9:
|
||||
case KEY_0:
|
||||
case KEY_TILDE:
|
||||
case KEY_COMMA:
|
||||
case KEY_PERIOD:
|
||||
case KEY_LBRACKET:
|
||||
case KEY_RBRACKET:
|
||||
case KEY_BACKSLASH:
|
||||
case KEY_SLASH:
|
||||
case KEY_DASH:
|
||||
case KEY_EQUAL:
|
||||
case KEY_SEMICOLON:
|
||||
case KEY_QUOTE:
|
||||
// let windows translate everything for us!
|
||||
scanCode = MapVirtualKeyEx(code,0,GetKeyboardLayout(0));
|
||||
GetKeyboardState(kbState);
|
||||
if (fIgnoreCapsLock)
|
||||
kbState[KEY_CAPSLOCK] = 0; // clear the caps lock key
|
||||
retVal = ToAsciiEx(code,scanCode,kbState,(unsigned short*)buffer,0,GetKeyboardLayout(0));
|
||||
if (retVal == 2)
|
||||
{
|
||||
if ((buffer[0] == buffer[1]) && (!fKeyIsDeadKey))
|
||||
{
|
||||
// it's actually a dead key, since the previous key wasn't a dead key
|
||||
c = (char)buffer[0];
|
||||
fKeyIsDeadKey = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = (char)buffer[1]; // it was an untranslated dead key, so copy the unconverted key
|
||||
fKeyIsDeadKey = false;
|
||||
}
|
||||
}
|
||||
else if (retVal == 0)
|
||||
c = 0; // it's invalid
|
||||
else
|
||||
{
|
||||
c = (char)buffer[0];
|
||||
if (retVal < 0) // the key was a dead key
|
||||
fKeyIsDeadKey = true;
|
||||
else
|
||||
fKeyIsDeadKey = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY_ESCAPE: c = 27; break;
|
||||
case KEY_TAB: c = '\t'; break;
|
||||
case KEY_BACKSPACE: c = 8; break;
|
||||
case KEY_ENTER: c = '\n'; break;
|
||||
case KEY_SPACE: c = ' '; break;
|
||||
|
||||
// numlock on numbers
|
||||
case KEY_NUMPAD0: c = '0'; break;
|
||||
case KEY_NUMPAD1: c = '1'; break;
|
||||
case KEY_NUMPAD2: c = '2'; break;
|
||||
case KEY_NUMPAD3: c = '3'; break;
|
||||
case KEY_NUMPAD4: c = '4'; break;
|
||||
case KEY_NUMPAD5: c = '5'; break;
|
||||
case KEY_NUMPAD6: c = '6'; break;
|
||||
case KEY_NUMPAD7: c = '7'; break;
|
||||
case KEY_NUMPAD8: c = '8'; break;
|
||||
case KEY_NUMPAD9: c = '9'; break;
|
||||
|
||||
// everything else
|
||||
default:
|
||||
c = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
delete [] kbState;
|
||||
delete [] buffer;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
// plMouseDevice
|
||||
//
|
||||
//
|
||||
|
||||
bool plMouseDevice::bMsgAlways = true;
|
||||
bool plMouseDevice::bCursorHidden = false;
|
||||
bool plMouseDevice::bCursorOverride = false;
|
||||
bool plMouseDevice::bInverted = false;
|
||||
hsScalar plMouseDevice::fWidth = BASE_WIDTH;
|
||||
hsScalar plMouseDevice::fHeight = BASE_HEIGHT;
|
||||
plMouseDevice* plMouseDevice::fInstance = 0;
|
||||
|
||||
plMouseDevice::plMouseDevice()
|
||||
{
|
||||
fXPos = 0;
|
||||
fYPos = 0;
|
||||
fCursorID = CURSOR_UP;
|
||||
fButtonState = 0;
|
||||
fOpacity = 1.f;
|
||||
|
||||
fCursor = nil;
|
||||
CreateCursor( fCursorID );
|
||||
plMouseDevice::fInstance = this;
|
||||
fXMsg = nil;
|
||||
fYMsg = nil;
|
||||
fB2Msg = nil;
|
||||
|
||||
fLeftBMsg[0] = nil;
|
||||
fLeftBMsg[1] = nil;
|
||||
fRightBMsg[0] = nil;
|
||||
fRightBMsg[1] = nil;
|
||||
fMiddleBMsg[0] = nil;
|
||||
fMiddleBMsg[1] = nil;
|
||||
|
||||
}
|
||||
|
||||
plMouseDevice::~plMouseDevice()
|
||||
{
|
||||
plPlateManager::Instance().DestroyPlate( fCursor );
|
||||
fCursor = nil;
|
||||
plMouseDevice::fInstance = nil;
|
||||
}
|
||||
void plMouseDevice::SetDisplayResolution(hsScalar Width, hsScalar Height)
|
||||
{
|
||||
fWidth = Width;
|
||||
fHeight = Height;
|
||||
IUpdateCursorSize();
|
||||
}
|
||||
|
||||
void plMouseDevice::CreateCursor( char* cursor )
|
||||
{
|
||||
if( fCursor == nil )
|
||||
{
|
||||
plPlateManager::Instance().CreatePlate( &fCursor );
|
||||
fCursor->CreateFromResource(cursor);
|
||||
}
|
||||
else
|
||||
{
|
||||
fCursor->ReloadFromResource(cursor);
|
||||
}
|
||||
fCursor->SetPosition( 0, 0, 0 );
|
||||
IUpdateCursorSize();
|
||||
|
||||
fCursor->SetVisible( true );
|
||||
fCursor->SetOpacity( fOpacity );
|
||||
}
|
||||
|
||||
void plMouseDevice::IUpdateCursorSize()
|
||||
{
|
||||
if(fCursor)
|
||||
{
|
||||
// set the size of the cursor based on resolution.
|
||||
fCursor->SetSize( 2*fCursor->GetMipmap()->GetWidth()/fWidth, 2*fCursor->GetMipmap()->GetHeight()/fHeight );
|
||||
}
|
||||
}
|
||||
|
||||
void plMouseDevice::AddNameToCursor(const char* name)
|
||||
{
|
||||
if (fInstance && name)
|
||||
{
|
||||
plDebugText &txt = plDebugText::Instance();
|
||||
txt.DrawString(fInstance->fWXPos + 12 ,fInstance->fWYPos - 7,name);
|
||||
}
|
||||
}
|
||||
void plMouseDevice::AddCCRToCursor()
|
||||
{
|
||||
if (fInstance)
|
||||
{
|
||||
plDebugText &txt = plDebugText::Instance();
|
||||
txt.DrawString(fInstance->fWXPos + 12, fInstance->fWYPos - 17, "CCR");
|
||||
}
|
||||
}
|
||||
void plMouseDevice::AddIDNumToCursor(UInt32 idNum)
|
||||
{
|
||||
if (fInstance && idNum)
|
||||
{
|
||||
plDebugText &txt = plDebugText::Instance();
|
||||
char str[256];
|
||||
sprintf(str, "%d",idNum);
|
||||
txt.DrawString(fInstance->fWXPos + 12 ,fInstance->fWYPos + 3,str);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void plMouseDevice::SetCursorX(hsScalar x)
|
||||
{
|
||||
/// Set the cursor position
|
||||
if( fCursor == nil && !plMouseDevice::bCursorHidden)
|
||||
CreateCursor( fCursorID );
|
||||
|
||||
if (fCursor)
|
||||
fCursor->SetPosition( ( x * 2.0f ) - 1.0f,
|
||||
( fYPos * 2.0f ) - 1.0f );
|
||||
|
||||
// plDebugText &txt = plDebugText::Instance();
|
||||
// txt.DrawString(fWXPos + 20,fWYPos - 5,"test");
|
||||
|
||||
}
|
||||
void plMouseDevice::SetCursorY(hsScalar y)
|
||||
{
|
||||
/// Set the cursor position
|
||||
if( fCursor == nil && !plMouseDevice::bCursorHidden)
|
||||
CreateCursor( fCursorID );
|
||||
|
||||
if (fCursor)
|
||||
fCursor->SetPosition( ( fXPos * 2.0f ) - 1.0f,
|
||||
( y * 2.0f ) - 1.0f );
|
||||
|
||||
// plDebugText &txt = plDebugText::Instance();
|
||||
// txt.DrawString(fWXPos + 20,fWYPos - 10,"test");
|
||||
|
||||
}
|
||||
|
||||
|
||||
void plMouseDevice::HideCursor(hsBool override)
|
||||
{
|
||||
if( fInstance->fCursor != nil )
|
||||
fInstance->fCursor->SetVisible( false );
|
||||
|
||||
plMouseDevice::bCursorOverride = (override != 0);
|
||||
plMouseDevice::bCursorHidden = true;
|
||||
|
||||
}
|
||||
|
||||
void plMouseDevice::ShowCursor(hsBool override)
|
||||
{
|
||||
if( !plMouseDevice::bCursorHidden )
|
||||
return;
|
||||
if (plMouseDevice::bCursorOverride && !override)
|
||||
return;
|
||||
|
||||
plMouseDevice::bCursorHidden = false;
|
||||
plMouseDevice::bCursorOverride = false;
|
||||
|
||||
if( fInstance->fCursor == nil )
|
||||
fInstance->CreateCursor( fInstance->fCursorID );
|
||||
fInstance->fCursor->SetVisible( true );
|
||||
}
|
||||
|
||||
void plMouseDevice::NewCursor(char* cursor)
|
||||
{
|
||||
fInstance->fCursorID = cursor;
|
||||
fInstance->CreateCursor(cursor);
|
||||
fInstance->SetCursorX(fInstance->GetCursorX());
|
||||
fInstance->SetCursorY(fInstance->GetCursorY());
|
||||
|
||||
if (!plMouseDevice::bCursorHidden)
|
||||
fInstance->fCursor->SetVisible( true );
|
||||
}
|
||||
|
||||
void plMouseDevice::SetCursorOpacity( hsScalar opacity )
|
||||
{
|
||||
fInstance->fOpacity = opacity;
|
||||
if( fInstance->fCursor != nil )
|
||||
fInstance->fCursor->SetOpacity( opacity );
|
||||
}
|
||||
|
||||
hsBool plMouseDevice::MsgReceive(plMessage* msg)
|
||||
{
|
||||
plEvalMsg* pEMsg = plEvalMsg::ConvertNoRef(msg);
|
||||
if (pEMsg)
|
||||
{
|
||||
if (fXMsg)
|
||||
{
|
||||
plgDispatch::MsgSend(fXMsg);
|
||||
fXMsg = nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
plMouseEventMsg* pMsg = TRACKED_NEW plMouseEventMsg;
|
||||
pMsg->SetXPos( fXPos );
|
||||
pMsg->SetYPos( fYPos );
|
||||
pMsg->SetDX(0);
|
||||
pMsg->SetDY(0);
|
||||
plgDispatch::MsgSend(pMsg);
|
||||
}
|
||||
|
||||
if (fYMsg)
|
||||
{
|
||||
plgDispatch::MsgSend(fYMsg);
|
||||
fYMsg = nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
plMouseEventMsg* pMsg = TRACKED_NEW plMouseEventMsg;
|
||||
pMsg->SetXPos( fXPos );
|
||||
pMsg->SetYPos( fYPos );
|
||||
pMsg->SetDX(0);
|
||||
pMsg->SetDY(0);
|
||||
plgDispatch::MsgSend(pMsg);
|
||||
}
|
||||
|
||||
if( fB2Msg )
|
||||
{
|
||||
fB2Msg->Send();
|
||||
fB2Msg = nil;
|
||||
}
|
||||
|
||||
// look for mouse button events in the queues to be sent now
|
||||
// ...Left mouse button
|
||||
if ( fLeftBMsg[0] != nil)
|
||||
{
|
||||
fLeftBMsg[0]->Send();
|
||||
// slide queue elements over... get 'em on the next eval
|
||||
fLeftBMsg[0] = fLeftBMsg[1];
|
||||
fLeftBMsg[1] = nil;
|
||||
}
|
||||
// ...Right mouse button
|
||||
if ( fRightBMsg[0] != nil)
|
||||
{
|
||||
fRightBMsg[0]->Send();
|
||||
// slide queue elements over... get 'em on the next eval
|
||||
fRightBMsg[0] = fRightBMsg[1];
|
||||
fRightBMsg[1] = nil;
|
||||
}
|
||||
// ...middle mouse button
|
||||
if ( fMiddleBMsg[0] != nil)
|
||||
{
|
||||
fMiddleBMsg[0]->Send();
|
||||
// slide queue elements over... get 'em on the next eval
|
||||
fMiddleBMsg[0] = fMiddleBMsg[1];
|
||||
fMiddleBMsg[1] = nil;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
plIMouseXEventMsg* pXMsg = plIMouseXEventMsg::ConvertNoRef(msg);
|
||||
if (pXMsg)
|
||||
{
|
||||
// send a mouse event
|
||||
plMouseEventMsg* pMsg = TRACKED_NEW plMouseEventMsg;
|
||||
if (pXMsg->fX == 999)
|
||||
pMsg->SetXPos( fXPos + 0.001f );
|
||||
else
|
||||
if (pXMsg->fX == -999)
|
||||
pMsg->SetXPos( fXPos - 0.001f );
|
||||
else
|
||||
pMsg->SetXPos(pXMsg->fX);
|
||||
pMsg->SetYPos( fYPos );
|
||||
pMsg->SetDX( ( fXPos - pMsg->GetXPos()) );
|
||||
pMsg->SetDY(0);
|
||||
|
||||
if (pMsg->GetDX() == 0.0f && !plMouseDevice::bMsgAlways)
|
||||
{
|
||||
delete pMsg;
|
||||
return true;
|
||||
}
|
||||
if (fXMsg)
|
||||
delete fXMsg;
|
||||
fXMsg = pMsg;
|
||||
|
||||
if (pXMsg->fX == 999)
|
||||
fXPos += 0.01;
|
||||
else
|
||||
if (pXMsg->fX == -999)
|
||||
fXPos -= 0.01;
|
||||
else
|
||||
fXPos = pXMsg->fX;
|
||||
|
||||
SetCursorX(fXPos);
|
||||
fWXPos = pXMsg->fWx;
|
||||
return true;
|
||||
}
|
||||
|
||||
plIMouseYEventMsg* pYMsg = plIMouseYEventMsg::ConvertNoRef(msg);
|
||||
if (pYMsg)
|
||||
{
|
||||
// send a mouse event
|
||||
plMouseEventMsg* pMsg = TRACKED_NEW plMouseEventMsg;
|
||||
pMsg->SetXPos( fXPos );
|
||||
if (pYMsg->fY == 999)
|
||||
pMsg->SetYPos( fYPos + 0.01f );
|
||||
else
|
||||
if (pYMsg->fY == -999)
|
||||
pMsg->SetYPos( fYPos - 0.01f );
|
||||
else
|
||||
pMsg->SetYPos(pYMsg->fY);
|
||||
pMsg->SetDX(0);
|
||||
pMsg->SetDY(fYPos - pMsg->GetYPos());
|
||||
|
||||
if (pMsg->GetDY() == 0.0f && !plMouseDevice::bMsgAlways)
|
||||
{
|
||||
delete pMsg;
|
||||
return true;
|
||||
}
|
||||
if (fYMsg)
|
||||
delete fYMsg;
|
||||
fYMsg = pMsg;
|
||||
|
||||
if (pYMsg->fY == 999)
|
||||
fYPos += 0.01;
|
||||
else
|
||||
if (pYMsg->fY == -999)
|
||||
fYPos -= 0.01;
|
||||
else
|
||||
fYPos = pYMsg->fY;
|
||||
|
||||
fWYPos = pYMsg->fWy;
|
||||
SetCursorY(fYPos);
|
||||
|
||||
return true;
|
||||
}
|
||||
plIMouseBEventMsg* pBMsg = plIMouseBEventMsg::ConvertNoRef(msg);
|
||||
if (pBMsg)
|
||||
{
|
||||
|
||||
// send a mouse event
|
||||
plMouseEventMsg* pMsg = TRACKED_NEW plMouseEventMsg;
|
||||
pMsg->SetXPos( fXPos );
|
||||
pMsg->SetYPos( fYPos );
|
||||
pMsg->SetDX(0);
|
||||
pMsg->SetDY(0);
|
||||
|
||||
bool deleteMe = true;
|
||||
|
||||
// which button is different?
|
||||
if (pBMsg->fButton & kLeftButtonDown && !(fButtonState & kLeftButtonDown))
|
||||
{
|
||||
// left button now down
|
||||
fButtonState |= kLeftButtonDown;
|
||||
pMsg->SetButton( kLeftButtonDown );
|
||||
deleteMe = false;
|
||||
}
|
||||
else
|
||||
if (pBMsg->fButton & kLeftButtonUp && fButtonState & kLeftButtonDown)
|
||||
{
|
||||
// left button now up
|
||||
fButtonState &= ~kLeftButtonDown;
|
||||
pMsg->SetButton( kLeftButtonUp );
|
||||
deleteMe = false;
|
||||
}
|
||||
else
|
||||
if (pBMsg->fButton & kRightButtonDown && !(fButtonState & kRightButtonDown))
|
||||
{
|
||||
// right button now down
|
||||
fButtonState |= kRightButtonDown;
|
||||
pMsg->SetButton( kRightButtonDown );
|
||||
deleteMe = false;
|
||||
}
|
||||
else
|
||||
if (pBMsg->fButton & kRightButtonUp && fButtonState & kRightButtonDown)
|
||||
{
|
||||
// right button now up
|
||||
fButtonState &= ~kRightButtonDown;
|
||||
pMsg->SetButton( kRightButtonUp );
|
||||
deleteMe = false;
|
||||
}
|
||||
else
|
||||
if (pBMsg->fButton & kMiddleButtonDown && !(fButtonState & kMiddleButtonDown))
|
||||
{
|
||||
// mouse wheel button now down
|
||||
fButtonState |= kMiddleButtonDown;
|
||||
pMsg->SetButton( kMiddleButtonDown );
|
||||
deleteMe = false;
|
||||
}
|
||||
else
|
||||
if (pBMsg->fButton & kMiddleButtonUp && fButtonState & kMiddleButtonDown)
|
||||
{
|
||||
// right button now up
|
||||
fButtonState &= ~kMiddleButtonDown;
|
||||
pMsg->SetButton( kMiddleButtonUp );
|
||||
deleteMe = false;
|
||||
}
|
||||
|
||||
if (pBMsg->fButton & kRightButtonDblClk)
|
||||
{
|
||||
// right button dbl clicked, send TWO messages
|
||||
plMouseEventMsg* pMsg2 = TRACKED_NEW plMouseEventMsg;
|
||||
pMsg2->SetXPos( fXPos );
|
||||
pMsg2->SetYPos( fYPos );
|
||||
pMsg2->SetDX(0);
|
||||
pMsg2->SetDY(0);
|
||||
pMsg2->SetButton( kRightButtonDblClk );
|
||||
|
||||
if( fB2Msg != nil )
|
||||
delete fB2Msg;
|
||||
fB2Msg = pMsg2;
|
||||
|
||||
pMsg->SetButton( kRightButtonDown );
|
||||
deleteMe = false;
|
||||
}
|
||||
else
|
||||
if (pBMsg->fButton & kLeftButtonDblClk)
|
||||
{
|
||||
// left button dbl clicked, send TWO messages
|
||||
plMouseEventMsg* pMsg2 = TRACKED_NEW plMouseEventMsg;
|
||||
pMsg2->SetXPos( fXPos );
|
||||
pMsg2->SetYPos( fYPos );
|
||||
pMsg2->SetDX(0);
|
||||
pMsg2->SetDY(0);
|
||||
pMsg2->SetButton( kLeftButtonDblClk );
|
||||
|
||||
if( fB2Msg != nil )
|
||||
delete fB2Msg;
|
||||
fB2Msg = pMsg2;
|
||||
|
||||
pMsg->SetButton( kLeftButtonDown );
|
||||
deleteMe = false;
|
||||
}
|
||||
|
||||
if( deleteMe )
|
||||
{
|
||||
// mouse button state not changed
|
||||
delete pMsg;
|
||||
return true;
|
||||
}
|
||||
|
||||
// we are going to save up to two button mouse events per button (left and right)
|
||||
// that will be dispatched on the next eval
|
||||
|
||||
// which button is this for?
|
||||
if ( pMsg->GetButton() == kLeftButtonDown || pMsg->GetButton() == kLeftButtonUp )
|
||||
{
|
||||
// see if the queue is just empty
|
||||
if ( fLeftBMsg[0] == nil)
|
||||
{
|
||||
// nothing to think about... goes in first slot
|
||||
fLeftBMsg[0] = pMsg;
|
||||
}
|
||||
else if (fLeftBMsg[1] == nil)
|
||||
{
|
||||
// nothing to think about... goes in second slot
|
||||
fLeftBMsg[1] = pMsg;
|
||||
}
|
||||
else
|
||||
{
|
||||
// else queue if full... need to make some decisions
|
||||
plMouseEventMsg* lastMsg = plMouseEventMsg::ConvertNoRef(pMsg);
|
||||
// ...if this is an up event and [1] is a down then we need to remove both
|
||||
// ...because we can't lose the up event and the down will have no match
|
||||
if ( pMsg->GetButton() == kLeftButtonUp && lastMsg && lastMsg->GetButton() == kLeftButtonDown)
|
||||
{
|
||||
delete pMsg;
|
||||
delete fLeftBMsg[1];
|
||||
fLeftBMsg[1] = nil;
|
||||
}
|
||||
// ... otherwise ignore this event
|
||||
else
|
||||
{
|
||||
delete pMsg;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( pMsg->GetButton() == kRightButtonDown || pMsg->GetButton() == kRightButtonUp )
|
||||
{
|
||||
// see if the queue is just empty
|
||||
if ( fRightBMsg[0] == nil)
|
||||
{
|
||||
// nothing to think about... goes in first slot
|
||||
fRightBMsg[0] = pMsg;
|
||||
}
|
||||
else if (fRightBMsg[1] == nil)
|
||||
{
|
||||
// nothing to think about... goes in second slot
|
||||
fRightBMsg[1] = pMsg;
|
||||
}
|
||||
else
|
||||
{
|
||||
// else queue if full... need to make some decisions
|
||||
plMouseEventMsg* lastMsg = plMouseEventMsg::ConvertNoRef(pMsg);
|
||||
// ...if this is an up event and [1] is a down then we need to remove both
|
||||
// ...because we can't lose the up event and the down will have no match
|
||||
if ( pMsg->GetButton() == kRightButtonUp && lastMsg && lastMsg->GetButton() == kRightButtonDown)
|
||||
{
|
||||
delete pMsg;
|
||||
delete fRightBMsg[1];
|
||||
fRightBMsg[1] = nil;
|
||||
}
|
||||
// ... otherwise ignore this event
|
||||
else
|
||||
{
|
||||
delete pMsg;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( pMsg->GetButton() == kMiddleButtonDown || pMsg->GetButton() == kMiddleButtonUp )
|
||||
{
|
||||
// see if the queue is just empty
|
||||
if ( fMiddleBMsg[0] == nil)
|
||||
{
|
||||
// nothing to think about... goes in first slot
|
||||
fMiddleBMsg[0] = pMsg;
|
||||
}
|
||||
else if (fMiddleBMsg[1] == nil)
|
||||
{
|
||||
// nothing to think about... goes in second slot
|
||||
fMiddleBMsg[1] = pMsg;
|
||||
}
|
||||
else
|
||||
{
|
||||
// else queue if full... need to make some decisions
|
||||
plMouseEventMsg* lastMsg = plMouseEventMsg::ConvertNoRef(pMsg);
|
||||
// ...if this is an up event and [1] is a down then we need to remove both
|
||||
// ...because we can't lose the up event and the down will have no match
|
||||
if ( pMsg->GetButton() == kMiddleButtonUp && lastMsg && lastMsg->GetButton() == kMiddleButtonDown)
|
||||
{
|
||||
delete pMsg;
|
||||
delete fMiddleBMsg[1];
|
||||
fMiddleBMsg[1] = nil;
|
||||
}
|
||||
// ... otherwise ignore this event
|
||||
else
|
||||
{
|
||||
delete pMsg;
|
||||
}
|
||||
}
|
||||
}
|
||||
// we are going to dispatch the mouse button events right away
|
||||
// and not wait for the next eval, because we shouldn't miss one of these
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
241
Sources/Plasma/PubUtilLib/plInputCore/plInputDevice.h
Normal file
241
Sources/Plasma/PubUtilLib/plInputCore/plInputDevice.h
Normal file
@ -0,0 +1,241 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
// plInputDevice.h
|
||||
|
||||
#ifndef PL_INPUT_DEVICE_H
|
||||
#define PL_INPUT_DEVICE_H
|
||||
|
||||
#include "HeadSpin.h"
|
||||
#include "hsWindows.h"
|
||||
//#include "../pnInputCore/plControlDefinition.h"
|
||||
#include "../pnInputCore/plOSMsg.h"
|
||||
#include "hsBitVector.h"
|
||||
#include "hsTemplates.h"
|
||||
class plMessage;
|
||||
enum plKeyDef;
|
||||
struct plMouseInfo;
|
||||
class plPipeline;
|
||||
|
||||
class plInputDevice
|
||||
{
|
||||
public:
|
||||
enum Flags
|
||||
{
|
||||
kDisabled = 0x1
|
||||
};
|
||||
protected:
|
||||
UInt32 fFlags;
|
||||
public:
|
||||
|
||||
plInputDevice() {;}
|
||||
virtual ~plInputDevice() {;}
|
||||
|
||||
virtual const char* GetInputName() = 0;
|
||||
|
||||
UInt32 GetFlags() { return fFlags; }
|
||||
void SetFlags(UInt32 f) { fFlags = f; }
|
||||
virtual void HandleKeyEvent(plOSMsg message, plKeyDef key, bool bKeyDown, hsBool bKeyRepeat) {;}
|
||||
virtual void HandleMouseEvent(plOSMsg message, plMouseState state) {;}
|
||||
virtual void HandleWindowActivate(bool bActive, HWND hWnd) {;}
|
||||
virtual hsBool MsgReceive(plMessage* msg) {return false;}
|
||||
virtual void Shutdown() {;}
|
||||
|
||||
|
||||
};
|
||||
|
||||
class plKeyEventMsg;
|
||||
|
||||
class plKeyboardDevice : public plInputDevice
|
||||
{
|
||||
hsBool fAltKeyDown;
|
||||
hsBool fShiftKeyDown;
|
||||
hsBool fCtrlKeyDown;
|
||||
hsBool fCapsLockKeyDown;
|
||||
int fControlMode;
|
||||
hsBool fCapsLockLock;
|
||||
|
||||
static bool fKeyboardState[256]; // virtual key code is the index, bool is whether it is down or not
|
||||
static hsBool fIgnoreCapsLock; // set if we want it to ignore this key when translating characters (i.e. for chatting)
|
||||
static hsBool fKeyIsDeadKey; // the key we just got was a dead key, store the value if you're a text input object
|
||||
|
||||
static plKeyboardDevice* fInstance;
|
||||
void InitKeyboardMaps();
|
||||
void InitKeyboardState();
|
||||
|
||||
void ReleaseAllKeys();
|
||||
|
||||
public:
|
||||
enum
|
||||
{
|
||||
CONSOLE_MODE = 0,
|
||||
CONSOLE_FULL,
|
||||
STANDARD_MODE,
|
||||
};
|
||||
plKeyboardDevice();
|
||||
~plKeyboardDevice();
|
||||
|
||||
void SetControlMode(int i) { fControlMode = i; }
|
||||
|
||||
const char* GetInputName() { return "keyboard"; }
|
||||
void HandleKeyEvent(plOSMsg message, plKeyDef key, bool bKeyDown, hsBool bKeyRepeat);
|
||||
virtual void HandleWindowActivate(bool bActive, HWND hWnd);
|
||||
virtual hsBool IsCapsLockKeyOn();
|
||||
virtual void Shutdown();
|
||||
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
void ForceNumLock(hsBool on);
|
||||
#endif
|
||||
|
||||
static hsBool IgnoreCapsLock() { return fIgnoreCapsLock; }
|
||||
static void IgnoreCapsLock(hsBool ignore) { fIgnoreCapsLock = ignore; }
|
||||
|
||||
static hsBool KeyIsDeadKey() { return fKeyIsDeadKey; }
|
||||
|
||||
static plKeyboardDevice* GetInstance() { return fInstance; }
|
||||
|
||||
static char KeyEventToChar( plKeyEventMsg *msg );
|
||||
|
||||
protected:
|
||||
hsBool fStartedUpWithNumLockOn; // maintaining a separate flag since apparently the other one can get confused
|
||||
hsBool fPrevNumLockOn;
|
||||
};
|
||||
|
||||
class plPlate;
|
||||
|
||||
#define CURSOR_UP "cursor_up.png"
|
||||
#define CURSOR_UPWARD "cursor_upward.png"
|
||||
#define CURSOR_DOWN "cursor_down.png"
|
||||
#define CURSOR_RIGHT "cursor_right.png"
|
||||
#define CURSOR_LEFT "cursor_left.png"
|
||||
#define CURSOR_OPEN "cursor_open.png"
|
||||
#define CURSOR_GRAB "cursor_grab.png"
|
||||
#define CURSOR_CLICKED "cursor_clicked.png"
|
||||
#define CURSOR_POISED "cursor_poised.png"
|
||||
#define CURSOR_4WAY_OPEN "cursor_4way_open.png"
|
||||
#define CURSOR_4WAY_CLOSED "cursor_4way_closed.png"
|
||||
#define CURSOR_UPDOWN_OPEN "cursor_updown_open.png"
|
||||
#define CURSOR_UPDOWN_CLOSED "cursor_updown_closed.png"
|
||||
#define CURSOR_LEFTRIGHT_OPEN "cursor_leftright_open.png"
|
||||
#define CURSOR_LEFTRIGHT_CLOSED "cursor_leftright_closed.png"
|
||||
#define CURSOR_OFFER_BOOK "cursor_book.png"
|
||||
#define CURSOR_OFFER_BOOK_HI "cursor_book_poised.png"
|
||||
#define CURSOR_OFFER_BOOK_CLICKED "cursor_book_clicked.png"
|
||||
#define CURSOR_CLICK_DISABLED "cursor_disabled.png"
|
||||
#define CURSOR_HAND "cursor_up.png"
|
||||
#define CURSOR_ARROW "cursor_up.png"
|
||||
|
||||
class plInputEventMsg;
|
||||
|
||||
class plMouseDevice : public plInputDevice
|
||||
{
|
||||
public:
|
||||
plMouseDevice();
|
||||
~plMouseDevice();
|
||||
|
||||
const char* GetInputName() { return "mouse"; }
|
||||
|
||||
hsBool HasControlFlag(int f) const { return fControlFlags.IsBitSet(f); }
|
||||
void SetControlFlag(int f)
|
||||
{
|
||||
fControlFlags.SetBit(f);
|
||||
}
|
||||
void ClearControlFlag(int which) { fControlFlags.ClearBit( which ); }
|
||||
void SetCursorX(hsScalar x);
|
||||
void SetCursorY(hsScalar y);
|
||||
hsScalar GetCursorX() { return fXPos; }
|
||||
hsScalar GetCursorY() { return fYPos; }
|
||||
UInt32 GetButtonState() { return fButtonState; }
|
||||
hsScalar GetCursorOpacity() { return fOpacity; }
|
||||
void SetDisplayResolution(hsScalar Width, hsScalar Height);
|
||||
|
||||
virtual hsBool MsgReceive(plMessage* msg);
|
||||
|
||||
static plMouseDevice* Instance() { return plMouseDevice::fInstance; }
|
||||
|
||||
static void SetMsgAlways(bool b) { plMouseDevice::bMsgAlways = b; }
|
||||
static void ShowCursor(hsBool override = false);
|
||||
static void NewCursor(char* cursor);
|
||||
static void HideCursor(hsBool override = false);
|
||||
static bool GetHideCursor() { return plMouseDevice::bCursorHidden; }
|
||||
static void SetCursorOpacity( hsScalar opacity = 1.f );
|
||||
static bool GetInverted() { return plMouseDevice::bInverted; }
|
||||
static void SetInverted(bool inverted) { plMouseDevice::bInverted = inverted; }
|
||||
static void AddNameToCursor(const char* name);
|
||||
static void AddIDNumToCursor(UInt32 idNum);
|
||||
static void AddCCRToCursor();
|
||||
|
||||
protected:
|
||||
plInputEventMsg* fXMsg;
|
||||
plInputEventMsg* fYMsg;
|
||||
plInputEventMsg* fB2Msg;
|
||||
|
||||
// mouse button event queues (only hold 2)
|
||||
plInputEventMsg* fLeftBMsg[2];
|
||||
plInputEventMsg* fRightBMsg[2];
|
||||
plInputEventMsg* fMiddleBMsg[2];
|
||||
|
||||
hsScalar fXPos;
|
||||
hsScalar fYPos;
|
||||
int fWXPos; // the windows coordinates of the cursor
|
||||
int fWYPos;
|
||||
UInt32 fButtonState;
|
||||
hsScalar fOpacity;
|
||||
hsBitVector fControlFlags;
|
||||
|
||||
|
||||
plPlate *fCursor;
|
||||
char* fCursorID;
|
||||
|
||||
static plMouseDevice* fInstance;
|
||||
static plMouseInfo fDefaultMouseControlMap[];
|
||||
void CreateCursor( char* cursor );
|
||||
void IUpdateCursorSize();
|
||||
static bool bMsgAlways;
|
||||
static bool bCursorHidden;
|
||||
static bool bCursorOverride;
|
||||
static bool bInverted;
|
||||
static hsScalar fWidth, fHeight;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // PL_INPUT_DEVICE_H
|
305
Sources/Plasma/PubUtilLib/plInputCore/plInputInterface.cpp
Normal file
305
Sources/Plasma/PubUtilLib/plInputCore/plInputInterface.cpp
Normal file
@ -0,0 +1,305 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// plInputInterface.cpp - A single layer on the input interface stack //
|
||||
// //
|
||||
//// History /////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// 2.20.02 mcn - Created. //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsConfig.h"
|
||||
#include "hsWindows.h"
|
||||
#include "hsTypes.h"
|
||||
#include "plInputInterface.h"
|
||||
#include "plInputInterfaceMgr.h"
|
||||
|
||||
#include "../pnInputCore/plKeyMap.h"
|
||||
#include "../plMessage/plInputEventMsg.h"
|
||||
|
||||
#include "hsResMgr.h"
|
||||
#include "plgDispatch.h"
|
||||
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
plInputInterface::plInputInterface()
|
||||
{
|
||||
fEnabled = false;
|
||||
fControlMap = TRACKED_NEW plKeyMap;
|
||||
}
|
||||
|
||||
plInputInterface::~plInputInterface()
|
||||
{
|
||||
delete fControlMap;
|
||||
}
|
||||
|
||||
void plInputInterface::ClearKeyMap()
|
||||
{
|
||||
if( fControlMap != nil )
|
||||
fControlMap->ClearAll();
|
||||
}
|
||||
|
||||
//// Read/Write //////////////////////////////////////////////////////////////
|
||||
|
||||
void plInputInterface::Read( hsStream* s, hsResMgr* mgr )
|
||||
{
|
||||
}
|
||||
|
||||
void plInputInterface::Write( hsStream* s, hsResMgr* mgr )
|
||||
{
|
||||
}
|
||||
|
||||
//// Helper Functions ////////////////////////////////////////////////////////
|
||||
|
||||
hsBool plInputInterface::IOwnsControlCode( ControlEventCode code )
|
||||
{
|
||||
if( fControlMap->FindBinding( code ) != nil )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//// IVerifyShiftKey /////////////////////////////////////////////////////////
|
||||
// special logic so the shift key can make everyone totally happy...
|
||||
|
||||
hsBool plInputInterface::IVerifyShiftKey( plKeyDef key, int index )
|
||||
{
|
||||
// if we are mapped to the actual shift key, return true
|
||||
if (key == KEY_SHIFT)
|
||||
return true;
|
||||
|
||||
// if anything else is mapped to this key + shift, return false
|
||||
/* for (int i=0; i < fControlMap->GetNumBindings(); i++)
|
||||
{
|
||||
if (index == i)
|
||||
continue;
|
||||
if (fKeyMap->fMap[i]->fKeyDef == key && fKeyMap->fMap[i]->fKeyFlags & plKeyInfo::kKeyShift )
|
||||
return false;
|
||||
}
|
||||
*/ return true;
|
||||
}
|
||||
|
||||
void plInputInterface::IDeactivateBinding(const plKeyBinding *binding)
|
||||
{
|
||||
if( !(binding->GetCodeFlags() & kControlFlagNoDeactivate) && !(binding->GetCodeFlags() & kControlFlagToggle) )
|
||||
{
|
||||
plCtrlCmd *pCmd = TRACKED_NEW plCtrlCmd( this );
|
||||
pCmd->fControlCode = binding->GetCode();
|
||||
pCmd->fControlActivated = false;
|
||||
pCmd->SetCmdString( binding->GetExtendedString() );
|
||||
pCmd->fNetPropagateToPlayers = ( binding->GetCodeFlags() & kControlFlagNetPropagate ) ? true : false;
|
||||
|
||||
fMessageQueue->Append( pCmd );
|
||||
}
|
||||
IClearKeyControlFlag(binding->GetCode());
|
||||
}
|
||||
|
||||
//// ProcessKeyBindings //////////////////////////////////////////////////////
|
||||
// Processes the given key event as a key binding, if one exists. If not,
|
||||
// returns false.
|
||||
|
||||
hsBool plInputInterface::ProcessKeyBindings( plInputEventMsg *msg )
|
||||
{
|
||||
int i;
|
||||
hsBool activate;
|
||||
|
||||
plKeyEventMsg *keyMsg = plKeyEventMsg::ConvertNoRef( msg );
|
||||
if( keyMsg == nil )
|
||||
return false;
|
||||
|
||||
|
||||
/// We might have controls that are currently enabled that are triggered in part by
|
||||
/// modifiers (ctrl or shift)...if that is true, then we want to disable them if either
|
||||
/// of those modifiers are up, no matter what key this message is for
|
||||
hsTArray<Int16> enabledCtrls;
|
||||
fKeyControlFlags.Enumerate( enabledCtrls );
|
||||
|
||||
for( i = 0; i < enabledCtrls.GetCount(); i++ )
|
||||
{
|
||||
const plKeyBinding *binding = fControlMap->FindBinding( (ControlEventCode)enabledCtrls[ i ] );
|
||||
if( binding == nil )
|
||||
; // Somehow we lost the binding??
|
||||
else
|
||||
{
|
||||
bool wantShift, wantCtrl;
|
||||
if( fKeyControlsFrom2ndKeyFlags.IsBitSet( enabledCtrls[ i ] ) )
|
||||
{
|
||||
wantShift = ( binding->GetKey2().fFlags & plKeyCombo::kShift ) || ( binding->GetKey2().fKey == KEY_SHIFT );
|
||||
wantCtrl = ( binding->GetKey2().fFlags & plKeyCombo::kCtrl ) || ( binding->GetKey2().fKey == KEY_CTRL );
|
||||
}
|
||||
else
|
||||
{
|
||||
wantShift = ( binding->GetKey1().fFlags & plKeyCombo::kShift ) || ( binding->GetKey1().fKey == KEY_SHIFT );
|
||||
wantCtrl = ( binding->GetKey1().fFlags & plKeyCombo::kCtrl ) || ( binding->GetKey1().fKey == KEY_CTRL );
|
||||
}
|
||||
|
||||
if( ( wantShift && !keyMsg->GetShiftKeyDown() ) || ( wantCtrl && !keyMsg->GetCtrlKeyDown() ) )
|
||||
{
|
||||
IDeactivateBinding(binding);
|
||||
fKeyControlsFrom2ndKeyFlags.SetBit(enabledCtrls[i], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Process any binding for this message's key code now
|
||||
plKeyCombo combo( keyMsg->GetKeyCode(), ( keyMsg->GetShiftKeyDown() ? plKeyCombo::kShift : 0 ) |
|
||||
( keyMsg->GetCtrlKeyDown() ? plKeyCombo::kCtrl : 0 ) );
|
||||
|
||||
hsTArray<const plKeyBinding *> bindings;
|
||||
fControlMap->FindAllBindingsByKey(combo, bindings);
|
||||
|
||||
// The first binding is the one we want. (FindAllBindingsByKey guarantees this)
|
||||
const plKeyBinding *binding = (bindings.GetCount() ? bindings[0] : nil);
|
||||
|
||||
// If other bindings were found, they lose out to the first one.
|
||||
for (i = 1; i < bindings.GetCount(); i++)
|
||||
IDeactivateBinding(bindings[i]);
|
||||
|
||||
/*
|
||||
const plKeyBinding *binding = fControlMap->FindBindingByKey( combo );
|
||||
if( binding == nil )
|
||||
{
|
||||
// Don't panic just yet, there are some special cases with the shift key to check first
|
||||
if( keyMsg->GetKeyCode() == KEY_SHIFT || keyMsg->GetShiftKeyDown() )
|
||||
{
|
||||
// See, there are two other cases to consider: 1) we have a binding directly to the shift
|
||||
// key, which wouldn't have the shift flag set (so the above search wouldn't have caught it).
|
||||
|
||||
// The second case would be if we have a matching binding without shift...
|
||||
// which is VALID so long as no other bindings respond to this key combo + shift, but of course,
|
||||
// if there were, we'd have found them already!
|
||||
|
||||
// Either way, we remove the shift flag and try again
|
||||
combo.fFlags &= ~plKeyCombo::kShift;
|
||||
|
||||
binding = fControlMap->FindBindingByKey( combo );
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (!binding)
|
||||
return false;
|
||||
|
||||
UInt32 codeFlags = binding->GetCodeFlags();
|
||||
|
||||
// Filter out no-repeat messages
|
||||
if( ( codeFlags & kControlFlagNoRepeat ) && keyMsg->GetRepeat() )
|
||||
return false;
|
||||
|
||||
if( codeFlags & kControlFlagNormal )
|
||||
{
|
||||
// "Normal" behavior--enable on key down, disable on key up
|
||||
activate = keyMsg->GetKeyDown() ? true : false;
|
||||
}
|
||||
else if( codeFlags & kControlFlagToggle )
|
||||
{
|
||||
// Toggle behavior
|
||||
if( ( codeFlags & kControlFlagDownEvent ) && !keyMsg->GetKeyDown() )
|
||||
return false;
|
||||
if( ( codeFlags & kControlFlagUpEvent ) && keyMsg->GetKeyDown() )
|
||||
return false;
|
||||
|
||||
if( IHasKeyControlFlag( binding->GetCode() ) )
|
||||
activate = false;
|
||||
else
|
||||
activate = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remaining ones are triggered to activate on their flagged event and
|
||||
// deactivate when that turns false
|
||||
if( ( codeFlags & kControlFlagDownEvent ) && !keyMsg->GetKeyDown() )
|
||||
activate = false;
|
||||
else if( ( codeFlags & kControlFlagUpEvent ) && keyMsg->GetKeyDown() )
|
||||
activate = false;
|
||||
else
|
||||
activate = true;
|
||||
}
|
||||
|
||||
hsBool wasActive = IHasKeyControlFlag(binding->GetCode());
|
||||
|
||||
// Set or clear our flags, since we do that even if we don't send a message
|
||||
if( activate )
|
||||
{
|
||||
ISetKeyControlFlag( binding->GetCode() );
|
||||
fKeyControlsFrom2ndKeyFlags.SetBit( binding->GetCode(), ( binding->GetKey2() == combo ) ? true : false );
|
||||
}
|
||||
else
|
||||
{
|
||||
IClearKeyControlFlag( binding->GetCode() );
|
||||
fKeyControlsFrom2ndKeyFlags.SetBit( binding->GetCode(), 0 );
|
||||
}
|
||||
|
||||
// Filter out codes that only want their activate messages sent (like console commands)
|
||||
if( ( codeFlags & kControlFlagNoDeactivate ) && !activate )
|
||||
return false;
|
||||
|
||||
if (!IControlCodeEnabled(binding->GetCode()))
|
||||
{
|
||||
if (activate || (codeFlags & kControlFlagToggle) || !wasActive)
|
||||
{
|
||||
// It's ok to deactivate a disabled control, but not activate it
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// OK, generate the message to send
|
||||
plCtrlCmd *pCmd = TRACKED_NEW plCtrlCmd( this );
|
||||
pCmd->fControlCode = binding->GetCode();
|
||||
pCmd->fControlActivated = activate;
|
||||
|
||||
pCmd->SetCmdString( binding->GetExtendedString() );
|
||||
pCmd->fNetPropagateToPlayers = ( codeFlags & kControlFlagNetPropagate ) ? true : false;
|
||||
|
||||
fMessageQueue->Append( pCmd );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
hsBool plInputInterface::IControlCodeEnabled(ControlEventCode code )
|
||||
{
|
||||
return (!fDisabledControls.IsBitSet(code));
|
||||
}
|
222
Sources/Plasma/PubUtilLib/plInputCore/plInputInterface.h
Normal file
222
Sources/Plasma/PubUtilLib/plInputCore/plInputInterface.h
Normal file
@ -0,0 +1,222 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// plInputInterface.cpp - A single layer on the input interface stack //
|
||||
// //
|
||||
//// History /////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// 2.20.02 mcn - Created. //
|
||||
// //
|
||||
//// Note on GetPriorityLevel() //////////////////////////////////////////////
|
||||
// //
|
||||
// The inputInterfaceMgr uses GetPriorityLevel() to place each interface //
|
||||
// into the stack relative to the other interfaces. Current priority //
|
||||
// levels are: //
|
||||
// Console - 100 //
|
||||
// GUI system - 75 //
|
||||
// Avatar input - 50 //
|
||||
// Scene interaction - 25 //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _plInputInterface_h
|
||||
#define _plInputInterface_h
|
||||
|
||||
#include "hsRefCnt.h"
|
||||
#include "hsTemplates.h"
|
||||
#include "hsBitVector.h"
|
||||
// Needed for UNIX Build
|
||||
// only windows will let you predeclare an enum
|
||||
#include "../../NucleusLib/pnInputCore/plKeyDef.h"
|
||||
#include "../../NucleusLib/pnInputCore/plControlEventCodes.h"
|
||||
|
||||
|
||||
//// Class Definition ////////////////////////////////////////////////////////
|
||||
|
||||
class hsStream;
|
||||
class hsResMgr;
|
||||
class plInputEventMsg;
|
||||
class plInputInterfaceMgr;
|
||||
class plMessage;
|
||||
class plKeyMap;
|
||||
class plCtrlCmd;
|
||||
class plKeyBinding;
|
||||
|
||||
class plInputInterface : public hsRefCnt
|
||||
{
|
||||
friend class plInputInterfaceMgr;
|
||||
|
||||
protected:
|
||||
|
||||
enum Priorities
|
||||
{
|
||||
kConsolePriority = 100,
|
||||
kGUISystemPriority = 75,
|
||||
kDebugCmdPrioity = 60,
|
||||
kSceneInteractionPriority = 50,
|
||||
kTelescopeInputPriority = 26,
|
||||
kAvatarInputPriority = 25,
|
||||
};
|
||||
|
||||
plInputInterfaceMgr *fManager;
|
||||
|
||||
plKeyMap *fControlMap;
|
||||
hsTArray<plCtrlCmd *> *fMessageQueue;
|
||||
|
||||
hsBitVector fKeyControlFlags;
|
||||
hsBitVector fKeyControlsFrom2ndKeyFlags;
|
||||
hsBitVector fDisabledControls;
|
||||
hsBool fEnabled;
|
||||
|
||||
void ISetMessageQueue( hsTArray<plCtrlCmd *> *queue ) { fMessageQueue = queue; }
|
||||
plKeyMap *IGetControlMap( void ) const { return fControlMap; }
|
||||
hsBool IOwnsControlCode( ControlEventCode code );
|
||||
hsBool IVerifyShiftKey( plKeyDef key, int index );
|
||||
|
||||
hsBool IHasKeyControlFlag(int f) const { return fKeyControlFlags.IsBitSet(f); }
|
||||
void ISetKeyControlFlag(int f) { fKeyControlFlags.SetBit(f); }
|
||||
void IClearKeyControlFlag(int which) { fKeyControlFlags.ClearBit( which ); }
|
||||
void IDisableControl(int which) { fDisabledControls.SetBit(which); }
|
||||
void IEnableControl(int which) { fDisabledControls.ClearBit(which); }
|
||||
|
||||
// The binding lost focus/priority. Behave as though they released the key and send
|
||||
// a deactivate message for the control code.
|
||||
void IDeactivateBinding(const plKeyBinding *binding);
|
||||
|
||||
|
||||
// Gets called once per IUpdate(), just like normal IEval()s
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty ) { return false; }
|
||||
|
||||
// Override to handle special-cased control messages of your own (same as receiving them via a message, but if you process them, nobody else gets them). Return false if you don't handle it.
|
||||
virtual hsBool IHandleCtrlCmd( plCtrlCmd *cmd ) { return false; }
|
||||
|
||||
// Override to let the input interfaces control when a binding is truly active. If this function returns false,
|
||||
// ProcessKeyBindings will ignore the keypress for the given control. This way, the interfaces can be selective
|
||||
// about which bindings are active when. By default, always returns true, since there are very few and rare
|
||||
// cases where you'd want to return false
|
||||
virtual hsBool IControlCodeEnabled( ControlEventCode code );
|
||||
|
||||
// Some helpers for derived classes to avoid including the manager unnecessariliy
|
||||
|
||||
public:
|
||||
|
||||
plInputInterface();
|
||||
virtual ~plInputInterface();
|
||||
|
||||
enum Cursors
|
||||
{
|
||||
kNullCursor = 0,
|
||||
kCursorUp,
|
||||
kCursorLeft,
|
||||
kCursorRight,
|
||||
kCursorDown,
|
||||
kCursorPoised,
|
||||
kCursorClicked,
|
||||
kCursorUnClicked,
|
||||
kCursorHidden,
|
||||
kCursorOpen,
|
||||
kCursorGrab,
|
||||
kCursorArrow,
|
||||
kCursor4WayDraggable,
|
||||
kCursor4WayDragging,
|
||||
kCursorUpDownDraggable,
|
||||
kCursorUpDownDragging,
|
||||
kCursorLeftRightDraggable,
|
||||
kCursorLeftRightDragging,
|
||||
kCursorOfferBook,
|
||||
kCursorOfferBookHilite,
|
||||
kCursorOfferBookClicked,
|
||||
kCursorClickDisabled,
|
||||
kCursorHand,
|
||||
kCursorUpward,
|
||||
};
|
||||
|
||||
virtual void Read( hsStream* s, hsResMgr* mgr );
|
||||
virtual void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
// Returns the priority of this interface layer, based on the Priorities enum
|
||||
virtual UInt32 GetPriorityLevel( void ) const = 0;
|
||||
|
||||
// Returns true if the message was handled, false if not and we want to pass it on to others in the stack
|
||||
virtual hsBool InterpretInputEvent( plInputEventMsg *pMsg ) = 0;
|
||||
|
||||
// Returns the currently active mouse cursor for this layer, as defined in pnMessage/plCursorChangeMsg.h
|
||||
virtual UInt32 GetCurrentCursorID( void ) const = 0;
|
||||
|
||||
// Returns the current opacity that this layer wants the cursor to be, from 0 (xparent) to 1 (opaque)
|
||||
virtual hsScalar GetCurrentCursorOpacity( void ) const { return 1.f; }
|
||||
|
||||
// Returns true if this layer is wanting to change the mouse, false if it isn't interested
|
||||
virtual hsBool HasInterestingCursorID( void ) const = 0;
|
||||
|
||||
// Gets called by the manager. If you want a message to come to you, set your manager as the destination
|
||||
virtual hsBool MsgReceive( plMessage *msg ) { return false; }
|
||||
|
||||
// Any initialization that requires a pointer to the manager needs to be done on Init()/Shutdown()
|
||||
virtual void Init( plInputInterfaceMgr *manager ) { fManager = manager; RestoreDefaultKeyMappings(); }
|
||||
virtual void Shutdown( void ) {}
|
||||
|
||||
// Gets called when any of the key mappings are changed, so that the interface layer can refresh the ones its interested in
|
||||
virtual void RefreshKeyMap( void ) {}
|
||||
|
||||
// Called when the interface manager is setting all key mappings to default
|
||||
virtual void RestoreDefaultKeyMappings( void ) {}
|
||||
|
||||
// Called on each interface layer that gets missed when processing inputEvents in the manager (i.e. you either get this call or InterpretInputEvent)
|
||||
virtual void MissedInputEvent( plInputEventMsg *pMsg ) {}
|
||||
|
||||
// Non-virtual, can't override--processes an inputEventMsg to see if we can handle it via a key binding (if so, InterpretInputEvent won't be called)
|
||||
hsBool ProcessKeyBindings( plInputEventMsg *keyMsg );
|
||||
|
||||
void SetEnabled( hsBool e ) { fEnabled = e; }
|
||||
hsBool IsEnabled( void ) const { return fEnabled; }
|
||||
|
||||
// clear all keys from map
|
||||
virtual void ClearKeyMap();
|
||||
|
||||
// reset clickable state
|
||||
virtual void ResetClickableState() {;}
|
||||
};
|
||||
|
||||
|
||||
#endif // _plInputInterface_h
|
963
Sources/Plasma/PubUtilLib/plInputCore/plInputInterfaceMgr.cpp
Normal file
963
Sources/Plasma/PubUtilLib/plInputCore/plInputInterfaceMgr.cpp
Normal file
@ -0,0 +1,963 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// plInputInterfaceMgr.cpp - The manager of all input interface layers //
|
||||
// //
|
||||
//// History /////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// 2.20.02 mcn - Created. //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsConfig.h"
|
||||
#include "hsWindows.h"
|
||||
#include "hsTypes.h"
|
||||
#include "plInputInterfaceMgr.h"
|
||||
#include "plInputInterface.h"
|
||||
#include "plInputDevice.h" // For mouse device stuff
|
||||
|
||||
#include "../pnInputCore/plKeyMap.h"
|
||||
#include "../plMessage/plInputEventMsg.h"
|
||||
#include "../plMessage/plInputIfaceMgrMsg.h"
|
||||
#include "../pnMessage/plClientMsg.h"
|
||||
#include "../pnMessage/plTimeMsg.h"
|
||||
#include "../pnMessage/plCmdIfaceModMsg.h"
|
||||
#include "../pnMessage/plPlayerPageMsg.h"
|
||||
|
||||
#include "../pnKeyedObject/plKey.h"
|
||||
#include "../pnKeyedObject/plFixedKey.h"
|
||||
|
||||
#include "../pnNetCommon/plNetApp.h"
|
||||
#include "../plNetClient/plNetClientMgr.h"
|
||||
|
||||
#include "hsResMgr.h"
|
||||
#include "plgDispatch.h"
|
||||
#include "plProfile.h"
|
||||
#include "../plResMgr/plLocalization.h"
|
||||
|
||||
plProfile_CreateTimer("Input", "Update", Input);
|
||||
|
||||
//// plCtrlCmd ///////////////////////////////////////////////////////////////
|
||||
|
||||
void plCtrlCmd::Write(hsStream* stream, hsResMgr* mgr)
|
||||
{
|
||||
stream->WriteSwap32( fControlCode );
|
||||
stream->WriteBool( fControlActivated );
|
||||
fPt.Write(stream);
|
||||
|
||||
// write cmd/string
|
||||
plMsgCStringHelper::Poke(fCmd, stream);
|
||||
}
|
||||
|
||||
void plCtrlCmd::Read(hsStream* stream, hsResMgr* mgr)
|
||||
{
|
||||
fControlCode = (ControlEventCode)stream->ReadSwap32();
|
||||
fControlActivated = stream->ReadBool();
|
||||
fPt.Read(stream);
|
||||
|
||||
// read cmd/string
|
||||
plMsgCStringHelper::Peek(fCmd, stream);
|
||||
}
|
||||
|
||||
//// plDefaultKeyCatcher /////////////////////////////////////////////////////
|
||||
|
||||
plDefaultKeyCatcher::~plDefaultKeyCatcher()
|
||||
{
|
||||
if( plInputInterfaceMgr::GetInstance() != nil )
|
||||
plInputInterfaceMgr::GetInstance()->SetDefaultKeyCatcher( nil );
|
||||
}
|
||||
|
||||
//// Statics /////////////////////////////////////////////////////////////////
|
||||
|
||||
plInputInterfaceMgr *plInputInterfaceMgr::fInstance = nil;
|
||||
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
plInputInterfaceMgr::plInputInterfaceMgr()
|
||||
{
|
||||
fClickEnabled = false;
|
||||
fCurrentCursor = -1;
|
||||
fCursorOpacity = 1.f;
|
||||
fForceCursorHidden = false;
|
||||
fForceCursorHiddenCount = 0;
|
||||
InitDefaultKeyMap();
|
||||
|
||||
#if 0
|
||||
// make sure we don't miss control keys on remote players
|
||||
SetSynchFlagsBit(plSynchedObject::kSendReliably);
|
||||
#endif
|
||||
hsAssert( fInstance == nil, "Attempting to create two input interface managers!" );
|
||||
fInstance = this;
|
||||
|
||||
fCurrentFocus = nil;
|
||||
fDefaultCatcher = nil;
|
||||
}
|
||||
|
||||
plInputInterfaceMgr::~plInputInterfaceMgr()
|
||||
{
|
||||
Shutdown();
|
||||
fInstance = nil;
|
||||
}
|
||||
|
||||
//// Init ////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "plAvatarInputInterface.h"
|
||||
#include "plSceneInputInterface.h"
|
||||
#include "plDebugInputInterface.h"
|
||||
#include "plTelescopeInputInterface.h"
|
||||
|
||||
void plInputInterfaceMgr::Init( void )
|
||||
{
|
||||
RegisterAs( kInputInterfaceMgr_KEY );
|
||||
|
||||
plgDispatch::Dispatch()->RegisterForType( plInputIfaceMgrMsg::Index(), GetKey() );
|
||||
plgDispatch::Dispatch()->RegisterForType( plInputEventMsg::Index(), GetKey() );
|
||||
|
||||
plgDispatch::Dispatch()->RegisterForType( plEvalMsg::Index(), GetKey() );
|
||||
plgDispatch::Dispatch()->RegisterForExactType( plPlayerPageMsg::Index(), GetKey() );
|
||||
plgDispatch::Dispatch()->RegisterForExactType( plCmdIfaceModMsg::Index(), GetKey() );
|
||||
plgDispatch::Dispatch()->RegisterForExactType( plClientMsg::Index(), GetKey() );
|
||||
|
||||
/// Hacks (?) for now
|
||||
plAvatarInputInterface *avatar = TRACKED_NEW plAvatarInputInterface();
|
||||
IAddInterface( avatar );
|
||||
hsRefCnt_SafeUnRef( avatar );
|
||||
|
||||
plSceneInputInterface *scene = TRACKED_NEW plSceneInputInterface();
|
||||
IAddInterface( scene );
|
||||
hsRefCnt_SafeUnRef( scene );
|
||||
|
||||
plDebugInputInterface *camDrive = TRACKED_NEW plDebugInputInterface();
|
||||
IAddInterface( camDrive );
|
||||
hsRefCnt_SafeUnRef( camDrive );
|
||||
|
||||
}
|
||||
|
||||
//// Shutdown ////////////////////////////////////////////////////////////////
|
||||
|
||||
void plInputInterfaceMgr::Shutdown( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
// WriteKeyMap();
|
||||
|
||||
for( i = 0; i < fInterfaces.GetCount(); i++ )
|
||||
{
|
||||
fInterfaces[ i ]->Shutdown();
|
||||
hsRefCnt_SafeUnRef( fInterfaces[ i ] );
|
||||
}
|
||||
fInterfaces.Reset();
|
||||
|
||||
for( i = 0; i < fMessageQueue.GetCount(); i++ )
|
||||
delete fMessageQueue[ i ];
|
||||
fMessageQueue.Reset();
|
||||
|
||||
plgDispatch::Dispatch()->UnRegisterForType( plInputIfaceMgrMsg::Index(), GetKey() );
|
||||
plgDispatch::Dispatch()->UnRegisterForType( plInputEventMsg::Index(), GetKey() );
|
||||
|
||||
plgDispatch::Dispatch()->UnRegisterForType( plEvalMsg::Index(), GetKey() );
|
||||
plgDispatch::Dispatch()->UnRegisterForExactType( plPlayerPageMsg::Index(), GetKey() );
|
||||
plgDispatch::Dispatch()->UnRegisterForExactType( plCmdIfaceModMsg::Index(), GetKey() );
|
||||
plgDispatch::Dispatch()->UnRegisterForExactType( plClientMsg::Index(), GetKey() );
|
||||
|
||||
UnRegisterAs( kInputInterfaceMgr_KEY );
|
||||
}
|
||||
|
||||
//// IAdd/RemoveInterface ////////////////////////////////////////////////////
|
||||
// Each interface has a "priority level", i.e. where in the list it should be.
|
||||
// Doing it this way allows us to keep the manager unaware of the number or
|
||||
// types of interfaces.
|
||||
|
||||
void plInputInterfaceMgr::IAddInterface( plInputInterface *iface )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for( i = 0; i < fInterfaces.GetCount(); i++ )
|
||||
{
|
||||
if( fInterfaces[ i ]->GetPriorityLevel() < iface->GetPriorityLevel() )
|
||||
break;
|
||||
}
|
||||
|
||||
fInterfaces.Insert( i, iface );
|
||||
hsRefCnt_SafeRef( iface );
|
||||
iface->Init( this );
|
||||
iface->ISetMessageQueue( &fMessageQueue );
|
||||
}
|
||||
|
||||
void plInputInterfaceMgr::IRemoveInterface( plInputInterface *iface )
|
||||
{
|
||||
int idx = fInterfaces.Find( iface );
|
||||
if( idx != fInterfaces.kMissingIndex )
|
||||
{
|
||||
fInterfaces[ idx ]->Shutdown();
|
||||
hsRefCnt_SafeUnRef( fInterfaces[ idx ] );
|
||||
fInterfaces.Remove( idx );
|
||||
}
|
||||
}
|
||||
|
||||
/// reset clickable state //////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void plInputInterfaceMgr::ResetClickableState()
|
||||
{
|
||||
// look for the scene input interface
|
||||
for(int i = 0; i < fInterfaces.GetCount(); i++ )
|
||||
fInterfaces[i]->ResetClickableState();
|
||||
}
|
||||
|
||||
//// IUpdateCursor ///////////////////////////////////////////////////////////
|
||||
|
||||
void plInputInterfaceMgr::IUpdateCursor( Int32 newCursor )
|
||||
{
|
||||
char* mouseCursorResID;
|
||||
|
||||
|
||||
fCurrentCursor = newCursor;
|
||||
if( fCurrentCursor == plInputInterface::kCursorHidden )
|
||||
plMouseDevice::HideCursor();
|
||||
else
|
||||
{
|
||||
plMouseDevice::ShowCursor();
|
||||
|
||||
switch( fCurrentCursor )
|
||||
{
|
||||
case plInputInterface::kCursorUp: mouseCursorResID = CURSOR_UP; break;
|
||||
case plInputInterface::kCursorLeft: mouseCursorResID = CURSOR_LEFT; break;
|
||||
case plInputInterface::kCursorRight: mouseCursorResID = CURSOR_RIGHT; break;
|
||||
case plInputInterface::kCursorDown: mouseCursorResID = CURSOR_DOWN; break;
|
||||
case plInputInterface::kCursorPoised: mouseCursorResID = CURSOR_POISED; break;
|
||||
case plInputInterface::kCursorClicked: mouseCursorResID = CURSOR_CLICKED; break;
|
||||
case plInputInterface::kCursorUnClicked: mouseCursorResID = CURSOR_POISED; break;
|
||||
case plInputInterface::kCursorOpen: mouseCursorResID = CURSOR_OPEN; break;
|
||||
case plInputInterface::kCursorGrab: mouseCursorResID = CURSOR_GRAB; break;
|
||||
case plInputInterface::kCursorArrow: mouseCursorResID = CURSOR_ARROW; break;
|
||||
case plInputInterface::kCursor4WayDraggable: mouseCursorResID = CURSOR_4WAY_OPEN; break;
|
||||
case plInputInterface::kCursor4WayDragging: mouseCursorResID = CURSOR_4WAY_CLOSED; break;
|
||||
case plInputInterface::kCursorUpDownDraggable: mouseCursorResID = CURSOR_UPDOWN_OPEN; break;
|
||||
case plInputInterface::kCursorUpDownDragging: mouseCursorResID = CURSOR_UPDOWN_CLOSED; break;
|
||||
case plInputInterface::kCursorLeftRightDraggable: mouseCursorResID = CURSOR_LEFTRIGHT_OPEN; break;
|
||||
case plInputInterface::kCursorLeftRightDragging: mouseCursorResID = CURSOR_LEFTRIGHT_CLOSED; break;
|
||||
case plInputInterface::kCursorOfferBook: mouseCursorResID = CURSOR_OFFER_BOOK; break;
|
||||
case plInputInterface::kCursorOfferBookHilite: mouseCursorResID = CURSOR_OFFER_BOOK_HI; break;
|
||||
case plInputInterface::kCursorOfferBookClicked: mouseCursorResID = CURSOR_OFFER_BOOK_CLICKED; break;
|
||||
case plInputInterface::kCursorClickDisabled: mouseCursorResID = CURSOR_CLICK_DISABLED; break;
|
||||
case plInputInterface::kCursorHand: mouseCursorResID = CURSOR_HAND; break;
|
||||
case plInputInterface::kCursorUpward: mouseCursorResID = CURSOR_UPWARD; break;
|
||||
default: mouseCursorResID = CURSOR_OPEN; break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
plMouseDevice::NewCursor( mouseCursorResID );
|
||||
}
|
||||
}
|
||||
|
||||
//// IEval ///////////////////////////////////////////////////////////////////
|
||||
// Inherited from plSingleModifier, gets called once per IUpdate() loop.
|
||||
|
||||
hsBool plInputInterfaceMgr::IEval( double secs, hsScalar del, UInt32 dirty )
|
||||
{
|
||||
const char *inputEval = "Eval";
|
||||
plProfile_BeginLap(Input, inputEval);
|
||||
int i;
|
||||
|
||||
|
||||
// Let all our layers eval
|
||||
for( i = 0; i < fInterfaces.GetCount(); i++ )
|
||||
fInterfaces[ i ]->IEval( secs, del, dirty );
|
||||
|
||||
// Handle our message queue now
|
||||
for( i = 0; i < fMessageQueue.Count(); i++ )
|
||||
{
|
||||
// Can its layer handle it?
|
||||
if( !fMessageQueue[ i ]->GetSource()->IHandleCtrlCmd( fMessageQueue[ i ] ) )
|
||||
{
|
||||
// Nope, just dispatch it like normal
|
||||
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
|
||||
for (int j = 0; j < fReceivers.Count(); j++)
|
||||
pMsg->AddReceiver( fReceivers[ j ] );
|
||||
pMsg->SetControlActivated( fMessageQueue[i]->fControlActivated );
|
||||
pMsg->SetControlCode( fMessageQueue[i]->fControlCode );
|
||||
pMsg->SetControlPct(fMessageQueue[i]->fPct);
|
||||
pMsg->SetTurnToPt( fMessageQueue[i]->fPt );
|
||||
pMsg->SetCmdString(fMessageQueue[i]->GetCmdString());
|
||||
pMsg->SetSender( GetKey() );
|
||||
plgDispatch::MsgSend( pMsg );
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// send same msg over network to players
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
if (fMessageQueue[i]->fNetPropagateToPlayers)
|
||||
{
|
||||
pMsg = TRACKED_NEW plControlEventMsg;
|
||||
for (int j = 0; j < fReceivers.Count(); j++)
|
||||
if (fReceivers[j] == plNetClientApp::GetInstance()->GetLocalPlayerKey())
|
||||
pMsg->AddReceiver( fReceivers[j] );
|
||||
if (pMsg->GetNumReceivers())
|
||||
{
|
||||
pMsg->SetControlActivated( fMessageQueue[i]->fControlActivated );
|
||||
pMsg->SetControlCode( fMessageQueue[i]->fControlCode );
|
||||
pMsg->SetControlPct(fMessageQueue[i]->fPct);
|
||||
pMsg->SetTurnToPt( fMessageQueue[i]->fPt );
|
||||
pMsg->SetCmdString(fMessageQueue[i]->GetCmdString());
|
||||
pMsg->SetSender( GetKey() );
|
||||
pMsg->SetBCastFlag(plMessage::kNetPropagate | plMessage::kPropagateToModifiers |
|
||||
plMessage::kNetUseRelevanceRegions); // bcast only to other players who care about the region I'm in
|
||||
pMsg->SetBCastFlag(plMessage::kLocalPropagate, false);
|
||||
|
||||
plgDispatch::MsgSend( pMsg );
|
||||
}
|
||||
else
|
||||
delete pMsg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the message queue
|
||||
for( i = 0; i < fMessageQueue.Count(); i++ )
|
||||
delete fMessageQueue[ i ];
|
||||
fMessageQueue.SetCount( 0 );
|
||||
|
||||
plProfile_EndLap(Input, inputEval);
|
||||
return true;
|
||||
}
|
||||
|
||||
void plInputInterfaceMgr::ForceCursorHidden( hsBool requestedState )
|
||||
{
|
||||
if ( requestedState )
|
||||
{
|
||||
fForceCursorHiddenCount++;
|
||||
fForceCursorHidden = requestedState;
|
||||
}
|
||||
else
|
||||
{
|
||||
fForceCursorHiddenCount--;
|
||||
|
||||
// this happens way too often to leave in
|
||||
// hsAssert(fForceCursorHiddenCount>=0,"ForceCursorHidded: unhiding more times than hidden" );
|
||||
|
||||
#define OnlyHideCursorOnLast
|
||||
#ifdef OnlyHideCursorOnLast
|
||||
// is this is the last person... then really unforce hidding the mouse cursor
|
||||
if ( fForceCursorHiddenCount <= 0 )
|
||||
{
|
||||
#endif //OnlyHideCursorOnLast
|
||||
|
||||
fForceCursorHidden = requestedState;
|
||||
fForceCursorHiddenCount = 0;
|
||||
|
||||
#ifdef OnlyHideCursorOnLast
|
||||
}
|
||||
#endif //OnlyHideCursorOnLast
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
hsBool plInputInterfaceMgr::ICheckCursor(plInputInterface *iFace)
|
||||
{
|
||||
if( iFace->IsEnabled() && iFace->HasInterestingCursorID() )
|
||||
{
|
||||
if( iFace->GetCurrentCursorID() != fCurrentCursor )
|
||||
IUpdateCursor( iFace->GetCurrentCursorID() );
|
||||
if( iFace->GetCurrentCursorOpacity() != fCursorOpacity )
|
||||
{
|
||||
fCursorOpacity = iFace->GetCurrentCursorOpacity();
|
||||
plMouseDevice::SetCursorOpacity( fCursorOpacity );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//// MsgReceive //////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool plInputInterfaceMgr::MsgReceive( plMessage *msg )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
plEvalMsg *pEvalMsg = plEvalMsg::ConvertNoRef( msg );
|
||||
if( pEvalMsg )
|
||||
{
|
||||
IEval( pEvalMsg->GetTimeStamp(), pEvalMsg->DelSeconds(), false );
|
||||
return true;
|
||||
}
|
||||
|
||||
plInputEventMsg *ieMsg = plInputEventMsg::ConvertNoRef( msg );
|
||||
if( ieMsg != nil )
|
||||
{
|
||||
const char *inputIEM = "InputEventMsg";
|
||||
plProfile_BeginLap(Input, inputIEM);
|
||||
hsBool handled = false;
|
||||
UInt32 missedInputStartIdx = 0;
|
||||
plInputInterface *oldCurrentFocus = fCurrentFocus;
|
||||
|
||||
// Current focus (if there is one) gets first crack
|
||||
if( fCurrentFocus )
|
||||
{
|
||||
if( fCurrentFocus->IsEnabled() )
|
||||
{
|
||||
handled = (fCurrentFocus->ProcessKeyBindings(ieMsg) || fCurrentFocus->InterpretInputEvent(ieMsg));
|
||||
}
|
||||
}
|
||||
|
||||
if (!handled)
|
||||
{
|
||||
// Walk our stack
|
||||
for( i = 0; i < fInterfaces.GetCount(); i++ )
|
||||
{
|
||||
if( fInterfaces[ i ]->IsEnabled() && fInterfaces[ i ] != oldCurrentFocus)
|
||||
{
|
||||
// Try the key bindings first (common for all layers)
|
||||
if( fInterfaces[ i ]->ProcessKeyBindings( ieMsg ) || fInterfaces[ i ]->InterpretInputEvent( ieMsg ))
|
||||
{
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !handled )
|
||||
{
|
||||
// Fell all the way through the stack...must've been a very uninteresting message...
|
||||
if( plKeyEventMsg::ConvertNoRef( ieMsg ) && fDefaultCatcher != nil )
|
||||
{
|
||||
// But somebody loves those keys :)
|
||||
fDefaultCatcher->HandleKeyEvent( plKeyEventMsg::ConvertNoRef( ieMsg ) );
|
||||
}
|
||||
}
|
||||
missedInputStartIdx = i + 1;
|
||||
}
|
||||
|
||||
// Notify the rest of the interfaces in the stack that they missed the event ("lost focus", as it were)
|
||||
for (i = missedInputStartIdx; i < fInterfaces.GetCount(); i++)
|
||||
if (fInterfaces[i] != oldCurrentFocus)
|
||||
fInterfaces[i]->MissedInputEvent(ieMsg);
|
||||
|
||||
// Now we re-walk to see who's the new interested party. Note that we have to re-walk
|
||||
// because a key down may have changed some layer's interest in the cursor
|
||||
if( !fForceCursorHidden )
|
||||
{
|
||||
hsBool cursorHandled = false;
|
||||
if (fCurrentFocus)
|
||||
cursorHandled = ICheckCursor(fCurrentFocus);
|
||||
|
||||
if (!cursorHandled)
|
||||
{
|
||||
for( i = 0; i < fInterfaces.GetCount(); i++ )
|
||||
{
|
||||
if (ICheckCursor(fInterfaces[i]))
|
||||
{
|
||||
cursorHandled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!cursorHandled)
|
||||
{
|
||||
// NOBODY is interested in the mouse, so set to our default cursor
|
||||
IUpdateCursor( plInputInterface::kCursorUp );
|
||||
fCursorOpacity = 1.f;
|
||||
plMouseDevice::SetCursorOpacity( fCursorOpacity );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Special debug flag to force the cursor to be hidden
|
||||
if( fCursorOpacity != 0.f )
|
||||
{
|
||||
fCursorOpacity = 0.f;
|
||||
plMouseDevice::SetCursorOpacity( fCursorOpacity );
|
||||
}
|
||||
}
|
||||
plProfile_EndLap(Input, inputIEM);
|
||||
return true;
|
||||
}
|
||||
|
||||
plInputIfaceMgrMsg *mgrMsg = plInputIfaceMgrMsg::ConvertNoRef( msg );
|
||||
if( mgrMsg != nil )
|
||||
{
|
||||
if( mgrMsg->GetCommand() == plInputIfaceMgrMsg::kAddInterface )
|
||||
{
|
||||
IAddInterface( mgrMsg->GetIFace() );
|
||||
return true;
|
||||
}
|
||||
else if( mgrMsg->GetCommand() == plInputIfaceMgrMsg::kRemoveInterface )
|
||||
{
|
||||
IRemoveInterface( mgrMsg->GetIFace() );
|
||||
return true;
|
||||
}
|
||||
else if( mgrMsg->GetCommand() == plInputIfaceMgrMsg::kEnableClickables )
|
||||
{
|
||||
fClickEnabled = true;
|
||||
}
|
||||
else if( mgrMsg->GetCommand() == plInputIfaceMgrMsg::kDisableClickables )
|
||||
{
|
||||
fClickEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
plPlayerPageMsg *pPMsg = plPlayerPageMsg::ConvertNoRef( msg );
|
||||
if( pPMsg != nil && !pPMsg->fUnload)
|
||||
{
|
||||
if( pPMsg->fPlayer == plNetClientMgr::GetInstance()->GetLocalPlayerKey() )
|
||||
fReceivers.Append( pPMsg->fPlayer );
|
||||
else
|
||||
{
|
||||
int idx = fReceivers.Find( pPMsg->fPlayer );
|
||||
if( idx != fReceivers.kMissingIndex )
|
||||
fReceivers.Remove( idx );
|
||||
}
|
||||
}
|
||||
|
||||
plCmdIfaceModMsg *pCMsg = plCmdIfaceModMsg::ConvertNoRef( msg );
|
||||
if( pCMsg )
|
||||
{
|
||||
if( pCMsg->Cmd( plCmdIfaceModMsg::kAdd ) )
|
||||
{
|
||||
for( int i = 0; i < fReceivers.Count(); i++ )
|
||||
{
|
||||
if( fReceivers[i] == pCMsg->GetSender() )
|
||||
return true;
|
||||
}
|
||||
fReceivers.Append( pCMsg->GetSender() );
|
||||
return true;
|
||||
}
|
||||
else
|
||||
if( pCMsg->Cmd( plCmdIfaceModMsg::kRemove ) )
|
||||
{
|
||||
for( int i = 0; i < fReceivers.Count(); i++ )
|
||||
{
|
||||
if( fReceivers[ i ] == pCMsg->GetSender() )
|
||||
{
|
||||
fReceivers.Remove( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
plClientMsg *cMsg = plClientMsg::ConvertNoRef(msg);
|
||||
if (cMsg && cMsg->GetClientMsgFlag() == plClientMsg::kInitComplete)
|
||||
{
|
||||
// Backwards compatability hack:
|
||||
// We've loaded in the user prefs for input. If they bind movement
|
||||
// to an arrow, or numpad, and the other binding is free, automatically
|
||||
// bind the other one.
|
||||
plKeyMap *map = plAvatarInputInterface::GetInstance()->fControlMap;
|
||||
map->HandleAutoDualBinding(KEY_UP, KEY_NUMPAD8);
|
||||
map->HandleAutoDualBinding(KEY_DOWN, KEY_NUMPAD2);
|
||||
map->HandleAutoDualBinding(KEY_LEFT, KEY_NUMPAD4);
|
||||
map->HandleAutoDualBinding(KEY_RIGHT, KEY_NUMPAD6);
|
||||
|
||||
plgDispatch::Dispatch()->UnRegisterForExactType( plClientMsg::Index(), GetKey() );
|
||||
return true;
|
||||
}
|
||||
// Wasn't one we want. Was it one that one of our interfaces wanted?
|
||||
for( i = 0; i < fInterfaces.GetCount(); i++ )
|
||||
{
|
||||
if( fInterfaces[ i ]->MsgReceive( msg ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
// Nothing, pass on...
|
||||
return plSingleModifier::MsgReceive( msg );
|
||||
}
|
||||
|
||||
//// Read/Write //////////////////////////////////////////////////////////////
|
||||
|
||||
void plInputInterfaceMgr::Read( hsStream* s, hsResMgr* mgr )
|
||||
{
|
||||
plSingleModifier::Read( s, mgr );
|
||||
}
|
||||
|
||||
void plInputInterfaceMgr::Write( hsStream* s, hsResMgr* mgr )
|
||||
{
|
||||
plSingleModifier::Write( s, mgr );
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Key Maps ////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// IGetRoutedKeyMap ////////////////////////////////////////////////////////
|
||||
|
||||
plKeyMap *plInputInterfaceMgr::IGetRoutedKeyMap( ControlEventCode code )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for( i = 0; i < fInterfaces.GetCount(); i++ )
|
||||
{
|
||||
if( fInterfaces[ i ]->IOwnsControlCode( code ) )
|
||||
return fInterfaces[ i ]->fControlMap;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
//// IUnbind /////////////////////////////////////////////////////////////////
|
||||
// Unmaps any mappings with the given key. This prevents you from mapping
|
||||
// a single key to multiple commands. Currently inactive because some people
|
||||
// think it's a good idea to be able to do that.
|
||||
|
||||
#define ALLOW_MULTIPLE_CMDS_PER_KEY 1
|
||||
|
||||
void plInputInterfaceMgr::IUnbind( const plKeyCombo &key )
|
||||
{
|
||||
#if !(ALLOW_MULTIPLE_CMDS_PER_KEY)
|
||||
int i;
|
||||
|
||||
|
||||
for( i = 0; i < fInterfaces.GetCount(); i++ )
|
||||
fInterfaces[ i ]->fControlMap->UnmapKey( key );
|
||||
#endif
|
||||
}
|
||||
|
||||
void plInputInterfaceMgr::ClearAllKeyMaps()
|
||||
{
|
||||
for (int i = 0; i < fInterfaces.Count(); i++)
|
||||
fInterfaces[i]->ClearKeyMap();
|
||||
}
|
||||
|
||||
//// Binding Routers /////////////////////////////////////////////////////////
|
||||
|
||||
void plInputInterfaceMgr::BindAction( const plKeyCombo &key, ControlEventCode code )
|
||||
{
|
||||
plKeyMap *map = IGetRoutedKeyMap( code );
|
||||
if( map != nil )
|
||||
{
|
||||
// Use default prefs
|
||||
map->EnsureKeysClear( key, plKeyCombo::kUnmapped );
|
||||
map->BindKey( key, code );
|
||||
}
|
||||
RefreshInterfaceKeyMaps();
|
||||
}
|
||||
|
||||
void plInputInterfaceMgr::BindAction( const plKeyCombo &key1, const plKeyCombo &key2,
|
||||
ControlEventCode code )
|
||||
{
|
||||
plKeyMap *map = IGetRoutedKeyMap( code );
|
||||
if( map != nil )
|
||||
{
|
||||
// Force the bindings to each key, since the user specified both
|
||||
map->EnsureKeysClear( key1, key2 );
|
||||
map->BindKey( key1, code, plKeyMap::kFirstAlways );
|
||||
map->BindKey( key2, code, plKeyMap::kSecondAlways );
|
||||
}
|
||||
RefreshInterfaceKeyMaps();
|
||||
}
|
||||
|
||||
const plKeyBinding* plInputInterfaceMgr::FindBinding( ControlEventCode code )\
|
||||
{
|
||||
plKeyMap *map = IGetRoutedKeyMap( code );
|
||||
if( map != nil )
|
||||
{
|
||||
// Use default prefs
|
||||
return map->FindBinding(code);
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
void plInputInterfaceMgr::BindConsoleCmd( const plKeyCombo &key, const char *cmd, plKeyMap::BindPref pref /*= kNoPreference*/ )
|
||||
{
|
||||
// not sure why this is not for external...since its done thru the different interfaces?
|
||||
//#ifdef PLASMA_EXTERNAL_RELEASE
|
||||
// return;
|
||||
//#endif
|
||||
|
||||
plKeyMap *map = IGetRoutedKeyMap( B_CONTROL_CONSOLE_COMMAND );
|
||||
if( map != nil )
|
||||
{
|
||||
// Default prefs again
|
||||
map->EnsureKeysClear( key, plKeyCombo::kUnmapped );
|
||||
// BindKeyToConsoleCmd only works if the console command in question has already been assigned
|
||||
// to this map. Oftentimes, this isn't true when the user is binding console commands, so go ahead
|
||||
// and add the command to this map. If it's already added, this call will just quietly fail and
|
||||
// we're ok to continue
|
||||
map->AddConsoleCommand( cmd );
|
||||
map->BindKeyToConsoleCmd( key, cmd, pref );
|
||||
}
|
||||
RefreshInterfaceKeyMaps();
|
||||
}
|
||||
|
||||
const plKeyBinding* plInputInterfaceMgr::FindBindingByConsoleCmd( const char *cmd )
|
||||
{
|
||||
plKeyMap *map = IGetRoutedKeyMap( B_CONTROL_CONSOLE_COMMAND );
|
||||
if( map != nil )
|
||||
{
|
||||
return map->FindConsoleBinding(cmd);
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
//// InitDefaultKeyMap ///////////////////////////////////////////////////////
|
||||
|
||||
void plInputInterfaceMgr::InitDefaultKeyMap( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < fInterfaces.GetCount(); i++ )
|
||||
fInterfaces[ i ]->RestoreDefaultKeyMappings();
|
||||
|
||||
RefreshInterfaceKeyMaps();
|
||||
}
|
||||
|
||||
//// RefreshInterfaceKeyMaps /////////////////////////////////////////////////
|
||||
|
||||
void plInputInterfaceMgr::RefreshInterfaceKeyMaps( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for( i = 0; i < fInterfaces.GetCount(); i++ )
|
||||
fInterfaces[ i ]->RefreshKeyMap();
|
||||
}
|
||||
|
||||
//// WriteKeyMap /////////////////////////////////////////////////////////////
|
||||
|
||||
void plInputInterfaceMgr::WriteKeyMap( void )
|
||||
{
|
||||
#ifdef PLASMA_EXTERNAL_RELEASE
|
||||
return;
|
||||
#endif
|
||||
FILE* gKeyFile = 0;
|
||||
gKeyFile = hsFopen( "init\\keyboard.fni", "wt" );
|
||||
|
||||
if (gKeyFile)
|
||||
{
|
||||
fprintf(gKeyFile, "# To remap a control to a new key,\n");
|
||||
fprintf(gKeyFile, "# just change the key listed. \n");
|
||||
fprintf(gKeyFile, "# The list of available commands is at the bottom.\n");
|
||||
fprintf(gKeyFile, "# For keys with multi-character names \n");
|
||||
fprintf(gKeyFile, "# like F1 or Backspace, be sure to enter \n");
|
||||
fprintf(gKeyFile, "# the key name as it appears in the list \n");
|
||||
fprintf(gKeyFile, "# at the end of the file. \n");
|
||||
fprintf(gKeyFile, "#\n");
|
||||
fprintf(gKeyFile, "# Be sure to put quotes around the actual command\n");
|
||||
fprintf(gKeyFile, "#\n");
|
||||
fprintf(gKeyFile, "# To add modifiers to a key mapping (like ctrl or shift)\n");
|
||||
fprintf(gKeyFile, "# append _C for ctrl or _S for Shift (or both)\n");
|
||||
fprintf(gKeyFile, "# to the actual name of the key.\n");
|
||||
fprintf(gKeyFile, "#\n");
|
||||
fprintf(gKeyFile, "# For example, to map Control-Shift-W to Walk Forward\n");
|
||||
fprintf(gKeyFile, "# your key mapping entry would look like this:\n");
|
||||
fprintf(gKeyFile, "# Keyboard.BindAction W_C_S \"Walk Forward\"\n");
|
||||
fprintf(gKeyFile, "# This also works for console command bindings\n");
|
||||
|
||||
|
||||
fprintf(gKeyFile, "# Keyboard.BindAction \t\tKey1\tKey2\t\t\t\tControl\n");
|
||||
fprintf(gKeyFile, "#\n");
|
||||
// fprintf(gKeyFile, "Keyboard.ClearBindings\n");
|
||||
int i;
|
||||
|
||||
for( i = 0; i < fInterfaces.GetCount(); i++ )
|
||||
IWriteNonConsoleCmdKeys( fInterfaces[ i ]->fControlMap, gKeyFile );
|
||||
|
||||
fprintf(gKeyFile, "#\n");
|
||||
fprintf(gKeyFile, "# Console command bindings:\n");
|
||||
fprintf(gKeyFile, "#\n");
|
||||
fprintf(gKeyFile, "# Keyboard.BindConsoleCmd \tKey\t\t\tCommand\n");
|
||||
fprintf(gKeyFile, "#\n");
|
||||
|
||||
for( i = 0; i < fInterfaces.GetCount(); i++ )
|
||||
IWriteConsoleCmdKeys( fInterfaces[ i ]->fControlMap, gKeyFile );
|
||||
|
||||
fprintf(gKeyFile, "#\n");
|
||||
fprintf(gKeyFile, "# Available game commands:\n");
|
||||
fprintf(gKeyFile, "#\n");
|
||||
|
||||
for( int j = 0; plKeyMap::fCmdConvert[ j ].fCode != END_CONTROLS; j++ )
|
||||
{
|
||||
if( stricmp( plKeyMap::fCmdConvert[ j ].fDesc, "Run Modifier" ) == 0)
|
||||
continue;
|
||||
fprintf( gKeyFile, "# %s\n", plKeyMap::fCmdConvert[ j ].fDesc );
|
||||
}
|
||||
|
||||
fprintf(gKeyFile, "#\n");
|
||||
fprintf(gKeyFile, "# Key name list (for a-z or 0-9 just use the character)\n");
|
||||
fprintf(gKeyFile, "#\n");
|
||||
|
||||
Win32keyConvert* keyConvert = &plKeyMap::fKeyConversionEnglish[0];
|
||||
switch (plLocalization::GetLanguage())
|
||||
{
|
||||
case plLocalization::kFrench:
|
||||
keyConvert = &plKeyMap::fKeyConversionFrench[0];
|
||||
break;
|
||||
case plLocalization::kGerman:
|
||||
keyConvert = &plKeyMap::fKeyConversionGerman[0];
|
||||
break;
|
||||
//case plLocalization::kSpanish:
|
||||
// keyConvert = &plKeyMap::fKeyConversionSpanish[0];
|
||||
// break;
|
||||
//case plLocalization::kItalian:
|
||||
// keyConvert = &plKeyMap::fKeyConversionItalian[0];
|
||||
// break;
|
||||
// default is English
|
||||
}
|
||||
for (i = 0; keyConvert[i].fVKey != 0xffffffff; i++)
|
||||
{
|
||||
// if (stricmp(fKeyMap->fKeyConversion[i].fKeyName, "Shift") == 0)
|
||||
// continue;
|
||||
fprintf(gKeyFile, "# %s\n", keyConvert[i].fKeyName);
|
||||
}
|
||||
fclose(gKeyFile);
|
||||
}
|
||||
}
|
||||
|
||||
void plInputInterfaceMgr::SetCurrentFocus(plInputInterface *focus)
|
||||
{
|
||||
fCurrentFocus = focus;
|
||||
}
|
||||
|
||||
void plInputInterfaceMgr::ReleaseCurrentFocus(plInputInterface *focus)
|
||||
{
|
||||
if (fCurrentFocus == focus)
|
||||
fCurrentFocus = nil;
|
||||
}
|
||||
|
||||
|
||||
//// IKeyComboToString ///////////////////////////////////////////////////////
|
||||
// Uses static string, so don't call twice and expect the first result to
|
||||
// be still valid!
|
||||
|
||||
const char *plInputInterfaceMgr::IKeyComboToString( const plKeyCombo &combo )
|
||||
{
|
||||
static char str[ 64 ];
|
||||
bool unmapped = false;
|
||||
|
||||
|
||||
if( combo == plKeyCombo::kUnmapped )
|
||||
sprintf( str, "(unmapped)" );
|
||||
else
|
||||
{
|
||||
char *c = plKeyMap::ConvertVKeyToChar( combo.fKey );
|
||||
if( c != nil )
|
||||
strncpy( str, c, sizeof( str ) );
|
||||
else
|
||||
{
|
||||
if( isalnum( combo.fKey ) )
|
||||
{
|
||||
str[ 0 ] = (char)combo.fKey;
|
||||
str[ 1 ] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( str, "(unmapped)" );
|
||||
unmapped = true;
|
||||
}
|
||||
}
|
||||
if( !unmapped )
|
||||
{
|
||||
if( combo.fFlags & plKeyCombo::kCtrl )
|
||||
strcat( str, "_C" );
|
||||
if( combo.fFlags & plKeyCombo::kShift )
|
||||
strcat( str, "_S" );
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
//// IWriteNonConsoleCmdKeys /////////////////////////////////////////////////
|
||||
|
||||
void plInputInterfaceMgr::IWriteNonConsoleCmdKeys( plKeyMap *keyMap, FILE *keyFile )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for( i = 0; i < keyMap->GetNumBindings(); i++ )
|
||||
{
|
||||
const plKeyBinding &binding = keyMap->GetBinding( i );
|
||||
|
||||
if( binding.GetCode() == B_CONTROL_CONSOLE_COMMAND )
|
||||
continue;
|
||||
|
||||
char key1[ 64 ];
|
||||
strcpy( key1, IKeyComboToString( binding.GetKey1() ) );
|
||||
|
||||
const char *key2 = IKeyComboToString( binding.GetKey2() );
|
||||
|
||||
const char *desc = plInputMap::ConvertControlCodeToString( binding.GetCode() );
|
||||
|
||||
fprintf( keyFile, "Keyboard.BindAction \t\t%s\t%s\t\t\t\t\"%s\"\n", key1, key2, desc );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//// IWriteConsoleCmdKeys ////////////////////////////////////////////////////
|
||||
|
||||
void plInputInterfaceMgr::IWriteConsoleCmdKeys( plKeyMap *keyMap, FILE *keyFile )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for( i = 0; i < keyMap->GetNumBindings(); i++ )
|
||||
{
|
||||
const plKeyBinding &binding = keyMap->GetBinding( i );
|
||||
|
||||
if( binding.GetCode() != B_CONTROL_CONSOLE_COMMAND )
|
||||
continue;
|
||||
|
||||
// Our bindConsoleCmd console command (echo echo) only takes 1 key combo, not 2,
|
||||
// so as not to confuse people. Or something. So if we got two bindings, we print
|
||||
// 2 commands, which is perfectly valid
|
||||
// if( binding.GetKey1() != plKeyCombo::kUnmapped )
|
||||
// {
|
||||
const char *key = IKeyComboToString( binding.GetKey1() );
|
||||
fprintf( keyFile, "Keyboard.BindConsoleCmd\t%s\t\t\t\"%s\"\n", key, binding.GetExtendedString() );
|
||||
// }
|
||||
|
||||
if( binding.GetKey2() != plKeyCombo::kUnmapped )
|
||||
{
|
||||
const char *key = IKeyComboToString( binding.GetKey2() );
|
||||
fprintf( keyFile, "Keyboard.BindConsoleCmd\t%s\t\t\t\"%s\"\n", key, binding.GetExtendedString() );
|
||||
}
|
||||
}
|
||||
}
|
202
Sources/Plasma/PubUtilLib/plInputCore/plInputInterfaceMgr.h
Normal file
202
Sources/Plasma/PubUtilLib/plInputCore/plInputInterfaceMgr.h
Normal file
@ -0,0 +1,202 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// plInputInterfaceMgr.h - The manager of all input interface layers //
|
||||
// //
|
||||
//// History /////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// 2.20.02 mcn - Created. //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _plInputInterfaceMgr_h
|
||||
#define _plInputInterfaceMgr_h
|
||||
|
||||
#include "../pnModifier/plSingleModifier.h"
|
||||
#include "hsTemplates.h"
|
||||
#include "hsGeometry3.h"
|
||||
#include "../pnInputCore/plKeyMap.h"
|
||||
|
||||
//// Class Definition ////////////////////////////////////////////////////////
|
||||
|
||||
class hsStream;
|
||||
class hsResMgr;
|
||||
class plInputInterface;
|
||||
//class plKeyMap;
|
||||
enum plKeyDef;
|
||||
enum ControlEventCode;
|
||||
class plKey;
|
||||
class plCtrlCmd;
|
||||
class plKeyCombo;
|
||||
class plDefaultKeyCatcher;
|
||||
class plKeyBinding;
|
||||
|
||||
class plInputInterfaceMgr : public plSingleModifier
|
||||
{
|
||||
protected:
|
||||
|
||||
static plInputInterfaceMgr *fInstance;
|
||||
|
||||
hsTArray<plInputInterface *> fInterfaces;
|
||||
hsTArray<plCtrlCmd *> fMessageQueue;
|
||||
hsTArray<plKey> fReceivers;
|
||||
|
||||
#ifdef MCN_DISABLE_OLD_WITH_NEW_HACK
|
||||
hsTArray<ControlEventCode> fDisabledCodes;
|
||||
hsTArray<UInt32> fDisabledKeys;
|
||||
#endif
|
||||
|
||||
hsBool fClickEnabled;
|
||||
Int32 fCurrentCursor;
|
||||
hsScalar fCursorOpacity;
|
||||
hsBool fForceCursorHidden;
|
||||
Int32 fForceCursorHiddenCount;
|
||||
plInputInterface *fCurrentFocus;
|
||||
plDefaultKeyCatcher *fDefaultCatcher;
|
||||
|
||||
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty );
|
||||
|
||||
void IAddInterface( plInputInterface *iface );
|
||||
void IRemoveInterface( plInputInterface *iface );
|
||||
|
||||
void IUpdateCursor( Int32 newCursor );
|
||||
hsBool ICheckCursor(plInputInterface *iFace); // returns true if the iface changed cursor settings
|
||||
|
||||
void IWriteConsoleCmdKeys( plKeyMap *keyMap, FILE *keyFile );
|
||||
void IWriteNonConsoleCmdKeys( plKeyMap *keyMap, FILE *keyFile );
|
||||
|
||||
plKeyMap *IGetRoutedKeyMap( ControlEventCode code ); // Null for console commands
|
||||
void IUnbind( const plKeyCombo &key );
|
||||
|
||||
const char *IKeyComboToString( const plKeyCombo &combo );
|
||||
|
||||
public:
|
||||
|
||||
plInputInterfaceMgr();
|
||||
virtual ~plInputInterfaceMgr();
|
||||
|
||||
CLASSNAME_REGISTER( plInputInterfaceMgr );
|
||||
GETINTERFACE_ANY( plInputInterfaceMgr, plSingleModifier );
|
||||
|
||||
virtual hsBool MsgReceive( plMessage *msg );
|
||||
virtual void Read( hsStream* s, hsResMgr* mgr );
|
||||
virtual void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
void Init( void );
|
||||
void Shutdown( void );
|
||||
|
||||
void InitDefaultKeyMap( void );
|
||||
void WriteKeyMap( void );
|
||||
void RefreshInterfaceKeyMaps( void );
|
||||
|
||||
void SetCurrentFocus(plInputInterface *focus);
|
||||
void ReleaseCurrentFocus(plInputInterface *focus);
|
||||
void SetDefaultKeyCatcher( plDefaultKeyCatcher *c ) { fDefaultCatcher = c; }
|
||||
|
||||
hsBool IsClickEnabled() { return fClickEnabled; }
|
||||
|
||||
void ForceCursorHidden( hsBool requestedState );
|
||||
|
||||
// Binding routers
|
||||
void BindAction( const plKeyCombo &key, ControlEventCode code );
|
||||
void BindAction( const plKeyCombo &key1, const plKeyCombo &key2, ControlEventCode code );
|
||||
void BindConsoleCmd( const plKeyCombo &key, const char *cmd, plKeyMap::BindPref pref = plKeyMap::kNoPreference );
|
||||
|
||||
const plKeyBinding* FindBinding( ControlEventCode code );
|
||||
const plKeyBinding* FindBindingByConsoleCmd( const char *cmd );
|
||||
|
||||
void ClearAllKeyMaps();
|
||||
void ResetClickableState();
|
||||
static plInputInterfaceMgr *GetInstance( void ) { return fInstance; }
|
||||
};
|
||||
|
||||
//// plCtrlCmd ///////////////////////////////////////////////////////////////
|
||||
// Networkable helper class that represents a single control statement
|
||||
|
||||
class plCtrlCmd
|
||||
{
|
||||
private:
|
||||
char* fCmd;
|
||||
plInputInterface *fSource;
|
||||
|
||||
public:
|
||||
plCtrlCmd( plInputInterface *source ) : fCmd(nil),fPct(1.0f), fSource(source) {;}
|
||||
~plCtrlCmd() { delete [] fCmd; }
|
||||
|
||||
const char* GetCmdString() { return fCmd; }
|
||||
void SetCmdString(const char* cs) { delete [] fCmd; fCmd=hsStrcpy(cs); }
|
||||
|
||||
ControlEventCode fControlCode;
|
||||
hsBool fControlActivated;
|
||||
hsPoint3 fPt;
|
||||
hsScalar fPct;
|
||||
|
||||
hsBool fNetPropagateToPlayers;
|
||||
|
||||
void Read( hsStream* s, hsResMgr* mgr );
|
||||
void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
plInputInterface *GetSource( void ) const { return fSource; }
|
||||
};
|
||||
|
||||
//// Tiny Virtual Class For The Default Key Processor ////////////////////////
|
||||
//
|
||||
// Basically, if you want to be the one to catch the leftover key events,
|
||||
// derive from this class and pass yourself to inputIFaceMgr.
|
||||
// (it'll auto-tell inputIFaceMgr when it goes away)
|
||||
//
|
||||
// Note: if you want to do more than just get the darned key event (like
|
||||
// mouse events or key bindings or change the cursor or the like), don't do
|
||||
// this; create your own plInputInterface instead.
|
||||
|
||||
class plKeyEventMsg;
|
||||
class plDefaultKeyCatcher
|
||||
{
|
||||
public:
|
||||
virtual ~plDefaultKeyCatcher();
|
||||
virtual void HandleKeyEvent( plKeyEventMsg *eventMsg ) = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif // _plInputInterfaceMgr_h
|
744
Sources/Plasma/PubUtilLib/plInputCore/plInputManager.cpp
Normal file
744
Sources/Plasma/PubUtilLib/plInputCore/plInputManager.cpp
Normal file
@ -0,0 +1,744 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
#include "hsConfig.h"
|
||||
#include "hsWindows.h"
|
||||
|
||||
// plInputManager.cpp
|
||||
#define DIRECTINPUT_VERSION 0x0800
|
||||
#include <dinput.h>
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "plInputManager.h"
|
||||
#include "plPipeline.h"
|
||||
#include "plInputDevice.h"
|
||||
#include "plDInputDevice.h"
|
||||
#include "../plMessage/plInputEventMsg.h"
|
||||
#include "plInputInterfaceMgr.h"
|
||||
#include "hsStream.h"
|
||||
#include "../pnKeyedObject/plKey.h"
|
||||
#include "../pnKeyedObject/plFixedKey.h"
|
||||
#include "hsResMgr.h"
|
||||
#include "hsTimer.h"
|
||||
#include "plgDispatch.h"
|
||||
#include "../pnMessage/plTimeMsg.h"
|
||||
#include "../pnMessage/plCmdIfaceModMsg.h"
|
||||
#include "../pnMessage/plPlayerPageMsg.h"
|
||||
|
||||
hsBool plInputManager::fUseDInput = false;
|
||||
UInt8 plInputManager::bRecenterMouse = 0;
|
||||
HWND plInputManager::fhWnd = nil;
|
||||
#define NUM_ACTIONS 17
|
||||
|
||||
struct plDIDevice
|
||||
{
|
||||
plDIDevice() : fDevice(nil), fCaps(nil) {;}
|
||||
plDIDevice(IDirectInputDevice8* _device) : fCaps(nil) { fDevice = _device;}
|
||||
IDirectInputDevice8* fDevice;
|
||||
DIDEVCAPS* fCaps;
|
||||
};
|
||||
|
||||
struct plDInput
|
||||
{
|
||||
plDInput() :
|
||||
fDInput(nil),
|
||||
fActionFormat(nil)
|
||||
{;}
|
||||
IDirectInput8* fDInput;
|
||||
hsTArray<plDIDevice*> fSticks;
|
||||
DIACTIONFORMAT* fActionFormat;
|
||||
};
|
||||
|
||||
class plDInputMgr
|
||||
{
|
||||
public:
|
||||
plDInputMgr();
|
||||
~plDInputMgr();
|
||||
|
||||
void Init(HINSTANCE hInst, HWND hWnd);
|
||||
void Update();
|
||||
void AddDevice(IDirectInputDevice8* device);
|
||||
void ConfigureDevice();
|
||||
virtual hsBool MsgReceive(plMessage* msg);
|
||||
|
||||
// dinput callback functions
|
||||
static int __stdcall EnumGamepadCallback(const DIDEVICEINSTANCE* device, void* pRef);
|
||||
// I should be using these but they don't work...
|
||||
// static int __stdcall SetAxisRange(const DIDEVICEOBJECTINSTANCE* obj, void* pRef);
|
||||
// static int __stdcall EnumSuitableDevices(const struct DIDEVICEINSTANCEA* devInst, struct IDirectInputDevice8* dev, unsigned long why, unsigned long devRemaining, void* pRef);
|
||||
|
||||
protected:
|
||||
plDInput* fDI;
|
||||
hsTArray<plDInputDevice*> fInputDevice;
|
||||
static DIACTION fActionMap[];
|
||||
HWND fhWnd;
|
||||
};
|
||||
// function pointers to dinput callbacks
|
||||
typedef int (__stdcall * Pfunc1) (const DIDEVICEINSTANCE* device, void* pRef);
|
||||
// I should need these...
|
||||
//typedef int (__stdcall * Pfunc2) (const DIDEVICEOBJECTINSTANCE* device, void* pRef);
|
||||
//typedef int (__stdcall * Pfunc3) (const struct DIDEVICEINSTANCEA* devInst, struct IDirectInputDevice8* dev, unsigned long why, unsigned long devRemaining, void* pRef);
|
||||
|
||||
|
||||
plInputManager* plInputManager::fInstance = nil;
|
||||
|
||||
plInputManager::plInputManager( HWND hWnd ) :
|
||||
fDInputMgr(nil),
|
||||
fInterfaceMgr(nil)
|
||||
{
|
||||
fhWnd = hWnd;
|
||||
fInstance = this;
|
||||
fActive = false;
|
||||
fFirstActivated = false;
|
||||
fMouseScale = 1.f;
|
||||
}
|
||||
|
||||
plInputManager::plInputManager() :
|
||||
fDInputMgr(nil),
|
||||
fInterfaceMgr(nil)
|
||||
{
|
||||
fInstance = this;
|
||||
fActive = false;
|
||||
fFirstActivated = false;
|
||||
fMouseScale = 1.f;
|
||||
}
|
||||
|
||||
plInputManager::~plInputManager()
|
||||
{
|
||||
fInterfaceMgr->Shutdown();
|
||||
fInterfaceMgr = nil;
|
||||
|
||||
for (int i = 0; i < fInputDevices.Count(); i++)
|
||||
{
|
||||
fInputDevices[i]->Shutdown();
|
||||
delete(fInputDevices[i]);
|
||||
}
|
||||
if (fDInputMgr)
|
||||
delete fDInputMgr;
|
||||
}
|
||||
|
||||
//static
|
||||
void plInputManager::SetRecenterMouse(hsBool b)
|
||||
{
|
||||
if (b)
|
||||
bRecenterMouse++;
|
||||
else if (bRecenterMouse > 0)
|
||||
bRecenterMouse--;
|
||||
}
|
||||
|
||||
|
||||
void plInputManager::RecenterCursor()
|
||||
{
|
||||
RECT rect;
|
||||
GetClientRect(fhWnd, &rect);
|
||||
POINT pt;
|
||||
// pt.y = ( (rect.bottom - rect.top) / 2 ) / fInstance->fMouseScale;
|
||||
// pt.x = ( (rect.right - rect.left) / 2 ) / fInstance->fMouseScale;
|
||||
ClientToScreen(fhWnd, &pt);
|
||||
SetCursorPos( pt.x, pt.y );
|
||||
}
|
||||
void plInputManager::CreateInterfaceMod(plPipeline* p)
|
||||
{
|
||||
fInterfaceMgr = TRACKED_NEW plInputInterfaceMgr();
|
||||
fInterfaceMgr->Init();
|
||||
}
|
||||
|
||||
void plInputManager::InitDInput(HINSTANCE hInst, HWND hWnd)
|
||||
{
|
||||
if (fUseDInput)
|
||||
{
|
||||
fDInputMgr = TRACKED_NEW plDInputMgr;
|
||||
fDInputMgr->Init(hInst, hWnd);
|
||||
}
|
||||
}
|
||||
|
||||
hsBool plInputManager::MsgReceive(plMessage* msg)
|
||||
{
|
||||
for (int i=0; i<fInputDevices.Count(); i++)
|
||||
if (fInputDevices[i]->MsgReceive(msg))
|
||||
return true;
|
||||
|
||||
if (fDInputMgr)
|
||||
return fDInputMgr->MsgReceive(msg);
|
||||
|
||||
return hsKeyedObject::MsgReceive(msg);
|
||||
}
|
||||
|
||||
void plInputManager::Update()
|
||||
{
|
||||
if (fDInputMgr)
|
||||
fDInputMgr->Update();
|
||||
}
|
||||
|
||||
void plInputManager::SetMouseScale( hsScalar s )
|
||||
{
|
||||
/* RECT rect;
|
||||
POINT currPos;
|
||||
|
||||
|
||||
// Gotta make sure to move the mouse to the correct new position for the scale
|
||||
GetClientRect( fhWnd, &rect );
|
||||
GetCursorPos( &currPos );
|
||||
ScreenToClient( fhWnd, &currPos );
|
||||
|
||||
float x = (float)currPos.x / rect.right;
|
||||
float y = (float)currPos.y / rect.bottom;
|
||||
|
||||
x *= fMouseScale; y *= fMouseScale;
|
||||
|
||||
fMouseScale = s;
|
||||
|
||||
// Refreshes all of the input devices so that they can reset mouse limits, etc
|
||||
RECT rect2 = rect;
|
||||
rect2.right /= fMouseScale;
|
||||
rect2.bottom /= fMouseScale;
|
||||
::MapWindowPoints( fhWnd, NULL, (POINT *)&rect2, 2 );
|
||||
BOOL ret = ::ClipCursor( &rect );
|
||||
|
||||
// Now move the cursor to the right spot
|
||||
|
||||
currPos.x = ( x / fMouseScale ) * rect.right;
|
||||
currPos.y = ( y / fMouseScale ) * rect.bottom;
|
||||
|
||||
ClientToScreen( fhWnd, &currPos );
|
||||
SetCursorPos( currPos.x, currPos.y );
|
||||
*/
|
||||
}
|
||||
|
||||
// Sometimes the keyboard driver "helps" us translating a key involved in a key
|
||||
// combo. For example pressing shif-numpad8 will actually generate a KEY_UP event,
|
||||
// the same as the up arrow. This function undoes that translation.
|
||||
plKeyDef plInputManager::UntranslateKey(plKeyDef key, hsBool extended)
|
||||
{
|
||||
if (!extended)
|
||||
{
|
||||
if (key == KEY_UP)
|
||||
return KEY_NUMPAD8;
|
||||
if (key == KEY_DOWN)
|
||||
return KEY_NUMPAD2;
|
||||
if (key == KEY_LEFT)
|
||||
return KEY_NUMPAD4;
|
||||
if (key == KEY_RIGHT)
|
||||
return KEY_NUMPAD6;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
#if HS_BUILD_FOR_WIN32
|
||||
/** Determines if we need to hackily flush cursor updates
|
||||
* \remarks Normally, we would just call SetCursorPos directly. However, in Windows 10's
|
||||
* 2017 Fall Creator's Update, SetCursorPos, GetCursorPos, and WM_MOUSEMOVE are buggy.
|
||||
* Research done by Deledrius matches my independent observations and failed fixes:
|
||||
* https://discourse.libsdl.org/t/win10-fall-creators-update-breaks-mouse-warping/23526
|
||||
* Many thanks to these fine folks who work on libsdl!
|
||||
*/
|
||||
static bool INeedsWin10CursorHack()
|
||||
{
|
||||
// According to Chromium, Microsoft will be fixing the cursor bug in the next build
|
||||
// of Windows 10, so we only need to test for the dreaded 2017 FCU...
|
||||
// Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=781182#c15
|
||||
// UPDATE: Bug is still present in the April 2018 Update (build 17134)...
|
||||
// so this bandage will now be applied to anything 2017 FCU and later :(
|
||||
const RTL_OSVERSIONINFOW& version = hsGetWindowsVersion();
|
||||
return version.dwMajorVersion == 10 && version.dwBuildNumber >= 16299;
|
||||
}
|
||||
|
||||
#endif // HS_BUILD_FOR_WIN32
|
||||
|
||||
void plInputManager::HandleWin32ControlEvent(UINT message, WPARAM Wparam, LPARAM Lparam, HWND hWnd)
|
||||
{
|
||||
if( !fhWnd )
|
||||
fhWnd = hWnd;
|
||||
|
||||
hsBool bExtended;
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case SYSKEYDOWN:
|
||||
case KEYDOWN:
|
||||
{
|
||||
bExtended = Lparam >> 24 & 1;
|
||||
hsBool bRepeat = ((Lparam >> 29) & 0xf) != 0;
|
||||
for (int i=0; i<fInputDevices.Count(); i++)
|
||||
fInputDevices[i]->HandleKeyEvent( KEYDOWN, UntranslateKey((plKeyDef)Wparam, bExtended), true, bRepeat );
|
||||
}
|
||||
break;
|
||||
case SYSKEYUP:
|
||||
case KEYUP:
|
||||
{
|
||||
bExtended = Lparam >> 24 & 1;
|
||||
for (int i=0; i<fInputDevices.Count(); i++)
|
||||
fInputDevices[i]->HandleKeyEvent( KEYUP, UntranslateKey((plKeyDef)Wparam, bExtended), false, false );
|
||||
}
|
||||
break;
|
||||
case MOUSEWHEEL:
|
||||
{
|
||||
plMouseEventMsg* pMsg = TRACKED_NEW plMouseEventMsg;
|
||||
int zDelta = GET_WHEEL_DELTA_WPARAM(Wparam);
|
||||
pMsg->SetWheelDelta((float)zDelta);
|
||||
if (zDelta < 0)
|
||||
pMsg->SetButton(kWheelNeg);
|
||||
else
|
||||
pMsg->SetButton(kWheelPos);
|
||||
|
||||
RECT rect;
|
||||
GetClientRect(hWnd, &rect);
|
||||
pMsg->SetXPos(LOWORD(Lparam) / (float)rect.right);
|
||||
pMsg->SetYPos(HIWORD(Lparam) / (float)rect.bottom);
|
||||
|
||||
pMsg->Send();
|
||||
}
|
||||
break;
|
||||
case MOUSEMOVE:
|
||||
case L_BUTTONDN:
|
||||
case L_BUTTONUP:
|
||||
case R_BUTTONDN:
|
||||
case R_BUTTONUP:
|
||||
case L_BUTTONDBLCLK:
|
||||
case R_BUTTONDBLCLK:
|
||||
case M_BUTTONDN:
|
||||
case M_BUTTONUP:
|
||||
{
|
||||
|
||||
RECT rect;
|
||||
GetClientRect(hWnd, &rect);
|
||||
|
||||
plIMouseXEventMsg* pXMsg = TRACKED_NEW plIMouseXEventMsg;
|
||||
plIMouseYEventMsg* pYMsg = TRACKED_NEW plIMouseYEventMsg;
|
||||
plIMouseBEventMsg* pBMsg = TRACKED_NEW plIMouseBEventMsg;
|
||||
|
||||
pXMsg->fWx = LOWORD(Lparam);
|
||||
pXMsg->fX = (float)LOWORD(Lparam) / (float)rect.right;
|
||||
pYMsg->fWy = HIWORD(Lparam);
|
||||
pYMsg->fY = (float)HIWORD(Lparam) / (float)rect.bottom;
|
||||
|
||||
// Apply mouse scale
|
||||
// pXMsg->fX *= fMouseScale;
|
||||
// pYMsg->fY *= fMouseScale;
|
||||
|
||||
if (Wparam & MK_LBUTTON && message != L_BUTTONUP)
|
||||
{
|
||||
pBMsg->fButton |= kLeftButtonDown;
|
||||
}
|
||||
else
|
||||
{
|
||||
pBMsg->fButton |= kLeftButtonUp;
|
||||
}
|
||||
|
||||
if (Wparam & MK_RBUTTON && message != R_BUTTONUP)
|
||||
{
|
||||
pBMsg->fButton |= kRightButtonDown;
|
||||
}
|
||||
else
|
||||
{
|
||||
pBMsg->fButton |= kRightButtonUp;
|
||||
}
|
||||
|
||||
if (Wparam & MK_MBUTTON && message != M_BUTTONUP)
|
||||
{
|
||||
pBMsg->fButton |= kMiddleButtonDown;
|
||||
}
|
||||
else
|
||||
{
|
||||
pBMsg->fButton |= kMiddleButtonUp;
|
||||
}
|
||||
|
||||
if( message == L_BUTTONDBLCLK )
|
||||
pBMsg->fButton |= kLeftButtonDblClk; // We send the double clicks separately
|
||||
if( message == R_BUTTONDBLCLK )
|
||||
pBMsg->fButton |= kRightButtonDblClk;
|
||||
|
||||
for (int i=0; i<fInputDevices.Count(); i++)
|
||||
{
|
||||
fInputDevices[i]->MsgReceive(pXMsg);
|
||||
fInputDevices[i]->MsgReceive(pYMsg);
|
||||
fInputDevices[i]->MsgReceive(pBMsg);
|
||||
}
|
||||
POINT pt;
|
||||
|
||||
if (RecenterMouse() && (pXMsg->fX <= 0.1 || pXMsg->fX >= 0.9) )
|
||||
{
|
||||
pt.x = (rect.right - rect.left) / 2;
|
||||
pt.y = HIWORD(Lparam);
|
||||
if (INeedsWin10CursorHack()) {
|
||||
pXMsg->fWx = pt.x;
|
||||
pXMsg->fX = pt.x / (float)rect.right;
|
||||
for (int i = 0; i < fInputDevices.Count(); i++)
|
||||
fInputDevices[i]->MsgReceive(pXMsg);
|
||||
}
|
||||
ClientToScreen(hWnd, &pt);
|
||||
SetCursorPos( pt.x, pt.y );
|
||||
}
|
||||
else
|
||||
if (RecenterMouse() && (pYMsg->fY <= 0.1 || pYMsg->fY >= 0.9) )
|
||||
{
|
||||
pt.y = (rect.bottom - rect.top) / 2;
|
||||
pt.x = LOWORD(Lparam);
|
||||
if (INeedsWin10CursorHack()) {
|
||||
pYMsg->fWy = pt.y;
|
||||
pYMsg->fY = pYMsg->fWy / (float)rect.bottom;
|
||||
for (int i = 0; i < fInputDevices.Count(); i++)
|
||||
fInputDevices[i]->MsgReceive(pYMsg);
|
||||
}
|
||||
|
||||
ClientToScreen(hWnd, &pt);
|
||||
SetCursorPos( pt.x, pt.y );
|
||||
}
|
||||
if (RecenterMouse() && Lparam == 0)
|
||||
{
|
||||
pt.y = (rect.bottom - rect.top) / 2;
|
||||
pt.x = (rect.right - rect.left) / 2;
|
||||
if (INeedsWin10CursorHack()) {
|
||||
pXMsg->fWx = pt.x;
|
||||
pXMsg->fX = pXMsg->fWx / (float)rect.right;
|
||||
pYMsg->fWy = pt.y;
|
||||
pYMsg->fY = pYMsg->fWy / (float)rect.bottom;
|
||||
|
||||
for (int i = 0; i < fInputDevices.Count(); i++) {
|
||||
fInputDevices[i]->MsgReceive(pXMsg);
|
||||
fInputDevices[i]->MsgReceive(pYMsg);
|
||||
}
|
||||
}
|
||||
ClientToScreen(hWnd, &pt);
|
||||
SetCursorPos( pt.x, pt.y );
|
||||
}
|
||||
delete(pXMsg);
|
||||
delete(pYMsg);
|
||||
delete(pBMsg);
|
||||
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
case WM_ACTIVATE:
|
||||
{
|
||||
bool activated = ( LOWORD( Wparam ) == WA_INACTIVE ) ? false : true;
|
||||
Activate( activated );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//// Activate ////////////////////////////////////////////////////////////////
|
||||
// Handles what happens when the app (window) activates/deactivates
|
||||
|
||||
void plInputManager::Activate( bool activating )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for( i = 0; i < fInputDevices.GetCount(); i++ )
|
||||
fInputDevices[ i ]->HandleWindowActivate( activating, fhWnd );
|
||||
|
||||
fActive = activating;
|
||||
fFirstActivated = true;
|
||||
}
|
||||
|
||||
//// AddInputDevice //////////////////////////////////////////////////////////
|
||||
|
||||
void plInputManager::AddInputDevice( plInputDevice *pDev )
|
||||
{
|
||||
fInputDevices.Append( pDev );
|
||||
if( fFirstActivated )
|
||||
pDev->HandleWindowActivate( fActive, fhWnd );
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// dinput manager
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
plDInputMgr::plDInputMgr() :
|
||||
fDI(nil)
|
||||
{
|
||||
fDI = TRACKED_NEW plDInput;
|
||||
}
|
||||
|
||||
plDInputMgr::~plDInputMgr()
|
||||
{
|
||||
if (fDI)
|
||||
{
|
||||
for (int i = 0; i < fDI->fSticks.Count(); i++)
|
||||
{
|
||||
plDIDevice* pD = fDI->fSticks[i];
|
||||
pD->fDevice->Release();
|
||||
delete(pD->fCaps);
|
||||
delete(pD);
|
||||
}
|
||||
fDI->fSticks.SetCountAndZero(0);
|
||||
delete(fDI->fActionFormat);
|
||||
fDI->fDInput->Release();
|
||||
for(int j = 0; j < fInputDevice.Count(); j++)
|
||||
delete(fInputDevice[j]);
|
||||
fInputDevice.SetCountAndZero(0);
|
||||
delete fDI;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void plDInputMgr::Init(HINSTANCE hInst, HWND hWnd)
|
||||
{
|
||||
|
||||
HRESULT hr;
|
||||
hr = DirectInput8Create(hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&fDI->fDInput, NULL);
|
||||
hsAssert(!hr, "failed to initialize directInput!");
|
||||
// enumerate game controllers
|
||||
Pfunc1 fPtr = &plDInputMgr::EnumGamepadCallback;
|
||||
int i = 0;
|
||||
|
||||
|
||||
// set up the action mapping
|
||||
fDI->fActionFormat = TRACKED_NEW DIACTIONFORMAT;
|
||||
fDI->fActionFormat->dwSize = sizeof(DIACTIONFORMAT);
|
||||
fDI->fActionFormat->dwActionSize = sizeof(DIACTION);
|
||||
fDI->fActionFormat->dwDataSize = NUM_ACTIONS * sizeof(DWORD);
|
||||
fDI->fActionFormat->dwNumActions = NUM_ACTIONS;
|
||||
fDI->fActionFormat->guidActionMap = PL_ACTION_GUID;
|
||||
fDI->fActionFormat->dwGenre = DIVIRTUAL_FIGHTING_THIRDPERSON;
|
||||
fDI->fActionFormat->rgoAction = fActionMap;
|
||||
fDI->fActionFormat->dwBufferSize = 16;
|
||||
fDI->fActionFormat->lAxisMin = -1000;
|
||||
fDI->fActionFormat->lAxisMax = 1000;
|
||||
sprintf( fDI->fActionFormat->tszActionMap, "Plasma 2.0 Game Actions" );
|
||||
|
||||
// this call should not work:
|
||||
fDI->fDInput->EnumDevices(DI8DEVCLASS_GAMECTRL, fPtr, fDI, DIEDFL_ATTACHEDONLY);
|
||||
|
||||
// apply the mapping to the game controller
|
||||
// this is the correct <but broken> way to apply the action map:
|
||||
// Pfunc3 fPtr3 = &plDInputMgr::EnumSuitableDevices;
|
||||
// hr = fDI->fDInput->EnumDevicesBySemantics(NULL, fDI->fActionFormat, EnumSuitableDevices, fDI, NULL);
|
||||
|
||||
|
||||
for (i = 0; i < fDI->fSticks.Count(); i++)
|
||||
{
|
||||
fDI->fSticks[i]->fCaps = TRACKED_NEW DIDEVCAPS;
|
||||
fDI->fSticks[i]->fCaps->dwSize = sizeof(DIDEVCAPS);
|
||||
hr = fDI->fSticks[i]->fDevice->GetCapabilities(fDI->fSticks[i]->fCaps);
|
||||
hsAssert(!hr, "Unable to acquire devcaps in DInput Device!");
|
||||
hr = fDI->fSticks[i]->fDevice->Acquire();
|
||||
hsAssert(!hr, "Unable to acquire DInput Device!");
|
||||
}
|
||||
|
||||
fhWnd = hWnd;
|
||||
|
||||
for (i = 0; i < fDI->fSticks.Count(); i++)
|
||||
fInputDevice.Append( TRACKED_NEW plDInputDevice );
|
||||
}
|
||||
|
||||
void plDInputMgr::Update()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (!fDI->fSticks.Count())
|
||||
return;
|
||||
|
||||
// Poll the devices to read the current state
|
||||
for (int i = 0; i < fDI->fSticks.Count(); i++)
|
||||
{
|
||||
hr = fDI->fSticks[i]->fDevice->Poll();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// Attempt to reacquire joystick
|
||||
while(hr == DIERR_INPUTLOST)
|
||||
{
|
||||
hr = fDI->fSticks[i]->fDevice->Acquire();
|
||||
char str[256];
|
||||
sprintf(str, "DInput Device # %d connection lost - press Ignore to attempt to reacquire!", i);
|
||||
hsAssert(!hr, str);
|
||||
}
|
||||
}
|
||||
|
||||
DIDEVICEOBJECTDATA data;
|
||||
ULONG size = 1;
|
||||
hr = fDI->fSticks[i]->fDevice->GetDeviceData(sizeof(DIDEVICEOBJECTDATA),&data,&size,0);
|
||||
|
||||
fInputDevice[i]->Update(&data);
|
||||
}
|
||||
}
|
||||
|
||||
void plDInputMgr::AddDevice(IDirectInputDevice8* device)
|
||||
{
|
||||
HRESULT hr = device->BuildActionMap(fDI->fActionFormat, NULL, NULL);
|
||||
if (!FAILED(hr))
|
||||
device->SetActionMap( fDI->fActionFormat, NULL, NULL );
|
||||
}
|
||||
|
||||
void plDInputMgr::ConfigureDevice()
|
||||
{
|
||||
::ShowCursor( TRUE );
|
||||
|
||||
DICOLORSET dics;
|
||||
ZeroMemory(&dics, sizeof(DICOLORSET));
|
||||
dics.dwSize = sizeof(DICOLORSET);
|
||||
|
||||
DICONFIGUREDEVICESPARAMS dicdp;
|
||||
ZeroMemory(&dicdp, sizeof(dicdp));
|
||||
dicdp.dwSize = sizeof(dicdp);
|
||||
dicdp.dwcUsers = 1;
|
||||
dicdp.lptszUserNames = NULL;
|
||||
|
||||
dicdp.dwcFormats = 1;
|
||||
dicdp.lprgFormats = fDI->fActionFormat;
|
||||
dicdp.hwnd = fhWnd;
|
||||
dicdp.lpUnkDDSTarget = NULL;
|
||||
|
||||
fDI->fDInput->ConfigureDevices(NULL, &dicdp, DICD_EDIT, NULL);
|
||||
for (int i = 0; i < fDI->fSticks.Count(); i++)
|
||||
fDI->fSticks[i]->fDevice->SetActionMap( fDI->fActionFormat, NULL, DIDSAM_FORCESAVE );
|
||||
|
||||
::ShowCursor( FALSE );
|
||||
}
|
||||
|
||||
hsBool plDInputMgr::MsgReceive(plMessage* msg)
|
||||
{
|
||||
plInputEventMsg* pMsg = plInputEventMsg::ConvertNoRef(msg);
|
||||
if (pMsg && pMsg->fEvent == plInputEventMsg::kConfigure)
|
||||
{
|
||||
ConfigureDevice();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// dinput required callback functions:
|
||||
|
||||
// enumerate the dinput devices
|
||||
int __stdcall plDInputMgr::EnumGamepadCallback(const DIDEVICEINSTANCE* device, void* pRef)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
plDInput* pDI = (plDInput*)pRef;
|
||||
IDirectInputDevice8* fStick = nil;
|
||||
hr = pDI->fDInput->CreateDevice(device->guidInstance, &fStick, NULL);
|
||||
|
||||
if(!FAILED(hr))
|
||||
{
|
||||
pDI->fSticks.Append(TRACKED_NEW plDIDevice(fStick));
|
||||
|
||||
// the following code pertaining to the action map shouldn't be here.
|
||||
// in fact this shouldn't work at all according to MS, but this is
|
||||
// currently the only way this works. Whatever - the correct
|
||||
// code is here and commented out in case this ever gets fixed by MS
|
||||
// in a future release of dinput.
|
||||
HRESULT hr = fStick->BuildActionMap(pDI->fActionFormat, NULL, NULL);
|
||||
if (!FAILED(hr))
|
||||
{
|
||||
hr = fStick->SetActionMap( pDI->fActionFormat, NULL, NULL );
|
||||
|
||||
DIPROPDWORD dipW;
|
||||
dipW.diph.dwSize = sizeof(DIPROPDWORD);
|
||||
dipW.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||
dipW.diph.dwHow = DIPH_DEVICE;
|
||||
dipW.diph.dwObj = 0;
|
||||
dipW.dwData = 500; // 5% of axis range for deadzone
|
||||
|
||||
hr = fStick->SetProperty(DIPROP_DEADZONE , &dipW.diph);
|
||||
}
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
return DIENUM_STOP;
|
||||
}
|
||||
|
||||
// look for axes on the controller and set the output range to +-100
|
||||
// apparently not needed with action mapping:
|
||||
/*
|
||||
int __stdcall plDInputMgr::SetAxisRange(const DIDEVICEOBJECTINSTANCE* obj, void* pRef)
|
||||
{
|
||||
HRESULT hr;
|
||||
DIPROPRANGE diprg;
|
||||
|
||||
diprg.diph.dwSize = sizeof(DIPROPRANGE);
|
||||
diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||||
diprg.diph.dwHow = DIPH_BYID;
|
||||
diprg.diph.dwObj = obj->dwType;
|
||||
diprg.lMin = -100;
|
||||
diprg.lMax = +100;
|
||||
|
||||
plDInput* pDI = (plDInput*)pRef;
|
||||
for (int i = 0; i < pDI->fSticks.Count(); i++)
|
||||
hr = pDI->fSticks[i]->fDevice->SetProperty(DIPROP_RANGE, &diprg.diph);
|
||||
|
||||
if(!FAILED(hr))
|
||||
return DIENUM_CONTINUE;
|
||||
|
||||
return DIENUM_STOP;
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
// apply mapping to controller
|
||||
// not used. why? no one really knows.
|
||||
// leave this here in case dinput ever gets fixed...
|
||||
/*
|
||||
int __stdcall plDInputMgr::EnumSuitableDevices(const struct DIDEVICEINSTANCEA* devInst, struct IDirectInputDevice8* dev, unsigned long why, unsigned long devRemaining, void* pRef)
|
||||
{
|
||||
plDInput* pDI = (plDInput*)pRef;
|
||||
HRESULT hr = dev->BuildActionMap(pDI->fActionFormat, NULL, NULL);
|
||||
if (!FAILED(hr))
|
||||
{
|
||||
hr = dev->SetActionMap( pDI->fActionFormat, NULL, NULL );
|
||||
}
|
||||
return DIENUM_STOP;
|
||||
}
|
||||
*/
|
||||
DIACTION plDInputMgr::fActionMap[NUM_ACTIONS] =
|
||||
{
|
||||
{A_CONTROL_MOVE, DIAXIS_TPS_MOVE, 0, "Walk Forward-Backward" ,},
|
||||
{A_CONTROL_TURN, DIAXIS_TPS_TURN, 0, "Turn Left-Right" ,},
|
||||
{A_CONTROL_MOUSE_X, DIAXIS_ANY_1, 0, "Move Camera Left-Right",},
|
||||
{A_CONTROL_MOUSE_Y, DIAXIS_ANY_2, 0, "Move Camera Up-Down" ,},
|
||||
{B_CONTROL_ACTION, DIBUTTON_TPS_ACTION, 0, "Action" ,},
|
||||
{B_CONTROL_JUMP, DIBUTTON_TPS_JUMP, 0, "Jump" ,},
|
||||
{B_CONTROL_STRAFE_LEFT, DIBUTTON_TPS_STEPLEFT, 0, "Strafe Left" ,},
|
||||
{B_CONTROL_STRAFE_RIGHT, DIBUTTON_TPS_STEPRIGHT, 0, "Strafe Right" ,},
|
||||
{B_CONTROL_MODIFIER_FAST, DIBUTTON_TPS_RUN, 0, "Run" ,},
|
||||
{B_CONTROL_EQUIP, DIBUTTON_TPS_SELECT, 0, "Equip Item" ,},
|
||||
{B_CONTROL_DROP, DIBUTTON_TPS_USE, 0, "Drop Item" ,},
|
||||
{B_CONTROL_MOVE_FORWARD, DIBUTTON_ANY(0), 0, "Walk Forward" ,},
|
||||
{B_CONTROL_MOVE_BACKWARD, DIBUTTON_ANY(1), 0, "Walk Backward" ,},
|
||||
{B_CONTROL_ROTATE_LEFT, DIBUTTON_ANY(2), 0, "Turn Left" ,},
|
||||
{B_CONTROL_ROTATE_RIGHT, DIBUTTON_ANY(3), 0, "Turn Right" ,},
|
||||
{B_CONTROL_TURN_TO, DIBUTTON_ANY(4), 0, "Pick Item" ,},
|
||||
{B_CAMERA_RECENTER, DIBUTTON_ANY(5), 0, "Recenter Camera" ,},
|
||||
};
|
112
Sources/Plasma/PubUtilLib/plInputCore/plInputManager.h
Normal file
112
Sources/Plasma/PubUtilLib/plInputCore/plInputManager.h
Normal file
@ -0,0 +1,112 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
// plInputManager.h
|
||||
|
||||
#ifndef PL_INPUT_MANAGER_H
|
||||
#define PL_INPUT_MANAGER_H
|
||||
|
||||
#include <windows.h>
|
||||
#include "hsTypes.h"
|
||||
#include "hsTemplates.h"
|
||||
#include "../pnKeyedObject/hsKeyedObject.h"
|
||||
#include "../pnInputCore/plInputMap.h"
|
||||
|
||||
class plDInputMgr;
|
||||
class plInputDevice;
|
||||
class plDInputDevice;
|
||||
class plInputInterfaceMgr;
|
||||
class plPipeline;
|
||||
|
||||
class plInputManager :public hsKeyedObject
|
||||
{
|
||||
private:
|
||||
static hsBool fUseDInput;
|
||||
public:
|
||||
plInputManager();
|
||||
plInputManager( HWND hWnd );
|
||||
~plInputManager();
|
||||
|
||||
CLASSNAME_REGISTER( plInputManager );
|
||||
GETINTERFACE_ANY( plInputManager, hsKeyedObject );
|
||||
|
||||
|
||||
void AddInputDevice(plInputDevice* pDev);
|
||||
void InitDInput(HINSTANCE hInst, HWND hWnd);
|
||||
|
||||
static void UseDInput(hsBool b) { fUseDInput = b; }
|
||||
void Update();
|
||||
static plInputManager* GetInstance() { return fInstance; }
|
||||
static plInputManager* fInstance;
|
||||
virtual hsBool MsgReceive(plMessage* msg);
|
||||
static hsBool RecenterMouse() { return bRecenterMouse > 0; }
|
||||
static void SetRecenterMouse(hsBool b);
|
||||
static void RecenterCursor();
|
||||
void CreateInterfaceMod(plPipeline* p);
|
||||
|
||||
void Activate( bool activating );
|
||||
|
||||
hsScalar GetMouseScale( void ) const { return fMouseScale; }
|
||||
void SetMouseScale( hsScalar s );
|
||||
|
||||
static plKeyDef UntranslateKey(plKeyDef key, hsBool extended);
|
||||
|
||||
protected:
|
||||
|
||||
hsTArray<plInputDevice*> fInputDevices;
|
||||
plDInputMgr* fDInputMgr;
|
||||
plInputInterfaceMgr *fInterfaceMgr;
|
||||
bool fActive, fFirstActivated;
|
||||
|
||||
hsScalar fMouseScale;
|
||||
static UInt8 bRecenterMouse;
|
||||
static HWND fhWnd;
|
||||
|
||||
public:
|
||||
// event handlers
|
||||
void HandleWin32ControlEvent(UINT message, WPARAM Wparam, LPARAM Lparam, HWND hWnd);
|
||||
};
|
||||
|
||||
|
||||
// {049DE53E-23A2-4d43-BF68-36AC1B57E357}
|
||||
static const GUID PL_ACTION_GUID = { 0x49de53e, 0x23a2, 0x4d43, { 0xbf, 0x68, 0x36, 0xac, 0x1b, 0x57, 0xe3, 0x57 } };
|
||||
|
||||
#endif
|
1242
Sources/Plasma/PubUtilLib/plInputCore/plSceneInputInterface.cpp
Normal file
1242
Sources/Plasma/PubUtilLib/plInputCore/plSceneInputInterface.cpp
Normal file
File diff suppressed because it is too large
Load Diff
149
Sources/Plasma/PubUtilLib/plInputCore/plSceneInputInterface.h
Normal file
149
Sources/Plasma/PubUtilLib/plInputCore/plSceneInputInterface.h
Normal file
@ -0,0 +1,149 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// plSceneInputInterface //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _plSceneInputInterface_h
|
||||
#define _plSceneInputInterface_h
|
||||
|
||||
#include "plInputInterface.h"
|
||||
#include "hsGeometry3.h"
|
||||
#include "../pnKeyedObject/plKey.h"
|
||||
#include "../pnUtils/pnUtils.h"
|
||||
|
||||
//// Class Definition ////////////////////////////////////////////////////////
|
||||
|
||||
class plPipeline;
|
||||
class plSceneObject;
|
||||
|
||||
class plSceneInputInterface : public plInputInterface
|
||||
{
|
||||
enum
|
||||
{
|
||||
kNotOffering = 0,
|
||||
kOfferBook,
|
||||
kBookOffered,
|
||||
kOfferAccepted,
|
||||
kOfferLinkPending,
|
||||
};
|
||||
protected:
|
||||
static plSceneInputInterface *fInstance;
|
||||
|
||||
UInt32 fCurrentCursor;
|
||||
UInt8 fButtonState;
|
||||
hsBool fClickability;
|
||||
plKey fCurrentClickable, fLastClicked, fCurrentClickableLogicMod;
|
||||
hsPoint3 fCurrentClickPoint;
|
||||
hsBool fCurrClickIsAvatar, fLastClickIsAvatar,fFadedLocalAvatar;
|
||||
hsBool fPendingLink;
|
||||
|
||||
int fBookMode; // are we in offer book mode?
|
||||
plKey fBookKey; // key for the python file modifier for the book we are offering
|
||||
plKey fOffereeKey;
|
||||
UInt32 fOffereeID; // ID for the guy who's accepted our link offer
|
||||
const char* fOfferedAgeFile;
|
||||
const char* fOfferedAgeInstance;
|
||||
const char* fSpawnPoint;
|
||||
Uuid fAgeInstanceGuid;
|
||||
struct clickableTest
|
||||
{
|
||||
clickableTest(plKey k)
|
||||
{
|
||||
key = k;
|
||||
val = false;
|
||||
}
|
||||
plKey key;
|
||||
hsBool val;
|
||||
};
|
||||
|
||||
hsTArray<clickableTest *> fClickableMap;
|
||||
hsTArray<plKey> fIgnoredAvatars; // these are ignored because they are engaged in avatar-avatar interactions which need to be left undisturbed
|
||||
hsTArray<plKey> fGUIIgnoredAvatars; // these are ignored because they have a GUI in their face right now
|
||||
hsTArray<plKey> fLocalIgnoredAvatars; // these are ALL avatars currently in your age. they are ignored when you press the 'ignore' key so you can
|
||||
// select clickable non-avatar objects through them.
|
||||
hsPoint3 fLastStartPt, fLastEndPt;
|
||||
plPipeline *fPipe;
|
||||
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty );
|
||||
|
||||
|
||||
void IRequestLOSCheck( hsScalar xPos, hsScalar yPos, int ID );
|
||||
void ISetLastClicked( plKey obj, hsPoint3 hitPoint );
|
||||
void IHalfFadeAvatar(hsBool out);
|
||||
|
||||
hsBool IWorldPosMovedSinceLastLOSCheck( void );
|
||||
void ClearClickableMap();
|
||||
void ISendOfferNotification(plKey& offeree, int ID, hsBool net);
|
||||
void IManageIgnoredAvatars(plKey& offeree, hsBool add);
|
||||
void ISendAvatarDisabledNotification(hsBool enabled);
|
||||
void ILinkOffereeToAge();
|
||||
public:
|
||||
|
||||
plSceneInputInterface();
|
||||
virtual ~plSceneInputInterface();
|
||||
|
||||
static hsBool fShowLOS;
|
||||
|
||||
// Always return true, since the cursor should be representing how we control the avatar
|
||||
virtual hsBool HasInterestingCursorID( void ) const { return ( fCurrentCursor != kNullCursor ) ? true : false; }
|
||||
virtual UInt32 GetPriorityLevel( void ) const { return kSceneInteractionPriority; }
|
||||
virtual UInt32 GetCurrentCursorID( void ) const {return fCurrentCursor;}
|
||||
UInt32 SetCurrentCursorID(UInt32 id);
|
||||
virtual hsBool InterpretInputEvent( plInputEventMsg *pMsg );
|
||||
void RequestAvatarTurnToPointLOS();
|
||||
|
||||
virtual hsBool MsgReceive( plMessage *msg );
|
||||
|
||||
virtual void Init( plInputInterfaceMgr *manager );
|
||||
virtual void Shutdown( void );
|
||||
|
||||
virtual void ResetClickableState();
|
||||
|
||||
plKey GetCurrMousedAvatar( void ) const { if( fCurrClickIsAvatar ) return fCurrentClickable; else return nil; }
|
||||
static plSceneInputInterface *GetInstance( void ) { return fInstance; }
|
||||
};
|
||||
|
||||
|
||||
#endif //_plSceneInputInterface_h
|
@ -0,0 +1,141 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// plTelescopeInputInterface //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsConfig.h"
|
||||
#include "hsWindows.h"
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "plTelescopeInputInterface.h"
|
||||
|
||||
#include "plInputInterfaceMgr.h"
|
||||
#include "plInputManager.h"
|
||||
#include "plInputDevice.h"
|
||||
#include "../pnInputCore/plKeyMap.h"
|
||||
|
||||
#include "plgDispatch.h"
|
||||
|
||||
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
plTelescopeInputInterface::plTelescopeInputInterface()
|
||||
{
|
||||
SetEnabled( true ); // Always enabled
|
||||
|
||||
|
||||
// Add our control codes to our control map. Do NOT add the key bindings yet.
|
||||
// Note: HERE is where you specify the actions for each command, i.e. net propagate and so forth.
|
||||
// This part basically declares us master of the bindings for these commands.
|
||||
|
||||
// IF YOU ARE LOOKING TO CHANGE THE DEFAULT KEY BINDINGS, DO NOT LOOK HERE. GO TO
|
||||
// RestoreDefaultKeyMappings()!!!!
|
||||
|
||||
fControlMap->AddCode( B_CONTROL_EXIT_MODE, kControlFlagNormal | kControlFlagNoRepeat );
|
||||
fControlMap->AddCode( B_CAMERA_PAN_LEFT, kControlFlagNormal );
|
||||
fControlMap->AddCode( B_CAMERA_PAN_RIGHT, kControlFlagNormal );
|
||||
fControlMap->AddCode( B_CAMERA_PAN_UP, kControlFlagNormal );
|
||||
fControlMap->AddCode( B_CAMERA_PAN_DOWN, kControlFlagNormal );
|
||||
fControlMap->AddCode( B_CAMERA_RECENTER, kControlFlagNormal | kControlFlagNoRepeat );
|
||||
fControlMap->AddCode( B_CAMERA_ZOOM_IN, kControlFlagNormal );
|
||||
fControlMap->AddCode( B_CAMERA_ZOOM_OUT, kControlFlagNormal );
|
||||
|
||||
// IF YOU ARE LOOKING TO CHANGE THE DEFAULT KEY BINDINGS, DO NOT LOOK HERE. GO TO
|
||||
// RestoreDefaultKeyMappings()!!!!
|
||||
}
|
||||
|
||||
plTelescopeInputInterface::~plTelescopeInputInterface()
|
||||
{
|
||||
}
|
||||
|
||||
//// Init/Shutdown ///////////////////////////////////////////////////////////
|
||||
|
||||
void plTelescopeInputInterface::Init( plInputInterfaceMgr *manager )
|
||||
{
|
||||
plInputInterface::Init( manager );
|
||||
}
|
||||
|
||||
//// IEval ///////////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool plTelescopeInputInterface::IEval( double secs, hsScalar del, UInt32 dirty )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//// MsgReceive //////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool plTelescopeInputInterface::MsgReceive( plMessage *msg )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//// InterpretInputEvent /////////////////////////////////////////////////////
|
||||
|
||||
hsBool plTelescopeInputInterface::InterpretInputEvent( plInputEventMsg *pMsg )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//// RestoreDefaultKeyMappings ///////////////////////////////////////////////
|
||||
|
||||
void plTelescopeInputInterface::RestoreDefaultKeyMappings( void )
|
||||
{
|
||||
if( fControlMap == nil )
|
||||
return;
|
||||
|
||||
fControlMap->UnmapAllBindings();
|
||||
|
||||
fControlMap->BindKey( KEY_BACKSPACE, B_CONTROL_EXIT_MODE );
|
||||
fControlMap->BindKey( KEY_NUMPAD5, B_CAMERA_RECENTER );
|
||||
fControlMap->BindKey( KEY_C, B_CAMERA_RECENTER );
|
||||
fControlMap->BindKey( KEY_NUMPAD_ADD, B_CAMERA_ZOOM_IN );
|
||||
fControlMap->BindKey( KEY_NUMPAD_SUBTRACT, B_CAMERA_ZOOM_OUT );
|
||||
fControlMap->BindKey( KEY_NUMPAD4, B_CAMERA_PAN_LEFT );
|
||||
fControlMap->BindKey( KEY_NUMPAD6, B_CAMERA_PAN_RIGHT );
|
||||
fControlMap->BindKey( KEY_NUMPAD8, B_CAMERA_PAN_UP );
|
||||
fControlMap->BindKey( KEY_NUMPAD2, B_CAMERA_PAN_DOWN );
|
||||
}
|
||||
|
@ -0,0 +1,90 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// plTelescopeInputInterface //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _plTelescopeInputInterface_h
|
||||
#define _plTelescopeInputInterface_h
|
||||
|
||||
#include "plInputInterface.h"
|
||||
#include "../pnKeyedObject/plKey.h"
|
||||
|
||||
//// Class Definition ////////////////////////////////////////////////////////
|
||||
|
||||
class plTelescopeInputInterface : public plInputInterface
|
||||
{
|
||||
protected:
|
||||
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty );
|
||||
|
||||
public:
|
||||
|
||||
plTelescopeInputInterface();
|
||||
virtual ~plTelescopeInputInterface();
|
||||
|
||||
virtual void RestoreDefaultKeyMappings( void );
|
||||
|
||||
virtual hsBool InterpretInputEvent( plInputEventMsg *pMsg );
|
||||
|
||||
virtual hsBool MsgReceive( plMessage *msg );
|
||||
|
||||
virtual void Init( plInputInterfaceMgr *manager );
|
||||
virtual void Shutdown( void ) {;}
|
||||
|
||||
// Returns the priority of this interface layer, based on the Priorities enum
|
||||
virtual UInt32 GetPriorityLevel( void ) const { return kTelescopeInputPriority; }
|
||||
|
||||
// Returns the currently active mouse cursor for this layer, as defined in pnMessage/plCursorChangeMsg.h
|
||||
virtual UInt32 GetCurrentCursorID( void ) const { return kCursorUp; }
|
||||
|
||||
// Returns the current opacity that this layer wants the cursor to be, from 0 (xparent) to 1 (opaque)
|
||||
virtual hsScalar GetCurrentCursorOpacity( void ) const { return 1.f; }
|
||||
|
||||
// Returns true if this layer is wanting to change the mouse, false if it isn't interested
|
||||
virtual hsBool HasInterestingCursorID( void ) const { return false; }
|
||||
};
|
||||
|
||||
|
||||
#endif //_plTelescopeInputInterface_h
|
Reference in New Issue
Block a user