//////////////////////////////////////////////////////////////////////////////////////
// 
// FILE : Tools_Entity_AdvancedLight.cpp
//
// AUTHOR : Martin G. Harris
//
// Copyright 2002 Rebellion, All Rights Reserved.
//
//////////////////////////////////////////////////////////////////////////////////////

#include "Core/Asura.h"

#ifndef ASURA_TARGET_SM3

#include "Entity/Tools_Entity_AdvancedLight.h"

#include "Animation/Asura_Hierarchy.h"
#include "Camera/Asura_Camera.h"
#include "ChunkSystem/Asura_Chunk_Loaders.h"
#include "Core/Asura_Timers.h"
#include "Entity/Asura_Entity_Classification.h"
#include "Interface/Asura_Dialog.h"
#include "Interface/Asura_Overlay.h"
#include "Interface/Asura_Overlay_System.h"
#include "Mesh/Asura_Mesh.h"
#include "Mesh/Asura_Mesh_System.h"
#include "Network/Asura_Network.h"
#include "Rendering/Asura_Render.h"
#include "Rendering/Asura_Text_Output.h"
#include "Light/Asura_Photon.h"
#include "Entity/PhysicalObject/Asura_ClientEntity_AdvancedLight.h"
#include "Debugging/Asura_DebugText.h"

#include "Tools_Overlays.h"
#include "Entity/Tools_Entity_Data.h"
#include "Interface/Tools_ColourPicker.h"
#include "Misc/Tools_Timed_Messages.h"
#include "Objects/Tools_Object_System.h"
#include "Shapes/Tools_Shapes.h"

/////////////////////////////////////////////////////////////////////////////////////////
// Tools_Entity_AdvancedLight
/////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////
// Static member variables //
/////////////////////////////

const char* const Tools_Entity_AdvancedLight::s_szLongName  = "Advanced Light";
const char* const Tools_Entity_AdvancedLight::s_szShortName = "AdvLight";
bool Tools_Entity_AdvancedLight::s_bModified = false;
Asura_Hashed_List<Tools_Entity_AdvancedLight> Tools_Entity_AdvancedLight::s_xList;

Tools_Entity_AdvancedLight::Tools_Entity_AdvancedLight(Asura_ServerEntity_AdvancedLight* pxDestLight)
: Tools_Entity_PhysicalObject(NULL) // ignored
, Tools_Entity_DestructibleLight(pxDestLight)
{
  	Type = TOT_Entity_AdvancedLight;
	m_pxAdvLight = pxDestLight;
	s_xList.AddToList(this);

	// initial setting for flicker control variable
	m_bFlicker = false;
	if( (m_pxAdvLight->m_fMinTimeOn != -1.0f) || (m_pxAdvLight->m_fMaxTimeOn != -1.0f) ||
		(m_pxAdvLight->m_fMinTimeOff != -1.0f) || (m_pxAdvLight->m_fMaxTimeOff != -1.0f) )
	{
		m_bFlicker = true;
	}

	// initial setting for colour fade control variable
	m_bColourFade = false;
	if( (m_pxAdvLight->m_fMinStartColourTime != -1.0f) || (m_pxAdvLight->m_fMaxStartColourTime != -1.0f) ||
		(m_pxAdvLight->m_fMinEndColourTime != -1.0f) || (m_pxAdvLight->m_fMaxEndColourTime != -1.0f) )
	{
		m_bColourFade = true;
	}

	// intial setting for range face control variable
	m_bRangeFade = false;
	if( (m_pxAdvLight->m_fMinStartRadiusTime != -1.0f) || (m_pxAdvLight->m_fMaxStartRadiusTime != -1.0f) ||
		(m_pxAdvLight->m_fMinEndRadiusTime != -1.0f) || (m_pxAdvLight->m_fMaxEndRadiusTime != -1.0f) )		
	{
		m_bRangeFade = true;
	}

	// bak values of control variables
	m_bPrevFlicker    = m_bFlicker;
	m_bPrevColourFade = m_bColourFade;
	m_bPrevRangeFade  = m_bRangeFade;

	// Dialog pointers
	m_pxMinTimeOffDlg = NULL;
	m_pxMaxTimeOffDlg = NULL;
	m_pxMinTimeOnDlg  = NULL;
	m_pxMaxTimeOnDlg  = NULL;
	
	m_pxMinStartColourTimeDlg = NULL;
	m_pxMaxStartColourTimeDlg = NULL;
	m_pxMinFadeDownTimeDlg = NULL;
	m_pxMaxFadeDownTimeDlg = NULL;
	m_pxMinEndColourTimeDlg = NULL;
	m_pxMaxEndColourTimeDlg = NULL;
	m_pxMinFadeUpTimeDlg = NULL;
	m_pxMaxFadeUpTimeDlg = NULL;
	
	m_pxStartRedDlg   = NULL;
	m_pxStartGreenDlg = NULL;
	m_pxStartBlueDlg  = NULL;
	
	m_pxEndRedDlg   = NULL;
	m_pxEndGreenDlg = NULL;
	m_pxEndBlueDlg  = NULL;

	m_pxMinStartRangeTimeDlg = NULL;
	m_pxMaxStartRangeTimeDlg = NULL;
	m_pxMinRangeDownTimeDlg = NULL;
	m_pxMaxRangeDownTimeDlg = NULL;
	m_pxMinEndRangeTimeDlg = NULL;
	m_pxMaxEndRangeTimeDlg = NULL;
	m_pxMinRangeUpTimeDlg = NULL;
	m_pxMaxRangeUpTimeDlg = NULL;
	
	m_pxStartRangeDlg = NULL;
	m_pxEndRangeDlg = NULL;

	// set photon values
	m_fStrobeTimer = 0.0f;
	m_fCurrentStrobeDuration = m_pxAdvLight->m_fMaxTimeOn;
	
	m_fFadeTimer = 0.0f;
	m_fCurrentFadeDuration = m_pxAdvLight->m_fMaxStartColourTime;
	m_eColourFadePhase = FADE_PHASE_ATSTART;

	m_fRadiusTimer = 0.0f;
	m_fCurrentRadiusDuration = m_pxAdvLight->m_fMaxStartRadiusTime;
	m_eRadiusPhase = FADE_PHASE_ATSTART;  

	float fScale = (m_pxAdvLight->m_fBrightness / 255.0f) / 2.0f;

	m_fEndColourR = m_pxAdvLight->m_fEndColourR * fScale;
	m_fEndColourG = m_pxAdvLight->m_fEndColourG * fScale;
	m_fEndColourB = m_pxAdvLight->m_fEndColourB * fScale;
	
	m_fStartColourR = m_pxAdvLight->m_fStartColourR * fScale;
	m_fStartColourG = m_pxAdvLight->m_fStartColourG * fScale;
	m_fStartColourB = m_pxAdvLight->m_fStartColourB * fScale;
	
	s_bModified = false;
	m_bActive = m_pxAdvLight->m_uActive;
	m_bUseMasterOrient = m_pxAdvLight->m_uUseMasterOrient;

	SetPhotonToValuesOfEntity();
}


Tools_Entity_AdvancedLight::~Tools_Entity_AdvancedLight()
{
	s_xList.RemoveFromList(this);
	// if the light has been modified since selection, need to re-create the client entities
	if(s_bModified)
	{
		if(m_pxAdvLight)
		{
			m_pxAdvLight->MakeCreateMessage(ASURA_GUID_UNREGISTERED);
			s_bModified = false;
		}
	}
	s_pxCurrentSelectedAdvLight = NULL;
}


