Browse Source

Merge pull request #203 from blackberry-gaming/next

Next
Sean Paul Taylor 13 years ago
parent
commit
ebc46fb8f0

+ 2 - 2
gameplay-template/gameplay-template.vcxproj

@@ -169,8 +169,8 @@
     <None Include="res\box.dae" />
     <None Include="res\box.gpb" />
     <None Include="res\box.material" />
-    <None Include="res\colored.fsh" />
-    <None Include="res\colored.vsh" />
+    <None Include="res\colored.frag" />
+    <None Include="res\colored.vert" />
   </ItemGroup> 
   <ItemGroup>
     <ClCompile Include="src\TemplateGame.cpp" />

+ 1 - 1
gameplay/src/AudioSource.h

@@ -13,7 +13,7 @@ class Node;
 class NodeCloneContext;
 
 /**
- *  Declares an audio source in 3D space.
+ * Declares an audio source in 3D space.
  */
 class AudioSource : public Ref, public Transform::Listener
 {

+ 0 - 25
gameplay/src/Game.cpp

@@ -62,31 +62,6 @@ 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();

+ 41 - 47
gameplay/src/Game.h

@@ -75,53 +75,6 @@ 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().
      * 
@@ -321,6 +274,47 @@ public:
      * @see Mouse::MouseEvent
      */
     virtual bool mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta);
+    
+    /** 
+     * Gets whether the current platform supports mouse input.
+     *
+     * @return true if a mouse is supported, false otherwise.
+     */
+    inline bool hasMouse();
+    
+    /**
+     * Gets whether mouse input is currently captured.
+     *
+     * @return is the mouse captured.
+     */
+    inline 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.
+     */
+    inline void setMouseCaptured(bool captured);
+    
+    /**
+     * Sets the visibility of the platform cursor.
+     *
+     * @param visible true to show the platform cursor, false to hide it.
+     */
+    inline void setCursorVisible(bool visible);
+    
+    /**
+     * Determines whether the platform cursor is currently visible.
+     *
+     * @return true if the platform cursor is visible, false otherwise.
+     */
+    inline bool isCursorVisible();
 
     /**
      * Gamepad callback on gamepad events.

+ 25 - 0
gameplay/src/Game.inl

@@ -57,6 +57,31 @@ void Game::renderOnce(T* instance, void (T::*method)(void*), void* cookie)
     Platform::swapBuffers();
 }
 
+inline bool Game::hasMouse()
+{
+    return Platform::hasMouse();
+}
+
+inline bool Game::isMouseCaptured()
+{
+    return Platform::isMouseCaptured();
+}
+
+inline void Game::setMouseCaptured(bool captured)
+{
+    Platform::setMouseCaptured(captured);
+}
+
+inline void Game::setCursorVisible(bool visible)
+{
+    Platform::setCursorVisible(visible);
+}
+
+inline bool Game::isCursorVisible()
+{
+    return Platform::isCursorVisible();
+}
+
 inline void Game::setMultiTouch(bool enabled)
 {
     Platform::setMultiTouch(enabled);

+ 2 - 2
gameplay/src/Joystick.cpp

@@ -105,9 +105,9 @@ bool Joystick::touchEvent(Touch::TouchEvent touchEvent, int x, int y, unsigned i
 
                 notifyListeners(Listener::PRESS);
 
-                _displacement.set(0.0f, 0.0f);
+                _displacement.set(dx, dy);
                 
-                Vector2 value(0.0f, 0.0f);
+                Vector2 value(dx, dy);
                 if (_value != value)
                 {
                     _value.set(value);

+ 1 - 7
gameplay/src/Node.h

@@ -347,9 +347,7 @@ public:
     Vector3 getForwardVectorWorld() const;
 
     /**
-     *  Returns the forward vector of the Node in view space.
-     *
-     * @param normalize True to return the vector normalized, false (default) otherwise.
+     * Returns the forward vector of the Node in view space.
      *
      * @return The forwward vector in view space.
      */
@@ -358,8 +356,6 @@ public:
     /**
      * Returns the right vector of the Node in world space.
      *
-     * @param normalize True to return the vector normalized, false (default) otherwise.
-     *
      * @return The right vector in world space.
      */
     Vector3 getRightVectorWorld() const;
