Trash DirectInput

This commit is contained in:
kaetemi 2014-07-08 22:21:11 +02:00
parent 3650ef83b7
commit 0f5f1f9047
58 changed files with 162 additions and 4253 deletions

View file

@ -42,9 +42,6 @@
namespace NLMISC
{
class IEventEmitter;
struct IMouseDevice;
struct IKeyboardDevice;
struct IInputDeviceManager;
class CRect;
class CLog;
}
@ -869,25 +866,6 @@ public:
/// x and y must be between 0.0 and 1.0
virtual void setMousePos(float x, float y) = 0;
/** Enable / disable low level mouse. This allow to take advantage of some options (speed of the mouse, automatic wrapping)
* It returns a interface to these parameters when it is supported, or NULL otherwise
* The interface pointer is valid as long as the low level mouse is enabled.
* A call to disable the mouse returns NULL, and restore the default mouse behavior
* NB : - In this mode the mouse cursor isn't drawn.
* - Calls to showCursor have no effects
* - Calls to setCapture have no effects
*/
virtual NLMISC::IMouseDevice *enableLowLevelMouse(bool enable, bool exclusive) = 0;
/** Enable / disable a low level keyboard.
* Such a keyboard can only send KeyDown and KeyUp event. It just consider the keyboard as a
* gamepad with lots of buttons...
* This returns a interface to some parameters when it is supported, or NULL otherwise.
* The interface pointer is valid as long as the low level keyboard is enabled.
* A call to disable the keyboard returns NULL, and restore the default keyboard behavior
*/
virtual NLMISC::IKeyboardDevice *enableLowLevelKeyboard(bool enable) = 0;
/** Get the delay in ms for mouse double clicks.
*/
virtual uint getDoubleClickDelay(bool hardwareMouse) = 0;
@ -908,11 +886,6 @@ public:
// Change default scale for all cursors
virtual void setCursorScale(float scale) = 0;
/** Check whether there is a low level device manager available, and get its interface. Return NULL if not available
* From this interface you can deal with mouse and keyboard as above, but you can also manage game device (joysticks, joypads ...)
*/
virtual NLMISC::IInputDeviceManager *getLowLevelInputDeviceManager() = 0;
// @}

View file

@ -410,21 +410,6 @@ public:
virtual bool fillBuffer (CBitmap &bitmap);
// @}
/// \name Mouse / Keyboards / Game devices
// @{
virtual NLMISC::IMouseDevice *enableLowLevelMouse(bool enable, bool exclusive);
//
virtual NLMISC::IKeyboardDevice *enableLowLevelKeyboard(bool enable);
virtual NLMISC::IInputDeviceManager *getLowLevelInputDeviceManager();
/**
* wrapper for IEventEmitter::emulateMouseRawMode()
*/
virtual void emulateMouseRawMode(bool enable);
virtual uint getDoubleClickDelay(bool hardwareMouse);
/// show cursor if b is true, or hide it if b is false
virtual void showCursor (bool b);
/// x and y must be between 0.0 and 1.0

View file

@ -556,36 +556,6 @@ public:
/// \name Mouse / Keyboard / Gamedevices
// @{
/** Enable / disable low level mouse. This allow to take advantage of some options (speed of the mouse, automatic wrapping)
* It returns a interface to these parameters when it is supported, or NULL otherwise
* The interface pointer is valid as long as the low level mouse is enabled.
* A call to disable the mouse returns NULL, and restore the default mouse behaviour
* NB : - In this mode the mouse cursor isn't drawn.
* - Calls to showCursor have no effects
* - Calls to setCapture have no effects
*/
virtual NLMISC::IMouseDevice *enableLowLevelMouse(bool enable, bool hardware) = 0;
/** Enable / disable a low level keyboard.
* This returns a interface to some parameters when it is supported, or NULL otherwise.
* The interface pointer is valid as long as the low level keyboard is enabled.
* A call to disable the keyboard returns NULL, and restore the default keyboard behaviour.
*/
virtual NLMISC::IKeyboardDevice *enableLowLevelKeyboard(bool enable) = 0;
/** Check whether there is a low level device manager available, and get its interface. Return NULL if not available.
* From this interface you can deal with mouse and keyboard as above, but you can also manage game devices (joysticks, joypads ...)
*/
virtual NLMISC::IInputDeviceManager *getLowLevelInputDeviceManager() = 0;
/**
* wrapper for IEventEmitter::emulateMouseRawMode()
*/
virtual void emulateMouseRawMode(bool enable) = 0;
// get delay used for mouse double click
virtual uint getDoubleClickDelay(bool hardwareMouse) = 0;
/** show cursor if b is true, or hide it if b is false
* NB: This has no effects if a low level mouse is used.
*/

View file

@ -1,204 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_DI_EVENT_EMITTER_H
#define NL_DI_EVENT_EMITTER_H
#include "types_nl.h"
#ifdef NL_OS_WINDOWS
#define DIRECTINPUT_VERSION 0x0800
#include "input_device_server.h"
#include "input_device_manager.h"
#include "event_emitter.h"
#include "smart_ptr.h"
#include "events.h"
#include "rect.h"
#include "game_device.h"
#ifndef NL_COMP_MINGW
# define NOMINMAX
#endif
#include <windows.h>
#include <dinput.h>
namespace NLMISC
{
class CWinEventEmitter;
class CDIKeyboard;
class CDIMouse;
struct IMouseDevice;
struct IKeyboardDevice;
//
struct EDirectInput : public EInputDevice
{
EDirectInput(const char *reason) : EInputDevice(reason) {}
};
//
struct EDirectInputLibNotFound : public EDirectInput
{
EDirectInputLibNotFound() : EDirectInput("can't found the direct input dll") {}
};
//
struct EDirectInputInitFailed : public EDirectInput
{
EDirectInputInitFailed() : EDirectInput("Direct input initialization failed") {}
};
//
struct EDirectInputCooperativeLevelFailed : public EDirectInput
{
EDirectInputCooperativeLevelFailed() : EDirectInput("Direct Input Device Cooperative level couldn't be set") {}
};
// Class to represent Direct Inputs events
struct CDIEvent : public IInputDeviceEvent
{
virtual bool operator < (const IInputDeviceEvent &ide) const
{
// just compare the dates
return Datas.dwTimeStamp < (safe_cast<const CDIEvent *>(&ide))->Datas.dwTimeStamp;
}
DIDEVICEOBJECTDATA Datas;
};
/**
* This manage events by using DirectInput8.
* This should be polled regularly.
* This can be mixed with a CWinEmitter (for example, you may have mouse using direct input, and keyboard using standard messages)
* \author Nicolas Vizerie
* \author Nevrax France
* \date 2002
*/
class CDIEventEmitter : public IEventEmitter, public IInputDeviceManager
{
public:
/** Build a Direct Input Event Emitter object. An exception containing the reason is thrown if the initialization failed.
* The obtained object must be released by deleting it.
* \param hinst the instance of the application.
* \param hwnd the main window of the application.
* \param we A windows eventsemitter. Can be NULL. Needed if you want to mix WIN32 events and Direct Input events
* (for example, a Direct Input Mouse and a Win32 Keyboard)
*/
static CDIEventEmitter *create(HINSTANCE hinst, HWND hwnd, CWinEventEmitter *we) throw(EDirectInput);
~CDIEventEmitter();
public:
/// This poll the direct input state, directly storing the result in the given server, or keeping the result in internal server if NULL.
void poll(CEventServer *server = NULL);
///\name From IDeviceManager, access to devices
//@{
// Test if a mouse has been created (by a call to getMouseDeivce)
virtual bool isMouseCreated() { return _Mouse != NULL; }
/** Create the mouse device if needed (one active at a time for that object, repeated calls returns the same pointer) and get an interface on it. An exception if thrown if it couldn't be obtained.
* If this object has a pointer on a win32 emiter, Win32 mouse messages are replaced by this mouse messages.
*/
virtual IMouseDevice *getMouseDevice(bool hardware) throw(EInputDevice);
/// remove the direct input mouse
virtual void releaseMouse();
/** Create the keyboard device if needed (one active at a time for that object, repeated calls returns the same pointer) and get an interface on it.
* If this object has a pointer on a win32 emiter, Win32 keyboard messages are replaced by this keyboard messages.
* NB: A direct input has no notion of localization or key combinations. See keyboard_device.h for more infos
*/
virtual IKeyboardDevice *getKeyboardDevice() throw(EInputDevice);
/// remove the direct input keyboard
virtual void releaseKeyboard();
// Enumerates current game devices (gamepads, joystick etc.). The result is stored in the given vector
virtual void enumerateGameDevice(TDeviceDescVect &descs) throw(EInputDevice);
// Create the given game device from its instance name. It also means that it will begin to sends inputs
virtual IGameDevice *createGameDevice(const std::string &instanceName) throw(EInputDevice);
// Release the given game device
virtual void releaseGameDevice(IGameDevice *);
//@}
/// from IEventEmitter
virtual void submitEvents(CEventServer &server, bool allWindows);
virtual void emulateMouseRawMode(bool enable);
// Build a TMouseButton value from the current buttons state
TMouseButton buildButtonsFlags() const;
// Build a TMouseButton value (but with no mouse values)
TMouseButton buildKeyboardButtonFlags() const
{
return (TMouseButton) (buildButtonsFlags() & (ctrlButton|shiftButton|altButton));
}
//================================================================
//================================================================
//================================================================
private:
typedef HRESULT (WINAPI * TPDirectInput8Create) (HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID* ppvOut, LPUNKNOWN punkOuter);
// Private internal server message, used to stored all messages internally before to dispatch them, when no server is supplied to poll(...
class CDIEventServer : CEventServer
{
friend class CDIEventEmitter;
public:
void setServer (CEventServer *server)
{
_Server = server;
}
private:
bool pumpEvent(CEvent *event)
{
CEventServer::pumpEvent(event);
_Server->postEvent (event);
return false;
}
private:
CEventServer *_Server;
};
private:
HWND _hWnd;
TMouseButton _ButtonsFlags;
NLMISC::CRefPtr<CWinEventEmitter> _WE;
static HMODULE _DirectInputLibHandle;
static TPDirectInput8Create _PDirectInput8Create;
static uint _NumCreatedInterfaces;
private:
static bool loadLib();
static void unloadLib();
//====
private:
CDIEventServer _InternalServer;
CInputDeviceServer _DeviceServer;
IDirectInput8 *_DInput8;
CDIMouse *_Mouse;
CDIKeyboard *_Keyboard;
private:
CDIEventEmitter(HWND hwnd, CWinEventEmitter *we);
};
} // NLMISC
#endif // NL_WINDOWS
#endif // NL_DX_EVENT_EMITTER_H
/* End of dx_event_emitter.h */

View file

@ -49,19 +49,6 @@ public:
* \param server
*/
virtual void submitEvents(CEventServer & server, bool allWindows) = 0;
/**
* Instruct the event emitter to send CGDMouseMove instead of CEventMouseMove.
*
* On windows, the mouse device can be set into RawMode. Using this mode,
* CGDMouseMove events (only containing the raw movement delta) are emitted
* instead of the normal CEventMouseMove events (containing the mouse position).
*
* On Linux and Mac OS X, there is no MouseDevice implementation, all the
* events are created by the event emitter. So the event emitter has to
* emulate the mouse raw mode.
*/
virtual void emulateMouseRawMode(bool) = 0;
};

View file

@ -47,7 +47,6 @@ public:
const IEventEmitter *getEmitter(uint index) const;
/// From IEventEmitter. This call submitEvents on all the emitters
virtual void submitEvents(CEventServer &server, bool allWindows);
virtual void emulateMouseRawMode(bool enable);
virtual bool copyTextToClipboard(const ucstring &text);
virtual bool pasteTextFromClipboard(ucstring &text);

View file

@ -1,114 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_GAME_DEVICE_H
#define NL_GAME_DEVICE_H
#include "types_nl.h"
#include "input_device.h"
#include <string>
#include <vector>
namespace NLMISC
{
/// Describe a game device
struct CGameDeviceDesc
{
// type of the device
enum TDevType { GamePad, Joystick, DontKnow, DevTypeLast } DevType;
// Friendly name for the instance. For example, "Joystick 1."
std::string InstanceName;
// Friendly name for the product
std::string ProductName;
// Tells whether this device is connected
bool Connected;
};
// a list of game device description
typedef std::vector<CGameDeviceDesc> TDeviceDescVect;
/// for devices comparison. The 'Connected' field is ignored.
inline bool operator == (const CGameDeviceDesc &lhs, const CGameDeviceDesc &rhs)
{
return lhs.InstanceName == rhs.InstanceName && lhs.ProductName == rhs.ProductName;
}
//
inline bool operator != (const CGameDeviceDesc &lhs, const CGameDeviceDesc &rhs)
{
return !(lhs == rhs);
}
/**
* This abstract a joystick or gamepad
* \author Nicolas Vizerie
* \author Nevrax France
* \date 2002
*/
struct IGameDevice : public IInputDevice
{
enum TAxis { XAxis = 0, YAxis, ZAxis, /* translation */
RXAxis, RYAxis, RZAxis, /* rotations */
MaxNumAxis
};
/// Get a general description of this device
virtual const CGameDeviceDesc &getDescription() const = 0;
///\name Controls presence
//@{
// returns the number of buttons available on this game device
virtual uint getNumButtons() const = 0;
/** Check if the given axe is present on this game device
* NB : only absolute axis are managed
*/
virtual bool hasAxis(TAxis axis) const = 0;
// Check the number of sliders presents on this game device
virtual uint getNumSliders() const = 0;
// Check the number of point of views controls present on this game device
virtual uint getNumPOV() const = 0;
//@}
///\name Controls names. Must ensure that controls are present before calling these methods.
//@{
virtual const char *getButtonName(uint index) const = 0;
virtual const char *getAxisName(TAxis axis) const = 0;
virtual const char *getSliderName(uint index) const = 0;
virtual const char *getPOVName(uint index) const = 0;
//@}
///\name Controls state. Must ensure that controls are present before calling these methods.
//@{
// Return true if the given button is pushed.
virtual bool getButtonState(uint index) const = 0;
// Return a value in [-1, 1] for a translation axis, or an orientation.
virtual float getAxisValue(TAxis axis) const = 0;
// Return a value in [0, 1]
virtual float getSliderPos(uint index) const = 0;
// Return a CCW angle in degrees
virtual float getPOVAngle(uint index) const = 0;
//@}
};
} // NLMISC
#endif // NL_GAME_DEVICE_H
/* End of GAME_device.h */

View file

@ -1,209 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_GAME_DEVICE_EVENT_H
#define NL_GAME_DEVICE_EVENT_H
#include "types_nl.h"
#include "events.h"
#include "game_device.h"
namespace NLMISC
{
struct IMouseDevice;
struct IGameDevice;
const CClassId EventGDMouseMove(0x12142bc4, 0x43c73e74);
const CClassId EventGDButtonDownId(0x57141957, 0x3efb143a);
const CClassId EventGDButtonUpId(0x16105e06, 0x302536b2);
const CClassId EventGDAxisMovedId(0x073306, 0x41173626);
const CClassId EventGDSliderMovedId(0x68776586, 0x394a6916);
const CClassId EventGDPOVChanged(0x362851b9, 0x395c4d61);
//==========================================================================================
/// A raw mouse move message, expressed in mickeys (relative values)
class CGDMouseMove : public CEvent
{
public:
IMouseDevice *MD;
sint X, Y;
public:
CGDMouseMove(IEventEmitter *emitter, IMouseDevice *md, sint x, sint y) : CEvent(emitter, EventGDMouseMove), MD(md), X(x), Y(y)
{}
virtual CEvent *clone() const {return new CGDMouseMove(*this);}
};
//==========================================================================================
/**
* An event from a game device (joystick, joypad ...)
*/
class CGameDeviceEvent : public CEvent
{
public:
/// the game device this event come from
IGameDevice *GameDevice;
public:
CGameDeviceEvent(
IGameDevice *gameDevice,
IEventEmitter *emitter,
const CClassId &classId
)
: CEvent(emitter, classId),
GameDevice(gameDevice)
{}
};
//==========================================================================================
/** A button state has changed
*/
class CGDButton : public CGameDeviceEvent
{
public:
// index of the buttons that has been pushed
uint ButtonIndex;
bool Pushed;
public:
///
CGDButton(
uint buttonIndex,
bool pushed,
IGameDevice *gameDevice,
IEventEmitter *emitter,
const CClassId &classId
)
: CGameDeviceEvent(gameDevice, emitter, classId),
ButtonIndex(buttonIndex),
Pushed(pushed)
{}
};
//==========================================================================================
/** A button has been pushed
*/
class CGDButtonDown : public CGDButton
{
public:
///
CGDButtonDown(uint buttonIndex, IGameDevice *gameDevice, IEventEmitter *emitter)
: CGDButton(buttonIndex, true, gameDevice, emitter, EventGDButtonDownId)
{}
virtual CEvent *clone() const {return new CGDButtonDown(*this);}
};
//==========================================================================================
/** A button has been released
*/
class CGDButtonUp : public CGDButton
{
public:
///
CGDButtonUp(uint buttonIndex, IGameDevice *gameDevice, IEventEmitter *emitter)
: CGDButton(buttonIndex, false, gameDevice, emitter, EventGDButtonUpId)
{}
virtual CEvent *clone() const {return new CGDButtonUp(*this);}
};
//==========================================================================================
/// An axis has moved
class CGDAxisMoved : public CGameDeviceEvent
{
public:
IGameDevice::TAxis Axis;
// current position of the axis, ranges from -1.f to 1.f
float Value;
public:
CGDAxisMoved(
IGameDevice::TAxis axis,
float value,
IGameDevice *gameDevice,
IEventEmitter *emitter
)
: CGameDeviceEvent(gameDevice, emitter, EventGDAxisMovedId),
Axis(axis),
Value(value)
{}
virtual CEvent *clone() const {return new CGDAxisMoved(*this);}
};
//==========================================================================================
/// A slider position has changed
class CGDSliderMoved : public CGameDeviceEvent
{
public:
uint SliderIndex;
// current position of the slider, ranges from 0.f to 1.f
float SliderPos;
public:
CGDSliderMoved(
float sliderPos,
uint sliderIndex,
IGameDevice *gameDevice,
IEventEmitter *emitter
)
: CGameDeviceEvent(gameDevice, emitter, EventGDSliderMovedId),
SliderIndex(sliderIndex),
SliderPos(sliderPos)
{}
virtual CEvent *clone() const {return new CGDSliderMoved(*this);}
};
//==========================================================================================
/// A point of view control changed
class CGDPOVChanged : public CGameDeviceEvent
{
public:
uint POVIndex;
bool Centered;
// The POV angle, in degrees (CW)
float POVAngle;
public:
CGDPOVChanged(
bool centered,
float povAngle,
uint povIndex,
IGameDevice *gameDevice,
IEventEmitter *emitter
)
: CGameDeviceEvent(gameDevice, emitter, EventGDPOVChanged),
POVIndex(povIndex),
Centered(centered),
POVAngle(povAngle)
{}
virtual CEvent *clone() const {return new CGDPOVChanged(*this);}
};
} // NLMISC
#endif // NL_GAME_DEVICE_EVENT_H
/* End of game_device_event.h */

