////////////////////////////////////////////////////
//
// Particles Generator and Source
//
////////////////////////////////////////////////////
#include "StdAfx.h"

#define D_MSPrtSrc_StructureDefine

#include "TPG_OGen.hpp"
#include "TPG_OEnv.hpp"
#include "TPG_OSys.hpp"
#include "_Minterf.hpp"
#include "TPG_Strg.hpp"
#include "TPG_ClBk.hpp"


#include "PRT.h"
#include "MTH.h"
#include "CTL.h"
#include "ErO.h" 

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


////////////////////////////////////////////
// Constructor and destructor
////////////////////////////////////////////
CPA_PartGen_Generator:: CPA_PartGen_Generator(CString _csName, tdxHandleToParticleGenerator _hGenerator, BOOL _bIsLoaded) 
					  : CPA_SaveObject( g_pclInterface, g_C_csPartGenGeneratorName, E_ss_Responsible )
{
	//*** initialization for CPA_SaveObject
	SetSectionData( this );
	SetCallBackSave( m_s_fn_vCallBackSaveGenerator );
	SetDataPath( C_szEffectPath );

	if ( fn_eRename(_csName) != E_mc_None )
		SetDefaultValidName();

	fn_vUpdateSectionName();

	//*** Section to save the associated source ***
	/*
	ERROR_PREPARE_M
		(
			g_c_csPartGenModuleNameForErrors,
			"Creating a new generator",
			"CPA_PartGen_Generator::CPA_PartGen_Generator",
			E_ERROR_GRAVITY_FATAL,
			"the new section for the source associated is not allocated"
		);

	m_pri_p_clSourceSection = new CPA_SectionObject
									( 
										m_pri_fn_csGetSourceReferencedSectionName(), 
										C_szEffectPath,
										m_s_fn_vCallBackSaveSource,
										this
									);

	ERROR_ASSERT( m_pri_p_clSourceSection != NULL );
	*/

	if ( !_bIsLoaded ) //object find in a script file but not loaded in link table
	{
		fn_vUpdateData(NULL);
		m_pri_hGenerator = NULL;
		//m_pri_p_stSource = NULL;

		SetExistingSection( TRUE );
		//m_pri_p_clSourceSection->SetExistingSection( TRUE );
	}
	else 
	{
		if ( _hGenerator == NULL ) 
		{
			SetExistingSection( FALSE );
			//m_pri_p_clSourceSection->SetExistingSection( FALSE );

			// for a new generator, initializes all the values
			ERROR_PREPARE_M
				(
					g_c_csPartGenModuleNameForErrors,
					"Creating a new generator",
					"CPA_PartGen_Generator::CPA_PartGen_Generator",
					E_ERROR_GRAVITY_FATAL,
					"the engine object generator is not allocated"
				);

			_hGenerator= fn_hParticleGeneratorAllocation();
			ERROR_ASSERT( _hGenerator != NULL );
			fn_vUpdateData( (void*)_hGenerator );
			m_pri_hGenerator = _hGenerator;
			m_pub_fn_vSetEnvActiveWater( TRUE );
			m_pub_fn_vSetEnvActiveAir( TRUE );
			m_pub_fn_vSetLinkToEnv( FALSE );
	
			/*
			ERROR_PREPARE_M
				(
					g_c_csPartGenModuleNameForErrors,
					"Creating a new generator",
					"CPA_PartGen_Generator::CPA_PartGen_Generator",
					E_ERROR_GRAVITY_FATAL,
					"the engine object source is not allocated"
				);
			PRT_fn_vCreateParticlesSource( &m_pri_p_stSource );
			ERROR_ASSERT( m_pri_p_stSource != NULL );
			fn_vPrtGenSetSrc( m_pri_hGenerator, m_pri_p_stSource );
			
			m_pub_fn_vSetGenerationMode( (short)PRT_C_ucNoGeneration );
			m_pub_fn_vSetNbGenerateMode( (short)PRT_C_ucConstantNb );
			m_pub_fn_vSetGeometryMode( (short)PRT_C_ucPoint);
			m_pub_fn_vSetLinkMode( (short)PRT_C_ucRotationLink);
			m_pub_fn_vSetSpeed( (double)0 );
			m_pub_fn_vSetSpeedRange( (double)0 );
			*/

			m_pri_fn_vFillDataList();
		}
		else 
		{	
			SetExistingSection( TRUE );
			//m_pri_p_clSourceSection->SetExistingSection( TRUE );

			fn_vUpdateData( (void*)_hGenerator );
			m_pri_hGenerator = _hGenerator;
			//m_pri_p_stSource = fn_p_stPrtGenGetSrc(m_pri_hGenerator);

			CPA_PartGen_Environment *p_clEnv = m_pub_fn_p_clGetEnv();
			p_clEnv->m_pub_fn_vSetGenerator( this );
			
			m_pri_fn_vFillDataList();
		}
	}
	SetAvailable( _bIsLoaded );
}

