UE5: Content browser工具编写02

DebugHeader.h 中的全局变量,已经在一个cpp file中被include了,如果在另一个cpp file中再include它,就会有一些conflicts。先全部给加一个static

  • Add static keyword to debug functions
  • Wrap all the functions inside of a namespace
  • print message to the screen when pressing delete unused assets
#pragma once
#include "Misc/MessageDialog.h"
#include "Widgets/Notifications/SNotificationList.h"
#include "Framework/Notifications/NotificationManager.h"static void Print(const FString& Message, const FColor& Color)
{if (GEngine){GEngine->AddOnScreenDebugMessage(-1, 8.f, Color, Message);}
}static void PrintLog(const FString& Message)
{UE_LOG(LogTemp, Warning, TEXT("%s"),*Message);
}static EAppReturnType::Type ShowMsgDialog(EAppMsgType::Type MsgType, const FString& Message,
bool bShowMsgAsWarning = true) 
{if (bShowMsgAsWarning == true) {FText MsgTitle = FText::FromString(TEXT("Warning"));return FMessageDialog::Open(MsgType, FText::FromString(Message), &MsgTitle);//return FMessageDialog::Open(MsgType, FText::FromString(TEXT("Warning: ") + Message));}else{return FMessageDialog::Open(MsgType, FText::FromString(Message));}
}static void ShowNotifyInfo(const FString& Message)
{FNotificationInfo NotifyInfo(FText::FromString(Message));NotifyInfo.bUseLargeFont = true;NotifyInfo.FadeOutDuration = 7.f;FSlateNotificationManager::Get().AddNotification(NotifyInfo);
}

EditorAssetLibrary.h里面,ListAssets的功能

UFUNCTION(BlueprintCallable, Category = "Editor Scripting | Asset")
static TArray<FString> ListAssets(const FString& DirectoryPath, bool bRecursive = true, bool bIncludeFolder = false);

ListAssets 函数中,bRecursive 是一个布尔变量,通常用来控制函数是否以递归方式列出某个目录下的所有资产(Assets)。(if we go inside of the subfolder)

  • bRecursivetrue 时,函数会递归遍历指定目录以及其所有子目录,并列出其中的所有资产。
  • bRecursivefalse 时,函数只会列出指定目录中的资产,而不会深入子目录。

bool bIncludeFolder

假设你的资产结构目录如下

/Assets
├── File1.uasset
├── Folder1
│   └── File2.uasset
└── Folder2
  • bIncludeFolder = true:
    输出可能是:File1.uasset, Folder1/, Folder1/File2.uasset, Folder2/

  • bIncludeFolder = false:
    输出可能是:File1.uasset, Folder1/File2.uasset

在content folder里面,不要碰collections和developers目录。DO NOT TOUCH ROOT FOLDER (COLLECTIONS/DEVELOPERS)

示例代码

// Copyright Epic Games, Inc. All Rights Reserved.#include "SuperManager.h"
#include "ContentBrowserModule.h"
#include "DebugHeader.h"
#include "EditorAssetLibrary.h"
#include "ObjectTools.h"//DeleteAssets()#define LOCTEXT_NAMESPACE "FSuperManagerModule"void FSuperManagerModule::StartupModule()
{InitContentBrowserExtension();
}void FSuperManagerModule::ShutdownModule()
{//This function may be called during shutdown to clean up your module.  For modules that support dynamic reloading,//we call this function before unloading the module.
}#pragma region ContentBrowserMenuExtension
void FSuperManagerModule::InitContentBrowserExtension()
{FContentBrowserModule& ContentBrowserModule = FModuleManager::LoadModuleChecked<FContentBrowserModule>(TEXT("ContentBrowser"));TArray<FContentBrowserMenuExtender_SelectedPaths>& ContentBrowserModuleMenuExtenders = ContentBrowserModule.GetAllPathViewContextMenuExtenders();//FContentBrowserMenuExtender_SelectedPaths CustomContentBrowserMenuDelegate;//CustomContentBrowserMenuDelegate.BindRaw(this, &FSuperManagerModule::CustomContentBrowserMenuExtender);//ContentBrowserModuleMenuExtenders.Add(CustomContentBrowserMenuDelegate);//***same with the two lines belowContentBrowserModuleMenuExtenders.Add(FContentBrowserMenuExtender_SelectedPaths::CreateRaw(this, &FSuperManagerModule::CustomContentBrowserMenuExtender));}TSharedRef<FExtender> FSuperManagerModule::CustomContentBrowserMenuExtender(const TArray<FString>& SelectedPaths)
{TSharedRef<FExtender> MenuExtender(new FExtender());if (SelectedPaths.Num() > 0) {//define the position//-> 是一个运算符,用于访问指针所指向对象的成员。MenuExtender->AddMenuExtension(FName("Delete"),//name of extension hook//we want to insert after DELETE(extension hook)EExtensionHook::After,TSharedPtr<FUICommandList>(),//no hotkey//first bindingFMenuExtensionDelegate::CreateRaw(this, &FSuperManagerModule::AddContentBrowserMenuEntry));//second bindingFolderPathsSelected = SelectedPaths;//then we have access to the folders that the user has currently selected};return MenuExtender;
}void FSuperManagerModule::AddContentBrowserMenuEntry(FMenuBuilder& MenuBuilder)
{//in this function we can define all the details for our menu entry //and we can use the menu builder to do soMenuBuilder.AddMenuEntry(FText::FromString(TEXT("Delete Unused Assets")),FText::FromString(TEXT("Safely delete all unused assets under folder")),FSlateIcon(),//empty placeholder//SECOND BINDINGFExecuteAction::CreateRaw(this, &FSuperManagerModule::OnDeleteUnusedAssetButtonClicked));
}void FSuperManagerModule::OnDeleteUnusedAssetButtonClicked()
{if (FolderPathsSelected.Num() > 1)//delete stuff in multiple folders will cause some unexpected behaviors{DebugHeader::ShowMsgDialog(EAppMsgType::Ok, TEXT("Please select ONE folder"));return;}//DebugHeader::Print(TEXT("Currently selected folder: ")+ FolderPathsSelected[0], FColor::Green);//pure debug, can be deleted laterTArray<FString> AssetsPathName = UEditorAssetLibrary::ListAssets(FolderPathsSelected[0]);if (AssetsPathName.Num() == 0){DebugHeader::ShowMsgDialog(EAppMsgType::Ok, TEXT("No Asset found under selected folder"));return;}//not finished yet//DebugHeader::ShowMsgDialog(EAppMsgType::Ok, TEXT("Delete Unused Assets"));//DebugHeader::Print(TEXT("Unused Assets Deleted"), FColor::Red);FString Message = FString::Printf(TEXT("A total of %d found.\nConfirm deletion?"), AssetsPathName.Num());//%d 是一个格式说明符,用于表示一个整数(int 类型)EAppReturnType::Type ConfirmResult =DebugHeader::ShowMsgDialog(EAppMsgType::OkCancel, Message);//error   error   //EAppReturnType::Type ConfirmResult = DebugHeader::ShowMsgDialog(EAppMsgType::OkCancel, TEXT("A total of ") + FString::Printf(AssetsPathName.Num()) + TEXT(" found.\nConfirm deletion?"));if (ConfirmResult == EAppReturnType::Cancel)return;TArray<FAssetData>UnusedAssetsDataArray;for (const FString& AssetPathNameWWWWW : AssetsPathName){if (AssetPathNameWWWWW.Contains(TEXT("Collections")) || AssetPathNameWWWWW.Contains(TEXT("Developers"))){continue;//不执行操作,继续循环}//DO NOT TOUCH ROOT FOLDER (COLLECTIONS/DEVELOPERS)if (!UEditorAssetLibrary::DoesAssetExist(AssetPathNameWWWWW)) continue;//if we don't do this, sometimes we will get some error message saying that Assets does not existTArray<FString> AssetReferencers = UEditorAssetLibrary::FindPackageReferencersForAsset(AssetPathNameWWWWW);//it is same with(delete asset from selection)if (AssetReferencers.Num() == 0)//this asset is unused//error   error   E0137	expression must be a modifiable lvalue//报错的中文意思是:“表达式必须是可修改的左值。”//这是因为在这段代码里,你错误地使用了单等号 = ,而不是双等号 == ,在比较语句中使用了赋值运算符。{const FAssetData UnusedAssetData = UEditorAssetLibrary::FindAssetData(AssetPathNameWWWWW);UnusedAssetsDataArray.Add(UnusedAssetData);}//塞入“无用资产”动态数组if (UnusedAssetsDataArray.Num() > 0){ObjectTools::DeleteAssets(UnusedAssetsDataArray);}else{DebugHeader::ShowMsgDialog(EAppMsgType::Ok, TEXT("No Unused Asset found under selected folder"));}}}#pragma endregion#undef LOCTEXT_NAMESPACEIMPLEMENT_MODULE(FSuperManagerModule, SuperManager)

可以将 C++ 中的 delegate 比作一个 “邮递员”

比喻解释:

  1. 邮递员:邮递员负责将信件从一个地方送到另一个地方。你把信件(消息、请求等)交给邮递员,告诉他该去哪个地址送达。

  2. 委托的角色

    • 发送者:在你的代码中,发送者(或发布者)就像是给邮递员信件的人。发送者生成一个事件(例如某个操作完成)并把它交给邮递员(委托)。
    • 邮递员(委托):邮递员不处理信件的内容,只负责把信件送到指定的地址。在委托的情况下,它会将事件传递给事先注册好的接收者(或订阅者)。
    • 接收者:接收者就像是收件人,当邮递员把信件送到他们那里时,他们会根据信件的内容采取相应的行动。

具体流程:

  • 注册接收者:想象一下,收件人提前告诉邮递员自己的地址(注册委托)。这样,当邮递员接收到信件时,他就知道要把信送到哪个地方。
  • 发送事件:当某个事件发生(例如按钮被点击),发送者会把这个事件的信息交给邮递员。
  • 处理事件:邮递员把信息传递给注册的接收者,接收者根据收到的信息执行相应的操作(例如,更新界面、执行某个功能等)。

优点:

  • 解耦合:使用邮递员的方式可以避免发送者和接收者之间的直接联系。发送者不需要知道接收者是谁,只需把事件交给邮递员。这样可以让代码更灵活,方便维护和扩展。
  • 多个接收者:就像一个邮递员可以把同一封信件送到多个收件人一样,委托可以有多个绑定的接收者,所有的接收者都会在事件发生时被通知。

总结:

将 C++ 中的 delegate 比作“邮递员”可以帮助你理解它的工作原理和用途:通过一个中介,将事件或消息从发送者传递给接收者,同时保持二者之间的解耦。这种方式在事件驱动编程和回调机制中非常有效。

使用 C++ 中的 delegate 可以实现一些直接调用函数所无法实现的功能:

1. 解耦合

  • 使用直接调用:如果直接调用一个函数,调用者需要了解被调用函数的具体实现和参数。这使得代码之间的耦合度增加。
  • 使用委托:通过委托,发送者和接收者之间没有直接关系。发送者只需要发布事件,接收者可以在不影响发送者的情况下独立处理事件。这种解耦合使得代码更加灵活,方便修改和扩展。

2. 动态绑定

  • 使用直接调用:在编译时,调用的函数是固定的,无法在运行时改变。
  • 使用委托:委托允许在运行时动态绑定多个回调函数。你可以根据不同的条件选择不同的回调,这种动态性在事件处理和响应用户输入时非常有用。

3. 多重订阅

  • 使用直接调用:直接调用通常只能调用一个函数。
  • 使用委托:一个委托可以绑定多个接收者,所有订阅这个委托的函数都会被调用。这种特性非常适合于需要通知多个对象的情况,如用户界面事件(按钮点击、状态变化等)。

4. 异步处理

  • 使用直接调用:直接调用函数通常是同步的,即调用者会等待函数执行完成后才能继续执行下一步。
  • 使用委托:委托可以与异步编程结合使用,允许事件在后台线程中处理,调用者可以继续执行其他任务,而不必等待事件处理完成。

5. 简化事件处理

  • 使用直接调用:如果要处理多种类型的事件,代码中会有大量的条件语句,增加了复杂性。
  • 使用委托:通过委托,可以创建更为简洁和结构化的事件处理代码,注册和注销事件处理器变得简单直观。

6. 回调机制

  • 使用直接调用:没有灵活的回调机制,调用者在调用函数时必须事先知道它将要做什么。
  • 使用委托:允许在某些操作完成时进行回调,例如在异步操作完成后执行特定的代码,或在游戏状态改变时更新界面。

例子:

假设你有一个游戏,玩家按下按钮时要播放音效并更新得分。使用直接调用时,按钮的点击处理代码需要直接调用音效播放函数和得分更新函数,这会使得代码紧密耦合。使用委托,你可以在按钮被点击时发布一个事件,多个处理函数(音效播放、得分更新)可以同时订阅这个事件并处理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/54846.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

锐尔15注册机 锐尔文档扫描影像处理系统15功能介绍

锐尔文档扫描影像处理系统是一款全中文操作界面的文件、档案扫描及影像优化处理软件&#xff0c;是目前国内档案数字化行业里专业且优秀的影像优化处理软件。 无论是从纸质文件制作高质量的影像文件&#xff0c;或是检查已经制作好的影像文件&#xff0c;锐尔文档扫描影像处理…

大数据新视界 --大数据大厂之 Druid 实时数据分析平台在大数据中的应用

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

在Windows系统上安装的 Arrow C++ 库

在Windows系统上安装的 Arrow C 库 正文第一步第二步第三步第四步注: 检查是否安装成功 吐槽 正文 第一步 git clone gitgithub.com:apache/arrow.git第二步 打开powershell (好像cmd也可以,不过我试了powershell中不报错,cmd中报错,不是很清楚为什么) 打开arrow的目录 cd …

贝锐洋葱头浏览器随时随地访问教务系统,轻松搞定选课

教育网的“拥堵”早已是老生常谈&#xff0c;学生数量庞大、上网时间集中、带宽有限&#xff0c;导致网络速度慢。尤其是从外部网络访问教育网时&#xff0c;更是因为跨运营商的缘故变得缓慢。 而学校内网也是类似的情况&#xff0c;课余时间和上课时间的网络使用情况差别巨大…

xpath在爬虫中的应用、xpath插件的安装及使用

安装 1、打开谷歌浏览器进入扩展程序安装页面(右上角会有"开发者模式按钮")默认是关闭的&#xff0c;当安装此插件时需要把开发者模式打开。 2、下载下来的xpath_helper是zip格式的&#xff0c;需要解压缩即可安装。 3、重启浏览器&#xff0c;再次点击扩展程序即…

C++八股进阶

之前那个只是总结了一下常考点&#xff0c;这个是纯手打记笔记加深理解 这里写目录标题 C的四种智能指针为什么要使用智能指针&#xff1f;四种智能指针&#xff1a; C中的内存分配情况C中的指针参数传递和引用参数传递C 中 const 和 static 关键字&#xff08;定义&#xff0…

NLP 序列标注任务核心梳理

句向量标注 用 bert 生成句向量用 lstm 或 bert 承接 bert 的输出&#xff0c;保证模型可以学习到内容的连续性。此时 lstm 输入形状为&#xff1a; pooled_output.unsqueeze(0) (1, num_sentence, vector_size) 应用场景 词性标注句法分析 文本加标点 相当于粗粒度的分词任…

(done) 声音信号处理基础知识(4) (Understanding Audio Signals for ML)

来源&#xff1a;https://www.youtube.com/watch?vdaB9naGBVv4 模拟信号特点如下 时域连续(x轴) 振幅连续(y轴) 如下是模拟信号的一个例子&#xff1a; 数字信号特点如下&#xff1a; 一个离散值序列 数据点的值域是一系列有限的值 ADC&#xff1a;模拟信号到数字信号的…

【WRF运行第三期】服务器上运行WRF模型(官网案例-Hurricane Matthew)

【WRF运行第三期】运行WRF模型&#xff08;官网案例-Hurricane Matthew&#xff09; 官网案例-Hurricane Matthew介绍0 创建DATA文件夹1 WPS预处理1.1 解压GRIB数据&#xff08;ungrib.exe&#xff09;1.1.1 解压GRIB数据---GFS&#xff08;Matthew案例研究数据&#xff09;1.1…

vue打包exe之electron-quick-start的npm install 报错

vue打包exe之electron-quick-start的npm install 报错 1、github地址2、问题3、解决4、其他(打包exe)参考 1、github地址 https://github.com/electron/electron-quick-start2、问题 我使用的pnpm install正常安装&#xff0c;执行npm start提示错误 3、解决 在package.js…

计算机前沿技术-人工智能算法-大语言模型-最新论文阅读-2024-09-23

计算机前沿技术-人工智能算法-大语言模型-最新论文阅读-2024-09-23 本期&#xff0c;我们对大语言模型在表情推荐, 软件安全和 自动化软件漏洞检测等方面如何应用&#xff0c;提供几篇最新的参考文章。 1 Semantics Preserving Emoji Recommendation with Large Language Mod…

如何正确连接和使用滑动变阻器?

滑动变阻器是可以改变电阻值的电子元件&#xff0c;广泛应用于各种电子设备和电路中。正确连接和使用滑动变阻器对于保证电路的正常工作和延长设备的使用寿命至关重要。以下是关于如何正确连接和使用滑动变阻器的一些建议&#xff1a; 了解滑动变阻器的基本原理和结构&#xf…

DERT目标检测源码流程图main.py的执行

DERT目标检测源码流程图main.py的执行 官网预测脚本 补充官网提供的预测部分的代码信息。 from PIL import Image import requests import matplotlib.pyplot as pltimport torch from torch import nn from torchvision.models import resnet50 import torchvision.transform…

大数据Flink(一百二十四):案例实践——淘宝母婴数据加速查询

文章目录 案例实践——淘宝母婴数据加速查询 一、​​​​​​​创建数据库表并导入数据 二、​​​​​​​​​​​​​​创建session集群 三、​​​​​​​​​​​​​​源表查询 四、​​​​​​​​​​​​​​指标计算 案例实践——淘宝母婴数据加速查询 随着…

新建flask项目,配置入口文件,启动项目

pycharm新建flask项目时&#xff0c;会提供一个创建flask项目的导向&#xff0c;自动设置虚拟环境&#xff0c;并且安装flask及其依赖而vscode新建flask项目时&#xff0c;需要手动设置虚拟环境并安装flask&#xff0c;需要在终端使用pip install flask命令来安装flask及其依赖…

无人船在海洋勘探领域的应用!

一、具体应用 海底地形测绘&#xff1a; 无人船可以搭载多波束测深仪等先进设备&#xff0c;进行高精度的海底地形测绘。这些设备能够生成详细的海底地形图&#xff0c;为海洋工程设计和施工提供详尽的水下地形资料。 海底资源勘探&#xff1a; 通过搭载磁力仪、重力仪等地…

HTML5实现唐朝服饰网站模板源码

文章目录 1.设计来源1.1 网站首页-界面效果1.2 唐装演变-界面效果1.3 唐装配色-界面效果1.4 唐装花纹-界面效果1.5 唐装文化-界面效果 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&#xff1a;xcL…

UE虚幻引擎云渲染汽车动画的优势!

在汽车广告和动画制作领域&#xff0c;虚幻引擎&#xff08;UE&#xff09;结合云渲染技术正掀起一场技术革命。这项技术以其高性能、成本效益和灵活性&#xff0c;为创作者提供了强大的工具&#xff0c;以实现更加逼真和高效的汽车动画制作。 一、为什么选择UE虚幻引擎制作汽车…

2024年厦门市大数据创新应用大赛圆满收官

2024年厦门市大数据创新应用大赛圆满收官 2024年9月19日-20日&#xff0c;由厦门市数据管理局、厦门市公安局、厦门市生态环境局联合主办&#xff0c;厦门市信息中心承办的2024年厦门市大数据创新应用大赛圆满收官。 经专家评审团评审 最终决出获奖名单 决赛评审会现场 2024年…

PMI-ACP®认证考试内容将于2025年第一期考试更新

PMI敏捷管理专业人士&#xff08;PMI-ACP&#xff09;认证即将在2025年迎来引入中国大陆的十周年纪念。 十年时间&#xff0c;我们见证了敏捷实践方法普及和敏捷项目管理的“知行合一”&#xff0c;采用敏捷方法的中国企业团队比例的快速持续增长&#xff0c;中国PMI-ACP专业人…