View file

@ -1,84 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_INPUT_DEVICE_H
#define NL_INPUT_DEVICE_H
#include "types_nl.h"
namespace NLMISC
{
class CEventServer;
class CInputDeviceServer;
struct IInputDeviceEvent;
/**
* Base class that wrap to a device
* \author Nicolas Vizerie
* \author Nevrax France
* \date 2002
*/
struct IInputDevice
{
/** Set the buffer size for this device (the number of samples it can retains).
* This return true if the size could be set
*/
virtual bool setBufferSize(uint size) = 0;
/// Get the buffer size for this device
virtual uint getBufferSize() const = 0;
///\name Device server specifics. You usually don't want to call these
//@{
/** For device server usage :
* Called at the beginning of each events retrieval.
* If a device doesn't support buffered datas, the state changes can be directly send to the event server.
* The default does nothing.
*/
virtual void begin(CEventServer * /* server */) {}
/** For device server usage :
* Poll all events from that device, and notify them to the given device server, so that they can be sorted between devices.
* This retrieves messages, but do not process them.
*/
virtual void poll(CInputDeviceServer *dev) = 0;
/** For device server usage :
* Process an event (eventually update this device state), and translate the message to a IEventServerMessage
*/
virtual void submit(IInputDeviceEvent *deviceEvent, CEventServer *server) = 0;
/** For device server usage :
* Says that the next message is for another device, or that it is the last message that will be received.
* This allow to pack several messages in one (for example, to sum up mouse moves until a click occurs)
* The default does nothing.
* The next message can be used to get a time stamp for example. It may be NULL is no next message is available
*/
virtual void transitionOccured(CEventServer * /* server */, const IInputDeviceEvent * /* nextMessage */) {}
//@}
// dtor
virtual ~IInputDevice() {}
};
} // NLMISC
#endif // NL_INPUT_DEVICE_H
/* End of input_device.h */

View file

@ -1,69 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_INPUT_DEVICE_MANAGER_H
#define NL_INPUT_DEVICE_MANAGER_H
#include "types_nl.h"
#include "game_device.h"
#include "common.h"
namespace NLMISC
{
struct IMouseDevice;
struct IKeyboardDevice;
struct EInputDevice : public Exception
{
EInputDevice(const char *reason) : Exception(reason) {}
};
/** Interface for objects that give low level access to devices (mouse, keyboard, joypads and joysticks).
* Generally an object implementing this interface will send the appropriate events when a device is 'created'.
* (Example of implementation : a direct input event emitter)
*/
struct IInputDeviceManager
{
// Test if a mouse has been created (by a call to getMouseDeivce)
virtual bool isMouseCreated() = 0;
/// Create the low level mouse device if needed (one active at a time for that object, repeated calls returns the same pointer). An exception if thrown if it couldn't be obtained.
virtual IMouseDevice *getMouseDevice(bool hardware) throw(EInputDevice) = 0;
/// remove the low level mouse
virtual void releaseMouse() = 0;
/// Create the low level keyboard device if needed (one active at a time for that object, repeated calls returns the same pointer). An exception if thrown if it couldn't be obtained.
virtual IKeyboardDevice *getKeyboardDevice() throw(EInputDevice) = 0;
/// remove the low level keyboard
virtual void releaseKeyboard() = 0;
// Enumerates current game devices (gamepads, joystick etc.). The result is stored in the given vector
virtual void enumerateGameDevice(TDeviceDescVect &descs) throw(EInputDevice) = 0;
// Create the given game device interface from its instance name. It also means that it will begin to sends events.
virtual IGameDevice *createGameDevice(const std::string &instanceName) throw(EInputDevice) = 0;
// Release the given game device.
virtual void releaseGameDevice(IGameDevice *gd) = 0;
};
} // NLMISC
#endif // NL_INPUT_DEVICE_MANAGER_H
/* End of device_manager.h */

View file

@ -1,84 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_INPUT_DEVICE_SERVER_H
#define NL_INPUT_DEVICE_SERVER_H
#include "types_nl.h"
#include <vector>
namespace NLMISC
{
class CEventServer;
struct IInputDevice;
struct IInputDeviceEvent;
/** Base class for an input device server. Unlike an event server, it manages several devices, and can sort their events (by date for example).
* It keeps a list of active devices.
* It can poll datas from every active device.
* It can sort devices messages to submit them in correct order to a CEventServer.
*/
class CInputDeviceServer
{
public:
/// register a device into this device server.
void registerDevice(IInputDevice *device);
/// remove a device from this server (but does not delete it).
void removeDevice(IInputDevice *device);
// returns the number of registered devices
uint getNumDevices() const { return (uint)_Devices.size(); }
// return a device
IInputDevice *getDevice(uint index) { return _Devices[index]; }
/// Test whether the given device is handled by this server.
bool isDevice(IInputDevice *device) const;
/// Retrieve datas from the devices, and submit them to the given CEventServer.
void poll(CEventServer *server);
/// Allow an input device to register an event. The event will then be deleted by this server
void submitEvent(IInputDeviceEvent *deviceEvent);
// dtor
virtual ~CInputDeviceServer() {}
private:
typedef std::vector<IInputDevice *> TDeviceCont;
typedef std::vector<IInputDeviceEvent *> TEventCont;
private:
TDeviceCont _Devices;
TEventCont _Events;
};
/** An event from an input device.
*/
struct IInputDeviceEvent
{
IInputDevice *Emitter; // the input device that emitted that event
// Used to sort events by time stamp.
virtual bool operator < (const IInputDeviceEvent &IInputDeviceEvent) const = 0;
virtual ~IInputDeviceEvent() {}
};
} // NLMISC
#endif // NL_INPUT_DEVICE_SERVER_H
/* End of input_device_server.h */

View file

@ -1,63 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_KEYBOARD_DEVICE_H
#define NL_KEYBOARD_DEVICE_H
#include "types_nl.h"
#include "events.h"
#include "input_device.h"
namespace NLMISC
{
/** Gives access to low level keyboard parameters
* - 'Shift' messages are replaced by RShift and LShift msg.
* - 'Control' messages are replaced by 'RControl' and 'LControl' msg.
* - 'Menu' (alternate) messages are replaced by 'RMenu' and 'LMenu' msg.
*/
struct IKeyboardDevice : public IInputDevice
{
/// Max number of supported keys
enum { NumKeys = 256 };
/// Get the delay before key repeat, in milliseconds
virtual uint getKeyRepeatDelay() const = 0;
/// Get the delay before key repeat, in milliseconds
virtual void setKeyRepeatDelay(uint delay) = 0;
/// Get the period before key repeat, in milliseconds
virtual uint getKeyRepeatPeriod() const = 0;
/// Get the period before key repeat, in milliseconds
virtual void setKeyRepeatPeriod(uint period) = 0;
/// Set a set of keys for which repetition is disabled
virtual void disableRepetition(const TKey *keyTab, uint numKey) = 0;
/// Get the number of disabled keys
virtual uint getNumDisabledRepetition() const = 0;
/** Get the disabled keys and stores in the given tab.
* NB: must ensure the destination table has the right size
* \see getNumDisabledKeys()
*/
virtual void getDisabledRepetitions(TKey *destTab) const = 0;
};
} // NLMISC
#endif // NL_KEYBOARD_DEVICE_H
/* End of keyboard_device.h */

View file

@ -1,130 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_MOUSE_DEVICE_H
#define NL_MOUSE_DEVICE_H
#include "types_nl.h"
#include "input_device.h"
namespace NLMISC
{
class CRect;
/// An interface to a low level mouse device
struct IMouseDevice : public IInputDevice
{
enum TAxisMode { Raw, Clamped, AxisModeLast };
enum TAxis { XAxis = 0, YAxis = 1, AxisLast };
enum TMessageMode { NormalMode, RawMode, MessageModeLast };
///\name Messages
//@{
/** Tells what messages should be sent :
* DEFAULT is 'raw' messages
* Raw messages : - no clamping nor frames applied
* - no speed applied
* - no factor applied
* - CGDMouseMove messages are sent
* - Move expressed in mickeys
* Normal messages : - CEventMouseMove messages are sent
* - A frame may clamp one or both axis
* - The mouse speed can be changed
*/
virtual void setMessagesMode(TMessageMode mode) = 0;
/// retrieve what kinds of messages are sent
virtual TMessageMode getMessagesMode() const = 0;
//@}
///\name Mouse MOVE, valid only
//@{
/** Set the mode of axis of the mouse. This can be raw, or clamped. In clamped mode, a frame is used to limit the move.
* NB : invalid in raw message mode
* \see setMouseFrame(const CRect &rect)
*/
virtual void setMouseMode(TAxis axis, TAxisMode axisMode) = 0;
/** returns the mode of the mouse for the given axis.
* NB : invalid in raw message mode
*/
virtual TAxisMode getMouseMode(TAxis axis) const = 0;
/** Set the mouse speed. It must be in the ]0, +inf] range, 1 gives the natural mouse speed.
* NB : invalid in raw message mode
*/
virtual void setMouseSpeed(float speed) = 0;
/** Get the mouse speed.
* NB : invalid in raw message mode
*/
virtual float getMouseSpeed() const = 0;
/** Set the mouse acceleration. It is the threshold in mickey, when start the acceleration. 0 means not acceleration.
*/
virtual void setMouseAcceleration(uint speed) = 0;
/** Get the mouse acceleration.
*/
virtual uint getMouseAcceleration() const = 0;
/** Set the current frame in which the mouse can move, expressed in pixels.
* NB do not forget to call setMouseFactors if you want the results to be reported in the 0-1 range.
* NB : invalid in raw message mode.
* \see setMouseFactors
*/
virtual void setMouseFrame(const CRect &rect) = 0;
/** Gives factor by which the mouse coordinates must be multiplied before an event is sent.
* The default factor is 1.
* NB : invalid in raw message mode.
*
* Example : this set a frame of 800x600 and reports event in the [0, 1] range.
* \code
* mouse->setMouseFrame(800, 600);
* mouse->setMouseMode(XAxis, IMouseDevice::Clamped);
* mouse->setMouseMode(YAxis, IMouseDevice::Clamped);
* mouse->setFactors(1.f / 800, 1.f / 600);
* \endcode
*/
virtual void setFactors(float xFactor, float yFactor) = 0;
/** Get the x factor, use to multiply the mouse position before an event is sent.
* NB : invalid in raw message mode.
* \see setFactors()
*/
virtual float getXFactor() const = 0;
/** Get the y factor, use to multiply the mouse position before an event is sent.
* NB : invalid in raw message mode.
* \see setFactors()
*/
virtual float getYFactor() const = 0;
//@}
// Get the current frame used for limiting mouse movements
virtual const CRect &getMouseFrame() const = 0;
// Set the maximum delay for a double click to be taken in account (in ms).
virtual void setDoubleClickDelay(uint ms) = 0;
// Get the maximum delay for double click (in ms)
virtual uint getDoubleClickDelay() const = 0;
// Force the position of the mouse, expressed in pixels
virtual void setMousePos(float x, float y) = 0;
/// From a delta of a mouse position input (eg from CEventMouseMove), deduce delta in mickeys (eg: like received from a CGDMouseMove)
virtual void convertStdMouseMoveInMickeys(float &dx, float &dy) const = 0;
};
} // NLMISC
#endif // NL_MOUSE_DEVICE_H
/* End of u_mouse_device.h */

View file

@ -100,8 +100,6 @@ public:
*/
bool processMessage (HWND hWnd, uint32 msg, WPARAM wParam, LPARAM lParam, CEventServer *server=NULL);
void emulateMouseRawMode(bool enable);
private:
CWinEventServer _InternalServer;
HWND _HWnd;

View file

@ -25,8 +25,6 @@
#include "nel/3d/light.h"
#include "nel/3d/index_buffer.h"
#include "nel/misc/rect.h"
#include "nel/misc/di_event_emitter.h"
#include "nel/misc/mouse_device.h"
#include "nel/misc/dynloadlib.h"
#include "nel/3d/viewport.h"
#include "nel/3d/scissor.h"

View file

@ -19,8 +19,6 @@
#include "nel/3d/index_buffer.h"
#include "nel/3d/light.h"
#include "nel/misc/rect.h"
#include "nel/misc/di_event_emitter.h"
#include "nel/misc/mouse_device.h"
#include "nel/3d/viewport.h"
#include "nel/3d/scissor.h"
#include "nel/3d/u_driver.h"

View file

@ -17,9 +17,6 @@
#include "stddirect3d.h"
#include "driver_direct3d.h"
#include "nel/misc/di_event_emitter.h"
#include "nel/misc/mouse_device.h"
using namespace std;
using namespace NLMISC;

View file

@ -20,8 +20,6 @@
#include "nel/3d/light.h"
#include "nel/3d/index_buffer.h"
#include "nel/misc/rect.h"
#include "nel/misc/di_event_emitter.h"
#include "nel/misc/mouse_device.h"
#include "nel/3d/viewport.h"
#include "nel/3d/scissor.h"
#include "nel/3d/u_driver.h"

View file

@ -21,8 +21,6 @@
#include "nel/3d/index_buffer.h"
#include "nel/3d/texture_bump.h"
#include "nel/misc/rect.h"
#include "nel/misc/di_event_emitter.h"
#include "nel/misc/mouse_device.h"
#include "nel/3d/viewport.h"
#include "nel/3d/scissor.h"
#include "nel/3d/u_driver.h"

View file

@ -20,8 +20,6 @@
#include "nel/3d/light.h"
#include "nel/3d/index_buffer.h"
#include "nel/misc/rect.h"
#include "nel/misc/di_event_emitter.h"
#include "nel/misc/mouse_device.h"
#include "nel/3d/viewport.h"
#include "nel/3d/scissor.h"
#include "nel/3d/u_driver.h"

View file

@ -20,8 +20,6 @@
#include "nel/3d/light.h"
#include "nel/3d/index_buffer.h"
#include "nel/misc/rect.h"
#include "nel/misc/di_event_emitter.h"
#include "nel/misc/mouse_device.h"
#include "nel/misc/fast_mem.h"
#include "nel/3d/viewport.h"
#include "nel/3d/scissor.h"

View file

@ -20,8 +20,6 @@
#include "nel/3d/light.h"
#include "nel/3d/index_buffer.h"
#include "nel/misc/rect.h"
#include "nel/misc/di_event_emitter.h"
#include "nel/misc/mouse_device.h"
#include "nel/3d/viewport.h"
#include "nel/3d/scissor.h"
#include "nel/3d/u_driver.h"

View file

@ -20,8 +20,6 @@
#include "nel/3d/light.h"
#include "nel/3d/index_buffer.h"
#include "nel/misc/rect.h"
#include "nel/misc/di_event_emitter.h"
#include "nel/misc/mouse_device.h"
#include "nel/3d/viewport.h"
#include "nel/3d/scissor.h"
#include "nel/3d/u_driver.h"

View file

@ -28,8 +28,6 @@
#include "nel/3d/light.h"
#include "nel/3d/index_buffer.h"
#include "nel/misc/rect.h"
#include "nel/misc/di_event_emitter.h"
#include "nel/misc/mouse_device.h"
#include "nel/misc/hierarchical_timer.h"
#include "nel/misc/dynloadlib.h"
#include "driver_opengl_vertex_buffer_hard.h"

View file

@ -27,8 +27,6 @@
# endif // HAVE_XCURSOR
#endif // defined(NL_OS_UNIX) && !defined(NL_OS_MAC)
#include "nel/misc/mouse_device.h"
#include "nel/misc/di_event_emitter.h"
#include "nel/3d/u_driver.h"
#include "nel/misc/file.h"

View file

@ -38,8 +38,6 @@
# define _NET_WM_STATE_ADD 1
#endif // NL_OS_UNIX
#include "nel/misc/mouse_device.h"
#include "nel/misc/di_event_emitter.h"
#include "nel/3d/u_driver.h"
#include "nel/misc/file.h"

View file

