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"
2023-04-26 11:54:13 -04:00
# include "Selection/ToolSelectionUtil.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
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 )
{
2023-04-26 14:35:53 -04:00
SleepOrShutdownTarget ( Target , false ) ;
2022-12-01 16:11:52 -05:00
}
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 )
{
2023-04-26 14:35:53 -04:00
SleepOrShutdownTarget ( Target , false ) ;
2022-06-30 12:09:44 -04:00
}
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 ) ;
ModelingMode: selection system bugfixes & improvements.
Add DynamicMeshSelector::UpdateAfterGeometryEdit API. StaticMeshSelector implementation updates static mesh after an Edit instead of emitting MeshChange on temporary DynamicMesh.
Delete and Retriangulate Commands now use this API instead of directly emitting transaction, so now these commands work properly on Static Meshes.
FStaticMeshComponentSelectorFactory::CanBuildForTarget now only allows UStaticMeshComponent specifically, filtering out subclasses. This is not ideal but I don't know what else we can do for now, there are many subclasses like ISMC, SplineMeshComponent, etc, that will not work w/ the Selection system. Also now filtering out Engine assets and cooked assets.
ModelingToolsEditorMode now listens for blueprint pre-compiles, and when this occurs, clears the active selection and selection targets. This is necessary because if the selection Component was part of a BP, on recompile it is re-instanced and the old pointer goes stale. Possibly can handle this better or at a more granular level, but clearing the selection is safest. This currently results in things not being undoable because the FChange transactions are on the "old" UDynamicMesh that no longer exists.
UModelingToolsEditorMode::UpdateSelectionManagerOnEditorSelectionChange now does a more thorough job of inspecting the current Actor/Component selection to find Components that could work w/ the selection system.
#rb lonnie.li
[CL 26133442 by ryan schmidt in 5.3 branch]
2023-06-20 16:31:27 -04:00
if ( SelectionTarget . IsValid ( ) = = false )
{
return false ;
}
2022-06-30 12:09:44 -04:00
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 )
{
2023-04-21 14:04:50 -04:00
GetTransactionsAPI ( ) - > BeginUndoTransaction (
( bLocked ) ? LOCTEXT ( " Lock Target " , " Lock Target " ) : LOCTEXT ( " Unlock Target " , " Unlock Target " ) ) ;
2023-04-10 12:36:37 -04:00
bInTransaction = true ;
}
TUniquePtr < FGeometrySelectionManager_TargetLockStateChange > Change = MakeUnique < FGeometrySelectionManager_TargetLockStateChange > ( ) ;
Change - > TargetIdentifier = Target - > TargetIdentifier ;
Change - > bToState = bLocked ;
2023-04-21 14:04:50 -04:00
GetTransactionsAPI ( ) - > AppendChange ( this , MoveTemp ( Change ) ,
( bLocked ) ? LOCTEXT ( " Lock Target " , " Lock Target " ) : LOCTEXT ( " Unlock Target " , " Unlock Target " ) ) ;
2023-04-10 12:36:37 -04:00
}
}
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 ) ;
}
}
2023-04-26 14:35:53 -04:00
void UGeometrySelectionManager : : SleepOrShutdownTarget ( TSharedPtr < FGeometrySelectionTarget > Target , bool bForceShutdown )
2022-06-30 12:09:44 -04:00
{
if ( Target - > Selector - > SupportsSleep ( ) & & bForceShutdown = = false )
{
2023-04-26 14:35:53 -04:00
if ( Target - > Selector - > Sleep ( ) )
{
return ;
}
2022-06-30 12:09:44 -04:00
}
2023-04-26 14:35:53 -04:00
// if target cannot sleep or if sleeping failed, make sure it is not in the target
// cache so that we do not try to restore it later
TargetCache . Remove ( Target - > TargetIdentifier ) ;
Target - > Selector - > GetOnGeometryModifed ( ) . Remove ( Target - > OnGeometryModifiedHandle ) ;
Target - > Selector - > Shutdown ( ) ;
2022-06-30 12:09:44 -04:00
}
TSharedPtr < UGeometrySelectionManager : : FGeometrySelectionTarget > UGeometrySelectionManager : : GetCachedTarget ( FGeometryIdentifier TargetIdentifier , const IGeometrySelectorFactory * UseFactory )
{
if ( TargetCache . Contains ( TargetIdentifier ) )
{
TSharedPtr < FGeometrySelectionTarget > FoundTarget = TargetCache [ TargetIdentifier ] ;
FoundTarget - > Selection . Reset ( ) ;
2023-04-26 14:35:53 -04:00
bool bRestored = FoundTarget - > Selector - > Restore ( ) ;
if ( bRestored )
{
// ensure these are current, as they may have changed while Target was asleep
FoundTarget - > Selection . ElementType = GetSelectionElementType ( ) ;
FoundTarget - > Selection . TopologyType = GetSelectionTopologyType ( ) ;
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
2023-04-26 14:35:53 -04:00
return FoundTarget ;
}
else
{
// if restore failed, something is wrong w/ TargetCache, remove this Target
TargetCache . Remove ( TargetIdentifier ) ;
}
2022-06-30 12:09:44 -04:00
}
// if we are in a situation where we don't have a cache, currently we need the Factory to exist?
ModelingMode: selection system bugfixes & improvements.
Add DynamicMeshSelector::UpdateAfterGeometryEdit API. StaticMeshSelector implementation updates static mesh after an Edit instead of emitting MeshChange on temporary DynamicMesh.
Delete and Retriangulate Commands now use this API instead of directly emitting transaction, so now these commands work properly on Static Meshes.
FStaticMeshComponentSelectorFactory::CanBuildForTarget now only allows UStaticMeshComponent specifically, filtering out subclasses. This is not ideal but I don't know what else we can do for now, there are many subclasses like ISMC, SplineMeshComponent, etc, that will not work w/ the Selection system. Also now filtering out Engine assets and cooked assets.
ModelingToolsEditorMode now listens for blueprint pre-compiles, and when this occurs, clears the active selection and selection targets. This is necessary because if the selection Component was part of a BP, on recompile it is re-instanced and the old pointer goes stale. Possibly can handle this better or at a more granular level, but clearing the selection is safest. This currently results in things not being undoable because the FChange transactions are on the "old" UDynamicMesh that no longer exists.
UModelingToolsEditorMode::UpdateSelectionManagerOnEditorSelectionChange now does a more thorough job of inspecting the current Actor/Component selection to find Components that could work w/ the selection system.
#rb lonnie.li
[CL 26133442 by ryan schmidt in 5.3 branch]
2023-06-20 16:31:27 -04:00
if ( UseFactory = = nullptr )
{
return nullptr ;
}
2022-06-30 12:09:44 -04:00
// selector has to be built properly
TUniquePtr < IGeometrySelector > Selector = UseFactory - > BuildForTarget ( TargetIdentifier ) ;
ModelingMode: selection system bugfixes & improvements.
Add DynamicMeshSelector::UpdateAfterGeometryEdit API. StaticMeshSelector implementation updates static mesh after an Edit instead of emitting MeshChange on temporary DynamicMesh.
Delete and Retriangulate Commands now use this API instead of directly emitting transaction, so now these commands work properly on Static Meshes.
FStaticMeshComponentSelectorFactory::CanBuildForTarget now only allows UStaticMeshComponent specifically, filtering out subclasses. This is not ideal but I don't know what else we can do for now, there are many subclasses like ISMC, SplineMeshComponent, etc, that will not work w/ the Selection system. Also now filtering out Engine assets and cooked assets.
ModelingToolsEditorMode now listens for blueprint pre-compiles, and when this occurs, clears the active selection and selection targets. This is necessary because if the selection Component was part of a BP, on recompile it is re-instanced and the old pointer goes stale. Possibly can handle this better or at a more granular level, but clearing the selection is safest. This currently results in things not being undoable because the FChange transactions are on the "old" UDynamicMesh that no longer exists.
UModelingToolsEditorMode::UpdateSelectionManagerOnEditorSelectionChange now does a more thorough job of inspecting the current Actor/Component selection to find Components that could work w/ the selection system.
#rb lonnie.li
[CL 26133442 by ryan schmidt in 5.3 branch]
2023-06-20 16:31:27 -04:00
if ( Selector . IsValid ( ) = = false )
{
return nullptr ;
}
2022-06-30 12:09:44 -04:00
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 ( )
{
2023-04-28 16:01:06 -04:00
// SleepOrShutdownTarget may modify TargetCache
TArray < TSharedPtr < FGeometrySelectionTarget > > ToShutdown ;
TargetCache . GenerateValueArray ( ToShutdown ) ;
for ( TSharedPtr < FGeometrySelectionTarget > Target : ToShutdown )
2022-06-30 12:09:44 -04:00
{
2023-04-28 16:01:06 -04:00
SleepOrShutdownTarget ( Target , true ) ;
2022-06-30 12:09:44 -04:00
}
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 )
{
2023-04-26 11:54:13 -04:00
ToolSelectionUtil : : DebugRenderGeometrySelectionElements ( RenderAPI , Elements , false ) ;
2022-06-30 12:09:44 -04:00
}
2023-04-26 11:54:13 -04:00
ToolSelectionUtil : : DebugRenderGeometrySelectionElements ( RenderAPI , CachedPreviewRenderElements , true ) ;
2022-06-30 12:09:44 -04:00
}
2022-11-22 20:17:33 -05:00
# undef LOCTEXT_NAMESPACE