From 1760935ed2493d890d33c2e4d469a45729d287d4 Mon Sep 17 00:00:00 2001
From: walbourn_cp <SND\walbourn_cp>
Date: Wed, 22 Jan 2014 12:21:49 -0800
Subject: [PATCH] DirectXTK: Added rotation support to SpriteBatch to simplify
 handling of Windows Store/Phone orientation changes

---
 Inc/SpriteBatch.h   |  4 +++
 Src/SpriteBatch.cpp | 67 +++++++++++++++++++++++++++++++++++++--------
 2 files changed, 60 insertions(+), 11 deletions(-)

diff --git a/Inc/SpriteBatch.h b/Inc/SpriteBatch.h
index c49095a9e..a2f7cb5b6 100644
--- a/Inc/SpriteBatch.h
+++ b/Inc/SpriteBatch.h
@@ -78,6 +78,10 @@ namespace DirectX
         void XM_CALLCONV Draw(_In_ ID3D11ShaderResourceView* texture, RECT const& destinationRectangle, FXMVECTOR color = Colors::White);
         void XM_CALLCONV Draw(_In_ ID3D11ShaderResourceView* texture, RECT const& destinationRectangle, _In_opt_ RECT const* sourceRectangle, FXMVECTOR color = Colors::White, float rotation = 0, XMFLOAT2 const& origin = Float2Zero, SpriteEffects effects = SpriteEffects_None, float layerDepth = 0);
 
+        // Rotation mode to be applied to the sprite transformation
+        void SetRotation( DXGI_MODE_ROTATION mode );
+        DXGI_MODE_ROTATION GetRotation() const;
+
     private:
         // Private implementation.
         class Impl;
diff --git a/Src/SpriteBatch.cpp b/Src/SpriteBatch.cpp
index 11b7b127b..b7310688c 100644
--- a/Src/SpriteBatch.cpp
+++ b/Src/SpriteBatch.cpp
@@ -58,6 +58,7 @@ __declspec(align(16)) class SpriteBatch::Impl : public AlignedNew<SpriteBatch::I
         static_assert((SpriteEffects_FlipBoth & (SourceInTexels | DestSizeInPixels)) == 0, "Flag bits must not overlap");
     };
 
+    DXGI_MODE_ROTATION mRotation;
 
 private:
     // Implementation helper methods.
@@ -72,7 +73,7 @@ __declspec(align(16)) class SpriteBatch::Impl : public AlignedNew<SpriteBatch::I
     static void XM_CALLCONV RenderSprite(_In_ SpriteInfo const* sprite, _Out_cap_c_(VerticesPerSprite) VertexPositionColorTexture* vertices, FXMVECTOR textureSize, FXMVECTOR inverseTextureSize);
 
     static XMVECTOR GetTextureSize(_In_ ID3D11ShaderResourceView* texture);
-    static XMMATRIX GetViewportTransform(_In_ ID3D11DeviceContext* deviceContext);
+    static XMMATRIX GetViewportTransform(_In_ ID3D11DeviceContext* deviceContext, DXGI_MODE_ROTATION rotation );
 
 
     // Constants.
@@ -329,7 +330,8 @@ void SpriteBatch::Impl::ContextResources::CreateVertexBuffer()
 
 // Per-SpriteBatch constructor.
 SpriteBatch::Impl::Impl(_In_ ID3D11DeviceContext* deviceContext)
-  : mSpriteQueueCount(0),
+  : mRotation( DXGI_MODE_ROTATION_IDENTITY ),
+    mSpriteQueueCount(0),
     mSpriteQueueArraySize(0),
     mInBeginEndPair(false),
     mSortMode(SpriteSortMode_Deferred),
@@ -526,7 +528,7 @@ void SpriteBatch::Impl::PrepareForRendering()
     deviceContext->IASetIndexBuffer(mDeviceResources->indexBuffer.Get(), DXGI_FORMAT_R16_UINT, 0);
 
     // Set the viewport transform matrix.
-    XMMATRIX transformMatrix = mTransformMatrix * GetViewportTransform(deviceContext);
+    XMMATRIX transformMatrix = mTransformMatrix * GetViewportTransform(deviceContext, mRotation);
 
     mContextResources->constantBuffer.SetData(deviceContext, transformMatrix);
 
@@ -862,7 +864,7 @@ XMVECTOR SpriteBatch::Impl::GetTextureSize(_In_ ID3D11ShaderResourceView* textur
 
 
 // Generates a viewport transform matrix for rendering sprites using x-right y-down screen pixel coordinates.
-XMMATRIX SpriteBatch::Impl::GetViewportTransform(_In_ ID3D11DeviceContext* deviceContext)
+XMMATRIX SpriteBatch::Impl::GetViewportTransform(_In_ ID3D11DeviceContext* deviceContext, DXGI_MODE_ROTATION rotation )
 {
     // Look up the current viewport.
     D3D11_VIEWPORT viewport;
@@ -877,13 +879,44 @@ XMMATRIX SpriteBatch::Impl::GetViewportTransform(_In_ ID3D11DeviceContext* devic
     float xScale = (viewport.Width  > 0) ? 2.0f / viewport.Width  : 0.0f;
     float yScale = (viewport.Height > 0) ? 2.0f / viewport.Height : 0.0f;
 
-    return XMMATRIX
-    (
-         xScale,  0,       0,  0,
-         0,      -yScale,  0,  0,
-         0,       0,       1,  0,
-        -1,       1,       0,  1
-    );
+    switch( rotation )
+    {
+    case DXGI_MODE_ROTATION_ROTATE90:
+        return XMMATRIX
+        (
+             0,       -yScale,  0,  0,
+             -xScale, 0,        0,  0,
+             0,       0,        1,  0,
+             1,       1,        0,  1
+        );
+
+    case DXGI_MODE_ROTATION_ROTATE270:
+        return XMMATRIX
+        (
+             0,       yScale,   0,  0,
+             xScale,  0,        0,  0,
+             0,       0,        1,  0,
+            -1,      -1,        0,  1
+        );
+
+    case DXGI_MODE_ROTATION_ROTATE180:
+        return XMMATRIX
+        (
+            -xScale,  0,       0,  0,
+             0,       yScale,  0,  0,
+             0,       0,       1,  0,
+             1,      -1,       0,  1
+        );
+
+    default:
+        return XMMATRIX
+        (
+             xScale,  0,       0,  0,
+             0,      -yScale,  0,  0,
+             0,       0,       1,  0,
+            -1,       1,       0,  1
+        );
+    }
 }
 
 
@@ -1003,3 +1036,15 @@ void XM_CALLCONV SpriteBatch::Draw(_In_ ID3D11ShaderResourceView* texture, RECT
     
     pImpl->Draw(texture, destination, sourceRectangle, color, originRotationDepth, effects | Impl::SpriteInfo::DestSizeInPixels);
 }
+
+
+void SpriteBatch::SetRotation( DXGI_MODE_ROTATION mode )
+{
+    pImpl->mRotation = mode;
+}
+
+
+DXGI_MODE_ROTATION SpriteBatch::GetRotation() const
+{
+    return pImpl->mRotation;
+}