//-----------------------------------------------------------------------------
// Purpose: 
// Input  : pszValue - 
//			pWorld - The world object that we are contained in.
//-----------------------------------------------------------------------------
void CMapSideList::BuildFaceListForValue(char const *pszValue, CMapWorld *pWorld)
{
	CMapFaceList NewFaces;
	pWorld->FaceID_StringToFaceLists(&NewFaces, NULL, pszValue);

	//
	// Detach from the faces that are not in the new list. Go
	// in reverse order since we are removing items as we go.
	//
	if (m_Faces.Count() > 0)
	{
		for (int i = m_Faces.Count() - 1; i >= 0; i--)
		{
			CMapFace *pFace = m_Faces.Element(i);
			ASSERT(pFace != NULL);
			if ((pFace != NULL) && (NewFaces.Find(pFace) == -1))
			{
				CMapSolid *pSolid = (CMapSolid *)pFace->GetParent();
				UpdateDependency(pSolid, NULL);
				m_Faces.FastRemove(i);
			}
		}
	}

	//
	// Attach to the faces that are not in the old list.
	//
	for (int i = 0; i < NewFaces.Count(); i++)
	{
		CMapFace *pFace = NewFaces.Element(i);
		ASSERT(pFace != NULL);

		if ((pFace != NULL) && (m_Faces.Find(pFace) == -1))
		{
			CMapSolid *pSolid = (CMapSolid *)pFace->GetParent();
			UpdateDependency(NULL, pSolid);
			m_Faces.AddToTail(pFace);
		}
	}

	CalcBounds();
}
//-----------------------------------------------------------------------------
// Purpose: Called just after this object has been removed from the world so
//			that it can unlink itself from other objects in the world.
// Input  : pWorld - The world that we were just removed from.
//			bNotifyChildren - Whether we should forward notification to our children.
//-----------------------------------------------------------------------------
void CMapSideList::OnRemoveFromWorld(CMapWorld *pWorld, bool bNotifyChildren)
{
	CMapClass::OnRemoveFromWorld(pWorld, bNotifyChildren);

	for (int i = 0; i < m_Faces.Count(); i++)
	{
		CMapFace *pFace = m_Faces.Element(i);
		CMapSolid *pSolid = (CMapSolid *)pFace->GetParent();
		UpdateDependency(pSolid, NULL);
	}
	
	m_Faces.RemoveAll();
}
//-----------------------------------------------------------------------------
// Purpose: Reports errors for all faces with duplicate face IDs.
// Input  : pList - 
//			pWorld -  
//-----------------------------------------------------------------------------
static void CheckDuplicateFaceIDs(CListBox *pList, CMapWorld *pWorld)
{
	FindDuplicateFaceIDs_t Lists;
	Lists.All.SetGrowSize(128);
	Lists.Duplicates.SetGrowSize(128);

	pWorld->EnumChildren((ENUMMAPCHILDRENPROC)FindDuplicateFaceIDs, (DWORD)&Lists, MAPCLASS_TYPE(CMapSolid));

	for (int i = 0; i < Lists.Duplicates.Count(); i++)
	{
		CMapFace *pFace = Lists.Duplicates.Element(i);
		AddError(pList, ErrorDuplicateFaceIDs, (DWORD)pFace, (CMapSolid *)pFace->GetParent());
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : List - 
//-----------------------------------------------------------------------------
void CMapSideList::RemoveFacesNotInList(CMapObjectList &List)
{
	if (m_Faces.Count() > 0)
	{
		for (int i = m_Faces.Count() - 1; i >= 0; i--)
		{
			CMapFace *pFace = m_Faces.Element(i);

			if (FindFaceIDInList(pFace->GetFaceID(), List) == NULL)
			{
				CMapSolid *pSolid = (CMapSolid *)pFace->GetParent();
				UpdateDependency(pSolid, NULL);
				m_Faces.FastRemove(i);
			}
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: Turns us into an exact copy of the given object.
// Input  : pFrom - Object to copy.
// Input  : bUpdateDependencies - Whether we should link to any other objects
//				in the world when we copy pointers.
//-----------------------------------------------------------------------------
CMapClass *CMapSideList::CopyFrom(CMapClass *pOther, bool bUpdateDependencies)
{
	CMapSideList *pFrom = dynamic_cast <CMapSideList *>(pOther);
	ASSERT(pFrom != NULL);

	CMapClass::CopyFrom(pOther, bUpdateDependencies);

	strcpy(m_szKeyName, pFrom->m_szKeyName);
	m_Faces = pFrom->m_Faces;

	if (bUpdateDependencies)
	{
		for (int i = 0; i < m_Faces.Count(); i++)
		{
			CMapFace *pFace = m_Faces.Element(i);
			CMapSolid *pSolid = (CMapSolid *)pFace->GetParent();
			UpdateDependency(pSolid, NULL);
		}
	}

	return(this);
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : pObject - 
//			eNotifyType - 
//-----------------------------------------------------------------------------
void CMapSideList::OnNotifyDependent(CMapClass *pObject, Notify_Dependent_t eNotifyType)
{
	if (eNotifyType == Notify_Removed)
	{
		//
		// Check for a solid that we refer to via face ID going away.
		//
		CMapSolid *pSolid = dynamic_cast<CMapSolid *>(pObject);
		if ((pSolid != NULL) && (m_Faces.Count() > 0))
		{
			//
			// Remove faces from our list that are in this solid.
			// Do it backwards so we can remove them as we go. Also, add
			// the face IDs to our list of lost IDs so that we can reacquire
			// the face in our list if the solid comes back later.
			//
			for (int i = m_Faces.Count() - 1; i >= 0; i--)
			{
				CMapFace *pFace = m_Faces.Element(i);
				if (pFace != NULL)
				{
					CMapSolid *pParent = (CMapSolid *)pFace->GetParent();
					if (pParent == pSolid)
					{
						m_LostFaceIDs.AddToTail(pFace->GetFaceID());
						m_Faces.FastRemove(i);
					}
				}
			}
		
			//
			// Submit the updated face list to our parent entity.
			//
			UpdateParentKey();
		}
	}
}