@@ -367,8 +363,6 @@ public:
     /**
      * Returns the up vector of the Node in world space.
      *
-     * @param normalize True to return the vector normalized, false (default) otherwise.
-     *
      * @return The up vector in world space.
      */
     Vector3 getUpVectorWorld() const;

+ 1 - 1
gameplay/src/PhysicsCollisionObject.h

@@ -178,7 +178,7 @@ public:
     /**
      * Sets the collision object be enabled or disabled.
      *
-     * @param enable true enables the collision object, false diables it.
+     * @param enable true enables the collision object, false disables it.
      */
     void setEnabled(bool enable);
 

+ 13 - 27
gameplay/src/PhysicsConstraint.cpp

@@ -35,8 +35,8 @@ Vector3 PhysicsConstraint::centerOfMassMidpoint(const Node* a, const Node* b)
     a->getWorldMatrix().getTranslation(&tA);
     b->getWorldMatrix().getTranslation(&tB);
 
-    tA = getWorldCenterOfMass(a->getModel());
-    tB = getWorldCenterOfMass(b->getModel());
+    tA = getWorldCenterOfMass(a);
+    tB = getWorldCenterOfMass(b);
     
     Vector3 d(tA, tB);
     d.scale(0.5f);
@@ -130,36 +130,22 @@ btTransform PhysicsConstraint::getTransformOffset(const Node* node, const Vector
     return btTransform(BQ(r), BV(t));
 }
 
-Vector3 PhysicsConstraint::getWorldCenterOfMass(const Model* model)
+Vector3 PhysicsConstraint::getWorldCenterOfMass(const Node* node)
 {
-    GP_ASSERT(model && model->getMesh() && model->getNode());
+    GP_ASSERT(node);
 
-    Vector3 center;
-    const BoundingBox& box = model->getMesh()->getBoundingBox();
-    if (!(box.min.isZero() && box.max.isZero()))
-    {
-        Vector3 bMin, bMax;
-        model->getNode()->getWorldMatrix().transformPoint(box.min, &bMin);
-        model->getNode()->getWorldMatrix().transformPoint(box.max, &bMax);
-        center.set(bMin, bMax);
-        center.scale(0.5f);
-        center.add(bMin);
-    }
-    else
+    const BoundingSphere& sphere = node->getBoundingSphere();
+    if (!(sphere.center.isZero() && sphere.radius == 0))
     {
-        const BoundingSphere& sphere = model->getMesh()->getBoundingSphere();
-        if (!(sphere.center.isZero() && sphere.radius == 0))
-        {
-            model->getNode()->getWorldMatrix().transformPoint(sphere.center, &center);
-        }
-        else
-        {
-            // Warn the user that the model has no bounding volume.
-            GP_WARN("Model '%s' has no bounding volume - center of mass is defaulting to local coordinate origin.", model->getNode()->getId());
-            model->getNode()->getWorldMatrix().transformPoint(&center);
-        }
+        // The world-space center of mass is the sphere's center.
+        return sphere.center;
     }
 
+    // Warn the user that the node has no bounding volume.
+    GP_WARN("Node %s' has no bounding volume - center of mass is defaulting to local coordinate origin.", node->getId());
+
+    Vector3 center;
+    node->getWorldMatrix().transformPoint(&center);
     return center;
 }
 

+ 2 - 3
gameplay/src/PhysicsConstraint.h

@@ -2,7 +2,6 @@
 #define PHYSICSCONSTRAINT_H_
 
 #include "Base.h"
-#include "Model.h"
 #include "Vector3.h"
 
 namespace gameplay
@@ -93,9 +92,9 @@ protected:
     static btTransform getTransformOffset(const Node* node, const Vector3& origin);
     
     /**
-     * Calculates the center of mass in world space of the given model.
+     * Calculates the center of mass in world space of the given node.
      */
-    static Vector3 getWorldCenterOfMass(const Model* model);
+    static Vector3 getWorldCenterOfMass(const Node* node);
 
     /**
      * Offsets the given vector by the given node's center of mass.

+ 6 - 2
gameplay/src/Platform.h

@@ -26,10 +26,11 @@ public:
      * Creates a platform for the specified game which is will interacte with.
      *
      * @param game The game to create a platform for.
+     * @param attachToWindow The native window handle to optionally attach to.
      * 
      * @return The created platform interface.
      */
