
/******************************************************************************
*                                                                             *
* Tut_3d.cpp : definition of the TUT_CTutorialManager class                   *
*                                                                             *
* Contains the methods of the class that are specific to the 3d view          *
* So it is dependant on the ACP.                                              *
* The symbol TUT_3D must be defined for this file to be compiled              *
*                                                                             *
* Author : Alexis Vaisse                                                      *
*                                                                             *
******************************************************************************/


#ifndef TUT_3D
    #include "stdafx.h"
    #include "Tut_Mngr.hpp"
    int TUT_CTutorialManager::m_fn_iExecute3dGetPosition        (char *) { return TUT_C_iError_FunctionNotCompiled; }
    int TUT_CTutorialManager::m_fn_iExecute3dClic3dView         (char *) { return TUT_C_iError_FunctionNotCompiled; }
    int TUT_CTutorialManager::m_fn_iExecute3dIsProtected        (char *) { return TUT_C_iError_FunctionNotCompiled; }
    int TUT_CTutorialManager::m_fn_iExecute3dMove3d             (char *) { return TUT_C_iError_FunctionNotCompiled; }
    int TUT_CTutorialManager::m_fn_iExecute3dSelectModel        (char *) { return TUT_C_iError_FunctionNotCompiled; }
    int TUT_CTutorialManager::m_fn_iExecute3dGetModel           (char *) { return TUT_C_iError_FunctionNotCompiled; }
    int TUT_CTutorialManager::m_fn_iExecute3dGetNumberOfModels  (char *) { return TUT_C_iError_FunctionNotCompiled; }
    int TUT_CTutorialManager::m_fn_iExecute3dIsAvailable        (char *) { return TUT_C_iError_FunctionNotCompiled; }
    int TUT_CTutorialManager::m_fn_iExecute3dGetPrefix          (char *) { return TUT_C_iError_FunctionNotCompiled; }
    int TUT_CTutorialManager::m_fn_iExecute3dIsExistingModel    (char *) { return TUT_C_iError_FunctionNotCompiled; }
	int TUT_CTutorialManager::m_fn_iExecute3dGetStatusBarText	(char *) { return TUT_C_iError_FunctionNotCompiled; }
	// 3DView specific
	BOOL TUT_CTutorialManager::m_fn_bIsModelView				(HWND _hWnd)	{ return FALSE; }
	BOOL TUT_CTutorialManager::m_fn_bLButtonDown3DViewProc		(int iHookType, HWND hwnd, UINT uiMessage, WPARAM wParam, LPARAM lParam)	{ return FALSE;}
	BOOL TUT_CTutorialManager::m_fn_bLButtonUp3DViewProc		(int iHookType, HWND hwnd, UINT uiMessage, WPARAM wParam, LPARAM lParam)	{ return FALSE;}
	BOOL TUT_CTutorialManager::m_fn_bLButtonDownModelViewProc	(int iHookType, HWND hwnd, UINT uiMessage, WPARAM wParam, LPARAM lParam)	{ return FALSE;}
	BOOL TUT_CTutorialManager::m_fn_bLButtonUpModelViewProc		(int iHookType, HWND hwnd, UINT uiMessage, WPARAM wParam, LPARAM lParam)	{ return FALSE;}
#else


#include "stdafx.h"

#include "ACP_Base.h"
#include "ITF.h"
#include "OGD.h"
#include "IncOPD.h"
#include "\CPA\Main\inc\_EditID.h"
#include "Tut_Mngr.hpp"

#define TUT_M_GetCurrentWorld()			(M_GetMainApp () -> fn_p_oGetMainWorld () -> M_GetWorld ())
#define TUT_M_GetCurrentViewPort()		((DEV_ViewPort3D *) (DEV_ViewPort *) M_GetMainDevice2 () -> GetDevice (M_GetMainDevice2 () -> GetFocusDevice () -> GetNumber()) -> GetViewPort())
#define TUT_M_GetCurrentEditor()		(M_GetMainApp () -> fn_p_oGetMainWorld () -> GetCurrentEditor ())

MTH3D_tdstVector g_stInitialPoint;

//-----------------------------------------------------------------------------
// fnp_oFindSuperObjectByName
// Find a super objet which has an associated object of the given name
// Return NULL if not found
//-----------------------------------------------------------------------------
CPA_SuperObject * fnp_oFindSuperObjectByName (char * _sz3dObjectName)
{
    CPA_List<CPA_SuperObject> * pListOfSuperObject = TUT_M_GetCurrentWorld () -> GetListAllObjects ();
    ASSERT (pListOfSuperObject);

    POSITION Pos = pListOfSuperObject -> GetHeadPosition ();
    while (Pos)
    {
        CPA_SuperObject * pSuperObject = (CPA_SuperObject *) pListOfSuperObject -> GetNext (Pos);
        CPA_BaseObject  * pObject      = pSuperObject -> GetObject ();

        if (pObject && stricmp (pObject -> fn_p_szGetName () , _sz3dObjectName) == 0)  return pSuperObject;
    }

    return NULL;    // Not found
}

