Procházet zdrojové kódy

Adding support for mouse capture.

Steve Grenier před 13 roky
rodič
revize
bcb73a074e

+ 27 - 76
gameplay/src/Game.cpp

@@ -20,8 +20,7 @@ Game::Game()
     : _initialized(false), _state(UNINITIALIZED), 
       _frameLastFPS(0), _frameCount(0), _frameRate(0), 
       _clearDepth(1.0f), _clearStencil(0), _properties(NULL),
-      _animationController(NULL), _audioController(NULL), _physicsController(NULL), _audioListener(NULL), 
-      _gamepadCount(0), _gamepads(NULL)
+      _animationController(NULL), _audioController(NULL), _physicsController(NULL), _audioListener(NULL)
 {
     GP_ASSERT(__gameInstance == NULL);
     __gameInstance = this;
@@ -64,6 +63,31 @@ void Game::setVsync(bool enable)
     Platform::setVsync(enable);
 }
 
+bool Game::hasMouse()
+{
+    return Platform::hasMouse();
+}
+
+bool Game::isMouseCaptured()
+{
+    return Platform::isMouseCaptured();
+}
+
+void Game::setMouseCapture(bool captured)
+{
+    Platform::setMouseCapture(captured);
+}
+
+void Game::setCursorVisible(bool visible)
+{
+    Platform::setCursorVisible(visible);
+}
+
+bool Game::isCursorVisible()
+{
+    return Platform::isCursorVisible();
+}
+
 bool Game::isVsync()
 {
     return Platform::isVsync();
@@ -96,7 +120,7 @@ bool Game::startup()
     setViewport(Rectangle(0.0f, 0.0f, (float)_width, (float)_height));
     RenderState::initialize();
     FrameBuffer::initialize();
-    
+
     _animationController = new AnimationController();
     _animationController->initialize();
 
@@ -106,8 +130,6 @@ bool Game::startup()
     _physicsController = new PhysicsController();
     _physicsController->initialize();
 
-    loadGamepad();
-    
     _state = RUNNING;
 
     return true;
@@ -125,15 +147,6 @@ void Game::shutdown()
         Platform::signalShutdown();
         finalize();
 
-        if (_gamepads)
-        {
-            for (unsigned int i = 0; i < _gamepadCount; i++)
-            {
-                SAFE_DELETE(_gamepads[i]);
-            }
-            SAFE_DELETE_ARRAY(_gamepads);
-        }
-
         _animationController->finalize();
         SAFE_DELETE(_animationController);
 
@@ -219,12 +232,6 @@ void Game::frame()
         // Update the physics.
         _physicsController->update(elapsedTime);
 
-        if (_gamepads)
-        {
-            for (unsigned int i = 0; i < _gamepadCount; i++)
-                _gamepads[i]->update();
-        }
-
         // Application Update.
         update(elapsedTime);
 
@@ -233,12 +240,6 @@ void Game::frame()
 
         // Graphics Rendering.
         render(elapsedTime);
-        
-        if (_gamepads)
-        {
-            for (unsigned int i = 0; i < _gamepadCount; i++)
-                _gamepads[i]->render();
-        }
 
         // Update FPS.
         ++_frameCount;
@@ -329,10 +330,6 @@ void Game::touchEvent(Touch::TouchEvent evt, int x, int y, unsigned int contactI
 {
 }
 
-void Game::gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int index)
-{
-}
-
 void Game::schedule(float timeOffset, TimeListener* timeListener, void* cookie)
 {
     GP_ASSERT(_timeEvents);
@@ -414,50 +411,4 @@ bool Game::TimeEvent::operator<(const TimeEvent& v) const
     return time > v.time;
 }
 
-Gamepad* Game::createGamepad(const char* gamepadFormPath)
-{
-    GP_ASSERT(gamepadFormPath);
-
-    Gamepad* gamepad = new Gamepad(gamepadFormPath);
-    GP_ASSERT(gamepad);
-
-    if (!_gamepads)
-    {
-        _gamepadCount++;
-        _gamepads = new Gamepad*[_gamepadCount];
-        _gamepads[0] = gamepad;
-    }
-    else
-    {
-        int oldSize = _gamepadCount;
-        _gamepadCount++;
-        Gamepad** tempGamepads = new Gamepad*[_gamepadCount];
-        memcpy(tempGamepads, _gamepads, sizeof(Gamepad*) * oldSize);
-        tempGamepads[oldSize] = gamepad;
-        
-        SAFE_DELETE_ARRAY(_gamepads);
-        _gamepads = tempGamepads;
-    }
-
-    return gamepad;
-}
-
-void Game::loadGamepad()
-{
-    if (_properties)
-    {
-        // Check if there is a virtual keyboard included in the .config file.
-        // If there is, try to create it and assign it to "player one".
-        Properties* gamepadProperties = _properties->getNamespace("gamepad", true);
-        if (gamepadProperties && gamepadProperties->exists("form"))
-        {
-            const char* gamepadFormPath = gamepadProperties->getString("form");
-            GP_ASSERT(gamepadFormPath);
-
-            Gamepad* gamepad = createGamepad(gamepadFormPath);
-            GP_ASSERT(gamepad);
-        }
-    }
-}
-
 }

