UE5引擎编辑器插件开发归档

下面是自己在学习编辑器界面开发学习内容的总结,有错误的地方希望大家指出,谢谢~

学习的教程为:https://www.bilibili.com/video/BV1M84y1K7m4

  1. 创建空编辑器插件

新添加一个编辑器的插件,修改插件的设定,"Type": 从Runtime改为Editor,"LoadingPhase": "Default"改为PreDefault

此处参考文档:https://blog.csdn.net/pp1191375192/article/details/103139304/

{
    "FileVersion": 3,
    "Version": 1,
    "VersionName": "1.0",
    "FriendlyName": "SuperManager",
    "Description": "",
    "Category": "Other",
    "CreatedBy": "",
    "CreatedByURL": "",
    "DocsURL": "",
    "MarketplaceURL": "",
    "SupportURL": "",
    "CanContainContent": true,
    "IsBetaVersion": false,
    "IsExperimentalVersion": false,
    "Installed": false,
    "Modules": [
        {
            "Name": "SuperManager",
            "Type": "Editor",
            "LoadingPhase": "PreDefault"
        }
    ]
}
  1. 新建类继承AssetActionUtility并添加至插件目录

添加后报错,少引入模块

在cs文件中添加指定的模块"Blutility",继续添加私有模块

        PrivateIncludePaths.AddRange(
            new string[] {
                System.IO.Path.GetFullPath(Target.RelativeEnginePath)+    "/Source/Editor/Blutility/Private" 
            
            }
            );
            
        
        PublicDependencyModuleNames.AddRange(
            new string[]
            {
                "Core",
                "Blutility",
                // ... add other public dependencies that you statically link with here ...
            }

测试代码

#pragma once

#include "CoreMinimal.h"    
#include "Blutility/Classes/AssetActionUtility.h"
#include "QuickAssetAction.generated.h"

/**
 * 
 */
UCLASS()
class SUPERMANAGER_API UQuickAssetAction : public UAssetActionUtility
{
    GENERATED_BODY()

public:
    UFUNCTION(CallInEditor)
    void TestFun();
    
};

#include "AssetActions/QuickAssetAction.h"

void UQuickAssetAction::TestFun()
{
    if (GEngine)
    {
        GEngine->AddOnScreenDebugMessage(-1,8.0f,FColor::Cyan,TEXT("worlking"));
    }
}

在编辑器中新建蓝图 并在窗口中右击显示测试,点击后打印到屏幕上

  1. 复制资源文件功能

首先引入两个

#include "EditorAssetLibrary.h"

#include "EditorUtilityLibrary.h"

添加"EditorScriptingUtilities"模块到cs

添加"EditorScriptingUtilities"到插件目录

EditorAssetLibrary 是一个 Unreal Engine 4 中的静态类,提供了许多用于在编辑器中管理和操作资产的功能。它包含许多静态函数,可以在 C++ 代码中使用。

以下是一些 EditorAssetLibrary 可用的功能:

  • 获取资产的标签(GetAssetRegistryTags

  • 检查资产是否处于编辑器内(IsAssetLoadedInEditor

  • 获取资产的路径(GetPathNameForLoadedAsset

  • 获取资产的类型(GetAssetType

  • 保存资产(SaveAsset

  • 创建新的资产(CreateAsset

  • 检查资产是否存在(DoesAssetExist

  • 加载资产(LoadAsset

这些函数可以帮助您在编辑器中进行资产管理和操作,例如创建新的资产、保存资产、加载资产等。这些函数还可以帮助您在运行时访问编辑器中的资产,例如获取资产的路径、类型和标签等。

需要注意的是,EditorAssetLibrary 是一个专门用于编辑器的类,它不适用于在游戏运行时使用。如果您需要在游戏运行时加载、创建或保存资产,则需要使用其他类和函数,例如 AssetRegistryAssetToolsFAssetData 等。

EditorUtilityLibrary 是 Unreal Engine 4 中的一个静态类,提供了一些有用的函数,可以在编辑器中使用。这些函数可以帮助您处理编辑器中的对象、场景和资产,以及与编辑器交互的其他功能。

本示例中获取选中的资源函数 UEditorUtilityLibrary::GetSelectedAssetData();

以下是一些 EditorUtilityLibrary 可用的功能:

  • 捕捉视图到指定的Actor或位置(GetActorBoundsGetActorBoundsLocalGetBoundsForSelection等)

  • 启用或禁用编辑器视口中的游戏模式(SetGameView

  • 将选定的对象重定位到编辑器视口的中心(FocusViewportOnSelectedObjects

  • 执行命令(ExecuteEditorCommand

  • 清空编辑器控制台(ClearEditorConsole

  • 检查资产是否处于编辑器内(IsAssetLoadedInEditor

  • 打开资产在资产编辑器中的编辑器(OpenEditorForAsset

  • 获取或设置编辑器选项(GetEditorUserSettingsSetEditorUserSettings

EditorUtilityLibrary 可以帮助您简化在编辑器中执行的任务,例如在编辑器中捕捉对象的边界框、执行编辑器命令、清空编辑器控制台等。它还可以帮助您管理编辑器选项和资产。

需要注意的是,EditorUtilityLibrary 是一个专门用于编辑器的类,它不适用于在游戏运行时使用。如果您需要在游戏运行时执行这些功能,则需要使用其他类和函数。

    UFUNCTION(CallInEditor)
    void DuplicateAssets(int32 NumOfDuplicates);
void UQuickAssetAction::DuplicateAssets(int32 NumOfDuplicates)
{
  if (NumOfDuplicates<=0)
  {
    Print(TEXT("请指定资源的数量"),FColor::Red);
    return;
  }
  
//获取当前选中的资源data
  TArray<FAssetData> SelectedAssetData = UEditorUtilityLibrary::GetSelectedAssetData();
  uint32 Counter = 0;

//遍历选中的文件
for(const FAssetData& SelectedData:SelectedAssetData)
{
  for (int32 i  =0;i<NumOfDuplicates;i++)
  {
//获取资源路径
    const FString SourceAssetPath = SelectedData.GetSoftObjectPath().ToString();
    //const FString SourceAsserPath = SelectedData.ObjectPath.ToString();
    //IDE提示上面的函数 下个版本弃用
//获取资源名称 并在新命名的文件后加上数量
    const FString NewDuplicatedAssetName=SelectedData.AssetName.ToString() + TEXT("_") +FString::FromInt(i+1);
//将文件夹前缀名字 和 新文件路径名称拼到一起 
   const FString NewPathName = FPaths::Combine(SelectedData.PackagePath.ToString(),NewDuplicatedAssetName);

//复制资源 保存资源
    if (UEditorAssetLibrary::DuplicateAsset(SourceAssetPath,NewPathName))
    {
      UEditorAssetLibrary::SaveAsset(NewPathName,false);
      ++Counter;
    }

  }
}
  if (Counter>0)
  {
    Print(TEXT("复制成功"+FString::FromInt(Counter)+" 文件"),FColor::Green);
  }
  
  
}

编译后右击资源文件 选择复制

  1. 提示确认框 和 通知UI

当用户输入一个错误的复制数量时,弹出一个提示框

在DebugHeader.h中引入下面头文件

#include "Misc/MessageDialog.h"

EAppReturnType::Type ShowMsgDialog(EAppMsgType::Type MsgType,const FString& Message,bool BShowMsgWaring = true)
{
     
    //是否显示警告弹框文字
    if (BShowMsgWaring)
    {
        //弹框标题
         FText MsgTitle = FText::FromString(TEXT("警告"));
         return  FMessageDialog::Open(MsgType,FText::FromString(Message),&MsgTitle);
    }
    else
    {
        return  FMessageDialog::Open(MsgType,FText::FromString(Message));
    }
}

输入<=0时

void UQuickAssetAction::DuplicateAssets(int32 NumOfDuplicates)
{
  if (NumOfDuplicates<=0)
  {
    ShowMsgDialog(EAppMsgType::Ok,TEXT("请指定有效资源数量"),false);
    
    return;
  }

弹出提示框

当复制成功时,弹出UI提示用户,复制成功

在DebugHeader.h中引入下面头文件

#include "Widgets/Notifications/SNotificationList.h"

#include "Framework/Notifications/NotificationManager.h"

void ShowNotifyInfo(const FString &Message)
{

    //创建info
    FNotificationInfo NotifyInfo(FText::FromString(Message));
    //大号字体
    NotifyInfo.bUseLargeFont =true;
    //消失时间
    NotifyInfo.FadeOutDuration =7.0f;

    //通过Manager 弹出
    FSlateNotificationManager::Get().AddNotification(NotifyInfo);
    
}
  if (Counter>0)
  {
 
    ShowNotifyInfo(TEXT("拷贝成功文件数量:  "+FString::FromInt(Counter)));
  }

弹出Slate UI

MessageDialog 是 Unreal Engine 中的一个类,用于在游戏或编辑器中显示消息对话框。消息对话框通常用于向用户显示信息、警告或错误消息,并让用户选择接受或拒绝。

MessageDialog 提供了创建和显示消息对话框的方法,以及处理用户响应的方法。您可以使用 MessageDialog 在游戏或编辑器中显示自定义消息对话框,以向用户显示重要信息或警告。

以下是一些 MessageDialog 可用的功能:

  • 创建消息对话框(Open

  • 设置消息对话框的标题、正文和按钮

  • 显示消息对话框,并等待用户响应(ShowModal

  • 处理用户响应,例如确定、取消或其他自定义按钮(OnButtonClicked

例如,您可以使用 MessageDialog 在编辑器中显示警告消息,并询问用户是否要继续进行某个操作。在游戏中,您可以使用 MessageDialog 在游戏中显示任务完成消息或错误消息,并要求用户重新尝试或退出游戏。

总之,MessageDialog 是 Unreal Engine 中非常有用的一个类,可用于向用户显示消息对话框并处理用户响应

FSlateNotificationManager 是 Unreal Engine 4 中的一个类,用于在 Slate UI 框架中管理通知(notifications)。通知是用于向用户提供关于操作或状态的信息的消息。通知可以出现在 UI 中的任何地方,例如在屏幕的左上角或右下角。

FSlateNotificationManager 管理通知的创建、显示和消失。它可以处理各种通知类型,例如成功消息、警告消息、错误消息、进度消息等。

以下是一些 FSlateNotificationManager 可用的功能:

  • 创建通知(AddNotification

  • 设置通知的文本、图标和持续时间(SetNotificationTextSetNotificationIconSetExpireDuration

  • 显示通知(ShowNotification

  • 隐藏通知(HideNotification

  • 关闭通知(RemoveNotification

FSlateNotificationManager 可以帮助您在 UI 中显示通知,以提供操作或状态的信息。例如,您可以在 UI 中显示一个通知,以告诉用户文件已经成功保存,或者通知用户正在进行某个耗时操作的进度。

需要注意的是,FSlateNotificationManager 是 Slate UI 框架的一部分,而不是 Unreal Engine 的其他部分。它仅适用于 Slate UI,不能在其他 UI 框架中使用。

  1. 批量按资源类型 添加前缀

新建一个Tmap中存储要替换 类 对应 名称

private:
    TMap<UClass*,FString> PrefixMap =
        {
{
    UBlueprint::StaticClass(),TEXT("BP_")
}
        };

新建编辑器函数

    UFUNCTION(CallInEditor,meta=(DisplayName ="统一修改前缀"))
    void AddPrefixes();

函数内实现:根据资源类型 找到对应的前缀 替换资源名称

void UQuickAssetAction::AddPrefixes()
{
  TArray<UObject*>SelectedObject =UEditorUtilityLibrary::GetSelectedAssets();
  uint32 Counter =0;
  for (UObject* Object:SelectedObject)
  {
    //如果无效 跳出当前循环
    if (!Object) continue;
    //寻找前缀
    FString* PrefixFound = PrefixMap.Find(Object->GetClass());

    //指针无效或者找到的值是空时 提示用户
    if (!PrefixFound || PrefixFound->IsEmpty())
    {
      Print(TEXT("无法找到前缀"+ Object->GetClass()->GetName()),FColor::Red);
      continue;
    }

    FString OldName =  Object->GetName();
    //检查当前文件是不是已经加过前缀
    if (OldName.StartsWith(*PrefixFound))
    {
      Print(OldName+TEXT("此文件已包含前缀"),FColor::Red);
      continue;
    }

    //添加前缀
    const FString NewNameWithPrefix = *PrefixFound +OldName;
    UEditorUtilityLibrary::RenameAsset(Object,NewNameWithPrefix);
    ++Counter;
  }

  ShowNotifyInfo("重命名成功文件数量:  "+FString::FromInt(Counter));
}
  1. 删除无引用资源文件

批量删除,如果资源有引用存在 则提示用户

void UQuickAssetAction::RemoveUnusedAssets()
{
  TArray<FAssetData> SelectedObject = UEditorUtilityLibrary::GetSelectedAssetData();
  TArray<FAssetData> UnusedAssetsDatas;
  for (auto Object : SelectedObject)
  {
    //检索资源的引用数量
    TArray<FString> AssetReferencersNums = UEditorAssetLibrary::FindPackageReferencersForAsset(
      Object.GetSoftObjectPath().ToString(), false);
    //如果引用数量为0 则添加到待删除数组中
    if (AssetReferencersNums.Num() == 0)
    {
      UnusedAssetsDatas.Add(Object);
    }
  }

  //如果待删除数量为0
  if (UnusedAssetsDatas.Num()==0)
  {
    ShowMsgDialog(EAppMsgType::Ok,TEXT("所选资源有引用,无法删除"),false);
    return;
  }

  //检查待删除的数量
  const int32 DeleteNums = ObjectTools::DeleteAssets(UnusedAssetsDatas);
  //如果为0 则没有待删除的 直接return
  if (DeleteNums==0)return;
  //删除后提示用户
  ShowNotifyInfo(TEXT("成功删除资源数量: ")+FString::FromInt(DeleteNums));

}
  1. 修复资源文件重定向

参考文档:https://www.codenong.com/cs107010490/

当一个Assets文件移动了新的路径后,如果没有重定向文件夹,再次移动时会有路径错误的问题。

文件夹重定向之后修复。

将路径下的FAssetData转成UObjectRedirector

UObjectRedirector 是虚幻引擎中的一个类,用于处理对象重定向。当您删除一个对象时,如果有其他对象引用了该对象,这些引用就会变为无效。如果您尝试访问这些无效的引用,程序就会崩溃。为了解决这个问题,虚幻引擎提供了 UObjectRedirector 类,用于在删除对象时自动将引用该对象的其他对象重定向到新的对象上。

当您删除一个对象时,虚幻引擎会自动创建一个 UObjectRedirector 对象,并将其添加到 Redirector 目录下。UObjectRedirector 对象存储了指向被删除对象的引用,以及指向新对象的引用。当您尝试访问引用被删除的对象时,虚幻引擎会自动查找对应的 UObjectRedirector 对象,并将引用重定向到新对象上。

AssetRegistry 是 Unreal Engine 中的一个系统级别的工具,用于提供所有项目中的资产(Assets)和资产相关的元数据(MetaData)信息,包括资产的类型、名称、路径、标签等。通过 AssetRegistry,您可以获得项目中所有可用资产的信息,而无需在运行时加载这些资产。

AssetRegistry 具有以下一些主要功能:

  1. 资产搜索:可以按照各种标准搜索资产,如类型、标签、路径、状态等,可以对搜索结果进行排序和过滤。

  1. 资产监听:可以订阅资产的创建、删除、移动、更改等事件,以便您的代码可以在资产发生变化时及时响应。

  1. 资产缓存:可以缓存资产和元数据,以便快速访问它们,减少运行时的加载时间和内存占用。

  1. 资产依赖关系:可以获取资产之间的依赖关系,以便您可以构建更复杂的资产和资源系统。

  1. 资产过滤:可以通过过滤器和标准筛选出特定的资产,以便进行更精细的操作。

在 UE4 中,AssetRegistry 是通过异步任务执行的,因此,您需要注册回调函数来接收搜索结果、监听事件等。AssetRegistry 还可以在游戏运行时使用,以便您的代码可以访问项目中的资产并执行操作。

void UQuickAssetAction::FixUpRedirectors()
{
    
    TArray<UObjectRedirector*>RedirectorsToFixArray;
   //拿到AssetRegistryModule:
    FAssetRegistryModule& AssetRegistryModule =
    FModuleManager::Get().LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry"));

   //Filter 用作AssetRegistry进行查询时的过滤器,可以配置多个属性
   FARFilter Filter;
   Filter.bRecursivePaths =true;
   Filter.PackagePaths.Emplace("/Game");

  
  
   TArray<FAssetData>OutRedirectors;
   //筛选资产数据
   AssetRegistryModule.Get().GetAssets(Filter,OutRedirectors);

  //遍历数据 FAssetData 转换为 UObjectRedirector
  for(const FAssetData& RedirectorData:OutRedirectors)
  {
    if (UObjectRedirector* RedirectorToFix = Cast<UObjectRedirector>(RedirectorData.GetAsset()))
    {
      RedirectorsToFixArray.Add(RedirectorToFix);
    }
  }

   //拿到FAssetToolsModule:
    FAssetToolsModule &AssetToolsModule =
    FModuleManager::LoadModuleChecked<FAssetToolsModule>(TEXT("AssetTools"));

   //重定向
   AssetToolsModule.Get().FixupReferencers(RedirectorsToFixArray);
 
}
  1. 拓展Content Browser 自定义按钮

ContentBrowserModule是UE4中的一个模块,用于管理和显示项目中的内容,包括静态资产、蓝图、关卡和插件等。常用的一些函数包括:

  1. FContentBrowserModule::Get(): 获取ContentBrowserModule单例对象。

  1. FContentBrowserModule::GetAllAssetViewContextMenuExtenders(): 获取所有资产视图的右键菜单扩展器。

  1. FContentBrowserModule::GetAssetContextMenuExtender(): 获取资产视图的右键菜单扩展器。

  1. FContentBrowserModule::GetAssetContextMenuActions(): 获取资产视图的右键菜单动作。

  1. FContentBrowserModule::CreateNewAsset(): 创建新的资产。

  1. FContentBrowserModule::SyncBrowserToAssets(): 将资源同步到内容浏览器。

  1. FContentBrowserModule::GetSelectedAssets(): 获取当前选择的资产。

  1. FContentBrowserModule::Get().Get()->RegisterNotificationCallback(): 注册内容浏览器通知回调函数。

  1. FContentBrowserModule::Get().Get()->UnregisterNotificationCallback(): 取消注册内容浏览器通知回调函数。

这些函数可以帮助开发人员更方便地管理和操作项目中的内容。

本节要在Content Browser中添加我们自定义的事件按钮。在编辑器开始加载的时候就要实现事件的初始化和函数绑定,于是前往模块的StartupModule()下新建初始化函数

模块加载时初始化

void FSuperManagerModule::StartupModule()
{
    InitCBMenuExtention();
}

初始化的函数

在UE5中,GetAllPathViewContextMenuExtenders()是一个静态函数,用于获取注册在编辑器中的所有Path View上下文菜单扩展器。Path View是UE5编辑器中的一个资源管理器,用于浏览和管理项目中的资源。此函数返回一个数组,其中包含所有注册的Path View上下文菜单扩展器的指针。可以使用这些指针来访问扩展器的功能,并将它们添加到Path View上下文菜单中。

void FSuperManagerModule::InitCBMenuExtention()
{
    //拿到FContentBrowserModule:
    FContentBrowserModule &ContentBrowserModule =
    FModuleManager::LoadModuleChecked<FContentBrowserModule>(TEXT("ContentBrowser"));

    //返回&时 保留& 而不是重新复制一份
    //拿到所有PathView 委托的 数组
    TArray<FContentBrowserMenuExtender_SelectedPaths> & ContentBrowserModuleMenuExtenders =
        ContentBrowserModule.GetAllPathViewContextMenuExtenders();

    //创建自己的委托 
    FContentBrowserMenuExtender_SelectedPaths CustomCBMenuDelegate;
    //绑定委托事件
    CustomCBMenuDelegate.BindRaw(this,&FSuperManagerModule::CustomCBMenuExtender);
    //并添加到数组中
    ContentBrowserModuleMenuExtenders.Add(CustomCBMenuDelegate);

    //另外一种写法 add时添加
    /*ContentBrowserModuleMenuExtenders.Add
    (FContentBrowserMenuExtender_SelectedPaths::CreateRaw(this,&FSuperManagerModule::CustomCBMenuExtender));*/
}

添加绑定委托 Hook可以打开编辑器设定里的 显示菜单中的Hook信息

TSharedRef<FExtender> FSuperManagerModule::CustomCBMenuExtender(const TArray<FString>& SelectedPaths)
{
    //创建一个TSharedRef<FExtender> 
    TSharedRef<FExtender> MenuExtender (new  FExtender());
    if (SelectedPaths.Num()>0)
    {
        //找到目标的Hook钩子 , 设置添加的位置, 设置快捷键, 添加绑定的事件委托)
        MenuExtender->AddMenuExtension( TEXT("Delete"),
        EExtensionHook::After,TSharedPtr< FUICommandList >(),
        FMenuExtensionDelegate::CreateRaw(this,&FSuperManagerModule::AddCBMenuEntry ));
    }
    return MenuExtender;
}

完成后继续使用委托设置菜单按钮的信息

//设置菜单按钮的一些信息
void FSuperManagerModule::AddCBMenuEntry(FMenuBuilder& MenuBuilder)
{
    MenuBuilder.AddMenuEntry
    (
    //按钮名称
    FText::FromString(TEXT("删除未被引用的资源")),
    //提示文本
    FText::FromString(TEXT("批量安全删除未使用的Asset")),
    //按钮图标
    FSlateIcon(),
    //绑定要执行的事件
    FExecuteAction::CreateRaw(this,&FSuperManagerModule::OnDeleteUnsuedAssetButtonClicked)
    
        );
}

最后是按钮真正要处理的事件绑定函数

void FSuperManagerModule::OnDeleteUnsuedAssetButtonClicked()
{
    
}

成功添加了一个我们自定义的按钮

  1. 注册创建一个自定义编辑器界面

首先注册编辑器面板 在模块初始化时调用

    //注册窗口
    void RegisterAdvanceDeletionTab();
    //窗口绑定的委托
    TSharedRef<SDockTab> OnSpawnAdvanceDeletionTab(const FSpawnTabArgs& SpawnTabArgs);
void FSuperManagerModule::RegisterAdvanceDeletionTab()
{
    //FGlobalTabmanager注册一个面板 绑定委托 设置窗口名称
    FTabSpawnerEntry TabSpawnerEntry = FGlobalTabmanager::Get()->RegisterNomadTabSpawner(FName("AdvancedDelete"),
        FOnSpawnTab::CreateRaw(this, &FSuperManagerModule::OnSpawnAdvanceDeletionTab));

    TabSpawnerEntry.SetDisplayName(FText::FromString(TEXT("Advanced Delete")));
}

TSharedRef<SDockTab> FSuperManagerModule::OnSpawnAdvanceDeletionTab(const FSpawnTabArgs& SpawnTabArgs)
{
    
    return    SNew(SDockTab).TabRole(NomadTab);
}

点击时弹出

接着尝试绘制窗口内的元素

新建一个C++空类 放置插件目录 新建SlateWidgets 内

#pragma once
#include  "Widgets/SCompoundWidget.h"

class SAdvancedDeletionTab:public  SCompoundWidget
{
    SLATE_BEGIN_ARGS(SAdvancedDeletionTab){}
    //可以传递参数
    SLATE_ARGUMENT(FString,TestString)
    SLATE_END_ARGS()
public:
    void Construct(const FArguments& InArgs);
};
#include "SlateWidgets/AdvancedDeleteWidget.h"

void SAdvancedDeletionTab::Construct(const FArguments& InArgs)
{
    bCanSupportFocus = true;


    ChildSlot
    [
        //传递参数需要带下划线 _TestString
        SNew(STextBlock).Text(FText::FromString(InArgs._TestString))

    ];
}

修改 在打开SNew(SDockTab)的时候尝试传递参数

TSharedRef<SDockTab> FSuperManagerModule::OnSpawnAdvanceDeletionTab(const FSpawnTabArgs& SpawnTabArgs)
{
    
    return    SNew(SDockTab).TabRole(NomadTab)[
                                               SNew(SAdvancedDeletionTab)
                                               .TestString(TEXT("456"))
                                               ];

}

这是弹框显示文本

设置自定义界面的标题

void SAdvancedDeletionTab::Construct(const FArguments& InArgs)
{
    bCanSupportFocus = true;

    //设置字体大小 字体类型 等
    FSlateFontInfo FontInfo;
    //未设置字体会显示 ????
    FontInfo = FCoreStyle::Get().GetFontStyle(TEXT("NormalFont"));
    FontInfo.Size = 30;

    ChildSlot
    [

        SNew(SVerticalBox)

        + SVerticalBox::Slot()
        .AutoHeight()
        [
            SNew(STextBlock)
        .Text(FText::FromString("Advance Deletion"))
        .Font(FontInfo)
        .Justification(ETextJustify::Center) //居中
        .ColorAndOpacity(FColor::White) // 颜色
        ]

    ];
}

  1. SListView显示资产信息

为了拿到右键文件夹的资产信息,修改代码 传递一个 FAssetData类型的指针数组

    //可以传递参数
    SLATE_ARGUMENT(TArray<TSharedPtr<FAssetData>>,AssetDataToStore)

因此在弹框时 ,获取资产并传递

//弹框时的委托事件
TSharedRef<SDockTab> FSuperManagerModule::OnSpawnAdvanceDeletionTab(const FSpawnTabArgs& SpawnTabArgs)
{
    
    return    SNew(SDockTab).TabRole(NomadTab)[
                                               SNew(SAdvancedDeletionTab)
                                           .AssetDataToStore(GetAllAssetDataUnderSelectedFolder())
                                               ];

}
//获取当前选择的文件夹下的资产
TArray<TSharedPtr<FAssetData>> FSuperManagerModule::GetAllAssetDataUnderSelectedFolder()
{
     TArray<TSharedPtr<FAssetData>> AvaiableAssetDatas;
     TArray<FString> AssetsPathNames= UEditorAssetLibrary::ListAssets(FolderPathsSelected[0]);

     for (auto PathNames: AssetsPathNames)
     {
         if (!UEditorAssetLibrary::DoesAssetExist(PathNames))continue;

         const FAssetData Data = UEditorAssetLibrary::FindAssetData(PathNames);

         AvaiableAssetDatas.Add(MakeShared<FAssetData>(Data));
     } 

    return AvaiableAssetDatas;

}

修改弹框的样式,新增一个SScrollBox的滚动框

void SAdvancedDeletionTab::Construct(const FArguments& InArgs)
{
    bCanSupportFocus = true;
    StoreAssetData = InArgs._AssetDataToStore;
    //设置字体大小 字体类型 等
    FSlateFontInfo FontInfo;
    //未设置字体会显示 ????
    FontInfo = FCoreStyle::Get().GetFontStyle(TEXT("NormalFont"));
    FontInfo.Size = 30;

    ChildSlot
    [

        SNew(SVerticalBox)

        + SVerticalBox::Slot()
        .AutoHeight()
        [
            SNew(STextBlock)
        .Text(FText::FromString("Advance Deletion"))
        .Font(FontInfo)
        .Justification(ETextJustify::Center) //居中
        .ColorAndOpacity(FColor::White) // 颜色
        ]

        //第二个插槽
        + SVerticalBox::Slot()
        .AutoHeight()
        [
            SNew(SHorizontalBox)

        ]

        //第三个插槽
        + SVerticalBox::Slot()
        .AutoHeight()
        [
            SNew(SScrollBox)
            + SScrollBox::Slot()
            [
                SNew(SListView<TSharedPtr<FAssetData>>)
.ItemHeight(24.0f)
//使用InArgs传递过来的资产信息
.ListItemsSource(&StoreAssetData)
.ScrollbarVisibility(EVisibility::Collapsed)
//生成一行item的委托
.OnGenerateRow(this, &SAdvancedDeletionTab::OnGenerateItemRow)

            ]

        ]

        //第四个插槽
        + SVerticalBox::Slot()
        .AutoHeight()
        [
            SNew(SHorizontalBox)

        ]
    ];
}

绑定生成itemrow的委托

TSharedRef<ITableRow> SAdvancedDeletionTab::OnGenerateItemRow(TSharedPtr<FAssetData> Item,
    const TSharedRef<STableViewBase>& OwnerTable)
{
    return SNew(STableRow<TSharedPtr<FAssetData>>, OwnerTable)
    [
        SNew(STextBlock)
        .Text(FText::FromString(Item->AssetName.ToString()))
    ];
}

此时右击Content目录已经可以获取资产的名称

发现虽然列表显示了,但是没有滚动条

将AutoHeight() 修改为.VAlign(VAlign_Fill)后滚动条显示正常

//使用AutoHeight会显示不出滚动条

//第三个插槽
        + SVerticalBox::Slot()
        //使用AutoHeight会显示不出滚动条
        //.AutoHeight()
        .VAlign(VAlign_Fill)
  1. SCheckBox复选框

为了显示资源的信息,OnGenerateItemRow的时候 修改横向显示一些信息

TSharedRef<ITableRow> SAdvancedDeletionTab::OnGenerateItemRow(TSharedPtr<FAssetData> Item,
    const TSharedRef<STableViewBase>& OwnerTable)
{

    return SNew(STableRow<TSharedPtr<FAssetData>>, OwnerTable)[
    SNew(SHorizontalBox)
    +SHorizontalBox::Slot()
    [
    //生成一个CheckBox
    //传入Item参数
    ConstructCheckBox(Item)
    ]

+ SHorizontalBox::Slot()
[
    SNew(STextBlock)
    .Text(FText::FromString(Item->GetClass()->GetName()))
]
+ SHorizontalBox::Slot()
[
    SNew(STextBlock)
    .Text(FText::FromString(Item->AssetName.ToString()))
]
+ SHorizontalBox::Slot()
[SNew(SButton)

]
];

构造一个CheckBox选中框

    //生成一个CheckBox
    TSharedRef<SCheckBox> ConstructCheckBox(TSharedPtr<FAssetData> Item);
TSharedRef<SCheckBox> SAdvancedDeletionTab::ConstructCheckBox(TSharedPtr<FAssetData> Item)
{
    //生成一个checkbox
     TSharedRef<SCheckBox> CheckBox = SNew(SCheckBox)
    .Type(ESlateCheckBoxType::CheckBox)
    //选中切换时的事件
    .OnCheckStateChanged(this,&SAdvancedDeletionTab::OnCheckBoxStateChanged,Item)
    .Visibility(EVisibility::Visible);
    return CheckBox;
}

在绑定切换选中的事件

    //checkbox选中的事件
   void OnCheckBoxStateChanged(ECheckBoxState NewState,TSharedPtr<FAssetData> ItemAssetData);
void SAdvancedDeletionTab::OnCheckBoxStateChanged(ECheckBoxState NewState, TSharedPtr<FAssetData> ItemAssetData)
{
    DebugHeader::Print(ItemAssetData->AssetName.ToString(),FColor::Green);
}

此时切换checkbox时 打印出资源的名称

  1. 删除按钮 SButton

新增一个右侧的按钮,方便快速的删除资源

[
  //生成一个Button
  ConstructButton(Item)
]
TSharedRef<SButton> SAdvancedDeletionTab::ConstructButton(const TSharedPtr<FAssetData> &ClickItem)
{
     TSharedRef<SButton> ConstructButton =SNew(SButton)
    .Text(FText::FromString(TEXT("删除")))
    //绑定删除的事件
    .OnClicked(this,&SAdvancedDeletionTab::OnDeleteButtonClick,ClickItem);
    return ConstructButton;
}

为了后续的删除资源,将删除资源的函数写在FSuperManagerModule中,方便以后的调用

//删除单个资源
bool DelectSingeAsset(const FAssetData& Data);
bool FSuperManagerModule::DelectSingeAsset(const FAssetData& Data)
{
    TArray<FAssetData> AssetsDatas;
    AssetsDatas.Add(Data);
    //返回bool >0时则删除是成功的 
    if (ObjectTools::DeleteAssets(AssetsDatas) > 0)
    {
        return true;
    }
    return false;
}

在用户点击按钮时,调用绑定的函数

FReply SAdvancedDeletionTab::OnDeleteButtonClick(TSharedPtr<FAssetData> ClickItem)
{
    //获取FSuperManagerModule模块
    FSuperManagerModule SuperManagerModule = FModuleManager::LoadModuleChecked<FSuperManagerModule>(
        TEXT("SuperManager"));
    //判断用户是否点了取消删除
    //取对象
    const bool DelectBool = SuperManagerModule.DelectSingeAsset(*ClickItem.Get());
    //刷新列表
    if (DelectBool)
    {
        //如果资源列表中包含目标的item
        if (StoreAssetData.Contains(ClickItem))
        {
            StoreAssetData.Remove(ClickItem);
            AssetList->RebuildList();
        }
    }
    return FReply::Handled();
}
  1. 底部 全部删除 全部选择 全部取消 按钮

将第四个SVerticalBox::Slot()的Snew出来一个面板 新增构造函数 ConstructHorizontalBox()

        //第四个插槽  三个按钮
        + SVerticalBox::Slot()
        .FillHeight(0.2)
        [
        //底部按钮
        ConstructHorizontalBox()
         ]
         
         ];

构造面板的函数

TSharedRef<SHorizontalBox> SAdvancedDeletionTab::ConstructHorizontalBox()
{
    TSharedRef<SHorizontalBox> Menubutton  =  SNew(SHorizontalBox)

        + SHorizontalBox::Slot()
          .VAlign(VAlign_Fill)
          .Padding(20, 20, 20, 20)
        [
            SNew(SButton)
    .VAlign(VAlign_Center)
    .HAlign(HAlign_Center)
    .OnClicked(this,&SAdvancedDeletionTab::OnAllDeleteButtonClick)
    .Text(FText::FromString(TEXT("删除全部")))
        ]

        + SHorizontalBox::Slot()
          .VAlign(VAlign_Fill)
          .Padding(20, 20, 20, 20)
        [
            SNew(SButton)
    .VAlign(VAlign_Center)
    .HAlign(HAlign_Center)
    .OnClicked(this,&SAdvancedDeletionTab::OnAllSelectButtonClick)
    .Text(FText::FromString(TEXT("选择全部")))
        ]

        + SHorizontalBox::Slot()
          .VAlign(VAlign_Fill)
          .Padding(20, 20, 20, 20)
        [
            SNew(SButton)
    .VAlign(VAlign_Center)
    .HAlign(HAlign_Center)
    .OnClicked(this,&SAdvancedDeletionTab::OnAllUnSelectButtonClick)
    .Text(FText::FromString(TEXT("取消全部")))
        ];

    return Menubutton;

}

三个按钮的绑定事件

    //底部三个按钮的事件
    FReply OnAllDeleteButtonClick();
    FReply OnAllSelectButtonClick();
    FReply OnAllUnSelectButtonClick();

  1. 三个按钮的绑定事件

为了将CheckBox状态和FAssetData绑定到一起,这里新增一个结构体,用来存贮CheckBox 和 FAssetData的指针

struct FCheckBoxStruct
{
   TSharedPtr<SCheckBox> CheckBox ;
   TSharedPtr<FAssetData> FAssetData ;
};
    //当前选中的CheckBox的FAssetData
    TArray<TSharedPtr<FAssetData>> FAssetDataCheckArray;
    //CheckBox选中数据对应FAssetData
    TArray <FCheckBoxStruct> CheckBoxStructArray;

全部删除

FReply SAdvancedDeletionTab::OnAllDeleteButtonClick()
{
    //获取FSuperManagerModule模块
    FSuperManagerModule SuperManagerModule = FModuleManager::LoadModuleChecked<FSuperManagerModule>(
        TEXT("SuperManager"));

    //待删除的资源数组
    TArray<TSharedPtr<FAssetData>> DeleteFAssetDataArray;

    //遍历目前选中的checkbox 将FAssetData加入待删除的资源数组
    for (auto CheckBoxStruct : CheckBoxStructArray)
    {
        if (CheckBoxStruct.CheckBox->IsChecked())
        {
            DeleteFAssetDataArray.Add(CheckBoxStruct.FAssetData);
        }
    }
    //FAssetDataCheckArray中是全部选中的资源
    bool DelectBool = SuperManagerModule.DelectMultipleAsset(DeleteFAssetDataArray);
    if (DelectBool)
    {
        AssetList->RebuildList();
        for (auto FAssetDataArray : DeleteFAssetDataArray)
        {
            //如果显示的资源列表中包含待删除的数据 就移除 为了后面的刷新列表
            if (StoreAssetData.Contains(FAssetDataArray))StoreAssetData.Remove(FAssetDataArray);
        }
        
        //清空CheckBoxStructArray数组
        CheckBoxStructArray.Empty();
    }
    
    return FReply::Handled();
}

全部选中

FReply SAdvancedDeletionTab::OnAllSelectButtonClick()
{
    //遍历所有结构体 将CheckBox设为选中
    for (const auto  & CheckBoxStruct : CheckBoxStructArray)
    {
        CheckBoxStruct.CheckBox->SetIsChecked(ECheckBoxState::Checked);
    }
    return FReply::Handled();
}

全部取消选中

FReply SAdvancedDeletionTab::OnAllUnSelectButtonClick()
{
    //遍历所有结构体 将CheckBox设为未选中
    for (const auto & CheckBoxStruct : CheckBoxStructArray)
    {
        CheckBoxStruct.CheckBox->SetIsChecked(ECheckBoxState::Unchecked);
    }
    return FReply::Handled();
}
  1. Combox下拉框

构建一个Combox方便筛选资源类型

    //生成一个Combox
    TSharedRef< SComboBox< TSharedPtr<FString> > >ConstructComboBox();

    //Combox下拉框文本
     TArray<TSharedPtr<FString>>ComboBoxTextArray ;
    //接受显示
     TSharedPtr<STextBlock>ComboBoxText;
     TSharedRef<SWidget> OnGenerateComboContent(TSharedPtr<FString> SourceItem);
    
     void OnComboChanged(TSharedPtr<FString> SelectedOption, ESelectInfo::Type SelectInfo);

构建一个combox

        //第二个插槽
        + SVerticalBox::Slot()
        .AutoHeight()
        [
            SNew(SHorizontalBox)
            +SHorizontalBox::Slot()
            .AutoWidth()
            [
             ConstructComboBox()
            ]

        ]

生成combox

TSharedRef<SComboBox<TSharedPtr<FString>>> SAdvancedDeletionTab::ConstructComboBox()
{
    TSharedRef<SComboBox<TSharedPtr<FString>>> ConstructComboBox =
    SNew(SComboBox<TSharedPtr<FString>>)
    //下拉框的数量
    .OptionsSource(&ComboBoxTextArray)
    //生成下拉框的样式
    .OnGenerateWidget(this,&SAdvancedDeletionTab::OnGenerateComboContent)
    //选择时的绑定函数
    .OnSelectionChanged(this,&SAdvancedDeletionTab::OnComboChanged)
    [
    //接受显示的STextBlock  固定写法 并不是OnSelectionChanged下的
     SAssignNew(ComboBoxText,STextBlock)
    .Text(FText::FromString("Asset Type"))
    ];
    return ConstructComboBox;
}

生成Combo内容

TSharedRef<SWidget> SAdvancedDeletionTab::OnGenerateComboContent(TSharedPtr<FString> SourceItem)
{
    TSharedRef<SWidget>  Widget= SNew(STextBlock).Text(FText::FromString(*SourceItem.Get()));
    return Widget;
}

点击状态变更绑定的函数

void SAdvancedDeletionTab::OnComboChanged(TSharedPtr<FString> Item, ESelectInfo::Type SelectInfo)
{
    DebugHeader::Print(*Item.Get(),FColor::Green);
    ComboBoxText->SetText(FText::FromString(*Item.Get()));
}

使用宏在字段数组中加入下拉字段

#define ListAll TEXT("全部的类型")
    //使用宏简化后续文本
    ComboBoxTextArray.Add(MakeShared<FString>(ListAll));

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值