//-----------------------------------------------------------------------------
// fnp_oFindSuperObjectByHandle
// Find a super objet which has an associated object of the given engine handle
// Return NULL if not found
//-----------------------------------------------------------------------------
CPA_SuperObject * fnp_oFindSuperObjectByHandle (HIE_tdxHandleToSuperObject _hSupObject)
{
    CPA_List<CPA_SuperObject> * pListOfSuperObject = TUT_M_GetCurrentWorld () -> GetListAllObjects ();
    ASSERT (pListOfSuperObject);

    POSITION Pos = pListOfSuperObject -> GetHeadPosition ();
    while (Pos)
    {
        CPA_SuperObject * pSuperObject = (CPA_SuperObject *) pListOfSuperObject -> GetNext (Pos);
		
		if (pSuperObject -> GetData () == (void*)_hSupObject)				return pSuperObject;
	}

    return NULL;    // Not found
}
//-----------------------------------------------------------------------------
// fn_bGetPointOfSuperObject
// Compute the coordinate of one point of the given super object
// (hope we will select the object when clicking on this point)
// Return FALSE if it cannot find one point
//-----------------------------------------------------------------------------
BOOL fn_bGetPointOfSuperObject (CPA_SuperObject * _pSuperObject , MTH3D_tdstVector * _p_stPosition)
{
    POS_tdstCompletePosition * pGlobalMatrix = HIE_fn_hGetSuperObjectGlobalMatrix (_pSuperObject -> GetStruct ());
    POS_fn_vGetTranslationVector (pGlobalMatrix , _p_stPosition);    // Compute origine point in world coordinates

    // Geometric object : we can found one point
    CPA_BaseObject * pObject = _pSuperObject -> GetObject ();
    if (pObject && (pObject -> fn_bIsOfType (C_szGeometricObjectTypeName) ||
                    pObject -> fn_bIsOfType (C_szPhysicalObjectTypeName)))
    {
        ACP_tdxHandleOfObject hObject;
        if (pObject -> fn_bIsOfType (C_szGeometricObjectTypeName))
            hObject = (ACP_tdxHandleOfObject) pObject -> GetData ();
        else
        if (pObject -> fn_bIsOfType (C_szPhysicalObjectTypeName ))
            hObject = (ACP_tdxHandleOfObject) ((EditorPO *) pObject) -> m_fnp_oGetGeometricWithDistance (0.0) -> GetData ();
        else ASSERT (0);

        if (GEO_xGetGeometricObjectNumberOfPoints (hObject) > 0)
        {
            // Compute barycenter
            MTH3D_tdstVector Total;
            MTH3D_M_vNullVector (& Total);
            for (ACP_tdxIndex xNumPoint = 0 ; xNumPoint < GEO_xGetGeometricObjectNumberOfPoints (hObject) ; xNumPoint++)
            {
                MTH3D_tdstVector Point;
                GEO_vGetPointOfObject (hObject , & Point, xNumPoint);
                MTH3D_M_vAddVector (& Total , & Total , & Point);
            }
            MTH3D_M_vDivScalarVector (& Total , & Total , GEO_xGetGeometricObjectNumberOfPoints (hObject));

            POS_fn_vMulMatrixVertex(_p_stPosition , pGlobalMatrix , & Total);    // Convert in world coordinates

            return TRUE;
        }
    }

    CPA_SuperObject * pChildSuperObject = _pSuperObject -> GetSuperObjectFirstChild ();
    while (pChildSuperObject)
    {
        if (fn_bGetPointOfSuperObject (pChildSuperObject , _p_stPosition))  return TRUE;
        pChildSuperObject = _pSuperObject -> GetSuperObjectNextChild (pChildSuperObject);
    }

    return FALSE;    // Not found
}

//-----------------------------------------------------------------------------
// gs_fn_p_oGetModelView
// ...
// ...
// ...
//-----------------------------------------------------------------------------
C3ListView *gs_fn_p_oGetModelView()
{
	C3ListView		*p_oListView		= NULL;
	CPA_EditorBase	*p_oCurrentEditor	= TUT_M_GetCurrentEditor ();

	if( p_oCurrentEditor && p_oCurrentEditor -> GetCurrentEditorName() == C_szDLLMaterialName )
	{
		CSplitFrame	* p_oBottomFrame = (CSplitFrame*)g_oFrameGest . ma_p_oWinArray [2] [3];
		ASSERT (p_oBottomFrame);
		p_oListView = (C3ListView*)p_oBottomFrame -> m_fn_p_oGetPane (1);
	}
	else
	{
		// Get the model view
		FRMBase          * p_oModelFrame = g_oFrameGest . ma_p_oWinArray [2] [3];
		ASSERT (p_oModelFrame);
		CPA_DialogInsert * p_oModelWnd   = (CPA_DialogInsert *) p_oModelFrame -> GetWindow (GW_CHILD);
		ASSERT (p_oModelWnd);
		EDT_ModelView    * p_oModelView  = p_oModelWnd -> GetModelView ();
		ASSERT (p_oModelView);
		p_oListView = (C3ListView*) p_oModelView;
	}
	return p_oListView;
}

CStatusBar *gs_fn_p_oGetStatusBar()
{
	FRMBaseMenu	*p_FRMBaseMenu = M_GetMainWnd2();

	if( p_FRMBaseMenu )
		return & p_FRMBaseMenu -> m_oStatusBar;
	else
		return NULL;
}