CPA_PartGen_Generator::~CPA_PartGen_Generator()
{
	fn_vNotifyUnSave();
}


///////////////////////////////////////
// Virtual functions
long CPA_PartGen_Generator::GetDataType( void )
{
	return( 0 );
}

void* CPA_PartGen_Generator::GetData( void )
{
	return (void*) m_pri_hGenerator;
}

CString CPA_PartGen_Generator::fn_csComputeReferencedSectionName(const CString _csNewName)
{
	CString csReturnedName =  "Generators.prt^";
	csReturnedName += C_SectionParticleGenerator;
	csReturnedName += ":";
	return( csReturnedName + _csNewName );
}

void CPA_PartGen_Generator::fn_vNotifySave( void )
{
	CPA_SaveObject::fn_vNotifySave();
	//m_pri_p_clSourceSection->fn_vWriteSection();
}

void CPA_PartGen_Generator::fn_vNotifyUnSave( void )
{
	CPA_SaveObject::fn_vNotifyUnSave();
	//m_pri_p_clSourceSection->fn_vDeleteSection();
}

//**************************************************
// Load if necessary
BOOL CPA_PartGen_Generator::m_pub_fn_vLoadIfUnloaded()
{
	if ( !fn_bIsAvailable() )
	{
		CString csSectionName = GetReferencedSectionName();

		SCR_tdst_Cxt_Values *p_stValues;
		p_stValues = SCR_fnp_st_RdL0_AnalyseSection((char *)LPCTSTR(csSectionName), SCR_CDF_uw_Anl_Normal);

		tdxHandleToParticleGenerator hGenerator = (tdxHandleToParticleGenerator)p_stValues->a_ulValues[0];
		fn_vUpdateData( (void*)hGenerator );
		m_pri_hGenerator = hGenerator;
		//m_pri_p_stSource = fn_p_stPrtGenGetSrc(m_pri_hGenerator);
		SetAvailable(TRUE);
		m_pri_fn_vFillDataList();

		return TRUE;
	}
	return FALSE;
}



/*
 ----------------------------------------------------------------------------------------
  Description   : set engine data 
  _hGenerator         -> engine generator
 ----------------------------------------------------------------------------------------
 */
void CPA_PartGen_Generator::m_pub_fn_vSetGenerator( tdxHandleToParticleGenerator _hGenerator)
{
	fn_vUpdateData( (void*) _hGenerator );
	m_pri_hGenerator = _hGenerator;
	SetAvailable( TRUE );

	m_pri_fn_vFillDataList();
}

//***************************************************************
// returns a pointer on the associated ParticleSource
CPA_PartGen_Source* CPA_PartGen_Generator::m_pub_fn_p_clGetSource()
{
	PRT_tdstParticlesSource *p_stPrtSrc;

	if( m_pri_hGenerator == NULL )
		return NULL;

	if( (p_stPrtSrc = fn_p_stPrtGenGetSrc( m_pri_hGenerator )) == NULL )
		return NULL;
	
	return g_pclInterface->m_pub_fn_p_clFindSourceWithEngine( p_stPrtSrc );
}


//***************************************************************
// returns a pointer on the system associated
CPA_PartGen_System* CPA_PartGen_Generator::m_pub_fn_p_clGetSystem()
{
	PRT_tdstParticlesSystem *p_stSystem;

	if( m_pri_hGenerator == NULL )
		return NULL;

	p_stSystem = fn_p_stPrtGenGetPrtSys( m_pri_hGenerator );
	if( p_stSystem == NULL )
		return NULL;
	
	return g_pclInterface->m_pub_fn_p_clFindSystemWithEngine( p_stSystem );
}

//***************************************************************
// returns a pointer on the environment associated
CPA_PartGen_Environment* CPA_PartGen_Generator::m_pub_fn_p_clGetEnv()
{
	PRT_tdstParticlesEnvironment *p_stEnv;

	if( m_pri_hGenerator == NULL )
		return NULL;

	p_stEnv = fn_p_stPrtGenGetPrtEnv( m_pri_hGenerator );
	if( p_stEnv == NULL )
		return NULL;
		
	return g_pclInterface->m_pub_fn_p_clFindEnvWithEngine( p_stEnv );
}

//***************************************************************
// returns a pointer on the linked generator associated
CPA_PartGen_Generator *CPA_PartGen_Generator::m_pub_fn_p_oGetLinkedPrtGen()
{
	tdxHandleToParticleGenerator hPrtGen;

	if( m_pri_hGenerator == NULL )
		return NULL;

	hPrtGen = fn_hPrtGenGetLinkedGen( m_pri_hGenerator );
	if( hPrtGen == NULL )
		return NULL;
		
	return g_pclInterface->m_pub_fn_p_clFindPrtGenWithEngine( hPrtGen );
}



///////////////////////////////////////////////
// Associated source, System and Environment

void CPA_PartGen_Generator::m_pub_fn_vSetSource( CPA_PartGen_Source* _p_oPrtSrc )
{
	if( _p_oPrtSrc != NULL )
		fn_vPrtGenSetSrc( m_pri_hGenerator, _p_oPrtSrc->m_pub_fn_p_stGetSource() );
	else
		fn_vPrtGenSetSrc( m_pri_hGenerator, NULL );
	fn_vNotifySave();
}

void CPA_PartGen_Generator::m_pub_fn_vSetSystem( CPA_PartGen_System* _p_clSystem )
{
	if( _p_clSystem != NULL )
		fn_vPrtGenSetPrtSys( m_pri_hGenerator, _p_clSystem->m_pub_fn_p_stGetSystem() );
	else
		fn_vPrtGenSetPrtSys( m_pri_hGenerator, NULL );
	fn_vNotifySave();
}

void CPA_PartGen_Generator::m_pub_fn_vSetEnv( CPA_PartGen_Environment* _p_clEnv )
{
	if( _p_clEnv != NULL )
		{
		fn_vPrtGenSetPrtEnv( m_pri_hGenerator, _p_clEnv->m_pub_fn_p_stGetEnv() );
		m_pub_fn_vSetGenInEnv();
		}
	else
		fn_vPrtGenSetPrtEnv( m_pri_hGenerator, NULL );

	
	fn_vNotifySave();
}

void CPA_PartGen_Generator::m_pub_fn_vSetGenInEnv()
{
	CPA_PartGen_Environment *p_clEnv = m_pub_fn_p_clGetEnv();
	p_clEnv->m_pub_fn_vSetGenerator( this );
}


//////////////////////////////////////////////////
// Link to environment
void CPA_PartGen_Generator::m_pub_fn_vSetLinkToEnv( BOOL _bFlag )
{
	fn_vPrtGenSetLinkValue( m_pri_hGenerator, (unsigned char)_bFlag );
	fn_vNotifySave();
}

BOOL CPA_PartGen_Generator::m_pub_fn_bGetLinkToEnv()
{
	return (BOOL)fn_ucPrtGenGetLinkValue( m_pri_hGenerator );
}


///////////////////////////////////////////////////////
// Environment Mask
void CPA_PartGen_Generator::m_pub_fn_vSetEnvActiveWater( BOOL _bFlag )
{
	long lMask = fn_lPrtGenGetEnvironmentMask( m_pri_hGenerator );
	lMask = ( _bFlag ? (lMask | C_lEnvironmentWater) : (lMask & (C_lAllEnvironments - C_lEnvironmentWater)) );
	fn_vPrtGenSetEnvironmentMask( m_pri_hGenerator, lMask );
	fn_vNotifySave();
}

void CPA_PartGen_Generator::m_pub_fn_vSetEnvActiveAir( BOOL _bFlag )
{
	long lMask = fn_lPrtGenGetEnvironmentMask( m_pri_hGenerator );
	lMask = ( _bFlag ? (lMask | C_lEnvironmentAir) : (lMask & (C_lAllEnvironments - C_lEnvironmentAir)) );
	fn_vPrtGenSetEnvironmentMask( m_pri_hGenerator, lMask );
	fn_vNotifySave();
}


long CPA_PartGen_Generator::m_pub_fn_lGetEnvironmentMask()
{
	return fn_lPrtGenGetEnvironmentMask( m_pri_hGenerator );
}


/////////////////////////////////////////////////////////
// CallBack and function for save
void CPA_PartGen_Generator::m_s_fn_vCallBackSaveGenerator
	(
		SCR_tdst_File_Description *_p_stFile,
		char *_p_szSectionName,
		void *_p_vData,
		SCR_tde_Ntfy_Action _eAction 
	)
{
	ERROR_PREPARE_M
		(
			g_c_csPartGenModuleNameForErrors,
			"Saving a generator",
			"CPA_PartGen_Generator::m_s_fn_vCallBackSaveGenerator",
			E_ERROR_GRAVITY_FATAL,
			"trying to save a NULL generator"
		);
	
	CPA_PartGen_Generator *p_clGen = (CPA_PartGen_Generator*)_p_vData;
	ERROR_ASSERT( p_clGen != NULL );
	CString csHeaderName = C_SectionParticleGenerator;
	
	switch( _eAction )
	{
		case SCR_EA_Ntfy_AddSection:
		case SCR_EA_Ntfy_AddOrModifySection:
		case SCR_EA_Ntfy_AddOrRebuildSection:
		case SCR_EA_Ntfy_RebuildSection:
		case SCR_EA_Ntfy_ModifySection:
			
			csHeaderName += ":";
			csHeaderName += p_clGen->GetName();

			SCR_M_SvL0_SaveBeginSection( _p_stFile, M_MAKECHAR(csHeaderName), SCR_CC_C_Cfg_EOL );
			p_clGen->m_pri_fn_vSaveGenerator( _p_stFile );
			SCR_M_SvL0_SaveEndSection( _p_stFile, SCR_CC_C_Cfg_EOL );

			p_clGen->fn_vSectionSaved();
			break;

		case SCR_EA_Ntfy_DeleteIfExists:
		case SCR_EA_Ntfy_DeleteSection:
			p_clGen->fn_vSectionDeleted();
			break;
		}
}

