///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
// delete all ModifSections ........
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ACP_Base.h"

#include "ITF.h"
#include "incGAM.h"
#include "GLI.h"
#include "DPT.h"
#include "ErO.h"

#undef CPA_WANTS_IMPORT
#undef CPA_EXPORT
#define CPA_WANTS_EXPORT
    #include "OGD.h"
#undef CPA_WANTS_EXPORT
#define CPA_WANTS_IMPORT

#include "3Dinterf.hpp"
#include "X:/CPA/main/inc/_editid.h"
//#include "3DSctn.hpp"

///////////////////////////////////////////////////////////////////////////////
// DEFINE
///////////////////////////////////////////////////////////////////////////////

#define M_bHasPTModification()  (m_oListOfModifiedPoints . GetCount() )
#define M_bHasGMTModification() (m_oListOfGMTModif . GetCount() )
#define M_bHasFMDModification() (m_oListOfFMDModif . GetCount() )

#define M_LKTB_SearchKeyByValue( p_stLinkTable, ulValue )               SCR_M_p_sz_Link_GetKey( SCR_fnp_st_Link_SearchValue( p_stLinkTable, ulValue ) )
#define M_LKTB_SearchValueByKey( p_stLinkTable, szKey )                 SCR_M_ul_Link_GetValue( SCR_fnp_st_Link_SearchKey( p_stLinkTable, szKey ) )
#define M_LKTB_SearchAdditionalLongByValue( p_stLinkTable, ulValue )    SCR_M_ul_Link_GetAdditionalLong( SCR_fnp_st_Link_SearchValue( p_stLinkTable, ulValue ), 1 )

#define M_LKTB_GetKeyAndAdditionalLongByValue( p_stLinkTable, ulValue , p_cKey, ulLong )\
        {\
            SCR_tdst_Link_Value *p_stValue = SCR_fnp_st_Link_SearchValue( p_stLinkTable, ulValue );\
            if ( p_stValue )\
            {\
                p_cKey = SCR_M_p_sz_Link_GetKey( p_stValue );\
                ulLong = SCR_M_ul_Link_GetAdditionalLong( p_stValue, 1 );\
            }\
            else\
            {\
                p_cKey = NULL;\
                ulLong = 0;\
            }\
        }

#define M_GetMaterialValue(szKey)          ((GMT_tdxHandleToGameMaterial)M_LKTB_SearchValueByKey(GMT_fn_p_stGetLinkTable(),szKey))

#define M_GetElementType(_szName,_Type)    for( (_Type) = 0 ; strcmpi(g_szElementTypeName[_Type],"END") && strcmpi(g_szElementTypeName[_Type],_szName) ; (_Type)++);

#define M_GetFMTToElementFMD(xElementFMD, xFaceFMD)    (((GEO_tdstElementFaceMapDescriptors*)GetStruct() -> d_stListOfElements[xElementFMD]) -> d_stListOfFacesQuadrupled[xFaceFMD])
#define M_GetFMDToElementFMD(xElementFMD, xFaceFMD)    (M_GetFMTToElementFMD(xElementFMD, xFaceFMD) . hFaceMapDescriptor)

#define M_ForEachElement( oList, oElement, Pos )\
            for( oElement = (oList) . GetHeadElement( Pos ) ; \
                 oElement ; \
                 oElement = (oList) . GetNextElement( Pos ) )

#define C_szDefaultMaterial     "Common\\Common.gmt^GameMaterial:Default"

//=======================================================================================
// ENGINE
//=======================================================================================
DeclareTemplateStatic(ACP_tdxHandleOfObject);

void del(ACP_tdxHandleOfObject h)
{
//	if ( h )
//    delete h;
}

//=======================================================================================
// GLOBALS
//=======================================================================================
char *g_szElementTypeName[] =
{
	"",
	"IndexedTriangles",
	"FaceMapDescriptors",
	"Sprites",
	"TMeshes",
	"Points",
	"Lines",
	"Spheres",
	"AlignedBoxes",
	"Cones",
	"",
	"Altimap",
    "END"
};


static CPA_DLLBase *s_p_oDLLTGM;

//
//
// implementation
//
//

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
void Geometry3D::StaticInit(CPA_MainWorld *_p_oMainWorld)
{
	CPA_EdMot<ACP_tdxHandleOfObject>::Init(NULL,NULL,del);

    SCR_fn_v_RdL0_RegisterCallback( "Edit-Geometric", Geometry3D::CallBackLoad, SCR_CRC_c_RdL0_ForSection );
    SCR_fn_v_RdL0_RegisterCallback( C_szModifActionName, Geometry3D::CallBackLoadModif, SCR_CRC_c_RdL0_ForSection );
    
    s_p_oDLLTGM = _p_oMainWorld -> GetToolDLLWithName( C_szDLLMaterialName );
}

// ----------------------------------------------------------------------------
// Description : constructor to encapsulate an existing engine object
// ----------------------------------------------------------------------------
Geometry3D::Geometry3D(CPA_EditorBase *_p_oEditor, CPA_BaseObject *_p_oOwnerFile, ACP_tdxHandleOfObject _hObject,
                       const CString _csName /*=""*/, char *_p_cRefPath /*=NULL*/, tdeSaveStatus _eStatus /*=E_ss_Modify*/)
           :CPA_ModifiableObject( _p_oEditor, C_szGeometricType, _eStatus, _p_oOwnerFile, TRUE, NULL, Geometry3D::CallBackSaveGeometricObject),
            CPA_EdMot<ACP_tdxHandleOfObject>(_hObject)
{
    ASSERT( _p_oOwnerFile || _eStatus == E_ss_NoSave);
    ASSERT( _hObject );

	int iPathLength;

    //m_p_oModifListSection = NULL;
    m_p_oModifSection = NULL;
    //
    // path
    if (_p_oOwnerFile)
	{
		char szShortSectionName[SCR_CV_ui_Cfg_MaxLenName];
		if( _p_cRefPath == NULL )
		{
			_p_cRefPath = (char*) GetEditor() -> OnQueryAction( NULL, C_uiGetOGDTypePath, (long)(char*)(LPCTSTR)((CPA_FileObject*)_p_oOwnerFile) -> GetCompleteName() );
		}
		SetDataPath( _p_cRefPath );
		iPathLength = (_p_cRefPath) ? strlen( _p_cRefPath ) + 1 : 0;
		SCR_fn_v_RdL0_ComputeSectionName( szShortSectionName, (char*)(LPCTSTR)(((CPA_FileObject*)_p_oOwnerFile) -> GetCompleteName()) + iPathLength,
															  "Geometric", " " );
		SetReferencedSectionName( szShortSectionName );
		SetSectionData( this );
		SetExistingSection( TRUE );
	}
	else
	{
		SetReferencedSectionName( "Bidon.mod^Geometric:This" );
		SetSectionData( this );
		SetExistingSection( FALSE );
	}

    //
    // name
    BOOL bLoading = GetEditor()->GetInterface()->fn_bIsLoadingWorld();
	if (_eStatus == E_ss_NoSave)
		GetEditor()->GetInterface()->SetLoadingWorld(FALSE);
	
	if( fn_eRename( _csName ) != E_mc_None )
        SetDefaultValidName();

	if (_eStatus == E_ss_NoSave)
		GetEditor()->GetInterface()->SetLoadingWorld(bLoading);

    fn_vUpdateSectionName();
    //
    // datas
    SetExistingSection( (_p_oOwnerFile!=NULL) );
    // create list of ElementSection
    ACP_tdxIndex xNbElements = GEO_xGetGeometricObjectNumberOfElements( _hObject );
    SCR_tdst_Link_Table *p_stLkTb;

    for( ACP_tdxIndex xElement = 0; xElement < xNbElements ; xElement++ )
    {
        switch ( GEO_xGetElementType(_hObject, xElement) )
        {
		case GEO_C_xElementIndexedTriangles:
            p_stLkTb = GLI_p_stGetLinkTableOfElementIndexedTriangle();
			break;
		case GEO_C_xElementFaceMapDescriptors:
            p_stLkTb = GLI_p_stGetLinkTableOfElementFaceMapDescriptor();
			break;
		case GEO_C_xElementSprites:
            p_stLkTb = GLI_p_stGetLinkTableOfElementSprite();
			break;
		case GEO_C_xElementTMeshes:
            p_stLkTb = GLI_p_stGetLinkTableOfElementTMeshe();
			break;
		case GEO_C_xElementPoints:
            p_stLkTb = GLI_p_stGetLinkTableOfElementPoint();
			break;
		case GEO_C_xElementLines:
            p_stLkTb = GLI_p_stGetLinkTableOfElementLine();
			break;
		case GEO_C_xElementSpheres:
            p_stLkTb = GLI_p_stGetLinkTableOfElementSphere();
			break;
		case GEO_C_xElementAlignedBoxes:
            p_stLkTb = GLI_p_stGetLinkTableOfElementAlignedBoxe();
			break;
		case GEO_C_xElementCones:
            p_stLkTb = GLI_p_stGetLinkTableOfElementCone();
			break;
        //VLNEWGLI
        /*
		// BEGIN CPA2 Cristi Petrescu 98-03-
		case GEO_C_xElementAltimap:
			p_stLkTb = GLI_p_stGetLinkTableOfElementAltimap ();
			break;
		// END CPA2 Cristi Petrescu 98-03-
        */
        //EVL

        default:
            p_stLkTb = NULL;
        }
        if( p_stLkTb )
        {
            char *p_cLinkName;
            unsigned long ulValue;

            M_LKTB_GetKeyAndAdditionalLongByValue( p_stLkTb, (unsigned long) _hObject -> d_stListOfElements[ xElement ], p_cLinkName, ulValue );
            if( p_cLinkName )
            {
                SectionElement *p_oElementSection = new SectionElement(p_cLinkName + ulValue, _p_cRefPath,
                                                                    Geometry3D::CallBackSaveGeometricElement );
                p_oElementSection -> SetSectionData( p_oElementSection );
                p_oElementSection -> SetElement( (void*)_hObject -> d_stListOfElements[ xElement ] );
                m_oListOfElementSections . AddTail( p_oElementSection );
            }
        }
    }
    // data members
    m_oListOfModifiedPoints . RemoveAll();
    m_oListOfGMTModif . RemoveAll();
	// BEGIN CPA2 Cristi Petrescu 98-02-
	m_oListOfFMDModif . RemoveAll ();
	// END CPA2 Cristi Petrescu 98-02-
    m_hBoundingVolume = NULL;
    m_bMustRecomputeBdV = TRUE;
    m_bEndCreated = TRUE;
    fn_vInitFMD();
	// init Modif Sections
    //fn_vInitModifSections();
	if (_p_oOwnerFile)
		mfn_vLoadModifSection ();
}

// ----------------------------------------------------------------------------
// Description : constructor to create and save a new object
// ----------------------------------------------------------------------------
Geometry3D::Geometry3D(CPA_EditorBase *_p_oEditor, ACP_tdxIndex xNbPoints, ACP_tdxIndex xNbElements,
                       CPA_BaseObject *_p_oOwnerFile, const CString _csName /*=""*/, char *_p_cRefPath /*=NULL*/,
                       tdeSaveStatus _eStatus /*=E_ss_Responsible*/)
		   :CPA_ModifiableObject( _p_oEditor, C_szGeometricType, _eStatus, _p_oOwnerFile, TRUE, NULL, Geometry3D::CallBackSaveGeometricObject),
            CPA_EdMot<ACP_tdxHandleOfObject>((ACP_tdxHandleOfObject)NULL)
{
    ASSERT( _p_oOwnerFile );
    //
    char szShortSectionName[SCR_CV_ui_Cfg_MaxLenName];
    ACP_tdxHandleOfObject hObject;

    //m_p_oModifListSection = NULL;
    m_p_oModifSection = NULL;
    //
    // path
    if( _p_cRefPath == NULL )
    {
        _p_cRefPath = (char*)GetEditor() -> OnQueryAction( NULL, C_uiGetOGDTypePath, (long)(char*)(LPCTSTR)((CPA_FileObject*)_p_oOwnerFile) -> GetCompleteName() );
    }
    SetDataPath( _p_cRefPath );
    SCR_fn_v_RdL0_ComputeSectionName( szShortSectionName, (char*)(LPCTSTR)(((CPA_FileObject*)_p_oOwnerFile) -> GetCompleteName()) + strlen( _p_cRefPath ) + 1, "Geometric", " " );
    SetReferencedSectionName( szShortSectionName );
    SetSectionData( this );
    SetExistingSection( FALSE );
    //
    // datas
    GEO_vCreateGeometricObject( &hObject, xNbPoints , xNbElements );
    SetStruct( (ACP_tdxHandleOfObject) hObject );
    // create list of ElementSection
    for( ACP_tdxIndex xElement = 0; xElement < xNbElements ; xElement++ )
    {
        SectionElement *p_oElementSection = new SectionElement("", _p_cRefPath, Geometry3D::CallBackSaveGeometricElement);
        p_oElementSection -> SetSectionData( p_oElementSection );
        p_oElementSection -> SetExistingSection( FALSE );
        m_oListOfElementSections . AddTail( p_oElementSection );
    }
    //
    // name
    if( fn_eRename( _csName ) != E_mc_None )
        SetDefaultValidName();
    fn_vUpdateSectionName();
    //
    m_oListOfModifiedPoints . RemoveAll();
    m_oListOfGMTModif . RemoveAll();
	// BEGIN CPA2 Cristi Petrescu 98-02-
	m_oListOfFMDModif . RemoveAll ();
	// END CPA2 Cristi Petrescu 98-02-
    m_hBoundingVolume = NULL;
    m_bMustRecomputeBdV = TRUE;
    m_bEndCreated = FALSE;
    fn_vInitFMD();
	// init Modif Sections
    // fn_vInitModifSections();
	mfn_vLoadModifSection ();
}