//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_iExecute3dGetPosition
// Execute a "get position" tutorial script action
// Return 0 if no error
//-----------------------------------------------------------------------------
int TUT_CTutorialManager::m_fn_iExecute3dGetPosition (char * _szParameter)
{
    // Get parameters : 3d object name and variable name for X, variable name for Y, variable name for Z
    int    iNumberOfParameter;
    char * sz3dObjectName , * szVariableNameForX , * szVariableNameForY , * szVariableNameForZ;

    int    iReturnValue = m_fn_iGetParameters (_szParameter , 4 , 4 , & iNumberOfParameter , & sz3dObjectName ,
                                               & szVariableNameForX , & szVariableNameForY , & szVariableNameForZ);
    if (iReturnValue != TUT_C_iNoError)  return iReturnValue;

    // Search the super object
    CPA_SuperObject * pSuperObject = fnp_oFindSuperObjectByName (sz3dObjectName);
    if (! pSuperObject)  return TUT_C_iError_Unknown3dObject;

    // Find the three variables
    TUT_tdstVariableDefinition * p_stVariableForX = m_fnp_stFindVariable (szVariableNameForX);
    TUT_tdstVariableDefinition * p_stVariableForY = m_fnp_stFindVariable (szVariableNameForY);
    TUT_tdstVariableDefinition * p_stVariableForZ = m_fnp_stFindVariable (szVariableNameForZ);
    if (p_stVariableForX == NULL || p_stVariableForY == NULL || p_stVariableForZ == NULL)
        return TUT_C_iError_UnknownVariable;

    MTH3D_tdstVector stTranslationVector;
    fn_bGetPointOfSuperObject (pSuperObject , & stTranslationVector);

    p_stVariableForX -> csValue . Format ("%.6g" , stTranslationVector . xX);
    p_stVariableForY -> csValue . Format ("%.6g" , stTranslationVector . xY);
    p_stVariableForZ -> csValue . Format ("%.6g" , stTranslationVector . xZ);

    return TUT_C_iNoError;
}

//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_iExecute3dClic3dView
// Execute a "clic 3d view" tutorial script action
// Return 0 if no error
//-----------------------------------------------------------------------------
int TUT_CTutorialManager::m_fn_iExecute3dClic3dView (char * _szParameter)
{
    // Get parameter : 3d object name or three coordinates
    int    iNumberOfParameter;
    char * szParameter1 , * szParameter2 , * szParameter3;

    int    iReturnValue = m_fn_iGetParameters (_szParameter , 1 , 3 , & iNumberOfParameter ,
                                               & szParameter1 , & szParameter2 , & szParameter3);
    if (iReturnValue != TUT_C_iNoError)  return iReturnValue;
    if (iNumberOfParameter == 2)  return TUT_C_iError_ParameterRequired;  // Only 1 or 3 parameters

    MTH3D_tdstVector  stTranslationVector;
    CPA_SuperObject * pSuperObject = NULL;
    double dX , dY , dZ;
    dX = dY = dZ = 0.0;

    if (iNumberOfParameter == 1)    // One parameter : this is the name of the 3d object
    {
        // Get the super object
        pSuperObject = fnp_oFindSuperObjectByName (szParameter1);
        if (! pSuperObject)  return TUT_C_iError_Unknown3dObject;

        // Get the position of the super object
        fn_bGetPointOfSuperObject (pSuperObject , & stTranslationVector);
    }
    else                            // Three parameters : this is the three coordinates
    {
        dX = m_fn_dConvertToDouble (szParameter1);
        dY = m_fn_dConvertToDouble (szParameter2);
        dZ = m_fn_dConvertToDouble (szParameter3);

        if (dX == TUT_C_dErrorNotANumber || dY == TUT_C_dErrorNotANumber || dZ == TUT_C_dErrorNotANumber)
            return TUT_C_iError_InvalidNumber;

        MTH3D_M_vSetVectorElements (& stTranslationVector , MTH_M_xDoubleToReal (dX) , MTH_M_xDoubleToReal (dY) , MTH_M_xDoubleToReal (dZ));
    }

    // Convert this 3D position into a 2D position
    GLI_tdst2DVertex st2DPosition;
    DEV_ViewPort3D * pViewport3d = TUT_M_GetCurrentViewPort ();
    pViewport3d -> Convert3dTo2d (& st2DPosition , & stTranslationVector);
    CPoint Pos;
    Pos . x = (long) st2DPosition . xX;
    Pos . y = (long) st2DPosition . xY;
    if (GLI_lWhatIsGLI () == GLI_C_VersionGlide)  pViewport3d -> VoodooToClient (Pos);

    // Check if this 2D position is inside the 3D view
    CRect stViewport3dRect;
    pViewport3d -> GetClientRect (& stViewport3dRect);
    if (! stViewport3dRect . PtInRect (Pos))
    {
        // If not, zoom the camera to the object or the point and refresh the display
        if (iNumberOfParameter == 1)
        {
            pViewport3d -> GetCameraInterface () -> ZoomOnTarget (pViewport3d -> GetCamera () , pSuperObject);
        }
        else
        {
            CPA_CameraCoords oCameraCoords (WorldCoordinates , (float) dX , (float) dY , (float) dZ);
            pViewport3d -> GetCameraInterface () -> SetTargetPoint (pViewport3d -> GetCamera () , & oCameraCoords);
            pViewport3d -> GetCameraInterface () -> SetTargetType  (pViewport3d -> GetCamera () , tPoint);
            pViewport3d -> GetCameraInterface () -> Update (pViewport3d -> GetCamera ());
            pViewport3d -> GetCameraInterface () -> SetTargetType (pViewport3d -> GetCamera () , tNone);
        }
        pViewport3d -> GetCameraInterface () -> GetInterface () -> fn_vUpdateAll (E_mc_JustDraw);

        // And compute the new 3D position
        pViewport3d -> Convert3dTo2d (& st2DPosition , & stTranslationVector);
        Pos . x = (long) st2DPosition . xX;
        Pos . y = (long) st2DPosition . xY;
        if (GLI_lWhatIsGLI () == GLI_C_VersionGlide)  pViewport3d -> VoodooToClient (Pos);
    }

    CPoint ScreenPos = Pos;
    pViewport3d -> ClientToScreen (& ScreenPos);
    m_fn_vMoveMouseCursor (ScreenPos , pViewport3d -> m_hWnd);

    LPARAM lParam = MAKELPARAM (Pos . x , Pos . y);
	WPARAM wParam = (m_bUseShift ? MK_SHIFT : 0) | (m_bUseControl ? MK_CONTROL : 0);

    if (m_bUseDrop)
    {
        //Sleep (0);  // To be sure the last OnMouseMove message has been treated when making a drag and drop
		//m_fn_vSleep(10);
		Sleep(10);
    }
    else
    {
        if (m_bUseRightButton)  pViewport3d -> PostMessage (WM_RBUTTONDOWN , wParam + MK_RBUTTON , lParam);
                          else  pViewport3d -> PostMessage (WM_LBUTTONDOWN , wParam + MK_LBUTTON , lParam);
		m_fn_vSleep (60);
    }

    if (m_bUseRightButton)  pViewport3d -> PostMessage (WM_RBUTTONUP , wParam , lParam);
                      else  pViewport3d -> PostMessage (WM_LBUTTONUP , wParam , lParam);
	m_fn_vSleep (60);

    if (m_bUseDoubleClic)
    {
        if (m_bUseRightButton)
        {
            pViewport3d -> PostMessage (WM_RBUTTONDBLCLK , wParam + MK_RBUTTON , lParam);
			m_fn_vSleep (60);
            pViewport3d -> PostMessage (WM_RBUTTONUP     , wParam , lParam);
			m_fn_vSleep (60);
        }
        else
        {
            pViewport3d -> PostMessage (WM_LBUTTONDBLCLK , wParam + MK_LBUTTON , lParam);
			m_fn_vSleep (60);
            pViewport3d -> PostMessage (WM_LBUTTONUP     , wParam , lParam);
			m_fn_vSleep (60);
        }
    }

    return TUT_C_iNoError;
}

