/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


		#include "ui/ui.h"
		#include "ui/ui_camera.h"
		#include "ui/ui_sprite.h"
		#include "core/renderer.h"
		#include "gpu/gpu_triangle_batch.h"

		using namespace GS;
		using namespace S2D;


//------------------------------------------------------------------------------
static	float		ItemCompareDrawOrder(const S2D::Item *c, const S2D::Item *n)
{	return -(c->GetZOrder() - n->GetZOrder());	}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
void				Scene::SetRenderMatrices(Renderer &renderer)
{
	const Vector2 &resolution = current_camera->resolution;
	float k_ar = (renderer.GetOutputAspectRatio() * renderer.GetGlobalAspectRatio()) / (resolution.y / resolution.x);

	// UI to normalized screen and back.
	ui_to_screen =	Matrix3::TranslationMatrix(Vector2(0.5f, 0.5f)) *
					(
						(offset_matrix * Matrix3::ScaleMatrix(Vector2(k_ar / resolution.x, 1.f / resolution.y))) *
						(Matrix3::TranslationMatrix(Vector2(-resolution.x * 0.5f, -resolution.y * 0.5f)) * current_camera->GetInverseMatrix())
					);
	ui_to_screen.Inverse(screen_to_ui);

	// Render matrices.
	Matrix4 identity(Matrix4::IdentityMatrix());
	renderer.SetViewMatrix(identity, &identity);
	renderer.SetWorldMatrix(identity, &identity);

	Matrix3 projection(2.f * k_ar / resolution.x, 0, 0, 0, -2.f / resolution.y, 0, -1.f * k_ar, 1.f, 0.0f);	// z = 0.0f
	projection = offset_matrix * (projection * current_camera->GetInverseMatrix());
	renderer.SetProjectionMatrix(Matrix4::FromMatrix3(projection));
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
void				Scene::Render(Renderer &renderer, GPU::TriangleBatch *batch)
{
	// Enforce window positioning.
	item_list.MergeSort(ItemCompareDrawOrder);

	// Render items.
	SetRenderMatrices(renderer);
	ListForeachPtr(Item *, i, item_list)
		if	(i->item_flags.IsSet(Item::Flag_ItemActive))
			switch (i->GetItemType())
			{
				case Item::Type_Sprite:
				case Item::Type_Window:
					((Sprite *)i)->Render(renderer, batch);
					break;
			}

	if	(batch)
		batch->Flush();
}
void				Scene::RenderGlobalFade(Renderer &renderer)
{
	if	(global_fade_color.w < 0.01f)
		return;

	renderer.SetProjectionMatrix(Matrix4::IdentityMatrix());

	// Setup attributes.
	Vector4 vtx_attr[4];
	vtx_attr[0].Set(-1, -1, 1);
	vtx_attr[1].Set(1, -1, 1);
	vtx_attr[2].Set(1, 1, 1);
	vtx_attr[3].Set(-1, 1, 1);

	Color color_attr[4];
	for	(uint n = 0; n < 4; ++n)
		color_attr[n] = global_fade_color;

	ushort idx[6] = { 2, 1, 0, 3, 2, 0 };
	renderer.DrawTriangle(2, vtx_attr, idx, color_attr, NULL, NULL, Core::Material::Blend_Alpha, Core::Material::Render_NoZTest);
}
//------------------------------------------------------------------------------
