

/*=========================================================================
* DEVVP3D.cpp :        Implementation of ViewPort 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 "incgli.h"
#include "tex.h"
#include "col.h"
#define HieFriend
#include "spo.h"
#include "lst.hpp"

#include "itf/DEVVp3D.hpp"
#include "itf/CPADD.hpp"
#include "itf/devmul3d.hpp"
#include "itf/camdllb.hpp"

#include "itf/CPAProj.hpp"
#include "itf/CPACont.hpp"
#include "itf/CPAConst.hpp"

#include "itf/CPAInter.hpp"
#include "itf/CPAMWorl.hpp"
#include "itf/StdDLLID.h"
#include "DEVTimer.hpp"
#include "acp_driver.h"



static long MouseSprite[] = {	0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
								0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,
								0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0x00000000,
								0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0x00000000,
								0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0x00000000,
								0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000};
								

ACP_tdxHandleOfMaterial g_hMouseMaterial ;
//CPA2 Gabi Dumitrascu 98/07/13
ACP_tdxHandleOfMaterial g_hNormalMouseMaterial ;
ACP_tdxHandleOfMaterial g_hDragMouseMaterial ;
BOOL g_bDragDropActivate = FALSE;
//End CPA2 Gabi Dumitrascu 98/07/13
ACP_tdxHandleOfTexture p_stTextureBar1;
ACP_tdxHandleOfTexture p_stTextureBar2;
static BOOL	g_bOnce = FALSE;
static BOOL g_bLButtonDown;
static UINT	g_Flags;


#define C_PI 3.14159265
#define M_GetCameraDLL(Camera) ((CPA_CameraDLLBase*) (Camera)->GetEditor())

//CPA2 Corneliu Babiuc 13-05-98
//definition of constant for keyboard action
//************************  WARNING!!! *********************************
//these constant must be also defined in cpaproj.cpp file as they are!!!
//I didn't put them in a .hpp file in order to not modify the public files or a project

// object drawing flags
#define KA_CancelAllDrawingFlags		10
#define KA_IgnoreDrawingFlags			11
#define KA_NormalObject					12
#define KA_GridedObject					13
#define KA_WiredObject					14
// object parameters
#define KA_ShowObjectAxis				20
#define KA_BVObject						22
// centers
#define KA_ShowMainCenters				25
#define KA_ShowAllCenters				26
#define KA_ShowNoCenter					27
// world drawing flags
#define KA_NormalWorld					30
#define KA_GridedWorld					31
#define KA_WiredWorld					32
// world display mode
#define KA_WorldSectors					40
#define KA_VisibleSectors				41
#define KA_CurrentSector				42
#define KA_CollisionMap					43
// bounding volumes
#define KA_SectorsBV					50
#define KA_ActorsBV						51
#define KA_ObjectsBV					52
#define KA_NoBV							53
// colors
#define KA_SelectBackgroundColor		55
// selection
#define KA_CancelSelection				60 
#define KA_FullSelection				61
#define KA_DeltaSelection				62
#define KA_FixedDepthPyramid			63
#define KA_RealTimePyramid				64
// status bar							
#define KA_DisplayInstanceInfo			70
#define KA_DisplayInstanceToCam			71
#define KA_DisplayCameraInfo			72
#define KA_DisplayDistance				73
// options
#define KA_ScaleEditorObjects			80
#define KA_ShowNoAxis					81
#define KA_ShowAxisLeft					82
#define KA_ShowAxisRight				83
#define KA_Borders					   100
#define KA_ComputeCenters			   110
#define KA_ForceMousePos			   120


//CPA2 Gabi Dumitrascu 98/06/29
#define EDGE_TOLERANCE					1
#define RIGHT_EDGE_TOLERANCE			1
#define TOP_TOLERANCE					10
#define VOODOO_WIDTH					640
#define VOODOO_HEIGHT					480
//End CPA2 Gabi Dumitrascu 98/06/29


#ifdef USE_DIRECTX
extern "C"
{
#include "gliglou\multidrv\inc\dllinter.h"
}
#endif


//END CPA2 Corneliu Babiuc 19-05-98

IMPLEMENT_DYNCREATE(DEV_ViewPort3D, CWnd)
BEGIN_MESSAGE_MAP(DEV_ViewPort3D, DEV_ViewPort)
//{{AFX_MSG_MAP(DEV_ViewPort3D)
ON_WM_CREATE()
ON_WM_DESTROY()
#ifdef ACTIVE_EDITOR
ON_WM_KEYDOWN()
ON_WM_KEYUP()
// CPA2 Corneliu Babiuc (Alt Key) 14-05-98
ON_WM_SYSKEYDOWN()
ON_WM_SYSKEYUP()
// END CPA2 Corneliu Babiuc (Alt Key) 14-05-98 
ON_WM_LBUTTONDBLCLK()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_RBUTTONDOWN()
ON_WM_RBUTTONUP() // CPA_Ed_1 FS
ON_WM_MOUSEMOVE()
//CPA2 Gabi Dumitrascu 98/07/13
ON_WM_NCMOUSEMOVE()
ON_WM_NCHITTEST()
ON_WM_KILLFOCUS()
ON_WM_SETFOCUS()
//End CPA2 Gabi Dumitrascu 98/07/13
ON_WM_SETFOCUS()
ON_MESSAGE(WM_DRAGDROP_LOOSEFOCUS, OnDragDropLooseFocus)
ON_MESSAGE(WM_DRAGDROP_GAINFOCUS, OnDragDropGainFocus)
ON_MESSAGE(WM_DRAGDROP_MOVE, OnDragDropMove)
ON_MESSAGE(WM_DRAGDROP_END, OnDragDropEnd)
ON_WM_TIMER()
#endif // ACTIVE_EDITOR
//}}AFX_MSG_MAP
END_MESSAGE_MAP()



//==========================================================================
DEV_ViewPort3D::DEV_ViewPort3D()
{
	m_Attributes3D.p_stCam = NULL;
#ifdef ACTIVE_EDITOR
	m_p_oCamera = NULL;
	m_p_oCameraSO = NULL;
	m_p_oCameraInterface = NULL;

	m_uiLastMouseState = 0;

	m_bWasInSecondScreen = FALSE;
	m_bIsVerticalSwap = FALSE;
#endif // ACTIVE_EDITOR
}

DEV_ViewPort3D::~DEV_ViewPort3D()
{
#ifdef ACTIVE_EDITOR
	//CPA2 Gabi Dumitrascu 98/07/09
	if (M_bFullScreenEditor() && m_p_oDevice->IsFullScreen() && !IsCursorInFirstScreen ())
		mfn_vChangeCursorFrom2To1 (CPoint (1, 1), eSwapRight);
	//End CPA2 Gabi Dumitrascu 98/07/09
#endif // ACTIVE_EDITOR
}

//==========================================================================
void DEV_ViewPort3D::CreateViewPort(void * device, GLD_tdhDevice DisplayDevice)
{
	RECT r;
	GLD_tdstViewportAttributes stViewportAttr;

	m_hDisplayDevice = DisplayDevice;

	((CWnd*)device)->GetClientRect(&r);

	Create(NULL, (LPCTSTR) "ViewPort",
		WS_OVERLAPPED | WS_CLIPSIBLINGS | WS_VISIBLE | WS_CHILD,
		CRect(r), (CWnd*)device, 1);

	// The Viewport take all the device client zone.
//ANNECY CB
	stViewportAttr.dwWidthInPercent = 100;
	stViewportAttr.dwHeightInPercent = 100;
	stViewportAttr.dwClipTopInPercent = 0;
	stViewportAttr.dwClipBottomInPercent = 100;
	stViewportAttr.dwClipLeftInPercent = 0;
	stViewportAttr.dwClipRightInPercent = 100;
	stViewportAttr.iOffsetPosX = 0;
	stViewportAttr.iOffsetPosY = 0;
//ENDANNECY

	if (!GLD_bCreateViewport(m_hDisplayDevice, &stViewportAttr, &m_hDisplayViewport))
	{
		ASSERT(0);
	}

	if (!GLD_bGiveSpecificAttributesToViewport(m_hDisplayDevice, m_hDisplayViewport, (void *)&m_Attributes3D))
	{
		ASSERT(0);
	}
}

GLI_tdxHandleToCamera DEV_ViewPort3D::GetEngineCamera()
{
	return m_Attributes3D.p_stCam;
}


//==========================================================================
int DEV_ViewPort3D::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (DEV_ViewPort::OnCreate(lpCreateStruct) == -1)
		return -1;
#ifdef ACTIVE_EDITOR
	DD_eAddReference(GetSafeHwnd(), "Evt_Editor", C_ucModel, FALSE);
#endif
	return 0;
}


//==========================================================================
void DEV_ViewPort3D::OnDestroy()
{

#ifdef ACTIVE_EDITOR
	if (GetParentMultiDevice()->mbOnDestroy == FALSE)
	{
		// if there's a camera, destroy it !!!
		if (m_p_oCameraInterface)
			m_p_oCameraInterface->DestroyCamera(m_p_oCameraSO);
	}
	m_p_oCameraInterface = NULL;
	m_p_oCameraSO = NULL;
	m_p_oCamera = NULL;
	DD_eDelReference(GetSafeHwnd());
#endif //ACTIVE_EDITOR
}


#ifdef ACTIVE_EDITOR
//=========================================================================
// Change the current camera
// return the old camera
//=========================================================================


CPA_SuperObject *DEV_ViewPort3D::ChangeCamera(CPA_SuperObject *p_oCameraSO, BOOL bWithPrevCam)
{
	CPA_CameraSlots *p_oCamSlots;
	CPA_SuperObject *p_oOldCameraSO;
	CPA_BaseObject *p_oOldCamera;
	CPA_BaseObject *p_oCamera;
	
	p_oCamSlots = ((DEV_MultiDevice3D*)(GetDevice()->GetWindowParent()))->GetWorld()->GetCameraSlots();
	p_oOldCameraSO = m_p_oCameraSO;
	p_oOldCamera = m_p_oCamera;
	
	// if there was a camera in this viewport, check prevcamtip
	if (p_oOldCamera != NULL)
	{
		// if the prevcam is active for this world :
		if (bWithPrevCam && p_oCamSlots->IsPrevCamTipActive())
		{
			// save the old camera in the reserved slot
			p_oCamSlots->SaveCameraInSlot(p_oCamSlots->GetPrevCamSlot(),"Previous Camera",p_oOldCamera,MakeACopy);
		}
		// and disactivate this camera
		M_GetCameraDLL(p_oOldCamera)->Disactivate(p_oOldCamera);
	}

	if (p_oCameraSO != NULL)
	{
		p_oCamera = p_oCameraSO->GetObject();
		ASSERT(p_oCamera != NULL);
		// cannot put a camera that is already active
		ASSERT(!(M_GetCameraDLL(p_oCamera)->IsActive(p_oCamera)));
		
		m_p_oCamera = p_oCamera;
		m_p_oCameraSO = p_oCameraSO;
		m_p_oCameraInterface = M_GetCameraDLL(p_oCamera);
		m_p_oCameraInterface->Activate(m_p_oCamera,this,(GetParentDialogBar()),CPoint(598,-1));
	}
	else
	{
		m_p_oCamera = NULL;
		m_p_oCameraSO = NULL;
		m_p_oCameraInterface = NULL;
	}
	return p_oOldCameraSO;
}


//=========================================================================
// INIT LIGHTS IN VIEWPORT
// Main function of drawing in edit mode
// This function is called for each display viewport
//=========================================================================
void DEV_ViewPort3D::fn_vInitLightsInViewport (GLD_tdxHandleToViewportAttributes _hVpt, GLI_tdxHandleToLight _hLight, CPA_MainWorld *pMainWorld)
{
	long								lIndex;

	// clear lights
	GLI_vClearListOfLightInViewport(_hVpt);
	m_lCurrentLights = 0;

	// ambiant light (if no local light)
	if ((pMainWorld->m_lNbLocalLights == 0)&&(pMainWorld->m_lNbDynamicLights == 0))
	{
		GLI_vAddLightToViewport(_hVpt,_hLight);
		m_a_tdxhArrayOfLights[m_lCurrentLights].hLight = _hLight;
		GLI_xGetLightState(_hLight, &m_a_tdxhArrayOfLights[m_lCurrentLights].lInitialState);
		m_lCurrentLights++;
	}

	// local lights
	for (lIndex = 0; lIndex < pMainWorld->m_lNbLocalLights; lIndex++)
	{
		GLI_vAddLightToViewport(_hVpt, pMainWorld->m_a_tdxhArrayOfLocalLights[lIndex]);
		m_a_tdxhArrayOfLights[m_lCurrentLights].hLight = pMainWorld->m_a_tdxhArrayOfLocalLights[lIndex];
		GLI_xGetLightState(pMainWorld->m_a_tdxhArrayOfLocalLights[lIndex], &m_a_tdxhArrayOfLights[m_lCurrentLights].lInitialState);
		m_lCurrentLights++;
	}

	// dynamic lights
	for (lIndex = 0; lIndex < pMainWorld->m_lNbDynamicLights; lIndex++)
	{
		GLI_vAddLightToViewport(_hVpt,pMainWorld->m_a_tdxhArrayOfDynamicLights[lIndex]);
		m_a_tdxhArrayOfLights[m_lCurrentLights].hLight = pMainWorld->m_a_tdxhArrayOfDynamicLights[lIndex];
		GLI_xGetLightState(pMainWorld->m_a_tdxhArrayOfDynamicLights[lIndex], &m_a_tdxhArrayOfLights[m_lCurrentLights].lInitialState);
		m_lCurrentLights++;
	}
}

//=========================================================================
// DRAWOBJECT
// Main function of drawing in edit mode
// This function is called for each display viewport
//=========================================================================
void DEV_ViewPort3D::DrawObject(GLI_tdxHandleToLight hLight, HIE_tdxHandleToSuperObject hObject)
{
	GLD_tdstViewportAttributes			stViewportAttr;
	BOOL								bEnabledWrite;

	if (!GetParentMultiDevice3D()->IsActive())
		return;

	if (!GLD_bClearViewport(m_hDisplayDevice, m_hDisplayViewport))
	{
		ASSERT(0);
	}

	GLI_xClearViewingList();

	if (!GLD_bRequestWriteToViewport(m_hDisplayDevice, m_hDisplayViewport, &stViewportAttr, &bEnabledWrite))
	{
		ASSERT(0);
	}

	if (bEnabledWrite)
	{
        if(hObject)
		{
			fn_vInitLightsInViewport
			(
				(struct GLD_tdstViewportAttributes_ *)&stViewportAttr, 
				hLight, 
				GetParentMultiDevice3D()->GetInterface()->GetMainWorld()
			);
			HIE_fn_vInitMatrixStack();
			HIE_fn_bInitCameraMatrixStack((struct GLD_tdstViewportAttributes_ *)&stViewportAttr);
			HIE_fn_vSendSuperObjectToViewport((struct GLD_tdstViewportAttributes_ *)&stViewportAttr, hObject, GLI_C_lAllIsEnable&(GLI_C_lIsNotDrawCollideInformation^0xffffffff));
		}

        // Call editor method to draw special object in viewport
		if (m_p_oCamera)
			m_p_oCamera->GetEditor()->fn_vAddObjectsToDraw(&stViewportAttr, hLight, this);
        if(GetParentContact())
            GetParentContact()->fn_vAddObjectsToDraw(&stViewportAttr, hLight, this);

		
		if(hObject)
		    GLI_xSendListToViewport(&stViewportAttr);

		if (!GLD_bWriteToViewportFinished(m_hDisplayDevice, m_hDisplayViewport))
		{
			ASSERT(0);
		}

        // Call editor method to draw special object in viewport
        if(GetParentContact())
            GetParentContact()->fn_vAddObjectsToDraw2(&stViewportAttr, NULL);
	}
}
//=========================================================================
// DRAWOBJECT
// Main function of drawing in edit mode
// This function is called for each display viewport
//=========================================================================
void DEV_ViewPort3D::DrawEditorObject(GLI_tdxHandleToLight hLight, CPA_SuperObject *pRoot)
{
	GLD_tdstViewportAttributes			stViewportAttr;
	BOOL								bEnabledWrite;

	if (!GetParentMultiDevice3D()->IsActive())
		return;
	
	// clear all
	if (!GLD_bClearViewport(m_hDisplayDevice, m_hDisplayViewport))
	{
		ASSERT(0);
	}

	// if gli has not been initialized, I can't draw !!!
	if (GLI_xIsGliInit() == 0)
		return;

	GLI_xClearViewingList();

	// request write
	if (!GLD_bRequestWriteToViewport(m_hDisplayDevice, m_hDisplayViewport, &stViewportAttr, &bEnabledWrite))
	{
		ASSERT(0);
	}

	
	// draw world
	if (bEnabledWrite)
	{
		if(GetParentContact())
			GetParentContact()->fn_vBeforeDrawingWorld(&stViewportAttr, hLight, this);
		if(pRoot)
		{
			CPA_Interface *pInterface = pRoot->GetEditor()->GetInterface();
			pInterface->GetSpecificInterface()->fn_vDisplayWorld (this,
				(struct GLD_tdstViewportAttributes_ *)&stViewportAttr, hLight, pRoot);
		}

        // Call editor method to draw special object in viewport
		if (m_p_oCamera)
			m_p_oCamera->GetEditor()->fn_vAddObjectsToDraw(&stViewportAttr, hLight, this);

		if(GetParentContact())
			GetParentContact()->fn_vAddObjectsToDraw(&stViewportAttr, hLight, this);


		if(pRoot)
			GLI_xSendListToViewport(&stViewportAttr);

		if (!GLD_bWriteToViewportFinished(m_hDisplayDevice, m_hDisplayViewport))
		{
			ASSERT(0);
		}

		if(GetParentContact())
			GetParentContact()->GetInterface()->fn_vDrawSuperObjectsCenters(&stViewportAttr);

		// Call editor method to draw special object in viewport
		if(GetParentContact())
			GetParentContact()->fn_vAddObjectsToDraw2(&stViewportAttr, NULL);
	}

	// draw mouse if fullscreen
	if (M_bFullScreenEditor() && m_p_oDevice->IsFullScreen())
	{
		if(!g_bOnce)
		{
			//CPA2 Gabi Dumitrascu 98/07/13
			GLI_xCreateMaterial(&g_hNormalMouseMaterial);
			GLI_xLoadTexture(&p_stTextureBar1, NULL,"curseur_nz.tga", 0, 0);
			if (p_stTextureBar1) 
				TEX_vSetTextureQualityLevel(p_stTextureBar1,(char)TEX_C_QHIGH); // eventuellement

			GLI_xCreateMaterial(&g_hDragMouseMaterial);
			GLI_xLoadTexture(&p_stTextureBar2, NULL,"curseur_nz_drag.tga", 0, 0);
			if (p_stTextureBar2) 
				TEX_vSetTextureQualityLevel(p_stTextureBar2,(char)TEX_C_QHIGH); // eventuellement

			// si les textures ne sont pas deja chargees
			GLI_vEndofGeometricLoad();
			
			GLI_xSetMaterialTexture(g_hNormalMouseMaterial,p_stTextureBar1);
			GLI_xSetMaterialTexture(g_hDragMouseMaterial,p_stTextureBar2);

			g_hMouseMaterial = g_hNormalMouseMaterial;
			//End CPA2 Gabi Dumitrascu 98/07/13
			g_bOnce = TRUE;
		}
		
		//CPA2 Gabi Dumitrascu 98/07/13
		g_hMouseMaterial = g_bDragDropActivate? g_hDragMouseMaterial : g_hNormalMouseMaterial;
		//End CPA2 Gabi Dumitrascu 98/07/13

		DetectMouseSwap(TRUE, &stViewportAttr);

	}
	//CPA2 Gabi Dumitrascu 98/07/13
	else if (!IsCursorInFirstScreen ())
	{
		POINT ptMouse;
		GetCursorPos (&ptMouse);
		mfn_vChangeCursorFrom2To1 (CPoint (ptMouse), eSwapRight);
	}
	//End CPA2 Gabi Dumitrascu 98/07/13

}

//=========================================================================
// DETECTMOUSESWAP
// Called to detect the swap between 2 screens
//=========================================================================
void DEV_ViewPort3D::DetectMouseSwap (BOOL bDrawCursor, GLD_tdstViewportAttributes *p_stViewportAttr)
{
	POINT	stPoint;
	CPoint	oPoint;
	CRect oScreenViewRect;

	GetCursorPos(&stPoint);
	oPoint = CPoint(stPoint);

	oScreenViewRect.right -= 4;
	oScreenViewRect.bottom -= 4;
	
	if (GetParentContact()->GetInterface()->fn_bGetAutomaticSwap () && !IsCursorInFirstScreen ())
	{
		oScreenViewRect.top = 0;
		oScreenViewRect.left = 0;
		oScreenViewRect.right = GetSystemMetrics (SM_CXFULLSCREEN);
		oScreenViewRect.bottom = GetSystemMetrics (SM_CYFULLSCREEN);
	}
	else
		GetWindowRect(oScreenViewRect);

	//CPA2 Gabi Dumitrascu 98/06/26
	if (GetParentContact()->GetInterface()->fn_bGetAutomaticSwap ())
	{
		BOOL bChangeCursorFrom1To2 = FALSE;
		BOOL bChangeCursorFrom2To1 = FALSE;

		int xLeft = oPoint.x - oScreenViewRect.left;
		int yTop = oPoint.y - oScreenViewRect.top;
		int xRight = oScreenViewRect.right - oPoint.x;
		int yBottom = oScreenViewRect.bottom - oPoint.y;
		const int nScreenWidth = GetSystemMetrics (SM_CXFULLSCREEN);

		tdeForceSwap eForceSwap = GetParentContact()->GetInterface()->fn_eGetForceSwap();
		tdeForceSwap eSwapMode = eSwapRight;

		// Mode Right Swap
		if (eForceSwap == eSwapRight || eForceSwap == eSwapBoth)
		{
			// cursor pos on the left edge of the screen
			if (xLeft <= EDGE_TOLERANCE && !IsCursorInFirstScreen () && !m_bObjectIsMoving)
			{
				bChangeCursorFrom2To1 = TRUE;
				eSwapMode = eSwapRight;
			}
			// cursor pos on the right edge of the screen
			else if (xRight <= EDGE_TOLERANCE && IsCursorInFirstScreen ())
			{
				bChangeCursorFrom1To2 = TRUE;
				eSwapMode = eSwapRight;
			}
		}
		// Mode Left Swap
		if (eForceSwap == eSwapLeft || eForceSwap == eSwapBoth)
		{
			// cursor pos on the left edge of the screen
			if (xRight <= EDGE_TOLERANCE && !IsCursorInFirstScreen () && !m_bObjectIsMoving)
			{
				bChangeCursorFrom2To1 = TRUE;
				eSwapMode = eSwapLeft;
			}
			// cursor pos on the right edge of the screen
			else if (/*xLeft*/oPoint.x <= EDGE_TOLERANCE && IsCursorInFirstScreen ())
			{
				bChangeCursorFrom1To2 = TRUE;
				eSwapMode = eSwapLeft;
			}
		}
		// For Top Limit
		if (!IsCursorInFirstScreen () && !m_bObjectIsMoving && yTop <= EDGE_TOLERANCE)
		{
			bChangeCursorFrom2To1 = TRUE;
			m_bIsVerticalSwap = TRUE;
		}

		// For Bottom Limit
		if (!IsCursorInFirstScreen () && !m_bObjectIsMoving && yBottom <= EDGE_TOLERANCE)
			SetCursorPos(oPoint.x, oScreenViewRect.bottom + EDGE_TOLERANCE + 1);

		if (bChangeCursorFrom1To2)
			mfn_vChangeCursorFrom1To2 (oPoint, eSwapMode);
		else if (bChangeCursorFrom2To1)
			mfn_vChangeCursorFrom2To1 (oPoint, eSwapMode, m_bIsVerticalSwap);
	}

	if (bDrawCursor)
	{
		if (oPoint.x >= oScreenViewRect.left && oPoint.x <= oScreenViewRect.right &&
			oPoint.y >= oScreenViewRect.top  && oPoint.y <= oScreenViewRect.bottom)
		{
			CPoint	oScreen;
			oScreen.x = oScreenViewRect.right;
			oScreen.y = oPoint.y;
			
			//CPA2 Gabi Dumitrascu 98/06/26
			if (GetParentContact()->GetInterface()->fn_bGetAutomaticSwap ())
			{
				if (!IsCursorInFirstScreen ())
				{
					//End CPA2 Gabi Dumitrascu 98/06/26
					ScreenToClient(&oPoint);
					ClientToVoodooFullScreen(oPoint);
					// adjust width to screen size
					ScreenToClient(&oScreen);
					ClientToVoodooFullScreen(oScreen);
					float xWidth = ((oScreen.x - oPoint.x) <= 16.0f) ? (oScreen.x - oPoint.x) : 16.0f;
					
					GLI_vDraw2DSprite(p_stViewportAttr, (float)oPoint.x, oPoint.x + xWidth, (float)oPoint.y, oPoint.y + 16.0f, g_hMouseMaterial);           
                    //VLNG4
			        GLI_xSendListToViewport(p_stViewportAttr);
			        //EVL
					//CPA2 Gabi Dumitrascu 98/06/26
				}
			}
			else 
			{
				ScreenToClient(&oPoint);
				ClientToVoodooFullScreen(oPoint);
				// adjust width to screen size
				ScreenToClient(&oScreen);
				ClientToVoodooFullScreen(oScreen);
				float xWidth = ((oScreen.x - oPoint.x) <= 16.0f) ? (oScreen.x - oPoint.x) : 16.0f;

				GLI_vDraw2DSprite(p_stViewportAttr, (float)oPoint.x, oPoint.x + xWidth, (float)oPoint.y, oPoint.y + 16.0f, g_hMouseMaterial);           
                //VLNG4
			    GLI_xSendListToViewport(p_stViewportAttr);
			    //EVL
			}
			//End CPA2 Gabi Dumitrascu 98/06/26
		}
	}
}

