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/mappath.cpp | |
| download | archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip | |
Diffstat (limited to 'hammer/mappath.cpp')
| -rw-r--r-- | hammer/mappath.cpp | 721 |
1 files changed, 721 insertions, 0 deletions
diff --git a/hammer/mappath.cpp b/hammer/mappath.cpp new file mode 100644 index 0000000..686bab9 --- /dev/null +++ b/hammer/mappath.cpp @@ -0,0 +1,721 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "stdafx.h" +#include "MapPath.h" +#include "hammer.h" +#include "EditPathDlg.h" +#include "MapEntity.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + + +float GetFileVersion(void); + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CMapPath::CMapPath(void) +{ + m_iDirection = dirOneway; + SetName(""); + SetClass("path_corner"); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CMapPath::~CMapPath(void) +{ +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CMapPathNode::CMapPathNode(void) +{ + bSelected = FALSE; + szName[0] = 0; +} + +CMapPathNode::CMapPathNode(const CMapPathNode& src) +{ + *this = src; +} + + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : src - +// Output : CMapPathNode +//----------------------------------------------------------------------------- +CMapPathNode &CMapPathNode::operator=(const CMapPathNode &src) +{ + // we don't care. + Q_strncpy( szName, src.szName, sizeof(szName) ); + bSelected = src.bSelected; + kv.RemoveAll(); + for ( int i=src.kv.GetFirst(); i != src.kv.GetInvalidIndex(); i=src.kv.GetNext( i ) ) + { + MDkeyvalue KeyValue = src.kv.GetKeyValue(i); + kv.SetValue(KeyValue.szKey, KeyValue.szValue); + } + pos = src.pos; + dwID = src.dwID; + + return *this; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : dwID - +// piIndex - +// Output : CMapPathNode * +//----------------------------------------------------------------------------- +CMapPathNode *CMapPath::NodeForID(DWORD dwID, int* piIndex) +{ + for(int iNode = 0; iNode < m_Nodes.Count(); iNode++) + { + if(m_Nodes[iNode].dwID == dwID) + { + if(piIndex) + piIndex[0] = iNode; + return &m_Nodes[iNode]; + } + } + + return NULL; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Output : DWORD +//----------------------------------------------------------------------------- +DWORD CMapPath::GetNewNodeID(void) +{ + DWORD dwNewID = 1; + while(true) + { + int iNode; + for(iNode = 0; iNode < m_Nodes.Count(); iNode++) + { + if(m_Nodes[iNode].dwID == dwNewID) + break; + } + + if(iNode == m_Nodes.Count()) + return dwNewID; + + ++dwNewID; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : dwAfterID - +// vecPos - +// Output : +//----------------------------------------------------------------------------- +DWORD CMapPath::AddNode(DWORD dwAfterID, const Vector &vecPos) +{ + int iPos; + + if(dwAfterID == ADD_START) + iPos = 0; + else if(dwAfterID == ADD_END) + iPos = m_Nodes.Count(); + else if(!NodeForID(dwAfterID, &iPos)) + return 0; // not found! + + CMapPathNode node; + node.pos = vecPos; + node.bSelected = FALSE; + node.dwID = GetNewNodeID(); + + if(iPos == m_Nodes.Count()) + { + // add at tail + m_Nodes.AddToTail(node); + } + else + { + m_Nodes.InsertBefore( iPos, node ); + } + + return node.dwID; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : dwID - +// *pt - +//----------------------------------------------------------------------------- +void CMapPath::SetNodePosition(DWORD dwID, Vector& pt) +{ + int iIndex; + NodeForID(dwID, &iIndex); + + m_Nodes[iIndex].pos = pt; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : dwID - +//----------------------------------------------------------------------------- +void CMapPath::DeleteNode(DWORD dwID) +{ + int iIndex; + if ( NodeForID(dwID, &iIndex) ) + { + m_Nodes.Remove(iIndex); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : file - +// fIsStoring - +//----------------------------------------------------------------------------- +void CMapPath::SerializeRMF(std::fstream& file, BOOL fIsStoring) +{ + int iSize; + + if(fIsStoring) + { + // save!! + file.write(m_szName, 128); + file.write(m_szClass, 128); + file.write((char*) &m_iDirection, sizeof(m_iDirection)); + + iSize = m_Nodes.Count(); + file.write((char*) &iSize, sizeof iSize); + for(int i = 0; i < m_Nodes.Count(); i++) + { + CMapPathNode& node = m_Nodes[i]; + // store each node + file.write((char*) &node.pos[0], 3 * sizeof(float)); + file.write((char*) &node.dwID, sizeof(node.dwID)); + file.write((char*) &node.szName, sizeof(node.szName)); + + // + // Write keyvalue count. + // + WCKeyValues &kv = node.kv; + iSize = 0; + for ( int z=kv.GetFirst(); z != kv.GetInvalidIndex(); z=kv.GetNext( z ) ) + { + ++iSize; + } + file.write((char*) &iSize, sizeof(iSize)); + + // + // Write keyvalues. + // + for (int k = kv.GetFirst(); k != kv.GetInvalidIndex(); k=kv.GetNext( k ) ) + { + MDkeyvalue &KeyValue = kv.GetKeyValue(k); + if (KeyValue.szKey[0] != '\0') + { + KeyValue.SerializeRMF(file, TRUE); + } + } + } + } + else + { + // load!! + file.read(m_szName, 128); + file.read(m_szClass, 128); + file.read((char*) &m_iDirection, sizeof m_iDirection); + + file.read((char*) &iSize, sizeof iSize); + int nNodes = iSize; + m_Nodes.RemoveAll(); + + // read nodes + for(int i = 0; i < nNodes; i++) + { + CMapPathNode node; + // store each node + file.read((char*) &node.pos[0], 3 * sizeof(float)); + file.read((char*) &node.dwID, sizeof(node.dwID)); + if(GetFileVersion() >= 1.6f) + { + file.read((char*) &node.szName, sizeof(node.szName)); + + // read keyvalues + file.read((char*) &iSize, sizeof(iSize)); + WCKeyValues &kv = node.kv; + for (int k = 0; k < iSize; k++) + { + MDkeyvalue KeyValue; + KeyValue.SerializeRMF(file, FALSE); + kv.SetValue( KeyValue.szKey, KeyValue.szValue ); + } + } + + m_Nodes.AddToTail(node); + } + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : iIndex - +// iName - +// str - +//----------------------------------------------------------------------------- +void CMapPath::GetNodeName(int iIndex, int iName, CString& str) +{ + if(m_Nodes[iIndex].szName[0]) + str = m_Nodes[iIndex].szName; + else + { + if(iName) + str.Format("%s%02d", m_szName, iName); + else + str = m_szName; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : file - +// fIsStoring - +// *pIntersecting - +//----------------------------------------------------------------------------- +void CMapPath::SerializeMAP(std::fstream& file, BOOL fIsStoring, BoundBox *pIntersecting) +{ + if( m_Nodes.Count() == 0) + return; + + // if saving WITHIN a box, check all nodes to see if they all + // fit within that box. if not, don't save ANY of the path. + if(pIntersecting) + { + for(int i = 0; i < m_Nodes.Count(); i++) + { + if (!pIntersecting->ContainsPoint(m_Nodes[i].pos)) + { + return; // doesn't intersect - don't save path + } + } + } + + + Assert(fIsStoring); + + CString strTemp; + MDkeyvalue kvTemp; + + // initialize nodes for saving + for(int i = 0; i < m_Nodes.Count(); i++) + { + m_Nodes[i].nTargets = 0; + } + + int iDirec = 1; + int iCurNode = 0; + int iMax = m_Nodes.Count()-1; + int iName = 0; + + // resolve targets + int iLastNodeIndex = -1; + BOOL bFirstPass = TRUE; + +ResolveNamesAgain: + while(1) + { + // store targetname + GetNodeName(iCurNode, iName, strTemp); + + // store our name in the previous node (if not -1) + if(iLastNodeIndex != -1) + { + CMapPathNode &prevNode = m_Nodes[iLastNodeIndex]; + strcpy(prevNode.szTargets[prevNode.nTargets++], strTemp); + } + + ++iName; + + iLastNodeIndex = iCurNode; + + if(iCurNode == iMax) + break; + iCurNode += iDirec; + } + + if(bFirstPass && m_iDirection == dirPingpong && m_Nodes.Count() > 2) + { + // redo loop + bFirstPass = FALSE; + iDirec = -1; + iCurNode = m_Nodes.Count()-2; + iMax = 0; + goto ResolveNamesAgain; + } + else if (m_iDirection == dirCircular) + { + // + // Connect the last node to the first node. + // + CMapPathNode &LastNode = m_Nodes[iMax]; + GetNodeName(iCurNode, 0, strTemp); + strcpy(LastNode.szTargets[LastNode.nTargets], strTemp); + LastNode.nTargets++; + } + + iDirec = 1; + iCurNode = 0; + iMax = m_Nodes.Count()-1; + iName = 0; + +SaveAgain: + while(1) + { + file << "{" << "\r\n"; + + // store name + kvTemp.Set("classname", m_szClass); + kvTemp.SerializeMAP(file, TRUE); + + CMapPathNode &node = m_Nodes[iCurNode]; + + // store location + strTemp.Format("%.0f %.0f %.0f", node.pos[0], node.pos[1], + node.pos[2]); + kvTemp.Set("origin", strTemp); + kvTemp.SerializeMAP(file, TRUE); + + // store targetname + GetNodeName(iCurNode, iName, strTemp); + kvTemp.Set("targetname", strTemp); + kvTemp.SerializeMAP(file, TRUE); + + // store target (if not last) + BOOL bStoreTarget = TRUE; + if(iCurNode == iMax && m_iDirection == dirOneway) + bStoreTarget = FALSE; + + if (bStoreTarget) + { + kvTemp.Set("target", (iDirec == 1) ? node.szTargets[0] : node.szTargets[1]); + kvTemp.SerializeMAP(file, TRUE); + } + + // other keyvalues + WCKeyValues &kv = node.kv; + for (int k = kv.GetFirst(); k != kv.GetInvalidIndex(); k=kv.GetNext( k ) ) + { + MDkeyvalue &KeyValue = kv.GetKeyValue(k); + if (KeyValue.szKey[0] != '\0') + { + KeyValue.SerializeMAP(file, TRUE); + } + } + + file << "}" << "\r\n"; + + ++iName; + iLastNodeIndex = iCurNode; + + if(iCurNode == iMax) + break; + iCurNode += iDirec; + } + + if(iDirec == 1 && m_iDirection == dirPingpong && m_Nodes.Count() > 2) + { + // redo loop + iDirec = -1; + iCurNode = m_Nodes.Count()-2; + iMax = 1; + goto SaveAgain; + } +} + +// Edit + +void CMapPath::EditInfo() +{ + CEditPathDlg dlg; + dlg.m_strName = m_szName; + dlg.m_strClass = m_szClass; + dlg.m_iDirection = m_iDirection; + + if(dlg.DoModal() != IDOK) + return; + + SetName(dlg.m_strName); + SetClass(dlg.m_strClass); + m_iDirection = dlg.m_iDirection; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : dwNodeID - +// Output : CMapEntity * +//----------------------------------------------------------------------------- +CMapEntity *CMapPath::CreateEntityForNode(DWORD dwNodeID) +{ + int iIndex; + CMapPathNode *pNode = NodeForID(dwNodeID, &iIndex); + if (pNode == NULL) + { + return NULL; // no node, no entity! + } + + CMapEntity *pEntity = new CMapEntity; + + for (int k = pNode->kv.GetFirst(); k != pNode->kv.GetInvalidIndex(); k=pNode->kv.GetNext( k ) ) + { + pEntity->SetKeyValue(pNode->kv.GetKey(k), pNode->kv.GetValue(k)); + } + + // store target/targetname properties: + CString str; + str.Format("%s%02d", m_szName, iIndex); + pEntity->SetKeyValue("targetname", str); + + int iNext = iIndex + 1; + if(iNext != -1) + { + str.Format("%s%02d", m_szName, iNext); + pEntity->SetKeyValue("target", str); + } + + pEntity->SetClass(m_szClass); + + return pEntity; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : dwNodeID - +// *pEntity - +//----------------------------------------------------------------------------- +void CMapPath::CopyNodeFromEntity(DWORD dwNodeID, CMapEntity *pEntity) +{ + CMapPathNode *pNode = NodeForID(dwNodeID); + if (!pNode) + { + return; // no node, no copy! + } + + pNode->kv.RemoveAll(); + + // + // Copy all the keys except target and targetname from the entity to the pathnode. + // + for ( int i=pEntity->GetFirstKeyValue(); i != pEntity->GetInvalidKeyValue(); i=pEntity->GetNextKeyValue( i ) ) + { + if (!strcmp(pEntity->GetKey(i), "target") || !strcmp(pEntity->GetKey(i), "targetname")) + { + continue; + } + + pNode->kv.SetValue(pEntity->GetKey(i), pEntity->GetKeyValue(i)); + } +} + + +/* +//----------------------------------------------------------------------------- +// Purpose: +// Input : *szKey - +// *szValue - +// *pNode - +// Output : CChunkFileResult_t +//----------------------------------------------------------------------------- + +UNDONE: Nobody uses the path tool because the user interface is so poor. + Path support has been pulled until the tool itself can be fixed or replaced. + +CChunkFileResult_t CMapPathNode::LoadKeyCallback(const char *szKey, const char *szValue, CMapPathNode *pNode) +{ + if (!stricmp(szKey, "origin")) + { + CChunkFile::ReadKeyValueVector3(szValue, pNode->pos); + } + else if (!stricmp(szKey, "id")) + { + CChunkFile::ReadKeyValueInt(szValue, &pNode->dwID); + } + else if (!stricmp(szKey, "name")) + { + strcpy(pNode->szName, szValue); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pFile - +// Output : ChunkFileResult_t +//----------------------------------------------------------------------------- +ChunkFileResult_t CMapPathNode::SaveVMF(CChunkFile *pFile, CSaveInfo *pSaveInfo) +{ + ChunkFileResult_t eResult = pFile->BeginChunk("node"); + + if (eResult == ChunkFile_Ok) + { + eResult = pFile->WriteKeyValueVector3("origin", node.pos); + } + + if (eResult == ChunkFile_Ok) + { + eResult = pFile->WriteKeyValueInt("id", node.dwID); + } + + if (eResult == ChunkFile_Ok) + { + eResult = pFile->WriteKeyValue("name", node.szName); + } + + if (eResult == ChunkFile_Ok) + { + eResult = pFile->BeginChunk("keys"); + } + + // + // Write keyvalues. + // + if (eResult == ChunkFile_Ok) + { + iSize = kv.GetCount(); + for (int k = 0; k < iSize; k++) + { + MDkeyvalue &KeyValue = kv.GetKeyValue(k); + if (eResult == ChunkFile_Ok) + { + eResult = pFile->WriteKeyValue(KeyValue.GetKey(), KeyValue.GetValue()); + } + } + } + + // End the keys chunk. + if (eResult == ChunkFile_Ok) + { + eResult = pFile->EndChunk(); + } + + // End the node chunk. + if (eResult == ChunkFile_Ok) + { + eResult = pFile->EndChunk(); + } + + return(eResult); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *szKey - +// *szValue - +// *pPath - +// Output : CChunkFileResult_t +//----------------------------------------------------------------------------- +CChunkFileResult_t CMapPath::LoadKeyCallback(const char *szKey, const char *szValue, CMapPath *pPath) +{ + if (!stricmp(szKey, "name")) + { + pPath->SetName(szValue); + } + else if (!stricmp(szKey, "classname")) + { + pPath->SetClass(szValue); + } + else if (!stricmp(szKey, "direction")) + { + CChunkFile::ReadKeyValueInt(szValue, &pPath->m_iDirection); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pFile - +//----------------------------------------------------------------------------- +void CMapPath::LoadVMF(CChunkFile *pFile) +{ + file.read((char*) &iSize, sizeof iSize); + m_nNodes = iSize; + m_Nodes.SetSize(m_nNodes); + + // read nodes + for (int i = 0; i < m_nNodes; i++) + { + CMapPathNode &node = m_Nodes[i]; + + // read keyvalues + file.read((char*) &iSize, sizeof(iSize)); + KeyValues &kv = node.kv; + kv.SetSize(iSize); + for (int k = 0; k < iSize; k++) + { + MDkeyvalue &KeyValue = kv.GetKeyValue(k); + KeyValue.SerializeRMF(file, FALSE); + } + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pFile - +//----------------------------------------------------------------------------- +void CMapPath::SaveVMF(CChunkFile *pFile, CSaveInfo *pSaveInfo) +{ + int iSize; + + ChunkFileResult_t eResult = pFile->BeginChunk("path"); + + if (eResult == ChunkFile_Ok) + { + eResult = pFile-WriteKeyValue("name", m_szName); + } + + if (eResult == ChunkFile_Ok) + { + eResult = pFile->WriteKeyValue("classname", m_szClass); + } + + if (eResult == ChunkFile_Ok) + { + eResult = pFile->WriteKeyValueInt("direction", m_iDirection); + } + + if (eResult == ChunkFile_Ok) + { + for (int i = 0; i < m_nNodes; i++) + { + CMapPathNode &node = m_Nodes[i]; + eResult = node.SaveVMF(pFile, pSaveInfo); + } + } + + if (eResult == ChunkFile_Ok) + { + eResult = pFile->EndChunk(); + } +} +*/ |