//
// Tools_Entity_EffectVolume.cpp
//
// Created by Emil Popovic - 12/12/2008
// 
// Copyright (C) 2008 Rebellion, All Rights Reserved.
//


// core
#include "Core/Asura.h"

// header
#include "Entity/EffectVolume/Tools_Entity_EffectVolume.h"

// asura
#include "Core/Asura_UserInput.h"
#include "Entity/Triggers/EffectVolume/Asura_ServerEntity_EffectVolume.h"
#include "Independent/Volume/Asura_Volume_Cuboid.h"
#include "Independent/Volume/Asura_Volume_Sphere.h"
#include "Independent/Volume/Asura_Volume_Cylinder.h"
#include "Mesh/Asura_Mesh_System.h"

// tools
#include "Tools_System.h"
#include "Load&Save/Tools_SaveAsura.h"
#include "Entity/EffectVolume/Tools_EffectVolume_FogOverlay.h"
#include "Entity/EffectVolume/Tools_EffectVolume_FSFXOverlay.h"
#include "Misc/Tools_Render_Options.h"
#include "FSFX/Asura_FSFX_Template.h"
#include "FSFX/Tools_Mode_FSFX.h"


#include "Objects/Tools_VolumeGroupEdit_Controller.h"


const char* Tools_Entity_EffectVolume::s_aszEffectVolumeTypeNames[NUM_EFFECT_VOLUME_EFFECT_TYPES] = 
{
	"Fog Effect Volume",		//EFFECT_VOLUME_EFFECT_FOG
	"FSFX Specific Animation",	//EFFECT_VOLUME_EFFECT_FSFX
};


// Static functions ----------------------------------------------------

bool						Tools_Entity_EffectVolume::s_bMoveVolumeWithObject	= true;
bool						Tools_Entity_EffectVolume::s_bShowAllVolumes		= false;
bool						Tools_Entity_EffectVolume::s_bShowSelectedVolume	= false;
bool						Tools_Entity_EffectVolume::s_bShowAllTransitionVolumes = false;
bool						Tools_Entity_EffectVolume::s_bShowSelectedTransitionVolume = false;
Tools_Entity_EffectVolume*	Tools_Entity_EffectVolume::s_pxSelectedEffectVolume	= NULL;
Tools_Entity_EffectVolume*	Tools_Entity_EffectVolume::s_pxLastSelected			= NULL;
bool						Tools_Entity_EffectVolume::s_bPreviewSelected		= false;
bool						Tools_Entity_EffectVolume::s_bPreviewAll			= false;


Tools_Entity_EffectVolume::Tools_Entity_EffectVolume(Asura_Entity* pxEntity)
:PARENT(pxEntity)
{
	m_pxListDialog = NULL;
	m_iInputListSize = 0;
	m_pszInputList = 0;
	m_iInputSelection = 0;

	m_pxVolumeController = 0;
	m_pxTransitionVolumeController = 0;
	m_xPreviousPosition = Position;
	m_xPreviousOrientation = Orientation;

	s_pxSelectedEffectVolume = this;

	Type = TOT_Entity_EffectVolume;
	Mesh = Asura_Mesh_System::GetMesh("ToolsShape_GamePlayVolume");

	// Reset initial states for global bools.
	s_bPreviewSelected		= false;
	s_bPreviewAll			= false;
	s_bMoveVolumeWithObject	= true;
	s_bShowAllVolumes		= false;
	s_bShowSelectedVolume	= false;
	s_bShowAllTransitionVolumes = false;
	s_bShowSelectedTransitionVolume = false;
}

Tools_Entity_EffectVolume::~Tools_Entity_EffectVolume()
{
	if( m_pxVolumeController )
	{
		delete m_pxVolumeController;
		m_pxVolumeController = NULL;
	}

	if( m_pxTransitionVolumeController )
	{
		delete m_pxTransitionVolumeController;
		m_pxTransitionVolumeController = NULL;
	}

	DeleteInputList();
}

void Tools_Entity_EffectVolume::Create()
{
	Tools_Object* pxObject = Create(false);
	Tools_Object_System::SelectObject(pxObject);
}