#endif // ACTIVE_EDITOR

//===========================================================================
//
// MOUSE
//
//===========================================================================

#ifdef ACTIVE_EDITOR

// JT
// Init and close the mouse session
void DEV_ViewPort3D::InitMouseMove (MTH3D_tdstVector *stMousePos3D, GLI_tdst2DVertex* stMousePos2D)
{
	m_stMousePos = *stMousePos3D;   // We keep in memory the 3D position of the mouse
	GetParentContact()->GetInterface()->SetMovePlaneCenter(&m_stMousePos);
	GLI_vInitDeplacement(m_hDisplayDevice, m_hDisplayViewport, stMousePos2D, stMousePos3D);

	if (GetParentContact())
	{
		GetParentContact()->GetInterface()->fn_vEnterObjectMouseMoveMode();
		m_oLastCursorScreenPos = CPoint((int) stMousePos2D->xX, (int) stMousePos2D->xY);
	}
	else
		GetParentContact()->GetInterface()->fn_vLeaveObjectMouseMoveMode();
}

void DEV_ViewPort3D::DoneMouseMove (void)
{
}

//=========================================================================
// make the camera follow the moved object (called only when an object is)
// being moved with the mouse)
// Author : Benoit Germmain
// 24/02/97 Modification: corrected a bug forcing the scroll of the camera
// if the moved object was already in the outer limit of the viewport
//=========================================================================
void DEV_ViewPort3D::m_vFakeMouseMove(CPoint oScreenMousePoint)
{
	GLI_tdst2DVertex    stMouseScreenCoords;
	tdstMousePos        stMousePos;
	GLI_tdst2DVertex     stNewMouseScreenCoords, stOldMouseScreenCoords;
	MTH3D_tdstVector stMouseInduced3DMove;
	const short c_wMaxBorderPercent = 100;
	const short c_wScrollBorderPercent = c_wMaxBorderPercent * 90 / 100;

	//BOOL bRemoveMouseMessages = TRUE;
	m_bObjectIsMoving = FALSE;

	//get the current screen client area of the viewport
	CRect oScreenViewRect;
	if (M_bFullScreenEditor() && m_p_oDevice->IsFullScreen() && !IsCursorInFirstScreen () && 
		GetParentContact()->GetInterface()->fn_bGetAutomaticSwap ())
	{
		oScreenViewRect.top = 0;
		oScreenViewRect.left = 0;
		oScreenViewRect.right = GetSystemMetrics (SM_CXFULLSCREEN);
		oScreenViewRect.bottom = GetSystemMetrics (SM_CYFULLSCREEN);
	}
	else
		GetWindowRect(oScreenViewRect);

	//make the rest of the code believe the cursor is always inside the client boundaries
	//if we are moving an object (or trying to, at least)
	if ( GetParentContact()->GetInterface()->fn_bGetObjectMouseMoveMode() )
	{
		oScreenMousePoint.x = max(oScreenMousePoint.x, oScreenViewRect.left);
		oScreenMousePoint.x = min(oScreenMousePoint.x, oScreenViewRect.right);
		oScreenMousePoint.y = max(oScreenMousePoint.y, oScreenViewRect.top);
		oScreenMousePoint.y = min(oScreenMousePoint.y, oScreenViewRect.bottom);
	}

	//get the position in client coordinates
	CPoint oClientMousePoint = oScreenMousePoint;
	ScreenToClient(&oClientMousePoint);
	//get the position in client voodoo coordinates
	CPoint oVoodooMousePoint = oClientMousePoint;
#ifndef USE_DIRECTX
	if (GLI_lWhatIsGLI() == GLI_C_VersionGlide)
#endif
		ClientToVoodoo(oVoodooMousePoint);
	//get the relative client area
	CRect oClientViewRect(oScreenViewRect);
	oClientViewRect.OffsetRect(-oScreenViewRect.left, -oScreenViewRect.top);

	//##########################################################
	//here the current cursor position is inside the client area
	//##########################################################

	//fill the stMousePos structure
	stMousePos.stPos = oScreenMousePoint;
	stMousePos.stPos3D = m_stMousePos;

	stMouseScreenCoords.xX = GLI_M_LongToValue(oVoodooMousePoint.x);
	stMouseScreenCoords.xY = GLI_M_LongToValue(oVoodooMousePoint.y);
	stMousePos. stPos2D.xX = GLI_M_LongToValue(oVoodooMousePoint.x);
	stMousePos. stPos2D.xY = GLI_M_LongToValue(oVoodooMousePoint.y);

	if ( !GLI_bGetVecteurDeplacement(&stMouseScreenCoords, &stMouseInduced3DMove) ) // no object is moved
	{
		if(GetParentContact())
			GetParentContact()->_OnMouseMove(0, &stMousePos, NULL);

		if(m_p_oCameraInterface)
			m_p_oCameraInterface->SendMouseMoveToCamera(m_p_oCamera,0, &stMousePos, NULL);

		//keep the cursor at the current position when we are back
		if (M_bFullScreenEditor())
		{
			GetParentMultiDevice3D()->DrawEditorObject();
		}
		return;
	}

	//##################################################
	//here and object is picked and moved with the mouse
	//##################################################

	// the camera is used to move or rotate an object: make the cursor follow the object
	// ALX
	// The mouse move is constrained into a specific plane selected by SetPlaneForMouseMove
	// if the object moved out of the depth autoscroll zone, translate the camera of the object's movement
	// get too far or too close
	MTH3D_tdstVector stDepthAutoScroll;
	BOOL bDepthAutoScroll;
	if ( bDepthAutoScroll = ComputeMouseMoveIntoPlane(&stMouseInduced3DMove, &stMouseInduced3DMove) )
		stDepthAutoScroll = stMouseInduced3DMove;
	else
	  MTH3D_M_vNullVector(&stDepthAutoScroll);

	//move faster is the cursor is in the autoscroll area
	int iCurX, iCurY;
	iCurX = (oClientMousePoint.x - oClientViewRect.right / 2) * (c_wMaxBorderPercent * 2) / oClientViewRect.right;
	iCurY = (oClientMousePoint.y - oClientViewRect.bottom / 2) * (c_wMaxBorderPercent * 2) / oClientViewRect.bottom;
	if ( abs(iCurX) >= c_wScrollBorderPercent || abs(iCurY) >= c_wScrollBorderPercent )
	{
		if ( int iScrollSpeed = min(c_wMaxBorderPercent, max(abs(iCurY), abs(iCurX))) - c_wScrollBorderPercent )
		{
			if (!MTH3D_M_bIsNullVector(&stMouseInduced3DMove))
				MTH3D_M_vNormalizeVector(&stMouseInduced3DMove, &stMouseInduced3DMove);
			MTH3D_M_vMulScalarVector(&stMouseInduced3DMove, iScrollSpeed * iScrollSpeed / (float) 2.0 / c_wMaxBorderPercent, &stMouseInduced3DMove);
		}
	}


	// Send the 3D vector to the frame base.
	if
	(
		   !GetParentContact()       // the given mouse pos is *before* the movement!
		|| !GetParentContact()->_OnMouseMove(m_uiLastMouseState, &stMousePos, &stMouseInduced3DMove)
	) //the object did not move, so we dont have to continue...
	{
		//SetCursorPos(m_oLastCursorScreenPos.x, m_oLastCursorScreenPos.y);
		if (M_bFullScreenEditor())
		{
			GetParentMultiDevice3D()->DrawEditorObject();
		}
		return;
	}

	m_bObjectIsMoving = TRUE;

	if ( !GetParentContact()->GetInterface()->fn_bGetObjectMouseMoveMode() )
	{
		//SetCursorPos(m_oLastCursorScreenPos.x, m_oLastCursorScreenPos.y);
		if (M_bFullScreenEditor())
		{
			GetParentMultiDevice3D()->DrawEditorObject();
		}
		return;
	}

	//TODO-B: if the moved object is the current camera target, untarget the camera immediately ?

	//########################################################
	//here we want the camera to follow the object being moved
	//########################################################

	// we update the 3D-position of the mouse, but after keeping the original position
	MTH3D_tdstVector stMousePosBeforeMove = m_stMousePos;
	MTH3D_M_vAddVector(&m_stMousePos, &stMousePosBeforeMove, &stMouseInduced3DMove);

	// with the 3D-position, we compute the new 2D-position of the mouse
	Convert3dTo2d(&stOldMouseScreenCoords, &stMousePosBeforeMove);
	Convert3dTo2d(&stNewMouseScreenCoords, &m_stMousePos);

	// make the camera follow the movement if the cursor gets close to a border of the viewport
	// and if the cursor moves towards the same border... //bbb 24/02/97
	// move the viewrect in the mouse position coordinates, ie the viewrect itself.

	//get the initial client position of the moved object -> of the cursor
	CPoint	oClientInitialMousePos((int) stOldMouseScreenCoords.xX, (int) stOldMouseScreenCoords.xY);
	
	//get the resulting client position of the moved object -> of the cursor
	CPoint	oClientResultingMousePos((int) stNewMouseScreenCoords.xX, (int) stNewMouseScreenCoords.xY);
		
	//if (GLI_lWhatIsGLI() == GLI_C_VersionGlide)
			VoodooToClient(oClientInitialMousePos);
	//if (GLI_lWhatIsGLI() == GLI_C_VersionGlide)
			VoodooToClient(oClientResultingMousePos);
	
	// specific for 2nd screen
	if (M_bFullScreenEditor() && m_p_oDevice->IsFullScreen() && !IsCursorInFirstScreen () && 
		GetParentContact()->GetInterface()->fn_bGetAutomaticSwap ())
	{
		ClientToScreen(&oClientInitialMousePos);
		ClientToScreen(&oClientResultingMousePos);
	}

	//compute the offset percentage of the old cursor pos relatively to the center of the viewport
	int iStartX, iStartY;
	iStartX = (oClientInitialMousePos.x - oClientViewRect.right / 2) * (c_wMaxBorderPercent * 2) / oClientViewRect.right;
	iStartY = (oClientInitialMousePos.y - oClientViewRect.bottom / 2) * (c_wMaxBorderPercent * 2) / oClientViewRect.bottom;
	//compute the offset percentage of the new cursor pos relatively to the center of the viewport
	int iEndX, iEndY; 
	iEndX = (oClientResultingMousePos.x - oClientViewRect.right / 2) * (c_wMaxBorderPercent * 2) / oClientViewRect.right;
	iEndY = (oClientResultingMousePos.y - oClientViewRect.bottom / 2) * (c_wMaxBorderPercent * 2) / oClientViewRect.bottom;

	//do not move the camera if not far enough from the center, or if the designer moved
	//towards the center of the viewport
	const short c_wNotPushed = 0;
	const short c_wPushedLeft = 1;
	const short c_wPushedTop = 2;
	const short c_wPushedRight = 4;
	const short c_wPushedBottom = 8;
	const short c_wPushVertical = c_wPushedTop + c_wPushedBottom;
	const short c_wPushHorizontal = c_wPushedLeft + c_wPushedRight;
	short wPushDir = c_wNotPushed;
	float fRatioX = 1.0, fRatioY = 1.0;

	//now we want the camera to move only so that the anchor will land at the border of the screen
	//the autoscroll area of the viewport: the ratio to reduce the 3D movement is the
	//penetration depth into the autoscroll area divided by the total movement percentage
	if ( (iEndX <= -c_wScrollBorderPercent) && ((iEndX - iStartX) < 0) )
	{
		wPushDir += c_wPushedLeft;
		fRatioX = abs(c_wScrollBorderPercent - abs(iEndX)) / (float) abs(iEndX - iStartX); // < 1
	}
	else if ( (iEndX >= c_wScrollBorderPercent) && ((iEndX - iStartX) > 0) )
	{
		wPushDir += c_wPushedRight;
		fRatioX = abs(c_wScrollBorderPercent - abs(iEndX)) / (float) abs(iEndX - iStartX); // < 1
	}
	if ( (iEndY <= -c_wScrollBorderPercent) && ((iEndY - iStartY) < 0) )
	{
		wPushDir += c_wPushedTop;
		fRatioY = abs(c_wScrollBorderPercent - abs(iEndY)) / (float) abs(iEndY - iStartY); // < 1
	}
	else if ( (iEndY >= c_wScrollBorderPercent) && ((iEndY - iStartY) > 0) )
	{
		wPushDir += c_wPushedBottom;
		fRatioY = abs(c_wScrollBorderPercent - abs(iEndY)) / (float) abs(iEndY - iStartY); // < 1
	}

	CPA_CameraCoords oCoords;
	if ( wPushDir ) //if the camera is pushed to keep the object in the viewport
	{
		//convert the vector into camera coordinates
		if ( m_p_oCameraInterface )
			m_p_oCameraInterface->WorldToCameraCoordinates_Vector(m_p_oCamera, stMouseInduced3DMove);
			
		//zero the axis that is not pushed
		if ( !(wPushDir & c_wPushHorizontal) ) //we do not push horizontal
			stMouseInduced3DMove.xX = 0.0;
		if ( !(wPushDir & c_wPushVertical) ) //we do not push vertical
			stMouseInduced3DMove.xY = 0.0;
		//
		//scale the vector
		MTH3D_M_vMulScalarVector(&stMouseInduced3DMove, min(fRatioX, fRatioY), &stMouseInduced3DMove);
		//if the object landed in the outer border, translate the camera so that the object
		//gets back in the center area
		// move the camera with the induced vector for the moved object...

		oCoords.SetXYZ(stMouseInduced3DMove.xX, stMouseInduced3DMove.xY, stMouseInduced3DMove.xZ);
		oCoords.SetAxisSystem(CameraCoordinates);

		//release the camera target only if an object is moved...
		if (m_p_oCameraInterface)
			m_p_oCameraInterface->SetTargetType(m_p_oCamera, tNone);

		//and move the camera
		m_p_oCameraInterface->Translate(m_p_oCamera, &oCoords);
	}

	//handle the depth movement: add it to the camera's movement
	if ( bDepthAutoScroll )
	{
		oCoords.SetXYZ(stDepthAutoScroll.xX, stDepthAutoScroll.xY, stDepthAutoScroll.xZ);
		oCoords.SetAxisSystem(WorldCoordinates);
		m_p_oCameraInterface->Translate(m_p_oCamera, &oCoords);
	}

	// now lets move the mouse to make it stand over the moved object in the view, as before
	// the camera moved to recenter the moved object...

	Convert3dTo2d(&stNewMouseScreenCoords, &m_stMousePos);

	// Call InitDeplacement to reinit the engine functions
	GLI_vInitDeplacement(m_hDisplayDevice,	m_hDisplayViewport,	&stNewMouseScreenCoords, &m_stMousePos);

	//remember where the cursor lands after the object move
	m_oLastCursorScreenPos = CPoint((int) stNewMouseScreenCoords.xX, (int) stNewMouseScreenCoords.xY);
	//if (GLI_lWhatIsGLI() == GLI_C_VersionGlide)
		VoodooToClient(m_oLastCursorScreenPos);
	ClientToScreen(&m_oLastCursorScreenPos);

	//redraw everything, since the object or the camera moved, and the hierarchy
	//editor did now refresh the display...
	GetParentMultiDevice3D()->GetInterface()->fn_vUpdateAll(E_mc_JustDraw);

	//remove all mousemove messages that could have occurred during all this
	MSG Message;
	while ( PeekMessage(&Message, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE) );

	//and make windows send a mouse move message to where the cursor is right now
	GetCursorPos(&oScreenMousePoint);
	SetCursorPos(oScreenMousePoint.x, oScreenMousePoint.y);

	//we want to draw the move plane with the center on the moved object (where the 3D mouse is...)
	GetParentContact()->GetInterface()->SetMovePlaneCenter(&m_stMousePos);

	if (M_bFullScreenEditor())
	{
		GetParentMultiDevice3D()->DrawEditorObject();
	}

}

