#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2013 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library 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 IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License #ifndef NUCLEX_INPUT_DEVICES_VIRTUALMOUSE_H #define NUCLEX_INPUT_DEVICES_VIRTUALMOUSE_H #include "Nuclex/Input/Devices/Mouse.h" #include "Nuclex/Input/Devices/MouseButtons.h" namespace Nuclex { namespace Input { namespace Devices { /// Forwards mouse input from an exchangeable backing device /// /// /// If this library directly dealt out instances of the input device implementations, /// disconnecting a device and connecting another one, for example, would mean that /// any pointers the user has to the disconnected device become either invalid. /// /// /// So the design choice was to either let the library's user in on when devices are /// replaced, forcing him to unsubscribe from events, resubscribe, replace pointers /// he has stored to the old device and so on, or to use a forwarder device that /// allows the underlying real input device to be replaced at will without anyone /// outside of the library noticing. /// /// /// Without a forwarding device assigned, this class can also be used as a dummy /// device to fill slots for devices not available or not supported by the current /// system (think keyboard on iPhone, etc.) /// /// class VirtualMouse : public Mouse, public sigslot::has_slots<> { /// Initializes a new virtual mouse public: VirtualMouse() : forwardingMouse(nullptr) { this->neutralState.Reset(); } /// Destroys the virtual mouse public: virtual ~VirtualMouse() { if(this->forwardingMouse != nullptr) { unsubscribe(this->forwardingMouse); } } /// Assigns the mouse for which this instance forwards input /// Mouse for which input will be forwarded public: void SetForwardingMouse(Mouse *forwardingMouse) { if(this->forwardingMouse != nullptr) { unsubscribe(this->forwardingMouse); } this->forwardingMouse = forwardingMouse; if(this->forwardingMouse != nullptr) { subscribe(this->forwardingMouse); } } /// Whether the input device is currently attached /// True if the input device is attached, otherwise false public: virtual bool IsAttached() const { if(this->forwardingMouse == nullptr) { return false; } else { return this->forwardingMouse->IsAttached(); } } /// Retrieves the human-readable name of the input device /// The human-readable name of the input device public: virtual const std::string &GetName() const { static std::string notConnected("No mouse connected"); if(this->forwardingMouse == nullptr) { return notConnected; } else { return this->forwardingMouse->GetName(); } } /// Retrieves the current state of the input device /// The input device's current state public: virtual const MouseState &GetState() const { if(this->forwardingMouse == nullptr) { return this->neutralState; } else { return this->forwardingMouse->GetState(); } } /// Updates the state of the input device protected: virtual void Update() { if(this->forwardingMouse != nullptr) { this->forwardingMouse->Update(); } } /// Takes a snapshot of the input device's current state protected: virtual void TakeSnapshot() { if(this->forwardingMouse != nullptr) { this->forwardingMouse->TakeSnapshot(); } } /// Removes all snapshots the device has taken protected: virtual void ClearSnapshots() { if(this->forwardingMouse != nullptr) { this->forwardingMouse->ClearSnapshots(); } } /// Subscribes to the events of the forwarding mouse /// Mouse to whose events to subscribe private: void subscribe(Mouse *mouse) { mouse->CursorMoved.connect(this, &VirtualMouse::onCursorMoved); mouse->Moved.connect(this, &VirtualMouse::onMoved); mouse->ButtonPressed.connect(this, &VirtualMouse::onButtonPressed); mouse->ButtonReleased.connect(this, &VirtualMouse::onButtonReleased); mouse->WheelRotated.connect(this, &VirtualMouse::onWheelRotated); } /// Unsubscribes from the events of the forwarding mouse /// Mouse from whose events to unsubscribe private: void unsubscribe(Mouse *mouse) { mouse->WheelRotated.disconnect(this); mouse->ButtonReleased.disconnect(this); mouse->ButtonPressed.disconnect(this); mouse->Moved.disconnect(this); mouse->CursorMoved.disconnect(this); } /// Forwards a cursor movement notification to the library user /// New X coordinate of the mouse cursor /// New Y coordinate of the mouse cursor private: void onCursorMoved(int x, int y) { CursorMoved(x, y); } /// Forwards a mouse move notification to the library user /// Units by which the mouse was moved on the X axis /// Units by which the mouse was moved on the Y axis private: void onMoved(float deltaX, float deltaY) { Moved(deltaX, deltaY); } /// Forwards a mouse press notification to the library user /// Mouse button the user has pressed private: void onButtonPressed(MouseButtons::Enum button) { ButtonPressed(button); } /// Forwards a mouse release notification to the library user /// Mouse button the user has released private: void onButtonReleased(MouseButtons::Enum button) { ButtonReleased(button); } /// Forwards a wheel rotation notification to the library user /// Ticks by which the mouse wheel has been rotated private: void onWheelRotated(float wheelDelta) { WheelRotated(wheelDelta); } /// Disabled copy constructor for the virtual mouse private: VirtualMouse(const VirtualMouse &); /// Disabled assignment operator for the virtual mouse private: void operator =(const VirtualMouse &); /// Mouse that is forwarded by this instance private: Mouse *forwardingMouse; /// Neutral state that is returned when no mouse is connected private: MouseState neutralState; }; }}} // namespace Nuclex::Input::Devices #endif // NUCLEX_INPUT_DEVICES_VIRTUALMOUSE_H