void Tools_Entity_AdvancedLight::SetPhotonToValuesOfEntity()
{
	if (!m_pxAdvLight) return; // give up
	
    UpdateCorona();
    
    if (m_pxPhoton)
    {
		float fScale = (m_pxAdvLight->m_fBrightness / 255.0f) / 2.0f;
		if(m_eColourFadePhase == FADE_PHASE_NONE)
		{
			SetPhotonAndCoronaColour( m_pxAdvLight->m_fR * fScale, m_pxAdvLight->m_fG * fScale, m_pxAdvLight->m_fB * fScale);
		}
		if(m_eRadiusPhase == FADE_PHASE_NONE)
		{
			m_pxPhoton->SetRange( m_pxAdvLight->m_fRange );
		}
		//m_pxPhoton->SetCorona( m_pxAdvLight->HasCorona() );
		m_pxPhoton->SetPosition( m_pxAdvLight->GetPosition() );
		m_pxPhoton->SetUseBoundingBox(m_pxAdvLight->m_bUseBoundingBox);
		m_pxPhoton->SetBoundingBox(m_pxAdvLight->m_xBoundingBox);
		m_pxPhoton->SetDontLightEnv(m_pxAdvLight->m_bDontLightEnv);
    }
}


void Tools_Entity_AdvancedLight::AddOverlayControls(Asura_Overlay* pxNewOverlay, Asura_Vector_2& xOffset)
{
	if (!m_pxAdvLight) return; // give up

// No parent call here - AdvancedLight is multiply inherited and project 
// subclass will call both parents
    Asura_Dialog* pxNewDialog;

	pxNewDialog = new Asura_Function_Dialog("Select Shape", xOffset, SelectShape_Dialog);
	pxNewDialog->SetHelpText("Choose shape for this light.");
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

	AddMergeWithEnvOverlayControl(pxNewOverlay,xOffset);

	AddHealthOverlayControl(pxNewOverlay, xOffset, true);

	pxNewDialog = new Asura_Tickbox_Dialog("Starts Active", xOffset, &m_bActive, &s_bModified );
	pxNewDialog->SetHelpText("Light is on initially.");
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

	pxNewDialog = new Asura_Function_Dialog("Flicker & Strobe", xOffset, CreateFlickerDlg );
	pxNewDialog->SetHelpText("Edit flicker and strobe settings.");
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

	pxNewDialog = new Asura_Function_Dialog("Colour Fade", xOffset, CreateColourFadeDlg );
	pxNewDialog->SetHelpText("Edit colour fade settings.");
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

	pxNewDialog = new Asura_Function_Dialog("Range Fade", xOffset, CreateRangeFadeDlg );
	pxNewDialog->SetHelpText("Edit range fade settings (for interpolating of light range).");
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

	pxNewDialog = new Asura_Function_Dialog("Attach To Object", xOffset, CreateAttachDlg );
	pxNewDialog->SetHelpText("Select object that this light should be attached to.");
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
	pxNewDialog = new Asura_Function_Dialog("Unattach", xOffset, UnattachLight );
	pxNewDialog->SetHelpText("Detach this light from wheatever object it was attached to.");
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

	

}



void Tools_Entity_AdvancedLight::Render(void)
{
	Tools_Entity_DestructibleLight::Render();
	
	// if the light is attached, draw a line from it to the master object
	if( IsSelected() )
	{
		Tools_Object* pxMaster = Tools_Object_System::GetObjectFromGuid( m_pxAdvLight->m_uMasterEntity);
		if(pxMaster) 
		{
			Asura_Render::RenderLine( Position, pxMaster->Position, 0xff00ff00 );
		}
	}	
}


// virtual functions for onselect/deselect
void Tools_Entity_AdvancedLight::OnSelection()
{
	s_pxCurrentSelectedAdvLight = this;
	Tools_Entity_DestructibleLight::OnSelection();
}

void Tools_Entity_AdvancedLight::OnDeselection()
{
	// if the light has been modified since selection, need to re-create the client entities
	if(s_bModified)
	{
		if(m_pxAdvLight)
		{
			m_pxAdvLight->MakeCreateMessage(ASURA_GUID_UNREGISTERED);
			s_bModified = false;
		}
	}
	
	if(s_bResetCurrentLightPtrOnDeselect)
	{
		s_pxCurrentSelectedAdvLight = NULL;
	}		
	
	Tools_Entity_DestructibleLight::OnDeselection();
}