//---------------------------------------------------------------------------
void DEV_ViewPort3D::OnSetFocus(CWnd* pOldWnd)
{
	CPA_BaseObject *p_oCamera;

	if (m_bWasInSecondScreen)
	{
		m_bWasInSecondScreen = FALSE;

		if (M_bFullScreenEditor() && m_p_oDevice->IsFullScreen() && IsCursorInFirstScreen() &&
			GetParentContact()->GetInterface()->fn_bGetAutomaticSwap())
		{
			while (ShowCursor(FALSE) >= 0);
			SetCapture ();
			SetCursorInSecondScreen ();
		}
	}

	// if there is a dialog bar in this multidevice
	if (GetParentDialogBar() != NULL)
	{
		// get the old camera 
		p_oCamera = GetParentDialogBar()->m_p_oCamera;
		
		// if the new camera is different from the old one
		if (p_oCamera != m_p_oCamera)
		{
			// hide the old camera toolbar
			if (p_oCamera != NULL)
				M_GetCameraDLL(p_oCamera)->HideDialogBar(p_oCamera);

			// set the new camera toolbar
			if (m_p_oCameraInterface != NULL)
				m_p_oCameraInterface->ShowDialogBar(m_p_oCamera);
		}
	}
	DEV_ViewPort::OnSetFocus(pOldWnd);
}

#ifndef USE_DIRECTX
//--------------------------------------------------------------------
// FBFFBF temporary, to remove when we have rush voodoo cards
void DEV_ViewPort3D::ClientToVoodoo(CPoint &point)
{
	CRect oClientSize;
	long lWidth,lHeight;
	double dTx,dTy;

	//voodoo screen size is 512*480

	// special case : 2nd screen mode
	if (M_bFullScreenEditor() && m_p_oDevice->IsFullScreen() && !IsCursorInFirstScreen () && 
		GetParentContact()->GetInterface()->fn_bGetAutomaticSwap ())
	{
		ClientToScreen(&point);
		lWidth = GetSystemMetrics (SM_CXFULLSCREEN);
		lHeight = GetSystemMetrics (SM_CYFULLSCREEN);
	}
	else
	{
		// get the window size
		GetClientRect(&oClientSize);
		lWidth = oClientSize.Width();
		lHeight = oClientSize.Height();
	}

	// if the window is smaller (x and y) than 512*480, don't touch coordinates!
	if (lWidth <= 640 && lHeight <= 480 && !M_bFullScreenEditor())
		return;
	dTx = ((double)640)/((double)lWidth);
	dTy = ((double)480)/((double)lHeight);

	// backstretch horizontaly
	if (lWidth > 640 || M_bFullScreenEditor())
		point.x = (long) (point.x * dTx);
	// backstretch verticaly
	if (lHeight > 480 || M_bFullScreenEditor())
		point.y = (long) (point.y * dTy);
}


