/* ----------------------------------------------------------------------------- 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); } } //------------------------------------------------------------------------------