/*=========================================================================
 * DEVMul3D.cpp :	Implementation of Multidevice 3D.
 * This is a part of the PCA project.
 *
 * Version			1.0
 * Creation date	17/07/96
 * Revision date
 *
 *
 * (c) Ubi Studios 1996
 *=======================================================================*/

#include "stdafx.h"
#include "acp_base.h"
#include "geo.h"
#include "gli.h"
#include "itf/CPARes.h"
#include "itf/DEVMul3D.hpp"
#include "itf/CPAProj.hpp"
#include "itf/CPAConst.hpp"
#include "itf/CPAkacnf.hpp"
#include "itf/cpaworld.hpp"
#include "itf/cpasobj.hpp"
#include "itf/CPAInter.hpp"

IMPLEMENT_DYNCREATE(DEV_MultiDevice3D, DEV_MultiDevice)

BEGIN_MESSAGE_MAP(DEV_MultiDevice3D, DEV_MultiDevice)
	//{{AFX_MSG_MAP(DEV_MultiDevice3D)
	ON_WM_CREATE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

//==========================================================================
DEV_MultiDevice3D::DEV_MultiDevice3D()
{
    DEV_MultiDevice3D::Init();
}

DEV_MultiDevice3D::DEV_MultiDevice3D(int flags) :
	DEV_MultiDevice(flags)
{
    DEV_MultiDevice3D::Init();
}

DEV_MultiDevice3D::~DEV_MultiDevice3D()
{
}

void DEV_MultiDevice3D::Init(void)
{
#ifdef ACTIVE_EDITOR
	m_p_oWorld = NULL;
#endif // ACTIVE_EDITOR

	m_hSuperObjectWorld = NULL;
    DEV_MultiDevice::Init();
}

//==========================================================================
int DEV_MultiDevice3D::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (DEV_MultiDevice::OnCreate(lpCreateStruct) == -1)
		return -1;

    //
	// Init light.
    //
    GLI_xCreateLight(&m_hLight , GLI_C_lParallelLight);
#ifdef ACTIVE_EDITOR
    m_p_oParent = GetParent();
#endif // ACTIVE_EDITOR
	return 0;
}

#ifdef ACTIVE_EDITOR
//===========================================================================
//      Description:    Set the Rotation Unit.
//      Creation date:  26/07/96
//      Author:         LOL
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
/*void DEV_MultiDevice3D::SetRotateUnitIndex(int iIndex, int iMul)
{
	mxRotateUnit = GLI_M_Mul(C_DefaultRotateUnit, iMul);
	miRotateUnitIndex = iIndex;
}
*/
//===========================================================================
//      Description:    Set the Translation Unit.
//      Creation date:  26/07/96
//      Author:         LOL
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
/*void DEV_MultiDevice3D::SetTranslateUnitIndex(int iIndex, int iMul)
{
	mxTranslateUnit = GLI_M_Mul(C_DefaultTranslateUnit, iMul);
	miTranslateUnitIndex = iIndex;
}
*/

//===========================================================================
//      Description:    Sets a new world in the multidevice.
//                      this world will be the new current world
//      Creation date:  25/09/96
//      Author:         FBF
//---------------------------------------------------------------------------
//      Revision date:
//      Author:         FBF
//===========================================================================
void DEV_MultiDevice3D::SetWorld(CPA_World *p_oWorld)
{
	if (m_cIsAdditional == 0)
	{
		// if there was allready a world, remove it
		if (m_p_oWorld)
			m_p_oWorld->SetMultiDevice(NULL);
		SetEngineWorld(NULL);
		
		m_p_oWorld = p_oWorld;
		
		if (m_p_oWorld)
		{
			m_p_oWorld->SetMultiDevice(this);
			if (m_p_oWorld->GetRoot())
				SetEngineWorld(p_oWorld->GetRoot()->GetStruct());
		}
		
		if (GetInterface())
			GetInterface()->fn_vChangeWorld();
	}
	else
	{
		GetPane_0_0()->SetWorld(p_oWorld);
	}
}

CPA_World *DEV_MultiDevice3D::GetWorld()
{
	if (m_cIsAdditional == 0)
		return m_p_oWorld;
	else
		return GetPane_0_0()->GetWorld();
}

GLI_tdxHandleToLight DEV_MultiDevice3D::GetEngineLight()		
{
	if (m_cIsAdditional == 0)
		return m_hLight;
	else
		return GetPane_0_0()->GetEngineLight();
}

		
HIE_tdxHandleToSuperObject DEV_MultiDevice3D::GetEngineWorld()
{
	if (m_cIsAdditional == 0)
		return m_hSuperObjectWorld;
	else
		return GetPane_0_0()->GetEngineWorld();
}

#endif

void DEV_MultiDevice3D::SetEngineWorld(HIE_tdxHandleToSuperObject hObj)
{
#ifdef ACTIVE_EDITOR
	if (m_cIsAdditional == 0)
		m_hSuperObjectWorld = hObj;
	else
		GetPane_0_0()->SetEngineWorld(hObj);
#else
	m_hSuperObjectWorld = hObj;
#endif
}