//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_iExecute3dIsProtected
// Execute a "is protected" tutorial script action
// Return 0 if no error
//-----------------------------------------------------------------------------
int TUT_CTutorialManager::m_fn_iExecute3dIsProtected (char * _szParameter)
{
    // Get parameters : 3d object name and variable name
    int    iNumberOfParameter;
    char * sz3dObjectName , * szVariableName;

    int    iReturnValue = m_fn_iGetParameters (_szParameter , 2 , 2 , & iNumberOfParameter , & sz3dObjectName , & szVariableName);
    if (iReturnValue != TUT_C_iNoError)  return iReturnValue;

    // Search the super object
    CPA_SuperObject * pSuperObject = fnp_oFindSuperObjectByName (sz3dObjectName);
    if (! pSuperObject)  return TUT_C_iError_Unknown3dObject;

    // Find the variable
    TUT_tdstVariableDefinition * p_stVariableDef = m_fnp_stFindVariable (szVariableName);
    if (p_stVariableDef == NULL)  return TUT_C_iError_UnknownVariable;

    p_stVariableDef -> csValue = pSuperObject -> fn_bIsEditProtected () ? TUT_C_szTrue : TUT_C_szFalse;

    return TUT_C_iNoError;
}

//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_iExecute3dMove3d
// Execute a "move 3D" tutorial script action
// Return 0 if no error
//-----------------------------------------------------------------------------
int TUT_CTutorialManager::m_fn_iExecute3dMove3d  (char * _szParameter)
{
    // Get parameters : 3d object name,  (X,Y) translation coordinates
    int    iNumberOfParameter;
    char * sz3dObjectName , * szDeltaX , * szDeltaY;

    int    iReturnValue = m_fn_iGetParameters (_szParameter , 3 , 3 , & iNumberOfParameter , & sz3dObjectName ,
                                               & szDeltaX , & szDeltaY);
    if (iReturnValue != TUT_C_iNoError)  return iReturnValue;

    // Search the super object
    CPA_SuperObject * pSuperObject = fnp_oFindSuperObjectByName (sz3dObjectName);
    if (! pSuperObject)  return TUT_C_iError_Unknown3dObject;

    // Get the coordinates
    double dDeltaX = m_fn_dConvertToDouble (szDeltaX);
    double dDeltaY = m_fn_dConvertToDouble (szDeltaY);
    if (dDeltaX == TUT_C_dErrorNotANumber || dDeltaY == TUT_C_dErrorNotANumber)  return TUT_C_iError_InvalidNumber;

    // Get the position of the super object
    MTH3D_tdstVector stTranslationVector;
    fn_bGetPointOfSuperObject (pSuperObject , & stTranslationVector);

    // Convert this 3D position into a 2D position
    GLI_tdst2DVertex st2DPosition;
    DEV_ViewPort3D * pViewport3d = TUT_M_GetCurrentViewPort ();
    pViewport3d -> Convert3dTo2d (& st2DPosition , & stTranslationVector);
    CPoint Pos;

    Pos . x = (long) st2DPosition . xX;
    Pos . y = (long) st2DPosition . xY;
    if (GLI_lWhatIsGLI () == GLI_C_VersionGlide)  pViewport3d -> VoodooToClient (Pos);

    // Send a LBUTTONDOWN message
	WPARAM wParam    = (m_bUseShift ? MK_SHIFT : 0) | (m_bUseControl ? MK_CONTROL : 0);
    CPoint ScreenPos = Pos;
    pViewport3d -> ClientToScreen (& ScreenPos);
    m_fn_vMoveMouseCursor (ScreenPos , pViewport3d -> m_hWnd);
    pViewport3d -> SendMessage (WM_LBUTTONDOWN , wParam + MK_LBUTTON , MAKELPARAM (Pos . x , Pos . y));

    // Compute the final position
    CPA_SuperObject *       pCameraSuperObject = pViewport3d -> GetCameraSO ();
    POS_tdxHandleToPosition hGlobalMatrix      = HIE_fn_hGetSuperObjectGlobalMatrix (pCameraSuperObject -> GetStruct ());
    MTH3D_tdstVector        stVectorX , stVectorY , stVectorZ;
    POS_fn_vGetRotationMatrix (hGlobalMatrix , & stVectorX , & stVectorY , & stVectorZ);

    MTH3D_M_vMulScalarVector (& stVectorX , MTH_M_xDoubleToReal (- dDeltaX) , & stVectorX);
    MTH3D_M_vMulScalarVector (& stVectorY , MTH_M_xDoubleToReal (- dDeltaY) , & stVectorY);

    MTH3D_tdstVector        stDelta;
    MTH3D_M_vAddVector       (& stDelta , & stVectorX , & stVectorY);
    MTH3D_M_vAddVector       (& stTranslationVector , & stDelta , & stTranslationVector);

    // Compute the final 3D position into a 2D position
    pViewport3d -> Convert3dTo2d (& st2DPosition , & stTranslationVector);
    Pos . x = (long) st2DPosition . xX;
    Pos . y = (long) st2DPosition . xY;
    if (GLI_lWhatIsGLI () == GLI_C_VersionGlide)  pViewport3d -> VoodooToClient (Pos);

    // Send a LBUTTONUP message
    ScreenPos = Pos;
    pViewport3d -> ClientToScreen (& ScreenPos);
    m_fn_vMoveMouseCursor (ScreenPos , pViewport3d -> m_hWnd);
    pViewport3d -> SendMessage (WM_LBUTTONUP , wParam , MAKELPARAM (Pos . x , Pos . y));

    return TUT_C_iNoError;
}

