void FEdModeGeometry::PostUndo() { // Rebuild the geometry data from the current brush state GetFromSource(); // Restore selection information. for( int32 o = 0 ; o < GeomObjects.Num() ; ++o ) { int32 Idx = 0; FGeomObject* go = GeomObjects[o]; ABrush* Actor = go->GetActualBrush(); // First, clear the current selection go->SelectNone(); // Next, restore the cached selection int32 res = go->SetPivotFromSelectionArray( Actor->SavedSelections ); //use the centre of the actor if we didnt find a suitable selection if( res == INDEX_NONE ) { FEditorModeTools& Tools = GEditorModeTools(); Tools.SetPivotLocation( Actor->GetActorLocation() , false ); } go->ForceLastSelectionIndex( res ); } }
/** * Deselects all edges, polygons, and vertices for all selected objects. */ void FEdModeGeometry::GeometrySelectNone(bool bStoreSelection, bool bResetPivot) { for( int32 ObjectIdx = 0 ; ObjectIdx < GeomObjects.Num() ; ++ObjectIdx ) { FGeomObject* GeomObject = GeomObjects[ObjectIdx]; GeomObject->Select( 0 ); for( int VertexIdx = 0 ; VertexIdx < GeomObject->EdgePool.Num() ; ++VertexIdx ) { GeomObject->EdgePool[VertexIdx].Select( 0 ); } for( int VertexIdx = 0 ; VertexIdx < GeomObject->PolyPool.Num() ; ++VertexIdx ) { GeomObject->PolyPool[VertexIdx].Select( 0 ); } for( int VertexIdx = 0 ; VertexIdx < GeomObject->VertexPool.Num() ; ++VertexIdx ) { GeomObject->VertexPool[VertexIdx].Select( 0 ); } GeomObject->SelectionOrder.Empty(); } if (bStoreSelection) { FModeTool_GeometryModify* GeometryModifier = (FModeTool_GeometryModify*)FindTool(MT_GeometryModify); GeometryModifier->StoreAllCurrentGeomSelections(); } if (bResetPivot && (GeomObjects.Num() > 0)) { FEditorModeTools& ModeTools = GEditorModeTools(); ModeTools.SetPivotLocation(GeomObjects[0]->GetActualBrush()->GetActorLocation(), false); } }
bool FEdModeGeometry::GetCustomDrawingCoordinateSystem( FMatrix& InMatrix, void* InData ) { if( GetSelectionState() == GSS_None ) { return 0; } if( InData ) { InMatrix = FRotationMatrix( ((FGeomBase*)InData)->GetNormal().Rotation() ); } else { // If we don't have a specific geometry object to get the normal from // use the one that was last selected. for( int32 o = 0 ; o < GeomObjects.Num() ; ++o ) { FGeomObject* go = GeomObjects[o]; go->CompileSelectionOrder(); if( go->SelectionOrder.Num() ) { InMatrix = FRotationMatrix( go->SelectionOrder[ go->SelectionOrder.Num()-1 ]->GetWidgetRotation() ); return 1; } } } return 0; }
/** @return true if something was selected/deselected, false otherwise. */ bool FModeTool_GeometryModify::FrustumSelect( const FConvexVolume& InFrustum, bool InSelect /* = true */ ) { bool bResult = false; if( GEditorModeTools().IsModeActive( FBuiltinEditorModes::EM_Geometry ) ) { FEdModeGeometry* mode = (FEdModeGeometry*)GEditorModeTools().GetActiveMode( FBuiltinEditorModes::EM_Geometry ); for( FEdModeGeometry::TGeomObjectIterator Itor( mode->GeomObjectItor() ) ; Itor ; ++Itor ) { FGeomObject* go = *Itor; FTransform ActorToWorld = go->GetActualBrush()->ActorToWorld(); // Check each vertex to see if its inside the frustum for( int32 v = 0 ; v < go->VertexPool.Num() ; ++v ) { FGeomVertex& gv = go->VertexPool[v]; if( InFrustum.IntersectBox( ActorToWorld.TransformPosition( gv.GetMid() ), FVector::ZeroVector ) ) { gv.Select( InSelect ); bResult = true; } } } } return bResult; }
/** @return true if something was selected/deselected, false otherwise. */ bool FModeTool_GeometryModify::BoxSelect( FBox& InBox, bool InSelect ) { bool bResult = false; if( GEditorModeTools().IsModeActive( FBuiltinEditorModes::EM_Geometry ) ) { FEdModeGeometry* mode = (FEdModeGeometry*)GEditorModeTools().GetActiveMode( FBuiltinEditorModes::EM_Geometry ); for( FEdModeGeometry::TGeomObjectIterator Itor( mode->GeomObjectItor() ) ; Itor ; ++Itor ) { FGeomObject* go = *Itor; FTransform ActorToWorld = go->GetActualBrush()->ActorToWorld(); // Only verts for box selection for( int32 v = 0 ; v < go->VertexPool.Num() ; ++v ) { FGeomVertex& gv = go->VertexPool[v]; if( FMath::PointBoxIntersection( ActorToWorld.TransformPosition( gv.GetMid() ), InBox ) ) { gv.Select( InSelect ); bResult = true; } } } } return bResult; }
FPoly* FGeomPoly::GetActualPoly() { FGeomObject* Parent = GetParentObject(); check( Parent ); ABrush* Brush = Parent->GetActualBrush(); check( Brush ); return &( Brush->Brush->Polys->Element[ActualPolyIndex] ); }
void FEdModeGeometry::SendToSource() { for( int32 o = 0 ; o < GeomObjects.Num() ; ++o ) { FGeomObject* go = GeomObjects[o]; go->SendToSource(); } }
bool FEdModeGeometry::FinalizeSourceData() { bool Result = 0; for( int32 o = 0 ; o < GeomObjects.Num() ; ++o ) { FGeomObject* go = GeomObjects[o]; if( go->FinalizeSourceData() ) { Result = 1; } } return Result; }
bool FModeTool_GeometryModify::EndModify() { // Let the modifier finish up. if( CurrentModifier != NULL ) { FEdModeGeometry* mode = ((FEdModeGeometry*)GEditorModeTools().GetActiveMode(FBuiltinEditorModes::EM_Geometry)); // Update the source data to match the current geometry data. mode->SendToSource(); // Make sure the source data has remained viable. if( mode->FinalizeSourceData() ) { // If the source data was modified, reconstruct the geometry data to reflect that. mode->GetFromSource(); } CurrentModifier->EndModify(); // Update internals. for( FEdModeGeometry::TGeomObjectIterator Itor( mode->GeomObjectItor() ) ; Itor ; ++Itor ) { FGeomObject* go = *Itor; go->ComputeData(); FBSPOps::bspUnlinkPolys( go->GetActualBrush()->Brush ); // If geometry was actually changed, call PostEditBrush if(bGeomModified) { ABrush* Brush = go->GetActualBrush(); if(Brush) { if(!Brush->IsStaticBrush()) { FBSPOps::csgPrepMovingBrush(Brush); } } bGeomModified = false; } } } return 1; }
bool FEdModeGeometry::GetCustomDrawingCoordinateSystem( FMatrix& InMatrix, void* InData ) { if( GetSelectionState() == GSS_None ) { return 0; } if( InData ) { FGeomBase* GeomBase = static_cast<FGeomBase*>(InData); FGeomObject* GeomObject = GeomBase->GetParentObject(); check(GeomObject != nullptr); ABrush* Brush = GeomObject->GetActualBrush(); InMatrix = FRotationMatrix(GeomBase->GetNormal().Rotation()) * FRotationMatrix(Brush->GetActorRotation()); } else { // If we don't have a specific geometry object to get the normal from // use the one that was last selected. for( int32 o = 0 ; o < GeomObjects.Num() ; ++o ) { FGeomObject* go = GeomObjects[o]; go->CompileSelectionOrder(); if( go->SelectionOrder.Num() ) { FGeomBase* GeomBase = go->SelectionOrder[go->SelectionOrder.Num() - 1]; check(GeomBase != nullptr); FGeomObject* GeomObject = GeomBase->GetParentObject(); check(GeomObject != nullptr); ABrush* Brush = GeomObject->GetActualBrush(); InMatrix = FRotationMatrix( go->SelectionOrder[ go->SelectionOrder.Num()-1 ]->GetWidgetRotation() ) * FRotationMatrix(Brush->GetActorRotation()); return 1; } } } return 0; }
void FEdModeGeometry::GetFromSource() { GWarn->BeginSlowTask( NSLOCTEXT("EditorModes", "GeometryMode-BeginRebuildingBSPTask", "Rebuilding BSP"), false); TArray<HGeomMidPoints> GeomData; // Go through each brush and update its components before updating below for( int32 i=0; i<GeomObjects.Num(); i++ ) { FGeomObject* GeomObject = GeomObjects[i]; if(GeomObject && GeomObject->ActualBrush) { #ifdef BSP_RESELECT // Cache any information that'll help us reselect the object after it's reconstructed CacheSelectedData( GeomData, *GeomObject ); #endif // BSP_RESELECT GeomObject->ActualBrush->UnregisterAllComponents(); if (GeomObject->ActualBrush->GetWorld()) { GeomObject->ActualBrush->RegisterAllComponents(); } delete GeomObject; } } GeomObjects.Empty(); TArray<FGeomBase*> SelectedGeom; // Notify the selected actors that they have been moved. bool bFound = true; for ( FSelectionIterator It( GEditor->GetSelectedActorIterator() ) ; It ; ++It ) { AActor* Actor = static_cast<AActor*>( *It ); checkSlow( Actor->IsA(AActor::StaticClass()) ); ABrush* BrushActor = Cast< ABrush >( Actor ); if ( BrushActor ) { if( BrushActor->Brush != NULL ) { FGeomObject* GeomObject = new FGeomObject(); GeomObject->SetParentObjectIndex( GeomObjects.Add( GeomObject ) ); GeomObject->ActualBrush = BrushActor; GeomObject->GetFromSource(); #ifdef BSP_RESELECT // Attempt to find all the previously selected geometry on this object if everything has gone OK so far if ( bFound && !FindFromCache( GeomData, *GeomObject, SelectedGeom ) ) { #ifdef BSP_RESELECT__ALL_OR_NOTHING // If it didn't succeed, don't attempt to reselect anything as the user will only end up moving part of their previous selection UE_LOG(LogGeometryMode, Warning, TEXT( "Unable to find all previously selected geometry data, resetting selection" ) ); SelectedGeom.Empty(); GeomData.Empty(); bFound = false; #endif // BSP_RESELECT__ALL_OR_NOTHING } #endif // BSP_RESELECT } } } #ifdef BSP_RESELECT // Reselect anything that came close to the cached midpoints SelectCachedData( SelectedGeom ); #endif // BSP_RESELECT GWarn->EndSlowTask(); }