//----------------------------------------------------------------------------- // Purpose: // Input : *piIndex - // bUseMRU - // Output : //----------------------------------------------------------------------------- IEditorTexture *CTextureSystem::EnumActiveTextures(int *piIndex, TEXTUREFORMAT eDesiredFormat) const { Assert(piIndex != NULL); if (piIndex != NULL) { if (m_pActiveGroup != NULL) { IEditorTexture *pTex = NULL; do { pTex = m_pActiveGroup->GetTexture(*piIndex); if (pTex != NULL) { (*piIndex)++; if ((eDesiredFormat == tfNone) || (pTex->GetTextureFormat() == eDesiredFormat)) { return(pTex); } } } while (pTex != NULL); } } return(NULL); }
//----------------------------------------------------------------------------- // Purpose: Load any materials that reference this texture. Used so we can refresh a // material's preview image if a relevant .vtf changes. //----------------------------------------------------------------------------- void CTextureSystem::ReloadMaterialsUsingTexture( ITexture *pTestTexture ) { for ( int i=0; i < m_Textures.Count(); i++ ) { IEditorTexture *pEditorTex = m_Textures[i]; IMaterial *pMat = pEditorTex->GetMaterial( false ); if ( !pMat ) continue; IMaterialVar **pParams = pMat->GetShaderParams(); int nParams = pMat->ShaderParamCount(); for ( int iParam=0; iParam < nParams; iParam++ ) { if ( pParams[iParam]->GetType() != MATERIAL_VAR_TYPE_TEXTURE ) continue; ITexture *pTex = pParams[iParam]->GetTextureValue(); if ( !pTex ) continue; if ( pTex == pTestTexture ) { pEditorTex->Reload( true ); } } } }
void CReplaceTexDlg::BrowseTex(int iEdit) { CString strTex; CWnd *pWnd = GetDlgItem(iEdit); pWnd->GetWindowText(strTex); CTextureBrowser *pBrowser = new CTextureBrowser(GetMainWnd()); pBrowser->SetUsed(iEdit == IDC_FIND); pBrowser->SetInitialTexture(strTex); if (pBrowser->DoModal() == IDOK) { IEditorTexture *pTex = g_Textures.FindActiveTexture(pBrowser->m_cTextureWindow.szCurTexture); char szName[MAX_PATH]; if (pTex != NULL) { pTex->GetShortName(szName); } else { szName[0] = '\0'; } pWnd->SetWindowText(szName); } delete pBrowser; }
//----------------------------------------------------------------------------- // Purpose: // Input : wParam - // lParam - // Output : LRESULT //----------------------------------------------------------------------------- LRESULT CTextureBox::OnSelectString(WPARAM wParam, LPARAM lParam) { LPCTSTR pszSelect = LPCTSTR(lParam); int iLen = strlen(pszSelect); int nCount = GetCount(); IEditorTexture *pTex; for(int i = wParam + 1; i < nCount; i++) { pTex = (IEditorTexture *)GetItemDataPtr(i); if (pTex != NULL) { char szName[MAX_PATH]; pTex->GetShortName(szName); if (!stricmp(szName, pszSelect)) { SetCurSel(i); return i; } } } return LB_ERR; }
//----------------------------------------------------------------------------- // Purpose: Sorts the group. //----------------------------------------------------------------------------- void CTextureGroup::Sort(void) { m_Textures.Sort(SortTexturesProc); // Redo the name map. m_TextureNameMap.RemoveAll(); for ( int i=0; i < m_Textures.Count(); i++ ) { IEditorTexture *pTex = m_Textures[i]; m_TextureNameMap.Insert( pTex->GetName(), i ); } // Changing the order means we don't know where we should be loading from m_nTextureToLoad = 0; }
//----------------------------------------------------------------------------- // Quickly find a texture by name. //----------------------------------------------------------------------------- IEditorTexture* CTextureGroup::FindTextureByName( const char *pName, int *piIndex, TEXTUREFORMAT eDesiredFormat ) { int iMapEntry = m_TextureNameMap.Find( pName ); if ( iMapEntry == m_TextureNameMap.InvalidIndex() ) { return NULL; } else { IEditorTexture *pTex = m_Textures[ m_TextureNameMap[iMapEntry] ]; if ((eDesiredFormat == tfNone) || (pTex->GetTextureFormat() == eDesiredFormat)) return pTex; else return NULL; } }
void CTextureSystem::OnFileChange( const char *pFilename, int context, CTextureSystem::EFileType eFileType ) { // It requires the forward slashes later... char fixedSlashes[MAX_PATH]; V_StrSubst( pFilename, "\\", "/", fixedSlashes, sizeof( fixedSlashes ) ); // Get rid of the extension. if ( V_strlen( fixedSlashes ) < 5 ) { Assert( false ); return; } fixedSlashes[ V_strlen( fixedSlashes ) - 4 ] = 0; // Handle it based on what type of file we've got. if ( eFileType == k_eFileTypeVMT ) { IEditorTexture *pTex = FindActiveTexture( fixedSlashes, NULL, FALSE ); if ( pTex ) { pTex->Reload( true ); } else { EnumMaterial( fixedSlashes, context ); IEditorTexture *pTex = FindActiveTexture( fixedSlashes, NULL, FALSE ); if ( pTex ) { GetMainWnd()->m_TextureBar.NotifyNewMaterial( pTex ); GetMainWnd()->GetFaceEditSheet()->NotifyNewMaterial( pTex ); } } } else if ( eFileType == k_eFileTypeVTF ) { // Whether a VTF was added, removed, or modified, we do the same thing.. refresh it and any materials that reference it. ITexture *pTexture = materials->FindTexture( fixedSlashes, TEXTURE_GROUP_UNACCOUNTED, false ); if ( pTexture ) { pTexture->Download( NULL ); ReloadMaterialsUsingTexture( pTexture ); } } }
//----------------------------------------------------------------------------- // Purpose: Replaces any missing textures with the default texture. // Input : pError - //----------------------------------------------------------------------------- static void FixInvalidTexture(MapError *pError) { CMapSolid *pSolid = (CMapSolid *)pError->pObjects[0]; int nFaces = pSolid->GetFaceCount(); for (int i = 0; i < nFaces; i++) { CMapFace *pFace = pSolid->GetFace(i); if (pFace != NULL) { IEditorTexture *pTex = pFace->GetTexture(); if (pTex != NULL) { if (pTex->IsDummy()) { pFace->SetTexture(GetDefaultTextureName()); } } } } }
//----------------------------------------------------------------------------- // 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: // 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: Determines if there are any invalid textures or texture axes on any // face of this solid. Adds an error message to the list box for each // error found. // Input : pSolid - Solid to check. // pList - Pointer to the error list box. // Output : Returns TRUE. //----------------------------------------------------------------------------- static BOOL _CheckInvalidTextures(CMapSolid *pSolid, CListBox *pList) { int nFaces = pSolid->GetFaceCount(); for(int i = 0; i < nFaces; i++) { const CMapFace *pFace = pSolid->GetFace(i); IEditorTexture *pTex = pFace->GetTexture(); if (pTex->IsDummy()) { AddError(pList, ErrorInvalidTexture, (DWORD)pFace->texture.texture, pSolid); return TRUE; } if (!pFace->IsTextureAxisValid()) { AddError(pList, ErrorInvalidTextureAxes, i, pSolid); return(TRUE); } } return(TRUE); }
//----------------------------------------------------------------------------- // Purpose: // Input : pszName - // piIndex - // bDummy - // Output : //----------------------------------------------------------------------------- IEditorTexture *CTextureSystem::FindActiveTexture(LPCSTR pszInputName, int *piIndex, BOOL bDummy) { // The .vmf file format gets confused if there are backslashes in material names, // so make sure they're all using forward slashes here. char szName[MAX_PATH]; Q_StrSubst( pszInputName, "\\", "/", szName, sizeof( szName ) ); const char *pszName = szName; IEditorTexture *pTex = NULL; // // Check the cache first. // if (m_pLastTex && !stricmp(pszName, m_pLastTex->GetName())) { if (piIndex) { *piIndex = m_nLastIndex; } return m_pLastTex; } int iIndex = 0; // We're finding by name, so we don't care what the format is as long as the name matches. if ( m_pActiveGroup ) { pTex = m_pActiveGroup->FindTextureByName( pszName, &iIndex, tfNone ); if ( pTex ) { if ( piIndex ) *piIndex = iIndex; m_pLastTex = pTex; m_nLastIndex = iIndex; return pTex; } } // // Let's try again, this time with \textures\ decoration // TODO: remove this? // { iIndex = 0; char szBuf[512]; sprintf(szBuf, "textures\\%s", pszName); for (int i = strlen(szBuf) -1; i >= 0; i--) { if (szBuf[i] == '/') szBuf[i] = '\\'; } strlwr(szBuf); if ( m_pActiveGroup ) { pTex = m_pActiveGroup->FindTextureByName( szBuf, &iIndex, tfNone ); if ( pTex ) { if ( piIndex ) *piIndex = iIndex; m_pLastTex = pTex; m_nLastIndex = iIndex; return pTex; } } } // // Caller doesn't want dummies. // if (!bDummy) { return(NULL); } Assert(!piIndex); // // Check the list of dummies for a texture with the same name and texture format. // if (m_pActiveContext) { int nDummyCount = m_pActiveContext->Dummies.Count(); for (int nDummy = 0; nDummy < nDummyCount; nDummy++) { IEditorTexture *pTex = m_pActiveContext->Dummies.Element(nDummy); if (!strcmpi(pszName, pTex->GetName())) { m_pLastTex = pTex; m_nLastIndex = -1; return(pTex); } } // // Not found; add a dummy as a placeholder for the missing texture. // pTex = AddDummy(pszName, g_pGameConfig->GetTextureFormat()); } if (pTex != NULL) { m_pLastTex = pTex; m_nLastIndex = -1; } return(pTex); }
//----------------------------------------------------------------------------- // 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(); // // 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 ); } } // // 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; } } CMapDoc::GetActiveMapDoc()->SetModifiedFlag(); }
//----------------------------------------------------------------------------- // Purpose: // Input : lpDrawItemStruct - //----------------------------------------------------------------------------- void CTextureBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { // if(!pGD) // return; CDC dc; dc.Attach(lpDrawItemStruct->hDC); dc.SaveDC(); RECT& r = lpDrawItemStruct->rcItem; int iFontHeight = dc.GetTextExtent("J", 1).cy; if (lpDrawItemStruct->itemID != -1) { IEditorTexture *pTex = (IEditorTexture *)GetItemDataPtr(lpDrawItemStruct->itemID); dc.SetROP2(R2_COPYPEN); CPalette *pOldPalette = NULL; if (pTex != NULL) { pTex->Load(); pOldPalette = dc.SelectPalette(pTex->HasPalette() ? pTex->GetPalette() : g_pGameConfig->Palette, FALSE); dc.RealizePalette(); } COLORREF dwBackColor = RGB(255,255,255); COLORREF dwForeColor = RGB(0,0,0); if (lpDrawItemStruct->itemState & ODS_SELECTED) { dwBackColor = GetSysColor(COLOR_HIGHLIGHT); dwForeColor = GetSysColor(COLOR_HIGHLIGHTTEXT); } // draw background CBrush brush; brush.CreateSolidBrush(dwBackColor); dc.FillRect(&r, &brush); if (pTex == NULL) { // separator dc.SelectStockObject(BLACK_PEN); dc.MoveTo(r.left, r.top+5); dc.LineTo(r.right, r.top+5); } else { char szName[MAX_PATH]; int iLen = pTex->GetShortName(szName); // when we get here, we are drawing a regular graphic. we // check the size of the rectangle - if it's > 32 (just // a nice number), we're drawing an item in the drop list. if ((r.bottom - r.top) > 32) { // draw graphic CRect r2(r); r2.InflateRect(-4, -4); r2.right = r2.left + 64; pTex->Draw(&dc, r2, 0, 0); // draw name dc.SetTextColor(dwForeColor); dc.SetBkMode(TRANSPARENT); dc.TextOut(r2.right + 4, r2.top + 4, szName, iLen); // draw size sprintf(szName, "%dx%d", pTex->GetWidth(), pTex->GetHeight()); dc.TextOut(r2.right + 4, r2.top + 4 + iFontHeight, szName, strlen(szName)); } // if it's < 32, we're drawing the item in the "closed" // combo box, so just draw the name of the texture else { // just draw name - dc.SetTextColor(dwForeColor); dc.SetBkMode(TRANSPARENT); dc.TextOut(r.left + 4, r.top + 2, szName, iLen); } } if (pOldPalette) { dc.SelectPalette(pOldPalette, FALSE); } } else if (lpDrawItemStruct->itemState & ODS_FOCUS) { dc.DrawFocusRect(&r); } dc.RestoreDC(-1); dc.Detach(); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTextureBox::LoadGraphicList(void) { if (g_pGameConfig->GetTextureFormat() == tfNone) { return; } SetRedraw(FALSE); ResetContent(); InitStorage(g_Textures.GetActiveTextureCount() + 32, sizeof(PVOID)); // // Add the MRU textures to the list. // int nStrCount = 0; POSITION pos = g_Textures.MRUGetHeadPosition(); while (pos != NULL) { IEditorTexture *pTex = g_Textures.MRUGetNext(pos, g_pGameConfig->GetTextureFormat()); if (pTex != NULL) { char szStr[MAX_PATH]; pTex->GetShortName(szStr); int err = AddString(szStr); SetItemDataPtr(nStrCount, (void *)pTex); nStrCount++; } } // // Add the MRU seperator to the list, unless the MRU was empty. // if (nStrCount > 0) { AddString(""); SetItemDataPtr(nStrCount, NULL); nStrCount++; } // // Add the rest of the textures to the list. // int nIndex = 0; IEditorTexture *pTex = g_Textures.EnumActiveTextures(&nIndex, g_pGameConfig->GetTextureFormat()); while (pTex != NULL) { char szStr[MAX_PATH]; pTex->GetShortName(szStr); int err = AddString(szStr); assert( (err != CB_ERR) && (err != CB_ERRSPACE) ); SetItemDataPtr(nStrCount, (void *)pTex); nStrCount++; pTex = g_Textures.EnumActiveTextures(&nIndex, g_pGameConfig->GetTextureFormat()); } // // Hack: Select one that doesn't start with '+', '!', or '*', and doesn't have "door" in it. // SetCurSel(0); int nSel = GetCount(); for (int i = 0; i < nSel; i++) { IEditorTexture *pTexSearch = (IEditorTexture *)GetItemDataPtr(i); if (pTexSearch != NULL) { char szName[MAX_PATH]; pTexSearch->GetShortName(szName); if ((szName[0] != 0) && (szName[0] != '*') && (szName[0] != '+') && (szName[0] != '!') && (strstr(szName, "door") == NULL)) { // this one is ok SetCurSel(i); break; } } } SetRedraw(TRUE); Invalidate(); }
//----------------------------------------------------------------------------- // Purpose: Rebuilds the MRU for this texture combo box. //----------------------------------------------------------------------------- void CTextureBox::RebuildMRU(void) { SetRedraw(FALSE); int nCurSel = GetCurSel(); // // Delete current MRUs from list. // int nItems = GetCount(); int nDelimiterIndex = 0; while (nDelimiterIndex < nItems) { // // The first item with a NULL item data pointer is the MRU delimiter. // if (GetItemDataPtr(nDelimiterIndex) == NULL) { break; } nDelimiterIndex++; } // // If the MRU delimiter was found, delete everything before it. // if (nDelimiterIndex != nItems) { do { DeleteString(0); } while(nDelimiterIndex--); } // // Add each texture from the graphics MRU to this list's MRU. // int nCount = 0; POSITION pos = g_Textures.MRUGetHeadPosition(); while (pos != NULL) { IEditorTexture *pTex = g_Textures.MRUGetNext(pos, g_pGameConfig->GetTextureFormat()); if (pTex != NULL) { char szBuf[MAX_PATH]; pTex->GetShortName(szBuf); int nIndex = InsertString(nCount, szBuf); SetItemDataPtr(nIndex, pTex); nCount++; } } // // Add the MRU seperator to the list, unless the MRU was empty. // if (nCount > 0) { int nIndex = InsertString(nCount, ""); SetItemDataPtr(nIndex, NULL); } // // Restore the original selection. // SetCurSel(nCurSel); SetRedraw(TRUE); Invalidate(); }