/*
 =======================================================================================
  Name        : podialog.cpp
 
  Author      : vincent lhullier            Date :26/08/97
 
  Description : implementation file for PO editor dialog boxes
 =======================================================================================
  Modification -> Author :                  Date :
  Description :
 =======================================================================================
 */

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#include "stdafx.h"
#include "ACP_Base.h"
#include "ITF.h"
#include "TUT.h"
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#define D_PhysiCol_Define
#include "incGAM.h"
//#define PO_FRIEND
#include "PO.h"
//#undef	PO_FRIEND
#undef  D_PhysiCol_Define
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#include "incOPD.h"
#include "podialog.h"
#include "x:\Cpa\Main\inc\_EditId.h"
#include "..\..\GLIGLOU\MULTIDRV\inc\VisuS_st.h"
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

/*
 =======================================================================================
 =======================================================================================
	CPOVseModif
 =======================================================================================
 =======================================================================================
 */

/*
 ----------------------------------------------------------------------------------------
  Description   : constructor
 ----------------------------------------------------------------------------------------
 */
CPOVseModif::CPOVseModif( EditorPO *_p_oPO, GEO_tdxHandleToVisualSet _hVSE, ACP_tdxIndex _xNbModifs ) : CPA_Modif( 0, "Vse treshold" )
{
	ACP_tdxIndex xIndex;

	m_p_oPO = _p_oPO;
	m_hVisualSet = _hVSE;
	m_xNbModifs = _xNbModifs;
	if (m_xNbModifs)
	{
		m_d_xIndex = (ACP_tdxIndex *) malloc ( m_xNbModifs * sizeof( ACP_tdxIndex ) );
		m_d_xDiff = (MTH_tdxReal *) malloc ( m_xNbModifs * sizeof( MTH_tdxReal ) );

		for (xIndex = 0; xIndex < m_xNbModifs; xIndex++ )
			m_d_xIndex[ xIndex ] = -1;
	}
}

/*
 ----------------------------------------------------------------------------------------
  Description   : destructor
 ----------------------------------------------------------------------------------------
 */
CPOVseModif::~CPOVseModif( void )
{
	if (m_xNbModifs)
	{
		free( m_d_xIndex );
		free( m_d_xDiff );
	}
}

/*
 ----------------------------------------------------------------------------------------
  Description   : Do the modif
 ----------------------------------------------------------------------------------------
 */
CPOVseModif::Do( void )
{
	ACP_tdxIndex			xModif;
	MTH_tdxReal				xTreshold;
	ACP_tdxHandleOfObject	xGeometric;

	for ( xModif = 0; xModif < m_xNbModifs; xModif++)
	{
		if (m_d_xIndex[ xModif ] != -1)
		{
			GLI_vGetVisualSetLOD( m_hVisualSet, m_d_xIndex[ xModif ], &xTreshold, &xGeometric );
			xTreshold += m_d_xDiff[ xModif ];
			GLI_vSetVisualSetLOD( m_hVisualSet, m_d_xIndex[ xModif ], xTreshold, xGeometric );
		}
	}
	if (m_p_oPO->fn_p_oGetVSESection())
		m_p_oPO->fn_p_oGetVSESection()->fn_vWriteSection();
	(((DEV_MultiDevice*)g_oFrameGest.ma_p_oWinArray[2][2]->GetActiveView())->DrawObject());
	return TRUE;
}

/*
 ----------------------------------------------------------------------------------------
  Description   : UnDo the modif
 ----------------------------------------------------------------------------------------
 */
CPOVseModif::Undo( void )
{
	ACP_tdxIndex			xModif;
	MTH_tdxReal				xTreshold;
	ACP_tdxHandleOfObject	xGeometric;

	for ( xModif = 0; xModif < m_xNbModifs; xModif++)
	{
		if (m_d_xIndex[ xModif ] != -1)
		{
			GLI_vGetVisualSetLOD( m_hVisualSet, m_d_xIndex[ xModif ], &xTreshold, &xGeometric );
			xTreshold -= m_d_xDiff[ xModif ];
			GLI_vSetVisualSetLOD( m_hVisualSet, m_d_xIndex[ xModif ], xTreshold, xGeometric );
		}
	}
	return TRUE;
}


/*
 ----------------------------------------------------------------------------------------
  Description   : set modification for a given treshold
  _xLod               -> index of lod (treshold)
  _xDiff              -> difference between new and old treshold
 ----------------------------------------------------------------------------------------
 */
void CPOVseModif::m_fn_vSetDiff( ACP_tdxIndex _xLod, MTH_tdxReal _xDiff )
{
	ACP_tdxIndex	xModif;

	for (xModif = 0; xModif < m_xNbModifs; xModif++)
		if (m_d_xIndex[ xModif ] == -1)
			break;
	
	if (xModif == m_xNbModifs)
		return;

	m_d_xIndex[ xModif ] = _xLod;
	m_d_xDiff[ xModif ] = _xDiff;
}

/*
 =======================================================================================
 =======================================================================================
	CPODlgVse
 =======================================================================================
 =======================================================================================
 */
IMPLEMENT_DYNCREATE(CPODlgVse, CFormView)


/*
 ----------------------------------------------------------------------------------------
  Description   : constructor
 ----------------------------------------------------------------------------------------
 */
CPODlgVse::CPODlgVse(): CFormView(CPODlgVse::IDD)
{
	//{{AFX_DATA_INIT(CPODlgVse)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	m_p_oParentDLL = NULL;
	m_xSwapLod = -1;
}


/*
 ----------------------------------------------------------------------------------------
  Description   : destructor
 ----------------------------------------------------------------------------------------
 */