-    static Platform* create(Game* game);
+    static Platform* create(Game* game, void* attachToWindow = NULL);
 
     /**
      * Begins processing the platform messages.
@@ -37,6 +38,9 @@ public:
      * This method handles all OS window messages and drives the game loop.
      * It normally does not return until the application is closed.
      * 
+     * If a attachToWindow is passed to Platform::create the message pump will instead attach
+     * to or allow the attachToWindow to drive the game loop on the platform.
+     *
      * @return The platform message pump return code.
      */
     int enterMessagePump();
@@ -127,7 +131,7 @@ public:
      *
      * @param captured True to enable mouse capture, false to disable it.
      */
-    static void setMouseCapture(bool captured);
+    static void setMouseCaptured(bool captured);
 
     /**
      * Determines if mouse capture is currently enabled.

+ 2 - 3
gameplay/src/PlatformAndroid.cpp

@@ -715,10 +715,9 @@ Platform::~Platform()
 {
 }
 
-Platform* Platform::create(Game* game)
+Platform* Platform::create(Game* game, void* attachToWindow)
 {
     Platform* platform = new Platform(game);
-    
     return platform;
 }
 
@@ -930,7 +929,7 @@ bool Platform::hasMouse()
     return false;
 }
 
-void Platform::setMouseCapture(bool captured)
+void Platform::setMouseCaptured(bool captured)
 {
     // not supported
 }

+ 55 - 11
gameplay/src/PlatformMacOSX.mm

@@ -35,7 +35,10 @@ static bool __otherMouseDown = false;
 static bool __shiftDown = false;
 static char* __title = NULL;
 static bool __fullscreen = false;
-
+static void* __attachToWindow = NULL;
+static bool __mouseCaptured = false;
+static CGPoint __mouseCapturePoint;
+static bool __cursorVisible = true;
 
 double getMachTimeInMilliseconds()
 {
@@ -238,10 +241,24 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTime
     [self mouse: Mouse::MOUSE_RELEASE_LEFT_BUTTON orTouchEvent: Touch::TOUCH_RELEASE x: point.x y: __height - point.y s: 0];
 }
 
-- (void)mouseMoved:(NSEvent *) event 
+- (void)mouseMoved:(NSEvent*) event 
 {
     NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
-    gameplay::Platform::mouseEventInternal(Mouse::MOUSE_MOVE, point.x, __height - point.y, 0);
+    
+
+    if (__mouseCaptured)
+    {
+        point.x = [event deltaX];
+        point.y = [event deltaY];
+
+        NSWindow* window = __view.window;
+        NSRect rect = window.frame;
+        CGPoint centerPoint;
+        centerPoint.x = rect.origin.x + (rect.size.width / 2);
+        centerPoint.y = rect.origin.y + (rect.size.height / 2);
+        CGDisplayMoveCursorToPoint(CGDisplayPrimaryDisplay(NULL), centerPoint);
+    }
+    gameplay::Platform::mouseEventInternal(Mouse::MOUSE_MOVE, point.x, point.y, 0);
 }
 
 - (void) mouseDragged: (NSEvent*) event
@@ -622,8 +639,9 @@ Platform::~Platform()
 {
 }
 
-Platform* Platform::create(Game* game)
+Platform* Platform::create(Game* game, void* attachToWindow)
 {
+	__attachToWindow = attachToWindow;
     Platform* platform = new Platform(game);
     
     return platform;
@@ -766,26 +784,52 @@ bool Platform::hasMouse()
     return true;
 }
 
-void Platform::setMouseCapture(bool captured)
+void Platform::setMouseCaptured(bool captured)
 {
-    // TODO: not implemented
+    if (captured != __mouseCaptured)
+    {
+        if (captured)
+        {
+            [NSCursor hide];
+        }
+        else
+        {   
+            [NSCursor unhide];
+        }
+        NSWindow* window = __view.window;
+        NSRect rect = window.frame;
+        CGPoint centerPoint;
+        centerPoint.x = rect.origin.x + (rect.size.width / 2);
+        centerPoint.y = rect.origin.y + (rect.size.height / 2);
+        CGDisplayMoveCursorToPoint(CGDisplayPrimaryDisplay(NULL), centerPoint);
+        __mouseCaptured = captured;
+    }
 }
 
 bool Platform::isMouseCaptured()
 {
-    // TODO: not implemented
-    return false;
+    return __mouseCaptured;
 }
 
 void Platform::setCursorVisible(bool visible)
 {
-    // TODO: not implemented
+    if (visible != __cursorVisible)
+    {
+        if (visible)
+        {
+             [NSCursor unhide];
+        }
+        else 
+        {
+             [NSCursor hide];
+        }
+        __cursorVisible = visible;
+    }
 }
 
 bool Platform::isCursorVisible()
 {
-    // TODO: not implemented
-    return true;
+    return __cursorVisible;
 }
 
 void Platform::swapBuffers()

+ 2 - 3
gameplay/src/PlatformQNX.cpp

@@ -488,10 +488,9 @@ Platform::~Platform()
     }
 }
 
-Platform* Platform::create(Game* game)
+Platform* Platform::create(Game* game, void* attachToWindow)
 {
     FileSystem::setResourcePath("./app/native/");
-
     Platform* platform = new Platform(game);
 
     bps_initialize();
@@ -1126,7 +1125,7 @@ bool Platform::hasMouse()
     return false;
 }
 
-void Platform::setMouseCapture(bool captured)
+void Platform::setMouseCaptured(bool captured)
 {
     // not supported
 }

+ 138 - 114
gameplay/src/PlatformWin32.cpp

@@ -21,6 +21,7 @@ static bool __vsync = WINDOW_VSYNC;
 static float __roll;
 static float __pitch;
 static HINSTANCE __hinstance = 0;
+static HWND __attachToWindow = 0;
 static HWND __hwnd = 0;
 static HDC __hdc = 0;
 static HGLRC __hrc = 0;
@@ -477,112 +478,8 @@ Platform::~Platform()
     }
 }
 
-Platform* Platform::create(Game* game)
+bool initializeGL()
 {
-    GP_ASSERT(game);
-
-    FileSystem::setResourcePath("./");
-
-    Platform* platform = new Platform(game);
-
-    // Get the application module handle.
-    __hinstance = ::GetModuleHandle(NULL);
-
-    LPCTSTR windowClass = L"gameplay";
-    std::wstring windowName;
-    bool fullscreen = false;
-    
-    // Read window settings from config.
-    if (game->getConfig())
-    {
-        Properties* config = game->getConfig()->getNamespace("window", true);
-        if (config)
-        {
-            // Read window title.
-            const char* title = config->getString("title");
-            if (title)
-            {
-                int len = MultiByteToWideChar(CP_ACP, 0, title, -1, NULL, 0);
-                wchar_t* wtitle = new wchar_t[len];
-                MultiByteToWideChar(CP_ACP, 0, title, -1, wtitle, len);
-                windowName = wtitle;
-                SAFE_DELETE_ARRAY(wtitle);
-            }
-
-            // Read window size.
-            int width = config->getInt("width");
-            if (width != 0)
-                __width = width;
-            int height = config->getInt("height");
-            if (height != 0)
-                __height = height;
-
-            // Read fullscreen state.
-            fullscreen = config->getBool("fullscreen");
-        }
-    }
-
-    RECT rect = { 0, 0, __width, __height };
-
-    // Register our window class.
-    WNDCLASSEX wc;
-    wc.cbSize = sizeof(WNDCLASSEX);
-    wc.style          = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
-    wc.lpfnWndProc    = (WNDPROC)__WndProc;
-    wc.cbClsExtra     = 0;
-    wc.cbWndExtra     = 0;
-    wc.hInstance      = __hinstance;
-    wc.hIcon          = LoadIcon(NULL, IDI_APPLICATION);
-    wc.hIconSm        = NULL;
-    wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
-    wc.hbrBackground  = NULL;  // No brush - we are going to paint our own background
-    wc.lpszMenuName   = NULL;  // No default menu
-    wc.lpszClassName  = windowClass;
-
-    if (!::RegisterClassEx(&wc))
-    {
-        GP_ERROR("Failed to register window class.");
-        goto error;
-    }
-
-    if (fullscreen)
-    {
-        DEVMODE dm;
-        memset(&dm, 0, sizeof(dm));
-        dm.dmSize= sizeof(dm);
-        dm.dmPelsWidth	= __width;
-        dm.dmPelsHeight	= __height;
-        dm.dmBitsPerPel	= 32;
-        dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
-
-        // Try to set selected mode and get results. NOTE: CDS_FULLSCREEN gets rid of start bar.
-        if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
-        {
-            fullscreen = false;
-            GP_ERROR("Failed to start game in full-screen mode with resolution %dx%d.", __width, __height);
-            goto error;
-        }
-    }
-
-    // Set the window style.
-    DWORD style   = (fullscreen ? WS_POPUP : WS_POPUP | WS_BORDER | WS_CAPTION | WS_SYSMENU) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
-    //DWORD style   = (fullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
-    DWORD styleEx = (fullscreen ? WS_EX_APPWINDOW : WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
-
-    // Adjust the window rectangle so the client size is the requested size.
-    AdjustWindowRectEx(&rect, style, FALSE, styleEx);
-
-    // Create the native Windows window.
-    __hwnd = CreateWindowEx(styleEx, windowClass, windowName.c_str(), style, 0, 0, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, __hinstance, NULL);
-
-    // Get the drawing context.
-    __hdc = GetDC(__hwnd);
-
-    // Center the window
-    const int screenX = (GetSystemMetrics(SM_CXSCREEN) - __width) / 2;
-    const int screenY = (GetSystemMetrics(SM_CYSCREEN) - __height) / 2;
-    ::SetWindowPos(__hwnd, __hwnd, screenX, screenY, -1, -1, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
-
     // Choose pixel format. 32-bit. RGBA.
     PIXELFORMATDESCRIPTOR pfd;
     memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
@@ -599,12 +496,12 @@ Platform* Platform::create(Game* game)
     if (pixelFormat == 0)
     {
         GP_ERROR("Failed to choose a pixel format.");
-        goto error;
+        return false;
     }
     if (!SetPixelFormat (__hdc, pixelFormat, &pfd))
     {
         GP_ERROR("Failed to set the pixel format.");
-        goto error;
+        return false;
     }
 
     HGLRC tempContext = wglCreateContext(__hdc);
@@ -613,7 +510,7 @@ Platform* Platform::create(Game* game)
     if (GLEW_OK != glewInit())
     {
         GP_ERROR("Failed to initialize GLEW.");
-        goto error;
+        return false;
     }
 
     int attribs[] =
@@ -627,21 +524,146 @@ Platform* Platform::create(Game* game)
     {
         wglDeleteContext(tempContext);
         GP_ERROR("Failed to create OpenGL context.");
-        goto error;
+        return false;
     }
     wglDeleteContext(tempContext);
 
     if (!wglMakeCurrent(__hdc, __hrc) || !__hrc)
     {
         GP_ERROR("Failed to make the window current.");
-        goto error;
+        return false;
     }
 
     // Vertical sync.
     wglSwapIntervalEXT(__vsync ? 1 : 0);
 
-    // Show the window.
-    ShowWindow(__hwnd, SW_SHOW);
+    return true;
+}
+
+Platform* Platform::create(Game* game, void* attachToWindow)
+{
+    GP_ASSERT(game);
+
+    FileSystem::setResourcePath("./");
+    Platform* platform = new Platform(game);
+
+    // Get the application module handle.
+    __hinstance = ::GetModuleHandle(NULL);
+
+    __attachToWindow = (HWND)attachToWindow;
+    if (!__attachToWindow)
+    {
+        LPCTSTR windowClass = L"gameplay";
+        std::wstring windowName;
+        bool fullscreen = false;
+    
+        // Read window settings from config.
+        if (game->getConfig())
+        {
+            Properties* config = game->getConfig()->getNamespace("window", true);
+            if (config)
+            {
+                // Read window title.
+                const char* title = config->getString("title");
+                if (title)
+                {
+                    int len = MultiByteToWideChar(CP_ACP, 0, title, -1, NULL, 0);
+                    wchar_t* wtitle = new wchar_t[len];
+                    MultiByteToWideChar(CP_ACP, 0, title, -1, wtitle, len);
+                    windowName = wtitle;
+                    SAFE_DELETE_ARRAY(wtitle);
+                }
+
+                // Read window size.
+                int width = config->getInt("width");
+                if (width != 0)
+                    __width = width;
+                int height = config->getInt("height");
+                if (height != 0)
+                    __height = height;
+
+                // Read fullscreen state.
+                fullscreen = config->getBool("fullscreen");
+            }
+        }
+
+        RECT rect = { 0, 0, __width, __height };
+
+        // Register our window class.
+        WNDCLASSEX wc;
+        wc.cbSize = sizeof(WNDCLASSEX);
+        wc.style          = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+        wc.lpfnWndProc    = (WNDPROC)__WndProc;
+        wc.cbClsExtra     = 0;
+        wc.cbWndExtra     = 0;
+        wc.hInstance      = __hinstance;
+        wc.hIcon          = LoadIcon(NULL, IDI_APPLICATION);
+        wc.hIconSm        = NULL;
+        wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
+        wc.hbrBackground  = NULL;  // No brush - we are going to paint our own background
+        wc.lpszMenuName   = NULL;  // No default menu
+        wc.lpszClassName  = windowClass;
+
+        if (!::RegisterClassEx(&wc))
+        {
+            GP_ERROR("Failed to register window class.");
+            goto error;
+        }
+
+        if (fullscreen)
+        {
+            DEVMODE dm;
+            memset(&dm, 0, sizeof(dm));
+            dm.dmSize= sizeof(dm);
+            dm.dmPelsWidth	= __width;
+            dm.dmPelsHeight	= __height;
+            dm.dmBitsPerPel	= 32;
+            dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+
+            // Try to set selected mode and get results. NOTE: CDS_FULLSCREEN gets rid of start bar.
+            if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
+            {
+                fullscreen = false;
+                GP_ERROR("Failed to start game in full-screen mode with resolution %dx%d.", __width, __height);
+                goto error;
+            }
+        }
+
+        // Set the window style.
+        DWORD style   = (fullscreen ? WS_POPUP : WS_POPUP | WS_BORDER | WS_CAPTION | WS_SYSMENU) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
+        DWORD styleEx = (fullscreen ? WS_EX_APPWINDOW : WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
+
+        // Adjust the window rectangle so the client size is the requested size.
+        AdjustWindowRectEx(&rect, style, FALSE, styleEx);
+
+        // Create the native Windows window.
+        __hwnd = CreateWindowEx(styleEx, windowClass, windowName.c_str(), style, 0, 0, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, __hinstance, NULL);
+
+        // Get the drawing context.
+        __hdc = GetDC(__hwnd);
+
+        // Center the window
+        const int screenX = (GetSystemMetrics(SM_CXSCREEN) - __width) / 2;
+        const int screenY = (GetSystemMetrics(SM_CYSCREEN) - __height) / 2;
+        ::SetWindowPos(__hwnd, __hwnd, screenX, screenY, -1, -1, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
+
+        if (!initializeGL())
+            goto error;
+
+        // Show the window.
+        ShowWindow(__hwnd, SW_SHOW);
+    }
+    else
+    {
+        // Attach to a previous windows
+        __hwnd = (HWND)__attachToWindow;
+        __hdc = GetDC(__hwnd);
+
+        SetWindowLongPtr(__hwnd, GWL_WNDPROC, (LONG)(WNDPROC)__WndProc);
+        
+        if (!initializeGL())
+            goto error;
+    }
 
     return platform;
 
@@ -674,6 +696,9 @@ int Platform::enterMessagePump()
     if (_game->getState() != Game::RUNNING)
         _game->run();
 
+    if (__attachToWindow)
+        return 0;
+
     // Enter event dispatch loop.
     MSG msg;
     while (true)
@@ -699,7 +724,6 @@ int Platform::enterMessagePump()
         if (_game->getState() == Game::UNINITIALIZED)
             break;
     }
-
     return msg.wParam;
 }
 
@@ -768,7 +792,7 @@ bool Platform::hasMouse()
     return true;
 }
 
-void Platform::setMouseCapture(bool captured)
+void Platform::setMouseCaptured(bool captured)
 {
     if (captured != __mouseCaptured)
     {

+ 2 - 2
gameplay/src/PlatformiOS.mm

@@ -833,7 +833,7 @@ Platform::~Platform()
 {
 }
 
-Platform* Platform::create(Game* game)
+Platform* Platform::create(Game* game, void* attachToWindow)
 {
     Platform* platform = new Platform(game);
     return platform;
@@ -900,7 +900,7 @@ bool Platform::hasMouse()
     return false;
 }
 
-void Platform::setMouseCapture(bool captured)
+void Platform::setMouseCaptured(bool captured)
 {
     // not supported
 }

+ 5 - 0
gameplay/src/SpriteBatch.h

@@ -273,6 +273,11 @@ public:
      */
     void setProjectionMatrix(const Matrix& matrix);
 
+    /**
+     * Gets the projection matrix for the SpriteBatch.
+     * 
+     * @return The projection matrix.
+     */
     const Matrix& getProjectionMatrix() const;
 
 private: