622 lines
24 KiB
C++
622 lines
24 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "ConvexVolume.h"
|
|
#include "Selections/GeometrySelection.h"
|
|
#include "Selection/GeometrySelector.h"
|
|
#include "Selection/GeometrySelectionChanges.h"
|
|
|
|
#include "GeometrySelectionManager.generated.h"
|
|
|
|
#define UE_API MODELINGCOMPONENTS_API
|
|
|
|
class UPreviewGeometry;
|
|
class IGeometrySelector;
|
|
class UInteractiveToolsContext;
|
|
class IToolsContextRenderAPI;
|
|
class IToolsContextTransactionsAPI;
|
|
class UGeometrySelectionEditCommand;
|
|
class UGeometrySelectionEditCommandArguments;
|
|
|
|
USTRUCT()
|
|
struct FMeshElementSelectionParams
|
|
{
|
|
GENERATED_BODY()
|
|
TStaticArray<FString, 3> Identifiers {};
|
|
float DepthBias = 0.0f;
|
|
float LineThickness = 0.0f;
|
|
float PointSize = 0.0f;
|
|
FColor Color = FColor(0,0,0);
|
|
UPROPERTY()
|
|
TObjectPtr<UMaterialInstanceDynamic> SelectionFillColor = nullptr;
|
|
};
|
|
|
|
enum class EEnumerateRenderCachesDirtyFlags: uint8
|
|
{
|
|
None = 0,
|
|
|
|
SelectionCachesDirty = 1 << 0,
|
|
UnselectedCachesDirty = 1 << 1, //SelectableRenderCaches
|
|
PreviewCachesDirty = 1 << 2,
|
|
|
|
Default = SelectionCachesDirty | UnselectedCachesDirty | PreviewCachesDirty,
|
|
};
|
|
ENUM_CLASS_FLAGS(EEnumerateRenderCachesDirtyFlags);
|
|
|
|
/**
|
|
* UGeometrySelectionManager provides the infrastructure for "Element Selection", ie
|
|
* geometric sub-elements of some geometry object like a Triangle Mesh. The Manager is
|
|
* designed to work with a relatively vague concept of "element", so it doesn't explicitly
|
|
* reference triangles/etc, and the selectable-elements and how-elements-are-selected
|
|
* concepts are provided by abstract-interfaces that allow various implememtations.
|
|
*
|
|
* The "Geometry Objects", eg like a DynamicMeshComponent, Gameplay Volume, etc, are
|
|
* referred to as "Active Targets" in the Manager. External code provides and updates
|
|
* the set of Active Targets, eg for example tracking the active Actor Selection in the Editor.
|
|
*
|
|
* For a given Target, a tuple (Selector, Selection, SelectionEditor) is created and maintained.
|
|
* The FGeometrySelection is ultimately a basic list of integers and does not have any knowledge
|
|
* of what it is a selection *of*, and is not intended to be directly edited. Instead the
|
|
* SelectionEditor provides that functionality. This separation allows "selection editing" to
|
|
* be customized, eg to enforce invariants or constraints that might apply to certain kinds of selections.
|
|
*
|
|
* The IGeometrySelector provides the core implementation of what "selection" means for a given
|
|
* Target, eg like a mesh Component, or mesh object like a UDynamicMesh. The Selector is
|
|
* created by a registered Factory, allowing client code to provide custom implementations for
|
|
* different Target Types. Updates to the Selection are done via the Selector, as well as queries
|
|
* about (eg) renderable selection geometry. 3D Transforms are also applied via the Selector,
|
|
* as only it has the knowledge about what can be transformed and how it can be applied.
|
|
*
|
|
* The GeometrySelectionManager provides high-level interfaces for this system, for example
|
|
* external code (eg such as something that creates a Gizmo for the active selection) only
|
|
* needs to interact with SelectionManager, calling functions like
|
|
* ::BeginTransformation() / ::UpdateTransformation() / ::EndTransformation().
|
|
* The SelectionManager also handles Transactions/FChanges for the active Targets and Selections.
|
|
*
|
|
*/
|
|
UCLASS(MinimalAPI)
|
|
class UGeometrySelectionManager : public UObject
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
|
|
using FGeometrySelection = UE::Geometry::FGeometrySelection;
|
|
using FGeometrySelectionEditor = UE::Geometry::FGeometrySelectionEditor;
|
|
using FGeometrySelectionBounds = UE::Geometry::FGeometrySelectionBounds;
|
|
using FGeometrySelectionElements = UE::Geometry::FGeometrySelectionElements;
|
|
using FGeometrySelectionUpdateConfig = UE::Geometry::FGeometrySelectionUpdateConfig;
|
|
using FGeometrySelectionUpdateResult = UE::Geometry::FGeometrySelectionUpdateResult;
|
|
using EGeometryElementType = UE::Geometry::EGeometryElementType;
|
|
using EGeometryTopologyType = UE::Geometry::EGeometryTopologyType;
|
|
|
|
//
|
|
// Setup/Teardown
|
|
//
|
|
|
|
UE_API virtual void Initialize(UInteractiveToolsContext* ToolsContextIn, IToolsContextTransactionsAPI* TransactionsAPIIn);
|
|
|
|
UE_API virtual void RegisterSelectorFactory(TUniquePtr<IGeometrySelectorFactory> Factory);
|
|
|
|
UE_API virtual void Shutdown();
|
|
UE_API virtual bool HasBeenShutDown() const;
|
|
|
|
UInteractiveToolsContext* GetToolsContext() const { return ToolsContext; }
|
|
IToolsContextTransactionsAPI* GetTransactionsAPI() const { return TransactionsAPI; }
|
|
|
|
//
|
|
// Configuration
|
|
//
|
|
|
|
/** EMeshTopologyMode determines what level of mesh element will be selected */
|
|
enum class EMeshTopologyMode
|
|
{
|
|
None = 0,
|
|
/** Select mesh triangles, edges, and vertices */
|
|
Triangle = 1,
|
|
/** Select mesh polygroups, polygroup-borders, and polygroup-corners */
|
|
Polygroup = 2
|
|
};
|
|
|
|
UE_API virtual void SetSelectionElementType(EGeometryElementType ElementType);
|
|
virtual EGeometryElementType GetSelectionElementType() const { return SelectionElementType; }
|
|
|
|
UE_API virtual void SetMeshTopologyMode(EMeshTopologyMode SelectionMode);
|
|
virtual EMeshTopologyMode GetMeshTopologyMode() const { return MeshTopologyMode; }
|
|
UE_API virtual EGeometryTopologyType GetSelectionTopologyType() const;
|
|
|
|
// Switch the selection mode and type, optionally converting any existing selection to the new type and mode
|
|
UE_API virtual void SetMeshSelectionTypeAndMode(EGeometryElementType NewElementType, EMeshTopologyMode NewSelectionMode, bool bConvertSelection);
|
|
|
|
/**
|
|
* Removes Triangle, Line, and Point sets with the given SetIdentifier prefix
|
|
* Full Identifier strings are in the format: SetIdentifier_Triangles, SetIdentifier_Lines, and SetIdentifier_Points
|
|
*/
|
|
UE_API void RemoveSets(const TArrayView<FString>& SetIdentifiers) const;
|
|
|
|
|
|
|
|
//
|
|
// Target Management / Queries
|
|
// TODO: be able to update active target set w/o losing current selections?
|
|
//
|
|
|
|
/**
|
|
* @return true if there are any active selection targets
|
|
*/
|
|
UE_API bool HasActiveTargets() const;
|
|
|
|
/**
|
|
* Attempt to validate the current selection state; can be called to detect if e.g. selected objects have been deleted from under the selection manager.
|
|
* @return true if current active selection state appears to be valid (i.e., does not include stale / deleted objects)
|
|
*/
|
|
UE_API bool ValidateSelectionState() const;
|
|
|
|
/**
|
|
* Empty the active selection target set
|
|
* @warning Active selection must be cleared (eg via ClearSelection()) before calling this function
|
|
*/
|
|
UE_API void ClearActiveTargets();
|
|
|
|
/**
|
|
* Add a target to the active target set, if a valid IGeometrySelectorFactory can be found
|
|
* @return true on success
|
|
*/
|
|
UE_API bool AddActiveTarget(FGeometryIdentifier Target);
|
|
|
|
|
|
UE_API bool GetAnyCurrentTargetsLockable() const;
|
|
UE_API bool GetAnyCurrentTargetsLocked() const;
|
|
UE_API void SetCurrentTargetsLockState(bool bLocked);
|
|
|
|
|
|
/**
|
|
* Update the current active target set based on DesiredActiveSet, assuming that a valid IGeometrySelectorFactory
|
|
* can be found for each identifier.
|
|
* This function will emit a transaction/change if the target set is modified.
|
|
* @param WillChangeActiveTargetsCallback this function will be called if the DesiredActiveSet is not the same as the current active set, allowing calling code to (eg) clear the active selection
|
|
*/
|
|
UE_API void SynchronizeActiveTargets(
|
|
const TArray<FGeometryIdentifier>& DesiredActiveSet,
|
|
TFunctionRef<void()> WillChangeActiveTargetsCallback );
|
|
|
|
/**
|
|
* Test if a World-space ray "hits" the current active target set, which can be used to (eg)
|
|
* determine if a higher-level user interaction for selection should "Capture" the click
|
|
* @param HitResultOut hit information is returned here
|
|
* @return true on hit
|
|
*/
|
|
UE_API virtual bool RayHitTest(
|
|
const FRay3d& WorldRay,
|
|
FInputRayHit& HitResultOut
|
|
);
|
|
|
|
/**
|
|
* Invalidates all cached selection elements by default.
|
|
* When desired, can choose to not mark the Selectable render cache as dirty
|
|
*/
|
|
UE_API void MarkRenderCachesDirty(bool bMarkSelectableDirty = true);
|
|
|
|
//
|
|
// Selection Updates
|
|
//
|
|
public:
|
|
/**
|
|
* Clear any active element selections.
|
|
* This function will emit a Transaction for the selection change.
|
|
* @param bSaveSelectionBeforeClear if true, calls SaveCurrentSelection() before the selection is cleared, so it can be restored later.
|
|
*/
|
|
UE_API virtual void ClearSelection(bool bSaveSelectionBeforeClear = false);
|
|
|
|
protected:
|
|
/**
|
|
* Save the active selection. Overwrites any existing saved selections with the current selections. Typically used via ClearSelection(true)
|
|
*/
|
|
UE_API virtual void SaveCurrentSelection();
|
|
|
|
public:
|
|
/**
|
|
* Attempt to restore (and then discard) the most recent saved selection.
|
|
* If there is no active saved selection, does nothing. On failure to restore, will still discard the saved selection.
|
|
* @return false if could not restore selection, which can happen if the restore was called while transacting (e.g., when a tool is exited via undo), or if the selection objects were not found or not valid
|
|
*/
|
|
UE_API virtual bool RestoreSavedSelection();
|
|
|
|
/**
|
|
* Discard the saved selection, if there is one.
|
|
*/
|
|
UE_API virtual void DiscardSavedSelection();
|
|
|
|
/**
|
|
* @return true if there is a non-empty saved selection, false otherwise.
|
|
*/
|
|
UE_API virtual bool HasSavedSelection();
|
|
|
|
/**
|
|
* Use the given WorldRay to update the active element selection based on UpdateConfig.
|
|
* The intention is that this function is called by higher-level user interaction code after
|
|
* RayHitTest() has returned true.
|
|
* @param ResultOut information on any element selection modifications is returned here
|
|
*/
|
|
UE_API virtual void UpdateSelectionViaRaycast(
|
|
const FRay3d& WorldRay,
|
|
const FGeometrySelectionUpdateConfig& UpdateConfig,
|
|
FGeometrySelectionUpdateResult& ResultOut
|
|
);
|
|
|
|
|
|
/**
|
|
* Use the given ConvexVolume to update the active element selection based on UpdateConfig.
|
|
* @param ResultOut information on any element selection modifications is returned here
|
|
*/
|
|
UE_API virtual void UpdateSelectionViaConvex(
|
|
const FConvexVolume& ConvexVolume,
|
|
const FGeometrySelectionUpdateConfig& UpdateConfig,
|
|
FGeometrySelectionUpdateResult& ResultOut
|
|
);
|
|
|
|
|
|
|
|
//
|
|
// Support for more complex selection changes that might (eg) occur over multiple frames,
|
|
// or be computed externally. The usage pattern is:
|
|
// - verify that CanBeginTrackedSelectionChange() returns true
|
|
// - call BeginTrackedSelectionChange(), this opens transacation
|
|
// - modify selection here, eg via multiple calls to AccumulateSelectionUpdate_Raycast
|
|
// - call EndTrackedSelectionChange() to emit changes and close transaction
|
|
|
|
/** @return true if a tracked selection change can be initialized */
|
|
UE_API virtual bool CanBeginTrackedSelectionChange() const;
|
|
|
|
/** @return true if an active tracked selection change is in flight */
|
|
virtual bool IsInTrackedSelectionChange() const { return bInTrackedSelectionChange; }
|
|
|
|
/**
|
|
* Begin a tracked selection change. CanBeginTrackedSelectionChange() must return true to call this function.
|
|
* EndTrackedSelectionChange() must be called to close the selection change.
|
|
* @param UpdateConfig how the selection will be modified. Currently this must be consistent across the entire tracked change (ie, only add, only subtract, etc)
|
|
* @param bClearOnBegin if true, selection will be initially cleared (eg Replace-style)
|
|
*/
|
|
UE_API virtual bool BeginTrackedSelectionChange(FGeometrySelectionUpdateConfig UpdateConfig, bool bClearOnBegin);
|
|
|
|
/**
|
|
* Update the tracked selection change via a single Raycast, using the active UpdateConfig mode passed to BeginTrackedSelectionChange
|
|
* @param ResultOut information on any element selection modifications is returned here*
|
|
*/
|
|
UE_API virtual void AccumulateSelectionUpdate_Raycast(
|
|
const FRay3d& WorldRay,
|
|
FGeometrySelectionUpdateResult& ResultOut
|
|
);
|
|
|
|
/**
|
|
* Close an active tracked selection change.
|
|
* This will emit one or more FChanges for the selection modifications, and then close the open Transaction
|
|
*/
|
|
UE_API virtual void EndTrackedSelectionChange();
|
|
|
|
|
|
/**
|
|
* Directly set the current Selection for the specified Component to NewSelection.
|
|
* This function allows external code to construct explicit selections, eg for a Tool or Command to emit a new Selection.
|
|
* Component must already be an active target, ie set via AddActiveTarget.
|
|
* If the selection of the Target would be modified, a selection-change transaction will be emitted.
|
|
*/
|
|
UE_API virtual bool SetSelectionForComponent(UPrimitiveComponent* Component, const FGeometrySelection& NewSelection);
|
|
|
|
|
|
DECLARE_MULTICAST_DELEGATE(FModelingSelectionInteraction_SelectionModified);
|
|
/**
|
|
* OnSelectionModified is broadcast if the selection is modified via the above functions.
|
|
* There are no arguments.
|
|
*/
|
|
FModelingSelectionInteraction_SelectionModified OnSelectionModified;
|
|
|
|
|
|
|
|
//
|
|
// Hover/Preview support
|
|
//
|
|
public:
|
|
|
|
UE_API virtual bool UpdateSelectionPreviewViaRaycast(
|
|
const FRay3d& WorldRay
|
|
);
|
|
|
|
/**
|
|
* Resets the active preview selection and invalidates its associated cached render elements.
|
|
*/
|
|
UE_API virtual void ClearSelectionPreview();
|
|
|
|
|
|
//
|
|
// Selection queries
|
|
//
|
|
public:
|
|
/** @return true if there is an active element selection */
|
|
UE_API virtual bool HasSelection() const;
|
|
|
|
/**
|
|
* Get available information about the active selection/state
|
|
*/
|
|
UE_API virtual void GetActiveSelectionInfo(EGeometryTopologyType& TopologyTypeOut, EGeometryElementType& ElementTypeOut, int& NumTargetsOut, bool& bIsEmpty) const;
|
|
|
|
/** @return a world-space bounding box for the active element selection */
|
|
UE_API virtual bool GetSelectionBounds(FGeometrySelectionBounds& BoundsOut) const;
|
|
|
|
/** @return a 3D transformation frame suitable for use with the active element selection */
|
|
UE_API virtual void GetSelectionWorldFrame(UE::Geometry::FFrame3d& SelectionFrame) const;
|
|
|
|
/** @return a 3D transformation frame suitable for use with the set of active targets */
|
|
UE_API virtual void GetTargetWorldFrame(UE::Geometry::FFrame3d& SelectionFrame) const;
|
|
|
|
/** @return true if there is an active IGeometrySelector target for the given Component and it has a non-empty selection */
|
|
UE_API virtual bool HasSelectionForComponent(UPrimitiveComponent* Component) const;
|
|
/**
|
|
* Get the active element selection for the given Component, if it exists
|
|
* @return true if a valid non-empty selection was returned in SelectionOut
|
|
*/
|
|
UE_API virtual bool GetSelectionForComponent(UPrimitiveComponent* Component, FGeometrySelection& SelectionOut) const;
|
|
|
|
|
|
|
|
//
|
|
// Transformations
|
|
//
|
|
protected:
|
|
// Set of existing transformer objects, collected from active IGeometrySelector::InitializeTransformation().
|
|
// The SelectionManager does not own these objects, they must not be deleted.
|
|
// Instead they need to be returned via IGeometrySelector::ShutdownTransformation
|
|
TArray<IGeometrySelectionTransformer*> ActiveTransformations;
|
|
|
|
public:
|
|
/** @return true if SelectionManager is actively transforming element selections (ie during a mouse-drag) */
|
|
virtual bool IsInActiveTransformation() const { return (ActiveTransformations.Num() > 0); }
|
|
|
|
/**
|
|
* Begin a transformation of element selections in active Targets.
|
|
* @return true if at least one valid Transformer was initialized, ie the transformation will do something
|
|
*/
|
|
UE_API virtual bool BeginTransformation();
|
|
|
|
/**
|
|
* Update the active transformations with the given PositionTransformFunc.
|
|
* See IGeometrySelectionTransformer::UpdateTransform for details on this callback
|
|
*/
|
|
UE_API virtual void UpdateTransformation( TFunctionRef<FVector3d(int32 VertexID, const FVector3d&, const FTransform&)> PositionTransformFunc );
|
|
|
|
/**
|
|
* End the current active transformation, and emit changes/transactions
|
|
*/
|
|
UE_API virtual void EndTransformation();
|
|
|
|
|
|
//
|
|
// Command Execution
|
|
//
|
|
public:
|
|
/**
|
|
* @return true if Command->CanExecuteCommand() returns true for *all* the current Selections
|
|
*/
|
|
UE_API bool CanExecuteSelectionCommand(UGeometrySelectionEditCommand* Command);
|
|
|
|
/**
|
|
* execute the selection command for *all* the current selections
|
|
*/
|
|
UE_API void ExecuteSelectionCommand(UGeometrySelectionEditCommand* Command);
|
|
|
|
|
|
protected:
|
|
// This is set to current selection during CanExecuteSelectionCommand/ExecuteSelectionCommand, to keep the UObject alive
|
|
// Not expected to be used outside that context
|
|
UPROPERTY()
|
|
TObjectPtr<UGeometrySelectionEditCommandArguments> SelectionArguments;
|
|
|
|
// apply ProcessFunc to active selections via handles, perhaps should be public?
|
|
UE_API void ProcessActiveSelections(TFunctionRef<void(FGeometrySelectionHandle)> ProcessFunc);
|
|
|
|
|
|
|
|
//
|
|
// Undo/Redo
|
|
//
|
|
public:
|
|
UE_API virtual void ApplyChange(IGeometrySelectionChange* Change);
|
|
UE_API virtual void RevertChange(IGeometrySelectionChange* Change);
|
|
|
|
|
|
//
|
|
// Debugging stuff
|
|
//
|
|
public:
|
|
/** Print information about the active selection using UE_LOG */
|
|
UE_API virtual void DebugPrintSelection();
|
|
/** Visualize the active selection using PDI drawing */
|
|
UE_API virtual void DebugRender(IToolsContextRenderAPI* RenderAPI);
|
|
|
|
/** Set the colors to be used during mesh element selection for:
|
|
* Unselected elements, Hover over selection, Hover over non-selection, and Selected elements
|
|
*/
|
|
UE_API void SetSelectionColors(FLinearColor UnselectedCol, FLinearColor HoverOverSelectedCol, FLinearColor HoverOverUnselectedCol, FLinearColor GeometrySelectedCol);
|
|
|
|
/** Disconnect and cleanup for PreviewGeometry object. */
|
|
UE_API void DisconnectPreviewGeometry();
|
|
|
|
protected:
|
|
|
|
// current selection mode settings
|
|
|
|
EGeometryElementType SelectionElementType = EGeometryElementType::Face;
|
|
UE_API void SetSelectionElementTypeInternal(EGeometryElementType NewElementType);
|
|
|
|
EMeshTopologyMode MeshTopologyMode = EMeshTopologyMode::None;
|
|
UE_API void SetMeshTopologyModeInternal(EMeshTopologyMode NewTopologyMode);
|
|
|
|
UE_API UE::Geometry::FGeometrySelectionHitQueryConfig GetCurrentSelectionQueryConfig() const;
|
|
|
|
public:
|
|
// Selection Filters
|
|
UE_API void SetHitBackFaces(bool bInHitBackFaces);
|
|
bool GetHitBackFaces() const { return bHitBackFaces; }
|
|
|
|
protected:
|
|
bool bHitBackFaces = true;
|
|
|
|
// ITF references
|
|
|
|
UPROPERTY()
|
|
TObjectPtr<UInteractiveToolsContext> ToolsContext;
|
|
|
|
IToolsContextTransactionsAPI* TransactionsAPI;
|
|
|
|
// set of registered IGeometrySelector factories
|
|
TArray<TUniquePtr<IGeometrySelectorFactory>> Factories;
|
|
|
|
|
|
|
|
// FGeometrySelectionTarget is the set of information tracked for a given "Active Target",
|
|
// which is (eg) a Mesh Component or other external object that "owns" selectable Geometry.
|
|
// This includes the IGeometrySelector for that target, the SelectionEditor, and the active Selection
|
|
struct FGeometrySelectionTarget
|
|
{
|
|
public:
|
|
FGeometryIdentifier TargetIdentifier; // identifier of target object used to initialize the selection (eg Component/etc)
|
|
FGeometryIdentifier SelectionIdentifer; // identifier of object that is being selected-on, eg UDynamicMesh/etc
|
|
|
|
TUniquePtr<IGeometrySelector> Selector; // active Selector
|
|
|
|
FGeometrySelection Selection; // current Selection
|
|
TUniquePtr<FGeometrySelectionEditor> SelectionEditor; // active Selection Editor
|
|
|
|
FDelegateHandle OnGeometryModifiedHandle; // hooked up to (eg) UDynamicMesh OnMeshChanged, etc
|
|
};
|
|
|
|
// Set of active Selection Targets updated by SynchronizeActiveTargets / etc
|
|
TArray<TSharedPtr<FGeometrySelectionTarget>> ActiveTargetReferences;
|
|
|
|
// map from external Identifiers to active Selection Targets
|
|
TMap<FGeometryIdentifier, TSharedPtr<FGeometrySelectionTarget>> ActiveTargetMap;
|
|
|
|
|
|
TArray<FGeometryIdentifier> UnlockedTargets;
|
|
|
|
|
|
//
|
|
// Support for cached FGeometrySelectionTarget / IGeometrySelectors.
|
|
// The intention here is to reduce the overhead on selection changes.
|
|
// Functional, but needs to be smarter.
|
|
//
|
|
TMap<FGeometryIdentifier, TSharedPtr<FGeometrySelectionTarget>> TargetCache;
|
|
UE_API void SleepOrShutdownTarget(TSharedPtr<FGeometrySelectionTarget> Target, bool bForceShutdown);
|
|
UE_API TSharedPtr<FGeometrySelectionTarget> GetCachedTarget(FGeometryIdentifier Identifier, const IGeometrySelectorFactory* UseFactory);
|
|
UE_API void ResetTargetCache();
|
|
UE_API void SetTargetsOnUndoRedo(TArray<FGeometryIdentifier> NewTargets);
|
|
UE_API TArray<FGeometryIdentifier> GetCurrentTargetIdentifiers() const;
|
|
|
|
UE_API void OnTargetGeometryModified(IGeometrySelector* Selector);
|
|
|
|
|
|
// todo [nickolas.drake]: cane we move CachedSelectionRenderElements, Cached[Un]selectedPreviewRenderElements, and bSelectionRenderCachesDirty to private?
|
|
|
|
UPROPERTY()
|
|
TObjectPtr<UPreviewGeometry> PreviewGeometry = nullptr;
|
|
|
|
/**
|
|
* Calls the CreateOrUpdate function for Triangle, Line, and Point sets to build sets for PreviewGeometry
|
|
* @param SelectionParams struct containing information (color, depth bias, line thickness, identifier) for the type of selection we are currently
|
|
* building a set for (as Selected, Selectable, HoverSelected, HoverUnselected all have different visual information needed to contruct their sets)
|
|
*/
|
|
UE_API void CreateOrUpdateAllSets(const FGeometrySelectionElements& Elements, const FMeshElementSelectionParams SelectionParams) const;
|
|
|
|
TArray<FGeometrySelectionElements> CachedSelectionRenderElements; // Cached 3D geometry for current selection
|
|
UE_API void UpdateSelectionRenderCacheOnTargetChange();
|
|
UE_API void RebuildSelectionRenderCaches();
|
|
|
|
FGeometrySelection ActivePreviewSelection;
|
|
FGeometrySelection SelectedActivePreviewSelection;
|
|
FGeometrySelection UnselectedActivePreviewSelection;
|
|
|
|
FGeometrySelectionElements CachedSelectedPreviewRenderElements; // Cached 3D geometry for active preview elements that are in the current selection
|
|
FGeometrySelectionElements CachedUnselectedPreviewRenderElements; // Cached 3D geometry for active preview elements that are NOT in the current selection
|
|
UE_API void ClearActivePreview();
|
|
|
|
inline static TStaticArray<FString, 3> UnselectedSetIds = { "Unselected_Vertices", "Unselected_Lines", "Unselected_Triangles"};
|
|
inline static TStaticArray<FString, 3> HoverOverSelectedSetIds = { "HoverSelected_Vertices", "HoverSelected_Lines", "HoverSelected_Triangles"};
|
|
inline static TStaticArray<FString, 3> HoverOverUnselectedSetIds = { "HoverUnselected_Vertices", "HoverUnselected_Lines", "HoverUnselected_Triangles" };
|
|
inline static TStaticArray<FString, 3> SelectedSetIds = {"Selected_Vertices", "Selected_Lines", "Selected_Triangles"};
|
|
|
|
UPROPERTY()
|
|
FMeshElementSelectionParams UnselectedParams {UnselectedSetIds, 5.f, 2.f, 8.f};
|
|
UPROPERTY()
|
|
FMeshElementSelectionParams HoverOverSelectedParams {HoverOverSelectedSetIds, 10.f, 6.f, 10.f};
|
|
UPROPERTY()
|
|
FMeshElementSelectionParams HoverOverUnselectedParams {HoverOverUnselectedSetIds, 10.f, 6.f, 10.f};
|
|
UPROPERTY()
|
|
FMeshElementSelectionParams SelectedParams {SelectedSetIds, 6.f, 6.f, 10.f};
|
|
|
|
|
|
|
|
// various change types need internal access
|
|
|
|
friend class FGeometrySelectionManager_SelectionTypeChange;
|
|
friend class FGeometrySelectionManager_ActiveTargetsChange;
|
|
|
|
friend class FGeometrySelectionManager_TargetLockStateChange;
|
|
UE_API void SetTargetLockStateOnUndoRedo(FGeometryIdentifier TargetIdentifier, bool bLocked);
|
|
|
|
|
|
// support for complex selection changes that are driven externally
|
|
bool bInTrackedSelectionChange = false;
|
|
FGeometrySelectionUpdateConfig ActiveTrackedUpdateConfig;
|
|
FGeometrySelection ActiveTrackedSelection;
|
|
UE::Geometry::FGeometrySelectionDelta InitialTrackedDelta;
|
|
UE::Geometry::FGeometrySelectionDelta ActiveTrackedDelta;
|
|
bool bSelectionModifiedDuringTrackedChange = false;
|
|
|
|
private:
|
|
|
|
//
|
|
// 3D geometry for element selections of each ActiveTarget is cached
|
|
// to improve rendering performance
|
|
//
|
|
|
|
UE_API void RebuildSelectionRenderCache();
|
|
|
|
TArray<FGeometrySelectionElements> CachedSelectableRenderElements; // Cached 3D geometry for all selectable elements
|
|
UE_API void RebuildSelectableRenderCache();
|
|
|
|
UE_API void RebuildPreviewRenderCache();
|
|
|
|
EEnumerateRenderCachesDirtyFlags RenderCachesDirtyFlags = EEnumerateRenderCachesDirtyFlags::None;
|
|
|
|
UE_API void RemoveAllSets() const;
|
|
|
|
UE_API void RebuildSelectable() const;
|
|
|
|
// Tracks saved selection state. Useful when the selection is temporarily cleared (e.g., for a tool)
|
|
struct FSavedSelection
|
|
{
|
|
TArray<TWeakObjectPtr<UObject>> Targets;
|
|
TArray<FGeometrySelection> Selections;
|
|
void Empty()
|
|
{
|
|
Targets.Empty();
|
|
Selections.Empty();
|
|
}
|
|
void Reset()
|
|
{
|
|
Targets.Reset();
|
|
Selections.Reset();
|
|
}
|
|
};
|
|
FSavedSelection SavedSelection;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#undef UE_API
|