CPODlgVse::~CPODlgVse()
{
}


/*
 ----------------------------------------------------------------------------------------
  Description   : Message Map
 ----------------------------------------------------------------------------------------
 */
BEGIN_MESSAGE_MAP(CPODlgVse, CFormView)
	//{{AFX_MSG_MAP(CPODlgVse)
	ON_WM_DRAWITEM()
	ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_CURRENTLOD, OnDeltaposSpinCurrentlod)
	ON_EN_KILLFOCUS(IDC_EDIT_CURRENTLOD, OnKillfocusEditCurrentlod)
	ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_FROM, OnDeltaposSpinFrom)
	ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_TO, OnDeltaposSpinTo)
	ON_EN_KILLFOCUS(IDC_EDIT_FROM, OnKillfocusEditFrom)
	ON_EN_KILLFOCUS(IDC_EDIT_TO, OnKillfocusEditTo)
	ON_BN_CLICKED(IDC_BUTTON_APPLY, OnButtonApply)
	ON_BN_CLICKED(IDC_BUTTON_TRESHOLD, OnButtonTreshold)
	ON_BN_DOUBLECLICKED(IDC_BUTTON_TRESHOLD, OnDoubleclickedButtonTreshold)
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/*
 ----------------------------------------------------------------------------------------
  Description   : Creation of FormView, register window and control
 ----------------------------------------------------------------------------------------
 */
BOOL CPODlgVse::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) 
{
	if ( !CFormView::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext) )
		return FALSE;

	TUT_M_vGetTutDll();
	TUT_M_vRegisterControl( GetSafeHwnd(),			"OPD_VisualSetEditionDialog",	TUT_e_Window ); 
	TUT_M_vRegisterControlID( IDC_BUTTON_APPLY,		"OPD_Vse_ApplyModifButton",		TUT_e_Button );
	TUT_M_vRegisterControlID( IDC_BUTTON_TRESHOLD,	"OPD_Vse_ThresholdBar",			TUT_e_Button );
	TUT_M_vRegisterControlID( IDC_EDIT_CURRENTLOD,	"OPD_Vse_CurrentLod",			TUT_e_TextEdit );
	TUT_M_vRegisterControlID( IDC_EDIT_FROM,		"OPD_Vse_EditThresholdStart",	TUT_e_TextEdit );
	TUT_M_vRegisterControlID( IDC_EDIT_NBLODS,		"OPD_Vse_NumberOfLods",			TUT_e_TextEdit );
	TUT_M_vRegisterControlID( IDC_EDIT_TO,			"OPD_Vse_EditThresholdEnd",		TUT_e_TextEdit );
	TUT_M_vRegisterControlID( IDC_SPIN_CURRENTLOD,	"OPD_Vse_SpinCurrentLod",		TUT_e_Spin );
	TUT_M_vRegisterControlID( IDC_SPIN_FROM,		"OPD_Vse_SpinThresholdStart",	TUT_e_Spin );
	TUT_M_vRegisterControlID( IDC_SPIN_TO,			"OPD_Vse_SpinThresholdEnd",		TUT_e_Spin );
	return TRUE;
}

/*
 ----------------------------------------------------------------------------------------
  Description   : Unregister control from TUT
 ----------------------------------------------------------------------------------------
 */
void CPODlgVse::OnDestroy() 
{
	TUT_M_vGetTutDll();
	TUT_M_vUnregisterControl( GetSafeHwnd() ); 
	TUT_M_vUnregisterControlID( IDC_BUTTON_APPLY );
	TUT_M_vUnregisterControlID( IDC_BUTTON_TRESHOLD );
	TUT_M_vUnregisterControlID( IDC_EDIT_CURRENTLOD );
	TUT_M_vUnregisterControlID( IDC_EDIT_FROM );
	TUT_M_vUnregisterControlID( IDC_EDIT_NBLODS );
	TUT_M_vUnregisterControlID( IDC_EDIT_TO );
	TUT_M_vUnregisterControlID( IDC_SPIN_CURRENTLOD );
	TUT_M_vUnregisterControlID( IDC_SPIN_FROM );
	TUT_M_vUnregisterControlID( IDC_SPIN_TO );
	
	CFormView::OnDestroy();	
}

/*
 =======================================================================================
	CPODlgVse diagnostics
 =======================================================================================
 */
#ifdef _DEBUG
void CPODlgVse::AssertValid() const
{
	CFormView::AssertValid();
}

void CPODlgVse::Dump(CDumpContext& dc) const
{
	CFormView::Dump(dc);
}
#endif //_DEBUG

/*
 =======================================================================================
	Specific functions 
 =======================================================================================
 */

/*
 ----------------------------------------------------------------------------------------
  Description   : update info about a PO object
 ----------------------------------------------------------------------------------------
 */
void CPODlgVse::fn_vUpdateInfo(class EditorPO *_p_oPO)
{
	m_fn_vSwapLOD( 0, TRUE, TRUE );

	if ( (m_p_oPO = _p_oPO) != NULL)
	{
		PO_tdxHandleToPhysicalObject hPO;

		hPO = _p_oPO->GetStruct();
		if (hPO != NULL)
		{
			m_hVisualSet = PO_fn_hGetVisualSet( hPO );
			m_hCollSet = PO_fn_hGetCollideSet( hPO );
		}
		else
			m_p_oPO = NULL;
	}

	if (m_p_oPO == NULL)
	{
		m_hVisualSet = 0;
		m_hCollSet = 0;
	}

	m_fn_vInitVisualSetData( m_hVisualSet );
	m_fn_vShowCollideSet( m_hCollSet );
}