//--------------------------------------------------------------------
// FBFFBF temporary, to remove when we have rush voodoo cards
void DEV_ViewPort3D::ClientToVoodooFullScreen(CPoint &point)
{
	CRect oClientSize;
	long lWidth,lHeight;
	double dTx,dTy;

	//voodoo screen size is 640*480

	// special case : 2nd screen mode
	if (M_bFullScreenEditor() && m_p_oDevice->IsFullScreen() && !IsCursorInFirstScreen () && 
		GetParentContact()->GetInterface()->fn_bGetAutomaticSwap ())
	{
		ClientToScreen(&point);
		lWidth = GetSystemMetrics (SM_CXFULLSCREEN);
		lHeight = GetSystemMetrics (SM_CYFULLSCREEN);
	}
	else
	{
		// get the window size
		GetClientRect(&oClientSize);
		lWidth = oClientSize.Width();
		lHeight = oClientSize.Height();
	}

	dTx = ((double)640)/((double)lWidth);
	dTy = ((double)480)/((double)lHeight);

	// backstretch horizontaly
	point.x = (long) (point.x * dTx);
	// backstretch verticaly
	point.y = (long) (point.y * dTy);
}




//--------------------------------------------------------------------
// FBFFBF temporary, to remove when we have rush voodoo cards
void DEV_ViewPort3D::VoodooToClient(CPoint &point)
{
	CRect oClientSize;
	long lWidth,lHeight;
	double dTx,dTy;

	//voodoo screen size is 512*480

	// special case : 2nd screen mode
	if (M_bFullScreenEditor() && m_p_oDevice->IsFullScreen() && !IsCursorInFirstScreen () && 
		GetParentContact()->GetInterface()->fn_bGetAutomaticSwap ())
	{
		lWidth = GetSystemMetrics (SM_CXFULLSCREEN);
		lHeight = GetSystemMetrics (SM_CYFULLSCREEN);
	}
	else
	{
		// get the window size
		GetClientRect(&oClientSize);
		lWidth = oClientSize.Width();
		lHeight = oClientSize.Height();
	}

	// if the window is smaller (x and y) than 512*480, don't touch coordinates!
	if (lWidth <= 640 && lHeight <= 480 && !M_bFullScreenEditor())
		return;
	dTx = ((double)640)/((double)lWidth);
	dTy = ((double)480)/((double)lHeight);

	// backstretch horizontaly
	if (lWidth > 640 || M_bFullScreenEditor())
		point.x = (long) (point.x / dTx);
	// backstretch verticaly
	if (lHeight > 480 || M_bFullScreenEditor())
		point.y = (long) (point.y / dTy);

	if (M_bFullScreenEditor() && m_p_oDevice->IsFullScreen() && !IsCursorInFirstScreen () && 
		GetParentContact()->GetInterface()->fn_bGetAutomaticSwap ())
	{
		ScreenToClient(&point);
	}

}

//--------------------------------------------------------------------
// ALX 11 temporary, to remove when we have rush voodoo cards
void DEV_ViewPort3D::ClientToVoodoo(GLI_tdst2DVertex & point)
{
	CRect oClientSize;
	long lWidth,lHeight;
	double dTx,dTy;

	//voodoo screen size is 512*480

	// special case : 2nd screen mode
	if (M_bFullScreenEditor() && m_p_oDevice->IsFullScreen() && !IsCursorInFirstScreen () && 
		GetParentContact()->GetInterface()->fn_bGetAutomaticSwap ())
	{
		CPoint oPoint ((int)point.xX, (int)point.xY);
		ClientToScreen(&oPoint);
		point.xX = (float) oPoint.x;
		point.xY = (float) oPoint.y;
		lWidth = GetSystemMetrics (SM_CXFULLSCREEN);
		lHeight = GetSystemMetrics (SM_CYFULLSCREEN);
	}
	else
	{
		// get the window size
		GetClientRect(&oClientSize);
		lWidth = oClientSize.Width();
		lHeight = oClientSize.Height();
	}

	// if the window is smaller (x and y) than 512*480, don't touch coordinates!
	if (lWidth <= 640 && lHeight <= 480 && !M_bFullScreenEditor())
		return;
	dTx = ((double)640)/((double)lWidth);
	dTy = ((double)480)/((double)lHeight);

	// backstretch horizontaly
	if (lWidth > 640 || M_bFullScreenEditor())
		point.xX *= (long) dTx;
	// backstretch verticaly
	if (lHeight > 480 || M_bFullScreenEditor())
		point.xY *= (long) dTy;
}
// End ALX 11

//--------------------------------------------------------------------
void DEV_ViewPort3D::PointToMousePos(CPoint point, tdstMousePos* pstMousePos)
{
	pstMousePos->stPos = point;
	ClientToScreen(&pstMousePos->stPos);

	if (GLI_lWhatIsGLI() == GLI_C_VersionGlide)
	{
		ClientToVoodoo (point);
		pstMousePos->stPos2D.xX = GLI_M_LongToValue(point.x);
		pstMousePos->stPos2D.xY = GLI_M_LongToValue(point.y);
		VoodooToClient (point);
	}
	else
	{
	    pstMousePos->stPos2D.xX = GLI_M_LongToValue(point.x);
		pstMousePos->stPos2D.xY = GLI_M_LongToValue(point.y);
	}

}
#else //USE_DIRECTX
void DEV_ViewPort3D::ClientToVoodoo(CPoint &point)
{
	CRect oClientSize;
	long lWidth,lHeight;
	double dTx,dTy;
	GLD_tdstViewportAttributes stViewAttrib; // MR1110
	long lScreenWidth,lScreenHeight;	// MR1110
#if 0
	// special case : 2nd screen mode
	if (M_bFullScreenEditor() && m_p_oDevice->IsFullScreen() && !IsCursorInFirstScreen () && 
		GetParentContact()->GetInterface()->fn_bGetAutomaticSwap ())
	{
		ClientToScreen(&point);
		lWidth = GetSystemMetrics (SM_CXFULLSCREEN);
		lHeight = GetSystemMetrics (SM_CYFULLSCREEN);
	}
	else
	{
		// get the window size
		GetClientRect(&oClientSize);
		lWidth = oClientSize.Width();
		lHeight = oClientSize.Height();
		// JOB 23/01/01 {
		if( !GLI_fn_iGetFullScreen() )
		{
			point.x = (long) (point.x/GLI_fn_fGetRatio());
			point.y = (long) (point.y/GLI_fn_fGetRatio());
			return;
		}
		// JOB 23/01/01 }
	}

	// MR1110
	/*// if the window is smaller (x and y) than 512*480, don't touch coordinates!
	if (lWidth <= 640 && lHeight <= 480 && !M_bFullScreenEditor())
	return;
	dTx = ((double)640)/((double)lWidth);
	dTy = ((double)480)/((double)lHeight);

	// backstretch horizontaly
	if (lWidth > 640 || M_bFullScreenEditor())
	point.x = (long) (point.x * dTx);
	// backstretch verticaly
	if (lHeight > 480 || M_bFullScreenEditor())
	point.y = (long) (point.y * dTy);*/
	GLD_bGetViewportAttributes(m_hDisplayDevice,m_hDisplayViewport,&stViewAttrib);
	lScreenWidth = stViewAttrib.dwWidth;
	lScreenHeight = stViewAttrib.dwHeight;

	dTx = ((double)lScreenWidth)/((double)lWidth);
	dTy = ((double)lScreenHeight)/((double)lHeight);

	// backstretch horizontaly
	point.x = (long) (point.x * dTx);
	// backstretch verticaly
	point.y = (long) (point.y * dTy);
#else
	// get the window size
	GetClientRect(&oClientSize);
	lWidth = oClientSize.Width();
	lHeight = oClientSize.Height();


	GLD_bGetViewportAttributes(m_hDisplayDevice,m_hDisplayViewport,&stViewAttrib);
	lScreenWidth = 640;//stViewAttrib.dwWidth;
	lScreenHeight = 480;//stViewAttrib.dwHeight;
	
	dTx = ((double)lScreenWidth)/((double)lWidth);
	dTy = ((double)lScreenHeight)/((double)lHeight);

	// backstretch horizontaly
	point.x = (long) (point.x * dTx*GLI_gst_DllInfo.f_WidthRatio);
	// backstretch verticaly
	point.y = (long) (point.y * dTy*GLI_gst_DllInfo.f_HeightRatio);

#endif
}


//--------------------------------------------------------------------
// MT : generalization to all display type
void DEV_ViewPort3D::ClientToVoodooFullScreen(CPoint &point)
{
	ClientToVoodoo(point);
}




//--------------------------------------------------------------------
// MT : generalization to all display type
void DEV_ViewPort3D::VoodooToClient(CPoint &point)
{
	CRect oClientSize;
	long lWidth,lHeight;
	double dTx,dTy;
	long lScreenWidth,lScreenHeight;
	GLD_tdstViewportAttributes stViewAttrib;
#if 0
	// special case : 2nd screen mode
	if (M_bFullScreenEditor() && m_p_oDevice->IsFullScreen() && !IsCursorInFirstScreen () && 
		GetParentContact()->GetInterface()->fn_bGetAutomaticSwap ())
	{
		lWidth = GetSystemMetrics (SM_CXFULLSCREEN);
		lHeight = GetSystemMetrics (SM_CYFULLSCREEN);
	}
	else
	{
		// get the window size
		GetClientRect(&oClientSize);
		lWidth = oClientSize.Width();
		lHeight = oClientSize.Height();
		// JOB 23/01/01 {
		if( !GLI_fn_iGetFullScreen() )
		{
			point.x = (long) (point.x*GLI_fn_fGetRatio());
			point.y = (long) (point.y*GLI_fn_fGetRatio());
			return;
		}
		// JOB 23/01/01 }
	}

	GLD_bGetViewportAttributes(m_hDisplayDevice,m_hDisplayViewport,&stViewAttrib);
	lScreenWidth = 640;//stViewAttrib.dwWidth;
	lScreenHeight = 480;//stViewAttrib.dwHeight;

	dTx = ((double)lScreenWidth)/((double)lWidth);
	dTy = ((double)lScreenHeight)/((double)lHeight);

	point.x = (long) (point.x / dTx);
	point.y = (long) (point.y / dTy);

	if (M_bFullScreenEditor() && m_p_oDevice->IsFullScreen() && !IsCursorInFirstScreen () && 
		GetParentContact()->GetInterface()->fn_bGetAutomaticSwap ())
	{
		ScreenToClient(&point);
	}
#else

	// get the window size
	GetClientRect(&oClientSize);
	lWidth = oClientSize.Width();
	lHeight = oClientSize.Height();

	GLD_bGetViewportAttributes(m_hDisplayDevice,m_hDisplayViewport,&stViewAttrib);
	lScreenWidth = stViewAttrib.dwWidth;
	lScreenHeight = stViewAttrib.dwHeight;

	dTx = ((double)lScreenWidth)/((double)lWidth);
	dTy = ((double)lScreenHeight)/((double)lHeight);

	point.x = (long) ((point.x / dTx)/GLI_gst_DllInfo.f_WidthRatio);
	point.y = (long) ((point.y / dTy)/GLI_gst_DllInfo.f_HeightRatio);

#endif
}

//--------------------------------------------------------------------
// MT : never used
void DEV_ViewPort3D::ClientToVoodoo(GLI_tdst2DVertex & point)
{
	assert(0);
}
// End ALX 11

//--------------------------------------------------------------------
// MT : generalization to all display type
void DEV_ViewPort3D::PointToMousePos(CPoint point, tdstMousePos* pstMousePos)
{
	pstMousePos->stPos = point;
	ClientToScreen(&pstMousePos->stPos);
	ClientToVoodoo (point);
	pstMousePos->stPos2D.xX = GLI_M_LongToValue(point.x);
	pstMousePos->stPos2D.xY = GLI_M_LongToValue(point.y);
	pstMousePos->stPos2D.xOoZ = 1.f; /* Portage Windows 2000 */    
}




#endif

//--------------------------------------------------------------------
void DEV_ViewPort3D::OnLButtonDown(UINT nFlags, CPoint point)
{
	HIE_tdxHandleToSuperObject  hSupObject;
	HIE_aDEF_stTabOfPickInfo	a_stPickInfo;
	ACP_tdxIndex				xNbPicked;
	tdstMousePos				stMousePos;
	BOOL						bRes;

	//CPA2 Gabi Dumitrascu 98/06/29
	if (IsCursorInDeadScreen ())
		return;

	if (M_bFullScreenEditor() && m_p_oDevice->IsFullScreen() && !IsCursorInFirstScreen () && 
		GetParentContact()->GetInterface()->fn_bGetAutomaticSwap())
	{
		SetFocus();
	}
	//End CPA2 Gabi Dumitrascu 98/06/29

	g_bLButtonDown = TRUE;

	m_uiLastMouseState = nFlags;
	xNbPicked = 0;

	// selection
	PointToMousePos(point, &stMousePos);

	//send command to camera 
	if( GetParentContact()->GetInterface()->fn_bMoveCamera() )
		if ( m_p_oCameraInterface)
		{
			bRes = m_p_oCameraInterface->SendLButtonDownToCamera(m_p_oCamera, nFlags, &stMousePos, 0, NULL);
		
			if (bRes) 
			{
				m_p_oGrabCapture();
				return; // processed by camera
			}
		}

	//try to pick an object
	hSupObject = GetParentMultiDevice3D()->GetEngineWorld();
	if (hSupObject != NULL)
	{
		xNbPicked = HIE_xIsSuperObjectPick(GLI_C_ModePickingFace,m_hDisplayDevice,
			m_hDisplayViewport, &stMousePos.stPos2D, hSupObject, a_stPickInfo);
	}

	m_bObjectIsMoving = xNbPicked > 1;// if more than one objects are pointed by mouse

	ClientToScreen(&point);

	// not in CameraPickObject mode
	if (xNbPicked != 0)
	{
		InitMouseMove (&a_stPickInfo[0].stPickedObject.aDEF_stDataOfElement[0].stHit, &stMousePos.stPos2D);
	}

	// Capture the mouse
	m_p_oGrabCapture();
	
	if (GetParentContact())
	{
		if (xNbPicked != 0)
			bRes = GetParentContact()->_OnLButtonDown(nFlags, &stMousePos, xNbPicked, a_stPickInfo);
		else
			bRes = GetParentContact()->_OnLButtonDown(nFlags, &stMousePos, 0, NULL);
	}

	m_bBeginMove = TRUE;
	if (bRes) // processed by contact
	{
		m_vFakeMouseLButtonDown(point);
		return; 
	}


	//send command to camera
	if (m_p_oCameraInterface)
	{
		if (xNbPicked != 0)
			bRes = m_p_oCameraInterface->SendLButtonDownToCamera(m_p_oCamera, nFlags, &stMousePos, xNbPicked, a_stPickInfo);
		else
			bRes = m_p_oCameraInterface->SendLButtonDownToCamera(m_p_oCamera, nFlags, &stMousePos, 0, NULL);
	}
	if (bRes)  // processed by camera
	{
		//m_vFakeMouseMove(point);
		m_vFakeMouseLButtonDown(point);
		//m_bObjectIsMoving = xNbPicked > 1;
		return; 
	}
	// add your code here
	m_vFakeMouseLButtonDown(point);
}


