/*
 *=======================================================================================
 * Name        : 3dgmodif.cpp
 *
 * Author      : Marc Trabucato				Date : ...
 *
 * Description : implementation of Geometry3D_Modif class use to store a move point
 *				modification
 *=======================================================================================
 * Modification -> Author : Vincent Lhullier  Date : 24/04/97
 * Description : add notification for saving modified object
 *=======================================================================================
 */

/*---------------------------------------------*/
#include "stdafx.h"

#include "ACP_Base.h"
#include "incITF.h"			// interface
#include "incGAM.h"

//ROMTEAM WorldEditor (Nicu 16/01/98) 
#include "OGD.h"
//ENDROMTEAM WorldEditor (Nicu) 

#include "3DGModif.hpp"
#include "3DInterf.hpp"
//#include "GLI.h"
//#include "SCR.h"

#define TYPE_MOVE 0

/*---------------------------------------------*/

/*---------------------------------------------*/
#undef CPA_WANTS_IMPORT
#undef CPA_EXPORT
#define CPA_WANTS_EXPORT
    #include "OGD.h"
#undef CPA_WANTS_EXPORT
#define CPA_WANTS_IMPORT
/*---------------------------------------------*/

/*
 *=======================================================================================
 * MACROS
 *=======================================================================================
 */

// to redraw world in 3D View
#define M_RedrawWorld()     (((DEV_MultiDevice*)g_oFrameGest.ma_p_oWinArray[2][2]->GetActiveView())->DrawObject())

/*
 *=======================================================================================
 * Geometry3D_Modif
 *=======================================================================================
 */

/*
 ----------------------------------------------------------------------------------------
  Description   : constructor for Geometr3D_Modif which is the modif object used when a point
					of a geometric object is moved
  _p_xObject          -> editor geometric object that is modified
  _xIndexPoint        -> moved point
  _st3DTranslation    -> moving vector
 ----------------------------------------------------------------------------------------
 */
//Geometry3D_Modif::Geometry3D_Modif(Geometry3D *_p_xObject, ACP_tdxIndex _xIndexPoint, MTH3D_tdstVector _st3DTranslation, DWORD *adr)
//CPA2 Corneliu Babiuc 09-09-98 (duplicated points)
/*
Geometry3D_Modif::Geometry3D_Modif(Geometry3D *_p_xObject,int NbPoints, ACP_tdxIndex *_xIndexPoints, float *Dist, MTH3D_tdstVector _st3DTranslation, DWORD *adr)
                 :CPA_Modif(TYPE_MOVE, "Move point", FALSE)
{
    m_p_xObject   = _p_xObject;

//ROMTEAM WorldEditor (Viorel Preoteasa 20/01/98) 
//    m_xIndexPoint = _xIndexPoint;
	m_iNbPoints = NbPoints;
	m_xIndexPoints = (ACP_tdxIndex *)malloc(m_iNbPoints * sizeof(ACP_tdxIndex));
	memcpy(m_xIndexPoints, _xIndexPoints, m_iNbPoints * sizeof(ACP_tdxIndex));
	m_fDist = (float *)malloc(m_iNbPoints * sizeof(float));
	memcpy(m_fDist, Dist, m_iNbPoints * sizeof(float));
//ENDROMTEAM WorldEditor (Viorel Preoteasa) 
*/
Geometry3D_Modif::Geometry3D_Modif(CPA_List<CPA_PointsList> * _lstPoints, MTH3D_tdstVector _st3DTranslation, DWORD *adr, BOOL _bFirstTime)
                 :CPA_Modif(TYPE_MOVE, "Move point", FALSE)
{
    POSITION    pos;
    CPA_PointsList  * p_oPoints;
    for (p_oPoints = _lstPoints->GetHeadElement(pos); p_oPoints; p_oPoints = _lstPoints->GetNextElement(pos))
    {
        m_lstPointsList.AddTail( new CPA_PointsList(*p_oPoints) );
    }
    m_bFirstTime = _bFirstTime;

    // use in Doing function to indicate that first time the transmlation is already done
    m_bFirstTime = _bFirstTime;
//    m_bFirstTime  = TRUE;
//END CPA2 Corneliu Babiuc 09-09-98 (duplicated points)
    memcpy(&m_st3DTranslation,&_st3DTranslation,sizeof(MTH3D_tdstVector));

//ROMTEAM WorldEditor (Nicu 05/12/97) 
		m_adrGeom = adr;
		if(adr) m_pGeom = *adr;
//ROMTEAM WorldEditor (Nicu) 

}


/*
 ----------------------------------------------------------------------------------------
  Description   : destructor
 ----------------------------------------------------------------------------------------
 */
Geometry3D_Modif::~Geometry3D_Modif()
{
//ROMTEAM WorldEditor (Viorel Preoteasa 20/01/98) 
//CPA2 Corneliu Babiuc 10-09-98 (duplicated points)
/*
    free(m_xIndexPoints);
	free(m_fDist);
*/
    while (!m_lstPointsList.IsEmpty()) delete (m_lstPointsList.RemoveHead());
//END CPA2 Corneliu Babiuc 10-09-98 (duplicated points)
//ENDROMTEAM WorldEditor (Viorel Preoteasa) 
}