/*
 ----------------------------------------------------------------------------------------
  Description   : display info about the visual set
 ----------------------------------------------------------------------------------------
 */
void CPODlgVse::m_fn_vShowVisualSet( GEO_tdxHandleToVisualSet hVisualSet )
{
	BOOL bVisible = ( hVisualSet != 0 );
	char szNbLods[10];

	m_xCurrentLod = 0;

	GetDlgItem( IDC_BUTTON_TRESHOLD   )->ShowWindow( bVisible );
	GetDlgItem( IDC_STATIC_NBLODS     )->ShowWindow( bVisible );
	GetDlgItem( IDC_EDIT_NBLODS       )->ShowWindow( bVisible );
	GetDlgItem( IDC_STATIC_CURRENTLOD )->ShowWindow( bVisible );
	GetDlgItem( IDC_STATIC_CURLOD     )->ShowWindow( bVisible );
	GetDlgItem( IDC_EDIT_CURRENTLOD   )->ShowWindow( bVisible );
	((CEdit *) GetDlgItem( IDC_EDIT_CURRENTLOD ))->SetReadOnly( m_xNbLods <= 1 );
	GetDlgItem( IDC_SPIN_CURRENTLOD   )->ShowWindow( bVisible && (m_xNbLods > 1));
	GetDlgItem( IDC_STATIC_FROM       )->ShowWindow( bVisible );
	GetDlgItem( IDC_EDIT_FROM         )->ShowWindow( bVisible );
	GetDlgItem( IDC_SPIN_FROM         )->ShowWindow( bVisible );
	GetDlgItem( IDC_STATIC_TO         )->ShowWindow( bVisible );
	GetDlgItem( IDC_EDIT_TO           )->ShowWindow( bVisible );
	GetDlgItem( IDC_SPIN_TO           )->ShowWindow( bVisible );
	GetDlgItem( IDC_BUTTON_APPLY      )->ShowWindow( bVisible );

	if (!bVisible)
		return;

	GetDlgItem( IDC_EDIT_NBLODS )->SetWindowText( itoa( m_xNbLods, szNbLods, 10) );
	m_fn_vShowCurrentLod();
}

/*
 ----------------------------------------------------------------------------------------
  Description   : initialize data about visual set
 ----------------------------------------------------------------------------------------
 */
void CPODlgVse::m_fn_vInitVisualSetData( GEO_tdxHandleToVisualSet hVisualSet )
{
	if (hVisualSet == 0)
	{
		m_xCurrentLod = -1;
	}
	else
	{
		m_xNbLods = (ACP_tdxIndex) GLI_lGetVisualSetNumbertOfLOD( hVisualSet );
		for( m_xCurrentLod = 0; m_xCurrentLod < m_xNbLods; m_xCurrentLod ++ )
			GLI_vGetVisualSetLOD( hVisualSet, m_xCurrentLod, &m_a_xTresholds[m_xCurrentLod], &m_a_xGeometrics[m_xCurrentLod] );
		m_a_xTresholds[ 0 ] = 0;
		m_xCurrentLod = 0;
	}
	m_fn_vShowVisualSet( hVisualSet );
}



/*
 ----------------------------------------------------------------------------------------
  Description   : display info about current lod
 ----------------------------------------------------------------------------------------
 */
void CPODlgVse::m_fn_vShowCurrentLod( )
{
	char	szValue[10];

	GetDlgItem( IDC_SPIN_FROM)->ShowWindow( m_xCurrentLod != 0 );
	GetDlgItem( IDC_SPIN_TO)->ShowWindow( m_xCurrentLod != m_xNbLods - 1 );

	GetDlgItem( IDC_EDIT_CURRENTLOD )->SetWindowText( itoa( m_xCurrentLod, szValue, 10 ) );
	
	//GetDlgItem( IDC_EDIT_FROM )->SetWindowText( m_xCurrentLod == 0 ? "0" : ftoa ((int) m_a_xTresholds[m_xCurrentLod - 1], szValue, 10) );
	sprintf( szValue, "%g", (m_xCurrentLod == 0) ? 0 : m_a_xTresholds[m_xCurrentLod] );
	GetDlgItem( IDC_EDIT_FROM )->SetWindowText( szValue );
	((CEdit *) GetDlgItem( IDC_EDIT_FROM ))->SetReadOnly( m_xCurrentLod == 0 );
	//GetDlgItem( IDC_EDIT_TO )->SetWindowText( (m_xCurrentLod + 1 == m_xNbLods) ? "infini" : itoa( (int) m_a_xTresholds[m_xCurrentLod], szValue, 10) );
	if (m_xCurrentLod + 1 == m_xNbLods )
		strcpy( szValue, "infini");
	else
		sprintf( szValue, "%g", m_a_xTresholds[ m_xCurrentLod + 1] );
	GetDlgItem( IDC_EDIT_TO )->SetWindowText( szValue );
	((CEdit *) GetDlgItem( IDC_EDIT_TO ))->SetReadOnly( m_xCurrentLod+1 == m_xNbLods );

	GetDlgItem( IDC_BUTTON_TRESHOLD )->Invalidate();
}

/*
 ----------------------------------------------------------------------------------------
  Description   : display info about collide set
 ----------------------------------------------------------------------------------------
 */
void CPODlgVse::m_fn_vShowCollideSet( PCS_tdxHandleToPhysicalCollSet hCollSet )
{
}


/*
 ----------------------------------------------------------------------------------------
  Description   : change value of a treshold
  cIndex              -> index of lod (and treshold)
  xValue              -> new treshold value
 ----------------------------------------------------------------------------------------
 */
