Counter Strike : Global Offensive Source Code
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.

180 lines
5.2 KiB

  1. //========= Copyright � 1996-2005, 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( INVALID_EHANDLE );
  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. // objects with physics need to know that they got teleported. Otherwise physics will tell us where to go later.
  97. IPhysicsObject *pObject = pRemove->VPhysicsGetObject();
  98. if( pObject )
  99. {
  100. pObject->SetPosition( vecAbsOrigin, angAbsRotation, true );
  101. }
  102. // pRemove->SetLocalAngularVelocity(vecAbsAngVelocity);
  103. if ( pRemove->GetMoveType() != MOVETYPE_NONE && pRemove->GetMoveType() != MOVETYPE_VPHYSICS )
  104. {
  105. pRemove->UpdateWaterState();
  106. }
  107. }
  108. }
  109. //-----------------------------------------------------------------------------
  110. // Purpose: Clears the parent of all the children of the given object.
  111. //-----------------------------------------------------------------------------
  112. void UnlinkAllChildren( CBaseEntity *pParent )
  113. {
  114. CBaseEntity *pChild = pParent->FirstMoveChild();
  115. while ( pChild )
  116. {
  117. CBaseEntity *pNext = pChild->NextMovePeer();
  118. UnlinkFromParent( pChild );
  119. pChild = pNext;
  120. }
  121. }
  122. bool EntityIsParentOf( CBaseEntity *pParent, CBaseEntity *pEntity )
  123. {
  124. while ( pEntity->GetMoveParent() )
  125. {
  126. pEntity = pEntity->GetMoveParent();
  127. if ( pParent == pEntity )
  128. return true;
  129. }
  130. return false;
  131. }
  132. static void GetAllChildren_r( CBaseEntity *pEntity, CUtlVector<CBaseEntity *> &list )
  133. {
  134. for ( ; pEntity != NULL; pEntity = pEntity->NextMovePeer() )
  135. {
  136. list.AddToTail( pEntity );
  137. GetAllChildren_r( pEntity->FirstMoveChild(), list );
  138. }
  139. }
  140. int GetAllChildren( CBaseEntity *pParent, CUtlVector<CBaseEntity *> &list )
  141. {
  142. if ( !pParent )
  143. return 0;
  144. GetAllChildren_r( pParent->FirstMoveChild(), list );
  145. return list.Count();
  146. }
  147. int GetAllInHierarchy( CBaseEntity *pParent, CUtlVector<CBaseEntity *> &list )
  148. {
  149. if (!pParent)
  150. return 0;
  151. list.AddToTail( pParent );
  152. return GetAllChildren( pParent, list ) + 1;
  153. }