//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION     Tools_Entity_AdvancedLight::UpdateWhileSelected().
// PARAMETERS   None.
// RETURNS      None.
// DESCRIPTION  virtual function override
// AUTHOR       Mike Healey - 04.09.2002.
//
//////////////////////////////////////////////////////////////////////////////
void Tools_Entity_AdvancedLight::UpdateWhileSelected()
{
	// this skips the destructible light version as we don't want to set the photon values directly
    Tools_Entity_DestructibleLight::UpdateWhileSelected();
	if(!m_pxAdvLight) return;
	
	// deal with change in flicker & strobe control variable
	if(m_bFlicker != m_bPrevFlicker)
	{
		// if flicker is turned off then all timer values must be set to -1
		if(!m_bFlicker)
		{
			m_pxAdvLight->m_fMinTimeOff = -1.0f;
			m_pxAdvLight->m_fMaxTimeOff = -1.0f;
			m_pxAdvLight->m_fMinTimeOn  = -1.0f;
			m_pxAdvLight->m_fMaxTimeOn  = -1.0f;
		}
		else
		{
			// reset timer values to something sensible
			m_pxAdvLight->m_fMinTimeOff = 1.0f;
			m_pxAdvLight->m_fMaxTimeOff = 1.0f;
			m_pxAdvLight->m_fMinTimeOn  = 1.0f;
			m_pxAdvLight->m_fMaxTimeOn  = 1.0f;
		}
		m_fCurrentStrobeDuration = m_pxAdvLight->m_fMaxTimeOn;
		m_bPrevFlicker = m_bFlicker;
	}

	if(m_bColourFade != m_bPrevColourFade)
	{
		// if colour fade is turned off then all timer values must be set to -1
		if(!m_bColourFade)
		{
			m_pxAdvLight->m_fMinStartColourTime = -1.0f;
			m_pxAdvLight->m_fMaxStartColourTime = -1.0f;
			m_pxAdvLight->m_fMinEndColourTime = -1.0f;
			m_pxAdvLight->m_fMaxEndColourTime = -1.0f;

		}	
		else
		{
			// reset timer values to something sensible
			m_pxAdvLight->m_fMinStartColourTime = 1.0f;
			m_pxAdvLight->m_fMaxStartColourTime = 1.0f;
			m_pxAdvLight->m_fMinEndColourTime = 1.0f;
			m_pxAdvLight->m_fMaxEndColourTime = 1.0f;
			
			m_pxAdvLight->m_fStartColourR = m_pxAdvLight->m_fR; 
			m_pxAdvLight->m_fStartColourG = m_pxAdvLight->m_fG;  
			m_pxAdvLight->m_fStartColourB = m_pxAdvLight->m_fB; 
		}
				
		m_fCurrentFadeDuration = m_pxAdvLight->m_fMaxStartColourTime;
		m_bPrevColourFade = m_bColourFade;
	}

	if(m_bRangeFade != m_bPrevRangeFade)
	{
		// if range fade is turned off then all timer values must be set to -1
		if(!m_bRangeFade)
		{
			m_pxAdvLight->m_fMinStartRadiusTime = -1.0f;
			m_pxAdvLight->m_fMaxStartRadiusTime = -1.0f;
			m_pxAdvLight->m_fMinEndRadiusTime = -1.0f;
			m_pxAdvLight->m_fMaxEndRadiusTime = -1.0f;
		}
		else
		{
			// reset timer values to something sensible
			m_pxAdvLight->m_fMinStartRadiusTime = 1.0f;
			m_pxAdvLight->m_fMaxStartRadiusTime = 1.0f;
			m_pxAdvLight->m_fMinEndRadiusTime = 1.0f;
			m_pxAdvLight->m_fMaxEndRadiusTime = 1.0f;

			m_pxAdvLight->m_fStartRadius = m_pxAdvLight->m_fRange;
		}	
	
		m_fCurrentRadiusDuration = m_pxAdvLight->m_fMaxStartRadiusTime;
		m_bPrevRangeFade = m_bRangeFade;
	}	

	// make sure all minimum timer values are less than or equal to the maximum values
	// flicker
	{
		m_pxAdvLight->m_fMinTimeOff = (m_pxAdvLight->m_fMinTimeOff <= m_pxAdvLight->m_fMaxTimeOff) ? m_pxAdvLight->m_fMinTimeOff : m_pxAdvLight->m_fMaxTimeOff;
		m_pxAdvLight->m_fMinTimeOn  = (m_pxAdvLight->m_fMinTimeOn <= m_pxAdvLight->m_fMaxTimeOn) ? m_pxAdvLight->m_fMinTimeOn : m_pxAdvLight->m_fMaxTimeOn;		
	}

	// colour fade
	{
		m_pxAdvLight->m_fMinStartColourTime  = (m_pxAdvLight->m_fMinStartColourTime <= m_pxAdvLight->m_fMaxStartColourTime) ? m_pxAdvLight->m_fMinStartColourTime : m_pxAdvLight->m_fMaxStartColourTime;
		m_pxAdvLight->m_fMinEndColourTime    = (m_pxAdvLight->m_fMinEndColourTime <= m_pxAdvLight->m_fMaxEndColourTime) ? m_pxAdvLight->m_fMinEndColourTime : m_pxAdvLight->m_fMaxEndColourTime;
		m_pxAdvLight->m_fMinFadeDownDuration = (m_pxAdvLight->m_fMinFadeDownDuration <= m_pxAdvLight->m_fMaxFadeDownDuration) ? m_pxAdvLight->m_fMinFadeDownDuration : m_pxAdvLight->m_fMaxFadeDownDuration;		
		m_pxAdvLight->m_fMinFadeUpDuration   = (m_pxAdvLight->m_fMinFadeUpDuration <= m_pxAdvLight->m_fMaxFadeUpDuration) ? m_pxAdvLight->m_fMinFadeUpDuration : m_pxAdvLight->m_fMaxFadeUpDuration;				
	}

	// range fade
	{
		m_pxAdvLight->m_fMinStartRadiusTime  = (m_pxAdvLight->m_fMinStartRadiusTime <= m_pxAdvLight->m_fMaxStartRadiusTime) ? m_pxAdvLight->m_fMinStartRadiusTime : m_pxAdvLight->m_fMaxStartRadiusTime;
		m_pxAdvLight->m_fMinEndRadiusTime    = (m_pxAdvLight->m_fMinEndRadiusTime <= m_pxAdvLight->m_fMaxEndRadiusTime) ? m_pxAdvLight->m_fMinEndRadiusTime : m_pxAdvLight->m_fMaxEndRadiusTime;
		m_pxAdvLight->m_fMinRadiusDownDuration = (m_pxAdvLight->m_fMinRadiusDownDuration <= m_pxAdvLight->m_fMaxRadiusDownDuration) ? m_pxAdvLight->m_fMinRadiusDownDuration : m_pxAdvLight->m_fMaxRadiusDownDuration;		
		m_pxAdvLight->m_fMinRadiusUpDuration   = (m_pxAdvLight->m_fMinRadiusUpDuration <= m_pxAdvLight->m_fMaxRadiusUpDuration) ? m_pxAdvLight->m_fMinRadiusUpDuration : m_pxAdvLight->m_fMaxRadiusUpDuration;						
	}

	// update flicker overlay
	if(!Asura_Overlay_System::DoesOverlayExist(TOOLS_OVERLAY_ADVLIGHTFLICKER))
	{
		m_pxMinTimeOffDlg = NULL;
		m_pxMaxTimeOffDlg = NULL;
		m_pxMinTimeOnDlg  = NULL;
		m_pxMaxTimeOnDlg  = NULL;
	}
	else
	{	
		if(m_pxMinTimeOffDlg) m_pxMinTimeOffDlg->SetEnabled(m_bFlicker);
		if(m_pxMaxTimeOffDlg) m_pxMaxTimeOffDlg->SetEnabled(m_bFlicker);
		if(m_pxMinTimeOnDlg) m_pxMinTimeOnDlg->SetEnabled(m_bFlicker);
		if(m_pxMaxTimeOnDlg) m_pxMaxTimeOnDlg->SetEnabled(m_bFlicker);
	}

	// update colour overlay
	if(!Asura_Overlay_System::DoesOverlayExist(TOOLS_OVERLAY_ADVLIGHTCOLOURFADE))
	{
		m_pxMinStartColourTimeDlg = NULL;
		m_pxMaxStartColourTimeDlg = NULL;
		m_pxMinFadeDownTimeDlg = NULL;
		m_pxMaxFadeDownTimeDlg = NULL;
		m_pxMinEndColourTimeDlg = NULL;
		m_pxMaxEndColourTimeDlg = NULL;
		m_pxMinFadeUpTimeDlg = NULL;
		m_pxMaxFadeUpTimeDlg = NULL;
		
		m_pxStartRedDlg   = NULL;
		m_pxStartGreenDlg = NULL;
		m_pxStartBlueDlg  = NULL;
		
		m_pxEndRedDlg   = NULL;
		m_pxEndGreenDlg = NULL;
		m_pxEndBlueDlg  = NULL;
	}
	else
	{
		if(m_pxMinStartColourTimeDlg) m_pxMinStartColourTimeDlg->SetEnabled(m_bColourFade);
		if(m_pxMaxStartColourTimeDlg) m_pxMaxStartColourTimeDlg->SetEnabled(m_bColourFade);
		if(m_pxMinFadeDownTimeDlg) m_pxMinFadeDownTimeDlg->SetEnabled(m_bColourFade);
		if(m_pxMaxFadeDownTimeDlg) m_pxMaxFadeDownTimeDlg->SetEnabled(m_bColourFade);
		if(m_pxMinEndColourTimeDlg) m_pxMinEndColourTimeDlg->SetEnabled(m_bColourFade);
		if(m_pxMaxEndColourTimeDlg) m_pxMaxEndColourTimeDlg->SetEnabled(m_bColourFade);
		if(m_pxMinFadeUpTimeDlg) m_pxMinFadeUpTimeDlg->SetEnabled(m_bColourFade);
		if(m_pxMaxFadeUpTimeDlg) m_pxMaxFadeUpTimeDlg->SetEnabled(m_bColourFade);

		if(m_pxStartRedDlg) m_pxStartRedDlg->SetEnabled(m_bColourFade);
		if(m_pxStartGreenDlg) m_pxStartGreenDlg->SetEnabled(m_bColourFade);
		if(m_pxStartBlueDlg) m_pxStartBlueDlg->SetEnabled(m_bColourFade);
 
		if(m_pxEndRedDlg) m_pxEndRedDlg->SetEnabled(m_bColourFade);
		if(m_pxEndGreenDlg) m_pxEndGreenDlg->SetEnabled(m_bColourFade);
		if(m_pxEndBlueDlg) m_pxEndBlueDlg->SetEnabled(m_bColourFade);
	}

	if(!Asura_Overlay_System::DoesOverlayExist(TOOLS_OVERLAY_ADVLIGHTRANGEFADE))
	{
		m_pxMinStartRangeTimeDlg = NULL;
		m_pxMaxStartRangeTimeDlg = NULL;
		m_pxMinRangeDownTimeDlg = NULL;
		m_pxMaxRangeDownTimeDlg = NULL;
		m_pxMinEndRangeTimeDlg = NULL;
		m_pxMaxEndRangeTimeDlg = NULL;
		m_pxMinRangeUpTimeDlg = NULL;
		m_pxMaxRangeUpTimeDlg = NULL;
		
		m_pxStartRangeDlg = NULL;
		m_pxEndRangeDlg = NULL;
	}
	else
	{
		if(m_pxMinStartRangeTimeDlg) m_pxMinStartRangeTimeDlg->SetEnabled(m_bRangeFade);
		if(m_pxMaxStartRangeTimeDlg) m_pxMaxStartRangeTimeDlg->SetEnabled(m_bRangeFade);
		if(m_pxMinRangeDownTimeDlg) m_pxMinRangeDownTimeDlg->SetEnabled(m_bRangeFade);
		if(m_pxMaxRangeDownTimeDlg) m_pxMaxRangeDownTimeDlg->SetEnabled(m_bRangeFade);
		if(m_pxMinEndRangeTimeDlg) m_pxMinEndRangeTimeDlg->SetEnabled(m_bRangeFade);
		if(m_pxMaxEndRangeTimeDlg) m_pxMaxEndRangeTimeDlg->SetEnabled(m_bRangeFade);
		if(m_pxMinRangeUpTimeDlg) m_pxMinRangeUpTimeDlg->SetEnabled(m_bRangeFade);
		if(m_pxMaxRangeUpTimeDlg) m_pxMaxRangeUpTimeDlg->SetEnabled(m_bRangeFade);
		
		if(m_pxStartRangeDlg) m_pxStartRangeDlg->SetEnabled(m_bRangeFade);
		if(m_pxEndRangeDlg) m_pxEndRangeDlg->SetEnabled(m_bRangeFade);
	}	
	
	{
		m_pxAdvLight->m_uActive = m_bActive;
		m_pxAdvLight->m_uUseMasterOrient = m_bUseMasterOrient;
	}

	float fScale = (m_pxAdvLight->m_fBrightness / 255.0f) / 2.0f;
	m_fEndColourR = m_pxAdvLight->m_fEndColourR * fScale;
	m_fEndColourG = m_pxAdvLight->m_fEndColourG * fScale;
	m_fEndColourB = m_pxAdvLight->m_fEndColourB * fScale;
	
	m_fStartColourR = m_pxAdvLight->m_fStartColourR * fScale;
	m_fStartColourG = m_pxAdvLight->m_fStartColourG * fScale;
	m_fStartColourB = m_pxAdvLight->m_fStartColourB * fScale;

	
	// update photon
	float fTimeSlice = Asura_Timers::GetGameTimeSlice();
	if(m_pxAdvLight->m_uActive)    
	{
		if( !m_pxPhoton->IsActive() && (m_fCurrentStrobeDuration == -1.0f) )
		{
			SetPhotonAndCoronaActive(true);
		}

		// update strobe/flicker
		{
			m_fStrobeTimer += fTimeSlice;

			// check whether a phase (on/off) change is required
			if( (m_fStrobeTimer > m_fCurrentStrobeDuration) && (m_fCurrentStrobeDuration != -1.0f) )	 
			{
				// check the current status of the photon
				if( m_pxPhoton->IsActive() )
				{
					// if the photon is currently on, switch to an inactive (off) phase & set a new random duration
					m_fCurrentStrobeDuration = Asura_Random::GetFloat( m_pxAdvLight->m_fMinTimeOff, m_pxAdvLight->m_fMaxTimeOff );
					SetPhotonAndCoronaActive(false);
				}
				else
				{
					m_fCurrentStrobeDuration = Asura_Random::GetFloat( m_pxAdvLight->m_fMinTimeOn, m_pxAdvLight->m_fMaxTimeOn );
					SetPhotonAndCoronaActive(true);
				}
				m_fStrobeTimer = 0.0f;
			}	

			if(m_fCurrentStrobeDuration == -1.0f)
			{
				SetPhotonAndCoronaActive(true);
			}
		}

		// update colour fade
		if( (m_pxAdvLight->m_fMinStartColourTime == -1.0f) && (m_pxAdvLight->m_fMaxStartColourTime == -1.0f) && 
			(m_pxAdvLight->m_fMinEndColourTime == -1.0f) && (m_pxAdvLight->m_fMaxEndColourTime == -1.0f) )
		{
			m_eColourFadePhase = FADE_PHASE_NONE;
		}
		else
		{
			if(m_eColourFadePhase == FADE_PHASE_NONE)
			{
				m_eColourFadePhase = FADE_PHASE_ATSTART;
			}

			m_fFadeTimer += fTimeSlice;

			// if we're currently fading, set the current colour of the photon
			if( (m_eColourFadePhase == FADE_PHASE_DOWN) && (m_fCurrentFadeDuration > 0.0f) )
			{
				float fFadePercent = (m_fFadeTimer / m_fCurrentFadeDuration);
				if(fFadePercent > 1.0f) fFadePercent = 1.0f;
				SetPhotonAndCoronaColour( m_fStartColourR + ((m_fEndColourR - m_fStartColourR) * fFadePercent),
										m_fStartColourG + ((m_fEndColourG - m_fStartColourG) * fFadePercent),
										m_fStartColourB + ((m_fEndColourB - m_fStartColourB) * fFadePercent) );
				Asura_Text_Output::Print(10.0f,10.0f,0xffffffff,0,"Fadepercent: %f",fFadePercent);
			}
			else if( (m_eColourFadePhase == FADE_PHASE_UP) && (m_fCurrentFadeDuration > 0.0f) )
			{
				float fFadePercent = (m_fFadeTimer / m_fCurrentFadeDuration);
				if(fFadePercent > 1.0f) fFadePercent = 1.0f;
				SetPhotonAndCoronaColour( m_fEndColourR + ((m_fStartColourR - m_fEndColourR) * fFadePercent),
										m_fEndColourG + ((m_fStartColourG - m_fEndColourG) * fFadePercent),
										m_fEndColourB + ((m_fStartColourB - m_fEndColourB) * fFadePercent) );
				Asura_Text_Output::Print(10.0f,10.0f,0xffffffff,0,"Fadepercent: %f",fFadePercent);
			}
			

			// check for phase end/switch
			if( (m_fFadeTimer > m_fCurrentFadeDuration) && (m_fCurrentFadeDuration != -1.0f) )
			{
				switch(m_eColourFadePhase)
				{
					case FADE_PHASE_UP : 
					{	
						m_eColourFadePhase = FADE_PHASE_ATSTART;  
						m_fCurrentFadeDuration = Asura_Random::GetFloat( m_pxAdvLight->m_fMinStartColourTime, m_pxAdvLight->m_fMaxStartColourTime );
						break;
					}

					case FADE_PHASE_DOWN : 
					{
						m_eColourFadePhase = FADE_PHASE_ATEND; 
						m_fCurrentFadeDuration = Asura_Random::GetFloat( m_pxAdvLight->m_fMinEndColourTime, m_pxAdvLight->m_fMaxEndColourTime );
						break;
					}

					case FADE_PHASE_ATSTART : 
					{
						m_eColourFadePhase = FADE_PHASE_DOWN;  
						m_fCurrentFadeDuration = Asura_Random::GetFloat( m_pxAdvLight->m_fMinFadeDownDuration, m_pxAdvLight->m_fMaxFadeDownDuration );
						break;
					}

					case FADE_PHASE_ATEND : 
					{
						if(m_pxAdvLight->m_uLoopFade)
						{
							m_eColourFadePhase = FADE_PHASE_UP; 
							m_fCurrentFadeDuration = Asura_Random::GetFloat( m_pxAdvLight->m_fMinFadeUpDuration, m_pxAdvLight->m_fMaxFadeUpDuration );						
						}
						break;
					}

					default : break;// do nothing 
				}

				m_fFadeTimer = 0.0f;
			}
		}

		// update radius fade
		if( (m_pxAdvLight->m_fMinStartRadiusTime == -1.0f) && (m_pxAdvLight->m_fMaxStartRadiusTime == -1.0f) && 
			(m_pxAdvLight->m_fMinEndRadiusTime == -1.0f) && (m_pxAdvLight->m_fMaxEndRadiusTime == -1.0f) )
		{
			m_eRadiusPhase = FADE_PHASE_NONE;
		}
		else
		{
			if(m_eRadiusPhase == FADE_PHASE_NONE)
			{
				m_eRadiusPhase = FADE_PHASE_ATSTART;
			}

			m_fRadiusTimer += fTimeSlice;
			
			// if we're currently fading, set the current colour of the photon
			if( (m_eRadiusPhase == FADE_PHASE_DOWN) && (m_fCurrentRadiusDuration > 0.0f) )
			{
				float fFadePercent = (m_fRadiusTimer / m_fCurrentRadiusDuration);
				if(fFadePercent > 1.0f) fFadePercent = 1.0f;
				m_pxPhoton->SetRange( m_pxAdvLight->m_fStartRadius + ((m_pxAdvLight->m_fEndRadius - m_pxAdvLight->m_fStartRadius) * fFadePercent) );
			}
			else if( (m_eRadiusPhase == FADE_PHASE_UP) && (m_fCurrentRadiusDuration > 0.0f) )
			{
				float fFadePercent = (m_fRadiusTimer / m_fCurrentRadiusDuration);
				if(fFadePercent > 1.0f) fFadePercent = 1.0f;
				m_pxPhoton->SetRange( m_pxAdvLight->m_fEndRadius + ((m_pxAdvLight->m_fStartRadius - m_pxAdvLight->m_fEndRadius) * fFadePercent) );
			}
			
			// check for phase end/switch
			if( (m_fRadiusTimer > m_fCurrentRadiusDuration) && (m_fCurrentRadiusDuration != -1.0f) )
			{
				switch(m_eRadiusPhase)
				{
				case FADE_PHASE_UP : 
					{	
						m_eRadiusPhase = FADE_PHASE_ATSTART;  
						m_fCurrentRadiusDuration = Asura_Random::GetFloat( m_pxAdvLight->m_fMinStartRadiusTime, m_pxAdvLight->m_fMaxStartRadiusTime );
						break;
					}
					
				case FADE_PHASE_DOWN : 
					{
						m_eRadiusPhase = FADE_PHASE_ATEND; 
						m_fCurrentRadiusDuration = Asura_Random::GetFloat( m_pxAdvLight->m_fMinEndRadiusTime, m_pxAdvLight->m_fMaxEndRadiusTime );
						break;
					}
					
				case FADE_PHASE_ATSTART : 
					{
						m_eRadiusPhase = FADE_PHASE_DOWN;  
						m_fCurrentRadiusDuration = Asura_Random::GetFloat( m_pxAdvLight->m_fMinRadiusDownDuration, m_pxAdvLight->m_fMaxRadiusDownDuration );
						break;
					}
					
				case FADE_PHASE_ATEND : 
					{
						if(m_pxAdvLight->m_uLoopRadius)
						{
							m_eRadiusPhase = FADE_PHASE_UP; 
							m_fCurrentRadiusDuration = Asura_Random::GetFloat( m_pxAdvLight->m_fMinRadiusUpDuration, m_pxAdvLight->m_fMaxRadiusUpDuration );						
						}
						break;
					}
					
				default : break;// do nothing 
				}
				
				m_fRadiusTimer = 0.0f;
			}
		}

	}
	else
	{
		// deactivate photon
		SetPhotonAndCoronaActive(false);
	}	 
}