@ -20,7 +20,6 @@
#include "nel/misc/event_emitter.h"
#include "nel/misc/event_server.h"
#include "nel/misc/events.h"
#include "nel/misc/game_device_events.h"
#include "nel/3d/driver.h"
#import "cocoa_opengl_view.h"
@ -52,7 +51,6 @@ public:
void init(NL3D::IDriver*, CocoaOpenGLView*, bool eventLoop);
bool processMessage(NSEvent* event, CEventServer* server = NULL);
virtual void submitEvents(CEventServer& server, bool allWindows);
virtual void emulateMouseRawMode(bool enable);
bool handleQuitRequest();
virtual bool copyTextToClipboard(const ucstring &text);

View file

@ -83,7 +83,6 @@
#include "nel/misc/event_emitter_multi.h"
#include "nel/misc/time_nl.h"
#include "nel/misc/rect.h"
#include "nel/misc/mouse_device.h"
#include "nel/misc/dynloadlib.h"
#include "nel/misc/file.h"

View file

@ -37,7 +37,7 @@ static Atom XA_WM_DELETE_WINDOW = 0;
namespace NLMISC {
CUnixEventEmitter::CUnixEventEmitter ():_dpy(NULL), _win(0), _emulateRawMode(false), _driver(NULL)
CUnixEventEmitter::CUnixEventEmitter ():_dpy(NULL), _win(0), _driver(NULL)
{
_im = 0;
_ic = 0;
@ -158,25 +158,6 @@ static Bool isMouseMoveEvent(Display *display, XEvent *event, XPointer arg)
return (event->type == MotionNotify);
}
void CUnixEventEmitter::emulateMouseRawMode(bool enable)
{
_emulateRawMode = enable;
if(_emulateRawMode)
{
XWindowAttributes xwa;
XGetWindowAttributes(_dpy, _win, &xwa);
XWarpPointer(_dpy, None, _win, None, None, None, None,
(xwa.width / 2), (xwa.height / 2));
// remove all outstanding mouse move events, they happened before the mouse
// was pulled back to 0.5 / 0.5, so a wrong movement delta would be
// reported otherwise
XEvent event;
while(XCheckIfEvent(_dpy, &event, &isMouseMoveEvent, NULL)) { };
}
}
#ifndef AltMask
# ifdef NL_OS_MAC
# define AltMask (8192)
@ -512,33 +493,13 @@ bool CUnixEventEmitter::processMessage (XEvent &event, CEventServer *server)
{
TMouseButton button=getMouseButton (event.xbutton.state);
// if raw mode should be emulated
if(_emulateRawMode)
{
// when we just wrapped back the pointer to 0.5 / 0.5, ignore event
if(event.xbutton.x == xwa.width / 2 && event.xbutton.y == xwa.height / 2)
break;
// get the relative mouse position
float fX = (float) event.xbutton.x / (float) xwa.width;
float fY = 1.0f - (float) event.xbutton.y / (float) xwa.height;
// post a CGDMouseMove with the movement delta to the event server
server->postEvent(
new CGDMouseMove(this, NULL /* no mouse device */,
event.xbutton.x - (xwa.width / 2),
(xwa.height / 2) - event.xbutton.y));
// post a normal mouse move event to the event server
server->postEvent (new CEventMouseMove (fX, fY, button, this));
// move the pointer back to the center of the window
XWarpPointer(_dpy, None, _win, None, None, None, None,
(xwa.width / 2), (xwa.height / 2));
}
// if in normal mouse mode
else
{
// get the relative mouse position
float fX = (float) event.xbutton.x / (float) xwa.width;
float fY = 1.0f - (float) event.xbutton.y / (float) xwa.height;
// post a normal mouse move event to the event server
server->postEvent (new CEventMouseMove (fX, fY, button, this));
}
break;
}
case KeyPress:

View file

@ -20,7 +20,6 @@
#include "nel/misc/types_nl.h"
#include "nel/misc/event_emitter.h"
#include "nel/misc/events.h"
#include "nel/misc/game_device_events.h"
#include "nel/3d/driver.h"
@ -56,11 +55,6 @@ public:
*/
virtual void submitEvents(CEventServer & server, bool allWindows);
/**
* enable or disable mouse raw mode
*/
virtual void emulateMouseRawMode(bool emulate);
/**
* process input-related events (mouse and keyboard)
*/

View file

@ -1609,36 +1609,6 @@ bool CDriverUser::fillBuffer (CBitmap &bitmap)
// ***************************************************************************
// ***************************************************************************
NLMISC::IMouseDevice *CDriverUser::enableLowLevelMouse(bool enable, bool exclusive)
{
NL3D_HAUTO_UI_DRIVER;
return _Driver->enableLowLevelMouse(enable, exclusive);
}
NLMISC::IKeyboardDevice *CDriverUser::enableLowLevelKeyboard(bool enable)
{
NL3D_HAUTO_UI_DRIVER;
return _Driver->enableLowLevelKeyboard(enable);
}
void CDriverUser::emulateMouseRawMode(bool enable)
{
_Driver->getEventEmitter()->emulateMouseRawMode(enable);
}
uint CDriverUser::getDoubleClickDelay(bool hardwareMouse)
{
NL3D_HAUTO_UI_DRIVER;
return _Driver->getDoubleClickDelay(hardwareMouse);
}
NLMISC::IInputDeviceManager *CDriverUser::getLowLevelInputDeviceManager()
{
NL3D_HAUTO_UI_DRIVER;
return _Driver->getLowLevelInputDeviceManager();
}
void CDriverUser::showCursor (bool b)
{
NL3D_HAUTO_UI_DRIVER;

View file

@ -1,354 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdmisc.h"
#include "nel/misc/di_event_emitter.h"
#include "nel/misc/events.h"
#include "nel/misc/win_event_emitter.h"
//
#include "di_mouse_device.h"
#include "di_keyboard_device.h"
#include "di_game_device.h"
#ifdef NL_OS_WINDOWS
#ifdef DEBUG_NEW
#define new DEBUG_NEW
#endif
namespace NLMISC
{
static const char DirectInputLibName[] = "dinput8.dll";
/////////////////////////////////
// CDIEventEmitter statics //
/////////////////////////////////
HMODULE CDIEventEmitter::_DirectInputLibHandle = 0;
CDIEventEmitter::TPDirectInput8Create CDIEventEmitter::_PDirectInput8Create = NULL;
uint CDIEventEmitter::_NumCreatedInterfaces = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////
// CDIEventEmitter implementation //
////////////////////////////////////
//======================================================
CDIEventEmitter::CDIEventEmitter(HWND hwnd, CWinEventEmitter *we)
:
_hWnd(hwnd),
_WE(we),
_DInput8(NULL),
_Keyboard(NULL),
_Mouse(NULL),
_ButtonsFlags(noButton)
{
}
//======================================================
CDIEventEmitter::~CDIEventEmitter()
{
releaseMouse();
releaseKeyboard();
// release all devices
while (_DeviceServer.getNumDevices() != 0)
{
IInputDevice *dev = _DeviceServer.getDevice(0);
_DeviceServer.removeDevice(dev);
delete dev;
}
if (_DInput8) _DInput8->Release();
-- _NumCreatedInterfaces;
if (_NumCreatedInterfaces == 0) unloadLib();
}
//======================================================
CDIEventEmitter *CDIEventEmitter::create(HINSTANCE hinst, HWND hwnd, CWinEventEmitter *we) throw(EDirectInput)
{
if (!loadLib()) throw EDirectInputLibNotFound();
std::auto_ptr<CDIEventEmitter> dxee(new CDIEventEmitter(hwnd, we));
HRESULT result = _PDirectInput8Create(hinst,
DIRECTINPUT_VERSION,
IID_IDirectInput8A,
(void **) &dxee->_DInput8,
NULL);
if (result != DI_OK) throw EDirectInputInitFailed();
// ok, everything's fine, commit changes
++_NumCreatedInterfaces;
return dxee.release();
}
//======================================================
bool CDIEventEmitter::loadLib()
{
if (_DirectInputLibHandle != 0) return true; // library already loaded ?
HMODULE handle = ::LoadLibrary(DirectInputLibName);
if (handle == 0) return false;
// try to get the creation function
TPDirectInput8Create cf = (TPDirectInput8Create) ::GetProcAddress(handle, "DirectInput8Create");
if (!cf)
{
::FreeLibrary(handle);
return false;
}
// commit changes
_DirectInputLibHandle = handle;
_PDirectInput8Create = cf;
return true;
}
//======================================================
void CDIEventEmitter::unloadLib()
{
nlassert(_DirectInputLibHandle != 0);
::FreeLibrary(_DirectInputLibHandle);
_DirectInputLibHandle = 0;
_PDirectInput8Create = NULL;
}
//======================================================
void CDIEventEmitter::poll(CEventServer *server)
{
if (_WE) _ButtonsFlags = _WE->buildFlags();
if (!server)
server=&_InternalServer;
_DeviceServer.poll(server);
}
//======================================================
TMouseButton CDIEventEmitter::buildButtonsFlags() const
{
uint mouseFlags;
uint keybFlags;
//
if (_Mouse) // takes the flags from the direct input mouse
{
mouseFlags = (_Mouse->getButton(0) ? leftButton : 0)
| (_Mouse->getButton(1) ? rightButton : 0)
| (_Mouse->getButton(2) ? middleButton : 0);
}
else // takes the flags from the system mouse
{
mouseFlags = _ButtonsFlags & (leftButton | rightButton | middleButton);
}
//
if (_Keyboard) // takes the flags from the direct input keyboard
{
keybFlags = (_Keyboard->ShiftPressed ? shiftButton : 0)
| (_Keyboard->AltPressed ? altButton : 0)
| (_Keyboard->CtrlPressed ? ctrlButton : 0);
}
else // takes the flags from the system keyboard
{
keybFlags = _ButtonsFlags & (shiftButton | altButton | ctrlButton);
}
return (TMouseButton) (keybFlags | mouseFlags);
}
//======================================================
IMouseDevice *CDIEventEmitter::getMouseDevice(bool hardware) throw(EInputDevice)
{
if (_Mouse) return _Mouse; // already created ?
try
{
// Create a mouse
std::auto_ptr<CDIMouse> mouse(CDIMouse::createMouseDevice(_DInput8, _hWnd, this, hardware, _WE));
// register to the device server
_DeviceServer.registerDevice(mouse.get());
_Mouse = mouse.get();
return mouse.release();
}
catch (...)
{
if (_WE) _WE->enableMouseEvents(true);
throw;
}
}
//======================================================
void CDIEventEmitter::releaseMouse()
{
if (!_Mouse) return;
// reupdate the system keyboard flags
if (_WE)
{
_WE->resetButtonFlagState();
_WE->enableMouseEvents(true);
}
// remove the device
_DeviceServer.removeDevice(_Mouse);
delete _Mouse;
_Mouse = NULL;
}
//===========================================================================
IKeyboardDevice *CDIEventEmitter::getKeyboardDevice() throw(EInputDevice)
{
if (_Keyboard) return _Keyboard;
try
{
// create a keyboard
std::auto_ptr<CDIKeyboard> keyboard(CDIKeyboard::createKeyboardDevice(_DInput8, _hWnd, this, _WE));
// register to the device server
_DeviceServer.registerDevice(keyboard.get());
_Keyboard = keyboard.get();
return keyboard.release();
}
catch (...)
{
if (_WE) _WE->enableKeyboardEvents(true);
throw;
}
}
//==========================================================================
void CDIEventEmitter::releaseKeyboard()
{
if (!_Keyboard) return;
// reupdate the system keyboard flags
if (_WE)
{
_WE->resetButtonFlagState();
_WE->enableKeyboardEvents(true);
}
//
_DeviceServer.removeDevice(_Keyboard);
delete _Keyboard;
_Keyboard = NULL;
}
//==========================================================================
void CDIEventEmitter::submitEvents(CEventServer &server, bool allWindows)
{
_InternalServer.setServer(&server);
_InternalServer.pump(allWindows);
}
//==========================================================================
void CDIEventEmitter::emulateMouseRawMode(bool enable)
{
nlerror("no raw mode emulation on windows, the CDIMouse has a real raw mode");
}
//==========================================================================
/// Tool fct to retrieve the game devices.
static BOOL CALLBACK DIEnumDevicesDescCallback
(
LPCDIDEVICEINSTANCE lpddi,
LPVOID pvRef
)
{
CGameDeviceDesc desc;
desc.InstanceName = lpddi->tszInstanceName;
desc.ProductName = lpddi->tszProductName;
switch (lpddi->wUsage & 0xff)
{
case DI8DEVTYPE_JOYSTICK: desc.DevType = CGameDeviceDesc::Joystick; break;
case DI8DEVTYPE_GAMEPAD: desc.DevType = CGameDeviceDesc::GamePad; break;
default: desc.DevType = CGameDeviceDesc::DontKnow; break;
}
TDeviceDescVect *dv = (TDeviceDescVect *) pvRef;
dv->push_back(desc);
return DIENUM_CONTINUE;
}
//==========================================================================
/// Tool fct to retrieve the game devices GUID
static BOOL CALLBACK DIEnumDevicesGUIDCallback
(
LPCDIDEVICEINSTANCE lpddi,
LPVOID pvRef
)
{
std::vector<GUID> *gv = (std::vector<GUID> *) pvRef;
gv->push_back(lpddi->guidInstance);
return DIENUM_CONTINUE;
}
//==========================================================================
void CDIEventEmitter::enumerateGameDevice(TDeviceDescVect &descs) throw(EInputDevice)
{
uint k;
nlassert(_DInput8);
descs.clear();
// enum all devices of interest
_DInput8->EnumDevices(DI8DEVCLASS_GAMECTRL, &DIEnumDevicesDescCallback, (LPVOID) &descs, DIEDFL_ALLDEVICES);
for (k = 0; k < descs.size(); ++k) descs[k].Connected = false;
// enum all connected devices
static TDeviceDescVect connecteds;
_DInput8->EnumDevices(DI8DEVCLASS_GAMECTRL, &DIEnumDevicesDescCallback, (LPVOID) &connecteds, DIEDFL_ATTACHEDONLY);
// see which devices are connected
for (k = 0; k < connecteds.size(); ++k)
{
TDeviceDescVect::iterator it = std::find(descs.begin(), descs.end(), connecteds[k]);
it->Connected = true;
}
}
//==========================================================================
IGameDevice *CDIEventEmitter::createGameDevice(const std::string &instanceName) throw(EInputDevice)
{
static TDeviceDescVect deviceDescs;
static std::vector<GUID> deviceGUID;
nlassert(_DInput8);
enumerateGameDevice(deviceDescs);
// get the ID for each device
deviceGUID.clear();
HRESULT r = _DInput8->EnumDevices(DI8DEVCLASS_GAMECTRL, &DIEnumDevicesGUIDCallback, (LPVOID) &deviceGUID, DIEDFL_ALLDEVICES);
nlassert(r == DI_OK);
nlassert(deviceDescs.size() == deviceGUID.size());
// search the device that match the instance name
for (uint k = 0; k < deviceDescs.size(); ++k)
{
if (deviceDescs[k].InstanceName == instanceName)
{
std::auto_ptr<CDIGameDevice> gd(CDIGameDevice::createGameDevice(_DInput8, _hWnd, this, deviceDescs[k], deviceGUID[k]));
// insert in the device server
_DeviceServer.registerDevice(gd.get());
return gd.release();
}
}
return NULL;
}
//==========================================================================
void CDIEventEmitter::releaseGameDevice(IGameDevice *gd)
{
nlassert(gd);
CDIGameDevice *digd = safe_cast<CDIGameDevice *>(gd);
_DeviceServer.removeDevice(digd);
delete gd;
}
} // NLMISC
#endif // NL_OS_WINDOWS

View file

@ -1,523 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdmisc.h"
#include "di_game_device.h"
#include "nel/misc/game_device_events.h"
#ifdef NL_OS_WINDOWS
#ifdef DEBUG_NEW
#define new DEBUG_NEW
#endif
namespace NLMISC
{
//============================================================================
CDIGameDevice::CDIGameDevice() : _Device(NULL)
{
::memset(&_CurrentState, 0, sizeof(_CurrentState));
}
//============================================================================
CDIGameDevice::~CDIGameDevice()
{
if (_Device)
{
_Device->Unacquire();
_Device->Release();
}
}
//============================================================================
CDIGameDevice *CDIGameDevice::createGameDevice(IDirectInput8 *di8,
HWND hwnd,
CDIEventEmitter *diEventEmitter,
const CGameDeviceDesc &desc,
REFGUID rguid) throw(EDirectInput)
{
nlassert(diEventEmitter);
nlassert(di8);
std::auto_ptr<CDIGameDevice> dev(new CDIGameDevice);
//
HRESULT r = di8->CreateDevice(rguid, &dev->_Device, NULL);
if (r != DI_OK) throw EDirectInputGameDeviceNotCreated();
r = dev->_Device->SetDataFormat(pJoyDataFormat);
nlassert(r == DI_OK);
//
r = dev->_Device->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE);
if (r != DI_OK) throw EDirectInputCooperativeLevelFailed();
//
//
dev->_Desc = desc;
dev->_EventEmitter = diEventEmitter;
dev->querryControls();
return dev.release();
}
//============================================================================
void CDIGameDevice::begin(CEventServer *server)
{
nlassert(_Device);
HRESULT r;
r = _Device->Poll();
if (r == DIERR_INPUTLOST || r == DIERR_NOTACQUIRED)
{
r = _Device->Acquire();
if (r != DI_OK) return;
r = _Device->Poll();
if (r != DI_OK) return;
}
CDIJoyState newState;
r = _Device->GetDeviceState(sizeof(CDIJoyState), &newState);
if (r != DI_OK) return;
uint k;
//////////
// Axis //
//////////
for (k = 0; k < MaxNumAxis; ++k)
{
CAxis &axis = _Axis[k];
if (axis.Present)
{
if (((LONG *) &newState)[k] != ((LONG *) &_CurrentState)[k]) // state changed ?
{
// update position
axis.Value = 2.f * (((LONG *) &newState)[k] - axis.Min) / (float) (axis.Max - axis.Min) - 1.f;
// create event
CGDAxisMoved *event = new CGDAxisMoved((IGameDevice::TAxis) k, axis.Value, this, _EventEmitter);
// update state
((LONG *) &_CurrentState)[k] = ((LONG *) &newState)[k];
//
server->postEvent(event);
//
}
}
}
/////////////
// Buttons //
/////////////
for (k = 0; k < _Buttons.size(); ++k)
{
CButton &bt = _Buttons[k];
if ((newState.rgbButtons[k] & 0x80) != (_CurrentState.rgbButtons[k] & 0x80))
{
bool pushed = (newState.rgbButtons[k] & 0x80) != 0;
// update the state of the button
bt.Pushed = pushed;
CGDButton *event;
if (pushed) event = new CGDButtonDown(k, this, _EventEmitter);
else event = new CGDButtonUp(k, this, _EventEmitter);
// update state
_CurrentState.rgbButtons[k] = newState.rgbButtons[k];
server->postEvent(event);
}
}
/////////////
// Sliders //
/////////////
for (k = 0; k < _Sliders.size(); ++k)
{
CSlider &sl = _Sliders[k];
if (newState.rglSlider[k] != _CurrentState.rglSlider[k]) // state changed ?
{
// update position
sl.Pos = ( newState.rglSlider[k] - sl.Min) / (float) (sl.Max - sl.Min);
// create event
CGDSliderMoved *event = new CGDSliderMoved(sl.Pos, k, this, _EventEmitter);
// update state
_CurrentState.rglSlider[k] = newState.rglSlider[k];
//
server->postEvent(event);
}
}
//////////
// POVs //
//////////
for (k = 0; k < _POVs.size(); ++k)
{
CPOV &pov = _POVs[k];
if (newState.rgdwPOV[k] != _CurrentState.rgdwPOV[k]) // state changed ?
{
DWORD value = newState.rgdwPOV[k];
pov.Centered = (LOWORD(value) == 0xFFFF);
if (!pov.Centered)
{
// update position
pov.Angle = value / 100.f;
}
// create event
CGDPOVChanged *event = new CGDPOVChanged(pov.Centered, pov.Angle, k, this, _EventEmitter);
// update state
_CurrentState.rgdwPOV[k] = newState.rgdwPOV[k];
//
server->postEvent(event);
}
}
}
//============================================================================
void CDIGameDevice::poll(CInputDeviceServer *dev)
{
// buffered datas not supported
}
//============================================================================
void CDIGameDevice::submit(IInputDeviceEvent *deviceEvent, CEventServer *server)
{
// should never be called, buffered datas not supported
nlassert(0);
}
//============================================================================
/** Tool fct : tests whether a DIDEVICEOBJECTINSTANCE contains a controls name and return it,
* or build a default one
*/
static void BuildCtrlName(LPCDIDEVICEOBJECTINSTANCE lpddoi,
std::string &destName,
const char *defaultName)
{
if (lpddoi->dwSize >= offsetof(DIDEVICEOBJECTINSTANCE, tszName) + sizeof(TCHAR[MAX_PATH]))
{
destName = (::strcmp("N/A", lpddoi->tszName) == 0) ? defaultName
: lpddoi->tszName;
}
else
{
destName = defaultName;
}
}
//============================================================================
// A callback to enumerate the controls of a device
BOOL CALLBACK DIEnumDeviceObjectsCallback
(
LPCDIDEVICEOBJECTINSTANCE lpddoi,
LPVOID pvRef
)
{
CDIGameDevice *gd = (CDIGameDevice *) pvRef;
return gd->processEnumObject(lpddoi);
}
//=======================================================================
// get range for an axis
static HRESULT GetDIAxisRange(LPDIRECTINPUTDEVICE8 device, uint offset, DWORD type, sint &min, sint &max)
{
DIPROPRANGE diprg;
diprg.diph.dwSize = sizeof(DIPROPRANGE);
diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
diprg.diph.dwHow = DIPH_BYOFFSET;
diprg.diph.dwObj = offset;
// Set the range for the axis
HRESULT r = device->GetProperty(DIPROP_RANGE, &diprg.diph);
if (r == DIERR_OBJECTNOTFOUND)
{
// try from its ID
diprg.diph.dwHow = DIPH_BYID;
diprg.diph.dwObj = type;
// Set the range for the axis
HRESULT r = device->GetProperty(DIPROP_RANGE, &diprg.diph);
if (r != DI_OK)
{
// setup default values ...
min = 0;
max = 65535;
return r;
}
}
else if (r != DI_OK)
{
min = 0;
max = 65535;
return r;
}
/* switch (r)
{
default:
nlinfo("ok");
break;
case DIERR_INVALIDPARAM:
nlinfo("invalid param");
break;
case DIERR_NOTEXCLUSIVEACQUIRED:
nlinfo("DIERR_NOTEXCLUSIVEACQUIRED");
break;
case DIERR_NOTINITIALIZED:
nlinfo("DIERR_NOTINITIALIZED");
break;
case DIERR_OBJECTNOTFOUND:
nlinfo("DIERR_OBJECTNOTFOUND");
break;
case DIERR_UNSUPPORTED:
nlinfo("DIERR_UNSUPPORTED");
break;
}*/
min = (sint) diprg.lMin;
max = (sint) diprg.lMax;
return r;
}
//============================================================================
BOOL CDIGameDevice::processEnumObject(LPCDIDEVICEOBJECTINSTANCE lpddoi)
{
// the dwSize field gives us the size of the objects, and the available fields
// has this object the field guidType and dwOfs ?
if (lpddoi->dwSize < offsetof(DIDEVICEOBJECTINSTANCE, dwOfs) + sizeof(DWORD)) return DIENUM_CONTINUE;
uint ctrlType = (uint) lpddoi->dwType;
///////////////////////////////////////////
// axis, we only support absolute ones //
///////////////////////////////////////////
if (lpddoi->guidType == GUID_XAxis && (ctrlType & DIDFT_ABSAXIS) )
{
GetDIAxisRange(_Device, lpddoi->dwOfs, lpddoi->dwType, _Axis[XAxis].Min, _Axis[XAxis].Max);
BuildCtrlName(lpddoi, _Axis[XAxis].Name, "X Axis");
_Axis[XAxis].Present = true;
return DIENUM_CONTINUE;
}
if (lpddoi->guidType == GUID_YAxis && (ctrlType & DIDFT_ABSAXIS))
{
GetDIAxisRange(_Device, lpddoi->dwOfs, lpddoi->dwType, _Axis[YAxis].Min, _Axis[YAxis].Max);
BuildCtrlName(lpddoi, _Axis[YAxis].Name, "Y Axis");
_Axis[YAxis].Present = true;
return DIENUM_CONTINUE;
}
if (lpddoi->guidType == GUID_ZAxis && (ctrlType & DIDFT_ABSAXIS))
{
GetDIAxisRange(_Device, lpddoi->dwOfs, lpddoi->dwType, _Axis[ZAxis].Min, _Axis[ZAxis].Max);
BuildCtrlName(lpddoi, _Axis[ZAxis].Name, "Z Axis");
_Axis[ZAxis].Present = true;
return DIENUM_CONTINUE;
}
if (lpddoi->guidType == GUID_RxAxis && (ctrlType & DIDFT_ABSAXIS))
{
GetDIAxisRange(_Device, lpddoi->dwOfs, lpddoi->dwType, _Axis[RXAxis].Min, _Axis[RXAxis].Max);
BuildCtrlName(lpddoi, _Axis[RXAxis].Name, "RX Axis");
_Axis[RXAxis].Present = true;
return DIENUM_CONTINUE;
}
if (lpddoi->guidType == GUID_RyAxis && (ctrlType & DIDFT_ABSAXIS))
{
GetDIAxisRange(_Device, lpddoi->dwOfs, lpddoi->dwType, _Axis[RYAxis].Min, _Axis[RYAxis].Max);
BuildCtrlName(lpddoi, _Axis[RYAxis].Name, "RY Axis");
_Axis[RYAxis].Present = true;
return DIENUM_CONTINUE;
}
if (lpddoi->guidType == GUID_RzAxis && (ctrlType & DIDFT_ABSAXIS))
{
GetDIAxisRange(_Device, lpddoi->dwOfs, lpddoi->dwType, _Axis[RZAxis].Min, _Axis[RZAxis].Max);
BuildCtrlName(lpddoi, _Axis[RZAxis].Name, "RZ Axis");
_Axis[RZAxis].Present = true;
return DIENUM_CONTINUE;
}
// has this object the field dwType ?
if (lpddoi->dwSize < offsetof(DIDEVICEOBJECTINSTANCE, dwType) + sizeof(DWORD)) return DIENUM_CONTINUE;
uint type = lpddoi->dwType;
/////////////
// Buttons //
/////////////
if (type & DIDFT_BUTTON)
{
if (_Buttons.size() < MaxNumButtons)
{
_Buttons.push_back(CButton());
uint buttonIndex = (uint)_Buttons.size() - 1;
char defaultButtonName[32];
smprintf(defaultButtonName, 32, "BUTTON %d", buttonIndex + 1);
BuildCtrlName(lpddoi, _Buttons[buttonIndex].Name, defaultButtonName);
return DIENUM_CONTINUE;
}
}
/////////////
// Sliders //
/////////////
if (type & DIDFT_ABSAXIS)
{
if (_Sliders.size() < MaxNumSliders)
{
_Sliders.push_back(CSlider());
uint sliderIndex = (uint)_Sliders.size() - 1;
GetDIAxisRange(_Device, lpddoi->dwOfs, lpddoi->dwType, _Sliders[sliderIndex].Min, _Sliders[sliderIndex].Max);
char defaultSliderName[32];
smprintf(defaultSliderName, 32, "SLIDER %d", sliderIndex + 1);
BuildCtrlName(lpddoi, _Sliders[sliderIndex].Name, defaultSliderName);
}
return DIENUM_CONTINUE;
}
//////////
// POVs //
//////////
if (type & DIDFT_POV)
{
if (_POVs.size() < MaxNumPOVs)
{
_POVs.push_back(CPOV());
uint povIndex = (uint)_POVs.size() - 1;
char defaultPOVName[16];
smprintf(defaultPOVName, 16, "POV %d", povIndex + 1);
BuildCtrlName(lpddoi, _POVs[povIndex].Name, defaultPOVName);
}
return DIENUM_CONTINUE;
}
return DIENUM_CONTINUE;
}
//============================================================================
void CDIGameDevice::querryControls()
{
HRESULT r = _Device->EnumObjects(&DIEnumDeviceObjectsCallback, (LPVOID) this, DIDFT_ALL);
nlassert(r == DI_OK);
}
//============================================================================
bool CDIGameDevice::setBufferSize(uint size)
{
// uisually not supported by this kind of devices
return false;
}
//============================================================================
uint CDIGameDevice::getBufferSize() const
{
// uisually not supported by this kind of devices
return 0;
}
//============================================================================
uint CDIGameDevice::getNumButtons() const
{
return (uint)_Buttons.size();
}
//============================================================================
bool CDIGameDevice::hasAxis(TAxis axis) const
{
nlassert(axis < MaxNumAxis);
return _Axis[axis].Present;
}
//============================================================================
uint CDIGameDevice::getNumSliders() const
{
return (uint)_Sliders.size();
}
//============================================================================
uint CDIGameDevice::getNumPOV() const
{
return (uint)_POVs.size();
}
//============================================================================
const char *CDIGameDevice::getButtonName(uint index) const
{
nlassert(index < _Buttons.size());
return _Buttons[index].Name.c_str();
}
//============================================================================
const char *CDIGameDevice::getAxisName(TAxis axis) const
{
nlassert(axis < MaxNumAxis);
nlassert(hasAxis(axis)); // ! Not an axis of this device
return _Axis[axis].Name.c_str();
}
//============================================================================
const char *CDIGameDevice::getSliderName(uint index) const
{
nlassert(index < _Sliders.size());
return _Sliders[index].Name.c_str();
}
//============================================================================
const char *CDIGameDevice::getPOVName(uint index) const
{
nlassert(index < _POVs.size());
return _POVs[index].Name.c_str();
}
//============================================================================
bool CDIGameDevice::getButtonState(uint index) const
{
nlassert(index < _Buttons.size());
return _Buttons[index].Pushed;
}
//============================================================================
float CDIGameDevice::getAxisValue(TAxis axis) const
{
nlassert(axis < MaxNumAxis);
nlassert(hasAxis(axis)); // ! Not an axis of this device
return _Axis[axis].Value;
}
//============================================================================
float CDIGameDevice::getSliderPos(uint index) const
{
nlassert(index < _Sliders.size());
return _Sliders[index].Pos;
}
//============================================================================
float CDIGameDevice::getPOVAngle(uint index) const
{
nlassert(index < _POVs.size());
return _POVs[index].Angle;
}
} // NLMISC
#endif // NL_OS_WINDOWS

View file

@ -1,170 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_DI_GAME_DEVICE_H
#define NL_DI_GAME_DEVICE_H
#include "nel/misc/types_nl.h"
#ifdef NL_OS_WINDOWS
#include "nel/misc/di_event_emitter.h"
#include "nel/misc/game_device.h"
namespace NLMISC
{
//
typedef DIJOYSTATE2 CDIJoyState;
const DIDATAFORMAT * const pJoyDataFormat = &c_dfDIJoystick2;
const uint MaxNumSliders = 2;
const uint MaxNumPOVs = 4;
const uint MaxNumButtons = 128;
//
struct EDirectInputGameDeviceNotCreated : EDirectInput
{
EDirectInputGameDeviceNotCreated() : EDirectInput("Unable to create a game device") {}
};
/**
* Direct input implementation of a game device.
*/
class CDIGameDevice : public IGameDevice
{
public:
/// Create a direct input game device from the given RGUID. Destroy it with delete
static CDIGameDevice *createGameDevice(IDirectInput8 *di8,
HWND hwnd,
CDIEventEmitter *diEventEmitter,
const CGameDeviceDesc &desc,
REFGUID rguid) throw(EDirectInput);
~CDIGameDevice();
///\name From IInputDevice
//@{
virtual bool setBufferSize(uint size);
virtual uint getBufferSize() const;
//@}
///\name From IGameDevice
//@{
virtual const CGameDeviceDesc &getDescription() const { return _Desc; }
//
virtual uint getNumButtons() const;
virtual bool hasAxis(TAxis axis) const;
virtual uint getNumSliders() const;
virtual uint getNumPOV() const;
//
virtual const char *getButtonName(uint index) const;
virtual const char *getAxisName(TAxis axis) const;
virtual const char *getSliderName(uint index) const;
virtual const char *getPOVName(uint index) const;
//
virtual bool getButtonState(uint index) const;
virtual float getAxisValue(TAxis axis) const;
virtual float getSliderPos(uint index) const;
virtual float getPOVAngle(uint index) const;
//@}
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
private:
// base class for controls
struct CCtrl
{
std::string Name;
};
// a button
struct CButton : public CCtrl
{
bool Pushed;
CButton() : Pushed(false) {}
};
// an axis. Its value either gives its position (-1 .. 1) or its angle (CCW in radians)
struct CAxis : public CCtrl
{
bool Present; // is this axis used ?
// min and max values from Direct Input
sint Min, Max;
float Value;
CAxis() : Value(0.f), Present(false) {}
};
// a slider
struct CSlider : public CCtrl
{
sint Min, Max;
float Pos;
CSlider() : Pos(0.f) {}
};
// a POV
struct CPOV : public CCtrl
{
bool Centered;
float Angle;
CPOV() : Angle(0.f), Centered(true) {}
};
private:
// ctor
CDIGameDevice();
///\name From IInputDevice
//@{
virtual void begin(CEventServer *server);
virtual void poll(CInputDeviceServer *dev);
virtual void submit(IInputDeviceEvent *deviceEvent, CEventServer *server);
//@}
/** Get the controls (buttons, slider..) of this device from the Direct Input interface to build this object infos.
*/
void querryControls();
/// Called during EnumObject
BOOL processEnumObject(LPCDIDEVICEOBJECTINSTANCE lpddoi);
friend BOOL CALLBACK DIEnumDeviceObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef);
private:
LPDIRECTINPUTDEVICE8 _Device;
CGameDeviceDesc _Desc;
CDIEventEmitter *_EventEmitter;
///\name Device infos
//@{
CAxis _Axis[MaxNumAxis];
std::vector<CButton> _Buttons;
std::vector<CSlider> _Sliders;
std::vector<CPOV> _POVs;
//@}
CDIJoyState _CurrentState;
};
} // NLMISC
#endif // NL_OS_WINDOWS
#endif // NL_DI_GAME_DEVICE_H
/* End of di_play_device.h */

