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.

523 lines
16 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Defines a common class for all objects in the world object tree.
  4. //
  5. // Pointers to other objects in the object tree may be stored, but
  6. // they should be set via UpdateDependency rather than directly. This
  7. // insures proper linkage to the other object so that if it moves, is
  8. // removed from the world, or changes in any other way, the dependent
  9. // object is properly notified.
  10. //
  11. //=============================================================================//
  12. #ifndef MAPCLASS_H
  13. #define MAPCLASS_H
  14. #ifdef _WIN32
  15. #pragma once
  16. #endif
  17. #include "tier0/basetypes.h"
  18. #pragma warning(push, 1)
  19. #pragma warning(disable:4701 4702 4530)
  20. #include <fstream>
  21. #pragma warning(pop)
  22. #include "BoundBox.h"
  23. #include "MapPoint.h"
  24. #include "utlvector.h"
  25. #include "visgroup.h"
  26. #include "fgdlib/wckeyvalues.h"
  27. #include "tier1/smartptr.h"
  28. class Box3D;
  29. class CBaseTool;
  30. class CChunkFile;
  31. class GDclass;
  32. class CMapClass;
  33. class CMapEntity;
  34. class CMapSolid;
  35. class CMapView2D;
  36. class CMapViewLogical;
  37. class CMapWorld;
  38. class CPoint;
  39. class CRender3D;
  40. class CSaveInfo;
  41. class CSSolid;
  42. class CVisGroupList;
  43. class CMapFaceList;
  44. struct MapError;
  45. enum ChunkFileResult_t;
  46. struct MapObjectPair_t
  47. {
  48. CMapClass *pObject1;
  49. CMapClass *pObject2;
  50. };
  51. //-----------------------------------------------------------------------------
  52. // Structure used for returning hits when calling ObjectsAt.
  53. //-----------------------------------------------------------------------------
  54. typedef struct HitInfo_s
  55. {
  56. CMapClass *pObject; // Pointer to the CMapAtom that was clicked on.
  57. unsigned int uData; // Additional data provided by the CMapAtom object.
  58. unsigned int nDepth; // Depth value of the object that was clicked on.
  59. VMatrix m_LocalMatrix;
  60. } HitInfo_t;
  61. //
  62. // Passed into PrepareSelection to control what gets selected.
  63. //
  64. enum SelectMode_t
  65. {
  66. selectGroups = 0, // select groups, ungrouped entities, and ungrouped solids
  67. selectObjects, // select entities and solids not in entities
  68. selectSolids, // select point entities, solids in entities, solids
  69. };
  70. enum VisGroupSelection
  71. {
  72. AUTO = 0,
  73. USER
  74. };
  75. // helper macro for linked lists as pointers
  76. #define FOR_EACH_OBJ( listName, iteratorName ) \
  77. for( int iteratorName=0; iteratorName<(listName).Count(); iteratorName++)
  78. typedef const char * MAPCLASSTYPE;
  79. typedef BOOL (*ENUMMAPCHILDRENPROC)(CMapClass *, unsigned int dwParam);
  80. typedef CUtlVector<CMapClass*> CMapObjectList;
  81. #define MAX_ENUM_CHILD_DEPTH 16
  82. struct EnumChildrenStackEntry_t
  83. {
  84. CMapClass *pParent;
  85. int pos;
  86. };
  87. struct EnumChildrenPos_t
  88. {
  89. EnumChildrenStackEntry_t Stack[MAX_ENUM_CHILD_DEPTH];
  90. int nDepth;
  91. };
  92. typedef struct
  93. {
  94. MAPCLASSTYPE Type;
  95. CMapClass * (*pfnNew)();
  96. } MCMSTRUCT;
  97. // This is a reference-counted class that holds a pointer to an object.
  98. // When the object goes away, it can set the pointer in here to NULL
  99. // and anyone else who holds a reference to this can know that the
  100. // object has gone away. It's similar to the EHANDLEs in the engine,
  101. // except there's no finite list of objects that's managed anywhere.
  102. template<class T>
  103. class CSafeObject
  104. {
  105. public:
  106. static CSmartPtr< CSafeObject< T > > Create( T *pObject )
  107. {
  108. CSafeObject<T> *pRet = new CSafeObject<T>( pObject );
  109. return CSmartPtr< CSafeObject< T> >( pRet );
  110. }
  111. void AddRef()
  112. {
  113. ++m_RefCount;
  114. }
  115. void Release()
  116. {
  117. --m_RefCount;
  118. if ( m_RefCount <= 0 )
  119. delete this;
  120. }
  121. int GetRefCount() const
  122. {
  123. return m_RefCount;
  124. }
  125. public:
  126. T *m_pObject;
  127. private:
  128. CSafeObject( T *pObject )
  129. {
  130. m_RefCount = 0;
  131. m_pObject = pObject;
  132. }
  133. private:
  134. int m_RefCount; // This object goes away when all smart pointers to it go away.
  135. };
  136. class CMapClass : public CMapPoint
  137. {
  138. public:
  139. //
  140. // Construction/destruction:
  141. //
  142. CMapClass(void);
  143. virtual ~CMapClass(void);
  144. const CSmartPtr< CSafeObject< CMapClass > >& GetSafeObjectSmartPtr();
  145. inline int GetID(void);
  146. inline void SetID(int nID);
  147. virtual size_t GetSize(void);
  148. //
  149. // Can belong to one or more visgroups:
  150. //
  151. virtual void AddVisGroup(CVisGroup *pVisGroup);
  152. int GetVisGroupCount(void);
  153. CVisGroup *GetVisGroup(int nIndex);
  154. void RemoveAllVisGroups(void);
  155. void RemoveVisGroup(CVisGroup *pVisGroup);
  156. int IsInVisGroup(CVisGroup *pVisGroup);
  157. void SetColorVisGroup(CVisGroup *pVisGroup);
  158. virtual bool UpdateObjectColor();
  159. //
  160. // Can be tracked in the Undo/Redo system:
  161. //
  162. inline void SetTemporary(bool bTemporary) { m_bTemporary = bTemporary; }
  163. inline bool IsTemporary(void) const { return m_bTemporary; }
  164. union
  165. {
  166. struct
  167. {
  168. unsigned ID : 28;
  169. unsigned Types : 4; // 0 - copy, 1 - relationship, 2 - delete
  170. } Kept;
  171. unsigned int dwKept;
  172. };
  173. //
  174. // Has children:
  175. //
  176. virtual void AddChild(CMapClass *pChild);
  177. virtual void CopyChildrenFrom(CMapClass *pobj, bool bUpdateDependencies);
  178. virtual void RemoveAllChildren(void);
  179. virtual void RemoveChild(CMapClass *pChild, bool bUpdateBounds = true);
  180. virtual void UpdateChild(CMapClass *pChild);
  181. inline int GetChildCount(void) { return( m_Children.Count()); }
  182. inline const CMapObjectList *GetChildren() { return &m_Children; }
  183. CMapClass *GetFirstDescendent(EnumChildrenPos_t &pos);
  184. CMapClass *GetNextDescendent(EnumChildrenPos_t &pos);
  185. virtual CMapClass *GetParent(void)
  186. {
  187. Assert( (m_pParent == NULL) || (dynamic_cast<CMapClass*>(m_pParent) != NULL) );
  188. return( (CMapClass*)m_pParent);
  189. }
  190. virtual void SetParent(CMapAtom *pParent)
  191. {
  192. Assert( (pParent == NULL) || (dynamic_cast<CMapClass*>(pParent) != NULL) );
  193. UpdateParent((CMapClass*)pParent);
  194. }
  195. const CMapObjectList *GetDependents() { return &m_Dependents; }
  196. virtual void FindTargetNames( CUtlVector< const char * > &Names ) { }
  197. virtual void ReplaceTargetname(const char *szOldName, const char *szNewName);
  198. //
  199. // Notifications.
  200. //
  201. virtual void OnAddToWorld(CMapWorld *pWorld);
  202. virtual void OnClone(CMapClass *pClone, CMapWorld *pWorld, const CMapObjectList &OriginalList, CMapObjectList &NewList);
  203. virtual void OnPreClone(CMapClass *pClone, CMapWorld *pWorld, const CMapObjectList &OriginalList, CMapObjectList &NewList);
  204. virtual void OnPrePaste(CMapClass *pCopy, CMapWorld *pSourceWorld, CMapWorld *pDestWorld, const CMapObjectList &OriginalList, CMapObjectList &NewList);
  205. virtual void OnPaste(CMapClass *pCopy, CMapWorld *pSourceWorld, CMapWorld *pDestWorld, const CMapObjectList &OriginalList, CMapObjectList &NewList);
  206. virtual void OnNotifyDependent(CMapClass *pObject, Notify_Dependent_t eNotifyType);
  207. virtual void OnParentKeyChanged(const char* key, const char* value) {}
  208. virtual void OnRemoveFromWorld(CMapWorld *pWorld, bool bNotifyChildren);
  209. virtual void OnUndoRedo(void) {}
  210. virtual bool OnApply( void ) { return true; }
  211. //
  212. // Bounds calculation and intersection functions.
  213. //
  214. virtual void CalcBounds(BOOL bFullUpdate = FALSE);
  215. void GetCullBox(Vector &mins, Vector &maxs);
  216. void SetCullBoxFromFaceList( CMapFaceList *pFaces );
  217. void GetBoundingBox( Vector &mins, Vector &maxs );
  218. void SetBoundingBoxFromFaceList( CMapFaceList *pFaces );
  219. void GetRender2DBox(Vector &mins, Vector &maxs);
  220. // NOTE: Logical position is in global space
  221. virtual void SetLogicalPosition( const Vector2D &vecPosition ) {}
  222. virtual const Vector2D& GetLogicalPosition( );
  223. // NOTE: Logical bounds is in global space
  224. virtual void GetRenderLogicalBox( Vector2D &mins, Vector2D &maxs );
  225. // HACK: temp stuff to ease the transition to not inheriting from BoundBox
  226. void GetBoundsCenter(Vector &vecCenter) { m_Render2DBox.GetBoundsCenter(vecCenter); }
  227. void GetBoundsSize(Vector &vecSize) { m_Render2DBox.GetBoundsSize(vecSize); }
  228. inline bool IsInsideBox(Vector const &Mins, Vector const &Maxs) const { return(m_Render2DBox.IsInsideBox(Mins, Maxs)); }
  229. inline bool IsIntersectingBox(const Vector &vecMins, const Vector& vecMaxs) const { return(m_Render2DBox.IsIntersectingBox(vecMins, vecMaxs)); }
  230. virtual CMapClass *PrepareSelection(SelectMode_t eSelectMode);
  231. void PostUpdate(Notify_Dependent_t eNotifyType);
  232. static void UpdateAllDependencies(CMapClass *pObject);
  233. void SetOrigin(Vector& origin);
  234. // hierarchy
  235. virtual void UpdateAnimation( float animTime ) {}
  236. virtual bool GetTransformMatrix( VMatrix& matrix );
  237. virtual MAPCLASSTYPE GetType(void) = 0;
  238. virtual BOOL IsMapClass(MAPCLASSTYPE Type) = 0;
  239. virtual bool IsWorld() { return false; }
  240. virtual CMapClass *Copy(bool bUpdateDependencies);
  241. virtual CMapClass *CopyFrom(CMapClass *pFrom, bool bUpdateDependencies);
  242. virtual bool HitTest2D(CMapView2D *pView, const Vector2D &point, HitInfo_t &HitData);
  243. virtual bool HitTestLogical(CMapViewLogical *pView, const Vector2D &point, HitInfo_t &HitData);
  244. // Objects that can be clicked on and activated as tools implement this and return a CBaseTool-derived object.
  245. virtual CBaseTool *GetToolObject(int nHitData, bool bAttachObject) { return NULL; }
  246. //
  247. // Can be serialized:
  248. //
  249. virtual ChunkFileResult_t SaveVMF(CChunkFile *pFile, CSaveInfo *pSaveInfo);
  250. virtual ChunkFileResult_t SaveEditorData(CChunkFile *pFile);
  251. virtual bool ShouldSerialize(void) { return true; }
  252. virtual int SerializeRMF(std::fstream &File, BOOL bRMF);
  253. virtual int SerializeMAP(std::fstream &File, BOOL bRMF);
  254. virtual void PostloadWorld(CMapWorld *pWorld);
  255. virtual void PresaveWorld(void) {}
  256. bool PostloadVisGroups( bool bIsLoading );
  257. virtual bool IsGroup(void) { return false; }
  258. virtual bool IsScaleable(void) { return false; }
  259. virtual bool IsClutter(void) { return false; } // Whether this object should be hidden when the user hides helpers.
  260. virtual bool IsCulledByCordon(const Vector &vecMins, const Vector &vecMaxs); // Whether this object is hidden based on its own intersection with the cordon, independent of its parent's intersection.
  261. virtual bool IsEditable( void );
  262. virtual bool ShouldSnapToHalfGrid() { return false; }
  263. virtual bool IsSolid( ) { return false; }
  264. // searching
  265. virtual CMapEntity *FindChildByKeyValue( const char* key, const char* value, bool *bIsInInstance = NULL, VMatrix *InstanceMatrix = NULL );
  266. // HACK: get the world that this object is contained within.
  267. static CMapWorld *GetWorldObject(CMapAtom *pStart);
  268. virtual const char* GetDescription() { return ""; }
  269. BOOL EnumChildren(ENUMMAPCHILDRENPROC pfn, unsigned int dwParam = 0, MAPCLASSTYPE Type = NULL);
  270. BOOL EnumChildrenRecurseGroupsOnly(ENUMMAPCHILDRENPROC pfn, unsigned int dwParam, MAPCLASSTYPE Type = NULL);
  271. BOOL IsChildOf(CMapAtom *pObject);
  272. virtual bool ShouldAppearInLightingPreview(void)
  273. {
  274. return true; //false;
  275. }
  276. virtual bool ShouldAppearInRaytracedLightingPreview(void)
  277. {
  278. return false;
  279. }
  280. inline bool IsVisible(void) { return(m_bVisible); }
  281. void SetVisible(bool bVisible);
  282. inline bool IsVisGroupShown(void) { return m_bVisGroupShown && m_bVisGroupAutoShown; }
  283. void VisGroupShow(bool bShow, VisGroupSelection eVisGroup = USER);
  284. bool CheckVisibility(bool bIsLoading = false);
  285. //
  286. // Visible2D functions are used only for hiding solids being morphed. Remove?
  287. //
  288. bool IsVisible2D(void) { return m_bVisible2D; }
  289. void SetVisible2D(bool bVisible2D) { m_bVisible2D = bVisible2D; }
  290. // Is this class potentially visible in 2D visio view?
  291. virtual bool IsLogical(void) { return false; }
  292. // Is this class actually visible in 2D visio view?
  293. virtual bool IsVisibleLogical(void) { return false; }
  294. //
  295. // Overridden to set the render color of each of our children.
  296. //
  297. virtual void SetRenderColor(unsigned char red, unsigned char green, unsigned char blue);
  298. virtual void SetRenderColor(color32 rgbColor);
  299. //
  300. // Can be rendered:
  301. //
  302. virtual void Render2D(CRender2D *pRender);
  303. virtual void Render3D(CRender3D *pRender);
  304. virtual void RenderLogical( CRender2D *pRender ) {}
  305. virtual bool RenderPreload(CRender3D *pRender, bool bNewContext);
  306. inline int GetRenderFrame(void) { return(m_nRenderFrame); }
  307. inline void SetRenderFrame(int nRenderFrame) { m_nRenderFrame = nRenderFrame; }
  308. SelectionState_t SetSelectionState(SelectionState_t eSelectionState);
  309. //
  310. // Has a set of editor-specific properties that are loaded from the VMF file.
  311. // The keys are freed after being handled by the map post-load code.
  312. //
  313. int GetEditorKeyCount(void);
  314. const char *GetEditorKey(int nIndex);
  315. const char *GetEditorKeyValue(int nIndex);
  316. const char *GetEditorKeyValue(const char *szKey);
  317. void RemoveEditorKeys(void);
  318. void SetEditorKeyValue(const char *szKey, const char *szValue);
  319. virtual void InstanceMoved( void );
  320. public:
  321. // Set to true while loading a VMF file so it can delay certain calls like UpdateBounds.
  322. // Drastically speeds up load times.
  323. static bool s_bLoadingVMF;
  324. protected:
  325. //
  326. // Implements CMapAtom transformation interface:
  327. //
  328. virtual void DoTransform(const VMatrix &matrix);
  329. //
  330. // Serialization callbacks.
  331. //
  332. static ChunkFileResult_t LoadEditorCallback(CChunkFile *pFile, CMapClass *pObject);
  333. static ChunkFileResult_t LoadEditorKeyCallback(const char *szKey, const char *szValue, CMapClass *pObject);
  334. //
  335. // Has a list of objects that must be notified if it changes size or position.
  336. //
  337. void AddDependent(CMapClass *pDependent);
  338. void NotifyDependents(Notify_Dependent_t eNotifyType);
  339. void RemoveDependent(CMapClass *pDependent);
  340. virtual void UpdateDependencies(CMapWorld *pWorld, CMapClass *pObject) {};
  341. CMapClass *UpdateDependency(CMapClass *pOldAttached, CMapClass *pNewAttached);
  342. void UpdateParent(CMapClass *pNewParent);
  343. void SetBoxFromFaceList( CMapFaceList *pFaces, BoundBox &Box );
  344. CSmartPtr< CSafeObject< CMapClass > > m_pSafeObject;
  345. BoundBox m_CullBox; // Our bounds for culling in the 3D views and intersecting with the cordon.
  346. BoundBox m_BoundingBox; // Our bounds for brushes / entities themselves. This size may be smaller than m_CullBox ( i.e. spheres are not included )
  347. BoundBox m_Render2DBox; // Our bounds for rendering in the 2D views.
  348. CMapObjectList m_Children; // Each object can have many children. Children usually transform with their parents, etc.
  349. CMapObjectList m_Dependents; // Objects that this object should notify if it changes.
  350. int m_nID; // This object's unique ID.
  351. bool m_bTemporary; // Whether to track this object for Undo/Redo.
  352. int m_nRenderFrame; // Frame counter used to avoid rendering the same object twice in a 3D frame.
  353. bool m_bVisible2D; // Whether this object is visible in the 2D view. Currently only used for morphing.
  354. bool m_bVisible; // Whether this object is currently visible in the 2D and 3D views based on ALL factors: visgroups, cordon, etc.
  355. bool m_bVisGroupShown; // Whether this object is shown or hidden by user visgroups. Kept separate from m_bVisible so we can
  356. // reflect this state in the visgroups list independent of the cordon, hide entities state, etc.
  357. bool m_bVisGroupAutoShown; // Whether this object is shown or hidden by auto visgroups.
  358. CVisGroupList m_VisGroups; // Visgroups to which this object belongs, EMPTY if none.
  359. CVisGroup *m_pColorVisGroup; // The visgroup from which we get our color, NULL if none.
  360. WCKeyValuesT<WCKVBase_Vector> *m_pEditorKeys; // Temporary storage for keys loaded from the "editor" chunk of the VMF file, freed after loading.
  361. friend class CTrackEntry; // Friends with Undo/Redo system so that parentage can be changed.
  362. friend void FixHiddenObject(MapError *pError); // So that the Check for Problems dialog can fix visgroups problems.
  363. };
  364. //-----------------------------------------------------------------------------
  365. // Purpose: Returns this object's unique ID.
  366. //-----------------------------------------------------------------------------
  367. int CMapClass::GetID(void)
  368. {
  369. return(m_nID);
  370. }
  371. //-----------------------------------------------------------------------------
  372. // Purpose: Sets this object's unique ID.
  373. //-----------------------------------------------------------------------------
  374. void CMapClass::SetID(int nID)
  375. {
  376. m_nID = nID;
  377. }
  378. class CMapClassManager
  379. {
  380. public:
  381. virtual ~CMapClassManager();
  382. CMapClassManager(MAPCLASSTYPE Type, CMapClass * (*pfnNew)());
  383. static CMapClass * CreateObject(MAPCLASSTYPE Type);
  384. };
  385. #define MAPCLASS_TYPE(class_name) \
  386. (class_name::__Type)
  387. #define IMPLEMENT_MAPCLASS(class_name) \
  388. char * class_name::__Type = #class_name; \
  389. MAPCLASSTYPE class_name::GetType() { return __Type; } \
  390. BOOL class_name::IsMapClass(MAPCLASSTYPE Type) \
  391. { return (Type == __Type) ? TRUE : FALSE; } \
  392. CMapClass * class_name##_CreateObject() \
  393. { return new class_name; } \
  394. CMapClassManager mcm_##class_name(class_name::__Type, \
  395. class_name##_CreateObject);
  396. #define DECLARE_MAPCLASS(class_name,class_base) \
  397. typedef class_base BaseClass; \
  398. static char * __Type; \
  399. virtual MAPCLASSTYPE GetType(); \
  400. virtual BOOL IsMapClass(MAPCLASSTYPE Type);
  401. class CCheckFaceInfo
  402. {
  403. public:
  404. CCheckFaceInfo() { iPoint = -1; }
  405. char szDescription[128];
  406. int iPoint;
  407. };
  408. #endif // MAPCLASS_H