// ----------------------------------------------------------------------------
// Description : constructor to create and a new object which can't be save
// ----------------------------------------------------------------------------
Geometry3D::Geometry3D(CPA_EditorBase *_p_oEditor, ACP_tdxIndex xNbPoints, ACP_tdxIndex xNbElements,
                       const CString _csName /*=""*/, tdeSaveStatus _eStatus /*=E_ss_NoSave*/)
           :CPA_ModifiableObject( _p_oEditor, C_szGeometricType, _eStatus, NULL, TRUE),
            CPA_EdMot<ACP_tdxHandleOfObject>((ACP_tdxHandleOfObject)NULL)
{
    ASSERT( xNbPoints > 0 );
    ASSERT( xNbElements > 0 );
    //
    ACP_tdxHandleOfObject hObject;

    //m_p_oModifListSection = NULL;
    m_p_oModifSection = NULL;
    //
    // path
    SetSectionData( NULL );
    SetExistingSection( FALSE );
    //
    // datas
    GEO_vCreateGeometricObject( &hObject, xNbPoints , xNbElements );
    SetStruct( (ACP_tdxHandleOfObject) hObject );
    m_oListOfElementSections . RemoveAll();
    //
    // name
    if( fn_eRename( _csName ) != E_mc_None )
        SetDefaultValidName();
    fn_vUpdateSectionName();
    //
    m_oListOfModifiedPoints . RemoveAll();
    m_oListOfGMTModif . RemoveAll();
	// BEGIN CPA2 Cristi Petrescu 98-02-
	m_oListOfFMDModif . RemoveAll ();
	// END CPA2 Cristi Petrescu 98-02-
    m_hBoundingVolume = NULL;
    m_bMustRecomputeBdV = TRUE;
    m_bEndCreated = FALSE;
	// init Modif Sections
    //fn_vInitModifSections();
	//mfn_vCreateModifSection ();
    fn_vInitFMD();
}


// ----------------------------------------------------------------------------
// Description : destructor
// ----------------------------------------------------------------------------
Geometry3D::~Geometry3D()
{
    while ( ! m_oListOfElementSections . IsEmpty() )
        delete m_oListOfElementSections . RemoveHead();

    while ( ! m_oListOfFMD . IsEmpty() )
        free( m_oListOfFMD . RemoveHead() );

    //if( m_p_oModifListSection ) delete m_p_oModifListSection;
    if( m_p_oModifSection )     delete m_p_oModifSection;
    //
    fn_vClearFMDModificationsList();
    fn_vClearGMTModificationsList();
    fn_vClearModificationsList();
}

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
void Geometry3D::fn_vInitModifSections(void)
{
    /*
    char szFileName[SCR_CV_ui_Cfg_MaxLenName];
    char szShortSectionName[SCR_CV_ui_Cfg_MaxLenName];

    SCR_fn_v_RdL0_SplitSectionName( (char*)(LPCTSTR) GetReferencedSectionName(), szFileName, NULL, NULL );
    // Modif List Section
    SCR_fn_v_RdL0_ComputeSectionName( szShortSectionName, szFileName, C_szModifListActionName, NULL );
    m_p_oModifListSection = new CPA_SectionObject( szShortSectionName, GetDataPath(), Geometry3D::CallBackSaveModifListGeometricObject );
    m_p_oModifListSection -> SetSectionData( this );
    m_p_oModifListSection -> SetExistingSection( FALSE );
    // Modif Section
    SCR_fn_v_RdL0_ComputeSectionName( szShortSectionName, szFileName, C_szModifActionName, fn_p_szGetName() );
    m_p_oModifSection = new CPA_SectionObject( szShortSectionName, GetDataPath(), Geometry3D::CallBackSaveModifGeometricObject );
    m_p_oModifSection -> SetSectionData( this );
    m_p_oModifSection -> SetExistingSection( FALSE );
    */
}

// ----------------------------------------------------------------------------
//  Author      : MT
//  Creation    : 30/07/97
//
// Description :
// ----------------------------------------------------------------------------
void Geometry3D::fn_vInitFMD(void)
{
    m_bMustSaveFMD = FALSE;
    m_oListOfFMD . RemoveAll();
    m_lUniqueFMD = 0;
    if ( fn_bCanBeNotified() )
    {
        ACP_tdxHandleOfObject p_stObj = GetStruct();
        ACP_tdxIndex          xElementFMD;

        // search for a Face descriptor element
        for ( xElementFMD = 0 ; xElementFMD < p_stObj->xNbElements; xElementFMD++ )
        {
            if (  p_stObj -> d_xListOfElementsTypes[ xElementFMD ] == GEO_C_xElementFaceMapDescriptors )
                break;
        }

        if ( xElementFMD != p_stObj -> xNbElements )
        {
            // face map descriptor found, must update m_lUniqueFMD
            ACP_tdxIndex xNbFaces = ((GEO_tdstElementFaceMapDescriptors*)p_stObj -> d_stListOfElements[ xElementFMD ]) -> xNbFaces;
            ACP_tdxIndex xIndexFace;

            for ( xIndexFace = 0 ; xIndexFace < xNbFaces ; xIndexFace++ )
            {
                ACP_tdxHandleOfFMD hFMD         = M_GetFMDToElementFMD( xElementFMD, xIndexFace );
                char               *szLinkName  = M_LKTB_SearchKeyByValue( GLI_p_stGetLinkTableOfFaceMapDescriptor(), (unsigned long)hFMD);

                if( szLinkName )
                {
                    char *p_cPoint = strrchr( szLinkName, '_' );
                    if( p_cPoint )
                    {
                        long lValue = atol( p_cPoint + 1 );
                        m_lUniqueFMD = max( m_lUniqueFMD, lValue );
                    }
                }
            }
        }
    }
}

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
void Geometry3D::fn_vUpdateSectionName(void)
{
    CPA_ModifiableObject::fn_vUpdateSectionName();
    if( m_p_oModifSection != NULL )
    {
        char szFileName[SCR_CV_ui_Cfg_MaxLenName];
        char szShortSectionName[SCR_CV_ui_Cfg_MaxLenName];

        SCR_fn_v_RdL0_SplitSectionName( (char*)(LPCTSTR) m_p_oModifSection -> GetReferencedSectionName(), szFileName, NULL, NULL );
        SCR_fn_v_RdL0_ComputeSectionName( szShortSectionName, szFileName, C_szModifActionName, fn_p_szGetName() );
        m_p_oModifSection -> SetReferencedSectionName( szShortSectionName );
    }
}

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
void Geometry3D::SetExistingModifSection(BOOL _bExists)
{
    if( m_p_oModifSection ) m_p_oModifSection -> SetExistingSection( _bExists );
}

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
/*
void Geometry3D::SetExistingModifListSection(BOOL _bExists)
{
    if( m_p_oModifListSection ) m_p_oModifListSection -> SetExistingSection( _bExists );
}
*/

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
void Geometry3D::fn_vNotifySave()
{
    if( fn_bCanBeNotified() )
    {
        // main section of object
        fn_vWriteSection();
        // Element Sections
        SectionElement *p_oSectionElement;
        POSITION        xPos;
        M_ForEachElement( m_oListOfElementSections, p_oSectionElement, xPos )
        {
            p_oSectionElement -> fn_vWriteSection();
        }
        // modif section
        if( GetSaveStatus() == E_ss_Modify )
        {
            //if( m_p_oModifListSection ) m_p_oModifListSection -> fn_vWriteSection();
            if( m_p_oModifSection ) m_p_oModifSection -> fn_vWriteSection();
        }
    }
}

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
void Geometry3D::fn_vNotifyUnSave()
{
    if( fn_bCanBeNotified() )
    {
        // main section of object
        fn_vDeleteSection();
        // Element Sections
        SectionElement *p_oSectionElement;
        POSITION        xPos;
        M_ForEachElement( m_oListOfElementSections, p_oSectionElement, xPos )
        {
            p_oSectionElement -> fn_vDeleteSection();
        }
    }
}

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
void Geometry3D::fn_vNotifyRestore()
{
    if( fn_bCanBeNotified() )
    {
        // main section of object
        fn_vRestoreSection();
        // Element Sections
        SectionElement *p_oSectionElement;
        POSITION        xPos;
        M_ForEachElement( m_oListOfElementSections, p_oSectionElement, xPos )
        {
            p_oSectionElement -> fn_vRestoreSection();
        }
    }
}

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
void Geometry3D::fn_vNotifyRename()
{
    if( fn_bCanBeNotified() )
    {
        // main section of object
        fn_vRenameSection(fn_csComputeReferencedSectionName(GetName()));
        // modif section
        if( ( GetSaveStatus() == E_ss_Modify ) && m_p_oModifSection )
        {
            char szFileName[SCR_CV_ui_Cfg_MaxLenName];
            char szShortSectionName[SCR_CV_ui_Cfg_MaxLenName];

            //m_p_oModifListSection -> fn_vWriteSection();
            SCR_fn_v_RdL0_SplitSectionName( (char*)(LPCTSTR) m_p_oModifSection -> GetReferencedSectionName(), szFileName, NULL, NULL );
            SCR_fn_v_RdL0_ComputeSectionName( szShortSectionName, szFileName, C_szModifActionName, fn_p_szGetName() );

            m_p_oModifSection -> fn_vRenameSection( szShortSectionName );
        }
        // Element Sections
        SectionElement *p_oSectionElement;
        POSITION        xPos;
        int             iElement = 0;
        M_ForEachElement( m_oListOfElementSections, p_oSectionElement, xPos )
        {
            char szShortSectionName[SCR_CV_ui_Cfg_MaxLenName];

            fn_vComputeElementReferencedSectionName( szShortSectionName, iElement );
            p_oSectionElement -> fn_vRenameSection( szShortSectionName );
            iElement++;
        }
    }
}

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
void Geometry3D::fn_vNotifySaveObject(void)
{
    if( fn_bCanBeNotified() )
    {
        fn_vWriteSection();
        // modif section
        if( GetSaveStatus() == E_ss_Modify )
        {
            //if( m_p_oModifListSection ) m_p_oModifListSection -> fn_vWriteSection();
            if( m_p_oModifSection ) m_p_oModifSection -> fn_vWriteSection();
        }
    }
}

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
void Geometry3D::fn_vNotifyUnSaveObject(void)
{
    if( fn_bCanBeNotified() )
        fn_vDeleteSection();
}

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
void Geometry3D::fn_vNotifyRestoreObject(void)
{
    if( fn_bCanBeNotified() )
        fn_vRestoreSection();
}

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
void Geometry3D::fn_vNotifyRenameObject(void)
{
}

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
void Geometry3D::fn_vNotifySaveElement(ACP_tdxHandleOfElement _hElement)
{
    POSITION xPos = m_oListOfElementSections . FindIndex( _hElement );
    if( xPos )
    {
        m_oListOfElementSections . GetAt( xPos ) -> fn_vWriteSection();
        // modif section
        if( GetSaveStatus() == E_ss_Modify )
        {
            //if( m_p_oModifListSection ) m_p_oModifListSection -> fn_vWriteSection();
            if( m_p_oModifSection ) m_p_oModifSection -> fn_vWriteSection();
        }
    }
}

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
void Geometry3D::fn_vNotifyUnSaveElement(ACP_tdxHandleOfElement _hElement)
{
    POSITION xPos = m_oListOfElementSections . FindIndex( _hElement );
    if( xPos )
    {
        m_oListOfElementSections . GetAt( xPos ) -> fn_vDeleteSection();
    }
}

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
void Geometry3D::fn_vNotifyRestoreElement(ACP_tdxHandleOfElement _hElement)
{
    POSITION xPos = m_oListOfElementSections . FindIndex( _hElement );
    if( xPos )
    {
        m_oListOfElementSections . GetAt( xPos ) -> fn_vRestoreSection();
    }
}

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
// BEGIN CPA2 Cristi Petrescu 98-02-
/*
void Geometry3D::fn_vSetOnState(CString _ocsModificationType, BOOL _bInitialState)
{
    if( fn_bIsModified(_ocsModificationType) && (fn_bIsOnInitialState(_ocsModificationType) != _bInitialState) )
    {
        if( _ocsModificationType == C_szFormModif )
        {
            // swap positions
            MTH3D_tdstVector    st3DTmpPoint;
            tdstModifPoint      *p_stModif;
            POSITION            xPos;

            M_ForEachElement( m_oListOfModifiedPoints, p_stModif, xPos )
            {
                fn_vGetPoint( p_stModif -> xIndexOfPoint , &st3DTmpPoint );
                fn_vOwnerSetPoint( p_stModif -> xIndexOfPoint , &(p_stModif -> st3DPoint) );
                memcpy( &(p_stModif -> st3DPoint), &st3DTmpPoint, sizeof(MTH3D_tdstVector) );
            }
            if( ! m_oListOfModifiedPoints . IsEmpty() )
                fn_vEndModification();
        }
        else if ( _ocsModificationType == C_szMaterialModif )
        {
            // swap material
            GMT_tdxHandleToGameMaterial hGameMaterial;
            tdstModifGMT                *p_stModif;
            POSITION                    xPos;

            M_ForEachElement( m_oListOfGMTModif, p_stModif, xPos )
            {
                hGameMaterial = fn_hGetGameMaterial( p_stModif -> hElement, p_stModif -> xIndexInElement );
                fn_vOwnerSetMaterial( p_stModif -> hElement, p_stModif -> xIndexInElement, p_stModif -> hGameMaterial );
                p_stModif -> hGameMaterial = hGameMaterial;
            }
        }
    }
}
*/
// END CPA2 Cristi Petrescu 98-02-

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
BOOL Geometry3D::fn_bCanBeModified(void)
{
    switch ( GetSaveStatus() )
    {
    case E_ss_Responsible:
        // BEGIN CPA2 Cristi Petrescu 98-02-
		return !( M_bHasPTModification() || M_bHasGMTModification() || M_bHasFMDModification() );
		// END CPA2 Cristi Petrescu 98-02-
        break;
    case E_ss_NoSave:
    case E_ss_Modify:
        return TRUE;
        break;
    case E_ss_NoModif:
        return FALSE;
        break;
    }
    return FALSE;
}

// ----------------------------------------------------------------------------
// Description : CallBack from reading 'Edit-Geometric' section
// ----------------------------------------------------------------------------
SCR_tde_Anl_ReturnValue Geometry3D::CallBackLoad(SCR_tdst_File_Description *_p_stFile, char *_pszName,
                                                 char *_ap_szParams[], SCR_tde_Anl_Action _eAction)
{
    ASSERT(0);
    return SCR_ERV_Anl_NormalReturn;
}

