UE5 创建自定义工具上下文的方法

ops/2025/2/7 18:28:47/

自定义工具管理类上下文

工具管理类: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;
}

 到这里是创建工具管理类的基本方法,创建完整的自定义工具类还需要继续创建自定义工具,然后在工具管理类中注册


http://www.ppmy.cn/ops/156502.html

相关文章

Spring Boot 实例解析:从概念到代码

SpringBoot 简介&#xff1a; 简化 Spring 应用开发的一个框架整合 Spring 技术栈的一个大整合J2EE 开发的一站式解决方案优点&#xff1a;快速创建独立运行的 Spring 项目以及与主流框架集成使用嵌入式的 Servlet 容器&#xff0c;应用无需打成 war 包&#xff0c;内嵌 Tomcat…

DeepSeek横空出世,AI格局或将改写?

引言 这几天&#xff0c;国产AI大模型DeepSeek R1&#xff0c;一飞冲天&#xff0c;在全球AI圈持续引爆热度&#xff0c;DeepSeek R1 已经是世界上最先进的 AI 模型之一&#xff0c;可与 OpenAI 的新 o1 和 Meta 的 Llama AI 模型相媲美。 DeepSeek-V3模型发布后&#xff0c;在…

Unity VideoPlayer播放视屏不清晰的一种情况

VideoPlayer的Rnder Texture可以设置Size,如果你的视屏是1920*1080那么就设置成1920*1080。 如果设置成其他分辨率比如800*600会导致视屏不清晰。

C# Winform制作一个登录系统

using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;namespace 登录 {p…

【再谈设计模式】命令模式~封装请求的指挥者

一、引言 在软件工程&#xff0c;软件开发过程中&#xff0c;高效的设计模式是构建灵活、可维护和可扩展系统的关键。命令模式作为一种行为型设计模式&#xff0c;为处理各种操作请求提供了一种巧妙的解决方案。它像是一个指挥中心&#xff0c;有条不紊地协调请求的发送者和执行…

物联网 STM32【源代码形式-使用以太网】连接OneNet IOT从云产品开发到底层MQTT实现,APP控制 【保姆级零基础搭建】

物联网&#xff08;IoT&#xff09;‌是指通过各种信息传感器、射频识别技术、全球定位系统、红外感应器等装置与技术&#xff0c;实时采集并连接任何需要监控、连接、互动的物体或过程&#xff0c;实现对物品和过程的智能化感知、识别和管理。物联网的核心功能包括数据采集与监…

unity学习28:灯光light相关 类型type,模式mode等

目录 1 场景里的默认灯光 1.1 默认灯光 1.2 可以添加多个灯光 2 灯光类型 2.0 灯光的类型 2.1 定向灯光 directional light&#xff08;想象成太阳&#xff09; 2.1.1 全局和局部 2.2 聚光 spot ---- 类手电筒的光线 2.2.1 控制效果 2.2.2 还可以控制 spot light的…

C# 程序计算圆的面积(Program to find area of a circle)

给定圆的半径&#xff0c;求该圆的面积。 可以使用以下公式简单地计算圆的面积。 其中 r 是圆的半径&#xff0c;它可能是浮点数&#xff0c;因为饼图的值为 3.14 方法&#xff1a;使用给定的半径&#xff0c;使用上述公式找到面积&#xff1a;&#xff08;pi * r * r&#…