//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_iExecute3dSelectModel
// Execute a "select model" tutorial script action
// Return 0 if no error
//-----------------------------------------------------------------------------
int TUT_CTutorialManager::m_fn_iExecute3dSelectModel (char * _szParameter)
{
    // Get parameter : model name
    int    iNumberOfParameter;
    char * szModelName;

    int    iReturnValue = m_fn_iGetParameters (_szParameter , 1 , 1 , & iNumberOfParameter , & szModelName);
    if (iReturnValue != TUT_C_iNoError)  return iReturnValue;

	C3ListView *p_oListView	= gs_fn_p_oGetModelView ();
	ASSERT( p_oListView );

    // Find the model into the view
    long lIndex = p_oListView -> m_fn_lFindName (-1 , szModelName , p_oListView -> m_fn_cGetOrder ());
    if (lIndex == TSL_cItemNotFound)  return TUT_C_iError_ModelNotFound;

    // To be sure the model will be visible
    p_oListView -> m_vScrollToMakeItemVisible ((short) lIndex);

    // Get the position of the model
    CRect stRect;
    p_oListView -> m_fn_vGetCaseRect ((short) lIndex , & stRect);
    POINT stCenter = stRect . CenterPoint ();

    // Move the mouse cursor to the model
    p_oListView -> ClientToScreen (& stRect);
    m_fn_vMoveMouseCursor (stRect . CenterPoint ());

	WPARAM wParam = (m_bUseShift ? MK_SHIFT : 0) | (m_bUseControl ? MK_CONTROL : 0);
    // Clic to select the model
    PostMessage (p_oListView -> m_hWnd , WM_LBUTTONDOWN , wParam + MK_LBUTTON , MAKELPARAM (stCenter . x , stCenter . y));
    // Release the button if this is not a drag & drop
    if (! m_bUseDrag)
        PostMessage (p_oListView -> m_hWnd , WM_LBUTTONUP , wParam , MAKELPARAM (stCenter . x , stCenter . y));

    return TUT_C_iNoError;
}

//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_iExecute3dGetModel
// Execute a "get model" tutorial script action
// Return 0 if no error
//-----------------------------------------------------------------------------
int TUT_CTutorialManager::m_fn_iExecute3dGetModel (char * _szParameter)
{
    // Get parameter : variable name
    int    iNumberOfParameter;
    char * szVariableName;

    int    iReturnValue = m_fn_iGetParameters (_szParameter , 1 , 1 , & iNumberOfParameter , & szVariableName);
    if (iReturnValue != TUT_C_iNoError)  return iReturnValue;

	C3ListView *p_oListView	= gs_fn_p_oGetModelView ();
	ASSERT( p_oListView );

    // Find the variable
    TUT_tdstVariableDefinition * p_stVariableDef = m_fnp_stFindVariable (szVariableName);
    if (p_stVariableDef == NULL)  return TUT_C_iError_UnknownVariable;

    // Get the selected item
    long lIndex = p_oListView -> m_fn_lGetSelectedItem (p_oListView -> m_fn_cGetOrder ());

    // Get the name of the item and fill the variable
    if (lIndex == TSL_cItemNotFound)  p_stVariableDef -> csValue = "";
                                else  p_stVariableDef -> csValue = p_oListView -> m_fn_csGetName (lIndex , p_oListView -> m_fn_cGetOrder ());

    return TUT_C_iNoError;
}