//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method : m_vFakeMouseLButtonDown
// Date   : 97.12.11
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description : It make the calculation for the position of an object when is just selected.
// Author      : Viorel Preoteasa
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification :
// Date         :
// By           :
//////////////////////////////////////////////////////////////////////////////////////////////////////
void DEV_ViewPort3D::m_vFakeMouseLButtonDown(CPoint oScreenMousePoint)
{
	GLI_tdst2DVertex    stMouseScreenCoords;
	tdstMousePos        stMousePos;
//	GLI_tdst2DVertex     stNewMouseScreenCoords, stOldMouseScreenCoords;
	MTH3D_tdstVector stMouseInduced3DMove;
	const short c_wMaxBorderPercent = 100;
	const short c_wScrollBorderPercent = c_wMaxBorderPercent * 90 / 100;
	//BOOL bRemoveMouseMessages = TRUE;
	//get the current screen client area of the viewport
	CRect oScreenViewRect;
	if (M_bFullScreenEditor() && m_p_oDevice->IsFullScreen() && !IsCursorInFirstScreen () && 
		GetParentContact()->GetInterface()->fn_bGetAutomaticSwap ())
	{
		oScreenViewRect.top = 0;
		oScreenViewRect.left = 0;
		oScreenViewRect.right = GetSystemMetrics (SM_CXFULLSCREEN);
		oScreenViewRect.bottom = GetSystemMetrics (SM_CYFULLSCREEN);
	}
	else
		GetWindowRect(oScreenViewRect);

	//make the rest of the code believe the cursor is always inside the client boundaries
	//if we are moving an object (or trying to, at least)
	if ( GetParentContact()->GetInterface()->fn_bGetObjectMouseMoveMode() )
	{
		oScreenMousePoint.x = max(oScreenMousePoint.x, oScreenViewRect.left);
		oScreenMousePoint.x = min(oScreenMousePoint.x, oScreenViewRect.right);
		oScreenMousePoint.y = max(oScreenMousePoint.y, oScreenViewRect.top);
		oScreenMousePoint.y = min(oScreenMousePoint.y, oScreenViewRect.bottom);
	}

	//get the position in client coordinates
	CPoint oClientMousePoint = oScreenMousePoint;
	ScreenToClient(&oClientMousePoint);
	//get the position in client voodoo coordinates
	CPoint oVoodooMousePoint = oClientMousePoint;
	//if (GLI_lWhatIsGLI() == GLI_C_VersionGlide)
		ClientToVoodoo(oVoodooMousePoint);
	//get the relative client area
	CRect oClientViewRect(oScreenViewRect);
	oClientViewRect.OffsetRect(-oScreenViewRect.left, -oScreenViewRect.top);

	//##########################################################
	//here the current cursor position is inside the client area
	//##########################################################

	//fill the stMousePos structure
	stMousePos.stPos = oScreenMousePoint;
	stMousePos.stPos3D = m_stMousePos;

	stMouseScreenCoords.xX = GLI_M_LongToValue(oVoodooMousePoint.x);
	stMouseScreenCoords.xY = GLI_M_LongToValue(oVoodooMousePoint.y);
	stMousePos. stPos2D.xX = GLI_M_LongToValue(oVoodooMousePoint.x);
	stMousePos. stPos2D.xY = GLI_M_LongToValue(oVoodooMousePoint.y);

	if ( !GLI_bGetVecteurDeplacement(&stMouseScreenCoords, &stMouseInduced3DMove) ) // no object is moved
	{
		return;
	}

	//##################################################
	//here and object is picked and moved with the mouse
	//##################################################

	// the camera is used to move or rotate an object: make the cursor follow the object
	// ALX
	// The mouse move is constrained into a specific plane selected by SetPlaneForMouseMove
	// if the object moved out of the depth autoscroll zone, translate the camera of the object's movement
	// get too far or too close
	MTH3D_tdstVector stDepthAutoScroll;
	BOOL bDepthAutoScroll;
	if ( bDepthAutoScroll = ComputeMouseMoveIntoPlane(&stMouseInduced3DMove, &stMouseInduced3DMove) )
		stDepthAutoScroll = stMouseInduced3DMove;
	else
	  MTH3D_M_vNullVector(&stDepthAutoScroll);
}



// CPA_Ed_1 FS begin
//---------------------------------------------------------------------------
void DEV_ViewPort3D::OnRButtonUp(UINT nFlags, CPoint point) // FLORIN
{
	ACP_tdxIndex				xNbPicked;
    tdstMousePos				stMousePos;

	//CPA2 Gabi Dumitrascu 98/06/29
	if (IsCursorInDeadScreen ())
		return;
	//End CPA2 Gabi Dumitrascu 98/06/29

   // if (GLI_lWhatIsGLI() == GLI_C_VersionGlide)
	if(1)
	{
		ClientToVoodoo (point);
		stMousePos.stPos2D.xX = GLI_M_LongToValue(point.x);
		stMousePos.stPos2D.xY = GLI_M_LongToValue(point.y);
		VoodooToClient(point);
	}
	else
	{
		stMousePos.stPos2D.xX = GLI_M_LongToValue(point.x);
		stMousePos.stPos2D.xY = GLI_M_LongToValue(point.y);
	}

	m_uiLastMouseState = nFlags;

    ClientToScreen(&point);
    stMousePos.stPos = point;
	xNbPicked = 0;

	if( GetParentContact()->GetInterface()->fn_bMoveCamera() )
		if (m_p_oCameraInterface)
			if( m_p_oCameraInterface->SendRButtonUpToCamera(m_p_oCamera, nFlags, &stMousePos ) )
				return;

	if(GetParentContact())
		GetParentContact()->_OnRButtonUp(nFlags, NULL);
}

//--------------------------------------------------------------------
void DEV_ViewPort3D::OnLButtonUp(UINT nFlags, CPoint point)
{
    tdstMousePos            stMousePos;

	//CPA2 Gabi Dumitrascu 98/06/29
	if (IsCursorInDeadScreen ())
		return;
	//End CPA2 Gabi Dumitrascu 98/06/29

	g_bLButtonDown = FALSE;
	
	m_uiLastMouseState = nFlags;

	// ALX 11
#ifndef USE_DIRECTX
    if (GLI_lWhatIsGLI() == GLI_C_VersionGlide)
	{
#endif
		ClientToVoodoo (point);
		stMousePos. stPos2D.xX = GLI_M_LongToValue(point.x);
		stMousePos. stPos2D.xY = GLI_M_LongToValue(point.y);
#ifdef USE_DIRECTX
                 stMousePos. stPos2D.xOoZ = 1.f;
#endif
		VoodooToClient (point);
#ifndef USE_DIRECTX
	}
	else
	{
		stMousePos. stPos2D.xX = GLI_M_LongToValue(point.x);
		stMousePos. stPos2D.xY = GLI_M_LongToValue(point.y);
	}
#endif
    ClientToScreen(&point);
    stMousePos.stPos = point;

	//send command to camera
	if( GetParentContact()->GetInterface()->fn_bMoveCamera() )
		if (m_p_oCameraInterface)
		{
			if (m_p_oCameraInterface->SendLButtonUpToCamera(m_p_oCamera,nFlags,&stMousePos))
			{
				m_p_oSurrenderCapture(FALSE);
				return;
			}
		}

	GLI_vEndDeplacement();

	GetParentContact()->GetInterface()->fn_vLeaveObjectMouseMoveMode();

	if(GetParentContact())
	{
		GetParentContact()->_OnLButtonUp(nFlags, &stMousePos);
		
		//send command to camera
		if (m_p_oCameraInterface)
		{
			if (m_p_oCameraInterface->SendLButtonUpToCamera(m_p_oCamera,nFlags,&stMousePos))
				return;
		}
	}

	// Release the mouse
	m_p_oSurrenderCapture(FALSE);

	if(m_bObjectIsMoving)
		M_GetMainWnd()->UpdateStatus((char*)LPCTSTR(m_csMessage), C_STATUSPANE_INFOS, C_STATUS_NORMAL);

	DoneMouseMove ();

}

//--------------------------------------------------------------------
void DEV_ViewPort3D::OnRButtonDown(UINT nFlags, CPoint point)
{
	HIE_tdxHandleToSuperObject	hSupObject;
	HIE_aDEF_stTabOfPickInfo	a_stPickInfo;
	ACP_tdxIndex				xNbPicked;
    tdstMousePos				stMousePos;
	BOOL						bRes;

	//CPA2 Gabi Dumitrascu 98/06/29
	if (IsCursorInDeadScreen ())
		return;
	//End CPA2 Gabi Dumitrascu 98/06/29

// CB
#ifndef USE_DIRECTX
    if (GLI_lWhatIsGLI() == GLI_C_VersionGlide)
	{
#endif
		ClientToVoodoo (point);
		stMousePos.stPos2D.xX = GLI_M_LongToValue(point.x);
		stMousePos.stPos2D.xY = GLI_M_LongToValue(point.y);
#ifdef USE_DIRECTX
		stMousePos.stPos2D.xOoZ = 1.f;
#endif
		VoodooToClient(point);
#ifndef USE_DIRECTX
	}
	else
	{
		stMousePos.stPos2D.xX = GLI_M_LongToValue(point.x);
		stMousePos.stPos2D.xY = GLI_M_LongToValue(point.y);
	}
#endif
	m_uiLastMouseState = nFlags;

    ClientToScreen(&point);
    stMousePos.stPos = point;
	xNbPicked = 0;

	if( GetParentContact()->GetInterface()->fn_bMoveCamera() )
		if (m_p_oCameraInterface)
			if( m_p_oCameraInterface->SendRButtonDownToCamera(m_p_oCamera, nFlags, &stMousePos, 0, NULL) )
				return;

	//try to pick an object
	hSupObject = GetParentMultiDevice3D()->GetEngineWorld();
	if (hSupObject != NULL)
	{
		xNbPicked = HIE_xIsSuperObjectPick(GLI_C_ModePickingFace,m_hDisplayDevice,
			m_hDisplayViewport, &stMousePos.stPos2D, hSupObject, a_stPickInfo );
	}
	
	if(GetParentContact())
	{
		if (xNbPicked != 0)
			bRes = GetParentContact()->_OnRButtonDown(nFlags, &stMousePos, xNbPicked, a_stPickInfo);
		else
			bRes = GetParentContact()->_OnRButtonDown(nFlags, &stMousePos, 0, NULL);
	}
	if (bRes) return;

	//send command to camera
	if (m_p_oCameraInterface)
	{
		if (xNbPicked != 0)
			bRes = m_p_oCameraInterface->SendRButtonDownToCamera(m_p_oCamera, nFlags, &stMousePos, xNbPicked, a_stPickInfo);
		else
			bRes = m_p_oCameraInterface->SendRButtonDownToCamera(m_p_oCamera, nFlags, &stMousePos, 0, NULL);
	}
	if (bRes) return;

	//add your code here
}

//--------------------------------------------------------------------
void DEV_ViewPort3D::OnLButtonDblClk(UINT nFlags, CPoint point)
{
	HIE_tdxHandleToSuperObject	hSupObject;
	HIE_aDEF_stTabOfPickInfo	a_stPickInfo;
	ACP_tdxIndex				xNbPicked;
	tdstMousePos				stMousePos;
	BOOL						bRes;

	//CPA2 Gabi Dumitrascu 98/06/29
	if (IsCursorInDeadScreen ())
		return;
	//End CPA2 Gabi Dumitrascu 98/06/29

// CB
#ifndef USE_DIRECTX
    if (GLI_lWhatIsGLI() == GLI_C_VersionGlide)
	{
#endif
		ClientToVoodoo (point);
		stMousePos.stPos2D.xX = GLI_M_LongToValue(point.x);
		stMousePos.stPos2D.xY = GLI_M_LongToValue(point.y);
#ifdef USE_DIRECTX
		stMousePos.stPos2D.xOoZ = 1.f;
#endif
		VoodooToClient(point);
#ifndef USE_DIRECTX
	}
	else
	{
		stMousePos.stPos2D.xX = GLI_M_LongToValue(point.x);
		stMousePos.stPos2D.xY = GLI_M_LongToValue(point.y);
	}
#endif
// ENDCB

	m_uiLastMouseState = nFlags;
	ClientToScreen(&point);
	stMousePos.stPos = point;

	// try to pick object
	xNbPicked = 0;
	hSupObject = GetParentMultiDevice3D()->GetEngineWorld();
	if (hSupObject != NULL)
	{
		xNbPicked = HIE_xIsSuperObjectPick(GLI_C_ModePickingFace,m_hDisplayDevice,
			m_hDisplayViewport, &stMousePos.stPos2D, hSupObject,a_stPickInfo);
	}
	if(GetParentContact())
	{
		if (xNbPicked != 0)
			bRes = GetParentContact()->_OnLButtonDblClk(nFlags, &stMousePos, xNbPicked, a_stPickInfo);
		else
			bRes = GetParentContact()->_OnLButtonDblClk(nFlags, &stMousePos, 0, NULL);
	}

	if (bRes) return; // dblclick allready processed by contact

	//send command to camera
	if (m_p_oCameraInterface)
	{
		if (xNbPicked != 0)
			bRes = m_p_oCameraInterface->SendLButtonDblClkToCamera(m_p_oCamera, nFlags, &stMousePos, xNbPicked, a_stPickInfo);
		else
			bRes = m_p_oCameraInterface->SendLButtonDblClkToCamera(m_p_oCamera, nFlags, &stMousePos, 0, NULL);
	}
	if (bRes) 
		return; // dblclick allready processed by camera

	// process here the viewport dblclick
}

