//----------------------------------------------------------------------------- // Purpose: Enumerates a this object's children, only recursing into groups. // Children of entities will not be enumerated. // Input : pfn - Enumeration callback function. Called once per child. // dwParam - User data to pass into the enumerating callback. // Type - Unless NULL, only objects of the given type will be enumerated. // Output : Returns FALSE if the enumeration was terminated early, TRUE if it completed. //----------------------------------------------------------------------------- BOOL CMapClass::EnumChildrenRecurseGroupsOnly(ENUMMAPCHILDRENPROC pfn, DWORD dwParam, MAPCLASSTYPE Type) { POSITION pos = Children.GetHeadPosition(); while (pos) { CMapClass *pChild = Children.GetNext(pos); if (!Type || pChild->IsMapClass(Type)) { if (!(*pfn)(pChild, dwParam)) { return FALSE; } } if (pChild->IsGroup()) { if (!pChild->EnumChildrenRecurseGroupsOnly(pfn, dwParam, Type)) { return FALSE; } } } return TRUE; }
//----------------------------------------------------------------------------- // Purpose: // Input : pDependent - //----------------------------------------------------------------------------- void CMapClass::AddDependent(CMapClass *pDependent) { // // Never add ourselves to our dependents. It creates a circular dependency // which is bad. // if (pDependent != this) { // // Also, never add one of our ancestors as a dependent. This too creates a // nasty circular dependency. // bool bIsOurAncestor = false; CMapClass *pTestParent = GetParent(); while (pTestParent != NULL) { if (pTestParent == pDependent) { bIsOurAncestor = true; break; } pTestParent = pTestParent->GetParent(); } if (!bIsOurAncestor) { m_Dependents.AddTail(pDependent); } } }
//------------------------------------------------------------------------------ // Purpose: Set icon being displayed on output button. //------------------------------------------------------------------------------ void CObjectProperties::UpdateOutputButton(void) { //VPROF_BUDGET( "CObjectProperties::UpdateOutputButton", "Object Properties" ); if (!m_pOutputButton) { return; } bool bHaveConnection = false; bool bIgnoreHiddenTargets = false; if ( m_pOutput ) bIgnoreHiddenTargets = !m_pOutput->ShouldShowHiddenTargets(); FOR_EACH_OBJ( m_DstObjects, pos ) { CMapClass *pObject = m_DstObjects.Element(pos); if ((pObject != NULL) && (pObject->IsMapClass(MAPCLASS_TYPE(CMapEntity)))) { CMapEntity *pEntity = (CMapEntity *)pObject; int nStatus = CEntityConnection::ValidateOutputConnections(pEntity, true, bIgnoreHiddenTargets); if (nStatus == CONNECTION_BAD) { SetOutputButtonState(CONNECTION_BAD); return; } else if (nStatus == CONNECTION_GOOD) { bHaveConnection = true; } } }
//----------------------------------------------------------------------------- // Purpose: Removes an object from the world. // Input : pObject - object to remove from the world. // bChildren - whether we're removing the object's children as well. //----------------------------------------------------------------------------- void CMapWorld::RemoveObjectFromWorld(CMapClass *pObject, bool bRemoveChildren) { Assert(pObject != NULL); if (pObject == NULL) { return; } // // Unlink the object from the tree. // CMapClass *pParent = pObject->GetParent(); Assert(pParent != NULL); if (pParent != NULL) { pParent->RemoveChild(pObject); } // // If it (or any of its children) is an entity, remove it from this // world's list of entities. // EntityList_Remove(pObject, bRemoveChildren); // // Notify the object so it can release any pointers it may have to other // objects in the world. We don't do this in RemoveChild because the object // may only be changing parents rather than leaving the world. // pObject->OnRemoveFromWorld(this, bRemoveChildren); }
//----------------------------------------------------------------------------- // Purpose: // Input : pNode - //----------------------------------------------------------------------------- void CMapWorld::CullTree_DumpNode(CCullTreeNode *pNode, int nDepth) { int nChildCount = pNode->GetChildCount(); char szText[100]; if (nChildCount == 0) { // Leaf OutputDebugString("LEAF:\n"); int nObjectCount = pNode->GetObjectCount(); for (int nObject = 0; nObject < nObjectCount; nObject++) { CMapClass *pMapClass = pNode->GetCullTreeObject(nObject); sprintf(szText, "%*c %p %s\n", nDepth, ' ', pMapClass, pMapClass->GetType()); OutputDebugString(szText); } } else { // Node sprintf(szText, "%*s\n", nDepth, "+"); OutputDebugString(szText); for (int nChild = 0; nChild < nChildCount; nChild++) { CCullTreeNode *pChild = pNode->GetCullTreeChild(nChild); CullTree_DumpNode(pChild, nDepth + 1); } OutputDebugString("\n"); } }
//----------------------------------------------------------------------------- // Purpose: // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool COP_Groups::SaveData(void) { if (!IsWindow(m_hWnd)) { return(false); } // // Apply the dialog data to all the objects being edited. // POSITION pos = m_pObjectList->GetHeadPosition(); while (pos != NULL) { CMapClass *pObject = m_pObjectList->GetNext(pos); // get current selection int iSel = m_cGroups.GetCurSel(); // find ID from selection (in listbox data) DWORD id = m_cGroups.GetItemData(iSel); if (id == NO_GROUP_ID && pObject->GetVisGroup()) { pObject->SetVisGroup(NULL); } else if (id != VALUE_DIFFERENT_ID) { CVisGroup *pGroup = CMapDoc::GetActiveMapDoc()->VisGroups_GroupForID(id); pObject->SetVisGroup(pGroup); } } return(true); }
//----------------------------------------------------------------------------- // Purpose: // Input : pObject - The object whose bounding box has changed. //----------------------------------------------------------------------------- void CCullTreeNode::UpdateAllCullTreeObjectsRecurse(void) { int nChildCount = GetChildCount(); if (nChildCount != 0) { for (int nChild = 0; nChild < nChildCount; nChild++) { CCullTreeNode *pChild = GetCullTreeChild(nChild); pChild->UpdateAllCullTreeObjectsRecurse(); } } else { int nObjectCount = GetObjectCount(); for (int nObject = 0; nObject < nObjectCount; nObject++) { CMapClass *pObject = GetCullTreeObject(nObject); Vector mins; Vector maxs; pObject->GetCullBox(mins, maxs); if (!BoxesIntersect(mins, maxs, bmins, bmaxs)) { RemoveCullTreeObject(pObject); } } } }
//----------------------------------------------------------------------------- // Purpose: This functions sets up the list of objects to be clipped. // Initially the list is passed in (typically a Selection set). On // subsequent "translation" updates the list is refreshed from the // m_pOrigObjects list. // Input: pList - the list of objects (solids) to be clipped //----------------------------------------------------------------------------- void Clipper3D::SetClipObjects( CMapObjectList *pList ) { // check for an empty list if( !pList ) return; // save the original list m_pOrigObjects = pList; // clear the clip results list ResetClipResults(); // // copy solids into the clip list // POSITION pos = m_pOrigObjects->GetHeadPosition(); while( pos ) { CMapClass *pObject = m_pOrigObjects->GetNext( pos ); if( !pObject ) continue; if( pObject->IsMapClass( MAPCLASS_TYPE( CMapSolid ) ) ) { AddToClipList( ( CMapSolid* )pObject, this ); } pObject->EnumChildren( ENUMMAPCHILDRENPROC( AddToClipList ), DWORD( this ), MAPCLASS_TYPE( CMapSolid ) ); } // the clipping list is not empty anymore m_bEmpty = FALSE; }
//----------------------------------------------------------------------------- // Purpose: Called after a map file has been completely loaded. // Input : pWorld - The world that we are in. //----------------------------------------------------------------------------- void CMapClass::PostloadWorld(CMapWorld *pWorld) { POSITION pos = Children.GetHeadPosition(); while (pos != NULL) { CMapClass *pChild = Children.GetNext(pos); pChild->PostloadWorld(pWorld); } }
//----------------------------------------------------------------------------- // Purpose: // Input : *szOldName - // *szNewName - //----------------------------------------------------------------------------- void CMapClass::ReplaceTargetname(const char *szOldName, const char *szNewName) { POSITION pos = Children.GetHeadPosition(); while (pos != NULL) { CMapClass *pObject = Children.GetNext(pos); pObject->ReplaceTargetname(szOldName, szNewName); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMapClass::RemoveAllVisGroups(void) { m_VisGroups.RemoveAll(); // Remove all visgroups from children as well. FOR_EACH_OBJ( m_Children, pos ) { CMapClass *pChild = m_Children.Element(pos); pChild->RemoveAllVisGroups(); }
//----------------------------------------------------------------------------- // Purpose: // Input : pError - //----------------------------------------------------------------------------- static void FixEmptyEntity(MapError *pError) { CMapClass *pKillMe = pError->pObjects[0]; if (pKillMe->GetParent() != NULL) { GetHistory()->KeepForDestruction(pKillMe); pKillMe->GetParent()->RemoveChild(pKillMe); } }
//----------------------------------------------------------------------------- // Purpose: Returns a coordinate frame to render in // Input : matrix - // Output : returns true if a new matrix is returned, false if it is invalid //----------------------------------------------------------------------------- bool CMapClass::GetTransformMatrix( matrix4_t& matrix ) { // try and get our parents transform matrix CMapClass *p = CMapClass::GetParent(); if ( p ) { return p->GetTransformMatrix( matrix ); } return false; }
//----------------------------------------------------------------------------- // Purpose: // Input : bVisible - //----------------------------------------------------------------------------- void CMapClass::SetVisible(bool bVisible) { POSITION pos = Children.GetHeadPosition(); while (pos != NULL) { CMapClass *pChild = Children.GetNext(pos); pChild->SetVisible(bVisible); } m_bVisible = bVisible; }
//----------------------------------------------------------------------------- // Purpose: Flips this object about a given point. // Input : RefPoint - Reference point about which to flip. Set any of the indices // to COORD_NOTINIT to NOT flip about that axis. //----------------------------------------------------------------------------- void CMapClass::DoTransFlip(const Vector &RefPoint) { CMapPoint::DoTransFlip(RefPoint); POSITION p = Children.GetHeadPosition(); while(p) { CMapClass *pChild = Children.GetNext(p); pChild->TransFlip(RefPoint); } }
//----------------------------------------------------------------------------- // Purpose: Moves all children. Derived implementations should call this, // then do their own thing. // Input : delta - //----------------------------------------------------------------------------- void CMapClass::DoTransMove(const Vector &delta) { CMapPoint::DoTransMove(delta); POSITION p = Children.GetHeadPosition(); while (p) { CMapClass *pChild = Children.GetNext(p); pChild->TransMove(delta); } }
//----------------------------------------------------------------------------- // Purpose: Transforms all children. Derived implementations should call this, // then do their own thing. // Input : t - Pointer to class containing transformation information. //----------------------------------------------------------------------------- void CMapClass::DoTransform(Box3D *t) { CMapPoint::DoTransform(t); POSITION p = Children.GetHeadPosition(); while (p != NULL) { CMapClass *pChild = Children.GetNext(p); pChild->Transform(t); } }
//----------------------------------------------------------------------------- // Purpose: Calls RenderPreload for each of our children. This allows them to // cache any resources that they need for rendering. // Input : pRender - Pointer to the 3D renderer. //----------------------------------------------------------------------------- bool CMapClass::RenderPreload(CRender3D *pRender, bool bNewContext) { POSITION pos = Children.GetHeadPosition(); while (pos != NULL) { CMapClass *pChild = Children.GetNext(pos); pChild->RenderPreload(pRender, bNewContext); } return(true); }
//----------------------------------------------------------------------------- // Purpose: Copies all children of a given object as children of this object. // NOTE: The child objects are replicated, not merely added as children. // Input : pobj - The object whose children are to be copied. //----------------------------------------------------------------------------- void CMapClass::CopyChildrenFrom(CMapClass *pobj, bool bUpdateDependencies) { POSITION p = pobj->Children.GetHeadPosition(); while (p != NULL) { CMapClass *pChild = pobj->Children.GetNext(p); CMapClass *pChildCopy = pChild->Copy(bUpdateDependencies); pChildCopy->CopyChildrenFrom(pChild, bUpdateDependencies); AddChild(pChildCopy); } }
//----------------------------------------------------------------------------- // Purpose: Called to notify the object that it has just been cloned // iterates through and notifies all the children of their cloned state // NOTE: assumes that the children are in the same order in both the // original and the clone // Input : pNewObj - the clone of this object // OriginalList - The list of objects that were cloned // NewList - The parallel list of clones of objects in OriginalList //----------------------------------------------------------------------------- void CMapClass::OnPreClone( CMapClass *pNewObj, CMapWorld *pWorld, CMapObjectList &OriginalList, CMapObjectList &NewList ) { POSITION p = Children.GetHeadPosition(); POSITION q = pNewObj->Children.GetHeadPosition(); while ( p && q ) { CMapClass *pChild = Children.GetNext( p ); CMapClass *pNewChild = pNewObj->Children.GetNext( q ); pChild->OnPreClone( pNewChild, pWorld, OriginalList, NewList ); } }
//----------------------------------------------------------------------------- // Purpose: Called after this object is added to the world. // // NOTE: This function is NOT called during serialization. Use PostloadWorld // to do similar bookkeeping after map load. // // Input : pWorld - The world that we have been added to. //----------------------------------------------------------------------------- void CMapClass::OnAddToWorld(CMapWorld *pWorld) { // // Notify all our children. // POSITION pos = Children.GetHeadPosition(); while (pos != NULL) { CMapClass *pChild = Children.GetNext(pos); pChild->OnAddToWorld(pWorld); } }
//----------------------------------------------------------------------------- // Purpose: Notifies this object that a copy of itself is being pasted. // Allows the object to fixup any references to other objects in the // clipboard with references to their copies. // Input : pCopy - // pSourceWorld - // pDestWorld - // OriginalList - // NewList - //----------------------------------------------------------------------------- void CMapClass::OnPaste(CMapClass *pCopy, CMapWorld *pSourceWorld, CMapWorld *pDestWorld, CMapObjectList &OriginalList, CMapObjectList &NewList) { POSITION p = Children.GetHeadPosition(); POSITION q = pCopy->Children.GetHeadPosition(); while (p && q) { CMapClass *pChild = Children.GetNext(p); CMapClass *pCopyChild = pCopy->Children.GetNext(q); pChild->OnPaste(pCopyChild, pSourceWorld, pDestWorld, OriginalList, NewList); } }
//----------------------------------------------------------------------------- // Purpose: Sets the origin of this object and its children. // FIXME: Should our children necessarily have the same origin as us? // Seems like we should translate our children by our origin delta //----------------------------------------------------------------------------- void CMapClass::SetOrigin( Vector& origin ) { CMapPoint::SetOrigin( origin ); POSITION pos = Children.GetHeadPosition(); while ( pos != NULL ) { CMapClass *pChild = Children.GetNext( pos ); pChild->SetOrigin( origin ); } PostUpdate(Notify_Changed); }
BOOL CMapClass::IsChildOf(CMapClass *pObject) { CMapClass *pParent = Parent; while(1) { if(pParent == pObject) return TRUE; if(pParent->IsWorldObject()) break; // world object, not parent .. return false. pParent = pParent->Parent; } return FALSE; }
//----------------------------------------------------------------------------- // Purpose: // Input : pView - // point - // nData - // Output : //----------------------------------------------------------------------------- CMapClass *CMapClass::HitTest2D(CMapView2D *pView, const Vector2D &point, int &nHitData) { POSITION pos = Children.GetHeadPosition(); while (pos != NULL) { CMapClass *pChild = Children.GetNext(pos); CMapClass *pHit = pChild->HitTest2D(pView, point, nHitData); if (pHit != NULL) { return pHit; } } return NULL; }
//----------------------------------------------------------------------------- // Purpose: Returns the world object that the given object belongs to. // Input : pStart - Object to traverse up from to find the world object. //----------------------------------------------------------------------------- CMapWorld *CMapClass::GetWorldObject(CMapClass *pStart) { CMapClass *pobj = pStart; while (pobj != NULL) { if (pobj->IsWorldObject()) { return((CMapWorld *)pobj); } pobj = pobj->Parent; } // has no world: return NULL; }
//----------------------------------------------------------------------------- // Purpose: Iterates through an object, and all it's children, looking for an // entity with a matching key and value // Input : key - // value - // Output : CMapEntity - the entity found //----------------------------------------------------------------------------- CMapEntity *CMapClass::FindChildByKeyValue( LPCSTR key, LPCSTR value ) { if ( !key || !value ) return NULL; POSITION p = Children.GetHeadPosition(); while( p ) { CMapClass *pChild = Children.GetNext( p ); CMapEntity *e = pChild->FindChildByKeyValue( key, value ); if ( e ) return e; } return NULL; }
//----------------------------------------------------------------------------- // Purpose: Sets the render color of this object and all its children. // Input : uchRed, uchGreen, uchBlue - Color components. //----------------------------------------------------------------------------- void CMapClass::SetRenderColor(unsigned char uchRed, unsigned char uchGreen, unsigned char uchBlue) { CMapAtom::SetRenderColor(uchRed, uchGreen, uchBlue); // // Set the render color of all our children. // POSITION pos = Children.GetHeadPosition(); while (pos != NULL) { CMapClass *pChild = Children.GetNext(pos); if (pChild != NULL) { pChild->SetRenderColor(uchRed, uchGreen, uchBlue); } } }
//----------------------------------------------------------------------------- // Purpose: Sets the render color of this object and all its children. // Input : uchRed, uchGreen, uchBlue - Color components. //----------------------------------------------------------------------------- void CMapClass::SetRenderColor(color32 rgbColor) { CMapAtom::SetRenderColor(rgbColor); // // Set the render color of all our children. // POSITION pos = Children.GetHeadPosition(); while (pos != NULL) { CMapClass *pChild = Children.GetNext(pos); if (pChild != NULL) { pChild->SetRenderColor(rgbColor); } } }
//----------------------------------------------------------------------------- // Purpose: Recalculate's this object's bounding boxes. CMapClass-derived classes // should call this first, then update using their local data. // Input : bFullUpdate - When set to TRUE, call CalcBounds on all children // before updating our bounds. //----------------------------------------------------------------------------- void CMapClass::CalcBounds(BOOL bFullUpdate) { m_CullBox.ResetBounds(); m_Render2DBox.ResetBounds(); POSITION p = Children.GetHeadPosition(); while (p) { CMapClass *pChild = Children.GetNext(p); if (bFullUpdate) { pChild->CalcBounds(TRUE); } m_CullBox.UpdateBounds(&pChild->m_CullBox); m_Render2DBox.UpdateBounds(&pChild->m_Render2DBox); } }