// ----------------------------------------------------------------------------
// Description : CallBack from reading 'Edit-ModifGeometric' section
// ----------------------------------------------------------------------------
SCR_tde_Anl_ReturnValue Geometry3D::CallBackLoadModif(SCR_tdst_File_Description *_p_stFile, char *_pszName,
                                                      char *_ap_szParams[], SCR_tde_Anl_Action _eAction)
{
    Geometry3D *p_oGeom;
    SCR_M_RdL0_GetContextLong(0, 0, Geometry3D*, p_oGeom);

    switch ( _eAction )
    {
    case SCR_EA_Anl_BeginSection:
        p_oGeom -> m_oListOfModifiedPoints . RemoveAll();
        p_oGeom -> m_oListOfGMTModif . RemoveAll();
		// BEGIN CPA2 Cristi Petrescu 98-02-
		p_oGeom -> m_oListOfFMDModif . RemoveAll ();
		// END CPA2 Cristi Petrescu 98-02-
        break;
    case SCR_EA_Anl_Entry:
        if( ! strcmpi(_pszName,"MovedPoint") )
        {
            ACP_tdxIndex xIndex = atoi( _ap_szParams[0] );
            if( xIndex < GEO_xGetGeometricObjectNumberOfPoints( p_oGeom -> GetStruct() ) )
            {
				// BEGIN CPA2 Cristi Petrescu 98-02-
				/*
                MTH3D_tdstVector st3D;
                MTH3D_M_vSetVectorElements( &st3D, (MTH_tdxReal)atof(_ap_szParams[1]),
                                                   (MTH_tdxReal)atof(_ap_szParams[2]),
                                                   (MTH_tdxReal)atof(_ap_szParams[3]) );
				*/
                p_oGeom -> fn_vAddModification( xIndex/*, &st3D */);
				// END CPA2 Cristi Petrescu 98-02-
            }
        }
        else if( ! strcmpi(_pszName,"GameMaterial") )
        {
            ACP_tdxHandleOfElement      hElement        = atoi( _ap_szParams[0] );
            // BEGIN CPA2 Cristi Petrescu 98-03-
			ACP_tdxIndex                xIndexInElement = 0; //atoi( _ap_szParams[2] );
			// END CPA2 Cristi Petrescu 98-03-

			// BEGIN CPA2 Cristi Petrescu 98-02-
			GMT_tdxHandleToGameMaterial hGM = NULL;
			SCR_tdst_Link_Value *p_stValue = SCR_fnp_st_Link_SearchKey (GMT_fn_p_stGetLinkTable(), _ap_szParams[2]);
			if (p_stValue)
				hGM = (GMT_tdxHandleToGameMaterial) SCR_M_ul_Link_GetValue (p_stValue);
			//M_GetMaterialValue( _ap_szParams[2] );
			/*
			char *szGameMaterialName = _ap_szParams[2];
			GMT_tdxHandleToGameMaterial hGM;
			SCR_tdst_Link_Table *p_stGameMaterialLinkTable = GMT_fn_p_stGetLinkTable();
			SCR_tdst_Link_Value *p_stMaterialEntry = SCR_fnp_st_Link_SearchValue(p_stGameMaterialLinkTable, (unsigned long) hGameMaterial);
			hGM = (GMT_tdxHandleToGameMaterial) SCR_M_ul_Link_GetValue (p_stMaterialEntry);
			*/
			if (hGM)
				p_oGeom -> fn_vAddGMTModification( hElement, xIndexInElement, hGM );
			// END CPA2 Cristi Petrescu 98-02-
        }
		// BEGIN CPA2 Cristi Petrescu 98-02-
		else if( ! strcmpi(_pszName,"MovedFace") )
		{
            ACP_tdxIndex				xElementIT = atoi( _ap_szParams[0] );
            ACP_tdxIndex                xIndexFaceIT = atoi( _ap_szParams[1] );
			ACP_tdxIndex				xElementFMD = atoi( _ap_szParams[2] );
            ACP_tdxIndex                xIndexFaceFMD = atoi( _ap_szParams[3] );

			p_oGeom -> fn_vAddFMDModification( xElementIT, xIndexFaceIT, xElementFMD, xIndexFaceFMD);
		}
		// END CPA2 Cristi Petrescu 98-02-
        break;
    case SCR_EA_Anl_EndSection:
        // form modif
        if( !p_oGeom -> m_oListOfModifiedPoints . IsEmpty() )
            p_oGeom -> fn_vSetCurrentState( C_szFormModif, FALSE );    // use modification
        // material modif
        if( !p_oGeom -> m_oListOfGMTModif . IsEmpty() )
            p_oGeom -> fn_vSetCurrentState( C_szMaterialModif,FALSE );
		// BEGIN CPA2 Cristi Petrescu 98-02-
		// FMD modif
		if( !p_oGeom -> m_oListOfFMDModif . IsEmpty() )
            p_oGeom -> fn_vSetCurrentState( C_szFMDModif,FALSE );
		// END CPA2 Cristi Petrescu 98-02-
        break;
    }
    return SCR_ERV_Anl_NormalReturn;
}

// ----------------------------------------------------------------------------
// Description : CallBack from reading 'Edit-ListModifGeometric' section
// ----------------------------------------------------------------------------
/*
SCR_tde_Anl_ReturnValue Geometry3D::CallBackLoadModifList
                                    (SCR_tdst_File_Description *_p_stFile, char *_pszName,
                                     char *_ap_szParams[], SCR_tde_Anl_Action _eAction)
{
    CListOfString *p_oListOfModifSection;
    SCR_M_RdL0_GetContextLong(0, 0, CListOfString*, p_oListOfModifSection);

    switch ( _eAction )
    {
    case SCR_EA_Anl_BeginSection:
        p_oListOfModifSection -> AddTail( CString("File Loaded") );
        break;
    case SCR_EA_Anl_Entry:
        if( ! strcmpi(_pszName,"AddModif") )
            p_oListOfModifSection -> AddTail( CString(_ap_szParams[0]) );
        break;
    case SCR_EA_Anl_EndSection:
        break;
    }
    return SCR_ERV_Anl_NormalReturn;
}
*/

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
//
// CallBack Save functions
//
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------

/*===========================================================================
*		Description:	Call Back Save for List of Modif Section
*		Creation date:
*		Author:			Marc
*---------------------------------------------------------------------------
*		Revision date:                                      Author:
*=========================================================================*/
/*
void Geometry3D::CallBackSaveModifListGeometricObject(SCR_tdst_File_Description *p_stFile,
                                                      char *p_szSectionName, void *p_vData,
                                                      SCR_tde_Ntfy_Action eAction)
{
    Geometry3D           *p_oGeom               = (Geometry3D*)p_vData;
    CPA_BaseObject       *p_oOwnerFile          = p_oGeom -> GetOwner();
    CPA_BaseObjectList   *p_oListOfGeometric    = p_oGeom -> GetBaseObjectList();
	char				  szSectionName[SCR_CV_ui_Cfg_MaxLenName];
    Position              stPos;

    switch( eAction )
    {
    case SCR_EA_Ntfy_AddSection:
    case SCR_EA_Ntfy_RebuildSection:
		// get section name
		SCR_fn_v_RdL0_ComputeSectionName(szSectionName, NULL, C_szModifListActionName, " ");
		// save begin section
		SCR_M_SvL0_SaveBeginSection(p_stFile, szSectionName, SCR_CC_C_Cfg_EOL);
        // save entries
        stPos = p_oListOfGeometric -> GetHeadPosition();
        while ( stPos )
        {
            Geometry3D *p_oObject = (Geometry3D*) p_oListOfGeometric -> GetNext( stPos );

            if( (p_oObject -> GetSaveStatus() == E_ss_Modify) &&
                (p_oObject -> GetOwner() == p_oOwnerFile) &&
                ( (! p_oObject -> m_oListOfModifiedPoints . IsEmpty()) || (! p_oObject -> m_oListOfGMTModif . IsEmpty()) )
              )
            {
                SCR_M_SvL0_SaveEntry(p_stFile, "AddModif", SCR_CC_C_Cfg_NoChar);
                SCR_fn_v_RdL0_ComputeSectionName(szSectionName, NULL, C_szModifActionName, p_oObject -> fn_p_szGetName() );
                SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Normal, 1, szSectionName );
            }
        }
		// write end section
		SCR_M_SvL0_SaveEndSection(p_stFile, SCR_CC_C_Cfg_EOL);
        if (eAction == SCR_EA_Ntfy_AddSection)
            SCR_M_SvL0_SaveBlankLine (p_stFile);
        //
        p_oGeom -> m_p_oModifListSection -> fn_vSectionSaved();
        break;
    case SCR_EA_Ntfy_DeleteSection:
        p_oGeom -> m_p_oModifListSection -> fn_vSectionDeleted();
        break;
    }
}
    */

/*===========================================================================
*		Description:	Call Back Save for geometric object (Modif Section)
*		Creation date:
*		Author:			Marc
*---------------------------------------------------------------------------
*		Revision date:                                      Author:
*=========================================================================*/
void Geometry3D::CallBackSaveModifGeometricObject(SCR_tdst_File_Description *p_stFile, char *p_szSectionName, void *p_vData, SCR_tde_Ntfy_Action eAction)
{
	GEO_tdstGeometricObject *p_stGeometric;
	Geometry3D				*p_oObject;
	char					szSectionName[SCR_CV_ui_Cfg_MaxLenName];
	char					szActionName[SCR_CV_ui_Cfg_MaxLenName];
	char					szName[SCR_CV_ui_Cfg_MaxLenName];
	double					dUnit = 1;
    POSITION                xPos;
	// init parameters
	p_oObject = (Geometry3D *) p_vData;
	p_stGeometric = (GEO_tdstGeometricObject *) p_oObject->GetData();
    switch( eAction )
    {
    case SCR_EA_Ntfy_AddSection:
        // go to end of file (we need all file directive to load this section)
        SCR_fn_v_SvL1_ToEndSection(p_stFile);
        SCR_M_SvL0_SaveBlankLine (p_stFile);
    case SCR_EA_Ntfy_RebuildSection:
        // Get unit from script file
        SCR_M_RdL0_GetFileDouble(0, 1, dUnit);
        if (dUnit == 0)
            dUnit = 1.0;
        // get section name
        SCR_fn_v_RdL0_SplitSectionName(p_szSectionName, NULL, szActionName, szName);
        SCR_fn_v_RdL0_ComputeSectionName(szSectionName, NULL, szActionName, szName);
        // save begin section
        SCR_M_SvL0_SaveBeginSection(p_stFile, szSectionName, SCR_CC_C_Cfg_EOL);
        // save entries (FormModif)
        xPos = p_oObject -> m_oListOfModifiedPoints . GetHeadPosition();
        while ( xPos )
        {
            tdstModifPoint *p_stModif = p_oObject -> m_oListOfModifiedPoints . GetNext( xPos );
			// BEGIN CPA2 Cristi Petrescu 98-02-
			MTH3D_tdstVector st3DPoint;
			p_oObject-> fn_vGetPoint (p_stModif -> xIndexOfPoint, &st3DPoint);
            SCR_M_SvL0_SaveEntry(p_stFile, "MovedPoint", SCR_CC_C_Cfg_NoChar);
            SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1,
                "%d,%.6f,%.6f,%.6f",
                p_stModif -> xIndexOfPoint,
                /*p_stModif ->*/ st3DPoint . xX / dUnit,
                /*p_stModif ->*/ st3DPoint . xY / dUnit,
                /*p_stModif ->*/ st3DPoint . xZ / dUnit);
			// END CPA2 Cristi Petrescu 98-02-
        }
        // save entries (GMTModif)
        xPos = p_oObject -> m_oListOfGMTModif . GetHeadPosition();
        while( xPos )
        {
            tdstModifGMT    *p_stModif  = p_oObject -> m_oListOfGMTModif . GetNext( xPos );
            // BEGIN CPA2 Cristi Petrescu 98-02-
			GMT_tdxHandleToGameMaterial hGameMaterial;
			hGameMaterial = p_oObject -> fn_hGetGameMaterial (p_stModif -> hElement, p_stModif -> xIndexInElement);
			CPA_SaveObject *p_oGM = (CPA_SaveObject*)s_p_oDLLTGM -> GetBaseObject(/*p_stModif ->*/ hGameMaterial, C_szGameMaterialTypeName);
			CPA_SaveObject *p_oInitialGM = (CPA_SaveObject*)s_p_oDLLTGM -> GetBaseObject(p_stModif -> hGameMaterial, C_szGameMaterialTypeName);
			
			CString csGameMaterialName = p_oGM -> GetCompleteSectionName();
			CString csInitialGameMaterialName = p_oInitialGM -> GetCompleteSectionName();
			//GMT_tdxHandleToGameMaterial hGM = M_GetMaterialValue ((char*)(LPCTSTR)csGameMaterialName);
			// END CPA2 Cristi Petrescu 98-02-

            // BEGIN CPA2 Cristi Petrescu 98-03-
			SCR_M_SvL0_SaveEntry(p_stFile, "GameMaterial", SCR_CC_C_Cfg_NoChar);
            SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1, "%d,%s,%s,%s",
                p_stModif -> hElement,
                // p_stModif -> xIndexInElement,
                (char*)(LPCTSTR)csGameMaterialName,
				(char*)(LPCTSTR)csInitialGameMaterialName,
				g_szElementTypeName[ p_stModif -> xElementType ]);
			// END CPA2 Cristi Petrescu 98-03-
        }
		// BEGIN CPA2 Cristi Petrescu 98-02-
		// save entries (FMDModif)
        xPos = p_oObject -> m_oListOfFMDModif . GetHeadPosition();
        while( xPos )
        {
            tdstModifFMD    *p_stModif  = p_oObject -> m_oListOfFMDModif . GetNext( xPos );
			GMT_tdxHandleToGameMaterial hGameMaterial;
			hGameMaterial = p_oObject -> fn_hGetGameMaterial (p_stModif -> xElementFMD, p_stModif -> xIndexFaceFMD);
			CPA_SaveObject *p_oGM = (CPA_SaveObject*)s_p_oDLLTGM -> GetBaseObject(hGameMaterial, C_szGameMaterialTypeName);
			CString csGameMaterialName = p_oGM -> GetCompleteSectionName();
			
            SCR_M_SvL0_SaveEntry(p_stFile, "MovedFace", SCR_CC_C_Cfg_NoChar);
            SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1, "%d,%d,%d,%d,%s",
                p_stModif -> xElementIT,
                p_stModif -> xIndexFaceIT,
				p_stModif -> xElementFMD,
                p_stModif -> xIndexFaceFMD,
                (char*)(LPCTSTR)csGameMaterialName );
        }
		// END CPA2 Cristi Petrescu 98-02-
        // write end section
        SCR_M_SvL0_SaveEndSection(p_stFile, SCR_CC_C_Cfg_EOL);
        if (eAction == SCR_EA_Ntfy_AddSection)
            SCR_M_SvL0_SaveBlankLine (p_stFile);
        p_oObject -> m_p_oModifSection -> fn_vSectionSaved();
        break;
    case SCR_EA_Ntfy_DeleteSection:
        p_oObject -> m_p_oModifSection -> fn_vSectionDeleted();
        break;
    }
}