// ALX
//=========================================================================
// Function used by OnMouseMove to compute mouse move into the selected plane
// Input : p_stOriginalMouseMove, output : p_stConstrainedMouseMove
// Author : Alexis VAISSE
//=========================================================================
//TODO: remove this declaration when function is publicly declared by GLI
extern "C" MTH_tdxReal GLI_xGetCameraFocalizationPlane(GLI_tdxHandleToCamera hCam);
BOOL DEV_ViewPort3D::ComputeMouseMoveIntoPlane (MTH3D_tdstVector * p_stConstrainedMouseMove,
                                                MTH3D_tdstVector * p_stOriginalMouseMove)
{

	MTH3D_tdstVector stTempVector, stMouseXAxe, stMouseYAxe;
	GetParentContact()->GetInterface()->GetPlaneForMouseMove(&stMouseXAxe, &stMouseYAxe);

	//where is the cursor in 3D space now ?
	MTH3D_tdstVector stMovedMousePos;
	MTH3D_M_vAddVector(&stMovedMousePos, p_stOriginalMouseMove, &m_stMousePos);

	// Get the matrix and inverted matrix of the camera
	POS_tdstCompletePosition	stCameraMatrix, stInvCameraMatrix;
	POS_fn_vSetIdentityMatrix(&stCameraMatrix);
	POS_fn_vSetIdentityMatrix(&stInvCameraMatrix);

	
	GLI_xGetCameraMatrix(GetEngineCamera(), &stCameraMatrix);
	POS_fn_vInvertIsoMatrix(&stInvCameraMatrix, &stCameraMatrix);

	//get a point that is beyond the focal plane of the camera
	MTH_tdxReal xCameraFocal = (MTH_tdxReal) (15.0 * GLI_xGetCameraFocalizationPlane(GetEngineCamera()));


	//get the 3D position of the camera, because we will nullify it in the matrix later
	MTH3D_tdstVector stCamPos, stFocalPos;
	POS_fn_vGetTranslationVector(&stInvCameraMatrix, &stCamPos);
	//build the 3d position of the focus point (the origin of the focal plane) in camera coordinates
	MTH3D_M_vSetVectorElements(&stFocalPos, 0.0, 0.0, xCameraFocal);
	//convert the vertex into world coordinates
	POS_fn_vMulMatrixVertex(&stFocalPos, &stInvCameraMatrix, &stFocalPos);

	//now set the translation vector to null : we work with vectors, so no translation
	MTH3D_M_vNullVector(&stTempVector);
	POS_fn_vSetTranslationVector(&stInvCameraMatrix, &stTempVector);
	POS_fn_vSetTranslationVector(&stCameraMatrix, &stTempVector);

	//get the 2 axis of the camera that define the plane for the mouse move, in world coordinates
	MTH3D_tdstVector stCamXaxis, stCamYaxis;
	POS_fn_vMulMatrixVertex(&stCamXaxis, &stInvCameraMatrix, &stMouseXAxe);
	POS_fn_vMulMatrixVertex(&stCamYaxis, &stInvCameraMatrix, &stMouseYAxe);

	//get the vector from the camera to the initial position of the object, in world coordinates
	MTH3D_tdstVector stCamToStartingPos, stCamCamToStartingPos;
	MTH3D_M_vSubVector(&stCamToStartingPos, &m_stMousePos, &stCamPos);
	//get a version in camera coordinates
	POS_fn_vMulMatrixVertex(&stCamCamToStartingPos, &stCameraMatrix, &stCamToStartingPos);

	//get the normalized vector from the focal point to the initial position of the object, in world coordinates
	MTH3D_tdstVector stFocalToStartingPos;
	MTH3D_M_vSubVector(&stFocalToStartingPos, &m_stMousePos, &stFocalPos);
	MTH3D_M_vNormalizeVector(&stFocalToStartingPos, &stFocalToStartingPos);

	//in which plane did we start moving ?
	tdeMouseMovePlane eMMP = GetParentContact()->GetInterface()->fn_eGetMouseMovePlane();

	MTH3D_tdstVector stPlaneNormal;
	// if we move the object in the visual plane, or if it is far enough, move it along the standard plane
	if ( eMMP == E_mmp_Standard ) 
	{
		//we move the object in plane defined by the depth (Z) and width axis of the camera, and the old position
		//of the cursor, so build it:
		//->the plane is parallel to the camera's Z
		MTH3D_M_vCrossProductVector(&stPlaneNormal, &stCamXaxis, &stCamYaxis);
		GetParentContact()->GetInterface()->RememberLastMouseMovePlane(&stCamXaxis, &stCamYaxis);
	}
	else if ( eMMP == E_mmp_Warped )// else move it along a plane that includes the positions of the camera and the moved object
	{
		//the plane's normal is a vector orthogonal to stCamToStartingPos and the camera's X axis
		//->the plane is not parallel to the camera's Z, and includes the object's initial position and the focal point
		MTH3D_M_vCrossProductVector(&stPlaneNormal, &stCamXaxis, &stFocalToStartingPos);
		GetParentContact()->GetInterface()->RememberLastMouseMovePlane(&stCamXaxis, &stFocalToStartingPos);
	}
	else
		ASSERT(FALSE);

	//now define the plane's normal
	MTH3D_M_vNormalizeVector(&stPlaneNormal, &stPlaneNormal);
	GLI_tdstEqPlan stPlane;
	//the plane always includes the initial position of the moved object
	GLI_vDefinePlanByNormale(&stPlane, &stPlaneNormal, &m_stMousePos);

	//if we find where a line defined by the original and projected positions of the mouse
	BOOL bDepthAutoscroll = FALSE;
	if ( GLI_bIntersectionPlanDroite(&stPlane, &stCamPos, &stMovedMousePos, &stTempVector) )
	{
		//compute the vector from the initial position to the newly computed ending position of the mouse
		MTH3D_M_vSubVector(p_stConstrainedMouseMove, &stTempVector, &m_stMousePos);

		//get the vector from the camera to the ending position of the mouse
		MTH3D_tdstVector stCamToEndingPos;
		MTH3D_M_vSubVector(&stCamToEndingPos, &stTempVector, &stCamPos);
		//convert it into camera coordinates
		POS_fn_vMulMatrixVertex(&stCamToEndingPos, &stCameraMatrix, &stCamToEndingPos);

		//cancel moves that are behind the camera
		if ( stCamToEndingPos.xZ < 0.0 )
		{
			MTH3D_M_vNullVector(p_stConstrainedMouseMove);
		}
		else
		{
			MTH_tdxReal xDeltaZ = stCamToEndingPos.xZ - stCamCamToStartingPos.xZ;
			bDepthAutoscroll = xDeltaZ > 0.0
			? (stCamToEndingPos.xZ > xCameraFocal + 50.0)
			: (stCamToEndingPos.xZ < xCameraFocal);
			bDepthAutoscroll = bDepthAutoscroll && (stMouseYAxe.xZ ? TRUE : FALSE);

			if ( bDepthAutoscroll )
			{
				MTH_tdxReal xNorm = MTH3D_M_xNormVector(p_stConstrainedMouseMove);
				if ( xNorm > 1.0 )
					MTH3D_M_vNormalizeVector(p_stConstrainedMouseMove, p_stConstrainedMouseMove);
			}

			if(m_bBeginMove) 
			{
				m_stCamToEndingPos = stCamToEndingPos;
				m_stInitMousePos = stTempVector;
				m_bBeginMove = FALSE;
			}
		}
	}
	else
		MTH3D_M_vNullVector(p_stConstrainedMouseMove);

	return bDepthAutoscroll;
}
// End ALX

// ALX
//=========================================================================
// Function used by OnMouseMove
// Convert 3D-coordinates to a 2D-position into the window
// Author : Alexis VAISSE
//=========================================================================
#ifndef USE_DIRECTX
void DEV_ViewPort3D::Convert3dTo2d (GLI_tdst2DVertex * p_stDest , MTH3D_tdstVector * p_stSource)
{
    // Get the matrix of the camera
    POS_tdstCompletePosition	stCameraMatrix;
	POS_fn_vSetIdentityMatrix(&stCameraMatrix);
    GLI_xGetCameraMatrix  (GetEngineCamera () , & stCameraMatrix);

    MTH3D_tdstVector        Temp;
	POS_fn_vMulMatrixVertex(&Temp,&stCameraMatrix,p_stSource);
    GLI_xProjection (GetEngineCamera(),&Temp,p_stDest);
// ALX 11
// MT 03/08/98 {	
	/*
	if (GLI_lWhatIsGLI() == GLI_C_VersionGlide)
	{
		p_stDest -> xX -= (float)(3.0 * pow(2,(23-5)));
		p_stDest -> xY -= (float)(3.0 * pow(2,(23-5)));
	}
	*/
// End MT 03/08/98 }
// End ALX 11
}
// End ALX

#else
void DEV_ViewPort3D::Convert3dTo2d (GLI_tdst2DVertex * p_stDest , MTH3D_tdstVector * p_stSource)
{
    /* Begin Portage Windows 2000 */
	MTH3D_tdstVector     stCamCoords;
	GLI_tdstCamera      *p_stCam  = GetEngineCamera();

	// Convert from world space to camera space
	POS_fn_vMulMatrixVertex( &stCamCoords, &p_stCam->stMatrix, p_stSource );

	// Project on screen
	GLI_xProjection( p_stCam, &stCamCoords, p_stDest );
    /* End Portage Windows 2000 */
}
#endif	//



//--------------------------------------------------------------------
//NOTE: oMousePoint is relative to the client area, NOT the screen!
/*
void DEV_ViewPort3D::OnMouseMove(UINT nFlags, CPoint oMousePoint)
{
	m_uiLastMouseState = nFlags;


	const short wScrollLimits = 10;
	// ALX
	CPoint               oMousePosAtBegin = oMousePoint;
	// End ALX
	CRect   oViewRect;

	GetWindowRect(oViewRect);

	// try to keep the cursor inside the viewport boundaries if the mouse is used to move an object or
	// to change the camera orientation/position
	//no longer necessary in move object mode: the handler will cancel any cursor position outside
	//the client area

	// not in camera mousemove mode
	
	if ( !m_bMouseMoveFakerIsOn && GetParentContact() )
	{
		MTH3D_tdstVector      stMouseInduced3DMove;
		GLI_tdst2DVertex    stMouseScreenCoords;
		tdstMousePos        stMousePos;

// ALX 11
        if (GLI_lWhatIsGLI() == GLI_C_VersionGlide)
		{
			ClientToVoodoo (oMousePoint);
			stMouseScreenCoords.xX = GLI_M_LongToValue(oMousePoint.x);
			stMouseScreenCoords.xY = GLI_M_LongToValue(oMousePoint.y);
			stMousePos. stPos2D.xX = GLI_M_LongToValue(oMousePoint.x);
			stMousePos. stPos2D.xY = GLI_M_LongToValue(oMousePoint.y);
			VoodooToClient (oMousePoint);
		}
		else
		{
			stMouseScreenCoords.xX = GLI_M_LongToValue(oMousePoint.x);
			stMouseScreenCoords.xY = GLI_M_LongToValue(oMousePoint.y);
			stMousePos. stPos2D.xX = GLI_M_LongToValue(oMousePoint.x);
			stMousePos. stPos2D.xY = GLI_M_LongToValue(oMousePoint.y);
		}
// End ALX 11
		ClientToScreen(&oMousePoint);
		stMousePos.stPos = oMousePoint;
		stMousePos.stPos3D = m_stMousePos;

		// if the mousemove-faker timer is not enabled, send the event to the contact
		if ( GLI_bGetVecteurDeplacement(&stMouseScreenCoords, &stMouseInduced3DMove) )
		{
			// the camera is used to move or rotate an object: make the cursor follow the object
			// ALX
			// The mouse move is constrained into a specific plane selected by SetPlaneForMouseMove
			ComputeMouseMoveIntoPlane (& stMouseInduced3DMove , & stMouseInduced3DMove);

			// Send the 3D vector to the frame base.
			// the given mouse pos is *before* the movement!
			if ( GetParentContact()->_OnMouseMove(nFlags, &stMousePos, &stMouseInduced3DMove) )
				// we update the 3D-position of the mouse
				MTH3D_M_vAddVector   (&m_stMousePos, &m_stMousePos, &stMouseInduced3DMove);
		}
		else
		{
			GetParentContact()->_OnMouseMove(nFlags, &stMousePos, NULL);
			if (m_p_oCameraInterface)
				m_p_oCameraInterface->SendMouseMoveToCamera(m_p_oCamera,nFlags, &stMousePos, NULL);
		}

	}

	MSG     stMsg;
	while(::PeekMessage(&stMsg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE));

	// other mousemove processing here
}
*/
void DEV_ViewPort3D::OnMouseMove(UINT nFlags, CPoint oMousePoint)
{
	m_uiLastMouseState = nFlags;

	ACP_tdxIndex				xNbPicked;
    tdstMousePos				stMousePos;
	
	CPoint point=oMousePoint;

	//if (GLI_lWhatIsGLI() == GLI_C_VersionGlide)
	if(1)
	{
		ClientToVoodoo (point);
		stMousePos.stPos2D.xX = GLI_M_LongToValue(point.x);
		stMousePos.stPos2D.xY = GLI_M_LongToValue(point.y);
		VoodooToClient(point);
	}
	else
	{
		stMousePos.stPos2D.xX = GLI_M_LongToValue(point.x);
		stMousePos.stPos2D.xY = GLI_M_LongToValue(point.y);
	}

	m_uiLastMouseState = nFlags;

    ClientToScreen(&point);
    stMousePos.stPos = point;
	xNbPicked = 0;

	if( GetParentContact()->GetInterface()->fn_bMoveCamera() )
		if (m_p_oCameraInterface)
			if( m_p_oCameraInterface->SendMouseMoveToCamera(m_p_oCamera,nFlags, &stMousePos, NULL) )
				return;

	ClientToScreen(&oMousePoint);
	m_vFakeMouseMove(oMousePoint);
	// other mousemove processing here
}

//--------------------------------------------------------------------
//--------------------------------------------------------------------
LONG DEV_ViewPort3D::OnDragDropEnd(WPARAM wparam, LPARAM lparam)
{
	BOOL bRes;
	
	//CPA2 Gabi Dumitrascu 98/07/13
	g_bDragDropActivate = FALSE;
	//End CPA2 Gabi Dumitrascu 98/07/13

	if (M_bFullScreenEditor() && m_p_oDevice->IsFullScreen() && !IsCursorInFirstScreen () && 
		GetParentContact()->GetInterface()->fn_bGetAutomaticSwap())
	{
		SetFocus();
	}

	if(GetParentContact())
	{
		bRes = GetParentContact()->_OnDragDropEnd(wparam,lparam);
		if (bRes) return NULL; //contact allready processed the key
	}

	// other dragdrop processing here
	return NULL;
}

//--------------------------------------------------------------------
//--------------------------------------------------------------------
LONG DEV_ViewPort3D::OnDragDropLooseFocus(WPARAM wparam, LPARAM lparam)
{
	BOOL bRes;
	
	//CPA2 Gabi Dumitrascu 98/07/13
	g_bDragDropActivate = FALSE;
	//End CPA2 Gabi Dumitrascu 98/07/13

	if(GetParentContact())
	{
		bRes = GetParentContact()->_OnDragDropLooseFocus(wparam,lparam);
		if (bRes) return NULL; //contact allready processed the key
	}

	// other dragdrop processing here
	return NULL;

}

//--------------------------------------------------------------------
//--------------------------------------------------------------------
LONG DEV_ViewPort3D::OnDragDropGainFocus(WPARAM wparam, LPARAM lparam)
{
	BOOL bRes;
	
	//CPA2 Gabi Dumitrascu 98/07/13
	g_bDragDropActivate = TRUE;
	//End CPA2 Gabi Dumitrascu 98/07/13

	if(GetParentContact())
	{
		bRes = GetParentContact()->_OnDragDropGainFocus(wparam,lparam);
		if (bRes) return NULL; //contact allready processed the key
	}
	
	// other dragdrop processing here
	return NULL;

}

//--------------------------------------------------------------------
//--------------------------------------------------------------------
LONG DEV_ViewPort3D::OnDragDropMove(WPARAM wparam, LPARAM lparam)
{
	BOOL bRes;
	

	if (M_bFullScreenEditor())
	{
		GetParentMultiDevice3D()->DrawEditorObject();
		//	GetParentMultiDevice3D()->GetInterface()->fn_vUpdateAll(E_mc_JustDraw);
	}
	
	if(GetParentContact())
	{
		bRes = GetParentContact()->_OnDragDropMove(wparam,lparam);
		if (bRes) return NULL; //contact allready processed the key
	}

	// other dragdrop processing here
	return NULL;

}