void CPODlgVse::m_fn_vChangeTreshold( ACP_tdxIndex _xIndex, MTH_tdxReal _xValue)
{
	MTH_tdxReal xMin, xMax;

	if ( _xIndex == 0 )
		_xValue = 0;
	else
	{
		xMin = m_a_xTresholds[ _xIndex - 1 ];
		xMax = (_xIndex == m_xNbLods - 1) ? -1 : m_a_xTresholds[ _xIndex + 1];
	
		if (_xValue < xMin)
			_xValue = xMin;
		else if ( (xMax != -1) && (_xValue > xMax) )
			_xValue = xMax;
	}
	m_a_xTresholds[ _xIndex ] = _xValue;
	m_fn_vShowCurrentLod();
}

/*
 ----------------------------------------------------------------------------------------
  Description   : Get index of clicked lod in sheme drawn in IDC_BUTTON_TRESHOLD button
 ----------------------------------------------------------------------------------------
 */
ACP_tdxIndex CPODlgVse::m_fn_xGetClickedLodIndex( void ) 
{
	CButton			*p_oBt = (CButton *) GetDlgItem( IDC_BUTTON_TRESHOLD );
	POINT			stPoint;
	RECT			stRect;
	long			lHeight, lLodHeight, lY;
	ACP_tdxIndex	xLod = -1;
	
	GetCursorPos( &stPoint );
	p_oBt->ScreenToClient( &stPoint );

	if ( (stPoint.x >= 5) && (stPoint.x <= 12) )
	{
		p_oBt->GetClientRect( &stRect );
		lHeight = stRect.bottom - stRect.top;
		lLodHeight = (lHeight - 9) / m_xNbLods;
		lY = ( lHeight - (lLodHeight * m_xNbLods) ) / 2;
		while (lY < stPoint.y)
		{
			if (++xLod == m_xNbLods)
			{
				xLod = -1;
				break;
			}
			lY += lLodHeight;
		}
	}
	return xLod;
}


/*
 ----------------------------------------------------------------------------------------
  Description   : swap/restore swap of LOD to force drawing of a given LOD
  _xLod               -> index of lod to force
  _bRestore           -> TRUE to restore initial Visual Set
  _bRedraw			  -> TRUE if world must be redrawn
 ----------------------------------------------------------------------------------------
 */
void CPODlgVse::m_fn_vSwapLOD( ACP_tdxIndex _xLod, BOOL _bRestore, BOOL _bRedraw )
{
	ACP_tdxHandleOfObject	xGeometric0, xGeometric;
	MTH_tdxReal				xTreshold0, xTreshold;

	if (_bRestore)
	{
		if (m_xSwapLod != -1)
		{
			((struct GEO_tdstVisualSet_ *) m_hVisualSet)->xNbLodDefinitions = m_xNbLods;
			GLI_vGetVisualSetLOD( m_hVisualSet, 0, &xTreshold0, &xGeometric0 );
			GLI_vGetVisualSetLOD( m_hVisualSet, m_xSwapLod, &xTreshold, &xGeometric );
			GLI_vSetVisualSetLOD( m_hVisualSet, m_xSwapLod, xTreshold, xGeometric0 );
			GLI_vSetVisualSetLOD( m_hVisualSet, 0, xTreshold0, xGeometric );
			m_xSwapLod = -1;
		}
	}
	else
	{
		if (m_xSwapLod != -1)
			m_fn_vSwapLOD( 0, TRUE, FALSE );

		GLI_vGetVisualSetLOD( m_hVisualSet, 0, &xTreshold0, &xGeometric0 );
		GLI_vGetVisualSetLOD( m_hVisualSet, _xLod, &xTreshold, &xGeometric );
		GLI_vSetVisualSetLOD( m_hVisualSet, _xLod, xTreshold, xGeometric0 );
		GLI_vSetVisualSetLOD( m_hVisualSet, 0, xTreshold0, xGeometric );
		((GEO_tdstVisualSet *) m_hVisualSet)->xNbLodDefinitions = 1;
		m_xSwapLod = _xLod;
	}

	if (_bRedraw)
		(((DEV_MultiDevice*)g_oFrameGest.ma_p_oWinArray[2][2]->GetActiveView())->DrawObject());
}


/*
 =======================================================================================
	MESSAGE HANDLER 
 =======================================================================================
 */


/*
 ----------------------------------------------------------------------------------------
  Description   : WM_DRAWITEM
 ----------------------------------------------------------------------------------------
 */
