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


		#include "project/project.h"
		#include "scene3d/scene.h"
		#include "ui/ui.h"
		#include "core/renderer.h"
		#include "script/script_engine_types.h"
		#include "script/script_variant.h"

		using namespace GS::Core;
		using namespace GS::Script;


static float CompareLayerZOrder(const ProjectLayer *c, const ProjectLayer *n) { return c->zorder - n->zorder; }

//------------------------------------------------------------------------------
void				Project::Render(Renderer &renderer, RenderFlag render_flag)
{
	__PROJECT_ACTION_SAFETY_CHECK_RAW

	bool send_events = render_flag & FlagDisableScript ? false : true;

	// Sort the layer list.
	layer_list.Sort(CompareLayerZOrder);

	// OnRender callback.
	if	(script_unit->SetupFunctionCall("OnRender"))
		script_unit->DoFunctionCall();

	// Render the layer display list.
	int active_layer = 0;

	ListForeachPtr(ProjectLayer *, layer, layer_list)
		if	(layer->inst && IsActive(*layer->inst))
		{
			// OnRenderScene callback.
			if	(send_events && script_unit->SetupFunctionCall("OnRenderScene"))
			{
				switch (layer->inst->GetType())
				{
					case ProjectSceneInstance::Type_Scene2d:
						script_unit->PushFunctionCallArgument(Script::Variant(layer->inst->instance, typetag_Scene2d));
						break;

					case ProjectSceneInstance::Type_Scene3d:
						script_unit->PushFunctionCallArgument(Script::Variant(layer->inst->instance, typetag_Scene3d));
						break;
				}
				script_unit->PushFunctionCallArgument(Script::Variant(layer, typetag_ProjectLayer));
				script_unit->DoFunctionCall();
			}

			// Specialized rendering.
			prohibit_project_action = true;

			switch (layer->inst->GetType())
			{
				case ProjectSceneInstance::Type_Scene2d:
				{
					GS::S2D::Scene *scene = layer->inst->instance_2d;

					if	(active_layer == 0)
						renderer.Clear(0, 0, 0);
					scene->Render(renderer);
				}
				break;

				case ProjectSceneInstance::Type_Scene3d:
				{
					GS::S3D::Scene *scene = layer->inst->instance_3d;

					scene->flags.Raise(S3D::Scene::FlagDebugPhysics, flags.IsSet(ProjectFlagDebugPhysics));	// synchronize scene flag with project one
					scene->Render(renderer);
					scene->RenderUI(renderer);
				}
				break;
			}
			prohibit_project_action = false;

			++active_layer;
		}
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
void				Project::Update(uint eval_flag)
{
	__PROJECT_ACTION_SAFETY_CHECK_RAW

	// OnUpdate callback.
	if	(script_unit->SetupFunctionCall("OnUpdate", script_unit->update_callback))
		script_unit->DoFunctionCall();

	// Evaluate all instantiated scenes.
	prohibit_project_action = true;

	ListForeachPtr(ProjectSceneInstance *, inst, instance_list)
		if	(IsActive(*inst))
			switch (inst->GetType())
			{
				case ProjectSceneInstance::Type_Scene2d:
					if	(inst->instance_2d)
						inst->instance_2d->Update();
					break;

				case ProjectSceneInstance::Type_Scene3d:
					if	(inst->instance_3d)
					{
						inst->instance_3d->SetAsScriptGlobalScene();
						inst->instance_3d->Update(eval_flag);
					}
					break;
			}

	prohibit_project_action = false;
}
//------------------------------------------------------------------------------