Tools_Entity_AdvancedLight* Tools_Entity_AdvancedLight::s_pxCurrentSelectedAdvLight = NULL;
bool Tools_Entity_AdvancedLight::s_bResetCurrentLightPtrOnDeselect = true;

void Tools_Entity_AdvancedLight::CreateFlickerDlg(void)
{
	if(Asura_Overlay_System::DoesOverlayExist(TOOLS_OVERLAY_ADVLIGHTFLICKER)) return;

	Asura_Overlay* pxNewOverlay = new Asura_Overlay( "Flicker & Strobe", false );
	Asura_Dialog* pxNewDialog;
	Asura_Vector_2 xOffset(1.0f,3.0f);

	if(!s_pxCurrentSelectedAdvLight) return;
	Tools_Entity_AdvancedLight* pxObject = s_pxCurrentSelectedAdvLight;

	pxNewDialog = new Asura_Tickbox_Dialog("Use Flicker & Strobe", xOffset, &pxObject->m_bFlicker, &s_bModified);
	pxNewDialog->SetHelpText("Activates the settings on this overlay.");
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y+=Asura_Dialog::LargeSpacing();
	xOffset.x+=2.0f;
	
    pxObject->m_pxMinTimeOffDlg = new Asura_Numerical_Dialog("Min Time Off",xOffset,&(pxObject->m_pxAdvLight->m_fMinTimeOff), 0,100.0f,0.01f,"%0.2f",&s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxMinTimeOffDlg);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
    pxObject->m_pxMaxTimeOffDlg = new Asura_Numerical_Dialog("Max Time Off",xOffset,&(pxObject->m_pxAdvLight->m_fMaxTimeOff), 0,100.0f,0.01f,"%0.2f",&s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxMaxTimeOffDlg);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
    pxObject->m_pxMinTimeOnDlg = new Asura_Numerical_Dialog("Min Time On",xOffset,&(pxObject->m_pxAdvLight->m_fMinTimeOn), 0,100.0f,0.01f,"%0.2f",&s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxMinTimeOnDlg);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
    pxObject->m_pxMaxTimeOnDlg = new Asura_Numerical_Dialog("Max Time On",xOffset,&(pxObject->m_pxAdvLight->m_fMaxTimeOn), 0,100.0f,0.01f,"%0.2f",&s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxMaxTimeOnDlg);
	xOffset.y+=Asura_Dialog::LargeSpacing();
	xOffset.x -= 2.0f;

	pxNewOverlay->m_uID = TOOLS_OVERLAY_ADVLIGHTFLICKER;	
	Asura_Overlay_System::SubmitNewOverlay(pxNewOverlay);
}