//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_iExecute3dGetNumberOfModels
// Execute a "get number of models" tutorial script action
// Return 0 if no error
//-----------------------------------------------------------------------------
int TUT_CTutorialManager::m_fn_iExecute3dGetNumberOfModels (char * _szParameter)
{
    // Get parameter : variable name
    int    iNumberOfParameter;
    char * szVariableName;

    int    iReturnValue = m_fn_iGetParameters (_szParameter , 1 , 1 , & iNumberOfParameter , & szVariableName);
    if (iReturnValue != TUT_C_iNoError)  return iReturnValue;

	C3ListView *p_oListView	= gs_fn_p_oGetModelView ();
	ASSERT( p_oListView );

    // Get the number of models
    long lNumberOfModel = p_oListView -> m_fn_lGetCount ();

    // Find the variable and fill it
    TUT_tdstVariableDefinition * p_stVariableDef = m_fnp_stFindVariable (szVariableName);
    if (p_stVariableDef == NULL)  return TUT_C_iError_UnknownVariable;

    m_fn_vSetValueToVariable (p_stVariableDef , lNumberOfModel);

    return TUT_C_iNoError;
}

//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_iExecute3dIsAvailable
// Execute a "is available" tutorial script action
// Return 0 if no error
//-----------------------------------------------------------------------------
int TUT_CTutorialManager::m_fn_iExecute3dIsAvailable (char * _szParameter)
{
    // Get parameters : object name, type name and variable name
    int    iNumberOfParameter;
    char * szObjectName , * szTypeName , * szVariableName;

    int    iReturnValue = m_fn_iGetParameters (_szParameter , 3 , 3 , & iNumberOfParameter ,
                                               & szObjectName , & szTypeName , & szVariableName);
    if (iReturnValue != TUT_C_iNoError)  return iReturnValue;

    TUT_tdstVariableDefinition * p_stVariableDef = m_fnp_stFindVariable (szVariableName);
    if (p_stVariableDef == NULL)  return TUT_C_iError_UnknownVariable;

    CPA_BaseObject * pObject = M_GetMainApp () -> fn_p_oGetMainWorld () ->
                               fn_p_oFindObject (szObjectName , szTypeName , NO_CRITERIA , E_rc_AllObjects);
    if (! pObject)  return TUT_C_iError_UnknownObject;

    p_stVariableDef -> csValue = pObject -> fn_bIsAvailable () ? TUT_C_szTrue : TUT_C_szFalse;
    return TUT_C_iNoError;
}

//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_iExecute3dGetPrefix
// Execute a "get prefix" tutorial script action
// Return 0 if no error
//-----------------------------------------------------------------------------
int TUT_CTutorialManager::m_fn_iExecute3dGetPrefix (char * _szParameter)
{
    // Get parameters : variable name
    int    iNumberOfParameter;
    char * szVariableName;

    int    iReturnValue = m_fn_iGetParameters (_szParameter , 1 , 1 , & iNumberOfParameter , & szVariableName);
    if (iReturnValue != TUT_C_iNoError)  return iReturnValue;

    TUT_tdstVariableDefinition * p_stVariableDef = m_fnp_stFindVariable (szVariableName);
    if (p_stVariableDef == NULL)  return TUT_C_iError_UnknownVariable;

    p_stVariableDef -> csValue = M_GetMainApp () -> GetInterface () -> GetUserPrefix ();
    return TUT_C_iNoError;
}

//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_iExecute3dIsExistingModel
// Execute a "Is Existing Model" tutorial script action
// Return 0 if no error
//-----------------------------------------------------------------------------
int TUT_CTutorialManager::m_fn_iExecute3dIsExistingModel (char * _szParameter)
{
    // Get parameters : variable name
    int    iNumberOfParameter;
    char * szModelName , * szVariableName;

    int    iReturnValue = m_fn_iGetParameters (_szParameter , 2 , 2 , & iNumberOfParameter , & szModelName , & szVariableName);
    if (iReturnValue != TUT_C_iNoError)  return iReturnValue;

	TUT_tdstVariableDefinition * p_stVariableDef = m_fnp_stFindVariable (szVariableName);
    if (p_stVariableDef == NULL)  return TUT_C_iError_UnknownVariable;

	C3ListView *p_oListView	= gs_fn_p_oGetModelView ();
	ASSERT( p_oListView );

    // Find the model into the view
    long lIndex = p_oListView -> m_fn_lFindName (-1 , szModelName , p_oListView -> m_fn_cGetOrder ());
	p_stVariableDef -> csValue = lIndex == TSL_cItemNotFound ? TUT_C_szFalse : TUT_C_szTrue;

    return TUT_C_iNoError;
}

