//*******************************************************************
//
// File: Asura_Platform_Botanicals_InstanceManager.cpp
//
// Created: 14 Mar 2006
//
// Description: 
//
//*******************************************************************

// system libraries
#include "Core/Asura.h"

#if defined( ASURA_USE_BOTANICALS)

// main header
#include "Botanicals/Asura_Botanicals_TemplateManager.h"
#include "Botanicals/Asura_Botanicals_InstanceManager.h"
#include "Botanical/Asura_Direct3D_Botanicals_Game_Render.h"

#include "Rendering/Asura_Module.h"

#if defined( ASURA_TOOLS)
#include "Tools_System.h"

#include "Botanicals/Tools_Botanicals_Statistics.h"
#include "Camera/Asura_Camera.h"
#include "Core/Asura_UserInput.h"
#include "Core/Asura_Timers.h"
#include "Debugging/Asura_Profiling_System.h"
#include "Misc/Tools_Render_Options.h"

#endif


// other libraries

// internal dependencies

//*******************************************************************
// Constants
//*******************************************************************


//*******************************************************************
// Local Classes
//*******************************************************************

//*******************************************************************
// Local Data
//*******************************************************************

//*******************************************************************
// Function Definitions
//*******************************************************************

void Asura_Botanicals_InstanceManager::Platform_Initialise()
{
	// JAT 11/04/06 - placeholder to be filled in by Duncan
	Reset();
}

void Asura_Botanicals_InstanceManager::Platform_Shutdown()
{
	Asura_Direct3D_Botanicals_Game_Render::ClearDataSet();
	
	Reset();
}

void Asura_Botanicals_InstanceManager::Platform_Reset()
{
	Asura_Direct3D_Botanicals_Game_Render::ClearDataSet();
}

