diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /hammer/wadtexture.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'hammer/wadtexture.cpp')
| -rw-r--r-- | hammer/wadtexture.cpp | 720 |
1 files changed, 720 insertions, 0 deletions
diff --git a/hammer/wadtexture.cpp b/hammer/wadtexture.cpp new file mode 100644 index 0000000..75e1d98 --- /dev/null +++ b/hammer/wadtexture.cpp @@ -0,0 +1,720 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Implementation of the IEditorTexture interface for WAD textures. +// +//=============================================================================// + + +#include "stdafx.h" +#include <process.h> +#include <afxtempl.h> +#include <io.h> +#include <sys\stat.h> +#include <fcntl.h> +#include "hammer.h" +#include "MapDoc.h" +#include "Options.h" +#include "MainFrm.h" +#include "GlobalFunctions.h" +#include "WADTypes.h" +#include "BSPFile.h" +#include "bitmap/imageformat.h" // hack : don't want to include this just for ImageFormat +#include "TextureSystem.h" +#include "WADTexture.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + + +#pragma warning(disable:4244) + + +#define _GraphicCacheAllocate(n) malloc(n) + + +//----------------------------------------------------------------------------- +// Stuff for loading WAD3 files. +//----------------------------------------------------------------------------- +typedef struct WAD3miptex_s +{ + char name[16]; + unsigned width, height; + unsigned offsets[4]; // four mip maps stored +} WAD3miptex_t; + + +//----------------------------------------------------------------------------- +// Stuff for loading WAL files. +//----------------------------------------------------------------------------- +typedef struct // Mip Graphic +{ + char name[32]; // Name of the Graphic. + DWORD width; // width of picture, must be a multiple of 8 + DWORD height; // height of picture, must be a multiple of 8 + DWORD offset1; // offset to u_char Pix[width * height] + DWORD offset2; // offset to u_char Pix[width/2 * height/2] + DWORD offset4; // offset to u_char Pix[width/4 * height/4] + DWORD offset8; // offset to u_char Pix[width/8 * height/8] + char animname[32]; + DWORD surface; + DWORD contents; + DWORD value; +} walhdr_t; + + +static char *g_pLoadBuf = NULL; +static int g_nLoadSize = 128 * 1024; + + +extern void ScaleBitmap(CSize sizeSrc, CSize sizeDest, char *src, char *dest); + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : nSize - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +static bool AllocateLoadBuffer(int nSize) +{ + if (nSize > g_nLoadSize) + { + g_nLoadSize = nSize; + + if (g_pLoadBuf != NULL) + { + delete[] g_pLoadBuf; + g_pLoadBuf = NULL; + } + } + + if (g_pLoadBuf == NULL) + { + g_pLoadBuf = new char[g_nLoadSize]; + } + + if (g_pLoadBuf == NULL) + { + return(false); + } + + return(true); +} + + +//----------------------------------------------------------------------------- +// Purpose: Constructor. Initializes data members. +//----------------------------------------------------------------------------- +CWADTexture::CWADTexture(void) +{ + memset(m_szName, 0, sizeof(m_szName)); + memset(m_szFileName, 0, sizeof(m_szFileName)); + + m_datawidth = 0; + m_dataheight = 0; + + m_WALsurface = 0; + m_WALvalue = 0; + m_WALcontents = 0; + + m_ulFileOffset = 0; + m_ulFileID = 0; + + memset(&format, 0, sizeof(format)); + + m_pPalette = NULL; + m_bLocalPalette = false; + + m_nWidth = 0; + m_nHeight = 0; + + m_pData = NULL; +} + + +//----------------------------------------------------------------------------- +// Purpose: Destructor. Frees texture image data and palette. +//----------------------------------------------------------------------------- +CWADTexture::~CWADTexture(void) +{ + // + // Free image data. + // + if (m_pData != NULL) + { + free(m_pData); + m_pData = NULL; + } + + // + // Free palette. + // + if (m_pPalette != NULL) + { + free(m_pPalette); + m_pPalette = NULL; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Returns the full path of the file (WAD, PAK, or WAL) from which this +// texture was loaded. +//----------------------------------------------------------------------------- +const char *CWADTexture::GetFileName( void ) const +{ + return(m_szFileName); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : fd - +// ulFileID - +// bLoad - +// pszName - +// Output : Returns TRUE on success, FALSE on failure. +//----------------------------------------------------------------------------- +BOOL CWADTexture::Init(int fd, DWORD ulFileID, BOOL bLoad, LPCTSTR pszName) +{ + // + // Load header and copy needed data into members variables. + // + GRAPHICSFILESTRUCT FileInfo; + bool bFound = g_Textures.FindGraphicsFile(&FileInfo, ulFileID); + if (!bFound) + { + miptex_t hdr; + _read(fd, (char *)&hdr, sizeof(hdr)); + + m_nWidth = hdr.width; + m_nHeight = hdr.height; + } + else if (FileInfo.format == tfWAD3) + { + WAD3miptex_t hdr; + _read(fd, (char *)&hdr, sizeof(hdr)); + + m_nWidth = hdr.width; + m_nHeight = hdr.height; + + if (m_nHeight < 0) + { + return(FALSE); + } + } + else + { + return(FALSE); + } + + m_ulFileID = ulFileID; + + strcpy(m_szName, pszName); + + if (bFound) + { + strcpy(m_szFileName, FileInfo.filename); + } + + if (m_nWidth * m_nHeight > MAX_TEXTURESIZE) + { + return(FALSE); + } + + if (!m_szName[0]) + { + return(FALSE); + } + + // set offset + m_ulFileOffset = _tell(fd); + + if (bLoad) + { + return(Load()); + } + + return(TRUE); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : +// Output : CPalette * +//----------------------------------------------------------------------------- +CPalette *CWADTexture::GetPalette(void) const +{ + static CPalette pal; + pal.DeleteObject(); + pal.CreatePalette(m_pPalette); + return &pal; +} + + +//----------------------------------------------------------------------------- +// Purpose: Returns a string of comma delimited keywords associated with this +// material. +// Input : pszKeywords - Buffer to receive keywords, NULL to query string length. +// Output : Returns the number of characters in the keyword string. +//----------------------------------------------------------------------------- +int CWADTexture::GetKeywords(char *pszKeywords) const +{ + // + // Set the keywords to the WAD file name. + // + if (pszKeywords != NULL) + { + const char *pszLastSlash = strrchr(m_szFileName, '\\'); + if (pszLastSlash != NULL) + { + pszLastSlash++; + strcpy(pszKeywords, pszLastSlash); + } + else + { + strcpy(pszKeywords, m_szFileName); + } + } + + return(strlen(m_szFileName)); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pszName - +// Output : Returns the length of the short name in characters. +//----------------------------------------------------------------------------- +int CWADTexture::GetShortName(char *pszName) const +{ + char szBuf[MAX_PATH]; + szBuf[0] = '\0'; + + if (pszName == NULL) + { + pszName = szBuf; + } + + if (format == tfWAL) + { + const char *pszCopy = strstr(m_szName, "textures"); + if (pszCopy == NULL) + { + pszCopy = m_szName; + } + else + { + pszCopy += strlen("textures\\"); + } + + strcpy(pszName, pszCopy); + + // remove extension + char *psz = strstr(szBuf, ".wal"); + if (psz != NULL) + { + *psz = 0; + } + } + else + { + strcpy(pszName, m_szName); + } + + return(strlen(pszName)); +} + + +//----------------------------------------------------------------------------- +// Purpose: Resizes a texture to be even powers of 2 in width and height. +// Input : pLoadBuf - +// Output : Returns TRUE on success, FALSE on failure. +//----------------------------------------------------------------------------- +BOOL CWADTexture::AdjustTexture(char *pLoadBuf) +{ + // make height/width power of two + int i, i2; + + for (i = 0; ; i++) + { + i2 = 1 << i; + if (i2 >= m_nWidth) + { + m_datawidth = i2; + break; + } + } + + for (i = 0; ; i++) + { + i2 = 1 << i; + if (i2 >= m_nHeight) + { + m_dataheight = i2; + break; + } + } + + // allocate data + m_pData = _GraphicCacheAllocate(m_datawidth * m_dataheight); + + if (m_pData == NULL) + { + CString errmsg; + errmsg.Format(IDS_ERRLOADGRAPHIC, m_szName); + AfxMessageBox(errmsg); + return FALSE; + } + + // scale up to data + ScaleBitmap(CSize(m_nWidth, m_nHeight), CSize(m_datawidth, m_dataheight), pLoadBuf, (char *)m_pData); + + return TRUE; +} + +bool CWADTexture::IsLoaded() const +{ + return (m_pData != NULL); +} + +//----------------------------------------------------------------------------- +// Purpose: Load data from file associated with m_ulFileID. +// Input : fd - +// hFile - +// Output : Returns TRUE on success, FALSE on failure. +//----------------------------------------------------------------------------- +BOOL CWADTexture::Load(int fd, HANDLE hFile) +{ + if (m_pData) + { + return TRUE; // already loaded + } + + // if fd is -1, get it from base file.. otherwise we've been + // given an fd by caller, so use that in loading + GRAPHICSFILESTRUCT fileInfo; + Q_memset( &fileInfo, 0, sizeof(fileInfo)); + + + if (fd == -1) + { + // find graphics file - different loading based on wad type. + if (!g_Textures.FindGraphicsFile(&fileInfo, m_ulFileID)) + { + return(FALSE); + } + + // keep fd + fd = fileInfo.fd; + + // seek to offset + _lseek(fd, m_ulFileOffset, SEEK_SET); + } + + m_bLocalPalette = FALSE; + + // dvs: if fd != -1, using FileInfo without initializing it!! + if (!AllocateLoadBuffer(m_nWidth * m_nHeight)) + { + AfxMessageBox("Couldn't allocate a texture loading buffer."); + return FALSE; + } + + // load bitmap + _read(fd, g_pLoadBuf, m_nWidth * m_nHeight); + + // + // If WAD3, read the palette. + // + if (fileInfo.format == tfWAD3) + { + WORD nPal; + + _lseek(fd, (m_nWidth / 2 * m_nHeight / 2) + (m_nWidth / 4 * m_nHeight / 4) + (m_nWidth / 8 * m_nHeight / 8), SEEK_CUR); + + _read(fd, &nPal, sizeof nPal); + + Assert(nPal <= 256); + + if ((nPal > 0) && (nPal < 1024)) + { + m_bLocalPalette = TRUE; + + // setup palette + m_pPalette = (LOGPALETTE *)malloc(sizeof(WORD) * 2 + sizeof(PALETTEENTRY) * nPal); + + // fast load - throw into buffer + static unsigned char PalBuf[3 * 1024]; + _read(fd, PalBuf, nPal * 3); + + // convert to LOGPALETTE + for (int i = 0; i < nPal; i++) + { + m_pPalette->palPalEntry[i].peRed = PalBuf[i*3]; + m_pPalette->palPalEntry[i].peGreen = PalBuf[i*3+1]; + m_pPalette->palPalEntry[i].peBlue = PalBuf[i*3+2]; + m_pPalette->palPalEntry[i].peFlags = D3DRMPALETTE_READONLY | PC_NOCOLLAPSE; + } + + m_pPalette->palVersion = 0x300; + m_pPalette->palNumEntries = nPal; + } + } + + AdjustTexture(g_pLoadBuf); + + return TRUE; +} + + +//----------------------------------------------------------------------------- +// Purpose: If the buffer pointer passed in is not NULL, copies the image data +// in RGB format to the buffer +// Input : pImageRGB - Pointer to buffer that receives the image data. If the +// pointer is NULL, no data is copied, only the data size is returned. +// Output : Returns a the size of the RGB image in bytes. +//----------------------------------------------------------------------------- +int CWADTexture::GetImageDataRGB( void *pImageRGB ) +{ + if ( pImageRGB != NULL ) + { + Load(); + + unsigned char *puchImage = ( unsigned char * )m_pData; + unsigned char *pIndex = ( unsigned char * )pImageRGB; + + for (int y = 0; y < m_dataheight; y++) + { + for (int x = 0; x < m_datawidth; x++) + { + unsigned char chPaletteEntry = puchImage[y * m_datawidth + x]; + + *pIndex = m_pPalette->palPalEntry[chPaletteEntry].peRed; + pIndex++; + + *pIndex = m_pPalette->palPalEntry[chPaletteEntry].peGreen; + pIndex++; + + *pIndex = m_pPalette->palPalEntry[chPaletteEntry].peBlue; + pIndex++; + } + } + } + + return( m_datawidth * m_dataheight * 3 ); +} + + +//----------------------------------------------------------------------------- +// Purpose: If the buffer pointer passed in is not NULL, copies the image data +// in RGBA format to the buffer +// Input : pImageRGBA - Pointer to buffer that receives the image data. If the +// pointer is NULL, no data is copied, only the data size is returned. +// Output : Returns a the size of the RGBA image in bytes. +//----------------------------------------------------------------------------- +int CWADTexture::GetImageDataRGBA( void *pImageRGBA ) +{ + if ( pImageRGBA != NULL ) + { + unsigned char *puchImage = (unsigned char *)m_pData; + unsigned char *pIndex = (unsigned char *)pImageRGBA; + + for (int y = 0; y < m_dataheight; y++) + { + for (int x = 0; x < m_datawidth; x++) + { + unsigned char chPaletteEntry = puchImage[y * m_datawidth + x]; + + *pIndex = m_pPalette->palPalEntry[chPaletteEntry].peRed; + pIndex++; + + *pIndex = m_pPalette->palPalEntry[chPaletteEntry].peGreen; + pIndex++; + + *pIndex = m_pPalette->palPalEntry[chPaletteEntry].peBlue; + pIndex++; + + *pIndex = 0; + pIndex++; + } + } + } + + return( m_datawidth * m_dataheight * 4 ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : size - +//----------------------------------------------------------------------------- +void CWADTexture::GetSize(SIZE& size) +{ + size.cx = m_nWidth; + size.cy = m_nHeight; +} + + +//----------------------------------------------------------------------------- +// Purpose: Draws white "No Image" text in a black rectangle. +// Input : pDC - +// rect - +// iFontHeight - +// dwFlags - +//----------------------------------------------------------------------------- +void CWADTexture::DrawNoImage(CDC *pDC, RECT& rect, int iFontHeight) +{ + // draw "no data" + CFont *pOldFont = (CFont*) pDC->SelectStockObject(ANSI_VAR_FONT); + COLORREF cr = pDC->SetTextColor(RGB(0xff, 0xff, 0xff)); + COLORREF cr2 = pDC->SetBkColor(RGB(0, 0, 0)); + + // draw black rect first + pDC->FillRect(&rect, CBrush::FromHandle(HBRUSH(GetStockObject(BLACK_BRUSH)))); + + // then text + pDC->TextOut(rect.left+2, rect.top+2, "No Image", 8); + pDC->SelectObject(pOldFont); + pDC->SetTextColor(cr); + pDC->SetBkColor(cr2); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pDC - +// rect - +// iFontHeight - +// dwFlags - +//----------------------------------------------------------------------------- +void CWADTexture::Draw(CDC *pDC, RECT& rect, int iFontHeight, int iIconHeight, DrawTexData_t &DrawTexData) +{ + if (!m_nWidth) + { + DrawNoImage(pDC, rect, iFontHeight); + return; + } + + // no data - + if (!m_pData) + { + // try to load - + if (!Load()) + { + DrawNoImage(pDC, rect, iFontHeight); + return; + } + } + + static struct + { + BITMAPINFOHEADER bmih; + unsigned short colorindex[256]; + } bmi; + + BITMAPINFOHEADER& bmih = bmi.bmih; + memset(&bmih, 0, sizeof bmih); + bmih.biSize = sizeof(bmih); + bmih.biWidth = m_datawidth; + bmih.biHeight = -m_dataheight; // top-down DIB + bmih.biCompression = BI_RGB; + bmih.biBitCount = 8; + + bmih.biPlanes = 1; + + static BOOL bInit = FALSE; + if (!bInit) + { + bInit = TRUE; + for (int i = 0; i < 256; i++) + { + bmi.colorindex[i] = i; + } + } + + int dest_width = rect.right - rect.left; + int dest_height = rect.bottom - rect.top; + + if (DrawTexData.nFlags & drawCaption) + { + dest_height -= iFontHeight + 4; + } + + if (!(DrawTexData.nFlags & drawResizeAlways)) + { + if (m_nWidth < dest_width) + { + dest_width = m_nWidth; + } + + if (m_nHeight < dest_height) + { + dest_height = m_nHeight; + } + } + + SetStretchBltMode(pDC->m_hDC, COLORONCOLOR); + + if (StretchDIBits(pDC->m_hDC, rect.left, rect.top, dest_width, dest_height, 0, 0, m_datawidth, m_dataheight, m_pData, (BITMAPINFO*)&bmi, DIB_PAL_COLORS, SRCCOPY) == GDI_ERROR) + { + Msg(mwError, "CWADTexture::Draw(): StretchDIBits failed."); + } + + // + // Caption. + // + if (DrawTexData.nFlags & drawCaption) + { + // draw background for name + CBrush brCaption(RGB(0, 0, 255)); + CRect rcCaption(rect); + + rcCaption.top = rcCaption.bottom - (iFontHeight + 5); + pDC->FillRect(rcCaption, &brCaption); + + // draw name + char szShortName[MAX_PATH]; + int iLen = GetShortName(szShortName); + pDC->TextOut(rect.left, rect.bottom - (iFontHeight + 4), szShortName, iLen); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Frees the static load buffer. +//----------------------------------------------------------------------------- +bool CWADTexture::Initialize(void) +{ + return(AllocateLoadBuffer(g_nLoadSize)); +} + + +//----------------------------------------------------------------------------- +// Purpose: Loads this texture from disk, if it is not already loaded. +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool CWADTexture::Load( void ) +{ + if (m_pData != NULL) + { + // Already loaded. + return(true); + } + + return(Load(-1, NULL) == TRUE); +} + + +//----------------------------------------------------------------------------- +// Purpose: Frees the static load buffer. +//----------------------------------------------------------------------------- +void CWADTexture::ShutDown(void) +{ + if (g_pLoadBuf != NULL) + { + delete[] g_pLoadBuf; + g_pLoadBuf = NULL; + } +} + |