//====================================================================
//
// VIEWPORT 3D KEYBOARD
//
//====================================================================

//--------------------------------------------------------------------
//CPA2 Corneliu Babiuc (Alt Key) 14-05-98
inline void DEV_ViewPort3D::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	OnKeyDown(nChar, nRepCnt, nFlags);
}

inline void DEV_ViewPort3D::OnSysKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	OnKeyUp(nChar, nRepCnt, nFlags);
}
//END CPA2 Corneliu Babiuc (Alt Key) 19-05-98

//--------------------------------------------------------------------
void DEV_ViewPort3D::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	BOOL    bRes;

	if (M_GetMainApp()->m_bEditorsAreActive == FALSE)
		return;

	switch ( nChar )
	{
	case VK_SHIFT:
		m_uiLastMouseState |= MK_SHIFT;
		break;

	case VK_CONTROL:
		m_uiLastMouseState |= MK_CONTROL;
		break;

	default:
		break;
	}
	
	if(GetParentContact())
	{
		bRes = GetParentContact()->_OnKeyDown(nChar, nRepCnt, nFlags);
		if (bRes) return; //contact allready processed the key
	}

//CPA2 Corneliu Babiuc 13-05-98	
	//get the selected object
	CPA_SuperObject * pSelected = GetParentMultiDevice3D()->GetInterface()->GetCurrentWorld()->GetSingleSelection();
	CPA_Interface * pInterface = GetParentContact() ? GetParentContact()->GetInterface() : NULL;
//END CPA2 Corneliu Babiuc 13-05-98	

	switch(M_GetMainApp()->mp_oDevKeyboard->mfn_uwKeyToAction(nChar))
	{
//CPA2 Corneliu Babiuc 13-05-98

// object drawing flags
	case KA_CancelAllDrawingFlags:
		if ( pInterface )
		{
			pInterface->fn_vCancelAllDrawingFlags();
			pInterface->fn_vUpdateAll(E_mc_JustDraw);
		}
		return;

	case KA_IgnoreDrawingFlags:
		pInterface->SetIgnoreFlags(TRUE);
		return;

	case KA_NormalObject:
		if ( pSelected && pInterface)
		{
			pSelected->SetDrawingFlag(E_df_Normal);
			pInterface->fn_vUpdateAll(E_mc_JustDraw);
		}
		return;

	case KA_GridedObject:
		if ( pSelected && pInterface)
		{
			pSelected->SetDrawingFlag(E_df_Grided);
			pInterface->fn_vUpdateAll(E_mc_JustDraw);
		}
		return;

	case KA_WiredObject:
		if ( pSelected && pInterface)
		{
			pSelected->SetDrawingFlag(E_df_Wired);
			pInterface->fn_vUpdateAll(E_mc_JustDraw);
		}
		return;

// object parameters
	case KA_ShowObjectAxis:
		if ( pSelected && pInterface)
		{
			pSelected->SetDrawnAxis(!pSelected->fn_bIsAxisDrawn());
			pInterface -> fn_vUpdateAll(E_mc_JustDraw);
		}
		return;

	case KA_BVObject:
		if ( pSelected && pInterface)
		{
			pSelected->SetDrawingFlag(E_df_BoundingV);
			pInterface->fn_vUpdateAll(E_mc_JustDraw);
		}
		return;

//objects centers
	case KA_ShowMainCenters:
		if ( pInterface )
			pInterface->SetShowcenter(2);
		return;

	case KA_ShowAllCenters:
		if ( pInterface )
			pInterface->SetShowcenter(1);
		return;

	case KA_ShowNoCenter:
		if ( pInterface )
			pInterface->SetShowcenter(0);
		return;

// world drawing flags
	case KA_NormalWorld:
		if ( pInterface )
			pInterface -> fn_vChangeWorldMask(GLI_C_lIsTextured, !pInterface->fn_bWorldIsTextured());
		return;

	case KA_GridedWorld:
		if ( pInterface )
			pInterface->fn_vChangeWorldMask(GLI_C_lIsNotGrided, pInterface->fn_bWorldIsGrided());
		return;

	case KA_WiredWorld:
		if ( pInterface )
			pInterface->fn_vChangeWorldMask(GLI_C_lIsNotWired, pInterface->fn_bWorldIsWired());
		return;

// world display mode
	case KA_WorldSectors:
		if ( pInterface )
			pInterface->GetSpecificInterface()->fn_vOnChangeDisplayMode(E_dm_DrawWorld);
		return;

	case KA_VisibleSectors:
		if ( pInterface )
			pInterface->GetSpecificInterface()->fn_vOnChangeDisplayMode(E_dm_DrawVisibleSectors);
		return;

	case KA_CurrentSector:
		if ( pInterface )
			pInterface->GetSpecificInterface()->fn_vOnChangeDisplayMode(E_dm_DrawOnlyCurrentSector);
		return;

	case KA_CollisionMap:
		if ( pInterface )
			pInterface->GetSpecificInterface()->fn_vOnChangeDisplayMode(E_dm_DrawCollisionMap);
		return;

// bounding volumes
	case KA_SectorsBV:
		if ( pInterface )
		{
			pInterface->fn_vSetBVMode(E_bv_Sectors);
			pInterface->fn_vUpdateAll(E_mc_JustDraw);
		}
		return;

	case KA_ActorsBV:
		if ( pInterface )
		{
			pInterface->fn_vSetBVMode(E_bv_Actors);
			pInterface->fn_vUpdateAll(E_mc_JustDraw);
		}
		return;

	case KA_ObjectsBV:
		if ( pInterface )
		{
			pInterface->fn_vSetBVMode(E_bv_Objects);
			pInterface->fn_vUpdateAll(E_mc_JustDraw);
		}
		return;

	case KA_NoBV:
		if ( pInterface )
		{
			pInterface->fn_vSetBVMode(E_bv_None);
			pInterface->fn_vUpdateAll(E_mc_JustDraw);
		}
		return;

// colors
	case KA_SelectBackgroundColor:
	{
		CColorDialog	oColorDialog;
		COLORREF		stColor;

		// display color dialog
		if (oColorDialog.DoModal() == IDOK)
		{
			// get selected color
			stColor = oColorDialog.GetColor(); 
			// update controls
			GetParentMultiDevice3D()->SetBackgroundColor(stColor);
		}
		return;
	}

// selection
	case KA_CancelSelection:
		pInterface->fn_vCancelCurrentSelection();
		return;

	case KA_FullSelection:
		pInterface->SetFullSelect(!pInterface->fn_bFullSelect());
		pInterface->fn_vUpdateAll(E_mc_UpdateDialog);
		pInterface->GetFrameBase()->m_oGeneralDialogBar.fn_vUpdateFullSelect(pInterface->fn_bFullSelect());
		return;

	case KA_DeltaSelection:
		pInterface->SetDeltaSelect(!pInterface->fn_bDeltaSelect());
		pInterface->GetFrameBase()->m_oGeneralDialogBar.fn_vUpdateDeltaSelect(pInterface->fn_bDeltaSelect());
		return;

// pyramidal selection
	case KA_FixedDepthPyramid:
		pInterface->SetFixedDepthPyramid(!pInterface->GetFixedDepthPyramid());
		return;

	case KA_RealTimePyramid:
		pInterface->SetRealTimePyramid(!pInterface->GetRealTimePyramid());
		return;

// status bar
	case KA_DisplayInstanceInfo:
		pInterface->SetStatusBarMode(E_sb_InstanceInfo);
		fn_vUpdateStatusBarMessage();
		return;

	case KA_DisplayInstanceToCam:
		pInterface->SetStatusBarMode(E_sb_InstanceToCamera);
		fn_vUpdateStatusBarMessage();
		return;

	case KA_DisplayCameraInfo:
		pInterface->SetStatusBarMode(E_sb_CameraInfo);
		fn_vUpdateStatusBarMessage();
		return;

	case KA_DisplayDistance:
		pInterface->SetDisplayDistance(TRUE);
		return;

// options
	case KA_ScaleEditorObjects:
		if (pInterface)
		{
			if (pInterface->fn_bIsScaleActive())
			{
				pInterface->fn_vReScale();
				pInterface->fn_bSetScaleActive(FALSE);
				pInterface->fn_vUpdateAll(E_mc_JustDraw);
			}
			else
			{
				pInterface->fn_vScale();
				pInterface->fn_vUpdatePositions();
				pInterface->fn_vScale();
				pInterface->fn_bSetScaleActive(TRUE);
				pInterface->fn_vUpdateAll(E_mc_JustDraw);
			}
		}
		return;

	case KA_ShowNoAxis:
		if (pInterface && GetCameraInterface())
		{
			GetCameraInterface()->SetReferentialDisplayMode(DisplayNone);
			pInterface->fn_vUpdateAll(E_mc_JustDraw);
		}
		return;

	case KA_ShowAxisLeft:
		if (pInterface && GetCameraInterface())
		{
			GetCameraInterface()->SetReferentialDisplayMode(DisplayDownLeft);
			pInterface->fn_vUpdateAll(E_mc_JustDraw);
		}
		return;

	case KA_ShowAxisRight:
		if (pInterface && GetCameraInterface())
		{
			GetCameraInterface()->SetReferentialDisplayMode(DisplayDownRight);
			pInterface->fn_vUpdateAll(E_mc_JustDraw);
		}
		return;

	case KA_Borders:
		if ( pInterface )
		{
			CPA_DLLBase *p_oSectorInterface = pInterface->GetMainWorld()->GetObjectDLLWithName(C_szDLLSectorName);			
			p_oSectorInterface->_OnSubMenuCommand(NULL, KA_Borders);
		}
		return;
		
	case KA_ComputeCenters:
		if (pInterface)
		{
			pInterface->fn_vComputeSuperObjectsCenters(NULL);
			pInterface->fn_vUpdateAll(E_mc_JustDraw);
		}
		return;
		
	case KA_ForceMousePos:
		// show the cursos
		while (ShowCursor(TRUE) < 0);
		//disable the confine of the cursor
		ReleaseCapture ();
		ClipCursor (NULL);
		// force cursor in first screen
		SetCursorInFirstScreen ();
		// reinit flags
		m_bWasInSecondScreen = FALSE;
		g_bLButtonDown = FALSE;
		// redraw world
		GetParentContact()->GetDevice()->DrawEditorObject();
		return;
	}

	//send key to camera
	if (m_p_oCameraInterface && m_p_oCameraInterface->SendKeyDownToCamera(m_p_oCamera,nChar,nRepCnt,nFlags))
		return;
}

//--------------------------------------------------------------------
void DEV_ViewPort3D::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    BOOL    bRes;

	if (M_GetMainApp()->m_bEditorsAreActive == FALSE)
		return;

	switch ( nChar )
	{
	case VK_SHIFT:
		m_uiLastMouseState &= ~MK_SHIFT;
		break;

	case VK_CONTROL:
		m_uiLastMouseState &= ~MK_CONTROL;
		break;

	default:
		break;
	}
	
	
	if(GetParentContact())
	{
		bRes = GetParentContact()->_OnKeyUp(nChar, nRepCnt, nFlags);
		if (bRes) return; //contact allready processed the key
	}

	//send key to camera
	if (m_p_oCameraInterface && m_p_oCameraInterface->SendKeyUpToCamera(m_p_oCamera,nChar,nRepCnt,nFlags))
		return;
    // treat viewport key here

	CPA_Interface * pInterface = GetParentContact() ? GetParentContact()->GetInterface() : NULL;

	switch(M_GetMainApp()->mp_oDevKeyboard->mfn_uwKeyToAction(nChar))
	{
	// drawing flag
	case KA_IgnoreDrawingFlags:
		pInterface->SetIgnoreFlags(FALSE);
		return;

	// status bar
	case KA_DisplayDistance:
		pInterface->SetDisplayDistance(FALSE);
		return;
	}


}

//=================================================================
// MESSAGES FROM TOOLBAR
//=================================================================

/*===========================================================================
call each timer vector handler in turn
=========================================================================*/

void DEV_ViewPort3D::OnTimer(UINT uiIdEvent)
{

}


/*===========================================================================
 find the name of the selected instance
=========================================================================*/
CString DEV_ViewPort3D::fn_csGetSelectedInstanceName( ACP_tdxIndex xIndex, HIE_tdstPickInfo*p_stPickInfo, tdstMousePos*p_stMousePos )
{
	CPA_SuperObject * p_csSelectedObject;
	BOOL bDummy;
	p_csSelectedObject = GetParentContact()->GetInterface()->GetPickingSelection( E_sm_SelectNormal, xIndex, p_stPickInfo, p_stMousePos, &bDummy );
	if( p_csSelectedObject && p_csSelectedObject->GetObject() )
		return p_csSelectedObject->GetObject()->GetName();
	else
		return "";
}


void fn_vConvertRotateMatrixToAngles (MTH3D_tdstVector *pAngles, POS_tdstCompletePosition *pMatrix)
{

#define M(a,b) (MTH3D_M_xGet##b##ofVector(&stVect##a))

	MTH3D_tdstVector	stVectI,stVectJ,stVectK;

	POS_fn_vGetRotationMatrix(pMatrix,&stVectI,&stVectJ,&stVectK);
    // Calculate the 3 angles
    GLI_tdxValue Divide = (float) sqrt(M(I,X)*M(I,X)+M(I,Y)*M(I,Y));

    pAngles->xX =   (float) asin (M(J,Z) / Divide);    // We get an angle between -90° and 90°
    pAngles->xZ =   (float) asin (M(I,Y) / Divide);    // We get an angle between -90° and 90°
    pAngles->xY =	(float) asin (M(I,Z));             // We get an angle between -90° and 90°


    if (M(K,Z) < 0)
    {
        if (pAngles->xX >= 0)  
			pAngles->xX =   GLI_M_PI - pAngles->xX;  // Angle between   90° and 180°
		else 
			pAngles->xX = - GLI_M_PI - pAngles->xX;  // Angle between -180° and -90°
    }

    if (M(I,X) < 0)
    {
        if (pAngles->xZ >= 0)  
			pAngles->xZ =   GLI_M_PI - pAngles->xZ;  // Angle between   90° and 180°
		else 
			pAngles->xZ = - GLI_M_PI - pAngles->xZ;  // Angle between -180° and -90°
    }

    if (M(I,X) < 0 && M(K,Z) < 0)
    {
		if (pAngles->xY >= 0)  
			pAngles->xY =   GLI_M_PI - pAngles->xY;  // Angle between   90° and 180°
		else 
			pAngles->xY = - GLI_M_PI - pAngles->xY;  // Angle bewteen -180° and -90°

        if (pAngles->xX >= 0)  
			pAngles->xX -= GLI_M_PI;
		else 
			pAngles->xX += GLI_M_PI;
 
		if (pAngles->xZ >= 0)  
			pAngles->xZ -= GLI_M_PI;
		else 
			pAngles->xZ += GLI_M_PI;
    }
   
	// Convert from radians to degrees
    const GLI_tdxValue ConvertToDegrees = 180 / GLI_M_PI;
    MTH3D_M_vMulScalarVector (pAngles,ConvertToDegrees, pAngles);
}

