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;
}
Beispiel #10
0
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();
}