void Tools_Entity_AdvancedLight::CreateColourFadeDlg(void)
{
	if(Asura_Overlay_System::DoesOverlayExist(TOOLS_OVERLAY_ADVLIGHTCOLOURFADE)) return;

	Asura_Overlay* pxNewOverlay = new Asura_Overlay( "Colour Fade", false );
	Asura_Dialog* pxNewDialog;
	Asura_Vector_2 xOffset(1.0f,3.0f);
	
	if(!s_pxCurrentSelectedAdvLight) return;
	Tools_Entity_AdvancedLight* pxObject = s_pxCurrentSelectedAdvLight;
	
	pxNewDialog = new Asura_Tickbox_Dialog("Use Colour Fade", xOffset, &pxObject->m_bColourFade, &s_bModified );
	pxNewDialog->SetHelpText("Activates the settings on this overlay.");
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y+=Asura_Dialog::LargeSpacing();
	xOffset.x+=2.0f;

	xOffset.x += 16.0f;
	pxNewDialog = new Tools_ColourPicker_Dialog("Start Colour",xOffset,Asura_Vector_2(4.0f,3.0f),&(pxObject->m_pxAdvLight->m_fStartColourR),&(pxObject->m_pxAdvLight->m_fStartColourG),&(pxObject->m_pxAdvLight->m_fStartColourB),255.0f,&s_bModified);
	pxNewDialog->SetHelpText("Starting colour for fade");
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.x -= 16.0f;
	
	
	pxNewDialog = new Asura_Numerical_Dialog("Start Red",xOffset,&(pxObject->m_pxAdvLight->m_fStartColourR),0.0f,255.0f,1.0f,"%0.0f", &s_bModified);
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

	pxNewDialog = new Asura_Numerical_Dialog("Start Green",xOffset,&(pxObject->m_pxAdvLight->m_fStartColourG),0.0f,255.0f,1.0f,"%0.0f", &s_bModified);
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

	pxNewDialog = new Asura_Numerical_Dialog("Start Blue",xOffset,&(pxObject->m_pxAdvLight->m_fStartColourB),0.0f,255.0f,1.0f,"%0.0f", &s_bModified);
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();


	xOffset.x += 16.0f;
	pxNewDialog = new Tools_ColourPicker_Dialog("End Colour",xOffset,Asura_Vector_2(4.0f,3.0f),&(pxObject->m_pxAdvLight->m_fEndColourR),&(pxObject->m_pxAdvLight->m_fEndColourG),&(pxObject->m_pxAdvLight->m_fEndColourB),255.0f,&s_bModified);
	pxNewDialog->SetHelpText("End colour for fade");
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.x -= 16.0f;

	pxNewDialog = new Asura_Numerical_Dialog("End Red",xOffset,&(pxObject->m_pxAdvLight->m_fEndColourR),0.0f,255.0f,1.0f,"%0.0f", &s_bModified);
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
	pxNewDialog = new Asura_Numerical_Dialog("End Green",xOffset,&(pxObject->m_pxAdvLight->m_fEndColourG),0.0f,255.0f,1.0f,"%0.0f", &s_bModified);
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
	pxNewDialog = new Asura_Numerical_Dialog("End Blue",xOffset,&(pxObject->m_pxAdvLight->m_fEndColourB),0.0f,255.0f,1.0f,"%0.0f", &s_bModified);
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

    pxObject->m_pxMinStartColourTimeDlg = new Asura_Numerical_Dialog("Min Start Colour Time",xOffset,&(pxObject->m_pxAdvLight->m_fMinStartColourTime), 0,100.0f,0.01f,"%0.2f", &s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxMinStartColourTimeDlg);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
    pxObject->m_pxMaxStartColourTimeDlg = new Asura_Numerical_Dialog("Max Start Colour Time",xOffset,&(pxObject->m_pxAdvLight->m_fMaxStartColourTime), 0,100.0f,0.01f,"%0.2f", &s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxMaxStartColourTimeDlg);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

	pxObject->m_pxMinFadeDownTimeDlg = new Asura_Numerical_Dialog("Min Fade Down Time",xOffset,&(pxObject->m_pxAdvLight->m_fMinFadeDownDuration), 0,100.0f,0.01f,"%0.2f", &s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxMinFadeDownTimeDlg);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
    pxObject->m_pxMaxFadeDownTimeDlg = new Asura_Numerical_Dialog("Max Fade Down Time",xOffset,&(pxObject->m_pxAdvLight->m_fMaxFadeDownDuration), 0,100.0f,0.01f,"%0.2f", &s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxMaxFadeDownTimeDlg);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

    pxObject->m_pxMinEndColourTimeDlg = new Asura_Numerical_Dialog("Min End Colour Time",xOffset,&(pxObject->m_pxAdvLight->m_fMinEndColourTime), 0,100.0f,0.01f,"%0.2f", &s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxMinEndColourTimeDlg);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
    pxObject->m_pxMaxEndColourTimeDlg = new Asura_Numerical_Dialog("Max End Colour Time",xOffset,&(pxObject->m_pxAdvLight->m_fMaxEndColourTime), 0,100.0f,0.01f,"%0.2f", &s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxMaxEndColourTimeDlg);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

	pxObject->m_pxMinFadeUpTimeDlg = new Asura_Numerical_Dialog("Min Fade Up Time",xOffset,&(pxObject->m_pxAdvLight->m_fMinFadeUpDuration), 0,100.0f,0.01f,"%0.2f", &s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxMinFadeUpTimeDlg);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
    pxObject->m_pxMaxFadeUpTimeDlg = new Asura_Numerical_Dialog("Max Fade Up Time",xOffset,&(pxObject->m_pxAdvLight->m_fMaxFadeUpDuration), 0,100.0f,0.01f,"%0.2f", &s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxMaxFadeUpTimeDlg);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	xOffset.x -= 2.0f;

	pxNewOverlay->m_uID = TOOLS_OVERLAY_ADVLIGHTCOLOURFADE;	
	Asura_Overlay_System::SubmitNewOverlay(pxNewOverlay);
}


void Tools_Entity_AdvancedLight::CreateRangeFadeDlg(void)
{
	if(Asura_Overlay_System::DoesOverlayExist(TOOLS_OVERLAY_ADVLIGHTRANGEFADE)) return;

	Asura_Overlay* pxNewOverlay = new Asura_Overlay( "Range Fade", false );
	Asura_Dialog* pxNewDialog;
	Asura_Vector_2 xOffset(1.0f,3.0f);
	
	if(!s_pxCurrentSelectedAdvLight) return;
	Tools_Entity_AdvancedLight* pxObject = s_pxCurrentSelectedAdvLight;
	
	pxNewDialog = new Asura_Tickbox_Dialog("Use Range Fade", xOffset, &pxObject->m_bRangeFade, &s_bModified);
	pxNewDialog->SetHelpText("Activates the settings on this overlay.");
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y+=Asura_Dialog::LargeSpacing();
	xOffset.x+=2.0f;
	

	pxObject->m_pxStartRangeDlg = new Asura_Numerical_Dialog("Start Range",xOffset,&(pxObject->m_pxAdvLight->m_fStartRadius), 0,999.0f,0.1f,"%0.1f", &s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxStartRangeDlg);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
	pxObject->m_pxEndRangeDlg  = new Asura_Numerical_Dialog("End Range",xOffset,&(pxObject->m_pxAdvLight->m_fEndRadius), 0,999.0f,0.1f,"%0.1f", &s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxEndRangeDlg);
	xOffset.y+=Asura_Dialog::LargeSpacing();
	
	
    pxObject->m_pxMinStartRangeTimeDlg = new Asura_Numerical_Dialog("Min Start Range Time",xOffset,&(pxObject->m_pxAdvLight->m_fMinStartRadiusTime), 0,100.0f,0.01f,"%0.2f", &s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxMinStartRangeTimeDlg);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
    pxObject->m_pxMaxStartRangeTimeDlg = new Asura_Numerical_Dialog("Max Start Range Time",xOffset,&(pxObject->m_pxAdvLight->m_fMaxStartRadiusTime), 0,100.0f,0.01f,"%0.2f", &s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxMaxStartRangeTimeDlg);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
	pxObject->m_pxMinRangeDownTimeDlg = new Asura_Numerical_Dialog("Min Fade Down Time",xOffset,&(pxObject->m_pxAdvLight->m_fMinRadiusDownDuration), 0,100.0f,0.01f,"%0.2f", &s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxMinRangeDownTimeDlg);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
    pxObject->m_pxMaxRangeDownTimeDlg = new Asura_Numerical_Dialog("Max Fade Down Time",xOffset,&(pxObject->m_pxAdvLight->m_fMaxRadiusDownDuration), 0,100.0f,0.01f,"%0.2f", &s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxMaxRangeDownTimeDlg);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
    pxObject->m_pxMinEndRangeTimeDlg = new Asura_Numerical_Dialog("Min End Range Time",xOffset,&(pxObject->m_pxAdvLight->m_fMinEndRadiusTime), 0,100.0f,0.01f,"%0.2f", &s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxMinEndRangeTimeDlg);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
    pxObject->m_pxMaxEndRangeTimeDlg = new Asura_Numerical_Dialog("Max End Range Time",xOffset,&(pxObject->m_pxAdvLight->m_fMaxEndRadiusTime), 0,100.0f,0.01f,"%0.2f", &s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxMaxEndRangeTimeDlg);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
	pxObject->m_pxMinRangeUpTimeDlg = new Asura_Numerical_Dialog("Min Fade Up Time",xOffset,&(pxObject->m_pxAdvLight->m_fMinRadiusUpDuration), 0,100.0f,0.01f,"%0.2f", &s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxMinRangeUpTimeDlg);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
    pxObject->m_pxMaxRangeUpTimeDlg = new Asura_Numerical_Dialog("Max Fade Up Time",xOffset,&(pxObject->m_pxAdvLight->m_fMaxRadiusUpDuration), 0,100.0f,0.01f,"%0.2f", &s_bModified);
	pxNewOverlay->AddDialog(pxObject->m_pxMaxRangeUpTimeDlg);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	xOffset.x -= 2.0f;
	
	pxNewOverlay->m_uID = TOOLS_OVERLAY_ADVLIGHTRANGEFADE;	
	Asura_Overlay_System::SubmitNewOverlay(pxNewOverlay);	
}


void Tools_Entity_AdvancedLight::CreateAttachDlg(void)
{
	Asura_Overlay* pxNewOverlay = new Asura_Overlay( "Attach To Object", false );
	Asura_Dialog* pxNewDialog;
	Asura_Vector_2 xOffset(1.0f,3.0f);
	
	s_bResetCurrentLightPtrOnDeselect = false;

	if(!s_pxCurrentSelectedAdvLight) return;
	Tools_Entity_AdvancedLight* pxObject = s_pxCurrentSelectedAdvLight;

	pxNewDialog = new Asura_Function_Dialog("Attach", xOffset, SetMasterObject );
	pxNewDialog->SetHelpText("Attaches this light to the selected object.");
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
	pxNewDialog = new Asura_Function_Dialog("Set Offset", xOffset, SetAttachOffset );
	pxNewDialog->SetHelpText("Light should maintain the current offset from the object that it is attached to.");
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

	pxNewDialog = new Asura_Function_Dialog("Set Marker", xOffset, SetAttachMarker );
	pxNewDialog->SetHelpText("Attaches the light to a marker point on an animating object.");
	pxNewDialog->m_iControlID = DialogID_SelectMarker;
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y+=Asura_Dialog::LargeSpacing();


	pxNewDialog = new Asura_Tickbox_Dialog( "Use Master Orient", xOffset, &(pxObject->m_bUseMasterOrient), &s_bModified );
	pxNewDialog->SetHelpText("Light should use the orientation of the object/marker point that it is attached to.");
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();

	pxNewOverlay->m_uID = TOOLS_OVERLAY_ADVLIGHTATTACHMAIN;
	Asura_Overlay_System::SubmitNewOverlay(pxNewOverlay);	

	UpdateAttachDlg();
}

void Tools_Entity_AdvancedLight::UpdateAttachDlg()
{
	Asura_Overlay* pxOverlay = Asura_Overlay_System::GetOverlay(TOOLS_OVERLAY_ADVLIGHTATTACHMAIN);
	if(!pxOverlay) return;

	//get marker name
	Asura_String xName;
	GetAttachMarkerName(xName);

	char szText[200];
	sprintf(szText,"Marker : %s",xName.GetString());
	//update the marker point control
	pxOverlay->UpdateDialogLabel(DialogID_SelectMarker,szText);
}

void Tools_Entity_AdvancedLight::CreateSelectMasterDlg(void)
{
	Asura_Overlay* pxNewOverlay = new Asura_Overlay( "Select Master", false );
	Asura_Dialog* pxNewDialog;
	Asura_Vector_2 xOffset(1.0f,3.0f);

	pxNewDialog = new Asura_Function_Dialog("Attach", xOffset, SetMasterObject );
	pxNewOverlay->AddDialog(pxNewDialog);
	xOffset.y+=Asura_Dialog::DefaultSpacing();
	
	pxNewOverlay->m_uID = TOOLS_OVERLAY_ADVLIGHTATTACH;
	Asura_Overlay_System::SubmitNewOverlay(pxNewOverlay,false,false);	
}


void Tools_Entity_AdvancedLight::SetMasterObject(void)
{
	if(!s_pxCurrentSelectedAdvLight) 
	{
		Tools_Timed_Message_System::AddMessage( 0xff0000, "ERROR - lost light pointer!" );	
	}
	else
	{
		if( Tools_Object_System::SelectedObject->GetGuid() != s_pxCurrentSelectedAdvLight->GetGuid() )
		{
			s_pxCurrentSelectedAdvLight->m_pxAdvLight->m_uMasterEntity = Tools_Object_System::SelectedObject->GetGuid();
		}
		else
		{
			Tools_Timed_Message_System::AddMessage( 0xff0000, "Can't attach light to itself! Select a different object!" );
		}
	}	

	s_bResetCurrentLightPtrOnDeselect = true;
	Asura_Overlay* pxOverlay = Asura_Overlay_System::GetOverlay(TOOLS_OVERLAY_ADVLIGHTATTACH);
	if(pxOverlay)
	{
		s_bModified = true;
		pxOverlay->m_bShouldClose = true;
	}	
	
	Tools_Object_System::SelectObject(s_pxCurrentSelectedAdvLight);
}

void Tools_Entity_AdvancedLight::SetAttachOffset(void)
{
	if( NULL == s_pxCurrentSelectedAdvLight)
	{
		Tools_Timed_Message_System::AddMessage( 0xff0000, "ERROR - No Selected Advance Light" );
		return;
	}
	if( NULL == s_pxCurrentSelectedAdvLight->m_pxAdvLight)
	{
		Tools_Timed_Message_System::AddMessage( 0xff0000, "ERROR - Selected Advance Light, Light Pointer is NULL" );
		return;
	}
	
	Tools_Object* pxMaster = Tools_Object_System::GetObjectFromGuid( s_pxCurrentSelectedAdvLight->m_pxAdvLight->m_uMasterEntity);
	if(!pxMaster) 
	{
		Tools_Timed_Message_System::AddMessage( 0xff0000, "ERROR - Couldn't find master object" );
		return;
	}

	s_bModified = true;

	s_pxCurrentSelectedAdvLight->m_pxAdvLight->m_xOffsetFromMaster = s_pxCurrentSelectedAdvLight->Position - pxMaster->Position;
}

void Tools_Entity_AdvancedLight::SetAttachMarker()
{
	if( NULL == s_pxCurrentSelectedAdvLight)
	{
		Tools_Timed_Message_System::AddMessage( 0xff0000, "ERROR - No Selected Advance Light" );
		return;
	}
	if( NULL == s_pxCurrentSelectedAdvLight->m_pxAdvLight)
	{
		Tools_Timed_Message_System::AddMessage( 0xff0000, "ERROR - Selected Advance Light, Light Pointer is NULL" );
		return;
	}
	
	Asura_ServerEntity_PhysicalObject* pxMaster = Asura_ServerEntity_PhysicalObject::FindEntity(s_pxCurrentSelectedAdvLight->m_pxAdvLight->m_uMasterEntity);
	if(!pxMaster) 
	{
		Tools_Timed_Message_System::AddMessage( 0xff0000, "ERROR - Couldn't find master object" );
		return;
	}

	//does the object use a skin?
	Asura_Hash_ID uSkin = pxMaster->GetSkinID();
	if(uSkin == ASURA_HASH_ID_UNSET)
	{
		Tools_Timed_Message_System::AddMessage( 0xff0000, "ERROR - Master object doesn't have a skin/hierarchy" );
		return;
	}

	//get the skin
	Asura_Hierarchy_Skin* pxSkin = Asura_Animation_System::GetSkinByHash(uSkin);
	if(!pxSkin)
	{
		Tools_Timed_Message_System::AddMessage(0xff0000,"Failed to find skin for master object. Unable to give list of marker points.");
		return;
	}
	
	if(!pxSkin->NumberOfMarkerPoints)
	{
		Tools_Timed_Message_System::AddMessage(0xff0000,"The master object's skin doesn't have any marker points");
		return;
	}

	//add all the marker points to a selection overlay
	ListSelection_Overlay xOverlay("Select marker point to attach light to");
	for(int i=0;i<pxSkin->NumberOfMarkerPoints;i++)
	{
		xOverlay.AddItem(pxSkin->MarkerPoint[i].GetName().GetString(),Asura_GetHashID(pxSkin->MarkerPoint[i].GetName().GetString()));
	}
	//add option for clearing marker point
	xOverlay.AddItem("*None*",ASURA_HASH_ID_UNSET);
	if(!xOverlay.DoModal()) return;

	s_bModified = true;
	s_pxCurrentSelectedAdvLight->m_pxAdvLight->m_uMasterMarker = (Asura_Hash_ID)xOverlay.GetSelectionData();

	UpdateAttachDlg();

}

