2020-01-27 20:11:15 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "DrawPolyPathTool.h"
# include "InteractiveToolManager.h"
# include "ToolBuilderUtil.h"
# include "BaseBehaviors/SingleClickBehavior.h"
# include "BaseBehaviors/MouseHoverBehavior.h"
# include "ToolSceneQueriesUtil.h"
# include "Util/ColorConstants.h"
# include "ToolSetupUtil.h"
2021-05-22 01:32:46 -04:00
# include "DynamicMesh/MeshIndexUtil.h"
2020-01-27 20:11:15 -05:00
# include "Generators/RectangleMeshGenerator.h"
2021-11-18 14:37:34 -05:00
# include "Generators/PolygonEdgeMeshGenerator.h"
2020-01-27 20:11:15 -05:00
# include "Distance/DistLine3Line3.h"
2021-06-02 15:58:00 -04:00
# include "ModelingObjectsCreationAPI.h"
2021-06-13 00:36:02 -04:00
# include "DynamicMesh/MeshTransforms.h"
2020-01-27 20:11:15 -05:00
# include "Selection/ToolSelectionUtil.h"
# include "Operations/ExtrudeMesh.h"
2021-06-13 00:36:02 -04:00
# include "DynamicMesh/MeshNormals.h"
2021-10-13 12:32:03 -04:00
# include "MeshBoundaryLoops.h"
# include "ToolDataVisualizer.h"
2020-01-27 20:11:15 -05:00
2021-03-09 19:33:56 -04:00
using namespace UE : : Geometry ;
2020-01-27 20:11:15 -05:00
2021-03-09 19:33:56 -04:00
# define LOCTEXT_NAMESPACE "UDrawPolyPathTool"
2020-01-27 20:11:15 -05:00
2021-11-18 14:37:34 -05:00
namespace DrawPolyPathToolLocals
2020-03-09 13:52:38 -04:00
{
2021-11-18 14:37:34 -05:00
void ComputeArcLengths ( const TArray < FFrame3d > & PathPoints , TArray < double > & ArcLengths )
2020-03-09 13:52:38 -04:00
{
2021-11-18 14:37:34 -05:00
double CurPathLength = 0 ;
ArcLengths . SetNum ( PathPoints . Num ( ) ) ;
ArcLengths [ 0 ] = 0.0f ;
for ( int32 k = 1 ; k < PathPoints . Num ( ) ; + + k )
2020-03-09 13:52:38 -04:00
{
2021-11-18 14:37:34 -05:00
CurPathLength + = Distance ( PathPoints [ k ] . Origin , PathPoints [ k - 1 ] . Origin ) ;
ArcLengths [ k ] = CurPathLength ;
}
}
2021-12-10 18:05:44 -05:00
void GeneratePathMesh ( FDynamicMesh3 & Mesh ,
const TArray < FFrame3d > & InPathPoints ,
const TArray < double > & InOffsetScaleFactors ,
double OffsetDistance ,
bool bPathIsClosed ,
bool bRampMode ,
bool bSinglePolyGroup ,
bool bRoundedCorners ,
double CornerRadiusFraction ,
bool bLimitCornerRadius ,
int NumCornerArcPoints )
2021-11-18 14:37:34 -05:00
{
Mesh . Clear ( ) ;
TArray < FFrame3d > UsePathPoints = InPathPoints ;
TArray < double > UseOffsetScaleFactors = InOffsetScaleFactors ;
if ( bPathIsClosed & & bRampMode )
{
// Duplicate vertices at the beginning/end of the path when generating a ramp
const FFrame3d FirstPoint = InPathPoints [ 0 ] ;
UsePathPoints . Add ( FirstPoint ) ;
const double FirstScaleFactor = InOffsetScaleFactors [ 0 ] ;
UseOffsetScaleFactors . Add ( FirstScaleFactor ) ;
2020-03-09 13:52:38 -04:00
}
2021-11-18 14:37:34 -05:00
const int NumPoints = UsePathPoints . Num ( ) ;
2020-03-09 13:52:38 -04:00
2021-11-18 14:37:34 -05:00
TArray < double > ArcLengths ;
ComputeArcLengths ( UsePathPoints , ArcLengths ) ;
2021-12-10 18:05:44 -05:00
double PathLength = ArcLengths . Last ( ) ;
2021-11-18 14:37:34 -05:00
if ( bPathIsClosed )
2020-03-09 13:52:38 -04:00
{
2021-12-10 18:05:44 -05:00
double CornerRadius = 2.0 * CornerRadiusFraction * OffsetDistance ;
FPolygonEdgeMeshGenerator MeshGen ( UsePathPoints , UseOffsetScaleFactors , OffsetDistance , FVector3d : : UnitZ ( ) , bRoundedCorners , CornerRadius , bLimitCornerRadius , NumCornerArcPoints ) ;
2021-11-18 14:37:34 -05:00
MeshGen . bSinglePolyGroup = bSinglePolyGroup ;
MeshGen . UVWidth = PathLength ;
MeshGen . UVHeight = 2 * OffsetDistance ;
MeshGen . Generate ( ) ;
Mesh . Copy ( & MeshGen ) ;
2020-03-09 13:52:38 -04:00
2021-11-18 14:37:34 -05:00
Mesh . EnableVertexUVs ( FVector2f : : Zero ( ) ) ;
2020-03-09 13:52:38 -04:00
2021-11-18 14:37:34 -05:00
if ( bRampMode )
2020-03-09 13:52:38 -04:00
{
2021-12-10 18:05:44 -05:00
// Temporarily set vertex UVs to arclengths, for use in interpolating height in ramp mode
if ( bRoundedCorners )
{
// If we added arcs to the corners, recompute arc lengths
const int N = Mesh . VertexCount ( ) / 2 ;
ArcLengths . Init ( 0.0 , N ) ;
double CurPathLength = 0 ;
for ( int k = 1 ; k < N ; + + k )
{
CurPathLength + = Distance ( Mesh . GetVertex ( 2 * k ) , Mesh . GetVertex ( 2 * ( k - 1 ) ) ) ;
ArcLengths [ k ] = CurPathLength ;
}
PathLength = ArcLengths . Last ( ) ;
}
int NumMeshVertices = Mesh . VertexCount ( ) ;
2021-11-18 14:37:34 -05:00
ensure ( NumMeshVertices = = Mesh . MaxVertexID ( ) ) ;
2021-12-10 18:05:44 -05:00
ensure ( NumMeshVertices = = 2 * ArcLengths . Num ( ) ) ;
for ( int k = 0 ; k < NumMeshVertices / 2 ; + + k )
{
const float Alpha = ( float ) ArcLengths [ k ] / PathLength ;
Mesh . SetVertexUV ( 2 * k , FVector2f ( Alpha , ( float ) k ) ) ;
Mesh . SetVertexUV ( 2 * k + 1 , FVector2f ( Alpha , ( float ) k ) ) ;
}
// Set last vertex positions to match first vertex locations so we can construct the vertical wall
2021-11-18 14:37:34 -05:00
Mesh . SetVertex ( NumMeshVertices - 2 , Mesh . GetVertex ( 0 ) ) ;
Mesh . SetVertex ( NumMeshVertices - 1 , Mesh . GetVertex ( 1 ) ) ;
2020-03-09 13:52:38 -04:00
}
}
2021-11-18 14:37:34 -05:00
else
{
FRectangleMeshGenerator MeshGen ;
MeshGen . bSinglePolyGroup = bSinglePolyGroup ;
MeshGen . Width = PathLength ;
MeshGen . Height = 2 * OffsetDistance ;
MeshGen . Normal = FVector3f : : UnitZ ( ) ;
MeshGen . Origin = FVector3d ( PathLength / 2 , 0 , 0 ) ;
MeshGen . HeightVertexCount = 2 ;
MeshGen . WidthVertexCount = NumPoints ;
MeshGen . Generate ( ) ;
Mesh . Copy ( & MeshGen ) ;
Mesh . EnableVertexUVs ( FVector2f : : Zero ( ) ) ; // we will store arc length for each vtx in VertexUV
double ShiftX = 0 ;
double DeltaX = PathLength / ( double ) ( NumPoints - 1 ) ;
for ( int32 k = 0 ; k < NumPoints ; + + k )
{
FFrame3d PathFrame = UsePathPoints [ k ] ;
FVector3d V0 = Mesh . GetVertex ( k ) ;
V0 . X - = ShiftX ;
V0 . Y * = UseOffsetScaleFactors [ k ] ;
V0 = PathFrame . FromFramePoint ( V0 ) ;
Mesh . SetVertex ( k , V0 ) ;
const float Alpha = ( float ) ArcLengths [ k ] / PathLength ;
Mesh . SetVertexUV ( k , FVector2f ( Alpha , ( float ) k ) ) ;
FVector3d V1 = Mesh . GetVertex ( NumPoints + k ) ;
V1 . X - = ShiftX ;
V1 . Y * = UseOffsetScaleFactors [ k ] ;
V1 = PathFrame . FromFramePoint ( V1 ) ;
Mesh . SetVertex ( NumPoints + k , V1 ) ;
Mesh . SetVertexUV ( NumPoints + k , FVector2f ( Alpha , ( float ) k ) ) ;
ShiftX + = DeltaX ;
}
}
}
} // namespace DrawPolyPathToolLocals
2020-03-09 13:52:38 -04:00
2020-01-27 20:11:15 -05:00
/*
* ToolBuilder
*/
bool UDrawPolyPathToolBuilder : : CanBuildTool ( const FToolBuilderState & SceneState ) const
{
2021-06-02 15:58:00 -04:00
return true ;
2020-01-27 20:11:15 -05:00
}
UInteractiveTool * UDrawPolyPathToolBuilder : : BuildTool ( const FToolBuilderState & SceneState ) const
{
UDrawPolyPathTool * NewTool = NewObject < UDrawPolyPathTool > ( SceneState . ToolManager ) ;
NewTool - > SetWorld ( SceneState . World ) ;
return NewTool ;
}
/*
* Tool methods
*/
void UDrawPolyPathTool : : SetWorld ( UWorld * World )
{
this - > TargetWorld = World ;
}
void UDrawPolyPathTool : : Setup ( )
{
UInteractiveTool : : Setup ( ) ;
// register click behavior
USingleClickInputBehavior * ClickBehavior = NewObject < USingleClickInputBehavior > ( this ) ;
ClickBehavior - > Initialize ( this ) ;
AddInputBehavior ( ClickBehavior ) ;
UMouseHoverBehavior * HoverBehavior = NewObject < UMouseHoverBehavior > ( this ) ;
HoverBehavior - > Initialize ( this ) ;
AddInputBehavior ( HoverBehavior ) ;
DrawPlaneWorld = FFrame3d ( ) ;
PlaneMechanic = NewObject < UConstructionPlaneMechanic > ( this ) ;
PlaneMechanic - > Setup ( this ) ;
PlaneMechanic - > CanUpdatePlaneFunc = [ this ] ( ) { return CanUpdateDrawPlane ( ) ; } ;
PlaneMechanic - > Initialize ( TargetWorld , DrawPlaneWorld ) ;
PlaneMechanic - > UpdateClickPriority ( ClickBehavior - > GetPriority ( ) . MakeHigher ( ) ) ;
PlaneMechanic - > OnPlaneChanged . AddLambda ( [ this ] ( ) {
DrawPlaneWorld = PlaneMechanic - > Plane ;
UpdateSurfacePathPlane ( ) ;
} ) ;
ModelingTools: add support for creating Volumes directly from DrawPolygon, DrawRevolve, DrawPolyPath, and AddPrimitive, CombineMeshes, CutMeshWithMesh, PlaneCut, BaseCreateFromSelected Tools. Improve support for Editing volumes, eg handling mesh/volume interactions, and add configurable auto-simplification for volumes to avoid painful Editor hangs.
- Move ToolTarget implementations, DynamicMeshToVolume to ModelingComponentsEditorOnly module
- move VolumeToDynamicMesh, DynamicMeshProvider/Commiter interfaces to ModelingComponents module
- Add UCreateMeshObjectTypeProperties property set to expose mesh/volume options
- Add FCreateMeshObjectParams::TypeHintClass to allow AVolume type (or other UClass hints) to be passed to creation APIs
- Add UE::ToolTarget::ConfigureCreateMeshObjectParams() util function in ModelingToolTargetUtil, tries to determine output type in a FCreateMeshObjectParams based on input ToolTarget
- Add UEditorModelingObjectsCreationAPI::CreateVolume() implementation
- Add UEditorModelingObjectsCreationAPI::FilterMaterials() that strips out any internal materials and replaces with WorldGridMaterial. This occurs when (eg) subtracting a Volume from a StaticMesh, because the temporary volume mesh gets assigned internal materials, but the Tools don't know this. Use in EditorModelingObjectsCreationAPI when creating new objects. UStaticMeshComponentToolTarget also does this filtering in ::CommitMaterialSetUpdate().
- Add ::ComponentTypeSupportsCollision() function to ComponentCollisionUtil, use to avoid checks/ensures for Volume targets
- Add support for automatic mesh simplification in DynamicMeshToVolume. Add CVar to VolumeDynamicMeshToolTarget.h to control max triangle count (default 500). Apply auto-simplify when creating or updating an AVolume. This prevents the Editor from blocking for long periods on meshes that are too high-res for volumes (even 500 is quite high).
- DynamicMeshToVolume now emits polygroup-faces that contain holes (ie multiple boundary loops) as a set of triangles, rather than emitting separate overlapping faces for each boundary loop
#rb none
#rnx
#jira none
#preflight 60ba50632c42ea0001cb54c5
[CL 16561742 by Ryan Schmidt in ue5-main branch]
2021-06-04 16:04:03 -04:00
OutputTypeProperties = NewObject < UCreateMeshObjectTypeProperties > ( this ) ;
OutputTypeProperties - > RestoreProperties ( this ) ;
OutputTypeProperties - > InitializeDefault ( ) ;
OutputTypeProperties - > WatchProperty ( OutputTypeProperties - > OutputType , [ this ] ( FString ) { OutputTypeProperties - > UpdatePropertyVisibility ( ) ; } ) ;
AddToolPropertySource ( OutputTypeProperties ) ;
2020-01-27 20:11:15 -05:00
// add properties
TransformProps = NewObject < UDrawPolyPathProperties > ( this ) ;
TransformProps - > RestoreProperties ( this ) ;
AddToolPropertySource ( TransformProps ) ;
2021-10-25 20:05:28 -04:00
TransformProps - > WatchProperty ( TransformProps - > bSnapToWorldGrid , [ this ] ( bool )
{
if ( SurfacePathMechanic ! = nullptr )
{
SurfacePathMechanic - > bSnapToWorldGrid = TransformProps - > bSnapToWorldGrid ;
}
} ) ;
2020-01-27 20:11:15 -05:00
2021-11-07 23:43:01 -05:00
TransformProps - > WatchProperty ( TransformProps - > ExtrudeMode , [ this ] ( EDrawPolyPathExtrudeMode )
{
if ( ExtrudeHeightMechanic ! = nullptr )
{
// regenerate the base path mesh
BeginInteractiveExtrudeHeight ( ) ;
}
} ) ;
2020-01-27 20:11:15 -05:00
ExtrudeProperties = NewObject < UDrawPolyPathExtrudeProperties > ( ) ;
ExtrudeProperties - > RestoreProperties ( this ) ;
AddToolPropertySource ( ExtrudeProperties ) ;
SetToolPropertySourceEnabled ( ExtrudeProperties , false ) ;
// initialize material properties for new objects
MaterialProperties = NewObject < UNewMeshMaterialProperties > ( this ) ;
MaterialProperties - > RestoreProperties ( this ) ;
MaterialProperties - > bShowExtendedOptions = false ;
AddToolPropertySource ( MaterialProperties ) ;
// begin path draw
InitializeNewSurfacePath ( ) ;
2021-10-21 17:57:49 -04:00
SetToolDisplayName ( LOCTEXT ( " ToolName " , " Path Extrude " ) ) ;
2020-01-27 20:11:15 -05:00
}
void UDrawPolyPathTool : : Shutdown ( EToolShutdownType ShutdownType )
{
2021-11-23 10:39:20 -05:00
if ( bHasSavedWidth )
{
TransformProps - > Width = SavedWidth ;
bHasSavedWidth = false ;
}
if ( bHasSavedExtrudeHeight )
{
TransformProps - > ExtrudeHeight = SavedExtrudeHeight ;
SavedExtrudeHeight = false ;
}
2020-01-27 20:11:15 -05:00
PlaneMechanic - > Shutdown ( ) ;
PlaneMechanic = nullptr ;
ModelingTools: add support for creating Volumes directly from DrawPolygon, DrawRevolve, DrawPolyPath, and AddPrimitive, CombineMeshes, CutMeshWithMesh, PlaneCut, BaseCreateFromSelected Tools. Improve support for Editing volumes, eg handling mesh/volume interactions, and add configurable auto-simplification for volumes to avoid painful Editor hangs.
- Move ToolTarget implementations, DynamicMeshToVolume to ModelingComponentsEditorOnly module
- move VolumeToDynamicMesh, DynamicMeshProvider/Commiter interfaces to ModelingComponents module
- Add UCreateMeshObjectTypeProperties property set to expose mesh/volume options
- Add FCreateMeshObjectParams::TypeHintClass to allow AVolume type (or other UClass hints) to be passed to creation APIs
- Add UE::ToolTarget::ConfigureCreateMeshObjectParams() util function in ModelingToolTargetUtil, tries to determine output type in a FCreateMeshObjectParams based on input ToolTarget
- Add UEditorModelingObjectsCreationAPI::CreateVolume() implementation
- Add UEditorModelingObjectsCreationAPI::FilterMaterials() that strips out any internal materials and replaces with WorldGridMaterial. This occurs when (eg) subtracting a Volume from a StaticMesh, because the temporary volume mesh gets assigned internal materials, but the Tools don't know this. Use in EditorModelingObjectsCreationAPI when creating new objects. UStaticMeshComponentToolTarget also does this filtering in ::CommitMaterialSetUpdate().
- Add ::ComponentTypeSupportsCollision() function to ComponentCollisionUtil, use to avoid checks/ensures for Volume targets
- Add support for automatic mesh simplification in DynamicMeshToVolume. Add CVar to VolumeDynamicMeshToolTarget.h to control max triangle count (default 500). Apply auto-simplify when creating or updating an AVolume. This prevents the Editor from blocking for long periods on meshes that are too high-res for volumes (even 500 is quite high).
- DynamicMeshToVolume now emits polygroup-faces that contain holes (ie multiple boundary loops) as a set of triangles, rather than emitting separate overlapping faces for each boundary loop
#rb none
#rnx
#jira none
#preflight 60ba50632c42ea0001cb54c5
[CL 16561742 by Ryan Schmidt in ue5-main branch]
2021-06-04 16:04:03 -04:00
OutputTypeProperties - > SaveProperties ( this ) ;
2020-01-27 20:11:15 -05:00
TransformProps - > SaveProperties ( this ) ;
ExtrudeProperties - > SaveProperties ( this ) ;
MaterialProperties - > SaveProperties ( this ) ;
ClearPreview ( ) ;
}
bool UDrawPolyPathTool : : HitTest ( const FRay & Ray , FHitResult & OutHit )
{
if ( SurfacePathMechanic ! = nullptr )
{
FFrame3d HitPoint ;
2021-11-17 21:06:46 -05:00
if ( SurfacePathMechanic - > IsHitByRay ( FRay3d ( Ray ) , HitPoint ) )
2020-01-27 20:11:15 -05:00
{
2021-11-17 21:06:46 -05:00
OutHit . Distance = FRay3d ( Ray ) . GetParameter ( HitPoint . Origin ) ;
2020-01-27 20:11:15 -05:00
OutHit . ImpactPoint = ( FVector ) HitPoint . Origin ;
OutHit . ImpactNormal = ( FVector ) HitPoint . Z ( ) ;
return true ;
}
return false ;
}
else if ( CurveDistMechanic ! = nullptr )
{
OutHit . ImpactPoint = Ray . PointAt ( 100 ) ;
OutHit . Distance = 100 ;
return true ;
}
else if ( ExtrudeHeightMechanic ! = nullptr )
{
OutHit . ImpactPoint = Ray . PointAt ( 100 ) ;
OutHit . Distance = 100 ;
return true ;
}
return false ;
}
FInputRayHit UDrawPolyPathTool : : IsHitByClick ( const FInputDeviceRay & ClickPos )
{
FHitResult OutHit ;
if ( HitTest ( ClickPos . WorldRay , OutHit ) )
{
return FInputRayHit ( OutHit . Distance ) ;
}
// background capture, if nothing else is hit
return FInputRayHit ( TNumericLimits < float > : : Max ( ) ) ;
}
void UDrawPolyPathTool : : OnClicked ( const FInputDeviceRay & ClickPos )
{
if ( SurfacePathMechanic ! = nullptr )
{
2021-11-17 21:06:46 -05:00
if ( SurfacePathMechanic - > TryAddPointFromRay ( ( FRay3d ) ClickPos . WorldRay ) )
2020-01-27 20:11:15 -05:00
{
if ( SurfacePathMechanic - > IsDone ( ) )
{
2020-03-09 13:52:38 -04:00
bPathIsClosed = SurfacePathMechanic - > LoopWasClosed ( ) ;
2021-12-10 18:05:44 -05:00
GetToolManager ( ) - > EmitObjectChange ( this , MakeUnique < FDrawPolyPathStateChange > ( CurrentCurveTimestamp ) , LOCTEXT ( " DrawPolyPathFinishPath " , " Finish path " ) ) ;
2020-01-27 20:11:15 -05:00
OnCompleteSurfacePath ( ) ;
}
else
{
2021-12-10 18:05:44 -05:00
GetToolManager ( ) - > EmitObjectChange ( this , MakeUnique < FDrawPolyPathStateChange > ( CurrentCurveTimestamp ) , LOCTEXT ( " DrawPolyPathAddToPath " , " Add point to path " ) ) ;
2020-01-27 20:11:15 -05:00
}
}
}
2021-12-10 18:05:44 -05:00
else if ( CurveDistMechanic ! = nullptr & & ! bSpecifyingRadius )
2020-01-27 20:11:15 -05:00
{
2021-12-10 18:05:44 -05:00
GetToolManager ( ) - > EmitObjectChange ( this , MakeUnique < FDrawPolyPathStateChange > ( CurrentCurveTimestamp ) , LOCTEXT ( " DrawPolyPathBeginWidth " , " Set path width " ) ) ;
OnCompleteWidth ( ) ;
}
else if ( CurveDistMechanic ! = nullptr & & bSpecifyingRadius )
{
GetToolManager ( ) - > EmitObjectChange ( this , MakeUnique < FDrawPolyPathStateChange > ( CurrentCurveTimestamp ) , LOCTEXT ( " DrawPolyPathBeginRadius " , " Set corner radius " ) ) ;
OnCompleteRadius ( ) ;
2020-01-27 20:11:15 -05:00
}
else if ( ExtrudeHeightMechanic ! = nullptr )
{
2021-11-23 10:39:20 -05:00
CurHeight = TransformProps - > ExtrudeHeight ;
2021-12-10 18:05:44 -05:00
GetToolManager ( ) - > EmitObjectChange ( this , MakeUnique < FDrawPolyPathStateChange > ( CurrentCurveTimestamp ) , LOCTEXT ( " DrawPolyPathBeginExtrude " , " Set extrude height " ) ) ;
2020-01-27 20:11:15 -05:00
OnCompleteExtrudeHeight ( ) ;
}
}
FInputRayHit UDrawPolyPathTool : : BeginHoverSequenceHitTest ( const FInputDeviceRay & PressPos )
{
FHitResult OutHit ;
if ( HitTest ( PressPos . WorldRay , OutHit ) )
{
return FInputRayHit ( OutHit . Distance ) ;
}
// background capture, if nothing else is hit
return FInputRayHit ( TNumericLimits < float > : : Max ( ) ) ;
}
bool UDrawPolyPathTool : : OnUpdateHover ( const FInputDeviceRay & DevicePos )
{
if ( SurfacePathMechanic ! = nullptr )
{
2021-11-17 21:06:46 -05:00
SurfacePathMechanic - > UpdatePreviewPoint ( ( FRay3d ) DevicePos . WorldRay ) ;
2020-01-27 20:11:15 -05:00
}
else if ( CurveDistMechanic ! = nullptr )
{
CurveDistMechanic - > UpdateCurrentDistance ( DevicePos . WorldRay ) ;
2021-11-07 23:43:01 -05:00
2021-12-10 18:05:44 -05:00
double CurveDistance = CurveDistMechanic - > CurrentDistance ;
2021-11-07 23:43:01 -05:00
if ( TransformProps - > bSnapToWorldGrid )
{
2021-12-10 18:05:44 -05:00
CurveDistance = ToolSceneQueriesUtil : : SnapDistanceToWorldGridSize ( this , CurveDistance ) ;
}
if ( bSpecifyingRadius )
{
TransformProps - > CornerRadius = FMath : : Clamp ( CurveDistance / CurWidth , 0.0 , 2.0 ) ;
CurRadius = TransformProps - > CornerRadius ;
2021-11-07 23:43:01 -05:00
}
else
{
2021-12-10 18:05:44 -05:00
TransformProps - > Width = CurveDistance ;
CurWidth = 0.5 * CurveDistance ;
2021-11-07 23:43:01 -05:00
}
2020-01-27 20:11:15 -05:00
UpdatePathPreview ( ) ;
}
else if ( ExtrudeHeightMechanic ! = nullptr )
{
ExtrudeHeightMechanic - > UpdateCurrentDistance ( DevicePos . WorldRay ) ;
CurHeight = ExtrudeHeightMechanic - > CurrentHeight ;
2021-10-21 17:57:49 -04:00
TransformProps - > ExtrudeHeight = ExtrudeHeightMechanic - > CurrentHeight ;
2020-01-27 20:11:15 -05:00
UpdateExtrudePreview ( ) ;
}
return true ;
}
2020-04-18 18:42:59 -04:00
void UDrawPolyPathTool : : OnTick ( float DeltaTime )
2020-01-27 20:11:15 -05:00
{
if ( PlaneMechanic ! = nullptr )
{
PlaneMechanic - > Tick ( DeltaTime ) ;
}
}
void UDrawPolyPathTool : : Render ( IToolsContextRenderAPI * RenderAPI )
{
GetToolManager ( ) - > GetContextQueriesAPI ( ) - > GetCurrentViewState ( CameraState ) ;
if ( PlaneMechanic ! = nullptr )
{
PlaneMechanic - > Render ( RenderAPI ) ;
}
if ( ExtrudeHeightMechanic ! = nullptr )
{
ExtrudeHeightMechanic - > Render ( RenderAPI ) ;
}
if ( CurveDistMechanic ! = nullptr )
{
CurveDistMechanic - > Render ( RenderAPI ) ;
}
if ( SurfacePathMechanic ! = nullptr )
{
SurfacePathMechanic - > Render ( RenderAPI ) ;
}
2021-10-13 12:32:03 -04:00
if ( CurPolyLoop . Num ( ) > 0 )
{
FToolDataVisualizer LineRenderer ;
LineRenderer . LineColor = LinearColors : : DarkOrange3f ( ) ;
LineRenderer . LineThickness = 4.0f ;
LineRenderer . bDepthTested = false ;
LineRenderer . BeginFrame ( RenderAPI ) ;
int32 NumPoints = CurPolyLoop . Num ( ) ;
for ( int32 k = 0 ; k < NumPoints ; + + k )
{
LineRenderer . DrawLine ( CurPolyLoop [ k ] , CurPolyLoop [ ( k + 1 ) % NumPoints ] ) ;
}
if ( SecondPolyLoop . Num ( ) > 0 )
{
NumPoints = SecondPolyLoop . Num ( ) ;
for ( int32 k = 0 ; k < NumPoints ; + + k )
{
LineRenderer . DrawLine ( SecondPolyLoop [ k ] , SecondPolyLoop [ ( k + 1 ) % NumPoints ] ) ;
}
}
LineRenderer . EndFrame ( ) ;
}
2020-01-27 20:11:15 -05:00
}
void UDrawPolyPathTool : : InitializeNewSurfacePath ( )
{
SurfacePathMechanic = NewObject < UCollectSurfacePathMechanic > ( this ) ;
SurfacePathMechanic - > Setup ( this ) ;
double SnapTol = ToolSceneQueriesUtil : : GetDefaultVisualAngleSnapThreshD ( ) ;
SurfacePathMechanic - > SpatialSnapPointsFunc = [ this , SnapTol ] ( FVector3d Position1 , FVector3d Position2 )
{
2021-10-21 17:57:49 -04:00
return ToolSceneQueriesUtil : : PointSnapQuery ( this - > CameraState , Position1 , Position2 , SnapTol ) ;
2020-01-27 20:11:15 -05:00
} ;
2020-03-09 13:52:38 -04:00
SurfacePathMechanic - > SetDoubleClickOrCloseLoopMode ( ) ;
2021-10-25 20:05:28 -04:00
if ( TransformProps )
{
SurfacePathMechanic - > bSnapToWorldGrid = TransformProps - > bSnapToWorldGrid ;
}
2020-01-27 20:11:15 -05:00
UpdateSurfacePathPlane ( ) ;
2020-03-10 14:00:36 -04:00
ShowStartupMessage ( ) ;
2020-01-27 20:11:15 -05:00
}
bool UDrawPolyPathTool : : CanUpdateDrawPlane ( ) const
{
return ( SurfacePathMechanic ! = nullptr & & SurfacePathMechanic - > HitPath . Num ( ) = = 0 ) ;
}
void UDrawPolyPathTool : : UpdateSurfacePathPlane ( )
{
if ( SurfacePathMechanic ! = nullptr )
{
SurfacePathMechanic - > InitializePlaneSurface ( DrawPlaneWorld ) ;
}
}
void UDrawPolyPathTool : : OnCompleteSurfacePath ( )
{
check ( SurfacePathMechanic ! = nullptr ) ;
CurPathPoints = SurfacePathMechanic - > HitPath ;
int NumPoints = CurPathPoints . Num ( ) ;
// align frames
FVector3d PlaneNormal = DrawPlaneWorld . Z ( ) ;
2021-03-17 19:32:44 -04:00
CurPathPoints [ 0 ] . ConstrainedAlignAxis ( 0 , UE : : Geometry : : Normalized ( CurPathPoints [ 1 ] . Origin - CurPathPoints [ 0 ] . Origin ) , PlaneNormal ) ;
CurPathPoints [ NumPoints - 1 ] . ConstrainedAlignAxis ( 0 , UE : : Geometry : : Normalized ( CurPathPoints [ NumPoints - 1 ] . Origin - CurPathPoints [ NumPoints - 2 ] . Origin ) , PlaneNormal ) ;
2020-01-27 20:11:15 -05:00
double DistOffsetDelta = 0.01 ;
OffsetScaleFactors . SetNum ( NumPoints ) ;
OffsetScaleFactors [ 0 ] = OffsetScaleFactors [ NumPoints - 1 ] = 1.0 ;
2020-03-09 13:52:38 -04:00
// Set local frames for path points. If the path is closed, we will adjust the first and last frames for continuity,
// otherwise we will leave them as set above.
int LastPointIndex = bPathIsClosed ? NumPoints : NumPoints - 1 ;
int FirstPointIndex = bPathIsClosed ? 0 : 1 ;
for ( int j = FirstPointIndex ; j < LastPointIndex ; + + j )
2020-01-27 20:11:15 -05:00
{
2020-03-09 13:52:38 -04:00
int NextJ = ( j + 1 ) % NumPoints ;
int PrevJ = ( j - 1 + NumPoints ) % NumPoints ;
FVector3d Prev ( CurPathPoints [ PrevJ ] . Origin ) , Next ( CurPathPoints [ NextJ ] . Origin ) , Cur ( CurPathPoints [ j ] . Origin ) ;
2020-01-27 20:11:15 -05:00
FLine3d Line1 ( FLine3d : : FromPoints ( Prev , Cur ) ) , Line2 ( FLine3d : : FromPoints ( Cur , Next ) ) ;
Line1 . Origin + = DistOffsetDelta * PlaneNormal . Cross ( Line1 . Direction ) ;
Line2 . Origin + = DistOffsetDelta * PlaneNormal . Cross ( Line2 . Direction ) ;
2021-12-10 18:05:44 -05:00
if ( FMath : : Abs ( Line1 . Direction . Dot ( Line2 . Direction ) ) > 0.999 )
2020-01-27 20:11:15 -05:00
{
2021-03-17 19:32:44 -04:00
CurPathPoints [ j ] . ConstrainedAlignAxis ( 0 , UE : : Geometry : : Normalized ( Next - Prev ) , PlaneNormal ) ;
2020-01-27 20:11:15 -05:00
OffsetScaleFactors [ j ] = 1.0 ;
}
else
{
2021-03-30 21:25:22 -04:00
FDistLine3Line3d LineDist ( Line1 , Line2 ) ;
LineDist . GetSquared ( ) ;
FVector3d OffsetPoint = 0.5 * ( LineDist . Line1ClosestPoint + LineDist . Line2ClosestPoint ) ;
OffsetScaleFactors [ j ] = Distance ( OffsetPoint , Cur ) / DistOffsetDelta ;
2021-03-17 19:32:44 -04:00
FVector3d TangentDir = UE : : Geometry : : Normalized ( OffsetPoint - Cur ) . Cross ( PlaneNormal ) ;
2020-01-27 20:11:15 -05:00
CurPathPoints [ j ] . ConstrainedAlignAxis ( 0 , TangentDir , PlaneNormal ) ;
}
}
CurPolyLine . Reset ( ) ;
for ( const FFrame3d & Point : SurfacePathMechanic - > HitPath )
{
CurPolyLine . Add ( Point . Origin ) ;
}
SurfacePathMechanic = nullptr ;
2021-10-21 17:57:49 -04:00
if ( TransformProps - > WidthMode = = EDrawPolyPathWidthMode : : Fixed )
2020-01-27 20:11:15 -05:00
{
2021-12-10 18:05:44 -05:00
BeginConstantWidth ( ) ;
2020-01-27 20:11:15 -05:00
}
else
{
2021-12-10 18:05:44 -05:00
BeginInteractiveWidth ( ) ;
2020-01-27 20:11:15 -05:00
}
}
2021-12-10 18:05:44 -05:00
void UDrawPolyPathTool : : BeginInteractiveWidth ( )
2020-01-27 20:11:15 -05:00
{
2021-12-10 18:05:44 -05:00
bSpecifyingRadius = false ;
2021-11-23 10:39:20 -05:00
bHasSavedWidth = true ;
SavedWidth = TransformProps - > Width ;
2020-01-27 20:11:15 -05:00
// begin setting offset distance
CurveDistMechanic = NewObject < USpatialCurveDistanceMechanic > ( this ) ;
CurveDistMechanic - > Setup ( this ) ;
2021-03-18 12:46:27 -04:00
CurveDistMechanic - > InitializePolyCurve ( CurPolyLine , UE : : Geometry : : FTransform3d : : Identity ( ) ) ;
2020-01-27 20:11:15 -05:00
InitializePreviewMesh ( ) ;
2020-03-10 14:00:36 -04:00
ShowOffsetMessage ( ) ;
2020-01-27 20:11:15 -05:00
}
2021-12-10 18:05:44 -05:00
void UDrawPolyPathTool : : BeginConstantWidth ( )
2020-01-27 20:11:15 -05:00
{
2021-12-10 18:05:44 -05:00
bSpecifyingRadius = false ;
2020-01-27 20:11:15 -05:00
InitializePreviewMesh ( ) ;
2021-12-10 18:05:44 -05:00
CurWidth = TransformProps - > Width * 0.5 ;
2020-01-27 20:11:15 -05:00
UpdatePathPreview ( ) ;
2021-12-10 18:05:44 -05:00
OnCompleteWidth ( ) ;
}
void UDrawPolyPathTool : : OnCompleteWidth ( )
{
if ( TransformProps - > bRoundedCorners )
{
if ( TransformProps - > WidthMode = = EDrawPolyPathWidthMode : : Fixed )
{
BeginConstantRadius ( ) ;
}
else
{
BeginInteractiveRadius ( ) ;
}
}
else
{
BeginConstantRadius ( ) ;
}
2020-01-27 20:11:15 -05:00
}
2021-12-10 18:05:44 -05:00
void UDrawPolyPathTool : : BeginConstantRadius ( )
{
bSpecifyingRadius = true ;
InitializePreviewMesh ( ) ;
CurRadius = TransformProps - > CornerRadius ;
UpdatePathPreview ( ) ;
OnCompleteRadius ( ) ;
}
2020-01-27 20:11:15 -05:00
2021-12-10 18:05:44 -05:00
void UDrawPolyPathTool : : BeginInteractiveRadius ( )
{
bSpecifyingRadius = true ;
// begin setting offset distance
CurveDistMechanic = NewObject < USpatialCurveDistanceMechanic > ( this ) ;
CurveDistMechanic - > Setup ( this ) ;
CurveDistMechanic - > InitializePolyCurve ( CurPolyLine , UE : : Geometry : : FTransform3d : : Identity ( ) ) ;
InitializePreviewMesh ( ) ;
}
void UDrawPolyPathTool : : OnCompleteRadius ( )
2020-01-27 20:11:15 -05:00
{
CurveDistMechanic = nullptr ;
2021-10-21 17:57:49 -04:00
if ( TransformProps - > ExtrudeMode = = EDrawPolyPathExtrudeMode : : Flat )
2020-01-27 20:11:15 -05:00
{
2021-11-23 10:39:20 -05:00
CurHeight = 0.0 ;
2020-01-27 20:11:15 -05:00
OnCompleteExtrudeHeight ( ) ;
}
2021-10-21 17:57:49 -04:00
else if ( TransformProps - > ExtrudeMode = = EDrawPolyPathExtrudeMode : : Fixed | | TransformProps - > ExtrudeMode = = EDrawPolyPathExtrudeMode : : RampFixed )
2020-01-27 20:11:15 -05:00
{
2021-10-21 17:57:49 -04:00
CurHeight = TransformProps - > ExtrudeHeight ;
2020-01-27 20:11:15 -05:00
OnCompleteExtrudeHeight ( ) ;
}
else
{
BeginInteractiveExtrudeHeight ( ) ;
}
}
void UDrawPolyPathTool : : OnCompleteExtrudeHeight ( )
{
ExtrudeHeightMechanic = nullptr ;
ClearPreview ( ) ;
2021-11-23 10:39:20 -05:00
EmitNewObject ( ) ;
2020-01-27 20:11:15 -05:00
InitializeNewSurfacePath ( ) ;
CurrentCurveTimestamp + + ;
}
void UDrawPolyPathTool : : UpdatePathPreview ( )
{
check ( EditPreview ! = nullptr ) ;
FDynamicMesh3 PathMesh ;
GeneratePathMesh ( PathMesh ) ;
EditPreview - > ReplaceMesh ( MoveTempIfPossible ( PathMesh ) ) ;
}
void UDrawPolyPathTool : : GeneratePathMesh ( FDynamicMesh3 & Mesh )
{
2021-10-13 12:32:03 -04:00
CurPolyLoop . Reset ( ) ;
SecondPolyLoop . Reset ( ) ;
2021-11-18 14:37:34 -05:00
const bool bRampMode = ( TransformProps - > ExtrudeMode = = EDrawPolyPathExtrudeMode : : RampFixed ) | | ( TransformProps - > ExtrudeMode = = EDrawPolyPathExtrudeMode : : RampInteractive ) ;
2021-12-10 18:05:44 -05:00
constexpr bool bLimitCornerRadius = true ;
DrawPolyPathToolLocals : : GeneratePathMesh ( Mesh ,
CurPathPoints ,
OffsetScaleFactors ,
CurWidth ,
bPathIsClosed ,
bRampMode ,
TransformProps - > bSinglePolyGroup ,
TransformProps - > bRoundedCorners ,
CurRadius ,
bLimitCornerRadius ,
TransformProps - > RadialSlices ) ;
2021-11-18 14:37:34 -05:00
FMeshNormals : : QuickRecomputeOverlayNormals ( Mesh ) ;
FMeshBoundaryLoops Loops ( & Mesh , true ) ;
if ( Loops . Loops . Num ( ) > 0 )
2020-01-27 20:11:15 -05:00
{
2021-11-18 14:37:34 -05:00
Loops . Loops [ 0 ] . GetVertices < FVector3d > ( CurPolyLoop ) ;
if ( Loops . Loops . Num ( ) > 1 )
2021-11-07 23:43:01 -05:00
{
2021-11-18 14:37:34 -05:00
Loops . Loops [ 1 ] . GetVertices < FVector3d > ( SecondPolyLoop ) ;
2021-10-13 12:32:03 -04:00
}
2020-01-27 20:11:15 -05:00
}
}
void UDrawPolyPathTool : : BeginInteractiveExtrudeHeight ( )
{
2021-11-23 10:39:20 -05:00
bHasSavedExtrudeHeight = true ;
SavedExtrudeHeight = TransformProps - > ExtrudeHeight ;
2020-01-27 20:11:15 -05:00
// begin extrude
ExtrudeHeightMechanic = NewObject < UPlaneDistanceFromHitMechanic > ( this ) ;
ExtrudeHeightMechanic - > Setup ( this ) ;
ExtrudeHeightMechanic - > WorldHitQueryFunc = [ this ] ( const FRay & WorldRay , FHitResult & HitResult )
{
2021-12-09 14:46:09 -05:00
return ToolSceneQueriesUtil : : FindNearestVisibleObjectHit ( this , HitResult , WorldRay ) ;
2020-01-27 20:11:15 -05:00
} ;
ExtrudeHeightMechanic - > WorldPointSnapFunc = [ this ] ( const FVector3d & WorldPos , FVector3d & SnapPos )
{
return TransformProps - > bSnapToWorldGrid & & ToolSceneQueriesUtil : : FindWorldGridSnapPoint ( this , WorldPos , SnapPos ) ;
} ;
ExtrudeHeightMechanic - > CurrentHeight = 1.0f ; // initialize to something non-zero...prob should be based on polygon bounds maybe?
InitializePreviewMesh ( ) ;
FDynamicMesh3 PathMesh ;
GeneratePathMesh ( PathMesh ) ;
EditPreview - > InitializeExtrudeType ( MoveTemp ( PathMesh ) , DrawPlaneWorld . Z ( ) , nullptr , false ) ;
FDynamicMesh3 TmpMesh ;
EditPreview - > MakeExtrudeTypeHitTargetMesh ( TmpMesh , false ) ;
FFrame3d UseFrame = DrawPlaneWorld ;
UseFrame . Origin = CurPathPoints . Last ( ) . Origin ;
ExtrudeHeightMechanic - > Initialize ( MoveTemp ( TmpMesh ) , UseFrame , true ) ;
2020-03-10 14:00:36 -04:00
ShowExtrudeMessage ( ) ;
2020-01-27 20:11:15 -05:00
}
void UDrawPolyPathTool : : UpdateExtrudePreview ( )
{
2021-11-18 14:37:34 -05:00
EditPreview - > UpdateExtrudeType ( [ & ] ( FDynamicMesh3 & Mesh ) { GenerateExtrudeMesh ( Mesh ) ; } , true ) ;
2020-01-27 20:11:15 -05:00
}
void UDrawPolyPathTool : : InitializePreviewMesh ( )
{
if ( EditPreview = = nullptr )
{
EditPreview = NewObject < UPolyEditPreviewMesh > ( this ) ;
EditPreview - > CreateInWorld ( TargetWorld , FTransform : : Identity ) ;
2021-10-07 22:25:54 -04:00
ToolSetupUtil : : ApplyRenderingConfigurationToPreview ( EditPreview , nullptr ) ;
2020-01-27 20:11:15 -05:00
if ( MaterialProperties - > Material = = nullptr )
{
EditPreview - > SetMaterial (
ToolSetupUtil : : GetSelectionMaterial ( FLinearColor ( 0.8f , 0.75f , 0.0f ) , GetToolManager ( ) ) ) ;
}
else
{
2020-10-09 22:42:26 -04:00
EditPreview - > SetMaterial ( MaterialProperties - > Material . Get ( ) ) ;
2020-01-27 20:11:15 -05:00
}
}
}
void UDrawPolyPathTool : : ClearPreview ( )
{
if ( EditPreview ! = nullptr )
{
EditPreview - > Disconnect ( ) ;
EditPreview = nullptr ;
}
2021-10-13 12:32:03 -04:00
CurPolyLoop . Reset ( ) ;
SecondPolyLoop . Reset ( ) ;
2020-01-27 20:11:15 -05:00
}
void UDrawPolyPathTool : : GenerateExtrudeMesh ( FDynamicMesh3 & PathMesh )
{
FExtrudeMesh Extruder ( & PathMesh ) ;
2021-11-18 14:37:34 -05:00
const FVector3d ExtrudeDir = DrawPlaneWorld . Z ( ) ;
const bool bRampMode = ( TransformProps - > ExtrudeMode = = EDrawPolyPathExtrudeMode : : RampFixed ) | | ( TransformProps - > ExtrudeMode = = EDrawPolyPathExtrudeMode : : RampInteractive ) ;
if ( bRampMode )
{
const double RampStartRatio = TransformProps - > RampStartRatio ;
const double StartHeight = FMathd : : Max ( 0.1 , RampStartRatio * FMathd : : Abs ( CurHeight ) ) * FMathd : : Sign ( CurHeight ) ;
const double EndHeight = CurHeight ;
Extruder . ExtrudedPositionFunc = [ & PathMesh , StartHeight , EndHeight , & ExtrudeDir ] ( const FVector3d & P , const FVector3f & N , int32 VID ) {
FVector2f UV = PathMesh . GetVertexUV ( VID ) ;
double UseHeight = FMathd : : Lerp ( StartHeight , EndHeight , UV . X ) ;
return P + UseHeight * ExtrudeDir ;
} ;
}
else
{
Extruder . ExtrudedPositionFunc = [ this , & ExtrudeDir ] ( const FVector3d & P , const FVector3f & N , int32 VID ) {
return P + CurHeight * ExtrudeDir ;
} ;
}
const FAxisAlignedBox3d Bounds = PathMesh . GetBounds ( ) ;
2020-01-27 20:11:15 -05:00
Extruder . UVScaleFactor = 1.0 / Bounds . MaxDim ( ) ;
Extruder . IsPositiveOffset = ( CurHeight > = 0 ) ;
Extruder . Apply ( ) ;
2020-03-03 16:57:38 -05:00
FMeshNormals : : QuickRecomputeOverlayNormals ( PathMesh ) ;
2020-01-27 20:11:15 -05:00
}
2021-11-23 10:39:20 -05:00
void UDrawPolyPathTool : : EmitNewObject ( )
2020-01-27 20:11:15 -05:00
{
FDynamicMesh3 PathMesh ;
GeneratePathMesh ( PathMesh ) ;
2021-11-18 14:37:34 -05:00
GenerateExtrudeMesh ( PathMesh ) ;
2020-01-27 20:11:15 -05:00
PathMesh . DiscardVertexUVs ( ) ; // throw away arc lengths
FFrame3d MeshTransform = DrawPlaneWorld ;
FVector3d Center = PathMesh . GetBounds ( ) . Center ( ) ;
MeshTransform . Origin = MeshTransform . ToPlane ( Center , 2 ) ;
MeshTransforms : : WorldToFrameCoords ( PathMesh , MeshTransform ) ;
GetToolManager ( ) - > BeginUndoTransaction ( LOCTEXT ( " CreatePolyPath " , " Create PolyPath " ) ) ;
2021-06-02 15:58:00 -04:00
FCreateMeshObjectParams NewMeshObjectParams ;
NewMeshObjectParams . TargetWorld = TargetWorld ;
NewMeshObjectParams . Transform = MeshTransform . ToFTransform ( ) ;
NewMeshObjectParams . BaseName = TEXT ( " Path " ) ;
NewMeshObjectParams . Materials . Add ( MaterialProperties - > Material . Get ( ) ) ;
NewMeshObjectParams . SetMesh ( & PathMesh ) ;
ModelingTools: add support for creating Volumes directly from DrawPolygon, DrawRevolve, DrawPolyPath, and AddPrimitive, CombineMeshes, CutMeshWithMesh, PlaneCut, BaseCreateFromSelected Tools. Improve support for Editing volumes, eg handling mesh/volume interactions, and add configurable auto-simplification for volumes to avoid painful Editor hangs.
- Move ToolTarget implementations, DynamicMeshToVolume to ModelingComponentsEditorOnly module
- move VolumeToDynamicMesh, DynamicMeshProvider/Commiter interfaces to ModelingComponents module
- Add UCreateMeshObjectTypeProperties property set to expose mesh/volume options
- Add FCreateMeshObjectParams::TypeHintClass to allow AVolume type (or other UClass hints) to be passed to creation APIs
- Add UE::ToolTarget::ConfigureCreateMeshObjectParams() util function in ModelingToolTargetUtil, tries to determine output type in a FCreateMeshObjectParams based on input ToolTarget
- Add UEditorModelingObjectsCreationAPI::CreateVolume() implementation
- Add UEditorModelingObjectsCreationAPI::FilterMaterials() that strips out any internal materials and replaces with WorldGridMaterial. This occurs when (eg) subtracting a Volume from a StaticMesh, because the temporary volume mesh gets assigned internal materials, but the Tools don't know this. Use in EditorModelingObjectsCreationAPI when creating new objects. UStaticMeshComponentToolTarget also does this filtering in ::CommitMaterialSetUpdate().
- Add ::ComponentTypeSupportsCollision() function to ComponentCollisionUtil, use to avoid checks/ensures for Volume targets
- Add support for automatic mesh simplification in DynamicMeshToVolume. Add CVar to VolumeDynamicMeshToolTarget.h to control max triangle count (default 500). Apply auto-simplify when creating or updating an AVolume. This prevents the Editor from blocking for long periods on meshes that are too high-res for volumes (even 500 is quite high).
- DynamicMeshToVolume now emits polygroup-faces that contain holes (ie multiple boundary loops) as a set of triangles, rather than emitting separate overlapping faces for each boundary loop
#rb none
#rnx
#jira none
#preflight 60ba50632c42ea0001cb54c5
[CL 16561742 by Ryan Schmidt in ue5-main branch]
2021-06-04 16:04:03 -04:00
OutputTypeProperties - > ConfigureCreateMeshObjectParams ( NewMeshObjectParams ) ;
2021-06-02 15:58:00 -04:00
FCreateMeshObjectResult Result = UE : : Modeling : : CreateMeshObject ( GetToolManager ( ) , MoveTemp ( NewMeshObjectParams ) ) ;
if ( Result . IsOK ( ) & & Result . NewActor ! = nullptr )
2020-01-27 20:11:15 -05:00
{
2021-06-02 15:58:00 -04:00
ToolSelectionUtil : : SetNewActorSelection ( GetToolManager ( ) , Result . NewActor ) ;
2020-01-27 20:11:15 -05:00
}
GetToolManager ( ) - > EndUndoTransaction ( ) ;
2021-10-13 12:32:03 -04:00
2021-11-23 10:39:20 -05:00
if ( bHasSavedWidth )
{
TransformProps - > Width = SavedWidth ;
bHasSavedWidth = false ;
}
if ( bHasSavedExtrudeHeight )
{
TransformProps - > ExtrudeHeight = SavedExtrudeHeight ;
bHasSavedExtrudeHeight = false ;
}
2021-10-13 12:32:03 -04:00
CurPolyLoop . Reset ( ) ;
SecondPolyLoop . Reset ( ) ;
2020-01-27 20:11:15 -05:00
}
2020-03-10 14:00:36 -04:00
void UDrawPolyPathTool : : ShowStartupMessage ( )
{
GetToolManager ( ) - > DisplayMessage (
2021-10-26 13:33:36 -04:00
LOCTEXT ( " OnStartDraw " , " Draw a path on the drawing plane, set its width, and extrude it. Left-click to place path vertices, and click on the last or first vertex to complete the path. Hold Shift to ignore snapping. " ) ,
2020-03-10 14:00:36 -04:00
EToolMessageLevel : : UserNotification ) ;
}
void UDrawPolyPathTool : : ShowOffsetMessage ( )
{
GetToolManager ( ) - > DisplayMessage (
2021-10-21 17:57:49 -04:00
LOCTEXT ( " OnStartOffset " , " Set the width of the path by clicking on the drawing plane. " ) ,
2020-03-10 14:00:36 -04:00
EToolMessageLevel : : UserNotification ) ;
}
void UDrawPolyPathTool : : ShowExtrudeMessage ( )
{
GetToolManager ( ) - > DisplayMessage (
2021-10-21 17:57:49 -04:00
LOCTEXT ( " OnStartExtrude " , " Set the height of the extrusion by positioning the mouse over the extrusion volume, or over objects to snap to their heights. Hold Shift to ignore snapping. " ) ,
2020-03-10 14:00:36 -04:00
EToolMessageLevel : : UserNotification ) ;
}
2020-01-27 20:11:15 -05:00
void UDrawPolyPathTool : : UndoCurrentOperation ( )
{
if ( SurfacePathMechanic ! = nullptr )
{
SurfacePathMechanic - > PopLastPoint ( ) ;
if ( SurfacePathMechanic - > HitPath . Num ( ) = = 0 )
{
CurrentCurveTimestamp + + ;
}
}
else if ( CurveDistMechanic ! = nullptr )
{
2021-12-10 18:05:44 -05:00
if ( ! bSpecifyingRadius )
{
CurveDistMechanic = nullptr ;
ClearPreview ( ) ;
InitializeNewSurfacePath ( ) ;
SurfacePathMechanic - > HitPath = CurPathPoints ;
}
else
{
BeginInteractiveWidth ( ) ;
}
2020-01-27 20:11:15 -05:00
}
else if ( ExtrudeHeightMechanic ! = nullptr )
{
ExtrudeHeightMechanic = nullptr ;
2021-12-10 18:05:44 -05:00
if ( TransformProps - > bRoundedCorners & & TransformProps - > WidthMode = = EDrawPolyPathWidthMode : : Interactive )
{
BeginInteractiveRadius ( ) ;
}
else
{
if ( TransformProps - > WidthMode = = EDrawPolyPathWidthMode : : Fixed )
{
// Pop all the way back to initial path creation
CurveDistMechanic = nullptr ;
ClearPreview ( ) ;
InitializeNewSurfacePath ( ) ;
SurfacePathMechanic - > HitPath = CurPathPoints ;
}
else
{
BeginInteractiveWidth ( ) ;
}
}
2020-01-27 20:11:15 -05:00
}
}
void FDrawPolyPathStateChange : : Revert ( UObject * Object )
{
Cast < UDrawPolyPathTool > ( Object ) - > UndoCurrentOperation ( ) ;
bHaveDoneUndo = true ;
}
bool FDrawPolyPathStateChange : : HasExpired ( UObject * Object ) const
{
return bHaveDoneUndo | | ( Cast < UDrawPolyPathTool > ( Object ) - > CheckInCurve ( CurveTimestamp ) = = false ) ;
}
FString FDrawPolyPathStateChange : : ToString ( ) const
{
return TEXT ( " FDrawPolyPathStateChange " ) ;
}
# undef LOCTEXT_NAMESPACE