예제 #1
0
//-----------------------------------------------------------------------------
// Purpose: Determines whether a solid is good or bad.
// Input  : pSolid - Solid to check.
//			pList - List box into which to place errors.
// Output : Always returns TRUE to continue enumerating.
//-----------------------------------------------------------------------------
static BOOL _CheckSolidIntegrity(CMapSolid *pSolid, CListBox *pList)
{
	CCheckFaceInfo cfi;
	int nFaces = pSolid->GetFaceCount();
	for (int i = 0; i < nFaces; i++)
	{
		CMapFace *pFace = pSolid->GetFace(i);

		//
		// Reset the iPoint member so results from previous faces don't carry over.
		//
		cfi.iPoint = -1;

		//
		// Check the face.
		//
		if (!pFace->CheckFace(&cfi))
		{
			AddError(pList, ErrorSolidStructure, 0, pSolid);
			break;
		}
	}

	return(TRUE);
}
예제 #2
0
//-----------------------------------------------------------------------------
// Purpose: Repairs an invalid solid.
// Input  : pError - Contains information about the error.
//-----------------------------------------------------------------------------
static void FixSolidStructure(MapError *pError)
{
	CMapSolid *pSolid = (CMapSolid *)pError->pObjects[0];

	//
	// First make sure all the faces are good.
	//
	int nFaces = pSolid->GetFaceCount();
	for (int i = nFaces - 1; i >= 0; i--)
	{
		CMapFace *pFace = pSolid->GetFace(i);
		if (!pFace->CheckFace(NULL))
		{
			pFace->Fix();
		}
		//
		// If the face has no points, just remove it from the solid.
		//
		if (pFace->GetPointCount() == 0)
		{
			pSolid->DeleteFace(i);
		}
	}

	//
	// Rebuild the solid from the planes.
	//
	pSolid->CreateFromPlanes();
	pSolid->PostUpdate(Notify_Changed);
}
예제 #3
0
//-----------------------------------------------------------------------------
// Purpose: Fixes duplicate face IDs by assigning the face a unique ID within
//			the world.
// Input  : pError - Holds the world and the face that is in error.
//-----------------------------------------------------------------------------
static void FixDuplicateFaceIDs(MapError *pError)
{
	CMapWorld *pWorld = (CMapWorld *)pError->pObjects[0];
	CMapFace *pFace = (CMapFace *)pError->dwExtra;

	pFace->SetFaceID(pWorld->FaceID_GetNext());
}
예제 #4
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : pSolid - 
//			pList - 
// Output : 
//-----------------------------------------------------------------------------
static BOOL _CheckLightmapSizeOnDisplacement( CMapSolid *pSolid, CListBox *pList )
{
	//
	// check all faces with the displacement parameter for proper 
	// lightmap size
	//
	int faceCount = pSolid->GetFaceCount();
	for( int i = 0; i < faceCount; i++ )
	{
		//
		// check for faces with a displacement map
		//
		CMapFace *pFace = pSolid->GetFace( i );
		if( !pFace->HasDisp() )
			continue;

		//
		// check the lightmap extents
		//
		if( !pFace->ValidLightmapSize() )
		{
			AddError( pList, ErrorInvalidLightmapSizeOnDisplacement, i, pSolid );
			break;
		}		
	}

	return TRUE;
}
예제 #5
0
//-----------------------------------------------------------------------------
// Purpose: Initialize the cull box with the bounds of the faces.
//-----------------------------------------------------------------------------
void CMapClass::SetCullBoxFromFaceList( CMapFaceList *pFaces )
{
	//
	// Calculate our 3D bounds.
	//
	m_CullBox.ResetBounds();
	for (int i = 0; i < pFaces->Count(); i++)
	{
		CMapFace *pFace = pFaces->Element(i);
		int nPoints = pFace->GetPointCount();
		for (int i = 0; i < nPoints; i++)
		{
			Vector point;
			pFace->GetPoint(point, i);

			//
			// Push the culling box out in all directions.
			// TODO: rotate the culling box based on the cone orientation
			//			
			for (int nDim = 0; nDim < 3; nDim++)
			{
				m_CullBox.bmins[0] = min(m_CullBox.bmins[0], m_Origin[0] - point[nDim]);
				m_CullBox.bmins[1] = min(m_CullBox.bmins[1], m_Origin[1] - point[nDim]);
				m_CullBox.bmins[2] = min(m_CullBox.bmins[2], m_Origin[2] - point[nDim]);

				m_CullBox.bmaxs[0] = max(m_CullBox.bmaxs[0], m_Origin[0] + point[nDim]);
				m_CullBox.bmaxs[1] = max(m_CullBox.bmaxs[1], m_Origin[1] + point[nDim]);
				m_CullBox.bmaxs[2] = max(m_CullBox.bmaxs[2], m_Origin[2] + point[nDim]);
			}
		}
	}
}
예제 #6
0
//-----------------------------------------------------------------------------
// 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();
}
예제 #7
0
static void FixInvalidTextureAxes(MapError *pError)
{
	CMapSolid *pSolid = (CMapSolid *)pError->pObjects[0];

	int nFaces = pSolid->GetFaceCount();
	for (int i = 0; i < nFaces; i++)
	{
		CMapFace *pFace = pSolid->GetFace(i);
		if (!pFace->IsTextureAxisValid())
		{
			pFace->InitializeTextureAxes(Options.GetTextureAlignment(), INIT_TEXTURE_FORCE | INIT_TEXTURE_AXES);
		}
	}
}
예제 #8
0
//-----------------------------------------------------------------------------
// 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  : Extents - 
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::GetAllFaceExtents( Extents_t Extents )
{
	BOOL		bFirst = TRUE;
	Extents_t	FaceExtents;

	CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent();
	int faceCount = pSheet->GetFaceListCount();	

	for( int nFace = 0; nFace < faceCount; nFace++ )
	{
		CMapFace *pFace = pSheet->GetFaceListDataFace( nFace );
		pFace->GetFaceExtents(FaceExtents);

		if ((FaceExtents[EXTENTS_XMIN][0] < Extents[EXTENTS_XMIN][0]) || (bFirst))
		{
			Extents[EXTENTS_XMIN] = FaceExtents[EXTENTS_XMIN];
		}

		if ((FaceExtents[EXTENTS_XMAX][0] > Extents[EXTENTS_XMAX][0]) || (bFirst))
		{
			Extents[EXTENTS_XMAX] = FaceExtents[EXTENTS_XMAX];
		}

		if ((FaceExtents[EXTENTS_YMIN][1] < Extents[EXTENTS_YMIN][1]) || (bFirst))
		{
			Extents[EXTENTS_YMIN] = FaceExtents[EXTENTS_YMIN];
		}

		if ((FaceExtents[EXTENTS_YMAX][1] > Extents[EXTENTS_YMAX][1]) || (bFirst))
		{
			Extents[EXTENTS_YMAX] = FaceExtents[EXTENTS_YMAX];
		}

		if ((FaceExtents[EXTENTS_ZMIN][2] < Extents[EXTENTS_ZMIN][2]) || (bFirst))
		{
			Extents[EXTENTS_ZMIN] = FaceExtents[EXTENTS_ZMIN];
		}

		if ((FaceExtents[EXTENTS_ZMAX][2] > Extents[EXTENTS_ZMAX][2]) || (bFirst))
		{
			Extents[EXTENTS_ZMAX] = FaceExtents[EXTENTS_ZMAX];
		}

		bFirst = FALSE;
	}
}
예제 #10
0
//-----------------------------------------------------------------------------
// 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);
			}
		}
	}
}
void CBSPTree_CollisionModel_Exporter::MakePolygonFromFace(ConvexPolygon& rPolygon, // [out]
														   CMapFace& rFace)			 // [in]
{
	Vector3 avVertex[128];
	int i;
	for( i=0; i<rFace.GetNumVertices(); i++ )
		avVertex[i] = rFace.GetVertex(i);

	rPolygon.SetVertices( avVertex, rFace.GetNumVertices() );
	rPolygon.SetNormal( rFace.GetPlane().normal );
	rPolygon.SetDistance( rFace.GetPlane().dist );

//	if( rFace.m_iPolygonIndex < 0 )
//		MessageBox( NULL, "invalid polygon index", "error", MB_OK|MB_ICONWARNING );

	// set the index to the corresponding 'SPolygon'
	rPolygon.m_iPolygonIndex = rFace.m_iPolygonIndex;
}
예제 #12
0
//-----------------------------------------------------------------------------
// 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();
}
예제 #13
0
//-----------------------------------------------------------------------------
// Purpose: Sets the fully selected and partially selected faces for the picker.
// Input  : FaceListFull - 
//			FaceListPartial - 
//-----------------------------------------------------------------------------
void CToolPickFace::SetSelectedFaces(CMapFaceList &FaceListFull, CMapFaceList &FaceListPartial)
{
	m_Faces.RemoveAll();

	for (int i = 0; i < FaceListFull.Count(); i++)
	{
		CMapFace *pFace = FaceListFull.Element(i);

		AddToList(pFace, FaceState_Select);
		pFace->SetSelectionState(SELECT_NORMAL);
	}

	for (i = 0; i < FaceListPartial.Count(); i++)
	{
		CMapFace *pFace = FaceListPartial.Element(i);

		AddToList(pFace, FaceState_Partial);
		pFace->SetSelectionState(SELECT_MULTI_PARTIAL);
	}
}
예제 #14
0
//-----------------------------------------------------------------------------
// 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);
}
예제 #15
0
//-----------------------------------------------------------------------------
// Purpose: Replaces any missing textures with the default texture.
// Input  : pError - 
//-----------------------------------------------------------------------------
static void FixInvalidTexture(MapError *pError)
{
	CMapSolid *pSolid = (CMapSolid *)pError->pObjects[0];

	int nFaces = pSolid->GetFaceCount();
	for (int i = 0; i < nFaces; i++)
	{
		CMapFace *pFace = pSolid->GetFace(i);
		if (pFace != NULL)
		{
			IEditorTexture *pTex = pFace->GetTexture();
			if (pTex != NULL)
			{
				if (pTex->IsDummy())
				{
					pFace->SetTexture(GetDefaultTextureName());
				}
			}
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : uCmd - 
// Output : Returns TRUE on success, FALSE on failure.
//-----------------------------------------------------------------------------
BOOL CFaceEditMaterialPage::OnAlign( UINT uCmd )
{
	// Set the material tool current.
	SetMaterialPageTool( MATERIALPAGETOOL_MATERIAL );

	// mark position in undo stack
	GetHistory()->MarkUndoPosition(NULL, "Align texture");

	CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent();
	int faceCount = pSheet->GetFaceListCount();

	for( int i = 0; i < faceCount; i++ )
	{
		CMapFace *pFace = pSheet->GetFaceListDataFace( i );

		CMapSolid *pSolid = pSheet->GetFaceListDataSolid( i );
		GetHistory()->Keep( pSolid );

		switch( uCmd )
		{
			case IDC_ALIGN_WORLD:
			{
				pFace->InitializeTextureAxes( TEXTURE_ALIGN_WORLD, INIT_TEXTURE_AXES | INIT_TEXTURE_FORCE );
				break;
			}

			case IDC_ALIGN_FACE:
			{
				pFace->InitializeTextureAxes( TEXTURE_ALIGN_FACE, INIT_TEXTURE_AXES | INIT_TEXTURE_FORCE );
				break;
			}
		}
	}

	CMapDoc::GetActiveMapDoc()->SetModifiedFlag();

	UpdateDialogData();

	return ( TRUE );
}
예제 #17
0
//-----------------------------------------------------------------------------
// 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);
}
예제 #18
0
//-----------------------------------------------------------------------------
// Purpose: Renders us in the 3D view.
// Input  : pRender - Interface to use for rendering.
//-----------------------------------------------------------------------------
void CMapSideList::Render3D(CRender3D *pRender)
{
	if (Parent->IsSelected())
	{
		//
		// Draw lines from us to the center of all faces in the list.
		//
		pRender->SetRenderMode(RENDER_MODE_WIREFRAME);

		CMeshBuilder meshBuilder;
		IMesh *pMesh = MaterialSystemInterface()->GetDynamicMesh();

		meshBuilder.Begin(pMesh, MATERIAL_LINES, m_Faces.Count());

		for (int i = 0; i < m_Faces.Count(); i++)
		{
			CMapFace *pFace = m_Faces.Element(i);

			Vector Center;
			pFace->GetCenter(Center);

			unsigned char color[3];
			color[0] = SELECT_EDGE_RED; 
			color[1] = SELECT_EDGE_GREEN;
			color[2] = SELECT_EDGE_BLUE;

			meshBuilder.Color3ubv( color );
			meshBuilder.Position3f(m_Origin.x, m_Origin.y, m_Origin.z);
			meshBuilder.AdvanceVertex();

			meshBuilder.Color3ubv( color );
			meshBuilder.Position3f(Center.x, Center.y, Center.z);
			meshBuilder.AdvanceVertex();
		}

		meshBuilder.End();
		pMesh->Draw();
	}
}
예제 #19
0
//-----------------------------------------------------------------------------
// 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);
}
예제 #20
0
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
static void FixInvalidLightmapSizeOnDisplacement( MapError *pError )
{
	CMapSolid *pSolid = ( CMapSolid* )pError->pObjects[0];

	//
	// check and fix all displacement faces of the solid with improper lightmap
	// extents
	//
	int faceCount = pSolid->GetFaceCount();
	for( int i = 0; i < faceCount; i++ )
	{
		CMapFace *pFace = pSolid->GetFace( i );
		if( !pFace->HasDisp() )
			continue;

		// find the bad surfaces
		if( pFace->ValidLightmapSize() )
			continue;

		// adjust the lightmap scale
		pFace->AdjustLightmapScale();
	}
}
예제 #21
0
//-----------------------------------------------------------------------------
// 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();
		}
	}
}
예제 #22
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *pSolid - 
//			*pList - 
// Output : static BOOL
//-----------------------------------------------------------------------------
static BOOL AddUsedTextures(CMapSolid *pSolid, CUsedTextureList *pList)
{
	if (!pSolid->IsVisible())
		return TRUE;

	int nFaces = pSolid->GetFaceCount();
	IEditorTexture *pLastTex = NULL;
	int nLastElement = 0;

	for (int i = 0; i < nFaces; i++)
	{
		CMapFace *pFace = pSolid->GetFace(i);

		UsedTexture_t Tex;
		Tex.pTex = pFace->GetTexture();
		Tex.nUsageCount = 0;

		if (Tex.pTex != NULL)
		{
			if (Tex.pTex != pLastTex)
			{
				int nElement = pList->Find(Tex.pTex);
				if (nElement == -1)
				{
					nElement = pList->AddToTail(Tex);
				}

				nLastElement = nElement;
				pLastTex = Tex.pTex;
			}

			pList->Element(nLastElement).nUsageCount++;
		}
	}

	return TRUE;
}
예제 #23
0
//-----------------------------------------------------------------------------
// Purpose: Calculates our bounds.
// Input  : bFullUpdate - 
//-----------------------------------------------------------------------------
void CMapSideList::CalcBounds(BOOL bFullUpdate)
{
	//
	// We're just a point in the 2D view because we don't render there.
	//
	m_Render2DBox.ResetBounds();
	m_Render2DBox.UpdateBounds(m_Origin);

	//
	// Our culling bounds includes the endpoints of all the lines we draw when
	// our parent entity is selected.
	//
	m_CullBox.ResetBounds();
	m_CullBox.UpdateBounds(m_Origin);

	for (int i = 0; i < m_Faces.Count(); i++)
	{
		CMapFace *pFace = m_Faces.Element(i);

		Vector Center;
		pFace->GetCenter(Center);
		m_CullBox.UpdateBounds(Center);
	}
}
예제 #24
0
void CBSPMapData::SearchAdjacentLightSourceFaces_r( vector<CMapFace>* pvecAdjacentFace,
												    CMapFace& rFace1, vector<CMapFace>* pvecSourceFace)
{
	for(int i=0; i<pvecSourceFace->size(); i++)
	{
		CMapFace& rFace2 = pvecSourceFace->at(i);

		if( !rFace2.ReadTypeFlag(CMapFace::TYPE_LIGHTSOURCE) )
			continue;

		if( rFace2.m_bFlag == true )
			continue;

		if( rFace1.SharingPointWith(rFace2) )
		{
			rFace2.m_bFlag = true;
			pvecAdjacentFace->push_back(rFace2);

			SearchAdjacentLightSourceFaces_r( pvecAdjacentFace, rFace2 , pvecSourceFace);
		}
	}
}
예제 #25
0
void CSSolid::ToMapSolid(CMapSolid *p)
{
	// so we can pass NULL (default) or another solid (to copy):
	CMapSolid *pSolid;
	if (p)
	{
		pSolid = p;
	}
	else
	{
		pSolid = m_pMapSolid;
	}

	pSolid->SetFaceCount(0);

	for (int i = 0; i < m_nFaces; i++)
	{
		CSSFace &face = m_Faces[i];
		CMapFace SolidFace;

		//
		// Copy original texture information and face ID back.
		//
		memcpy(&SolidFace.texture, &face.texture, sizeof(TEXTURE));
		SolidFace.SetTexture(SolidFace.texture.texture);
		SolidFace.SetFaceID(face.m_nFaceID);

		//
		// Create face from new points.
		//
		Vector *pts = CreatePointList(face);
		if (pts)
		{
			SolidFace.CreateFace(pts, face.nEdges);

			//
			// Vertex manipulation; the face orientation may have changed. If one of the texture axes is now
			// perpendicular to the face, recalculate the texture axes using the default alignment (world or face).
			// Ideally we would transform the texture axes so that their orientation relative to the face is preserved.
			// By reinitializing the axes we risk having the axes rotate unpredictably.
			//
			if (!SolidFace.IsTextureAxisValid())
			{
				SolidFace.InitializeTextureAxes(Options.GetTextureAlignment(), INIT_TEXTURE_AXES | INIT_TEXTURE_FORCE);
			}
				
			// Attempt to update the displacement - if there is one.
			if ( face.m_hDisp != EDITDISPHANDLE_INVALID )
			{
				EditDispHandle_t hDisp = EditDispMgr()->Create();
				CMapDisp *pSolidDisp = EditDispMgr()->GetDisp( hDisp );
				CMapDisp *pDisp = EditDispMgr()->GetDisp( face.m_hDisp );
				pSolidDisp->CopyFrom( pDisp, false );
				int iStart = pSolidDisp->GetSurfPointStartIndex();
				pSolidDisp->SetSurfPointStartIndex( (iStart+3)%4 );
				pSolidDisp->InitDispSurfaceData( &SolidFace, false );
				pSolidDisp->Create();
				SolidFace.SetDisp( hDisp );
			}

			pSolid->AddFace(&SolidFace);

			delete[] pts;
		}
	}

	pSolid->PostUpdate(Notify_Changed);
}
예제 #26
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *pRender - 
//-----------------------------------------------------------------------------
void Clipper3D::RenderTool2D(CRender2D *pRender)
{
    // sanity check!
    if( m_bEmpty )
        return;

    // check flag for rendering vertices
    bool bDrawVerts = ( bool )( Options.view2d.bDrawVertices == TRUE );

    // setup the line to use
    pRender->SetLineType( CRender2D::LINE_SOLID, CRender2D::LINE_THICK, 255, 255, 255 );

    //
    // render the clipped solids
    //
    POSITION pos = m_ClipResults.GetHeadPosition();
    while( pos )
    {
        CClipGroup *pClipGroup = m_ClipResults.GetNext( pos );
        CMapSolid *pClipBack = pClipGroup->GetClipSolid( CClipGroup::BACK );
        CMapSolid *pClipFront = pClipGroup->GetClipSolid( CClipGroup::FRONT );
        if( !pClipBack && !pClipFront )
            continue;

        //
        // draw clip solids with the extents
        //
        if( pClipBack )
        {
            int faceCount = pClipBack->GetFaceCount();
            for( int i = 0; i < faceCount; i++ )
            {
                CMapFace *pFace = pClipBack->GetFace( i );
                if( pFace->IsIgnored() )
                    continue;

                pRender->DrawLineLoop( pFace->nPoints, pFace->Points, bDrawVerts, 4 );

                if( m_bDrawMeasurements )
                {
                    DrawBrushExtents( pRender, pClipBack, DBT_TOP | DBT_LEFT | DBT_BACK );
                }
            }
        }

        if( pClipFront )
        {
            int faceCount = pClipFront->GetFaceCount();
            for( int i = 0; i < faceCount; i++ )
            {
                CMapFace *pFace = pClipFront->GetFace( i );
                if( pFace->IsIgnored() )
                    continue;

                pRender->DrawLineLoop( pFace->nPoints, pFace->Points, bDrawVerts, 4 );

                if( m_bDrawMeasurements )
                {
                    DrawBrushExtents( pRender, pClipFront, DBT_BOTTOM | DBT_RIGHT );
                }
            }
        }
	}

    //
    // draw the clip-plane endpoints
    //
    pRender->SetFillColor( 255, 255, 255 );
    pRender->DrawPoint( m_ClipPoints[0], 4 );
    pRender->DrawPoint( m_ClipPoints[1], 4 );
    
    //
    // draw the clip-plane
    //
    pRender->SetLineColor( 0, 255, 255 );
    pRender->DrawLine( m_ClipPoints[0], m_ClipPoints[1] );
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : uCmd - 
// Output : Returns TRUE on success, FALSE on failure.
//-----------------------------------------------------------------------------
BOOL CFaceEditMaterialPage::OnJustify( UINT uCmd )
{
	// Set the material tool current.
	SetMaterialPageTool( MATERIALPAGETOOL_MATERIAL );

	BOOL		bTreatManyAsOneFace;
	Extents_t	Extents;

	// mark undo position
	GetHistory()->MarkUndoPosition( NULL, "Justify texture" );

	CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent();
	int faceCount = pSheet->GetFaceListCount();	

	// If multiple faces are selected, use the m_bTreatManyAsOneFace variable to determine
	// how to perform the justification.
	if( faceCount > 1 )
	{
		bTreatManyAsOneFace = m_bTreatAsOneFace;
		if( bTreatManyAsOneFace )
		{
			GetAllFaceExtents( Extents );
		}
	}
	// If only one face is selected, treat it singly.
	else
	{
		bTreatManyAsOneFace = FALSE;
	}

	for( int i = 0; i < faceCount; i++ )
	{
		CMapFace *pFace = pSheet->GetFaceListDataFace( i );

		CMapSolid *pSolid = pSheet->GetFaceListDataSolid( i );
		GetHistory()->Keep( pSolid );

		if( !bTreatManyAsOneFace )
		{
			pFace->GetFaceExtents( Extents );
		}

		switch (uCmd)
		{
			case IDC_JUSTIFY_TOP:
			{
				pFace->JustifyTextureUsingExtents(TEXTURE_JUSTIFY_TOP, Extents);
				break;
			}

			case IDC_JUSTIFY_BOTTOM:
			{
				pFace->JustifyTextureUsingExtents(TEXTURE_JUSTIFY_BOTTOM, Extents);
				break;
			}

			case IDC_JUSTIFY_LEFT:
			{
				pFace->JustifyTextureUsingExtents(TEXTURE_JUSTIFY_LEFT, Extents);
				break;
			}

			case IDC_JUSTIFY_RIGHT:
			{
				pFace->JustifyTextureUsingExtents(TEXTURE_JUSTIFY_RIGHT, Extents);
				break;
			}

			case IDC_JUSTIFY_CENTER:
			{
				pFace->JustifyTextureUsingExtents(TEXTURE_JUSTIFY_CENTER, Extents);
				break;
			}

			case IDC_JUSTIFY_FITTOFACE:
			{
				pFace->JustifyTextureUsingExtents(TEXTURE_JUSTIFY_FIT, Extents);
				break;
			}
		}
	}

	CMapDoc::GetActiveMapDoc()->SetModifiedFlag();

	UpdateDialogData();

	return(TRUE);
}
//-----------------------------------------------------------------------------
// Purpose: Applies dialog data to the list of selected faces.
// Input  : *pOnlyFace - 
//			bAll - 
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::Apply( CMapFace *pOnlyFace, int flags )
{
	int			i;
	CString		str;
	float		fshiftX = NOT_INIT;
	float		fshiftY = NOT_INIT;
	float		fscaleX = NOT_INIT;
	float		fscaleY = NOT_INIT;
	float		frotate = NOT_INIT;
	int			material = NOT_INIT;
	int			nLightmapScale = NOT_INIT;
	IEditorTexture	*pTex = m_TexturePic.GetTexture();

	//
	// Get numeric data.
	//
	if (flags & FACE_APPLY_MAPPING)
	{
		TransferToFloat( &m_shiftX, fshiftX );
		TransferToFloat( &m_shiftY, fshiftY );
		TransferToFloat( &m_scaleX, fscaleX );
		TransferToFloat( &m_scaleY, fscaleY );
		TransferToFloat( &m_rotate, frotate );
	}

	if (flags & FACE_APPLY_LIGHTMAP_SCALE)
	{
		TransferToInteger( &m_cLightmapScale, nLightmapScale );
	}

	if ( !pOnlyFace )
	{
		GetHistory()->MarkUndoPosition( NULL, "Apply Face Attributes" );

		// make sure we apply everything in this case.
		flags |= FACE_APPLY_ALL;

		// Keep the solids that we are about to change.
		// In the pOnlyFace case we do the Keep before calling ClickFace. Why?
		CUtlVector<CMapSolid *> kept;
		CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent();
		for( i = 0; i < pSheet->GetFaceListCount(); i++ )
		{
			CMapSolid *pSolid = pSheet->GetFaceListDataSolid( i );
			if ( kept.Find( pSolid ) == -1 )
			{
				GetHistory()->Keep( pSolid );
				kept.AddToTail( pSolid );
			}
		}
	}
		
	//
	// Run thru stored faces & apply.
	//
	CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent();
	int faceCount = pSheet->GetFaceListCount();
	for( i = 0; i < faceCount || pOnlyFace; i++ )
	{
		CMapFace *pFace;
		if( pOnlyFace )
		{
			pFace = pOnlyFace;
		}
		else
		{
			pFace = pSheet->GetFaceListDataFace( i );
		}

		//
		// Get values for texture shift, scale, rotate, and material.
		//
		if ((flags & FACE_APPLY_MAPPING) && (!(flags & FACE_APPLY_ALIGN_EDGE)))
		{
			if ( fshiftX != NOT_INIT )
			{
				pFace->texture.UAxis[3] = fshiftX;
			}

			if ( fshiftY != NOT_INIT )
			{
				pFace->texture.VAxis[3] = fshiftY;
			}

			if ( fscaleX != NOT_INIT )
			{
				pFace->texture.scale[0] = fscaleX;
			}
			
			if ( fscaleY != NOT_INIT )
			{
				pFace->texture.scale[1] = fscaleY;
			}

			if ( frotate != NOT_INIT )
			{
				pFace->RotateTextureAxes( frotate - pFace->texture.rotate );
				pFace->texture.rotate = frotate;
			}
		}

		if (flags & FACE_APPLY_CONTENTS_DATA)
		{
			if ( material != NOT_INIT )
			{
				pFace->texture.material = material;
			}
		}

		if (flags & FACE_APPLY_LIGHTMAP_SCALE)
		{
			if (nLightmapScale != NOT_INIT)
			{
				pFace->texture.nLightmapScale = max( nLightmapScale, 1 );
			}
		}

		//
		// Update the texture and recalculate texture coordinates.
		//
		if ((flags & FACE_APPLY_MATERIAL) && (pTex != NULL))
		{
			char szCurrentTexName[MAX_PATH];
			char szNewTexName[MAX_PATH];

			pFace->GetTextureName( szCurrentTexName );
			pTex->GetShortName( szNewTexName );

			if( stricmp( szCurrentTexName, szNewTexName ) != 0 )
			{
				pFace->SetTexture( szNewTexName );
			}
		}

		//
		// Copy texture coordinate system.
		//
		if ((flags & FACE_APPLY_ALIGN_EDGE) && (faceCount >= 1))
		{
			CopyTCoordSystem( pSheet->GetFaceListDataFace( faceCount - 1 ), pFace );
		}

		//
		// Recalculate texture coordinates.
		//
		pFace->CalcTextureCoords();

		//
		// Update the face flags.
		//
		if (flags & FACE_APPLY_CONTENTS_DATA)
		{
			//
			// Copy the bits from this face into our variables.
			//
			m_FaceContents = pFace->texture.q2contents;
			m_FaceSurface = pFace->texture.q2surface;

			//
			// Update our variables based on the state of the checkboxes.
			//
			for( int nItem = 0; nItem < sizeof( FaceAttributes ) / sizeof( FaceAttributes[0] ); nItem++ )
			{
				CButton *pButton = ( CButton* )GetDlgItem( FaceAttributes[nItem].uControlID );
				if( pButton != NULL )
				{
					int nSet = pButton->GetCheck();

					if (nSet == 0)
					{
						*FaceAttributes[nItem].puAttribute &= ~FaceAttributes[nItem].uFlag;
					}
					else if (nSet == 1)
					{
						*FaceAttributes[nItem].puAttribute |= FaceAttributes[nItem].uFlag;
					}
				}	
			}

			//
			// Copy our variables back into this face.
			//
			pFace->texture.q2contents = m_FaceContents;
			pFace->texture.q2surface = m_FaceSurface;
		}

		if( pOnlyFace )
		{
			break;
		}
	}

	CMapDoc::GetActiveMapDoc()->SetModifiedFlag();
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *pOnlyFace - 
//-----------------------------------------------------------------------------
void CFaceEditMaterialPage::UpdateDialogData( CMapFace *pOnlyFace )
{
	BOOL	bFirst;
	int		nFaceAlignCount;
	int		nWorldAlignCount;
	float	fshiftX = NOT_INIT;
	float	fshiftY = NOT_INIT;
	float	fscaleX = NOT_INIT;
	float	fscaleY = NOT_INIT;
	float	frotate = NOT_INIT;
	//float fsmooth = NOT_INIT;
	int		material = NOT_INIT;
	int		nLightmapScale = NOT_INIT;
	CString strTexture;

	bFirst = TRUE;
	nFaceAlignCount = 0;
	nWorldAlignCount = 0;

	CFaceEditSheet *pSheet = ( CFaceEditSheet* )GetParent();
	int faceCount = pSheet->GetFaceListCount();

	for( int i = 0; i < faceCount || pOnlyFace; i++ )
	{
		CMapFace *pFace;

		if( pOnlyFace )
		{
			pFace = pOnlyFace;
		}
		else
		{
			pFace = pSheet->GetFaceListDataFace( i );
		}
		
		TEXTURE &t = pFace->texture;

		//
		// Gather statistics about the texture alignment of all the selected faces.
		// This is used later to set the state of the alignment checkboxes.
		//
		int nAlignment = pFace->GetTextureAlignment();
		if (nAlignment & TEXTURE_ALIGN_FACE)
		{
			nFaceAlignCount++;
		}

		if (nAlignment & TEXTURE_ALIGN_WORLD)
		{
			nWorldAlignCount++;
		}

		//
		// First update - copy first face's stuff into edit fields.
		//
		if (bFirst)
		{
			fshiftX = t.UAxis[3];
			fshiftY = t.VAxis[3];
			fscaleX = t.scale[0];
			fscaleY = t.scale[1];
			frotate = t.rotate;
			material = t.material;
			strTexture = t.texture;
			nLightmapScale = t.nLightmapScale;

			//
			// Get the face's orientation. This is used by Apply to make intelligent decisions.
			//
			m_eOrientation = pFace->GetOrientation();
			Assert(m_eOrientation != FACE_ORIENTATION_INVALID);

			//
			// Set the appropriate checkbox state for the face attributes.
			//
			m_FaceContents = t.q2contents;
			m_FaceSurface = t.q2surface;

			for (int nItem = 0; nItem < sizeof(FaceAttributes) / sizeof(FaceAttributes[0]); nItem++)
			{
				int nSet = ((*FaceAttributes[nItem].puAttribute & FaceAttributes[nItem].uFlag) != 0);
				CButton *pButton = (CButton *)GetDlgItem(FaceAttributes[nItem].uControlID);
				if (pButton != NULL)
				{
					pButton->SetCheck(nSet);
				}
			}

			bFirst = FALSE;
	
			if (pOnlyFace)	// use one face - now break
			{	
				break;
			}
		}
		else
		{
			// update fields with face's data
			if (t.UAxis[3] != fshiftX)
			{
				fshiftX = NOT_INIT;
			}

			if (t.VAxis[3] != fshiftY)
			{
				fshiftY = NOT_INIT;
			}

			if (t.scale[0] != fscaleX)
			{
				fscaleX = NOT_INIT;
			}

			if (t.scale[1] != fscaleY)
			{
				fscaleY = NOT_INIT;
			}

			if (t.rotate != frotate)
			{
				frotate = NOT_INIT;
			}

			if (t.material != material)
			{
				material = NOT_INIT;
			}

			if (t.nLightmapScale != nLightmapScale)
			{
				nLightmapScale = NOT_INIT;
			}

			if (!strTexture.IsEmpty() && strTexture != t.texture)
			{
				strTexture = "";
			}

			//
			// Update the checkbox state for the face attributes. If any of this face's
			// attributes are different from the current checkbox state, set the checkbox
			// to the undefined state.
			//
			m_FaceContents = t.q2contents;
			m_FaceSurface = t.q2surface;

			for (int nItem = 0; nItem < sizeof(FaceAttributes) / sizeof(FaceAttributes[0]); nItem++)
			{
				int nSet = ((*FaceAttributes[nItem].puAttribute & FaceAttributes[nItem].uFlag) != 0);
				CButton *pButton = (CButton *)GetDlgItem(FaceAttributes[nItem].uControlID);
				if (pButton != NULL)
				{
					if (pButton->GetCheck() != nSet)
					{
						pButton->SetButtonStyle(BS_AUTO3STATE);
						pButton->SetCheck(2);
					}
				}
			}
		}
	}

	//
	// Set the state of the face alignment checkbox.
	//
	CButton *pFaceAlign = (CButton *)GetDlgItem(IDC_ALIGN_FACE);

	if (nFaceAlignCount == 0)
	{
		pFaceAlign->SetCheck(0);
	}
	else if (nFaceAlignCount == faceCount)
	{
		pFaceAlign->SetCheck(1);
	}
	else
	{
		pFaceAlign->SetCheck(2);
	}

	//
	// Set the state of the world alignment checkbox.
	//
	CButton *pWorldAlign = (CButton *)GetDlgItem(IDC_ALIGN_WORLD);

	if (nWorldAlignCount == 0)
	{
		pWorldAlign->SetCheck(0);
	}
	else if (nWorldAlignCount == faceCount)
	{
		pWorldAlign->SetCheck(1);
	}
	else
	{
		pWorldAlign->SetCheck(2);
	}

	//
	// Set up fields.
	//
	FloatToSpin(fshiftX, (CSpinButtonCtrl*)GetDlgItem(IDC_SPINSHIFTX), FALSE);
	FloatToSpin(fshiftY, (CSpinButtonCtrl*)GetDlgItem(IDC_SPINSHIFTY), FALSE);
	IntegerToSpin(nLightmapScale, (CSpinButtonCtrl *)GetDlgItem(IDC_SPIN_LIGHTMAP_SCALE));

	FloatToWnd(fscaleX, &m_scaleX);
	FloatToWnd(fscaleY, &m_scaleY);

	FloatToSpin(frotate, (CSpinButtonCtrl*)GetDlgItem(IDC_SPINROTATE), TRUE);

	if (!strTexture.IsEmpty())
	{
		SelectTexture( strTexture );
	}
	else
	{
		// make empty
		m_TextureList.SetCurSel( -1 );
	}

	//
	// if no faces selected -- get selection from texture bar
	//
	if( faceCount == 0 )
	{
		CString strTexName = GetDefaultTextureName();
		SelectTexture( strTexName );
	}

	//
	// Call ctexturebar implementation because OUR implementation sets the 
	// q2 checkboxes, which flashes the screen a bit (cuz we change them
	// again three lines down.)
	//
	UpdateTexture();

	// Update the smoothing group data.
	if ( GetMaterialPageTool() == MATERIALPAGETOOL_SMOOTHING_GROUP )
	{
		m_FaceSmoothDlg.UpdateControls();
	}
}
예제 #30
0
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;
		}
	}
}