//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #include #include #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 CToolDisplace* GetDisplacementTool() { return dynamic_cast(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_TAG_REMOVE, OnButtonTagRemove ) 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 ) || ( m_uiTool == FACEEDITTOOL_TAG_BUILD ) || ( m_uiTool == FACEEDITTOOL_TAG_REMOVE ) ) { 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 ); CButton *pButtonRemove = ( CButton* )GetDlgItem( ID_DISP_TAG_REMOVE ); 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 ); pButtonRemove->SetCheck( m_uiTool == FACEEDITTOOL_TAG_REMOVE ); // 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 buildable tool. SetTool( FACEEDITTOOL_TAG_BUILD ); pDispTool->SetTool( DISPTOOL_TAG_BUILDABLE ); if ( !pDoc->IsDispDrawBuildable() ) { pDoc->SetDispDrawBuildable( true ); m_bForceShowBuildable = true; } } UpdateDialogData(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CFaceEditDispPage::OnButtonTagRemove( void ) { // Set removed 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_REMOVE ) { // Set the select tool. SetTool( FACEEDITTOOL_SELECT ); pDispTool->SetTool( DISPTOOL_SELECT_DISP_FACE ); pDoc->SetDispDrawRemove( false ); } else { // Set the tag remove tool. SetTool( FACEEDITTOOL_TAG_REMOVE ); pDispTool->SetTool( DISPTOOL_TAG_REMOVE ); if ( !pDoc->IsDispDrawRemove() ) { pDoc->SetDispDrawRemove( 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. 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 ) { // Get the active map doc. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc(); // Walkable if ( m_bForceShowWalkable ) { if ( pDoc ) { pDoc->SetDispDrawWalkable( false ); } m_bForceShowWalkable = false; } // Buildable if ( m_bForceShowBuildable ) { if ( pDoc ) { pDoc->SetDispDrawBuildable( false ); } m_bForceShowBuildable = false; } // Always force this off! if ( pDoc ) { pDoc->SetDispDrawRemove( 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; } }