/*
 ----------------------------------------------------------------------------------------
  Description   : do the moving point modification
  Returns (BOOL) TRUE if modif is done, FALSE otherwise
 ----------------------------------------------------------------------------------------
 */
BOOL Geometry3D_Modif::Do (void)
{
	// the first time this function is called, the translation is already done
    if(!m_bFirstTime)
    {
        // translate point
//--------------------------------------------------------------
//ROMTEAM WorldEditor (Viorel Preoteasa 20/01/98) 
//		m_p_xObject->fn_vTranslatePoint(m_xIndexPoint,&m_st3DTranslation);
//CPA2 Corneliu Babiuc 10-09-98 (duplicated points)
/*
        int i;
		MTH3D_tdstVector st3DTranslation;
		GEO_tdstGeometricObject *GeomObj = m_p_xObject->GetStruct();
		for(i=0; i<m_iNbPoints; i++)
		{
		    st3DTranslation = m_st3DTranslation;
			st3DTranslation.xX *= m_fDist[i];
			st3DTranslation.xY *= m_fDist[i];
			st3DTranslation.xZ *= m_fDist[i];
			if(m_iNbPoints == 1)m_p_xObject->fn_vTranslatePoint(m_xIndexPoints[i],&st3DTranslation);
			else
			{
				(GeomObj->d_stListOfPoints[m_xIndexPoints[i]]).xX += st3DTranslation.xX;
				(GeomObj->d_stListOfPoints[m_xIndexPoints[i]]).xY += st3DTranslation.xY;
				(GeomObj->d_stListOfPoints[m_xIndexPoints[i]]).xZ += st3DTranslation.xZ;
			}
//			m_p_xObject->fn_vTranslatePoint(m_xIndexPoints[i],&st3DTranslation);
		}
		if(m_iNbPoints != 1)
		{
			m_p_xObject->fn_vEndModification();
			m_p_xObject->fn_vSetMustRecomputeBdV();
		}
*/
        POSITION pos;
        MTH3D_tdstVector st3DTranslation;
        for( CPA_PointsList * p_oPoints = m_lstPointsList.GetHeadElement(pos);
            p_oPoints;
            p_oPoints = m_lstPointsList.GetNextElement(pos) )
        {
            GEO_tdstGeometricObject * GeomObj = p_oPoints->GetObject()->GetStruct();
            for( int i=0; i<p_oPoints->GetNumberOfSelectedPoints(); i++)
            {
                ACP_tdxIndex xPointIndex = p_oPoints->GetPoint(i);
                MTH3D_M_vMulScalarVector(&st3DTranslation, p_oPoints->m_fDist[i], &m_st3DTranslation);
                if( i == p_oPoints->GetNumberOfSelectedPoints()-1)
                    p_oPoints->GetObject()->fn_vTranslatePoint(xPointIndex, &st3DTranslation);
                else
                {
                    MTH3D_M_vAddVector(&(GeomObj->d_stListOfPoints[xPointIndex]), 
                                        &(GeomObj->d_stListOfPoints[xPointIndex]), &st3DTranslation);
                }
            }
            p_oPoints->GetObject()->fn_vSetMustRecomputeBdV();
        }
//END CPA2 Corneliu Babiuc 10-09-98 (duplicated points)
//ENDROMTEAM WorldEditor (Viorel Preoteasa) 
//--------------------------------------------------------------
        // redraw the world
        M_RedrawWorld();
    }
	// indicate that first time is over
	m_bFirstTime = FALSE;

//ROMTEAM WorldEditor (Nicu 05/12/97) 
				if(m_adrGeom) *m_adrGeom = 0;
//ENDROMTEAM WorldEditor (Nicu) 

	/*
	 * Notify that object has been modified
	 */
//CPA2 Corneliu Babiuc 10-09-98 (duplicated points)
    POSITION pos;
    for( CPA_PointsList * p_oPoints = m_lstPointsList.GetHeadElement(pos); pos;
        m_lstPointsList.GetNextElement(pos) )
        p_oPoints->GetObject()->fn_vNotifySaveObject();
//    m_p_xObject->fn_vNotifySaveObject();
//END CPA2 Corneliu Babiuc 10-09-98 (duplicated points)

    return TRUE;
}


/*
 ----------------------------------------------------------------------------------------
  Description   : undo the moving point modification
  Returns (BOOL) TRUE when undoing success (always the case)
 ----------------------------------------------------------------------------------------
 */
