text: //========= Copyright Valve Corporation, All rights reserved. ============//
  //
  // Purpose: A page in a tabbed dialog that allows the editing of face properties.
  //
  //=============================================================================//
  
  #include <stdafx.h>
  #include "hammer.h"
  #include "MainFrm.h"
  #include "GlobalFunctions.h"
  #include "FaceEditSheet.h"
  #include "MapSolid.h"
  #include "MapFace.h"
  #include "MapDisp.h"
  #include "ToolManager.h"
  #include "mapdoc.h"
  
  // memdbgon must be the last include file in a .cpp file!!!
  #include <tier0/memdbgon.h>
  
  
  IMPLEMENT_DYNAMIC( CFaceEditSheet, CPropertySheet )
  
  BEGIN_MESSAGE_MAP( CFaceEditSheet, CPropertySheet )
  	//{{AFX_MSG_MAP( CFaceEdtiSheet )
  	ON_WM_CLOSE()
  	//}}AFX_MSG_MAP
  END_MESSAGE_MAP()
  
  //-----------------------------------------------------------------------------
  //-----------------------------------------------------------------------------
  CFaceEditSheet::CFaceEditSheet( LPCTSTR pszCaption, CWnd *pParentWnd, UINT iSelectPage ) : 
                  CPropertySheet( pszCaption, pParentWnd, iSelectPage )
  {
  	m_ClickMode = -1;
  	m_bEnableUpdate = true;
  }
  
  
  //-----------------------------------------------------------------------------
  //-----------------------------------------------------------------------------
  CFaceEditSheet::~CFaceEditSheet()
  {
  }
  
  
  //-----------------------------------------------------------------------------
  //-----------------------------------------------------------------------------
  void CFaceEditSheet::SetupPages( void )
  {
  	//
  	// add pages to sheet
  	//
  	AddPage( &m_MaterialPage );
  	AddPage( &m_DispPage );
  }
  
  
  //-----------------------------------------------------------------------------
  //-----------------------------------------------------------------------------
  void CFaceEditSheet::Setup( void )
  {
  	SetupPages();
  }
  
  
  //-----------------------------------------------------------------------------
  //-----------------------------------------------------------------------------
  BOOL CFaceEditSheet::Create( CWnd *pParentWnd )
  {
  	if( !CPropertySheet::Create( pParentWnd ) )
  		return FALSE;
  
  	//
  	// touch all pages so they create the hWnd for each
  	//
  	SetActivePage( &m_DispPage );
  	SetActivePage( &m_MaterialPage );
  
  	//
  	// initialize the pages
  	//
  	m_MaterialPage.Init();
  //	m_DispPage.Init();
  
  	return TRUE;
  }
  
  
  //-----------------------------------------------------------------------------
  // Purpose: Disables window updates when adding a large number of faces to the
  //			dialog at once. When updates are re-enabled, the window is updated.
  // Input  : bEnable - true to enable updates, false to disable them.
  //-----------------------------------------------------------------------------
  void CFaceEditSheet::EnableUpdate( bool bEnable )
  {
  	bool bOld = m_bEnableUpdate;
  	m_bEnableUpdate = bEnable;
  
  	if( ( bEnable ) && ( !bOld ) )
  	{
  		m_MaterialPage.UpdateDialogData();
  	}
  }
  
  
  //-----------------------------------------------------------------------------
  // Purpose: Called when a new material is detected.
  //-----------------------------------------------------------------------------
  void CFaceEditSheet::NotifyNewMaterial( IEditorTexture *pTex )
  {
  	m_MaterialPage.NotifyNewMaterial( pTex );
  }
  
  
  //-----------------------------------------------------------------------------
  // Purpose: Clear the face list.
  //-----------------------------------------------------------------------------
  void CFaceEditSheet::ClearFaceList( void )
  {
  	//
  	// reset selection state of all faces currently in the list
  	//
  	for( int i = 0; i < m_Faces.Count(); i++ )
  	{
  		m_Faces[i].pMapFace->SetSelectionState( SELECT_NONE );
  		EditDispHandle_t handle = m_Faces[i].pMapFace->GetDisp();
  		CMapDisp *pDisp = EditDispMgr()->GetDisp( handle );
  		if( pDisp )
  		{
  			pDisp->ResetTexelHitIndex();
  		}
  	}
  
  	//
  	// reset the list
  	//
  	m_Faces.Purge();
  
  	CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  	if ( pDoc )
  		pDoc->UpdateAllViews( MAPVIEW_UPDATE_ONLY_3D );
  }
  
  
  void CFaceEditSheet::ClearFaceListByMapDoc( CMapDoc *pDoc )
  {
  	// Remove any faces from our list that came from this CMapDoc.
  	for( int i = 0; i < m_Faces.Count(); i++ )
  	{
  		if ( m_Faces[i].pMapDoc == pDoc )
  		{
  			m_Faces.Remove( i );
  			--i;
  		}
  	}
  }
  
  
  //-----------------------------------------------------------------------------
  // Purpose: Search for the given face in the face selection list.  If found, 
  //          return the index of the face in the list.  Otherwise, return -1.  
  //-----------------------------------------------------------------------------
  int CFaceEditSheet::FindFaceInList( CMapFace *pFace )
  {
  	for( int i = 0; i < m_Faces.Count(); i++ )
  	{
  		if( m_Faces[i].pMapFace == pFace )
  			return i;
  	}
  
  	return -1;
  }
  
  
  //-----------------------------------------------------------------------------
  // It is really lame that I have to have material/displacement specific code
  // here!  It is unfortunately necessary - see CMapDoc (SelectFace).  ClickFace
  // not only specifies face selection (which it should do only!!!), but also
  // specifies the "mode" (material specific) of the click -- LAME!!!!  This will
  // be a problem spot if/when we make face selection general.  cab
  //-----------------------------------------------------------------------------
  void CFaceEditSheet::ClickFace( CMapSolid *pSolid, int faceIndex, int cmd, int clickMode )
  {
  	//
  	// set the click mode (either to new mode or previously used)
  	//
  	if( clickMode == -1 )
  	{
  		clickMode = m_ClickMode;
  	}
  
  	//
  	// clear the face list?
  	//
  	if( cmd & cfClear )
  	{
  		ClearFaceList();
  	}
  	cmd &= ~cfClear;
  
  	//
  	// check for valid solid
  	//
  	if( !pSolid )
  		return;
  
  	//
  	// check for face in list, -1 from FindFaceInList indicates face not found
  	//
  	CMapFace *pFace = pSolid->GetFace( faceIndex );
  	int selectIndex = FindFaceInList( pFace );
  	bool bFoundInList = ( selectIndex != -1 );
  
  	//
  	// handle the face list selection
  	//
  	if( ( clickMode == ModeSelect ) || ( clickMode == ModeLiftSelect ) )
  	{
  		// toggle selection if necessary
  		if( cmd == cfToggle )
  		{
  			cmd = bFoundInList ? cfUnselect : cfSelect;			
  		}
  
  		CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  		if( ( cmd == cfSelect ) && !bFoundInList )
  		{
  			// add face to list
  			StoredFace_t sf;
  			sf.pMapDoc = pDoc;
  			sf.pMapFace = pFace;
  			sf.pMapSolid = pSolid;
  			m_Faces.AddToTail( sf );
  			pFace->SetSelectionState( SELECT_NORMAL );
  		}
  		else if( ( cmd == cfUnselect ) && bFoundInList )
  		{
  			// remove from list
  			m_Faces.Remove( selectIndex );
  			pFace->SetSelectionState( SELECT_NONE );
  			EditDispHandle_t handle = pFace->GetDisp();
  			CMapDisp *pDisp = EditDispMgr()->GetDisp( handle );
  			if( pDisp )
  			{
  				pDisp->ResetTexelHitIndex();
  			}
  		}
  
  		if ( pDoc )
  			pDoc->UpdateAllViews( MAPVIEW_UPDATE_ONLY_3D );
  	}
  
  	//
  	// pass to children (pages)
  	//
  	m_MaterialPage.ClickFace( pSolid, faceIndex, cmd, clickMode );
  	m_DispPage.ClickFace( pSolid, faceIndex, cmd, clickMode );
  }
  
  
  //-----------------------------------------------------------------------------
  //-----------------------------------------------------------------------------
  void CFaceEditSheet::SetVisibility( bool bVisible )
  {
  	if( bVisible )
  	{
  		ShowWindow( SW_SHOW );
  		SetActivePage( &m_DispPage );			// gross hack to active the default button!!!!
  		SetActivePage( &m_MaterialPage );
  		m_MaterialPage.UpdateDialogData();
  		m_DispPage.UpdateDialogData();
  	}
  	else
  	{
  		ShowWindow( SW_HIDE );
  	}
  }
  
  
  //-----------------------------------------------------------------------------
  //-----------------------------------------------------------------------------
  BOOL CFaceEditSheet::PreTranslateMessage( MSG *pMsg )
  {
  	HACCEL hAccel = GetMainWnd()->GetAccelTable();
  	if( !(hAccel && ::TranslateAccelerator( GetMainWnd()->m_hWnd, hAccel, pMsg ) ) )
  	{
  		if (IsDialogMessage(pMsg))
  		{
  			return(TRUE);
  		}
  
  		return CWnd::PreTranslateMessage( pMsg );
  	}
  
  	return TRUE;
  }
  
  
  //-----------------------------------------------------------------------------
  //-----------------------------------------------------------------------------
  void CFaceEditSheet::OnClose( void )
  {
  	// make sure all dialogs are closed upon exit!!
  	m_DispPage.CloseAllDialogs();
  	m_DispPage.ResetForceShows();
  
  	// toggle the face edit sheet and texture bar!
  	GetMainWnd()->ShowFaceEditSheetOrTextureBar( false );
  
  	// Force the material page to the original tool.  This will clear out all
  	// dialogs
  	m_MaterialPage.SetMaterialPageTool( CFaceEditMaterialPage::MATERIALPAGETOOL_MATERIAL );
  
  	// set the tool pointer as default tool
  	ToolManager()->SetTool(TOOL_POINTER);
  }
  
  //-----------------------------------------------------------------------------
  //-----------------------------------------------------------------------------
  void CFaceEditSheet::CloseAllPageDialogs( void )
  {
  	// Make sure all dialogs are closed upon exit!
  	m_DispPage.CloseAllDialogs();
  	m_DispPage.ResetForceShows();
  }
  
  //-----------------------------------------------------------------------------
  //-----------------------------------------------------------------------------
  void CFaceEditSheet::UpdateControls( void )
  {
  	// Currently this is only needed for the material page.
  	m_MaterialPage.UpdateDialogData();
  }
  