//----------------------------------------------------------------------------- // 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); }
//----------------------------------------------------------------------------- // 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); }
//----------------------------------------------------------------------------- // 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()); }
//----------------------------------------------------------------------------- // 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; }
//----------------------------------------------------------------------------- // 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]); } } } }
//----------------------------------------------------------------------------- // 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(); }
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); } } }
//----------------------------------------------------------------------------- // 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; } }
//----------------------------------------------------------------------------- // 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; }
//----------------------------------------------------------------------------- // 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: 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); } }
//----------------------------------------------------------------------------- // 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: 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 ); }
//----------------------------------------------------------------------------- // 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: 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(); } }
//----------------------------------------------------------------------------- // 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); }
//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- 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(); } }
//----------------------------------------------------------------------------- // 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(); } } }
//----------------------------------------------------------------------------- // 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; }
//----------------------------------------------------------------------------- // 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); } }
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); } } }
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); }
//----------------------------------------------------------------------------- // 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(); } }
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; } } }