void CPA_PartGen_Generator::m_pri_fn_vSaveGenerator( SCR_tdst_File_Description *_p_stFile )
{
	// associated source
	CPA_PartGen_Source *p_oPrtSrc = m_pub_fn_p_clGetSource();
	if( p_oPrtSrc != NULL )
	{
		SCR_M_SvL0_SaveEntry( _p_stFile, C_EntryPrtGenLoadParticleSource, SCR_CC_C_Cfg_NoChar );
		SCR_fn_v_SvL0_SaveParameters_MP( _p_stFile, SCR_EF_SvL0_Scanf, 1, M_MAKECHAR( p_oPrtSrc->GetReferencedSectionName() ) );
	}

	// associated system
	CPA_PartGen_System *p_clSys = m_pub_fn_p_clGetSystem();
	if( p_clSys != NULL )
	{
		SCR_M_SvL0_SaveEntry( _p_stFile, C_EntryPrtGenLoadParticleSystem, SCR_CC_C_Cfg_NoChar );
		SCR_fn_v_SvL0_SaveParameters_MP( _p_stFile, SCR_EF_SvL0_Scanf, 1, M_MAKECHAR( p_clSys->GetReferencedSectionName() ) );
	}

	// associated environment
	CPA_PartGen_Environment *p_clEnv = m_pub_fn_p_clGetEnv();
	if( p_clEnv != NULL )
	{
		SCR_M_SvL0_SaveEntry( _p_stFile, C_EntryPrtGenLoadParticleEnvironment, SCR_CC_C_Cfg_NoChar );
		SCR_fn_v_SvL0_SaveParameters_MP( _p_stFile, SCR_EF_SvL0_Scanf, 1, M_MAKECHAR( p_clEnv->GetReferencedSectionName() ) );
	}

	// linked to environment
	SCR_M_SvL0_SaveEntry( _p_stFile, C_EntryPrtGenLinkedToEnvironment, SCR_CC_C_Cfg_NoChar );
	if( m_pub_fn_bGetLinkToEnv() )
		SCR_fn_v_SvL0_SaveParameters_MP( _p_stFile, SCR_EF_SvL0_Scanf, 1, C_szLinkedToEnvironment );
	else
		SCR_fn_v_SvL0_SaveParameters_MP( _p_stFile, SCR_EF_SvL0_Scanf, 1, C_szNotLinkedToEnvironment );

	// environment mask
	SCR_M_SvL0_SaveEntry( _p_stFile, C_EntryPrtGenEnvironmentMask, SCR_CC_C_Cfg_NoChar );
	SCR_fn_v_SvL0_SaveParameters_MP( _p_stFile, SCR_EF_SvL0_Scanf, 2, "%d", m_pub_fn_lGetEnvironmentMask() );

	// linked generator data
	CPA_PartGen_Generator *p_oPrtGen = m_pub_fn_p_oGetLinkedPrtGen();
	if (p_oPrtGen != NULL)
	{
		// linked generator mask
		SCR_M_SvL0_SaveEntry( _p_stFile, C_EntryPrtGenLinkedPrtGenMask, SCR_CC_C_Cfg_NoChar );
		SCR_fn_v_SvL0_SaveParameters_MP( _p_stFile, SCR_EF_SvL0_Scanf, 2, "%d", fn_lPrtGenGetEnvironmentMask( m_pri_hGenerator ) );

		// linked generator reference
		SCR_M_SvL0_SaveEntry( _p_stFile, C_EntryPrtGenLinkedPrtGen, SCR_CC_C_Cfg_NoChar );
		SCR_fn_v_SvL0_SaveParameters_MP( _p_stFile, SCR_EF_SvL0_Scanf, 1, M_MAKECHAR( p_oPrtGen->GetReferencedSectionName() ) );
	}
}




void CPA_PartGen_Generator::m_pri_fn_vFillDataList()
{
	m_pri_fn_vFillGeneratorDataList();
}


