summaryrefslogtreecommitdiff
path: root/hammer/wadtexture.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /hammer/wadtexture.cpp
downloadarchived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz
archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip
Diffstat (limited to 'hammer/wadtexture.cpp')
-rw-r--r--hammer/wadtexture.cpp720
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;
+ }
+}
+