View file

@ -1,686 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdmisc.h"
#include "di_keyboard_device.h"
#ifdef NL_OS_WINDOWS
#include "nel/misc/win_event_emitter.h"
#include <dinput.h>
#include <Winuser.h>
#include "Mmsystem.h"
#ifdef DEBUG_NEW
#define new DEBUG_NEW
#endif
namespace NLMISC
{
// used to do a conversion from DX key code to Nel keys enums
struct CKeyConv
{
uint DIKey;
TKey NelKey;
const char *KeyName;
bool Repeatable;
};
// this is used to build a conversion table
static const CKeyConv DIToNel[] =
{
//
{DIK_F1, KeyF1, "F1", true},
{DIK_F2, KeyF2, "F2", true},
{DIK_F3, KeyF3, "F3", true},
{DIK_F4, KeyF4, "F4", true},
{DIK_F5, KeyF5, "F5", true},
{DIK_F6, KeyF6, "F6", true},
{DIK_F7, KeyF7, "F7", true},
{DIK_F8, KeyF8, "F8", true},
{DIK_F9, KeyF9, "F9", true},
{DIK_F10, KeyF10, "F10", true},
{DIK_F11, KeyF11, "F11", true},
{DIK_F12, KeyF12, "F12", true},
{DIK_F13, KeyF13, "F13", true},
{DIK_F14, KeyF14, "F14", true},
{DIK_F15, KeyF15, "F15", true},
//
{DIK_NUMPAD0, KeyNUMPAD0, "NUMPAD0", true},
{DIK_NUMPAD1, KeyNUMPAD1, "NUMPAD1", true},
{DIK_NUMPAD2, KeyNUMPAD2, "NUMPAD2", true},
{DIK_NUMPAD3, KeyNUMPAD3, "NUMPAD3", true},
{DIK_NUMPAD4, KeyNUMPAD4, "NUMPAD4", true},
{DIK_NUMPAD5, KeyNUMPAD5, "NUMPAD5", true},
{DIK_NUMPAD6, KeyNUMPAD6, "NUMPAD6", true},
{DIK_NUMPAD7, KeyNUMPAD7, "NUMPAD7", true},
{DIK_NUMPAD8, KeyNUMPAD8, "NUMPAD8", true},
{DIK_NUMPAD9, KeyNUMPAD9, "NUMPAD9", true},
//
{DIK_DIVIDE, KeyDIVIDE, "/", true},
{DIK_DECIMAL, KeyDECIMAL, "NUMPAD .", true},
//
{DIK_LSHIFT, KeyLSHIFT, "LEFT SHIFT", false},
{DIK_RSHIFT, KeyRSHIFT, "RIGHT SHIFT", false},
//
{DIK_LCONTROL, KeyLCONTROL, "LEFT CONTROL", false},
{DIK_RCONTROL, KeyRCONTROL, "RIGHT CONTROL", false},
//
{DIK_LMENU, KeyLMENU, "ALT", false},
{DIK_RMENU, KeyRMENU, "ALT GR", false},
//
{DIK_UP, KeyUP, "UP", true},
{DIK_PRIOR, KeyPRIOR, "PRIOR", true},
{DIK_LEFT, KeyLEFT, "LEFT", true},
{DIK_RIGHT, KeyRIGHT, "RIGHT", true},
{DIK_END, KeyEND, "END", true},
{DIK_DOWN, KeyDOWN, "DOWN", true},
{DIK_NEXT, KeyNEXT, "NEXT", true},
{DIK_INSERT, KeyINSERT, "INSERT", true},
{DIK_DELETE, KeyDELETE, "DELETE", true},
{DIK_HOME, KeyHOME, "HOME", true},
{DIK_LWIN, KeyLWIN, "LEFT WIN", false},
{DIK_RWIN, KeyRWIN, "RIGHT WIN", false},
{DIK_APPS, KeyAPPS, "APPS", false},
{DIK_BACK, KeyBACK, "BACK", true},
//
{DIK_SYSRQ, KeySNAPSHOT, "SNAPSHOT", false},
{DIK_SCROLL, KeySCROLL, "SCROLL", false},
{DIK_PAUSE, KeyPAUSE, "PAUSE", false},
//
{DIK_NUMLOCK, KeyNUMLOCK, "NUMLOCK", false},
//
{DIK_NUMPADENTER, KeyRETURN, "RETURN", true},
//{DIK_NUMPADENTER, KeyRETURN, "ENTER", true},
//
{DIK_CONVERT, KeyCONVERT, "CONVERT", false},
{DIK_NOCONVERT, KeyNONCONVERT, "NOCONVERT", true},
//
{DIK_KANA, KeyKANA, "KANA", false},
{DIK_KANJI, KeyKANJI, "KANJI", false},
};
///========================================================================
const CKeyConv *CDIKeyboard::DIKeyToNelKeyTab[CDIKeyboard::NumKeys];
///========================================================================
CDIKeyboard::CDIKeyboard(CWinEventEmitter *we, HWND hwnd)
: _Keyboard(NULL),
_WE(we),
ShiftPressed(false),
CtrlPressed(false),
AltPressed(false),
_CapsLockToggle(true),
_hWnd(hwnd),
_RepeatDelay(250),
_RepeatPeriod(200),
_FirstPressDate(-1),
_LastDIKeyPressed(0)
{
if (::GetKeyboardState((PBYTE) _VKKeyState) == FALSE)
{
std::fill(_VKKeyState, _VKKeyState + NumKeys, 0);
}
// test whether the user toggle its keyboard with shift or not..
HKEY hKey;
if (::RegOpenKeyEx(HKEY_CURRENT_USER, "Keyboard Layout", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
DWORD type = REG_DWORD;
DWORD value;
DWORD size = sizeof(DWORD);
if (::RegQueryValueEx(hKey, "Attributes", NULL, &type, (LPBYTE) &value, &size) == ERROR_SUCCESS)
{
_CapsLockToggle = (value & (1 << 16)) == 0;
}
::RegCloseKey(hKey);
}
// get repeat delay and period
int keybDelay;
if (::SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &keybDelay, 0) != 0)
{
_RepeatDelay = 250 + 250 * keybDelay;
}
DWORD keybSpeed;
if (::SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &keybSpeed, 0) != 0)
{
_RepeatPeriod = (uint) (1000.f / (keybSpeed * (27.5f / 31.f) + 2.5f));
}
// get keyboard layout
_KBLayout = ::GetKeyboardLayout(0);
_RepetitionDisabled.resize(NumKeys);
_RepetitionDisabled.clearAll();
}
///========================================================================
void CDIKeyboard::updateVKKeyState(uint diKey, bool pressed, TKey &keyValue, TKey &charValue)
{
bool extKey;
bool repeatable;
keyValue = DIKeyToNelKey(diKey, extKey, repeatable);
//
if (keyValue == 0)
{
charValue = keyValue;
return;
}
//
if (pressed)
{
// check for toggle key
switch (keyValue)
{
case KeyPAUSE:
case KeyKANA:
case KeyKANJI:
_VKKeyState[keyValue] ^= 0x01; // toggle first bit
break;
case KeyCAPITAL:
if (_CapsLockToggle)
{
_VKKeyState[keyValue] ^= 0x01;
//toggleCapsLock(false);
}
else
{
if ((_VKKeyState[keyValue] & 0x01) == 0)
{
_VKKeyState[keyValue] |= 0x01;
//toggleCapsLock(false);
}
}
break;
case KeyNUMLOCK:
_VKKeyState[keyValue] ^= 0x01;
//setNumLock((_VKKeyState[keyValue] & 0x01) != 0);
break;
case KeySCROLL:
_VKKeyState[keyValue] ^= 0x01;
//toggleScrollLock();
break;
}
_VKKeyState[keyValue] |= 0x80;
}
else
{
_VKKeyState[keyValue] &= ~0x80;
}
//
switch (keyValue)
{
case KeyLSHIFT: charValue = KeySHIFT; break;
case KeyRSHIFT: charValue = KeySHIFT; break;
case KeyLCONTROL: charValue = KeyCONTROL; break;
case KeyRCONTROL: charValue = KeyCONTROL; break;
case KeyLMENU: charValue = KeyMENU; break;
case KeyRMENU: charValue = KeyMENU; break;
default: charValue = keyValue; break;
}
//
if (charValue == KeySHIFT && !_CapsLockToggle)
{
if (_VKKeyState[KeyCAPITAL] & 0x01)
{
_VKKeyState[KeyCAPITAL] &= ~0x01;
//toggleCapsLock(true);
}
}
//
if (charValue != keyValue)
{
_VKKeyState[charValue] = _VKKeyState[keyValue];
}
//
updateCtrlAltShiftValues();
}
///========================================================================
void CDIKeyboard::updateCtrlAltShiftValues()
{
ShiftPressed = (_VKKeyState[KeySHIFT] & 0x80) != 0;
CtrlPressed = (_VKKeyState[KeyCONTROL] & 0x80) != 0;
AltPressed = (_VKKeyState[KeyMENU] & 0x80) != 0;
}
///========================================================================
CDIKeyboard::~CDIKeyboard()
{
if (_Keyboard)
{
_Keyboard->Unacquire();
_Keyboard->Release();
}
}
///========================================================================
CDIKeyboard *CDIKeyboard::createKeyboardDevice(IDirectInput8 *di8,
HWND hwnd,
CDIEventEmitter *diEventEmitter,
CWinEventEmitter *we
) throw(EDirectInput)
{
std::auto_ptr<CDIKeyboard> kb(new CDIKeyboard(we, hwnd));
kb->_DIEventEmitter = diEventEmitter;
HRESULT result = di8->CreateDevice(GUID_SysKeyboard, &kb->_Keyboard, NULL);
if (result != DI_OK) throw EDirectInputNoKeyboard();
result = kb->_Keyboard->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE);
if (result != DI_OK) throw EDirectInputCooperativeLevelFailed();
result = kb->_Keyboard->SetDataFormat(&c_dfDIKeyboard);
kb->setBufferSize(16);
kb->_Keyboard->Acquire();
// Enable win32 keyboard messages only if hardware mouse in normal mode
if (kb->_WE)
kb->_WE->enableKeyboardEvents(false);
return kb.release();
}
///========================================================================
void CDIKeyboard::poll(CInputDeviceServer *dev)
{
nlassert(_Keyboard);
nlassert(_KeyboardBufferSize > 0);
static std::vector<DIDEVICEOBJECTDATA> datas;
datas.resize(_KeyboardBufferSize);
DWORD numElements = _KeyboardBufferSize;
HRESULT result = _Keyboard->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), &datas[0], &numElements, 0);
if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
{
result = _Keyboard->Acquire();
if (result != DI_OK) return;
// get device state
::GetKeyboardState((unsigned char *) _VKKeyState);
_LastDIKeyPressed = 0;
updateCtrlAltShiftValues();
result = _Keyboard->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), &datas[0], &numElements, 0);
if (result != DI_OK) return;
}
else if (result != DI_OK)
{
return;
}
_PollTime = (uint32) CTime::getLocalTime();
// process each message in the list
for (uint k = 0; k < numElements; ++k)
{
CDIEvent *die = new CDIEvent;
die->Emitter = this;
die->Datas = datas[k];
dev->submitEvent(die);
}
}
///========================================================================
void CDIKeyboard::transitionOccured(CEventServer *server, const IInputDeviceEvent *nextMessage)
{
repeatKey(buildDateFromEvent(nextMessage), server);
}
///========================================================================
TKeyButton CDIKeyboard::buildKeyButtonsFlags() const
{
return (TKeyButton) ( (ShiftPressed ? shiftKeyButton : 0)
| (CtrlPressed ? ctrlKeyButton : 0)
| (AltPressed ? altKeyButton : 0)
);
}
///========================================================================
void CDIKeyboard::keyTriggered(bool pressed, uint dikey, CEventServer *server, uint32 date)
{
#if 0
const uint numPairs = sizeof(DIToNel) / sizeof(CKeyConv);
for (uint k = 0; k < numPairs; ++k)
{
if (DIToNel[k].DIKey == key)
{
nlinfo(DIToNel[k].KeyName);
}
}
#endif
TKey keyValue, charValue;
updateVKKeyState(dikey, pressed, keyValue, charValue);
if (keyValue == 0) return;
CEventKey *ek;
if (pressed )
{
ek = new CEventKeyDown(keyValue, buildKeyButtonsFlags(), true, _DIEventEmitter);
}
else
{
ek = new CEventKeyUp(keyValue, buildKeyButtonsFlags(), _DIEventEmitter);
}
server->postEvent(ek);
if (pressed)
{
if (_RepetitionDisabled[(uint) keyValue] == false)
{
_LastEmitDate = _FirstPressDate = date;
_LastDIKeyPressed = dikey;
}
else // not a repeatable key
{
_LastDIKeyPressed = 0;
return;
}
}
else
{
// key released ?
if (dikey == _LastDIKeyPressed)
{
_LastDIKeyPressed = 0;
}
if (_RepetitionDisabled[(uint) keyValue] == true)
{
return;
}
}
// first char event (if repetition not disabled)
if (keyValue >= KeyNUMPAD0 && keyValue <= KeyNUMPAD9 || keyValue == KeyDECIMAL)
{
if ((_VKKeyState[KeyNUMLOCK] & 0x01) != 0)
{
sendUnicode(charValue, dikey, server, pressed);
}
}
else
{
sendUnicode(charValue, dikey, server, pressed);
}
_FirstPressDate = (uint32) NLMISC::CTime::getLocalTime(); // can't use the time stamp, because we can't not sure it matches the local time.
// time stamp is used for evenrts sorting only
}
///========================================================================
void CDIKeyboard::submit(IInputDeviceEvent *deviceEvent, CEventServer *server)
{
CDIEvent *die = safe_cast<CDIEvent *>(deviceEvent);
bool pressed = (die->Datas.dwData & 0x80) != 0;
keyTriggered(pressed, (uint) die->Datas.dwOfs, server, die->Datas.dwTimeStamp);
}
///========================================================================
TMouseButton CDIKeyboard::buildKeyboardButtonFlags() const
{
nlassert(_Keyboard);
return _DIEventEmitter->buildKeyboardButtonFlags();
}
///========================================================================
bool CDIKeyboard::setBufferSize(uint size)
{
nlassert(size > 0);
nlassert(_Keyboard);
_Keyboard->Unacquire();
DIPROPDWORD dipdw;
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE;
dipdw.dwData = size;
HRESULT r = _Keyboard->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph );
if (r != DI_OK) return false;
_KeyboardBufferSize = size;
return true;
}
///========================================================================
uint CDIKeyboard::getBufferSize() const
{
return _KeyboardBufferSize;
}
///========================================================================
TKey CDIKeyboard::DIKeyToNelKey(uint diKey, bool &extKey, bool &repeatable)
{
// some key are not handled by MapVirtualKeyEx so we need to convert them ourselves
static bool tableBuilt = false;
if (!tableBuilt)
{
uint k;
for (k = 0; k < NumKeys; ++k)
{
DIKeyToNelKeyTab[k] = NULL; // set as not a valid key by default
}
const uint numPairs = sizeof(DIToNel) / sizeof(CKeyConv);
for (k = 0; k < numPairs; ++k)
{
DIKeyToNelKeyTab[DIToNel[k].DIKey] = &DIToNel[k];
}
tableBuilt = true;
}
//
if (DIKeyToNelKeyTab[diKey] != NULL)
{
const CKeyConv &keyConv = *DIKeyToNelKeyTab[diKey];
extKey = true;
repeatable = keyConv.Repeatable;
return keyConv.NelKey;
}
// try doing the conversion using MapVirtualKey
TKey key = (TKey) ::MapVirtualKeyEx(diKey, 1, _KBLayout);
extKey = false;
return key;
}
///========================================================================
void CDIKeyboard::sendUnicode(TKey vkey, uint dikey, CEventServer *server, bool pressed)
{
uint8 oldShift = _VKKeyState[KeySHIFT];
/// If caps lock is off when pressing shift, we must disable shift, to get no minuscule letters when it is pressed and capslocks is on.
if (!_CapsLockToggle && _VKKeyState[KeyCAPITAL] & 0x01)
{
_VKKeyState[KeySHIFT] = 0;
}
// 'ToUnicode??' is supported since NT4.0 only
// Check if there's support
static bool init = false;
static bool toUnicodeSupported = false;
if (!init)
{
init = true;
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (::GetVersionEx (&osvi))
{
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
if (osvi.dwMajorVersion >= 4)
{
toUnicodeSupported = true;
}
}
}
}
if (toUnicodeSupported)
{
const uint maxNumKeys = 8;
WCHAR keyUnicodes[maxNumKeys];
int res = ::ToUnicodeEx(vkey, dikey | (pressed ? 0 : (1 << 15)), (unsigned char *) _VKKeyState, keyUnicodes, maxNumKeys, 0, _KBLayout);
//
_VKKeyState[KeySHIFT] = oldShift;
//
for (sint k = 0; k < res; ++k)
{
CEventChar *evc = new CEventChar((ucchar) keyUnicodes[k], buildKeyButtonsFlags(), _DIEventEmitter);
server->postEvent(evc);
}
}
else
{
unsigned char buf[2];
int res = ::ToAsciiEx(vkey, dikey | (pressed ? 0 : (1 << 15)), (unsigned char *) _VKKeyState, (LPWORD) buf, 0, _KBLayout);
for (sint k = 0; k < res; ++k)
{
CEventChar *evc = new CEventChar((ucchar) buf[k], buildKeyButtonsFlags(), _DIEventEmitter);
server->postEvent(evc);
}
}
}
///========================================================================
void CDIKeyboard::repeatKey(uint32 currentDate, CEventServer *server)
{
if (_LastDIKeyPressed == 0 || _LastDIKeyPressed == DIK_INSERT) return;
bool extKey;
bool repeatable;
TKey vkey = DIKeyToNelKey(_LastDIKeyPressed, extKey, repeatable);
if (vkey == 0) return;
if (currentDate - _FirstPressDate < _RepeatDelay) return;
sint32 firstDate = _LastEmitDate - (_FirstPressDate + _RepeatDelay);
sint32 lastDate = currentDate - (_FirstPressDate + _RepeatDelay);
if (firstDate < 0) firstDate = 0;
if (lastDate < firstDate) return;
uint numRep = (uint) ((lastDate + _RepeatPeriod - 1) / _RepeatPeriod - (firstDate + _RepeatPeriod - 1) / _RepeatPeriod);
//numRep = std::min(16u, numRep); // too much repetitions don't make sense...
if ((sint) numRep < 0) return; // 50 days loop..
numRep = 1; // fix : for now it seems better to limit the number of repetition to 1 per frame (it can be greater than 1 only if framerate is slow, but its not very useable)
// numpad case
if (vkey >= KeyNUMPAD0 && vkey <= KeyNUMPAD9 || vkey == KeyDECIMAL)
{
// check whether numlock is activated
if ((_VKKeyState[KeyNUMLOCK] & 0x01) != 0)
{
for (uint k = 0; k < numRep; ++k)
{
sendUnicode(vkey, _LastDIKeyPressed, server, true);
}
}
else
{
// arrow, home, end.. events
for (uint k = 0; k < numRep; ++k)
{
CEventKey *ek = new CEventKeyDown(vkey, buildKeyButtonsFlags(), false, _DIEventEmitter);
server->postEvent(ek);
}
}
}
else
{
for (uint k = 0; k < numRep; ++k)
{
// if it is an extended key, repetition won't be managed by sendUnicode
if (extKey && repeatable)
{
CEventKey *ek = new CEventKeyDown(vkey, buildKeyButtonsFlags(), false, _DIEventEmitter);
server->postEvent(ek);
}
else
{
sendUnicode(vkey, _LastDIKeyPressed, server, true);
}
}
}
_LastEmitDate = currentDate;
}
///========================================================================
uint32 CDIKeyboard::buildDateFromEvent(const IInputDeviceEvent *deviceEvent)
{
if (deviceEvent)
{
const CDIEvent *die = safe_cast<const CDIEvent *>(deviceEvent);
return (uint32) die->Datas.dwData;
}
else
{
return _PollTime;
}
}
///========================================================================
void CDIKeyboard::disableRepetition(const TKey *keyTab, uint numKey)
{
_RepetitionDisabled.clearAll();
for (uint k = 0; k < numKey; ++k)
{
_RepetitionDisabled.set((sint) keyTab[k]);
}
if (_LastDIKeyPressed != 0)
{
bool extKey;
bool repeatable;
TKey key = DIKeyToNelKey(_LastDIKeyPressed, extKey, repeatable);
if (_RepetitionDisabled[(uint) key])
{
// disable this key repetition
_LastDIKeyPressed = 0;
}
}
}
///========================================================================
uint CDIKeyboard::getNumDisabledRepetition() const
{
uint numKey = 0;
for (uint k = 0; k < NumKeys; ++k)
{
if (_RepetitionDisabled[k]) ++numKey;
}
return numKey;
}
///========================================================================
void CDIKeyboard::getDisabledRepetitions(TKey *destTab) const
{
for (uint k = 0; k < NumKeys; ++k)
{
if (_RepetitionDisabled[k]) *destTab++ = (TKey) k;
}
}
} // NLMISC
#endif // NL_OS_WINDOWS