/*===========================================================================
 update status bar with appropriate message
=========================================================================*/
void DEV_ViewPort3D::fn_vUpdateStatusBarMessage (void)
{
	GEO_tdxHandleToMatrix	hGlobalMatrix;
	MTH3D_tdstVector		stPosition;
	MTH3D_tdstVector		stRotation;
	CPA_Interface			*pInterface;

	pInterface = GetParentContact()->GetInterface();
	
	// display distance : special mode
	if (pInterface->GetDisplayDistance())
	{
		if ((m_csSelectedInstance == "") || (m_csPickedInstance == ""))
			m_csMessage.Format("");
		else 
			m_csMessage.Format("%s ==> %s  [ Vector :  %5.2f,  %5.2f,  %5.2f ]  [ Distance: %5.2f ]", 
				m_csSelectedInstance,
				m_csPickedInstance,
				m_stDistance.xX, m_stDistance.xY, m_stDistance.xZ,
				MTH3D_M_xNormVector(&m_stDistance));
	}
	else if (pInterface->GetSpecificInterface()->fn_bHasValidWorld())
	{
		switch (pInterface->GetStatusBarMode())
		{
		case E_sb_InstanceInfo:
			if (m_csSelectedInstance == "")
				m_csMessage.Format("");
			else if (MTH3D_M_xNormVector(&m_stMoveVector) != 0.f)
// Begin Silviu Simen 06 August 1998 Update Sector Status
//				m_csMessage.Format("%s    [ Position:  %5.2f,  %5.2f,  %5.2f ]  [ Move:  %5.2f,  %5.2f,  %5.2f ]  [ Distance: %5.2f ]", 
//					m_csSelectedInstance,
//					m_stPosition.xX, m_stPosition.xY, m_stPosition.xZ,
//					m_stMoveVector.xX, m_stMoveVector.xY, m_stMoveVector.xZ,
//					MTH3D_M_xNormVector(&m_stMoveVector));
				m_csMessage.Format("%s   [ Position:  %5.2f,  %5.2f,  %5.2f ] [ Move:  %5.2f,  %5.2f,  %5.2f ] [ Distance: %5.2f ] [ Sector: %s ]", 
					m_csSelectedInstance,
					m_stPosition.xX, m_stPosition.xY, m_stPosition.xZ,
					m_stMoveVector.xX, m_stMoveVector.xY, m_stMoveVector.xZ,
					MTH3D_M_xNormVector(&m_stMoveVector),
					pInterface->GetSpecificInterface()->GetCurrentSectorFromPos(&m_stPosition)->GetName());
			else
//				m_csMessage.Format("%s    [ Position:  %5.2f,  %5.2f,  %5.2f ]", 
//					m_csSelectedInstance,
//					m_stPosition.xX, m_stPosition.xY, m_stPosition.xZ);
				m_csMessage.Format("%s    [ Position:  %5.2f,  %5.2f,  %5.2f ] [ Sector: %s ]", 
					m_csSelectedInstance,
					m_stPosition.xX, m_stPosition.xY, m_stPosition.xZ,
					pInterface->GetSpecificInterface()->GetCurrentSectorFromPos(&m_stPosition)->GetName());
// End Silviu Simen 06 August 1998 Update Sector Status
			break;

		case E_sb_InstanceToCamera:
			if (m_csSelectedInstance == "")
				m_csMessage.Format("");
			else
				m_csMessage.Format("%s   [ Position / Camera:  %5.2f,  %5.2f,  %5.2f ]   [ Distance / Camera: %5.2f ]", 
					m_csSelectedInstance,
					m_stCameraDistance.xX, m_stCameraDistance.xY, m_stCameraDistance.xZ,
					MTH3D_M_xNormVector(&m_stCameraDistance));
			break;

		case E_sb_CameraInfo:
			hGlobalMatrix = HIE_fn_hGetSuperObjectMatrix(m_p_oCameraSO->GetStruct());
			POS_fn_vGetTranslationVector(hGlobalMatrix, &stPosition);
			fn_vConvertRotateMatrixToAngles(&stRotation, hGlobalMatrix);

			m_csMessage.Format("CAMERA  [ Mode: %s ]   [ Position:  %5.2f,  %5.2f,  %5.2f ]   [ Rotation:  %5.2f,  %5.2f,  %5.2f ]",
				(m_p_oCameraInterface->GetTargetType(m_p_oCamera) == tNone) ? "Free" : "Targeted",
				stPosition.xX, stPosition.xY, stPosition.xZ,
				stRotation.xX, stRotation.xY, stRotation.xZ);
			break;
		}
	}
	else
		m_csMessage.Format("");

	M_GetMainWnd()->UpdateStatus((char*)LPCTSTR(m_csMessage), C_STATUSPANE_INFOS, C_STATUS_NORMAL);
}

/*===========================================================================
 update message parameters
=========================================================================*/
void DEV_ViewPort3D::SetPosition (MTH3D_tdstVector *pNewPos)
{
	MTH3D_tdstVector stPosition;

	MTH3D_M_vCopyVector(&m_stPosition, pNewPos);

	POS_fn_vGetTranslationVector(HIE_fn_hGetSuperObjectMatrix(m_p_oCameraSO->GetStruct()), &stPosition);
	MTH3D_M_vSubVector(&m_stCameraDistance, &m_stPosition, &stPosition);
}

void DEV_ViewPort3D::SetMoveVector (MTH3D_tdstVector *pNewMove)
{
	MTH3D_M_vCopyVector(&m_stMoveVector, pNewMove);
}

void DEV_ViewPort3D::AddtoMoveVector (MTH3D_tdstVector *pNewMove)
{
	MTH3D_M_vAddVector(&m_stMoveVector, &m_stMoveVector, pNewMove);
}

void DEV_ViewPort3D::SetDistanceVector (MTH3D_tdstVector *pDist)
{
	MTH3D_M_vCopyVector(&m_stDistance, pDist);
}

void DEV_ViewPort3D::SetDistanceToCamera (MTH3D_tdstVector *pDist)
{
	MTH3D_M_vCopyVector(&m_stCameraDistance, pDist);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method	: IsCursorInDeadScreen 
// Date		: 98/06/29
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description	:
// Author		: Gabi Dumitrascu - CPA
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification	: 
// Date			:
// By			:
//////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL DEV_ViewPort3D::IsCursorInDeadScreen () 
{ 
	BOOL bCursorInDeadScreen = FALSE;
	if (GetParentContact()->GetInterface()->fn_bGetAutomaticSwap ())
		bCursorInDeadScreen = M_bFullScreenEditor() && m_p_oDevice->IsFullScreen() && IsCursorInFirstScreen ();

	return bCursorInDeadScreen;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method	: IsCursorInFirstScreen 
// Date		: 98/07/09
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description	:
// Author		: Gabi Dumitrascu - CPA
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification	: 
// Date			:
// By			:
//////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL DEV_ViewPort3D::IsCursorInFirstScreen () 
{ 
	CPA_Interface *pInterface = GetParentContact()->GetInterface();
	ASSERT (pInterface);
	
	return M_GetMainApp()->m_bCursorInFirstScreen;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method	: SetCursorInFirstScreen 
// Date		: 98/07/09
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description	:
// Author		: Gabi Dumitrascu - CPA
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification	: 
// Date			:
// By			:
//////////////////////////////////////////////////////////////////////////////////////////////////////
void DEV_ViewPort3D::SetCursorInFirstScreen () 
{ 
	CPA_Interface *pInterface = GetParentContact()->GetInterface();
	ASSERT (pInterface);
	M_GetMainApp()->m_bCursorInFirstScreen = TRUE;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method	: SetCursorInSecondScreen 
// Date		: 98/07/09
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description	:
// Author		: Gabi Dumitrascu - CPA
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification	: 
// Date			:
// By			:
//////////////////////////////////////////////////////////////////////////////////////////////////////
void DEV_ViewPort3D::SetCursorInSecondScreen () 
{ 
	CPA_Interface *pInterface = GetParentContact()->GetInterface();
	ASSERT (pInterface);
	M_GetMainApp()->m_bCursorInFirstScreen = FALSE;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method	: mfn_vChangeCursorFrom1To2 
// Date		: 98/07/09
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description	:
// Author		: Gabi Dumitrascu - CPA
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification	: 
// Date			:
// By			:
//////////////////////////////////////////////////////////////////////////////////////////////////////
void DEV_ViewPort3D::mfn_vChangeCursorFrom1To2 (CPoint &rptMouse, tdeForceSwap eSwapMode, BOOL bVerticalSwap)
{
	//ptMouse in screen coordinates
	CRect rcDeadScreen;
	GetWindowRect (rcDeadScreen);

	while (ShowCursor(FALSE) >= 0);
	SetCapture ();

	m_bIsVerticalSwap = FALSE;
	ClientToScreen(&rptMouse);
	
	if (bVerticalSwap)
		rptMouse.y = /*rcDeadScreen.top + */EDGE_TOLERANCE + 1;
	else
	{
		if (eSwapMode == eSwapLeft)
			rptMouse.x = rcDeadScreen.right - EDGE_TOLERANCE - 1;
		else
			rptMouse.x = /*rcDeadScreen.left + */EDGE_TOLERANCE + 1;
		rptMouse.y -= ( rcDeadScreen.top - EDGE_TOLERANCE - 1);
	}

	SetCursorPos (rptMouse.x, rptMouse.y);
	SetCursorInSecondScreen ();
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method	: mfn_vChangeCursorFrom2To1 
// Date		: 98/07/09
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description	:
// Author		: Gabi Dumitrascu - CPA
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification	: 
// Date			:
// By			:
//////////////////////////////////////////////////////////////////////////////////////////////////////
void DEV_ViewPort3D::mfn_vChangeCursorFrom2To1 (CPoint &rptMouse, tdeForceSwap eSwapMode, BOOL bVerticalSwap)
{
	//ptMouse in screen coordinates
	CRect rcViewRect;
	GetWindowRect (rcViewRect);

	ScreenToClient(&rptMouse);

	// vertical swap
	if (bVerticalSwap)
		rptMouse.y = rcViewRect.top;
	// horizontal swap
	else
	{
		if (eSwapMode == eSwapLeft)
			rptMouse.x = /*rcViewRect.left + */EDGE_TOLERANCE + 1;
		else
			rptMouse.x = rcViewRect.right - EDGE_TOLERANCE - 1;
		rptMouse.y += (rcViewRect.top + EDGE_TOLERANCE + 1);
	}

	SetCursorPos (rptMouse.x, rptMouse.y);
	while (ShowCursor(TRUE) < 0);
	//disable the confine of the cursor
	ReleaseCapture ();
	ClipCursor (NULL);
	SetCursorInFirstScreen ();
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method	: OnNcMouseMove 
// Date		: 98/07/13
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description	:
// Author		: Gabi Dumitrascu - CPA
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification	: 
// Date			:
// By			:
//////////////////////////////////////////////////////////////////////////////////////////////////////
void DEV_ViewPort3D::OnNcMouseMove (UINT nHitTest, CPoint point)
{
	if (M_bFullScreenEditor() && m_p_oDevice->IsFullScreen() && IsCursorInFirstScreen () && 
 		GetParentContact()->GetInterface()->fn_bGetAutomaticSwap () && nHitTest == HTBORDER)
	{
		POINT ptMouse;
		GetCursorPos (&ptMouse);
		const int nScreenWidth = GetSystemMetrics (SM_CXFULLSCREEN);

		tdeForceSwap eSwapMode = GetParentContact()->GetInterface()->fn_eGetForceSwap ();

		if (eSwapMode == eSwapLeft || eSwapMode == eSwapBoth)
		{
			if (ptMouse.x <= EDGE_TOLERANCE)
			{
				CRect rcViewRect;
				GetWindowRect (rcViewRect);
//				ptMouse.y = ptMouse.y < rcViewRect.top  ? rcViewRect.top : ptMouse.y;
//				ptMouse.y = ptMouse.y > rcViewRect.bottom ? rcViewRect.bottom : ptMouse.y;
				mfn_vChangeCursorFrom1To2 (CPoint (ptMouse), eSwapLeft);
			}
		}
		if (eSwapMode == eSwapRight || eSwapMode == eSwapBoth)
		{
			if (ptMouse.x >= (nScreenWidth - EDGE_TOLERANCE))
			{
				CRect rcViewRect;
				GetWindowRect (rcViewRect);
//				ptMouse.y = ptMouse.y < rcViewRect.top  ? rcViewRect.top : ptMouse.y;
//				ptMouse.y = ptMouse.y > rcViewRect.bottom ? rcViewRect.bottom : ptMouse.y;
				mfn_vChangeCursorFrom1To2 (CPoint (ptMouse), eSwapRight);
			}
		}
	}
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method	: OnNcHitTest 
// Date		: 98/07/13
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description	:
// Author		: Gabi Dumitrascu - CPA
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification	: 
// Date			:
// By			:
//////////////////////////////////////////////////////////////////////////////////////////////////////
UINT DEV_ViewPort3D::OnNcHitTest (CPoint point)
{
	if (M_bFullScreenEditor() && m_p_oDevice->IsFullScreen() && IsCursorInFirstScreen () && 
		GetParentContact()->GetInterface()->fn_bGetAutomaticSwap () && m_bIsVerticalSwap)
	{
		POINT ptMouse;
		GetCursorPos (&ptMouse);
		CRect rcViewRect;
		GetWindowRect (rcViewRect);

		// vertical swap
		if ((point.y > rcViewRect.top + TOP_TOLERANCE) && !g_bMouseLocked)
			mfn_vChangeCursorFrom1To2 (CPoint (ptMouse), eSwapBoth, TRUE);
	}

	return CWnd::OnNcHitTest(point);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
// Method	: OnKillFocus 
// Date		: 98/07/13
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Description	:
// Author		: Gabi Dumitrascu - CPA
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Modification	: 
// Date			:
// By			:
//////////////////////////////////////////////////////////////////////////////////////////////////////
void DEV_ViewPort3D::OnKillFocus (CWnd* pNewWnd)
{	
	if (M_bFullScreenEditor() && m_p_oDevice->IsFullScreen() && !IsCursorInFirstScreen () &&
		GetParentContact()->GetInterface()->fn_bGetAutomaticSwap())
	{
		m_bWasInSecondScreen = TRUE;

		if (g_bLButtonDown)
		{
			POINT ptMouse;
			GetCursorPos (&ptMouse);
			OnLButtonUp(m_uiLastMouseState, CPoint(ptMouse));
		}

		while (ShowCursor(TRUE) < 0);
		//disable the confine of the cursor
		ReleaseCapture ();
		ClipCursor (NULL);
		SetCursorInFirstScreen ();
		GetParentContact()->GetDevice()->DrawEditorObject();
	}
	DEV_ViewPort::OnKillFocus(pNewWnd);
}
#endif //ACTIVE_EDITOR
