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 );
	}
}
/** @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] );
}
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;
}