summaryrefslogtreecommitdiff
path: root/hammer/mappath.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/mappath.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'hammer/mappath.cpp')
-rw-r--r--hammer/mappath.cpp721
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();
+ }
+}
+*/