114 lines
3.1 KiB
C++
114 lines
3.1 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#include "ui/ui_sprite.h"
|
|
#include "gpu/gpu_triangle_batch.h"
|
|
#include "core/renderer.h"
|
|
|
|
using namespace GS::Render;
|
|
using namespace GS::S2D;
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void Sprite::Render(Renderer &render, GS::GPU::TriangleBatch *batch)
|
|
{
|
|
if (render_data.IsNull())
|
|
return;
|
|
if (opacity < 0.003f)
|
|
return;
|
|
|
|
ComputeMatrix();
|
|
|
|
// Test visibility.
|
|
bool should_show = true;
|
|
|
|
float final_opacity = opacity;
|
|
for (Item *p = GetParent(); p; p = p->GetParent())
|
|
if (Sprite *sp = (Sprite *)p)
|
|
final_opacity *= sp->opacity;
|
|
|
|
if (final_opacity < 0.003f)
|
|
should_show = false;
|
|
|
|
// Compute hierarchy matrix, opacity and visibility.
|
|
if (sprite_flags.IsSet(FlagSnapToPixel))
|
|
{
|
|
matrix.m[0][2] = Math::Floor(matrix.m[0][2]);
|
|
matrix.m[1][2] = Math::Floor(matrix.m[1][2]);
|
|
}
|
|
|
|
if (!should_show) // [EJ] do not move before matrix is updated
|
|
return;
|
|
|
|
Texture *t = render_data->texture;
|
|
if (t && t->format != Texture::FormatInvalid)
|
|
{
|
|
Vector4 vtx[4];
|
|
vtx[0].Set(0, 0, 1);
|
|
vtx[1].Set(size.x, 0, 1);
|
|
vtx[2].Set(size.x, size.y, 1);
|
|
vtx[3].Set(0, size.y, 1);
|
|
|
|
Vector4 vtx_attr[4];
|
|
matrix.Apply(vtx_attr, vtx, 4); // transform on the CPU for the batch system
|
|
|
|
Color color_attr[4];
|
|
for (uint n = 0; n < 4; ++n)
|
|
color_attr[n].Set(1, 1, 1, final_opacity);
|
|
|
|
Vector2 uv_attr[4];
|
|
|
|
float su = uv_origin.x / float(t->GetWidth()),
|
|
sv = uv_origin.y / float(t->GetHeight()),
|
|
eu = (uv_origin.x + size.x) / float(t->GetWidth()),
|
|
ev = (uv_origin.y + size.y) / float(t->GetHeight());
|
|
|
|
if (sprite_flags.IsSet(FlagFlipU)) Types::swap(su, eu);
|
|
if (sprite_flags.IsSet(FlagFlipV)) Types::swap(sv, ev);
|
|
|
|
if (sprite_flags.IsSet(FlagTransformUV))
|
|
{
|
|
Vector4 s_uv[4], o_uv[4];
|
|
|
|
s_uv[0].Set(su, sv, 1);
|
|
s_uv[1].Set(eu, sv, 1);
|
|
s_uv[2].Set(eu, ev, 1);
|
|
s_uv[3].Set(su, ev, 1);
|
|
|
|
uv_matrix.Apply(o_uv, s_uv, 4);
|
|
for (int n = 0; n < 4; ++n)
|
|
uv_attr[n].Set(o_uv[n].x, o_uv[n].y);
|
|
}
|
|
else
|
|
{
|
|
uv_attr[0].Set(su, sv);
|
|
uv_attr[1].Set(eu, sv);
|
|
uv_attr[2].Set(eu, ev);
|
|
uv_attr[3].Set(su, ev);
|
|
}
|
|
|
|
// Blend mode.
|
|
using Core::Material;
|
|
|
|
Material::BlendOperator blend_op;
|
|
|
|
if (sprite_flags.IsSet(FlagBlendOpaque))
|
|
blend_op = final_opacity < 1.f ? Material::Blend_Alpha : Material::Blend_None;
|
|
else blend_op = sprite_flags.IsSet(FlagBlendAdditive) ? Material::Blend_Add : Material::Blend_Alpha;
|
|
|
|
Material::RenderWord render_word = Material::RenderWord(Material::Render_NoZWrite | Material::Render_NoZTest);
|
|
|
|
// Draw.
|
|
ushort idx[6] = { 0, 1, 2, 0, 2, 3 };
|
|
|
|
if (batch)
|
|
batch->DrawTriangle(2, 4, vtx_attr, idx, color_attr, uv_attr, render_data->texture, blend_op, render_word);
|
|
else
|
|
render.DrawTriangle(2, vtx_attr, idx, color_attr, uv_attr, render_data->texture, blend_op, render_word);
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|