#ifdef ACTIVE_EDITOR

//===========================================================================
//      Description:    Draw the World which is set by the function SetObject.
//                      Call the DrawObject function of all his device.
//      Creation date:  26/07/96
//      Author:         LOL
//---------------------------------------------------------------------------
//      Revision date:
//      Author:         CB
//===========================================================================
void DEV_MultiDevice3D::DrawObject(void)
{
	if (!IsActive())
		return;
	if (M_bEditorsActive())
	{
		DrawEditorObject();
		return;
	}

	UINT i;
    {
	    for (i = 0; i < MAX_DEVICE; i++)
        {
	        if
            (
                (IsActivDevice(i)) 
                && 
                (
                    (GetDevice(i)->mbGameRefresh) 
                ||  (M_bEditorsActive())
                ||  (mbForceDrawing)
                )
            )
            {
#ifndef TEST_CPA_VERSION_3D
				if(M_bEditorsActive() || i || (this != M_GetMainDevice()))
#endif // TEST_CPA_VERSION_3D
				{
					if(m_hSuperObjectWorld)
						GetDevice(i)->DrawObject(m_hLight, m_hSuperObjectWorld);
					else
						GLD_bFlipDevice(GetDevice(i)->m_hDisplayDevice);
				}
            }
        }
    }

    if
    (
        (m_p_oParent) 
    &&  (m_p_oMultiToDraw == NULL)
    &&  (m_p_oParent->IsKindOf(RUNTIME_CLASS(FRMSplitter)))
    &&  (!mbForceDrawing)
    )
    {
        m_p_oMultiToDraw = this;
        ((FRMSplitter *) m_p_oParent)->DrawObject(this);
        m_p_oMultiToDraw = NULL;
    }
    mbForceDrawing = FALSE;
}

//===========================================================================
//      Description:    Draw the World which is set by the function SetObject.
//                      Call the DrawObject function of all his device.
//      Creation date:  26/07/96
//      Author:         LOL
//---------------------------------------------------------------------------
//      Revision date:
//      Author:         CB
//===========================================================================
void DEV_MultiDevice3D::DrawEditorObject(void)
{
	UINT i;

	for (i = 0; i < MAX_DEVICE; i++)
    {
	    if(IsActivDevice(i)) 
        {
			if (GetWorld())
				GetDevice(i)->DrawEditorObject(m_hLight, GetWorld()->GetRoot());
			else
				GLD_bFlipDevice(GetDevice(i)->m_hDisplayDevice);
        }
    }

    if
    (
        (m_p_oParent) 
    &&  (m_p_oMultiToDraw == NULL)
    &&  (m_p_oParent->IsKindOf(RUNTIME_CLASS(FRMSplitter)))
    )
    {
        m_p_oMultiToDraw = this;
        ((FRMSplitter *) m_p_oParent)->DrawObject(this);
        m_p_oMultiToDraw = NULL;
    }
    mbForceDrawing = FALSE;
}

void DEV_MultiDevice3D::DrawObjectExcept0()
{
	UINT i;
	for (i = 1; i < MAX_DEVICE; i++)
		{
		if 
		(
			(IsActivDevice(i)) 
		&&  (
				(GetDevice(i)->mbGameRefresh) 
			||  (M_bEditorsActive())
			||  (mbForceDrawing)
			)
		)
		{
			if(m_hSuperObjectWorld)
				GetDevice(i)->DrawObject(m_hLight, m_hSuperObjectWorld);
			else
				GLD_bFlipDevice(GetDevice(i)->m_hDisplayDevice);
		}
	}

    if
    (
        (m_p_oParent) 
    &&  (m_p_oMultiToDraw == NULL)
    &&  (m_p_oParent->IsKindOf(RUNTIME_CLASS(FRMSplitter)))
    &&  (!mbForceDrawing)
    )
    {
        m_p_oMultiToDraw = this;
        ((FRMSplitter *) m_p_oParent)->DrawObject(this);
        m_p_oMultiToDraw = NULL;
    }
    mbForceDrawing = FALSE;
}
#endif // ACTIVE_EDITOR

//==========================================================================
//
// TO TEST ACP VERSION
//
//==========================================================================
#if defined(ACTIVE_EDITOR)

void fn_vRotateX ( POS_tdstCompletePosition *p_stMatrix ,
                   GLI_tdxValue xXAngle )
{
	MTH3D_tdstVector	stVectI,stVectJ,stVectK;

	POS_fn_vGetRotationMatrix(p_stMatrix,&stVectI,&stVectJ,&stVectK);
	
	MTH3D_M_vSetYofVector(&stVectJ,GLI_M_Cos(xXAngle)) ;
	MTH3D_M_vSetZofVector(&stVectJ,GLI_M_Sin(xXAngle)) ;
	MTH3D_M_vSetYofVector(&stVectK,GLI_M_Neg(GLI_M_Sin(xXAngle))) ;
	MTH3D_M_vSetZofVector(&stVectK,GLI_M_Cos(xXAngle)) ;

	POS_fn_vSetRotationMatrix(p_stMatrix,&stVectI,&stVectJ,&stVectK);
}

