Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

384 lines
10 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include "stdafx.h"
  7. #include "ChunkFile.h"
  8. #include "MapDoc.h" // dvs: FIXME: I'd rather not have this class know about the doc
  9. #include "VisGroup.h"
  10. // memdbgon must be the last include file in a .cpp file!!!
  11. #include <tier0/memdbgon.h>
  12. bool CVisGroup::s_bShowAll = false;
  13. bool CVisGroup::s_bIsConvertingOldVisGroups = false;
  14. //
  15. // Holds context info for loading the hierarchical groups.
  16. //
  17. struct LoadVisGroupData_t
  18. {
  19. CMapDoc *pDoc; // The document that is loading.
  20. CVisGroup *pParent; // The parent visgroup of the visgroup being loaded, NULL if this is a root-level group.
  21. };
  22. //-----------------------------------------------------------------------------
  23. // Purpose:
  24. //-----------------------------------------------------------------------------
  25. CVisGroup::CVisGroup(void)
  26. {
  27. m_dwID = 0;
  28. m_rgbColor.r = 0;
  29. m_rgbColor.g = 0;
  30. m_rgbColor.b = 0;
  31. m_rgbColor.a = 0;
  32. m_pParent = NULL;
  33. m_eVisible = VISGROUP_HIDDEN;
  34. m_szName[0] = '\0';
  35. m_bIsAuto = false;
  36. }
  37. //-----------------------------------------------------------------------------
  38. // Purpose: Pre-hierarchical visgroups, the visibility state of each group was
  39. // kept in the VMF, whereas now it's purely a function of the visibility
  40. // of the member objects. So when loading old maps, we skip the step
  41. // in which we generate the visgroup state from the objects.
  42. //-----------------------------------------------------------------------------
  43. bool CVisGroup::IsConvertingOldVisGroups()
  44. {
  45. return s_bIsConvertingOldVisGroups;
  46. }
  47. //-----------------------------------------------------------------------------
  48. // Purpose:
  49. // Input : pFile -
  50. // pData -
  51. // Output : ChunkFileResult_t
  52. //-----------------------------------------------------------------------------
  53. ChunkFileResult_t CVisGroup::LoadKeyCallback(const char *szKey, const char *szValue, CVisGroup *pGroup)
  54. {
  55. if (!stricmp(szKey, "name"))
  56. {
  57. pGroup->SetName(szValue);
  58. if ( !stricmp(szValue, "Auto" ) )
  59. {
  60. pGroup->SetAuto(true);
  61. }
  62. }
  63. else if (!stricmp(szKey, "visgroupid"))
  64. {
  65. pGroup->SetID(atoi(szValue));
  66. }
  67. else if (!stricmp(szKey, "color"))
  68. {
  69. unsigned char chRed;
  70. unsigned char chGreen;
  71. unsigned char chBlue;
  72. CChunkFile::ReadKeyValueColor(szValue, chRed, chGreen, chBlue);
  73. pGroup->SetColor(chRed, chGreen, chBlue);
  74. }
  75. else if (!stricmp(szKey, "visible"))
  76. {
  77. // This is a pre-hierarchical visgroups map -- mark this visgroup as hidden.
  78. // We'll skip the code in CMapDoc::PostLoad that recalculates visibility.
  79. pGroup->SetVisible((atoi(szValue) == 1) ? VISGROUP_SHOWN : VISGROUP_HIDDEN);
  80. s_bIsConvertingOldVisGroups = true;
  81. }
  82. return(ChunkFile_Ok);
  83. }
  84. //-----------------------------------------------------------------------------
  85. // Purpose:
  86. // Input : pFile -
  87. // Output :
  88. //-----------------------------------------------------------------------------
  89. ChunkFileResult_t CVisGroup::LoadVMF(CChunkFile *pFile, CMapDoc *pDoc)
  90. {
  91. // Fill out a little context blob for passing to the handler.
  92. LoadVisGroupData_t LoadData;
  93. LoadData.pDoc = pDoc;
  94. LoadData.pParent = this;
  95. CChunkHandlerMap Handlers;
  96. Handlers.AddHandler("visgroup", (ChunkHandler_t)LoadVisGroupCallback, &LoadData);
  97. pFile->PushHandlers(&Handlers);
  98. ChunkFileResult_t eResult = pFile->ReadChunk((KeyHandler_t)LoadKeyCallback, this);
  99. pFile->PopHandlers();
  100. return(eResult);
  101. }
  102. //-----------------------------------------------------------------------------
  103. // Purpose:
  104. // Input : pFile -
  105. // pData -
  106. // Output : ChunkFileResult_t
  107. //-----------------------------------------------------------------------------
  108. ChunkFileResult_t CVisGroup::LoadVisGroupCallback(CChunkFile *pFile, LoadVisGroupData_t *pLoadData)
  109. {
  110. CVisGroup *pVisGroup = new CVisGroup;
  111. ChunkFileResult_t eResult = pVisGroup->LoadVMF(pFile, pLoadData->pDoc);
  112. if (eResult == ChunkFile_Ok)
  113. {
  114. if (pLoadData->pParent != NULL)
  115. {
  116. pLoadData->pParent->AddChild(pVisGroup);
  117. pVisGroup->SetParent(pLoadData->pParent);
  118. }
  119. if ( !pVisGroup->IsAutoVisGroup() )
  120. {
  121. pLoadData->pDoc->VisGroups_AddGroup(pVisGroup);
  122. }
  123. }
  124. return(eResult);
  125. }
  126. //-----------------------------------------------------------------------------
  127. // Purpose:
  128. // Input : pFile -
  129. // pData -
  130. // Output : ChunkFileResult_t
  131. //-----------------------------------------------------------------------------
  132. ChunkFileResult_t CVisGroup::LoadVisGroupsCallback(CChunkFile *pFile, CMapDoc *pDoc)
  133. {
  134. s_bIsConvertingOldVisGroups = false;
  135. // Fill out a little context blob for passing to the handler.
  136. LoadVisGroupData_t LoadData;
  137. LoadData.pDoc = pDoc;
  138. LoadData.pParent = NULL;
  139. //
  140. // Set up handlers for the subchunks that we are interested in.
  141. //
  142. CChunkHandlerMap Handlers;
  143. Handlers.AddHandler("visgroup", (ChunkHandler_t)LoadVisGroupCallback, &LoadData);
  144. pFile->PushHandlers(&Handlers);
  145. ChunkFileResult_t eResult = pFile->ReadChunk();
  146. pFile->PopHandlers();
  147. return(eResult);
  148. }
  149. //-----------------------------------------------------------------------------
  150. // Purpose:
  151. // Input : pChild -
  152. //-----------------------------------------------------------------------------
  153. void CVisGroup::MoveUp(CVisGroup *pChild)
  154. {
  155. int nIndex = m_Children.Find(pChild);
  156. if (nIndex > 0)
  157. {
  158. m_Children.Remove(nIndex);
  159. m_Children.InsertBefore(nIndex - 1, pChild);
  160. }
  161. }
  162. //-----------------------------------------------------------------------------
  163. // Purpose:
  164. // Input : pChild -
  165. //-----------------------------------------------------------------------------
  166. void CVisGroup::MoveDown(CVisGroup *pChild)
  167. {
  168. int nIndex = m_Children.Find(pChild);
  169. if ((nIndex >= 0) && (nIndex < (m_Children.Count() - 1)))
  170. {
  171. m_Children.Remove(nIndex);
  172. m_Children.InsertAfter(nIndex, pChild);
  173. }
  174. }
  175. //-----------------------------------------------------------------------------
  176. // Purpose: Returns whether or not this visgroup is currently visible.
  177. //-----------------------------------------------------------------------------
  178. VisGroupState_t CVisGroup::GetVisible(void)
  179. {
  180. return m_eVisible;
  181. }
  182. //-----------------------------------------------------------------------------
  183. // Purpose: Returns whether or not visgroup visibility is being overridden by
  184. // the "Show All" button.
  185. //-----------------------------------------------------------------------------
  186. bool CVisGroup::IsShowAllActive(void)
  187. {
  188. return s_bShowAll;
  189. }
  190. //-----------------------------------------------------------------------------
  191. // Purpose: Saves this visgroup.
  192. // Input : pFile - File to save into.
  193. // Output : Returns ChunkFile_Ok on success, an error code on failure.
  194. //-----------------------------------------------------------------------------
  195. ChunkFileResult_t CVisGroup::SaveVMF(CChunkFile *pFile, CSaveInfo *pSaveInfo)
  196. {
  197. ChunkFileResult_t eResult = pFile->BeginChunk("visgroup");
  198. if (eResult == ChunkFile_Ok)
  199. {
  200. eResult = pFile->WriteKeyValue("name", GetName());
  201. }
  202. if (eResult == ChunkFile_Ok)
  203. {
  204. DWORD dwID = GetID();
  205. eResult = pFile->WriteKeyValueInt("visgroupid", dwID);
  206. }
  207. if (eResult == ChunkFile_Ok)
  208. {
  209. color32 rgbColor = GetColor();
  210. eResult = pFile->WriteKeyValueColor("color", rgbColor.r, rgbColor.g, rgbColor.b);
  211. }
  212. //
  213. // Recurse into children, writing them within this chunk.
  214. //
  215. for (int i = 0; i < GetChildCount(); i++)
  216. {
  217. CVisGroup *pChild = GetChild(i);
  218. eResult = pChild->SaveVMF(pFile, pSaveInfo);
  219. if (eResult != ChunkFile_Ok)
  220. break;
  221. }
  222. if (eResult == ChunkFile_Ok)
  223. {
  224. eResult = pFile->EndChunk();
  225. }
  226. return(eResult);
  227. }
  228. //-----------------------------------------------------------------------------
  229. // Purpose: Overrides normal visgroup visibility, making all visgroups visible.
  230. //-----------------------------------------------------------------------------
  231. void CVisGroup::ShowAllVisGroups(bool bShow)
  232. {
  233. s_bShowAll = bShow;
  234. }
  235. //-----------------------------------------------------------------------------
  236. // Purpose:
  237. //-----------------------------------------------------------------------------
  238. void CVisGroup::AddChild(CVisGroup *pChild)
  239. {
  240. int nIndex = m_Children.Find(pChild);
  241. if (nIndex == -1)
  242. {
  243. m_Children.AddToTail(pChild);
  244. }
  245. }
  246. //-----------------------------------------------------------------------------
  247. // Purpose:
  248. // Input : pChild -
  249. //-----------------------------------------------------------------------------
  250. bool CVisGroup::CanMoveUp(CVisGroup *pChild)
  251. {
  252. return (m_Children.Find(pChild) > 0);
  253. }
  254. //-----------------------------------------------------------------------------
  255. // Purpose:
  256. // Input : pChild -
  257. //-----------------------------------------------------------------------------
  258. bool CVisGroup::CanMoveDown(CVisGroup *pChild)
  259. {
  260. int nIndex = m_Children.Find(pChild);
  261. return (nIndex >= 0) && (nIndex < m_Children.Count() - 1);
  262. }
  263. //-----------------------------------------------------------------------------
  264. // Purpose:
  265. //-----------------------------------------------------------------------------
  266. void CVisGroup::RemoveChild(CVisGroup *pChild)
  267. {
  268. int nIndex = m_Children.Find(pChild);
  269. if (nIndex != -1)
  270. {
  271. m_Children.Remove(nIndex);
  272. }
  273. }
  274. //-----------------------------------------------------------------------------
  275. // Purpose: Returns true if the group is one of our descendents, false if not.
  276. //-----------------------------------------------------------------------------
  277. bool CVisGroup::FindDescendent(CVisGroup *pGroup)
  278. {
  279. for (int i = 0; i < m_Children.Count(); i++)
  280. {
  281. CVisGroup *pChild = m_Children.Element(i);
  282. if ((pChild == pGroup) || (pChild->FindDescendent(pGroup)))
  283. {
  284. return true;
  285. }
  286. }
  287. return false;
  288. }
  289. bool CVisGroup::IsAutoVisGroup()
  290. {
  291. return m_bIsAuto;
  292. }
  293. void CVisGroup::SetAuto( bool bAuto )
  294. {
  295. m_bIsAuto = bAuto;
  296. }
  297. void CVisGroup::VisGroups_UpdateParent( VisGroupState_t state )
  298. {
  299. CVisGroup *pParent = GetParent();
  300. VisGroupState_t parentState = pParent->GetVisible();
  301. if ( state == VISGROUP_PARTIAL )
  302. {
  303. pParent->SetVisible( VISGROUP_PARTIAL );
  304. }
  305. if ( parentState == VISGROUP_UNDEFINED )
  306. {
  307. pParent->SetVisible( state );
  308. }
  309. else if ( parentState != state )
  310. {
  311. pParent->SetVisible( VISGROUP_PARTIAL );
  312. }
  313. if ( pParent->GetParent() != NULL )
  314. {
  315. pParent->VisGroups_UpdateParent( pParent->GetVisible() );
  316. }
  317. }