自定义工具管理类上下文
工具管理类: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、ContextTransactionsAPIToolsContext->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;
}
到这里是创建工具管理类的基本方法,创建完整的自定义工具类还需要继续创建自定义工具,然后在工具管理类中注册