自定义工具管理类上下文
工具管理类:MyToolsManager,管理类依赖类:ContextQueriesAPI、ContextTransactionsAPI
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "ContextQueriesAPI.h"
#include "ContextTransactionsAPI.h"
#include "InteractiveToolsContext.h"
#include "Subsystems/WorldSubsystem.h"
#include "MyToolsManager.generated.h"
UCLASS()
class CUSTOMTOOLS_API UMyToolsManager : public UTickableWorldSubsystem
{
GENERATED_BODY()
public:
static UMyToolsManager* Get(UObject* WorldContext = nullptr);
// 1 重写父类方法
virtual void OnWorldBeginPlay(UWorld& InWorld)override;
virtual void Deinitialize() override;
virtual bool DoesSupportWorldType(const EWorldType::Type WorldType) const override;
virtual void Tick(float DeltaTime) override;
virtual TStatId GetStatId() const override {RETURN_QUICK_DECLARE_CYCLE_STAT(UMyToolsManager, STATGROUP_Tickables);}
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
protected:
// 2 初始化工具上下文
void InitalizeToolsContext(UWorld& InWorld);
//5 关闭工具上下文
void ShutdownToolsContext();
private:
// 3 声明工具上下文
UPROPERTY()
TObjectPtr<UInteractiveToolsContext> ToolsContext;
// 4 声明当前激活的工具
UPROPERTY()
TObjectPtr<UInteractiveTool> CurrentActiveTool;
TSharedPtr<FContextQueriesAPI> QueriesAPI;
TSharedPtr<FContextTransactionsAPI> TransactionsAPI;
// 6 将这个管理类设置为单例模式
static UMyToolsManager* g_MyToolsManager;
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyToolsManager.h"
UMyToolsManager* UMyToolsManager::g_MyToolsManager = nullptr;
UMyToolsManager* UMyToolsManager::Get(UObject* WorldContext)
{
if (!g_MyToolsManager)
{
UWorld* World = GEngine->GetWorldFromContextObject(WorldContext, EGetWorldErrorMode::LogAndReturnNull);
if(!World)
{
World = GWorld;
}
if(World)
{
g_MyToolsManager = World->GetSubsystem<UMyToolsManager>();
}
}
return g_MyToolsManager;
}
void UMyToolsManager::OnWorldBeginPlay(UWorld& InWorld)
{
InitalizeToolsContext(InWorld);
}
void UMyToolsManager::Deinitialize()
{
ShutdownToolsContext();
}
bool UMyToolsManager::DoesSupportWorldType(const EWorldType::Type WorldType) const
{
return EWorldType::Game || EWorldType::PIE;
}
void UMyToolsManager::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void UMyToolsManager::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
}
void UMyToolsManager::InitalizeToolsContext(UWorld& InWorld)
{
// 创建工具上下文
ToolsContext = NewObject<UInteractiveToolsContext>();
QueriesAPI = MakeShareable(new FContextQueriesAPI(ToolsContext,&InWorld));
TransactionsAPI = MakeShareable(new FContextTransactionsAPI());
//查看父类UInteractiveToolsContext中的Initialize方法,需要两个参数
//IToolsContextQueriesAPI* QueriesAPI, IToolsContextTransactionsAPI* TransactionsAPI
//所以创建了继承至他们的类ContextQueriesAPI、ContextTransactionsAPI
ToolsContext->Initialize(QueriesAPI.Get(),TransactionsAPI.Get());
}
void UMyToolsManager::ShutdownToolsContext()
{
if(ToolsContext)
{
if(ToolsContext->ToolManager)
{
if(ToolsContext->ToolManager->HasActiveTool(EToolSide::Mouse))
{
EToolShutdownType ShutdownType = ToolsContext->ToolManager->CanCancelActiveTool(EToolSide::Mouse)?EToolShutdownType::Cancel:EToolShutdownType::Completed;
ToolsContext->ToolManager->DeactivateTool(EToolSide::Mouse,ShutdownType);
}
}
ToolsContext->Shutdown();
ToolsContext=nullptr;
}
QueriesAPI = nullptr;
TransactionsAPI = nullptr;
}
#pragma once
#include "InteractiveToolsContext.h"
#include "ToolContextInterfaces.h"
class FContextQueriesAPI : public IToolsContextQueriesAPI
{
public:
// 1 构造函数,查看父类,GetCurrentEditingWorld函数需要UWorld*,所以加入了该参数
// GetCurrentSelectionState函数的参数FToolBuilderState中需要UInteractiveToolManager* ToolManager,所以加入了该参数
FContextQueriesAPI(UInteractiveToolsContext* ToolsContext, UWorld* World);
// 2 重写父类方法
virtual UWorld* GetCurrentEditingWorld() const override;
virtual void GetCurrentSelectionState(FToolBuilderState& StateOut) const override;
virtual void GetCurrentViewState(FViewCameraState& StateOut) const override;
virtual EToolContextCoordinateSystem GetCurrentCoordinateSystem() const { return EToolContextCoordinateSystem::World; }
virtual EToolContextTransformGizmoMode GetCurrentTransformGizmoMode() const { return EToolContextTransformGizmoMode::Combined; }
virtual FToolContextSnappingConfiguration GetCurrentSnappingSettings() const { return FToolContextSnappingConfiguration(); }
virtual UMaterialInterface* GetStandardMaterial(EStandardToolContextMaterials MaterialType) const override;
//因为需要返回Viewport,所以需要声明一个Viewport变量
virtual FViewport* GetHoveredViewport() const override;
virtual FViewport* GetFocusedViewport() const override;
protected:
private:
// 3 声明当前世界
TWeakObjectPtr<UWorld> CurrentWorldWeakPtr;
TWeakObjectPtr<UInteractiveToolsContext> ToolsContextWeakPtr;
FViewport* CurrentActiveViewport = nullptr;
};
#include "ContextQueriesAPI.h"
#include "MaterialDomain.h"
#include "Kismet/GameplayStatics.h"
FContextQueriesAPI::FContextQueriesAPI(UInteractiveToolsContext* ToolsContext, UWorld* World)
: ToolsContextWeakPtr(ToolsContext), CurrentWorldWeakPtr(World)
{
check(ToolsContextWeakPtr.IsValid());
CurrentActiveViewport = GEngine->GameViewport->Viewport;
}
UWorld* FContextQueriesAPI::GetCurrentEditingWorld() const
{
if (CurrentWorldWeakPtr.IsValid()&&CurrentWorldWeakPtr->IsValidLowLevel())
{
return CurrentWorldWeakPtr.Get();
}
return nullptr;
}
void FContextQueriesAPI::GetCurrentSelectionState(FToolBuilderState& StateOut) const
{
StateOut.World = CurrentWorldWeakPtr.Get();
StateOut.ToolManager = ToolsContextWeakPtr->ToolManager;
StateOut.TargetManager = ToolsContextWeakPtr->TargetManager;
StateOut.GizmoManager = ToolsContextWeakPtr->GizmoManager;
}
void FContextQueriesAPI::GetCurrentViewState(FViewCameraState& StateOut) const
{
TObjectPtr<APlayerCameraManager> CurrentPlayerCameraManager = UGameplayStatics::GetPlayerController(ToolsContextWeakPtr.Get(),0)->PlayerCameraManager;
StateOut.Position = CurrentPlayerCameraManager->GetCameraLocation();
StateOut.Orientation = CurrentPlayerCameraManager->GetCameraRotation().Quaternion();
StateOut.HorizontalFOVDegrees = CurrentPlayerCameraManager->GetFOVAngle();
StateOut.AspectRatio = 1.f;
StateOut.bIsOrthographic = CurrentPlayerCameraManager->IsOrthographic();
StateOut.bIsVR = false;
}
UMaterialInterface* FContextQueriesAPI::GetStandardMaterial(EStandardToolContextMaterials MaterialType) const
{
return UMaterial::GetDefaultMaterial(MD_Surface);
}
FViewport* FContextQueriesAPI::GetHoveredViewport() const
{
return CurrentActiveViewport;
}
FViewport* FContextQueriesAPI::GetFocusedViewport() const
{
return CurrentActiveViewport;
}
#pragma once
#include "ToolContextInterfaces.h"
class FContextTransactionsAPI :public IToolsContextTransactionsAPI
{
public:
// 1 重写父类方法
virtual void DisplayMessage(const FText& Message, EToolMessageLevel Level) override;
virtual void PostInvalidation() override;
virtual void BeginUndoTransaction(const FText& Description) override;
virtual void EndUndoTransaction() override;
virtual void AppendChange(UObject* TargetObject, TUniquePtr<FToolCommandChange> Change, const FText& Description) override;
virtual bool RequestSelectionChange(const FSelectedObjectsChangeList& SelectionChange) override;
};
#include "ContextTransactionsAPI.h"
#include "InteractiveToolChange.h"
void FContextTransactionsAPI::DisplayMessage(const FText& Message, EToolMessageLevel Level)
{
UE_LOG(LogTemp,Log,TEXT("[Tool Message] %s"),*Message.ToString());
}
void FContextTransactionsAPI::PostInvalidation()
{
}
void FContextTransactionsAPI::BeginUndoTransaction(const FText& Description)
{
}
void FContextTransactionsAPI::EndUndoTransaction()
{
}
void FContextTransactionsAPI::AppendChange(UObject* TargetObject, TUniquePtr<FToolCommandChange> Change,
const FText& Description)
{
//编译报错,需要添加"InteractiveToolsFramework"模块,并加入#include "InteractiveToolChange.h" 头文件
}
bool FContextTransactionsAPI::RequestSelectionChange(const FSelectedObjectsChangeList& SelectionChange)
{
return false;
}
到这里是创建工具管理类的基本方法,创建完整的自定义工具类还需要继续创建自定义工具,然后在工具管理类中注册