/*===========================================================================
*		Description:	Call Back Save for geometric object
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                                      Author:
*=========================================================================*/
void Geometry3D::CallBackSaveGeometricObject( SCR_tdst_File_Description *p_stFile, char *p_szSectionName, void *p_vData, SCR_tde_Ntfy_Action eAction)
{
	GEO_tdstGeometricObject *p_stGeometric;
	Geometry3D				*p_oObject;
	char					szSectionName[SCR_CV_ui_Cfg_MaxLenName];
	char					szActionName[SCR_CV_ui_Cfg_MaxLenName];
	char					szFileName[SCR_CV_ui_Cfg_MaxLenName];
	char					szName[SCR_CV_ui_Cfg_MaxLenName];
	double					dUnit = 1;
	long					iInd;
    POSITION                xPos;
    SectionElement          *p_oElementSection;
// ANNECY MT 23/02/98 {
	ACP_tdxIndex			xIndexBdV;
// END ANNECY MT }

	// init parameters
	p_oObject = (Geometry3D *) p_vData;
	p_stGeometric = (GEO_tdstGeometricObject *) p_oObject->GetData();

	switch (eAction)
	{
		case SCR_EA_Ntfy_AddSection:
			// go to end of file (we need all file directive to load this section)
			SCR_fn_v_SvL1_ToEndSection(p_stFile);
			SCR_M_SvL0_SaveBlankLine (p_stFile);

		case SCR_EA_Ntfy_RebuildSection:
			// Get unit from script file
			SCR_M_RdL0_GetFileDouble(0, 1, dUnit);
			if (dUnit == 0)
				dUnit = 1.0;
			// get section name
			SCR_fn_v_RdL0_SplitSectionName(p_szSectionName, szFileName, szActionName, szName);
			SCR_fn_v_RdL0_ComputeSectionName(szSectionName, NULL, szActionName, szName);
			// save begin section
			SCR_M_SvL0_SaveBeginSection(p_stFile, szSectionName, SCR_CC_C_Cfg_NoChar);
			SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1, "%d,%d,%d",
				p_stGeometric->xNbPoints, 0 /*p_stGeometric->xNbEdges*/, p_stGeometric->xNbElements);
			// write list of points
			for (iInd = 0; iInd < p_stGeometric->xNbPoints; iInd++)
			{
				SCR_M_SvL0_SaveEntry(p_stFile, "AddVertex", SCR_CC_C_Cfg_NoChar);
				if( p_stGeometric->d_stListOfPointsReceivedLightIntensity )
				{
					SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1,
						"%d,%.6f,%.6f,%.6f,%.6f,%.6f,%.6f,%.1f,%.1f,%.1f",
						iInd,
						p_stGeometric->d_stListOfPoints[iInd].xX / dUnit,
						p_stGeometric->d_stListOfPoints[iInd].xY / dUnit,
						p_stGeometric->d_stListOfPoints[iInd].xZ / dUnit,
						p_stGeometric->d_stListOfPointsNormals[iInd].xX,
						p_stGeometric->d_stListOfPointsNormals[iInd].xY,
						p_stGeometric->d_stListOfPointsNormals[iInd].xZ,
						p_stGeometric->d_stListOfPointsReceivedLightIntensity[iInd].xR,
						p_stGeometric->d_stListOfPointsReceivedLightIntensity[iInd].xG,
						p_stGeometric->d_stListOfPointsReceivedLightIntensity[iInd].xB);
				}
				else
				{
					SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1,
						"%d,%.6f,%.6f,%.6f,%.6f,%.6f,%.6f",
						iInd,
						p_stGeometric->d_stListOfPoints[iInd].xX / dUnit,
						p_stGeometric->d_stListOfPoints[iInd].xY / dUnit,
						p_stGeometric->d_stListOfPoints[iInd].xZ / dUnit,
						p_stGeometric->d_stListOfPointsNormals[iInd].xX,
						p_stGeometric->d_stListOfPointsNormals[iInd].xY,
						p_stGeometric->d_stListOfPointsNormals[iInd].xZ);
				}
			}
			// write list of elements
            iInd = 0;
            M_ForEachElement( p_oObject -> m_oListOfElementSections, p_oElementSection, xPos )
            {
				xIndexBdV = GEO_xGetParallelBoxIndexOfElement( p_stGeometric, iInd );
                SCR_fn_v_RdL0_SplitSectionName( (char*)(LPCTSTR)p_oElementSection -> GetReferencedSectionName(), szFileName, szActionName, szName);
                SCR_fn_v_RdL0_ComputeSectionName(szSectionName, "*", szActionName, szName);
				SCR_M_SvL0_SaveEntry(p_stFile, "AddElement", SCR_CC_C_Cfg_NoChar);
// ANNECY MT 23/02/98 {
				if( xIndexBdV == GEO_C_xNoParallelBox )
				{
					SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1, "%d,%s,%s",
						iInd, g_szElementTypeName[p_stGeometric->d_xListOfElementsTypes[iInd]], szSectionName);
				}
				else
				{
					SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1, "%d,%s,%s,%d",
						iInd, g_szElementTypeName[p_stGeometric->d_xListOfElementsTypes[iInd]], szSectionName, xIndexBdV);
				}
// END ANNECY MT }
                iInd++;
            }

			// write end section
			SCR_M_SvL0_SaveEndSection(p_stFile, SCR_CC_C_Cfg_EOL);
			if (eAction == SCR_EA_Ntfy_AddSection)
				SCR_M_SvL0_SaveBlankLine (p_stFile);
			p_oObject -> fn_vSectionSaved();
			break;
		case SCR_EA_Ntfy_DeleteSection:
			p_oObject -> fn_vSectionDeleted();
			break;
	}
}


/*===========================================================================
*		Description:	Call Back Save for geometric element
*		Creation date:
*		Author:			Shaitan
*---------------------------------------------------------------------------
*		Revision date:                                      Author:
*=========================================================================*/
void Geometry3D::CallBackSaveGeometricElement (SCR_tdst_File_Description *p_stFile, char *p_szSectionName, void *p_vData, SCR_tde_Ntfy_Action eAction)
{
	ACP_tdxIndex	xElementType;
	char			szActionName[SCR_CV_ui_Cfg_MaxLenName];
	char			szName[SCR_CV_ui_Cfg_MaxLenName];
	char			*p_szActionName;
    SectionElement  *p_oElementSection = (SectionElement*) p_vData;

	switch (eAction)
	{
		case SCR_EA_Ntfy_AddSection:
            // go to end of file (we need all file directive to load this section)
            SCR_fn_v_SvL1_ToEndSection(p_stFile);
			SCR_M_SvL0_SaveBlankLine (p_stFile);
		case SCR_EA_Ntfy_RebuildSection:
			SCR_fn_v_RdL0_SplitSectionName(p_szSectionName, NULL, szActionName, szName);
			// find element type from action name
			p_szActionName = szActionName + strlen("Element");
            M_GetElementType( p_szActionName, xElementType );

			switch (xElementType)
			{
			case GEO_C_xElementIndexedTriangles:
                CallBackSaveElementIndexedTriangle(p_stFile, p_szSectionName, (GEO_tdstElementIndexedTriangles *) p_oElementSection -> hGetElement() );
				break;
			case GEO_C_xElementFaceMapDescriptors:
                CallBackSaveElementFaceMapDescriptors(p_stFile, p_szSectionName, (GEO_tdstElementFaceMapDescriptors *) p_oElementSection -> hGetElement() );
				break;
			case GEO_C_xElementSprites:
                CallBackSaveElementSprites(p_stFile, p_szSectionName, (GEO_tdstElementSprite *) p_oElementSection -> hGetElement() );
				break;
			case GEO_C_xElementTMeshes:
                CallBackSaveElementTMeshes(p_stFile, p_szSectionName, (GEO_tdstElementTMeshes *) p_oElementSection -> hGetElement() );
				break;
			case GEO_C_xElementPoints:
                CallBackSaveElementPoints(p_stFile, p_szSectionName, (GEO_tdstElementPoints *) p_oElementSection -> hGetElement() );
				break;
			case GEO_C_xElementLines:
                CallBackSaveElementLines(p_stFile, p_szSectionName, (GEO_tdstElementLines *) p_oElementSection -> hGetElement() );
				break;
			case GEO_C_xElementSpheres:
                CallBackSaveElementSpheres(p_stFile, p_szSectionName, (GEO_tdstElementSpheres *) p_oElementSection -> hGetElement() );
				break;
			case GEO_C_xElementAlignedBoxes:
                CallBackSaveElementAlignedBox(p_stFile, p_szSectionName, (GEO_tdstElementAlignedBoxes *) p_oElementSection -> hGetElement() );
				break;
			case GEO_C_xElementCones:
                CallBackSaveElementCones(p_stFile, p_szSectionName, (GEO_tdstElementCones *) p_oElementSection -> hGetElement() );
				break;
			// BEGIN CPA2 Cristi Petrescu 98-03-
			case GEO_C_xElementAltimap:
				CallBackSaveElementAltimap (p_stFile, p_szSectionName, (GEO_tdstElementAltimap *) p_oElementSection -> hGetElement());
				break;
			// END CPA2 Cristi Petrescu 98-03-
			}
            p_oElementSection -> fn_vSectionSaved();
			break;
        case SCR_EA_Ntfy_DeleteSection:
            p_oElementSection -> fn_vSectionDeleted();
            break;
	}
}


/*===========================================================================
*=========================================================================*/
void Geometry3D::CallBackSaveElementIndexedTriangle (SCR_tdst_File_Description *p_stFile, char *p_szSectionName, GEO_tdstElementIndexedTriangles *p_stElement)
{
	char	szSectionName[SCR_CV_ui_Cfg_MaxLenName];
	char	szActionName[SCR_CV_ui_Cfg_MaxLenName];
	char	szName[SCR_CV_ui_Cfg_MaxLenName];
	long	iInd;
	char    *p_szGMName;

	// find section name
	SCR_fn_v_RdL0_SplitSectionName(p_szSectionName, NULL, szActionName, szName);
	SCR_fn_v_RdL0_ComputeSectionName(szSectionName, NULL, szActionName, szName);
	// save begin section
	SCR_M_SvL0_SaveBeginSection(p_stFile, szSectionName, SCR_CC_C_Cfg_NoChar);
	SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1, "%d,%d",
		p_stElement->xNbFaces, p_stElement->xNbElementUV);

	// save material entry
    p_szGMName = mfn_p_szGetGameMaterialName( p_stElement->hMaterial );
	if (p_szGMName != NULL)
	{
		SCR_M_SvL0_SaveEntry(p_stFile, "Material", SCR_CC_C_Cfg_NoChar);
		SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Normal, 1, p_szGMName);
	}

	// save faces
	for (iInd = 0; iInd < p_stElement->xNbFaces; iInd++)
	{
		SCR_M_SvL0_SaveEntry(p_stFile, "AddFaceUV", SCR_CC_C_Cfg_NoChar);
		SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1,
			"%d,%d,%d,%d,%.6f,%.6f,%.6f,%d,%d,%d",
			iInd,
			p_stElement->d_stListOfFacesTripled[iInd].a3_xIndex[0],
			p_stElement->d_stListOfFacesTripled[iInd].a3_xIndex[1],
			p_stElement->d_stListOfFacesTripled[iInd].a3_xIndex[2],
			p_stElement->d_stListOfFacesNormals[iInd].xX,
			p_stElement->d_stListOfFacesNormals[iInd].xY,
			p_stElement->d_stListOfFacesNormals[iInd].xZ,
			p_stElement->d_stListOfFacesTripledIndexUV[iInd].a3_xIndex[0],
			p_stElement->d_stListOfFacesTripledIndexUV[iInd].a3_xIndex[1],
			p_stElement->d_stListOfFacesTripledIndexUV[iInd].a3_xIndex[2]);
	}

	// save list of uv
	for (iInd = 0; iInd < p_stElement->xNbElementUV; iInd++)
	{
		SCR_M_SvL0_SaveEntry(p_stFile, "AddUV", SCR_CC_C_Cfg_NoChar);
		SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1,
			"%d,%.6f,%.6f",
			iInd,
			p_stElement->d_stListOfElementUV[iInd].xU,
			p_stElement->d_stListOfElementUV[iInd].xV);
	}

	// end of section
	SCR_M_SvL0_SaveEndSection(p_stFile, SCR_CC_C_Cfg_EOL);
}


/*===========================================================================
*=========================================================================*/
void Geometry3D::CallBackSaveElementFaceMapDescriptors (SCR_tdst_File_Description *p_stFile, char *p_szSectionName, GEO_tdstElementFaceMapDescriptors *p_stElement)
{
	char	szSectionName[SCR_CV_ui_Cfg_MaxLenName];
	char	szActionName[SCR_CV_ui_Cfg_MaxLenName];
	char	szName[SCR_CV_ui_Cfg_MaxLenName];
	char	*szLinkName;
	long	iInd;

	// get section name
	SCR_fn_v_RdL0_SplitSectionName(p_szSectionName, NULL, szActionName, szName);
	SCR_fn_v_RdL0_ComputeSectionName(szSectionName, NULL, szActionName, szName);

	// save section beginning
	SCR_M_SvL0_SaveBeginSection(p_stFile, szSectionName, SCR_CC_C_Cfg_NoChar);
	SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1, "%d", p_stElement->xNbFaces);

	// save each face
	for(iInd = 0; iInd < p_stElement->xNbFaces; iInd++)
	{
        szLinkName = M_LKTB_SearchKeyByValue( GLI_p_stGetLinkTableOfFaceMapDescriptor(),(unsigned long)p_stElement->d_stListOfFacesQuadrupled[iInd].hFaceMapDescriptor );
		if (szLinkName == NULL)
			break;
        SCR_fn_v_RdL0_SplitSectionName(szLinkName, NULL, szActionName, szName);
        SCR_fn_v_RdL0_ComputeSectionName(szSectionName, "*", szActionName, szName);
		SCR_M_SvL0_SaveEntry(p_stFile, "AddFaceFMD", SCR_CC_C_Cfg_NoChar);
		SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1,
			"%d,%d,%d,%d,%.6f,%.6f,%.6f,%s",
			iInd,
			p_stElement->d_stListOfFacesQuadrupled[iInd].stFaceTripled.a3_xIndex[0],
			p_stElement->d_stListOfFacesQuadrupled[iInd].stFaceTripled.a3_xIndex[1],
			p_stElement->d_stListOfFacesQuadrupled[iInd].stFaceTripled.a3_xIndex[2],
			p_stElement->d_stListOfFacesNormals[iInd].xX,
			p_stElement->d_stListOfFacesNormals[iInd].xY,
			p_stElement->d_stListOfFacesNormals[iInd].xZ,
			szSectionName);
	}

	// save end of section
	SCR_M_SvL0_SaveEndSection(p_stFile, SCR_CC_C_Cfg_EOL);
}

