Files
UnrealEngineUWP/Engine/Plugins/Runtime/MeshModelingToolset/Source/ModelingComponents/Public/Snapping/ModelingSceneSnappingManager.h
ryan schmidt 48e1cabf77 Added support for world-space hit-testing and snapping to Volume and DynamicMeshComponent mesh vertices/edges/faces, by having Modeling Mode maintain a persistent set of spatial data structures for these scene meshes. With this change, new ToolSceneQueriesUtil functions can be used to provide more general scene mesh-element hit-testing/snapping via ModelingSceneSnappingManager. Updates to existing Tools/Mechanics to use these new query functions will be done in later CLs.
ToolsFramework:
- added new USceneSnappingManager::ExecuteSceneHitQuery API function, as well as accompanying FSceneHitQueryRequest/FSceneHitQueryResult structs
- added FSceneQueryVisibilityFilter struct which contains ComponentsToIgnore/InvisibleComponentsToInclude lists for snapping queries and provides shared IsVisible() implementation

ModelingComponents:
- add FLevelObjectsObserver, tracks Actors added/removed to a Level via various editor events
- add FSceneGeometrySpatialCache, maintains spatial data structures for known types of mesh-backed PrimitiveComponents, an octree based on their world-space bounding-boxes, and provides various spatial-query functions
- ModelingSceneSnappingManager now maintains a FSceneGeometrySpatialCache for a set of Actors/Components it is notified about, and updates the spatial cache if those components are modified or translated. Currently supports Volumes and DynamicMeshComponents.
- add ModelingSceneSnappingManager::ExecuteSceneHitQuery implementation, does raycasts into the world (for static mesh components) and FSceneGeometrySpatialCache for Volumes/DMCs
- modified ModelingSceneSnappingManager::ExecuteSceneSnapQuery to also do combined query against StaticMeshComponents via world-linetrace, and FSceneGeometrySpatialCache for Volumes/DMCs
- add ToolSceneQueriesUtil::FindNearestVisibleObjectHit variants that take a USceneSnappingManager or UInteractiveTool, and do queries via the SceneSnappingManger, instead of directly linetracing into a UWorld

ModleingToolsEditorMode:
- add FLevelObjectsObserver instance and use it to drive updates to active ModelingSceneSnappingManager

#rnx
#jira none
#preflight 61a664a09a226d9e823ad4c1

#ROBOMERGE-AUTHOR: ryan.schmidt
#ROBOMERGE-SOURCE: CL 18339853 in //UE5/Release-5.0/... via CL 18339869
#ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469)

[CL 18339891 by ryan schmidt in ue5-release-engine-test branch]
2021-12-01 11:15:01 -05:00