//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_iExecute3dGetStatusBarText
// Execute a "Is Existing Model" tutorial script action
// Return 0 if no error
//-----------------------------------------------------------------------------
int TUT_CTutorialManager::m_fn_iExecute3dGetStatusBarText (char * _szParameter)
{
    // Get parameters : variable name
    int    iNumberOfParameter;
    char * szPaneNumber , * szVariableName;

    int    iReturnValue = m_fn_iGetParameters (_szParameter , 2 , 2 , & iNumberOfParameter , & szPaneNumber , & szVariableName);
    if (iReturnValue != TUT_C_iNoError)  return iReturnValue;

	TUT_tdstVariableDefinition * p_stVariableDef = m_fnp_stFindVariable (szVariableName);
    if (p_stVariableDef == NULL)  return TUT_C_iError_UnknownVariable;

	CStatusBar *p_oStatusBar = gs_fn_p_oGetStatusBar ();
	ASSERT( p_oStatusBar );

    CStatusBarCtrl &rStat = p_oStatusBar -> GetStatusBarCtrl ();

	char szText[512];
    int	 iPane = m_fn_iConvertToInt (szPaneNumber);
	int	 iType;

	rStat . GetText (szText , iPane , &iType);
	p_stVariableDef -> csValue = szText;

    return TUT_C_iNoError;
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_bIsModelView
// 
// 
//-----------------------------------------------------------------------------
BOOL TUT_CTutorialManager::m_fn_bIsModelView (HWND _hWnd)
{
	C3ListView		*p_oListView		= NULL;
	CPA_EditorBase	*p_oCurrentEditor	= TUT_M_GetCurrentEditor ();

	if( p_oCurrentEditor && p_oCurrentEditor -> GetCurrentEditorName() == C_szDLLMaterialName )
	{
		CSplitFrame	* p_oBottomFrame = (CSplitFrame*)g_oFrameGest . ma_p_oWinArray [2] [3];
		if (p_oBottomFrame)
		{
			p_oListView = (C3ListView*)p_oBottomFrame -> m_fn_p_oGetPane (1);
		}
	}
	else
	{
		// Get the model view
		FRMBase          * p_oModelFrame = g_oFrameGest . ma_p_oWinArray [2] [3];
		if (p_oModelFrame)
		{
			CPA_DialogInsert * p_oModelWnd   = (CPA_DialogInsert *) p_oModelFrame -> GetWindow (GW_CHILD);
			if (p_oModelWnd)
			{
				EDT_ModelView    * p_oModelView  = p_oModelWnd -> GetModelView ();
				if (p_oModelView)
					p_oListView = (C3ListView*) p_oModelView;
			}
		}
	}

	return (p_oListView && p_oListView -> m_hWnd == _hWnd);
}


//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_bLButtonDown3DViewProc
// 
// 
//-----------------------------------------------------------------------------
BOOL TUT_CTutorialManager::m_fn_bLButtonDown3DViewProc(int iHookType, HWND hwnd, UINT uiMessage, WPARAM wParam, LPARAM lParam)
{
	CString						csText;
	CPoint						oPoint(LOWORD(lParam),HIWORD(lParam));
	DEV_ViewPort3D				* pViewport3d = TUT_M_GetCurrentViewPort ();
	tdstMousePos				stMousePos;
	HIE_tdxHandleToSuperObject  hSupObject;
	HIE_aDEF_stTabOfPickInfo	a_stPickInfo;
	ACP_tdxIndex				xNbPicked;

	pViewport3d -> PointToMousePos (oPoint, &stMousePos);

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

		if (xNbPicked > 0)
		{
			m_lDragDrop = 1;
			m_eDragDropType = TUT_eMove3d;
			MTH3D_M_vCopyVector (&g_stInitialPoint , &((((a_stPickInfo[0]).stPickedObject).aDEF_stDataOfElement[0]).stHit));
			return TRUE;
		}
	}
	return FALSE;
}

