csgo-2018-source/hammer/faceedit_disppage.cpp

1489 lines
40 KiB
C++
Raw Normal View History

2021-07-25 12:11:47 +08:00
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <stdafx.h>
#include <afxcmn.h>
#include "hammer.h"
#include "MainFrm.h"
#include "GlobalFunctions.h"
#include "MapDoc.h"
#include "FaceEdit_DispPage.h"
#include "MapSolid.h"
#include "MapFace.h"
#include "MapDisp.h"
#include "FaceEditSheet.h"
#include "MapView3D.h"
#include "History.h"
#include "ToolDisplace.h"
#include "ToolManager.h"
#include "DispSew.h"
#include "builddisp.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
CToolDisplace* GetDisplacementTool() { return dynamic_cast<CToolDisplace*>(ToolManager()->GetToolForID(TOOL_FACEEDIT_DISP)); }
//=============================================================================
IMPLEMENT_DYNAMIC( CFaceEditDispPage, CPropertyPage )
BEGIN_MESSAGE_MAP( CFaceEditDispPage, CPropertyPage )
//{{AFX_MSG_MAP( CFaceEditDispPage )
ON_BN_CLICKED( ID_DISP_MASK_SELECT, OnCheckMaskSelect )
ON_BN_CLICKED( ID_DISP_MASK_GRID, OnCheckMaskGrid )
ON_BN_CLICKED( ID_DISP_NOPHYSICS_COLL, OnCheckNoPhysicsCollide )
ON_BN_CLICKED( ID_DISP_NOHULL_COLL, OnCheckNoHullCollide )
ON_BN_CLICKED( ID_DISP_NORAY_COLL, OnCheckNoRayCollide )
ON_BN_CLICKED( ID_DISP_SELECT2, OnButtonSelect )
ON_BN_CLICKED( ID_DISP_CREATE, OnButtonCreate )
ON_BN_CLICKED( ID_DISP_DESTROY, OnButtonDestroy )
ON_BN_CLICKED( ID_DISP_NOISE, OnButtonNoise )
ON_BN_CLICKED( ID_DISP_SUBDIVIDE, OnButtonSubdivide )
ON_BN_CLICKED( ID_DISP_SEW, OnButtonSew )
ON_BN_CLICKED( ID_DISP_PAINT_GEO, OnButtonPaintGeo )
ON_BN_CLICKED( ID_DISP_PAINT_DATA, OnButtonPaintData )
ON_BN_CLICKED( ID_DISP_TAG_WALK, OnButtonTagWalkable )
ON_BN_CLICKED( ID_DISP_TAG_BUILD, OnButtonTagBuildable )
ON_BN_CLICKED( ID_DISP_INVERT_ALPHA, OnButtonInvertAlpha )
ON_BN_CLICKED( IDC_SELECT_ADJACENT, OnSelectAdjacent )
ON_NOTIFY( UDN_DELTAPOS, ID_SPIN_DISP_POWER, OnSpinUpDown )
ON_NOTIFY( UDN_DELTAPOS, ID_SPIN_DISP_ELEVATION, OnSpinUpDown )
ON_BN_CLICKED( ID_DISP_APPLY, OnButtonApply )
//}}AFX_MSG_MAP
ON_BN_CLICKED(ID_DISP_SCULPT_PAINT, &CFaceEditDispPage::OnBnClickedDispSculptPaint)
END_MESSAGE_MAP()
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CFaceEditDispPage::CFaceEditDispPage() : CPropertyPage( IDD )
{
m_uiTool = FACEEDITTOOL_SELECT;
m_bForceShowWalkable = false;
m_bForceShowBuildable = false;
}
//-----------------------------------------------------------------------------
// Purpose: Deconstructor
//-----------------------------------------------------------------------------
CFaceEditDispPage::~CFaceEditDispPage()
{
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
inline void CFaceEditDispPage::PostToolUpdate( void )
{
// update the mapdoc views
CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
if( pDoc )
{
pDoc->SetModifiedFlag();
}
// update the dialogs data
UpdateDialogData();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::ClickFace( CMapSolid *pSolid, int faceIndex, int cmd, int clickMode )
{
m_bIsEditable = ( pSolid ? pSolid->IsEditable() : true );
UpdateDialogData();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::UpdateEditControls( bool bAllDisps, bool bHasFace )
{
//
// masks - always active!!
//
CButton *pcheckSelect = ( CButton* )GetDlgItem( ID_DISP_MASK_SELECT );
CButton *pcheckGrid = ( CButton* )GetDlgItem( ID_DISP_MASK_GRID );
pcheckSelect->EnableWindow( TRUE );
pcheckGrid->EnableWindow( TRUE );
//
// tool buttons
//
CButton *pbuttonSelect = ( CButton* )GetDlgItem( ID_DISP_SELECT2 );
CButton *pbuttonCreate = ( CButton* )GetDlgItem( ID_DISP_CREATE );
CButton *pbuttonDestroy = ( CButton* )GetDlgItem( ID_DISP_DESTROY );
CButton *pbuttonPaintGeo = ( CButton* )GetDlgItem( ID_DISP_PAINT_GEO );
CButton *pbuttonPaintSculpt = ( CButton* )GetDlgItem( ID_DISP_SCULPT_PAINT );
CButton *pbuttonPaintData = ( CButton* )GetDlgItem( ID_DISP_PAINT_DATA );
CButton *pbuttonSubdiv = ( CButton* )GetDlgItem( ID_DISP_SUBDIVIDE );
CButton *pbuttonSew = ( CButton* )GetDlgItem( ID_DISP_SEW );
CButton *pbuttonNoise = ( CButton* )GetDlgItem( ID_DISP_NOISE );
CButton *pButtonWalk = ( CButton* )GetDlgItem( ID_DISP_TAG_WALK );
CButton *pButtonBuild = ( CButton* )GetDlgItem( ID_DISP_TAG_BUILD );
pbuttonSelect->EnableWindow( TRUE );
pbuttonCreate->EnableWindow( FALSE );
pbuttonDestroy->EnableWindow( FALSE );
pbuttonPaintGeo->EnableWindow( FALSE );
pbuttonPaintSculpt->EnableWindow( FALSE );
pbuttonPaintData->EnableWindow( FALSE );
pbuttonSubdiv->EnableWindow( FALSE );
pbuttonSew->EnableWindow( FALSE );
pbuttonNoise->EnableWindow( FALSE );
pButtonWalk->EnableWindow( TRUE );
pButtonBuild->EnableWindow( TRUE );
//
// attributes (displacement info)
//
CEdit *peditPower = ( CEdit* )GetDlgItem( ID_DISP_POWER );
CSpinButtonCtrl *pspinPower = ( CSpinButtonCtrl* )GetDlgItem( ID_SPIN_DISP_POWER );
CEdit *peditElevation = ( CEdit* )GetDlgItem( ID_DISP_ELEVATION );
CSpinButtonCtrl *pspinElevation = ( CSpinButtonCtrl* )GetDlgItem( ID_SPIN_DISP_ELEVATION );
CEdit *peditScale = ( CEdit* )GetDlgItem( ID_DISP_SCALE );
CButton *pbuttonApply = ( CButton* )GetDlgItem( ID_DISP_APPLY );
CButton *pbuttonInvertAlpha = ( CButton* )GetDlgItem( ID_DISP_INVERT_ALPHA );
CButton *pCheckNoPhysicsColl = ( CButton* )GetDlgItem( ID_DISP_NOPHYSICS_COLL );
CButton *pCheckNoHullColl = ( CButton* )GetDlgItem( ID_DISP_NOHULL_COLL );
CButton *pCheckNoRayColl = ( CButton* )GetDlgItem( ID_DISP_NORAY_COLL );
peditPower->EnableWindow( FALSE );
pspinPower->EnableWindow( FALSE );
peditElevation->EnableWindow( FALSE );
pspinElevation->EnableWindow( FALSE );
peditScale->EnableWindow( FALSE );
pbuttonApply->EnableWindow( FALSE );
pbuttonInvertAlpha->EnableWindow( FALSE );
pCheckNoPhysicsColl->EnableWindow( FALSE );
pCheckNoHullColl->EnableWindow( FALSE );
pCheckNoRayColl->EnableWindow( FALSE );
// if there aren't any faces selected then the only active item should be selection
if( !bHasFace )
return;
//
// if not all selected faces are displacements then highlight only
// SELECTION, CREATE, DESTROY, and SEW
//
if ( m_bIsEditable )
{
if( !bAllDisps )
{
pbuttonCreate->EnableWindow( TRUE );
pbuttonDestroy->EnableWindow( TRUE );
pbuttonSew->EnableWindow( TRUE );
}
// highlight all tool buttons, but CREATE
else
{
pbuttonDestroy->EnableWindow( TRUE );
pbuttonPaintGeo->EnableWindow( TRUE );
pbuttonPaintSculpt->EnableWindow( TRUE );
pbuttonPaintData->EnableWindow( TRUE );
pbuttonSubdiv->EnableWindow( TRUE );
pbuttonSew->EnableWindow( TRUE );
pbuttonNoise->EnableWindow( TRUE );
}
// active attributes if in selection mode
if( m_uiTool == FACEEDITTOOL_SELECT )
{
peditPower->EnableWindow( TRUE );
pspinPower->EnableWindow( TRUE );
peditElevation->EnableWindow( TRUE );
pspinElevation->EnableWindow( TRUE );
peditScale->EnableWindow( TRUE );
pbuttonApply->EnableWindow( TRUE );
pbuttonInvertAlpha->EnableWindow( TRUE );
pCheckNoPhysicsColl->EnableWindow( TRUE );
pCheckNoHullColl->EnableWindow( TRUE );
pCheckNoRayColl->EnableWindow( TRUE );
}
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::FillEditControls( bool bAllDisps )
{
CString strText;
//
// if all selected face have displacements
//
if( bAllDisps )
{
int power = 0;
bool bAllPower = true;
float elevation = 0.0f;
bool bAllElevation = true;
float scale = 1.0f;
bool bAllScale = true;
bool bAllNoPhysics = true;
bool bAllNoHull = true;
bool bAllNoRay = true;
CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent();
if( pSheet )
{
int faceCount = pSheet->GetFaceListCount();
if( faceCount > 0 )
{
CMapFace *pFace = pSheet->GetFaceListDataFace( 0 );
EditDispHandle_t handle = pFace->GetDisp();
CMapDisp *pDisp = EditDispMgr()->GetDisp( handle );
power = pDisp->GetPower();
elevation = pDisp->GetElevation();
scale = pDisp->GetScale();
}
//
// test all faces for "equal" attributes
//
for( int faceIndex = 0; faceIndex < faceCount; faceIndex++ )
{
CMapFace *pFace = pSheet->GetFaceListDataFace( faceIndex );
EditDispHandle_t handle = pFace->GetDisp();
CMapDisp *pDisp = EditDispMgr()->GetDisp( handle );
// test power, elevation, and scale
if( power != pDisp->GetPower() ) { bAllPower = false; }
if( elevation != pDisp->GetElevation() ) { bAllElevation = false; }
if( scale != pDisp->GetScale() ) { bAllScale = false; }
if ( !pDisp->CheckFlags( CCoreDispInfo::SURF_NOPHYSICS_COLL ) ) { bAllNoPhysics = false; }
if ( !pDisp->CheckFlags( CCoreDispInfo::SURF_NOHULL_COLL ) ) { bAllNoHull = false; }
if ( !pDisp->CheckFlags( CCoreDispInfo::SURF_NORAY_COLL ) ) { bAllNoRay = false; }
}
// set displacement power value to 3 - 9x9
SetDlgItemText( ID_DISP_POWER, "" );
if( bAllPower )
{
SetDlgItemInt( ID_DISP_POWER, power );
}
// set elevation value
SetDlgItemText( ID_DISP_ELEVATION, "" );
if( bAllElevation )
{
strText.Format( "%4.2f", elevation );
SetDlgItemText( ID_DISP_ELEVATION, strText );
}
// set scale value
SetDlgItemText( ID_DISP_SCALE, "" );
if( bAllScale )
{
strText.Format( "%4.4f", scale );
SetDlgItemText( ID_DISP_SCALE, strText );
}
CButton *pCheckBox;
pCheckBox = ( CButton* )GetDlgItem( ID_DISP_NOPHYSICS_COLL );
pCheckBox->SetCheck( FALSE );
if ( bAllNoPhysics )
{
pCheckBox->SetCheck( TRUE );
}
pCheckBox = ( CButton* )GetDlgItem( ID_DISP_NOHULL_COLL );
pCheckBox->SetCheck( FALSE );
if ( bAllNoHull )
{
pCheckBox->SetCheck( TRUE );
}
pCheckBox = ( CButton* )GetDlgItem( ID_DISP_NORAY_COLL );
pCheckBox->SetCheck( FALSE );
if ( bAllNoRay )
{
pCheckBox->SetCheck( TRUE );
}
}
}
else
{
// set initial displacement power value to 3 - 9x9
CSpinButtonCtrl *pSpin = ( CSpinButtonCtrl* )GetDlgItem( ID_SPIN_DISP_POWER );
pSpin->SetPos( 0 );
SetDlgItemInt( ID_DISP_POWER, 0 );
// set initial elevation value
pSpin = ( CSpinButtonCtrl* )GetDlgItem( ID_SPIN_DISP_ELEVATION );
pSpin->SetPos( 0 );
SetDlgItemText( ID_DISP_ELEVATION, "" );
// set initial scale value
SetDlgItemText( ID_DISP_SCALE, "" );
}
//
// get tool specific data for page
//
CToolDisplace *pDispTool = GetDisplacementTool();
if( pDispTool )
{
CButton *checkBox;
checkBox = ( CButton* )GetDlgItem( ID_DISP_MASK_SELECT );
checkBox->SetCheck( pDispTool->HasSelectMask() );
checkBox = ( CButton* )GetDlgItem( ID_DISP_MASK_GRID );
checkBox->SetCheck( pDispTool->HasGridMask() );
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::UpdateDialogData( void )
{
bool bAllDisps = false;
bool bHasFace = false;
//
// get face and displacement info
//
CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent();
if( pSheet )
{
int faceCount = pSheet->GetFaceListCount();
if( faceCount > 0 )
{
bHasFace = true;
bAllDisps = true;
}
for( int i = 0; i < faceCount; i++ )
{
CMapFace *pFace = pSheet->GetFaceListDataFace( i );
if( !pFace->HasDisp() )
{
bAllDisps = false;
}
}
}
// fill in edit controls
FillEditControls( bAllDisps );
// update the edit controls
UpdateEditControls( bAllDisps, bHasFace );
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::UpdatePaintDialogs( void )
{
m_PaintDistDlg.UpdateSpatialData();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::OnCheckMaskSelect( void )
{
// get the displacement tool
CToolDisplace *pDispTool = GetDisplacementTool();
if( pDispTool )
{
pDispTool->ToggleSelectMask();
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::OnCheckMaskGrid( void )
{
// get the displacement tool
CToolDisplace *pDispTool = GetDisplacementTool();
if( pDispTool )
{
pDispTool->ToggleGridMask();
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::OnCheckNoPhysicsCollide( void )
{
// Toggle marked faces as collidable.
CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent();
if( pSheet )
{
// Check for a face list.
int nFaceCount = pSheet->GetFaceListCount();
if( nFaceCount == 0 )
return;
// Are we setting or reseting the collision flag?
CButton *pCheckNoCollide = ( CButton* )GetDlgItem( ID_DISP_NOPHYSICS_COLL );
bool bReset = false;
if ( !pCheckNoCollide->GetCheck() )
{
bReset = true;
}
// Get faces with displacements and toggle the collide flag.
int iFace = 0;
for( iFace = 0; iFace < nFaceCount; iFace++ )
{
CMapFace *pFace = pSheet->GetFaceListDataFace( iFace );
if( !pFace || !pFace->HasDisp() )
continue;
EditDispHandle_t hDisp = pFace->GetDisp();
CMapDisp *pDisp = EditDispMgr()->GetDisp( hDisp );
if( pDisp )
{
if ( bReset )
{
int nFlags = pDisp->GetFlags();
nFlags &= ~CCoreDispInfo::SURF_NOPHYSICS_COLL;
pDisp->SetFlags( nFlags );
}
else
{
int nFlags = pDisp->GetFlags();
nFlags |= CCoreDispInfo::SURF_NOPHYSICS_COLL;
pDisp->SetFlags( nFlags );
}
}
}
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::OnCheckNoHullCollide( void )
{
// Toggle marked faces as collidable.
CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent();
if( pSheet )
{
// Check for a face list.
int nFaceCount = pSheet->GetFaceListCount();
if( nFaceCount == 0 )
return;
// Are we setting or reseting the collision flag?
CButton *pCheckNoCollide = ( CButton* )GetDlgItem( ID_DISP_NOHULL_COLL );
bool bReset = false;
if ( !pCheckNoCollide->GetCheck() )
{
bReset = true;
}
// Get faces with displacements and toggle the collide flag.
int iFace = 0;
for( iFace = 0; iFace < nFaceCount; iFace++ )
{
CMapFace *pFace = pSheet->GetFaceListDataFace( iFace );
if( !pFace || !pFace->HasDisp() )
continue;
EditDispHandle_t hDisp = pFace->GetDisp();
CMapDisp *pDisp = EditDispMgr()->GetDisp( hDisp );
if( pDisp )
{
if ( bReset )
{
int nFlags = pDisp->GetFlags();
nFlags &= ~CCoreDispInfo::SURF_NOHULL_COLL;
pDisp->SetFlags( nFlags );
}
else
{
int nFlags = pDisp->GetFlags();
nFlags |= CCoreDispInfo::SURF_NOHULL_COLL;
pDisp->SetFlags( nFlags );
}
}
}
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::OnCheckNoRayCollide( void )
{
// Toggle marked faces as collidable.
CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent();
if( pSheet )
{
// Check for a face list.
int nFaceCount = pSheet->GetFaceListCount();
if( nFaceCount == 0 )
return;
// Are we setting or reseting the collision flag?
CButton *pCheckNoCollide = ( CButton* )GetDlgItem( ID_DISP_NORAY_COLL );
bool bReset = false;
if ( !pCheckNoCollide->GetCheck() )
{
bReset = true;
}
// Get faces with displacements and toggle the collide flag.
int iFace = 0;
for( iFace = 0; iFace < nFaceCount; iFace++ )
{
CMapFace *pFace = pSheet->GetFaceListDataFace( iFace );
if( !pFace || !pFace->HasDisp() )
continue;
EditDispHandle_t hDisp = pFace->GetDisp();
CMapDisp *pDisp = EditDispMgr()->GetDisp( hDisp );
if( pDisp )
{
if ( bReset )
{
int nFlags = pDisp->GetFlags();
nFlags &= ~CCoreDispInfo::SURF_NORAY_COLL;
pDisp->SetFlags( nFlags );
}
else
{
int nFlags = pDisp->GetFlags();
nFlags |= CCoreDispInfo::SURF_NORAY_COLL;
pDisp->SetFlags( nFlags );
}
}
}
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::SetTool( unsigned int tool )
{
if( m_uiTool == FACEEDITTOOL_PAINTGEO )
{
m_PaintDistDlg.DestroyWindow();
}
if( m_uiTool == FACEEDITTOOL_PAINTSCULPT )
{
m_PaintSculptDlg.DestroyWindow();
}
if( m_uiTool == FACEEDITTOOL_PAINTDATA )
{
m_PaintDataDlg.DestroyWindow();
}
if ( m_uiTool == FACEEDITTOOL_TAG_WALK )
{
ResetForceShows();
}
if ( m_uiTool == FACEEDITTOOL_TAG_BUILD )
{
ResetForceShows();
}
m_uiTool = tool;
// set button checked
CButton *pbuttonSelect = ( CButton* )GetDlgItem( ID_DISP_SELECT2 );
CButton *pbuttonCreate = ( CButton* )GetDlgItem( ID_DISP_CREATE );
CButton *pbuttonDestroy = ( CButton* )GetDlgItem( ID_DISP_DESTROY );
CButton *pbuttonPaintGeo = ( CButton* )GetDlgItem( ID_DISP_PAINT_GEO );
CButton *pbuttonPaintSculpt = ( CButton* )GetDlgItem( ID_DISP_SCULPT_PAINT );
CButton *pbuttonPaintData = ( CButton* )GetDlgItem( ID_DISP_PAINT_DATA );
CButton *pbuttonSubdiv = ( CButton* )GetDlgItem( ID_DISP_SUBDIVIDE );
CButton *pbuttonSew = ( CButton* )GetDlgItem( ID_DISP_SEW );
CButton *pbuttonNoise = ( CButton* )GetDlgItem( ID_DISP_NOISE );
CButton *pButtonWalk = ( CButton* )GetDlgItem( ID_DISP_TAG_WALK );
CButton *pButtonBuild = ( CButton* )GetDlgItem( ID_DISP_TAG_BUILD );
pbuttonSelect->SetCheck( m_uiTool == FACEEDITTOOL_SELECT );
pbuttonCreate->SetCheck( m_uiTool == FACEEDITTOOL_CREATE );
pbuttonDestroy->SetCheck( m_uiTool == FACEEDITTOOL_DESTROY );
pbuttonPaintGeo->SetCheck( m_uiTool == FACEEDITTOOL_PAINTGEO );
pbuttonPaintSculpt->SetCheck( m_uiTool == FACEEDITTOOL_PAINTSCULPT );
pbuttonPaintData->SetCheck( m_uiTool == FACEEDITTOOL_PAINTDATA );
pbuttonSubdiv->SetCheck( m_uiTool == FACEEDITTOOL_SUBDIV );
pbuttonSew->SetCheck( m_uiTool == FACEEDITTOOL_SEW );
pbuttonNoise->SetCheck( m_uiTool == FACEEDITTOOL_NOISE );
pButtonWalk->SetCheck( m_uiTool == FACEEDITTOOL_TAG_WALK );
pButtonBuild->SetCheck( m_uiTool == FACEEDITTOOL_TAG_BUILD );
// Update button state, etc.
UpdateDialogData();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::OnButtonSelect( void )
{
// set selection tool
SetTool( FACEEDITTOOL_SELECT );
// get the displacement tool and set selection tool active
CToolDisplace *pDispTool = GetDisplacementTool();
if( pDispTool )
{
pDispTool->SetTool( DISPTOOL_SELECT );
UpdateDialogData();
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::OnButtonCreate( void )
{
// set creation tool
SetTool( FACEEDITTOOL_CREATE );
//
// "create" all selected faces
//
CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent();
if( pSheet )
{
// check for faces to create
int faceCount = pSheet->GetFaceListCount();
if( faceCount == 0 )
return;
//
// open the dialog and get the desired creation power
//
if( m_CreateDlg.DoModal() == IDCANCEL )
{
// reset selection tool
SetTool( FACEEDITTOOL_SELECT );
return;
}
// clamped the "power" (range [2..4])
int power = m_CreateDlg.m_Power;
//
// get the active map doc and displacement manager
//
IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
if( !pDispMgr )
return;
//
// create faces
//
for( int ndxFace = 0; ndxFace < faceCount; ndxFace++ )
{
CMapFace *pFace = pSheet->GetFaceListDataFace( ndxFace );
if( !pFace )
continue;
// make sure the face has the appropriate point count
if( pFace->GetPointCount() != 4 )
continue;
// check to see if the face already has a displacement,
// ignore it if so
if( pFace->HasDisp() )
continue;
EditDispHandle_t dispHandle = EditDispMgr()->Create();
CMapDisp *pDisp = EditDispMgr()->GetDisp( dispHandle );
if( pDisp )
{
// set dependencies
pFace->SetDisp( dispHandle );
pDisp->SetParent( pFace );
// get surface data
pDisp->InitDispSurfaceData( pFace, true );
// add displacement to world list (this should be done automatically!)
pDispMgr->AddToWorld( dispHandle );
// create a new displacement surface based on data
pDisp->InitData( power );
pDisp->Create();
// Post a change to the solid.
CMapSolid *pSolid = ( CMapSolid* )pFace->GetParent();
pSolid->PostUpdate( Notify_Changed );
// Update autovisgroups for the solid
CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
pDoc->RemoveFromAutoVisGroups( pSolid );
pDoc->AddToAutoVisGroup( pSolid );
}
}
}
// reset selection tool
SetTool( FACEEDITTOOL_SELECT );
// update
PostToolUpdate();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::OnButtonDestroy( void )
{
// set destruction tool
SetTool( FACEEDITTOOL_DESTROY );
//
// "destroy" all selected faces
//
CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent();
if( pSheet )
{
// check for faces to destroy
int faceCount = pSheet->GetFaceListCount();
if( faceCount == 0 )
return;
// get the displacement manager
IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
if( !pDispMgr )
return;
// mark history position
pDispMgr->PreUndo( "Displacement Destroy" );
for( int ndxFace = 0; ndxFace < faceCount; ndxFace++ )
{
// get the current displacement
// get current displacement
CMapFace *pFace = pSheet->GetFaceListDataFace( ndxFace );
if( !pFace || !pFace->HasDisp() )
continue;
CMapSolid *pSolid = ( CMapSolid* )pFace->GetParent();
if ( pSolid && !pSolid->IsVisible() )
continue;
EditDispHandle_t handle = pFace->GetDisp();
// setup for undo
pDispMgr->Undo( handle, false );
pDispMgr->RemoveFromWorld( handle );
pFace->SetDisp( EDITDISPHANDLE_INVALID );
// Post a change to the solid.
pSolid->PostUpdate( Notify_Changed );
CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
pDoc->RemoveFromAutoVisGroups( pSolid );
pDoc->AddToAutoVisGroup( pSolid );
}
pDispMgr->PostUndo();
}
// reset selection tool
SetTool( FACEEDITTOOL_SELECT );
// update
PostToolUpdate();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::OnButtonNoise( void )
{
// set noise tool
SetTool( FACEEDITTOOL_NOISE );
//
// "noise" all selected faces
//
CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent();
if( pSheet )
{
// check for faces to add noise to
int faceCount = pSheet->GetFaceListCount();
if( faceCount == 0 )
return;
//
// open the dialog and get the desired noise parameters
//
if( m_NoiseDlg.DoModal() == IDCANCEL )
{
// reset selection tool
SetTool( FACEEDITTOOL_SELECT );
return;
}
// mark for undo
// get the displacement manager
IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
if( !pDispMgr )
return;
pDispMgr->PreUndo( "Displacement Noise" );
for( int ndxFace = 0; ndxFace < faceCount; ndxFace++ )
{
// get current displacement
CMapFace *pFace = pSheet->GetFaceListDataFace( ndxFace );
if( pFace )
{
if( pFace->HasDisp() )
{
EditDispHandle_t handle = pFace->GetDisp();
// setup for undo
pDispMgr->Undo( handle, false );
CMapDisp *pDisp = EditDispMgr()->GetDisp( handle );
pDisp->ApplyNoise( m_NoiseDlg.m_Min, m_NoiseDlg.m_Max, 1.0f );
}
}
}
pDispMgr->PostUndo();
}
// reset selection tool
SetTool( FACEEDITTOOL_SELECT );
// update
PostToolUpdate();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::OnButtonSubdivide( void )
{
// set subdivision tool
SetTool( FACEEDITTOOL_SUBDIV );
//
// create selection list
//
IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
if( !pDispMgr )
return;
pDispMgr->SelectClear();
CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent();
if( pSheet )
{
// check for faces to subdivide
int faceCount = pSheet->GetFaceListCount();
if( faceCount == 0 )
return;
for( int ndxFace = 0; ndxFace < faceCount; ndxFace++ )
{
// get current displacement
CMapFace *pFace = pSheet->GetFaceListDataFace( ndxFace );
if( pFace )
{
if( pFace->HasDisp() )
{
EditDispHandle_t handle = pFace->GetDisp();
pDispMgr->AddToSelect( handle );
CMapDisp *pDisp = EditDispMgr()->GetDisp( handle );
pDisp->ResetTexelHitIndex();
}
}
}
}
// subdivide
pDispMgr->CatmullClarkSubdivide();
// reset selection tool
SetTool( FACEEDITTOOL_SELECT );
// update
PostToolUpdate();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::OnButtonSew( void )
{
// set sew tool
SetTool( FACEEDITTOOL_SEW );
//
// "sew" all selected faces
//
CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent();
if( pSheet )
{
// check for faces to sew
int faceCount = pSheet->GetFaceListCount();
if( faceCount == 0 )
return;
// get the displacement manager
IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
if( !pDispMgr )
return;
// mark history position
pDispMgr->PreUndo( "Displacement Sewing" );
for( int ndxFace = 0; ndxFace < faceCount; ndxFace++ )
{
// get the current displacement
// get current displacement
CMapFace *pFace = pSheet->GetFaceListDataFace( ndxFace );
if( pFace )
{
if( pFace->HasDisp() )
{
EditDispHandle_t handle = pFace->GetDisp();
// setup for undo
pDispMgr->Undo( handle, false );
}
}
}
pDispMgr->PostUndo();
// sew faces
FaceListSewEdges();
// update the parents - force a rebuild
for( int ndxFace = 0; ndxFace < faceCount; ndxFace++ )
{
// get current displacement
CMapFace *pFace = pSheet->GetFaceListDataFace( ndxFace );
if( pFace )
{
if( pFace->HasDisp() )
{
CMapSolid *pSolid = ( CMapSolid* )pFace->GetParent();
pSolid->PostUpdate( Notify_Rebuild );
}
}
}
}
// reset selection tool
SetTool( FACEEDITTOOL_SELECT );
// update
PostToolUpdate();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::OnButtonPaintGeo( void )
{
// set selection tool
SetTool( FACEEDITTOOL_PAINTGEO );
// get the displacement tool and set the paint tool active
CToolDisplace *pDispTool = GetDisplacementTool();
if( pDispTool )
{
pDispTool->SetTool( DISPTOOL_PAINT );
UpdateDialogData();
}
if( !m_PaintDistDlg.Create( IDD_DISP_PAINT_DIST, this ) )
return;
m_PaintDistDlg.ShowWindow( SW_SHOW );
}
//-----------------------------------------------------------------------------
// Purpose: handles the user clicking on the sculpt button
//-----------------------------------------------------------------------------
void CFaceEditDispPage::OnBnClickedDispSculptPaint( )
{
// set selection tool
SetTool( FACEEDITTOOL_PAINTSCULPT );
// get the displacement tool and set the paint tool active
CToolDisplace *pDispTool = GetDisplacementTool();
if( pDispTool )
{
pDispTool->SetTool( DISPTOOL_PAINT_SCULPT );
UpdateDialogData();
}
if( !m_PaintSculptDlg.Create( IDD_DISP_PAINT_SCULPT, this ) )
return;
m_PaintSculptDlg.ShowWindow( SW_SHOW );
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::OnButtonPaintData( void )
{
// set selection tool
SetTool( FACEEDITTOOL_PAINTDATA );
// get the displacement tool and set the paint tool active
CToolDisplace *pDispTool = GetDisplacementTool();
if( pDispTool )
{
pDispTool->SetTool( DISPTOOL_PAINT );
UpdateDialogData();
}
if( !m_PaintDataDlg.Create( IDD_DISP_PAINT_DATA, this ) )
return;
m_PaintDataDlg.ShowWindow( SW_SHOW );
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::OnButtonTagWalkable( void )
{
// Set walkalbe faces viewable -- if they are not already.
CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
if ( !pDoc )
return;
CToolDisplace *pDispTool = GetDisplacementTool();
if( !pDispTool )
return;
// Toggle the functionality.
if ( GetTool() == FACEEDITTOOL_TAG_WALK )
{
// Set the select tool.
SetTool( FACEEDITTOOL_SELECT );
pDispTool->SetTool( DISPTOOL_SELECT_DISP_FACE );
if ( m_bForceShowWalkable )
{
pDoc->SetDispDrawWalkable( false );
m_bForceShowWalkable = false;
}
}
else
{
// Set the tag walkable tool.
SetTool( FACEEDITTOOL_TAG_WALK );
pDispTool->SetTool( DISPTOOL_TAG_WALKABLE );
if ( !pDoc->IsDispDrawWalkable() )
{
pDoc->SetDispDrawWalkable( true );
m_bForceShowWalkable = true;
}
}
UpdateDialogData();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::OnButtonTagBuildable( void )
{
// Set buildalbe faces viewable -- if they are not already.
CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
if ( !pDoc )
return;
CToolDisplace *pDispTool = GetDisplacementTool();
if( !pDispTool )
return;
// Toggle the functionality.
if ( GetTool() == FACEEDITTOOL_TAG_BUILD )
{
// Set the select tool.
SetTool( FACEEDITTOOL_SELECT );
pDispTool->SetTool( DISPTOOL_SELECT_DISP_FACE );
if ( m_bForceShowBuildable )
{
pDoc->SetDispDrawBuildable( false );
m_bForceShowBuildable = false;
}
}
else
{
// Set the tag walkable tool.
SetTool( FACEEDITTOOL_TAG_BUILD );
pDispTool->SetTool( DISPTOOL_TAG_BUILDABLE );
if ( !pDoc->IsDispDrawBuildable() )
{
pDoc->SetDispDrawBuildable( true );
m_bForceShowBuildable = true;
}
}
UpdateDialogData();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFaceEditDispPage::OnButtonInvertAlpha( void )
{
// Invert the alpha channel on all the selected displacements.
CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent();
if( pSheet )
{
int nFaceCount = pSheet->GetFaceListCount();
for( int iFace = 0; iFace < nFaceCount; ++iFace )
{
CMapFace *pFace = pSheet->GetFaceListDataFace( iFace );
if( pFace )
{
if( pFace->HasDisp() )
{
EditDispHandle_t handle = pFace->GetDisp();
CMapDisp *pDisp = EditDispMgr()->GetDisp( handle );
pDisp->InvertAlpha();
}
}
}
}
// Update
PostToolUpdate();
}
//-----------------------------------------------------------------------------
// Purpose: Select any displacement faces adjacent to the already-selected ones.
//-----------------------------------------------------------------------------
void CFaceEditDispPage::OnSelectAdjacent()
{
IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
bool bSelectedAny = false;
// For all selected displacements...
CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent();
if( !pSheet )
return;
// check for faces
int faceCount = pSheet->GetFaceListCount();
if( faceCount == 0 )
return;
for( int ndxFace = 0; ndxFace < faceCount; ndxFace++ )
{
// get current displacement
CMapFace *pFace = pSheet->GetFaceListDataFace( ndxFace );
if( !pFace || !pFace->HasDisp() )
continue;
EditDispHandle_t handle = pFace->GetDisp();
CMapDisp *pDisp = EditDispMgr()->GetDisp( handle );
// Now test all other disps in the world. We could do the code commented below, but then
// we won't be selecting adjacent neighbors of a different power.
//
//for ( int iEdge=0; iEdge < 4; iEdge++ )
//{
// EditDispHandle_t hNeighbor = pDisp->GetEdgeNeighbor( iEdge );
int totalDispCount = pDispMgr->WorldCount();
for ( int iTestDisp=0; iTestDisp < totalDispCount; iTestDisp++ )
{
int edge1[4], edge2[4];
CMapDisp *pNeighbor = pDispMgr->GetFromWorld( iTestDisp );
if ( !pNeighbor || pNeighbor == pDisp || pDispMgr->NumSharedPoints( pDisp, pNeighbor, edge1, edge2 ) != 2 )
continue;
// Get its map face and solid.
CMapFace *pFace = dynamic_cast< CMapFace* >( pNeighbor->GetParent() );
if ( !pFace || pFace->GetSelectionState() != SELECT_NONE )
continue;
CMapSolid *pSolid = dynamic_cast< CMapSolid* >( pFace->GetParent() );
if ( !pSolid || !pSolid->IsVisible() )
continue;
// The function we use to select a face wants the face's index into its CMapSolid, so we need that.
int iFaceIndex = pSolid->GetFaceIndex( pFace );
if ( iFaceIndex == -1 )
continue;
// Finally, select the face.
pSheet->ClickFace( pSolid, iFaceIndex, CFaceEditSheet::cfSelect, CFaceEditSheet::ModeSelect );
bSelectedAny = true;
}
}
if ( bSelectedAny )
{
CMapDoc::GetActiveMapDoc()->UpdateAllViews( MAPVIEW_UPDATE_TOOL );
}
}
//-----------------------------------------------------------------------------
// Resample
//-----------------------------------------------------------------------------
void CFaceEditDispPage::UpdatePower( CMapDisp *pDisp )
{
// input check
if( !pDisp )
return;
//
// get the power from the power edit box
//
CString strPower;
GetDlgItemText( ID_DISP_POWER, strPower );
int power = atoi( strPower );
if( power < 2 ) { power = 2; }
if( power > 4 ) { power = 4; }
// check for a change and resample if need be
if( power != pDisp->GetPower() )
{
pDisp->Resample( power );
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::UpdateElevation( CMapDisp *pDisp )
{
// input check
if( !pDisp )
return;
//
// get current elevation value
//
CString strElevation;
GetDlgItemText( ID_DISP_ELEVATION, strElevation );
int elevation = atof( strElevation );
// check for change and set new elevation if need be
if( elevation != pDisp->GetElevation() )
{
pDisp->Elevate( elevation );
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pNMHDR -
// pResult -
//-----------------------------------------------------------------------------
void CFaceEditDispPage::OnSpinUpDown( NMHDR *pNMHDR, LRESULT *pResult )
{
//
// get scroll up down edit box
//
NM_UPDOWN *pNMUpDown = ( NM_UPDOWN* )pNMHDR;
switch( pNMUpDown->hdr.idFrom )
{
case ID_SPIN_DISP_POWER:
{
CEdit *pEdit = ( CEdit* )GetDlgItem( ID_DISP_POWER );
CString strPower;
pEdit->GetWindowText( strPower );
int power = atoi( strPower );
power += ( -pNMUpDown->iDelta );
if( power < 2 ) { power = 2; }
if( power > 4 ) { power = 4; }
strPower.Format( "%d", power );
pEdit->SetWindowText( strPower );
*pResult = 0;
break;
}
case ID_SPIN_DISP_ELEVATION:
{
CEdit *pEdit = ( CEdit* )GetDlgItem( ID_DISP_ELEVATION );
CString strElevation;
pEdit->GetWindowText( strElevation );
float elevation = atof( strElevation );
elevation += 0.5f * ( -pNMUpDown->iDelta );
strElevation.Format( "%4.2f", elevation );
pEdit->SetWindowText( strElevation );
*pResult = 0;
break;
}
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::UpdateScale( CMapDisp *pDisp )
{
if( !pDisp )
return;
//
// get the current scale value
//
CString strScale;
GetDlgItemText( ID_DISP_SCALE, strScale );
float scale = atof( strScale );
// check for change and set new scale if need be
if( scale != pDisp->GetScale() )
{
pDisp->Scale( scale );
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::OnButtonApply( void )
{
//
// "create" all selected faces
//
CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent();
if( pSheet )
{
int faceCount = pSheet->GetFaceListCount();
for( int ndxFace = 0; ndxFace < faceCount; ndxFace++ )
{
// get current face
CMapFace *pFace = pSheet->GetFaceListDataFace( ndxFace );
if( pFace )
{
if( pFace->HasDisp() )
{
EditDispHandle_t handle = pFace->GetDisp();
CMapDisp *pDisp = EditDispMgr()->GetDisp( handle );
// update attribs
UpdatePower( pDisp );
UpdateElevation( pDisp );
UpdateScale( pDisp );
}
}
}
}
// update
PostToolUpdate();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::CloseAllDialogs( void )
{
if( m_uiTool == FACEEDITTOOL_PAINTGEO )
{
m_PaintDistDlg.DestroyWindow();
}
if( m_uiTool == FACEEDITTOOL_PAINTSCULPT )
{
m_PaintSculptDlg.DestroyWindow();
}
if( m_uiTool == FACEEDITTOOL_PAINTDATA )
{
m_PaintDataDlg.DestroyWindow();
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditDispPage::ResetForceShows( void )
{
// Walkable
if ( m_bForceShowWalkable )
{
CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
if ( pDoc )
{
pDoc->SetDispDrawWalkable( false );
}
m_bForceShowWalkable = false;
}
// Buildable
if ( m_bForceShowBuildable )
{
CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
if ( pDoc )
{
pDoc->SetDispDrawBuildable( false );
}
m_bForceShowBuildable = false;
}
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
BOOL CFaceEditDispPage::OnSetActive( void )
{
ToolManager()->SetTool( TOOL_FACEEDIT_DISP );
// set the selection as the tool to use!!!
OnButtonSelect();
return CPropertyPage::OnSetActive();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
BOOL CFaceEditDispPage::OnKillActive( void )
{
CloseAllDialogs();
ResetForceShows();
return TRUE;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
BOOL CFaceEditDispPage::PreTranslateMessage( MSG *pMsg )
{
HACCEL hAccel = GetMainWnd()->GetAccelTable();
if( !(hAccel && ::TranslateAccelerator( GetMainWnd()->m_hWnd, hAccel, pMsg ) ) )
{
return CPropertyPage::PreTranslateMessage( pMsg );
}
else
{
return TRUE;
}
}