2022-06-30 12:09:44 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "Selection/GeometrySelectionManager.h"
2022-10-26 12:57:32 -04:00
# include "Engine/Engine.h"
2022-06-30 12:09:44 -04:00
# include "Selection/DynamicMeshSelector.h"
2022-07-15 13:49:13 -04:00
# include "Selection/SelectionEditInteractiveCommand.h"
2022-11-28 19:15:40 -05:00
# include "InteractiveToolsContext.h"
# include "InteractiveToolManager.h"
2022-06-30 12:09:44 -04:00
# include "ToolContextInterfaces.h"
# include "ToolDataVisualizer.h"
2022-11-28 19:15:40 -05:00
# include "Selections/GeometrySelectionUtil.h"
2022-06-30 12:09:44 -04:00
// for debug drawing
2023-01-04 17:07:40 -05:00
# include "SceneManagement.h"
# include "SceneView.h"
2022-06-30 12:09:44 -04:00
# include "DynamicMeshBuilder.h"
# include "ToolSetupUtil.h"
2022-11-22 20:17:33 -05:00
# include UE_INLINE_GENERATED_CPP_BY_NAME(GeometrySelectionManager)
2022-11-28 19:15:40 -05:00
static TAutoConsoleVariable < int32 > CVarGeometrySelectionManager_FullSelectionHoverHighlights (
TEXT ( " modeling.Selection.FullHoverHighlights " ) ,
0 ,
TEXT ( " Use full selection hover highlights instead of simplified highlights " )
) ;
2022-06-30 12:09:44 -04:00
using namespace UE : : Geometry ;
# define LOCTEXT_NAMESPACE "UGeometrySelectionManager"
void UGeometrySelectionManager : : Initialize ( UInteractiveToolsContext * ToolsContextIn , IToolsContextTransactionsAPI * TransactionsAPIIn )
{
ToolsContext = ToolsContextIn ;
TransactionsAPI = TransactionsAPIIn ;
}
void UGeometrySelectionManager : : RegisterSelectorFactory ( TUniquePtr < IGeometrySelectorFactory > Factory )
{
Factories . Add ( MoveTemp ( Factory ) ) ;
ResetTargetCache ( ) ;
}
void UGeometrySelectionManager : : Shutdown ( )
{
OnSelectionModified . Clear ( ) ;
ToolsContext = nullptr ;
TransactionsAPI = nullptr ;
2022-12-01 16:11:52 -05:00
for ( TSharedPtr < FGeometrySelectionTarget > Target : ActiveTargetReferences )
{
SleepOrShutdownTarget ( Target . Get ( ) , false ) ;
}
2022-06-30 12:09:44 -04:00
ResetTargetCache ( ) ;
2022-07-21 12:52:31 -04:00
ActiveTargetReferences . Reset ( ) ;
ActiveTargetMap . Reset ( ) ;
UpdateSelectionRenderCacheOnTargetChange ( ) ;
2022-06-30 12:09:44 -04:00
}
bool UGeometrySelectionManager : : HasBeenShutDown ( ) const
{
return ( ToolsContext = = nullptr ) ;
}
class FGeometrySelectionManager_SelectionTypeChange : public FToolCommandChange
{
public :
EGeometryElementType FromElementType = EGeometryElementType : : Face ;
EGeometryElementType ToElementType = EGeometryElementType : : Face ;
UGeometrySelectionManager : : EMeshTopologyMode FromTopologyMode = UGeometrySelectionManager : : EMeshTopologyMode : : None ;
UGeometrySelectionManager : : EMeshTopologyMode ToTopologyMode = UGeometrySelectionManager : : EMeshTopologyMode : : None ;
/** Makes the change to the object */
virtual void Apply ( UObject * Object ) override
{
if ( FromElementType ! = ToElementType )
{
CastChecked < UGeometrySelectionManager > ( Object ) - > SetSelectionElementTypeInternal ( ToElementType ) ;
}
if ( FromTopologyMode ! = ToTopologyMode )
{
CastChecked < UGeometrySelectionManager > ( Object ) - > SetMeshTopologyModeInternal ( ToTopologyMode ) ;
}
}
/** Reverts change to the object */
virtual void Revert ( UObject * Object ) override
{
if ( FromElementType ! = ToElementType )
{
CastChecked < UGeometrySelectionManager > ( Object ) - > SetSelectionElementTypeInternal ( FromElementType ) ;
}
if ( FromTopologyMode ! = ToTopologyMode )
{
CastChecked < UGeometrySelectionManager > ( Object ) - > SetMeshTopologyModeInternal ( FromTopologyMode ) ;
}
}
/** Describes this change (for debugging) */
virtual FString ToString ( ) const override { return TEXT ( " FGeometrySelectionManager_SelectionTypeChange " ) ; }
virtual bool HasExpired ( UObject * Object ) const override
{
UGeometrySelectionManager * Manager = Cast < UGeometrySelectionManager > ( Object ) ;
return ( Manager = = nullptr | | IsValid ( Manager ) = = false | | Manager - > HasBeenShutDown ( ) ) ;
}
} ;
void UGeometrySelectionManager : : SetSelectionElementTypeInternal ( EGeometryElementType NewElementType )
{
if ( SelectionElementType ! = NewElementType )
{
SelectionElementType = NewElementType ;
for ( TSharedPtr < FGeometrySelectionTarget > Target : ActiveTargetReferences )
{
Target - > Selection . ElementType = SelectionElementType ;
2022-12-01 16:11:52 -05:00
bool bEnableTopologyFilter = ( Target - > Selection . TopologyType = = EGeometryTopologyType : : Polygroup & & Target - > Selection . ElementType ! = EGeometryElementType : : Vertex ) ;
Target - > SelectionEditor - > UpdateQueryConfig ( GetCurrentSelectionQueryConfig ( ) , bEnableTopologyFilter ) ;
2022-06-30 12:09:44 -04:00
}
}
}
void UGeometrySelectionManager : : SetSelectionElementType ( EGeometryElementType NewElementType )
{
if ( SelectionElementType ! = NewElementType )
{
GetTransactionsAPI ( ) - > BeginUndoTransaction ( LOCTEXT ( " ChangeElementType " , " Selection Type " ) ) ;
if ( HasSelection ( ) )
{
ClearSelection ( ) ;
}
// We have to undo/redo the change to the selection type because if we want to 'undo' this later and restore
// the current selection, we need the active element type to be correct. Note that it goes *after* the Clear
// so that when we undo, we change to the correct type before we restore
TUniquePtr < FGeometrySelectionManager_SelectionTypeChange > TypeChange = MakeUnique < FGeometrySelectionManager_SelectionTypeChange > ( ) ;
TypeChange - > FromElementType = SelectionElementType ;
TypeChange - > ToElementType = NewElementType ;
2022-12-01 16:11:52 -05:00
TypeChange - > FromTopologyMode = TypeChange - > ToTopologyMode = MeshTopologyMode ; // no-op
2022-06-30 12:09:44 -04:00
GetTransactionsAPI ( ) - > AppendChange ( this , MoveTemp ( TypeChange ) , LOCTEXT ( " ChangeElementType " , " Selection Type " ) ) ;
SetSelectionElementTypeInternal ( NewElementType ) ;
GetTransactionsAPI ( ) - > EndUndoTransaction ( ) ;
}
}
void UGeometrySelectionManager : : SetMeshTopologyModeInternal ( EMeshTopologyMode NewTopologyMode )
{
if ( MeshTopologyMode ! = NewTopologyMode )
{
MeshTopologyMode = NewTopologyMode ;
for ( TSharedPtr < FGeometrySelectionTarget > Target : ActiveTargetReferences )
{
Target - > Selection . TopologyType = GetSelectionTopologyType ( ) ;
2022-12-01 16:11:52 -05:00
bool bEnableTopologyFilter = ( Target - > Selection . TopologyType = = EGeometryTopologyType : : Polygroup & & Target - > Selection . ElementType ! = EGeometryElementType : : Vertex ) ;
Target - > SelectionEditor - > UpdateQueryConfig ( GetCurrentSelectionQueryConfig ( ) , bEnableTopologyFilter ) ;
2022-06-30 12:09:44 -04:00
}
}
}
void UGeometrySelectionManager : : SetMeshTopologyMode ( EMeshTopologyMode NewTopologyMode )
{
if ( MeshTopologyMode ! = NewTopologyMode )
{
GetTransactionsAPI ( ) - > BeginUndoTransaction ( LOCTEXT ( " ChangeSelectionMode " , " Selection Mode " ) ) ;
if ( HasSelection ( ) )
{
ClearSelection ( ) ;
}
// We have to undo/redo the change to the selection type because if we want to 'undo' this later and restore
// the current selection, we need the active element type to be correct. Note that it goes *after* the Clear
// so that when we undo, we change to the correct type before we restore
TUniquePtr < FGeometrySelectionManager_SelectionTypeChange > TypeChange = MakeUnique < FGeometrySelectionManager_SelectionTypeChange > ( ) ;
TypeChange - > FromTopologyMode = MeshTopologyMode ;
2022-12-01 16:11:52 -05:00
TypeChange - > ToTopologyMode = NewTopologyMode ;
TypeChange - > FromElementType = TypeChange - > ToElementType = SelectionElementType ; // no-op
2022-06-30 12:09:44 -04:00
GetTransactionsAPI ( ) - > AppendChange ( this , MoveTemp ( TypeChange ) , LOCTEXT ( " ChangeSelectionMode " , " Selection Mode " ) ) ;
SetMeshTopologyModeInternal ( NewTopologyMode ) ;
GetTransactionsAPI ( ) - > EndUndoTransaction ( ) ;
}
}
EGeometryTopologyType UGeometrySelectionManager : : GetSelectionTopologyType ( ) const
{
if ( MeshTopologyMode = = EMeshTopologyMode : : Polygroup )
{
return EGeometryTopologyType : : Polygroup ;
}
else
{
return EGeometryTopologyType : : Triangle ;
}
}
2022-11-28 19:15:40 -05:00
UE : : Geometry : : FGeometrySelectionHitQueryConfig UGeometrySelectionManager : : GetCurrentSelectionQueryConfig ( ) const
{
FGeometrySelectionHitQueryConfig HitQueryConfig ;
HitQueryConfig . TopologyType = GetSelectionTopologyType ( ) ;
HitQueryConfig . ElementType = GetSelectionElementType ( ) ;
HitQueryConfig . bOnlyVisible = true ;
return HitQueryConfig ;
}
2022-06-30 12:09:44 -04:00
bool UGeometrySelectionManager : : HasSelection ( ) const
{
for ( TSharedPtr < FGeometrySelectionTarget > Target : ActiveTargetReferences )
{
if ( Target - > Selection . IsEmpty ( ) = = false )
{
return true ;
}
}
return false ;
}
2023-02-08 01:21:37 -05:00
void UGeometrySelectionManager : : GetActiveSelectionInfo ( EGeometryTopologyType & TopologyTypeOut , EGeometryElementType & ElementTypeOut , int & NumTargetsOut , bool & bIsEmpty ) const
{
FGeometrySelectionHitQueryConfig Config = GetCurrentSelectionQueryConfig ( ) ;
TopologyTypeOut = Config . TopologyType ;
ElementTypeOut = Config . ElementType ;
NumTargetsOut = ActiveTargetReferences . Num ( ) ;
bIsEmpty = ( NumTargetsOut = = 0 ) | | ActiveTargetReferences [ 0 ] - > Selection . IsEmpty ( ) ;
}
2022-06-30 12:09:44 -04:00
class FGeometrySelectionManager_ActiveTargetsChange : public FToolCommandChange
{
public :
TArray < FGeometryIdentifier > TargetsBefore ;
TArray < FGeometryIdentifier > TargetsAfter ;
virtual void Apply ( UObject * Object ) override
{
CastChecked < UGeometrySelectionManager > ( Object ) - > SetTargetsOnUndoRedo ( TargetsAfter ) ;
}
virtual void Revert ( UObject * Object ) override
{
CastChecked < UGeometrySelectionManager > ( Object ) - > SetTargetsOnUndoRedo ( TargetsBefore ) ;
}
virtual FString ToString ( ) const override { return TEXT ( " FGeometrySelectionManager_ActiveTargetsChange " ) ; }
virtual bool HasExpired ( UObject * Object ) const override
{
UGeometrySelectionManager * Manager = Cast < UGeometrySelectionManager > ( Object ) ;
return ( Manager = = nullptr | | IsValid ( Manager ) = = false | | Manager - > HasBeenShutDown ( ) ) ;
}
} ;
2023-04-10 12:36:37 -04:00
class FGeometrySelectionManager_TargetLockStateChange : public FToolCommandChange
{
public :
FGeometryIdentifier TargetIdentifier ;
bool bToState ;
virtual void Apply ( UObject * Object ) override
{
CastChecked < UGeometrySelectionManager > ( Object ) - > SetTargetLockStateOnUndoRedo ( TargetIdentifier , bToState ) ;
}
virtual void Revert ( UObject * Object ) override
{
CastChecked < UGeometrySelectionManager > ( Object ) - > SetTargetLockStateOnUndoRedo ( TargetIdentifier , ! bToState ) ;
}
virtual FString ToString ( ) const override { return TEXT ( " FGeometrySelectionManager_TargetLockStateChange " ) ; }
virtual bool HasExpired ( UObject * Object ) const override
{
UGeometrySelectionManager * Manager = Cast < UGeometrySelectionManager > ( Object ) ;
return ( Manager = = nullptr | | IsValid ( Manager ) = = false | | Manager - > HasBeenShutDown ( ) ) ;
}
} ;
2022-06-30 12:09:44 -04:00
bool UGeometrySelectionManager : : HasActiveTargets ( ) const
{
return ( ActiveTargetReferences . Num ( ) > 0 ) ;
}
void UGeometrySelectionManager : : ClearActiveTargets ( )
{
// generally at this point is it too late to clear the selection, because it will emit an
// undo that cannot be redone later, because on redo the Targets will not exist yet
// (one possibility would be to emit separate changes for when the target set is modified?? would that work w/ delete?? )
ensure ( HasSelection ( ) = = false ) ;
for ( TSharedPtr < FGeometrySelectionTarget > Target : ActiveTargetReferences )
{
SleepOrShutdownTarget ( Target . Get ( ) , false ) ;
}
ActiveTargetReferences . Reset ( ) ;
ActiveTargetMap . Reset ( ) ;
UpdateSelectionRenderCacheOnTargetChange ( ) ;
OnSelectionModified . Broadcast ( ) ;
}
bool UGeometrySelectionManager : : AddActiveTarget ( FGeometryIdentifier TargetIdentifier )
{
if ( ActiveTargetMap . Contains ( TargetIdentifier ) )
{
return false ;
}
// need to have a selector factory that can build for this target
const IGeometrySelectorFactory * UseFactory = nullptr ;
for ( const TUniquePtr < IGeometrySelectorFactory > & Factory : Factories )
{
if ( Factory - > CanBuildForTarget ( TargetIdentifier ) )
{
UseFactory = Factory . Get ( ) ;
break ;
}
}
if ( UseFactory = = nullptr )
{
return false ;
}
TSharedPtr < FGeometrySelectionTarget > SelectionTarget = GetCachedTarget ( TargetIdentifier , UseFactory ) ;
check ( SelectionTarget ! = nullptr ) ;
ActiveTargetMap . Add ( TargetIdentifier , SelectionTarget ) ;
ActiveTargetReferences . Add ( SelectionTarget ) ;
SelectionTarget - > OnGeometryModifiedHandle =
SelectionTarget - > Selector - > GetOnGeometryModifed ( ) . AddUObject ( this , & UGeometrySelectionManager : : OnTargetGeometryModified ) ;
UpdateSelectionRenderCacheOnTargetChange ( ) ;
return true ;
}
void UGeometrySelectionManager : : SynchronizeActiveTargets (
const TArray < FGeometryIdentifier > & DesiredActiveSet ,
TFunctionRef < void ( ) > WillChangeActiveTargetsCallback )
{
TArray < FGeometryIdentifier > Before = GetCurrentTargetIdentifiers ( ) ;
// currently only support single selection
if ( DesiredActiveSet . Num ( ) = = 1 )
{
// if we do not already have this target, select it
if ( ActiveTargetMap . Contains ( DesiredActiveSet [ 0 ] ) = = false )
{
WillChangeActiveTargetsCallback ( ) ;
ClearActiveTargets ( ) ;
AddActiveTarget ( DesiredActiveSet [ 0 ] ) ;
}
}
else
{
WillChangeActiveTargetsCallback ( ) ;
ClearActiveTargets ( ) ;
}
TArray < FGeometryIdentifier > After = GetCurrentTargetIdentifiers ( ) ;
if ( Before ! = After )
{
TUniquePtr < FGeometrySelectionManager_ActiveTargetsChange > Change = MakeUnique < FGeometrySelectionManager_ActiveTargetsChange > ( ) ;
Change - > TargetsBefore = Before ;
Change - > TargetsAfter = After ;
GetTransactionsAPI ( ) - > AppendChange ( this , MoveTemp ( Change ) , LOCTEXT ( " Change Targets " , " Change Targets " ) ) ;
}
}
2023-04-10 12:36:37 -04:00
bool UGeometrySelectionManager : : GetAnyCurrentTargetsLockable ( ) const
{
for ( TSharedPtr < FGeometrySelectionTarget > Target : ActiveTargetReferences )
{
if ( Target - > Selector - > IsLockable ( ) )
{
return true ;
}
}
return false ;
}
bool UGeometrySelectionManager : : GetAnyCurrentTargetsLocked ( ) const
{
for ( TSharedPtr < FGeometrySelectionTarget > Target : ActiveTargetReferences )
{
if ( Target - > Selector - > IsLockable ( ) & & Target - > Selector - > IsLocked ( ) )
{
return true ;
}
}
return false ;
}
void UGeometrySelectionManager : : SetCurrentTargetsLockState ( bool bLocked )
{
bool bInTransaction = false ;
bool bLockStateModified = false ;
for ( TSharedPtr < FGeometrySelectionTarget > Target : ActiveTargetReferences )
{
if ( Target - > Selector - > IsLockable ( ) & & Target - > Selector - > IsLocked ( ) ! = bLocked )
{
Target - > Selector - > SetLockedState ( bLocked ) ;
bLockStateModified = true ;
if ( ! bInTransaction )
{
GetTransactionsAPI ( ) - > BeginUndoTransaction ( ( bLocked ) ?
LOCTEXT ( " Lock Target " , " Lock Target " ) : LOCTEXT ( " Unlock Target " , " Unlock Target " ) ) ;
bInTransaction = true ;
}
TUniquePtr < FGeometrySelectionManager_TargetLockStateChange > Change = MakeUnique < FGeometrySelectionManager_TargetLockStateChange > ( ) ;
Change - > TargetIdentifier = Target - > TargetIdentifier ;
Change - > bToState = bLocked ;
GetTransactionsAPI ( ) - > AppendChange ( this , MoveTemp ( Change ) , LOCTEXT ( " Lock Target " , " Lock Target " ) ) ;
}
}
if ( bLockStateModified )
{
ClearSelection ( ) ;
}
if ( bInTransaction )
{
GetTransactionsAPI ( ) - > EndUndoTransaction ( ) ;
}
}
void UGeometrySelectionManager : : SetTargetLockStateOnUndoRedo ( FGeometryIdentifier TargetIdentifier , bool bLocked )
{
for ( TSharedPtr < FGeometrySelectionTarget > Target : ActiveTargetReferences )
{
if ( Target - > TargetIdentifier = = TargetIdentifier )
{
Target - > Selector - > SetLockedState ( bLocked ) ;
}
}
}
2022-06-30 12:09:44 -04:00
TArray < FGeometryIdentifier > UGeometrySelectionManager : : GetCurrentTargetIdentifiers ( ) const
{
TArray < FGeometryIdentifier > Result ;
for ( TSharedPtr < FGeometrySelectionTarget > Target : ActiveTargetReferences )
{
Result . Add ( Target - > TargetIdentifier ) ;
}
return Result ;
}
void UGeometrySelectionManager : : SetTargetsOnUndoRedo ( TArray < FGeometryIdentifier > NewTargets )
{
check ( HasSelection ( ) = = false ) ;
ClearActiveTargets ( ) ;
for ( FGeometryIdentifier Identifier : NewTargets )
{
AddActiveTarget ( Identifier ) ;
}
}
void UGeometrySelectionManager : : SleepOrShutdownTarget ( FGeometrySelectionTarget * Target , bool bForceShutdown )
{
if ( Target - > Selector - > SupportsSleep ( ) & & bForceShutdown = = false )
{
bool bOK = Target - > Selector - > Sleep ( ) ;
check ( bOK ) ;
}
else
{
Target - > Selector - > GetOnGeometryModifed ( ) . Remove ( Target - > OnGeometryModifiedHandle ) ;
Target - > Selector - > Shutdown ( ) ;
}
}
TSharedPtr < UGeometrySelectionManager : : FGeometrySelectionTarget > UGeometrySelectionManager : : GetCachedTarget ( FGeometryIdentifier TargetIdentifier , const IGeometrySelectorFactory * UseFactory )
{
if ( TargetCache . Contains ( TargetIdentifier ) )
{
TSharedPtr < FGeometrySelectionTarget > FoundTarget = TargetCache [ TargetIdentifier ] ;
FoundTarget - > Selection . Reset ( ) ;
FoundTarget - > Selector - > Restore ( ) ;
// ensure these are current, as they may have changed while Target was asleep
FoundTarget - > Selection . ElementType = GetSelectionElementType ( ) ;
FoundTarget - > Selection . TopologyType = GetSelectionTopologyType ( ) ;
2022-12-01 16:11:52 -05:00
bool bEnableTopologyFilter = ( FoundTarget - > Selection . TopologyType = = EGeometryTopologyType : : Polygroup & & FoundTarget - > Selection . ElementType ! = EGeometryElementType : : Vertex ) ;
FoundTarget - > SelectionEditor - > UpdateQueryConfig ( GetCurrentSelectionQueryConfig ( ) , bEnableTopologyFilter ) ;
2022-06-30 12:09:44 -04:00
return FoundTarget ;
}
// if we are in a situation where we don't have a cache, currently we need the Factory to exist?
check ( UseFactory ! = nullptr ) ;
// selector has to be built properly
TUniquePtr < IGeometrySelector > Selector = UseFactory - > BuildForTarget ( TargetIdentifier ) ;
// not going to handle this for now...
check ( Selector . IsValid ( ) ) ;
TSharedPtr < FGeometrySelectionTarget > SelectionTarget = MakeShared < FGeometrySelectionTarget > ( ) ;
SelectionTarget - > Selector = MoveTemp ( Selector ) ;
SelectionTarget - > TargetIdentifier = TargetIdentifier ;
SelectionTarget - > SelectionIdentifer = SelectionTarget - > Selector - > GetIdentifier ( ) ;
SelectionTarget - > Selection . ElementType = GetSelectionElementType ( ) ;
SelectionTarget - > Selection . TopologyType = GetSelectionTopologyType ( ) ;
SelectionTarget - > SelectionEditor = MakeUnique < FGeometrySelectionEditor > ( ) ;
2022-11-28 19:15:40 -05:00
FGeometrySelectionHitQueryConfig HitQueryConfig = GetCurrentSelectionQueryConfig ( ) ;
2022-12-01 16:11:52 -05:00
bool bEnableTopologyFilter = ( HitQueryConfig . TopologyType = = EGeometryTopologyType : : Polygroup & & HitQueryConfig . ElementType ! = EGeometryElementType : : Vertex ) ;
SelectionTarget - > SelectionEditor - > Initialize ( & SelectionTarget - > Selection , HitQueryConfig , bEnableTopologyFilter ) ;
2022-06-30 12:09:44 -04:00
if ( SelectionTarget - > Selector - > SupportsSleep ( ) )
{
TargetCache . Add ( TargetIdentifier , SelectionTarget ) ;
}
return SelectionTarget ;
}
void UGeometrySelectionManager : : ResetTargetCache ( )
{
for ( TPair < FGeometryIdentifier , TSharedPtr < FGeometrySelectionTarget > > Pair : TargetCache )
{
SleepOrShutdownTarget ( Pair . Value . Get ( ) , true ) ;
}
TargetCache . Reset ( ) ;
}
bool UGeometrySelectionManager : : RayHitTest (
const FRay3d & WorldRay ,
FInputRayHit & HitResultOut )
{
HitResultOut = FInputRayHit ( ) ;
if ( ActiveTargetReferences . Num ( ) = = 0 )
{
return false ;
}
2022-11-28 19:15:40 -05:00
IGeometrySelector : : FWorldRayQueryInfo RayQueryInfo ;
RayQueryInfo . WorldRay = WorldRay ;
IToolsContextQueriesAPI * QueryAPI = this - > ToolsContext - > ToolManager - > GetContextQueriesAPI ( ) ;
QueryAPI - > GetCurrentViewState ( RayQueryInfo . CameraState ) ;
// currently only going to support one object, not sure how to support more yet...
FGeometrySelectionTarget * Target = ActiveTargetReferences [ 0 ] . Get ( ) ;
FGeometrySelectionHitQueryConfig HitQueryConfig = GetCurrentSelectionQueryConfig ( ) ;
bool bHit = Target - > Selector - > RayHitTest ( RayQueryInfo , HitQueryConfig , HitResultOut ) ;
2022-06-30 12:09:44 -04:00
if ( bHit )
{
HitResultOut . HitOwner = ActiveTargetReferences [ 0 ] . Get ( ) ;
HitResultOut . HitObject = ( ActiveTargetReferences [ 0 ] - > TargetIdentifier . TargetType = = FGeometryIdentifier : : ETargetType : : PrimitiveComponent ) ?
ActiveTargetReferences [ 0 ] - > TargetIdentifier . TargetObject : nullptr ;
}
// currently only going to support one object, not sure how to support more yet...
return bHit ;
}
void UGeometrySelectionManager : : ClearSelection ( )
{
if ( ! HasSelection ( ) )
{
return ;
}
GetTransactionsAPI ( ) - > BeginUndoTransaction ( LOCTEXT ( " ClearSelection " , " Clear Selection " ) ) ;
for ( TSharedPtr < FGeometrySelectionTarget > Target : ActiveTargetReferences )
{
FGeometrySelectionDelta ClearDelta ;
Target - > SelectionEditor - > ClearSelection ( ClearDelta ) ;
if ( ClearDelta . IsEmpty ( ) = = false )
{
TUniquePtr < FGeometrySelectionDeltaChange > ClearChange = MakeUnique < FGeometrySelectionDeltaChange > ( ) ;
2023-04-10 12:36:37 -04:00
ClearChange - > Identifier = Target - > TargetIdentifier ;
2022-06-30 12:09:44 -04:00
ClearChange - > Delta = MoveTemp ( ClearDelta ) ;
2022-06-30 14:13:04 -04:00
GetTransactionsAPI ( ) - > AppendChange ( this , MoveTemp ( ClearChange ) , LOCTEXT ( " ClearSelection " , " Clear Selection " ) ) ;
2022-06-30 12:09:44 -04:00
}
}
GetTransactionsAPI ( ) - > EndUndoTransaction ( ) ;
bSelectionRenderCachesDirty = true ;
OnSelectionModified . Broadcast ( ) ;
}
void UGeometrySelectionManager : : UpdateSelectionViaRaycast (
const FRay3d & WorldRay ,
const FGeometrySelectionUpdateConfig & UpdateConfig ,
FGeometrySelectionUpdateResult & ResultOut
)
{
ResultOut . bSelectionModified = false ;
if ( ActiveTargetReferences . Num ( ) = = 0 )
{
return ;
}
// currently only going to support one object, not sure how to support more yet...
FGeometrySelectionTarget * Target = ActiveTargetReferences [ 0 ] . Get ( ) ;
2022-11-28 19:15:40 -05:00
IGeometrySelector : : FWorldRayQueryInfo RayQueryInfo ;
RayQueryInfo . WorldRay = WorldRay ;
IToolsContextQueriesAPI * QueryAPI = this - > ToolsContext - > ToolManager - > GetContextQueriesAPI ( ) ;
QueryAPI - > GetCurrentViewState ( RayQueryInfo . CameraState ) ;
2022-06-30 12:09:44 -04:00
Target - > Selector - > UpdateSelectionViaRaycast (
2022-11-28 19:15:40 -05:00
RayQueryInfo , * Target - > SelectionEditor , UpdateConfig , ResultOut
2022-06-30 12:09:44 -04:00
) ;
if ( ResultOut . bSelectionModified )
{
TUniquePtr < FGeometrySelectionDeltaChange > DeltaChange = MakeUnique < FGeometrySelectionDeltaChange > ( ) ;
2023-04-10 12:36:37 -04:00
DeltaChange - > Identifier = Target - > TargetIdentifier ;
2022-06-30 12:09:44 -04:00
DeltaChange - > Delta = ResultOut . SelectionDelta ;
GetTransactionsAPI ( ) - > BeginUndoTransaction ( LOCTEXT ( " UpdateSelectionViaRaycast " , " Change Selection " ) ) ;
GetTransactionsAPI ( ) - > AppendChange ( this , MoveTemp ( DeltaChange ) , LOCTEXT ( " UpdateSelectionViaRaycast " , " Change Selection " ) ) ;
GetTransactionsAPI ( ) - > EndUndoTransaction ( ) ;
bSelectionRenderCachesDirty = true ;
OnSelectionModified . Broadcast ( ) ;
}
else if ( ResultOut . bSelectionMissed & & UpdateConfig . ChangeType = = EGeometrySelectionChangeType : : Replace )
{
ClearSelection ( ) ;
}
}
2023-01-20 15:30:23 -05:00
void UGeometrySelectionManager : : UpdateSelectionViaConvex (
const FConvexVolume & ConvexVolume ,
const FGeometrySelectionUpdateConfig & UpdateConfig ,
FGeometrySelectionUpdateResult & ResultOut )
{
ResultOut . bSelectionModified = false ;
if ( ActiveTargetReferences . Num ( ) = = 0 )
{
return ;
}
// currently only going to support one object, not sure how to support more yet...
FGeometrySelectionTarget * Target = ActiveTargetReferences [ 0 ] . Get ( ) ;
IGeometrySelector : : FWorldShapeQueryInfo ShapeQueryInfo ;
ShapeQueryInfo . Convex = ConvexVolume ;
IToolsContextQueriesAPI * QueryAPI = this - > ToolsContext - > ToolManager - > GetContextQueriesAPI ( ) ;
QueryAPI - > GetCurrentViewState ( ShapeQueryInfo . CameraState ) ;
Target - > Selector - > UpdateSelectionViaShape (
ShapeQueryInfo , * Target - > SelectionEditor , UpdateConfig , ResultOut ) ;
if ( ResultOut . bSelectionModified )
{
TUniquePtr < FGeometrySelectionDeltaChange > DeltaChange = MakeUnique < FGeometrySelectionDeltaChange > ( ) ;
2023-04-10 12:36:37 -04:00
DeltaChange - > Identifier = Target - > TargetIdentifier ;
2023-01-20 15:30:23 -05:00
DeltaChange - > Delta = ResultOut . SelectionDelta ;
GetTransactionsAPI ( ) - > BeginUndoTransaction ( LOCTEXT ( " UpdateSelectionViaConvex " , " Change Selection " ) ) ;
GetTransactionsAPI ( ) - > AppendChange ( this , MoveTemp ( DeltaChange ) , LOCTEXT ( " UpdateSelectionViaConvex " , " Change Selection " ) ) ;
GetTransactionsAPI ( ) - > EndUndoTransaction ( ) ;
bSelectionRenderCachesDirty = true ;
OnSelectionModified . Broadcast ( ) ;
}
else if ( ResultOut . bSelectionMissed & & UpdateConfig . ChangeType = = EGeometrySelectionChangeType : : Replace )
{
ClearSelection ( ) ;
}
}
2022-12-01 16:11:52 -05:00
bool UGeometrySelectionManager : : CanBeginTrackedSelectionChange ( ) const
{
return ActiveTargetReferences . Num ( ) > 0 & & bInTrackedSelectionChange = = false ;
}
bool UGeometrySelectionManager : : BeginTrackedSelectionChange ( FGeometrySelectionUpdateConfig UpdateConfig , bool bClearOnBegin )
{
if ( ensureMsgf ( CanBeginTrackedSelectionChange ( ) , TEXT ( " Cannot begin Selection Change - validate CanBeginTrackedSelectionChange() before calling BeginTrackedSelectionChange() " ) ) = = false )
{
return false ;
}
GetTransactionsAPI ( ) - > BeginUndoTransaction ( LOCTEXT ( " ChangeSelection " , " Change Selection " ) ) ;
bInTrackedSelectionChange = true ;
// currently only going to support one object, not sure how to support more yet...
FGeometrySelectionTarget * Target = ActiveTargetReferences [ 0 ] . Get ( ) ;
ActiveTrackedUpdateConfig = UpdateConfig ;
bSelectionModifiedDuringTrackedChange = false ;
// if we are doing a Replace selection, we want to clear on initialization...
InitialTrackedDelta = FGeometrySelectionDelta ( ) ;
if ( bClearOnBegin )
{
Target - > SelectionEditor - > ClearSelection ( InitialTrackedDelta ) ;
bSelectionModifiedDuringTrackedChange = true ;
}
ActiveTrackedSelection = Target - > Selection ;
ActiveTrackedDelta = FGeometrySelectionDelta ( ) ;
if ( bClearOnBegin & & InitialTrackedDelta . IsEmpty ( ) = = false )
{
bSelectionRenderCachesDirty = true ;
OnSelectionModified . Broadcast ( ) ;
}
return true ;
}
void UGeometrySelectionManager : : AccumulateSelectionUpdate_Raycast (
const FRay3d & WorldRay ,
FGeometrySelectionUpdateResult & ResultOut )
{
if ( ! ensure ( bInTrackedSelectionChange ) ) return ;
// currently only going to support one object, not sure how to support more yet...
FGeometrySelectionTarget * Target = ActiveTargetReferences [ 0 ] . Get ( ) ;
IGeometrySelector : : FWorldRayQueryInfo RayQueryInfo ;
RayQueryInfo . WorldRay = WorldRay ;
IToolsContextQueriesAPI * QueryAPI = this - > ToolsContext - > ToolManager - > GetContextQueriesAPI ( ) ;
QueryAPI - > GetCurrentViewState ( RayQueryInfo . CameraState ) ;
Target - > Selector - > UpdateSelectionViaRaycast (
ModelingMode: Selection system improvements. Add Disconnect command and various new Selection-Edit Commands
Add UInteractiveCommandResult, UInteractiveCommand::ExecuteCommand() now optionally can return a result subclass
Add UGeometrySelectionEditCommandResult, UGeometrySelectionEditCommand now can optionally return an "output" selection via this type
UGeometrySelectionManager::ExecuteSelectionCommand optionally can restore a selection after a command, via UGeometrySelectionEditCommandResult
Add UDisconnectGeometrySelectionCommand, implements disconnection of selected triangles (ie separates but not into a new mesh)
Add UModifyGeometrySelectionCommand, implements various selection edits (select all, expand to connected, invert, invert connected, expand, contract)
Add IGeometrySelector::InitializeSelectionFromPredicate() and ::UpdateSelectionFromSelection(), implement in UDynamicMeshSelector, used to implement selection edit commands
Add UI to enable new commands in Modeling Mode
#rb none
#preflight 63c047f4305002c64170f6a2
[CL 23667880 by ryan schmidt in ue5-main branch]
2023-01-12 14:52:52 -05:00
RayQueryInfo , * Target - > SelectionEditor , ActiveTrackedUpdateConfig , ResultOut ) ;
2022-12-01 16:11:52 -05:00
if ( ResultOut . bSelectionModified )
{
bSelectionModifiedDuringTrackedChange = true ;
ActiveTrackedDelta . Added . Append ( ResultOut . SelectionDelta . Added ) ;
ActiveTrackedDelta . Removed . Append ( ResultOut . SelectionDelta . Removed ) ;
bSelectionRenderCachesDirty = true ;
OnSelectionModified . Broadcast ( ) ;
}
}
void UGeometrySelectionManager : : EndTrackedSelectionChange ( )
{
if ( ensure ( bInTrackedSelectionChange ) )
{
if ( bSelectionModifiedDuringTrackedChange )
{
FGeometrySelectionTarget * Target = ActiveTargetReferences [ 0 ] . Get ( ) ;
if ( InitialTrackedDelta . IsEmpty ( ) = = false )
{
TUniquePtr < FGeometrySelectionDeltaChange > InitialDeltaChange = MakeUnique < FGeometrySelectionDeltaChange > ( ) ;
2023-04-10 12:36:37 -04:00
InitialDeltaChange - > Identifier = Target - > TargetIdentifier ;
2022-12-01 16:11:52 -05:00
InitialDeltaChange - > Delta = MoveTemp ( InitialTrackedDelta ) ;
GetTransactionsAPI ( ) - > AppendChange ( this , MoveTemp ( InitialDeltaChange ) , LOCTEXT ( " ChangeSelection " , " Change Selection " ) ) ;
}
if ( ActiveTrackedDelta . IsEmpty ( ) = = false )
{
TUniquePtr < FGeometrySelectionDeltaChange > AccumDeltaChange = MakeUnique < FGeometrySelectionDeltaChange > ( ) ;
2023-04-10 12:36:37 -04:00
AccumDeltaChange - > Identifier = Target - > TargetIdentifier ;
2022-12-01 16:11:52 -05:00
AccumDeltaChange - > Delta = MoveTemp ( ActiveTrackedDelta ) ;
GetTransactionsAPI ( ) - > AppendChange ( this , MoveTemp ( AccumDeltaChange ) , LOCTEXT ( " ChangeSelection " , " Change Selection " ) ) ;
}
}
GetTransactionsAPI ( ) - > EndUndoTransaction ( ) ;
bInTrackedSelectionChange = false ;
}
}
ModelingMode: improve interop with new Selection System and existing Tools
Add support for Tools to provide an "output" selection. Add UGeometrySelectionManager::SetSelectionForComponent() which can set an explicit externally-provided selection. FBaseDynamicMeshSelector::UpdateSelectionFromSelection() now supports selection conversion when available and requested (is used to implement SetSelectionForComponent). New GeometrySelectionUtil functions InitializeSelectionFromTriangles() and ConvertSelection() are used to implement this (note: only Triangles->other conversion is currently supported). Add HaveAvailableGeometrySelection() and SetToolOutputGeometrySelectionForTarget() in StoredMeshSelectionUtil.h, this is the top-level function that Tools can use to set an Output selection.
ExtrudeMeshSelectionTool now emits output selection.
Update EditMeshPolygonsTool to use new Selection system and allow individual operations to be utilized as standalone Tools. Convert EditMeshPolygonsTool to be a USingleTargetWithSelectionTool, use FGeometrySelection to initialize selection. Add bTerminateOnPendingActionComplete flag, which is set when Tool is directly initialized to a specific operation, and forces tool to shut down when operation completes. This allows it to be used to more cleanly implement multiple action buttons in Modeling UI. When in this mode, selection panels are not shown. On Shutdown, now emits an "output" selection which GeometrySelectionManager can use to provide new selection to user. Update UPolygonSelectionMechanic Set/Get selection APIs to use FGeometrySelection instead of UPersistentMeshSelection.
port UVProjectionTool to derive from USingleTargetWithSelectionTool, use FGeometrySelection to initialize target ROI
deprecate UPersistentMeshSelection and related functions in StoredMeshSelectionUtil.h. Deprecate Tool Input Selection APIs in USingleSelectionMeshEditingTool and Builder.
Repurpose old ModelingMode-level PolyModel tab operations for new Selection Tools UI, now support Inset, Outset, Cut Faces, Insert Edge Loop, PushPull, and Bevel.
#rb none
#preflight 63c84fa2b065224750b9831f
[CL 23766643 by ryan schmidt in ue5-main branch]
2023-01-18 17:59:31 -05:00
bool UGeometrySelectionManager : : SetSelectionForComponent ( UPrimitiveComponent * Component , const FGeometrySelection & NewSelection )
{
for ( TSharedPtr < FGeometrySelectionTarget > Target : ActiveTargetReferences )
{
if ( Target - > TargetIdentifier . TargetObject = = Component )
{
FGeometrySelection InitialSelection = Target - > Selection ;
FGeometrySelectionDelta AfterDelta ;
Target - > Selector - > UpdateSelectionFromSelection (
NewSelection , true , * Target - > SelectionEditor ,
FGeometrySelectionUpdateConfig { EGeometrySelectionChangeType : : Replace } , & AfterDelta ) ;
if ( AfterDelta . IsEmpty ( ) = = false )
{
TUniquePtr < FGeometrySelectionReplaceChange > NewSelectionChange = MakeUnique < FGeometrySelectionReplaceChange > ( ) ;
2023-04-10 12:36:37 -04:00
NewSelectionChange - > Identifier = Target - > TargetIdentifier ; //Target->Selector->GetIdentifier();
ModelingMode: improve interop with new Selection System and existing Tools
Add support for Tools to provide an "output" selection. Add UGeometrySelectionManager::SetSelectionForComponent() which can set an explicit externally-provided selection. FBaseDynamicMeshSelector::UpdateSelectionFromSelection() now supports selection conversion when available and requested (is used to implement SetSelectionForComponent). New GeometrySelectionUtil functions InitializeSelectionFromTriangles() and ConvertSelection() are used to implement this (note: only Triangles->other conversion is currently supported). Add HaveAvailableGeometrySelection() and SetToolOutputGeometrySelectionForTarget() in StoredMeshSelectionUtil.h, this is the top-level function that Tools can use to set an Output selection.
ExtrudeMeshSelectionTool now emits output selection.
Update EditMeshPolygonsTool to use new Selection system and allow individual operations to be utilized as standalone Tools. Convert EditMeshPolygonsTool to be a USingleTargetWithSelectionTool, use FGeometrySelection to initialize selection. Add bTerminateOnPendingActionComplete flag, which is set when Tool is directly initialized to a specific operation, and forces tool to shut down when operation completes. This allows it to be used to more cleanly implement multiple action buttons in Modeling UI. When in this mode, selection panels are not shown. On Shutdown, now emits an "output" selection which GeometrySelectionManager can use to provide new selection to user. Update UPolygonSelectionMechanic Set/Get selection APIs to use FGeometrySelection instead of UPersistentMeshSelection.
port UVProjectionTool to derive from USingleTargetWithSelectionTool, use FGeometrySelection to initialize target ROI
deprecate UPersistentMeshSelection and related functions in StoredMeshSelectionUtil.h. Deprecate Tool Input Selection APIs in USingleSelectionMeshEditingTool and Builder.
Repurpose old ModelingMode-level PolyModel tab operations for new Selection Tools UI, now support Inset, Outset, Cut Faces, Insert Edge Loop, PushPull, and Bevel.
#rb none
#preflight 63c84fa2b065224750b9831f
[CL 23766643 by ryan schmidt in ue5-main branch]
2023-01-18 17:59:31 -05:00
NewSelectionChange - > After = Target - > Selection ;
NewSelectionChange - > Before = InitialSelection ;
GetTransactionsAPI ( ) - > AppendChange ( this , MoveTemp ( NewSelectionChange ) , LOCTEXT ( " NewSelection " , " New Selection " ) ) ;
2022-12-01 16:11:52 -05:00
ModelingMode: improve interop with new Selection System and existing Tools
Add support for Tools to provide an "output" selection. Add UGeometrySelectionManager::SetSelectionForComponent() which can set an explicit externally-provided selection. FBaseDynamicMeshSelector::UpdateSelectionFromSelection() now supports selection conversion when available and requested (is used to implement SetSelectionForComponent). New GeometrySelectionUtil functions InitializeSelectionFromTriangles() and ConvertSelection() are used to implement this (note: only Triangles->other conversion is currently supported). Add HaveAvailableGeometrySelection() and SetToolOutputGeometrySelectionForTarget() in StoredMeshSelectionUtil.h, this is the top-level function that Tools can use to set an Output selection.
ExtrudeMeshSelectionTool now emits output selection.
Update EditMeshPolygonsTool to use new Selection system and allow individual operations to be utilized as standalone Tools. Convert EditMeshPolygonsTool to be a USingleTargetWithSelectionTool, use FGeometrySelection to initialize selection. Add bTerminateOnPendingActionComplete flag, which is set when Tool is directly initialized to a specific operation, and forces tool to shut down when operation completes. This allows it to be used to more cleanly implement multiple action buttons in Modeling UI. When in this mode, selection panels are not shown. On Shutdown, now emits an "output" selection which GeometrySelectionManager can use to provide new selection to user. Update UPolygonSelectionMechanic Set/Get selection APIs to use FGeometrySelection instead of UPersistentMeshSelection.
port UVProjectionTool to derive from USingleTargetWithSelectionTool, use FGeometrySelection to initialize target ROI
deprecate UPersistentMeshSelection and related functions in StoredMeshSelectionUtil.h. Deprecate Tool Input Selection APIs in USingleSelectionMeshEditingTool and Builder.
Repurpose old ModelingMode-level PolyModel tab operations for new Selection Tools UI, now support Inset, Outset, Cut Faces, Insert Edge Loop, PushPull, and Bevel.
#rb none
#preflight 63c84fa2b065224750b9831f
[CL 23766643 by ryan schmidt in ue5-main branch]
2023-01-18 17:59:31 -05:00
bSelectionRenderCachesDirty = true ;
OnSelectionModified . Broadcast ( ) ;
}
return true ;
}
}
return false ;
}
2022-12-01 16:11:52 -05:00
2022-06-30 12:09:44 -04:00
2022-11-28 19:15:40 -05:00
bool UGeometrySelectionManager : : UpdateSelectionPreviewViaRaycast (
const FRay3d & WorldRay )
{
if ( ActiveTargetReferences . Num ( ) = = 0 )
{
return false ;
}
bool bUseSimplifiedPreviewHighlight = ( CVarGeometrySelectionManager_FullSelectionHoverHighlights . GetValueOnGameThread ( ) = = 0 ) ;
// currently only going to support one object, not sure how to support more yet...
FGeometrySelectionTarget * Target = ActiveTargetReferences [ 0 ] . Get ( ) ;
IGeometrySelector : : FWorldRayQueryInfo RayQueryInfo ;
RayQueryInfo . WorldRay = WorldRay ;
IToolsContextQueriesAPI * QueryAPI = this - > ToolsContext - > ToolManager - > GetContextQueriesAPI ( ) ;
QueryAPI - > GetCurrentViewState ( RayQueryInfo . CameraState ) ;
FGeometrySelectionPreview NewPreview ( * ( Target - > SelectionEditor ) ) ;
Target - > Selector - > GetSelectionPreviewForRaycast ( RayQueryInfo , NewPreview ) ;
if ( ! UE : : Geometry : : AreSelectionsIdentical ( NewPreview . PreviewSelection , ActivePreviewSelection ) )
{
ActivePreviewSelection = MoveTemp ( NewPreview . PreviewSelection ) ;
CachedPreviewRenderElements . Reset ( ) ;
if ( ActivePreviewSelection . IsEmpty ( ) = = false )
{
Target - > Selector - > AccumulateSelectionElements ( ActivePreviewSelection , CachedPreviewRenderElements , true , bUseSimplifiedPreviewHighlight ) ;
}
}
return ( ActivePreviewSelection . IsEmpty ( ) = = false ) ;
}
void UGeometrySelectionManager : : ClearSelectionPreview ( )
{
ActivePreviewSelection . Selection . Reset ( ) ;
CachedPreviewRenderElements . Reset ( ) ;
}
2022-06-30 12:09:44 -04:00
bool UGeometrySelectionManager : : GetSelectionBounds ( FGeometrySelectionBounds & BoundsOut ) const
{
BoundsOut = FGeometrySelectionBounds ( ) ;
for ( TSharedPtr < FGeometrySelectionTarget > Target : ActiveTargetReferences )
{
Target - > Selector - > AccumulateSelectionBounds ( Target - > Selection , BoundsOut , true ) ;
}
return ( BoundsOut . WorldBounds . IsEmpty ( ) = = false ) ;
}
void UGeometrySelectionManager : : GetSelectionWorldFrame ( FFrame3d & SelectionFrame ) const
{
SelectionFrame = FFrame3d ( ) ;
if ( HasSelection ( ) )
{
// only handling this case for now
//if (ActiveTargetReferences.Num() == 1)
TSharedPtr < FGeometrySelectionTarget > Target = ActiveTargetReferences [ 0 ] ;
Target - > Selector - > GetSelectionFrame ( Target - > Selection , SelectionFrame , true ) ;
}
}
bool UGeometrySelectionManager : : HasSelectionForComponent ( UPrimitiveComponent * Component ) const
{
if ( HasSelection ( ) )
{
for ( TSharedPtr < FGeometrySelectionTarget > Target : ActiveTargetReferences )
{
if ( Target - > TargetIdentifier . TargetObject = = Component )
{
return Target - > Selection . IsEmpty ( ) ;
}
}
}
return false ;
}
bool UGeometrySelectionManager : : GetSelectionForComponent ( UPrimitiveComponent * Component , FGeometrySelection & SelectionOut ) const
{
if ( HasSelection ( ) )
{
for ( TSharedPtr < FGeometrySelectionTarget > Target : ActiveTargetReferences )
{
if ( Target - > TargetIdentifier . TargetObject = = Component )
{
SelectionOut = Target - > Selection ;
return ! Target - > Selection . IsEmpty ( ) ;
}
}
}
return false ;
}
bool UGeometrySelectionManager : : BeginTransformation ( )
{
if ( ! ensure ( IsInActiveTransformation ( ) = = false ) )
{
return false ;
}
if ( HasSelection ( ) = = false )
{
return false ;
}
bool bHaveTransformers = false ;
for ( TSharedPtr < FGeometrySelectionTarget > Target : ActiveTargetReferences )
{
IGeometrySelectionTransformer * Transformer = Target - > Selector - > InitializeTransformation ( Target - > Selection ) ;
if ( Transformer ! = nullptr )
{
Transformer - > BeginTransform ( Target - > Selection ) ;
ActiveTransformations . Add ( Transformer ) ;
bHaveTransformers = true ;
}
else
{
ActiveTransformations . Add ( nullptr ) ;
}
}
if ( ! bHaveTransformers )
{
ActiveTransformations . Reset ( ) ;
return false ;
}
return true ;
}
void UGeometrySelectionManager : : UpdateTransformation (
TFunctionRef < FVector3d ( int32 VertexID , const FVector3d & , const FTransform & ) > PositionTransformFunc )
{
if ( ! ensure ( IsInActiveTransformation ( ) ) ) return ;
for ( int32 k = 0 ; k < ActiveTargetReferences . Num ( ) ; + + k )
{
if ( ActiveTransformations [ k ] ! = nullptr )
{
ActiveTransformations [ k ] - > UpdateTransform ( PositionTransformFunc ) ;
}
}
bSelectionRenderCachesDirty = true ;
}
void UGeometrySelectionManager : : EndTransformation ( )
{
if ( ! ensure ( IsInActiveTransformation ( ) ) ) return ;
GetTransactionsAPI ( ) - > BeginUndoTransaction ( LOCTEXT ( " EndTransformation " , " Transform Selection " ) ) ;
for ( int32 k = 0 ; k < ActiveTargetReferences . Num ( ) ; + + k )
{
if ( ActiveTransformations [ k ] ! = nullptr )
{
ActiveTransformations [ k ] - > EndTransform ( GetTransactionsAPI ( ) ) ;
ActiveTargetReferences [ k ] - > Selector - > ShutdownTransformation ( ActiveTransformations [ k ] ) ;
}
}
ActiveTransformations . Reset ( ) ;
GetTransactionsAPI ( ) - > EndUndoTransaction ( ) ;
bSelectionRenderCachesDirty = true ;
}
2022-07-15 13:49:13 -04:00
bool UGeometrySelectionManager : : CanExecuteSelectionCommand ( UGeometrySelectionEditCommand * Command )
{
if ( SelectionArguments = = nullptr )
{
SelectionArguments = NewObject < UGeometrySelectionEditCommandArguments > ( ) ;
}
bool bCanExecute = true ;
bool bHaveSelections = false ;
ProcessActiveSelections ( [ & ] ( FGeometrySelectionHandle Handle )
{
SelectionArguments - > SelectionHandle = Handle ;
SelectionArguments - > SetTransactionsAPI ( TransactionsAPI ) ;
bCanExecute = bCanExecute & & Command - > CanExecuteCommand ( SelectionArguments ) ;
bHaveSelections = true ;
} ) ;
2023-01-21 13:02:53 -05:00
return ( bHaveSelections | | ( Command - > AllowEmptySelection ( ) & & HasActiveTargets ( ) & & MeshTopologyMode ! = EMeshTopologyMode : : None ) ) & & bCanExecute ;
2022-07-15 13:49:13 -04:00
}
void UGeometrySelectionManager : : ExecuteSelectionCommand ( UGeometrySelectionEditCommand * Command )
{
if ( SelectionArguments = = nullptr )
{
SelectionArguments = NewObject < UGeometrySelectionEditCommandArguments > ( ) ;
}
// open transaction to wrap the entire set of Commands and selection changes
FText CommandText = Command - > GetCommandShortString ( ) ;
GetTransactionsAPI ( ) - > BeginUndoTransaction ( CommandText ) ;
for ( TSharedPtr < FGeometrySelectionTarget > Target : ActiveTargetReferences )
{
2023-01-21 13:02:53 -05:00
if ( Target - > Selection . IsEmpty ( ) & & Command - > AllowEmptySelection ( ) = = false ) continue ;
2022-07-15 13:49:13 -04:00
ModelingMode: Selection system improvements. Add Disconnect command and various new Selection-Edit Commands
Add UInteractiveCommandResult, UInteractiveCommand::ExecuteCommand() now optionally can return a result subclass
Add UGeometrySelectionEditCommandResult, UGeometrySelectionEditCommand now can optionally return an "output" selection via this type
UGeometrySelectionManager::ExecuteSelectionCommand optionally can restore a selection after a command, via UGeometrySelectionEditCommandResult
Add UDisconnectGeometrySelectionCommand, implements disconnection of selected triangles (ie separates but not into a new mesh)
Add UModifyGeometrySelectionCommand, implements various selection edits (select all, expand to connected, invert, invert connected, expand, contract)
Add IGeometrySelector::InitializeSelectionFromPredicate() and ::UpdateSelectionFromSelection(), implement in UDynamicMeshSelector, used to implement selection edit commands
Add UI to enable new commands in Modeling Mode
#rb none
#preflight 63c047f4305002c64170f6a2
[CL 23667880 by ryan schmidt in ue5-main branch]
2023-01-12 14:52:52 -05:00
// TODO: can use Command->IsModifySelectionCommand() to check if this is a command that only affects selection
// and not geometry. In that case we can skip the intermediate clear-selection and emit a single change.
2022-07-15 13:49:13 -04:00
// When initially executing the command, we do not clear the selection, because we pass it to the command.
// However, when we later *undo* any changes emitted by the command, we need to restore the selection aftewards.
// So we emit a clearing change here, so that undo un-clears.
// When we later Redo, it is also necessary to Clear as otherwise an invalid Selection might hang around.
// Note that this must happen *before* the Command. The Command will not be re-executed, only its emitted Changes,
// so it will not be holding onto the active Selection on Redo later
// (if that becomes necessary, this sequence of changes will need to become more complicated....)
TUniquePtr < FGeometrySelectionReplaceChange > ClearChange = MakeUnique < FGeometrySelectionReplaceChange > ( ) ;
2023-04-10 12:36:37 -04:00
ClearChange - > Identifier = Target - > TargetIdentifier ; //Target->Selector->GetIdentifier();
2022-07-15 13:49:13 -04:00
ClearChange - > Before = Target - > Selection ;
ClearChange - > After . InitializeTypes ( ClearChange - > Before ) ;
GetTransactionsAPI ( ) - > AppendChange ( this , MoveTemp ( ClearChange ) , LOCTEXT ( " ClearSelection " , " Clear Selection " ) ) ;
// q: we could clear the selection here, and pass the Handle a copy. Perhaps safer?
ModelingMode: Selection system improvements. Add Disconnect command and various new Selection-Edit Commands
Add UInteractiveCommandResult, UInteractiveCommand::ExecuteCommand() now optionally can return a result subclass
Add UGeometrySelectionEditCommandResult, UGeometrySelectionEditCommand now can optionally return an "output" selection via this type
UGeometrySelectionManager::ExecuteSelectionCommand optionally can restore a selection after a command, via UGeometrySelectionEditCommandResult
Add UDisconnectGeometrySelectionCommand, implements disconnection of selected triangles (ie separates but not into a new mesh)
Add UModifyGeometrySelectionCommand, implements various selection edits (select all, expand to connected, invert, invert connected, expand, contract)
Add IGeometrySelector::InitializeSelectionFromPredicate() and ::UpdateSelectionFromSelection(), implement in UDynamicMeshSelector, used to implement selection edit commands
Add UI to enable new commands in Modeling Mode
#rb none
#preflight 63c047f4305002c64170f6a2
[CL 23667880 by ryan schmidt in ue5-main branch]
2023-01-12 14:52:52 -05:00
UInteractiveCommandResult * ResultPtr = nullptr ;
SelectionArguments - > SelectionHandle = FGeometrySelectionHandle { Target - > Selector - > GetIdentifier ( ) , & Target - > Selection , Target - > Selector . Get ( ) } ;
2022-07-15 13:49:13 -04:00
SelectionArguments - > SetTransactionsAPI ( TransactionsAPI ) ;
ModelingMode: Selection system improvements. Add Disconnect command and various new Selection-Edit Commands
Add UInteractiveCommandResult, UInteractiveCommand::ExecuteCommand() now optionally can return a result subclass
Add UGeometrySelectionEditCommandResult, UGeometrySelectionEditCommand now can optionally return an "output" selection via this type
UGeometrySelectionManager::ExecuteSelectionCommand optionally can restore a selection after a command, via UGeometrySelectionEditCommandResult
Add UDisconnectGeometrySelectionCommand, implements disconnection of selected triangles (ie separates but not into a new mesh)
Add UModifyGeometrySelectionCommand, implements various selection edits (select all, expand to connected, invert, invert connected, expand, contract)
Add IGeometrySelector::InitializeSelectionFromPredicate() and ::UpdateSelectionFromSelection(), implement in UDynamicMeshSelector, used to implement selection edit commands
Add UI to enable new commands in Modeling Mode
#rb none
#preflight 63c047f4305002c64170f6a2
[CL 23667880 by ryan schmidt in ue5-main branch]
2023-01-12 14:52:52 -05:00
Command - > ExecuteCommand ( SelectionArguments , & ResultPtr ) ;
2022-07-15 13:49:13 -04:00
ModelingMode: Selection system improvements. Add Disconnect command and various new Selection-Edit Commands
Add UInteractiveCommandResult, UInteractiveCommand::ExecuteCommand() now optionally can return a result subclass
Add UGeometrySelectionEditCommandResult, UGeometrySelectionEditCommand now can optionally return an "output" selection via this type
UGeometrySelectionManager::ExecuteSelectionCommand optionally can restore a selection after a command, via UGeometrySelectionEditCommandResult
Add UDisconnectGeometrySelectionCommand, implements disconnection of selected triangles (ie separates but not into a new mesh)
Add UModifyGeometrySelectionCommand, implements various selection edits (select all, expand to connected, invert, invert connected, expand, contract)
Add IGeometrySelector::InitializeSelectionFromPredicate() and ::UpdateSelectionFromSelection(), implement in UDynamicMeshSelector, used to implement selection edit commands
Add UI to enable new commands in Modeling Mode
#rb none
#preflight 63c047f4305002c64170f6a2
[CL 23667880 by ryan schmidt in ue5-main branch]
2023-01-12 14:52:52 -05:00
// actually clear selection after executing command.
2022-07-15 13:49:13 -04:00
FGeometrySelectionDelta ClearDelta ;
Target - > SelectionEditor - > ClearSelection ( ClearDelta ) ;
ModelingMode: Selection system improvements. Add Disconnect command and various new Selection-Edit Commands
Add UInteractiveCommandResult, UInteractiveCommand::ExecuteCommand() now optionally can return a result subclass
Add UGeometrySelectionEditCommandResult, UGeometrySelectionEditCommand now can optionally return an "output" selection via this type
UGeometrySelectionManager::ExecuteSelectionCommand optionally can restore a selection after a command, via UGeometrySelectionEditCommandResult
Add UDisconnectGeometrySelectionCommand, implements disconnection of selected triangles (ie separates but not into a new mesh)
Add UModifyGeometrySelectionCommand, implements various selection edits (select all, expand to connected, invert, invert connected, expand, contract)
Add IGeometrySelector::InitializeSelectionFromPredicate() and ::UpdateSelectionFromSelection(), implement in UDynamicMeshSelector, used to implement selection edit commands
Add UI to enable new commands in Modeling Mode
#rb none
#preflight 63c047f4305002c64170f6a2
[CL 23667880 by ryan schmidt in ue5-main branch]
2023-01-12 14:52:52 -05:00
// if selection returned a result, and it was a non-empty selection, select it
if ( UGeometrySelectionEditCommandResult * SelectionResult = Cast < UGeometrySelectionEditCommandResult > ( ResultPtr ) )
{
if ( SelectionResult - > OutputSelection . IsEmpty ( ) = = false )
{
FGeometrySelectionDelta AfterDelta ;
Target - > Selector - > UpdateSelectionFromSelection (
SelectionResult - > OutputSelection , true , * Target - > SelectionEditor ,
FGeometrySelectionUpdateConfig { EGeometrySelectionChangeType : : Add } , & AfterDelta ) ;
if ( Target - > Selection . IsEmpty ( ) = = false )
{
TUniquePtr < FGeometrySelectionReplaceChange > NewSelectionChange = MakeUnique < FGeometrySelectionReplaceChange > ( ) ;
2023-04-10 12:36:37 -04:00
NewSelectionChange - > Identifier = Target - > TargetIdentifier ; //Target->Selector->GetIdentifier();
ModelingMode: Selection system improvements. Add Disconnect command and various new Selection-Edit Commands
Add UInteractiveCommandResult, UInteractiveCommand::ExecuteCommand() now optionally can return a result subclass
Add UGeometrySelectionEditCommandResult, UGeometrySelectionEditCommand now can optionally return an "output" selection via this type
UGeometrySelectionManager::ExecuteSelectionCommand optionally can restore a selection after a command, via UGeometrySelectionEditCommandResult
Add UDisconnectGeometrySelectionCommand, implements disconnection of selected triangles (ie separates but not into a new mesh)
Add UModifyGeometrySelectionCommand, implements various selection edits (select all, expand to connected, invert, invert connected, expand, contract)
Add IGeometrySelector::InitializeSelectionFromPredicate() and ::UpdateSelectionFromSelection(), implement in UDynamicMeshSelector, used to implement selection edit commands
Add UI to enable new commands in Modeling Mode
#rb none
#preflight 63c047f4305002c64170f6a2
[CL 23667880 by ryan schmidt in ue5-main branch]
2023-01-12 14:52:52 -05:00
NewSelectionChange - > After = Target - > Selection ;
NewSelectionChange - > Before . InitializeTypes ( Target - > Selection ) ;
GetTransactionsAPI ( ) - > AppendChange ( this , MoveTemp ( NewSelectionChange ) , LOCTEXT ( " NewSelection " , " New Selection " ) ) ;
}
}
}
2022-07-15 13:49:13 -04:00
}
GetTransactionsAPI ( ) - > EndUndoTransaction ( ) ;
// assume this is true for now
bSelectionRenderCachesDirty = true ;
OnSelectionModified . Broadcast ( ) ;
}
void UGeometrySelectionManager : : ProcessActiveSelections ( TFunctionRef < void ( FGeometrySelectionHandle ) > ProcessFunc )
{
for ( TSharedPtr < FGeometrySelectionTarget > Target : ActiveTargetReferences )
{
if ( Target - > Selection . IsEmpty ( ) = = false )
{
FGeometrySelectionHandle Handle ;
Handle . Selection = & Target - > Selection ;
Handle . Identifier = Target - > Selector - > GetIdentifier ( ) ;
ModelingMode: Selection system improvements. Add Disconnect command and various new Selection-Edit Commands
Add UInteractiveCommandResult, UInteractiveCommand::ExecuteCommand() now optionally can return a result subclass
Add UGeometrySelectionEditCommandResult, UGeometrySelectionEditCommand now can optionally return an "output" selection via this type
UGeometrySelectionManager::ExecuteSelectionCommand optionally can restore a selection after a command, via UGeometrySelectionEditCommandResult
Add UDisconnectGeometrySelectionCommand, implements disconnection of selected triangles (ie separates but not into a new mesh)
Add UModifyGeometrySelectionCommand, implements various selection edits (select all, expand to connected, invert, invert connected, expand, contract)
Add IGeometrySelector::InitializeSelectionFromPredicate() and ::UpdateSelectionFromSelection(), implement in UDynamicMeshSelector, used to implement selection edit commands
Add UI to enable new commands in Modeling Mode
#rb none
#preflight 63c047f4305002c64170f6a2
[CL 23667880 by ryan schmidt in ue5-main branch]
2023-01-12 14:52:52 -05:00
Handle . Selector = Target - > Selector . Get ( ) ;
2022-07-15 13:49:13 -04:00
ProcessFunc ( Handle ) ;
}
}
}
2022-06-30 12:09:44 -04:00
void UGeometrySelectionManager : : ApplyChange ( IGeometrySelectionChange * Change )
{
// We should not get here because selection changes should have been expired.
if ( ! ensure ( HasBeenShutDown ( ) = = false ) )
{
return ;
}
FGeometryIdentifier Identifer = Change - > GetIdentifier ( ) ;
for ( int32 k = 0 ; k < ActiveTargetReferences . Num ( ) ; + + k )
{
2023-04-10 12:36:37 -04:00
if ( ActiveTargetReferences [ k ] - > TargetIdentifier = = Identifer )
2022-06-30 12:09:44 -04:00
{
FGeometrySelectionDelta ApplyDelta ;
Change - > ApplyChange ( ActiveTargetReferences [ k ] - > SelectionEditor . Get ( ) , ApplyDelta ) ;
if ( ApplyDelta . IsEmpty ( ) = = false )
{
bSelectionRenderCachesDirty = true ;
OnSelectionModified . Broadcast ( ) ;
}
break ;
}
}
}
void UGeometrySelectionManager : : RevertChange ( IGeometrySelectionChange * Change )
{
// We should not get here because selection changes should have been expired.
if ( ! ensure ( HasBeenShutDown ( ) = = false ) )
{
return ;
}
FGeometryIdentifier Identifer = Change - > GetIdentifier ( ) ;
for ( int32 k = 0 ; k < ActiveTargetReferences . Num ( ) ; + + k )
{
2023-04-10 12:36:37 -04:00
if ( ActiveTargetReferences [ k ] - > TargetIdentifier = = Identifer )
2022-06-30 12:09:44 -04:00
{
FGeometrySelectionDelta RevertDelta ;
Change - > RevertChange ( ActiveTargetReferences [ k ] - > SelectionEditor . Get ( ) , RevertDelta ) ;
if ( RevertDelta . IsEmpty ( ) = = false )
{
bSelectionRenderCachesDirty = true ;
OnSelectionModified . Broadcast ( ) ;
}
break ;
}
}
}
void UGeometrySelectionManager : : OnTargetGeometryModified ( IGeometrySelector * Selector )
{
bSelectionRenderCachesDirty = true ;
2022-11-28 19:15:40 -05:00
ClearActivePreview ( ) ;
2022-06-30 12:09:44 -04:00
}
void UGeometrySelectionManager : : UpdateSelectionRenderCacheOnTargetChange ( )
{
CachedSelectionRenderElements . Reset ( ) ;
CachedSelectionRenderElements . SetNum ( ActiveTargetReferences . Num ( ) ) ;
bSelectionRenderCachesDirty = true ;
2022-11-28 19:15:40 -05:00
ClearActivePreview ( ) ;
2022-06-30 12:09:44 -04:00
}
void UGeometrySelectionManager : : RebuildSelectionRenderCaches ( )
{
if ( bSelectionRenderCachesDirty = = false )
{
return ;
}
check ( ActiveTargetReferences . Num ( ) = = CachedSelectionRenderElements . Num ( ) ) ;
for ( int32 k = 0 ; k < ActiveTargetReferences . Num ( ) ; + + k )
{
TSharedPtr < FGeometrySelectionTarget > Target = ActiveTargetReferences [ k ] ;
FGeometrySelectionElements & Elements = CachedSelectionRenderElements [ k ] ;
Elements . Reset ( ) ;
2022-11-28 19:15:40 -05:00
Target - > Selector - > AccumulateSelectionElements ( Target - > Selection , Elements , true , false ) ;
2022-06-30 12:09:44 -04:00
}
bSelectionRenderCachesDirty = false ;
}
2022-11-28 19:15:40 -05:00
void UGeometrySelectionManager : : ClearActivePreview ( )
{
ActivePreviewSelection . Reset ( ) ;
CachedPreviewRenderElements . Reset ( ) ;
}
2022-06-30 12:09:44 -04:00
void UGeometrySelectionManager : : DebugPrintSelection ( )
{
if ( ActiveTargetReferences . Num ( ) = = 0 )
{
UE_LOG ( LogGeometry , Warning , TEXT ( " [SelectionManager] No Active Selection " ) ) ;
return ;
}
int32 NumSelected = 0 ;
for ( TSharedPtr < FGeometrySelectionTarget > Target : ActiveTargetReferences )
{
NumSelected + = Target - > Selection . Num ( ) ;
}
UE_LOG ( LogGeometry , Warning , TEXT ( " [SelectionManager] %d selected items in %d active targets " ) , NumSelected , ActiveTargetReferences . Num ( ) ) ;
}
void UGeometrySelectionManager : : DebugRender ( IToolsContextRenderAPI * RenderAPI )
{
// disable selection during xform to avoid overhead
if ( IsInActiveTransformation ( ) )
{
2023-03-24 12:08:43 -04:00
for ( int32 k = 0 ; k < ActiveTargetReferences . Num ( ) ; + + k )
{
if ( ActiveTransformations [ k ] ! = nullptr )
{
ActiveTransformations [ k ] - > PreviewRender ( RenderAPI ) ;
}
}
2022-06-30 12:09:44 -04:00
return ;
}
//const UMaterialInterface* TriangleMaterial = ToolSetupUtil::GetSelectionMaterial(FLinearColor(1.0f, 0, 0, 0.5f), nullptr, 0.5f);
RebuildSelectionRenderCaches ( ) ;
for ( const FGeometrySelectionElements & Elements : CachedSelectionRenderElements )
{
// batch render all the triangles, vastly more efficient than drawing one by one!
FPrimitiveDrawInterface * CurrentPDI = RenderAPI - > GetPrimitiveDrawInterface ( ) ;
FDynamicMeshBuilder MeshBuilder ( CurrentPDI - > View - > GetFeatureLevel ( ) ) ;
int32 DepthPriority = SDPG_World ; // SDPG_Foreground; // SDPG_World
FVector2f UVs [ 3 ] = { FVector2f ( 0 , 0 ) , FVector2f ( 0 , 1 ) , FVector2f ( 1 , 1 ) } ;
FVector3f Normal = FVector3f ( 0 , 0 , 1 ) ;
FVector3f Tangent = FVector3f ( 1 , 0 , 0 ) ;
for ( const FTriangle3d & Triangle : Elements . Triangles )
{
int32 V0 = MeshBuilder . AddVertex ( FDynamicMeshVertex ( ( FVector3f ) Triangle . V [ 0 ] , Tangent , Normal , UVs [ 0 ] , FColor : : White ) ) ;
int32 V1 = MeshBuilder . AddVertex ( FDynamicMeshVertex ( ( FVector3f ) Triangle . V [ 1 ] , Tangent , Normal , UVs [ 1 ] , FColor : : White ) ) ;
int32 V2 = MeshBuilder . AddVertex ( FDynamicMeshVertex ( ( FVector3f ) Triangle . V [ 2 ] , Tangent , Normal , UVs [ 2 ] , FColor : : White ) ) ;
MeshBuilder . AddTriangle ( V0 , V1 , V2 ) ;
}
//FMaterialRenderProxy* MaterialRenderProxy = TriangleMaterial->GetRenderProxy(); // currently does not work, material does not render
FMaterialRenderProxy * MaterialRenderProxy = GEngine - > ConstraintLimitMaterialX - > GetRenderProxy ( ) ;
MeshBuilder . Draw ( CurrentPDI , FMatrix : : Identity , MaterialRenderProxy , DepthPriority , false , false ) ;
FToolDataVisualizer Visualizer ;
Visualizer . bDepthTested = false ;
Visualizer . BeginFrame ( RenderAPI ) ;
2022-11-28 19:15:40 -05:00
Visualizer . SetLineParameters ( FLinearColor ( 0 , 0.3f , 0.95f , 1 ) , 3.0f ) ;
2022-06-30 12:09:44 -04:00
for ( const FSegment3d & Segment : Elements . Segments )
{
Visualizer . DrawLine ( Segment . StartPoint ( ) , Segment . EndPoint ( ) ) ;
}
2022-11-28 19:15:40 -05:00
Visualizer . SetPointParameters ( FLinearColor ( 0 , 0.3f , 0.95f , 1 ) , 10.0f ) ;
2022-06-30 12:09:44 -04:00
for ( const FVector3d & Point : Elements . Points )
{
Visualizer . DrawPoint ( Point ) ;
}
Visualizer . EndFrame ( ) ;
}
2022-11-28 19:15:40 -05:00
// draw selection preview
{
FPrimitiveDrawInterface * CurrentPDI = RenderAPI - > GetPrimitiveDrawInterface ( ) ;
FDynamicMeshBuilder MeshBuilder ( CurrentPDI - > View - > GetFeatureLevel ( ) ) ;
int32 DepthPriority = SDPG_World ; // SDPG_Foreground; // SDPG_World
FVector2f UVs [ 3 ] = { FVector2f ( 0 , 0 ) , FVector2f ( 0 , 1 ) , FVector2f ( 1 , 1 ) } ;
FVector3f Normal = FVector3f ( 0 , 0 , 1 ) ;
FVector3f Tangent = FVector3f ( 1 , 0 , 0 ) ;
for ( const FTriangle3d & Triangle : CachedPreviewRenderElements . Triangles )
{
int32 V0 = MeshBuilder . AddVertex ( FDynamicMeshVertex ( ( FVector3f ) Triangle . V [ 0 ] , Tangent , Normal , UVs [ 0 ] , FColor : : White ) ) ;
int32 V1 = MeshBuilder . AddVertex ( FDynamicMeshVertex ( ( FVector3f ) Triangle . V [ 1 ] , Tangent , Normal , UVs [ 1 ] , FColor : : White ) ) ;
int32 V2 = MeshBuilder . AddVertex ( FDynamicMeshVertex ( ( FVector3f ) Triangle . V [ 2 ] , Tangent , Normal , UVs [ 2 ] , FColor : : White ) ) ;
MeshBuilder . AddTriangle ( V0 , V1 , V2 ) ;
}
//FMaterialRenderProxy* MaterialRenderProxy = TriangleMaterial->GetRenderProxy(); // currently does not work, material does not render
FMaterialRenderProxy * MaterialRenderProxy = GEngine - > ConstraintLimitMaterialX - > GetRenderProxy ( ) ;
MeshBuilder . Draw ( CurrentPDI , FMatrix : : Identity , MaterialRenderProxy , DepthPriority , false , false ) ;
FToolDataVisualizer Visualizer ;
Visualizer . bDepthTested = false ;
Visualizer . BeginFrame ( RenderAPI ) ;
Visualizer . SetLineParameters ( FLinearColor ( 1 , 1 , 0 , 1 ) , 1.0f ) ;
for ( const FSegment3d & Segment : CachedPreviewRenderElements . Segments )
{
Visualizer . DrawLine ( Segment . StartPoint ( ) , Segment . EndPoint ( ) ) ;
}
Visualizer . SetPointParameters ( FLinearColor ( 1 , 1 , 0 , 1 ) , 5.0f ) ;
for ( const FVector3d & Point : CachedPreviewRenderElements . Points )
{
Visualizer . DrawPoint ( Point ) ;
}
Visualizer . EndFrame ( ) ;
}
2022-06-30 12:09:44 -04:00
}
2022-11-22 20:17:33 -05:00
# undef LOCTEXT_NAMESPACE