void Tools_Entity_AdvancedLight::GetAttachMarkerName(Asura_String& xName)
{
	if( NULL == s_pxCurrentSelectedAdvLight)
	{
		Tools_Timed_Message_System::AddMessage( 0xff0000, "ERROR - No Selected Advance Light" );
		return;
	}
	if( NULL == s_pxCurrentSelectedAdvLight->m_pxAdvLight)
	{
		Tools_Timed_Message_System::AddMessage( 0xff0000, "ERROR - Selected Advance Light, Light Pointer is NULL" );
		return;
	}
	
	Asura_Hash_ID uMarkerHash = s_pxCurrentSelectedAdvLight->m_pxAdvLight->m_uMasterMarker;
	if(!uMarkerHash)
	{
		xName = "*None*";
		return;
	}
	//default to "unknown"
	xName = "*Unknown*";

	
	Asura_ServerEntity_PhysicalObject* pxMaster = Asura_ServerEntity_PhysicalObject::FindEntity(s_pxCurrentSelectedAdvLight->m_pxAdvLight->m_uMasterEntity);
	if(!pxMaster) 
	{
		return;
	}

	//does the object use a skin?
	Asura_Hash_ID uSkin = pxMaster->GetSkinID();
	if(uSkin == ASURA_HASH_ID_UNSET)
	{
		return;
	}

	//get the skin
	Asura_Hierarchy_Skin* pxSkin = Asura_Animation_System::GetSkinByHash(uSkin);
	if(!pxSkin)
	{
		Tools_Timed_Message_System::AddMessage(0xff0000,"Failed to find skin for master object. Unable to give list of marker points.");
		return;
	}
	
	//check the marker points for one with the correct hash
	for(int i=0;i<pxSkin->NumberOfMarkerPoints;i++)
	{
		if(uMarkerHash == Asura_GetHashID(pxSkin->MarkerPoint[i].GetName().GetString()))
		{
			xName = pxSkin->MarkerPoint[i].GetName().GetString();
			return;
		}
	}
}

void Tools_Entity_AdvancedLight::UnattachLight(void)
{
	s_pxCurrentSelectedAdvLight->m_pxAdvLight->m_uMasterEntity = ASURA_GUID_UNREGISTERED;
	s_pxCurrentSelectedAdvLight->m_pxAdvLight->m_xOffsetFromMaster = Asura_Maths::ZeroVector3;
	s_pxCurrentSelectedAdvLight->m_pxAdvLight->m_uUseMasterOrient  = true;
	s_pxCurrentSelectedAdvLight->m_pxAdvLight->m_uMasterMarker  = ASURA_HASH_ID_UNSET;

	s_bModified = true;
}



Tools_Object* Tools_Entity_AdvancedLight::CreateObjectOfThisType() const
{
	Tools_Object* pxOldSelection = Tools_Object_System::SelectedObject;
	Tools_Entity_AdvancedLight::Project_Create();
	Tools_Object* pxNewSelection = Tools_Object_System::SelectedObject;

	return (pxOldSelection!=pxNewSelection) ? pxNewSelection : 0;
}

void Tools_Entity_AdvancedLight::Copy(const Tools_Object* pxObject)
{
	const Tools_Entity_AdvancedLight* pxFromObject = s_xList.FindEntity(pxObject->GetGuid());
	if(!pxFromObject)
	{
		Asura_Assert(pxFromObject,"Failed to find advanced light in list");
		return;
	}

	//get the entities to copy between
	Asura_ServerEntity_AdvancedLight* pxFromEntity = pxFromObject->m_pxAdvLight;
	Asura_ServerEntity_AdvancedLight* pxToEntity = m_pxAdvLight;

	//copy between entities
	#define COPY_ENTITY_PARAM(PARAM) pxToEntity->PARAM = pxFromEntity->PARAM

	COPY_ENTITY_PARAM(m_fMinTimeOff);
	COPY_ENTITY_PARAM(m_fMaxTimeOff);
	COPY_ENTITY_PARAM(m_fMinTimeOn);
	COPY_ENTITY_PARAM(m_fMaxTimeOn);

	COPY_ENTITY_PARAM(m_fEndColourR);
	COPY_ENTITY_PARAM(m_fEndColourG);
	COPY_ENTITY_PARAM(m_fEndColourB);

	COPY_ENTITY_PARAM(m_fStartColourR);
	COPY_ENTITY_PARAM(m_fStartColourG);
	COPY_ENTITY_PARAM(m_fStartColourB);

	COPY_ENTITY_PARAM(m_fMaxFadeDownDuration);
	COPY_ENTITY_PARAM(m_fMinFadeDownDuration);
	COPY_ENTITY_PARAM(m_fMaxFadeUpDuration);
	COPY_ENTITY_PARAM(m_fMinFadeUpDuration);

	COPY_ENTITY_PARAM(m_fMinStartColourTime);
	COPY_ENTITY_PARAM(m_fMaxStartColourTime);
	COPY_ENTITY_PARAM(m_fMinEndColourTime);
	COPY_ENTITY_PARAM(m_fMaxEndColourTime);

	COPY_ENTITY_PARAM(m_fStartRadius);
	COPY_ENTITY_PARAM(m_fEndRadius);

	COPY_ENTITY_PARAM(m_fMinStartRadiusTime);
	COPY_ENTITY_PARAM(m_fMaxStartRadiusTime);
	COPY_ENTITY_PARAM(m_fMinEndRadiusTime);
	COPY_ENTITY_PARAM(m_fMaxEndRadiusTime);

	COPY_ENTITY_PARAM(m_uLoopRadius);
	COPY_ENTITY_PARAM(m_uLoopFade);
	COPY_ENTITY_PARAM(m_uUseMasterOrient);
	COPY_ENTITY_PARAM(m_uActive);

	COPY_ENTITY_PARAM(m_uMasterEntity);
	COPY_ENTITY_PARAM(m_xOffsetFromMaster);
	COPY_ENTITY_PARAM(m_uMasterMarker);

	#undef COPY_ENTITY_PARAM

	//copy between the tools objects

	#define COPY_TOOLS_PARAM(PARAM) PARAM = pxFromObject->PARAM

	COPY_TOOLS_PARAM(m_fStrobeTimer);
	COPY_TOOLS_PARAM(m_fCurrentStrobeDuration);

	COPY_TOOLS_PARAM(m_fFadeTimer);
	COPY_TOOLS_PARAM(m_fCurrentFadeDuration);
	COPY_TOOLS_PARAM(m_eColourFadePhase);

	COPY_TOOLS_PARAM(m_fRadiusTimer);
	COPY_TOOLS_PARAM(m_fCurrentRadiusDuration);
	COPY_TOOLS_PARAM(m_eColourFadePhase);

	COPY_TOOLS_PARAM(m_bFlicker);
	COPY_TOOLS_PARAM(m_bColourFade);
	COPY_TOOLS_PARAM(m_bRangeFade);

	COPY_TOOLS_PARAM(m_bPrevFlicker);
	COPY_TOOLS_PARAM(m_bPrevColourFade);
	COPY_TOOLS_PARAM(m_bPrevRangeFade);

	COPY_TOOLS_PARAM(m_bActive);
	COPY_TOOLS_PARAM(m_bUseMasterOrient);

	COPY_TOOLS_PARAM(m_fEndColourR);
	COPY_TOOLS_PARAM(m_fEndColourG);
	COPY_TOOLS_PARAM(m_fEndColourB);

	COPY_TOOLS_PARAM(m_fStartColourR);
	COPY_TOOLS_PARAM(m_fStartColourG);
	COPY_TOOLS_PARAM(m_fStartColourB);

	#undef COPY_TOOLS_PARAM

	//update the light
	SetPhotonToValuesOfEntity();

}

#endif // #ifndef ASURA_TARGET_SM3
