#include "ElementRendererHeaders.hpp"

HGOSHEAP
	ElementRenderer::g_LibraryHeap = NULL,
	ElementRenderer::g_Heap = NULL;

DEFINE_TIMER(ElementRenderer, Total_Video);
DEFINE_TIMER(ElementRenderer, Graph_Traversal);
DEFINE_TIMER(ElementRenderer, Draw_Shapes);
DEFINE_TIMER(ElementRenderer, Draw_Scalable);
DEFINE_TIMER(ElementRenderer, Draw_Effects);
DEFINE_TIMER(ElementRenderer, Draw_Quads);
DEFINE_TIMER(ElementRenderer, Setup_Sky);
DEFINE_TIMER(ElementRenderer, Render);

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ElementRenderer::InitializeClasses(Stuff::NotationFile *startup_ini)
{
	Verify(FirstFreeElementRendererClassID <= Stuff::LastElementRendererClassID);

	Verify(!g_LibraryHeap);
	g_LibraryHeap = gos_CreateMemoryHeap("ElementRenderer(All)");
	Check_Pointer(g_LibraryHeap);
	
	Verify(!g_Heap);
	g_Heap = gos_CreateMemoryHeap("ElementRenderer", 0, g_LibraryHeap);
	Check_Pointer(g_Heap);
	gos_PushCurrentHeap(g_Heap);

#if !(defined(NO_STATS) && defined(NO_TIMERS))
	StatisticFormat("");
	StatisticFormat("Element Renderer");
	StatisticFormat("================");
	StatisticFormat("");
#endif

	Element::InitializeClass();
	GroupElement::InitializeClass();
	CameraElement::InitializeClass(startup_ini);
	ShapeElement::InitializeClass(startup_ini);
	ListElement::InitializeClass();
	SwitchElement::InitializeClass();
	LODElement::InitializeClass(startup_ini);
	PointCloudElement::InitializeClass();
	TriangleCloudElement::InitializeClass();
	ScalableShapeElement::InitializeClass();
	ScreenQuadsElement::InitializeClass();
	gosFXElement::InitializeClass();

	StateChange::InitializeClass();

	GridElement::InitializeClass();
	LineCloudElement::InitializeClass();
	LightElement::InitializeClass();
	MultiLODElement::InitializeClass();
	ShapeLODElement::InitializeClass();
	TreeElement::InitializeClass();

	gos_PopCurrentHeap();

	//
	//---------------
	// Setup the menu
	//---------------
	//
	Initialize_Timer(Total_Video, "Total Video");
	Initialize_Timer(Setup_Sky, "  Setup and Sky");
	Initialize_Timer(Graph_Traversal, "  Culling");
	Initialize_Timer(Draw_Shapes, "    Draw Shapes");
	Initialize_Timer(Draw_Scalable, "    Draw Scaling Shapes");
	Initialize_Timer(Draw_Effects, "    Draw MLR Effects");
	Initialize_Timer(Draw_Quads, "    Draw Screen Quads");
	Initialize_Timer(Render, "  Render to MLR");
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ElementRenderer::TerminateClasses(Stuff::NotationFile *startup_ini)
{
	TreeElement::TerminateClass();
	ShapeLODElement::TerminateClass();
	MultiLODElement::TerminateClass();
	LightElement::TerminateClass();
	LineCloudElement::TerminateClass();

	GridElement::TerminateClass();

	StateChange::TerminateClass();

	gosFXElement::TerminateClass();
	ScreenQuadsElement::TerminateClass();
	ScalableShapeElement::TerminateClass();
	TriangleCloudElement::TerminateClass();
	PointCloudElement::TerminateClass();
	LODElement::TerminateClass(startup_ini);
	SwitchElement::TerminateClass();
	ListElement::TerminateClass();
	ShapeElement::TerminateClass(startup_ini);
	CameraElement::TerminateClass(startup_ini);
	GroupElement::TerminateClass();
	Element::TerminateClass();

	Check_Pointer(g_Heap);
	gos_DestroyMemoryHeap(g_Heap);
	g_Heap = NULL;

	Check_Pointer(g_LibraryHeap);
	gos_DestroyMemoryHeap(g_LibraryHeap);
	g_LibraryHeap = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	ElementRenderer::ReadERFVersion(Stuff::MemoryStream *erf_stream)
{
	Check_Object(erf_stream);

	//
	//------------------------------------------------------------------------
	// See if this file has an erf signature.  If so, the next int will be the
	// version number.  If not, assume it is version 1 and rewind the file
	//------------------------------------------------------------------------
	//
	int version = 1;
	int erf_signature;
	*erf_stream >> erf_signature;
	if (erf_signature == 'ERF#')
		*erf_stream >> version;
	else
		erf_stream->RewindPointer(sizeof(erf_signature));
	if (version > CurrentERFVersion)
		STOP(("Application must be rebuilt to use this version of ERF data"));
	return version;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ElementRenderer::WriteERFVersion(Stuff::MemoryStream *erf_stream)
{
	Check_Object(erf_stream);
	*erf_stream << 'ERF#' << static_cast<int>(CurrentERFVersion);
}