BOOL Geometry3D_Modif::Undo (void)
{
//-----------------------------------------------
//ROMTEAM WorldEditor (Viorel Preoteasa 20/01/98) 
// calculate the opposite translation
/*
    MTH3D_tdstVector st3DOppTranslation;
	MTH3D_M_vNullVector(&st3DOppTranslation);
	MTH3D_M_vSubVector(&st3DOppTranslation,&st3DOppTranslation,&m_st3DTranslation);
    // translate point
    m_p_xObject->fn_vTranslatePoint(m_xIndexPoint,&st3DOppTranslation);
*/
//CPA2 Corneliu Babiuc 10-09-98 (duplicated points)
/*
	int i;
	MTH3D_tdstVector st3DTranslation;
	GEO_tdstGeometricObject *GeomObj = m_p_xObject->GetStruct();
	for(i=0; i<m_iNbPoints; i++)
	{
		st3DTranslation = m_st3DTranslation;
		st3DTranslation.xX *= -m_fDist[i];
		st3DTranslation.xY *= -m_fDist[i];
		st3DTranslation.xZ *= -m_fDist[i];
		if(m_iNbPoints == 1)m_p_xObject->fn_vTranslatePoint(m_xIndexPoints[i],&st3DTranslation);
		else
		{
			(GeomObj->d_stListOfPoints[m_xIndexPoints[i]]).xX += st3DTranslation.xX;
			(GeomObj->d_stListOfPoints[m_xIndexPoints[i]]).xY += st3DTranslation.xY;
			(GeomObj->d_stListOfPoints[m_xIndexPoints[i]]).xZ += st3DTranslation.xZ;
		}
//		m_p_xObject->fn_vTranslatePoint(m_xIndexPoints[i],&st3DTranslation);
	}
	if(m_iNbPoints != 1)
	{
		m_p_xObject->fn_vEndModification();
		m_p_xObject->fn_vSetMustRecomputeBdV();
	}
*/
    POSITION pos;
    MTH3D_tdstVector st3DTranslation;
    for( CPA_PointsList * p_oPoints = m_lstPointsList.GetHeadElement(pos); 
        p_oPoints;
        p_oPoints = m_lstPointsList.GetNextElement(pos) )
    {
        GEO_tdstGeometricObject * GeomObj = p_oPoints->GetObject()->GetStruct();
        for( int i=0; i<p_oPoints->GetNumberOfSelectedPoints(); i++)
        {
            ACP_tdxIndex xPointIndex = p_oPoints->GetPoint(i);
            MTH3D_M_vMulScalarVector(&st3DTranslation, -p_oPoints->m_fDist[i], &m_st3DTranslation);
            if( i == p_oPoints->GetNumberOfSelectedPoints()-1)
                p_oPoints->GetObject()->fn_vTranslatePoint(xPointIndex, &st3DTranslation);
            else
            {
                MTH3D_M_vAddVector(&(GeomObj->d_stListOfPoints[xPointIndex]), 
                                    &(GeomObj->d_stListOfPoints[xPointIndex]), &st3DTranslation);
            }
            // it is not necesary to call Geometry3D::fn_vEndModification method.
            // This is done from fn_vTranslatePoint function !!!
            p_oPoints->GetObject()->fn_vSetMustRecomputeBdV();

        }
    }
//END CPA2 Corneliu Babiuc 10-09-98 (duplicated points)

//ENDROMTEAM WorldEditor (Viorel Preoteasa) 
//-----------------------------------------------
//ROMTEAM WorldEditor (Nicu 05/12/97) 
				if(m_adrGeom) *m_adrGeom = m_pGeom;
//ENDROMTEAM WorldEditor (Nicu) 


    // redraw the world
    M_RedrawWorld();

//CPA2 Corneliu Babiuc 10-09-98 (duplicated points)
    for( p_oPoints = m_lstPointsList.GetHeadElement(pos); pos;
        m_lstPointsList.GetNextElement(pos) )
        p_oPoints->GetObject()->fn_vNotifySaveObject();
//    m_p_xObject->fn_vNotifySaveObject();
//END CPA2 Corneliu Babiuc 10-09-98 (duplicated points)

    return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
// class Geometry3D_Rename

Geometry3D_Rename::Geometry3D_Rename(Geometry3D *_p_Object,CString _csName)
                 :CPA_Modif(TYPE_MOVE, "Rename Geometric object", FALSE)
{
    m_p_xObject = _p_Object;
    m_csNewName = _csName;
}

Geometry3D_Rename::~Geometry3D_Rename()
{
}

BOOL Geometry3D_Rename::Do(void)
{
    // update data
    CString csTmp = m_p_xObject -> GetName();

    if( csTmp == m_csNewName )
        return FALSE;

    m_p_xObject -> fn_eRename( m_csNewName );
    m_p_xObject -> fn_vNotifyRenameObject();
    m_csNewName = csTmp;

    // update display
    if( m_p_xObject -> GetEditor() -> fn_bIsCurrentEditor() )
        ((Geometry3D_Interface*)m_p_xObject -> GetEditor()) -> fn_vNameChanged();

    return TRUE;
}

BOOL Geometry3D_Rename::Undo(void)
{
    return Do();
}