/*===========================================================================
*=========================================================================*/
void Geometry3D::CallBackSaveFaceMapDescriptors (SCR_tdst_File_Description *p_stFile, char *p_szSectionName, void *p_vData, SCR_tde_Ntfy_Action eAction)
{
    char                szSectionName[SCR_CV_ui_Cfg_MaxLenName];
    char                szActionName[SCR_CV_ui_Cfg_MaxLenName];
    char                szName[SCR_CV_ui_Cfg_MaxLenName];
    char                *p_szGMName;
    ACP_tdxHandleOfFMD  hFMD = (ACP_tdxHandleOfFMD)p_vData;

	// get section name
	SCR_fn_v_RdL0_SplitSectionName(p_szSectionName, NULL, szActionName, szName);
	SCR_fn_v_RdL0_ComputeSectionName(szSectionName, NULL, szActionName, szName);

	// save section beginning
	SCR_M_SvL0_SaveBeginSection(p_stFile, szSectionName, SCR_CC_C_Cfg_EOL);

    // save Line
    SCR_M_SvL0_SaveEntry(p_stFile, "TripledUV", SCR_CC_C_Cfg_NoChar);
    SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1,
        "%.6f,%.6f,%.6f,%.6f,%.6f,%.6f",
        hFMD -> stUVValues[0] . xU, hFMD -> stUVValues[0] . xV,
        hFMD -> stUVValues[1] . xU, hFMD -> stUVValues[1] . xV,
        hFMD -> stUVValues[2] . xU, hFMD -> stUVValues[2] . xV);

	// save material entry
    p_szGMName = mfn_p_szGetGameMaterialName( hFMD->hMaterial );
	if (p_szGMName != NULL)
	{
		SCR_M_SvL0_SaveEntry(p_stFile, "Material", SCR_CC_C_Cfg_NoChar);
		SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Normal, 1, p_szGMName);
	}
	// end of section
	SCR_M_SvL0_SaveEndSection(p_stFile, SCR_CC_C_Cfg_EOL);
}

/*===========================================================================
*=========================================================================*/
void Geometry3D::CallBackSaveElementSprites (SCR_tdst_File_Description *p_stFile, char *p_szSectionName, GEO_tdstElementSprite *p_stElement)
{
	char	szSectionName[SCR_CV_ui_Cfg_MaxLenName];
	char	szActionName[SCR_CV_ui_Cfg_MaxLenName];
	char	szName[SCR_CV_ui_Cfg_MaxLenName];
	char	*szLinkName;
	long	iInd;

	// get section name
	SCR_fn_v_RdL0_SplitSectionName(p_szSectionName, NULL, szActionName, szName);
	SCR_fn_v_RdL0_ComputeSectionName(szSectionName, NULL, szActionName, szName);

	// save section beginning
	SCR_M_SvL0_SaveBeginSection(p_stFile, szSectionName, SCR_CC_C_Cfg_NoChar);
	SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1, "%d", p_stElement->xNbSprites);

	// save each sprites
	for (iInd = 0; iInd < p_stElement->xNbSprites; iInd++)
	{
        szLinkName = M_LKTB_SearchKeyByValue( GLI_p_stGetLinkTableOfElementSprite(),(unsigned long)p_stElement->d_stListOfSprites[iInd].hSprite );
		if (szLinkName == NULL)
			return;
        SCR_fn_v_RdL0_SplitSectionName(szLinkName, NULL, szActionName, szName);
        SCR_fn_v_RdL0_ComputeSectionName(szSectionName, "*", szActionName, szName);
		SCR_M_SvL0_SaveEntry(p_stFile, "AddSprite", SCR_CC_C_Cfg_NoChar);
		SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1,
			"%d,%d,%.6f,%.6f,%s",
			iInd,
			p_stElement->d_stListOfSprites[iInd].xCenterPoint,
			p_stElement->d_stListOfSprites[iInd].stSize.xX,
			p_stElement->d_stListOfSprites[iInd].stSize.xY,
            szSectionName );
	}

	// save end of section
	SCR_M_SvL0_SaveEndSection(p_stFile, SCR_CC_C_Cfg_EOL);
}

/*===========================================================================
*=========================================================================*/
void Geometry3D::CallBackSaveElementTMeshes (SCR_tdst_File_Description *p_stFile, char *p_szSectionName, GEO_tdstElementTMeshes *p_stElement)
{

}

/*===========================================================================
*=========================================================================*/
void Geometry3D::CallBackSaveElementPoints (SCR_tdst_File_Description *p_stFile, char *p_szSectionName, GEO_tdstElementPoints *p_stElement)
{
	char	szSectionName[SCR_CV_ui_Cfg_MaxLenName];
	char	szActionName[SCR_CV_ui_Cfg_MaxLenName];
	char	szName[SCR_CV_ui_Cfg_MaxLenName];
	long	iInd;
    char    *p_szGMName;

	// get section name
	SCR_fn_v_RdL0_SplitSectionName(p_szSectionName, NULL, szActionName, szName);
	SCR_fn_v_RdL0_ComputeSectionName(szSectionName, NULL, szActionName, szName);

	// save section beginning
	SCR_M_SvL0_SaveBeginSection(p_stFile, szSectionName, SCR_CC_C_Cfg_NoChar);
	SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1, "%d", p_stElement->xNbPoints);

	// save fatness entry
	SCR_M_SvL0_SaveEntry(p_stFile, "Fatness", SCR_CC_C_Cfg_NoChar);
	SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1, "%.6f", p_stElement->xFatness);

	// save list of points
	for (iInd = 0; iInd < p_stElement->xNbPoints; iInd++)
	{
		SCR_M_SvL0_SaveEntry(p_stFile, "AddPoint", SCR_CC_C_Cfg_NoChar);
		SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1,
			"%d,%d", iInd, p_stElement->d_xListOfPointIndex[iInd]);
	}

	// save GameMaterial Entry
    p_szGMName = mfn_p_szGetGameMaterialName( p_stElement->hMaterial );
	SCR_M_SvL0_SaveEntry(p_stFile, "GameMaterial", SCR_CC_C_Cfg_NoChar);
	SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1, "%s", p_szGMName);

	// save end of section
	SCR_M_SvL0_SaveEndSection(p_stFile, SCR_CC_C_Cfg_EOL);
}

/*===========================================================================
*=========================================================================*/
void Geometry3D::CallBackSaveElementLines (SCR_tdst_File_Description *p_stFile, char *p_szSectionName, GEO_tdstElementLines *p_stElement)
{
	char	szSectionName[SCR_CV_ui_Cfg_MaxLenName];
	char	szActionName[SCR_CV_ui_Cfg_MaxLenName];
	char	szName[SCR_CV_ui_Cfg_MaxLenName];
	long	iInd;

	// get section name
	SCR_fn_v_RdL0_SplitSectionName(p_szSectionName, NULL, szActionName, szName);
	SCR_fn_v_RdL0_ComputeSectionName(szSectionName, NULL, szActionName, szName);

	// save section beginning
	SCR_M_SvL0_SaveBeginSection(p_stFile, szSectionName, SCR_CC_C_Cfg_NoChar);
	SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1, "%d", p_stElement->xNbLines);

	// save thickness entry
	SCR_M_SvL0_SaveEntry(p_stFile, "Thickness", SCR_CC_C_Cfg_NoChar);
	SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1, "%.6f", p_stElement->xThickness);

	// save list of lines
	for (iInd = 0; iInd < p_stElement->xNbLines; iInd++)
	{
		SCR_M_SvL0_SaveEntry(p_stFile, "AddLine", SCR_CC_C_Cfg_NoChar);
		SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1,
			"%d,%d,%d",
			iInd,
			p_stElement->d_stListOfLineIndex[iInd].a2_xIndex[0],
			p_stElement->d_stListOfLineIndex[iInd].a2_xIndex[1]);
	}

	// Save end of section
	SCR_M_SvL0_SaveEndSection(p_stFile, SCR_CC_C_Cfg_EOL);
}

/*===========================================================================
*=========================================================================*/
void Geometry3D::CallBackSaveElementSpheres (SCR_tdst_File_Description *p_stFile, char *p_szSectionName, GEO_tdstElementSpheres *p_stElement)
{
	char	szSectionName[SCR_CV_ui_Cfg_MaxLenName];
	char	szActionName[SCR_CV_ui_Cfg_MaxLenName];
	char	szName[SCR_CV_ui_Cfg_MaxLenName];
	long	iInd;
	char    *p_szGMName;

	// get section name
	SCR_fn_v_RdL0_SplitSectionName(p_szSectionName, NULL, szActionName, szName);
	SCR_fn_v_RdL0_ComputeSectionName(szSectionName, NULL, szActionName, szName);

	// save section beginning
	SCR_M_SvL0_SaveBeginSection(p_stFile, szSectionName, SCR_CC_C_Cfg_NoChar);
	SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1, "%d", p_stElement->xNbSpheres);


	// save list of spheres
	for (iInd = 0; iInd < p_stElement->xNbSpheres; iInd++)
	{
        p_szGMName = mfn_p_szGetGameMaterialName( p_stElement->d_stListOfSpheres[iInd].hMaterial );
		SCR_M_SvL0_SaveEntry(p_stFile, "AddSphere", SCR_CC_C_Cfg_NoChar);
		SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1,
			"%d,%d,%.6f,%s",
			iInd,
			p_stElement->d_stListOfSpheres[iInd].xCenterPoint,
			p_stElement->d_stListOfSpheres[iInd].xRadius,
			p_szGMName);
	}

	// save end of section
	SCR_M_SvL0_SaveEndSection(p_stFile, SCR_CC_C_Cfg_EOL);
}

/*===========================================================================
*=========================================================================*/
void Geometry3D::CallBackSaveElementAlignedBox (SCR_tdst_File_Description *p_stFile, char *p_szSectionName, GEO_tdstElementAlignedBoxes *p_stElement)
{
	char	szSectionName[SCR_CV_ui_Cfg_MaxLenName];
	char	szActionName[SCR_CV_ui_Cfg_MaxLenName];
	char	szName[SCR_CV_ui_Cfg_MaxLenName];
	long	iInd;
    char    *p_szGMName;

    // get section name
	SCR_fn_v_RdL0_SplitSectionName(p_szSectionName, NULL, szActionName, szName);
	SCR_fn_v_RdL0_ComputeSectionName(szSectionName, NULL, szActionName, szName);

	// save section beginning
	SCR_M_SvL0_SaveBeginSection(p_stFile, szSectionName, SCR_CC_C_Cfg_NoChar);
	SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1, "%d", p_stElement->xNbAlignedBoxes);

	// save list of aligned boxes
	for (iInd = 0; iInd < p_stElement->xNbAlignedBoxes; iInd++)
	{
        p_szGMName = mfn_p_szGetGameMaterialName( p_stElement->d_stListOfAlignedBoxes[iInd].hMaterial );
		SCR_M_SvL0_SaveEntry(p_stFile, "AddAlignedBox", SCR_CC_C_Cfg_NoChar);
		SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1,
			"%d,%d,%d,%s",
			iInd,
			p_stElement->d_stListOfAlignedBoxes[iInd].xMinPoint,
			p_stElement->d_stListOfAlignedBoxes[iInd].xMaxPoint,
			p_szGMName);
	}

	// save end of section
	SCR_M_SvL0_SaveEndSection(p_stFile, SCR_CC_C_Cfg_EOL);
}

/*===========================================================================
*=========================================================================*/
void Geometry3D::CallBackSaveElementCones (SCR_tdst_File_Description *p_stFile, char *p_szSectionName, GEO_tdstElementCones *p_stElement)
{
	char	szSectionName[SCR_CV_ui_Cfg_MaxLenName];
	char	szActionName[SCR_CV_ui_Cfg_MaxLenName];
	char	szName[SCR_CV_ui_Cfg_MaxLenName];
	long	iInd;
	char    *p_szGMName;

	// get section name
	SCR_fn_v_RdL0_SplitSectionName(p_szSectionName, NULL, szActionName, szName);
	SCR_fn_v_RdL0_ComputeSectionName(szSectionName, NULL, szActionName, szName);

	// save section beginning
	SCR_M_SvL0_SaveBeginSection(p_stFile, szSectionName, SCR_CC_C_Cfg_NoChar);
	SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1, "%d", p_stElement->xNbCones);

	// save list of cones
	for (iInd = 0; iInd < p_stElement->xNbCones; iInd++)
	{
        p_szGMName = mfn_p_szGetGameMaterialName( p_stElement->d_stListOfCones[iInd].hMaterial );
		SCR_M_SvL0_SaveEntry(p_stFile, "AddCone", SCR_CC_C_Cfg_NoChar);
		SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1,
			"%d,%d,%d,%.6f,%s",
			iInd,
			p_stElement->d_stListOfCones[iInd].xTopPoint,
			p_stElement->d_stListOfCones[iInd].xBasePoint,
			p_stElement->d_stListOfCones[iInd].xBaseRadius,
            p_szGMName);
	}

	// save end of section
	SCR_M_SvL0_SaveEndSection(p_stFile, SCR_CC_C_Cfg_EOL);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method : Geometry3D::CallBackSaveElementAltimap