157 lines
6.1 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "GeometryBase.h"
#include "SceneQueries/SceneSnappingManager.h"
#include "ModelingSceneSnappingManager.generated.h"
class IToolsContextQueriesAPI;
class UInteractiveToolsContext;
class UInteractiveToolManager;
class UDynamicMeshComponent;
PREDECLARE_GEOMETRY(class FSceneGeometrySpatialCache);
/**
* UModelingSceneSnappingManager is an implementation of snapping suitable for use in
* Modeling Tools/Gizmos (and potentially other places).
*
* Currently Supports:
* - snap to position/rotation grid
* - snap to mesh vertex position
* - snap to mesh edge position
*
* Snapping to mesh vertex/edge positions currently works for Volume (BrushComponent), StaticMeshComponent,
* and DynamicMeshComponent.
*
* Currently the StaticMesh vertex/edge snapping is dependent on the Physics
* system, and may fail or return nonsense results in some cases, due to the physics
* complex-collision mesh deviating from the source-model mesh.
*/
UCLASS()
class MODELINGCOMPONENTS_API UModelingSceneSnappingManager : public USceneSnappingManager
{
GENERATED_BODY()
public:
virtual void Initialize(TObjectPtr<UInteractiveToolsContext> ToolsContext);
virtual void Shutdown();
//
// USceneSnappingManager API
//
/**
* Try to find a Hit Point in the scene that satisfies the HitQuery Request.
* @param Request hit query configuration
* @param ResultOut hit query result, if return is true
* @return true if a valid hit was found
* @warning implementations are not required (and may not be able) to support hit-testing
*/
virtual bool ExecuteSceneHitQuery(const FSceneHitQueryRequest& Request, FSceneHitQueryResult& ResultOut) const override;
/**
* Try to find Snap Targets in the scene that satisfy the Snap Query.
* @param Request snap query configuration
* @param Results list of potential snap results
* @return true if any valid snap target was found
* @warning implementations are not required (and may not be able) to support snapping
*/
virtual bool ExecuteSceneSnapQuery(const FSceneSnapQueryRequest& Request, TArray<FSceneSnapQueryResult>& Results) const override;
//
// API for managing the set of Actors/Components that the snapping system knows about.
// Currently this is for Volumes and DynamicMeshActors/Components, the SnappingManager builds
// it's own spatial data structure cache for these types of meshes. StaticMeshComponents are
// automatically included and handled via world-traces and the physics system.
//
public:
/** @return true if this Component type is supported by the spatial-cache tracking for hit and snap testing */
virtual bool IsComponentTypeSupported(const UPrimitiveComponent* Component) const;
/** Enable spatial-cache tracking for the Components of the Actor that pass the PrimitiveFilter */
virtual void OnActorAdded(AActor* Actor, TFunctionRef<bool(UPrimitiveComponent*)> PrimitiveFilter);
/** Disable spatial-cache tracking for any Components of the Actor */
virtual void OnActorRemoved(AActor* Actor);
/** Enable spatial-cache tracking for the Component */
virtual void OnComponentAdded(UPrimitiveComponent* Component);
/** Disable spatial-cache tracking for the Component */
virtual void OnComponentRemoved(UPrimitiveComponent* Component);
/** Notify the internal spatial-cache tracking system that the Component has been modified (ie cache needs to be rebiult) */
virtual void OnComponentModified(UActorComponent* Component);
/** Explicitly populate the spatial-cache tracking set with specific Actors/Components (alternative to OnActorAdded route) */
virtual void BuildSpatialCacheForWorld(
UWorld* World,
TFunctionRef<bool(AActor*)> ActorFilter,
TFunctionRef<bool(UPrimitiveComponent*)> PrimitiveFilter );
protected:
UPROPERTY()
TObjectPtr<UInteractiveToolsContext> ParentContext;
const IToolsContextQueriesAPI* QueriesAPI = nullptr;
virtual bool ExecuteSceneSnapQueryRotation(const FSceneSnapQueryRequest& Request, TArray<FSceneSnapQueryResult>& Results) const;
virtual bool ExecuteSceneSnapQueryPosition(const FSceneSnapQueryRequest& Request, TArray<FSceneSnapQueryResult>& Results) const;
// This map allows us to identify the Components belonging to Actors. Need to store this
// because if the Actor is deleted we will not be able to identify it's (previous) Components
TMap<UPrimitiveComponent*, AActor*> ComponentToActorMap;
// cache for objects in the level
TSharedPtr<UE::Geometry::FSceneGeometrySpatialCache> SpatialCache;
FDelegateHandle OnObjectModifiedHandler;
void HandleGlobalObjectModifiedDelegate(UObject* Object);
FDelegateHandle OnComponentTransformChangedHandle;
void HandleGlobalComponentTransformChangedDelegate(USceneComponent* Component);
TMap<UPrimitiveComponent*, TWeakObjectPtr<UDynamicMeshComponent>> DynamicMeshComponents;
void HandleDynamicMeshModifiedDelegate(UDynamicMeshComponent* Component);
};
namespace UE
{
namespace Geometry
{
//
// The functions below are helper functions that simplify usage of a UModelingSceneSnappingManager
// that is registered as a ContextStoreObject in an InteractiveToolsContext
//
/**
* If one does not already exist, create a new instance of UModelingSceneSnappingManager and add it to the
* ToolsContext's ContextObjectStore
* @return true if the ContextObjectStore now has a UModelingSceneSnappingManager (whether it already existed, or was created)
*/
MODELINGCOMPONENTS_API bool RegisterSceneSnappingManager(UInteractiveToolsContext* ToolsContext);
/**
* Remove any existing UModelingSceneSnappingManager from the ToolsContext's ContextObjectStore
* @return true if the ContextObjectStore no longer has a UModelingSceneSnappingManager (whether it was removed, or did not exist)
*/
MODELINGCOMPONENTS_API bool DeregisterSceneSnappingManager(UInteractiveToolsContext* ToolsContext);
/**
* Find an existing UModelingSceneSnappingManager in the ToolsContext's ContextObjectStore
* @return SelectionManager pointer or nullptr if not found
*/
MODELINGCOMPONENTS_API UModelingSceneSnappingManager* FindModelingSceneSnappingManager(UInteractiveToolManager* ToolManager);
}
}