void CPA_PartGen_Generator::m_pri_fn_vFillGeneratorDataList()
{
	CTL_Editor_Data *p_clData = NULL;
	CTL_Editor_EnumDescriptor *p_clEnumDescriptor = NULL;
	CTL_Editor_MaskDescriptor *p_clMaskDescriptor = NULL;

	//*** Associated Source **************************
	p_clEnumDescriptor = m_pub_fn_p_clGetDocument()->m_pub_fn_p_clGetEnumDescriptorByName( "Generator_Source" );
	p_clData = m_pub_clGeneratorDataList.m_fn_pclAddEnumData( p_clEnumDescriptor, "Source" );
	p_clData->m_fn_vSetMotorDataPtr( (void*)&(m_pri_hGenerator->p_stPrtSrc) );
	p_clData->m_pub_fn_vSetModificationFunctionWhenWrite( g_fn_vModificationWriteGeneratorSource );
	p_clData->m_pub_fn_pclAddOwnerData( (void*)this, "EditedGenerator" );
	p_clData->m_pub_fn_vSetDataChangedSpecialCallBackFunction( g_fn_vCallBackDataChangedSpecialDisplayAll );
	p_clData->m_pub_fn_vSetDataChangedCallBackFunction( g_fn_vCallBackDataChangedGenerator );

	//*** Associated System **************************
	p_clEnumDescriptor = m_pub_fn_p_clGetDocument()->m_pub_fn_p_clGetEnumDescriptorByName( "Generator_System" );
	p_clData = m_pub_clGeneratorDataList.m_fn_pclAddEnumData( p_clEnumDescriptor, "System" );
	p_clData->m_fn_vSetMotorDataPtr( (void*)&(m_pri_hGenerator->p_stPrtSys) );
	p_clData->m_pub_fn_vSetModificationFunctionWhenWrite( g_fn_vModificationWriteGeneratorSystem );
	p_clData->m_pub_fn_pclAddOwnerData( (void*)this, "EditedGenerator" );
	p_clData->m_pub_fn_vSetDataChangedSpecialCallBackFunction( g_fn_vCallBackDataChangedSpecialDisplayAll );
	p_clData->m_pub_fn_vSetDataChangedCallBackFunction( g_fn_vCallBackDataChangedGenerator );

	//*** Associated environment *********************
	p_clEnumDescriptor = m_pub_fn_p_clGetDocument()->m_pub_fn_p_clGetEnumDescriptorByName( "Generator_Env" );
	p_clData = m_pub_clGeneratorDataList.m_fn_pclAddEnumData( p_clEnumDescriptor, "Environment" );
	p_clData->m_fn_vSetMotorDataPtr( (void*)&(m_pri_hGenerator->p_stPrtEnv) );
	p_clData->m_pub_fn_vSetModificationFunctionWhenWrite( g_fn_vModificationWriteGeneratorEnvironment );
	p_clData->m_pub_fn_pclAddOwnerData( (void*)this, "EditedGenerator" );
	p_clData->m_pub_fn_vSetDataChangedSpecialCallBackFunction( g_fn_vCallBackDataChangedSpecialDisplayAll );
	p_clData->m_pub_fn_vSetDataChangedCallBackFunction( g_fn_vCallBackDataChangedGenerator );

	//*** Environment Mask ************************
	p_clMaskDescriptor = m_pub_fn_p_clGetDocument()->m_pub_fn_p_clGetMaskDescriptorByName( "Generator_Mask_Env" );
	p_clData = m_pub_clGeneratorDataList.m_fn_pclAddMaskedData( p_clMaskDescriptor, "Environment Mask" );
	p_clData->m_fn_vSetMotorDataPtr( (void*)&(m_pri_hGenerator->lEnvironmentMask) );
	p_clData->m_pub_fn_pclAddOwnerData( (void*)this, "EditedGenerator" );
	p_clData->m_pub_fn_vSetDataChangedCallBackFunction( g_fn_vCallBackDataChangedGenerator );

	//*** Link To Environment ************************
	p_clData = m_pub_clGeneratorDataList.m_fn_pclAddBooleanData( "Link To Environment" );
	p_clData->m_fn_vSetMotorDataPtr( (void*)&(m_pri_hGenerator->ucLinkedToEnvironment) );
	p_clData->m_pub_fn_pclAddOwnerData( (void*)this, "EditedGenerator" );
	p_clData->m_pub_fn_vSetDataChangedCallBackFunction( g_fn_vCallBackDataChangedGenerator );

	//*** Linked generator mask ************************
	p_clMaskDescriptor = m_pub_fn_p_clGetDocument()->m_pub_fn_p_clGetMaskDescriptorByName( "Generator_Mask_LinkedGen" );
	p_clData = m_pub_clGeneratorDataList.m_fn_pclAddMaskedData( p_clMaskDescriptor, "Linked Generator Mask" );
	p_clData->m_fn_vSetMotorDataPtr( (void*)&(m_pri_hGenerator->ulLinkedPrtGenMask) );
	p_clData->m_pub_fn_pclAddOwnerData( (void*)this, "EditedGenerator" );
	p_clData->m_pub_fn_vSetDataChangedCallBackFunction( g_fn_vCallBackDataChangedGenerator );

	//*** linked generator **************************
	p_clEnumDescriptor = m_pub_fn_p_clGetDocument()->m_pub_fn_p_clGetEnumDescriptorByName( "Generator_LinkedGenerator" );
	p_clData = m_pub_clGeneratorDataList.m_fn_pclAddEnumData( p_clEnumDescriptor, "Linked Generator" );
	p_clData->m_fn_vSetMotorDataPtr( (void*)&(m_pri_hGenerator->p_stLinkedPrtGen) );
	p_clData->m_pub_fn_vSetModificationFunctionWhenWrite( g_fn_vModificationWriteGeneratorLinkedGenerator );
	p_clData->m_pub_fn_pclAddOwnerData( (void*)this, "EditedGenerator" );
	p_clData->m_pub_fn_vSetDataChangedSpecialCallBackFunction( g_fn_vCallBackDataChangedSpecialDisplayAll );
	p_clData->m_pub_fn_vSetDataChangedCallBackFunction( g_fn_vCallBackDataChangedGenerator );
}

CPA_PartGen_MyDocument * CPA_PartGen_Generator::m_pub_fn_p_clGetDocument()
{
	return g_pclInterface->m_pub_fn_p_clGetDocument();
}