Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

724 lines
18 KiB

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "stdafx.h"
#include <oleauto.h>
#include <oaidl.h>
#if _MSC_VER < 1300
#include <afxpriv.h>
#endif
#include "CustomMessages.h"
#include "GlobalFunctions.h"
#include "History.h"
#include "FaceEditSheet.h"
#include "IEditorTexture.h"
#include "MainFrm.h"
#include "MapDoc.h"
#include "MapWorld.h"
#include "ReplaceTexDlg.h"
#include "TextureBrowser.h"
#include "TextureSystem.h"
#include "hammer.h"
#include "Selection.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
static LPCTSTR pszIniSection = "Texture Browser";
CStringArray CTextureBrowser::m_FilterHistory;
int CTextureBrowser::m_nFilterHistory;
char CTextureBrowser::m_szLastKeywords[MAX_PATH];
BEGIN_MESSAGE_MAP(CTextureBrowser, CDialog)
//{{AFX_MSG_MAP(CTextureBrowser)
ON_WM_SIZE()
ON_CBN_SELENDOK(IDC_TEXTURESIZE, OnSelendokTexturesize)
ON_WM_CLOSE()
ON_WM_TIMER()
ON_CBN_EDITCHANGE(IDC_FILTER, OnChangeFilterOrKeywords)
ON_CBN_SELENDOK(IDC_FILTER, OnUpdateFiltersNOW)
ON_CBN_EDITCHANGE(IDC_KEYWORDS, OnChangeFilterOrKeywords)
ON_CBN_SELENDOK(IDC_KEYWORDS, OnUpdateKeywordsNOW)
ON_BN_CLICKED(IDC_FILTER_OPAQUE, OnFilterOpaque)
ON_BN_CLICKED(IDC_FILTER_TRANSLUCENT, OnFilterTranslucent)
ON_BN_CLICKED(IDC_FILTER_SELFILLUM, OnFilterSelfIllum)
ON_BN_CLICKED(IDC_FILTER_ENVMASK, OnFilterEnvmask)
ON_BN_CLICKED(IDC_SHOW_ERROR, OnShowErrors)
ON_BN_CLICKED(IDC_USED, OnUsed)
ON_BN_CLICKED(IDC_MARK, OnMark)
ON_BN_CLICKED(IDC_REPLACE, OnReplace)
ON_BN_CLICKED(IDC_TEXTURES_OPEN_SOURCE, OnOpenSource)
ON_BN_CLICKED(IDC_TEXTURES_RELOAD, OnReload)
ON_MESSAGE(TWN_SELCHANGED, OnTexturewindowSelchange)
ON_MESSAGE(TWN_LBUTTONDBLCLK, OnTextureWindowDblClk)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//-----------------------------------------------------------------------------
// Purpose:
// Input : pParent -
//-----------------------------------------------------------------------------
CTextureBrowser::CTextureBrowser(CWnd* pParent)
: CDialog(IDD, pParent)
{
m_szNameFilter[0] = '\0';
szInitialTexture[0] = '\0';
m_bFilterChanged = FALSE;
m_uLastFilterChange = 0xffffffff;
m_bUsed = FALSE;
m_szLastKeywords[0] = '\0';
}
//-----------------------------------------------------------------------------
// Purpose: Handles resize messages. Moves the child windows to the proper positions.
// Input : nType -
// cx -
// cy -
//-----------------------------------------------------------------------------
void CTextureBrowser::OnSize(UINT nType, int cx, int cy)
{
if (nType == SIZE_MINIMIZED || !IsWindow(m_cTextureWindow.m_hWnd))
{
CDialog::OnSize(nType, cx, cy);
return;
}
// reposition controls
CRect clientrect;
GetClientRect(&clientrect);
CRect CtrlRect;
GetDlgItem(IDC_CONTROLHEIGHT)->GetWindowRect(&CtrlRect);
int iControlHeight = (CtrlRect.bottom - CtrlRect.top);
int iThisCtrlHeight;
//
// Resize the texture window.
//
CtrlRect = clientrect;
CtrlRect.bottom -= iControlHeight;
m_cTextureWindow.MoveWindow(CtrlRect);
clientrect.top = (clientrect.bottom - iControlHeight) + 4;
//
// Move the top row of controls to the correct vertical position,
// leaving their horizontal position as it was set up in the dialog.
//
int iIDList[] =
{
IDC_TEXTURESIZE,
IDC_SIZEPROMPT,
IDC_FILTERPROMPT,
IDC_FILTER,
IDC_CURNAME,
IDC_FILTER_OPAQUE,
IDC_FILTER_SELFILLUM,
IDC_SHOW_ERROR,
IDC_TEXTURES_OPEN_SOURCE,
-1
};
for (int i = 0; iIDList[i] != -1; i++)
{
CWnd *pWnd = GetDlgItem(iIDList[i]);
Assert(pWnd != NULL);
if (pWnd != NULL)
{
pWnd->GetWindowRect(&CtrlRect);
ScreenToClient(CtrlRect);
iThisCtrlHeight = CtrlRect.bottom - CtrlRect.top;
CtrlRect.top = clientrect.top;
CtrlRect.bottom = CtrlRect.top + iThisCtrlHeight;
pWnd->MoveWindow(CtrlRect);
}
}
//
// Move the middle row of controls to the correct vertical position,
// leaving their horizontal position as it was set up in the dialog.
//
int iIDList2[] =
{
IDC_KEYWORDS_TEXT,
IDC_KEYWORDS,
IDC_USED,
IDC_MARK,
IDC_REPLACE,
IDC_CURDESCRIPTION,
IDC_FILTER_TRANSLUCENT,
IDC_FILTER_ENVMASK,
IDC_TEXTURES_RELOAD,
-1
};
for (int i = 0; iIDList2[i] != -1; i++)
{
CWnd *pWnd = GetDlgItem(iIDList2[i]);
Assert(pWnd != NULL);
if (pWnd != NULL)
{
pWnd->GetWindowRect(&CtrlRect);
ScreenToClient(CtrlRect);
iThisCtrlHeight = CtrlRect.bottom - CtrlRect.top;
CtrlRect.top = clientrect.top + iControlHeight / 2 + 2;
CtrlRect.bottom = CtrlRect.top + iThisCtrlHeight;
pWnd->MoveWindow(CtrlRect);
}
}
CDialog::OnSize(nType, cx, cy);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : bUsed -
//-----------------------------------------------------------------------------
void CTextureBrowser::SetUsed(BOOL bUsed)
{
m_bUsed = bUsed;
if (m_bUsed)
{
CUsedTextureList Used;
GetActiveWorld()->GetUsedTextures(Used);
m_TextureSubList.RemoveAll();
for (int i = 0; i < Used.Count(); i++)
{
TextureWindowTex_t Tex;
Tex.pTex = Used.Element(i).pTex;
Tex.nUsageCount = Used.Element(i).nUsageCount;
m_TextureSubList.AddToTail(Tex);
}
m_cTextureWindow.SetSpecificList(&m_TextureSubList);
}
else
{
m_cTextureWindow.SetSpecificList(NULL);
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTextureBrowser::OnClose(void)
{
WriteSettings();
SaveAndExit();
CDialog::OnCancel();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTextureBrowser::OnCancel()
{
WriteSettings();
SaveAndExit();
CDialog::OnCancel();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTextureBrowser::OnUsed()
{
if(!GetActiveWorld())
return;
SetUsed(m_cUsed.GetCheck());
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pszTexture -
//-----------------------------------------------------------------------------
void CTextureBrowser::SetInitialTexture(LPCTSTR pszTexture)
{
strcpy(szInitialTexture, pszTexture);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTextureBrowser::OnSelendokTexturesize()
{
// change size of textures the texutre window displays
int iCurSel = m_cSizeList.GetCurSel();
switch(iCurSel)
{
case 0:
m_cTextureWindow.SetDisplaySize(128);
break;
case 1:
m_cTextureWindow.SetDisplaySize(256);
break;
case 2:
m_cTextureWindow.SetDisplaySize(512);
break;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
BOOL CTextureBrowser::OnInitDialog()
{
CDialog::OnInitDialog();
// Iterate all the active textures for debugging.
//int nCount = g_Textures.GetActiveTextureCount();
//for (int nTexture = 0; nTexture < nCount; nTexture++)
//{
// IEditorTexture *pTexture = g_Textures.GetActiveTexture(nTexture);
// const char *pszName = pTexture->GetName();
// DBG("%d: %s\n", nTexture, pszName);
//}
m_cSizeList.SubclassDlgItem(IDC_TEXTURESIZE, this);
m_cFilter.SubclassDlgItem(IDC_FILTER, this);
m_cKeywords.SubclassDlgItem(IDC_KEYWORDS, this);
m_cCurName.SubclassDlgItem(IDC_CURNAME, this);
m_cCurDescription.SubclassDlgItem(IDC_CURDESCRIPTION, this);
m_cUsed.SubclassDlgItem(IDC_USED, this);
m_FilterOpaque.SubclassDlgItem(IDC_FILTER_OPAQUE, this);
m_FilterTranslucent.SubclassDlgItem(IDC_FILTER_TRANSLUCENT, this);
m_FilterSelfIllum.SubclassDlgItem(IDC_FILTER_SELFILLUM, this);
m_FilterEnvMask.SubclassDlgItem(IDC_FILTER_ENVMASK, this);
m_ShowErrors.SubclassDlgItem(IDC_SHOW_ERROR, this);
m_FilterOpaque.SetCheck( true );
m_FilterTranslucent.SetCheck( true );
m_FilterSelfIllum.SetCheck( true );
m_FilterEnvMask.SetCheck( true );
m_ShowErrors.SetCheck( true );
//
// Create CTextureWindow that takes up area of dummy control.
//
{
RECT r;
GetDlgItem( IDC_BROWSERDUMMY )->GetClientRect( &r );
m_cTextureWindow.Create( this, r );
}
// Show everything initially
m_cTextureWindow.SetTypeFilter( ~0, true );
//
// Add latest history to the filter combo.
//
for (int i = 0; i < m_nFilterHistory; i++)
{
m_cFilter.AddString(m_FilterHistory[i]);
}
//
// Set the name filter unless one was explicitly specified.
//
if (m_szNameFilter[0] == '\0')
{
//
// No name filter specified. Use whatever is on top of the history.
//
if (m_cFilter.GetCount() > 0)
{
m_cFilter.GetLBText(0, m_szNameFilter);
m_cFilter.SetCurSel(0);
}
}
m_cFilter.SetWindowText(m_szNameFilter);
m_cTextureWindow.SetNameFilter(m_szNameFilter);
//
// Done with the name filter; clear it for next time.
//
m_szNameFilter[0] = '\0';
// Add the global list of keywords to the keywords combo.
for( int i=0; i< g_Textures.GetNumKeywords(); i++ )
{
m_cKeywords.AddString( g_Textures.GetKeyword(i) );
}
//
// Set the keyword filter.
//
m_cKeywords.SetWindowText(m_szLastKeywords);
m_cTextureWindow.SetKeywords(m_szLastKeywords);
m_cUsed.SetCheck(m_bUsed);
// Refresh the list of used textures if enabled.
if (m_bUsed)
{
SetUsed(TRUE);
}
CWinApp *pApp = AfxGetApp();
CString str = pApp->GetProfileString(pszIniSection, "Position");
if (!str.IsEmpty())
{
RECT r;
sscanf(str, "%d %d %d %d", &r.left, &r.top, &r.right, &r.bottom);
if (r.left < 0)
{
ShowWindow(SW_SHOWMAXIMIZED);
}
else
{
MoveWindow(r.left, r.top, r.right-r.left, r.bottom-r.top, FALSE);
}
}
int iSize = pApp->GetProfileInt(pszIniSection, "ShowSize", 0);
m_cSizeList.SetCurSel(iSize);
OnSelendokTexturesize();
if (szInitialTexture[0])
{
m_cTextureWindow.SelectTexture(szInitialTexture);
}
m_cTextureWindow.ShowWindow(SW_SHOW);
SetTimer(1, 500, NULL);
m_cFilter.SetFocus();
return(FALSE);
}
//-----------------------------------------------------------------------------
// Purpose: Called when either the filter combo or the keywords combo text changes.
//-----------------------------------------------------------------------------
void CTextureBrowser::OnChangeFilterOrKeywords()
{
//
// Start a timer to repaint the texture window using the new filters.
//
m_uLastFilterChange = time(NULL);
m_bFilterChanged = TRUE;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTextureBrowser::OnUpdateFiltersNOW()
{
m_uLastFilterChange = time(NULL);
m_bFilterChanged = FALSE;
CString str;
int iSel = m_cFilter.GetCurSel();
m_cFilter.GetLBText(iSel, str);
m_cTextureWindow.SetNameFilter(str);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTextureBrowser::OnUpdateKeywordsNOW()
{
m_uLastFilterChange = time(NULL);
m_bFilterChanged = FALSE;
CString str;
int iSel = m_cKeywords.GetCurSel();
m_cKeywords.GetLBText(iSel, str);
m_cTextureWindow.SetKeywords(str);
}
//-----------------------------------------------------------------------------
// Purpose: Timer used to control updates when the filter terms change.
// Input : nIDEvent -
//-----------------------------------------------------------------------------
void CTextureBrowser::OnTimer(UINT nIDEvent)
{
if (!m_bFilterChanged)
{
return;
}
if ((time(NULL) - m_uLastFilterChange) > 0)
{
KillTimer(nIDEvent);
m_bFilterChanged = FALSE;
m_cTextureWindow.EnableUpdate(false);
CString str;
m_cFilter.GetWindowText(str);
m_cTextureWindow.SetNameFilter(str);
m_cTextureWindow.EnableUpdate(true);
m_cKeywords.GetWindowText(str);
m_cTextureWindow.SetKeywords(str);
SetTimer(nIDEvent, 500, NULL);
}
CDialog::OnTimer(nIDEvent);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : wParam -
// lParam -
// Output : LRESULT
//-----------------------------------------------------------------------------
LRESULT CTextureBrowser::OnTextureWindowDblClk(WPARAM wParam, LPARAM lParam)
{
WriteSettings();
SaveAndExit();
return(0);
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : wParam -
// lParam -
// Output : LRESULT
//-----------------------------------------------------------------------------
LRESULT CTextureBrowser::OnTexturewindowSelchange(WPARAM wParam, LPARAM lParam)
{
IEditorTexture *pTex = g_Textures.FindActiveTexture(m_cTextureWindow.szCurTexture);
CString str;
char szName[MAX_PATH];
if (pTex != NULL)
{
// create description of texture
str.Format("%dx%d", pTex->GetWidth(), pTex->GetHeight());
pTex->GetShortName(szName);
}
else
{
szName[0] = '\0';
}
m_cCurName.SetWindowText(szName);
m_cCurDescription.SetWindowText(str);
return(0);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTextureBrowser::WriteSettings()
{
// write position information
CWinApp *pApp = AfxGetApp();
CString str;
CRect r;
GetWindowRect(r);
str.Format("%d %d %d %d", r.left, r.top, r.right, r.bottom);
pApp->WriteProfileString(pszIniSection, "Position", str);
pApp->WriteProfileInt(pszIniSection, "ShowSize", m_cSizeList.GetCurSel());
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTextureBrowser::SaveAndExit()
{
// save current filter string
CString str;
m_cFilter.GetWindowText(str);
int i;
for(i = 0; i < m_nFilterHistory; i++)
{
if(!m_FilterHistory[i].CompareNoCase(str))
break;
}
if(i != m_nFilterHistory) // delete first
{
m_FilterHistory.RemoveAt(i);
--m_nFilterHistory;
}
m_FilterHistory.InsertAt(0, str);
++m_nFilterHistory;
m_cKeywords.GetWindowText(m_szLastKeywords, sizeof(m_szLastKeywords));
EndDialog(IDOK);
}
//-----------------------------------------------------------------------------
// Purpose: Sets a name filter that will override whatever is in the history
// for this browser session.
//-----------------------------------------------------------------------------
void CTextureBrowser::SetFilter(const char *pszFilter)
{
if (pszFilter)
{
strcpy(m_szNameFilter, pszFilter);
}
else
{
m_szNameFilter[0] = '\0';
}
}
//-----------------------------------------------------------------------------
// Filter buttons
//-----------------------------------------------------------------------------
void CTextureBrowser::OnFilterOpaque(void)
{
bool checked = m_FilterOpaque.GetCheck( ) != 0;
m_cTextureWindow.SetTypeFilter( CTextureWindow::TYPEFILTER_OPAQUE, checked );
}
void CTextureBrowser::OnFilterTranslucent(void)
{
bool checked = m_FilterTranslucent.GetCheck( ) != 0;
m_cTextureWindow.SetTypeFilter( CTextureWindow::TYPEFILTER_TRANSLUCENT, checked );
}
void CTextureBrowser::OnFilterSelfIllum(void)
{
bool checked = m_FilterSelfIllum.GetCheck( ) != 0;
m_cTextureWindow.SetTypeFilter( CTextureWindow::TYPEFILTER_SELFILLUM, checked );
}
void CTextureBrowser::OnFilterEnvmask(void)
{
bool checked = m_FilterEnvMask.GetCheck( ) != 0;
m_cTextureWindow.SetTypeFilter( CTextureWindow::TYPEFILTER_ENVMASK, checked );
}
void CTextureBrowser::OnShowErrors(void)
{
bool checked = m_ShowErrors.GetCheck( ) != 0;
m_cTextureWindow.ShowErrors( checked );
}
//-----------------------------------------------------------------------------
// Opens the source file:
//-----------------------------------------------------------------------------
void CTextureBrowser::OnOpenSource()
{
if ( m_cTextureWindow.szCurTexture[0] )
{
g_Textures.OpenSource( m_cTextureWindow.szCurTexture );
}
}
void CTextureBrowser::OnReload()
{
if ( m_cTextureWindow.szCurTexture[0] )
{
g_Textures.ReloadTextures( m_cTextureWindow.szCurTexture );
m_cTextureWindow.Invalidate();
if (GetMainWnd())
{
GetMainWnd()->m_TextureBar.NotifyGraphicsChanged();
GetMainWnd()->m_pFaceEditSheet->NotifyGraphicsChanged();
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTextureBrowser::OnMark(void)
{
CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
if (pDoc != NULL)
{
pDoc->ReplaceTextures(m_cTextureWindow.szCurTexture, "", TRUE, 0x100, FALSE, FALSE);
EndDialog(IDOK);
}
}
//-----------------------------------------------------------------------------
// Purpose: Invokes the replace texture dialog.
//-----------------------------------------------------------------------------
void CTextureBrowser::OnReplace(void)
{
CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
if(!pDoc)
return;
CReplaceTexDlg dlg(pDoc->GetSelection()->GetCount());
dlg.m_strFind = m_cTextureWindow.szCurTexture;
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();
//EndDialog(IDOK);
if (m_bUsed)
{
SetUsed(TRUE);
}
}
//-----------------------------------------------------------------------------
// Purpose: Sets the texture format for browsing. Only textures of the given
// format will be visible in the browse window. By default, this
// format will be the same as the current active texture format.
// Input : eTextureFormat - Texture format to use for browsing.
//-----------------------------------------------------------------------------
void CTextureBrowser::SetTextureFormat(TEXTUREFORMAT eTextureFormat)
{
m_cTextureWindow.SetTextureFormat(eTextureFormat);
}