2018-12-14 13:41:00 -05:00
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
2014-03-14 14:13:41 -04:00
Copying //UE4/Dev-Build to //UE4/Dev-Main (Source: //UE4/Dev-Build @ 3209340)
#lockdown Nick.Penwarden
#rb none
==========================
MAJOR FEATURES + CHANGES
==========================
Change 3209340 on 2016/11/23 by Ben.Marsh
Convert UE4 codebase to an "include what you use" model - where every header just includes the dependencies it needs, rather than every source file including large monolithic headers like Engine.h and UnrealEd.h.
Measured full rebuild times around 2x faster using XGE on Windows, and improvements of 25% or more for incremental builds and full rebuilds on most other platforms.
* Every header now includes everything it needs to compile.
* There's a CoreMinimal.h header that gets you a set of ubiquitous types from Core (eg. FString, FName, TArray, FVector, etc...). Most headers now include this first.
* There's a CoreTypes.h header that sets up primitive UE4 types and build macros (int32, PLATFORM_WIN64, etc...). All headers in Core include this first, as does CoreMinimal.h.
* Every .cpp file includes its matching .h file first.
* This helps validate that each header is including everything it needs to compile.
* No engine code includes a monolithic header such as Engine.h or UnrealEd.h any more.
* You will get a warning if you try to include one of these from the engine. They still exist for compatibility with game projects and do not produce warnings when included there.
* There have only been minor changes to our internal games down to accommodate these changes. The intent is for this to be as seamless as possible.
* No engine code explicitly includes a precompiled header any more.
* We still use PCHs, but they're force-included on the compiler command line by UnrealBuildTool instead. This lets us tune what they contain without breaking any existing include dependencies.
* PCHs are generated by a tool to get a statistical amount of coverage for the source files using it, and I've seeded the new shared PCHs to contain any header included by > 15% of source files.
Tool used to generate this transform is at Engine\Source\Programs\IncludeTool.
[CL 3209342 by Ben Marsh in Main branch]
2016-11-23 15:48:37 -05:00
# include "CoreMinimal.h"
# include "EngineDefines.h"
# include "Misc/MessageDialog.h"
# include "InputCoreTypes.h"
# include "GameFramework/Actor.h"
# include "Engine/World.h"
# include "SceneView.h"
# include "Model.h"
# include "Settings/LevelEditorViewportSettings.h"
# include "Engine/Brush.h"
# include "Settings/LevelEditorMiscSettings.h"
# include "Engine/Polys.h"
# include "Engine/Selection.h"
# include "EditorModeManager.h"
# include "EditorModes.h"
# include "Dialogs/Dialogs.h"
# include "BSPOps.h"
# include "GeometryEdMode.h"
# include "EditorGeometry.h"
2014-05-29 16:47:33 -04:00
# include "Engine/BrushShape.h"
2014-05-21 10:00:58 -04:00
# include "EditorSupportDelegates.h"
2014-03-14 14:13:41 -04:00
# include "ScopedTransaction.h"
Copying //UE4/Dev-Build to //UE4/Dev-Main (Source: //UE4/Dev-Build @ 3209340)
#lockdown Nick.Penwarden
#rb none
==========================
MAJOR FEATURES + CHANGES
==========================
Change 3209340 on 2016/11/23 by Ben.Marsh
Convert UE4 codebase to an "include what you use" model - where every header just includes the dependencies it needs, rather than every source file including large monolithic headers like Engine.h and UnrealEd.h.
Measured full rebuild times around 2x faster using XGE on Windows, and improvements of 25% or more for incremental builds and full rebuilds on most other platforms.
* Every header now includes everything it needs to compile.
* There's a CoreMinimal.h header that gets you a set of ubiquitous types from Core (eg. FString, FName, TArray, FVector, etc...). Most headers now include this first.
* There's a CoreTypes.h header that sets up primitive UE4 types and build macros (int32, PLATFORM_WIN64, etc...). All headers in Core include this first, as does CoreMinimal.h.
* Every .cpp file includes its matching .h file first.
* This helps validate that each header is including everything it needs to compile.
* No engine code includes a monolithic header such as Engine.h or UnrealEd.h any more.
* You will get a warning if you try to include one of these from the engine. They still exist for compatibility with game projects and do not produce warnings when included there.
* There have only been minor changes to our internal games down to accommodate these changes. The intent is for this to be as seamless as possible.
* No engine code explicitly includes a precompiled header any more.
* We still use PCHs, but they're force-included on the compiler command line by UnrealBuildTool instead. This lets us tune what they contain without breaking any existing include dependencies.
* PCHs are generated by a tool to get a statistical amount of coverage for the source files using it, and I've seeded the new shared PCHs to contain any header included by > 15% of source files.
Tool used to generate this transform is at Engine\Source\Programs\IncludeTool.
[CL 3209342 by Ben Marsh in Main branch]
2016-11-23 15:48:37 -05:00
# include "LevelEditorViewport.h"
2014-03-14 14:13:41 -04:00
# include "Layers/ILayers.h"
# include "ActorEditorUtils.h"
Copying //UE4/Dev-Build to //UE4/Dev-Main (Source: //UE4/Dev-Build @ 3209340)
#lockdown Nick.Penwarden
#rb none
==========================
MAJOR FEATURES + CHANGES
==========================
Change 3209340 on 2016/11/23 by Ben.Marsh
Convert UE4 codebase to an "include what you use" model - where every header just includes the dependencies it needs, rather than every source file including large monolithic headers like Engine.h and UnrealEd.h.
Measured full rebuild times around 2x faster using XGE on Windows, and improvements of 25% or more for incremental builds and full rebuilds on most other platforms.
* Every header now includes everything it needs to compile.
* There's a CoreMinimal.h header that gets you a set of ubiquitous types from Core (eg. FString, FName, TArray, FVector, etc...). Most headers now include this first.
* There's a CoreTypes.h header that sets up primitive UE4 types and build macros (int32, PLATFORM_WIN64, etc...). All headers in Core include this first, as does CoreMinimal.h.
* Every .cpp file includes its matching .h file first.
* This helps validate that each header is including everything it needs to compile.
* No engine code includes a monolithic header such as Engine.h or UnrealEd.h any more.
* You will get a warning if you try to include one of these from the engine. They still exist for compatibility with game projects and do not produce warnings when included there.
* There have only been minor changes to our internal games down to accommodate these changes. The intent is for this to be as seamless as possible.
* No engine code explicitly includes a precompiled header any more.
* We still use PCHs, but they're force-included on the compiler command line by UnrealBuildTool instead. This lets us tune what they contain without breaking any existing include dependencies.
* PCHs are generated by a tool to get a statistical amount of coverage for the source files using it, and I've seeded the new shared PCHs to contain any header included by > 15% of source files.
Tool used to generate this transform is at Engine\Source\Programs\IncludeTool.
[CL 3209342 by Ben Marsh in Main branch]
2016-11-23 15:48:37 -05:00
# include "Framework/Notifications/NotificationManager.h"
# include "Widgets/Notifications/SNotificationList.h"
2014-11-12 04:58:53 -05:00
# include "Components/BrushComponent.h"
Copying //UE4/Dev-Build to //UE4/Dev-Main (Source: //UE4/Dev-Build @ 3209340)
#lockdown Nick.Penwarden
#rb none
==========================
MAJOR FEATURES + CHANGES
==========================
Change 3209340 on 2016/11/23 by Ben.Marsh
Convert UE4 codebase to an "include what you use" model - where every header just includes the dependencies it needs, rather than every source file including large monolithic headers like Engine.h and UnrealEd.h.
Measured full rebuild times around 2x faster using XGE on Windows, and improvements of 25% or more for incremental builds and full rebuilds on most other platforms.
* Every header now includes everything it needs to compile.
* There's a CoreMinimal.h header that gets you a set of ubiquitous types from Core (eg. FString, FName, TArray, FVector, etc...). Most headers now include this first.
* There's a CoreTypes.h header that sets up primitive UE4 types and build macros (int32, PLATFORM_WIN64, etc...). All headers in Core include this first, as does CoreMinimal.h.
* Every .cpp file includes its matching .h file first.
* This helps validate that each header is including everything it needs to compile.
* No engine code includes a monolithic header such as Engine.h or UnrealEd.h any more.
* You will get a warning if you try to include one of these from the engine. They still exist for compatibility with game projects and do not produce warnings when included there.
* There have only been minor changes to our internal games down to accommodate these changes. The intent is for this to be as seamless as possible.
* No engine code explicitly includes a precompiled header any more.
* We still use PCHs, but they're force-included on the compiler command line by UnrealBuildTool instead. This lets us tune what they contain without breaking any existing include dependencies.
* PCHs are generated by a tool to get a statistical amount of coverage for the source files using it, and I've seeded the new shared PCHs to contain any header included by > 15% of source files.
Tool used to generate this transform is at Engine\Source\Programs\IncludeTool.
[CL 3209342 by Ben Marsh in Main branch]
2016-11-23 15:48:37 -05:00
# include "GeomModifier.h"
# include "GeomModifier_Edit.h"
# include "GeomModifier_Clip.h"
# include "GeomModifier_Create.h"
# include "GeomModifier_Delete.h"
# include "GeomModifier_Extrude.h"
# include "GeomModifier_Flip.h"
# include "GeomModifier_Lathe.h"
# include "GeomModifier_Pen.h"
# include "GeomModifier_Split.h"
# include "GeomModifier_Triangulate.h"
# include "GeomModifier_Optimize.h"
# include "GeomModifier_Turn.h"
# include "GeomModifier_Weld.h"
2014-03-14 14:13:41 -04:00
DEFINE_LOG_CATEGORY_STATIC ( LogGeomModifier , Log , All ) ;
# define LOCTEXT_NAMESPACE "UnrealEd.GeomModifier"
2014-06-18 10:16:16 -04:00
static FVector ComputeWorldSpaceMousePos ( FEditorViewportClient * ViewportClient )
2014-03-14 14:13:41 -04:00
{
FSceneViewFamilyContext ViewFamily ( FSceneViewFamily : : ConstructionValues (
ViewportClient - > Viewport ,
ViewportClient - > GetScene ( ) ,
ViewportClient - > EngineShowFlags )
. SetRealtimeUpdate ( ViewportClient - > IsRealtime ( ) ) ) ;
FSceneView * View = ViewportClient - > CalcSceneView ( & ViewFamily ) ;
// Note only works for ortho viewports
return View - > PixelToWorld ( ViewportClient - > Viewport - > GetMouseX ( ) , ViewportClient - > Viewport - > GetMouseY ( ) , 0.5f ) ;
}
2014-10-14 10:29:11 -04:00
UGeomModifier : : UGeomModifier ( const FObjectInitializer & ObjectInitializer )
: Super ( ObjectInitializer )
2014-03-14 14:13:41 -04:00
{
bPushButton = false ;
bInitialized = false ;
2015-08-21 09:54:19 -04:00
bPendingPivotOffsetUpdate = false ;
2014-03-14 14:13:41 -04:00
CachedPolys = NULL ;
}
const FText & UGeomModifier : : GetModifierDescription ( ) const
{
return Description ;
}
2015-02-18 10:58:17 -05:00
const FText & UGeomModifier : : GetModifierTooltip ( ) const
{
return Tooltip ;
}
2014-03-14 14:13:41 -04:00
void UGeomModifier : : Initialize ( )
{
}
2014-06-18 10:16:16 -04:00
bool UGeomModifier : : InputKey ( FEditorViewportClient * ViewportClient , FViewport * Viewport , FKey Key , EInputEvent Event )
2014-03-14 14:13:41 -04:00
{
return false ;
}
2014-06-18 10:16:16 -04:00
bool UGeomModifier : : InputDelta ( FEditorViewportClient * InViewportClient , FViewport * InViewport , FVector & InDrag , FRotator & InRot , FVector & InScale )
2014-03-14 14:13:41 -04:00
{
2014-06-18 10:16:16 -04:00
if ( GLevelEditorModeTools ( ) . IsModeActive ( FBuiltinEditorModes : : EM_Geometry ) )
2014-03-14 14:13:41 -04:00
{
if ( ! bInitialized )
{
Initialize ( ) ;
bInitialized = true ;
}
}
return false ;
}
bool UGeomModifier : : Apply ( )
{
bool bResult = false ;
2014-06-18 10:16:16 -04:00
if ( GLevelEditorModeTools ( ) . IsModeActive ( FBuiltinEditorModes : : EM_Geometry ) )
2014-03-14 14:13:41 -04:00
{
StartTrans ( ) ;
bResult = OnApply ( ) ;
EndTrans ( ) ;
EndModify ( ) ;
}
return bResult ;
}
bool UGeomModifier : : OnApply ( )
{
return false ;
}
bool UGeomModifier : : Supports ( )
{
return true ;
}
void UGeomModifier : : GeomError ( const FString & InErrorMsg )
{
FMessageDialog : : Open ( EAppMsgType : : Ok , FText : : Format ( NSLOCTEXT ( " UnrealEd " , " Error_Modifier " , " Modifier ({0}) : {1} " ) , GetModifierDescription ( ) , FText : : FromString ( InErrorMsg ) ) ) ;
}
bool UGeomModifier : : StartModify ( )
{
bInitialized = false ;
2015-08-21 09:54:19 -04:00
bPendingPivotOffsetUpdate = false ;
2014-03-14 14:13:41 -04:00
return false ;
}
bool UGeomModifier : : EndModify ( )
{
2015-08-21 09:54:19 -04:00
if ( bPendingPivotOffsetUpdate )
{
UpdatePivotOffset ( ) ;
}
2014-03-14 14:13:41 -04:00
StoreAllCurrentGeomSelections ( ) ;
FEditorSupportDelegates : : RedrawAllViewports . Broadcast ( ) ;
return true ;
}
void UGeomModifier : : Render ( const FSceneView * View , FViewport * Viewport , FPrimitiveDrawInterface * PDI )
{
}
2014-06-18 10:16:16 -04:00
void UGeomModifier : : DrawHUD ( FEditorViewportClient * ViewportClient , FViewport * Viewport , const FSceneView * View , FCanvas * Canvas )
2014-03-14 14:13:41 -04:00
{
}
void UGeomModifier : : CacheBrushState ( )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * GeomMode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-06-12 04:17:47 -04:00
ABrush * BuilderBrush = GeomMode - > GetWorld ( ) - > GetDefaultBrush ( ) ;
2014-03-14 14:13:41 -04:00
if ( ! CachedPolys )
{
//Create the list of polys
2015-02-03 05:40:57 -05:00
CachedPolys = NewObject < UPolys > ( this ) ;
2014-03-14 14:13:41 -04:00
}
CachedPolys - > Element . Empty ( ) ;
//Create duplicates of all of the polys in the brush
for ( int32 polyIndex = 0 ; polyIndex < BuilderBrush - > Brush - > Polys - > Element . Num ( ) ; + + polyIndex )
{
FPoly currentPoly = BuilderBrush - > Brush - > Polys - > Element [ polyIndex ] ;
FPoly newPoly ;
newPoly . Init ( ) ;
newPoly . Base = currentPoly . Base ;
//Add all of the verts to the new poly
for ( int32 vertIndex = 0 ; vertIndex < currentPoly . Vertices . Num ( ) ; + + vertIndex )
{
FVector newVertex = currentPoly . Vertices [ vertIndex ] ;
newPoly . Vertices . Add ( newVertex ) ;
}
CachedPolys - > Element . Add ( newPoly ) ;
}
}
void UGeomModifier : : RestoreBrushState ( )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * GeomMode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-06-12 04:17:47 -04:00
ABrush * BuilderBrush = GeomMode - > GetWorld ( ) - > GetDefaultBrush ( ) ;
2014-03-14 14:13:41 -04:00
//Remove all of the current polys
BuilderBrush - > Brush - > Polys - > Element . Empty ( ) ;
//Add all of the cached polys
for ( int32 polyIndex = 0 ; polyIndex < CachedPolys - > Element . Num ( ) ; polyIndex + + )
{
BuilderBrush - > Brush - > Polys - > Element . Push ( CachedPolys - > Element [ polyIndex ] ) ;
}
BuilderBrush - > Brush - > BuildBound ( ) ;
BuilderBrush - > ReregisterAllComponents ( ) ;
GeomMode - > FinalizeSourceData ( ) ;
GeomMode - > GetFromSource ( ) ;
GEditor - > SelectNone ( true , true ) ;
GEditor - > RedrawLevelEditingViewports ( true ) ;
//Tell the user what just happened
FMessageDialog : : Debugf ( LOCTEXT ( " InvalidBrushState " , " Invalid brush state could fail to triangulate. Reverting to previous state. " ) ) ;
}
bool UGeomModifier : : DoEdgesOverlap ( )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
//Loop through all of the geometry objects
for ( FEdModeGeometry : : TGeomObjectIterator itor ( mode - > GeomObjectItor ( ) ) ; itor ; + + itor )
{
2015-04-02 16:34:30 -04:00
FGeomObjectPtr geomObject = * itor ;
2014-03-14 14:13:41 -04:00
//Loop through all of the edges
for ( int32 edgeIndex1 = 0 ; edgeIndex1 < geomObject - > EdgePool . Num ( ) ; + + edgeIndex1 )
{
FGeomEdge * edge1 = & geomObject - > EdgePool [ edgeIndex1 ] ;
for ( int32 edgeIndex2 = 0 ; edgeIndex2 < geomObject - > EdgePool . Num ( ) ; + + edgeIndex2 )
{
FGeomEdge * edge2 = & geomObject - > EdgePool [ edgeIndex2 ] ;
//Don't compare an edge with itself
if ( ! ( edge1 - > IsSameEdge ( * edge2 ) ) )
{
FVector closestPoint1 , closestPoint2 ;
FVector edge1Vert1 = geomObject - > VertexPool [ edge1 - > VertexIndices [ 0 ] ] ;
FVector edge2Vert1 = geomObject - > VertexPool [ edge2 - > VertexIndices [ 0 ] ] ;
FVector edge1Vert2 = geomObject - > VertexPool [ edge1 - > VertexIndices [ 1 ] ] ;
FVector edge2Vert2 = geomObject - > VertexPool [ edge2 - > VertexIndices [ 1 ] ] ;
//Find the distance between the two segments
FMath : : SegmentDistToSegment ( edge1Vert1 , edge1Vert2 , edge2Vert1 , edge2Vert2 , closestPoint1 , closestPoint2 ) ;
if ( ( closestPoint1 . Equals ( closestPoint2 ) ) )
{
//Identical closest points indicates that lines cross
bool bSharedVertex = ( ( edge1Vert1 . Equals ( edge2Vert1 ) ) | | ( edge1Vert1 . Equals ( edge2Vert2 ) )
| | ( edge1Vert2 . Equals ( edge2Vert1 ) ) | | ( edge1Vert2 . Equals ( edge2Vert2 ) ) ) ;
// Edges along the same line are exempt
if ( ! bSharedVertex )
{
bool bIntersectionIsVert = ( ( edge1Vert1 . Equals ( closestPoint2 , THRESH_POINTS_ARE_SAME ) ) | | ( edge1Vert2 . Equals ( closestPoint2 , THRESH_POINTS_ARE_SAME ) )
| | ( edge2Vert1 . Equals ( closestPoint2 , THRESH_POINTS_ARE_SAME ) ) | | ( edge2Vert2 . Equals ( closestPoint2 , THRESH_POINTS_ARE_SAME ) ) ) ;
// Edges intersecting at a vertex are exempt
if ( ! bIntersectionIsVert )
{
// Edges cross. The shape drawn with this brush will likely be undesireable
return true ;
}
}
}
}
}
}
}
return false ;
}
2015-07-27 12:49:14 -04:00
void UGeomModifier : : UpdatePivotOffset ( )
{
if ( ! GetDefault < ULevelEditorMiscSettings > ( ) - > bAutoMoveBSPPivotOffset )
{
return ;
}
FEdModeGeometry * Mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
for ( FEdModeGeometry : : TGeomObjectIterator It ( Mode - > GeomObjectItor ( ) ) ; It ; + + It )
{
FGeomObjectPtr GeomObject = * It ;
ABrush * Brush = GeomObject - > GetActualBrush ( ) ;
TSet < FVector > UniqueVertices ;
FVector VertexCenter = FVector : : ZeroVector ;
if ( Brush - > Brush & & Brush - > Brush - > Polys )
{
for ( const auto & Element : Brush - > Brush - > Polys - > Element )
{
for ( const auto & Vertex : Element . Vertices )
{
UniqueVertices . Add ( Vertex ) ;
}
}
for ( const auto & Vertex : UniqueVertices )
{
VertexCenter + = Vertex ;
}
if ( UniqueVertices . Num ( ) > 0 )
{
VertexCenter / = UniqueVertices . Num ( ) ;
}
}
2015-08-21 09:54:19 -04:00
Brush - > SetPivotOffset ( VertexCenter ) ;
2015-07-27 12:49:14 -04:00
}
}
2014-03-14 14:13:41 -04:00
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Transaction tracking.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace {
/**
* @ return The shared transaction object used by
*/
static FScopedTransaction * & StaticTransaction ( )
{
static FScopedTransaction * STransaction = NULL ;
return STransaction ;
}
/**
* Ends the outstanding transaction , if one exists .
*/
static void EndTransaction ( )
{
delete StaticTransaction ( ) ;
StaticTransaction ( ) = NULL ;
}
/**
* Begins a new transaction , if no outstanding transaction exists .
*/
static void BeginTransaction ( const FText & Description )
{
if ( ! StaticTransaction ( ) )
{
StaticTransaction ( ) = new FScopedTransaction ( Description ) ;
}
}
} // namespace
void UGeomModifier : : StartTrans ( )
{
2014-06-18 10:16:16 -04:00
if ( ! GLevelEditorModeTools ( ) . IsModeActive ( FBuiltinEditorModes : : EM_Geometry ) )
2014-03-14 14:13:41 -04:00
{
return ;
}
StoreAllCurrentGeomSelections ( ) ;
// Start the transaction.
BeginTransaction ( FText : : Format ( NSLOCTEXT ( " UnrealEd " , " Modifier_F " , " Modifier [{0}] " ) , GetModifierDescription ( ) ) ) ;
// Mark all selected brushes as modified.
2014-06-18 10:16:16 -04:00
FEdModeGeometry * CurMode = static_cast < FEdModeGeometry * > ( GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ) ;
2014-03-14 14:13:41 -04:00
for ( FEdModeGeometry : : TGeomObjectIterator Itor ( CurMode - > GeomObjectItor ( ) ) ; Itor ; + + Itor )
{
2015-04-02 16:34:30 -04:00
FGeomObjectPtr go = * Itor ;
2014-03-14 14:13:41 -04:00
ABrush * Actor = go - > GetActualBrush ( ) ;
Actor - > Modify ( ) ;
}
}
void UGeomModifier : : EndTrans ( )
{
EndTransaction ( ) ;
}
2015-04-02 16:34:30 -04:00
void UGeomModifier : : StoreCurrentGeomSelections ( TArray < struct FGeomSelection > & SelectionArray , FGeomObjectPtr go )
2014-03-14 14:13:41 -04:00
{
SelectionArray . Empty ( ) ;
FGeomSelection * gs = NULL ;
for ( int32 v = 0 ; v < go - > VertexPool . Num ( ) ; + + v )
{
FGeomVertex * gv = & go - > VertexPool [ v ] ;
if ( gv - > IsSelected ( ) )
{
gs = new ( SelectionArray ) FGeomSelection ;
gs - > Type = GS_Vertex ;
gs - > Index = v ;
gs - > SelectionIndex = gv - > GetSelectionIndex ( ) ;
}
}
for ( int32 e = 0 ; e < go - > EdgePool . Num ( ) ; + + e )
{
FGeomEdge * ge = & go - > EdgePool [ e ] ;
if ( ge - > IsSelected ( ) )
{
gs = new ( SelectionArray ) FGeomSelection ;
gs - > Type = GS_Edge ;
gs - > Index = e ;
gs - > SelectionIndex = ge - > GetSelectionIndex ( ) ;
}
}
for ( int32 p = 0 ; p < go - > PolyPool . Num ( ) ; + + p )
{
FGeomPoly * gp = & go - > PolyPool [ p ] ;
if ( gp - > IsSelected ( ) )
{
gs = new ( SelectionArray ) FGeomSelection ;
gs - > Type = GS_Poly ;
gs - > Index = p ;
gs - > SelectionIndex = gp - > GetSelectionIndex ( ) ;
}
}
}
void UGeomModifier : : StoreAllCurrentGeomSelections ( )
{
2014-06-18 10:16:16 -04:00
if ( ! GLevelEditorModeTools ( ) . IsModeActive ( FBuiltinEditorModes : : EM_Geometry ) )
2014-03-14 14:13:41 -04:00
{
return ;
}
2014-06-18 10:16:16 -04:00
FEdModeGeometry * CurMode = static_cast < FEdModeGeometry * > ( GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ) ;
2014-03-14 14:13:41 -04:00
// Record the current selection list into the selected brushes.
for ( FEdModeGeometry : : TGeomObjectIterator Itor ( CurMode - > GeomObjectItor ( ) ) ; Itor ; + + Itor )
{
2015-04-02 16:34:30 -04:00
FGeomObjectPtr go = * Itor ;
2014-03-14 14:13:41 -04:00
go - > CompileSelectionOrder ( ) ;
ABrush * Actor = go - > GetActualBrush ( ) ;
StoreCurrentGeomSelections ( Actor - > SavedSelections , go ) ;
}
}
2014-10-14 10:29:11 -04:00
UGeomModifier_Edit : : UGeomModifier_Edit ( const FObjectInitializer & ObjectInitializer )
: Super ( ObjectInitializer )
2014-03-14 14:13:41 -04:00
{
Description = NSLOCTEXT ( " UnrealEd " , " Edit " , " Edit " ) ;
2015-02-18 10:58:17 -05:00
Tooltip = NSLOCTEXT ( " UnrealEd.GeomModifier_Edit " , " Tooltip " , " Translate, rotate or scale existing geometry. " ) ;
2014-03-14 14:13:41 -04:00
}
2014-06-18 10:16:16 -04:00
bool UGeomModifier_Edit : : InputDelta ( FEditorViewportClient * InViewportClient , FViewport * InViewport , FVector & InDrag , FRotator & InRot , FVector & InScale )
2014-03-14 14:13:41 -04:00
{
if ( UGeomModifier : : InputDelta ( InViewportClient , InViewport , InDrag , InRot , InScale ) )
{
return true ;
}
2014-06-18 10:16:16 -04:00
if ( ! GLevelEditorModeTools ( ) . IsModeActive ( FBuiltinEditorModes : : EM_Geometry ) )
2014-03-14 14:13:41 -04:00
{
return false ;
}
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
FModeTool_GeometryModify * tool = ( FModeTool_GeometryModify * ) mode - > GetCurrentTool ( ) ;
TArray < FGeomVertex * > UniqueVertexList ;
/**
* All geometry objects can be manipulated by transforming the vertices that make
* them up . So based on the type of thing we ' re editing , we need to dig for those
* vertices a little differently .
*/
2015-02-09 12:06:26 -05:00
// Only permit scaling if there is exactly one selected poly. Make a note of it here
FGeomPoly * SelectedPoly = nullptr ;
int32 NumSelectedPolys = 0 ;
2014-03-14 14:13:41 -04:00
for ( FEdModeGeometry : : TGeomObjectIterator Itor ( mode - > GeomObjectItor ( ) ) ; Itor ; + + Itor )
{
2015-04-02 16:34:30 -04:00
FGeomObjectPtr go = * Itor ;
2014-03-14 14:13:41 -04:00
for ( int32 p = 0 ; p < go - > PolyPool . Num ( ) ; + + p )
{
FGeomPoly * gp = & go - > PolyPool [ p ] ;
if ( gp - > IsSelected ( ) )
{
2015-02-09 12:06:26 -05:00
SelectedPoly = gp ;
NumSelectedPolys + + ;
2014-03-14 14:13:41 -04:00
for ( int32 e = 0 ; e < gp - > EdgeIndices . Num ( ) ; + + e )
{
FGeomEdge * ge = & go - > EdgePool [ gp - > EdgeIndices [ e ] ] ;
UniqueVertexList . AddUnique ( & go - > VertexPool [ ge - > VertexIndices [ 0 ] ] ) ;
UniqueVertexList . AddUnique ( & go - > VertexPool [ ge - > VertexIndices [ 1 ] ] ) ;
}
}
}
for ( int32 e = 0 ; e < go - > EdgePool . Num ( ) ; + + e )
{
FGeomEdge * ge = & go - > EdgePool [ e ] ;
if ( ge - > IsSelected ( ) )
{
UniqueVertexList . AddUnique ( & go - > VertexPool [ ge - > VertexIndices [ 0 ] ] ) ;
UniqueVertexList . AddUnique ( & go - > VertexPool [ ge - > VertexIndices [ 1 ] ] ) ;
}
}
for ( int32 v = 0 ; v < go - > VertexPool . Num ( ) ; + + v )
{
FGeomVertex * gv = & go - > VertexPool [ v ] ;
if ( gv - > IsSelected ( ) )
{
UniqueVertexList . AddUnique ( gv ) ;
}
}
}
// If we didn't move any vertices, then tell the caller that we didn't handle the input.
// This allows LDs to drag brushes around in geometry mode as long as no geometry
// objects are selected.
if ( ! UniqueVertexList . Num ( ) )
{
return false ;
}
const bool bShiftPressed = InViewportClient - > IsShiftPressed ( ) ;
// If we're trying to rotate vertices, only allow that if Shift is held down. This just makes it easier
// to rotate brushes around while working in geometry mode, since you rarely ever want to rotate vertices
FRotator FinalRot = InRot ;
if ( ! bShiftPressed )
{
FinalRot = FRotator : : ZeroRotator ;
}
if ( InDrag . IsZero ( ) & & FinalRot . IsZero ( ) & & InScale . IsZero ( ) )
{
// No change, but handled
return true ;
}
StartTrans ( ) ;
// Let tool know that some modification has actually taken place
tool - > bGeomModified = true ;
/**
* Scaling needs to know the bounding box for the selected verts , so generate that before looping .
*/
Copying //UE4/Dev-Framework to //UE4/Dev-Main (Source: //UE4/Dev-Framework @ 3293188)
#rb none
#lockdown Nick.Penwarden
==========================
MAJOR FEATURES + CHANGES
==========================
Change 3203880 on 2016/11/18 by Ori.Cohen
Copying //UE4/Dev-Physics-Upgrade to Dev-Framework (//UE4/Dev-Framework)
Change 3207429 on 2016/11/22 by Marc.Audy
Merging //UE4/Dev-Main to Dev-Framework (//UE4/Dev-Framework) @ 3207285
Change 3252627 on 2017/01/10 by Lukasz.Furman
removed duplicated entries from visual logger shape rendering
#ue4
Change 3252675 on 2017/01/10 by Ori.Cohen
Add support for tagged memory regions (Copying //Tasks/UE4/Dev-ImmediateModePhysics to Dev-Framework (//UE4/Dev-Framework))
Change 3252686 on 2017/01/10 by Ori.Cohen
Refactor BodySetup to make it easier to reuse shape creation (Copying //Tasks/UE4/Dev-ImmediateModePhysics to Dev-Framework (//UE4/Dev-Framework))
Change 3252833 on 2017/01/10 by Ori.Cohen
Refactor constraint so that it can be used for external solvers. (Copying //Tasks/UE4/Dev-ImmediateModePhysics to Dev-Framework (//UE4/Dev-Framework))
Change 3252887 on 2017/01/10 by Dan.Reynolds
Increased modes to include:
Harmonic minor
Melodic minor (going up)
Pentatonic (Major)
Pentatonic (minor)
Whole Tone
Diminished (WH)
and Blues
Change 3252895 on 2017/01/10 by Aaron.McLeran
update to music utilities.
Change 3253060 on 2017/01/10 by Aaron.McLeran
Updates to synthesis plugin and some new features to DSP objects
Change 3253061 on 2017/01/10 by Aaron.McLeran
Updates to music maps
Change 3253078 on 2017/01/10 by Aaron.McLeran
Removing pragma optimization code accidentally checked in
Change 3253110 on 2017/01/10 by Ori.Cohen
First iteration of immediate mode ragdoll node (Copying //Tasks/UE4/Dev-ImmediateModePhysics to Dev-Framework (//UE4/Dev-Framework))
Change 3253315 on 2017/01/10 by Aaron.McLeran
Fixing a few bugs in DSP objects
- Added a new types file EpicSynth1 and EpicSynth1 component can share enums
Change 3253577 on 2017/01/11 by Aaron.McLeran
Checking in updates to assets for music -- celestial manager for rotating objects like planets, new ambient map
Change 3254052 on 2017/01/11 by Ori.Cohen
Fix build.
Change 3254059 on 2017/01/11 by Ori.Cohen
Turn off html5 trying to build apex.
Change 3254095 on 2017/01/11 by Ori.Cohen
Fix build
Change 3254200 on 2017/01/11 by Jon.Nabozny
Make vectorized FTransform Accumulate (with blend) and AccumulateWithAdditive (with blend) consistent with the non-vectorized version and comments.
#JIRA UE-40469
Change 3254334 on 2017/01/11 by Marc.Audy
Put in missing virtual
Change 3254397 on 2017/01/11 by dan.reynolds
Updates to OtonOkeMap
Change 3254410 on 2017/01/11 by Marc.Audy
Cleanup autos
Change 3254420 on 2017/01/11 by Marc.Audy
PR #3110: Add missing IsInAudioThread check (Contributed by projectgheist)
Modified somewhat, but based on what PR indicated as a problem.
#jira UE-40369
Change 3254423 on 2017/01/11 by Marc.Audy
Optimize GetDefaultSubobjectByName and GetDefaultSubobjects
Remove autos
Change 3254826 on 2017/01/11 by Aaron.McLeran
Bringing optimizations to dev-framework
Change 3254831 on 2017/01/11 by dan.reynolds
Modified MidiSynthTestBP to use Program Change events to pull a Preset from a Preset Bank--added a Data Blueprint Object ES1Bank_Default (containing Preset arrays) with children classes for different classifications of Presets.
Change 3254833 on 2017/01/11 by dan.reynolds
Updating MidiSynthTestBP's default SynthPreset pan value.
Change 3254851 on 2017/01/11 by dan.reynolds
Updating ES1Bank_Bass
Updating OtonOkeMap
Change 3254854 on 2017/01/11 by Aaron.McLeran
Some fixups for pan modulation
Change 3255682 on 2017/01/12 by aaron.mcleran
Turning the bass down a bit on OtonOkeMap
Change 3255721 on 2017/01/12 by Marc.Audy
Fix spelling error
Change 3255790 on 2017/01/12 by Marc.Audy
Copying //UE4/Dev-Physics-Upgrade to Dev-Framework (//UE4/Dev-Framework)
Change 3256263 on 2017/01/12 by Ori.Cohen
Refactor immediate mode api to take PxD6Joint and PxRigidActor instead.
Change 3256288 on 2017/01/12 by Ori.Cohen
Undo constraint refactor as we found a way around it and it made the code much harder to read/debug
Change 3256360 on 2017/01/12 by Ori.Cohen
Make sure physx actors passed into immediate mode are done so with proper locks (can probably improve this in the case where the actor is not even in the scene)
Change 3256846 on 2017/01/13 by Marc.Audy
Deprecate FBox/FBox2D int32 constructor because it makes no sense if you pass in a non 0 value. Use ForceInit instead.
Change 3256954 on 2017/01/13 by Marc.Audy
Fix missed fixup of deprecated constructor use
Change 3257167 on 2017/01/13 by Jon.Nabozny
Fix check in FBodyInstance::SetCollisionEnabled.
Create convenience methods for HasPhysics and HasQuery.
#jira UE-39633
Change 3257181 on 2017/01/13 by Zak.Parrish
Adding input map and some testing content to Xenakis
Change 3257183 on 2017/01/13 by Mieszko.Zielinski
Implemented an improved navigation projection BP function that retrieves both projected locaiton as well as a boolean indicating if the projection succeeded #UE4
Also, did similar changes to GetRandomReachablePointInRadius and GetRandomPointInNavigableRadius
#jira UE-40368
Change 3257211 on 2017/01/13 by Jon.Nabozny
Fix CIS issue caused by 3257167.
Change 3257220 on 2017/01/13 by Marc.Audy
Additional FBox constructor deprecation fixups
Change 3257236 on 2017/01/13 by zak.parrish
Fixed error on Xenakis input pawn
Change 3257242 on 2017/01/13 by zak.parrish
Update to InputListener
Change 3257273 on 2017/01/13 by Marc.Audy
No reason to pass simple types by reference
Change 3257418 on 2017/01/13 by Ori.Cohen
Attempt to turn android physx libs back to static libs.
Change 3257445 on 2017/01/13 by Ori.Cohen
Turn android libs back to OBJ and removed unreal side linking as it seems we are now just merging into a single physx lib
Change 3257903 on 2017/01/14 by Aaron.McLeran
Additions to synth module and updates to dsp objects
- Adding ability to create arbitrary modular patches from modulating sources to modulation destinations
- DSP objects define their default depths but patches can override
- Creating new SynthesisEditor module for synthesis plugin so we can create synthesis preset assets
- Adding a preset bank type so we can store a bank of presets (aka factory presets)
Change 3258179 on 2017/01/15 by Seth.Weedin
Duplicating input test map for some FX work
Change 3258181 on 2017/01/15 by Seth.Weedin
Modify skybox in test map to be dark and spooky
Change 3258183 on 2017/01/15 by aaron.johnson
substituted classes, changed wind speed and adjusted level lighting
Change 3258190 on 2017/01/15 by aaron.johnson
substituted triplet pawn and motion controller classes, enabled grabbing animations
Change 3258191 on 2017/01/15 by Aaron.McLeran
Getting source effects working for GDC demo
- Added new synthesis editor module to create instances of user-created source effects
- Added code to do source effects
- Modified old design to a newer, more simpler design for calling into client code to set parameters. No longer using the complex struct reflection design and instead just pass in the uobject preset the user created. They'll then cast it to the type that has the actual settings.
- Tweaks and fixes to existing dsp objects to get source effects working
- Modified existing engine code to allow for playing out source effect tails
- Only supporting mono and stereo assets for source effect processing. Multi-channel effect processing is overly complex for this feature though we may extend the capabilities in the future.
- Fixed issue of pitching with stereo delay effect on setting first interpolated param
- Moving synth/dsp stuff in synthesis plugins into appropriate public/private folders in plugin/module
- Deleting some cruft files no longer needed
Change 3258201 on 2017/01/15 by Seth.Weedin
C++ and BP classes for managing grid cells. Initial grid mapping tests. #rb none
Change 3258206 on 2017/01/15 by aaron.johnson
map push, triplets interface created, debug widget placed in level
Change 3258222 on 2017/01/15 by Aaron.McLeran
Fixing crash when there's a null entry in the source effect chain
Fixed some zippering introduced by applying volume twice.
Change 3258225 on 2017/01/15 by aaron.johnson
Interface changes, pawn output values wip
Change 3258228 on 2017/01/15 by aaron.johnson
Pawn should be outputting all correct values for Tripletsinterface
Change 3258242 on 2017/01/15 by Stanley.Hayes
Edge lights and Spherical Density Materials
Change 3258251 on 2017/01/16 by Seth.Weedin
More progress on grid FX. Add curve strength modifiers, begin hooking up interaction. #rb none
Change 3258284 on 2017/01/16 by Aaron.McLeran
Fixing CIS build error
Surprised that MSVC allows that...
Change 3258525 on 2017/01/16 by Mieszko.Zielinski
Made UGameplayTask::ResourceOverlapPolicy configurable via ini files #UE4
Change 3258537 on 2017/01/16 by Lukasz.Furman
fixed duplicated & undo operations not updating navigation area in nav link proxy and nav link component
#ue4
Change 3258595 on 2017/01/16 by Marc.Audy
Fix static analysis warning
Change 3259364 on 2017/01/16 by Mieszko.Zielinski
BTTask_RotateToFaceBBEntry comment spelling fix #UE4
#jira UE-40669
Change 3259683 on 2017/01/16 by dan.reynolds
Updated Preset Bank System implemented in MidiSynthTestBP and 4 Preset Banks have been started
Change 3260244 on 2017/01/17 by Lina.Halper
#anim
- optimize layer blend node to not create mask weights in run-time but in compile time.
#code review: Martin.Wilson
Change 3260617 on 2017/01/17 by Ori.Cohen
Immediate mode spawns its own actors.
Change 3260701 on 2017/01/17 by Ori.Cohen
Don't bother blending physics with animation when physics is QueryOnly
Change 3260796 on 2017/01/17 by Ori.Cohen
EndPhysics tick will no longer be scheduled if QueryOnly is used on a ragdoll.
Change 3261207 on 2017/01/17 by Ori.Cohen
First iteration of contact enabling/disabling for immediate mode.
Change 3262010 on 2017/01/18 by Marc.Audy
Remove some autos
Change 3262525 on 2017/01/18 by Lina.Halper
Fix crash with required bones index not using property indexing
#jira: UE-40786
Change 3263658 on 2017/01/19 by Martin.Wilson
Add AnimTechDemo to dev-framework (base third person + feng mao)
Change 3263684 on 2017/01/19 by Lina.Halper
#anim : layer node - fix allocation change I made by mistake
Change 3264523 on 2017/01/19 by Ori.Cohen
Immediate mode can now add static geometry it finds in the world. Also improve contact gen by caching iteration order
Change 3264701 on 2017/01/19 by Ori.Cohen
Make it so that immediate mode ragdolls collide with the ground in persona.This is a bit of an editor only hack which allows immediate mode to find non-static actors
Change 3264980 on 2017/01/19 by Ori.Cohen
Make sure physics asset collision disabled works in immediate mode.
Change 3265011 on 2017/01/19 by Ori.Cohen
Added the ability to override physics asset for immediate mode
Change 3265030 on 2017/01/19 by Ori.Cohen
Added override gravity for immediate mode.
Change 3265650 on 2017/01/20 by Benn.Gallagher
NvCloth Source
Change 3265652 on 2017/01/20 by Benn.Gallagher
NvCloth Lib
#rnx
Change 3265653 on 2017/01/20 by Benn.Gallagher
NvCloth Bin
#rnx
Change 3266195 on 2017/01/20 by Danny.Bouimad
Initial ClothTest Assets for NCloth Before and after comparison TM-MultiClothTest (Under Maps>Framework>Cloth)
Change 3266377 on 2017/01/20 by Marc.Audy
Ensure that OrphanedDataOnly and TrashClass blueprint generated classes are correctly considered a blueprint class for disregard for GC purposes.
Change 3267873 on 2017/01/23 by Jon.Nabozny
Fix SceneProxy shadowing in UGeometryCacheComponent.
Change 3268025 on 2017/01/23 by Benn.Gallagher
IWYU change, platform PCH generation seemed to hide this one.
Change 3268026 on 2017/01/23 by Benn.Gallagher
Fixed LOCTEXT_NAMESPACE being inconsistently scoped in an #if block
#rnx
Change 3268630 on 2017/01/23 by Zak.Parrish
Updating to add MIGS shooter content, as well as audio interaction Blueprints
Change 3268663 on 2017/01/23 by Ori.Cohen
Ragdoll animnode uses raw physics asset pointer to ensure it makes a hard reference.
Change 3268811 on 2017/01/23 by Ori.Cohen
Added component space sim for immediate mode
Change 3269369 on 2017/01/24 by Benn.Gallagher
Copying //Tasks/UE4/Dev-UEFW-11-NewClothingPipeline to Dev-Framework (//UE4/Dev-Framework)
Replaced clothing with new simulation framework
Change 3269417 on 2017/01/24 by danny.bouimad
Minor Update to cloth map for test
Change 3269420 on 2017/01/24 by Benn.Gallagher
Removed APEX simulation from clothing framework (used in testing, not fully complete)
Change 3269421 on 2017/01/24 by danny.bouimad
Small tweaks
Change 3269515 on 2017/01/24 by Lukasz.Furman
enabled gameplay debugger's OnSelectionChanged event support for both PIE and SIE modes
fixed GameplayAbility debugger's category not using IAbilitySystemInterface
#ue4
Change 3269595 on 2017/01/24 by mason.seay
Break apart physics asset for crash bug
Change 3269819 on 2017/01/24 by Ori.Cohen
Make the possibly kinematic actor the first actor in the immediate mode joint. This is consistent with physx vanilla solver.
Change 3270364 on 2017/01/24 by Josh.Stoddard
upgrade to the latest version of v-HACD:
https://github.com/kmammou/v-hacd/tree/master/src/VHACD_Lib
commit: 7a09f9d
NOTE: only updated windows binaries
mac and linux still using old binaries until they can be tested
#jira UE-40124 #rb josh.stoddard
Change 3271188 on 2017/01/25 by Jurre.deBaare
Post-import script support
#jira UEFW-80
Change 3271249 on 2017/01/25 by Thomas.Sarkanen
Move soundwave-internal curve tables to advanced display
Exposing it was confusing to audio people
Change 3271586 on 2017/01/25 by Marc.Audy
Don't rerun construction scripts twice on a level that has been hidden and reshown
#jira UE-40306
Change 3272048 on 2017/01/25 by Ori.Cohen
Fix for immediate mode sim when root body is the same as the root bone.
Change 3272083 on 2017/01/25 by Ori.Cohen
Make sure to warn when component space sim and collision are used together. Also handle it gracefully.
Change 3272300 on 2017/01/25 by Ori.Cohen
Fix incorrect collision generation when a shape's local pose is not identity.
Change 3273195 on 2017/01/26 by Jurre.deBaare
Fix for Anim import script crash in GetBonePosesForTime
Change 3273204 on 2017/01/26 by Ben.Marsh
Ignore PRAGMA_DISABLE_SHADOW_VARIABLE_WARNINGS and PRAGMA_ENABLE_SHADOW_VARIABLE_WARNINGS macros between include directives. Fixes CIS warning with IncludeTool.
Change 3273378 on 2017/01/26 by James.Golding
In AnimBP editor, call CopyNodeDataToPreviewNode when properties are edited, not just pin defaults changed
Change 3273381 on 2017/01/26 by James.Golding
Big refactor to PoseDriver
- RBF logic now moved into its own class/file
- Allow editing of transform and radial scaling per-target
- Add support for different falloff functions (not just Gaussian)
- Allow driving curves directly, rather than always poses
- Add details customization for pose driver node
- Edits to PoseDriver settings now take immediate effect, don't need to recompile
Change 3273826 on 2017/01/26 by Josh.Stoddard
modify VHACD to improve quality of hulls generated by convex decomposition
NOTE: mac libs not included - mac editor will use legacy libs for now
Change 3273902 on 2017/01/26 by Marc.Audy
Merging //UE4/Dev-Main to Dev-Framework (//UE4/Dev-Framework) @ 3273433
Change 3274018 on 2017/01/26 by Ori.Cohen
Added immediate physics preview in phat.
Change 3274165 on 2017/01/26 by Ori.Cohen
PhAT now depends on immediate mode plugin. Fix build
#JIRA UE-41179
Change 3275001 on 2017/01/27 by Jurre.deBaare
Fix for crash in Persona with Anim Modifiers
Change 3275297 on 2017/01/27 by Ori.Cohen
Big refactor to iterate over shapes instead of bodies (allows multiple shape per body collision)
Change 3275340 on 2017/01/27 by Benn.Gallagher
Fixed Paragon clothing crashes during clothing upgrade step, fixed bone mapping not getting updated on reimport with different hierarchy
#jira UE-41025
#jira UE-41039
Change 3275383 on 2017/01/27 by Benn.Gallagher
Blacklisted double promotion warning on ps4 NvCloth build
#rnx
Change 3275426 on 2017/01/27 by Benn.Gallagher
Removed CUDA dependencies from NvCloth cmake files
Change 3275670 on 2017/01/27 by Ori.Cohen
Fix phat ragdoll in immediate mode updating sketal mesh component transform
Change 3275673 on 2017/01/27 by Ori.Cohen
Add position/velocity iteration to immediate mode
Change 3276001 on 2017/01/27 by Alan.Noon
Migrated Immediate Mode Minion Ragdoll Content to GDC AnimTech Project. Updated DefaultInput.ini
none
Change 3276596 on 2017/01/28 by Aaron.McLeran
Removing unused #ifdef
Change 3276597 on 2017/01/28 by Aaron.McLeran
Getting rid of static analysis warning
Change 3277354 on 2017/01/30 by Lukasz.Furman
fixed custom navlink Id collisions
#ue4
Change 3277356 on 2017/01/30 by Lukasz.Furman
fixed comments in GameplayDebugger.h
#jira UE-41103
Change 3277371 on 2017/01/30 by mason.seay
Test map for spawn sound/force feedback bug.
Change 3277445 on 2017/01/30 by Lukasz.Furman
fixed compilation warning
#ue4
Change 3277560 on 2017/01/30 by Danny.Bouimad
Made checkin to Fix Crash that occured due to bad content.
Change 3277567 on 2017/01/30 by Ori.Cohen
Fix immediate mode crashing when joint is empty.
#JIRA UE-41026
Change 3277928 on 2017/01/30 by Ori.Cohen
Turn on immediate mode plugin by default
Change 3278433 on 2017/01/30 by Ori.Cohen
Immediate mode supports heightfield collision.
Change 3278449 on 2017/01/30 by Ori.Cohen
Fix immediate mode cache not being initialized properly.
Change 3278787 on 2017/01/31 by James.Golding
Fix CIS error in ImmediatePhysicsSimulation.cpp
Change 3279303 on 2017/01/31 by mason.seay
Assets for RigidBody node bug
Change 3279352 on 2017/01/31 by Benn.Gallagher
Fixed inertia blends on self collision cloth assets as we now only have local space simulation and these values weren't used before
Change 3279377 on 2017/01/31 by Alan.Noon
GDC AnimTech Demo: adjusted minion physics assets
none
Change 3279425 on 2017/01/31 by james.cobbett
Updating QA-Physics map.
Made one of the simulated physics objects more user-friendly, able to enable/disable physics on key-press now.
Change 3279436 on 2017/01/31 by Benn.Gallagher
Fixed inertia scales on Owen mesh
Change 3279480 on 2017/01/31 by Benn.Gallagher
Fixes for clothing behavior changes
#jira UE-41092
Change 3279495 on 2017/01/31 by Ori.Cohen
Remove unneeded cache clearing when contact pairs are not skipped, but there is no collision.
Change 3279579 on 2017/01/31 by james.cobbett
Added new scenario to QA-Physics map.
Moving platforms (up/down, left/right) with physics objects on them.
Change 3279695 on 2017/01/31 by mason.seay
RigidBody node test asset
Change 3280105 on 2017/01/31 by Ori.Cohen
Prevent query only ragdolls from simulating if their bodysetup is marked as simulated. Also remove slow check in term body for owning components. This is not true for destructibles or immediate mode
Change 3280148 on 2017/01/31 by mason.seay
First round of assets for force feedback testing
Change 3280860 on 2017/02/01 by James.Golding
Merge CL 3280853 to Dev-Framework
Fix crash with null CurrentSkeleton on AnimInstance when using Re-import button in SkelMesh Editor
Change 3281172 on 2017/02/01 by Marc.Audy
Merging //UE4/Dev-Main to Dev-Framework (//UE4/Dev-Framework) @ 3281156
Change 3281210 on 2017/02/01 by james.cobbett
Updated QA-Physics map
Added cube that starts off with physics enabled, then disables. Made physics toggleable on that and another cube.
Change 3281211 on 2017/02/01 by James.Golding
Details customization for editing PoseDriver targets list
Change 3281332 on 2017/02/01 by Marc.Audy
Fix bad merge
Fix file types
Change 3281388 on 2017/02/01 by mason.seay
Updated Force Feedback asset
Change 3281396 on 2017/02/01 by mason.seay
moving asset
Change 3281987 on 2017/02/01 by Benn.Gallagher
Fixed project generation failing after main merge
Change 3282047 on 2017/02/01 by Marc.Audy
Fix up Target and build cs files after changes from Dev-Build
Change 3282214 on 2017/02/01 by Ori.Cohen
Expose radial forces to immediate mode
Change 3282221 on 2017/02/01 by Alan.Noon
Immediate Mode GDC demo content: development on minion anim B, refined Orbital Laser Pawn controls, tweaked laser parameters
none
Change 3282273 on 2017/02/01 by Ori.Cohen
Fix crash when recompiling animbp of immediate mode due to null pointer.
Change 3282368 on 2017/02/01 by Ori.Cohen
Quick iteration on minion demo
Change 3282824 on 2017/02/02 by James.Golding
Fix for CIS in RBFSolver.h
Change 3282829 on 2017/02/02 by James.Golding
Fix CIS in PoseDriverDetails.cpp
Fix list UI not refreshing after copying targets from PoseAsset
Change 3282834 on 2017/02/02 by Danny.Bouimad
Adding Pose driver additive assets
Change 3282863 on 2017/02/02 by James.Golding
Add Mambo mesh and Skeleton
Change 3282892 on 2017/02/02 by James.Golding
Copy Aurora (Ice) and Mambo meshes/materials/some anims from Dev-General to AnimTechDemo project in Dev-Framework
Change 3283157 on 2017/02/02 by Mieszko.Zielinski
Cook Orion Win64 fix #UE4
Had to change the Extent param of K2_ProjectPointToNavigation. Updated the error causing Orion BP
Change 3283159 on 2017/02/02 by Marc.Audy
Additional CIS fixes
Change 3283179 on 2017/02/02 by Marc.Audy
More CIS fixes
Change 3283197 on 2017/02/02 by Jurre.deBaare
Fix for issues importing Fornite geometry cache assets
#fix Use actual import number of frames instead of total number of frames in the Alembic Cache
Change 3283201 on 2017/02/02 by Marc.Audy
Keep fixing CIS
Change 3283270 on 2017/02/02 by James.Golding
Merging CL 3276013 to Dev-Framework
- fix issue with additive pose preview applying twice
Change 3283499 on 2017/02/02 by Marc.Audy
More CIS fixes
Change 3283543 on 2017/02/02 by Jon.Nabozny
Update comment on AActor::GetActorBounds to properly reflect ChildActorComponents aren't included in the calculation.
Change 3283663 on 2017/02/02 by Ori.Cohen
Fix potential null dereference in ragdoll node
Change 3283757 on 2017/02/02 by Marc.Audy
May fix remaining CIS issues
Change 3283984 on 2017/02/02 by Marc.Audy
Fix linux CIS
Change 3284039 on 2017/02/02 by Marc.Audy
Merging //UE4/Dev-Main to Dev-Framework (//UE4/Dev-Framework) @ 3283913
Change 3284067 on 2017/02/02 by Marc.Audy
Fixup mistakes in converting redirects
Change 3284187 on 2017/02/02 by Ori.Cohen
Immediate mode works with radial force (not just radial impulse)
Change 3284358 on 2017/02/02 by Ori.Cohen
Update arcblade phys asset for immediate mode
Change 3284667 on 2017/02/02 by Marc.Audy
Arguments is an array not a string now. Fixing commented out code.
Change 3284684 on 2017/02/02 by Marc.Audy
Move AVIWriter out in to its own module to avoid any possible unity build issues where xwindows.h got indirectly included through the DirectShow third party library and caused FGenericWindow::IsMaximized and IsMinimized to conflict with a macro.
Change 3284707 on 2017/02/02 by Marc.Audy
Fix AVIWriter module compilation on Mac
Change 3285012 on 2017/02/03 by Benn.Gallagher
Fixes for Dx NvCloth shader warnings
Change 3285016 on 2017/02/03 by Marc.Audy
Fix missing include
Change 3285048 on 2017/02/03 by Benn.Gallagher
Fixed Persona needing a restart when changing number of clothing assets (import/delete)
#jira UE-41323
Change 3285325 on 2017/02/03 by Marc.Audy
Properly implement AVIWriter module
Change 3285538 on 2017/02/03 by Marc.Audy
Merging //UE4/Dev-Main to Dev-Framework (//UE4/Dev-Framework) @ 3285499
Change 3285735 on 2017/02/03 by Jon.Nabozny
Add IsInAir method to UVehicleWheel.
#jira UE-38369
Change 3285862 on 2017/02/03 by Aaron.McLeran
UE-41435 Fixing PIE audio
- Fixing PIE audio. Recent change to editor preferences from Dev-Editor branch (CL 3234495) caused all audio to be muted in PIE.
Change 3285914 on 2017/02/03 by danny.bouimad
RecomputeTangents Test Assets
Change 3286246 on 2017/02/03 by Mieszko.Zielinski
Changes to game-specific BPs containing calls to deprecated NavigationSystem functions #UE4
#jira UE-41527
#jira UE-41518
Change 3286308 on 2017/02/03 by Ori.Cohen
Make sure physx trimesh scale is never too small. Fix box clamping being ignored. Fixes cook warnings for Odin.
#JIRA UE-41529
Change 3286396 on 2017/02/03 by Ori.Cohen
Fix CIS
Change 3286479 on 2017/02/03 by Ori.Cohen
Copying //UE4/Dev-Physics-Upgrade to Dev-Framework (//UE4/Dev-Framework)
Change 3287421 on 2017/02/06 by James.Golding
Merging //UE4/Dev-Main to Dev-Framework (//UE4/Dev-Framework) @ 3286819
Change 3287427 on 2017/02/06 by James.Golding
Fix PoseBlendNode to 'pass through' if no poses are activated
Change 3287430 on 2017/02/06 by James.Golding
- Add support to PoseDriver for evaluating source bone in the space of a different bone
- Fix driven bone adding a scale of 1
- Fix posedriver values 'sticking' (reset all weights to zero each frame)
- Move CopyTargetsFromPoseAsset and AutoSetTargetScales from FAnimNode_PoseDriver to UAnimGraphNode_PoseDriver (not required outside editor)
- Tranlsation targets now draw larger when selected
- 'Copy from pose asset' now also auto-sets radius for you
- Remove spammy warnings for missing poses/curves
- Add UPoseAsset::GetNumTracks and ::GetFullPose
- Remove unused ExtractionContext from UPoseAsset::GetBaseAnimationPose
- Remove bIncludeRefPoseAsNeutralPose option (not really useful since we no longer always normalize weights to 1.0)
Change 3287496 on 2017/02/06 by Chad.Garyet
fixing busted quotes around defaultvalues
Change 3287569 on 2017/02/06 by Mieszko.Zielinski
Orion BP fixed after deprecating NavigationSystem's BP API #Orion
Change 3287595 on 2017/02/06 by Benn.Gallagher
BuildPhysX.Automation: Deploying PhysX & NvCloth Win64 Win32 PS4 libs.
Built for new NvCloth upgrade
Change 3287598 on 2017/02/06 by Benn.Gallagher
NvCloth Upgrade to 21604115
Added Linux+Mac support
Change 3287710 on 2017/02/06 by Lukasz.Furman
added option to disable navlink polys at the end of generated paths
#ue4
Change 3287857 on 2017/02/06 by Benn.Gallagher
Fixed NvCloth module files to correctly set up linux and mac hopefully
Change 3287894 on 2017/02/06 by Benn.Gallagher
Another fix to NvCloth build files, didn't get picked up in VS for some reason.
Change 3287917 on 2017/02/06 by Lina.Halper
Copy from CharacterRigging to Dev-Framework
#code review:Thomas.Sarkanen, Martin.Wilson, James.Golding, Andrew.Rodham
Change 3287938 on 2017/02/06 by Thomas.Sarkanen
Fix crash opening a media sound wave
#jira UE-41582 - Editor crashes when running Automation test
Change 3287942 on 2017/02/06 by Marc.Audy
Merging //UE4/Dev-Main to Dev-Framework (//UE4/Dev-Framework) @ 3287682
Change 3288035 on 2017/02/06 by James.Golding
Remove C++ GameMode and pawn classes (replace with floating BP instead)
Resave anims to remove Orion refs
Add simple AnimBP and map for Mambo testing
Change 3288036 on 2017/02/06 by Benn.Gallagher
Fix to BuildPhysX task to trigger Mac and Linux builds properly
Change 3288125 on 2017/02/06 by Ori.Cohen
Change PhysXCommon back to dylib
Change 3288127 on 2017/02/06 by Benn.Gallagher
Fixed project file identification not working for NvCloth under XCode
Change 3288156 on 2017/02/06 by Benn.Gallagher
Disable "expansion-to-defined" warning in Linux NvCloth builds
Change 3288159 on 2017/02/06 by Lina.Halper
potential compile fix for Ocean Editor
#code review:Thomas.Sarkanen
Change 3288190 on 2017/02/06 by Ori.Cohen
Link against static PhysXCommon for mac
Change 3288200 on 2017/02/06 by Marc.Audy
Fix CIS
Change 3288270 on 2017/02/06 by Lina.Halper
fix compile error
#code review:Thomas.Sarkanen, Marc.Audy
Change 3288302 on 2017/02/06 by Thomas.Sarkanen
Fixed ensure when deselecting bones in anim BP editor
#jira UE-41274 - Ensure when clicking in the viewport of an animation blueprint
Change 3288348 on 2017/02/06 by Lina.Halper
- Enabled control rig
- Changed plugin name to be Control Rig
Change 3288490 on 2017/02/06 by Benn.Gallagher
Fixes for Mac attempting static links against NvCloth and failing to load dynamic libraries. Worked with MasonS to get Mac editor up and running.
Change 3288511 on 2017/02/06 by Lina.Halper
compile fix
Change 3288513 on 2017/02/06 by Lina.Halper
Check in content to work with
Change 3288615 on 2017/02/06 by Ori.Cohen
Fix skeletal mesh not simulating when using an aggregate.
#JIRA UE-41593
Change 3288791 on 2017/02/06 by thomas.sarkanen
Exposed transforms to cinematics so they can be animated
Change 3288795 on 2017/02/06 by Ori.Cohen
Fix lock warnings for physx
#JIRA UE-41591
Change 3288817 on 2017/02/06 by Charles.Anderson
GDC Arcblade setup tests.
Change 3288825 on 2017/02/06 by Lina.Halper
Fix build issue of shadow variable
Change 3289058 on 2017/02/06 by Ori.Cohen
Fix crash when immediate mode constraint generates 0 rows. This is a potentially temporary fix until NVIDIA replies with a better solution.
#JIRA UE-41026
Change 3289348 on 2017/02/06 by Lina.Halper
fix compile issue
Change 3289369 on 2017/02/06 by Lina.Halper
Renamed leg control to limb control and will be used for arm/feet.
- changed vars.
- has unused variables that will be used soon but want to check in so that i don't block content change on BaseHuman.
#code review:Thomas.Sakanen
Change 3289422 on 2017/02/06 by Lina.Halper
Fixed IK sinking issue - or moving
#code review:Thomas.Sarkanen
Change 3289433 on 2017/02/06 by Lina.Halper
Fixed real shadow error
Change 3289485 on 2017/02/06 by Lina.Halper
fixed build issue
Change 3289657 on 2017/02/07 by thomas.sarkanen
Added rig bone mapping to Ice's skeletal mesh
Change 3289658 on 2017/02/07 by thomas.sarkanen
Added ControlRig map with Ice setup to pose
Change 3289662 on 2017/02/07 by Thomas.Sarkanen
Fixed up static analysis warning
Change 3289663 on 2017/02/07 by Thomas.Sarkanen
Fixed crash when attempting to bind to skeletal mesh with already-set anim BP
Anim instance may not have actually been created when binding, so dont dereference it
Change 3289717 on 2017/02/07 by Benn.Gallagher
Switch Linux NvCloth to static for Linux builds. Adjust lib directory to match actual directory
Change 3289718 on 2017/02/07 by Benn.Gallagher
BuildPhysX.Automation: Deploying NvCloth Linux_x86_64-unknown-linux-gnu libs.
Change 3289744 on 2017/02/07 by Benn.Gallagher
Fixed missing masses causing crash initialising clothing actors
#jira UE-41599
Change 3289746 on 2017/02/07 by Danny.Bouimad
Adding Some Content for JamesG he wanted some nicer looking Pose driver test files.
Change 3289756 on 2017/02/07 by danny.bouimad
Changing the asset for JamesG.
Change 3289785 on 2017/02/07 by James.Golding
Replace old PoseDrive test with Danny's new one
Change 3289858 on 2017/02/07 by Lina.Halper
fixed issue with undo transaction buffer
Change 3289860 on 2017/02/07 by Benn.Gallagher
Fixed crash after reimporting a clothing asset with the clothing config open and then changing the confg
#jira UE-41655
Change 3289912 on 2017/02/07 by Thomas.Sarkanen
Merging using Raven_To_Dev-Framework
Originally from CLs 3249471, 3258522, 3260271, 3273791:
Sequencer: More work supporting array properties more generically
+ fixes
Change 3289962 on 2017/02/07 by James.Golding
Add thickness option to DrawWireDiamond
Change 3289963 on 2017/02/07 by James.Golding
Add spin option to VectorInputBox
Change 3289966 on 2017/02/07 by James.Golding
Add weight bar chart to PoseDriver details
Stop drawing pose weight text in viewport
Fix position targets not drawing larger when selected
Change 3290094 on 2017/02/07 by Thomas.Sarkanen
Fixed typo in filename (fallout from search and replace)
Change 3290119 on 2017/02/07 by Thomas.Sarkanen
Manipulators can now have their IK/FK space set on them
They are not drawn when the space for the chain that they control is not the same as their setting
Also fixed a crash with invalid objects when reloading maps.
Change 3290145 on 2017/02/07 by Thomas.Sarkanen
CIS fix for fallout from Raven changes
#jira UE-41670 - Mac editor fails to compile with PropertyTrackEditor errors
Change 3290319 on 2017/02/07 by Marc.Audy
Make sound player nodes hard reference the assets unless they are in a chain below a quality node.
Change 3290484 on 2017/02/07 by Richard.Hinckley
Fixing grammar in popup messages.
Change 3290533 on 2017/02/07 by Marc.Audy
Make GetAIController BlueprintPure
#jira UE-41654
Change 3290624 on 2017/02/07 by Marc.Audy
Reorder header to avoid include tool warnings
Change 3290697 on 2017/02/07 by Lina.Halper
- support FK manipulator being in local space
- fixed FK key spamming issue for making blend weight to be not keyable - this creates conflicts with enum
#code review: Thomas.Sarkanen
Change 3290748 on 2017/02/07 by Ori.Cohen
Touch immediate mode file to force physx re-link
Change 3290807 on 2017/02/07 by Richard.Hinckley
#jira UE-39891
Updates to assist in automatic documentation generation.
Change 3290946 on 2017/02/07 by Lina.Halper
Fix issue of notify looping.
#jira: UE-31463
#Code review:Martin.Wilson
Change 3291553 on 2017/02/07 by Lina.Halper
Rename/move file(s)
- modified mesh mapping controller window to be Control Rig
Change 3291571 on 2017/02/07 by Lina.Halper
added set up spine option
#code review:Thomas.Sarkanen
Change 3291581 on 2017/02/07 by Ori.Cohen
Temporarily turn off phat immediate mode preview which crashes.
Change 3291949 on 2017/02/08 by James.Golding
Merging //UE4/Dev-Main to Dev-Framework (//UE4/Dev-Framework) @ 3291819
Change 3291966 on 2017/02/08 by Lina.Halper
Fix issue with notify looping bug
#jira: UE-31463
Change 3292247 on 2017/02/08 by Marc.Audy
Clean up bad merge caused by Fortnite integration to main
Change 3292326 on 2017/02/08 by Marc.Audy
Merging //UE4/Dev-Main to Dev-Framework (//UE4/Dev-Framework) @ 3292313
Change 3292409 on 2017/02/08 by Marc.Audy
Resubmit FortPawn.cpp with proper code even though perforce doesn't think there is a difference since when you sync it, the contents are wrong.
Change 3292481 on 2017/02/08 by Ori.Cohen
Fix for convex hull cooking (from Josh.S)
#JIRA UE-41656
Change 3292492 on 2017/02/08 by Mieszko.Zielinski
Redone replacement of deprecated navigation system's BP functions in Fortnite BPs #Fortnite
Change 3292778 on 2017/02/08 by Ori.Cohen
Touch physx DDC key for new cooking.
#JIRA UE-41656
[CL 3293329 by Marc Audy in Main branch]
2017-02-08 17:53:41 -05:00
FBox VertBBox ( ForceInit ) ;
2014-03-14 14:13:41 -04:00
for ( int32 x = 0 ; x < UniqueVertexList . Num ( ) ; + + x )
{
VertBBox + = * UniqueVertexList [ x ] ;
}
FVector BBoxExtent = VertBBox . GetExtent ( ) ;
/**
2015-02-09 12:06:26 -05:00
* We first generate a list of unique vertices and then transform that list
* in one shot . This prevents vertices from being touched more than once ( which
* would result in them transforming x times as fast as others ) .
*/
2014-03-14 14:13:41 -04:00
for ( int32 x = 0 ; x < UniqueVertexList . Num ( ) ; + + x )
{
FGeomVertex * vtx = UniqueVertexList [ x ] ;
2015-02-09 12:06:26 -05:00
const ABrush * Brush = vtx - > GetParentObject ( ) - > GetActualBrush ( ) ;
2014-03-14 14:13:41 -04:00
2015-02-09 12:06:26 -05:00
// Translate
if ( ! InDrag . IsZero ( ) )
{
* vtx + = Brush - > ActorToWorld ( ) . InverseTransformVector ( InDrag ) ;
}
2014-03-14 14:13:41 -04:00
// Rotate
if ( ! FinalRot . IsZero ( ) )
{
2015-02-09 12:06:26 -05:00
const FRotationMatrix Matrix ( FinalRot ) ;
2014-03-14 14:13:41 -04:00
FVector Wk ( vtx - > X , vtx - > Y , vtx - > Z ) ;
2015-02-09 12:06:26 -05:00
Wk = Brush - > ActorToWorld ( ) . TransformPosition ( Wk ) ;
2014-06-18 10:16:16 -04:00
Wk - = GLevelEditorModeTools ( ) . PivotLocation ;
2015-02-09 12:06:26 -05:00
Wk = Matrix . TransformPosition ( Wk ) ;
2014-06-18 10:16:16 -04:00
Wk + = GLevelEditorModeTools ( ) . PivotLocation ;
2015-02-09 12:06:26 -05:00
* vtx = Brush - > ActorToWorld ( ) . InverseTransformPosition ( Wk ) ;
2014-03-14 14:13:41 -04:00
}
// Scale
2015-02-09 12:06:26 -05:00
if ( ! InScale . IsZero ( ) & & NumSelectedPolys = = 1 )
2014-03-14 14:13:41 -04:00
{
2015-02-09 12:06:26 -05:00
// This is a quick fix for now.
// Scale needs to know the surface normal of the polys selected (and scale only makes sense on polys, not edges or verts),
// so remember one selected poly and use that transform.
// Since scaling is relative to the pivot, it would actually be horrible scaling multiple polys at once anyway.
const FScaleMatrix Matrix ( InScale + 1.0f ) ;
const FVector PivotInModelSpace = Brush - > ActorToWorld ( ) . InverseTransformPosition ( GLevelEditorModeTools ( ) . PivotLocation ) ;
const FRotationMatrix GeomBaseTransform = FRotationMatrix ( SelectedPoly - > GetWidgetRotation ( ) ) ;
2014-03-14 14:13:41 -04:00
2015-02-09 12:06:26 -05:00
FVector Wk ( vtx - > X , vtx - > Y , vtx - > Z ) ;
Wk - = PivotInModelSpace ;
Wk = GeomBaseTransform . TransformPosition ( Wk ) ;
Wk = Matrix . TransformPosition ( Wk ) ;
Wk = GeomBaseTransform . InverseTransformPosition ( Wk ) ;
Wk + = PivotInModelSpace ;
2014-11-26 07:06:03 -05:00
* vtx = Wk ;
2014-03-14 14:13:41 -04:00
}
}
if ( DoEdgesOverlap ( ) )
{
//Two edges overlap, which causes triangulation problems, so move the vertices back to their previous location
for ( int32 x = 0 ; x < UniqueVertexList . Num ( ) ; + + x )
{
FGeomVertex * vtx = UniqueVertexList [ x ] ;
2015-02-09 12:06:26 -05:00
const ABrush * Brush = vtx - > GetParentObject ( ) - > GetActualBrush ( ) ;
* vtx - = Brush - > ActorToWorld ( ) . InverseTransformVector ( InDrag ) ;
2014-03-14 14:13:41 -04:00
}
2015-02-09 12:06:26 -05:00
GLevelEditorModeTools ( ) . PivotLocation - = InDrag ;
GLevelEditorModeTools ( ) . SnappedLocation - = InDrag ;
2014-03-14 14:13:41 -04:00
}
const bool bIsCtrlPressed = InViewportClient - > IsCtrlPressed ( ) ;
const bool bIsAltPressed = InViewportClient - > IsAltPressed ( ) ;
if ( ! InDrag . IsZero ( ) & & bShiftPressed & & bIsCtrlPressed & & ! bIsAltPressed )
{
FVector CameraDelta ( InDrag ) ;
// Only apply camera speed modifiers to the drag if we aren't zooming in an ortho viewport.
if ( ! InViewportClient - > IsOrtho ( ) | | ! ( InViewport - > KeyState ( EKeys : : LeftMouseButton ) & & InViewport - > KeyState ( EKeys : : RightMouseButton ) ) )
{
2014-04-23 20:13:24 -04:00
const float CameraSpeed = InViewportClient - > GetCameraSpeed ( ) ;
2014-03-14 14:13:41 -04:00
CameraDelta * = CameraSpeed ;
}
InViewportClient - > MoveViewportCamera ( CameraDelta , InRot ) ;
}
EndTrans ( ) ;
2015-08-21 09:54:19 -04:00
bPendingPivotOffsetUpdate = true ;
2014-04-28 11:39:35 -04:00
GEditor - > RedrawLevelEditingViewports ( true ) ;
2014-03-14 14:13:41 -04:00
return true ;
}
/*------------------------------------------------------------------------------
UGeomModifier_Extrude
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2014-10-14 10:29:11 -04:00
UGeomModifier_Extrude : : UGeomModifier_Extrude ( const FObjectInitializer & ObjectInitializer )
: Super ( ObjectInitializer )
2014-03-14 14:13:41 -04:00
{
Description = NSLOCTEXT ( " UnrealEd " , " Extrude " , " Extrude " ) ;
2015-02-18 10:58:17 -05:00
Tooltip = NSLOCTEXT ( " UnrealEd.GeomModifier_Extrude " , " Tooltip " , " Moves the selected geometry element forward, creating new geometry behind it if necessary. " ) ;
2014-03-14 14:13:41 -04:00
Length = 16 ;
Segments = 1 ;
}
2016-02-01 14:57:29 -05:00
bool UGeomModifier_Extrude : : InputDelta ( FEditorViewportClient * InViewportClient , FViewport * InViewport , FVector & InDrag , FRotator & InRot , FVector & InScale )
{
FEdModeGeometry * Mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
const bool bGetRawValue = true ;
const bool bIsLocalCoords = GLevelEditorModeTools ( ) . GetCoordSystem ( bGetRawValue ) = = COORD_Local ;
if ( ! bIsLocalCoords )
{
// Before the modal dialog has popped up, force tracking to stop and reset the focus
InViewportClient - > LostFocus ( InViewport ) ;
InViewportClient - > ReceivedFocus ( InViewport ) ;
CheckCoordinatesMode ( ) ;
}
if ( ! bIsLocalCoords | | Mode - > GetCurrentWidgetAxis ( ) ! = EAxisList : : X )
{
InDrag = FVector : : ZeroVector ;
InRot = FRotator : : ZeroRotator ;
InScale = FVector : : ZeroVector ;
return false ;
}
return Super : : InputDelta ( InViewportClient , InViewport , InDrag , InRot , InScale ) ;
}
2014-03-14 14:13:41 -04:00
bool UGeomModifier_Extrude : : Supports ( )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
return mode - > HavePolygonsSelected ( ) ;
}
void UGeomModifier_Extrude : : WasActivated ( )
{
// Extrude requires a local coordinate system to work properly so automatically enable
// that here while saving the current coordinate system for restoration later.
const bool bGetRawValue = true ;
2014-06-18 10:16:16 -04:00
SaveCoordSystem = GLevelEditorModeTools ( ) . GetCoordSystem ( bGetRawValue ) ;
2014-03-14 14:13:41 -04:00
CheckCoordinatesMode ( ) ;
GEditor - > RedrawLevelEditingViewports ( true ) ;
}
void UGeomModifier_Extrude : : WasDeactivated ( )
{
// When the user leaves this modifier, restore their old coordinate system.
2014-06-18 10:16:16 -04:00
GLevelEditorModeTools ( ) . SetCoordSystem ( ( ECoordSystem ) SaveCoordSystem ) ;
2014-03-14 14:13:41 -04:00
GEditor - > RedrawLevelEditingViewports ( true ) ;
}
void UGeomModifier_Extrude : : CheckCoordinatesMode ( )
{
const bool bGetRawValue = true ;
2014-06-18 10:16:16 -04:00
if ( GLevelEditorModeTools ( ) . GetCoordSystem ( bGetRawValue ) ! = COORD_Local )
2014-03-14 14:13:41 -04:00
{
FSuppressableWarningDialog : : FSetupInfo Info ( LOCTEXT ( " ExtrudeCoordinateWarningBody " , " Extrude only works with Local Coordinates System " ) , LOCTEXT ( " ExtrudeCoordinateWarningTitle " , " Extrude Coordinates Mode Warning " ) , " ExtrudeCoordsWarning " ) ;
Info . ConfirmText = LOCTEXT ( " Close " , " Close " ) ;
FSuppressableWarningDialog WarnAboutCoordinatesSystem ( Info ) ;
WarnAboutCoordinatesSystem . ShowModal ( ) ;
2014-06-18 10:16:16 -04:00
GLevelEditorModeTools ( ) . SetCoordSystem ( COORD_Local ) ;
2014-03-14 14:13:41 -04:00
}
}
void UGeomModifier_Extrude : : Initialize ( )
{
//the user may have changed the mode AFTER going into extrude - double check its LOCAL not WORLD
CheckCoordinatesMode ( ) ;
Apply ( GEditor - > GetGridSize ( ) , 1 ) ;
}
bool UGeomModifier_Extrude : : OnApply ( )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
// When applying via the keyboard, we force the local coordinate system.
const bool bGetRawValue = true ;
2014-06-18 10:16:16 -04:00
const ECoordSystem SaveCS = GLevelEditorModeTools ( ) . GetCoordSystem ( bGetRawValue ) ;
GLevelEditorModeTools ( ) . SetCoordSystem ( COORD_Local ) ;
2014-03-14 14:13:41 -04:00
//GApp->DlgGeometryTools->PropertyWindow->FinalizeValues();
Apply ( Length , Segments ) ;
// Restore the coordinate system.
2014-06-18 10:16:16 -04:00
GLevelEditorModeTools ( ) . SetCoordSystem ( SaveCS ) ;
2014-03-14 14:13:41 -04:00
GEditor - > RebuildAlteredBSP ( ) ; // Brush has been altered, update the Bsp
2015-08-21 09:54:19 -04:00
bPendingPivotOffsetUpdate = true ;
2015-07-27 12:49:14 -04:00
2014-03-14 14:13:41 -04:00
return true ;
}
void ExtrudePolygonGroup ( ABrush * InBrush , FVector InGroupNormal , int32 InStartOffset , int32 InLength , TArray < FPoly > & InPolygonGroup )
{
TArray < TArray < FVector > > Windings ;
FPoly : : GetOutsideWindings ( InBrush , InPolygonGroup , Windings ) ;
for ( int32 w = 0 ; w < Windings . Num ( ) ; + + w )
{
TArray < FVector > * WindingVerts = & Windings [ w ] ;
FVector Offset = InGroupNormal * InLength ;
FVector StartOffset = InGroupNormal * InStartOffset ;
for ( int32 v = 0 ; v < WindingVerts - > Num ( ) ; + + v )
{
FVector vtx0 = StartOffset + ( * WindingVerts ) [ v ] ;
FVector vtx1 = StartOffset + ( * WindingVerts ) [ v ] + Offset ;
FVector vtx2 = StartOffset + ( * WindingVerts ) [ ( v + 1 ) % WindingVerts - > Num ( ) ] + Offset ;
FVector vtx3 = StartOffset + ( * WindingVerts ) [ ( v + 1 ) % WindingVerts - > Num ( ) ] ;
FPoly NewPoly ;
NewPoly . Init ( ) ;
NewPoly . Base = InBrush - > GetActorLocation ( ) ;
NewPoly . Vertices . Add ( vtx1 ) ;
NewPoly . Vertices . Add ( vtx0 ) ;
NewPoly . Vertices . Add ( vtx3 ) ;
NewPoly . Vertices . Add ( vtx2 ) ;
if ( NewPoly . Finalize ( InBrush , 1 ) = = 0 )
{
InBrush - > Brush - > Polys - > Element . Add ( NewPoly ) ;
}
}
}
}
void UGeomModifier_Extrude : : Apply ( int32 InLength , int32 InSegments )
{
2014-06-18 10:16:16 -04:00
if ( ! GLevelEditorModeTools ( ) . IsModeActive ( FBuiltinEditorModes : : EM_Geometry ) )
2014-03-14 14:13:41 -04:00
{
return ;
}
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
// Force user input to be valid
InLength = FMath : : Max ( 1 , InLength ) ;
InSegments = FMath : : Max ( 1 , InSegments ) ;
//
TArray < int32 > SavedSelectionIndices ;
for ( FEdModeGeometry : : TGeomObjectIterator Itor ( mode - > GeomObjectItor ( ) ) ; Itor ; + + Itor )
{
2015-04-02 16:34:30 -04:00
FGeomObjectPtr go = * Itor ;
2014-03-14 14:13:41 -04:00
ABrush * Brush = go - > GetActualBrush ( ) ;
go - > SendToSource ( ) ;
TArray < FPoly > Polygons ;
for ( int32 p = 0 ; p < go - > PolyPool . Num ( ) ; + + p )
{
FGeomPoly * gp = & go - > PolyPool [ p ] ;
2015-09-23 04:29:14 -04:00
FVector Normal = Brush - > GetActorQuat ( ) . Inverse ( ) . RotateVector ( mode - > GetWidgetNormalFromCurrentAxis ( gp ) ) ;
2014-03-14 14:13:41 -04:00
if ( gp - > IsSelected ( ) )
{
SavedSelectionIndices . Add ( p ) ;
FPoly * Poly = gp - > GetActualPoly ( ) ;
Polygons . Add ( * Poly ) ;
// Move the existing poly along the normal by InLength units.
for ( int32 v = 0 ; v < Poly - > Vertices . Num ( ) ; + + v )
{
FVector * vtx = & Poly - > Vertices [ v ] ;
* vtx + = Normal * ( InLength * InSegments ) ;
}
Poly - > Base + = Normal * ( InLength * InSegments ) ;
}
}
if ( Polygons . Num ( ) )
{
struct FCompareFPolyNormal
{
FORCEINLINE bool operator ( ) ( const FPoly & A , const FPoly & B ) const
{
2015-09-06 12:42:18 -04:00
return ( B . Normal - A . Normal ) . SizeSquared ( ) < 0.f ;
2014-03-14 14:13:41 -04:00
}
} ;
Polygons . Sort ( FCompareFPolyNormal ( ) ) ;
FVector NormalCompare ;
TArray < FPoly > PolygonGroup ;
for ( int32 p = 0 ; p < Polygons . Num ( ) ; + + p )
{
FPoly * Poly = & Polygons [ p ] ;
if ( p = = 0 )
{
NormalCompare = Poly - > Normal ;
}
if ( NormalCompare . Equals ( Poly - > Normal ) )
{
PolygonGroup . Add ( * Poly ) ;
}
else
{
if ( PolygonGroup . Num ( ) )
{
for ( int32 s = 0 ; s < InSegments ; + + s )
{
ExtrudePolygonGroup ( Brush , NormalCompare , InLength * s , InLength , PolygonGroup ) ;
}
}
NormalCompare = Poly - > Normal ;
PolygonGroup . Empty ( ) ;
PolygonGroup . Add ( * Poly ) ;
}
}
if ( PolygonGroup . Num ( ) )
{
for ( int32 s = 0 ; s < InSegments ; + + s )
{
ExtrudePolygonGroup ( Brush , NormalCompare , InLength * s , InLength , PolygonGroup ) ;
}
}
}
go - > FinalizeSourceData ( ) ;
go - > GetFromSource ( ) ;
for ( int32 x = 0 ; x < SavedSelectionIndices . Num ( ) ; + + x )
{
FGeomPoly * Poly = & go - > PolyPool [ SavedSelectionIndices [ x ] ] ;
Poly - > Select ( 1 ) ;
}
}
}
2014-10-14 10:29:11 -04:00
UGeomModifier_Lathe : : UGeomModifier_Lathe ( const FObjectInitializer & ObjectInitializer )
: Super ( ObjectInitializer )
2014-03-14 14:13:41 -04:00
{
Description = NSLOCTEXT ( " UnrealEd " , " Lathe " , " Lathe " ) ;
2015-02-18 10:58:17 -05:00
Tooltip = NSLOCTEXT ( " UnrealEd.GeomModifier_Lathe " , " Tooltip " , " Create new geometry by rotating the selected brush shape about the current pivot point. " ) ;
2014-03-14 14:13:41 -04:00
Axis = EAxis : : Y ;
TotalSegments = 16 ;
Segments = 4 ;
AlignToSide = false ;
}
bool UGeomModifier_Lathe : : Supports ( )
{
// Lathe mode requires ABrushShape actors to be selected.
for ( FSelectionIterator It ( GEditor - > GetSelectedActorIterator ( ) ) ; It ; + + It )
{
ABrush * Brush = Cast < ABrush > ( * It ) ;
if ( Brush & & Brush - > IsBrushShape ( ) )
{
return true ;
}
}
return false ;
}
void UGeomModifier_Lathe : : Initialize ( )
{
}
bool UGeomModifier_Lathe : : OnApply ( )
{
2014-06-18 10:16:16 -04:00
//FEdModeGeometry* mode = (FEdModeGeometry*)GLevelEditorModeTools().GetCurrentMode();
2014-03-14 14:13:41 -04:00
//GApp->DlgGeometryTools->PropertyWindow->FinalizeValues();
Apply ( TotalSegments , Segments , Axis ) ;
GEditor - > RebuildAlteredBSP ( ) ; // Brush has been altered, update the Bsp
2015-08-21 09:54:19 -04:00
bPendingPivotOffsetUpdate = true ;
2014-03-14 14:13:41 -04:00
return true ;
}
void UGeomModifier_Lathe : : Apply ( int32 InTotalSegments , int32 InSegments , EAxis : : Type InAxis )
{
2014-06-18 10:16:16 -04:00
if ( ! GLevelEditorModeTools ( ) . IsModeActive ( FBuiltinEditorModes : : EM_Geometry ) )
2014-03-14 14:13:41 -04:00
{
return ;
}
// Determine the axis from the active ortho viewport
if ( ! GLastKeyLevelEditingViewportClient | | ! GLastKeyLevelEditingViewportClient - > IsOrtho ( ) )
{
return ;
}
//Save the brush state in case a bogus shape is generated
CacheBrushState ( ) ;
switch ( GLastKeyLevelEditingViewportClient - > ViewportType )
{
case LVT_OrthoXZ :
Axis = EAxis : : X ;
break ;
case LVT_OrthoXY :
Axis = EAxis : : Y ;
break ;
case LVT_OrthoYZ :
Axis = EAxis : : Z ;
break ;
}
2014-06-18 10:16:16 -04:00
FEdModeGeometry * GeomMode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
InTotalSegments = FMath : : Max ( 3 , InTotalSegments ) ;
InSegments = FMath : : Max ( 1 , InSegments ) ;
if ( InSegments > InTotalSegments )
{
InTotalSegments = InSegments ;
}
// We will be replacing the builder brush, so get it prepped.
2014-06-12 04:17:47 -04:00
ABrush * BuilderBrush = GeomMode - > GetWorld ( ) - > GetDefaultBrush ( ) ;
2014-03-14 14:13:41 -04:00
BuilderBrush - > SetActorLocation ( GeomMode - > GetWidgetLocation ( ) , false ) ;
2015-07-07 03:41:52 -04:00
BuilderBrush - > SetPivotOffset ( FVector : : ZeroVector ) ;
2014-03-14 14:13:41 -04:00
BuilderBrush - > SetFlags ( RF_Transactional ) ;
BuilderBrush - > Brush - > Polys - > Element . Empty ( ) ;
// Ensure the builder brush is unhidden.
BuilderBrush - > bHidden = false ;
BuilderBrush - > bHiddenEdLayer = false ;
BuilderBrush - > SetIsTemporarilyHiddenInEditor ( false ) ;
// Some convenience flags
bool bNeedCaps = ( InSegments < InTotalSegments ) ;
// Lathe every selected ABrushShape actor into the builder brush
for ( FSelectionIterator It ( GEditor - > GetSelectedActorIterator ( ) ) ; It ; + + It )
{
TArray < FEdge > EdgePool ;
ABrushShape * BrushShape = Cast < ABrushShape > ( * It ) ;
if ( BrushShape )
{
if ( BrushShape - > Brush - > Polys - > Element . Num ( ) < 1 )
{
continue ;
}
TArray < TArray < FVector > > Windings ;
FPoly : : GetOutsideWindings ( BrushShape , BrushShape - > Brush - > Polys - > Element , Windings ) ;
FVector delta = GeomMode - > GetWidgetLocation ( ) - BrushShape - > GetActorLocation ( ) ;
//
// Let's lathe...
//
// Build up an array of vertices that represents the entire lathe.
float AngleStep = 360.f / ( float ) InTotalSegments ;
float Angle = 0 ;
for ( int32 w = 0 ; w < Windings . Num ( ) ; + + w )
{
TArray < FVector > * WindingVerts = & Windings [ w ] ;
TArray < FVector > ShapeVertices ;
for ( int32 s = 0 ; s < ( InSegments + 1 + ( AlignToSide ? 1 : 0 ) ) ; + + s )
{
FRotator rot = FRotator ( 0 , Angle , 0 ) ;
if ( Axis = = EAxis : : X )
{
rot = FRotator ( Angle , 0 , 0 ) ;
}
else if ( Axis = = EAxis : : Z )
{
rot = FRotator ( 0 , 0 , Angle ) ;
}
FRotationMatrix RotationMatrix ( rot ) ;
for ( int32 e = 0 ; e < WindingVerts - > Num ( ) ; + + e )
{
2015-07-07 03:41:52 -04:00
FVector vtx = ( * WindingVerts ) [ e ] - delta - BrushShape - > GetPivotOffset ( ) ;
2014-03-14 14:13:41 -04:00
vtx = RotationMatrix . TransformPosition ( vtx ) ;
ShapeVertices . Add ( vtx ) ;
}
if ( AlignToSide & & ( s = = 0 | | s = = InSegments ) )
{
Angle + = AngleStep / 2.0f ;
}
else
{
Angle + = AngleStep ;
}
}
int32 NumVertsInShape = WindingVerts - > Num ( ) ;
for ( int32 s = 0 ; s < InSegments + ( AlignToSide ? 1 : 0 ) ; + + s )
{
int32 BaseIdx = s * WindingVerts - > Num ( ) ;
for ( int32 v = 0 ; v < NumVertsInShape ; + + v )
{
FVector vtx0 = ShapeVertices [ BaseIdx + v ] ;
FVector vtx1 = ShapeVertices [ BaseIdx + NumVertsInShape + v ] ;
FVector vtx2 = ShapeVertices [ BaseIdx + NumVertsInShape + ( ( v + 1 ) % NumVertsInShape ) ] ;
FVector vtx3 = ShapeVertices [ BaseIdx + ( ( v + 1 ) % NumVertsInShape ) ] ;
FPoly NewPoly ;
NewPoly . Init ( ) ;
NewPoly . Base = BuilderBrush - > GetActorLocation ( ) ;
NewPoly . Vertices . Add ( vtx0 ) ;
NewPoly . Vertices . Add ( vtx1 ) ;
NewPoly . Vertices . Add ( vtx2 ) ;
NewPoly . Vertices . Add ( vtx3 ) ;
if ( NewPoly . Finalize ( BuilderBrush , 1 ) = = 0 )
{
BuilderBrush - > Brush - > Polys - > Element . Add ( NewPoly ) ;
}
}
}
}
// Create start/end capping polygons if they are necessary
if ( bNeedCaps )
{
for ( int32 w = 0 ; w < Windings . Num ( ) ; + + w )
{
TArray < FVector > * WindingVerts = & Windings [ w ] ;
//
// Create the start cap
//
FPoly Poly ;
Poly . Init ( ) ;
Poly . Base = BrushShape - > GetActorLocation ( ) ;
// Add the verts from the shape
for ( int32 v = 0 ; v < WindingVerts - > Num ( ) ; + + v )
{
2015-07-07 03:41:52 -04:00
Poly . Vertices . Add ( ( * WindingVerts ) [ v ] - delta - BrushShape - > GetPivotOffset ( ) ) ;
2014-03-14 14:13:41 -04:00
}
Poly . Finalize ( BuilderBrush , 1 ) ;
// Break the shape down into convex shapes.
TArray < FPoly > Polygons ;
Poly . Triangulate ( BuilderBrush , Polygons ) ;
FPoly : : OptimizeIntoConvexPolys ( BuilderBrush , Polygons ) ;
// Add the resulting convex polygons into the brush
for ( int32 p = 0 ; p < Polygons . Num ( ) ; + + p )
{
2014-03-15 01:14:25 -04:00
FPoly Polygon = Polygons [ p ] ;
2014-03-14 14:13:41 -04:00
2014-03-15 01:14:25 -04:00
if ( Polygon . Finalize ( BuilderBrush , 1 ) = = 0 )
2014-03-14 14:13:41 -04:00
{
2014-03-15 01:14:25 -04:00
BuilderBrush - > Brush - > Polys - > Element . Add ( Polygon ) ;
2014-03-14 14:13:41 -04:00
}
}
//
// Create the end cap
//
Poly . Init ( ) ;
Poly . Base = BrushShape - > GetActorLocation ( ) ;
// Add the verts from the shape
FRotator rot = FRotator ( 0 , AngleStep * InSegments , 0 ) ;
if ( Axis = = EAxis : : X )
{
rot = FRotator ( AngleStep * InSegments , 0 , 0 ) ;
}
else if ( Axis = = EAxis : : Z )
{
rot = FRotator ( 0 , 0 , AngleStep * InSegments ) ;
}
FRotationMatrix RotationMatrix ( rot ) ;
for ( int32 v = 0 ; v < WindingVerts - > Num ( ) ; + + v )
{
2015-07-07 03:41:52 -04:00
Poly . Vertices . Add ( RotationMatrix . TransformPosition ( ( * WindingVerts ) [ v ] - delta - BrushShape - > GetPivotOffset ( ) ) ) ;
2014-03-14 14:13:41 -04:00
}
Poly . Finalize ( BuilderBrush , 1 ) ;
// Break the shape down into convex shapes.
Polygons . Empty ( ) ;
Poly . Triangulate ( BuilderBrush , Polygons ) ;
FPoly : : OptimizeIntoConvexPolys ( BuilderBrush , Polygons ) ;
// Add the resulting convex polygons into the brush
for ( int32 p = 0 ; p < Polygons . Num ( ) ; + + p )
{
2014-03-15 01:14:25 -04:00
FPoly Polygon = Polygons [ p ] ;
Polygon . Reverse ( ) ;
2014-03-14 14:13:41 -04:00
2014-03-15 01:14:25 -04:00
if ( Polygon . Finalize ( BuilderBrush , 1 ) = = 0 )
2014-03-14 14:13:41 -04:00
{
2014-03-15 01:14:25 -04:00
BuilderBrush - > Brush - > Polys - > Element . Add ( Polygon ) ;
2014-03-14 14:13:41 -04:00
}
}
}
}
}
}
// Finalize the builder brush
BuilderBrush - > Brush - > BuildBound ( ) ;
BuilderBrush - > ReregisterAllComponents ( ) ;
GeomMode - > FinalizeSourceData ( ) ;
GeomMode - > GetFromSource ( ) ;
GEditor - > SelectNone ( true , true ) ;
GEditor - > SelectActor ( BuilderBrush , true , true ) ;
if ( DoEdgesOverlap ( ) )
{ //Overlapping edges yielded an invalid brush state
RestoreBrushState ( ) ;
}
else
{
GEditor - > RedrawLevelEditingViewports ( true ) ;
}
// Create additive brush from builder brush
GEditor - > Exec ( GeomMode - > GetWorld ( ) , TEXT ( " BRUSH ADD SELECTNEWBRUSH " ) ) ;
// Deselect & hide builder brush
BuilderBrush - > SetIsTemporarilyHiddenInEditor ( true ) ;
GEditor - > SelectActor ( BuilderBrush , false , false ) ;
}
/*------------------------------------------------------------------------------
UGeomModifier_Pen
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2014-10-14 10:29:11 -04:00
UGeomModifier_Pen : : UGeomModifier_Pen ( const FObjectInitializer & ObjectInitializer )
: Super ( ObjectInitializer )
2014-03-14 14:13:41 -04:00
{
Description = NSLOCTEXT ( " UnrealEd " , " Pen " , " Pen " ) ;
2015-02-18 10:58:17 -05:00
Tooltip = NSLOCTEXT ( " UnrealEd.GeomModifier_Pen " , " Tooltip " , " Create new geometry by drawing the vertices directly into an orthographic viewport. Press space bar to place a vertex, and Enter to close the polygon. " ) ;
2014-03-14 14:13:41 -04:00
bCreateBrushShape = false ;
bAutoExtrude = true ;
ExtrudeDepth = 256 ;
bCreateConvexPolygons = true ;
}
/**
* Gives the modifier a chance to initialize it ' s internal state when activated .
*/
void UGeomModifier_Pen : : WasActivated ( )
{
ShapeVertices . Empty ( ) ;
}
/**
* Implements the modifier application .
*/
bool UGeomModifier_Pen : : OnApply ( )
{
Apply ( ) ;
2015-08-21 09:54:19 -04:00
bPendingPivotOffsetUpdate = true ;
2014-03-14 14:13:41 -04:00
return true ;
}
void UGeomModifier_Pen : : Apply ( )
{
if ( ShapeVertices . Num ( ) > 2 )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * GeomMode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-06-12 04:17:47 -04:00
ABrush * ResultingBrush = GeomMode - > GetWorld ( ) - > GetDefaultBrush ( ) ;
ABrush * BuilderBrush = GeomMode - > GetWorld ( ) - > GetDefaultBrush ( ) ;
2014-03-14 14:13:41 -04:00
// Move all the vertices that the user placed to the same "height" as the builder brush, based on
// viewport orientation. This is preferable to always creating the new builder brush at height zero.
for ( int32 v = 0 ; v < ShapeVertices . Num ( ) ; + + v )
{
FVector * vtx = & ShapeVertices [ v ] ;
switch ( GLastKeyLevelEditingViewportClient - > ViewportType )
{
case LVT_OrthoXY :
vtx - > Z = BuilderBrush - > GetActorLocation ( ) . Z ;
break ;
case LVT_OrthoXZ :
vtx - > Y = BuilderBrush - > GetActorLocation ( ) . Y ;
break ;
case LVT_OrthoYZ :
vtx - > X = BuilderBrush - > GetActorLocation ( ) . X ;
break ;
}
}
// Generate center location from the shape's center
2014-09-29 04:23:44 -04:00
FBox WorldBounds ( ShapeVertices . GetData ( ) , ShapeVertices . Num ( ) ) ;
2014-03-14 14:13:41 -04:00
FVector BaseLocation = WorldBounds . GetCenter ( ) ;
//create a scoped transaction so that we can undo the creation/modification
const FScopedTransaction Transaction ( NSLOCTEXT ( " UnrealEd " , " BrushSet " , " Brush Set " ) ) ;
//if we are creating a brush we need to first create an actor for it
if ( bCreateBrushShape )
{
// Create a shape brush instead of modifying the builder brush
ResultingBrush = BuilderBrush - > GetWorld ( ) - > SpawnActor < ABrushShape > ( BaseLocation , FRotator : : ZeroRotator ) ;
ResultingBrush - > PreEditChange ( NULL ) ;
// It's OK to create an empty brush here as we are going to re-create the polys anyway.
FBSPOps : : csgCopyBrush ( ResultingBrush , BuilderBrush , PF_DefaultFlags , BuilderBrush - > GetFlags ( ) , true , true , true ) ;
ResultingBrush - > PostEditChange ( ) ;
}
else
{
ResultingBrush = FBSPOps : : csgAddOperation ( BuilderBrush , PF_DefaultFlags , Brush_Add ) ;
}
// Make sure the graphics engine isn't busy rendering this geometry before we go and modify it
FlushRenderingCommands ( ) ;
ResultingBrush - > SetActorLocation ( BaseLocation , false ) ;
2015-07-07 03:41:52 -04:00
ResultingBrush - > SetPivotOffset ( FVector : : ZeroVector ) ;
2014-03-14 14:13:41 -04:00
ResultingBrush - > SetFlags ( RF_Transactional ) ;
ResultingBrush - > Brush - > Polys - > Element . Empty ( ) ;
// Ensure the brush is unhidden.
ResultingBrush - > bHidden = false ;
ResultingBrush - > bHiddenEdLayer = false ;
ResultingBrush - > SetIsTemporarilyHiddenInEditor ( false ) ;
FPoly Poly ;
Poly . Init ( ) ;
Poly . Base = BaseLocation ;
for ( int32 v = 0 ; v < ShapeVertices . Num ( ) ; + + v )
{
new ( Poly . Vertices ) FVector ( ShapeVertices [ v ] - BaseLocation ) ;
}
if ( Poly . Finalize ( ResultingBrush , 1 ) = = 0 )
{
// Break the shape down into triangles.
TArray < FPoly > Triangles ;
Poly . Triangulate ( ResultingBrush , Triangles ) ;
TArray < FPoly > Polygons = Triangles ;
// Optionally, optimize the resulting triangles into convex polygons.
if ( bCreateConvexPolygons )
{
FPoly : : OptimizeIntoConvexPolys ( ResultingBrush , Polygons ) ;
}
// If the user isn't creating an ABrushShape, then carry on adding the sides and bottom face
// If the user wants a full brush created, add the rest of the polys
if ( ! bCreateBrushShape & & bAutoExtrude & & ExtrudeDepth > 0 )
{
// Extruding along delta
FVector HalfDelta ;
// Create another set of polygons that will represent the bottom face
for ( int32 p = 0 ; p < Polygons . Num ( ) ; + + p )
{
FPoly poly = Polygons [ p ] ;
if ( p = = 0 )
{
HalfDelta = 0.5f * poly . Normal * ExtrudeDepth ;
}
if ( poly . Finalize ( ResultingBrush , 0 ) = = 0 )
{
for ( int32 v = 0 ; v < poly . Vertices . Num ( ) ; + + v )
{
FVector * vtx = & poly . Vertices [ v ] ;
* vtx + = HalfDelta ;
}
new ( ResultingBrush - > Brush - > Polys - > Element ) FPoly ( poly ) ;
}
poly . Reverse ( ) ;
if ( poly . Finalize ( ResultingBrush , 0 ) = = 0 )
{
for ( int32 v = 0 ; v < poly . Vertices . Num ( ) ; + + v )
{
FVector * vtx = & poly . Vertices [ v ] ;
* vtx - = 2.0f * HalfDelta ;
}
new ( ResultingBrush - > Brush - > Polys - > Element ) FPoly ( poly ) ;
}
}
// Create the polygons that make up the sides of the brush
if ( Polygons . Num ( ) > 0 )
{
for ( int32 v = 0 ; v < ShapeVertices . Num ( ) ; + + v )
{
FVector vtx0 = ShapeVertices [ v ] + HalfDelta ;
FVector vtx1 = ShapeVertices [ ( v + 1 ) % ShapeVertices . Num ( ) ] + HalfDelta ;
FVector vtx2 = vtx1 - 2.0f * HalfDelta ;
FVector vtx3 = vtx0 - 2.0f * HalfDelta ;
FPoly SidePoly ;
SidePoly . Init ( ) ;
SidePoly . Vertices . Add ( vtx1 - BaseLocation ) ;
SidePoly . Vertices . Add ( vtx0 - BaseLocation ) ;
SidePoly . Vertices . Add ( vtx3 - BaseLocation ) ;
SidePoly . Vertices . Add ( vtx2 - BaseLocation ) ;
if ( SidePoly . Finalize ( ResultingBrush , 1 ) = = 0 )
{
new ( ResultingBrush - > Brush - > Polys - > Element ) FPoly ( SidePoly ) ;
}
}
}
}
else // not extruding a solid brush
{
// Now that we have a set of convex polygons, add them all to the brush. These will form the top face.
for ( int32 p = 0 ; p < Polygons . Num ( ) ; + + p )
{
if ( Polygons [ p ] . Finalize ( ResultingBrush , 0 ) = = 0 )
{
new ( ResultingBrush - > Brush - > Polys - > Element ) FPoly ( Polygons [ p ] ) ;
}
}
}
}
// Finish up
ResultingBrush - > Brush - > BuildBound ( ) ;
ResultingBrush - > ReregisterAllComponents ( ) ;
ShapeVertices . Empty ( ) ;
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
mode - > FinalizeSourceData ( ) ;
mode - > GetFromSource ( ) ;
GEditor - > SelectNone ( true , true ) ;
GEditor - > SelectActor ( ResultingBrush , true , true ) ;
// Switch back to edit mode
//FModeTool_GeometryModify* tool = (FModeTool_GeometryModify*)mode->GetCurrentTool();
//tool->SetCurrentModifier( tool->GetModifier(0) );
//force a rebuild of the brush (otherwise the auto-update will do it and this will result in the undo buffer being incorrect)
2015-04-16 11:45:01 -04:00
ABrush : : SetNeedRebuild ( ResultingBrush - > GetLevel ( ) ) ;
2014-03-14 14:13:41 -04:00
FBSPOps : : RebuildBrush ( ResultingBrush - > Brush ) ;
2015-04-16 11:45:01 -04:00
GEditor - > RebuildAlteredBSP ( ) ;
2014-03-14 14:13:41 -04:00
GEditor - > RedrawLevelEditingViewports ( true ) ;
}
}
2015-01-12 11:19:13 -05:00
#if 0
static bool DoesFinalLineIntersectWithShape ( const TArray < FVector > & Vertices , const FVector & FinalVertex )
{
// TODO: improve this, it often fails.
// Determine if the next line segment would intersect with any of the previous ones in the shape
for ( int32 Index = 0 ; Index < Vertices . Num ( ) - 1 ; Index + + )
{
const FVector & Segment1Start = Vertices [ Index ] ;
const FVector & Segment1End = Vertices [ Index + 1 ] ;
const FVector & Segment2Start = Vertices [ Vertices . Num ( ) - 1 ] ;
const FVector & Segment2End = FinalVertex ;
// Check that the two line segments are coplanar
check ( FMath : : IsNearlyZero ( FVector : : DotProduct ( Segment2Start - Segment1Start , FVector : : CrossProduct ( Segment1End - Segment1Start , Segment2End - Segment2Start ) ) ) ) ;
FVector Segment1Result ;
FVector Segment2Result ;
FMath : : SegmentDistToSegmentSafe ( Segment1Start , Segment1End , Segment2Start , Segment2End , Segment1Result , Segment2Result ) ;
if ( Segment1Result . Equals ( Segment2Result ) & & ! Segment1Result . Equals ( Segment1Start ) & & ! Segment1Result . Equals ( Segment1End ) )
{
return true ;
}
}
return false ;
}
# endif
static bool DoLineSegmentsIntersect ( const FVector2D & Segment1Start , const FVector2D & Segment1End , const FVector2D & Segment2Start , const FVector2D & Segment2End )
{
const FVector2D Segment1Dir = Segment1End - Segment1Start ;
const FVector2D Segment2Dir = Segment2End - Segment2Start ;
const float Determinant = FVector2D : : CrossProduct ( Segment1Dir , Segment2Dir ) ;
if ( ! FMath : : IsNearlyZero ( Determinant ) )
{
const FVector2D SegmentStartDelta = Segment2Start - Segment1Start ;
const float OneOverDet = 1.0f / Determinant ;
const float Seg1Intersection = FVector2D : : CrossProduct ( SegmentStartDelta , Segment2Dir ) * OneOverDet ;
const float Seg2Intersection = FVector2D : : CrossProduct ( SegmentStartDelta , Segment1Dir ) * OneOverDet ;
const float Epsilon = 1 / 128.0f ;
return ( Seg1Intersection > Epsilon & & Seg1Intersection < 1.0f - Epsilon & & Seg2Intersection > Epsilon & & Seg2Intersection < 1.0f - Epsilon ) ;
}
return false ;
}
/**
* Given an array of points forming an unclosed polygon , determines whether a line segment formed from the final polygon vertex and a given endpoint
* intersects with any edge of the polygon in the 2 D plane in which both segments lie .
*
* @ param Vertices Array of vertices forming unclosed polygon
* @ param EndVertex Endpoint of line segment starting from final point of polygon
*/
static bool DoesFinalLineIntersectWithShape ( const TArray < FVector > & Vertices , const FVector & EndVertex )
{
// Can't intersect if there are fewer than 2 vertices
if ( Vertices . Num ( ) < 2 )
{
return false ;
}
// All line segments in the polygon ought to be coplanar. Hence the problem can be reduced to detecting intersections of line segments
// projected onto their common plane, using 2D coordinates.
// Line segment 1 is the line to test against the rest of the shape
const FVector & Segment1Start = Vertices [ Vertices . Num ( ) - 1 ] ;
const FVector & Segment1End = EndVertex ;
const FVector Segment1Dir = Segment1End - Segment1Start ;
const float Segment1Len = Segment1Dir . Size ( ) ;
if ( FMath : : IsNearlyZero ( Segment1Len ) )
{
// Treat zero length line segments as non-intersecting
return false ;
}
// The direction of segment 1 on the plane will provide the X axis of the 2D basis on the plane
const FVector ProjectedXAxis = Segment1Dir / Segment1Len ;
for ( int32 Index = 0 ; Index < Vertices . Num ( ) - 1 ; Index + + )
{
// Line segment 2 is each edge of the shape
const FVector & Segment2Start = Vertices [ Index ] ;
const FVector & Segment2End = Vertices [ Index + 1 ] ;
const FVector Segment2Dir = Segment2End - Segment2Start ;
const FVector SegmentStartDelta = Segment2Start - Segment1Start ;
// If line segments 1 and 2 are coplanar, the plane normal will be shared, and be calculated from a cross product of their two directions
FVector PlaneNormal = FVector : : CrossProduct ( Segment1Dir , Segment2Dir ) ;
// Check that they are indeed coplanar
const bool bIsCoplanar = FMath : : IsNearlyZero ( FVector : : DotProduct ( SegmentStartDelta , PlaneNormal ) ) ;
if ( ! bIsCoplanar )
{
// Non-coplanar line segments can't possibly intersect (ignoring the case of coincident start/end points)
return false ;
}
// Parallel line segments will have yielded a zero normal. Attempt to calculate it from the segment start delta.
// If the lines are coincident, this will also yield a zero normal, resulting in a 1D basis (which is still sufficient to detect segment overlaps in projection space).
const bool bParallel = ( FMath : : IsNearlyZero ( PlaneNormal . SizeSquared ( ) ) ) ;
if ( bParallel )
{
PlaneNormal = FVector : : CrossProduct ( Segment1Dir , SegmentStartDelta ) ;
}
// Get the Y axis of the 2D basis from the X axis and the plane normal
const FVector ProjectedYAxis = FVector : : CrossProduct ( PlaneNormal . GetSafeNormal ( ) , ProjectedXAxis ) ;
// Project 3d points onto plane
const FVector2D ProjectedSegment1Start ( 0.0f , 0.0f ) ;
const FVector2D ProjectedSegment1End ( Segment1Len , 0.0f ) ;
const FVector2D ProjectedSegment2Start ( FVector : : DotProduct ( ProjectedXAxis , SegmentStartDelta ) , FVector : : DotProduct ( ProjectedYAxis , SegmentStartDelta ) ) ;
const FVector2D ProjectedSegment2End ( FVector : : DotProduct ( ProjectedXAxis , Segment2End - Segment1Start ) , FVector : : DotProduct ( ProjectedYAxis , Segment2End - Segment1Start ) ) ;
// Now check intersection of 2d segments.
if ( DoLineSegmentsIntersect ( ProjectedSegment1Start , ProjectedSegment1End , ProjectedSegment2Start , ProjectedSegment2End ) )
{
return true ;
}
}
return false ;
}
2014-03-14 14:13:41 -04:00
/**
* @ return true if the key was handled by this editor mode tool .
*/
2014-06-18 10:16:16 -04:00
bool UGeomModifier_Pen : : InputKey ( FEditorViewportClient * ViewportClient , FViewport * Viewport , FKey Key , EInputEvent Event )
2014-03-14 14:13:41 -04:00
{
bool bResult = false ;
# if WITH_EDITORONLY_DATA
if ( ViewportClient - > IsOrtho ( ) & & Event = = IE_Pressed )
{
const bool bCtrlDown = Viewport - > KeyState ( EKeys : : LeftControl ) | | Viewport - > KeyState ( EKeys : : RightControl ) ;
const bool bShiftDown = Viewport - > KeyState ( EKeys : : LeftShift ) | | Viewport - > KeyState ( EKeys : : RightShift ) ;
const bool bAltDown = Viewport - > KeyState ( EKeys : : LeftAlt ) | | Viewport - > KeyState ( EKeys : : RightAlt ) ;
// CTRL+RightClick (or SPACE bar) adds a vertex to the world
if ( ( bCtrlDown & & ! bShiftDown & & ! bAltDown & & Key = = EKeys : : RightMouseButton ) | | Key = = EKeys : : SpaceBar )
{
// if we're trying to edit vertices in a different viewport to the one we started in then popup a warning
if ( ShapeVertices . Num ( ) & & ViewportClient ! = UsingViewportClient )
{
FMessageDialog : : Open ( EAppMsgType : : Ok , NSLOCTEXT ( " UnrealEd " , " GeomModifierPen_Warning_AddingVertexInWrongViewport " , " Vertices can only be added to one viewport at a time. " ) ) ;
return true ;
}
if ( ShapeVertices . Num ( ) & & MouseWorldSpacePos . Equals ( ShapeVertices [ 0 ] ) )
{
2015-01-12 11:19:13 -05:00
if ( ! DoesFinalLineIntersectWithShape ( ShapeVertices , ShapeVertices [ 0 ] ) )
{
Apply ( ) ;
bResult = true ;
}
2014-03-14 14:13:41 -04:00
}
else
{
2015-01-12 11:19:13 -05:00
if ( ! DoesFinalLineIntersectWithShape ( ShapeVertices , MouseWorldSpacePos ) )
{
UsingViewportClient = ViewportClient ;
ShapeVertices . Add ( MouseWorldSpacePos ) ;
bResult = true ;
}
2014-03-14 14:13:41 -04:00
}
}
else if ( Key = = EKeys : : Escape | | Key = = EKeys : : BackSpace )
{
if ( ShapeVertices . Num ( ) )
{
ShapeVertices . RemoveAt ( ShapeVertices . Num ( ) - 1 ) ;
}
bResult = true ;
}
else if ( Key = = EKeys : : Enter )
{
2015-04-16 11:45:01 -04:00
if ( ShapeVertices . Num ( ) > 0 & & ! DoesFinalLineIntersectWithShape ( ShapeVertices , ShapeVertices [ 0 ] ) )
2015-01-12 11:19:13 -05:00
{
Apply ( ) ;
bResult = true ;
}
2014-03-14 14:13:41 -04:00
}
}
if ( bResult )
{
GEditor - > RedrawLevelEditingViewports ( true ) ;
}
# endif // WITH_EDITORONLY_DATA
return bResult ;
}
void UGeomModifier_Pen : : Render ( const FSceneView * View , FViewport * Viewport , FPrimitiveDrawInterface * PDI )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
FModeTool_GeometryModify * tool = ( FModeTool_GeometryModify * ) mode - > GetCurrentTool ( ) ;
if ( tool - > GetCurrentModifier ( ) ! = this )
{
return ;
}
// Only draw in ortho viewports
2014-06-18 10:16:16 -04:00
if ( ! ( ( FEditorViewportClient * ) ( Viewport - > GetClient ( ) ) ) - > IsOrtho ( ) )
2014-03-14 14:13:41 -04:00
{
return ;
}
FLinearColor Color = bCreateBrushShape ? GEngine - > C_BrushShape : GEngine - > C_BrushWire ;
// If we have more than 2 vertices placed, connect them with lines
if ( ShapeVertices . Num ( ) > 1 )
{
for ( int32 v = 0 ; v < ShapeVertices . Num ( ) - 1 ; + + v )
{
PDI - > DrawLine ( ShapeVertices [ v ] , ShapeVertices [ v + 1 ] , Color , SDPG_Foreground ) ;
}
}
// Draw vertices for each point the user has put down
for ( int32 v = 0 ; v < ShapeVertices . Num ( ) ; + + v )
{
PDI - > DrawPoint ( ShapeVertices [ v ] , Color , 6.f , SDPG_Foreground ) ;
}
if ( ShapeVertices . Num ( ) )
{
2015-01-12 11:19:13 -05:00
if ( ! DoesFinalLineIntersectWithShape ( ShapeVertices , MouseWorldSpacePos ) )
{
// Draw a dashed line from the last placed vertex to the current mouse position
DrawDashedLine ( PDI , ShapeVertices [ ShapeVertices . Num ( ) - 1 ] , MouseWorldSpacePos , FLinearColor ( 1 , 0.5f , 0 ) , GEditor - > GetGridSize ( ) , SDPG_Foreground ) ;
}
2014-03-14 14:13:41 -04:00
}
if ( ShapeVertices . Num ( ) > 2 )
{
2015-01-12 11:19:13 -05:00
if ( ! DoesFinalLineIntersectWithShape ( ShapeVertices , ShapeVertices [ 0 ] ) )
{
// Draw a darkened dashed line to show what the completed shape will look like
DrawDashedLine ( PDI , ShapeVertices [ ShapeVertices . Num ( ) - 1 ] , ShapeVertices [ 0 ] , FLinearColor ( .5 , 0 , 0 ) , GEditor - > GetGridSize ( ) , SDPG_Foreground ) ;
}
2014-03-14 14:13:41 -04:00
}
// Draw a box where the next vertex will be placed
int32 BoxSz = FMath : : Max ( GEditor - > GetGridSize ( ) / 2 , 1.f ) ;
DrawWireBox ( PDI , FBox : : BuildAABB ( MouseWorldSpacePos , FVector ( BoxSz , BoxSz , BoxSz ) ) , FLinearColor ( 1 , 1 , 1 ) , SDPG_Foreground ) ;
}
2014-06-18 10:16:16 -04:00
void UGeomModifier_Pen : : DrawHUD ( FEditorViewportClient * ViewportClient , FViewport * Viewport , const FSceneView * View , FCanvas * Canvas )
2014-03-14 14:13:41 -04:00
{
}
2014-06-18 10:16:16 -04:00
void UGeomModifier_Pen : : Tick ( FEditorViewportClient * ViewportClient , float DeltaTime )
2014-03-14 14:13:41 -04:00
{
if ( GCurrentLevelEditingViewportClient = = ViewportClient )
{
FVector NewMouseWorldSpacePos = ComputeWorldSpaceMousePos ( ViewportClient ) ;
// If the grid is enabled, figure out where the nearest grid location is to the mouse cursor
if ( GetDefault < ULevelEditorViewportSettings > ( ) - > GridEnabled )
{
NewMouseWorldSpacePos = NewMouseWorldSpacePos . GridSnap ( GEditor - > GetGridSize ( ) ) ;
}
// If the mouse position has moved, update the viewport
if ( NewMouseWorldSpacePos ! = MouseWorldSpacePos )
{
MouseWorldSpacePos = NewMouseWorldSpacePos ;
GEditor - > RedrawLevelEditingViewports ( true ) ;
}
}
}
/*------------------------------------------------------------------------------
UGeomModifier_Clip
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
namespace GeometryClipping {
/**
* Creates a giant brush aligned with this plane .
*
* @ param OutGiantBrush [ out ] The new brush .
* @ param InPlane Plane with which to align the brush .
*
* NOTE : it is up to the caller to set up the new brush upon return in regards to it ' s CSG operation and flags .
*/
static void BuildGiantAlignedBrush ( ABrush & OutGiantBrush , const FPlane & InPlane )
{
OutGiantBrush . SetActorLocation ( FVector : : ZeroVector , false ) ;
2015-07-07 03:41:52 -04:00
OutGiantBrush . SetPivotOffset ( FVector : : ZeroVector ) ;
2014-03-14 14:13:41 -04:00
verify ( OutGiantBrush . Brush ) ;
verify ( OutGiantBrush . Brush - > Polys ) ;
OutGiantBrush . Brush - > Polys - > Element . Empty ( ) ;
// Create a list of vertices that can be used for the new brush
FVector vtxs [ 8 ] ;
FPlane FlippedPlane = InPlane . Flip ( ) ;
FPoly TempPoly = FPoly : : BuildInfiniteFPoly ( FlippedPlane ) ;
TempPoly . Finalize ( & OutGiantBrush , 0 ) ;
vtxs [ 0 ] = TempPoly . Vertices [ 0 ] ;
vtxs [ 1 ] = TempPoly . Vertices [ 1 ] ;
vtxs [ 2 ] = TempPoly . Vertices [ 2 ] ;
vtxs [ 3 ] = TempPoly . Vertices [ 3 ] ;
FlippedPlane = FlippedPlane . Flip ( ) ;
FPoly TempPoly2 = FPoly : : BuildInfiniteFPoly ( FlippedPlane ) ;
vtxs [ 4 ] = TempPoly2 . Vertices [ 0 ] + ( TempPoly2 . Normal * - ( WORLD_MAX ) ) ; vtxs [ 5 ] = TempPoly2 . Vertices [ 1 ] + ( TempPoly2 . Normal * - ( WORLD_MAX ) ) ;
vtxs [ 6 ] = TempPoly2 . Vertices [ 2 ] + ( TempPoly2 . Normal * - ( WORLD_MAX ) ) ; vtxs [ 7 ] = TempPoly2 . Vertices [ 3 ] + ( TempPoly2 . Normal * - ( WORLD_MAX ) ) ;
// Create the polys for the new brush.
FPoly newPoly ;
// TOP
newPoly . Init ( ) ;
newPoly . Base = vtxs [ 0 ] ;
newPoly . Vertices . Add ( vtxs [ 0 ] ) ;
newPoly . Vertices . Add ( vtxs [ 1 ] ) ;
newPoly . Vertices . Add ( vtxs [ 2 ] ) ;
newPoly . Vertices . Add ( vtxs [ 3 ] ) ;
newPoly . Finalize ( & OutGiantBrush , 0 ) ;
new ( OutGiantBrush . Brush - > Polys - > Element ) FPoly ( newPoly ) ;
// BOTTOM
newPoly . Init ( ) ;
newPoly . Base = vtxs [ 4 ] ;
newPoly . Vertices . Add ( vtxs [ 4 ] ) ;
newPoly . Vertices . Add ( vtxs [ 5 ] ) ;
newPoly . Vertices . Add ( vtxs [ 6 ] ) ;
newPoly . Vertices . Add ( vtxs [ 7 ] ) ;
newPoly . Finalize ( & OutGiantBrush , 0 ) ;
new ( OutGiantBrush . Brush - > Polys - > Element ) FPoly ( newPoly ) ;
// SIDES
// 1
newPoly . Init ( ) ;
newPoly . Base = vtxs [ 1 ] ;
newPoly . Vertices . Add ( vtxs [ 1 ] ) ;
newPoly . Vertices . Add ( vtxs [ 0 ] ) ;
newPoly . Vertices . Add ( vtxs [ 7 ] ) ;
newPoly . Vertices . Add ( vtxs [ 6 ] ) ;
newPoly . Finalize ( & OutGiantBrush , 0 ) ;
new ( OutGiantBrush . Brush - > Polys - > Element ) FPoly ( newPoly ) ;
// 2
newPoly . Init ( ) ;
newPoly . Base = vtxs [ 2 ] ;
newPoly . Vertices . Add ( vtxs [ 2 ] ) ;
newPoly . Vertices . Add ( vtxs [ 1 ] ) ;
newPoly . Vertices . Add ( vtxs [ 6 ] ) ;
newPoly . Vertices . Add ( vtxs [ 5 ] ) ;
newPoly . Finalize ( & OutGiantBrush , 0 ) ;
new ( OutGiantBrush . Brush - > Polys - > Element ) FPoly ( newPoly ) ;
// 3
newPoly . Init ( ) ;
newPoly . Base = vtxs [ 3 ] ;
newPoly . Vertices . Add ( vtxs [ 3 ] ) ;
newPoly . Vertices . Add ( vtxs [ 2 ] ) ;
newPoly . Vertices . Add ( vtxs [ 5 ] ) ;
newPoly . Vertices . Add ( vtxs [ 4 ] ) ;
newPoly . Finalize ( & OutGiantBrush , 0 ) ;
new ( OutGiantBrush . Brush - > Polys - > Element ) FPoly ( newPoly ) ;
// 4
newPoly . Init ( ) ;
newPoly . Base = vtxs [ 0 ] ;
newPoly . Vertices . Add ( vtxs [ 0 ] ) ;
newPoly . Vertices . Add ( vtxs [ 3 ] ) ;
newPoly . Vertices . Add ( vtxs [ 4 ] ) ;
newPoly . Vertices . Add ( vtxs [ 7 ] ) ;
newPoly . Finalize ( & OutGiantBrush , 0 ) ;
new ( OutGiantBrush . Brush - > Polys - > Element ) FPoly ( newPoly ) ;
// Finish creating the new brush.
OutGiantBrush . Brush - > BuildBound ( ) ;
}
/**
* Clips the specified brush against the specified plane .
*
* @ param InWorld World context
* @ param InPlane The plane to clip against .
* @ param InBrush The brush to clip .
* @ return The newly created brush representing the portion of the brush in the plane ' s positive halfspace .
*/
static ABrush * ClipBrushAgainstPlane ( const FPlane & InPlane , ABrush * InBrush )
{
UWorld * World = InBrush - > GetWorld ( ) ;
ULevel * BrushLevel = InBrush - > GetLevel ( ) ;
// Create a giant brush in the level of the source brush to use in the intersection process.
ABrush * ClippedBrush = NULL ;
// When clipping non-builder brushes, create a duplicate of the brush
// to clip. This duplicate will replace the existing brush.
if ( ! FActorEditorUtils : : IsABuilderBrush ( InBrush ) )
{
// Select only the original brush to prevent other actors from being duplicated.
GEditor - > SelectNone ( false , true ) ;
GEditor - > SelectActor ( InBrush , true , false , false ) ;
// Duplicate the original brush. This will serve as our clipped brush.
GEditor - > edactDuplicateSelected ( BrushLevel , false ) ;
// Clipped brush should be the only selected
// actor if the duplication didn't fail.
ClippedBrush = GEditor - > GetSelectedActors ( ) - > GetTop < ABrush > ( ) ;
}
// To clip the builder brush, instead of replacing it, spawn a
// temporary brush to clip. Then, copy that to the builder brush.
else
{
// NOTE: This brush is discarded later on after copying the values to the builder brush.
FActorSpawnParameters SpawnInfo ;
SpawnInfo . OverrideLevel = BrushLevel ;
SpawnInfo . Template = InBrush ;
ClippedBrush = World - > SpawnActor < ABrush > ( InBrush - > GetClass ( ) , SpawnInfo ) ;
check ( ClippedBrush ) ;
}
// It's possible that the duplication failed.
if ( ! ClippedBrush )
{
return NULL ;
}
// The brushes should have the same class otherwise
// perhaps there were additional brushes were selected.
check ( ClippedBrush - > GetClass ( ) = = InBrush - > GetClass ( ) ) ;
2015-04-01 14:56:26 -04:00
ClippedBrush - > Brush = NewObject < UModel > ( ClippedBrush , NAME_None , RF_Transactional ) ;
2015-01-30 08:30:03 -05:00
ClippedBrush - > Brush - > Initialize ( nullptr ) ;
2014-10-16 09:02:30 -04:00
ClippedBrush - > GetBrushComponent ( ) - > Brush = ClippedBrush - > Brush ;
2014-03-14 14:13:41 -04:00
GeometryClipping : : BuildGiantAlignedBrush ( * ClippedBrush , InPlane ) ;
ClippedBrush - > BrushType = InBrush - > BrushType ;
ClippedBrush - > SetFlags ( InBrush - > GetFlags ( ) ) ;
ClippedBrush - > PolyFlags = InBrush - > PolyFlags ;
// Create a BSP for the brush that is being clipped.
FBSPOps : : bspBuild ( InBrush - > Brush , FBSPOps : : BSP_Optimal , 15 , 70 , 1 , 0 ) ;
FBSPOps : : bspRefresh ( InBrush - > Brush , true ) ;
FBSPOps : : bspBuildBounds ( InBrush - > Brush ) ;
// Intersect the giant brush with the source brush's BSP. This will give us the finished, clipping brush
// contained inside of the giant brush.
2015-06-25 09:42:17 -04:00
ClippedBrush - > Modify ( ) ;
InBrush - > Brush - > Modify ( ) ;
2014-03-14 14:13:41 -04:00
GEditor - > bspBrushCSG ( ClippedBrush , InBrush - > Brush , 0 , Brush_MAX , CSG_Intersect , false , false , true ) ;
FBSPOps : : bspUnlinkPolys ( ClippedBrush - > Brush ) ;
// Remove all polygons on the giant brush that don't match the normal of the clipping plane
for ( int32 p = 0 ; p < ClippedBrush - > Brush - > Polys - > Element . Num ( ) ; + + p )
{
FPoly * P = & ClippedBrush - > Brush - > Polys - > Element [ p ] ;
if ( P - > Finalize ( ClippedBrush , 1 ) = = 0 )
{
if ( ! FPlane ( P - > Vertices [ 0 ] , P - > Normal ) . Equals ( InPlane , 0.01f ) )
{
ClippedBrush - > Brush - > Polys - > Element . RemoveAt ( p ) ;
p = - 1 ;
}
}
}
// The BSP "CSG_Intersect" code sometimes creates some nasty polygon fragments so clean those up here before going further.
FPoly : : OptimizeIntoConvexPolys ( ClippedBrush , ClippedBrush - > Brush - > Polys - > Element ) ;
// Clip each polygon in the original brush against the clipping plane. For every polygon that is behind the plane or split by it, keep the back portion.
FVector PlaneBase = FVector ( InPlane . X , InPlane . Y , InPlane . Z ) * InPlane . W ;
for ( int32 p = 0 ; p < InBrush - > Brush - > Polys - > Element . Num ( ) ; + + p )
{
FPoly Poly = InBrush - > Brush - > Polys - > Element [ p ] ;
FPoly front , back ;
2014-11-26 10:01:12 -05:00
int32 res = Poly . SplitWithPlane ( PlaneBase , InPlane . GetSafeNormal ( ) , & front , & back , true ) ;
2014-03-14 14:13:41 -04:00
switch ( res )
{
case SP_Back :
ClippedBrush - > Brush - > Polys - > Element . Add ( Poly ) ;
break ;
case SP_Split :
ClippedBrush - > Brush - > Polys - > Element . Add ( back ) ;
break ;
}
}
// At this point we have a clipped brush with optimized capping polygons so we can finish up by fixing it's ordering in the actor array and other misc things.
ClippedBrush - > CopyPosRotScaleFrom ( InBrush ) ;
ClippedBrush - > PolyFlags = InBrush - > PolyFlags ;
// Clean the brush up.
for ( int32 poly = 0 ; poly < ClippedBrush - > Brush - > Polys - > Element . Num ( ) ; poly + + )
{
FPoly * Poly = & ( ClippedBrush - > Brush - > Polys - > Element [ poly ] ) ;
Poly - > iLink = poly ;
Poly - > Normal = FVector : : ZeroVector ;
Poly - > Finalize ( ClippedBrush , 0 ) ;
}
// One final pass to clean the polyflags of all temporary settings.
for ( int32 poly = 0 ; poly < ClippedBrush - > Brush - > Polys - > Element . Num ( ) ; poly + + )
{
FPoly * Poly = & ( ClippedBrush - > Brush - > Polys - > Element [ poly ] ) ;
Poly - > PolyFlags & = ~ PF_EdCut ;
Poly - > PolyFlags & = ~ PF_EdProcessed ;
}
// Move the new brush to where the new brush was to preserve brush ordering.
2014-06-12 04:17:47 -04:00
ABrush * BuilderBrush = World - > GetDefaultBrush ( ) ;
2014-03-14 14:13:41 -04:00
if ( InBrush = = BuilderBrush )
{
// Special-case behavior for the builder brush.
// Copy the temporary brush back over onto the builder brush (keeping object flags)
BuilderBrush - > Modify ( ) ;
Copying //UE4/Dev-Core to //UE4/Dev-Main (Source: //UE4/Dev-Core @ 3620134)
#lockdown Nick.Penwarden
#rb none
============================
MAJOR FEATURES & CHANGES
============================
Change 3550452 by Ben.Marsh
UAT: Improve readability of error message when an editor commandlet fails with an error code.
Change 3551179 by Ben.Marsh
Add methods for reading text files into an array of strings.
Change 3551260 by Ben.Marsh
Core: Change FFileHelper routines to use enum classes for flags.
Change 3555697 by Gil.Gribb
Fixed a rare crash when the asset registry scanner found old cooked files with package level compression.
#jira UE-47668
Change 3556464 by Ben.Marsh
UGS: If working in a virtual stream, use the name of the first non-virtual ancestor for writing version files.
Change 3557630 by Ben.Marsh
Allow the network version to be set via Build.version if it's not overriden from Version.h.
Change 3561357 by Gil.Gribb
Fixed crashes related to loading old unversioned files in the editor.
#jira UE-47806
Change 3565711 by Graeme.Thornton
PR #3839: Make non-encoding specific Base64 functions accessible (Contributed by stfx)
Change 3565864 by Robert.Manuszewski
Temp fix for a race condition with the async loading thread enabled - caching the linker in case it gets removed (but not deleted) from super class object.
Change 3569022 by Ben.Marsh
PR #3849: Update gitignore (Contributed by mhutch)
Change 3569113 by Ben.Marsh
Fix Japanese errors not displaying correctly in the cook output log.
#jira UE-47746
Change 3569486 by Ben.Marsh
UGS: Always sync the Enterprise folder if the selected .uproject file has the "Enterprise" flag set.
Change 3570483 by Graeme.Thornton
Minor C# cleanups. Removing some redundant "using" calls which also cause dotnetcore compile errors
Change 3570513 by Robert.Manuszewski
Fix for a race condition with async loading thread enabled.
Change 3570664 by Ben.Marsh
UBT: Use P/Invoke to determine number of physical processors on Windows rather than using WMI. Starting up WMIC adds 2.5 seconds to build times, and is not compatible with .NET core.
Change 3570708 by Robert.Manuszewski
Added ENABLE_GC_OBJECT_CHECKS macro to be able to quickly toggle UObject pointer checks in shipping builds when the garbage collector is running.
Change 3571592 by Ben.Marsh
UBT: Allow running with -installed without creating [InstalledPlatforms] entries in BaseEngine.ini. If there is no HasInstalledPlatformInfo=true setting, assume that all platforms are still available.
Change 3572215 by Graeme.Thornton
UBT
- Remove some unnecessary using directives
- Point SN-DBS code at the new Utils.GetPhysicalProcessorCount call, rather than trying to calculate it itself
Change 3572437 by Robert.Manuszewski
Game-specific fix for lazy object pointer issues in one of the test levels. The previous fix had to be partially reverted due to side-effects.
#jira UE-44996
Change 3572480 by Robert.Manuszewski
MaterialInstanceCollections will no longer be added to GC clusters to prevent materials staying around in memory for too long
Change 3573547 by Ben.Marsh
Add support for displaying log timestamps in local time. Set LogTimes=Local in *Engine.ini, or pass -LocalLogTimes on the command line.
Change 3574562 by Robert.Manuszewski
PR #3847: Add GC callbacks for script integrations (Contributed by mhutch)
Change 3575017 by Ben.Marsh
Move some functions related to generating window resolutions out of Core (FParse::Resolution, GenerateConvenientWindowedResolutions). Also remove a few headers from shared PCHs prior to splitting application functionality out of Core.
Change 3575689 by Ben.Marsh
Add a fixed URL for opening the API documentation, so it works correctly in "internal" and "perforce" builds.
Change 3575934 by Steve.Robb
Fix for nested preprocessor definitions.
Change 3575961 by Steve.Robb
Fix for nested zeros.
Change 3576297 by Robert.Manuszewski
Material resources will now be discarded in PostLoad (Game Thread) instead of in Serialize (potentially Async Loading Thread) so that shader deregistration doesn't assert when done from a different thread than the game thread.
#jira FORT-38977
Change 3576366 by Ben.Marsh
Add shim functions to allow redirecting FPlatformMisc::ClipboardCopy()/ClipboardPaste() to FPlatformApplicationMisc::ClipboardCopy()/ClipboardPaste() while they are deprecated.
Change 3578290 by Graeme.Thornton
Changes to Ionic zip library to allow building on dot net core
Change 3578291 by Graeme.Thornton
Ionic zip library binaries built for .NET Core
Change 3578354 by Graeme.Thornton
Added FBase64::GetDecodedDataSize() to determine the size of bytes of a decoded base64 string
Change 3578674 by Robert.Manuszewski
After loading packages flush linker cache on uncooked platforms to free precache memory
Change 3579068 by Steve.Robb
Fix for CLASS_Intrinsic getting stomped.
Fix to EClassFlags so that they are visible in the debugger.
Re-added mysteriously-removed comments.
Change 3579228 by Steve.Robb
BOM removed.
Change 3579297 by Ben.Marsh
Fix exception if a plugin lists the same module twice.
#jira UE-48232
Change 3579898 by Robert.Manuszewski
When creating GC clusters and asserting due to objects still being pending load, the object name and cluster name will now be logged with the assert.
Change 3579983 by Robert.Manuszewski
More fixes for freeing linker cache memory in the editor.
Change 3580012 by Graeme.Thornton
Remove redundant copy of FileReference.cs
Change 3580408 by Ben.Marsh
Validate that arguments passed to the checkf macro are valid sprintf types, and fix up a few places which are currently incorrect.
Change 3582104 by Graeme.Thornton
Added a dynamic compilation path that uses the latest roslyn apis. Currently only used by the .NET Core path.
Change 3582131 by Graeme.Thornton
#define out some PerformanceCounter calls that don't exist in .NET Core. They're only used by mono-specific calls anyway.
Change 3582645 by Ben.Marsh
PR #3879: fix bug when creating a new VS2017 C++ project (Contributed by mnannola)
#jira UE-48192
Change 3583955 by Robert.Manuszewski
Support for EDL cooked packages in the editor
Change 3584035 by Graeme.Thornton
Split RunExternalExecutable into RunExternaNativelExecutable and RunExternalDotNETExecutable. When running under .NET Core, externally launched DotNET utilities must be launched via the 'dotnet' proxy to work correctly.
Change 3584177 by Robert.Manuszewski
Removed unused member variable (FArchiveAsync2::bKeepRestOfFilePrecached)
Change 3584315 by Ben.Marsh
Move Android JNI accessor functions into separate header, to decouple it from the FAndroidApplication class.
Change 3584370 by Ben.Marsh
Move hooks which allow platforms to load any modules into the FPlatformApplicationMisc classes.
Change 3584498 by Ben.Marsh
Move functions for getting and setting the hardware window pointer onto the appropriate platform window classes.
Change 3585003 by Steve.Robb
Fix for TChunkedArray ranged-for iteration.
#jira UE-48297
Change 3585235 by Ben.Marsh
Remove LogEngine extern from Core; use the platform log channels instead.
Change 3585942 by Ben.Marsh
Move MessageBoxExt() implementation into application layer for platforms that require it.
Change 3587071 by Ben.Marsh
Move Linux's UngrabAllInput() function into a callback, so DebugBreak still works without SDL.
Change 3587161 by Ben.Marsh
Remove headers which will be stripped out of the Core module from Core.h and PlatformIncludes.h.
Change 3587579 by Steve.Robb
Fix for Children list not being rebuilt after hot reload.
Change 3587584 by Graeme.Thornton
Logging improvements for pak signature check failures
- Added "PakCorrupt" console command which corrupts the master signature table
- Added some extra log information about which block failed
- Re-hash the master signature table and to make sure that it hasn't changed since startup
- Moved the ensure around so that some extra logging messages can make it out before the ensure is hit
- Added PAK_SIGNATURE_CHECK_FAILS_ARE_FATAL to IPlatformFilePak.h so we have a single place to make signature check failures fatal again
Change 3587586 by Graeme.Thornton
Changes to make UBT build and run on .NET Core
- Added *_DNC csproj files for DotNETUtilities and UnrealBuildTool projects which contain the .NET Core build setups
- VCSharpProjectFile can no be asked for the CsProjectInfo for a particular configuration, which is cached for future use
- After loading VCSharpProjectFiles, .NET Core based projects will be excluded unless generating VSCode projects
Change 3587953 by Steve.Robb
Allow arbitrary UENUM initializers for enumerators.
Editor-only data UENUM support.
Enumerators named MAX are now treated as the UENUM's maximum, and will not cause a MAX+1 value to be generated.
#jira UE-46274
Change 3589827 by Graeme.Thornton
More fixes for VSCode project generation and for UBT running on .NET Core
- Use a different file extension for rules assemblies when build on .NET Core, so they never get used by their counterparts
- UEConsoleTraceListener supports stdout/stderror constructor parameter and outputs to the appropriate channel
- Added documentation for UEConsoleTraceListener
- All platforms .NET project compilation tasks/launch configs now use "dotnet" and not the normal batch files
- Restored the default UBT log verbosity to "Log" rather than "VeryVeryVerbose"
- Renamed assemblies for .NETCore versions of DotNETUtilities and UnrealBuildTool so they don't conflict with the output of the existing .NET Desktop Framework stuff
Change 3589868 by Graeme.Thornton
Separate .NET Core projects for UBT and DotNETCommon out into their own directories so that their intermediates don't overlap with the standard .NET builds, causing failures.
UBT registers ONLY .NET Core C# projects when generating VSCode solutions, and ONLY standard C# projects in all other cases
Change 3589919 by Robert.Manuszewski
Fixing crash when cooking textures that have already been cooked for EDL (support for cooked content in the editor)
Change 3589940 by Graeme.Thornton
Force UBT to think it's running on mono when actually running on .NET Core. Disables a lot of windows specific code paths.
Change 3590078 by Graeme.Thornton
Fully disable automatic assembly info generation in .NET Core projects
Change 3590534 by Robert.Manuszewski
Marking UObject as intrinsic clas to fix a crash on UFE startup.
Change 3591498 by Gil.Gribb
UE4 - Fixed several edge cases in the low level async loading code, especially around cancellation. Also PakFileTest is a console command which can be used to stress test pak file loading.
Change 3591605 by Gil.Gribb
UE4 - Follow up to fixing several edge cases in the low level async loading code.
Change 3592577 by Graeme.Thornton
.NET Core C# projects now reference source files explicitly, to stop it accidentally compiling various intermediates
Change 3592684 by Steve.Robb
Fix for EObjectFlags being passed as the wrong argument to csgCopyBrush.
Change 3592710 by Steve.Robb
Fix for invalid casts in ListProps command.
Some name changes in command output.
Change 3592715 by Ben.Marsh
Move Windows event log code into cpp file, and expose it to other modules even if it's not enabled by default.
Change 3592767 by Gil.Gribb
UE4 - Changed the logic so that engine UObjects boot before anything else. The engine classes are known to be cycle-free, so we will get them done before moving onto game modules.
Change 3592770 by Gil.Gribb
UE4 - Fixed a race condition with async read completion in the prescence of cancels.
Change 3593090 by Steve.Robb
Better error message when there two clashing type names are found.
Change 3593697 by Steve.Robb
VisitTupleElements function, which calls a functor for each element in the tuple.
Change 3595206 by Ben.Marsh
Include additional diagnostics for missing imports when a module load fails.
Change 3596140 by Graeme.Thornton
Batch file for running MSBuild
Change 3596267 by Steve.Robb
Thread safety fix to FPaths::GetProjectFilePath().
Change 3596271 by Robert.Manuszewski
Added code to verify compression flags in package file summary to avoid cases where corrupt packages are crashing the editor
#jira UE-47535
Change 3596283 by Steve.Robb
Redundant casts removed from UHT.
Change 3596303 by Ben.Marsh
EC: Improve parsing of Android Clang errors and warnings, which are formatted as MSVC diagnostics to allow go-to-line clicking in the Output Window.
Change 3596337 by Ben.Marsh
UBT: Format messages about incorrect headers in a way that makes them clickable from Visual Studio.
Change 3596367 by Steve.Robb
Iterator checks in ranged-for on TMap, TSet and TSparseArray.
Change 3596410 by Gil.Gribb
UE4 - Improved some error messages on runtime failures in the EDL.
Change 3596532 by Ben.Marsh
UnrealVS: Fix setting command line to empty not affecting property sheet. Also remove support for VS2013.
#jira UE-48119
Change 3596631 by Steve.Robb
Tool which takes a .map file and a .objmap file (from UBT) and creates a report which shows the size of all the symbols contributed by the source code per-folder.
Change 3596807 by Ben.Marsh
Improve Intellisense when generated headers are missing or out of date (eg. line numbers changed, etc...). These errors seem to be masked by VAX, but are present when using the default Visual Studio Intellisense.
* UCLASS macro is defined to empty when __INTELLISENSE__ is defined. Previous macro was preventing any following class declaration being parsed correctly if generated code was out of date, causing squiggles over all class methods/variables.
* Insert a semicolon after each expanded GENERATED_BODY macro, so that if it parses incorrectly, the compiler can still continue parsing the next declaration.
Change 3596957 by Steve.Robb
UBT can be used to write out an .objsrcmap file for use with the MapFileParser.
Renaming of ObjMap to ObjSrcMap in MapFileParser.
Change 3597213 by Ben.Marsh
Remove AutoReporter. We don't support this any more.
Change 3597558 by Ben.Marsh
UGS: Allow adding custom actions to the context menu for right clicking on a changelist. Actions are specified in the project's UnrealEngine.ini file, with the following syntax:
+ContextMenu=(Label="This is the menu item", Execute="foo.exe", Arguments="bar")
The standard set of variables for custom tools is expanded in each parameter (eg. $(ProjectDir), $(EditorConfig), etc...), plus the $(Change) variable.
Change 3597982 by Ben.Marsh
Add an option to allow overriding the local DDC path from the editor (under Editor Preferences > Global > Local Derived Data Cache).
#jira UE-47173
Change 3598045 by Ben.Marsh
UGS: Add variables for stream and client name, and the ability to escape any variables for URIs using the syntax $(VariableName:URI).
Change 3599214 by Ben.Marsh
Avoid string duplication when comparing extensions.
Change 3600038 by Steve.Robb
Fix for maps being modified during iteration in cache compaction.
Change 3600136 by Steve.Robb
GitHub #3538 : Fixed a bug with the handling of 'TMap' key/value types in the UnrealHeaderTool
Change 3600214 by Steve.Robb
More accurate error message when unsupported template parameters are provided in a TSet property.
Change 3600232 by Ben.Marsh
UBT: Force UHT to run again if the .build.cs file for a module has changed.
#jira UE-46119
Change 3600246 by Steve.Robb
GitHub #3045 : allow multiple interface definition in a file
Change 3600645 by Ben.Marsh
Convert QAGame to Include-What-You-Use.
Change 3600897 by Ben.Marsh
Fix invalid path (multiple slashes) in LibCurl.build.cs. Causes exception when scanning for includes.
Change 3601558 by Graeme.Thornton
Simple first pass VSCode editor integration plugin
Change 3601658 by Graeme.Thornton
Enable intellisense generation for VS Code project files and setup include paths properly
Change 3601762 by Ben.Marsh
UBT: Add support for adaptive non-unity builds when working from a Git repository.
The ISourceFileWorkingSet interface is now used to query files belonging to the working set, and has separate implementations for Perforce (PerforceSourceFileWorkingSet) and Git (GitSourceFileWorkingSet). The Git implementation is used if a .git directory is found in the directory containing the Engine folder, the directory containing the project file, or the parent directory of the project file, and spawns a "git status" process in the background to determine which files are untracked or staged.
Several new settings are supported in BuildConfiguration.xml to allow modifying default behavior:
<SourceFileWorkingSet>
<Provider>Default</Provider> <!-- May be None, Default, Git or Perforce -->
<RepositoryPath></RepositoryPath> <!-- Specifies the path to the repository, relative to the directory containing the Engine folder. If not set, tries to find a .git directory in the locations listed above. -->
<GitPath>git</GitPath> <!-- Specifies the path to the Git executable. Defaults to "git", which assumes that it will be on the PATH -->
</SourceFileWorkingSet>
Change 3604032 by Graeme.Thornton
First attempt at automatically detecting the existance and location of visual studio code in the source code accessor module. Only works for windows.
Change 3604038 by Graeme.Thornton
Added FSourceCodeNavigation::GetSelectedSourceCodeIDE() which returns the name of the selected source code accessor.
Replaced all usages of FSourceCodeNavigation::GetSuggestedSourceCodeIDE() with GetSelectedSourceCodeIDE(), where the message is referring to the opening or editing of code.
Change 3604106 by Steve.Robb
GitHub #3561 : UE-44950: Don't see all caps struct constructor as macro
Change 3604192 by Steve.Robb
GitHub #3911 : Improving ToUpper/ToLower efficiency
Change 3604273 by Graeme.Thornton
IWYU build fixes when malloc profiler is enabled
Change 3605457 by Ben.Marsh
Fix race for intiialization of ThreadID variable on FRunnableThreadWin, and restore a previous check that was working around it.
Change 3606720 by James.Hopkin
Dave Ratti's fix to character base recursion protection code - was missing a GetOwner call, instead attempting to cast a component to a pawn.
Change 3606807 by Graeme.Thornton
Disabled optimizations around FShooterStyle::Create(), which was crashing in Win64 shipping game builds due to some known compiler issue. Same variety of fix as BenZ did in CL 3567741.
Change 3607026 by James.Hopkin
Fixed incorrect ABrush cast - was attempting to cast a UModel to ABrush, which can never succeed
Change 3607142 by Graeme.Thornton
UBT - Minor refactor of BackgroundProcess shutdown in SourceFileWorkingSet. Check whether the process has already exited before trying to kill it during Dispose.
Change 3607146 by Ben.Marsh
UGS: Fix exception due to formatting string when Perforce throws an error.
Change 3607147 by Steve.Robb
Efficiency fix for integer properties, which were causing a property mismatch and thus a tag lookup every time.
Float and double conversion support added to int properties.
NAME_DoubleProperty added.
Fix for converting enum class enumerators > 255 to int properties.
Change 3607516 by Ben.Marsh
PR #3935: Fix DECLARE_DELEGATE_NineParams, DECLARE_MULTICAST_DELEGATE_NineParams. (Contributed by enginevividgames)
Change 3610421 by Ben.Marsh
UAT: Move help for RebuildLightMapsCommand into attributes, so they display when running with -help.
Change 3610657 by Ben.Marsh
UAT: Unify initialization of command environment for build machines and local execution. Always derive parameters which aren't manually set via environment variables.
Change 3611000 by Ben.Marsh
UAT: Remove the -ForceLocal command line option. Settings are now determined automatically, independently of the -Buildmachine argument.
Change 3612471 by Ben.Marsh
UBT: Move FastJSON into DotNETUtilities.
Change 3613479 by Ben.Marsh
UBT: Remove the bIsCodeProject flag from UProjectInfo. This was only really being used to determine which projects to generate an IDE project for, so it is now checked in the project file generator.
Change 3613910 by Ben.Marsh
UBT: Remove unnecessary code to guess a project from the target name; doesn't work due to init order, actual project is determined later.
Change 3614075 by Ben.Marsh
UBT: Remove hacks for testing project file attributes by name.
Change 3614090 by Ben.Marsh
UBT: Remove global lookup of project by name. Projects should be explicitly specified by path when necessary.
Change 3614488 by Ben.Marsh
UBT: Prevent annoying (but handled) exception when constructing SQLiteModuleSupport objects with -precompile enabled.
Change 3614490 by Ben.Marsh
UBT: Simplify generation of arguments for building intellisense; determine the platform/configuration to build from the project file generation code, rather than inside the target itself.
Change 3614962 by Ben.Marsh
UBT: Move the VS2017 strict conformance mode (/permissive-) behind a command line option (-Strict), and disable it by default. Building with this mode is not guaranteed to work correctly without updated Windows headers.
Change 3615416 by Ben.Marsh
EC: Include an icon showing the overall status of a build in the grid view.
Change 3615713 by Ben.Marsh
UBT: Delete any files in output directories which match output files in other directories. Allows automatically deleting build products which are moved into another folder.
#jira UE-48987
Change 3616652 by Ben.Marsh
Plugins: Fix incorrect dialog when binaries for a plugin are missing. Should only prompt to disable if starting a content-only project.
#jira UE-49007
Change 3616680 by Ben.Marsh
Add the CodeAPI-HTML.tgz file into the installed engine build.
Change 3616767 by Ben.Marsh
Plugins: Tweak error message if the FModuleManager::IsUpToDate() function returns false for a plugin module; the module may be missing, not just incompatible.
Change 3616864 by Ben.Marsh
Cap the length of the temporary package name during save, to prevent excessively long filenames going over the limit once a GUID is appended.
#jira UE-48711
Change 3619964 by Ben.Marsh
UnrealVS: Fix single file compile for foreign projects, where the command line contains $(SolutionDir) and $(ProjectName) variables.
Change 3548930 by Ben.Marsh
UBT: Remove UEBuildModuleCSDLL; there is no codepath that still supports creating them. Remove the remaining UEBuildModule/UEBuildModuleCPP abstraction.
Change 3558056 by Ben.Marsh
Deprecate FString::Trim() and FString::TrimTrailing(), and replace them with separate versions to mutate (TrimStartInline(), TrimEndInline()) or return by copy (TrimStart(), TrimEnd()). Also add a functions to trim whitespace from both ends of a string (TrimStartAndEnd(), TrimStartAndEndInline()).
Change 3563309 by Graeme.Thornton
Moved some common C# classes into the DotNETCommon assembly
Change 3570283 by Graeme.Thornton
Move some code out of RPCUtility and into DotNETCommon, removing the dependency between the two projects
Added UEConsoleTraceListener to replace ConsoleTraceListener, which doesn't exist in DotNetCore
Change 3572811 by Ben.Marsh
UBT: Add -enableasan / -enabletsan command line options and bEnableAddressSanitizer / bEnableThreadSanitizer settings in BuildConfiguration.xml (and remove environment variables).
Change 3573397 by Ben.Marsh
UBT: Create a <ExeName>.version file for every target built by UBT, in the same JSON format as Engine/Build/Build.version. This allows monolithic targets to read a version number at runtime, unlike when it's embedded in a modules file, and allows creating versioned client executables that will work with versioned servers when syncing through UGS.
Change 3575659 by Ben.Marsh
Remove CHM API documentation.
Change 3582103 by Graeme.Thornton
Simple ResX writer implemetation that the xbox deloyment code can use instead of the one from the windows forms assembly, which isn't supported on .NET Core
Removed reference to System.Windows.Form from UBT.
Change 3584113 by Ben.Marsh
Move key-mapping functionality into the InputCore module.
Change 3584278 by Ben.Marsh
Move FPlatformMisc::RequestMinimize() into FPlatformApplicationMisc.
Change 3584453 by Ben.Marsh
Move functionality for querying device display density to FApplicationMisc, due to dependence on application-level functionality on mobile platforms.
Change 3585301 by Ben.Marsh
Move PlatformPostInit() into an FPlatformApplicationMisc function.
Change 3587050 by Ben.Marsh
Move IsThisApplicationForeground() into FPlatformApplicationMisc.
Change 3587059 by Ben.Marsh
Move RequiresVirtualKeyboard() into FPlatformApplicationMisc.
Change 3587119 by Ben.Marsh
Move GetAbsoluteLogFilename() into FPlatformMisc.
Change 3587800 by Steve.Robb
Fixes to container visualizers for types whose pointer type isn't simply Type*.
Change 3588393 by Ben.Marsh
Move platform output devices into their own headers.
Change 3588868 by Ben.Marsh
Move creation of console, error and warning output devices int PlatformApplicationMisc.
Change 3589879 by Graeme.Thornton
All automation projects now have a reference to DotNETUtilities
Fixed a build error in the WEX automation library
Change 3590034 by Ben.Marsh
Move functionality related to windowing and input out of the Core module and into an ApplicationCore module, so it is possible to build utilities with Core without adding dependencies on XInput (Windows), SDL (Linux), and OpenGL (Mac).
Change 3593754 by Steve.Robb
Fix for tuple debugger visualization.
Change 3597208 by Ben.Marsh
Move CrashReporter out of a public folder; it's not in a form that is usable by subscribers and licensees.
Change 3600163 by Ben.Marsh
UBT: Simplify how targets are cleaned. Delete all intermediate folders for a platform/configuration, and delete any build products matching the UE4 naming convention for that target, rather than relying on the current build configuration or list of previous build products. This will ensure that build products which are no longer being generated will also be cleaned.
#jira UE-46725
Change 3604279 by Graeme.Thornton
Move pre/post garbage collection delegates into accessor functions so they can be used by globally constructed objects
Change 3606685 by James.Hopkin
Removed redundant 'Cast's (casting to either the same type or a base).
In SClassViewer, replaced cast with TAssetPtr::operator* call to get the wrapped UClass.
Also removed redundant 'IsA's from AnimationRetargetContent::AddRemappedAsset in EditorAnimUtils.cpp.
Change 3610950 by Ben.Marsh
UAT: Simplify logic for detecting Perforce settings, using environment variables if they are set, otherwise falling back to detecting them. Removes special cases for build machines, and makes it simpler to set up UAT commands on builders outside Epic.
Change 3610991 by Ben.Marsh
UAT: Use the correct P4 settings to detect settings if only some parameters are specified on the command line.
Change 3612342 by Ben.Marsh
UBT: Change JsonObject.Read() to take a FileReference parameter.
Change 3612362 by Ben.Marsh
UBT: Remove some more cases of paths being passed as strings rather than using FileReference objects.
Change 3619128 by Ben.Marsh
Include builder warnings and errors in the notification emails for automated tests, otherwise it's difficult to track down non-test failures.
[CL 3620189 by Ben Marsh in Main branch]
2017-08-31 12:08:38 -04:00
FBSPOps : : csgCopyBrush ( BuilderBrush , ClippedBrush , BuilderBrush - > PolyFlags , BuilderBrush - > GetFlags ( ) , 0 , true ) ;
2014-03-14 14:13:41 -04:00
GEditor - > Layers - > DisassociateActorFromLayers ( ClippedBrush ) ;
World - > EditorDestroyActor ( ClippedBrush , false ) ;
// Note that we're purposefully returning non-NULL here to report that the clip was successful,
// even though the ClippedBrush has been destroyed!
}
else
{
// Remove the old brush.
const int32 ClippedBrushIndex = BrushLevel - > Actors . Num ( ) - 1 ;
check ( BrushLevel - > Actors [ ClippedBrushIndex ] = = ClippedBrush ) ;
BrushLevel - > Actors . RemoveAt ( ClippedBrushIndex ) ;
// Add the new brush right after the old brush.
const int32 OldBrushIndex = BrushLevel - > Actors . Find ( InBrush ) ;
check ( OldBrushIndex ! = INDEX_NONE ) ;
BrushLevel - > Actors . Insert ( ClippedBrush , OldBrushIndex + 1 ) ;
}
return ClippedBrush ;
}
} // namespace GeometryClipping
2014-10-14 10:29:11 -04:00
UGeomModifier_Clip : : UGeomModifier_Clip ( const FObjectInitializer & ObjectInitializer )
: Super ( ObjectInitializer )
2014-03-14 14:13:41 -04:00
{
Description = NSLOCTEXT ( " UnrealEd " , " BrushClip " , " Brush Clip " ) ;
2015-02-18 10:58:17 -05:00
Tooltip = NSLOCTEXT ( " UnrealEd.GeomModifier_Clip " , " Tooltip " , " Given a dividing plane, cut the geometry into two pieces, optionally discarding one of them. This operation only works in an orthographic viewport. Define the vertices of the dividing plane with the space bar, and press Enter to apply. " ) ;
2014-03-14 14:13:41 -04:00
bFlipNormal = false ;
bSplit = false ;
}
void UGeomModifier_Clip : : WasActivated ( )
{
ClipMarkers . Empty ( ) ;
}
bool UGeomModifier_Clip : : Supports ( )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
return mode - > GetSelectionState ( ) ? false : true ;
}
bool UGeomModifier_Clip : : OnApply ( )
{
ApplyClip ( bSplit , bFlipNormal ) ;
GEditor - > RebuildAlteredBSP ( ) ; // Brush has been altered, update the Bsp
2015-08-21 09:54:19 -04:00
bPendingPivotOffsetUpdate = true ;
2014-03-14 14:13:41 -04:00
return true ;
}
void UGeomModifier_Clip : : ApplyClip ( bool InSplit , bool InFlipNormal )
{
if ( ! GLastKeyLevelEditingViewportClient )
{
return ;
}
// Assemble the set of selected brushes.
TArray < ABrush * > Brushes ;
for ( FSelectionIterator It ( GEditor - > GetSelectedActorIterator ( ) ) ; It ; + + It )
{
AActor * Actor = static_cast < AActor * > ( * It ) ;
checkSlow ( Actor - > IsA ( AActor : : StaticClass ( ) ) ) ;
ABrush * Brush = Cast < ABrush > ( Actor ) ;
if ( Brush )
{
Brushes . Add ( Brush ) ;
}
}
// Do nothing if no brushes are selected.
if ( Brushes . Num ( ) = = 0 )
{
return ;
}
// Make sure enough clip markers have been placed.
if ( ClipMarkers . Num ( ) ! = 2 )
{
GeomError ( NSLOCTEXT ( " UnrealEd " , " Error_NotEnoughClipMarkers " , " You haven't placed enough clip markers to perform this operation. " ) . ToString ( ) ) ;
return ;
}
// Focus has to be in an orthographic viewport so the editor can determine where the third point on the plane is
if ( ! GLastKeyLevelEditingViewportClient - > IsOrtho ( ) )
{
GeomError ( NSLOCTEXT ( " UnrealEd " , " Error_BrushClipViewportNotOrthographic " , " The focus needs to be in an orthographic viewport for brush clipping to work. " ) . ToString ( ) ) ;
return ;
}
// Create a clipping plane based on ClipMarkers present in the level.
const FVector vtx1 = ClipMarkers [ 0 ] ;
const FVector vtx2 = ClipMarkers [ 1 ] ;
FVector vtx3 ;
// Compute the third vertex based on the viewport orientation.
vtx3 = vtx1 ;
switch ( GLastKeyLevelEditingViewportClient - > ViewportType )
{
case LVT_OrthoXY :
vtx3 . Z - = 64 ;
break ;
case LVT_OrthoXZ :
vtx3 . Y - = 64 ;
break ;
case LVT_OrthoYZ :
vtx3 . X - = 64 ;
break ;
}
// Perform the clip.
{
const FScopedTransaction Transaction ( NSLOCTEXT ( " UnrealEd " , " BrushClip " , " Brush Clip " ) ) ;
GEditor - > SelectNone ( false , true ) ;
// Clip the brush list.
TArray < ABrush * > NewBrushes ;
TArray < ABrush * > OldBrushes ;
for ( int32 BrushIndex = 0 ; BrushIndex < Brushes . Num ( ) ; + + BrushIndex )
{
ABrush * SrcBrush = Brushes [ BrushIndex ] ;
// Compute a clipping plane in the local frame of the brush.
const FTransform ToBrushWorld ( SrcBrush - > ActorToWorld ( ) ) ;
const FVector LocalVtx1 ( ToBrushWorld . InverseTransformPosition ( vtx1 ) ) ;
const FVector LocalVtx2 ( ToBrushWorld . InverseTransformPosition ( vtx2 ) ) ;
const FVector LocalVtx3 ( ToBrushWorld . InverseTransformPosition ( vtx3 ) ) ;
FVector PlaneNormal ( ( LocalVtx2 - LocalVtx1 ) ^ ( LocalVtx3 - LocalVtx1 ) ) ;
if ( PlaneNormal . SizeSquared ( ) < THRESH_ZERO_NORM_SQUARED )
{
GeomError ( NSLOCTEXT ( " UnrealEd " , " Error_ClipUnableToComputeNormal " , " Unable to compute normal for brush clip! " ) . ToString ( ) ) ;
continue ;
}
PlaneNormal . Normalize ( ) ;
FPlane ClippingPlane ( LocalVtx1 , PlaneNormal ) ;
if ( InFlipNormal )
{
ClippingPlane = ClippingPlane . Flip ( ) ;
}
// Is the brush a builder brush?
const bool bIsBuilderBrush = FActorEditorUtils : : IsABuilderBrush ( SrcBrush ) ;
// Perform the clip.
bool bCreatedBrush = false ;
ABrush * NewBrush = GeometryClipping : : ClipBrushAgainstPlane ( ClippingPlane , SrcBrush ) ;
if ( NewBrush )
{
// Select the src brush for builders, or the returned brush for non-builders.
if ( ! bIsBuilderBrush )
{
NewBrushes . Add ( NewBrush ) ;
}
else
{
NewBrushes . Add ( SrcBrush ) ;
}
bCreatedBrush = true ;
}
// If we're doing a split instead of just a plain clip . . .
if ( InSplit )
{
// Don't perform a second clip if the builder brush was already split.
if ( ! bIsBuilderBrush | | ! bCreatedBrush )
{
// Clip the brush against the flipped clipping plane.
ABrush * NewBrush2 = GeometryClipping : : ClipBrushAgainstPlane ( ClippingPlane . Flip ( ) , SrcBrush ) ;
if ( NewBrush2 )
{
// We don't add the brush to the list of new brushes, so that only new brushes
// in the non-cleaved halfspace of the clipping plane will be selected.
bCreatedBrush = true ;
}
}
}
// Destroy source brushes that aren't builders.
if ( ! bIsBuilderBrush )
{
OldBrushes . Add ( SrcBrush ) ;
}
}
// Clear selection to prevent the second clipped brush from being selected.
// When both are selected, it's hard to tell that the brush is clipped.
GEditor - > SelectNone ( false , true ) ;
// Delete old brushes.
for ( int32 BrushIndex = 0 ; BrushIndex < OldBrushes . Num ( ) ; + + BrushIndex )
{
ABrush * OldBrush = OldBrushes [ BrushIndex ] ;
GEditor - > Layers - > DisassociateActorFromLayers ( OldBrush ) ;
OldBrush - > GetWorld ( ) - > EditorDestroyActor ( OldBrush , true ) ;
}
// Select new brushes.
for ( int32 BrushIndex = 0 ; BrushIndex < NewBrushes . Num ( ) ; + + BrushIndex )
{
ABrush * NewBrush = NewBrushes [ BrushIndex ] ;
GEditor - > SelectActor ( NewBrush , true , false ) ;
}
// Notify editor of new selection state.
GEditor - > NoteSelectionChange ( ) ;
}
2014-06-18 10:16:16 -04:00
FEdModeGeometry * Mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
Mode - > FinalizeSourceData ( ) ;
Mode - > GetFromSource ( ) ;
}
2014-06-18 10:16:16 -04:00
bool UGeomModifier_Clip : : InputKey ( FEditorViewportClient * ViewportClient , FViewport * Viewport , FKey Key , EInputEvent Event )
2014-03-14 14:13:41 -04:00
{
bool bResult = false ;
if ( ViewportClient - > IsOrtho ( ) & & Event = = IE_Pressed )
{
const bool bCtrlDown = Viewport - > KeyState ( EKeys : : LeftControl ) | | Viewport - > KeyState ( EKeys : : RightControl ) ;
const bool bShiftDown = Viewport - > KeyState ( EKeys : : LeftShift ) | | Viewport - > KeyState ( EKeys : : RightShift ) ;
const bool bAltDown = Viewport - > KeyState ( EKeys : : LeftAlt ) | | Viewport - > KeyState ( EKeys : : RightAlt ) ;
if ( ( bCtrlDown & & ! bShiftDown & & ! bAltDown & & Key = = EKeys : : RightMouseButton ) | | Key = = EKeys : : SpaceBar )
{
// if the user has 2 markers placed and the click location is on top of the second point, perform the cllck. This is a shortcut the LDs wanted.
if ( ClipMarkers . Num ( ) = = 2 )
{
const FVector * Pos = & ClipMarkers [ 1 ] ;
if ( Pos - > Equals ( SnappedMouseWorldSpacePos ) )
{
OnApply ( ) ;
return true ;
}
}
// If there are already 2 clip markers in the world, clear them out.
if ( ClipMarkers . Num ( ) > 1 )
{
ClipMarkers . Empty ( ) ;
}
ClipMarkers . Add ( SnappedMouseWorldSpacePos ) ;
bResult = true ;
}
else if ( Key = = EKeys : : Escape | | Key = = EKeys : : BackSpace )
{
if ( ClipMarkers . Num ( ) )
{
ClipMarkers . RemoveAt ( ClipMarkers . Num ( ) - 1 ) ;
}
bResult = true ;
}
else if ( Key = = EKeys : : Enter )
{
// If the user has 1 marker placed when they press ENTER, go ahead and place a second one at the current mouse location.
// This allows LDs to place one point, move to a good spot and press ENTER for a quick clip.
if ( ClipMarkers . Num ( ) = = 1 )
{
ClipMarkers . Add ( SnappedMouseWorldSpacePos ) ;
}
ApplyClip ( bAltDown , bShiftDown ) ;
bResult = true ;
}
}
if ( bResult )
{
GEditor - > RedrawLevelEditingViewports ( true ) ;
}
return bResult ;
}
void UGeomModifier_Clip : : Render ( const FSceneView * View , FViewport * Viewport , FPrimitiveDrawInterface * PDI )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
FModeTool_GeometryModify * tool = ( FModeTool_GeometryModify * ) mode - > GetCurrentTool ( ) ;
if ( tool - > GetCurrentModifier ( ) ! = this )
{
return ;
}
// Only draw in ortho viewports
2014-06-18 10:16:16 -04:00
if ( ! ( ( FEditorViewportClient * ) ( Viewport - > GetClient ( ) ) ) - > IsOrtho ( ) )
2014-03-14 14:13:41 -04:00
{
return ;
}
// Draw a yellow box on each clip marker
for ( int32 x = 0 ; x < ClipMarkers . Num ( ) ; + + x )
{
FVector * vtx = & ClipMarkers [ x ] ;
PDI - > DrawPoint ( * vtx , FLinearColor ( 1 , 0 , 0 ) , 6.f , SDPG_Foreground ) ;
}
// If 2 markers are placed, draw a line connecting them and a line showing the clip normal.
// If 1 marker is placed, draw a dashed line and normal to show where the clip plane will appear if the user commits.
if ( ClipMarkers . Num ( ) )
{
FVector LineStart = ClipMarkers [ 0 ] ;
FVector LineEnd = ( ClipMarkers . Num ( ) = = 2 ) ? ClipMarkers [ 1 ] : SnappedMouseWorldSpacePos ;
if ( ClipMarkers . Num ( ) = = 1 )
{
DrawDashedLine ( PDI , LineStart , LineEnd , FLinearColor ( 1 , .5 , 0 ) , GEditor - > GetGridSize ( ) , SDPG_Foreground ) ;
}
else
{
PDI - > DrawLine ( LineStart , LineEnd , FLinearColor ( 1 , 0 , 0 ) , SDPG_Foreground ) ;
}
FVector vtx1 , vtx2 , vtx3 ;
FPoly NormalPoly ;
vtx1 = LineStart ;
vtx2 = LineEnd ;
vtx3 = vtx1 ;
2014-06-18 10:16:16 -04:00
const FEditorViewportClient * ViewportClient = static_cast < FEditorViewportClient * > ( Viewport - > GetClient ( ) ) ;
2014-03-14 14:13:41 -04:00
switch ( ViewportClient - > ViewportType )
{
case LVT_OrthoXY :
vtx3 . Z - = 64 ;
break ;
case LVT_OrthoXZ :
vtx3 . Y - = 64 ;
break ;
case LVT_OrthoYZ :
vtx3 . X - = 64 ;
break ;
}
NormalPoly . Vertices . Add ( vtx1 ) ;
NormalPoly . Vertices . Add ( vtx2 ) ;
NormalPoly . Vertices . Add ( vtx3 ) ;
if ( ! NormalPoly . CalcNormal ( 1 ) )
{
FVector Start = ( vtx1 + vtx2 ) / 2.f ;
float NormalLength = ( vtx2 - vtx1 ) . Size ( ) / 2.f ;
if ( ClipMarkers . Num ( ) = = 1 )
{
DrawDashedLine ( PDI , Start , Start + NormalPoly . Normal * NormalLength , FLinearColor ( 1 , .5 , 0 ) , GEditor - > GetGridSize ( ) , SDPG_Foreground ) ;
}
else
{
PDI - > DrawLine ( Start , Start + NormalPoly . Normal * NormalLength , FLinearColor ( 1 , 0 , 0 ) , SDPG_Foreground ) ;
}
}
}
// Draw a box at the cursor location
int32 BoxSz = FMath : : Max ( GEditor - > GetGridSize ( ) / 2 , 1.f ) ;
DrawWireBox ( PDI , FBox : : BuildAABB ( SnappedMouseWorldSpacePos , FVector ( BoxSz , BoxSz , BoxSz ) ) , FLinearColor ( 1 , 1 , 1 ) , SDPG_Foreground ) ;
}
2014-06-18 10:16:16 -04:00
void UGeomModifier_Clip : : DrawHUD ( FEditorViewportClient * ViewportClient , FViewport * Viewport , const FSceneView * View , FCanvas * Canvas )
2014-03-14 14:13:41 -04:00
{
}
2014-06-18 10:16:16 -04:00
void UGeomModifier_Clip : : Tick ( FEditorViewportClient * ViewportClient , float DeltaTime )
2014-03-14 14:13:41 -04:00
{
if ( GCurrentLevelEditingViewportClient = = ViewportClient )
{
// Figure out where the nearest grid location is to the mouse cursor
FVector NewSnappedMouseWorldSpacePos = ComputeWorldSpaceMousePos ( ViewportClient ) . GridSnap ( GEditor - > GetGridSize ( ) ) ;
// If the snapped mouse position has moved, update the viewport
if ( NewSnappedMouseWorldSpacePos ! = SnappedMouseWorldSpacePos )
{
SnappedMouseWorldSpacePos = NewSnappedMouseWorldSpacePos ;
GEditor - > RedrawLevelEditingViewports ( true ) ;
}
}
}
2014-10-14 10:29:11 -04:00
UGeomModifier_Delete : : UGeomModifier_Delete ( const FObjectInitializer & ObjectInitializer )
: Super ( ObjectInitializer )
2014-03-14 14:13:41 -04:00
{
Description = NSLOCTEXT ( " UnrealEd " , " Delete " , " Delete " ) ;
2015-02-18 10:58:17 -05:00
Tooltip = NSLOCTEXT ( " UnrealEd.GeomModifier_Delete " , " Tooltip " , " Deletes the selected geometry elements (vertices, edges or polygons). " ) ;
2014-03-14 14:13:41 -04:00
bPushButton = true ;
}
bool UGeomModifier_Delete : : Supports ( )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
return ( mode - > HavePolygonsSelected ( ) | | mode - > HaveVerticesSelected ( ) ) ;
}
bool UGeomModifier_Delete : : OnApply ( )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
bool bHandled = false ;
for ( FEdModeGeometry : : TGeomObjectIterator Itor ( mode - > GeomObjectItor ( ) ) ; Itor ; + + Itor )
{
2015-04-02 16:34:30 -04:00
FGeomObjectPtr go = * Itor ;
2014-03-14 14:13:41 -04:00
// Polys
for ( int32 p = 0 ; p < go - > PolyPool . Num ( ) ; + + p )
{
FGeomPoly * gp = & go - > PolyPool [ p ] ;
if ( gp - > IsSelected ( ) )
{
gp - > GetParentObject ( ) - > GetActualBrush ( ) - > Brush - > Polys - > Element [ gp - > ActualPolyIndex ] . PolyFlags | = PF_GeomMarked ;
bHandled = 1 ;
}
}
for ( int32 p = 0 ; p < go - > GetActualBrush ( ) - > Brush - > Polys - > Element . Num ( ) ; + + p )
{
if ( ( go - > GetActualBrush ( ) - > Brush - > Polys - > Element [ p ] . PolyFlags & PF_GeomMarked ) > 0 )
{
go - > GetActualBrush ( ) - > Brush - > Polys - > Element . RemoveAt ( p ) ;
p = - 1 ;
}
}
// Verts
for ( int32 v = 0 ; v < go - > VertexPool . Num ( ) ; + + v )
{
FGeomVertex * gv = & go - > VertexPool [ v ] ;
if ( gv - > IsSelected ( ) )
{
for ( int32 x = 0 ; x < gv - > GetParentObject ( ) - > GetActualBrush ( ) - > Brush - > Polys - > Element . Num ( ) ; + + x )
{
FPoly * Poly = & gv - > GetParentObject ( ) - > GetActualBrush ( ) - > Brush - > Polys - > Element [ x ] ;
Poly - > RemoveVertex ( * gv ) ;
bHandled = 1 ;
}
}
}
go - > GetActualBrush ( ) - > SavedSelections . Empty ( ) ;
}
mode - > FinalizeSourceData ( ) ;
mode - > GetFromSource ( ) ;
GEditor - > RebuildAlteredBSP ( ) ; // Brush has been altered, update the Bsp
// Reset the pivot point to the newest selected object.
AActor * SelectedActor = Cast < AActor > ( GEditor - > GetSelectedActors ( ) - > GetBottom ( AActor : : StaticClass ( ) ) ) ;
GEditor - > GetSelectedActors ( ) - > Modify ( ) ;
if ( SelectedActor )
{
2014-06-18 10:16:16 -04:00
FEditorModeTools & Tools = GLevelEditorModeTools ( ) ;
2014-03-14 14:13:41 -04:00
Tools . SetPivotLocation ( SelectedActor - > GetActorLocation ( ) , false ) ;
}
2015-08-21 09:54:19 -04:00
bPendingPivotOffsetUpdate = true ;
2014-03-14 14:13:41 -04:00
return bHandled ;
}
2014-10-14 10:29:11 -04:00
UGeomModifier_Create : : UGeomModifier_Create ( const FObjectInitializer & ObjectInitializer )
: Super ( ObjectInitializer )
2014-03-14 14:13:41 -04:00
{
Description = NSLOCTEXT ( " UnrealEd " , " Create " , " Create " ) ;
2015-02-18 10:58:17 -05:00
Tooltip = NSLOCTEXT ( " UnrealEd.GeomModifier_Create " , " Tooltip " , " Creates a new polygon from the selected vertices. The vertices must be selected in clockwise order to create a poly with an outward facing normal. " ) ;
2014-03-14 14:13:41 -04:00
bPushButton = true ;
}
bool UGeomModifier_Create : : Supports ( )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
return mode - > HaveVerticesSelected ( ) ;
}
bool UGeomModifier_Create : : OnApply ( )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
for ( FEdModeGeometry : : TGeomObjectIterator Itor ( mode - > GeomObjectItor ( ) ) ; Itor ; + + Itor )
{
2015-04-02 16:34:30 -04:00
FGeomObjectPtr go = * Itor ;
2014-03-14 14:13:41 -04:00
go - > CompileSelectionOrder ( ) ;
// Create an ordered list of vertices based on the selection order.
TArray < FGeomVertex * > Verts ;
for ( int32 x = 0 ; x < go - > SelectionOrder . Num ( ) ; + + x )
{
FGeomBase * obj = go - > SelectionOrder [ x ] ;
if ( obj - > IsVertex ( ) )
{
Verts . Add ( ( FGeomVertex * ) obj ) ;
}
}
if ( Verts . Num ( ) > 2 )
{
// Create new geometry based on the selected vertices
FPoly * NewPoly = new ( go - > GetActualBrush ( ) - > Brush - > Polys - > Element ) FPoly ( ) ;
NewPoly - > Init ( ) ;
for ( int32 x = 0 ; x < Verts . Num ( ) ; + + x )
{
FGeomVertex * gv = Verts [ x ] ;
new ( NewPoly - > Vertices ) FVector ( * gv ) ;
}
NewPoly - > Normal = FVector : : ZeroVector ;
NewPoly - > Base = * Verts [ 0 ] ;
NewPoly - > PolyFlags = PF_DefaultFlags ;
}
}
mode - > FinalizeSourceData ( ) ;
mode - > GetFromSource ( ) ;
GEditor - > RebuildAlteredBSP ( ) ; // Brush has been altered, update the Bsp
2015-08-21 09:54:19 -04:00
bPendingPivotOffsetUpdate = true ;
2014-03-14 14:13:41 -04:00
return true ;
}
2014-10-14 10:29:11 -04:00
UGeomModifier_Flip : : UGeomModifier_Flip ( const FObjectInitializer & ObjectInitializer )
: Super ( ObjectInitializer )
2014-03-14 14:13:41 -04:00
{
Description = NSLOCTEXT ( " UnrealEd " , " Flip " , " Flip " ) ;
2015-02-18 10:58:17 -05:00
Tooltip = NSLOCTEXT ( " UnrealEd.GeomModifier_Flip " , " Tooltip " , " Flips the normal of the selected polygon so that it faces the other way. " ) ;
2014-03-14 14:13:41 -04:00
bPushButton = true ;
}
bool UGeomModifier_Flip : : Supports ( )
{
// Supports polygons selected and objects selected
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
return ( ! mode - > HaveEdgesSelected ( ) & & ! mode - > HaveVerticesSelected ( ) ) ;
}
bool UGeomModifier_Flip : : OnApply ( )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
bool bHavePolygonsSelected = mode - > HavePolygonsSelected ( ) ;
for ( FEdModeGeometry : : TGeomObjectIterator Itor ( mode - > GeomObjectItor ( ) ) ; Itor ; + + Itor )
{
2015-04-02 16:34:30 -04:00
FGeomObjectPtr go = * Itor ;
2014-03-14 14:13:41 -04:00
for ( int32 p = 0 ; p < go - > PolyPool . Num ( ) ; + + p )
{
FGeomPoly * gp = & go - > PolyPool [ p ] ;
if ( gp - > IsSelected ( ) | | ! bHavePolygonsSelected )
{
FPoly * Poly = & go - > GetActualBrush ( ) - > Brush - > Polys - > Element [ gp - > ActualPolyIndex ] ;
Poly - > Reverse ( ) ;
}
}
}
mode - > FinalizeSourceData ( ) ;
mode - > GetFromSource ( ) ;
GEditor - > RebuildAlteredBSP ( ) ; // Brush has been altered, update the Bsp
2015-08-21 09:54:19 -04:00
bPendingPivotOffsetUpdate = true ;
2014-03-14 14:13:41 -04:00
return true ;
}
2014-10-14 10:29:11 -04:00
UGeomModifier_Split : : UGeomModifier_Split ( const FObjectInitializer & ObjectInitializer )
: Super ( ObjectInitializer )
2014-03-14 14:13:41 -04:00
{
Description = NSLOCTEXT ( " UnrealEd " , " Split " , " Split " ) ;
2016-01-07 11:21:22 -05:00
Tooltip = NSLOCTEXT ( " UnrealEd.GeomModifier_Pen " , " Split_Tooltip " , " Split a brush in half, the exact operation depending on which geometry elements are selected. " ) ;
2014-03-14 14:13:41 -04:00
bPushButton = true ;
}
bool UGeomModifier_Split : : Supports ( )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
// This modifier assumes that a single geometry object is selected
if ( mode - > CountObjectsSelected ( ) ! = 1 )
{
return false ;
}
int32 NumPolygonsSelected = mode - > CountSelectedPolygons ( ) ;
int32 NumEdgesSelected = mode - > CountSelectedEdges ( ) ;
int32 NumVerticesSelected = mode - > CountSelectedVertices ( ) ;
if ( ( NumPolygonsSelected = = 1 & & NumEdgesSelected = = 1 & & NumVerticesSelected = = 0 ) // Splitting a face at an edge mid point (scalpel)
| | ( NumPolygonsSelected = = 0 & & NumEdgesSelected > 0 & & NumVerticesSelected = = 0 ) // Splitting a brush at an edge mid point (ring cut)
| | ( NumPolygonsSelected = = 1 & & NumEdgesSelected = = 0 & & NumVerticesSelected = = 2 ) // Splitting a polygon across 2 vertices
| | ( NumPolygonsSelected = = 0 & & NumEdgesSelected = = 0 & & NumVerticesSelected = = 2 ) // Splitting a brush across 2 vertices
)
{
return true ;
}
return false ;
}
bool UGeomModifier_Split : : OnApply ( )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
// Get a pointer to the selected geom object
2015-04-02 16:34:30 -04:00
FGeomObjectPtr GeomObject = NULL ;
2014-03-14 14:13:41 -04:00
for ( FEdModeGeometry : : TGeomObjectIterator Itor ( mode - > GeomObjectItor ( ) ) ; Itor ; + + Itor )
{
GeomObject = * Itor ;
break ;
}
2015-04-02 16:34:30 -04:00
if ( ! GeomObject . IsValid ( ) )
2014-03-14 14:13:41 -04:00
{
return false ;
}
// Count up how many of each subobject are selected so we can determine what the user is trying to split
int32 NumPolygonsSelected = mode - > CountSelectedPolygons ( ) ;
int32 NumEdgesSelected = mode - > CountSelectedEdges ( ) ;
int32 NumVerticesSelected = mode - > CountSelectedVertices ( ) ;
if ( NumPolygonsSelected = = 1 & & NumEdgesSelected = = 1 & & NumVerticesSelected = = 0 )
{
//
// Splitting a face at an edge mid point (scalpel)
//
// Get the selected edge
TArray < FGeomEdge * > Edges ;
mode - > GetSelectedEdges ( Edges ) ;
check ( Edges . Num ( ) = = 1 ) ;
FGeomEdge * SelectedEdge = Edges [ 0 ] ;
// Figure out the verts that are part of that edge
FGeomVertex * Vertex0 = & GeomObject - > VertexPool [ SelectedEdge - > VertexIndices [ 0 ] ] ;
FGeomVertex * Vertex1 = & GeomObject - > VertexPool [ SelectedEdge - > VertexIndices [ 1 ] ] ;
const FVector Vtx0 = * Vertex0 - > GetActualVertex ( Vertex0 - > ActualVertexIndices [ 0 ] ) ;
const FVector Vtx1 = * Vertex1 - > GetActualVertex ( Vertex1 - > ActualVertexIndices [ 0 ] ) ;
// Get the selected polygon
TArray < FGeomPoly * > Polygons ;
mode - > GetSelectedPolygons ( Polygons ) ;
check ( Polygons . Num ( ) = = 1 ) ;
FGeomPoly * Polygon = Polygons [ 0 ] ;
FPoly * SelectedPoly = Polygon - > GetActualPoly ( ) ;
// Get the selected brush
ABrush * Brush = GeomObject - > GetActualBrush ( ) ;
//
// Sanity checking
//
{
// 1. Make sure that the selected edge is part of the selected polygon
if ( ! SelectedPoly - > Vertices . Contains ( Vtx0 ) | | ! SelectedPoly - > Vertices . Contains ( Vtx1 ) )
{
GeomError ( NSLOCTEXT ( " UnrealEd " , " Error_SelectedEdgeMustBelongToSelectedPoly " , " The edge used for splitting must be part of the selected polygon. " ) . ToString ( ) ) ;
return false ;
}
}
// Generate a base and a normal for the cutting plane
2014-11-26 10:01:12 -05:00
const FVector PlaneNormal ( ( Vtx1 - Vtx0 ) . GetSafeNormal ( ) ) ;
2014-03-14 14:13:41 -04:00
const FVector PlaneBase = 0.5f * ( Vtx1 + Vtx0 ) ;
// Clip the selected polygon against the cutting plane
FPoly Front , Back ;
Front . Init ( ) ;
Back . Init ( ) ;
int32 Res = SelectedPoly - > SplitWithPlane ( PlaneBase , PlaneNormal , & Front , & Back , 1 ) ;
if ( Res = = SP_Split )
{
TArray < FPoly > NewPolygons ;
NewPolygons . Add ( Front ) ;
NewPolygons . Add ( Back ) ;
// At this point, see if any other polygons in the brush need to have a vertex added to an edge
FPlane CuttingPlane ( PlaneBase , PlaneNormal ) ;
for ( int32 p = 0 ; p < Brush - > Brush - > Polys - > Element . Num ( ) ; + + p )
{
FPoly * P = & Brush - > Brush - > Polys - > Element [ p ] ;
if ( P ! = SelectedPoly )
{
for ( int32 v = 0 ; v < P - > Vertices . Num ( ) ; + + v )
{
FVector * v0 = & P - > Vertices [ v ] ;
FVector * v1 = & P - > Vertices [ ( v + 1 ) % P - > Vertices . Num ( ) ] ;
// Make sure the line formed by the edge actually crosses the plane before checking for the intersection point.
if ( FMath : : IsNegativeFloat ( CuttingPlane . PlaneDot ( * v0 ) ) ! = FMath : : IsNegativeFloat ( CuttingPlane . PlaneDot ( * v1 ) ) )
{
FVector Intersection = FMath : : LinePlaneIntersection ( * v0 , * v1 , CuttingPlane ) ;
// Make sure that the intersection point lies on the same plane as the selected polygon as we only need to add it there and not
// to any other edge that might intersect the cutting plane.
if ( SelectedPoly - > OnPlane ( Intersection ) )
{
P - > Vertices . Insert ( Intersection , ( v + 1 ) % P - > Vertices . Num ( ) ) ;
break ;
}
}
}
NewPolygons . Add ( * P ) ;
}
}
// Replace the old polygon list with the new one
2015-06-25 09:42:17 -04:00
Brush - > Brush - > Polys - > Element = NewPolygons ;
2014-03-14 14:13:41 -04:00
}
}
else if ( NumPolygonsSelected = = 0 & & NumEdgesSelected > 0 & & NumVerticesSelected = = 0 )
{
//
// Splitting a brush at an edge mid point (ring cut)
//
// Get the selected edge
TArray < FGeomEdge * > Edges ;
mode - > GetSelectedEdges ( Edges ) ;
check ( Edges . Num ( ) > 0 ) ;
FGeomEdge * Edge = Edges [ 0 ] ;
// Generate a base and a normal for the cutting plane
FGeomVertex * Vertex0 = & GeomObject - > VertexPool [ Edge - > VertexIndices [ 0 ] ] ;
FGeomVertex * Vertex1 = & GeomObject - > VertexPool [ Edge - > VertexIndices [ 1 ] ] ;
const FVector v0 = * Vertex0 - > GetActualVertex ( Vertex0 - > ActualVertexIndices [ 0 ] ) ;
const FVector v1 = * Vertex1 - > GetActualVertex ( Vertex1 - > ActualVertexIndices [ 0 ] ) ;
2014-11-26 10:01:12 -05:00
const FVector PlaneNormal ( ( v1 - v0 ) . GetSafeNormal ( ) ) ;
2014-03-14 14:13:41 -04:00
const FVector PlaneBase = 0.5f * ( v1 + v0 ) ;
ABrush * Brush = GeomObject - > GetActualBrush ( ) ;
// The polygons for the new brush are stored in here and the polys inside of the original brush are replaced at the end of the loop
TArray < FPoly > NewPolygons ;
// Clip each polygon against the cutting plane
for ( int32 p = 0 ; p < Brush - > Brush - > Polys - > Element . Num ( ) ; + + p )
{
FPoly * Poly = & Brush - > Brush - > Polys - > Element [ p ] ;
FPoly Front , Back ;
Front . Init ( ) ;
Back . Init ( ) ;
int32 Res = Poly - > SplitWithPlane ( PlaneBase , PlaneNormal , & Front , & Back , 1 ) ;
switch ( Res )
{
case SP_Split :
NewPolygons . Add ( Front ) ;
NewPolygons . Add ( Back ) ;
break ;
default :
NewPolygons . Add ( * Poly ) ;
break ;
}
}
// Replace the old polygon list with the new one
2015-06-25 09:42:17 -04:00
Brush - > Brush - > Polys - > Element = NewPolygons ;
2014-03-14 14:13:41 -04:00
}
else if ( NumPolygonsSelected = = 1 & & NumEdgesSelected = = 0 & & NumVerticesSelected = = 2 )
{
//
// Splitting a polygon across 2 vertices
//
// Get the selected verts
TArray < FGeomVertex * > Verts ;
mode - > GetSelectedVertices ( Verts ) ;
check ( Verts . Num ( ) = = 2 ) ;
FGeomVertex * Vertex0 = Verts [ 0 ] ;
FGeomVertex * Vertex1 = Verts [ 1 ] ;
const FVector v0 = * Vertex0 - > GetActualVertex ( Vertex0 - > ActualVertexIndices [ 0 ] ) ;
const FVector v1 = * Vertex1 - > GetActualVertex ( Vertex1 - > ActualVertexIndices [ 0 ] ) ;
// Get the selected polygon
TArray < FGeomPoly * > Polys ;
mode - > GetSelectedPolygons ( Polys ) ;
check ( Polys . Num ( ) = = 1 ) ;
FGeomPoly * SelectedPoly = Polys [ 0 ] ;
FPoly * Poly = SelectedPoly - > GetActualPoly ( ) ;
//
// Sanity checking
//
{
// 1. Make sure that the selected vertices are part of the selected polygon
if ( ! SelectedPoly - > GetActualPoly ( ) - > Vertices . Contains ( v0 ) | | ! SelectedPoly - > GetActualPoly ( ) - > Vertices . Contains ( v1 ) )
{
GeomError ( NSLOCTEXT ( " UnrealEd " , " Error_SelectedVerticesMustBelongToSelectedPoly " , " The vertices used for splitting must be part of the selected polygon. " ) . ToString ( ) ) ;
return false ;
}
}
// Generate a base and a normal for the cutting plane
FVector v2 = v0 + ( SelectedPoly - > GetNormal ( ) * 64.0f ) ;
const FPlane PlaneNormal ( v0 , v1 , v2 ) ;
const FVector PlaneBase = 0.5f * ( v1 + v0 ) ;
ABrush * Brush = GeomObject - > GetActualBrush ( ) ;
// The polygons for the new brush are stored in here and the polys inside of the original brush are replaced at the end of the loop
TArray < FPoly > NewPolygons ;
// Clip the selected polygon against the cutting plane.
for ( int32 p = 0 ; p < Brush - > Brush - > Polys - > Element . Num ( ) ; + + p )
{
FPoly * P = & Brush - > Brush - > Polys - > Element [ p ] ;
if ( P = = Poly )
{
FPoly Front , Back ;
Front . Init ( ) ;
Back . Init ( ) ;
int32 Res = P - > SplitWithPlane ( PlaneBase , PlaneNormal , & Front , & Back , 1 ) ;
switch ( Res )
{
case SP_Split :
NewPolygons . Add ( Front ) ;
NewPolygons . Add ( Back ) ;
break ;
default :
NewPolygons . Add ( * P ) ;
break ;
}
}
else
{
NewPolygons . Add ( * P ) ;
}
}
// Replace the old polygon list with the new one
2015-06-25 09:42:17 -04:00
Brush - > Brush - > Polys - > Element = NewPolygons ;
2014-03-14 14:13:41 -04:00
}
else if ( NumPolygonsSelected = = 0 & & NumEdgesSelected = = 0 & & NumVerticesSelected = = 2 )
{
//
// Splitting a brush across 2 vertices
//
// Get the selected verts
TArray < FGeomVertex * > Verts ;
mode - > GetSelectedVertices ( Verts ) ;
check ( Verts . Num ( ) = = 2 ) ;
// Generate a base and a normal for the cutting plane
FGeomVertex * Vertex0 = Verts [ 0 ] ;
FGeomVertex * Vertex1 = Verts [ 1 ] ;
const FVector v0 = * Vertex0 - > GetActualVertex ( Vertex0 - > ActualVertexIndices [ 0 ] ) ;
const FVector v1 = * Vertex1 - > GetActualVertex ( Vertex1 - > ActualVertexIndices [ 0 ] ) ;
FVector v2 = ( ( Vertex0 - > GetNormal ( ) + Vertex1 - > GetNormal ( ) ) / 2.0f ) * 64.f ;
const FPlane PlaneNormal ( v0 , v1 , v2 ) ;
const FVector PlaneBase = 0.5f * ( v1 + v0 ) ;
ABrush * Brush = GeomObject - > GetActualBrush ( ) ;
// The polygons for the new brush are stored in here and the polys inside of the original brush are replaced at the end of the loop
TArray < FPoly > NewPolygons ;
// Clip each polygon against the cutting plane
for ( int32 p = 0 ; p < Brush - > Brush - > Polys - > Element . Num ( ) ; + + p )
{
FPoly * Poly = & Brush - > Brush - > Polys - > Element [ p ] ;
FPoly Front , Back ;
Front . Init ( ) ;
Back . Init ( ) ;
int32 Res = Poly - > SplitWithPlane ( PlaneBase , PlaneNormal , & Front , & Back , 1 ) ;
switch ( Res )
{
case SP_Split :
NewPolygons . Add ( Front ) ;
NewPolygons . Add ( Back ) ;
break ;
default :
NewPolygons . Add ( * Poly ) ;
break ;
}
}
// Replace the old polygon list with the new one
2015-06-25 09:42:17 -04:00
Brush - > Brush - > Polys - > Element = NewPolygons ;
2014-03-14 14:13:41 -04:00
}
mode - > FinalizeSourceData ( ) ;
mode - > GetFromSource ( ) ;
GEditor - > RebuildAlteredBSP ( ) ; // Brush has been altered, update the Bsp
2015-08-21 09:54:19 -04:00
bPendingPivotOffsetUpdate = true ;
2014-03-14 14:13:41 -04:00
return true ;
}
2014-10-14 10:29:11 -04:00
UGeomModifier_Triangulate : : UGeomModifier_Triangulate ( const FObjectInitializer & ObjectInitializer )
: Super ( ObjectInitializer )
2014-03-14 14:13:41 -04:00
{
Description = NSLOCTEXT ( " UnrealEd " , " Triangulate " , " Triangulate " ) ;
2015-02-18 10:58:17 -05:00
Tooltip = NSLOCTEXT ( " UnrealEd.GeomModifier_Triangulate " , " Tooltip " , " Break the selected polygons down into triangles. " ) ;
2014-03-14 14:13:41 -04:00
bPushButton = true ;
}
bool UGeomModifier_Triangulate : : Supports ( )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
return ( ! mode - > HaveEdgesSelected ( ) & & ! mode - > HaveVerticesSelected ( ) ) ;
}
bool UGeomModifier_Triangulate : : OnApply ( )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2015-02-18 10:58:17 -05:00
bool bHavePolygonsSelected = mode - > HavePolygonsSelected ( ) ;
2014-03-14 14:13:41 -04:00
// Mark the selected polygons so we can find them in the next loop, and create
// a local list of FPolys to triangulate later.
for ( FEdModeGeometry : : TGeomObjectIterator Itor ( mode - > GeomObjectItor ( ) ) ; Itor ; + + Itor )
{
2015-04-02 16:34:30 -04:00
FGeomObjectPtr go = * Itor ;
2014-03-14 14:13:41 -04:00
TArray < FPoly > PolyList ;
for ( int32 p = 0 ; p < go - > PolyPool . Num ( ) ; + + p )
{
FGeomPoly * gp = & go - > PolyPool [ p ] ;
if ( gp - > IsSelected ( ) | | ! bHavePolygonsSelected )
{
gp - > GetParentObject ( ) - > GetActualBrush ( ) - > Brush - > Polys - > Element [ gp - > ActualPolyIndex ] . PolyFlags | = PF_GeomMarked ;
PolyList . Add ( gp - > GetParentObject ( ) - > GetActualBrush ( ) - > Brush - > Polys - > Element [ gp - > ActualPolyIndex ] ) ;
}
}
// Delete existing polygons
for ( int32 p = 0 ; p < go - > GetActualBrush ( ) - > Brush - > Polys - > Element . Num ( ) ; + + p )
{
if ( ( go - > GetActualBrush ( ) - > Brush - > Polys - > Element [ p ] . PolyFlags & PF_GeomMarked ) > 0 )
{
go - > GetActualBrush ( ) - > Brush - > Polys - > Element . RemoveAt ( p ) ;
p = - 1 ;
}
}
// Triangulate the old polygons into the brush
for ( int32 p = 0 ; p < PolyList . Num ( ) ; + + p )
{
TArray < FPoly > Triangles ;
PolyList [ p ] . Triangulate ( go - > GetActualBrush ( ) , Triangles ) ;
for ( int32 t = 0 ; t < Triangles . Num ( ) ; + + t )
{
go - > GetActualBrush ( ) - > Brush - > Polys - > Element . Add ( Triangles [ t ] ) ;
}
}
}
mode - > FinalizeSourceData ( ) ;
mode - > GetFromSource ( ) ;
GEditor - > RebuildAlteredBSP ( ) ; // Brush has been altered, update the Bsp
return true ;
}
2014-10-14 10:29:11 -04:00
UGeomModifier_Optimize : : UGeomModifier_Optimize ( const FObjectInitializer & ObjectInitializer )
: Super ( ObjectInitializer )
2014-03-14 14:13:41 -04:00
{
Description = NSLOCTEXT ( " UnrealEd " , " Optimize " , " Optimize " ) ;
2015-02-18 10:58:17 -05:00
Tooltip = NSLOCTEXT ( " UnrealEd.GeomModifier_Optimize " , " Tooltip " , " Optimizes the selected geometry by merging together any polygons which can be formed into a single convex polygon. " ) ;
2014-03-14 14:13:41 -04:00
bPushButton = true ;
}
bool UGeomModifier_Optimize : : OnApply ( )
{
2015-06-23 09:43:20 -04:00
// First triangulate before performing optimize
Super : : OnApply ( ) ;
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
TArray < FPoly > Polygons ;
if ( mode - > HavePolygonsSelected ( ) )
{
for ( FEdModeGeometry : : TGeomObjectIterator Itor ( mode - > GeomObjectItor ( ) ) ; Itor ; + + Itor )
{
2015-04-02 16:34:30 -04:00
FGeomObjectPtr go = * Itor ;
2014-03-14 14:13:41 -04:00
ABrush * ActualBrush = go - > GetActualBrush ( ) ;
// Gather a list of polygons that are
for ( int32 p = 0 ; p < go - > PolyPool . Num ( ) ; + + p )
{
FGeomPoly * gp = & go - > PolyPool [ p ] ;
if ( gp - > IsSelected ( ) )
{
ActualBrush - > Brush - > Polys - > Element [ gp - > ActualPolyIndex ] . PolyFlags | = PF_GeomMarked ;
Polygons . Add ( ActualBrush - > Brush - > Polys - > Element [ gp - > ActualPolyIndex ] ) ;
}
}
// Delete existing polygons
for ( int32 p = 0 ; p < go - > GetActualBrush ( ) - > Brush - > Polys - > Element . Num ( ) ; + + p )
{
if ( ( ActualBrush - > Brush - > Polys - > Element [ p ] . PolyFlags & PF_GeomMarked ) > 0 )
{
ActualBrush - > Brush - > Polys - > Element . RemoveAt ( p ) ;
p = - 1 ;
}
}
// Optimize the polygons in the list
FPoly : : OptimizeIntoConvexPolys ( ActualBrush , Polygons ) ;
// Copy the new polygons into the brush
for ( int32 p = 0 ; p < Polygons . Num ( ) ; + + p )
{
FPoly Poly = Polygons [ p ] ;
Poly . PolyFlags & = ~ PF_GeomMarked ;
ActualBrush - > Brush - > Polys - > Element . Add ( Poly ) ;
}
}
}
else
{
for ( FEdModeGeometry : : TGeomObjectIterator Itor ( mode - > GeomObjectItor ( ) ) ; Itor ; + + Itor )
{
2015-04-02 16:34:30 -04:00
FGeomObjectPtr go = * Itor ;
2014-03-14 14:13:41 -04:00
ABrush * ActualBrush = go - > GetActualBrush ( ) ;
// Optimize the polygons
FPoly : : OptimizeIntoConvexPolys ( ActualBrush , ActualBrush - > Brush - > Polys - > Element ) ;
}
}
mode - > FinalizeSourceData ( ) ;
mode - > GetFromSource ( ) ;
GEditor - > RebuildAlteredBSP ( ) ; // Brush has been altered, update the Bsp
return true ;
}
2014-10-14 10:29:11 -04:00
UGeomModifier_Turn : : UGeomModifier_Turn ( const FObjectInitializer & ObjectInitializer )
: Super ( ObjectInitializer )
2014-03-14 14:13:41 -04:00
{
Description = NSLOCTEXT ( " UnrealEd " , " Turn " , " Turn " ) ;
2015-02-18 10:58:17 -05:00
Tooltip = NSLOCTEXT ( " UnrealEd.GeomModifier_Turn " , " Tooltip " , " Given a selected edge common to two triangles, turn the edge so that it is connected to the previously unconnected vertices. " ) ;
2014-03-14 14:13:41 -04:00
bPushButton = true ;
}
bool UGeomModifier_Turn : : Supports ( )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
return mode - > HaveEdgesSelected ( ) ;
}
bool UGeomModifier_Turn : : OnApply ( )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
// Edges
for ( FEdModeGeometry : : TGeomObjectIterator Itor ( mode - > GeomObjectItor ( ) ) ; Itor ; + + Itor )
{
2015-04-02 16:34:30 -04:00
FGeomObjectPtr go = * Itor ;
2014-03-14 14:13:41 -04:00
TArray < FGeomEdge > Edges ;
go - > CompileUniqueEdgeArray ( & Edges ) ;
// Make sure that all polygons involved are triangles
for ( int32 e = 0 ; e < Edges . Num ( ) ; + + e )
{
FGeomEdge * ge = & Edges [ e ] ;
for ( int32 p = 0 ; p < ge - > ParentPolyIndices . Num ( ) ; + + p )
{
FGeomPoly * gp = & go - > PolyPool [ ge - > ParentPolyIndices [ p ] ] ;
FPoly * Poly = gp - > GetActualPoly ( ) ;
if ( Poly - > Vertices . Num ( ) ! = 3 )
{
FNotificationInfo NotificationInfo ( LOCTEXT ( " Error_PolygonsOnEdgeToTurnMustBeTriangles " , " The polygons on each side of the edge you want to turn must be triangles. " ) ) ;
NotificationInfo . ExpireDuration = 3.0f ;
FSlateNotificationManager : : Get ( ) . AddNotification ( NotificationInfo ) ;
EndTrans ( ) ;
return 0 ;
}
}
}
// Turn the edges, one by one
for ( int32 e = 0 ; e < Edges . Num ( ) ; + + e )
{
FGeomEdge * ge = & Edges [ e ] ;
TArray < FVector > Quad ;
// Since we're doing each edge individually, they should each have exactly 2 polygon
// parents (and each one is a triangle (verified above))
if ( ge - > ParentPolyIndices . Num ( ) = = 2 )
{
FGeomPoly * gp = & go - > PolyPool [ ge - > ParentPolyIndices [ 0 ] ] ;
FPoly * Poly = gp - > GetActualPoly ( ) ;
FPoly SavePoly0 = * Poly ;
int32 idx0 = Poly - > GetVertexIndex ( go - > VertexPool [ ge - > VertexIndices [ 0 ] ] ) ;
int32 idx1 = Poly - > GetVertexIndex ( go - > VertexPool [ ge - > VertexIndices [ 1 ] ] ) ;
int32 idx2 = INDEX_NONE ;
if ( idx0 + idx1 = = 1 )
{
idx2 = 2 ;
}
else if ( idx0 + idx1 = = 3 )
{
idx2 = 0 ;
}
else
{
idx2 = 1 ;
}
Quad . Add ( Poly - > Vertices [ idx0 ] ) ;
Quad . Add ( Poly - > Vertices [ idx2 ] ) ;
Quad . Add ( Poly - > Vertices [ idx1 ] ) ;
gp = & go - > PolyPool [ ge - > ParentPolyIndices [ 1 ] ] ;
Poly = gp - > GetActualPoly ( ) ;
FPoly SavePoly1 = * Poly ;
for ( int32 v = 0 ; v < Poly - > Vertices . Num ( ) ; + + v )
{
Quad . AddUnique ( Poly - > Vertices [ v ] ) ;
}
2015-02-02 03:30:06 -05:00
// If the adjoining polys were coincident, don't try to turn the edge
if ( Quad . Num ( ) = = 3 )
{
continue ;
}
2014-03-14 14:13:41 -04:00
// Create new polygons
FPoly * NewPoly ;
NewPoly = new ( gp - > GetParentObject ( ) - > GetActualBrush ( ) - > Brush - > Polys - > Element ) FPoly ( ) ;
NewPoly - > Init ( ) ;
new ( NewPoly - > Vertices ) FVector ( Quad [ 2 ] ) ;
new ( NewPoly - > Vertices ) FVector ( Quad [ 1 ] ) ;
new ( NewPoly - > Vertices ) FVector ( Quad [ 3 ] ) ;
NewPoly - > Base = SavePoly0 . Base ;
NewPoly - > Material = SavePoly0 . Material ;
NewPoly - > PolyFlags = SavePoly0 . PolyFlags ;
NewPoly - > TextureU = SavePoly0 . TextureU ;
NewPoly - > TextureV = SavePoly0 . TextureV ;
NewPoly - > Normal = FVector : : ZeroVector ;
NewPoly - > Finalize ( go - > GetActualBrush ( ) , 1 ) ;
NewPoly = new ( gp - > GetParentObject ( ) - > GetActualBrush ( ) - > Brush - > Polys - > Element ) FPoly ( ) ;
NewPoly - > Init ( ) ;
new ( NewPoly - > Vertices ) FVector ( Quad [ 3 ] ) ;
new ( NewPoly - > Vertices ) FVector ( Quad [ 1 ] ) ;
new ( NewPoly - > Vertices ) FVector ( Quad [ 0 ] ) ;
NewPoly - > Base = SavePoly1 . Base ;
NewPoly - > Material = SavePoly1 . Material ;
NewPoly - > PolyFlags = SavePoly1 . PolyFlags ;
NewPoly - > TextureU = SavePoly1 . TextureU ;
NewPoly - > TextureV = SavePoly1 . TextureV ;
NewPoly - > Normal = FVector : : ZeroVector ;
NewPoly - > Finalize ( go - > GetActualBrush ( ) , 1 ) ;
// Tag the old polygons
for ( int32 p = 0 ; p < ge - > ParentPolyIndices . Num ( ) ; + + p )
{
2014-03-15 01:14:25 -04:00
FGeomPoly * GeomPoly = & go - > PolyPool [ ge - > ParentPolyIndices [ p ] ] ;
2014-03-14 14:13:41 -04:00
2014-03-15 01:14:25 -04:00
go - > GetActualBrush ( ) - > Brush - > Polys - > Element [ GeomPoly - > ActualPolyIndex ] . PolyFlags | = PF_GeomMarked ;
2014-03-14 14:13:41 -04:00
}
}
}
// Delete the old polygons
for ( int32 p = 0 ; p < go - > GetActualBrush ( ) - > Brush - > Polys - > Element . Num ( ) ; + + p )
{
if ( ( go - > GetActualBrush ( ) - > Brush - > Polys - > Element [ p ] . PolyFlags & PF_GeomMarked ) > 0 )
{
go - > GetActualBrush ( ) - > Brush - > Polys - > Element . RemoveAt ( p ) ;
p = - 1 ;
}
}
}
mode - > FinalizeSourceData ( ) ;
mode - > GetFromSource ( ) ;
GEditor - > RebuildAlteredBSP ( ) ; // Brush has been altered, update the Bsp
return true ;
}
2014-10-14 10:29:11 -04:00
UGeomModifier_Weld : : UGeomModifier_Weld ( const FObjectInitializer & ObjectInitializer )
: Super ( ObjectInitializer )
2014-03-14 14:13:41 -04:00
{
Description = NSLOCTEXT ( " UnrealEd " , " Weld " , " Weld " ) ;
2015-02-18 10:58:17 -05:00
Tooltip = NSLOCTEXT ( " UnrealEd.GeomModifier_Weld " , " Tooltip " , " Merge all selected vertices to the first selected vertex. " ) ;
2014-03-14 14:13:41 -04:00
bPushButton = true ;
}
bool UGeomModifier_Weld : : Supports ( )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
return ( mode - > HaveVerticesSelected ( ) & & ! mode - > HaveEdgesSelected ( ) & & ! mode - > HavePolygonsSelected ( ) ) ;
}
bool UGeomModifier_Weld : : OnApply ( )
{
2014-06-18 10:16:16 -04:00
FEdModeGeometry * mode = ( FEdModeGeometry * ) GLevelEditorModeTools ( ) . GetActiveMode ( FBuiltinEditorModes : : EM_Geometry ) ;
2014-03-14 14:13:41 -04:00
// Verts
for ( FEdModeGeometry : : TGeomObjectIterator Itor ( mode - > GeomObjectItor ( ) ) ; Itor ; + + Itor )
{
2015-04-02 16:34:30 -04:00
FGeomObjectPtr go = * Itor ;
2014-03-14 14:13:41 -04:00
go - > CompileSelectionOrder ( ) ;
if ( go - > SelectionOrder . Num ( ) > 1 )
{
//NOTE: function assumes ONLY vertices are selected, UGeomModifier_Weld::Supports must ensure this.
FGeomVertex * FirstSel = ( FGeomVertex * ) go - > SelectionOrder [ 0 ] ;
// Move all selected vertices to the location of the first vertex that was selected.
for ( int32 v = 1 ; v < go - > SelectionOrder . Num ( ) ; + + v )
{
FGeomVertex * gv = ( FGeomVertex * ) go - > SelectionOrder [ v ] ;
if ( gv - > IsSelected ( ) )
{
gv - > X = FirstSel - > X ;
gv - > Y = FirstSel - > Y ;
gv - > Z = FirstSel - > Z ;
}
}
go - > SendToSource ( ) ;
}
}
mode - > FinalizeSourceData ( ) ;
mode - > GetFromSource ( ) ;
GEditor - > RebuildAlteredBSP ( ) ; // Brush has been altered, update the Bsp
//finally, cache the selections AFTER the weld and set the widget to the appropriate selection
for ( FEdModeGeometry : : TGeomObjectIterator Itor ( mode - > GeomObjectItor ( ) ) ; Itor ; + + Itor )
{
2015-04-02 16:34:30 -04:00
FGeomObjectPtr go = * Itor ;
2014-03-14 14:13:41 -04:00
go - > CompileSelectionOrder ( ) ;
ABrush * Actor = go - > GetActualBrush ( ) ;
StoreCurrentGeomSelections ( Actor - > SavedSelections , go ) ;
go - > SelectNone ( ) ;
int32 res = go - > SetPivotFromSelectionArray ( Actor - > SavedSelections ) ;
if ( res = = INDEX_NONE )
{
2014-06-18 10:16:16 -04:00
FEditorModeTools & Tools = GLevelEditorModeTools ( ) ;
2014-03-14 14:13:41 -04:00
Tools . SetPivotLocation ( Actor - > GetActorLocation ( ) , false ) ;
}
go - > ForceLastSelectionIndex ( res ) ;
}
return true ;
}
2014-10-16 09:02:30 -04:00
# undef LOCTEXT_NAMESPACE