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.

169 lines
4.8 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Contains the set of functions for manipulating entity hierarchies.
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. // UNDONE: Reconcile this with SetParent()
  8. #include "cbase.h"
  9. #include "hierarchy.h"
  10. // memdbgon must be the last include file in a .cpp file!!!
  11. #include "tier0/memdbgon.h"
  12. //-----------------------------------------------------------------------------
  13. // Purpose: Does the linked list work of removing a child object from the hierarchy.
  14. // Input : pParent -
  15. // pChild -
  16. //-----------------------------------------------------------------------------
  17. void UnlinkChild( CBaseEntity *pParent, CBaseEntity *pChild )
  18. {
  19. CBaseEntity *pList;
  20. EHANDLE *pPrev;
  21. pList = pParent->m_hMoveChild;
  22. pPrev = &pParent->m_hMoveChild;
  23. while ( pList )
  24. {
  25. CBaseEntity *pNext = pList->m_hMovePeer;
  26. if ( pList == pChild )
  27. {
  28. // patch up the list
  29. pPrev->Set( pNext );
  30. // Clear hierarchy bits for this guy
  31. pList->m_hMoveParent.Set( NULL );
  32. pList->m_hMovePeer.Set( NULL );
  33. pList->NetworkProp()->SetNetworkParent( CBaseHandle() );
  34. pList->DispatchUpdateTransmitState();
  35. pList->OnEntityEvent( ENTITY_EVENT_PARENT_CHANGED, NULL );
  36. pParent->RecalcHasPlayerChildBit();
  37. return;
  38. }
  39. else
  40. {
  41. pPrev = &pList->m_hMovePeer;
  42. pList = pNext;
  43. }
  44. }
  45. // This only happens if the child wasn't found in the parent's child list
  46. Assert(0);
  47. }
  48. void LinkChild( CBaseEntity *pParent, CBaseEntity *pChild )
  49. {
  50. EHANDLE hParent;
  51. hParent.Set( pParent );
  52. pChild->m_hMovePeer.Set( pParent->FirstMoveChild() );
  53. pParent->m_hMoveChild.Set( pChild );
  54. pChild->m_hMoveParent = hParent;
  55. pChild->NetworkProp()->SetNetworkParent( hParent );
  56. pChild->DispatchUpdateTransmitState();
  57. pChild->OnEntityEvent( ENTITY_EVENT_PARENT_CHANGED, NULL );
  58. pParent->RecalcHasPlayerChildBit();
  59. }
  60. void TransferChildren( CBaseEntity *pOldParent, CBaseEntity *pNewParent )
  61. {
  62. CBaseEntity *pChild = pOldParent->FirstMoveChild();
  63. while ( pChild )
  64. {
  65. // NOTE: Have to do this before the unlink to ensure local coords are valid
  66. Vector vecAbsOrigin = pChild->GetAbsOrigin();
  67. QAngle angAbsRotation = pChild->GetAbsAngles();
  68. Vector vecAbsVelocity = pChild->GetAbsVelocity();
  69. // QAngle vecAbsAngVelocity = pChild->GetAbsAngularVelocity();
  70. UnlinkChild( pOldParent, pChild );
  71. LinkChild( pNewParent, pChild );
  72. // FIXME: This is a hack to guarantee update of the local origin, angles, etc.
  73. pChild->m_vecAbsOrigin.Init( FLT_MAX, FLT_MAX, FLT_MAX );
  74. pChild->m_angAbsRotation.Init( FLT_MAX, FLT_MAX, FLT_MAX );
  75. pChild->m_vecAbsVelocity.Init( FLT_MAX, FLT_MAX, FLT_MAX );
  76. pChild->SetAbsOrigin(vecAbsOrigin);
  77. pChild->SetAbsAngles(angAbsRotation);
  78. pChild->SetAbsVelocity(vecAbsVelocity);
  79. // pChild->SetAbsAngularVelocity(vecAbsAngVelocity);
  80. pChild = pOldParent->FirstMoveChild();
  81. }
  82. }
  83. void UnlinkFromParent( CBaseEntity *pRemove )
  84. {
  85. if ( pRemove->GetMoveParent() )
  86. {
  87. // NOTE: Have to do this before the unlink to ensure local coords are valid
  88. Vector vecAbsOrigin = pRemove->GetAbsOrigin();
  89. QAngle angAbsRotation = pRemove->GetAbsAngles();
  90. Vector vecAbsVelocity = pRemove->GetAbsVelocity();
  91. // QAngle vecAbsAngVelocity = pRemove->GetAbsAngularVelocity();
  92. UnlinkChild( pRemove->GetMoveParent(), pRemove );
  93. pRemove->SetLocalOrigin(vecAbsOrigin);
  94. pRemove->SetLocalAngles(angAbsRotation);
  95. pRemove->SetLocalVelocity(vecAbsVelocity);
  96. // pRemove->SetLocalAngularVelocity(vecAbsAngVelocity);
  97. pRemove->UpdateWaterState();
  98. }
  99. }
  100. //-----------------------------------------------------------------------------
  101. // Purpose: Clears the parent of all the children of the given object.
  102. //-----------------------------------------------------------------------------
  103. void UnlinkAllChildren( CBaseEntity *pParent )
  104. {
  105. CBaseEntity *pChild = pParent->FirstMoveChild();
  106. while ( pChild )
  107. {
  108. CBaseEntity *pNext = pChild->NextMovePeer();
  109. UnlinkFromParent( pChild );
  110. pChild = pNext;
  111. }
  112. }
  113. bool EntityIsParentOf( CBaseEntity *pParent, CBaseEntity *pEntity )
  114. {
  115. while ( pEntity->GetMoveParent() )
  116. {
  117. pEntity = pEntity->GetMoveParent();
  118. if ( pParent == pEntity )
  119. return true;
  120. }
  121. return false;
  122. }
  123. static void GetAllChildren_r( CBaseEntity *pEntity, CUtlVector<CBaseEntity *> &list )
  124. {
  125. for ( ; pEntity != NULL; pEntity = pEntity->NextMovePeer() )
  126. {
  127. list.AddToTail( pEntity );
  128. GetAllChildren_r( pEntity->FirstMoveChild(), list );
  129. }
  130. }
  131. int GetAllChildren( CBaseEntity *pParent, CUtlVector<CBaseEntity *> &list )
  132. {
  133. if ( !pParent )
  134. return 0;
  135. GetAllChildren_r( pParent->FirstMoveChild(), list );
  136. return list.Count();
  137. }
  138. int GetAllInHierarchy( CBaseEntity *pParent, CUtlVector<CBaseEntity *> &list )
  139. {
  140. if (!pParent)
  141. return 0;
  142. list.AddToTail( pParent );
  143. return GetAllChildren( pParent, list ) + 1;
  144. }