1
0
mirror of https://github.com/Halofreak1990/XFXFramework synced 2024-12-26 13:49:34 +01:00
XFXFramework/src/libXFX/SpriteBatch.cpp

326 lines
13 KiB
C++
Raw Normal View History

// Copyright (C) 2010-2012, XFX Team
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the copyright holder nor the names of any
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <Graphics/Color.h>
#include <Graphics/Sprite.h>
#include <Graphics/SpriteBatch.h>
#include <Graphics/SpriteFont.h>
#include <Graphics/Texture2D.h>
#include <Matrix.h>
#include <Rectangle.h>
#include <Vector2.h>
using namespace XFX;
namespace XFX
{
namespace Graphics
{
SpriteBatch::GraphicsDevice_()
{
return device;
spriteBlendMode = SpriteBlendMode::None
}
SpriteBatch::IsDisposed()
{
return disposed;
}
SpriteBatch::~SpriteBatch()
{
Dispose(false);
}
SpriteBatch::SpriteBatch(GraphicsDevice graphicsDevice)
{
device = graphicsDevice;
}
void SpriteBatch::Begin()
{
Begin(SpriteBlendMode::AlphaBlend, SpriteSortMode::Deferred, SaveStateMode::None, Matrix::Identity);
}
void SpriteBatch::Begin(SpriteBlendMode blendMode, SpriteSortMode sortMode, SaveStateMode stateMode)
{
Begin(blendMode, sortMode, stateMode, Matrix::Identity);
}
void Begin(SpriteBlendMode blendMode, SpriteSortMode sortMode, SaveStateMode stateMode, Matrix transformMatrix)
{
//to respect order Begin/Draw/end
if (isRunning)
return;
if (stateMode == SaveStateMode::SaveState)
saveState = StateBlock(device);
spriteBlendMode = blendMode;
this.sortMode = sortMode;
if (sortMode == SpriteSortMode::Immediate)
applyGraphicsDeviceSettings();
isRunning = true;
}
void SpriteBatch::Dispose(int disposing)
{
if (!disposed)
{
if (disposing)
{
// Release any managed components
}
disposed = true;
// Release any unmanaged components
}
}
void SpriteBatch::Dispose()
{
Dispose(true);
}
void SpriteBatch::Draw(Texture2D &texture, Rectangle &destinationRectangle, Color &color)
{
Draw(texture, destinationRectangle, Rectangle::Zero, color, 0f, Vector2::Zero, SpriteEffects::None, 0f);
}
void SriteBatch::Draw(Texture2D &texture, Rectangle &destinationRectangle, Rectangle &sourceRectangle, Color &color)
{
Draw(texture, destinationRectangle, sourceRectangle, color, 0f, Vector2::Zero, SpriteEffects::None, 0f);
}
void SpriteBatch::Draw(Texture2D &texture, Vector2 &position, Color &color)
{
Draw(texture, position, Rectangle::Zero, color);
}
void SpriteBatch::Draw(Texture2D &texture, Vector2 &position, Rectangle &sourceRectangle, Color &color)
{
Rectangle destination = Rectangle((int)vector.X, (int)vector.Y, texture.Width, texture.Height);
Draw(texture, destination, sourceRectangle, color, 0f, Vector2::Zero, SpriteEffects::None, 0f);
}
void SpriteBatch::Draw(Texture2D &texture, Vector2 &position, Rectangle &sourceRectangle, Color &color, float rotation, Vector2 &origin, float scale, SpriteEffects_t effects, float layerDepth)
{
int width;
int height;
if (sourceRectangle != Rectangle::Zero)
{
width = (int)(sourceRectangle.Width * scale);
height = (int)(sourceRectangle.Height * scale);
}
else
{
width = (int)(texture.Width * scale);
height = (int)(texture.Height * scale);
}
Rectangle destination = Rectangle((int)vector.X, (int)vector.Y, width, height);
Draw(texture, destination, sourceRectangle, color, rotation, origin, effects, layerDepth);
}
void SpriteBatch::Draw(Texture2D &texture, Vector2 &position, Rectangle &sourceRectangle, Color &color, float rotation, Vector2 &origin, Vector2 &scale, SpriteEffects_t effects, float layerDepth)
{
int width;
int height;
if (sourceRectangle != Rectangle::Zero)
{
width = (int)(sourceRectangle.Width * scale.X);
height = (int)(sourceRectangle.Height * scale.Y);
}
else
{
width = (int)(texture.Width * scale.X);
height = (int)(texture.Height * scale.Y);
}
Rectangle destination = Rectangle((int)vector.X, (int)vector.Y, width, height);
Draw(texture, destination, sourceRectangle, color, rotation, origin, effects, layerDepth);
}
void SpriteBatch::Draw(Texture2D &texture, Rectangle &destinationRectangle, Rectangle &sourceRectangle, Color &color, float rotation, Vector2 &origin, SpriteEffects_t &effects, float layerDepth)
{
if (!isRunning)
return;
Sprite temp = Sprite(texture, (sourceRectangle != Rectangle::Zero) ? sourceRectangle : Rectangle(0, 0, texture.Width, texture.Height),
destinationRectangle, color, rotation, origin, effects, layerDepth);
spriteList.Add(temp);
if (sortMode == SpriteSortMode::Immediate)
flush();
}
void SpriteBatch::DrawString(SpriteFont &spriteFont, char* text, Vector2 &position, Color &color)
{
if (!spriteFont)
return;
if (!text)
return;
spriteFont.Draw(text, *this, position, color, 0f, Vector2::Zero, Vector2::One, SpriteEffects::None, 0f);
}
void SpriteBatch::DrawString(SpriteFont &spriteFont, char* text, Vector2 &position, Color &color, float rotation, Vector2 &origin, float scale, SpriteEffects_t effects, float layerDepth)
{
Vector2 vector;
if (!spriteFont)
return;
if (!text)
return;
vector.X = scale;
vector.Y = scale;
spriteFont.Draw(text, *this, position, color, rotation, origin, vector, effects, layerDepth);
}
void SpriteBatch::End()
{
if (!isRunning)
return;
if (sortMode != SpriteSortMode::Immediate)
{
applyGraphicsDeviceSettings();
flush();
}
glDisable(GL_TEXTURE_2D);
Gl::glMatrixMode(Gl::GL_PROJECTION);
Gl::glPopMatrix();
Gl::glMatrixMode(Gl::GL_MODELVIEW);
Gl::glPopMatrix();
restoreRenderState();
isRunning = false;
}
void SpriteBatch::restoreRenderState()
{
if (stateMode == SaveStateMode::SaveState)
saveState.Apply();
}
void SpriteBatch::flush()
{
switch (sortMode)
{
case SpriteSortMode::BackToFront:
spriteList.Sort(BackToFrontSpriteComparer<Sprite>());
break;
case SpriteSortMode::FrontToBack:
spriteList.Sort(FrontToBackSpriteComparer<Sprite>());
break;
case SpriteSortMode::Texture: // nothing here?
break;
}
spriteList.First();
Sprite temp;
while(spriteList.Next(temp))
{
// Set the color, bind the texture for drawing and prepare the texture source
if (temp.Color.A <= 0) continue;
Gl::glColor4f((float)temp.Color.R / 255f, (float)temp.Color.G / 255f, (float)temp.Color.B / 255f, (float)temp.Color.A / 255f);
Gl::glBindTexture(Gl::GL_TEXTURE_2D, temp.Texture.textureId);
// Setup the matrix
Gl::glPushMatrix();
if ((temp.DestinationRectangle.X != 0) || (temp.DestinationRectangle.Y != 0))
Gl::glTranslatef(temp.DestinationRectangle.X, temp.DestinationRectangle.Y, 0f); // Position
if (temp.Rotation != 0)
Gl::glRotatef(MathHelper.ToDegrees(temp.Rotation), 0f, 0f, 1f); // Rotation
if ((temp.DestinationRectangle.Width != 0 && temp.Origin.X != 0) || (temp.DestinationRectangle.Height != 0 && temp.Origin.Y != 0))
Gl::glTranslatef( // Orientation
-temp.Origin.X * (float)temp.DestinationRectangle.Width / (float)temp.SourceRectangle.Width,
-temp.Origin.Y * (float)temp.DestinationRectangle.Height / (float)temp.SourceRectangle.Height, 0f);
// Calculate the points on the texture
float x = (float)temp.SourceRectangle.X / (float)temp.Texture.Width;
float y = (float)temp.SourceRectangle.Y / (float)temp.Texture.Height;
float twidth = (float)temp.SourceRectangle.Width / (float)temp.Texture.Width;
float theight = (float)temp.SourceRectangle.Height / (float)temp.Texture.Height;
// Draw
Gl::glBegin(Gl::GL_QUADS);
{
Gl::glTexCoord2f(x,y + theight);
Gl::glVertex2f(0f, temp.DestinationRectangle.Height);
Gl::glTexCoord2f(x + twidth, y + theight);
Gl::glVertex2f(temp.DestinationRectangle.Width, temp.DestinationRectangle.Height);
Gl::glTexCoord2f(x + twidth,y);
Gl::glVertex2f(temp.DestinationRectangle.Width, 0f);
Gl::glTexCoord2f(x,y);
Gl::glVertex2f(0f, 0f);
}
Gl::glEnd();
Gl::glPopMatrix(); // Finish with the matrix
}
spriteList.Clear();
}
void SpriteBatch::applyGraphicsDeviceSettings()
{
// Set the blend mode
switch (spriteBlendMode)
{
case SpriteBlendMode::AlphaBlend:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
break;
case SpriteBlendMode::Additive:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
break;
case SpriteBlendMode::None:
glDisable(GL_BLEND);
break;
default:
return;
}
glEnable(GL_TEXTURE_2D);
// Reset the projection matrix and use the orthographic matrix
int[] viewPort = new int[4];
Gl::glGetIntegerv(Gl::GL_VIEWPORT, viewPort);
Gl::glMatrixMode(Gl::GL_PROJECTION);
Gl::glPushMatrix();
Gl::glLoadIdentity();
Gl::glOrtho(0, viewPort[2], viewPort[3], 0, -1, 1); // viewPort[2] = width, viewPort[3] = height
Gl::glMatrixMode(Gl::GL_MODELVIEW);
Gl::glPushMatrix();
Gl::glLoadIdentity();
}
}
}