// Date   : 98.03
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description : saves an altimap into a file
// Author      : Cristi Petrescu
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification :
// Date         :
// By           :
//////////////////////////////////////////////////////////////////////////////////////////////////////
void Geometry3D::CallBackSaveElementAltimap (SCR_tdst_File_Description *p_stFile, char *p_szSectionName, GEO_tdstElementAltimap *p_stElement)
{
	char			szSectionName[SCR_CV_ui_Cfg_MaxLenName];
	char			szActionName[SCR_CV_ui_Cfg_MaxLenName];
	char			szName[SCR_CV_ui_Cfg_MaxLenName];
	char			*p_szGMName;
	ACP_tdxIndex	xI, xJ, xK, xF;

	// get section name
	SCR_fn_v_RdL0_SplitSectionName(p_szSectionName, NULL, szActionName, szName);
	SCR_fn_v_RdL0_ComputeSectionName(szSectionName, NULL, szActionName, szName);

	// save section beginning
	SCR_M_SvL0_SaveBeginSection(p_stFile, szSectionName, SCR_CC_C_Cfg_NoChar);
	// nb of vertex, square, faces, uv
	SCR_fn_v_SvL0_SaveParameters_MP (p_stFile, SCR_EF_SvL0_Scanf, 1, "%d,%d,%d,%d", 
		(p_stElement -> xWidth + 1) * (p_stElement -> xDepth + 1),
		p_stElement -> xWidth * p_stElement -> xDepth,
		p_stElement -> xNbFaces,
		p_stElement -> xNbUVValues);

	// save origin
	SCR_M_SvL0_SaveEntry(p_stFile, "Origin", SCR_CC_C_Cfg_NoChar);
	SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1,
		"%.6f,%.6f,%.6f",
		p_stElement -> stOrigin . xX,
		p_stElement -> stOrigin . xY,
		p_stElement -> stOrigin . xZ);

	// save square pattern
	SCR_M_SvL0_SaveEntry(p_stFile, "SquarePattern", SCR_CC_C_Cfg_NoChar);
	SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1,
		"%d,%.6f,%d,%.6f",
		p_stElement -> xWidth,
		p_stElement -> xDeltaX,
		p_stElement -> xDepth,
		p_stElement -> xDeltaY);

	// save list of vertexes
	//--- xI : Width
	//--- xJ : Height
	//--- xK : xJ * (Width+1) + xI
	for(xJ = 0, xK = 0; xJ < p_stElement -> xDepth + 1; xJ ++)
		for(xI = 0; xI < p_stElement -> xWidth + 1; xI ++, xK ++)
		{
			SCR_M_SvL0_SaveEntry(p_stFile, "SetVertex", SCR_CC_C_Cfg_NoChar);
			SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1,
				"%d,%.6f,%.6f,%.6f,.6f",
				xK,
				p_stElement -> d_xHeight [xK],
				p_stElement -> d_stPointNormals [xK] . xX,
				p_stElement -> d_stPointNormals [xK] . xY,
				p_stElement -> d_stPointNormals [xK] . xZ);
		}

	// save squares & triangles
	for(xK = 0; xK< p_stElement -> xWidth * p_stElement->xDepth; xK ++)
	{
		// the square
		xF = p_stElement -> d_stSquare [xK] . xFaceIndex;
		SCR_M_SvL0_SaveEntry(p_stFile, "SetSquare", SCR_CC_C_Cfg_NoChar);
		SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1,
			"%d,%u,%d",
			xK,
			(unsigned int) p_stElement -> d_stSquare [xK] . ucType,
			xF);
		// the faces
		switch (p_stElement -> d_stSquare [xK] . ucType)
		{
		case GEO_C_xAltiSquareBothTRBL:
		case GEO_C_xAltiSquareBothTLBR:
			// Save the Second triangle
			// ###########
			p_szGMName = mfn_p_szGetGameMaterialName (p_stElement->d_hMaterial[ p_stElement->d_stFaces[xF+1].ucMatIndex]);
			SCR_M_SvL0_SaveEntry(p_stFile, "SetTriangle", SCR_CC_C_Cfg_NoChar);
			SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1,
				"%d,%.6f,%.6f,%.6f,%s,%d,%d,%d",
				xF + 1,
				p_stElement -> d_stFaces [xF + 1] . stNormal . xX,
				p_stElement -> d_stFaces [xF + 1] . stNormal . xY,
				p_stElement -> d_stFaces [xF + 1] . stNormal . xZ,
				p_szGMName,
				p_stElement -> d_stFaces [xF + 1] . xUVIndex [0],
				p_stElement -> d_stFaces [xF + 1] . xUVIndex [1],
				p_stElement -> d_stFaces [xF + 1] . xUVIndex [2]);
			// Save the first triangle, too. No break.
		case GEO_C_xAltiSquareTopRight:
		case GEO_C_xAltiSquareBottomLeft:
		case GEO_C_xAltiSquareTopLeft:
		case GEO_C_xAltiSquareBottomRight:
			// ###########
			p_szGMName = mfn_p_szGetGameMaterialName (p_stElement->d_hMaterial[ p_stElement->d_stFaces[xF].ucMatIndex]);
			SCR_M_SvL0_SaveEntry(p_stFile, "SetTriangle", SCR_CC_C_Cfg_NoChar);
			SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1,
				"%d,%.6f,%.6f,%.6f,%s,%d,%d,%d",
				xF,
				p_stElement -> d_stFaces [xF] . stNormal . xX,
				p_stElement -> d_stFaces [xF] . stNormal . xY,
				p_stElement -> d_stFaces [xF] . stNormal . xZ,
				p_szGMName,
				p_stElement -> d_stFaces [xF] . xUVIndex [0],
				p_stElement -> d_stFaces [xF] . xUVIndex [1],
				p_stElement -> d_stFaces [xF] . xUVIndex [2]);
			break;
		case GEO_C_xAltiSquareVoid:
			break;
		default:
			ASSERT (FALSE);
		}
	}

	// save the uv
	for (xK = 0; xK < p_stElement -> xNbUVValues; xK ++)
	{
		SCR_M_SvL0_SaveEntry(p_stFile, "AddUV", SCR_CC_C_Cfg_NoChar);
		SCR_fn_v_SvL0_SaveParameters_MP(p_stFile, SCR_EF_SvL0_Scanf, 1,
			"%d,%.6f,%.6f",
			xK,
			p_stElement -> d_stUVValues [xK] . xU,
			p_stElement -> d_stUVValues [xK] . xV);
	}

	// save end of section
	SCR_M_SvL0_SaveEndSection(p_stFile, SCR_CC_C_Cfg_EOL);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//                             MODIFICATIONS                                 //
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

// ----------------------------------------------------------------------------
// Description : clear list of Points modifications
// ----------------------------------------------------------------------------
void Geometry3D::fn_vClearModificationsList()
{
    while ( ! m_oListOfModifiedPoints . IsEmpty() )
        delete m_oListOfModifiedPoints . RemoveHead();
    //
    fn_vSetModification( C_szFormModif, FALSE );
}

// ----------------------------------------------------------------------------
// Description : add a Point modification
// ----------------------------------------------------------------------------
void Geometry3D::fn_vAddModification(ACP_tdxIndex _xIndex/*, MTH3D_tdstVector *_p_st3DPoint*/)
{
    tdstModifPoint *p_stModif = fn_p_stGetModification( _xIndex );
    if( !p_stModif )
    {
        p_stModif = new(tdstModifPoint);
        p_stModif -> xIndexOfPoint = _xIndex;
        m_oListOfModifiedPoints . AddTail( p_stModif );

        if( m_oListOfModifiedPoints . GetCount() == 1 )
            fn_vSetModification( C_szFormModif, TRUE, FALSE );
    }
	// BEGIN CPA2 Cristi Petrescu 98-02-
	/*
    memcpy( &(p_stModif -> st3DPoint), _p_st3DPoint, sizeof(MTH3D_tdstVector) );
	*/
	// END CPA2 Cristi Petrescu 98-02-
}

// ----------------------------------------------------------------------------
// Description : return modification to given point, or null if none
// ----------------------------------------------------------------------------
tdstModifPoint *Geometry3D::fn_p_stGetModification(ACP_tdxIndex _xIndex)
{
    tdstModifPoint *p_stModif;
    POSITION        xPos;

    M_ForEachElement( m_oListOfModifiedPoints, p_stModif, xPos )
    {
        if( p_stModif -> xIndexOfPoint == _xIndex )
            return p_stModif;
    }
    return NULL;
}

// ----------------------------------------------------------------------------
// Description : set point to new values without responsability verification
// ----------------------------------------------------------------------------
void Geometry3D::fn_vOwnerSetPoint(ACP_tdxIndex xNumPoint,MTH3D_tdstVector *p_stPoint)
{
    GEO_vSetPointOfObject(GetStruct(),p_stPoint,xNumPoint);
    fn_vEndModification();
}

// ----------------------------------------------------------------------------
// Description : compute internal informations
// ----------------------------------------------------------------------------
void Geometry3D::fn_vEndModification(void)
{
// ANNECY MT 13-02-98 {
    if( m_bEndCreated )
	{
        GEO_vEndModifyObject2(GetStruct());
		if( GetStruct() -> d_hListOfPointsMaterial != NULL )
			GEO_vComputeObjectListOfPointsMaterial( GetStruct() );
	}
// END ANNECY MT }
}

// ----------------------------------------------------------------------------
// Description : clear list of Material modifications
// ----------------------------------------------------------------------------
void Geometry3D::fn_vClearGMTModificationsList()
{
    while ( ! m_oListOfGMTModif . IsEmpty() )
        delete m_oListOfGMTModif . RemoveHead();
    //
    fn_vSetModification( C_szMaterialModif, FALSE );
}

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
void Geometry3D::fn_vAddGMTModification(ACP_tdxHandleOfElement _hElement, ACP_tdxIndex _xIndexInElement, GMT_tdxHandleToGameMaterial _hGameMaterial)
{
	//CPA2 Stegaru Cristian 98-04
	//no previous game material
	if (NULL == _hGameMaterial)
		return;
	//End CPA2 Stegaru Cristian 98-04

    ACP_tdxIndex _xElementType = GEO_xGetElementType(GetStruct() , _hElement);

    tdstModifGMT *p_stModif = fn_p_stGetGMTModification( _hElement, _xIndexInElement );
    if( !p_stModif )
    {
        // add new modification
        p_stModif = new(tdstModifGMT);
        p_stModif -> xElementType = _xElementType;
        p_stModif -> hElement = _hElement;
		//BEGIN ROMTEAM Cristi Petrescu 98-06-
		if (_xElementType == GEO_C_xElementIndexedTriangles)
			p_stModif -> xIndexInElement = 0;
		else
			p_stModif -> xIndexInElement = _xIndexInElement;
		// set modif
		// BEGIN CPA2 Cristi Petrescu 98-02-
		p_stModif -> hGameMaterial = _hGameMaterial;
		// END CPA2 Cristi Petrescu 98-02-
		//END ROMTEAM Cristi Petrescu 98-06-
        m_oListOfGMTModif . AddTail( p_stModif );

        if( m_oListOfGMTModif . GetCount() == 1 )
            fn_vSetModification( C_szMaterialModif, TRUE, FALSE );
    }
	// BEGIN ROMTEAM Cristi Petrescu 98-06-
	// moved...
	// END ROMTEAM Cristi Petrescu 98-06-
}

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
tdstModifGMT *Geometry3D::fn_p_stGetGMTModification(ACP_tdxHandleOfElement _hElement, ACP_tdxIndex _xIndexInElement)
{
    ACP_tdxIndex _xElementType = GEO_xGetElementType(GetStruct(), _hElement);
    tdstModifGMT *p_stModif;
    POSITION     xPos;

    M_ForEachElement( m_oListOfGMTModif, p_stModif, xPos )
    {
        if( ( _xElementType == p_stModif -> xElementType ) &&
            ( _hElement == p_stModif -> hElement ) &&
            ( _xIndexInElement == p_stModif -> xIndexInElement)
          )
            return p_stModif;
    }
    return NULL;
}

// ----------------------------------------------------------------------------
// Description : set point to new values without responsability verification
// ----------------------------------------------------------------------------
void Geometry3D::fn_vOwnerSetMaterial(ACP_tdxHandleOfElement _hElement, ACP_tdxIndex _xIndexInElement, GMT_tdxHandleToGameMaterial _hGameMaterial)
{
    if( !_hGameMaterial )
        return;

    ACP_tdxIndex        _xElementType = GEO_xGetElementType(GetStruct(), _hElement);
    ACP_tdxIndex        xIndexUnused;
    ACP_tdxHandleOfFMD  p_stFMD;

    switch( _xElementType )
    {
		case GEO_C_xElementIndexedTriangles:
            if( fn_bIsIndexedTriangle( _hElement, _xIndexInElement ) )
                GEO_vSetGameMaterialOfIndexedTriangles(GetStruct(), _hElement, _hGameMaterial);
			break;
		case GEO_C_xElementFaceMapDescriptors:
            GEO_xGetFaceOfElementFaceMap( GetStruct(), _hElement , _xIndexInElement, &xIndexUnused, &xIndexUnused, &xIndexUnused, &p_stFMD );
            GEO_xSetFaceMapDescriptorGameMaterial( p_stFMD, _hGameMaterial);
			break;
		case GEO_C_xElementSprites:
            // no material
			break;
		case GEO_C_xElementTMeshes:
            // no function on element.h (engine )
			break;
		case GEO_C_xElementPoints:
            if( fn_bIsPoint( _hElement, _xIndexInElement ) )
                GEO_xSetGameMaterialOfElementPoints( GetStruct(), _hElement, _hGameMaterial );
			break;
		case GEO_C_xElementLines:
            if( fn_bIsLine( _hElement, _xIndexInElement ) )
                GEO_xSetGameMaterialOfElementLines( GetStruct(), _hElement, _xIndexInElement, _hGameMaterial );
			break;
		case GEO_C_xElementSpheres:
            if( fn_bIsSphere( _hElement, _xIndexInElement ) )
                GEO_vSetGameMaterialOfIndexedSphere( GetStruct(), _hElement, _xIndexInElement, _hGameMaterial );
			break;
		case GEO_C_xElementAlignedBoxes:
            if( fn_bIsAlignedBox( _hElement, _xIndexInElement ) )
                GEO_vSetGameMaterialOfIndexedAlignedBox( GetStruct(), _hElement, _xIndexInElement, _hGameMaterial );
			break;
		case GEO_C_xElementCones:
            if( fn_bIsCone( _hElement, _xIndexInElement ) )
                GEO_vSetGameMaterialOfIndexedCone( GetStruct(), _hElement, _xIndexInElement, _hGameMaterial );
			break;
    }
    fn_vEndGMTModification( _hElement, _xIndexInElement );
}

// ----------------------------------------------------------------------------
// Description : compute internal informations about GameMaterial
// ----------------------------------------------------------------------------
void Geometry3D::fn_vEndGMTModification(ACP_tdxHandleOfElement _hElement, ACP_tdxIndex _xDataElementIndex/*=0*/)
{
    if( m_bEndCreated )
        GEO_vComputeElementMaterial(GetStruct(), _hElement, _xDataElementIndex );
}

// ----------------------------------------------------------------------------
//  Author      : MT
//  Creation    : 31/07/97
//
// Description :
// ----------------------------------------------------------------------------
void Geometry3D::fn_vClearFMDModificationsList(void)
{
    while( ! m_oListOfFMDModif . IsEmpty() )
        free( m_oListOfFMDModif . RemoveHead() );
}

// ----------------------------------------------------------------------------
//  Author      : MT
//  Creation    : 31/07/97
//
// Description :
// ----------------------------------------------------------------------------
void Geometry3D::fn_vAddFMDModification(ACP_tdxIndex xElementIT, ACP_tdxIndex xFaceIT, ACP_tdxIndex xElementFMD, ACP_tdxIndex xFaceFMD)
{
    tdstModifFMD    *p_stFMDModif = fn_p_stGetFMDModification( xElementIT, xFaceIT, xElementFMD, xFaceFMD);

    if( p_stFMDModif == NULL )
    {
        p_stFMDModif = (tdstModifFMD*) malloc( sizeof( tdstModifFMD ) );
        p_stFMDModif -> xElementIT = xElementIT;
        p_stFMDModif -> xIndexFaceIT = xFaceIT;
        p_stFMDModif -> xElementFMD = xElementFMD;
        p_stFMDModif -> xIndexFaceFMD = xFaceFMD;
        m_oListOfFMDModif . AddHead( p_stFMDModif );
    }
}

