//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #include "stdafx.h" #include #include #if _MSC_VER < 1300 #include #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 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); }