void CPODlgVse::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDIS) 
{
	if (nIDCtl == IDC_BUTTON_TRESHOLD)
	{
		if (m_hVisualSet != 0)
		{
			// draw treshold bar
			RECT			rcLod;
			RECT			rcTreshold;
			long			lHeight;
			long			lLodHeight;
			long			lCurrentY;
			ACP_tdxIndex	xLod;
			char			szValue[10];
			
			CBitmap			oInfini;
			CBrush			oWhiteBrush(RGB(255,255,255));
			CBrush			oGrayBrush(RGB(128,128,128));
			CBrush			oBlackBrush(RGB(0,0,0));
			CPen			oRedPen( PS_SOLID, 1, RGB(255,0,0));
			CPen			oBlackPen( PS_SOLID, 1, RGB(0,0,0));
			CPen			oWhitePen( PS_SOLID, 1, RGB(255,255,255));
			CDC				*pDC = CDC::FromHandle( lpDIS->hDC );

			lHeight = lpDIS->rcItem.bottom - lpDIS->rcItem.top;
			lLodHeight = (lHeight - 9) / m_xNbLods;
			lCurrentY = lpDIS->rcItem.top + (( lHeight - (lLodHeight * m_xNbLods) ) / 2);

			rcLod.left = lpDIS->rcItem.left + 5;
			rcLod.right = rcLod.left + 8;

			rcTreshold.left = rcLod.right + 2;
			rcTreshold.right = lpDIS->rcItem.right - 5;

			for ( xLod = 0; xLod < m_xNbLods; xLod ++)
			{
				rcLod.top = lCurrentY;
				rcLod.bottom = rcLod.top + lLodHeight - 1;

				rcTreshold.top = lCurrentY - 5;
				rcTreshold.bottom = rcTreshold.top + 12;
				//itoa( xLod == 0 ? 0 : (int) m_a_xTresholds[xLod - 1], szValue, 10);
				sprintf( szValue, "%g", /*(xLod == 0) ? 0 : */m_a_xTresholds[xLod] );

				pDC->SelectObject( (xLod == m_xCurrentLod)?oRedPen:(xLod & 1)?oBlackPen:oWhitePen );
				pDC->SelectObject( (xLod == m_xSwapLod) ? oGrayBrush : ((xLod & 1) ? oBlackBrush : oWhiteBrush) );

				pDC->Rectangle( &rcLod );
				pDC->DrawText( szValue, strlen( szValue ), &rcTreshold, DT_VCENTER | DT_LEFT );

				lCurrentY += lLodHeight;
			}

			oInfini.LoadBitmap( IDB_BITMAP_INFINI );
			pDC->DrawState( CPoint( rcTreshold.left, lCurrentY - 4), CSize(22,8) , &oInfini, DST_BITMAP|DSS_MONO, &oBlackBrush );
			
			oInfini.DeleteObject();
			oWhiteBrush.DeleteObject();
			oBlackBrush.DeleteObject();
			oWhitePen.DeleteObject();
			oBlackPen.DeleteObject();
			oRedPen.DeleteObject();
		}
	}
	CFormView::OnDrawItem(nIDCtl, lpDIS);
}

/*
 ----------------------------------------------------------------------------------------
  Description   : UDN_DELTAPOS on IDC_SPIN_CURRENTLOD
 ----------------------------------------------------------------------------------------
 */
void CPODlgVse::OnDeltaposSpinCurrentlod(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
	
	if ( pNMUpDown->iDelta < 0)
		if (m_xCurrentLod == m_xNbLods - 1)
			m_xCurrentLod = 0;
		else
			m_xCurrentLod++;
	else
		if (m_xCurrentLod == 0)
			m_xCurrentLod = m_xNbLods - 1;
		else
			m_xCurrentLod--;

	m_fn_vShowCurrentLod();

	*pResult = 1;
}


/*
 ----------------------------------------------------------------------------------------
  Description   : EN_KILLFOCUS on IDC_EDIT_CURRENTLOD
 ----------------------------------------------------------------------------------------
 */
void CPODlgVse::OnKillfocusEditCurrentlod() 
{
	char szText[10];

	GetDlgItem( IDC_EDIT_CURRENTLOD )->GetWindowText( szText, 10 );
	m_xCurrentLod = atoi( szText );
	if (m_xCurrentLod >= m_xNbLods )
		m_xCurrentLod = m_xNbLods - 1;
	else if( m_xCurrentLod < 0)
		m_xCurrentLod = 0;

	m_fn_vShowCurrentLod();
}

/*
 ----------------------------------------------------------------------------------------
  Description   : UDN_DELTAPOS on IDC_SPIN_FROM
 ----------------------------------------------------------------------------------------
 */
void CPODlgVse::OnDeltaposSpinFrom(NMHDR* pNMHDR, LRESULT* pResult) 
{
	MTH_tdxReal xValue;
	MTH_tdxReal xDelta;

	NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
	xDelta = -1 * (MTH_tdxReal) pNMUpDown->iDelta;

	if (GetKeyState( VK_SHIFT) & 0x8000)
		xDelta /= 10;
	
	xValue = m_a_xTresholds[ m_xCurrentLod ] + xDelta;
	m_fn_vChangeTreshold( m_xCurrentLod , xValue );
	
	*pResult = 1;
}

/*
 ----------------------------------------------------------------------------------------
  Description   : EN_KILLFOCUS on IDC_EDIT_FROM
 ----------------------------------------------------------------------------------------
 */
void CPODlgVse::OnKillfocusEditFrom() 
{
	char szText[20];

	GetDlgItem( IDC_EDIT_FROM )->GetWindowText( szText, 20 );
	m_fn_vChangeTreshold( m_xCurrentLod, (float) atof( szText ) );
}

/*
 ----------------------------------------------------------------------------------------
  Description   : UDN_DELTAPOS on IDC_SPIN_TO
 ----------------------------------------------------------------------------------------
 */
void CPODlgVse::OnDeltaposSpinTo(NMHDR* pNMHDR, LRESULT* pResult) 
{
	MTH_tdxReal xValue;
	MTH_tdxReal xDelta;

	NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;
	xDelta = -1 * (MTH_tdxReal) pNMUpDown->iDelta;
	
	if (GetKeyState( VK_SHIFT) & 0x8000)
		xDelta /= 10;

	xValue = m_a_xTresholds[ m_xCurrentLod + 1] + xDelta;
	m_fn_vChangeTreshold( m_xCurrentLod + 1, xValue );
		
	*pResult = 1;
}

/*
 ----------------------------------------------------------------------------------------
  Description   : EN_KILLFOCUS on IDC_EDIT_TO
 ----------------------------------------------------------------------------------------
 */