void fn_vRotateY ( POS_tdstCompletePosition  *p_stMatrix ,
                   GLI_tdxValue xYAngle )
{
	MTH3D_tdstVector	stVectI,stVectJ,stVectK;

	POS_fn_vGetRotationMatrix(p_stMatrix,&stVectI,&stVectJ,&stVectK);
	
	MTH3D_M_vSetXofVector(&stVectI,GLI_M_Cos(xYAngle)) ;
	MTH3D_M_vSetZofVector(&stVectI,GLI_M_Sin(xYAngle)) ;
	MTH3D_M_vSetXofVector(&stVectK,GLI_M_Neg(GLI_M_Sin(xYAngle))) ;
	MTH3D_M_vSetZofVector(&stVectK,GLI_M_Cos(xYAngle)) ;

	POS_fn_vSetRotationMatrix(p_stMatrix,&stVectI,&stVectJ,&stVectK);
}

void fn_vRotateZ ( POS_tdstCompletePosition  *p_stMatrix ,
                   GLI_tdxValue xZAngle )
{
	MTH3D_tdstVector	stVectI,stVectJ,stVectK;

	POS_fn_vGetRotationMatrix(p_stMatrix,&stVectI,&stVectJ,&stVectK);
	
	MTH3D_M_vSetXofVector(&stVectI,GLI_M_Cos(xZAngle));
	MTH3D_M_vSetYofVector(&stVectI,GLI_M_Sin(xZAngle));
	MTH3D_M_vSetXofVector(&stVectJ,GLI_M_Neg(GLI_M_Sin(xZAngle)));
	MTH3D_M_vSetYofVector(&stVectJ,GLI_M_Cos(xZAngle));

	POS_fn_vSetRotationMatrix(p_stMatrix,&stVectI,&stVectJ,&stVectK);
}

void DEV_MultiDevice3D::RotateObjectX()
{
	POS_tdstCompletePosition  p_stMatrix;
	GLI_tdxValue   xXAngle;
	POS_fn_vSetIdentityMatrix(&p_stMatrix);

	if (m_hSuperObjectWorld != NULL)
	{
		xXAngle = (GLI_tdxValue)0.1;
		POS_fn_vSetIdentityMatrix(&p_stMatrix);
		fn_vRotateX(&p_stMatrix, xXAngle);
		POS_fn_vMulMatrixMatrix(HIE_fn_hGetSuperObjectMatrix(m_hSuperObjectWorld),
			                 HIE_fn_hGetSuperObjectMatrix(m_hSuperObjectWorld),
							 &p_stMatrix);
		POS_fn_vNormalizeMatrix(HIE_fn_hGetSuperObjectMatrix(m_hSuperObjectWorld));
	}
}

void DEV_MultiDevice3D::RotateObjectY()
{
	POS_tdstCompletePosition  p_stMatrix;
	GLI_tdxValue xYAngle;
	POS_fn_vSetIdentityMatrix(&p_stMatrix);

	if (m_hSuperObjectWorld != NULL)
	{
		xYAngle = (GLI_tdxValue)0.1;
		POS_fn_vSetIdentityMatrix(&p_stMatrix);
		fn_vRotateY(&p_stMatrix, xYAngle);
		POS_fn_vMulMatrixMatrix(HIE_fn_hGetSuperObjectMatrix(m_hSuperObjectWorld),
			                 HIE_fn_hGetSuperObjectMatrix(m_hSuperObjectWorld),
							 &p_stMatrix);
		POS_fn_vNormalizeMatrix(HIE_fn_hGetSuperObjectMatrix(m_hSuperObjectWorld));
	}
}

void DEV_MultiDevice3D::RotateObjectZ()
{
	POS_tdstCompletePosition  p_stMatrix;
	GLI_tdxValue xZAngle;
	POS_fn_vSetIdentityMatrix(&p_stMatrix);

	if (m_hSuperObjectWorld != NULL)
	{
		xZAngle = (GLI_tdxValue)0.1;
		POS_fn_vSetIdentityMatrix(&p_stMatrix);
		fn_vRotateZ(&p_stMatrix, xZAngle);
		POS_fn_vMulMatrixMatrix(HIE_fn_hGetSuperObjectMatrix(m_hSuperObjectWorld),
			                 HIE_fn_hGetSuperObjectMatrix(m_hSuperObjectWorld),
							 &p_stMatrix);
		POS_fn_vNormalizeMatrix(HIE_fn_hGetSuperObjectMatrix(m_hSuperObjectWorld));
	}
}

void DEV_MultiDevice3D::RotateWorldX()
{
	RotateObjectX();
}

void DEV_MultiDevice3D::RotateWorldY()
{
	RotateObjectY();
}

void DEV_MultiDevice3D::RotateWorldZ()
{
	RotateObjectZ();
}

#endif // ACTIVE_EDITOR
