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.

416 lines
12 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #include <stdafx.h>
  7. #include "smoothinggroupmgr.h"
  8. #include "mapface.h"
  9. #include "ChunkFile.h"
  10. class CSmoothingGroupMgr : public ISmoothingGroupMgr
  11. {
  12. public:
  13. CSmoothingGroupMgr();
  14. ~CSmoothingGroupMgr();
  15. SmoothingGroupHandle_t CreateGroup( void );
  16. void DestroyGroup( SmoothingGroupHandle_t hGroup );
  17. bool IsGroup( SmoothingGroupHandle_t hGroup );
  18. void AddFaceToGroup( SmoothingGroupHandle_t hGroup, CMapFace *pFace );
  19. void RemoveFaceFromGroup( SmoothingGroupHandle_t hGroup, CMapFace *pFace );
  20. void SetGroupSmoothingAngle( SmoothingGroupHandle_t hGroup, float flAngle );
  21. float GetGroupSmoothingAngle( SmoothingGroupHandle_t hGroup );
  22. int GetFaceCountInGroup( SmoothingGroupHandle_t hGroup );
  23. CMapFace *GetFaceFromGroup( SmoothingGroupHandle_t hGroup, int iFace );
  24. ChunkFileResult_t SaveVMF( CChunkFile *pFile, CSaveInfo *pSaveInfo );
  25. ChunkFileResult_t LoadVMF( CChunkFile *pFile );
  26. private:
  27. #if 0
  28. static ChunkFileResult_t LoadSmoothingGroupMgrCallback( const char *szKey, const char *szValue, CSmoothingGroupMgr *pSmoothingGroupMgr );
  29. static ChunkFileResult_t LoadSmoothingGroupMgrKeyCallback( const char *szKey, const char *szValue, CSmoothingGroupMgr *pSmoothingGroupMgr );
  30. static ChunkFileResult_t LoadSmoothingGroupCallback( CChunkFile *pFile, SmoothingGroup_t *pGroup );
  31. static ChunkFileResult_t LoadSmoothingGroupKeyCallback( const char *szKey, const char *szValue, SmoothingGroup_t *pGroup );
  32. #endif
  33. private:
  34. struct SmoothingGroup_t
  35. {
  36. int m_nID;
  37. CUtlVector<CMapFace*> m_aFaces;
  38. float m_flSmoothingAngle;
  39. };
  40. CUtlVector<SmoothingGroup_t> m_aSmoothingGroups;
  41. };
  42. //-----------------------------------------------------------------------------
  43. // Purpose:
  44. //-----------------------------------------------------------------------------
  45. ISmoothingGroupMgr *SmoothingGroupMgr( void )
  46. {
  47. static CSmoothingGroupMgr s_SmoothingGroupMgr;
  48. return &s_SmoothingGroupMgr;
  49. }
  50. //-----------------------------------------------------------------------------
  51. // Purpose: Constructor
  52. //-----------------------------------------------------------------------------
  53. CSmoothingGroupMgr::CSmoothingGroupMgr()
  54. {
  55. m_aSmoothingGroups.SetSize( MAX_SMOOTHING_GROUP_COUNT );
  56. }
  57. //-----------------------------------------------------------------------------
  58. // Purpose: Deconstructor
  59. //-----------------------------------------------------------------------------
  60. CSmoothingGroupMgr::~CSmoothingGroupMgr()
  61. {
  62. m_aSmoothingGroups.Purge();
  63. }
  64. //-----------------------------------------------------------------------------
  65. // Purpose: Add a face to the smoothing group.
  66. //-----------------------------------------------------------------------------
  67. void CSmoothingGroupMgr::AddFaceToGroup( SmoothingGroupHandle_t hGroup, CMapFace *pFace )
  68. {
  69. // Validate data.
  70. Assert( hGroup != INVALID_SMOOTHING_GROUP );
  71. Assert( hGroup >= 0 );
  72. Assert( hGroup < MAX_SMOOTHING_GROUP_COUNT );
  73. int iGroup = static_cast<int>( hGroup );
  74. SmoothingGroup_t *pGroup = &m_aSmoothingGroups[iGroup];
  75. if ( pGroup )
  76. {
  77. // Check to see if we already have this face in this group.
  78. if ( pGroup->m_aFaces.Find( pFace ) == -1 )
  79. {
  80. pFace->AddSmoothingGroupHandle( hGroup );
  81. pGroup->m_aFaces.AddToTail( pFace );
  82. }
  83. }
  84. }
  85. //-----------------------------------------------------------------------------
  86. //-----------------------------------------------------------------------------
  87. void CSmoothingGroupMgr::RemoveFaceFromGroup( SmoothingGroupHandle_t hGroup, CMapFace *pFace )
  88. {
  89. // Validate data.
  90. Assert( hGroup != INVALID_SMOOTHING_GROUP );
  91. Assert( hGroup >= 0 );
  92. Assert( hGroup < MAX_SMOOTHING_GROUP_COUNT );
  93. int iGroup = static_cast<int>( hGroup );
  94. SmoothingGroup_t *pGroup = &m_aSmoothingGroups[iGroup];
  95. if ( pGroup )
  96. {
  97. int iFace = pGroup->m_aFaces.Find( pFace );
  98. if ( iFace != -1 )
  99. {
  100. pFace->RemoveSmoothingGroupHandle( hGroup );
  101. pGroup->m_aFaces.Remove( iFace );
  102. }
  103. }
  104. }
  105. //-----------------------------------------------------------------------------
  106. //-----------------------------------------------------------------------------
  107. void CSmoothingGroupMgr::SetGroupSmoothingAngle( SmoothingGroupHandle_t hGroup, float flAngle )
  108. {
  109. // Validate data.
  110. Assert( hGroup != INVALID_SMOOTHING_GROUP );
  111. Assert( hGroup >= 0 );
  112. Assert( hGroup < MAX_SMOOTHING_GROUP_COUNT );
  113. int iGroup = static_cast<int>( hGroup );
  114. SmoothingGroup_t *pGroup = &m_aSmoothingGroups[iGroup];
  115. if ( pGroup )
  116. {
  117. pGroup->m_flSmoothingAngle = flAngle;
  118. }
  119. }
  120. //-----------------------------------------------------------------------------
  121. //-----------------------------------------------------------------------------
  122. float CSmoothingGroupMgr::GetGroupSmoothingAngle( SmoothingGroupHandle_t hGroup )
  123. {
  124. // Validate data.
  125. Assert( hGroup != INVALID_SMOOTHING_GROUP );
  126. Assert( hGroup >= 0 );
  127. Assert( hGroup < MAX_SMOOTHING_GROUP_COUNT );
  128. int iGroup = static_cast<int>( hGroup );
  129. SmoothingGroup_t *pGroup = &m_aSmoothingGroups[iGroup];
  130. if ( pGroup )
  131. {
  132. return pGroup->m_flSmoothingAngle;
  133. }
  134. return -1.0f;
  135. }
  136. //-----------------------------------------------------------------------------
  137. //-----------------------------------------------------------------------------
  138. int CSmoothingGroupMgr::GetFaceCountInGroup( SmoothingGroupHandle_t hGroup )
  139. {
  140. // Validate data.
  141. Assert( hGroup != INVALID_SMOOTHING_GROUP );
  142. Assert( hGroup >= 0 );
  143. Assert( hGroup < MAX_SMOOTHING_GROUP_COUNT );
  144. int iGroup = static_cast<int>( hGroup );
  145. SmoothingGroup_t *pGroup = &m_aSmoothingGroups[iGroup];
  146. if ( pGroup )
  147. {
  148. return pGroup->m_aFaces.Count();
  149. }
  150. return -1;
  151. }
  152. //-----------------------------------------------------------------------------
  153. //-----------------------------------------------------------------------------
  154. CMapFace *CSmoothingGroupMgr::GetFaceFromGroup( SmoothingGroupHandle_t hGroup, int iFace )
  155. {
  156. // Validate data.
  157. Assert( hGroup != INVALID_SMOOTHING_GROUP );
  158. Assert( hGroup >= 0 );
  159. Assert( hGroup < MAX_SMOOTHING_GROUP_COUNT );
  160. int iGroup = static_cast<int>( hGroup );
  161. SmoothingGroup_t *pGroup = &m_aSmoothingGroups[iGroup];
  162. if ( pGroup )
  163. {
  164. return pGroup->m_aFaces[iFace];
  165. }
  166. return NULL;
  167. }
  168. //-----------------------------------------------------------------------------
  169. // Purpose: Save the smoothing group data.
  170. //-----------------------------------------------------------------------------
  171. ChunkFileResult_t CSmoothingGroupMgr::SaveVMF( CChunkFile *pFile, CSaveInfo *pSaveInfo )
  172. {
  173. int nGroupCount = 0;
  174. for ( int iGroup = 0; iGroup < MAX_SMOOTHING_GROUP_COUNT; ++iGroup )
  175. {
  176. if ( m_aSmoothingGroups[iGroup].m_aFaces.Count() != 0 )
  177. {
  178. nGroupCount++;
  179. }
  180. }
  181. if ( nGroupCount == 0 )
  182. return ChunkFile_Ok;
  183. ChunkFileResult_t eResult = pFile->BeginChunk( "smoothing_groups" );
  184. for ( iGroup = 0; iGroup < MAX_SMOOTHING_GROUP_COUNT; ++iGroup )
  185. {
  186. SmoothingGroup_t *pGroup = &m_aSmoothingGroups[iGroup];
  187. int nFaceCount = pGroup->m_aFaces.Count();
  188. if ( nFaceCount == 0 )
  189. continue;
  190. char szBuf[MAX_KEYVALUE_LEN];
  191. char szTemp[80];
  192. // Save the smoothing group.
  193. if ( eResult == ChunkFile_Ok )
  194. {
  195. eResult = pFile->BeginChunk( "group" );
  196. if ( eResult == ChunkFile_Ok )
  197. {
  198. eResult = pFile->WriteKeyValueInt( "id", iGroup );
  199. if ( eResult == ChunkFile_Ok )
  200. {
  201. eResult = pFile->WriteKeyValueFloat( "angle", pGroup->m_flSmoothingAngle );
  202. }
  203. if ( eResult == ChunkFile_Ok )
  204. {
  205. eResult = pFile->WriteKeyValueInt( "number_faces", nFaceCount );
  206. }
  207. if ( eResult == ChunkFile_Ok )
  208. {
  209. int nColCount = 20;
  210. int nRowCount = ( nFaceCount / nColCount ) + 1;
  211. for ( int iRow = 0; iRow < nRowCount; ++iRow )
  212. {
  213. bool bFirst = true;
  214. szBuf[0] = '\0';
  215. for ( int iCol = 0; iCol < nColCount; ++iCol )
  216. {
  217. int iFace = ( iRow * 20 ) + iCol;
  218. if ( iFace >= nFaceCount )
  219. continue;
  220. if (!bFirst)
  221. {
  222. strcat(szBuf, " ");
  223. }
  224. CMapFace *pFace = pGroup->m_aFaces[iFace];
  225. if ( pFace )
  226. {
  227. bFirst = false;
  228. sprintf( szTemp, "%d", pFace->GetFaceID() );
  229. strcat( szBuf, szTemp );
  230. }
  231. }
  232. char szKey[10];
  233. sprintf( szKey, "row%d", iRow );
  234. eResult = pFile->WriteKeyValue( szKey, szBuf );
  235. }
  236. }
  237. }
  238. if ( eResult == ChunkFile_Ok )
  239. {
  240. eResult = pFile->EndChunk();
  241. }
  242. }
  243. }
  244. if ( eResult == ChunkFile_Ok )
  245. {
  246. eResult = pFile->EndChunk();
  247. }
  248. return eResult;
  249. }
  250. //-----------------------------------------------------------------------------
  251. // Purpose: Load smoothing group data.
  252. //-----------------------------------------------------------------------------
  253. ChunkFileResult_t CSmoothingGroupMgr::LoadVMF( CChunkFile *pFile )
  254. {
  255. // ChunkFileResult_t eResult = pFile->ReadChunk( ( KeyHandler_t )LoadSmoothingGroupMgrCallback, this );
  256. // return eResult;
  257. return ChunkFile_Ok;
  258. }
  259. #if 0
  260. //-----------------------------------------------------------------------------
  261. //-----------------------------------------------------------------------------
  262. ChunkFileResult_t CSmoothingGroupMgr::LoadSmoothingGroupMgrCallback( const char *szKey, const char *szValue,
  263. CSmoothingGroupMgr *pSmoothingGroupMgr )
  264. {
  265. // Get a pointer to the next available smoothing group slot.
  266. SmoothingGroup_t *pGroup = new SmoothingGroup_t;
  267. if ( !pGroup )
  268. return;
  269. // Set up handlers for the subchunks that we are interested in.
  270. CChunkHandlerMap Handlers;
  271. Handlers.AddHandler( "group", ( ChunkHandler_t )LoadsSmoothingGroupCallback, SmoothingGroup_t *pGroup );
  272. pFile->PushHandlers( &Handlers );
  273. ChunkFileResult_t eResult = pFile->ReadChunk( ( KeyHandler_t )LoadSmoothingGroupMgrCallback, this );
  274. pFile->PopHandlers();
  275. if ( eResult == ChunkFile_Ok )
  276. {
  277. pGroup->m_nID
  278. SmoothingGroup_t *pLoadGroup = &pSmoothingGroupMgr->m_aSmoothingGroups[pGroup->m_nID];
  279. if ( pLoadGroup )
  280. {
  281. pLoadGroup->m_nID = pGroup->m_nID;
  282. pLoadGroup->m_flSmoothingAngle = pGroup->m_flSmoothingAngle;
  283. pLoadGroup->m_aFaces.CopyArray( pGroup->m_aFaces.Base(), pGroup->m_aFaces.Count() );
  284. }
  285. }
  286. return eResult;
  287. }
  288. //-----------------------------------------------------------------------------
  289. //-----------------------------------------------------------------------------
  290. ChunkFileResult_t CSmoothingGroupMgr::LoadSmoothingGroupMgrKeyCallback( const char *szKey, const char *szValue,
  291. CSmoothingGroupMgr *pSmoothingGroupMgr )
  292. {
  293. return;
  294. }
  295. //-----------------------------------------------------------------------------
  296. //-----------------------------------------------------------------------------
  297. ChunkFileResult_t CSmoothingGroupMgr::LoadSmoothingGroupCallback( CChunkFile *pFile, SmoothingGroup_t *pGroup )
  298. {
  299. return( pFile->ReadChunk( ( KeyHandler_t )LoadDispNormalsKeyCallback, pGroup ) );
  300. }
  301. //-----------------------------------------------------------------------------
  302. //-----------------------------------------------------------------------------
  303. ChunkFileResult_t CSmoothingGroupMgr::LoadSmoothingGroupKeyCallback( const char *szKey, const char *szValue, SmoothingGroup_t *pGroup )
  304. {
  305. int nId;
  306. if ( !strnicmp( szKey, "id", 2 ) )
  307. {
  308. CChunkFile::ReadKeyValueInt( szValue, pGroup->m_nID );
  309. }
  310. if ( !strnicmp( szKey, "angle", 5 ) )
  311. {
  312. CChunkFile::ReadKeyValueFloat( szValue, pGroup->m_flSmoothingAngle );
  313. }
  314. if ( !strnicmp( szKey, "number_faces", 12 ) )
  315. {
  316. int nFaceCount;
  317. CChunkFile::ReadKeyValueInt( szValue, nFaceCount );
  318. pGroup->m_aFaces.SetSize( nFaceCount );
  319. }
  320. if ( !strnicmp(szKey, "row", 3 ) )
  321. {
  322. CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
  323. char szBuf[MAX_KEYVALUE_LEN];
  324. strcpy( szBuf, szValue );
  325. int iRow = atoi( &szKey[3] );
  326. char *pszNext = strtok( szBuf, " " );
  327. int nIndex = nRow * 20;
  328. int nFaceID;
  329. while ( pszNext != NULL )
  330. {
  331. nFaceID = ( float )atof( pszNext );
  332. CMapFace *pFace =
  333. CMapFace *CMapWorld::FaceID_FaceForID(int nFaceID)
  334. pszNext = strtok( NULL, " " );
  335. nIndex++;
  336. }
  337. }
  338. return ChunkFile_Ok ;
  339. }
  340. #endif