Tools_Entity_EffectVolume* Tools_Entity_EffectVolume::Create( bool bGenerateName )
{
	//get a name , and the position data
	Asura_Guid uGuid = Asura_Entity_System::GetNextToolsCreatedGuid();
	Tools_Entity_Data* pxToolsData = 0;

	if(bGenerateName)
	{
		pxToolsData = PARENT::CreateToolsDataWithDefaultName("Effect Volume","Effect Volume",uGuid,GetNamePrefix());
	}
	else
	{
		pxToolsData = PARENT::CreateToolsData("Effect Volume",0,GetNamePrefix());
	}

	if(!pxToolsData) return NULL;


	//create the asura data
	Asura_ServerEntity_EffectVolume* pxAsuraEntity = new Asura_ServerEntity_EffectVolume( uGuid );
	Asura_Entity_System::RegisterToolsGuid(uGuid);

	pxAsuraEntity->ToolsData = pxToolsData;

	//create the tools object
	Tools_Entity_EffectVolume* pxToolsEntityObject = new Tools_Entity_EffectVolume(pxAsuraEntity);

	Tools_SaveAsura::SetEntityModified();

	return pxToolsEntityObject;
}

Tools_Object* Tools_Entity_EffectVolume::CreateObjectOfThisType() const
{
	return Create(true);
}

void Tools_Entity_EffectVolume::Copy(const Tools_Object* pxObject)
{
	PARENT::Copy(pxObject);

	const Tools_Entity_EffectVolume* pxFromObject = (const Tools_Entity_EffectVolume*) pxObject;

	Asura_ServerEntity_EffectVolume* pxFromEntity = (Asura_ServerEntity_EffectVolume*) pxFromObject->Entity;
	Asura_ServerEntity_EffectVolume* pxToEntity = (Asura_ServerEntity_EffectVolume*) Entity;

	//delete the volume controller if it exists ,since we will be replacing the volumes. (NOTE:EP.19.01.2009. I copy this if statement from other parts of code, but I am not sure why exactly it needs to be here. But yeah, I am keeping consistency. :-)
	if( m_pxVolumeController )
	{
		delete m_pxVolumeController;
		m_pxVolumeController = 0;
	}

	if( m_pxTransitionVolumeController )
	{
		delete m_pxTransitionVolumeController;
		m_pxTransitionVolumeController = 0;
	}

	// Copy content of m_xData
	Asura_EffectVolume_EntityParameters::Tools_Copy( pxToEntity->m_xData, pxFromEntity->m_xData );


	// Make sure we will also move the VolumeEffect.
	if (s_bMoveVolumeWithObject)
	{
		Asura_Vector_3 xDisplace = Position - pxObject->Position;

		pxToEntity->GetData().GetVolume()->DisplaceVolumes(xDisplace);
		pxToEntity->GetData().GetTransitionVolume()->DisplaceVolumes(xDisplace);
	}

	Tools_SaveAsura::SetEntityModified();
}

void Tools_Entity_EffectVolume::OnSelection()
{
	s_pxSelectedEffectVolume = this;

	PARENT::OnSelection();
}

void Tools_Entity_EffectVolume::OnDeselection()
{
	PARENT::OnDeselection();

	s_pxSelectedEffectVolume = NULL;
}

// Make sure that all files that are associated with this EffectVolume are exported to final batch file.
void Tools_Entity_EffectVolume::AddFilesToExportList(List<Asura_String>& xNameList) const
{
#if defined(ASURA_USE_FSFX)
	Asura_ServerEntity_EffectVolume* pxEffectVolume = (Asura_ServerEntity_EffectVolume*) Entity;

	if( pxEffectVolume )
	{
		for( u_int u=0; u<pxEffectVolume->GetNumOfEffects(); u++ )
		{
			Asura_EffectVolume_Effect* pxEffect = pxEffectVolume->GetEffect(u);
			
			// For the moment, add only FSFX files to export.
			if( pxEffect->GetEffectTypeHash()==uEFFECTVOLUME_EFFECT_FSFX )
			{
				Asura_EffectVolume_Effect_FSFX* pxFSFX = static_cast<Asura_EffectVolume_Effect_FSFX*>(pxEffect);

				Asura_Hash_ID uFSFXHash = pxFSFX->GetParameters().GetTemplateHash();

				const Asura_FSFX_Template* const pxTemplate = Asura_FSFX_System::FindTemplate( uFSFXHash );
				Asura_Assertf(pxTemplate, ("Failed to find FSFX template 0x%08x for effect volume %d. Has it been deleted?", uFSFXHash, m_uGuid));

				if (pxTemplate)
				{
					List< const Asura_FSFX_Template* const > xTemplateList;
					xTemplateList.add_entry( pxTemplate );

					Tools_Mode_FSFX::ExportTemplateList( &xNameList, xTemplateList );
				}
			}
		}
	}
#endif	//defined(ASURA_USE_FSFX)

	PARENT::AddFilesToExportList( xNameList );
}