void CPODlgVse::OnKillfocusEditTo() 
{
	char szText[20];

	GetDlgItem( IDC_EDIT_TO )->GetWindowText( szText, 20 );
	m_fn_vChangeTreshold( m_xCurrentLod + 1, (float) atof( szText ) );
}

/*
 ----------------------------------------------------------------------------------------
  Description   : BN_CLICKED on IDC_BUTTON_APPLY
 ----------------------------------------------------------------------------------------
 */
void CPODlgVse::OnButtonApply() 
{
	MTH_tdxReal					a_xOldTreshold[ 10 ];
	MTH_tdxReal					xDiff;
	ACP_tdxIndex				xLod;
	char						cNbDiff;


	for( cNbDiff = 0, xLod = 0; xLod < m_xNbLods; xLod++ )
	{
		GLI_vGetVisualSetLOD( m_hVisualSet, xLod, &a_xOldTreshold[ xLod ], &m_a_xGeometrics[xLod] );
		if (a_xOldTreshold[ xLod ] != m_a_xTresholds[ xLod ])
			cNbDiff++;
	}

	if ( !cNbDiff )
		return;

	/* create modif object */
	CPOVseModif *p_oModif = new CPOVseModif( m_p_oPO, m_hVisualSet, cNbDiff );
	for ( xLod = 0; xLod < m_xNbLods; xLod ++)
	{
		xDiff = m_a_xTresholds[ xLod ] - a_xOldTreshold[ xLod ];
		if ( xDiff )
			p_oModif->m_fn_vSetDiff( xLod, xDiff );
	}

	m_p_oParentDLL->GetInterface()->GetMultiDevice()->GetEditManager()->AskFor( p_oModif );
}

/*
 ----------------------------------------------------------------------------------------
  Description   : BN_CLICKED on IDC_BUTTON_TRESHOLD
 ----------------------------------------------------------------------------------------
 */
void CPODlgVse::OnButtonTreshold() 
{
	ACP_tdxIndex	xLod;
	
	if ( (xLod = m_fn_xGetClickedLodIndex()) != -1)
	{
		m_xCurrentLod = xLod;
		m_fn_vShowCurrentLod();
	}
}

/*
 ----------------------------------------------------------------------------------------
  Description   : BN_DBLCLICKED on IDC_BUTTON_TRESHOLD
 ----------------------------------------------------------------------------------------
 */
void CPODlgVse::OnDoubleclickedButtonTreshold() 
{
	ACP_tdxIndex			xLod;

	if ( (xLod = m_fn_xGetClickedLodIndex()) != -1)
	{
		m_fn_vSwapLOD( xLod, (xLod == m_xSwapLod), TRUE );
		GetDlgItem( IDC_BUTTON_TRESHOLD )->Invalidate();
	}
}




/*
 =======================================================================================
 =======================================================================================
	CPODlgList class
 =======================================================================================
 =======================================================================================
 */
IMPLEMENT_DYNCREATE(CPODlgList, CFormView)


/*
 ----------------------------------------------------------------------------------------
  Description   : constructor
 ----------------------------------------------------------------------------------------
 */
CPODlgList::CPODlgList() : CFormView(CPODlgList::IDD)
{
	//{{AFX_DATA_INIT(CPODlgList)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}

/*
 ----------------------------------------------------------------------------------------
  Description   : destructor
 ----------------------------------------------------------------------------------------
 */
CPODlgList::~CPODlgList()
{
}

/*
 ----------------------------------------------------------------------------------------
  Description   : Message Map
 ----------------------------------------------------------------------------------------
 */
BEGIN_MESSAGE_MAP(CPODlgList, CFormView)
	//{{AFX_MSG_MAP(CPODlgList)
	ON_WM_SIZE()
	ON_NOTIFY(TVN_SELCHANGED, IDC_TREE_PO, OnSelchangedTreePos)
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/*
 ----------------------------------------------------------------------------------------
  Description   : Creation of FormView, register window and control
 ----------------------------------------------------------------------------------------
 */
BOOL CPODlgList::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) 
{
	if ( !CFormView::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext) )
		return FALSE;

	TUT_M_vGetTutDll();
	TUT_M_vRegisterControl( GetSafeHwnd(),"OPD_PhysicalObjectListDialog",	TUT_e_Window ); 
	TUT_M_vRegisterControlID( IDC_TREE_PO,"OPD_PhysicalObjectList",			TUT_e_TreeCtrl );

	return TRUE;
}

/*
 ----------------------------------------------------------------------------------------
  Description   : Unregister control from TUT
 ----------------------------------------------------------------------------------------
 */
void CPODlgList::OnDestroy() 
{
	TUT_M_vGetTutDll();
	TUT_M_vUnregisterControl( GetSafeHwnd() ); 
	TUT_M_vUnregisterControlID( IDC_TREE_PO );

	CFormView::OnDestroy();
}


/*
 =======================================================================================
	Diagnostic functions 
 =======================================================================================
 */
#ifdef _DEBUG
void CPODlgList::AssertValid() const
{
	CFormView::AssertValid();
}

void CPODlgList::Dump(CDumpContext& dc) const
{
	CFormView::Dump(dc);
}
#endif //_DEBUG

/*
 =======================================================================================
	CPODlgList specific functions
 =======================================================================================
 */


/*
 ----------------------------------------------------------------------------------------
  Description   : search by name a child of a tree item
 ----------------------------------------------------------------------------------------
 */