View file

@ -1,163 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_DI_KEYBOARD_H
#define NL_DI_KEYBOARD_H
#include "nel/misc/types_nl.h"
#ifdef NL_OS_WINDOWS
#include "nel/misc/input_device_server.h"
#include "nel/misc/keyboard_device.h"
#include "nel/misc/di_event_emitter.h"
#include "nel/misc/bit_set.h"
namespace NLMISC
{
class CWinEventEmitter;
//
struct EDirectInputNoKeyboard : public EDirectInput
{
EDirectInputNoKeyboard() : EDirectInput("No keyboard found") {}
};
struct CKeyConv;
/**
* Direct Input implementation of a keyboard.
* \see CDIEventEmitter
* \author Nicolas Vizerie
* \author Nevrax France
* \date 2002
*/
class CDIKeyboard : public IKeyboardDevice
{
public:
bool ShiftPressed, CtrlPressed, AltPressed;
public:
///\name Object
//@{
/** Create a keyboard device, that must then be deleted by the caller
* An optional WinEventEmiter can be provided, so that its flags can be in sync
* with a win32 keyboard flags (shift, ctrl, and alt)
*/
static CDIKeyboard *createKeyboardDevice(IDirectInput8 *di8,
HWND hwnd,
CDIEventEmitter *diEventEmitter,
CWinEventEmitter *we = NULL
) throw(EDirectInput);
// dtor
virtual ~CDIKeyboard();
//@}
///\name From IInputDevice
//@{
virtual bool setBufferSize(uint size);
virtual uint getBufferSize() const;
//@}
///\name From IInputDevice
//@{
uint getKeyRepeatDelay() const { return _RepeatDelay; }
void setKeyRepeatDelay(uint delay) { nlassert(delay > 0); _RepeatDelay = delay; }
uint getKeyRepeatPeriod() const { return _RepeatPeriod; }
void setKeyRepeatPeriod(uint period) { nlassert(period > 0); _RepeatPeriod = period; }
void disableRepetition(const TKey *keyTab, uint numKey);
uint getNumDisabledRepetition() const;
void getDisabledRepetitions(TKey *destTab) const;
//@}
TMouseButton buildKeyboardFlags() const;
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
private:
//
bool _CapsLockToggle; // true if caps lock off is triggered by caps lock, false if it toggled by shift
uint _RepeatDelay; // the delay before a key is repeated (in ms)
uint _RepeatPeriod; // The period for key repetitions (in ms)
//
LPDIRECTINPUTDEVICE8 _Keyboard;
uint _KeyboardBufferSize;
// virtual code state
uint8 _VKKeyState[NumKeys];
// tells for which keys repetition is disabled
CBitSet _RepetitionDisabled;
// The date at which the last key pressed has been pressed (not using 64 bits since note handled by Direct Input)
uint32 _FirstPressDate;
// The last date at which key repetition occured (not using 64 bits since note handled by Direct Input)
uint32 _LastEmitDate;
// The system date at which the last polling occured (not using 64 bits since note handled by Direct Input)
uint32 _PollTime;
uint _LastDIKeyPressed;
CWinEventEmitter *_WE;
HWND _hWnd;
HKL _KBLayout;
//
CDIEventEmitter *_DIEventEmitter;
//
static const CKeyConv *DIKeyToNelKeyTab[NumKeys];
private:
/// ctor
CDIKeyboard(CWinEventEmitter *we, HWND hwnd);
/** Convert a direct input scancode to a virtual key. Note that DirectInput scancodes do not always match system scan codes.
* Repeatable has a meaning only for extended keys
*/
TKey DIKeyToNelKey(uint diKey, bool &extKey, bool &repeatable);
/** This update virtual key state table.
* \param keyValue contains the value to send to a EventKeyDown or EventKeyUp message.
* \param charValue contains the value that must be used for Unicode conversion (which generate EventChar messages)
*/
void updateVKKeyState(uint diKey, bool pressed, TKey &keyValue, TKey &charValue);
// Use the given virtual key code and the current keyb state to produce Unicode
void sendUnicode(TKey vkey, uint dikey, CEventServer *server, bool pressed);
// Build a TKeyButton value from the state of shift, ctrl and alt
TKeyButton buildKeyButtonsFlags() const;
// Update the state of this object and send the appropriate message when a direct / input key has been pressed / released
void keyTriggered(bool pressed, uint key, CEventServer *server, uint32 date);
// The same as buildKeyButtonsFlags(), but the return is a TMouseButtonValue (with no mouse value setupped)
TMouseButton buildKeyboardButtonFlags() const;
// setup the state of the Ctrl, Alt and Shift key from the state in the _VKKeyState buffer
void updateCtrlAltShiftValues();
/// Repeat the current key, and create events
void repeatKey(uint32 currentDate, CEventServer *server);
/// Build a date by using an event time stamp, or generate one if NULL
uint32 buildDateFromEvent(const IInputDeviceEvent *deviceEvent);
///\name From IInputDevice
//@{
virtual void poll(CInputDeviceServer *dev);
virtual void submit(IInputDeviceEvent *deviceEvent, CEventServer *server);
virtual void transitionOccured(CEventServer *server, const IInputDeviceEvent *nextMessage);
//@}
};
} // NLMISC
#endif // NL_OS_WINDOWS
#endif // NL_DI_KEYBOARD_H
/* End of di_keyboard.h */