// ----------------------------------------------------------------------------
//  Author      : MT
//  Creation    : 31/07/97
//
// Description :
// ----------------------------------------------------------------------------
void Geometry3D::fn_vDelFMDModification(ACP_tdxIndex xElementIT, ACP_tdxIndex xFaceIT, ACP_tdxIndex xElementFMD, ACP_tdxIndex xFaceFMD)
{
    tdstModifFMD    *p_stFMDModif;
    POSITION        xPos;

    M_ForEachElement( m_oListOfFMDModif, p_stFMDModif, xPos )
    {
        if( ( p_stFMDModif -> xElementIT == xElementIT ) && ( p_stFMDModif -> xIndexFaceIT == xFaceIT ) )
        {
            m_oListOfFMDModif . RemoveAt( xPos );
            free( p_stFMDModif );
            break;
        }
    }
}

// ----------------------------------------------------------------------------
//  Author      : MT
//  Creation    : 31/07/97
//
// Description : search Modification by source
// ----------------------------------------------------------------------------
tdstModifFMD *Geometry3D::fn_p_stGetFMDModification(ACP_tdxIndex xElementIT, ACP_tdxIndex xFaceIT, ACP_tdxIndex xElementFMD, ACP_tdxIndex xFaceFMD)
{
    tdstModifFMD    *p_stFMDModif;
    POSITION        xPos;

    M_ForEachElement( m_oListOfFMDModif, p_stFMDModif, xPos )
    {
        if( ( p_stFMDModif -> xElementIT == xElementIT ) && ( p_stFMDModif -> xIndexFaceIT == xFaceIT ) &&
            ( p_stFMDModif -> xElementFMD == xElementFMD ) && ( p_stFMDModif -> xIndexFaceFMD == xFaceFMD ) )
            return p_stFMDModif;
    }
    return NULL;
}


// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
GMT_tdxHandleToGameMaterial Geometry3D::fn_hGetGameMaterial(ACP_tdxHandleOfElement _hElement, ACP_tdxIndex _xIndexInElement)
{
    GMT_tdxHandleToGameMaterial hGameMaterial = NULL;
    ACP_tdxIndex                xElementType  = GEO_xGetElementType(GetStruct(), _hElement);

    switch( xElementType )
    {
		case GEO_C_xElementIndexedTriangles:
            if( fn_bIsIndexedTriangle( _hElement, _xIndexInElement ) )
		        GEO_vGetGameMaterialOfIndexedTriangles(GetStruct(), _hElement, &hGameMaterial);
			break;
		case GEO_C_xElementFaceMapDescriptors:
            if ( fn_bIsFMD( _hElement, _xIndexInElement ) )
            {
                ACP_tdxIndex        xIndexUnused;
                ACP_tdxHandleOfFMD  p_stFMD;
                GEO_xGetFaceOfElementFaceMap( GetStruct(), _hElement , _xIndexInElement, &xIndexUnused, &xIndexUnused, &xIndexUnused, &p_stFMD );
                GEO_xGetFaceMapDescriptorGameMaterial( p_stFMD, &hGameMaterial );
            }
			break;
		case GEO_C_xElementSprites:
            // no material
			break;
		case GEO_C_xElementTMeshes:
            // no function on element.h (engine )
			break;
		case GEO_C_xElementPoints:
            if( fn_bIsPoint( _hElement, _xIndexInElement ) )
                hGameMaterial = GEO_xGetGameMaterialOfElementPoints( GetStruct(), _hElement );
			break;
		case GEO_C_xElementLines:
            if( fn_bIsLine( _hElement, _xIndexInElement ) )
                GEO_xGetGameMaterialOfElementLines( GetStruct(), _hElement, _xIndexInElement, &hGameMaterial );
			break;
		case GEO_C_xElementSpheres:
            if( fn_bIsSphere( _hElement, _xIndexInElement ) )
                hGameMaterial = GEO_hGetGameMaterialOfIndexedSphere( GetStruct(), _hElement, _xIndexInElement );
			break;
		case GEO_C_xElementAlignedBoxes:
            if( fn_bIsAlignedBox( _hElement, _xIndexInElement ) )
                hGameMaterial = GEO_vGetGameMaterialOfIndexedAlignedBox( GetStruct(), _hElement, _xIndexInElement );
			break;
		case GEO_C_xElementCones:
            if( fn_bIsCone( _hElement, _xIndexInElement ) )
                hGameMaterial = GEO_vGetGameMaterialOfIndexedCone ( GetStruct(), _hElement, _xIndexInElement );
			break;
    }

    return hGameMaterial;
}

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
GMT_tdxHandleToGameMaterial Geometry3D::fn_hGetDefaultGameMaterial(void)
{
    if( s_p_oDLLTGM )
    {
        return (GMT_tdxHandleToGameMaterial) s_p_oDLLTGM -> OnQueryAction( (CPA_DLLBase*)GetEditor(), (WPARAM)C_cGetDefaultGameMaterial, 0);
    }
    else
    {
		//if we did not create the editor materials, find an engine material in the link table
        // first, search default material
        char szFileName[SCR_CV_ui_Cfg_MaxLenName];
        char szCompleteSectionName[SCR_CV_ui_Cfg_MaxLenName];
		SCR_tdst_Link_Value *p_stEntry;
		SCR_tdst_Link_Table *p_stLinkTable = GMT_fn_p_stGetLinkTable();
		unsigned int uiPos;

        sprintf( szFileName, "%s\\Common\\Common.gmt", fn_szGetGameMaterialDataPath() );
        SCR_fn_v_RdL0_ComputeSectionName( szCompleteSectionName, szFileName, "GameMaterial", "Default" );

        p_stEntry = SCR_fnp_st_Link_SearchKey(GMT_fn_p_stGetLinkTable(),szCompleteSectionName);
        if( p_stEntry != NULL )
            return (GMT_tdxHandleToGameMaterial)SCR_M_ul_Link_GetValue( p_stEntry );
        // else get first entry on Link Table

        uiPos = 0;
		SCR_M_DyAr_GetNextElement( SCR_tdst_Link_Value, uiPos, p_stEntry, p_stLinkTable->stLinkArray );
		return (GMT_tdxHandleToGameMaterial)(p_stEntry ? SCR_M_ul_Link_GetValue(p_stEntry) : NULL);
    }
}

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
char * Geometry3D::mfn_p_szGetGameMaterialName(GMT_tdxHandleToGameMaterial hGameMaterial)
{
    if( s_p_oDLLTGM )
    {
        CPA_BaseObject *p_oGameMaterial = s_p_oDLLTGM -> GetBaseObject( (void*)hGameMaterial, C_szGameMaterialTypeName );
        if( p_oGameMaterial && p_oGameMaterial->fn_bCanBeSaved() )
            return ((char*)(LPCTSTR) ((CPA_SaveObject *) p_oGameMaterial )-> GetReferencedSectionName() );
    }
    // no DLL GameMaterial or No GameMaterial Editor Object
    SCR_tdst_Link_Value *p_stEntry = SCR_fnp_st_Link_SearchValue(GMT_fn_p_stGetLinkTable(),(unsigned long)hGameMaterial);
    if( p_stEntry )
    {
        char *szCompleteSectionName = SCR_M_p_sz_Link_GetKey( p_stEntry );
        unsigned long ulSize = SCR_M_ul_Link_GetAdditionalLong( p_stEntry ,1 );

        return ( szCompleteSectionName + ulSize );
    }
    return C_szDefaultMaterial;
}

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
BOOL Geometry3D::mfn_bMustSaveModifications()
{
    return ( ( GetSaveStatus() == E_ss_Modify ) &&
             ( ! m_oListOfModifiedPoints . IsEmpty() || ! m_oListOfGMTModif . IsEmpty() || ! m_oListOfFMDModif . IsEmpty() ) );
}

// ----------------------------------------------------------------------------
// Description :
// ----------------------------------------------------------------------------
void Geometry3D::mfn_vSaveModifications(FILE *_pFile, char *_szIdentity)
{
// BEGIN CPA2 Cristi Petrescu 98-02-	
/*
    tdstModifPoint          *p_stModif;
    tdstModifGMT            *p_stGMTModif;
    tdstModifFMD            *p_stFMDModif;
    POSITION                 xPos;
    char                     szName[SCR_CV_ui_Cfg_MaxLenName];
    char                    *p_cFMDName;
    SectionElement          *p_oSectionElement;
    GEO_tdstFaceMapTriangle *p_stFMT;

    // header
    fprintf( _pFile, "\nObject %s:\t\tModified : %s\n{\n", fn_p_szGetName(), _szIdentity );
    // Translation
    if( ! m_oListOfModifiedPoints . IsEmpty() )
    {
        fputs( "Translated Points\n", _pFile );
        M_ForEachElement( m_oListOfModifiedPoints, p_stModif, xPos )
        {

            fprintf( _pFile, "\tPoint %3d : initial position : ( %.6f , %.6f , %.6f )\n",
                             p_stModif -> xIndexOfPoint,
                             p_stModif -> st3DPoint . xX, p_stModif -> st3DPoint . xY, p_stModif -> st3DPoint . xZ);
        }
        fn_vClearModificationsList();
    }
    // FMD
    if( !m_oListOfFMDModif . IsEmpty() )
    {
        fputs( "Faces Move to FaceMapDescriptors\n", _pFile );
        M_ForEachElement( m_oListOfFMDModif, p_stFMDModif, xPos )
        {
            p_oSectionElement = m_oListOfElementSections . GetAt( m_oListOfElementSections . FindIndex( p_stFMDModif -> xElementIT ) );
            SCR_fn_v_RdL0_SplitSectionName( (char*)(LPCTSTR)p_oSectionElement -> GetCompleteSectionName(), NULL, NULL, szName );

            p_stFMT = & M_GetFMTToElementFMD( p_stFMDModif -> xElementFMD, p_stFMDModif -> xIndexFaceFMD );

            fprintf( _pFile, "\t Face %3d (%3d,%3d,%3d) of IT \"%s\"",
                            p_stFMDModif -> xIndexFaceIT,
                            p_stFMT -> stFaceTripled . a3_xIndex[0],
                            p_stFMT -> stFaceTripled . a3_xIndex[1],
                            p_stFMT -> stFaceTripled . a3_xIndex[2],
                            szName );

            p_oSectionElement = m_oListOfElementSections . GetAt( m_oListOfElementSections . FindIndex( p_stFMDModif -> xElementFMD ) );
            SCR_fn_v_RdL0_SplitSectionName( (char*)(LPCTSTR)p_oSectionElement -> GetCompleteSectionName(), NULL, NULL, szName );

            fprintf( _pFile, " Moved to Face %3d on ElementFMD \"%s\" ", p_stFMDModif -> xIndexFaceFMD, szName );

            p_cFMDName = M_LKTB_SearchKeyByValue( GLI_p_stGetLinkTableOfFaceMapDescriptor(), (unsigned long)M_GetFMDToElementFMD( p_stFMDModif -> xElementFMD, p_stFMDModif -> xIndexFaceFMD ) );
            SCR_fn_v_RdL0_SplitSectionName( p_cFMDName, NULL, NULL, szName );
            fprintf( _pFile, "\t Create FMD \"%s\"\n", szName );
        }
        fn_vClearFMDModificationsList();
    }
    // GMT
    if( ! m_oListOfGMTModif . IsEmpty() )
    {
        fputs( "Material \n", _pFile );
        M_ForEachElement( m_oListOfGMTModif, p_stGMTModif, xPos )
        {
            CPA_SaveObject *p_oPreviousGM = (CPA_SaveObject*)s_p_oDLLTGM -> GetBaseObject(p_stGMTModif -> hGameMaterial, C_szGameMaterialTypeName);
            CPA_SaveObject *p_oNewGM = (CPA_SaveObject*)fn_p_oGetGameMaterial( p_stGMTModif -> hElement, p_stGMTModif -> xIndexInElement );
			
			if( p_oPreviousGM && p_oNewGM )
			{
				fprintf( _pFile, "\t Element %3d \t Type \"%s\" \t IndexInElement %3d \t GameMaterial \"%s\" ===> \"%s\"\n",
								 p_stGMTModif -> hElement,
								 g_szElementTypeName[ p_stGMTModif -> xElementType ],
								 p_stGMTModif -> xIndexInElement,
								 (char*)(LPCTSTR)p_oPreviousGM -> GetReferencedSectionName(),
								 (char*)(LPCTSTR)p_oNewGM -> GetReferencedSectionName());
			}
        }
        fn_vClearGMTModificationsList();
    }
    //
    fputs( "}\n\n", _pFile );
    fputs( "///////////////////////////////////////////////////////////////////////////////////////////////////\n\n", _pFile );
*/
// END CPA2 Cristi Petrescu 98-02-
}

/*-----------------------------------------------------------------------------
 *  Author      : MT
 *  Creation    : 30/07/97
 *
 *  Description :
 *---------------------------------------------------------------------------*/
void Geometry3D::mfn_vSaveFMD(void)
{
    char szSectionName[SCR_CV_ui_Cfg_MaxLenName];
    char szFileName[SCR_CV_ui_Cfg_MaxLenName];
    char szName[SCR_CV_ui_Cfg_MaxLenName];
    char *p_cName;

    if( ! fn_bCanBeNotified() )
        return;

	// get section name
    SCR_fn_v_RdL0_SplitSectionName((char*)(LPCTSTR)GetCompleteSectionName(), szFileName, NULL, szName);

    strcat( szName,"_FMD_");
    p_cName = szName + strlen( szName );

    while( ! m_oListOfFMD . IsEmpty() )
    {
        tdstInfoFMD *p_stInfoFMD = m_oListOfFMD . RemoveHead();

        sprintf( p_cName, "%d", ++m_lUniqueFMD );
        SCR_fn_v_RdL0_ComputeSectionName(szSectionName,szFileName, GLI_C_SectionFaceMapDescriptor, szName);
        SCR_fn_v_SvL1_RegisterNotify(szSectionName, CallBackSaveFaceMapDescriptors, p_stInfoFMD -> hFMD, SCR_EA_Ntfy_AddSection);
        //
        SCR_fnp_st_Link_SetValue( GLI_p_stGetLinkTableOfFaceMapDescriptor(), szSectionName, (unsigned long)p_stInfoFMD -> hFMD );
        //
        free( p_stInfoFMD );
    }
    m_bMustSaveFMD = FALSE;
}