HTREEITEM CPODlgList::fn_hSearchTreeChild( CTreeCtrl *_p_oTree, HTREEITEM _hParent, CString _cstrName )
{
	HTREEITEM	hChild;

	hChild = _p_oTree->GetChildItem( _hParent );
	while (hChild != NULL)
	{
		if ( _cstrName.CompareNoCase( _p_oTree->GetItemText( hChild ) ) == 0 )
			break;
		hChild = _p_oTree->GetNextSiblingItem( hChild );
	}
	return hChild;
}

/*
 ----------------------------------------------------------------------------------------
  Description   : search by Data a child of a tree item
 ----------------------------------------------------------------------------------------
 */
HTREEITEM CPODlgList::fn_hSearchTreeChild( CTreeCtrl *_p_oTree, HTREEITEM _hParent, DWORD _dwData )
{
	HTREEITEM	hChild;

	hChild = _p_oTree->GetChildItem( _hParent );
	while (hChild != NULL)
	{
		if ( _p_oTree->GetItemData( hChild ) == _dwData )
			break;
		hChild = _p_oTree->GetNextSiblingItem( hChild );
	}
	return hChild;
}


/*
 ----------------------------------------------------------------------------------------
  Description   : search in tree item that include given PO
  _p_oTree            -> tree
  _p_oPO              -> PO to search the parent
  Returns (HTREEITEM) hItem of PO parent
 ----------------------------------------------------------------------------------------
 */
HTREEITEM CPODlgList::fn_hGetPOParentItem( CTreeCtrl *_p_oTree, EditorPO *_p_oPO )
{
	CPA_BaseObject			*p_oOwner;
	CPA_BaseObject			*p_oOwnerOwner;
	HTREEITEM				hCurrent;
	HTREEITEM				hFather;

	/*
	 * Get parent HTREEITEM of PO
	 */
	if ((p_oOwner = _p_oPO->GetOwner()) == NULL)
		return m_hWorldItem;

	if ( strcmp( p_oOwner->fn_p_szGetType(), C_szObjectTableTypeName) == 0 )
	{
		if (m_hObjectTable != NULL)
		{
			p_oOwnerOwner = p_oOwner->GetOwner();
			if (p_oOwnerOwner == NULL)
				hCurrent = m_hWithoutActor;
			else
				hCurrent = fn_hSearchTreeChild( _p_oTree, m_hObjectTable, p_oOwnerOwner->GetName());
		}
		else
			hCurrent = NULL;
	}
	else
	{
		hCurrent = m_hModelItem;
	}
		
	if (hCurrent != NULL)
		hFather = fn_hSearchTreeChild( _p_oTree, hCurrent, p_oOwner->GetName());
	else
		hFather = NULL;

	return hFather;
}


/*
 ----------------------------------------------------------------------------------------
  Description   : fill list of PO object present in memory
 ----------------------------------------------------------------------------------------
 */
void CPODlgList::fn_vRefreshListContent(void)
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	CTreeCtrl				*p_oTree = (CTreeCtrl *) GetDlgItem( IDC_TREE_PO );
	HTREEITEM				hCurrent;
	HTREEITEM				hFather;
	HTREEITEM				hSelected, hNewSelected = NULL;
	DWORD					dwSelectedData = 0;
	CString					cstrSelectedText = "";

	CPA_BaseObjectList		*p_oPOList;
	CPA_BaseObject			*p_oPO;
	CPA_BaseObject			*p_oOwner;
	CPA_BaseObject			*p_oOwnerOwner;

	Position				xPos;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

	/*
	 * Init
	 */
	if ( (hSelected = p_oTree->GetSelectedItem()) != NULL)
	{
		dwSelectedData = p_oTree->GetItemData( hSelected );
		cstrSelectedText = p_oTree->GetItemText( hSelected );
	}

	p_oTree->DeleteAllItems();
	m_hWorldItem = m_hModelItem = m_hObjectTable = m_hWithoutActor = NULL;

	p_oPOList = m_p_oParentDLL->GetMainWorld()->fn_p_oGetOriginalObjectList( C_szPhysicalObjectTypeName );

	if (p_oPOList != NULL)
	{
		xPos = p_oPOList->GetHeadPosition();
		while (xPos)
		{
			p_oPO = p_oPOList->GetNext( xPos );
			ASSERT( p_oPO );
			
			/*
			 * Get parent HTREEITEM of PO
			 */
			if ((p_oOwner = p_oPO->GetOwner()) == NULL)
			{
				if (m_hWorldItem == NULL)
					if ( (m_hWorldItem = p_oTree->InsertItem( "World Physical objects" )) != NULL)
					{
						p_oTree->SetItemData( m_hWorldItem, 0 );
						if ( (hSelected != NULL) && (dwSelectedData == 0) && (hNewSelected == NULL ) )
							if (cstrSelectedText.CompareNoCase( "World Physical objects" ) == 0)
								hNewSelected = m_hWorldItem;
					}
				hFather = m_hWorldItem;
			}
			else
			{
				if ( strcmp( p_oOwner->fn_p_szGetType(), C_szObjectTableTypeName) == 0 )
				{
					if (m_hObjectTable == NULL)
						if ( (m_hObjectTable = p_oTree->InsertItem( "Object Tables" )) != NULL)
						{
							p_oTree->SetItemData( m_hObjectTable, 0 );
							if ( (hSelected != NULL) && (dwSelectedData == 0) && (hNewSelected == NULL ) )
								if (cstrSelectedText.CompareNoCase( "Object Tables" ) == 0)
									hNewSelected = m_hObjectTable;
						}

					if (m_hObjectTable != NULL)
					{
						p_oOwnerOwner = p_oOwner->GetOwner();
						if (p_oOwnerOwner == NULL)
						{
							if (m_hWithoutActor == NULL )
								if ( (m_hWithoutActor = p_oTree->InsertItem( "Without owner", m_hObjectTable )) != NULL)
								{
									p_oTree->SetItemData( m_hWithoutActor, 0 );
									if ( (hSelected != NULL) && (dwSelectedData == 0) && (hNewSelected == NULL ) )
										if (cstrSelectedText.CompareNoCase( "Without owner" ) == 0)
											hNewSelected = m_hWithoutActor;
								}
								hCurrent = m_hWithoutActor;
						}
						else
						{
							if ( (hCurrent = fn_hSearchTreeChild( p_oTree, m_hObjectTable, p_oOwnerOwner->GetName())) == NULL)
								if ( (hCurrent = p_oTree->InsertItem( p_oOwnerOwner->GetName(), m_hObjectTable )) != NULL)
								{
									p_oTree->SetItemData( hCurrent, 0 );
									if ( (hSelected != NULL) && (dwSelectedData == 0) && (hNewSelected == NULL ) )
										if (cstrSelectedText.CompareNoCase( p_oOwnerOwner->GetName() ) == 0)
											hNewSelected = hCurrent;
								}
						}
					}
					else
						hCurrent = NULL;
				}
				else
				{
					if (m_hModelItem == NULL)
						if ( (m_hModelItem = p_oTree->InsertItem( "Model PO" )) != NULL)
						{
							p_oTree->SetItemData( m_hModelItem, 0 );
							if ( (hSelected != NULL) && (dwSelectedData == 0) && (hNewSelected == NULL ) )
								if (cstrSelectedText.CompareNoCase( "Model PO" ) == 0)
									hNewSelected = m_hModelItem;
						}
					hCurrent = m_hModelItem;
				}
				
				if (hCurrent != NULL)
				{
					if ( (hFather = fn_hSearchTreeChild( p_oTree, hCurrent, p_oOwner->GetName())) == NULL)
						if ( (hFather = p_oTree->InsertItem( p_oOwner->GetName(), hCurrent )) != NULL)
						{
							p_oTree->SetItemData( hFather, 0 );
							if ( (hSelected != NULL) && (dwSelectedData == 0) && (hNewSelected == NULL ) )
								if (cstrSelectedText.CompareNoCase( p_oOwner->GetName() ) == 0)
									hNewSelected = hFather;
						}
				}
			}
			/*
			 * add item
			 */
			if (hFather != NULL)
			{
				if ((hCurrent = p_oTree->InsertItem( p_oPO->GetName(), hFather )) != NULL)
				{
					p_oTree->SetItemData( hCurrent, (DWORD) p_oPO );
					if ( (DWORD) p_oPO == dwSelectedData )
						hNewSelected = hCurrent;
				}
			}
		}
	}
	p_oTree->SelectItem( hNewSelected );
}



