//-----------------------------------------------------------------------------
// Purpose: 
// Input  : pSolid - 
//			pData - 
// Output : Returns TRUE to continue enumerating.
//-----------------------------------------------------------------------------
static BOOL FindDuplicateFaceIDs(CMapSolid *pSolid, FindDuplicateFaceIDs_t *pData)
{
	int nFaceCount = pSolid->GetFaceCount();
	for (int i = 0; i < nFaceCount; i++)
	{
		CMapFace *pFace = pSolid->GetFace(i);
		if (pData->All.FindFaceID(pFace->GetFaceID()) != -1)
		{
			if (pData->Duplicates.FindFaceID(pFace->GetFaceID()) != -1)
			{
				pData->Duplicates.AddToTail(pFace);
			}
		}
		else
		{
			pData->All.AddToTail(pFace);
		}
	}

	return(TRUE);
}
//-----------------------------------------------------------------------------
// 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: Called from OnClone and OnPaste, updates references to face IDs 
//			in the one solid with references to corresponding face IDs in
//			another solid.
// Input  : pOrigSolid - Solid with faces to find.
//			pNewSolid - Solid with faces to replace with.
// Output : Returns true if it replaced at least one face.
//-----------------------------------------------------------------------------
bool CMapSideList::ReplaceSolidFaces(CMapSolid *pOrigSolid, CMapSolid *pNewSolid)
{
	bool bDidSomething = false;
	for (int i = 0; i < pOrigSolid->GetFaceCount(); i++)
	{
		CMapFace *pFace = pOrigSolid->GetFace(i);

		int nIndex = m_Faces.FindFaceID(pFace->GetFaceID());
		if (nIndex != -1)
		{
			//
			// Replace the element in our face list and unlink
			// us from the original solid, relinking us to the new solid.
			//
			m_Faces.Element(nIndex) = pNewSolid->GetFace(i);
			UpdateDependency(pOrigSolid, pNewSolid);
			bDidSomething = true;
		}
	}

	return(bDidSomething);
}
//-----------------------------------------------------------------------------
// 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();
		}
	}
}
void CSSolid::FromMapSolid(CMapSolid *p, bool bSkipDisplacementFaces)
{
	// so we can pass NULL (default) or another solid (to copy):
	CMapSolid *pSolid;
	if(p)
		pSolid = p;
	else
		pSolid = m_pMapSolid;

	m_nFaces = 0;
	m_nEdges = 0;
	m_nVertices = 0;

	// Create vertices, edges, faces.
	int nSolidFaces = pSolid->GetFaceCount();
	for(int i = 0; i < nSolidFaces; i++)
	{
		CMapFace *pSolidFace = pSolid->GetFace(i);

		if (bSkipDisplacementFaces)
		{
			if (pSolidFace->HasDisp())
				continue;
		}

		// Add a face
		CSSFace *pFace = AddFace();

		memcpy(pFace->PlanePts, pSolidFace->plane.planepts, sizeof(Vector) * 3);
		pFace->texture = pSolidFace->texture;
		pFace->normal = pSolidFace->plane.normal;
		pFace->m_nFaceID = pSolidFace->GetFaceID();

		// Displacement.
		if ( pSolidFace->HasDisp() )
		{
			pFace->m_hDisp = EditDispMgr()->Create();
			CMapDisp *pDisp = EditDispMgr()->GetDisp( pFace->m_hDisp );
			CMapDisp *pSolidDisp = EditDispMgr()->GetDisp( pSolidFace->GetDisp() );
			pDisp->CopyFrom( pSolidDisp, false );
		}

		// Convert vertices and edges
		int nFacePoints = pSolidFace->nPoints;
		Vector *pFacePoints = pSolidFace->Points;
		SSHANDLE hLastVertex = 0;	// valid IDs start at 1
		SSHANDLE hThisVertex, hFirstVertex;
		for(int pt = 0; pt <= nFacePoints; pt++)
		{
			int iVertex;
			
			if(pt < nFacePoints)
			{
				// YWB:  Change leniency from 1.0 down to 0.1
				iVertex = GetVertexIndex(pFacePoints[pt], 0.1f);
				if (iVertex == -1)
				{
					// not found - add the vertex
					CSSVertex *pVertex = AddVertex(&iVertex);
					pVertex->pos = pFacePoints[pt];
				}

				// assign this vertex handle
				hThisVertex = m_Vertices[iVertex].id;

				if (pt == 0)
					hFirstVertex = hThisVertex;
			}
			else
			{
				// connect last to first
				hThisVertex = hFirstVertex;
			}

			if (hLastVertex)
			{
				// create the edge from the last vertex to current vertex.
				//  first check to see if this edge already exists.. 
				int iEdge = GetEdgeIndex(hLastVertex, hThisVertex);
				CSSEdge *pEdge;
				if (iEdge == -1)
				{
					// not found - add new edge
					pEdge = AddEdge(&iEdge);
					pEdge->hvStart = hLastVertex;
					pEdge->hvEnd   = hThisVertex;

					// make sure edge center is valid:
					CalcEdgeCenter(pEdge);
				}
				else
				{
					pEdge = &m_Edges[iEdge];
				}

				// add the edge to the face
				pFace->Edges[pFace->nEdges++] = pEdge->id;

				// set edge's face array
				if(!pEdge->Faces[0])
					pEdge->Faces[0] = pFace->id;
				else if(!pEdge->Faces[1])
					pEdge->Faces[1] = pFace->id;
				else
				{
					// YWB try filling in front side
					//  rather than ASSERT(0) crash
					pEdge->Faces[0] = pFace->id;
					AfxMessageBox("Edge with both face id's already filled, skipping...");
				}
			}

			hLastVertex = hThisVertex;
		}
	}
}