diff options
Diffstat (limited to 'hammer/prefab3d.cpp')
| -rw-r--r-- | hammer/prefab3d.cpp | 593 |
1 files changed, 593 insertions, 0 deletions
diff --git a/hammer/prefab3d.cpp b/hammer/prefab3d.cpp new file mode 100644 index 0000000..109f0da --- /dev/null +++ b/hammer/prefab3d.cpp @@ -0,0 +1,593 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "stdafx.h" +#include <sys\types.h> +#include <sys\stat.h> +#include "ChunkFile.h" +#include "Prefab3D.h" +#include "Options.h" +#include "History.h" +#include "MapGroup.h" +#include "MapWorld.h" +#include "GlobalFunctions.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CPrefab3D::CPrefab3D() +{ + m_pWorld = NULL; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CPrefab3D::~CPrefab3D() +{ + FreeData(); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPrefab3D::FreeData() +{ + delete m_pWorld; + m_pWorld = NULL; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CMapClass *CPrefab3D::Create(void) +{ + if (!IsLoaded() && (Load() == -1)) + { + return(NULL); + } + + CMapClass *pCopy; + CMapClass *pOriginal; + + // + // Check for just one object - if only one, don't group it. + // + if (m_pWorld->GetChildCount() == 1) + { + + pOriginal = m_pWorld->GetChildren()->Element(0); + pCopy = pOriginal->Copy(false); + } + else + { + // Original object is world + pOriginal = m_pWorld; + + // New object is a new group + pCopy = (CMapClass *)new CMapGroup; + } + + // + // Copy children from original (if any). + // + pCopy->CopyChildrenFrom(pOriginal, false); + + // HACK: must calculate bounds here due to a hack in CMapClass::CopyChildrenFrom + pCopy->CalcBounds(); + + return(pCopy); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : point - Where to center the prefab. +// Output : CMapClass +//----------------------------------------------------------------------------- +CMapClass *CPrefab3D::CreateAtPoint(const Vector &point) +{ + // + // Create the prefab object. It will either be a single object + // or a group containing the prefab objects. + // + CMapClass *pObject = Create(); + + if (pObject != NULL) + { + // + // Move the prefab center to match the given point. + // + Vector move = point; + Vector center; + pObject->GetBoundsCenter(center); + for (int i = 0; i < 3; i++) + { + move[i] -= center[i]; + } + + BOOL bOldLock = Options.SetLockingTextures(TRUE); + pObject->TransMove(move); + Options.SetLockingTextures(bOldLock); + } + + return(pObject); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : +// Output : +//----------------------------------------------------------------------------- +CMapClass *CPrefab3D::CreateAtPointAroundOrigin( Vector const &point ) +{ + // + // Create the prefab object. It will either be a single object + // or a group containing the prefab objects. + // + CMapClass *pObject = Create(); + + if( !pObject ) + return NULL; + + Vector move = point; + + BOOL bOldLock = Options.SetLockingTextures( TRUE ); + pObject->TransMove( move ); + Options.SetLockingTextures( bOldLock ); + + return ( pObject ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pBox - +// Output : +//----------------------------------------------------------------------------- +CMapClass *CPrefab3D::CreateInBox(BoundBox *pBox) +{ + // + // Create the prefab object. It will either be a single object + // or a group containing the prefab objects. + // + CMapClass *pObject = Create(); + + if (pObject != NULL) + { + // + // Scale the prefab to match the box bounds. + // + Vector NewSize; + pBox->GetBoundsSize(NewSize); + + Vector CurSize; + pObject->GetBoundsSize(CurSize); + + Vector scale; + for (int i = 0; i < 3; i++) + { + scale[i] = NewSize[i] / CurSize[i]; + } + + Vector zero(0, 0, 0); + pObject->TransScale(zero, scale); + + // + // Move the prefab center to match the box center. + // + Vector move; + pBox->GetBoundsCenter(move); + + Vector center; + pObject->GetBoundsCenter(center); + for (int i = 0; i < 3; i++) + { + move[i] -= center[i]; + } + + BOOL bOldLock = Options.SetLockingTextures(TRUE); + pObject->TransMove(move); + Options.SetLockingTextures(bOldLock); + } + + return(pObject); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPrefab3D::CenterOnZero() +{ + Vector ptCenter; + m_pWorld->GetBoundsCenter(ptCenter); + ptCenter[0] = -ptCenter[0]; + ptCenter[1] = -ptCenter[1]; + ptCenter[2] = -ptCenter[2]; + + BOOL bOldLock = Options.SetLockingTextures(TRUE); + m_pWorld->TransMove(ptCenter); + Options.SetLockingTextures(bOldLock); +} + + +//----------------------------------------------------------------------------- +// Purpose: Returns true if the prefab data has been loaded from disk, false if not. +//----------------------------------------------------------------------------- +bool CPrefab3D::IsLoaded(void) +{ + return (m_pWorld != NULL); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CPrefabRMF::CPrefabRMF() +{ +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CPrefabRMF::~CPrefabRMF() +{ +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : file - +// dwFlags - +// Output : int +//----------------------------------------------------------------------------- +int CPrefabRMF::DoLoad(std::fstream& file, DWORD dwFlags) +{ + int iRvl; + + GetHistory()->Pause(); + + AddMRU(this); + + if(m_pWorld) + delete m_pWorld; + m_pWorld = new CMapWorld( NULL ); + + // read data + if(dwFlags & lsMAP) + iRvl = m_pWorld->SerializeMAP(file, FALSE); + else + iRvl = m_pWorld->SerializeRMF(file, FALSE); + + // error? + if(iRvl == -1) + { + GetHistory()->Resume(); + return iRvl; + } + + m_pWorld->CalcBounds(TRUE); + + GetHistory()->Resume(); + + return 1; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : file - +// dwFlags - +// Output : int +//----------------------------------------------------------------------------- +int CPrefabRMF::DoSave(std::fstream& file, DWORD dwFlags) +{ + // save world + if(dwFlags & lsMAP) + return m_pWorld->SerializeMAP(file, TRUE); + + return m_pWorld->SerializeRMF(file, TRUE); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : dwFlags - +// Output : int +//----------------------------------------------------------------------------- +int CPrefabRMF::Load(DWORD dwFlags) +{ + // + // Get parent library's file handle. + // + CPrefabLibraryRMF *pLibrary = dynamic_cast <CPrefabLibraryRMF *>(CPrefabLibrary::FindID(dwLibID)); + if (!pLibrary) + { + return -1; + } + + std::fstream &file = pLibrary->m_file; + file.seekg(dwFileOffset); + + return(DoLoad(file, dwFlags)); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pszFilename - +// bLoadNow - +// dwFlags - +// Output : int +//----------------------------------------------------------------------------- +int CPrefabRMF::Init(LPCTSTR pszFilename, BOOL bLoadNow, DWORD dwFlags) +{ + std::fstream file(pszFilename, std::ios::in | std::ios::binary); + + // ensure we're named + memset(szName, 0, sizeof szName); + strncpy(szName, pszFilename, sizeof szName - 1); + return Init(file, bLoadNow, dwFlags); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : file - +// bLoadNow - +// dwFlags - +// Output : int +//----------------------------------------------------------------------------- +int CPrefabRMF::Init(std::fstream &file, BOOL bLoadNow, DWORD dwFlags) +{ + int iRvl = 1; // start off ok + + if(bLoadNow) + { + // do load now + iRvl = DoLoad(file, dwFlags); + } + + if(!szName[0]) + { + // ensure we're named + strcpy(szName, "Prefab"); + } + + return iRvl; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pszFilename - +// dwFlags - +// Output : int +//----------------------------------------------------------------------------- +int CPrefabRMF::Save(LPCTSTR pszFilename, DWORD dwFlags) +{ + std::fstream file(pszFilename, std::ios::out | std::ios::binary); + return Save(file, dwFlags); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : file - +// dwFlags - +// Output : int +//----------------------------------------------------------------------------- +int CPrefabRMF::Save(std::fstream& file, DWORD dwFlags) +{ + if (!IsLoaded() && (Load() == -1)) + { + AfxMessageBox("Couldn't Load prefab to Save it."); + return -1; + } + + return DoSave(file, dwFlags); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CPrefabVMF::CPrefabVMF() +{ +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CPrefabVMF::~CPrefabVMF() +{ +} + + +//----------------------------------------------------------------------------- +// Purpose: Returns true if the prefab data has been loaded from disk, false if not. +//----------------------------------------------------------------------------- +bool CPrefabVMF::IsLoaded(void) +{ + if (m_pWorld == NULL) + { + return false; + } + + // + // We have loaded this prefab at least once this session. Check the file date/time + // against our cached date/time to see if we need to reload it. + // + struct _stat info; + if (_stat(m_szFilename, &info) == 0) + { + if (info.st_mtime > m_nFileTime) + { + return false; + } + } + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : dwFlags - +// Output : int +//----------------------------------------------------------------------------- +int CPrefabVMF::Load(DWORD dwFlags) +{ + // + // Create a new world to hold the loaded objects. + // + if (m_pWorld != NULL) + { + delete m_pWorld; + } + + m_pWorld = new CMapWorld( NULL ); + + // + // Open the file. + // + CChunkFile File; + ChunkFileResult_t eResult = File.Open(m_szFilename, ChunkFile_Read); + + // + // Read the file. + // + if (eResult == ChunkFile_Ok) + { + // + // Set up handlers for the subchunks that we are interested in. + // + CChunkHandlerMap Handlers; + Handlers.AddHandler("world", (ChunkHandler_t)CPrefabVMF::LoadWorldCallback, this); + Handlers.AddHandler("entity", (ChunkHandler_t)CPrefabVMF::LoadEntityCallback, this); + // dvs: Handlers.SetErrorHandler((ChunkErrorHandler_t)CPrefabVMF::HandleLoadError, this); + + File.PushHandlers(&Handlers); + + //CMapDoc::SetLoadingMapDoc( this ); dvs: fix - without this, no displacements in prefabs + + // + // Read the sub-chunks. We ignore keys in the root of the file, so we don't pass a + // key value callback to ReadChunk. + // + while (eResult == ChunkFile_Ok) + { + eResult = File.ReadChunk(); + } + + if (eResult == ChunkFile_EOF) + { + eResult = ChunkFile_Ok; + } + + //CMapDoc::SetLoadingMapDoc( NULL ); + + File.PopHandlers(); + } + + if (eResult == ChunkFile_Ok) + { + m_pWorld->PostloadWorld(); + m_pWorld->CalcBounds(); + + File.Close(); + + // + // Store the file modification time to use as a cache check. + // + struct _stat info; + if (_stat(m_szFilename, &info) == 0) + { + m_nFileTime = info.st_mtime; + } + } + else + { + //GetMainWnd()->MessageBox(File.GetErrorText(eResult), "Error loading prefab", MB_OK | MB_ICONEXCLAMATION); + } + + return(eResult == ChunkFile_Ok); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pFile - +// pData - +// Output : ChunkFileResult_t +//----------------------------------------------------------------------------- +ChunkFileResult_t CPrefabVMF::LoadEntityCallback(CChunkFile *pFile, CPrefabVMF *pPrefab) +{ + CMapEntity *pEntity = new CMapEntity; + + ChunkFileResult_t eResult = pEntity->LoadVMF(pFile); + + if (eResult == ChunkFile_Ok) + { + CMapWorld *pWorld = pPrefab->GetWorld(); + pWorld->AddChild(pEntity); + } + + return(ChunkFile_Ok); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pFile - +// pData - +// Output : ChunkFileResult_t +//----------------------------------------------------------------------------- +ChunkFileResult_t CPrefabVMF::LoadWorldCallback(CChunkFile *pFile, CPrefabVMF *pPrefab) +{ + CMapWorld *pWorld = pPrefab->GetWorld(); + ChunkFileResult_t eResult = pWorld->LoadVMF(pFile); + return(eResult); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pszFilename - +// dwFlags - +// Output : int +//----------------------------------------------------------------------------- +int CPrefabVMF::Save(LPCTSTR pszFilename, DWORD dwFlags) +{ + return 1; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CPrefabVMF::SetFilename(const char *szFilename) +{ + // + // Extract the file name without the path or extension as the prefab name. + // + _splitpath(szFilename, NULL, NULL, szName, NULL); + + strcpy(m_szFilename, szFilename); +} + |