void Tools_Entity_EffectVolume::AddOverlayControls(class Asura_Overlay* pxOverlay,class Asura_Vector_2& xOffset)
{
	PARENT::AddOverlayControls( pxOverlay, xOffset );

	s_pxLastSelected = this;

	Asura_Dialog* pxDialog;

	Asura_ServerEntity_EffectVolume* pxAsuraEntity = (Asura_ServerEntity_EffectVolume*) Entity;
	
	//----------------------------------------------------------

	pxDialog = new Asura_Numerical_Dialog( "Priority (10=Highest)", xOffset, &pxAsuraEntity->m_xData.m_uPriority, 1, 10, 1, "%d", &Changed  );
	pxDialog->SetHelpText( "Priority is used for sorting multiple FSFX" );
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::LargeSpacing();

	//----------------------------------------------------------

	pxDialog = new Asura_Numerical_Dialog( "Fade In Duration", xOffset, &pxAsuraEntity->m_xData.m_fFadeInDuration, 0.0f, 999.0f, 0.1f, "%3.1f", &Changed );
	pxDialog->SetHelpText( "Time is in seconds." );
	pxOverlay->AddDialog(pxDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Numerical_Dialog( "Fade Out Duration", xOffset, &pxAsuraEntity->m_xData.m_fFadeOutDuration, 0.0f, 999.0f, 0.1f, "%3.1f", &Changed );
	pxDialog->SetHelpText( "Time is in seconds." );
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	//----------------------------------------------------------

	pxDialog = new Asura_Function_Dialog("Edit Timer Volume",xOffset,EditVolume);
	pxDialog->SetHelpText("Edits the volume for this trigger. This Volume is based on time and it works together with 'Fade In Duration' and 'Fade Out Duration'.");
	pxOverlay->AddDialog(pxDialog);


	xOffset.x = pxDialog->m_xMaxCoord.x + 1.0f;
	pxDialog = new Asura_Tickbox_Dialog( "Show All", xOffset, &s_bShowAllVolumes);
	pxDialog->SetHelpText("Shows volumes for all (Time) volume triggers.");
	pxOverlay->AddDialog( pxDialog );
	xOffset.x =  1.0f;
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Tickbox_Dialog( "Show selected", xOffset, &s_bShowSelectedVolume);
	pxDialog->SetHelpText("Shows volume for last selected (Time) volume trigger.");
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::LargeSpacing();

	//----------------------------------------------------------

	pxDialog = new Asura_Function_Dialog("Edit Transition Volume",xOffset,EditTransitionVolume);
	pxDialog->SetHelpText("Edits the volume for this Transition trigger.");
	pxOverlay->AddDialog(pxDialog);

	xOffset.x = pxDialog->m_xMaxCoord.x + 1.0f;
	pxDialog = new Asura_Tickbox_Dialog( "Show All", xOffset, &s_bShowAllTransitionVolumes);
	pxDialog->SetHelpText("Shows volumes for all Transition volume triggers.");
	pxOverlay->AddDialog( pxDialog );
	xOffset.x =  1.0f;
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Tickbox_Dialog( "Show selected", xOffset, &s_bShowSelectedTransitionVolume);
	pxDialog->SetHelpText("Shows volume for last selected Transition volume trigger.");
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::LargeSpacing();

	//----------------------------------------------------------

	pxDialog = new Asura_Tickbox_Dialog( "Move Volumes With Object", xOffset, &s_bMoveVolumeWithObject, &Changed );
	pxDialog->SetHelpText("The volume attached to this trigger should be moved when the trigger's tools object is moved.\nThis is a global setting for all trigger volumes.");
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::LargeSpacing();

	//----------------------------------------------------------

	pxDialog = new Asura_Dialog("List of Effects :",xOffset);
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::SmallSpacing();


	m_pxListDialog = NULL;	// bug crash fix.
	UpdateInputList();
	pxDialog = m_pxListDialog = new Asura_List_Dialog(xOffset, m_pszInputList, &m_iInputSelection, 8, m_iInputListSize, NULL);
	m_pxListDialog->SetHelpText("Please note that editing any of the effects, will automaticaly turn off Preview Selected and PreviewAll. Instead it will start to preview only this particular effect.");
	m_pxListDialog->SetDoubleClickFunction(EditEffectNode,(int)this);

	pxOverlay->AddDialog(pxDialog);
	xOffset.y = pxDialog->m_xMaxCoord.y + 1.0f;

	//----------------------------------------------------------

	pxDialog = new Asura_Function_Dialog("Add Effect", xOffset, AddEffectNode,(int)this);
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Function_Dialog("Remove Selected Effect", xOffset, RemoveEffectNode,(int)this, NULL, _DoesAtLeastOneEffectExist );
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Function_Dialog("Edit Selected Effect", xOffset, EditEffectNode,(int)this, NULL, _DoesAtLeastOneEffectExist );
	pxOverlay->AddDialog(pxDialog);
	xOffset.y += Asura_Dialog::LargeSpacing();

	//----------------------------------------------------------

	pxDialog = new Asura_Tickbox_Dialog( "Preview Selected", xOffset, &s_bPreviewSelected );
	pxDialog->SetHelpText("Preview selected EffectVolume. Including functionality for Time Volumes and Transition Volumes. So to make it work, you must actually enter the volume to see the effect.");
	pxOverlay->AddDialog( pxDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxDialog = new Asura_Tickbox_Dialog( "Preview All", xOffset, &s_bPreviewAll );
	pxDialog->SetHelpText("Preview selected EffectVolume. Including functionality for Time Volumes and Transition Volumes. So to make it work, you must actually enter ANY volume to see it's effect.");
	pxOverlay->AddDialog( pxDialog );
}

bool Tools_Entity_EffectVolume::_DoesAtLeastOneEffectExist(void)
{
	Asura_Assert(s_pxSelectedEffectVolume, "No Effect Volume selected, should be impossible.");
	if (!s_pxSelectedEffectVolume) { return false; }

	return s_pxSelectedEffectVolume->DoesAtLeastOneEffectExist();
}

bool Tools_Entity_EffectVolume::DoesAtLeastOneEffectExist(void)
{
	Asura_ServerEntity_EffectVolume* pxEffectVolume = (Asura_ServerEntity_EffectVolume*) Entity;

	return ( pxEffectVolume==NULL ? false : (pxEffectVolume->m_xData.m_uNumEffects > 0));
}

void Tools_Entity_EffectVolume::AddEffectNode( int iThis )
{
	ListSelection_Overlay xOverlay("Select Effect");
	for( u_int u=0; u<NUM_EFFECT_VOLUME_EFFECT_TYPES; u++ )
	{
		xOverlay.AddItem( s_aszEffectVolumeTypeNames[u], u );
	}

	if( xOverlay.DoModal())
	{
		Tools_SaveAsura::SetEntityModified();

		int iData = xOverlay.GetSelectionData();

		Tools_Entity_EffectVolume* pxObj = (Tools_Entity_EffectVolume*) iThis;

		if( pxObj )
		{
			Asura_ServerEntity_EffectVolume* pxEffectVolume = (Asura_ServerEntity_EffectVolume*) pxObj->Entity;

			if( pxEffectVolume )
			{
				switch( iData )
				{
					case EFFECT_VOLUME_EFFECT_FOG:
					{
						pxEffectVolume->AddEffect( uEFFECTVOLUME_EFFECT_FOG );
						break;
					}
					case EFFECT_VOLUME_EFFECT_FSFX:
					{
						pxEffectVolume->AddEffect( uEFFECTVOLUME_EFFECT_FSFX );
						break;
					}
					default:
					{
						Asura_Assert( false, "Error: We are trying to add undefined effect. Please check this line of code." );
						break;
					}
				}
			}

			pxObj->UpdateInputList();
		}
	}
}

void Tools_Entity_EffectVolume::RemoveEffectNode( int iThis )
{
	// Ask User
	Asura_String xTitle( "Are you sure you wish to delete this effect?" );
	YesNo_Overlay xYesNoOverlay( xTitle );
	if ( !xYesNoOverlay.DoModal() ) { return; }

	Tools_Entity_EffectVolume* pxObj = (Tools_Entity_EffectVolume*) iThis;
	if( pxObj )
	{
		Asura_ServerEntity_EffectVolume* pxEffectVolume = (Asura_ServerEntity_EffectVolume*) pxObj->Entity;

		if( pxEffectVolume )
		{
			pxEffectVolume->RemoveEffect( pxObj->m_iInputSelection );

			Tools_SaveAsura::SetEntityModified();
		}

		pxObj->UpdateInputList();
	}
}

void Tools_Entity_EffectVolume::EditEffectNode( int iThis )
{
	Tools_Entity_EffectVolume* pxObj = (Tools_Entity_EffectVolume*) iThis;
	if( pxObj )
	{
		// Don't try to edit note if there is no node at all.
		if( !pxObj->DoesAtLeastOneEffectExist() )
		{
			return;
		}

		Asura_ServerEntity_EffectVolume* pxEffectVolume = (Asura_ServerEntity_EffectVolume*) pxObj->Entity;
		if( pxEffectVolume )
		{
			Asura_EffectVolume_Effect* pxEffect = pxEffectVolume->GetEffect( pxObj->m_iInputSelection );
			if( pxEffect )
			{
				// When editing individual effect, disable preview for all effects.
				bool bStore_PreviewSelected = s_bPreviewSelected;
				bool b_Store_PreviewAll		= s_bPreviewAll;
				s_bPreviewSelected = false;
				s_bPreviewAll = false;


				switch( pxEffect->GetEffectTypeHash() )
				{
					case uEFFECTVOLUME_EFFECT_FOG:
					{
						Asura_EffectVolume_Effect_Fog* pxFog = static_cast<Asura_EffectVolume_Effect_Fog*>(pxEffect);

						Asura_Fog_Parameters& xFogParameters = pxFog->GetFogParameters();

						Tools_EffectVolume_FogOverlay  xOverlay( xFogParameters );
						if( xOverlay.DoModal() )
						{
							xOverlay.WriteNewValuesToFogParameters( xFogParameters );
							Tools_SaveAsura::SetEntityModified();
						}
						break;
					}	// End Case
				
					case uEFFECTVOLUME_EFFECT_FSFX:
					{
#ifdef ASURA_USE_FSFX
						Asura_EffectVolume_Effect_FSFX* pxFsfx = static_cast<Asura_EffectVolume_Effect_FSFX*>(pxEffect);

						Tools_EffectVolume_FSFXOverlay xOverlay( pxFsfx );
						
						if( xOverlay.DoModal() )
						{
							Tools_SaveAsura::SetEntityModified();
						}
#endif // ASURA_USE_FSFX
						break;
					} // End Case
				}// End switch

				// Restore preview values.
				s_bPreviewSelected = bStore_PreviewSelected;
				s_bPreviewAll = b_Store_PreviewAll;
			}
		}
	}
}



void Tools_Entity_EffectVolume::UpdateInputList()
{
	DeleteInputList();

	Asura_ServerEntity_EffectVolume* pxEffectVolume = (Asura_ServerEntity_EffectVolume*) Entity;

	if( !pxEffectVolume )
	{
		return;
	}

	if( pxEffectVolume->GetData().GetNumOfEffects() )
	{
		m_iInputListSize = pxEffectVolume->GetData().GetNumOfEffects();
		m_pszInputList = new char*[m_iInputListSize];

		for(int i=0;i<m_iInputListSize; i++)
		{
			Asura_EffectVolume_Effect* pxEffect = pxEffectVolume->GetData().GetEffect(i);

			switch( pxEffect->GetEffectTypeHash() )
			{
			case uEFFECTVOLUME_EFFECT_FOG:
				{
					const char* szName = "Fog";
					m_pszInputList[i] = new char[strlen(szName)+1];
					strcpy(m_pszInputList[i], szName);
					break;
				}
			case uEFFECTVOLUME_EFFECT_FSFX:
				{
					const char* szName = "FSFX";
					m_pszInputList[i] = new char[strlen(szName)+1];
					strcpy(m_pszInputList[i], szName);
					break;
				}
			default:
				{
					Asura_Assert(false, "Error. Imposible reach this code. Inside: Tools_Entity_EffectVolume::UpdateInputList()");
				}
			}
		}
	}
	else
	{
		m_iInputListSize = 1;
		m_pszInputList = new char*[1];
		m_pszInputList[0] = new char[7];
		strcpy(m_pszInputList[0], "*Empty*");
	}

	m_iInputSelection = Asura_Maths::Min(m_iInputListSize-1, m_iInputSelection);

	if( m_pxListDialog )
	{
		m_pxListDialog->ReplaceStrings( m_iInputListSize, m_pszInputList );
	}
}


void Tools_Entity_EffectVolume::DeleteInputList()
{
	for(int i=0; i<m_iInputListSize; i++)
	{
		delete [] m_pszInputList[i];
	}
	delete [] m_pszInputList;
	m_pszInputList = 0;
	m_iInputListSize = 0;
}


// This function is copied from Tools_Entity_VolumeTrigger
void Tools_Entity_EffectVolume::UpdatePositionInAsuraData(bool bUpdateLinkedObjects)
{
	Asura_ServerEntity_EffectVolume* pxAsuraEntity = (Asura_ServerEntity_EffectVolume*) Entity;
	if(s_bMoveVolumeWithObject)
	{
		Asura_Vector_3 xOffset = Position-m_xPreviousPosition;
		pxAsuraEntity->GetData().GetVolume()->DisplaceVolumes(xOffset);
		pxAsuraEntity->GetData().GetTransitionVolume()->DisplaceVolumes(xOffset);

		if(m_pxVolumeController)
		{
			m_pxVolumeController->MoveVolumeObjects(xOffset);
		}
		if(m_pxTransitionVolumeController)
		{
			m_pxTransitionVolumeController->MoveVolumeObjects(xOffset);
		}

#if 1
		Asura_Euler_3 xLast;
		xLast.FromMatrix(m_xPreviousOrientation);
		Asura_Euler_3 xThis;
		xThis.FromMatrix(Orientation);
		Asura_Euler_3 xRot = xThis;
		xThis.Element[0]-=xLast.Element[0];
		xThis.Element[1]-=xLast.Element[1];
		xThis.Element[2]-=xLast.Element[2];
		Asura_Matrix_3x3 xAsMat;
		xThis.ToMatrix(xAsMat);

		if (xThis.MagnitudeSquared() > 0.0f)
		{
			pxAsuraEntity->GetData().GetVolume()->RotateVolumesAbout(Position, xAsMat);
			pxAsuraEntity->GetData().GetTransitionVolume()->RotateVolumesAbout(Position, xAsMat);

			if(m_pxVolumeController)
			{
				m_pxVolumeController->RotateVolumeObjectsAbout(Position, xAsMat);
			}
			if (m_pxTransitionVolumeController)
			{
				m_pxTransitionVolumeController->RotateVolumeObjectsAbout(Position, xAsMat);
			}
		}
#endif

	}

	m_xPreviousOrientation = Orientation;
	m_xPreviousPosition = Position;
	PARENT::UpdatePositionInAsuraData(bUpdateLinkedObjects);
}


// This function is called only inside tools. It will determine if the Effect will be active or inactive in the tools.
// false = non active, non preview-able
// true  = active, therefore preview-able
bool Tools_Entity_EffectVolume::CanPreviewThisObjectInTools(Asura_ServerEntity_EffectVolume* pxEntity)
{
	if( Tools_System::IsActive() )
	{
		// Tools_System::GetCurrentMode() != TOOLS_MODE_OBJECT && 
		if( Tools_Render_Options::GetEnableEffectVolume() )	// When the flag "show globally all effect volumes" is turn on, then lets show the object. ///////But only if we are not in object mode.
		{
			// If we trigger main trigger in Tools_Render_Options, then the object will be always active (or better say visible)
			return true;
		}

		if( s_pxSelectedEffectVolume==NULL )
		{
			// Main Trigger is off. So if we are not selecting any Volume Effect, always do not preview the object.
			return false;
		}

		if( s_bPreviewAll )
		{
			return true;
		}

		if( ThisEntity )
		{
			Tools_Entity_EffectVolume* pxToolsEntity = (Tools_Entity_EffectVolume*) ThisEntity;

			Asura_ServerEntity_EffectVolume* pxEffectVolume = static_cast<Asura_ServerEntity_EffectVolume*> (pxToolsEntity->Entity);

			if( s_bPreviewSelected && pxEntity==pxEffectVolume )
			{
				return true;
			}
		}

		return false;
	}

	return true;
}

void Tools_Entity_EffectVolume::Update()
{
	PARENT::Update();

	ShowVolume(s_bShowAllVolumes);
	ShowTransitionVolume(s_bShowAllTransitionVolumes);
}


void Tools_Entity_EffectVolume::EditVolume()
{
	Asura_Assert(ThisEntity,"");

	Tools_Entity_EffectVolume* pxToolsEntity = (Tools_Entity_EffectVolume*) ThisEntity;
	Asura_ServerEntity_EffectVolume* pxAsuraEntity = (Asura_ServerEntity_EffectVolume*) ThisEntity->Entity;
	
	//create controller for editing volumes if it hasn't been done yet
	if(!pxToolsEntity->m_pxVolumeController)
	{
		pxToolsEntity->m_pxVolumeController = new Tools_Object_VolumeGroupEdit_Controller(pxToolsEntity, pxAsuraEntity->m_xData.m_pxVolumeGroup, &pxToolsEntity->Changed);
	}

	//and get it to create the volume objects
	pxToolsEntity->m_pxVolumeController->StartVolumeEditing();

	Tools_SaveAsura::SetEntityModified();
}


void Tools_Entity_EffectVolume::ShowVolume(bool bShow)
{
	if(!m_pxVolumeController && !bShow && !s_bShowSelectedVolume) return;

	//create controller for editing volumes if it hasn't been done yet
	if(!m_pxVolumeController)
	{
		Asura_ServerEntity_EffectVolume* pxAsuraEntity = (Asura_ServerEntity_EffectVolume*) Entity;
		m_pxVolumeController = new Tools_Object_VolumeGroupEdit_Controller(this, pxAsuraEntity->m_xData.m_pxVolumeGroup, &Changed);
	}

	if (s_bShowSelectedVolume)
	{
		if (this == s_pxLastSelected) bShow =true;
	}

	//hide/show volume objects
	m_pxVolumeController->ShowVolumes(bShow || m_pxVolumeController->IsSelected());
}


void Tools_Entity_EffectVolume::Render(void)
{
	// Call the base-function...
	PARENT::Render();
}


void Tools_Entity_EffectVolume::EditTransitionVolume()
{
	Asura_Assert(ThisEntity,"");

	Tools_Entity_EffectVolume* pxToolsEntity = (Tools_Entity_EffectVolume*) ThisEntity;
	Asura_ServerEntity_EffectVolume* pxAsuraEntity = (Asura_ServerEntity_EffectVolume*) ThisEntity->Entity;

	//create controller for editing volumes if it hasn't been done yet
	if(!pxToolsEntity->m_pxTransitionVolumeController)
	{
		pxToolsEntity->m_pxTransitionVolumeController = new Tools_Object_VolumeGroupEdit_Controller(pxToolsEntity, pxAsuraEntity->m_xData.m_pxTransitionVolumeGroup, &pxToolsEntity->Changed);
	}

	//and get it to create the volume objects
	pxToolsEntity->m_pxTransitionVolumeController->StartVolumeEditing();

	Tools_SaveAsura::SetEntityModified();
}


void Tools_Entity_EffectVolume::ShowTransitionVolume(bool bShow)
{
	if(!m_pxTransitionVolumeController && !bShow && !s_bShowSelectedTransitionVolume) return;

	//create controller for editing volumes if it hasn't been done yet
	if(!m_pxTransitionVolumeController)
	{
		Asura_ServerEntity_EffectVolume* pxAsuraEntity = (Asura_ServerEntity_EffectVolume*) Entity;
		m_pxTransitionVolumeController = new Tools_Object_VolumeGroupEdit_Controller(this, pxAsuraEntity->m_xData.m_pxTransitionVolumeGroup, &Changed);
	}

	if (s_bShowSelectedTransitionVolume)
	{
		if (this == s_pxLastSelected) bShow =true;
	}

	//hide/show volume objects
	m_pxTransitionVolumeController->ShowVolumes(bShow || m_pxTransitionVolumeController->IsSelected());
}