//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_bLButtonUp3DViewProc
// 
// 
//-----------------------------------------------------------------------------
BOOL TUT_CTutorialManager::m_fn_bLButtonUp3DViewProc(int iHookType, HWND hwnd, UINT uiMessage, WPARAM wParam, LPARAM lParam)
{
	CString						csText;
	CPoint						oPoint(LOWORD(lParam),HIWORD(lParam));
	DEV_ViewPort3D				* pViewport3d = TUT_M_GetCurrentViewPort ();
	tdstMousePos				stMousePos;
	HIE_tdxHandleToSuperObject  hSupObject;
	HIE_aDEF_stTabOfPickInfo	a_stPickInfo;
	ACP_tdxIndex				xNbPicked;

	pViewport3d -> PointToMousePos (oPoint, &stMousePos);

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

		if (xNbPicked > 0)
		{
			switch (m_eDragDropType)
			{
			case TUT_eMove3d:
				{
					if (m_lDragDrop > 1 && !TUT_M_GetCurrentWorld () -> GetListSelected () -> IsEmpty ())
					{
						MTH3D_tdstVector		stDeplacement;
						CPA_SuperObject *       pCameraSuperObject = pViewport3d -> GetCameraSO ();
						POS_tdxHandleToPosition hGlobalMatrix      = HIE_fn_hGetSuperObjectGlobalMatrix (pCameraSuperObject -> GetStruct ());
						MTH3D_tdstVector        stVectorX , stVectorY , stVectorZ;
						MTH_tdxReal				xDeltaX , xDeltaY;
						CPA_SuperObject	*		p_oSuperObject = TUT_M_GetCurrentWorld () -> GetListSelected () -> GetTail ();
						CPA_BaseObject  *		pObject = p_oSuperObject -> GetObject ();

						POS_fn_vGetRotationMatrix (hGlobalMatrix , & stVectorX , & stVectorY , & stVectorZ);
						MTH3D_M_vSubVector (&stDeplacement , &((((a_stPickInfo[0]).stPickedObject).aDEF_stDataOfElement[0]).stHit) , &g_stInitialPoint);

						xDeltaX = MTH3D_M_xDotProductVector (&stDeplacement , &stVectorX);
						xDeltaY = MTH3D_M_xDotProductVector (&stDeplacement , &stVectorY);

						if (MTH_M_bIsNullWithEpsilon(xDeltaX,MTH_M_xDoubleToReal(0.01)) && MTH_M_bIsNullWithEpsilon(xDeltaY,MTH_M_xDoubleToReal(0.01)))
						{
							csText . Format ("%s(\"%s\")" , TUT_C_sz3DClic3dView , pObject -> fn_p_szGetName ());
						}
						else
						{
							csText . Format ("%s(\"%s\" , \"%.6f\" , \"%.6f\")" , TUT_C_sz3DMove3d , pObject -> fn_p_szGetName () , - xDeltaX , - xDeltaY);
						}
						m_fn_vAddCommand (csText);
						return TRUE;
					}
					else
					{
						if (!TUT_M_GetCurrentWorld () -> GetListSelected () -> IsEmpty ())
						{
							CPA_SuperObject *p_oSuperObject = TUT_M_GetCurrentWorld () -> GetListSelected () -> GetTail ();
							if (p_oSuperObject)
							{
								CPA_BaseObject  * pObject = p_oSuperObject -> GetObject ();
								if (pObject)
								{
									csText . Format ("%s(\"%s\")" , TUT_C_sz3DClic3dView , pObject -> fn_p_szGetName ());
									m_fn_vAddCommand (csText);
									return TRUE;
								}
							}
						}
						else
						{
							MTH3D_tdstVector *p_stHitPoint = &((((a_stPickInfo[0]).stPickedObject).aDEF_stDataOfElement[0]).stHit);

							csText . Format ("%s(\"%.6f\",\"%.6f\",\"%.6f\")" , TUT_C_sz3DClic3dView , p_stHitPoint->xX ,
																									   p_stHitPoint->xY ,
																									   p_stHitPoint->xZ);
							m_fn_vAddCommand (csText);
							return TRUE;
						}
					}
				}
				break;
			} // switch (m_eDragDropType)
		}
	}
	return FALSE;
}

//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_bLButtonDownModelViewProc
// 
// 
//-----------------------------------------------------------------------------
BOOL TUT_CTutorialManager::m_fn_bLButtonDownModelViewProc(int iHookType, HWND hwnd, UINT uiMessage, WPARAM wParam, LPARAM lParam)
{
	C3ListView *p_oListView	= gs_fn_p_oGetModelView ();

	ASSERT(p_oListView);

    // Get the selected item
    long lIndex = p_oListView -> m_fn_lGetSelectedItem (p_oListView -> m_fn_cGetOrder ());

    // Get the name of the item and fill the variable
    if (lIndex == TSL_cItemNotFound)
	{
		m_csDragDropElement = "";
	}
    else
	{
		m_csDragDropElement = p_oListView -> m_fn_csGetName (lIndex , p_oListView -> m_fn_cGetOrder ());
		m_lDragDrop = 1;
		m_eDragDropType = TUT_eSelectModel;
		return TRUE;
	}

	return FALSE;
}

//-----------------------------------------------------------------------------
// class TUT_CTutorialManager - m_fn_bLButtonUpModelViewProc
// 
// 
//-----------------------------------------------------------------------------
BOOL TUT_CTutorialManager::m_fn_bLButtonUpModelViewProc(int iHookType, HWND hwnd, UINT uiMessage, WPARAM wParam, LPARAM lParam)
{
	CString						csText;
	CPoint						oPoint(LOWORD(lParam),HIWORD(lParam));
	DEV_ViewPort3D				* pViewport3d = TUT_M_GetCurrentViewPort ();
	tdstMousePos				stMousePos;
	HIE_tdxHandleToSuperObject  hSupObject;
	HIE_aDEF_stTabOfPickInfo	a_stPickInfo;
	ACP_tdxIndex				xNbPicked;

	pViewport3d -> PointToMousePos (oPoint, &stMousePos);

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

		if (xNbPicked > 0)
		{
			switch (m_eDragDropType)
			{
			case TUT_eSelectModel:
				{
					if (m_lDragDrop > 1)
					{
						MTH3D_tdstVector *p_stHitPoint = &((((a_stPickInfo[0]).stPickedObject).aDEF_stDataOfElement[0]).stHit);

						m_fn_vRemoveToPause ();

						// drag
						csText . Format ("%s()" , TUT_C_szDrag);
						m_fn_vAddCommand (csText);
						// select model
						csText . Format ("%s(\"%s\")" , TUT_C_sz3DSelectModel , m_csDragDropElement);
						m_fn_vAddCommand (csText);
						// drop
						csText . Format ("%s()" , TUT_C_szDrop);
						m_fn_vAddCommand (csText);
						// clic3dView
						csText . Format ("%s(\"%.6f\",\"%.6f\",\"%.6f\")" , TUT_C_sz3DClic3dView , p_stHitPoint->xX ,
																								   p_stHitPoint->xY ,
																								   p_stHitPoint->xZ);
						m_fn_vAddCommand (csText);
						return TRUE;
					}
				}
				break;
			} // switch (m_eDragDropType)
		}
	}
	return FALSE;
}

//-----------------------------------------------------------------------------
#endif  // ifdef TUT_3D
