mirror of
https://github.com/Halofreak1990/XFXFramework
synced 2024-12-26 13:49:34 +01:00
346 lines
13 KiB
C++
346 lines
13 KiB
C++
// 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.
|
|
|
|
extern "C" {
|
|
#include "pbkit.h"
|
|
}
|
|
#include <Graphics/Color.h>
|
|
#include <Graphics/Sprite.h>
|
|
#include <Graphics/SpriteBatch.h>
|
|
#include <Graphics/SpriteFont.h>
|
|
#include <Graphics/Texture2D.h>
|
|
#include <MathHelper.h>
|
|
#include <Matrix.h>
|
|
#include <Rectangle.h>
|
|
#include <Vector2.h>
|
|
#include <Vector4.h>
|
|
|
|
using namespace XFX;
|
|
|
|
namespace XFX
|
|
{
|
|
namespace Graphics
|
|
{
|
|
SpriteBatch::SpriteBatch()
|
|
{
|
|
}
|
|
|
|
SpriteBatch::SpriteBatch(GraphicsDevice graphicsDevice)
|
|
{
|
|
device = graphicsDevice;
|
|
}
|
|
|
|
SpriteBatch::~SpriteBatch()
|
|
{
|
|
Dispose(false);
|
|
}
|
|
|
|
GraphicsDevice SpriteBatch::GraphicsDevice_()
|
|
{
|
|
return device;
|
|
}
|
|
|
|
bool SpriteBatch::IsDisposed()
|
|
{
|
|
return isDisposed;
|
|
}
|
|
|
|
void SpriteBatch::Begin()
|
|
{
|
|
Begin(SpriteBlendMode::AlphaBlend, SpriteSortMode::Deferred, SaveStateMode::None, Matrix::Identity);
|
|
}
|
|
|
|
void SpriteBatch::Begin(SpriteBlendMode_t blendMode)
|
|
{
|
|
Begin(blendMode, SpriteSortMode::Deferred, SaveStateMode::None, Matrix::Identity);
|
|
}
|
|
|
|
void SpriteBatch::Begin(SpriteBlendMode_t blendMode, SpriteSortMode_t sortMode, SaveStateMode_t stateMode)
|
|
{
|
|
Begin(blendMode, sortMode, stateMode, Matrix::Identity);
|
|
}
|
|
|
|
void SpriteBatch::Begin(SpriteBlendMode_t blendMode, SpriteSortMode_t sortMode, SaveStateMode_t stateMode, Matrix transformMatrix)
|
|
{
|
|
if (inBeginEndPair)
|
|
{
|
|
throw InvalidOperationException("Begin cannot be called again until End has been successfully called.");
|
|
}
|
|
|
|
if (stateMode == SaveStateMode::SaveState)
|
|
saveState = StateBlock(device);
|
|
spriteBlendMode = blendMode;
|
|
spriteSortMode = sortMode;
|
|
if (sortMode == SpriteSortMode::Immediate)
|
|
applyGraphicsDeviceSettings();
|
|
|
|
inBeginEndPair = true;
|
|
}
|
|
|
|
void SpriteBatch::Dispose(bool disposing)
|
|
{
|
|
if (disposing && !isDisposed)
|
|
{
|
|
if (Disposing != null)
|
|
{
|
|
Disposing(this, EventArgs::Empty);
|
|
}
|
|
}
|
|
isDisposed = true;
|
|
}
|
|
|
|
void SpriteBatch::Dispose()
|
|
{
|
|
Dispose(true);
|
|
}
|
|
|
|
void SpriteBatch::Draw(Texture2D texture, Rectangle destinationRectangle, Color color)
|
|
{
|
|
Draw(texture, destinationRectangle, Rectangle::Empty, color, 0.0f, Vector2::Zero, SpriteEffects::None, 0.0f);
|
|
}
|
|
|
|
void SpriteBatch::Draw(Texture2D texture, Vector2 position, Color color)
|
|
{
|
|
Draw(texture, position, Rectangle::Empty, color);
|
|
}
|
|
|
|
void SpriteBatch::Draw(Texture2D texture, Rectangle destinationRectangle, Rectangle sourceRectangle, Color color)
|
|
{
|
|
Draw(texture, destinationRectangle, sourceRectangle, color, 0.0f, Vector2::Zero, SpriteEffects::None, 0.0f);
|
|
}
|
|
|
|
void SpriteBatch::Draw(Texture2D texture, Vector2 position, Rectangle sourceRectangle, Color color)
|
|
{
|
|
Rectangle destination = Rectangle((int)position.X, (int)position.Y, texture.Width(), texture.Height());
|
|
Draw(texture, destination, sourceRectangle, color, 0.0f, Vector2::Zero, SpriteEffects::None, 0.0f);
|
|
}
|
|
|
|
void SpriteBatch::Draw(Texture2D texture, Rectangle destinationRectangle, Rectangle sourceRectangle, Color color, float rotation, Vector2 origin, SpriteEffects_t effects, float layerDepth)
|
|
{
|
|
Sprite sprite = Sprite(texture,
|
|
sourceRectangle != Rectangle::Empty ? sourceRectangle : Rectangle(0, 0, texture.Width(), texture.Height()),
|
|
destinationRectangle,
|
|
color,
|
|
rotation,
|
|
origin,
|
|
effects,
|
|
layerDepth);
|
|
|
|
SpriteList.Add(sprite);
|
|
|
|
if (spriteSortMode == SpriteSortMode::Immediate)
|
|
Flush();
|
|
}
|
|
|
|
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::Empty)
|
|
{
|
|
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)position.X, (int)position.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, float scale, SpriteEffects_t effects, float layerDepth)
|
|
{
|
|
int width;
|
|
int height;
|
|
if (sourceRectangle != Rectangle::Empty)
|
|
{
|
|
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)position.X, (int)position.Y, width, height);
|
|
Draw(texture, destination, sourceRectangle, color, rotation, origin, effects, layerDepth);
|
|
}
|
|
|
|
void SpriteBatch::DrawString(SpriteFont spriteFont, char* text, Vector2 position, Color color)
|
|
{
|
|
spriteFont.Draw(text, *this, position, color, 0.0f, Vector2::Zero, Vector2::One, SpriteEffects::None, 0.0f);
|
|
}
|
|
|
|
void SpriteBatch::DrawString(SpriteFont spriteFont, char* text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects_t effects, float layerDepth)
|
|
{
|
|
spriteFont.Draw(text, *this, position, color, rotation, origin, scale, effects, layerDepth);
|
|
}
|
|
|
|
void SpriteBatch::DrawString(SpriteFont spriteFont, char* text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects_t effects, float layerDepth)
|
|
{
|
|
Vector2 vector = Vector2::Zero;
|
|
vector.X = scale;
|
|
vector.Y = scale;
|
|
spriteFont.Draw(text, *this, position, color, rotation, origin, vector, effects, layerDepth);
|
|
}
|
|
|
|
void SpriteBatch::End()
|
|
{
|
|
if (!inBeginEndPair)
|
|
throw InvalidOperationException("Begin must be called successfully before End can be called.");
|
|
|
|
if (spriteSortMode != SpriteSortMode::Immediate)
|
|
{
|
|
applyGraphicsDeviceSettings();
|
|
Flush();
|
|
}
|
|
|
|
/*glDisable(GL_TEXTURE_2D);
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPopMatrix();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPopMatrix();*/
|
|
|
|
restoreRenderState();
|
|
|
|
inBeginEndPair = false;
|
|
}
|
|
|
|
void SpriteBatch::restoreRenderState()
|
|
{
|
|
if (saveStateMode == SaveStateMode::SaveState)
|
|
saveState.Apply();
|
|
}
|
|
|
|
void SpriteBatch::applyGraphicsDeviceSettings()
|
|
{
|
|
unsigned int* p;
|
|
|
|
// Set the blend mode
|
|
switch (spriteBlendMode)
|
|
{
|
|
case SpriteBlendMode::AlphaBlend:
|
|
p = pb_begin();
|
|
//Enable blending
|
|
pb_push(p, NV20_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1); p+=2;
|
|
//set blendmode
|
|
pb_push2(p, NV20_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC, (0x302<<16) | 0x302, (0x303<<16) | 0x303); p+=3;
|
|
//send data to GPU
|
|
pb_end(p);
|
|
break;
|
|
case SpriteBlendMode::Additive:
|
|
p = pb_begin();
|
|
//Enable blending
|
|
pb_push(p, NV20_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1); p+=2;
|
|
//set blendmode
|
|
pb_push2(p, NV20_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC, (0x302<<16) | 0x302, (1<<16) | 1); p+=3;
|
|
//send data to GPU
|
|
pb_end(p);
|
|
break;
|
|
case SpriteBlendMode::None:
|
|
p = pb_begin();
|
|
//Disable Blending
|
|
pb_push(p, NV20_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 0); p+=2;
|
|
//send data to GPU
|
|
pb_end(p);
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
//glEnable(GL_TEXTURE_2D);
|
|
|
|
// Reset the projection matrix and use the orthographic matrix
|
|
/*int viewPort[4];
|
|
glGetIntegerv(GL_VIEWPORT, viewPort);
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
glOrtho(0, device.Viewport_().Width, device.Viewport_().Height, 0, -1, 1); // viewPort[2] = width, viewPort[3] = height
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
glLoadIdentity();*/
|
|
}
|
|
|
|
void SpriteBatch::Flush()
|
|
{
|
|
switch (spriteSortMode)
|
|
{
|
|
case SpriteSortMode::BackToFront:
|
|
//SpriteList.Sort(BackToFrontSpriteComparer<Sprite>());
|
|
break;
|
|
case SpriteSortMode::FrontToBack:
|
|
//SpriteList.Sort(FrontToBackSpriteComparer<Sprite>());
|
|
break;
|
|
case SpriteSortMode::Texture: // nothing here?
|
|
break;
|
|
}
|
|
for (int i = 0; i < SpriteList.Count(); i++)
|
|
{
|
|
// Set the color, bind the texture for drawing and prepare the texture source
|
|
if (SpriteList[i].Color_().A() <= 0) continue;
|
|
//glColor4f((float)sprite.Color_().R() / 255f, (float)sprite.Color_().G() / 255f, (float)sprite.Color_().B() / 255f, (float)sprite.Color_().A() / 255f);
|
|
//glBindTexture(GL_TEXTURE_2D, sprite.Texture->textureId);
|
|
// Setup the matrix
|
|
//if ((SpriteList[i].DestinationRectangle().X != 0) || (SpriteList[i].DestinationRectangle().Y != 0))
|
|
// glTranslatef(SpriteList[i].DestinationRectangle().X, SpriteList[i].DestinationRectangle().Y, 0.0f); // Position
|
|
|
|
//if (SpriteList[i].Rotation() != 0)
|
|
// glRotatef(MathHelper::ToDegrees(SpriteList[i].Rotation()), 0.0f, 0.0f, 1.0f); // Rotation
|
|
|
|
/*if ((SpriteList[i].DestinationRectangle().Width != 0 && SpriteList[i].Origin().X != 0) || (SpriteList[i].DestinationRectangle().Height != 0 && SpriteList[i].Origin().Y != 0))
|
|
glTranslatef(
|
|
// Orientation
|
|
-SpriteList[i].Origin.X * (float)SpriteList[i].DestinationRectangle().Width / (float)SpriteList[i].SourceRectangle().Width,
|
|
-SpriteList[i].Origin.Y * (float)SpriteList[i].DestinationRectangle().Height / (float)SpriteList[i].SourceRectangle().Height, 0.0f);*/
|
|
// Calculate the points on the texture
|
|
float x = (float)SpriteList[i].SourceRectangle().X / (float)SpriteList[i].Texture().Width();
|
|
float y = (float)SpriteList[i].SourceRectangle().Y / (float)SpriteList[i].Texture().Height();
|
|
float twidth = (float)SpriteList[i].SourceRectangle().Width / (float)SpriteList[i].Texture().Width();
|
|
float theight = (float)SpriteList[i].SourceRectangle().Height / (float)SpriteList[i].Texture().Height();
|
|
// Draw
|
|
/*glBegin(GL_QUADS);
|
|
{
|
|
glTexCoord2f(x,y + theight);
|
|
glVertex2f(0f, SpriteList[i].DestinationRectangle().Height);
|
|
glTexCoord2f(x + twidth, y + theight);
|
|
glVertex2f(SpriteList[i].DestinationRectangle().Width, SpriteList[i].DestinationRectangle().Height);
|
|
glTexCoord2f(x + twidth,y);
|
|
glVertex2f(SpriteList[i].DestinationRectangle().Width, 0f);
|
|
glTexCoord2f(x,y);
|
|
glVertex2f(0f, 0f);
|
|
}
|
|
glEnd();
|
|
glPopMatrix(); // Finish with the matrix*/
|
|
}
|
|
SpriteList.Clear();
|
|
}
|
|
}
|
|
}
|