/*
 ----------------------------------------------------------------------------------------
  Description   : set current selected item in tree of PO
  _p_oPO              -> PO object
  _p_oActor           -> actor object
 ----------------------------------------------------------------------------------------
 */
void CPODlgList::fn_vSetCurrentItem( EditorPO *_p_oPO, CPA_BaseObject *_p_oActor )
{
	CTreeCtrl	*p_oTree = (CTreeCtrl *) GetDlgItem( IDC_TREE_PO );
	HTREEITEM	hItem = NULL;

	if (_p_oActor)
	{
		CPA_BaseObject *p_oOwner;
		if 
			( 
				( (hItem = m_hObjectTable) != NULL )
			 &&	( ( p_oOwner = _p_oActor->GetOwner() ) != NULL )
			 &&	( ( p_oOwner = p_oOwner->GetOwner() ) != NULL )
			)
		{
			hItem = fn_hSearchTreeChild( p_oTree, hItem, p_oOwner->GetName() );
		}
	}
	else if (_p_oPO)
	{
		if ( (hItem = fn_hGetPOParentItem( p_oTree, _p_oPO )) != NULL)
		{
			hItem = fn_hSearchTreeChild( p_oTree, hItem, (DWORD) _p_oPO );
		}
	}

	p_oTree->SelectItem( hItem );

}

/*
 =======================================================================================
	CPODlgList message handlers
 =======================================================================================
 */


/*
 ----------------------------------------------------------------------------------------
  Description   : WM_SIZE
 ----------------------------------------------------------------------------------------
 */
void CPODlgList::OnSize(UINT nType, int cx, int cy) 
{
	CFormView::OnSize(nType, cx, cy);
	
	CTreeCtrl *p_oTree = (CTreeCtrl *) GetDlgItem( IDC_TREE_PO );
	if (p_oTree)
	{
		RECT stRect;
		stRect.left = stRect.top = 5;
		stRect.right = cx - 10;
		stRect.bottom = cy - 10;
		p_oTree->MoveWindow( &stRect );
	}
}



/*
 ----------------------------------------------------------------------------------------
  Description   : TVN_SELCHANGED on IDC_TREE_PO
 ----------------------------------------------------------------------------------------
 */
void CPODlgList::OnSelchangedTreePos(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	HTREEITEM hItem = pNMTreeView->itemNew.hItem;
	CTreeCtrl *p_oTree = (CTreeCtrl *) GetDlgItem( IDC_TREE_PO );
	EditorPO *p_oPO;

	if (p_oTree)
	{
		if (hItem)
			p_oPO = (EditorPO *) p_oTree->GetItemData( hItem );
		else
			p_oPO = NULL;
		m_p_oParentDLL->fn_vDisplayPOInfo( p_oPO );
	}

	*pResult = 0;
}