View file

@ -1,507 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdmisc.h"
#include "di_mouse_device.h"
#include "nel/misc/game_device_events.h"
#include "nel/misc/win_event_emitter.h"
#ifdef NL_OS_WINDOWS
#ifdef DEBUG_NEW
#define new DEBUG_NEW
#endif
#ifdef NL_COMP_MINGW
# undef FIELD_OFFSET
# define FIELD_OFFSET(t,f) offsetof(t,f)
#endif
namespace NLMISC
{
//======================================================
CDIMouse::CDIMouse() : _MessageMode(RawMode),
_MouseSpeed(1.0f),
_MouseAccel(10000),
_Mouse(NULL),
_XAcc(0),
_YAcc(0),
_XMousePos(0),
_YMousePos(0),
_LastMouseButtonClicked(-1),
_DoubleClickDelay(300),
_XFactor(1.f),
_YFactor(1.f),
OldDIXPos(0),
OldDIYPos(0),
OldDIZPos(0),
_FirstX(true),
_FirstY(true),
_SwapButton(false)
{
std::fill(_MouseButtons, _MouseButtons + MaxNumMouseButtons, false);
std::fill(_MouseAxisMode, _MouseAxisMode + NumMouseAxis, Raw);
_MouseFrame.setWH(0, 0, 640, 480);
}
//======================================================
CDIMouse::~CDIMouse()
{
if (_Mouse)
{
_Mouse->Unacquire();
_Mouse->Release();
}
}
//======================================================
void CDIMouse::setMouseMode(TAxis axis, TAxisMode axisMode)
{
nlassert(axisMode < AxisModeLast);
nlassert(axis < AxisLast);
_MouseAxisMode[axis] = axisMode;
clampMouseAxis();
}
//======================================================
CDIMouse::TAxisMode CDIMouse::getMouseMode(TAxis axis) const
{
nlassert((int)axis < (int)NumMouseAxis);
return _MouseAxisMode[axis];
}
//======================================================
void CDIMouse::setMouseSpeed(float speed)
{
nlassert(_MessageMode == NormalMode);
nlassert(speed > 0);
_MouseSpeed = speed;
}
//======================================================
void CDIMouse::setMouseAcceleration(uint accel)
{
_MouseAccel = accel;
}
//======================================================
uint CDIMouse::getMouseAcceleration() const
{
return _MouseAccel;
}
//======================================================
bool CDIMouse::setBufferSize(uint size)
{
nlassert(size > 0);
nlassert(_Mouse);
_Mouse->Unacquire();
DIPROPDWORD dipdw;
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE;
dipdw.dwData = size;
HRESULT r = _Mouse->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph );
if (r != DI_OK) return false;
_MouseBufferSize = size;
return true;
}
//======================================================
uint CDIMouse::getBufferSize() const { return _MouseBufferSize; }
//======================================================
void CDIMouse::setMousePos(float x, float y)
{
nlassert(_MessageMode == NormalMode);
_XMousePos = (sint64) ((double) x * ((sint64) 1 << 32));
_YMousePos = (sint64) ((double) y * ((sint64) 1 << 32));
}
//======================================================
CDIMouse *CDIMouse::createMouseDevice(IDirectInput8 *di8, HWND hwnd, CDIEventEmitter *diEventEmitter, bool hardware, CWinEventEmitter *we) throw(EDirectInput)
{
std::auto_ptr<CDIMouse> mouse(new CDIMouse);
mouse->_DIEventEmitter = diEventEmitter;
mouse->_Hardware = hardware;
HRESULT result = di8->CreateDevice(GUID_SysMouse, &(mouse->_Mouse), NULL);
if (result != DI_OK) throw EDirectInputNoMouse();
result = mouse->_Mouse->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | (!hardware ? DISCL_EXCLUSIVE:DISCL_NONEXCLUSIVE));
if (result != DI_OK) throw EDirectInputCooperativeLevelFailed();
mouse->_Mouse->SetDataFormat(&c_dfDIMouse2);
mouse->setBufferSize(64);
mouse->_WE = we;
mouse->setDoubleClickDelay(::GetDoubleClickTime());
/** we want an absolute mouse mode, so that, if the event buffer get full, we can retrieve the right position
*/
DIPROPDWORD prop;
prop.diph.dwSize = sizeof(DIPROPDWORD);
prop.diph.dwHeaderSize = sizeof(DIPROPHEADER);
prop.diph.dwHow = DIPH_DEVICE;
prop.diph.dwObj = 0;
prop.dwData = DIPROPAXISMODE_ABS;
HRESULT r = mouse->_Mouse->SetProperty(DIPROP_AXISMODE, &prop.diph);
nlassert(r == DI_OK); // should always succeed...
//
mouse->_Mouse->Acquire();
mouse->_hWnd = hwnd;
// Enable win32 mouse message only if hardware mouse in normal mode
if (mouse->_WE)
mouse->_WE->enableMouseEvents(mouse->_Hardware && (mouse->_MessageMode == IMouseDevice::NormalMode));
mouse->_SwapButton = GetSystemMetrics(SM_SWAPBUTTON) != 0;
return mouse.release();
}
//======================================================
float CDIMouse::getMouseSpeed() const
{
nlassert(_MessageMode == NormalMode);
return _MouseSpeed;
}
//======================================================
const CRect &CDIMouse::getMouseFrame() const
{
nlassert(_MessageMode == NormalMode);
return _MouseFrame;
}
//======================================================
uint CDIMouse::getDoubleClickDelay() const { return _DoubleClickDelay; }
//======================================================
inline void CDIMouse::clampMouseAxis()
{
if (_MouseAxisMode[XAxis] == Clamped) clamp(_XMousePos, (sint64) _MouseFrame.X << 32, (sint64) (_MouseFrame.X + _MouseFrame.Width - 1) << 32);
if (_MouseAxisMode[YAxis] == Clamped) clamp(_YMousePos, (sint64) _MouseFrame.Y << 32, (sint64) (_MouseFrame.X + _MouseFrame.Height - 1) << 32);
}
//======================================================
void CDIMouse::poll(CInputDeviceServer *dev)
{
nlassert(_Mouse);
nlassert(_MouseBufferSize > 0);
static std::vector<DIDEVICEOBJECTDATA> datas;
datas.resize(_MouseBufferSize);
DWORD numElements = _MouseBufferSize;
HRESULT result = _Mouse->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), &datas[0], &numElements, 0);
if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
{
result = _Mouse->Acquire();
HRESULT result = _Mouse->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), &datas[0], &numElements, 0);
if (result != DI_OK) return;
}
else if (result != DI_OK) return;
if (::IsWindowEnabled(_hWnd) && ::IsWindowVisible(_hWnd))
{
for(uint k = 0; k < numElements; ++k)
{
CDIEvent *die = new CDIEvent;
die->Emitter = this;
die->Datas = datas[k];
dev->submitEvent(die);
}
}
}
//======================================================================
TMouseButton CDIMouse::buildMouseButtonFlags() const
{
if (_SwapButton)
return (TMouseButton) (
_DIEventEmitter->buildKeyboardButtonFlags()
| (_MouseButtons[0] ? rightButton : 0)
| (_MouseButtons[1] ? leftButton : 0)
| (_MouseButtons[2] ? middleButton : 0)
);
else
return (TMouseButton) (
_DIEventEmitter->buildKeyboardButtonFlags()
| (_MouseButtons[0] ? leftButton : 0)
| (_MouseButtons[1] ? rightButton : 0)
| (_MouseButtons[2] ? middleButton : 0)
);
}
//======================================================
TMouseButton CDIMouse::buildMouseSingleButtonFlags(uint button)
{
static const TMouseButton mb[] = { leftButton, rightButton, middleButton };
static const TMouseButton mbswap[] = { rightButton, leftButton, middleButton };
nlassert(button < MaxNumMouseButtons);
if (_SwapButton)
return (TMouseButton) (_DIEventEmitter->buildKeyboardButtonFlags() | mbswap[button]);
else
return (TMouseButton) (_DIEventEmitter->buildKeyboardButtonFlags() | mb[button]);
}
//======================================================
void CDIMouse::onButtonClicked(uint button, CEventServer *server, uint32 date)
{
// check for double click
if (_LastMouseButtonClicked == (sint) button)
{
if (date - _MouseButtonsLastClickDate < _DoubleClickDelay)
{
CEventMouseDblClk *emdc
= new CEventMouseDblClk((float) (_XMousePos >> 32),
(float) (_YMousePos >> 32),
buildMouseSingleButtonFlags(button),
_DIEventEmitter);
server->postEvent(emdc);
_LastMouseButtonClicked = -1;
}
else
{
_MouseButtonsLastClickDate = date;
}
}
else
{
_LastMouseButtonClicked = button;
_MouseButtonsLastClickDate = date;
}
}
//======================================================
void CDIMouse::processButton(uint button, bool pressed, CEventServer *server, uint32 date)
{
updateMove(server);
float mx = (float) (_XFactor * (double) _XMousePos / ((double) 65536 * (double) 65536));
float my = (float) (_YFactor * (double) _YMousePos / ((double) 65536 * (double) 65536));
if (pressed)
{
CEventMouseDown *emd =
new CEventMouseDown(mx, my, buildMouseSingleButtonFlags(button),
_DIEventEmitter);
server->postEvent(emd);
}
else
{
CEventMouseUp *emu =
new CEventMouseUp(mx, my, buildMouseSingleButtonFlags(button), _DIEventEmitter);
server->postEvent(emu);
onButtonClicked(button, server, date);
}
_MouseButtons[button] = pressed;
}
//======================================================
void CDIMouse::submit(IInputDeviceEvent *deviceEvent, CEventServer *server)
{
if (!_Hardware || (_MessageMode == RawMode))
{
CDIEvent *die = safe_cast<CDIEvent *>(deviceEvent);
bool pressed;
switch(die->Datas.dwOfs)
{
case DIMOFS_X:
{
if (!_FirstX)
{
sint dep = (sint32) die->Datas.dwData - OldDIXPos;
// Acceleration
if (_MouseAccel)
{
sint accelFactor = abs (dep) / (sint)_MouseAccel;
dep <<= accelFactor;
}
_XAcc += dep;
}
else
{
_FirstX = false;
}
OldDIXPos = (sint32) die->Datas.dwData;
}
break;
case DIMOFS_Y:
{
if (!_FirstY)
{
sint dep = (sint32) die->Datas.dwData - OldDIYPos;
// Acceleration
if (_MouseAccel)
{
sint accelFactor = abs (dep) / (sint)_MouseAccel;
dep <<= accelFactor;
}
_YAcc -= dep;
}
else
{
_FirstY = false;
}
OldDIYPos = (sint32) die->Datas.dwData;
}
break;
case DIMOFS_Z:
{
updateMove(server);
sint dep = die->Datas.dwData - OldDIZPos;
OldDIZPos = (sint32) die->Datas.dwData;
CEventMouseWheel *emw =
new CEventMouseWheel((float) (_XMousePos >> 32),
(float) (_XMousePos >> 32),
buildMouseButtonFlags(),
dep > 0,
_DIEventEmitter);
server->postEvent(emw);
}
break;
case DIMOFS_BUTTON0: /* left button */
pressed = (die->Datas.dwData & 0x80) != 0;
processButton(0, pressed, server, die->Datas.dwTimeStamp);
break;
case DIMOFS_BUTTON1: /* right button */
pressed = (die->Datas.dwData & 0x80) != 0;
processButton(1, pressed, server, die->Datas.dwTimeStamp);
break;
case DIMOFS_BUTTON2: /* middle button */
pressed = (die->Datas.dwData & 0x80) != 0;
processButton(2, pressed, server, die->Datas.dwTimeStamp);
break;
default:
return;
break;
}
}
}
//======================================================
void CDIMouse::updateMove(CEventServer *server)
{
if (_XAcc != 0 || _YAcc != 0)
{
if (_MessageMode == NormalMode)
{
_XMousePos += (sint64) ((double) _MouseSpeed * (sint64) _XAcc * ((sint64) 1 << 32));
_YMousePos += (sint64) ((double) _MouseSpeed * (sint64) _YAcc * ((sint64) 1 << 32));
clampMouseAxis();
CEventMouseMove *emm = new CEventMouseMove((float) (_XFactor * (double) _XMousePos / ((double) 65536 * (double) 65536)), (float) (_YFactor * (double) _YMousePos / ((double) 65536 * (double) 65536)), buildMouseButtonFlags(), _DIEventEmitter);
server->postEvent(emm);
}
else
{
CGDMouseMove *emm = new CGDMouseMove(_DIEventEmitter, this, _XAcc, _YAcc);
server->postEvent(emm);
}
_XAcc = _YAcc = 0;
}
}
//======================================================
void CDIMouse::convertStdMouseMoveInMickeys(float &dx, float &dy) const
{
// get in same scale as _XAcc and _YAcc
double xacc= ((double)dx/_XFactor) / _MouseSpeed;
double yacc= ((double)dy/_YFactor) / _MouseSpeed;
dx= float(xacc);
dy =float(yacc);
}
//======================================================
void CDIMouse::transitionOccured(CEventServer *server, const IInputDeviceEvent *)
{
updateMove(server);
}
//======================================================
void CDIMouse::setButton(uint button, bool pushed)
{
nlassert(button < MaxNumMouseButtons);
_MouseButtons[button] = pushed;
}
//======================================================
bool CDIMouse::getButton(uint button) const
{
nlassert(button < MaxNumMouseButtons);
return _MouseButtons[button];
}
//======================================================
void CDIMouse::setDoubleClickDelay(uint ms)
{
nlassert(ms > 0);
_DoubleClickDelay = ms;
}
//======================================================
void CDIMouse::setMouseFrame(const CRect &rect)
{
nlassert(_MessageMode == NormalMode);
_MouseFrame = rect;
}
//======================================================
void CDIMouse::setMessagesMode(TMessageMode mode)
{
nlassert(mode < MessageModeLast);
_MessageMode = mode;
_FirstX = _FirstY = true;
// Enable win32 mouse message only if hardware mouse in normal mode
if (_WE)
_WE->enableMouseEvents(_Hardware && (_MessageMode == NormalMode));
}
} // NLMISC
#endif // NL_OS_WINDOWS