//ROMTEAM WorldEditor (Cristian Stegaru 12/97)
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method : mfn_vInitElement 
// Date   : 97-12
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description :
// Author      : Cristian Stegaru - CPA2
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification :
// Date         :
// By           :
//////////////////////////////////////////////////////////////////////////////////////////////////////
void Geometry3D::mfn_vInitElement (char *szFileReference, char *szClassPath, BOOL bSectionExists/* = FALSE*/)
{
    SectionElement *p_oElementSection = new SectionElement(szFileReference, szClassPath,
                                                        Geometry3D::CallBackSaveGeometricElement);
    p_oElementSection->SetSectionData (p_oElementSection);
    p_oElementSection->SetElement ((void*)GetStruct ()->d_stListOfElements[0]);
    p_oElementSection->SetExistingSection (bSectionExists);
	m_oListOfElementSections.AddTail (p_oElementSection);

    // init Modif Sections
    fn_vInitModifSections();
	// data members
	m_oListOfModifiedPoints . RemoveAll();
	//CPA2 Stegaru Cristian 98-04
	//the list is emptied in constructor
	//	m_oListOfGMTModif . RemoveAll();
	//End CPA2 Stegaru Cristian 98-04
	m_oListOfFMDModif . RemoveAll();
	m_hBoundingVolume = NULL;
	m_bMustRecomputeBdV = TRUE;
	m_bEndCreated = TRUE;
    fn_vInitFMD();
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method : mfn_vRefreshElement 
// Date   : 97-12
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description :
// Author      : Cristian Stegaru - CPA2
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification :
// Date         :
// By           :
//////////////////////////////////////////////////////////////////////////////////////////////////////
void Geometry3D::mfn_vRefreshElement ()
{
	if(m_oListOfElementSections.IsEmpty()) return;
	SectionElement *p_oElementSection = m_oListOfElementSections.GetHead ();
	ASSERT (p_oElementSection);
  p_oElementSection->SetElement ((void*)GetStruct ()->d_stListOfElements[0]);
}

//ENDROMTEAM WorldEditor (Cristian Stegaru) 

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method : Geometry3D::mfn_vComputeModificationSectionName
// Date   : 98.02
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description : Computes the name of the modification section
// Author      : Cristi Petrescu
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification :
// Date         :
// By           :
//////////////////////////////////////////////////////////////////////////////////////////////////////
void Geometry3D::mfn_vComputeModifSectionName(char *szModifSectionName)
{
    CString csCompleteSectionName = GetReferencedSectionName();
    char *szSectionName = (char*)(LPCTSTR)csCompleteSectionName;
    char *szPoint = NULL;
	char szFileName[SCR_CV_ui_Cfg_MaxLenName];

    if( strchr( szSectionName, SCR_CC_c_Cfg_NameSeparator ) != NULL )
        SCR_fn_v_RdL0_SplitSectionName(szSectionName, szFileName, NULL, NULL);
    else
        strcpy( szFileName, szSectionName );

    szPoint = strrchr( szFileName, '.' );

    if ( szPoint )
    {
        ++ szPoint;
        strcpy( szPoint, "mdt" );
    }

	SCR_fn_v_RdL0_ComputeSectionName( szModifSectionName, szFileName, C_szModifActionName, fn_p_szGetName() );
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method : Geometry3D::mfn_vLoadModifSection
// Date   : 98.02
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description : Loads the modif section
// Author      : Cristi Petrescu
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification :
// Date         :
// By           :
//////////////////////////////////////////////////////////////////////////////////////////////////////
void Geometry3D::mfn_vLoadModifSection (void)
{ 
	// load it only if it is savable...
	if (GetSaveStatus() == E_ss_Modify)
	{
		char szModifSectionName[SCR_CV_ui_Cfg_MaxLenName];

		mfn_vComputeModifSectionName (szModifSectionName);

		// analyse "Modif-Geometric" section
		if(SCR_fn_c_RdL0_IsSectionExists (szModifSectionName))
		{
			// first create the ModifSection object
			ASSERT (! m_p_oModifSection);
			mfn_vCreateModifSection (szModifSectionName);
			// and load it from file
			SCR_M_RdL0_SetContextLong (1, 0, this);
			SCR_fnp_st_RdL0_AnalyseSection (szModifSectionName, SCR_CDF_uw_Anl_Normal);
		}
	}
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method : Geometry3D::mfn_vCreateModifSection
// Date   : 98.02
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description : Creates the Modif Section
// Author      : Cristi Petrescu
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification :
// Date         :
// By           :
//////////////////////////////////////////////////////////////////////////////////////////////////////
void Geometry3D::mfn_vCreateModifSection (char *szModifSectionName/*=NULL*/)
{
	if (!szModifSectionName)
	{
		// then is a new section (not loaded from a file)
		if (! m_p_oModifSection)
		{
			// and is not already created...
			char szModifSectionName[SCR_CV_ui_Cfg_MaxLenName];
			mfn_vComputeModifSectionName (szModifSectionName);
			m_p_oModifSection = new CPA_SectionObject( szModifSectionName, GetDataPath (), Geometry3D::CallBackSaveModifGeometricObject );
			m_p_oModifSection -> SetExistingSection( FALSE );
			m_p_oModifSection -> SetSectionData( this );
			m_p_oModifSection -> fn_vWriteSection ();
		}
	}
	else
	{
		// loading from file
		m_p_oModifSection = new CPA_SectionObject( szModifSectionName, GetDataPath (), Geometry3D::CallBackSaveModifGeometricObject );
		m_p_oModifSection -> SetExistingSection (TRUE);
		m_p_oModifSection -> SetSectionData( this );
	}
}



//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method : mfn_iGetFacesNumber 
// Date   : 98-05
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description :
// Author      : Stegaru Cristian - CPA2
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification :
// Date         :
// By           :
//////////////////////////////////////////////////////////////////////////////////////////////////////
ACP_tdxIndex Geometry3D::mfn_iGetFacesNumber ()
{
	GEO_tdstGeometricObject *pGeometricObject = GetStruct ();
	ASSERT (pGeometricObject);
	//particular situation
	if (1 == pGeometricObject->xNbPoints && 1 <= pGeometricObject->xNbElements)
	{
		if (GEO_C_xElementSprites == pGeometricObject->d_xListOfElementsTypes [0])
			return 1; //only one face for a sprite
	}

	if (pGeometricObject->xNbElements >= 1 && GEO_C_xElementIndexedTriangles == pGeometricObject->d_xListOfElementsTypes [0])
	{
		GEO_tdstElementIndexedTriangles *pElement = (GEO_tdstElementIndexedTriangles *)GetStruct ()->d_stListOfElements [0];
		ASSERT (pElement);
		return pElement->xNbFaces;
	}
	return 0;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method : mfn_3dvGetMinCoordinates 
// Date   : 98-05
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description :
// Author      : Stegaru Cristian - CPA2
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification :
// Date         :
// By           :
//////////////////////////////////////////////////////////////////////////////////////////////////////
MTH3D_tdstVector Geometry3D::mfn_3dvGetMinCoordinates ()
{
	MTH3D_tdstVector tdstMinCoordinates, tdstCurrentPoint;
	tdstMinCoordinates.xX = tdstMinCoordinates.xY = tdstMinCoordinates.xZ = 0;

	ACP_tdxHandleOfObject hObject = GetStruct ();
	ACP_tdxIndex	iObjectsNb = GEO_xGetGeometricObjectNumberOfPoints (hObject);
	if (1 < iObjectsNb)
	{
		//initialize with first point's coordinates
		GEO_vGetPointOfObject (hObject, &tdstCurrentPoint, 0);
		tdstMinCoordinates.xX = tdstCurrentPoint.xX;	
		tdstMinCoordinates.xY = tdstCurrentPoint.xY;	
		tdstMinCoordinates.xZ = tdstCurrentPoint.xZ;	
		for (int iInx = 0; iInx < iObjectsNb; iInx++)
		{
			GEO_vGetPointOfObject (hObject, &tdstCurrentPoint, iInx);
			tdstMinCoordinates.xX = tdstCurrentPoint.xX < tdstMinCoordinates.xX ? tdstCurrentPoint.xX : tdstMinCoordinates.xX;	
			tdstMinCoordinates.xY = tdstCurrentPoint.xY < tdstMinCoordinates.xY ? tdstCurrentPoint.xY : tdstMinCoordinates.xY;	
			tdstMinCoordinates.xZ = tdstCurrentPoint.xZ < tdstMinCoordinates.xZ ? tdstCurrentPoint.xZ : tdstMinCoordinates.xZ;	
		}
	}
	else if (1 == iObjectsNb)
	{
		if (GEO_C_xElementSprites == hObject->d_xListOfElementsTypes [0])
		{
			GEO_tdstElementSprite *pSpriteElement = (GEO_tdstElementSprite *)hObject->d_stListOfElements [0];
			MTH_tdxReal rXSize = 0, rYSize = 0;
			for (int iSpritesInx = 0; iSpritesInx < pSpriteElement->xNbSprites; iSpritesInx++)
			{
				ACP_tdxHandleOfSprite hSprite = pSpriteElement->d_stListOfSprites [iSpritesInx].hSprite;
				for (int iSprites2Inx = 0; iSprites2Inx < hSprite->xNbSprites; iSprites2Inx++)
				{
					rXSize = hSprite->d_xSizeOfSprite [iSprites2Inx].xX > rXSize? hSprite->d_xSizeOfSprite [iSprites2Inx].xX : rXSize;
					rYSize = hSprite->d_xSizeOfSprite [iSprites2Inx].xY > rYSize? hSprite->d_xSizeOfSprite [iSprites2Inx].xY : rYSize;
				}
			}
			//compute min coordinates using the center point and the size
			MTH3D_tdstVector tdstInsertionPoint;
			GEO_vGetPointOfObject (hObject, &tdstInsertionPoint, 0);
			tdstMinCoordinates.xX = tdstInsertionPoint.xX - (rXSize / 2);
			tdstMinCoordinates.xY = tdstInsertionPoint.xY - (rYSize / 2);
			tdstMinCoordinates.xZ =	tdstInsertionPoint.xZ;		
		}
	}

	return tdstMinCoordinates;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method : mfn_3dvGetMaxCoordinates 
// Date   : 98-05
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description :
// Author      : Stegaru Cristian - CPA2
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification :
// Date         :
// By           :
//////////////////////////////////////////////////////////////////////////////////////////////////////
MTH3D_tdstVector Geometry3D::mfn_3dvGetMaxCoordinates ()
{
	MTH3D_tdstVector tdstMaxCoordinates, tdstCurrentPoint;
	tdstMaxCoordinates.xX = tdstMaxCoordinates.xY = tdstMaxCoordinates.xZ = 0;

	ACP_tdxHandleOfObject hObject = GetStruct ();
	ACP_tdxIndex	iObjectsNb = GEO_xGetGeometricObjectNumberOfPoints (hObject);
	if (1 < iObjectsNb)
	{
		//initialize with first point's coordinates
		GEO_vGetPointOfObject (hObject, &tdstCurrentPoint, 0);
		tdstMaxCoordinates.xX = tdstCurrentPoint.xX;	
		tdstMaxCoordinates.xY = tdstCurrentPoint.xY;	
		tdstMaxCoordinates.xZ = tdstCurrentPoint.xZ;	
		for (int iInx = 0; iInx < iObjectsNb; iInx++)
		{
			GEO_vGetPointOfObject (hObject, &tdstCurrentPoint, iInx);
			tdstMaxCoordinates.xX = tdstCurrentPoint.xX > tdstMaxCoordinates.xX ? tdstCurrentPoint.xX : tdstMaxCoordinates.xX;	
			tdstMaxCoordinates.xY = tdstCurrentPoint.xY > tdstMaxCoordinates.xY ? tdstCurrentPoint.xY : tdstMaxCoordinates.xY;	
			tdstMaxCoordinates.xZ = tdstCurrentPoint.xZ > tdstMaxCoordinates.xZ ? tdstCurrentPoint.xZ : tdstMaxCoordinates.xZ;	
		}
	}
	else if (1 == iObjectsNb)
	{
		if (GEO_C_xElementSprites == hObject->d_xListOfElementsTypes [0])
		{
			GEO_tdstElementSprite *pSpriteElement = (GEO_tdstElementSprite *)hObject->d_stListOfElements [0];
			MTH_tdxReal rXSize = 0, rYSize = 0;
			for (int iSpritesInx = 0; iSpritesInx < pSpriteElement->xNbSprites; iSpritesInx++)
			{
				ACP_tdxHandleOfSprite hSprite = pSpriteElement->d_stListOfSprites [iSpritesInx].hSprite;
				for (int iSprites2Inx = 0; iSprites2Inx < hSprite->xNbSprites; iSprites2Inx++)
				{
					rXSize = hSprite->d_xSizeOfSprite [iSprites2Inx].xX > rXSize? hSprite->d_xSizeOfSprite [iSprites2Inx].xX : rXSize;
					rYSize = hSprite->d_xSizeOfSprite [iSprites2Inx].xY > rYSize? hSprite->d_xSizeOfSprite [iSprites2Inx].xY : rYSize;
				}
			}
			//compute min coordinates using the center point and the size
			MTH3D_tdstVector tdstInsertionPoint;
			GEO_vGetPointOfObject (hObject, &tdstInsertionPoint, 0);
			tdstMaxCoordinates.xX = tdstInsertionPoint.xX + (rXSize / 2);
			tdstMaxCoordinates.xY = tdstInsertionPoint.xY + (rYSize / 2);
			tdstMaxCoordinates.xZ =	tdstInsertionPoint.xZ;		
		}
	}

	return tdstMaxCoordinates;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method : mfn_3dvGetSizes 
// Date   : 98-05
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description :
// Author      : Stegaru Cristian - CPA2
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification :
// Date         :
// By           :
//////////////////////////////////////////////////////////////////////////////////////////////////////
MTH3D_tdstVector Geometry3D::mfn_3dvGetSizes ()	//dX, dY, dZ
{
	MTH3D_tdstVector tdstSizes, tdstMinCoordinates, tdstMaxCoordinates;
	tdstMinCoordinates = mfn_3dvGetMinCoordinates ();
	tdstMaxCoordinates = mfn_3dvGetMaxCoordinates ();
	tdstSizes.xX = tdstMaxCoordinates.xX - tdstMinCoordinates.xX;
	tdstSizes.xY = tdstMaxCoordinates.xY - tdstMinCoordinates.xY;
	tdstSizes.xZ = tdstMaxCoordinates.xZ - tdstMinCoordinates.xZ;
	return tdstSizes;
}



#include "3DObject.cxx"