+ 54 - 33
gameplay/src/Game.h

@@ -13,7 +13,6 @@
 #include "Rectangle.h"
 #include "Vector4.h"
 #include "TimeListener.h"
-#include "Gamepad.h"
 
 namespace gameplay
 {
@@ -23,7 +22,6 @@ namespace gameplay
  */
 class Game
 {
-
 public:
 
     /**
@@ -76,6 +74,53 @@ public:
      */
     static void setVsync(bool enable);
 
+    /** 
+     * Gets whether the current platform supports mouse input.
+     *
+      * @return true if a mouse is supported, false otherwise.
+      */
+    static bool hasMouse();
+
+    /**
+     * Gets whether mouse input is currently captured.
+     *
+     * @see Platform::isMouseCaptured()
+     */
+    static bool isMouseCaptured();
+
+    /**
+     * Enables or disables mouse capture.
+     *
+     * On platforms that support a mouse, when mouse capture is enabled,
+     * the platform cursor will be hidden and the mouse will be warped
+     * to the center of the screen. While mouse capture is enabled,
+     * all mouse move events will then be delivered as deltas instead
+     * of absolute positions.
+     *
+     * @param captured true to enable mouse capture mode, false to disable it.
+     *
+     * @see Platform::setMouseCapture(bool)
+     */
+    static void setMouseCapture(bool captured);
+
+    /**
+     * Sets the visibility of the platform cursor.
+     *
+     * @param visible true to show the platform cursor, false to hide it.
+     *
+     * @see Platform::setCursorVisible(bool)
+     */
+    static void setCursorVisible(bool visible);
+
+    /**
+     * Determines whether the platform cursor is currently visible.
+     *
+     * @return true if the platform cursor is visible, false otherwise.
+     *
+     * @see Platform::isCursorVisible()
+     */
+    static bool isCursorVisible();
+
     /**
      * Gets the total absolute running time (in milliseconds) since Game::run().
      * 
@@ -100,6 +145,13 @@ public:
      */
     inline State getState() const;
 
+    /**
+     * Determines if the game has been initialized.
+     *
+     * @return true if the game initialization has completed, false otherwise.
+     */
+    inline bool isInitialized() const;
+
     /**
      * Returns the game configuration object.
      *
@@ -269,15 +321,6 @@ public:
      */
     virtual bool mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta);
 
-    /**
-     * Gamepad callback on gamepad events.
-     *
-     * @param evt The gamepad event that occured.
-     * @param gamepad the gamepad the event occured on
-     * @param index The joystick or button index that triggered the event.
-     */
-    virtual void gamepadEvent(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int index);
-
     /**
      * Sets muli-touch is to be enabled/disabled. Default is disabled.
      *
@@ -310,21 +353,6 @@ public:
      */
     void schedule(float timeOffset, TimeListener* timeListener, void* cookie = 0);
 
-    /** 
-     * Creates a Gamepad object from a .form file.
-     *
-     * @param playerIndex
-     * @param formPath
-     */
-    Gamepad* createGamepad(const char* gamepadFormPath);
-
-    /**
-     * Gets the gamepad for the specified player index.
-     *
-     * @param playerIndex The player index to get the gamepad for (0 <= playerIndex <= 3) 
-     */
-    inline Gamepad* getGamepad(unsigned int playerIndex = 0);
-
 protected:
 
     /**
@@ -431,11 +459,6 @@ private:
      */
     void loadConfig();
 
-    /**
-     * Loads a gamepad from the configuration file.
-     */
-    void loadGamepad();
-
     bool _initialized;                          // If game has initialized yet.
     State _state;                               // The game state.
     static double _pausedTimeLast;              // The last time paused.
@@ -454,8 +477,6 @@ private:
     AudioController* _audioController;          // Controls audio sources that are playing in the game.
     PhysicsController* _physicsController;      // Controls the simulation of a physics scene and entities.
     AudioListener* _audioListener;              // The audio listener in 3D space.
-    unsigned int _gamepadCount;
-    Gamepad** _gamepads;
     std::priority_queue<TimeEvent, std::vector<TimeEvent>, std::less<TimeEvent> >* _timeEvents; // Contains the scheduled time events.
 
     // Note: Do not add STL object member variables on the stack; this will cause false memory leaks to be reported.

+ 6 - 11
gameplay/src/Game.inl

@@ -9,6 +9,11 @@ inline Game::State Game::getState() const
     return _state;
 }
 