View file

@ -1,167 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_DI_MOUSE_DEVICE_H
#define NL_DI_MOUSE_DEVICE_H
#include "nel/misc/types_nl.h"
#ifdef NL_OS_WINDOWS
#include "nel/misc/rect.h"
#include "nel/misc/di_event_emitter.h"
#include "nel/misc/input_device_server.h"
#include "nel/misc/mouse_device.h"
#include <dinput.h>
namespace NLMISC
{
//
struct EDirectInputNoMouse : public EDirectInput
{
EDirectInputNoMouse() : EDirectInput("No mouse found") {}
};
class CDXEventEmitter;
/**
* Direct Input implementation of a mouse
* \see CDIEventEmitter
* \author Nicolas Vizerie
* \author Nevrax France
* \date 2002
*/
class CDIMouse : public IMouseDevice
{
public:
enum { MaxNumMouseButtons = 3, NumMouseAxis = 3};
public:
///\name Object
//@{
virtual ~CDIMouse();
/** Create a mouse device from a valid DirectInput8 pointer. This must then be deleted by the caller.
* \return the interface or throw an exception if the creation failed
*/
static CDIMouse *createMouseDevice(IDirectInput8 *di8, HWND hwnd, CDIEventEmitter *diEventEmitter, bool hardware, class CWinEventEmitter *we) throw(EDirectInput);
//@}
///\name Mouse params, inherited from IMouseDevice
//@{
void setMessagesMode(TMessageMode mode);
TMessageMode getMessagesMode() const { return _MessageMode; }
void setMouseMode(TAxis axis, TAxisMode axisMode);
TAxisMode getMouseMode(TAxis axis) const;
void setMouseSpeed(float speed);
float getMouseSpeed() const;
void setMouseAcceleration(uint speed);
uint getMouseAcceleration() const;
void setMouseFrame(const CRect &rect);
const CRect &getMouseFrame() const;
void setDoubleClickDelay(uint ms);
uint getDoubleClickDelay() const;
void setMousePos(float x, float y);
void setFactors(float xFactor, float yFactor)
{
nlassert(_MessageMode == NormalMode);
_XFactor = xFactor;
_YFactor = yFactor;
}
float getXFactor() const { nlassert(_MessageMode == NormalMode); return _XFactor; }
float getYFactor() const { nlassert(_MessageMode == NormalMode); return _YFactor; }
void convertStdMouseMoveInMickeys(float &dx, float &dy) const;
//@}
///\name From IInputDevice
//@{
virtual bool setBufferSize(uint size);
virtual uint getBufferSize() const;
//@}
///\name From IInputDevice
//@{
void setButton(uint button, bool pushed);
bool getButton(uint button) const;
//@}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////
private:
LPDIRECTINPUTDEVICE8 _Mouse;
//
bool _Hardware;
//
TMessageMode _MessageMode;
//
TAxisMode _MouseAxisMode[NumMouseAxis];
sint64 _XMousePos, _YMousePos; // position encoded in fixed point 32 : 32. This allow wrapping and no loss of precision, when not in clamped mode
// NB: this is sint64 because of max range reached with 16:16 when looping around x with great mouse speed
bool _FirstX, _FirstY;
float _MouseSpeed;
uint _MouseAccel;
CRect _MouseFrame;
//
bool _MouseButtons[MaxNumMouseButtons];
uint32 _MouseButtonsLastClickDate;
sint _LastMouseButtonClicked;
uint _DoubleClickDelay;
uint _MouseBufferSize;
HWND _hWnd;
//
sint32 OldDIXPos, OldDIYPos, OldDIZPos; // old positions reported by direct input
sint _XAcc, _YAcc; // accumulate move (needed because they are generated on a single axis for each DI event)
float _XFactor, _YFactor;
//
CDIEventEmitter *_DIEventEmitter;
// The windows emitter to enable / disble win32 mouse messages
NLMISC::CRefPtr<CWinEventEmitter> _WE;
// Does the button left and right are swapped ?
bool _SwapButton;
private:
/// ctor
CDIMouse();
/// Clamp the mouse axis that need to be.
void clampMouseAxis();
/// Sum the mouse move and produce an event
void updateMove(CEventServer *server);
void processButton(uint button, bool pressed, CEventServer *server, uint32 date);
TMouseButton buildMouseButtonFlags() const;
TMouseButton buildMouseSingleButtonFlags(uint button);
void onButtonClicked(uint button, CEventServer *server, uint32 date);
///\name From IInputDevice
//@{
virtual void poll(CInputDeviceServer *dev);
virtual void submit(IInputDeviceEvent *deviceEvent, CEventServer *server);
virtual void transitionOccured(CEventServer *server, const IInputDeviceEvent *nextMessage);
//@}
};
} // NL3D
#endif // NL_OS_WINDOWS
#endif // NL_DI_MOUSE_H
/* End of di_mouse.h */

View file

@ -84,11 +84,6 @@ void CEventEmitterMulti::submitEvents(CEventServer &server, bool allWindows)
}
}
///============================================================
void CEventEmitterMulti::emulateMouseRawMode(bool enable)
{
}
///============================================================
IEventEmitter *CEventEmitterMulti::getEmitter(uint index)
{

View file

@ -1,28 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdmisc.h"
#include "nel/misc/game_device.h"
#ifdef DEBUG_NEW
#define new DEBUG_NEW
#endif
namespace NLMISC {
} // NLMISC

View file

@ -1,33 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdmisc.h"
#include "nel/misc/game_device_events.h"
#ifdef DEBUG_NEW
#define new DEBUG_NEW
#endif
namespace NLMISC
{
void dummyToAvoidStupidCompilerWarning_game_device_events_cpp()
{
}
} // NLMISC

View file

@ -1,31 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdmisc.h"
#include "nel/misc/input_device.h"
// remove stupid VC6 warnings
void foo_input_device_cpp() {}
#ifdef DEBUG_NEW
#define new DEBUG_NEW
#endif
namespace NLMISC
{
} // NLMISC

View file

@ -1,109 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdmisc.h"
#include "nel/misc/input_device_server.h"
#include "nel/misc/input_device.h"
#include "nel/misc/debug.h"
#ifdef DEBUG_NEW
#define new DEBUG_NEW
#endif
namespace NLMISC
{
//=======================================================================
void CInputDeviceServer::registerDevice(IInputDevice *device)
{
nlassert(!isDevice(device));
_Devices.push_back(device);
}
//=======================================================================
void CInputDeviceServer::removeDevice(IInputDevice *device)
{
TDeviceCont::iterator it = std::find(_Devices.begin(), _Devices.end(), device);
nlassert(it != _Devices.end());
_Devices.erase(it);
}
//=======================================================================
bool CInputDeviceServer::isDevice(IInputDevice *device) const
{
TDeviceCont::const_iterator it = std::find(_Devices.begin(), _Devices.end(), device);
return it != _Devices.end();
}
//=======================================================================
// Predicate to compare vents dates
struct CInputDeviceEventLess
{
bool operator()(const IInputDeviceEvent *lhs, const IInputDeviceEvent *rhs) const
{
return *lhs < *rhs;
}
};
//=======================================================================
void CInputDeviceServer::poll(CEventServer *server)
{
nlassert(_Events.empty());
TDeviceCont::iterator deviceIt;
for (deviceIt = _Devices.begin(); deviceIt != _Devices.end(); ++deviceIt)
{
(*deviceIt)->begin(server);
(*deviceIt)->poll(this);
}
// Sort the messages to get the right dates.
std::sort(_Events.begin(), _Events.end(), CInputDeviceEventLess());
// submit the result to the server
IInputDevice *lastVisitedDevice = NULL;
TEventCont::iterator eventIt;
for (eventIt = _Events.begin(); eventIt != _Events.end(); ++eventIt)
{
// see if this message is from a previous device then the last we visited.
if (lastVisitedDevice && (*eventIt)->Emitter != lastVisitedDevice)
{
// yes, tells that a transition occured
lastVisitedDevice->transitionOccured(server, *eventIt);
lastVisitedDevice = (*eventIt)->Emitter;
}
nlassert((*eventIt)->Emitter != NULL);
(*eventIt)->Emitter->submit(*eventIt, server);
}
//
for (deviceIt = _Devices.begin(); deviceIt != _Devices.end(); ++deviceIt)
{
(*deviceIt)->transitionOccured(server, NULL);
}
// delete the messages
for (eventIt = _Events.begin(); eventIt != _Events.end(); ++eventIt)
{
delete *eventIt;
}
//
_Events.clear();
}
//=======================================================================
void CInputDeviceServer::submitEvent(IInputDeviceEvent *deviceEvent)
{
_Events.push_back(deviceEvent);
}
} // NLMISC

View file

@ -1,36 +0,0 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdmisc.h"
//#include "nel/3d/u_keyboard_device.h"
#ifdef DEBUG_NEW
#define new DEBUG_NEW
#endif
namespace NL3D {
/*
* Constructor
*/
/*UKeyboardDevice::UKeyboardDevice()
{
}*/
} // NL3D

View file

@ -57,14 +57,6 @@ void CWinEventEmitter::submitEvents(CEventServer & server, bool allWindows)
_InternalServer.pump (allWindows);
}
/*------------------------------------------------------------------*\
emulateMouseRawMode()
\*------------------------------------------------------------------*/
void CWinEventEmitter::emulateMouseRawMode(bool enable)
{
nlerror("no raw mode emulation on windows, the CDIMouse has a real raw mode");
}
/*------------------------------------------------------------------*\
processMessage()
\*------------------------------------------------------------------*/

View file

@ -75,7 +75,6 @@ private Q_SLOTS:
void setBackgroundColor();
void submitEvents(NLMISC::CEventServer &server, bool allWindows) { }
void emulateMouseRawMode(bool) { }
protected:
virtual void resizeEvent(QResizeEvent *resizeEvent);

View file

@ -349,13 +349,6 @@ CClientConfig::CClientConfig()
ForceDeltaTime = 0; // Default ForceDeltaTime, disabled by default
#ifdef NL_OS_WINDOWS
DisableDirectInput = false; // Default DisableDirectInput
#else
DisableDirectInput = true; // no direct input on linux
#endif
DisableDirectInputKeyboard = true; // Default DisableDirectInput fort he keyboard only
HardwareCursor = true; // Default HardwareCursor
HardwareCursorScale = 0.85f;
CursorSpeed = 1.f; // Default CursorSpeed
@ -857,8 +850,6 @@ void CClientConfig::setValues()
////////////
// INPUTS //
READ_BOOL_FV(DisableDirectInput)
READ_BOOL_FV(DisableDirectInputKeyboard)
READ_BOOL_FV(HardwareCursor)
READ_FLOAT_FV(HardwareCursorScale)
READ_FLOAT_FV(CursorSpeed)

View file

@ -190,8 +190,6 @@ struct CClientConfig
/// \name Inputs
/// Use a hardware cursor
bool DisableDirectInput;
bool DisableDirectInputKeyboard;
bool HardwareCursor;
float HardwareCursorScale; // scale for hardware cursor bitmap (in ]0, 1])
float CursorSpeed;

View file

