///////////////////////////////////////////////////////////////////////////////////////////
// Sprite.cpp
//
//  Implementation of the Sprite class, which represents a rectangular textured object
// on the screen, with a 1:1 mapping between texels and pixels.
//
//  Note that a Sprite doesn't require resources, so you can use these freely as base
// classes for sprite objects in your applications.
//
//  Sprite supports multiple frames. Multi-frame sprites are in rectangular blocks, the
// width of which is specified in FramesAcross.
//
//  All the complexity is in FillVertexArray, which calculates the texture co-ordinates
// to achieve the texel-pixel equality.

#include "StdAfx.h"
#include "sprite.h"

using namespace System::Drawing;

namespace Sunlight
{
    namespace DirectX
    {
        namespace Graphics
        {
            Sprite::Sprite(SpriteManager *pManagerObject, System::Drawing::Rectangle rDimensions, Texture *pTextureObject, System::Drawing::Point ptSourcePosition, int nFramesAcross) : 
                ManagerObject(pManagerObject),
                TextureObject(pTextureObject),
                Left(rDimensions.X), Top(rDimensions.Y), 
                Width(rDimensions.Width), Height(rDimensions.Height), 
                SourceLeft(ptSourcePosition.X), SourceTop(ptSourcePosition.Y),
                SourceWidth(rDimensions.Width), SourceHeight(rDimensions.Height), 
                FramesAcross(nFramesAcross), CurrentFrame(0),
                ShadowDepth(0)
            {
            }
            Sprite::Sprite(SpriteManager *pManagerObject, System::Drawing::Rectangle rDimensions, Texture *pTextureObject, System::Drawing::Point ptSourcePosition) : 
                ManagerObject(pManagerObject),
                TextureObject(pTextureObject),
                Left(rDimensions.X), Top(rDimensions.Y), 
                Width(rDimensions.Width), Height(rDimensions.Height), 
                SourceLeft(ptSourcePosition.X), SourceTop(ptSourcePosition.Y),
                SourceWidth(rDimensions.Width), SourceHeight(rDimensions.Height), 
                FramesAcross(1), CurrentFrame(0),
                ShadowDepth(0)
            {
            }

            // Draw this sprite using its SpriteManager.
            void Sprite::Draw()
            {
                ManagerObject->Draw(this);
            }

            // Fill an array of SpriteVertexes with the vertex co-ordinates and texture co-ordinates.
            void Sprite::FillVertexArray(SpriteManager::SpriteVertex __nogc *vertices)
            {
                int xReal = SourceLeft + (CurrentFrame % FramesAcross) * SourceWidth;
                int yReal = SourceTop + (CurrentFrame / FramesAcross) * SourceHeight;

                vertices[0].x = vertices[2].x = (float)Left - 0.5f;
                vertices[1].x = vertices[3].x = (float)(Left + Width) - 0.5f;
                vertices[0].y = vertices[1].y = (float)Top - 0.5f;
                vertices[2].y = vertices[3].y = (float)(Top + Height) - 0.5f;
        
                // z and rhw co-ordinates are fixed at 0.5 and 1.0 respectively
                vertices[0].z = vertices[1].z = 
                    vertices[2].z = vertices[3].z = 0.5f;
        
                vertices[0].rhw = vertices[1].rhw = 
                    vertices[2].rhw = vertices[3].rhw = 1.0f;
        
                // White colour to avoid clashing with the texture
                vertices[0].dwColor = vertices[1].dwColor = 
                    vertices[2].dwColor = vertices[3].dwColor = 0xFFFFFFFF;

                // Texture co-ordinates
                vertices[0].tu = vertices[2].tu = (float)xReal / (float)TextureObject->Width;
                vertices[1].tu = vertices[3].tu = (float)(xReal + SourceWidth) / (float)TextureObject->Width;
        
                vertices[0].tv = vertices[1].tv = (float)yReal / (float)TextureObject->Height;
                vertices[2].tv = vertices[3].tv = (float)(yReal + SourceHeight) / (float)TextureObject->Height;
            }

            // Gets a rectangle enclosing the sprite.
            Drawing::Rectangle Sprite::get_Bounds()
            {
                return Drawing::Rectangle(Left, Top, Width, Height);
            }
        }
    }
}