|
|
//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include <stdafx.h>
#include "hammer.h"
#include "IEditorTexture.h"
#include "FaceEditSheet.h"
#include "MapFace.h"
#include "MapWorld.h"
#include "MainFrm.h"
#include "History.h"
#include "GlobalFunctions.h"
#include "mathlib/vmatrix.h"
#include "MapSolid.h"
#include "TextureBrowser.h"
#include "TextureSystem.h"
#include "MapView3D.h"
#include "ReplaceTexDlg.h"
#include "WADTypes.h"
#include "FaceEdit_MaterialPage.h"
#include "Camera.h"
#include "MapDoc.h"
#include "MapDisp.h"
#include "ToolManager.h"
#include "Selection.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//=============================================================================
IMPLEMENT_DYNAMIC( CFaceEditMaterialPage, CPropertyPage )
BEGIN_MESSAGE_MAP( CFaceEditMaterialPage, CPropertyPage ) //{{AFX_MSG_MAP( CFaceEditMaterialPage )
ON_BN_CLICKED( ID_FACEEDIT_APPLY, OnButtonApply ) ON_COMMAND_EX( IDC_ALIGN_WORLD, OnAlign ) ON_COMMAND_EX( IDC_ALIGN_FACE, OnAlign ) ON_BN_CLICKED( IDC_HIDEMASK, OnHideMask ) ON_COMMAND_EX( IDC_JUSTIFY_TOP, OnJustify ) ON_COMMAND_EX( IDC_JUSTIFY_BOTTOM, OnJustify ) ON_COMMAND_EX( IDC_JUSTIFY_LEFT, OnJustify ) ON_COMMAND_EX( IDC_JUSTIFY_CENTER, OnJustify ) ON_COMMAND_EX( IDC_JUSTIFY_RIGHT, OnJustify ) ON_COMMAND_EX( IDC_JUSTIFY_FITTOFACE, OnJustify ) ON_BN_CLICKED( IDC_MODE, OnMode ) ON_WM_VSCROLL() ON_NOTIFY( UDN_DELTAPOS, IDC_SPINSCALEX, OnDeltaPosFloatSpin ) ON_NOTIFY( UDN_DELTAPOS, IDC_SPINSCALEY, OnDeltaPosFloatSpin ) ON_WM_SIZE() ON_CBN_SELCHANGE( IDC_TEXTURES, OnSelChangeTexture ) ON_BN_CLICKED( IDC_Q2_LIGHT, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_SLICK, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_SKY, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_WARP, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_TRANS33, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_TRANS66, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_FLOWING, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_NODRAW, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_SOLID, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_WINDOW, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_AUX, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_LAVA, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_SLIME, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_WATER, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_MIST, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_CURRENT90, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_CURRENT180, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_CURRENT270, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_CURRENTUP, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_CURRENTDN, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_ORIGIN, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_MONSTER, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_CORPSE, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_DETAIL, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_TRANSLUCENT, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_LADDER, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_PLAYERCLIP, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_MONSTERCLIP, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_CURRENT0, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_HINT, OnCheckUnCheck ) ON_BN_CLICKED( IDC_Q2_SPLITTER, OnCheckUnCheck ) ON_COMMAND( IDC_TREAT_AS_ONE, OnTreatAsOne ) ON_BN_CLICKED( IDC_REPLACE, OnReplace ) ON_COMMAND_EX_RANGE( CFaceEditSheet::id_SwitchModeStart, CFaceEditSheet::id_SwitchModeEnd, OnSwitchMode ) ON_CBN_SELCHANGE( IDC_TEXTUREGROUPS, OnChangeTextureGroup ) ON_BN_CLICKED( IDC_BROWSE, OnBrowse ) ON_BN_CLICKED( ID_BUTTON_SMOOTHING_GROUPS, OnButtonSmoothingGroups ) ON_BN_CLICKED( ID_BUTTON_SHIFTX_RANDOM, OnButtonShiftXRandom ) ON_BN_CLICKED( ID_BUTTON_SHIFTY_RANDOM, OnButtonShiftYRandom ) //}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_FACE_MARK_BUTTON, &CFaceEditMaterialPage::OnBnClickedFaceMarkButton) END_MESSAGE_MAP()
//=============================================================================
#define CONTENTS_AREAPORTAL 0x8000
#define CONTENTS_PLAYERCLIP 0x10000
#define CONTENTS_MONSTERCLIP 0x20000
// I don't think we need these currents. We'll stick to triggers for this
#define CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity
#define CONTENTS_MONSTER 0x2000000 // should never be on a brush, only in game
#define CONTENTS_DEBRIS 0x4000000
#define CONTENTS_DETAIL 0x8000000 // brushes to be added after vis leafs
#define CONTENTS_TRANSLUCENT 0x10000000 // auto set if any surface has trans
#define CONTENTS_LADDER 0x20000000
//=============================================================================
const int NOT_INIT = -99999;
unsigned int CFaceEditMaterialPage::m_FaceContents = 0; unsigned int CFaceEditMaterialPage::m_FaceSurface = 0;
//=============================================================================
//-----------------------------------------------------------------------------
// This table defines the mapping of checkbox controls to flags which are set
// in certain face attributes values.
//-----------------------------------------------------------------------------
CFaceEditMaterialPage::FaceAttributeInfo_t FaceAttributes[] = { //
// Contents.
//
{ IDC_CONTENTS_AREAPORTAL, &CFaceEditMaterialPage::m_FaceContents, CONTENTS_AREAPORTAL }, { IDC_CONTENTS_PLAYERCLIP, &CFaceEditMaterialPage::m_FaceContents, CONTENTS_PLAYERCLIP }, { IDC_CONTENTS_MONSTERCLIP, &CFaceEditMaterialPage::m_FaceContents, CONTENTS_MONSTERCLIP }, { IDC_CONTENTS_ORIGIN, &CFaceEditMaterialPage::m_FaceContents, CONTENTS_ORIGIN }, { IDC_CONTENTS_DETAIL, &CFaceEditMaterialPage::m_FaceContents, CONTENTS_DETAIL }, { IDC_CONTENTS_TRANSLUCENT, &CFaceEditMaterialPage::m_FaceContents, CONTENTS_TRANSLUCENT }, { IDC_CONTENTS_LADDER, &CFaceEditMaterialPage::m_FaceContents, CONTENTS_LADDER },
//
// Surface attributes.
//
{ IDC_SURF_NODRAW, &CFaceEditMaterialPage::m_FaceSurface, SURF_NODRAW }, { IDC_SURF_HINT, &CFaceEditMaterialPage::m_FaceSurface, SURF_HINT }, { IDC_SURF_SKIP, &CFaceEditMaterialPage::m_FaceSurface, SURF_SKIP } };
//=============================================================================
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
CFaceEditMaterialPage::CFaceEditMaterialPage() : CPropertyPage( IDD ) { m_bHideMask = FALSE; m_bInitialized = FALSE; m_bIgnoreResize = FALSE; m_bTreatAsOneFace = FALSE; }
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
CFaceEditMaterialPage::~CFaceEditMaterialPage() { }
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
BOOL CFaceEditMaterialPage::PreTranslateMessage( MSG *pMsg ) { HACCEL hAccel = GetMainWnd()->GetAccelTable(); if( !(hAccel && ::TranslateAccelerator( GetMainWnd()->m_hWnd, hAccel, pMsg ) ) ) { return CPropertyPage::PreTranslateMessage( pMsg ); } else { return TRUE; } }
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::Init( void ) { //
// Connect dialog control objects to their control IDs.
//
m_shiftX.SubclassDlgItem( IDC_SHIFTX, this ); m_shiftY.SubclassDlgItem( IDC_SHIFTY, this ); m_scaleX.SubclassDlgItem( IDC_SCALEX, this ); m_scaleY.SubclassDlgItem( IDC_SCALEY, this ); m_rotate.SubclassDlgItem( IDC_ROTATE, this ); m_cHideMask.SubclassDlgItem( IDC_HIDEMASK, this ); m_cExpand.SubclassDlgItem( IDC_EXPAND, this ); m_cLightmapScale.SubclassDlgItem( IDC_LIGHTMAP_SCALE, this );
//
// Set spin ranges.
//
CWnd *pWnd = GetDlgItem(IDC_SPINSHIFTX); ::PostMessage(pWnd->m_hWnd, UDM_SETRANGE, 0, MAKELONG(MAX_TEXTUREWIDTH, -MAX_TEXTUREWIDTH));
pWnd = GetDlgItem(IDC_SPINSHIFTY); ::PostMessage(pWnd->m_hWnd, UDM_SETRANGE, 0, MAKELONG(MAX_TEXTUREHEIGHT, -MAX_TEXTUREHEIGHT));
pWnd = GetDlgItem(IDC_SPINROTATE); ::PostMessage(pWnd->m_hWnd, UDM_SETRANGE, 0, MAKELONG(359, -359));
pWnd = GetDlgItem(IDC_SPINSCALEX); ::PostMessage(pWnd->m_hWnd, UDM_SETRANGE, 0, MAKELONG(UD_MAXVAL, UD_MINVAL));
pWnd = GetDlgItem(IDC_SPINSCALEY); ::PostMessage(pWnd->m_hWnd, UDM_SETRANGE, 0, MAKELONG(UD_MAXVAL, UD_MINVAL));
pWnd = GetDlgItem(IDC_SPIN_LIGHTMAP_SCALE); ::PostMessage(pWnd->m_hWnd, UDM_SETRANGE, 0, MAKELONG(UD_MAXVAL, 1));
// set the initial switch mode
OnSwitchMode( CFaceEditSheet::ModeLiftSelect );
//
// set up controls
//
m_TextureGroupList.SubclassDlgItem( IDC_TEXTUREGROUPS, this ); m_TextureList.SubclassDlgItem( IDC_TEXTURES, this ); m_TexturePic.SubclassDlgItem( IDC_TEXTUREPIC, this );
m_pCurTex = NULL;
//
// initially update the texture controls
//
NotifyGraphicsChanged(); UpdateTexture();
// initialized!
m_bInitialized = TRUE; }
//-----------------------------------------------------------------------------
// NOTE: clean this up and make a global function!!!
// Purpose:
// Input : fValue -
// *pSpin -
// bMantissa -
// Output : static void
//-----------------------------------------------------------------------------
void FloatToSpin(float fValue, CSpinButtonCtrl *pSpin, BOOL bMantissa) { char szNew[128];
CWnd *pEdit = pSpin->GetBuddy();
if (fValue == NOT_INIT) { szNew[0] = 0; } else { if(bMantissa) sprintf(szNew, "%.2f", fValue); else sprintf(szNew, "%.0f", fValue); }
pSpin->SetPos(atoi(szNew));
char szCurrent[128]; pEdit->GetWindowText(szCurrent, 128); if (strcmp(szNew, szCurrent)) { pEdit->SetWindowText(szNew); } }
//-----------------------------------------------------------------------------
// Purpose:
// Input : nValue -
// pSpin -
// Output : static void
//-----------------------------------------------------------------------------
void IntegerToSpin(int nValue, CSpinButtonCtrl *pSpin) { char szNew[128];
CWnd *pEdit = pSpin->GetBuddy();
if (nValue == NOT_INIT) { szNew[0] = 0; } else { sprintf(szNew, "%d", abs(nValue)); }
pSpin->SetPos(atoi(szNew));
char szCurrent[128]; pEdit->GetWindowText(szCurrent, 128); if (strcmp(szNew, szCurrent) != 0) { pEdit->SetWindowText(szNew); } }
//-----------------------------------------------------------------------------
// Purpose:
// Input : fValue -
// *pWnd -
// Output : static void
//-----------------------------------------------------------------------------
void FloatToWnd(float fValue, CWnd *pWnd) { char szCurrent[128]; char szNew[128];
if(fValue == NOT_INIT) { szNew[0] = 0; } else { sprintf(szNew, "%.3f", fValue); }
pWnd->GetWindowText(szCurrent, 128); if(strcmp(szNew, szCurrent)) pWnd->SetWindowText(szNew); }
//-----------------------------------------------------------------------------
// Purpose: Fetches a string value from a window and places it in a float. The
// float is only modified if there is text in the window.
// Input : pWnd - Window from which to get text.
// fValue - Float in which to place value.
//-----------------------------------------------------------------------------
void TransferToFloat( CWnd *pWnd, float &fValue ) { CString str; pWnd->GetWindowText( str );
if( !str.IsEmpty() ) { fValue = ( float )atof( str ); } }
//-----------------------------------------------------------------------------
// Purpose: Fetches a string value from a window and places it in an integer. The
// integer is only modified if there is text in the window.
// Input : pWnd - Window from which to get text.
// nValue - Float in which to place value.
//-----------------------------------------------------------------------------
void TransferToInteger( CWnd *pWnd, int &nValue ) { CString str; pWnd->GetWindowText( str );
if( !str.IsEmpty() ) { nValue = abs( atoi( str ) ); } }
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::ClickFace( CMapSolid *pSolid, int faceIndex, int cmd, int clickMode ) { // get the face
CMapFace *pFace = pSolid->GetFace( faceIndex ); bool bIsEditable = pSolid->IsEditable();
//
// are updates enabled?
//
CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent(); bool bEnableUpdate = pSheet->HasUpdateEnabled();
SetReadOnly( !bIsEditable );
//
// find the behavior of the page based on the "click mode"
//
switch( clickMode ) { case CFaceEditSheet::ModeAlignToView: { if ( bIsEditable ) { AlignToView( pFace ); } break; }
case CFaceEditSheet::ModeLift: { if( bEnableUpdate ) { UpdateDialogData( pFace ); } break; }
case CFaceEditSheet::ModeLiftSelect: { if ( bEnableUpdate ) { UpdateDialogData(); } break; }
case CFaceEditSheet::ModeApplyLightmapScale: { // Apply the lightmap scale only. Leave everything else alone.
if ( bIsEditable ) { Apply(pFace, FACE_APPLY_LIGHTMAP_SCALE); } break; }
case CFaceEditSheet::ModeApply: case CFaceEditSheet::ModeApplyAll: { if ( bIsEditable ) { int flags = 0;
if (cmd & CFaceEditSheet::cfEdgeAlign) { // Adust the mapping to align with a reference face.
flags |= FACE_APPLY_ALIGN_EDGE; }
if (clickMode == CFaceEditSheet::ModeApplyAll) { // Apply the material, mapping, lightmap scale, etc.
flags |= FACE_APPLY_ALL; } else { // Apply the material only. Leave everything else alone.
flags |= FACE_APPLY_MATERIAL; }
Apply(pFace, flags); } break; } } }
//-----------------------------------------------------------------------------
// Maps the texture onto the face using the 3D view's up and right vectors.
// This can be useful for mapping curvy things like hills because if you don't
// move the 3D view, the texture will line up on any polies you map this way.
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::AlignToView( CMapFace *pFace ) { CView *pActiveView; CMapView3D *pView3D; CFrameWnd *pFrame; Vector vView; if((pFrame = GetMainWnd()->GetActiveFrame()) != NULL) { if((pActiveView = pFrame->GetActiveView()) != NULL) { if(pActiveView->IsKindOf(RUNTIME_CLASS(CMapView3D))) { pView3D = dynamic_cast<CMapView3D*>(pActiveView); if(pView3D) { const CCamera *pCamera = pView3D->GetCamera(); if(pCamera) { Vector right, up; pCamera->GetViewRight(right); pCamera->GetViewUp(up); pCamera->GetViewPoint(vView);
pFace->texture.UAxis.AsVector3D() = right; pFace->texture.VAxis.AsVector3D() = up; pFace->texture.UAxis[3] = DotProduct( right, vView); pFace->texture.VAxis[3] = DotProduct( up, vView); pFace->NormalizeTextureShifts();
pFace->texture.rotate = 0.0f; pFace->texture.scale[0] = g_pGameConfig->GetDefaultTextureScale(); pFace->texture.scale[1] = g_pGameConfig->GetDefaultTextureScale();
pFace->CalcTextureCoords(); } } } } } }
//-----------------------------------------------------------------------------
// Copies the texture coordinate system from pFrom into pTo. Then it rotates
// the texture around the edge until it's as close to pTo's normal as possible.
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::CopyTCoordSystem( const CMapFace *pFrom, CMapFace *pTo ) { Vector axis[2], vEdge, vEdgePt, vOrigin; Vector vFromPt, vNextFromPt; Vector vToPt, vPrevToPt; Vector vTestTextureNormal, vTextureNormal; VMatrix mEdgeRotation, mOriginRotation, mTranslation; float fAngle, fDot; bool bRotate; float fShift[2]; Vector vProjTexNormal; Vector vProjPolyNormal;
// The edge vector lies on both planes.
vEdge = pFrom->plane.normal.Cross(pTo->plane.normal); VectorNormalize( vEdge );
// To find a point on the plane, we make a plane from the edge vector and find the intersection
// between the three planes (without the third plane, there are an infinite number of solutions).
if( PlaneIntersection( VPlane(pFrom->plane.normal, pFrom->plane.dist), VPlane(pTo->plane.normal, pTo->plane.dist), VPlane(vEdge, 0.0f), vEdgePt ) ) { bRotate = true; } else { // Ok, in this case, the planes are parallel so we don't need to rotate around the edge anyway!
bRotate = false; }
// Copy the texture coordinate system.
axis[0] = pFrom->texture.UAxis.AsVector3D(); axis[1] = pFrom->texture.VAxis.AsVector3D(); fShift[0] = pFrom->texture.UAxis[3]; fShift[1] = pFrom->texture.VAxis[3]; vOrigin = axis[0]*fShift[0]*pFrom->texture.scale[0] + axis[1]*fShift[1]*pFrom->texture.scale[1]; vTextureNormal = axis[0].Cross(axis[1]); VectorNormalize(vTextureNormal); if(bRotate) { // Project texture normal and poly normal into the plane of rotation
// to get the angle between them.
vProjTexNormal = vTextureNormal - vEdge * vEdge.Dot(vTextureNormal); vProjPolyNormal = pTo->plane.normal - vEdge * vEdge.Dot(pTo->plane.normal);
VectorNormalize( vProjTexNormal ); VectorNormalize( vProjPolyNormal );
fDot = vProjTexNormal.Dot(vProjPolyNormal); fAngle = (float)(acos(fDot) * (180.0f / M_PI)); if(fDot < 0.0f) fAngle = 180.0f - fAngle;
// Ok, rotate them for the final values.
mEdgeRotation = SetupMatrixAxisRot(vEdge, fAngle); axis[0] = mEdgeRotation.ApplyRotation(axis[0]); axis[1] = mEdgeRotation.ApplyRotation(axis[1]);
// Origin needs translation and rotation to rotate around the edge.
mTranslation = SetupMatrixTranslation(vEdgePt); mOriginRotation = ~mTranslation * mEdgeRotation * mTranslation; vOrigin = mOriginRotation * vOrigin; }
pTo->texture.UAxis.AsVector3D() = axis[0]; pTo->texture.VAxis.AsVector3D() = axis[1];
pTo->texture.UAxis[3] = axis[0].Dot(vOrigin) / pFrom->texture.scale[0]; pTo->texture.VAxis[3] = axis[1].Dot(vOrigin) / pFrom->texture.scale[1]; pTo->NormalizeTextureShifts();
pTo->texture.scale[0] = pFrom->texture.scale[0]; pTo->texture.scale[1] = pFrom->texture.scale[1];
// rotate is only for UI purposes, it doesn't actually do anything.
pTo->texture.rotate = 0.0f;
pTo->CalcTextureCoords(); }
//-----------------------------------------------------------------------------
// Purpose: Applies dialog data to the list of selected faces.
// Input : *pOnlyFace -
// bAll -
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::Apply( CMapFace *pOnlyFace, int flags ) { int i; CString str; float fshiftX = NOT_INIT; float fshiftY = NOT_INIT; float fscaleX = NOT_INIT; float fscaleY = NOT_INIT; float frotate = NOT_INIT; int material = NOT_INIT; int nLightmapScale = NOT_INIT; IEditorTexture *pTex = m_TexturePic.GetTexture(); CMapDoc *pMapDoc = CMapDoc::GetActiveMapDoc();
//
// Get numeric data.
//
if (flags & FACE_APPLY_MAPPING) { TransferToFloat( &m_shiftX, fshiftX ); TransferToFloat( &m_shiftY, fshiftY ); TransferToFloat( &m_scaleX, fscaleX ); TransferToFloat( &m_scaleY, fscaleY ); TransferToFloat( &m_rotate, frotate ); }
if (flags & FACE_APPLY_LIGHTMAP_SCALE) { TransferToInteger( &m_cLightmapScale, nLightmapScale ); }
if ( !pOnlyFace ) { GetHistory()->MarkUndoPosition( NULL, "Apply Face Attributes" );
// make sure we apply everything in this case.
flags |= FACE_APPLY_ALL;
// Keep the solids that we are about to change.
// In the pOnlyFace case we do the Keep before calling ClickFace. Why?
CUtlVector<CMapSolid *> kept; CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent(); for( i = 0; i < pSheet->GetFaceListCount(); i++ ) { CMapSolid *pSolid = pSheet->GetFaceListDataSolid( i ); if ( kept.Find( pSolid ) == -1 ) { GetHistory()->Keep( pSolid ); kept.AddToTail( pSolid ); } } } //
// Run thru stored faces & apply.
//
CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent(); int faceCount = pSheet->GetFaceListCount(); for( i = 0; i < faceCount || pOnlyFace; i++ ) { CMapFace *pFace; if( pOnlyFace ) { pFace = pOnlyFace; } else { pFace = pSheet->GetFaceListDataFace( i ); }
//
// Get values for texture shift, scale, rotate, and material.
//
if ((flags & FACE_APPLY_MAPPING) && (!(flags & FACE_APPLY_ALIGN_EDGE))) { if ( fshiftX != NOT_INIT ) { pFace->texture.UAxis[3] = fshiftX; }
if ( fshiftY != NOT_INIT ) { pFace->texture.VAxis[3] = fshiftY; }
if ( fscaleX != NOT_INIT ) { pFace->texture.scale[0] = fscaleX; } if ( fscaleY != NOT_INIT ) { pFace->texture.scale[1] = fscaleY; }
if ( frotate != NOT_INIT ) { pFace->RotateTextureAxes( frotate - pFace->texture.rotate ); pFace->texture.rotate = frotate; } }
if (flags & FACE_APPLY_CONTENTS_DATA) { if ( material != NOT_INIT ) { pFace->texture.material = material; } }
if (flags & FACE_APPLY_LIGHTMAP_SCALE) { if (nLightmapScale != NOT_INIT) { pFace->texture.nLightmapScale = max( nLightmapScale, 1 ); } }
//
// Update the texture and recalculate texture coordinates.
//
if ((flags & FACE_APPLY_MATERIAL) && (pTex != NULL)) { char szCurrentTexName[MAX_PATH]; char szNewTexName[MAX_PATH];
pFace->GetTextureName( szCurrentTexName ); pTex->GetShortName( szNewTexName );
if( stricmp( szCurrentTexName, szNewTexName ) != 0 ) { pFace->SetTexture( szNewTexName );
CMapClass *pParent = dynamic_cast< CMapClass * >( pFace->GetParent() ); if ( pParent ) { pMapDoc->RemoveFromAutoVisGroups( pParent ); pMapDoc->AddToAutoVisGroup( pParent ); } } }
//
// Copy texture coordinate system.
//
if ((flags & FACE_APPLY_ALIGN_EDGE) && (faceCount >= 1)) { CopyTCoordSystem( pSheet->GetFaceListDataFace( faceCount - 1 ), pFace ); }
//
// Recalculate texture coordinates.
//
pFace->CalcTextureCoords();
//
// Update the face flags.
//
if (flags & FACE_APPLY_CONTENTS_DATA) { //
// Copy the bits from this face into our variables.
//
m_FaceContents = pFace->texture.q2contents; m_FaceSurface = pFace->texture.q2surface;
//
// Update our variables based on the state of the checkboxes.
//
for( int nItem = 0; nItem < sizeof( FaceAttributes ) / sizeof( FaceAttributes[0] ); nItem++ ) { CButton *pButton = ( CButton* )GetDlgItem( FaceAttributes[nItem].uControlID ); if( pButton != NULL ) { int nSet = pButton->GetCheck();
if (nSet == 0) { *FaceAttributes[nItem].puAttribute &= ~FaceAttributes[nItem].uFlag; } else if (nSet == 1) { *FaceAttributes[nItem].puAttribute |= FaceAttributes[nItem].uFlag; } } }
//
// Copy our variables back into this face.
//
pFace->texture.q2contents = m_FaceContents; pFace->texture.q2surface = m_FaceSurface; }
if( pOnlyFace ) { break; } }
pMapDoc->SetModifiedFlag(); }
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pOnlyFace -
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::UpdateDialogData( CMapFace *pOnlyFace ) { BOOL bFirst; int nFaceAlignCount; int nWorldAlignCount; float fshiftX = NOT_INIT; float fshiftY = NOT_INIT; float fscaleX = NOT_INIT; float fscaleY = NOT_INIT; float frotate = NOT_INIT; //float fsmooth = NOT_INIT;
int material = NOT_INIT; int nLightmapScale = NOT_INIT; CString strTexture;
bFirst = TRUE; nFaceAlignCount = 0; nWorldAlignCount = 0;
CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent(); int faceCount = pSheet->GetFaceListCount();
for( int i = 0; i < faceCount || pOnlyFace; i++ ) { CMapFace *pFace;
if( pOnlyFace ) { pFace = pOnlyFace; } else { pFace = pSheet->GetFaceListDataFace( i ); } TEXTURE &t = pFace->texture;
//
// Gather statistics about the texture alignment of all the selected faces.
// This is used later to set the state of the alignment checkboxes.
//
int nAlignment = pFace->GetTextureAlignment(); if (nAlignment & TEXTURE_ALIGN_FACE) { nFaceAlignCount++; }
if (nAlignment & TEXTURE_ALIGN_WORLD) { nWorldAlignCount++; }
//
// First update - copy first face's stuff into edit fields.
//
if (bFirst) { fshiftX = t.UAxis[3]; fshiftY = t.VAxis[3]; fscaleX = t.scale[0]; fscaleY = t.scale[1]; frotate = t.rotate; material = t.material; strTexture = t.texture; nLightmapScale = t.nLightmapScale;
//
// Get the face's orientation. This is used by Apply to make intelligent decisions.
//
m_eOrientation = pFace->GetOrientation(); Assert(m_eOrientation != FACE_ORIENTATION_INVALID);
//
// Set the appropriate checkbox state for the face attributes.
//
m_FaceContents = t.q2contents; m_FaceSurface = t.q2surface;
for (int nItem = 0; nItem < sizeof(FaceAttributes) / sizeof(FaceAttributes[0]); nItem++) { int nSet = ((*FaceAttributes[nItem].puAttribute & FaceAttributes[nItem].uFlag) != 0); CButton *pButton = (CButton *)GetDlgItem(FaceAttributes[nItem].uControlID); if (pButton != NULL) { pButton->SetCheck(nSet); } }
bFirst = FALSE; if (pOnlyFace) // use one face - now break
{ break; } } else { // update fields with face's data
if (t.UAxis[3] != fshiftX) { fshiftX = NOT_INIT; }
if (t.VAxis[3] != fshiftY) { fshiftY = NOT_INIT; }
if (t.scale[0] != fscaleX) { fscaleX = NOT_INIT; }
if (t.scale[1] != fscaleY) { fscaleY = NOT_INIT; }
if (t.rotate != frotate) { frotate = NOT_INIT; }
if (t.material != material) { material = NOT_INIT; }
if (t.nLightmapScale != nLightmapScale) { nLightmapScale = NOT_INIT; }
if (!strTexture.IsEmpty() && strTexture != t.texture) { strTexture = ""; }
//
// Update the checkbox state for the face attributes. If any of this face's
// attributes are different from the current checkbox state, set the checkbox
// to the undefined state.
//
m_FaceContents = t.q2contents; m_FaceSurface = t.q2surface;
for (int nItem = 0; nItem < sizeof(FaceAttributes) / sizeof(FaceAttributes[0]); nItem++) { int nSet = ((*FaceAttributes[nItem].puAttribute & FaceAttributes[nItem].uFlag) != 0); CButton *pButton = (CButton *)GetDlgItem(FaceAttributes[nItem].uControlID); if (pButton != NULL) { if (pButton->GetCheck() != nSet) { pButton->SetButtonStyle(BS_AUTO3STATE); pButton->SetCheck(2); } } } } }
//
// Set the state of the face alignment checkbox.
//
CButton *pFaceAlign = (CButton *)GetDlgItem(IDC_ALIGN_FACE);
if (nFaceAlignCount == 0) { pFaceAlign->SetCheck(0); } else if (nFaceAlignCount == faceCount) { pFaceAlign->SetCheck(1); } else { pFaceAlign->SetCheck(2); }
//
// Set the state of the world alignment checkbox.
//
CButton *pWorldAlign = (CButton *)GetDlgItem(IDC_ALIGN_WORLD);
if (nWorldAlignCount == 0) { pWorldAlign->SetCheck(0); } else if (nWorldAlignCount == faceCount) { pWorldAlign->SetCheck(1); } else { pWorldAlign->SetCheck(2); }
//
// Set up fields.
//
FloatToSpin(fshiftX, (CSpinButtonCtrl*)GetDlgItem(IDC_SPINSHIFTX), FALSE); FloatToSpin(fshiftY, (CSpinButtonCtrl*)GetDlgItem(IDC_SPINSHIFTY), FALSE); IntegerToSpin(nLightmapScale, (CSpinButtonCtrl *)GetDlgItem(IDC_SPIN_LIGHTMAP_SCALE));
FloatToWnd(fscaleX, &m_scaleX); FloatToWnd(fscaleY, &m_scaleY);
FloatToSpin(frotate, (CSpinButtonCtrl*)GetDlgItem(IDC_SPINROTATE), TRUE);
if (!strTexture.IsEmpty()) { SelectTexture( strTexture ); } else { // make empty
m_TextureList.SetCurSel( -1 ); }
//
// if no faces selected -- get selection from texture bar
//
if( faceCount == 0 ) { CString strTexName = GetDefaultTextureName(); SelectTexture( strTexName ); }
//
// Call ctexturebar implementation because OUR implementation sets the
// q2 checkboxes, which flashes the screen a bit (cuz we change them
// again three lines down.)
//
UpdateTexture();
// Update the smoothing group data.
if ( GetMaterialPageTool() == MATERIALPAGETOOL_SMOOTHING_GROUP ) { m_FaceSmoothDlg.UpdateControls(); } }
//-----------------------------------------------------------------------------
// Purpose:
// Input : uCmd -
// Output : Returns TRUE on success, FALSE on failure.
//-----------------------------------------------------------------------------
BOOL CFaceEditMaterialPage::OnAlign( UINT uCmd ) { // Set the material tool current.
SetMaterialPageTool( MATERIALPAGETOOL_MATERIAL );
// mark position in undo stack
GetHistory()->MarkUndoPosition(NULL, "Align texture");
CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent(); int faceCount = pSheet->GetFaceListCount();
for( int i = 0; i < faceCount; i++ ) { CMapFace *pFace = pSheet->GetFaceListDataFace( i );
CMapSolid *pSolid = pSheet->GetFaceListDataSolid( i ); GetHistory()->Keep( pSolid );
switch( uCmd ) { case IDC_ALIGN_WORLD: { pFace->InitializeTextureAxes( TEXTURE_ALIGN_WORLD, INIT_TEXTURE_AXES | INIT_TEXTURE_FORCE ); break; }
case IDC_ALIGN_FACE: { pFace->InitializeTextureAxes( TEXTURE_ALIGN_FACE, INIT_TEXTURE_AXES | INIT_TEXTURE_FORCE ); break; } } }
CMapDoc::GetActiveMapDoc()->SetModifiedFlag();
UpdateDialogData();
return ( TRUE ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::OnHideMask(void) { m_bHideMask = m_cHideMask.GetCheck();
CMapFace::SetShowSelection( m_bHideMask == FALSE );
CMapDoc::GetActiveMapDoc()->UpdateAllViews( MAPVIEW_UPDATE_ONLY_3D | MAPVIEW_UPDATE_OBJECTS | MAPVIEW_UPDATE_COLOR ); }
//-----------------------------------------------------------------------------
// Purpose:
// Input : Extents -
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::GetAllFaceExtents( Extents_t Extents ) { BOOL bFirst = TRUE; Extents_t FaceExtents;
CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent(); int faceCount = pSheet->GetFaceListCount();
for( int nFace = 0; nFace < faceCount; nFace++ ) { CMapFace *pFace = pSheet->GetFaceListDataFace( nFace ); pFace->GetFaceExtents(FaceExtents);
if ((FaceExtents[EXTENTS_XMIN][0] < Extents[EXTENTS_XMIN][0]) || (bFirst)) { Extents[EXTENTS_XMIN] = FaceExtents[EXTENTS_XMIN]; }
if ((FaceExtents[EXTENTS_XMAX][0] > Extents[EXTENTS_XMAX][0]) || (bFirst)) { Extents[EXTENTS_XMAX] = FaceExtents[EXTENTS_XMAX]; }
if ((FaceExtents[EXTENTS_YMIN][1] < Extents[EXTENTS_YMIN][1]) || (bFirst)) { Extents[EXTENTS_YMIN] = FaceExtents[EXTENTS_YMIN]; }
if ((FaceExtents[EXTENTS_YMAX][1] > Extents[EXTENTS_YMAX][1]) || (bFirst)) { Extents[EXTENTS_YMAX] = FaceExtents[EXTENTS_YMAX]; }
if ((FaceExtents[EXTENTS_ZMIN][2] < Extents[EXTENTS_ZMIN][2]) || (bFirst)) { Extents[EXTENTS_ZMIN] = FaceExtents[EXTENTS_ZMIN]; }
if ((FaceExtents[EXTENTS_ZMAX][2] > Extents[EXTENTS_ZMAX][2]) || (bFirst)) { Extents[EXTENTS_ZMAX] = FaceExtents[EXTENTS_ZMAX]; }
bFirst = FALSE; } }
//-----------------------------------------------------------------------------
// Purpose:
// Input : uCmd -
// Output : Returns TRUE on success, FALSE on failure.
//-----------------------------------------------------------------------------
BOOL CFaceEditMaterialPage::OnJustify( UINT uCmd ) { // Set the material tool current.
SetMaterialPageTool( MATERIALPAGETOOL_MATERIAL );
BOOL bTreatManyAsOneFace; Extents_t Extents;
// mark undo position
GetHistory()->MarkUndoPosition( NULL, "Justify texture" );
CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent(); int faceCount = pSheet->GetFaceListCount();
// If multiple faces are selected, use the m_bTreatManyAsOneFace variable to determine
// how to perform the justification.
if( faceCount > 1 ) { bTreatManyAsOneFace = m_bTreatAsOneFace; if( bTreatManyAsOneFace ) { GetAllFaceExtents( Extents ); } } // If only one face is selected, treat it singly.
else { bTreatManyAsOneFace = FALSE; }
for( int i = 0; i < faceCount; i++ ) { CMapFace *pFace = pSheet->GetFaceListDataFace( i );
CMapSolid *pSolid = pSheet->GetFaceListDataSolid( i ); GetHistory()->Keep( pSolid );
if( !bTreatManyAsOneFace ) { pFace->GetFaceExtents( Extents ); }
switch (uCmd) { case IDC_JUSTIFY_TOP: { pFace->JustifyTextureUsingExtents(TEXTURE_JUSTIFY_TOP, Extents); break; }
case IDC_JUSTIFY_BOTTOM: { pFace->JustifyTextureUsingExtents(TEXTURE_JUSTIFY_BOTTOM, Extents); break; }
case IDC_JUSTIFY_LEFT: { pFace->JustifyTextureUsingExtents(TEXTURE_JUSTIFY_LEFT, Extents); break; }
case IDC_JUSTIFY_RIGHT: { pFace->JustifyTextureUsingExtents(TEXTURE_JUSTIFY_RIGHT, Extents); break; }
case IDC_JUSTIFY_CENTER: { pFace->JustifyTextureUsingExtents(TEXTURE_JUSTIFY_CENTER, Extents); break; }
case IDC_JUSTIFY_FITTOFACE: { pFace->JustifyTextureUsingExtents(TEXTURE_JUSTIFY_FIT, Extents); break; } } }
CMapDoc::GetActiveMapDoc()->SetModifiedFlag();
UpdateDialogData();
return(TRUE); }
//-----------------------------------------------------------------------------
// Purpose:
// Input : id -
// Output : Returns TRUE on success, FALSE on failure.
//-----------------------------------------------------------------------------
BOOL CFaceEditMaterialPage::OnSwitchMode( UINT id ) { CWnd *pButton = GetDlgItem( IDC_MODE );
CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent(); pSheet->SetClickMode( id );
switch( id ) { case CFaceEditSheet::ModeLiftSelect: // set
pButton->SetWindowText( "Mode: Lift+Select" ); break; case CFaceEditSheet::ModeLift: pButton->SetWindowText( "Mode: Lift" ); break; case CFaceEditSheet::ModeSelect: pButton->SetWindowText( "Mode: Select" ); break; case CFaceEditSheet::ModeApply: pButton->SetWindowText( "Mode: Apply (texture)" ); break; case CFaceEditSheet::ModeApplyAll: pButton->SetWindowText( "Mode: Apply (all)" ); break; case CFaceEditSheet::ModeAlignToView: pButton->SetWindowText( "Align To View" ); break; }
return TRUE; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::OnMode() { // Set the material tool current.
SetMaterialPageTool( MATERIALPAGETOOL_MATERIAL );
// switch mode -
// LIFT - lift texture from clicked face
// APPLY - apply selected texture to clicked face
// SELECT - mark each face
// LIFT/SELECT - mark clicked faces & lift textures
CMenu menu; menu.CreatePopupMenu(); menu.AppendMenu( MF_STRING, CFaceEditSheet::ModeLiftSelect, "Lift+Select" ); menu.AppendMenu( MF_STRING, CFaceEditSheet::ModeLift, "Lift" ); menu.AppendMenu( MF_STRING, CFaceEditSheet::ModeSelect, "Select" ); menu.AppendMenu( MF_STRING, CFaceEditSheet::ModeApply, "Apply (texture only)" ); menu.AppendMenu( MF_STRING, CFaceEditSheet::ModeApplyAll, "Apply (texture + values)" ); menu.AppendMenu( MF_STRING, CFaceEditSheet::ModeAlignToView, "Align To View" );
// track menu
CWnd *pButton = GetDlgItem( IDC_MODE ); CRect r; pButton->GetWindowRect( r ); menu.TrackPopupMenu( TPM_LEFTALIGN | TPM_LEFTBUTTON, r.left, r.bottom, this, NULL ); }
//-----------------------------------------------------------------------------
// Purpose:
// Input : nSBCode -
// nPos -
// *pScrollBar -
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::OnVScroll( UINT nSBCode, UINT nPos, CScrollBar *pScrollBar ) { Apply(NULL, FACE_APPLY_MAPPING); }
//-----------------------------------------------------------------------------
// Purpose:
// Input : pNMHDR -
// pResult -
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::OnDeltaPosFloatSpin( NMHDR *pNMHDR, LRESULT *pResult ) { NM_UPDOWN *pNMUpDown = ( NM_UPDOWN* )pNMHDR;
CEdit *pEdit = NULL; switch( pNMUpDown->hdr.idFrom ) { case IDC_SPINSCALEY: { pEdit = &m_scaleY; break; }
case IDC_SPINSCALEX: { pEdit = &m_scaleX; break; } }
if( pEdit != NULL ) { CString str; pEdit->GetWindowText(str); float fTmp = atof(str); fTmp += 0.005f * float( pNMUpDown->iDelta ); str.Format( "%.3f", fTmp ); pEdit->SetWindowText( str );
*pResult = 0; } }
//-----------------------------------------------------------------------------
// Purpose:
// Input : nType -
// cx -
// cy -
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::OnSize( UINT nType, int cx, int cy ) { return; }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::OnSelChangeTexture( void ) { // Set the material tool current.
SetMaterialPageTool( MATERIALPAGETOOL_MATERIAL );
if( !m_bInitialized ) { return; }
UpdateTexture();
if( m_pCurTex != NULL ) { m_TextureList.AddMRU( m_pCurTex ); } }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::OnCheckUnCheck( void ) { Apply(NULL, FACE_APPLY_MAPPING); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::OnTreatAsOne( void ) { // Set the material tool current.
SetMaterialPageTool( MATERIALPAGETOOL_MATERIAL );
CButton *pCheck = ( CButton* )GetDlgItem( IDC_TREAT_AS_ONE ); Assert( pCheck != NULL ); m_bTreatAsOneFace = pCheck->GetCheck(); }
//-----------------------------------------------------------------------------
// Purpose: Invokes the texture replace dialog.
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::OnReplace( void ) { // Set the material tool current.
SetMaterialPageTool( MATERIALPAGETOOL_MATERIAL );
//
// get active map doc
//
CMapDoc *pDoc = CMapDoc::GetActiveMapDoc(); if( !pDoc ) return;
// ready the replace dialog
CReplaceTexDlg dlg( pDoc->GetSelection()->GetCount() );
// get the texture to replace -- the default texture?!
dlg.m_strFind = GetDefaultTextureName();
//
// open replace dialog -- modal
//
if( dlg.DoModal() != IDOK ) return; // mark undo position
GetHistory()->MarkUndoPosition( pDoc->GetSelection()->GetList(), "Replace Textures" );
if( dlg.m_bMarkOnly ) { pDoc->SelectObject( NULL, scClear ); // clear selection first
}
dlg.DoReplaceTextures(); }
//-----------------------------------------------------------------------------
// Purpose: Updates the m_pTexture data member based on the current selection.
// Also updates the window text and the texture picture.
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::UpdateTexture( void ) { int iSel = m_TextureList.GetCurSel();
if( iSel == LB_ERR ) { m_TexturePic.SetTexture( NULL ); m_pCurTex = NULL; return; }
m_pCurTex = ( IEditorTexture* )m_TextureList.GetItemDataPtr( iSel ); m_TexturePic.SetTexture( m_pCurTex );
if( m_pCurTex ) { char szBuf[128]; sprintf( szBuf, "%dx%d", m_pCurTex->GetWidth(), m_pCurTex->GetHeight() ); GetDlgItem( IDC_TEXTURESIZE )->SetWindowText( szBuf );
char szTexName[128]; m_pCurTex->GetShortName( szTexName ); SetDefaultTextureName( szTexName ); } }
//-----------------------------------------------------------------------------
// Purpose: Selects a texture by name.
// Input : pszTextureName - Texture name to select.
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::SelectTexture( LPCSTR pszTextureName ) { int nIndex = m_TextureList.SelectString( -1, pszTextureName );
//
// If the texture is not in the list, add it to the list.
//
if( nIndex == LB_ERR ) { IEditorTexture *pTex = g_Textures.FindActiveTexture( pszTextureName ); if( pTex != NULL ) { nIndex = m_TextureList.AddString( pszTextureName ); m_TextureList.SetItemDataPtr( nIndex, pTex ); m_TextureList.SetCurSel( nIndex ); } }
UpdateTexture();
if( nIndex != LB_ERR ) { IEditorTexture *pTex = ( IEditorTexture* )m_TextureList.GetItemDataPtr( nIndex ); m_TextureList.AddMRU( pTex ); } }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::NotifyGraphicsChanged( void ) { if( !IsWindow( m_hWnd ) ) { return; }
// load groups into group list
CString str; int iCurSel = m_TextureGroupList.GetCurSel(); if (iCurSel != LB_ERR) { m_TextureGroupList.GetLBText(iCurSel, str); }
m_TextureGroupList.SetRedraw(FALSE); m_TextureGroupList.ResetContent(); m_TextureGroupList.AddString("All Textures");
int nCount = g_Textures.GroupsGetCount(); if (nCount > 1) { //
// Skip first group ("All Textures").
//
for (int i = 1; i < nCount; i++) { CTextureGroup *pGroup = g_Textures.GroupsGet(i); if (pGroup->GetTextureFormat() == g_pGameConfig->GetTextureFormat()) { const char *p = strstr(pGroup->GetName(), "textures\\"); if (p) { p += strlen("textures\\"); } else { p = pGroup->GetName(); }
m_TextureGroupList.AddString(p); } } } m_TextureGroupList.SetRedraw(TRUE);
if (iCurSel == LB_ERR || m_TextureGroupList.SelectString(-1, str) == LB_ERR) { m_TextureGroupList.SetCurSel(0); } m_TextureGroupList.Invalidate();
char szName[MAX_PATH]; m_TextureGroupList.GetLBText(m_TextureGroupList.GetCurSel(), szName); g_Textures.SetActiveGroup(szName);
//
// This is called when the loaded graphics list is changed,
// or on first init by this->Create().
//
m_TextureList.LoadGraphicList(); UpdateTexture(); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::OnBrowse( void ) { // Set the material tool current.
SetMaterialPageTool( MATERIALPAGETOOL_MATERIAL );
CTextureBrowser *pBrowser = GetMainWnd()->pTextureBrowser;
int iSel = m_TextureList.GetCurSel();
if (iSel != LB_ERR) { IEditorTexture *pTex = (IEditorTexture *)m_TextureList.GetItemDataPtr(iSel); if (pTex != NULL) { char sz[128]; pTex->GetShortName(sz); pBrowser->SetInitialTexture(sz); } }
if (pBrowser->DoModal() == IDOK) { IEditorTexture *pTex = g_Textures.FindActiveTexture(pBrowser->m_cTextureWindow.szCurTexture); if (pTex != NULL) { int iCount = m_TextureList.GetCount(); for (int i = 0; i < iCount; i++) { if (pTex == (IEditorTexture *)m_TextureList.GetItemDataPtr(i)) { m_TextureList.SetCurSel(i); UpdateTexture(); m_TextureList.AddMRU(pTex); break; } } } } }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::OnChangeTextureGroup( void ) { // Set the material tool current.
SetMaterialPageTool( MATERIALPAGETOOL_MATERIAL );
int iGroup = m_TextureGroupList.GetCurSel();
//
// Set the active texture group by name.
//
char szName[MAX_PATH]; m_TextureGroupList.GetLBText(iGroup, szName); g_Textures.SetActiveGroup(szName);
//
// Refresh the texture list contents.
//
m_TextureList.LoadGraphicList(); }
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::OnButtonApply( void ) { // Set the material tool current.
SetMaterialPageTool( MATERIALPAGETOOL_MATERIAL );
Apply(NULL, FACE_APPLY_ALL); }
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
BOOL CFaceEditMaterialPage::OnSetActive( void ) { CMainFrame *pMainFrm = GetMainWnd(); if( !pMainFrm ) return FALSE;
ToolManager()->SetTool( TOOL_FACEEDIT_MATERIAL );
// Set the initial face edit tool state.
SetMaterialPageTool( MATERIALPAGETOOL_MATERIAL );
return CPropertyPage::OnSetActive(); }
//-----------------------------------------------------------------------------
// Purpose: Brings up the smoothing group dialog.
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::OnButtonSmoothingGroups( void ) { if( !m_FaceSmoothDlg.Create( IDD_SMOOTHING_GROUPS, this ) ) return;
m_FaceSmoothDlg.ShowWindow( SW_SHOW );
// Set the initial face edit tool state.
SetMaterialPageTool( MATERIALPAGETOOL_SMOOTHING_GROUP );
return; }
//-----------------------------------------------------------------------------
// Purpose: Apply a random value to the x shift
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::OnButtonShiftXRandom( void ) { IntegerToSpin( rand() % 512, (CSpinButtonCtrl*)GetDlgItem(IDC_SPINSHIFTX) ); Apply(NULL, FACE_APPLY_MAPPING); }
//-----------------------------------------------------------------------------
// Purpose: Apply a random value to the y shift
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::OnButtonShiftYRandom( void ) { IntegerToSpin( rand() % 512, (CSpinButtonCtrl*)GetDlgItem(IDC_SPINSHIFTY) ); Apply(NULL, FACE_APPLY_MAPPING); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::SetMaterialPageTool( unsigned short iMaterialTool ) { if ( m_iMaterialTool == MATERIALPAGETOOL_SMOOTHING_GROUP ) { // Close the window.
m_FaceSmoothDlg.DestroyWindow(); }
// Set the new material tool.
m_iMaterialTool = iMaterialTool; }
//-----------------------------------------------------------------------------
// Purpose: Called when a new material (.vmt file) is detected.
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::NotifyNewMaterial( IEditorTexture *pTex ) { m_TextureList.LoadGraphicList(); UpdateTexture(); }
//-----------------------------------------------------------------------------
// Purpose: Called to set the enabled state of the dialog controls
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::SetReadOnly( bool bIsReadOnly ) { BOOL State = ( bIsReadOnly ? FALSE : TRUE );
m_shiftX.EnableWindow( State ); m_shiftY.EnableWindow( State ); m_scaleX.EnableWindow( State ); m_scaleY.EnableWindow( State ); m_rotate.EnableWindow( State ); m_cLightmapScale.EnableWindow( State ); m_cHideMask.EnableWindow( State ); m_cExpand.EnableWindow( State ); m_TextureList.EnableWindow( State ); m_TextureGroupList.EnableWindow( State );
::EnableWindow( ::GetDlgItem( m_hWnd, IDC_JUSTIFY_LEFT ), State ); ::EnableWindow( ::GetDlgItem( m_hWnd, IDC_JUSTIFY_RIGHT ), State ); ::EnableWindow( ::GetDlgItem( m_hWnd, IDC_JUSTIFY_FITTOFACE ), State ); ::EnableWindow( ::GetDlgItem( m_hWnd, IDC_JUSTIFY_TOP ), State ); ::EnableWindow( ::GetDlgItem( m_hWnd, IDC_JUSTIFY_BOTTOM ), State ); ::EnableWindow( ::GetDlgItem( m_hWnd, IDC_JUSTIFY_CENTER ), State ); ::EnableWindow( ::GetDlgItem( m_hWnd, IDC_TREAT_AS_ONE ), State ); ::EnableWindow( ::GetDlgItem( m_hWnd, IDC_ALIGN_WORLD ), State ); ::EnableWindow( ::GetDlgItem( m_hWnd, IDC_ALIGN_FACE ), State ); ::EnableWindow( ::GetDlgItem( m_hWnd, IDC_BROWSE ), State ); ::EnableWindow( ::GetDlgItem( m_hWnd, IDC_REPLACE ), State ); ::EnableWindow( ::GetDlgItem( m_hWnd, ID_FACEEDIT_APPLY ), State ); ::EnableWindow( ::GetDlgItem( m_hWnd, IDC_MODE ), State ); ::EnableWindow( ::GetDlgItem( m_hWnd, ID_BUTTON_SMOOTHING_GROUPS ), State ); }
//-----------------------------------------------------------------------------
// Purpose: Select all faces that have the currently selected texture applied
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::OnBnClickedFaceMarkButton() { CMapDoc *pDoc = CMapDoc::GetActiveMapDoc(); if (pDoc == NULL) return;
int iSel = m_TextureList.GetCurSel(); if (iSel == LB_ERR) return;
IEditorTexture *pTex = (IEditorTexture *)m_TextureList.GetItemDataPtr(iSel); if (pTex == NULL) return;
char sz[128]; pTex->GetShortName(sz); pDoc->ReplaceTextures(sz, "", TRUE, 0x100, FALSE, FALSE); }
|