@ -116,6 +116,8 @@ extern void saveMovieShooting();
extern void displaySpecialTextProgress(const char *text);
extern bool InitMouseWithCursor(bool hardware);
extern bool SetMousePosFirstTime;
/////////////
// Globals // initialization occurs in the function : connection
/////////////
@ -544,6 +546,7 @@ bool reconnection()
if (ClientCfg.SelectCharacter == -1)
{
// Re-initialise the mouse (will be now in hardware mode, if required)
SetMousePosFirstTime = true;
InitMouseWithCursor (ClientCfg.HardwareCursor); // the return value of enableLowLevelMouse() has already been tested at startup
// no ui init if character selection is automatic

View file

@ -21,7 +21,6 @@
#include "events_listener.h"
#include "nel/misc/events.h"
#include "nel/misc/game_device_events.h"
#include "nel/misc/event_server.h"
#include "release.h"
#include "actions.h"
@ -29,11 +28,13 @@
#include "time_client.h"
#include "input.h"
#include "interface_v3/interface_manager.h"
#include "global.h"
using namespace NLMISC;
extern CActionsManager Actions; // Actions Manager.
extern bool MouseFreeLook;
//---------------------------------------------------
// CEventsListener :
@ -82,7 +83,6 @@ CEventsListener::~CEventsListener()
//---------------------------------------------------
void CEventsListener::addToServer(CEventServer& server)
{
server.addListener(EventGDMouseMove, this);
server.addListener(EventMouseMoveId, this);
server.addListener(EventMouseDownId, this);
server.addListener(EventMouseUpId, this);
@ -101,7 +101,6 @@ void CEventsListener::addToServer(CEventServer& server)
//---------------------------------------------------
void CEventsListener::removeFromServer (CEventServer& server)
{
server.removeListener(EventGDMouseMove, this);
server.removeListener(EventMouseMoveId, this);
server.removeListener(EventMouseDownId, this);
server.removeListener(EventMouseUpId, this);
@ -113,6 +112,12 @@ void CEventsListener::removeFromServer (CEventServer& server)
server.removeListener(EventSetFocusId, this);
}// removeFromServer //
static bool s_MouseFreeLookReady = false;
static sint s_MouseFreeLookLastX;
static sint s_MouseFreeLookLastY;
static sint s_MouseFreeLookFrameX = 0;
static sint s_MouseFreeLookFrameY = 0;
static bool s_MouseFreeLookWaitCenter;
//---------------------------------------------------
// operator() :
@ -148,20 +153,61 @@ void CEventsListener::operator()(const CEvent& event)
{
CAHManager::getInstance()->runActionHandler("enter_modal", NULL, "group=ui:interface:quit_dialog");
}
// Event from the Mouse (ANGLE)
if(event == EventGDMouseMove)
{
CGDMouseMove* mouseEvent=(CGDMouseMove*)&event;
// Mouse acceleration
sint dX = mouseEvent->X;
sint dY = ClientCfg.FreeLookInverted ? -mouseEvent->Y : mouseEvent->Y;
updateFreeLookPos((float) dX, (float) dY);
}
// Event from the Mouse (MOVE)
else if(event == EventMouseMoveId)
{
CEventMouseMove* mouseEvent=(CEventMouseMove*)&event;
updateCursorPos(mouseEvent->X, mouseEvent->Y);
if (!MouseFreeLook)
{
updateCursorPos(mouseEvent->X, mouseEvent->Y);
s_MouseFreeLookReady = false;
}
else
{
// Get in pixel space, centered
uint32 drW, drH;
Driver->getWindowSize(drW, drH);
float fX = mouseEvent->X; // from 0 to 1.0
float fY = (ClientCfg.FreeLookInverted ? -mouseEvent->Y : mouseEvent->Y);
sint scX = (sint32)(fX * (float)drW) - ((sint32)drW >> 1); // in pixels, centered
sint scY = (sint32)(fY * (float)drH) - ((sint32)drH >> 1);
if (!s_MouseFreeLookReady)
{
float pfX = _MouseX;
float pfY = (ClientCfg.FreeLookInverted ? -_MouseY : _MouseY);
sint pscX = (sint32)(pfX * (float)drW) - ((sint32)drW >> 1); // in pixels, centered
sint pscY = (sint32)(pfY * (float)drH) - ((sint32)drH >> 1);
s_MouseFreeLookReady = true;
s_MouseFreeLookLastX = pscX;
s_MouseFreeLookLastY = pscY;
s_MouseFreeLookWaitCenter = false;
}
if (s_MouseFreeLookWaitCenter && scX == 0 && scY == 0)
{
// Centered, ignore
s_MouseFreeLookLastX = 0;
s_MouseFreeLookLastY = 0;
}
else
{
// Get delta since last center
sint scXd = scX - s_MouseFreeLookLastX;
sint scYd = scY - s_MouseFreeLookLastY;
s_MouseFreeLookLastX = scX;
s_MouseFreeLookLastY = scY;
s_MouseFreeLookFrameX += scXd;
s_MouseFreeLookFrameY += scYd;
// updateFreeLookPos is called in updateMouseSmoothing per frame
// Center cursor
if (abs(scX) > (drW >> 3) || abs(scY) > (drH >> 3))
{
s_MouseFreeLookWaitCenter = true;
Driver->setMousePos(0.5f, 0.5f);
}
}
}
}
// Event from the Mouse (DOWN BUTTONS)
else if(event == EventMouseDownId)
@ -233,16 +279,9 @@ void CEventsListener::updateMouseSmoothing()
{
if (_LastFreeLookUpdateDate != TimeInSec)
{
if (ClientCfg.FreeLookSmoothingPeriod != 0.f && _MouseSmoothingOn)
{
// free look hasn't been updated that frame because there was no
// mouse move msg.
// mouse pos must be updated however because of smoothing
updateFreeLookPos(0, 0);
}
updateFreeLookPos((float)s_MouseFreeLookFrameX, (float)s_MouseFreeLookFrameY);
s_MouseFreeLookFrameX = 0;
s_MouseFreeLookFrameY = 0;
}
}
@ -267,7 +306,6 @@ void CEventsListener::enableMouseSmoothing(bool on)
// ***************************************************************
void CEventsListener::updateFreeLookPos(float x, float y)
{
if (ClientCfg.FreeLookSmoothingPeriod == 0 || !_MouseSmoothingOn)
{
_MouseDeltaAX = x * ClientCfg.FreeLookSpeed;

View file

@ -1069,34 +1069,6 @@ void prelogInit()
FPU_CHECKER_ONCE
// Test mouse & keyboard low-level mode, if DisableDirectInput not set.
// In case of failure, exit the client.
// In case of success, set it back to normal mode, to provide for the user
// the ability to manually set the firewall's permissions when the client connects.
// The low-level mode will actually be set when "launching" (after loading).
if (!ClientCfg.DisableDirectInput)
{
// Test mouse and set back to normal mode
if (!Driver->enableLowLevelMouse (true, ClientCfg.HardwareCursor))
{
ExitClientError (CI18N::get ("can_t_initialise_the_mouse").toUtf8 ().c_str ());
// ExitClientError() call exit() so the code after is never called
return;
}
Driver->enableLowLevelMouse (false, ClientCfg.HardwareCursor);
// Test keyboard and set back to normal mode
// NB : keyboard will be initialized later now
/*if (!Driver->enableLowLevelKeyboard (true))
{
ExitClientError (CI18N::get ("can_t_initialise_the_keyboard").toUtf8 ().c_str ());
// ExitClientError() call exit() so the code after is never called
return;
}
Driver->enableLowLevelKeyboard (false);
*/
}
// Set the monitor color properties
CMonitorColorProperties monitorColor;
for ( uint i=0; i<3; i++)

View file

@ -125,6 +125,8 @@ namespace R2
extern bool ReloadUIFlag;
}
extern bool SetMousePosFirstTime;
extern EGSPD::CSeason::TSeason ManualSeasonValue;
UTextureFile *LoadingBitmap = NULL;
UTextureFile *LoadingBitmapFull = NULL;
@ -1253,6 +1255,7 @@ void initMainLoop()
// NLMEMORY::CheckHeap (true);
// Re-initialise the mouse (will be now in hardware mode, if required)
SetMousePosFirstTime = true;
InitMouseWithCursor (ClientCfg.HardwareCursor); // the return value of enableLowLevelMouse() has already been tested at startup
// Re-initialise the keyboard, now in low-level mode, if required

View file

@ -30,7 +30,6 @@
// 3D
#include "nel/3d/u_driver.h"
// Misc
#include "nel/misc/mouse_device.h"
#include "nel/misc/mouse_smoother.h"
#include "nel/misc/system_utils.h"
// Game Share
@ -54,7 +53,6 @@ extern CActionsManager Actions; // Actions Manager.
////////////
// GLOBAL //
////////////
IMouseDevice *MouseDevice = NULL;
bool MouseHardware = false;
bool MouseFreeLook = false;
float MouseCursorSpeed = 1.f;
@ -81,93 +79,40 @@ bool InitMouseWithCursor (bool hardware)
{
Driver->showCursor(false);
// First init ?
if (MouseDevice)
{
// No.. change soft to hard or hard to soft ?
if (hardware ^ MouseHardware)
{
// Ok, reinit the mouse
Driver->enableLowLevelMouse (false, false);
MouseDevice = NULL;
MouseHardware = false;
}
}
// Get the new mouse state
MouseHardware = hardware;
CViewPointer::setHWMouse( hardware );
// Reinit ?
if (MouseDevice == NULL)
// Update mouse information
UpdateMouse ();
if (InitMouseFirstTime)
{
if (!ClientCfg.DisableDirectInput)
InitMouseFirstTime = false;
}
else
{
if (!MouseFreeLook)
{
// mouse capture not taken in account for hardware mouse
MouseDevice = Driver->enableLowLevelMouse(true, hardware);
if (!MouseDevice)
return false;
}
// Update mouse information
UpdateMouse ();
if (InitMouseFirstTime)
{
InitMouseFirstTime = false;
}
else
{
if (!MouseFreeLook)
// Get the current mouse position
CInterfaceManager *pIm = CInterfaceManager::getInstance();
CViewPointer *vp = static_cast< CViewPointer* >( CWidgetManager::getInstance()->getPointer() );
Driver->showCursor(hardware);
if (vp)
{
// Get the current mouse position
if (hardware)
float x = (float) vp->getX();
float y = (float) vp->getY();
// First, hide the hardware mouse
uint width = Driver->getWindowWidth();
uint height = Driver->getWindowHeight();
if (SetMousePosFirstTime)
{
Driver->showCursor(true);
CViewPointer *pointer = static_cast< CViewPointer* >( CWidgetManager::getInstance()->getPointer() );
if (pointer)
{
float x = (float)pointer->getX()/(float)Driver->getWindowWidth();
float y = (float)pointer->getY()/(float)Driver->getWindowHeight();
if (SetMousePosFirstTime)
{
SetMousePosFirstTime = false;
}
else
{
Driver->setMousePos(x, y);
nlwarning("mouse pos %f,%f", x, y);
}
}
}
else
{
CInterfaceManager *pIm = CInterfaceManager::getInstance();
CViewPointer *vp = static_cast< CViewPointer* >( CWidgetManager::getInstance()->getPointer() );
Driver->showCursor(false);
SetMousePosFirstTime = false;
if (vp)
{
float x = (float) vp->getX();
float y = (float) vp->getY();
// First, hide the hardware mouse
if (MouseDevice)
{
MouseDevice->setMousePos(x, y);
}
else
{
uint width = Driver->getWindowWidth();
uint height = Driver->getWindowHeight();
if (width != 0 && height != 0)
{
Driver->setMousePos(x / width, y / height);
}
}
}
}
else if (width != 0 && height != 0)
{
nlwarning("mouse pos %u, %u", x, y);
Driver->setMousePos(x / width, y / height);
}
}
}
@ -187,45 +132,6 @@ bool IsMouseCursorHardware ()
// Set the mouse mode. Call this method once per frame to update window size
void UpdateMouse ()
{
// Freelook ?
if (MouseFreeLook)
{
// Raw mode
if (MouseDevice)
{
MouseDevice->setMessagesMode(IMouseDevice::RawMode);
MouseDevice->setMouseAcceleration(ClientCfg.FreeLookAcceleration);
}
else
{
// no mouse device implementation on X11 and Cocoa, emulate raw mode
Driver->emulateMouseRawMode(true);
}
}
else
{
// Set the mouse properties
if (MouseDevice)
{
// Get the driver size
uint32 width, height;
Driver->getWindowSize(width, height);
MouseDevice->setMessagesMode(IMouseDevice::NormalMode);
MouseDevice->setMouseMode(IMouseDevice::XAxis, IMouseDevice::Clamped);
MouseDevice->setMouseMode(IMouseDevice::YAxis, IMouseDevice::Clamped);
CRect window (0, 0, width, height);
MouseDevice->setMouseFrame(window);
MouseDevice->setFactors(1.f/std::max((float)width, 1.0f), 1.f/std::max((float)height, 1.0f));
MouseDevice->setMouseSpeed(MouseCursorSpeed);
MouseDevice->setMouseAcceleration(MouseCursorAcceleration);
}
else
{
// no mouse device implementation on X11 and Cocoa, emulate raw mode
Driver->emulateMouseRawMode(false);
}
}
if (!Driver->isSystemCursorCaptured())
{
DownMouseButtons = 0;
@ -303,19 +209,7 @@ void SetMouseCursor (bool updatePos)
if (updatePos)
{
if (MouseDevice)
{
MouseDevice->setMousePos((float)ix, (float)iy);
}
else
{
Driver->setMousePos(x, y);
}
if (MouseHardware)
{
Driver->setMousePos(x, y);
}
Driver->setMousePos(x, y);
}
// Update the interface pointer
@ -404,25 +298,18 @@ CNiceInputAuto::CNiceInputAuto()
{
if (_Count == 0)
{
Driver->enableLowLevelMouse(false, false); // but ignore direct input (win 32 msg only)
Driver->setCursor("curs_default.tga", CRGBA::White, 0, 0x15, 0x18);
Driver->showCursor(true); // keep cursor visible in windowed mode
MouseDevice = NULL;
Driver->enableLowLevelKeyboard (false);
}
++ _Count;
++_Count;
}
CNiceInputAuto::~CNiceInputAuto()
{
-- _Count;
--_Count;
nlassert(_Count >= 0);
if (_Count == 0)
{
InitMouseWithCursor (ClientCfg.HardwareCursor);
Driver->enableLowLevelKeyboard (!ClientCfg.DisableDirectInputKeyboard); // the return value has already been tested at startup
InitMouseWithCursor(ClientCfg.HardwareCursor);
}
}

View file

@ -20,7 +20,6 @@
#include "nel/misc/i_xml.h"
#include "nel/misc/file.h"
#include "nel/misc/game_device_events.h"
#include "nel/misc/xml_auto_ptr.h"
@ -92,7 +91,6 @@ void CInputHandlerManager::addToServer(NLMISC::CEventServer * server)
_EventServer = server;
// System
server->addListener(EventGDMouseMove, this);
server->addListener(EventDestroyWindowId, this);
server->addListener(EventCloseWindowId, this);
server->addListener(EventSetFocusId, this);
@ -117,7 +115,6 @@ void CInputHandlerManager::addToServer(NLMISC::CEventServer * server)
void CInputHandlerManager::release()
{
// System
_EventServer->removeListener(EventGDMouseMove, this);
_EventServer->removeListener(EventDestroyWindowId, this);
_EventServer->removeListener(EventCloseWindowId, this);
_EventServer->removeListener(EventSetFocusId, this);

View file

@ -73,6 +73,8 @@ using namespace std;
// ***************************************************************************
extern bool SetMousePosFirstTime;
vector<CShard> Shards;
string LoginLogin, LoginPassword, ClientApp, Salt;
@ -857,16 +859,15 @@ bool login()
IngameDbMngr.flushObserverCalls();
NLGUI::CDBManager::getInstance()->flushObserverCalls();
bool tmpDI = ClientCfg.DisableDirectInput;
ClientCfg.DisableDirectInput = true;
SetMousePosFirstTime = true;
InitMouseWithCursor(false);
Driver->showCursor (false);
SetMouseFreeLook ();
SetMouseCursor (false);
SetMouseSpeed (ClientCfg.CursorSpeed);
SetMouseAcceleration (ClientCfg.CursorAcceleration);
SetMousePosFirstTime = true;
InitMouseWithCursor (ClientCfg.HardwareCursor);
ClientCfg.DisableDirectInput = tmpDI;
// if (ClientCfg.TestBrowser)
// {

View file

@ -414,7 +414,6 @@ void CUserControls::keyboardRotationCameraLR (bool left, bool right)
_RotateCameraLRVelocity = 0;
}
//-----------------------------------------------
// getMouseAngleMove
//-----------------------------------------------
@ -424,13 +423,9 @@ void CUserControls::getMouseAngleMove(float &dx, float &dy)
dy = 0.0f;
// The mouse may still "StandardMove" ie through a CEventMouseMove
// This can happens cause DirectInputDisabled, or because of the
// "Rotation Anti-Lag system" which start to rotate before the mouse is hid
// and message mode passed to RawMode
//
// On X11 and Cocoa, there is no MouseDevice, do it without.
extern IMouseDevice *MouseDevice;
// This can happen because of the "Rotation Anti-Lag system" which
// start to rotate before the mouse is hid and message mode passed
// to updateFreeLookPos
// if the mouse position changed
if( EventsListener.getMousePosX() != _LastFrameMousePosX ||
@ -441,28 +436,23 @@ void CUserControls::getMouseAngleMove(float &dx, float &dy)
float dmpy= EventsListener.getMousePosY() - _LastFrameMousePosY;
// simulate mickeys mode if there is a mouse device
if (MouseDevice)
MouseDevice->convertStdMouseMoveInMickeys(dmpx, dmpy);
else
{
dmpx *= (float)Driver->getWindowWidth();
dmpy *= (float)Driver->getWindowHeight();
}
dmpx *= (float)Driver->getWindowWidth();
dmpy *= (float)Driver->getWindowHeight();
// handle inverted mouse, if enabled
if(ClientCfg.FreeLookInverted) dmpy = -dmpy;
if (ClientCfg.FreeLookInverted) dmpy = -dmpy;
// update free look
EventsListener.updateFreeLookPos(dmpx, dmpy);
}
// If the mouse move on the axis X, with a CGDMouseMove
if(EventsListener.isMouseAngleX())
dx = -EventsListener.getMouseAngleX ();
if (EventsListener.isMouseAngleX())
dx = -EventsListener.getMouseAngleX();
// If the mouse move on the axis Y, with a CGDMouseMove
if(EventsListener.isMouseAngleY())
dy = EventsListener.getMouseAngleY ();
if (EventsListener.isMouseAngleY())
dy = EventsListener.getMouseAngleY();
}
@ -1294,7 +1284,6 @@ void CUserControls::commonSetView()
}
}
//-----------------------------------------------
// startFreeLook()
//-----------------------------------------------

View file

@ -55,7 +55,6 @@
#include <nel/misc/matrix.h>
#include <nel/misc/md5.h>
#include <nel/misc/mem_stream.h>
#include <nel/misc/mouse_device.h>
#include <nel/misc/path.h>
#include <nel/misc/polygon.h>
#include <nel/misc/progress_callback.h>