Files
UnrealEngineUWP/Engine/Source/Runtime/InteractiveToolsFramework/Private/InteractiveGizmoManager.cpp

361 lines
12 KiB
C++
Raw Normal View History

// Copyright Epic Games, Inc. All Rights Reserved.
#include "InteractiveGizmoManager.h"
#include "InteractiveToolsContext.h"
#include "BaseGizmos/AxisPositionGizmo.h"
#include "BaseGizmos/GizmoViewContext.h"
#include "BaseGizmos/PlanePositionGizmo.h"
#include "BaseGizmos/AxisAngleGizmo.h"
#include "BaseGizmos/CombinedTransformGizmo.h"
#include "BaseGizmos/RepositionableTransformGizmo.h"
#include "BaseGizmos/ScalableSphereGizmo.h"
#include "ContextObjectStore.h"
#define LOCTEXT_NAMESPACE "UInteractiveGizmoManager"
UInteractiveGizmoManager::UInteractiveGizmoManager()
{
QueriesAPI = nullptr;
TransactionsAPI = nullptr;
InputRouter = nullptr;
}
void UInteractiveGizmoManager::Initialize(IToolsContextQueriesAPI* QueriesAPIIn, IToolsContextTransactionsAPI* TransactionsAPIIn, UInputRouter* InputRouterIn)
{
this->QueriesAPI = QueriesAPIIn;
this->TransactionsAPI = TransactionsAPIIn;
this->InputRouter = InputRouterIn;
}
void UInteractiveGizmoManager::Shutdown()
{
this->QueriesAPI = nullptr;
TArray<FActiveGizmo> AllGizmos = ActiveGizmos;
for (FActiveGizmo& ActiveGizmo : AllGizmos)
{
DestroyGizmo(ActiveGizmo.Gizmo);
}
ActiveGizmos.Reset();
this->TransactionsAPI = nullptr;
if (bDefaultGizmosRegistered)
{
DeregisterGizmoType(DefaultAxisPositionBuilderIdentifier);
DeregisterGizmoType(DefaultPlanePositionBuilderIdentifier);
DeregisterGizmoType(DefaultAxisAngleBuilderIdentifier);
DeregisterGizmoType(DefaultThreeAxisTransformBuilderIdentifier);
DeregisterGizmoType(DefaultScalableSphereBuilderIdentifier);
}
}
void UInteractiveGizmoManager::RegisterGizmoType(const FString& Identifier, UInteractiveGizmoBuilder* Builder)
{
if (ensure(GizmoBuilders.Contains(Identifier) == false))
{
GizmoBuilders.Add(Identifier, Builder);
}
}
bool UInteractiveGizmoManager::DeregisterGizmoType(const FString& BuilderIdentifier)
{
if (GizmoBuilders.Contains(BuilderIdentifier) == false)
{
DisplayMessage(
FText::Format(LOCTEXT("DeregisterFailedMessage", "UInteractiveGizmoManager::DeregisterGizmoType: could not find requested type {0}"), FText::FromString(BuilderIdentifier) ),
EToolMessageLevel::Internal);
return false;
}
GizmoBuilders.Remove(BuilderIdentifier);
return true;
}
UInteractiveGizmo* UInteractiveGizmoManager::CreateGizmo(const FString& BuilderIdentifier, const FString& InstanceIdentifier, void* Owner)
{
if ( GizmoBuilders.Contains(BuilderIdentifier) == false )
{
DisplayMessage(
FText::Format(LOCTEXT("CreateGizmoCannotFindFailedMessage", "UInteractiveGizmoManager::CreateGizmo: could not find requested type {0}"), FText::FromString(BuilderIdentifier) ),
EToolMessageLevel::Internal);
return nullptr;
}
UInteractiveGizmoBuilder* FoundBuilder = GizmoBuilders[BuilderIdentifier];
// check if we have used this instance identifier
if (InstanceIdentifier.IsEmpty() == false)
{
for (FActiveGizmo& ActiveGizmo : ActiveGizmos)
{
if (ActiveGizmo.InstanceIdentifier == InstanceIdentifier)
{
DisplayMessage(
FText::Format(LOCTEXT("CreateGizmoExistsMessage", "UInteractiveGizmoManager::CreateGizmo: instance identifier {0} already in use!"), FText::FromString(InstanceIdentifier) ),
EToolMessageLevel::Internal);
return nullptr;
}
}
}
FToolBuilderState CurrentSceneState;
QueriesAPI->GetCurrentSelectionState(CurrentSceneState);
UInteractiveGizmo* NewGizmo = FoundBuilder->BuildGizmo(CurrentSceneState);
if (NewGizmo == nullptr)
{
DisplayMessage(LOCTEXT("CreateGizmoReturnNullMessage", "UInteractiveGizmoManager::CreateGizmo: BuildGizmo() returned null"), EToolMessageLevel::Internal);
return nullptr;
}
NewGizmo->Setup();
// register new active input behaviors
InputRouter->RegisterSource(NewGizmo);
PostInvalidation();
FActiveGizmo ActiveGizmo = { NewGizmo, BuilderIdentifier, InstanceIdentifier, Owner };
ActiveGizmos.Add(ActiveGizmo);
return NewGizmo;
}
bool UInteractiveGizmoManager::DestroyGizmo(UInteractiveGizmo* Gizmo)
{
auto Pred = [Gizmo](const FActiveGizmo& ActiveGizmo) {return ActiveGizmo.Gizmo == Gizmo; };
if (!ensure(ActiveGizmos.FindByPredicate(Pred)))
{
return false;
}
InputRouter->ForceTerminateSource(Gizmo);
Gizmo->Shutdown();
InputRouter->DeregisterSource(Gizmo);
ActiveGizmos.RemoveAll(Pred);
PostInvalidation();
return true;
}
TArray<UInteractiveGizmo*> UInteractiveGizmoManager::FindAllGizmosOfType(const FString& BuilderIdentifier)
{
TArray<UInteractiveGizmo*> Found;
for (int i = 0; i < ActiveGizmos.Num(); ++i)
{
if (ActiveGizmos[i].BuilderIdentifier == BuilderIdentifier)
{
Found.Add(ActiveGizmos[i].Gizmo);
}
}
return Found;
}
void UInteractiveGizmoManager::DestroyAllGizmosOfType(const FString& BuilderIdentifier)
{
TArray<UInteractiveGizmo*> ToRemove = FindAllGizmosOfType(BuilderIdentifier);
for (int i = 0; i < ToRemove.Num(); ++i)
{
DestroyGizmo(ToRemove[i]);
}
}
void UInteractiveGizmoManager::DestroyAllGizmosByOwner(void* Owner)
{
TArray<UInteractiveGizmo*> Found;
for ( const FActiveGizmo& ActiveGizmo : ActiveGizmos )
{
if (ActiveGizmo.Owner == Owner)
{
Found.Add(ActiveGizmo.Gizmo);
}
}
for (UInteractiveGizmo* Gizmo : Found)
{
DestroyGizmo(Gizmo);
}
}
UInteractiveGizmo* UInteractiveGizmoManager::FindGizmoByInstanceIdentifier(const FString& Identifier)
{
for (int i = 0; i < ActiveGizmos.Num(); ++i)
{
if (ActiveGizmos[i].InstanceIdentifier == Identifier)
{
return ActiveGizmos[i].Gizmo;
}
}
return nullptr;
}
void UInteractiveGizmoManager::Tick(float DeltaTime)
{
for (FActiveGizmo& ActiveGizmo : ActiveGizmos)
{
ActiveGizmo.Gizmo->Tick(DeltaTime);
}
}
void UInteractiveGizmoManager::Render(IToolsContextRenderAPI* RenderAPI)
{
for (FActiveGizmo& ActiveGizmo : ActiveGizmos)
{
ActiveGizmo.Gizmo->Render(RenderAPI);
}
}
void UInteractiveGizmoManager::DrawHUD( FCanvas* Canvas, IToolsContextRenderAPI* RenderAPI )
{
for (FActiveGizmo& ActiveGizmo : ActiveGizmos)
{
ActiveGizmo.Gizmo->DrawHUD(Canvas, RenderAPI);
}
}
void UInteractiveGizmoManager::DisplayMessage(const FText& Message, EToolMessageLevel Level)
{
TransactionsAPI->DisplayMessage(Message, Level);
}
void UInteractiveGizmoManager::PostInvalidation()
{
TransactionsAPI->PostInvalidation();
}
void UInteractiveGizmoManager::BeginUndoTransaction(const FText& Description)
{
TransactionsAPI->BeginUndoTransaction(Description);
}
void UInteractiveGizmoManager::EndUndoTransaction()
{
TransactionsAPI->EndUndoTransaction();
}
void UInteractiveGizmoManager::EmitObjectChange(UObject* TargetObject, TUniquePtr<FToolCommandChange> Change, const FText& Description)
{
TransactionsAPI->AppendChange(TargetObject, MoveTemp(Change), Description );
}
Gizmos: refactor Modeling Mode gizmo creation out of InteractiveGizmoManager. Editor will use other "default" transform gizmo implementations, and so the UTransformGizmo creation helper functions do not belong in GizmoManager. Instead a UTransformGizmoContextObject now provides this functionality. ModelingToolsEditorMode (and any other modes/systems that want to use these gizmo convenience functions) creates an instance of UTransformGizmoContextObject and registers it with the ContextObjectStore. Calling code can spawn a new UTransformGizmo by looking this object up in the ContextStore and calling it's helper functions. Static versions of the helper functions in the UE::TransformGizmoUtil:: namespace provide a single-line interface that replaces the previous GizmoManager call sites in the MeshModelingTools library. IntervalGizmo is now just registered and unregistered as needed by the MeshSpaceDeformerTool, as this is the only place it is currently used. Previous implementation in InteractiveGizmoManager is left intact as there are a few uses outside of MeshModelingTools that need to be cleaned up before it can be deleted. UTransformGizmo now requires it's Builder to tell it which sub-gizmo identifier strings to pass to the GizmoManager to create axis/plane/rotation sub-gizmos (and the code that registers the Builder must then provide these strings). This cleans up previous explicit references to UInteractiveGizmoManager static strings from UTransformGizmo. #rb Christina.TempelaarL, david.hill #rnx #jira none [CL 16409673 by Ryan Schmidt in ue5-main branch]
2021-05-20 16:39:39 -04:00
UContextObjectStore* UInteractiveGizmoManager::GetContextObjectStore() const
{
return Cast<UInteractiveToolsContext>(GetOuter())->ContextObjectStore;
}
FString UInteractiveGizmoManager::DefaultAxisPositionBuilderIdentifier = TEXT("StandardXFormAxisTranslationGizmo");
FString UInteractiveGizmoManager::DefaultPlanePositionBuilderIdentifier = TEXT("StandardXFormPlaneTranslationGizmo");
FString UInteractiveGizmoManager::DefaultAxisAngleBuilderIdentifier = TEXT("StandardXFormAxisRotationGizmo");
FString UInteractiveGizmoManager::DefaultThreeAxisTransformBuilderIdentifier = TEXT("DefaultThreeAxisTransformBuilderIdentifier");
const FString UInteractiveGizmoManager::CustomThreeAxisTransformBuilderIdentifier = TEXT("CustomThreeAxisTransformBuilderIdentifier");
const FString UInteractiveGizmoManager::CustomRepositionableThreeAxisTransformBuilderIdentifier = TEXT("CustomRepositionableThreeAxisTransformBuilderIdentifier");
FString UInteractiveGizmoManager::DefaultScalableSphereBuilderIdentifier = TEXT("DefaultScalableSphereBuilderIdentifier");
void UInteractiveGizmoManager::RegisterDefaultGizmos()
{
check(bDefaultGizmosRegistered == false);
UAxisPositionGizmoBuilder* AxisTranslationBuilder = NewObject<UAxisPositionGizmoBuilder>();
RegisterGizmoType(DefaultAxisPositionBuilderIdentifier, AxisTranslationBuilder);
UPlanePositionGizmoBuilder* PlaneTranslationBuilder = NewObject<UPlanePositionGizmoBuilder>();
RegisterGizmoType(DefaultPlanePositionBuilderIdentifier, PlaneTranslationBuilder);
UAxisAngleGizmoBuilder* AxisRotationBuilder = NewObject<UAxisAngleGizmoBuilder>();
RegisterGizmoType(DefaultAxisAngleBuilderIdentifier, AxisRotationBuilder);
UCombinedTransformGizmoBuilder* TransformBuilder = NewObject<UCombinedTransformGizmoBuilder>();
Gizmos: refactor Modeling Mode gizmo creation out of InteractiveGizmoManager. Editor will use other "default" transform gizmo implementations, and so the UTransformGizmo creation helper functions do not belong in GizmoManager. Instead a UTransformGizmoContextObject now provides this functionality. ModelingToolsEditorMode (and any other modes/systems that want to use these gizmo convenience functions) creates an instance of UTransformGizmoContextObject and registers it with the ContextObjectStore. Calling code can spawn a new UTransformGizmo by looking this object up in the ContextStore and calling it's helper functions. Static versions of the helper functions in the UE::TransformGizmoUtil:: namespace provide a single-line interface that replaces the previous GizmoManager call sites in the MeshModelingTools library. IntervalGizmo is now just registered and unregistered as needed by the MeshSpaceDeformerTool, as this is the only place it is currently used. Previous implementation in InteractiveGizmoManager is left intact as there are a few uses outside of MeshModelingTools that need to be cleaned up before it can be deleted. UTransformGizmo now requires it's Builder to tell it which sub-gizmo identifier strings to pass to the GizmoManager to create axis/plane/rotation sub-gizmos (and the code that registers the Builder must then provide these strings). This cleans up previous explicit references to UInteractiveGizmoManager static strings from UTransformGizmo. #rb Christina.TempelaarL, david.hill #rnx #jira none [CL 16409673 by Ryan Schmidt in ue5-main branch]
2021-05-20 16:39:39 -04:00
TransformBuilder->AxisPositionBuilderIdentifier = DefaultAxisPositionBuilderIdentifier;
TransformBuilder->PlanePositionBuilderIdentifier = DefaultPlanePositionBuilderIdentifier;
TransformBuilder->AxisAngleBuilderIdentifier = DefaultAxisAngleBuilderIdentifier;
RegisterGizmoType(DefaultThreeAxisTransformBuilderIdentifier, TransformBuilder);
UGizmoViewContext* GizmoViewContext = GetContextObjectStore()->FindContext<UGizmoViewContext>();
if (!GizmoViewContext)
{
GizmoViewContext = NewObject<UGizmoViewContext>();
GetContextObjectStore()->AddContextObject(GizmoViewContext);
}
GizmoActorBuilder = MakeShared<FCombinedTransformGizmoActorFactory>(GizmoViewContext);
UCombinedTransformGizmoBuilder* CustomThreeAxisBuilder = NewObject<UCombinedTransformGizmoBuilder>();
Gizmos: refactor Modeling Mode gizmo creation out of InteractiveGizmoManager. Editor will use other "default" transform gizmo implementations, and so the UTransformGizmo creation helper functions do not belong in GizmoManager. Instead a UTransformGizmoContextObject now provides this functionality. ModelingToolsEditorMode (and any other modes/systems that want to use these gizmo convenience functions) creates an instance of UTransformGizmoContextObject and registers it with the ContextObjectStore. Calling code can spawn a new UTransformGizmo by looking this object up in the ContextStore and calling it's helper functions. Static versions of the helper functions in the UE::TransformGizmoUtil:: namespace provide a single-line interface that replaces the previous GizmoManager call sites in the MeshModelingTools library. IntervalGizmo is now just registered and unregistered as needed by the MeshSpaceDeformerTool, as this is the only place it is currently used. Previous implementation in InteractiveGizmoManager is left intact as there are a few uses outside of MeshModelingTools that need to be cleaned up before it can be deleted. UTransformGizmo now requires it's Builder to tell it which sub-gizmo identifier strings to pass to the GizmoManager to create axis/plane/rotation sub-gizmos (and the code that registers the Builder must then provide these strings). This cleans up previous explicit references to UInteractiveGizmoManager static strings from UTransformGizmo. #rb Christina.TempelaarL, david.hill #rnx #jira none [CL 16409673 by Ryan Schmidt in ue5-main branch]
2021-05-20 16:39:39 -04:00
CustomThreeAxisBuilder->AxisPositionBuilderIdentifier = DefaultAxisPositionBuilderIdentifier;
CustomThreeAxisBuilder->PlanePositionBuilderIdentifier = DefaultPlanePositionBuilderIdentifier;
CustomThreeAxisBuilder->AxisAngleBuilderIdentifier = DefaultAxisAngleBuilderIdentifier;
CustomThreeAxisBuilder->GizmoActorBuilder = GizmoActorBuilder;
RegisterGizmoType(CustomThreeAxisTransformBuilderIdentifier, CustomThreeAxisBuilder);
URepositionableTransformGizmoBuilder* CustomRepositionableThreeAxisBuilder = NewObject<URepositionableTransformGizmoBuilder>();
Gizmos: refactor Modeling Mode gizmo creation out of InteractiveGizmoManager. Editor will use other "default" transform gizmo implementations, and so the UTransformGizmo creation helper functions do not belong in GizmoManager. Instead a UTransformGizmoContextObject now provides this functionality. ModelingToolsEditorMode (and any other modes/systems that want to use these gizmo convenience functions) creates an instance of UTransformGizmoContextObject and registers it with the ContextObjectStore. Calling code can spawn a new UTransformGizmo by looking this object up in the ContextStore and calling it's helper functions. Static versions of the helper functions in the UE::TransformGizmoUtil:: namespace provide a single-line interface that replaces the previous GizmoManager call sites in the MeshModelingTools library. IntervalGizmo is now just registered and unregistered as needed by the MeshSpaceDeformerTool, as this is the only place it is currently used. Previous implementation in InteractiveGizmoManager is left intact as there are a few uses outside of MeshModelingTools that need to be cleaned up before it can be deleted. UTransformGizmo now requires it's Builder to tell it which sub-gizmo identifier strings to pass to the GizmoManager to create axis/plane/rotation sub-gizmos (and the code that registers the Builder must then provide these strings). This cleans up previous explicit references to UInteractiveGizmoManager static strings from UTransformGizmo. #rb Christina.TempelaarL, david.hill #rnx #jira none [CL 16409673 by Ryan Schmidt in ue5-main branch]
2021-05-20 16:39:39 -04:00
CustomRepositionableThreeAxisBuilder->AxisPositionBuilderIdentifier = DefaultAxisPositionBuilderIdentifier;
CustomRepositionableThreeAxisBuilder->PlanePositionBuilderIdentifier = DefaultPlanePositionBuilderIdentifier;
CustomRepositionableThreeAxisBuilder->AxisAngleBuilderIdentifier = DefaultAxisAngleBuilderIdentifier;
CustomRepositionableThreeAxisBuilder->GizmoActorBuilder = GizmoActorBuilder;
RegisterGizmoType(CustomRepositionableThreeAxisTransformBuilderIdentifier, CustomRepositionableThreeAxisBuilder);
UScalableSphereGizmoBuilder* ScalableSphereBuilder = NewObject<UScalableSphereGizmoBuilder>();
RegisterGizmoType(DefaultScalableSphereBuilderIdentifier, ScalableSphereBuilder);
bDefaultGizmosRegistered = true;
}
UCombinedTransformGizmo* UInteractiveGizmoManager::Create3AxisTransformGizmo(void* Owner, const FString& InstanceIdentifier)
{
check(bDefaultGizmosRegistered);
UInteractiveGizmo* NewGizmo = CreateGizmo(DefaultThreeAxisTransformBuilderIdentifier, InstanceIdentifier, Owner);
check(NewGizmo);
return Cast<UCombinedTransformGizmo>(NewGizmo);
}
UCombinedTransformGizmo* UInteractiveGizmoManager::CreateCustomTransformGizmo(ETransformGizmoSubElements Elements, void* Owner, const FString& InstanceIdentifier)
{
check(bDefaultGizmosRegistered);
GizmoActorBuilder->EnableElements = Elements;
UInteractiveGizmo* NewGizmo = CreateGizmo(CustomThreeAxisTransformBuilderIdentifier, InstanceIdentifier, Owner);
check(NewGizmo);
return Cast<UCombinedTransformGizmo>(NewGizmo);
}
UCombinedTransformGizmo* UInteractiveGizmoManager::CreateCustomRepositionableTransformGizmo(ETransformGizmoSubElements Elements, void* Owner, const FString& InstanceIdentifier)
{
check(bDefaultGizmosRegistered);
GizmoActorBuilder->EnableElements = Elements;
UInteractiveGizmo* NewGizmo = CreateGizmo(CustomRepositionableThreeAxisTransformBuilderIdentifier, InstanceIdentifier, Owner);
check(NewGizmo);
return Cast<UCombinedTransformGizmo>(NewGizmo);
}
#undef LOCTEXT_NAMESPACE