From 39ed87570bdb2f86969d4be821c94b722dc71179 Mon Sep 17 00:00:00 2001 From: Joe Ludwig Date: Wed, 26 Jun 2013 15:22:04 -0700 Subject: First version of the SOurce SDK 2013 --- mp/src/game/server/hierarchy.cpp | 169 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 mp/src/game/server/hierarchy.cpp (limited to 'mp/src/game/server/hierarchy.cpp') diff --git a/mp/src/game/server/hierarchy.cpp b/mp/src/game/server/hierarchy.cpp new file mode 100644 index 00000000..df3126a1 --- /dev/null +++ b/mp/src/game/server/hierarchy.cpp @@ -0,0 +1,169 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Contains the set of functions for manipulating entity hierarchies. +// +// $NoKeywords: $ +//=============================================================================// + +// UNDONE: Reconcile this with SetParent() + +#include "cbase.h" +#include "hierarchy.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//----------------------------------------------------------------------------- +// Purpose: Does the linked list work of removing a child object from the hierarchy. +// Input : pParent - +// pChild - +//----------------------------------------------------------------------------- +void UnlinkChild( CBaseEntity *pParent, CBaseEntity *pChild ) +{ + CBaseEntity *pList; + EHANDLE *pPrev; + + pList = pParent->m_hMoveChild; + pPrev = &pParent->m_hMoveChild; + while ( pList ) + { + CBaseEntity *pNext = pList->m_hMovePeer; + if ( pList == pChild ) + { + // patch up the list + pPrev->Set( pNext ); + + // Clear hierarchy bits for this guy + pList->m_hMoveParent.Set( NULL ); + pList->m_hMovePeer.Set( NULL ); + pList->NetworkProp()->SetNetworkParent( CBaseHandle() ); + pList->DispatchUpdateTransmitState(); + pList->OnEntityEvent( ENTITY_EVENT_PARENT_CHANGED, NULL ); + + pParent->RecalcHasPlayerChildBit(); + return; + } + else + { + pPrev = &pList->m_hMovePeer; + pList = pNext; + } + } + + // This only happens if the child wasn't found in the parent's child list + Assert(0); +} + +void LinkChild( CBaseEntity *pParent, CBaseEntity *pChild ) +{ + EHANDLE hParent; + hParent.Set( pParent ); + pChild->m_hMovePeer.Set( pParent->FirstMoveChild() ); + pParent->m_hMoveChild.Set( pChild ); + pChild->m_hMoveParent = hParent; + pChild->NetworkProp()->SetNetworkParent( hParent ); + pChild->DispatchUpdateTransmitState(); + pChild->OnEntityEvent( ENTITY_EVENT_PARENT_CHANGED, NULL ); + pParent->RecalcHasPlayerChildBit(); +} + +void TransferChildren( CBaseEntity *pOldParent, CBaseEntity *pNewParent ) +{ + CBaseEntity *pChild = pOldParent->FirstMoveChild(); + while ( pChild ) + { + // NOTE: Have to do this before the unlink to ensure local coords are valid + Vector vecAbsOrigin = pChild->GetAbsOrigin(); + QAngle angAbsRotation = pChild->GetAbsAngles(); + Vector vecAbsVelocity = pChild->GetAbsVelocity(); +// QAngle vecAbsAngVelocity = pChild->GetAbsAngularVelocity(); + + UnlinkChild( pOldParent, pChild ); + LinkChild( pNewParent, pChild ); + + // FIXME: This is a hack to guarantee update of the local origin, angles, etc. + pChild->m_vecAbsOrigin.Init( FLT_MAX, FLT_MAX, FLT_MAX ); + pChild->m_angAbsRotation.Init( FLT_MAX, FLT_MAX, FLT_MAX ); + pChild->m_vecAbsVelocity.Init( FLT_MAX, FLT_MAX, FLT_MAX ); + + pChild->SetAbsOrigin(vecAbsOrigin); + pChild->SetAbsAngles(angAbsRotation); + pChild->SetAbsVelocity(vecAbsVelocity); +// pChild->SetAbsAngularVelocity(vecAbsAngVelocity); + + pChild = pOldParent->FirstMoveChild(); + } +} + +void UnlinkFromParent( CBaseEntity *pRemove ) +{ + if ( pRemove->GetMoveParent() ) + { + // NOTE: Have to do this before the unlink to ensure local coords are valid + Vector vecAbsOrigin = pRemove->GetAbsOrigin(); + QAngle angAbsRotation = pRemove->GetAbsAngles(); + Vector vecAbsVelocity = pRemove->GetAbsVelocity(); +// QAngle vecAbsAngVelocity = pRemove->GetAbsAngularVelocity(); + + UnlinkChild( pRemove->GetMoveParent(), pRemove ); + + pRemove->SetLocalOrigin(vecAbsOrigin); + pRemove->SetLocalAngles(angAbsRotation); + pRemove->SetLocalVelocity(vecAbsVelocity); +// pRemove->SetLocalAngularVelocity(vecAbsAngVelocity); + pRemove->UpdateWaterState(); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Clears the parent of all the children of the given object. +//----------------------------------------------------------------------------- +void UnlinkAllChildren( CBaseEntity *pParent ) +{ + CBaseEntity *pChild = pParent->FirstMoveChild(); + while ( pChild ) + { + CBaseEntity *pNext = pChild->NextMovePeer(); + UnlinkFromParent( pChild ); + pChild = pNext; + } +} + +bool EntityIsParentOf( CBaseEntity *pParent, CBaseEntity *pEntity ) +{ + while ( pEntity->GetMoveParent() ) + { + pEntity = pEntity->GetMoveParent(); + if ( pParent == pEntity ) + return true; + } + + return false; +} + +static void GetAllChildren_r( CBaseEntity *pEntity, CUtlVector &list ) +{ + for ( ; pEntity != NULL; pEntity = pEntity->NextMovePeer() ) + { + list.AddToTail( pEntity ); + GetAllChildren_r( pEntity->FirstMoveChild(), list ); + } +} + +int GetAllChildren( CBaseEntity *pParent, CUtlVector &list ) +{ + if ( !pParent ) + return 0; + + GetAllChildren_r( pParent->FirstMoveChild(), list ); + return list.Count(); +} + +int GetAllInHierarchy( CBaseEntity *pParent, CUtlVector &list ) +{ + if (!pParent) + return 0; + list.AddToTail( pParent ); + return GetAllChildren( pParent, list ) + 1; +} -- cgit v1.2.3