void Asura_Botanicals_InstanceManager::Platform_Render( const float fGlobalFade )
{
#if !defined( ASURA_TOOLS )
	if( Asura_Direct3D_Botanicals_Game_Render::HasDataSet())
	{
		Asura_Direct3D_Botanicals_Game_Render::Render();
	}
#else

	// If we're in botanicals mode, bail out now, as we don't need to render this list
	int eToolsMode = Tools_System::GetCurrentMode();
#if !defined( ASURA_BOTANICALS_BGR_IN_EDIT)
	if( eToolsMode == TOOLS_MODE_BOTANICALS)
	{
		return;
	}
#endif

	// DLH - Create the BGR Data Set if it does not exist
	switch( eToolsMode)
	{
		case TOOLS_MODE_BOTANICALS:
		case TOOLS_MODE_BOTANICALCREATION:
		{
			break;
		}
		default:
		{
			if( false == Asura_Direct3D_Botanicals_Game_Render::HasDataSet())
			{
				Asura_LinkList< Asura_Botanicals_Instance*>& xListBotanicalInstances = Asura_Botanicals_InstanceManager::GetInstanceList();
				
				if( NULL != xListBotanicalInstances.Front())
				{
					Asura_Direct3D_Botanicals_Game_Render::MakeDataSet( xListBotanicalInstances);
				}
			}
			break;
		}
	}

	TOOLS_BOTANICAL_STATISTICS_RESET();
	
#if defined( ASURA_BOTANICAL_INSTANCEMANAGER_PROFILE)	
//	const char* pszProfileName = "";
	int iOverallTimer	= Asura_Profiling_CreateTimer();

	Asura_Profiling_StartTiming( iOverallTimer );
#endif //  #if defined( ASURA_BOTANICAL_INSTANCEMANAGER_PROFILE)	
	
	if( Asura_Direct3D_Botanicals_Game_Render::HasDataSet())
	{
		Asura_Direct3D_Botanicals_Game_Render::Render();
	}
	else
	{
		// Support a distance cut-off
		bool  bLimitedRange=Tools_Render_Options::IsBotanicalsRangeLimited();
		float fVisibleDistanceSquared=Tools_Render_Options::GetBotanicalsRange();
		
		fVisibleDistanceSquared = fVisibleDistanceSquared*fVisibleDistanceSquared;

		Asura_Vector_3 xCamPos = *Asura_Camera::GetPosition();
		for (Asura_ListElt<Asura_Botanicals_Instance*> *pxElt = s_xInstanceList.Front();
			pxElt; pxElt = pxElt->Next())
		{
			Asura_Botanicals_Instance*	pxInst		= pxElt->Data();
#if defined(ASURA_USE_NEW_VISIBILITY_SYSTEM)
			const Asura_Bounding_Box&	xBB			= pxInst->pxShapeInstance->GetBB();
			bool						bVisible	= pxInst->m_xVisibilityQuery.IsAABBVisibleFromCurrentCamera(xBB);
#else
			bool						bVisible	= (pxInst->iModuleIdx>=0 && Asura_Module_System::IsModuleVisible(pxInst->iModuleIdx));
#endif	//defined(ASURA_USE_NEW_VISIBILITY_SYSTEM)

			if(bVisible)
			{					
				Asura_Botanicals_Template *pxTmp=Asura_Botanicals_TemplateManager::GetTemplate(pxInst->iTemplateIdx);

				if (bLimitedRange)
				{
					if ((pxInst->xPosition - xCamPos).MagnitudeSquared() > fVisibleDistanceSquared)
					{
						bVisible=false;
					}
				}
				//If merged into environment , then we won't want to render it here
				//(Putting it in tools define , since outside of tools I'm not bothering creating
				//instances for these)
				//RAR 17/03/2006
				if(pxInst->uFlags & ASURA_BOTANICAL_FLAG_RENDERMESHMERGED)
				{
					bVisible = false;
				}
				if (pxInst && pxTmp && bVisible)
				{
					if (pxTmp->eType==ASURA_BOTANICALS_TEMPLATE_SHAPE)
					{
						if (pxTmp->uShapeID!=ASURA_HASH_ID_UNSET)
						{		
							// Slightly less crappy rendering - it caches the ShapeInstances now, instead of
							// creating/deleting every frame...

							if (!pxInst->pxShapeInstance)
							{					
								Asura_Shape_Instance *pxShapeInstance = new Asura_Shape_Instance(pxTmp->uShapeID);
								pxShapeInstance->AddFlags(ASURA_SHAPE_INSTANCE_NO_SHADOW);

								Asura_Matrix_3x3 OrientationAndScale;
								OrientationAndScale.Identity();			
								OrientationAndScale[0][0]=pxInst->fScale;
								OrientationAndScale[1][1]=pxInst->fScale;
								OrientationAndScale[2][2]=pxInst->fScale;
								OrientationAndScale=pxInst->xOrientation*OrientationAndScale;

								pxShapeInstance->SetNewPosAndOri(pxInst->xPosition,OrientationAndScale);

								pxInst->pxShapeInstance=pxShapeInstance;
							}

							pxInst->pxShapeInstance->Render();					
							#if defined( ASURA_BOTANICAL_INSTANCEMANAGER_PROFILE)	
								TOOLS_BOTANICAL_STATISTICS_ADD( s_uInstanceCount, 1);
							#endif
						}
					}
					// We only have tools rendering code for these at the moment
					if (pxTmp->eType==ASURA_BOTANICALS_TEMPLATE_BOTANICALSHAPE)
					{
						if (pxTmp->pxBotanicalShape)
						{
							Tools_BotanicalShape *pxToolsShape=pxTmp->pxBotanicalShape->GetToolsShape();

							if (pxToolsShape)
							{
								pxToolsShape->Render(&pxInst->xPosition,&pxInst->xOrientation,pxInst->fScale);							
								#if defined( ASURA_BOTANICAL_INSTANCEMANAGER_PROFILE)	
									TOOLS_BOTANICAL_STATISTICS_ADD( s_uInstanceCount, 1);
								#endif
							}
						}				
					}	
				}
			}
		}
	}
#if defined( ASURA_BOTANICAL_INSTANCEMANAGER_PROFILE)	
	{
		const float fOverallTime = Asura_Timers::TicksToSeconds( Asura_Profiling_StopTiming( iOverallTimer ) );

		TOOLS_BOTANICAL_STATISTICS_SET( s_fTime, fOverallTime);
		
		Asura_Profiling_DestroyTimer(iOverallTimer);
	}
#endif // #if defined( ASURA_BOTANICAL_INSTANCEMANAGER_PROFILE)	

#endif // #if !defined( ASURA_TOOLS )
}

#endif //defined( ASURA_USE_BOTANICALS)

//*******************************************************************
//
// (c) 2006 Rebellion (Derby)
//
// Warning: This computer program is protected by copyright law and 
// international treaties. Unauthorized reproduction or distribution
// of this program, or any portion of it, may result in severe civil and
// criminal penalties, and will be prosecuted to the maximum extent 
// possible under the law.
//
//*******************************************************************