+inline bool Game::isInitialized() const
+{
+    return _initialized;
+}
+
 inline unsigned int Game::getFrameRate() const
 {
     return _frameRate;
@@ -72,14 +77,4 @@ inline void Game::displayKeyboard(bool display)
     Platform::displayKeyboard(display);
 }
 
-inline Gamepad* Game::getGamepad(unsigned int playerIndex)
-{
-    GP_ASSERT(playerIndex < _gamepadCount);
-
-    if (_gamepads)
-        return _gamepads[playerIndex];
-    else
-        return NULL;
-}
-
-}
+}

+ 52 - 1
gameplay/src/Platform.h

@@ -91,7 +91,10 @@ public:
     static void setVsync(bool enable);
 
     /**
-     * Set if multi-touch is enabled on the platform
+     * Set if multi-touch is enabled on the platform.
+     *
+     * Note that this method does nothing on platforms that do not
+     * support multi-touch.
      */
     static void setMultiTouch(bool enabled);
 
@@ -100,6 +103,54 @@ public:
     */
     static bool isMultiTouch();
 
+    /**
+     * Whether the platform has mouse support.
+     */
+    static bool hasMouse();
+    
+    /**
+     * Enables or disabled mouse capture.
+     *
+     * When mouse capture is enabled, the platform cursor is hidden
+     * and mouse event points are delivered as position deltas instead
+     * of absolute positions.
+     *
+     * This is useful for games that wish to provide uninhibited mouse
+     * movement, such as when implementing free/mouse look in an FPS
+     * game.
+     *
+     * Disabling mouse capture moves the mouse back to the center of the
+     * screen and shows the platform cursor.
+     *
+     * Note that this method does nothing on platforms that do not
+     * support a mouse.
+     *
+     * @param captured True to enable mouse capture, false to disable it.
+     */
+    static void setMouseCapture(bool captured);
+
+    /**
+     * Determines if mouse capture is currently enabled.
+     */
+    static bool isMouseCaptured();
+
+    /**
+     * Sets the visibility of the platform cursor.
+     *
+     * On platforms that support a visible cursor, this method
+     * toggles the visibility of the cursor.
+     *
+     * @param visible true to show the platform cursor, false to hide it.
+     */
+    static void setCursorVisible(bool visible);
+
+    /**
+     * Determines whether the platform cursor is currently visible.
+     *
+     * @return true if the platform cursor is visible, false otherwise.
+     */
+    static bool isCursorVisible();
+
     /**
      * Gets the platform accelerometer values.
      * 

+ 78 - 2
gameplay/src/PlatformWin32.cpp

@@ -24,6 +24,9 @@ static HINSTANCE __hinstance = 0;
 static HWND __hwnd = 0;
 static HDC __hdc = 0;
 static HGLRC __hrc = 0;
+static bool __mouseCaptured = false;
+static POINT __mouseCapturePoint = { 0, 0 };
+static bool __cursorVisible = true;
 
 static gameplay::Keyboard::Key getKey(WPARAM win32KeyCode, bool shiftDown)
 {
@@ -255,9 +258,18 @@ void UpdateCapture(LPARAM lParam)
         ReleaseCapture();
 }
 
+void WarpMouse(int clientX, int clientY)
+{
+    POINT p = { clientX, clientY };
+    ClientToScreen(__hwnd, &p);
+    SetCursorPos(p.x, p.y);
+}
+
 LRESULT CALLBACK __WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
-    if (hwnd != __hwnd)
+    static gameplay::Game* game = gameplay::Game::getInstance();
+
+    if (!game->isInitialized() || hwnd != __hwnd)
     {
         // Ignore messages that are not for our game window.
         return DefWindowProc(hwnd, msg, wParam, lParam);
@@ -335,6 +347,21 @@ LRESULT CALLBACK __WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
         int x = GET_X_LPARAM(lParam);
         int y = GET_Y_LPARAM(lParam);
 
+        if (__mouseCaptured)
+        {
+            // If the incoming position is the mouse capture point, ignore this event
+            // since this is the event that warped the cursor back.
+            if (x == __mouseCapturePoint.x && y == __mouseCapturePoint.y)
+                break;
+
+            // Convert to deltas
+            x -= __mouseCapturePoint.x;
+            y -= __mouseCapturePoint.y;
+
+            // Warp mouse back to center of screen.
+            WarpMouse(__mouseCapturePoint.x, __mouseCapturePoint.y);
+        }
+
         // Allow Game::mouseEvent a chance to handle (and possibly consume) the event.
         if (!gameplay::Platform::mouseEventInternal(gameplay::Mouse::MOUSE_MOVE, x, y, 0))
         {
@@ -690,7 +717,7 @@ unsigned int Platform::getDisplayHeight()
 {
     return __height;
 }
-    
+
 double Platform::getAbsoluteTime()
 {
     LARGE_INTEGER queryTime;
@@ -719,6 +746,7 @@ void Platform::setVsync(bool enable)
 
 void Platform::setMultiTouch(bool enabled)
 {
+    // not supported
 }
 
 bool Platform::isMultiTouch()
@@ -735,6 +763,54 @@ void Platform::getAccelerometerValues(float* pitch, float* roll)
     *roll = __roll;
 }
 
+void Platform::setMouseCapture(bool captured)
+{
+    if (captured != __mouseCaptured)
+    {
+        if (captured)
+        {
+            // Hide the cursor and warp it to the center of the screen
+            __mouseCapturePoint.x = getDisplayWidth() / 2;
+            __mouseCapturePoint.y = getDisplayHeight() / 2;
+
+            ShowCursor(FALSE);
+            WarpMouse(__mouseCapturePoint.x, __mouseCapturePoint.y);
+        }
+        else
+        {
+            // Restore cursor
+            WarpMouse(__mouseCapturePoint.x, __mouseCapturePoint.y);
+            ShowCursor(TRUE);
+        }
+
+        __mouseCaptured = captured;
+    }
+}
+
+bool Platform::hasMouse()
+{
+    return true;
+}
+
+bool Platform::isMouseCaptured()
+{
+    return __mouseCaptured;
+}
+
+void Platform::setCursorVisible(bool visible)
+{
+    if (visible != __cursorVisible)
+    {
+        ShowCursor(visible ? TRUE : FALSE);
+        __cursorVisible = visible;
+    }
+}
+
+bool Platform::isCursorVisible()
+{
+    return __cursorVisible;
+}
+
 void Platform::swapBuffers()
 {
     if (__hdc)