本文涉及到的软件有:FairyGUI,VSCode
代码环境涉及到了:Lua
VSCode插件:EmmyLua
在编写FairyGUI编辑器菜单前,了解一下FairyGUIEditor的API会有效的帮助我们解决很多问题。FairyGUI的扩展是通过编辑器自带的插件功能实现的,插件中我使用的是lua环境模板。导入编辑器的LuaAPI,文件可以在FairyGUI-Editor源码的插件目录中找到。接下来将通过功能来说明对应的API作用。
插件的位置
如果找不到插件面板,可以通过“视图→插件”或“工具→插件”添加插件面板。
1、打开插件目录,插件目录是在“项目目录/plugins"文件夹下,每个插件对应一个子文件夹。
2、创建新插件
3、刷新插件列表
一个新插件的诞生
点击创建新插件,可以在插件模板选择要写的插件类型和语言格式
点击创建后,插件列表中就会出现刚刚创建的新插件。
这时候,点击打开插件目录,会发现原本空空的插件目录中多了一个刚刚新建的插件文件夹,右键使用VSCode打开。
可以注意到,目录下有两个文件“main.lua”和“package.json”。其中main.lua是插件的入口脚本,package.json是插件的配置文件。
双击main.lua后可以看到“onDestroy”方法,可以将之后的清理代码添加到此处。保存编写后的代码,在编辑器中点击刷新插件列表,可以将最新插件代码同步到编辑器。如果这时候编辑器保存,如果不是代码书写错误,可以通过重启编辑器进行刷新插件。
编辑器的个人常用API
App是工程入口类,类型:CS.FairyEditor.App。通过LuaAPI中的CS_FairyEditor_App可以看到编辑器中的功能字段。下面将列出将要用的字段和方法。
CS.FairyEditor.App | ||
字段名 | 类型 | 作用 |
project | CS.FairyEditor.FProject | 记录当前工程的配置和资源 |
libView | CS.FairyEditor.View.LibraryView | 编辑器的资源库面板 |
inspectorView | CS.FairyEditor.View.InspectorView | 编辑器的检查器面板 |
consoleView | CS.FairyEditor.View.ConsoleView | 编辑器的控制台面板 |
menu | CS.FairyEditor.Component.IMenu | 编辑器的菜单栏 |
pluginManager | CS.FairyEditor.PluginManager | 插件管理 |
CS.FairyEditor.FProject | ||
字段名 | 类型 | 作用 |
name | string | 工程名“如:FGUIProject” |
basePath | string | 工程的路径“如:D:\Documents\FGUIProject” |
assetsPath | string | 工程的路径“如:D:\Documents\FGUIProject\assets” |
allPackages | CS.FairyEditor.Fpackage[] | 工程中的所有包 |
allBranches | string[] | 工程中的所有分支 |
CS.FairyEditor.Fpackage | ||
字段名 | 类型 | 作用 |
name | string | 当前包的名字 |
items | CS.FairyEditor.FPackageItem[] | 当前包下的资源 |
CS.FairyEditor.FPackageItem | ||
字段名 | 类型 | 作用 |
path | string | 资源路径 |
name | string | 资源名 |
CS.FairyEditor.View.LibraryView | ||
字段名 | 类型 | 作用 |
contextMenu | CS.FairyEditor.Component.NPopupMenu | 资源库的右键菜单 |
CS.FairyEditor.Component.NPopupMenu | ||
方法名 | 参数 | 作用 |
AddItem | caption:string, name:string, selectCallback:(fun():void) | 添加一个菜单项并设置选中回调事件 |
AddSeperator | 添加菜单分割线 | |
SetItemGrayed | string name, bool grayed | 设置目标不能点击 |
onPopup | CS.FairyGUI.EventListener | 菜单弹出事件 |
开始编写插件代码
需求1
需求1:在工具菜单中添加“导出所有UI名字”的菜单项,点击后复制结果。
前提:所有UI界面具有相同的命名规则,这里我用的是UIXXX,所以在获取所有UI的时候只需要检测当前文件的名字UI是否存在。在这个需求实现的功能中,需要准备一个lua代码格式的文本代码,之后会将classField替换为获取到的UI名。
local tmp_ui_type = [[
---@class UIType
return {
classField
}
]]
代码已经加了详细的注解,可以直接查看完整代码:
---@type CS.FairyEditor.App
local _app = CS.FairyEditor.App
local project = _app.project
---输出绝对文件路径
local file_out_path =("%s/UIType.lua"):format(project.basePath)
---Lua模板
local tmp_ui_type = [[
---@class UIType
return {
classField
}
]]
---获取工具菜单
---@type CS.FairyEditor.Component.MenuBar
local toolMenu = _app.menu:GetSubMenu("tool")
---添加分隔符
toolMenu:AddSeperator()
---添加菜单,显示名字,内部标签名,回调方法
toolMenu:AddItem("导出UIType","XiaoExportUIType",function()
local _classField = ""
---获取工程中的所有包,返回值是列表
local allPackages = _app.project.allPackages
for i = 1, allPackages.Count do
---C#索引从0开始
---@type CS.FairyEditor.FPackage
local package = allPackages[i - 1]
---获取当前包中的所有子项,返回值是列表
local items = package.items
for i = 1, items.Count do
---@type CS.FairyEditor.FPackageItem
local item = items[i - 1]
---记录所有UI开头的子项
if string.find(item.name,"UI") == 1 then
local uiType = string.format("%s = %s_%s,\n\t",item.name,package.name,item.name)
_classField = _classField .. uiType
end
end
end
---输出日志打印
fprint(_classField)
---替换模板
tmp_ui_type = tmp_ui_type:gsub("classField",_classField)
---写出模板
local f = io.open(file_out_path,"w")
f:write(tmp_ui_type)
f:close()
---输出路径打印
fprint(string.format("导出UIType:[url]%s[/url]",file_out_path))
end)
function onDestroy()
-------do cleanup here-------
toolMenu:RemoveItem("XiaoExportUIType")
end
需求2:
需求2:在资源库的右键菜单中添加“复制组件脚本路径”,方便提取当前组件的require路径。并且实现组件筛选,在不满足条件的情况下,“复制组件脚本路径”菜单项置灰不可用。
前提:所有非UI的组件都在当前包的Comps的文件夹下存放。
重新新建一个插件或者在之前的插件中继续编写,这里我是接着之前的插件继续写。
---添加资源库右键菜单
---需求:复制Comps文件夹下的组件所转化的脚本路径
---获取右键菜单
local libcontextMenu = _app.libView.contextMenu
---添加分割线
libcontextMenu:AddSeperator()
libcontextMenu:AddItem("复制组件脚本路径","XiaoCopyAssetPath",function()
---获取当前选中的资源
---@type CS.FairyEditor.FPackageItem
local item = _app.libView:GetSelectedResource()
---检测资源是否满足条件
if item.path:find("/Comps/") == 1 then
---准备复制
local cp_str = ("require(\"UI.%s.Comps.%s\")"):format(item.owner.name,item.name)
---Unity复制操作
CS.UnityEngine.GUIUtility.systemCopyBuffer = cp_str
---弹窗提示
_app.Alert("复制成功")
else
_app.Alert("复制失败")
end
end)
---在弹出的菜单中检测当前选择的资源是否满足条件
libcontextMenu.onPopup:Add(function()
---@type CS.FairyEditor.FPackageItem
local item = _app.libView:GetSelectedResource()
local grayed = true
if item.path:find("/Comps/") == 1 then
-- body
grayed = false
end
libcontextMenu:SetItemGrayed("XiaoCopyAssetPath",grayed)
end)
之后不要忘记在onDestroy方法中移除我们的菜单项“XiaoCopyAssetPath”
toolMenu:RemoveItem("XiaoCopyAssetPath")
完整插件代码
---@type CS.FairyEditor.App
local _app = CS.FairyEditor.App
local project = _app.project
---输出绝对文件路径
local file_out_path =("%s/UIType.lua"):format(project.basePath)
---Lua模板
local tmp_ui_type = [[
---@class UIType
return {
classField
}
]]
---获取工具菜单
---@type CS.FairyEditor.Component.MenuBar
local toolMenu = _app.menu:GetSubMenu("tool")
---添加分隔符
toolMenu:AddSeperator()
---添加菜单,显示名字,内部标签名,回调方法
toolMenu:AddItem("导出UIType","XiaoExportUIType",function()
local _classField = ""
---获取工程中的所有包,返回值是列表
local allPackages = _app.project.allPackages
for i = 1, allPackages.Count do
---C#索引从0开始
---@type CS.FairyEditor.FPackage
local package = allPackages[i - 1]
---获取当前包中的所有子项,返回值是列表
local items = package.items
for i = 1, items.Count do
---@type CS.FairyEditor.FPackageItem
local item = items[i - 1]
---记录所有UI开头的子项
if string.find(item.name,"UI") == 1 then
local uiType = string.format("%s = %s_%s,\n\t",item.name,package.name,item.name)
_classField = _classField .. uiType
end
end
end
---输出日志打印
fprint(_classField)
---替换模板
tmp_ui_type = tmp_ui_type:gsub("classField",_classField)
---写出模板
local f = io.open(file_out_path,"w")
f:write(tmp_ui_type)
f:close()
---输出路径打印
fprint(string.format("导出UIType:[url]%s[/url]",file_out_path))
end)
---添加资源库右键菜单
---需求:复制Comps文件夹下的组件所转化的脚本路径
---获取右键菜单
local libcontextMenu = _app.libView.contextMenu
---添加分割线
libcontextMenu:AddSeperator()
libcontextMenu:AddItem("复制组件脚本路径","XiaoCopyAssetPath",function()
---获取当前选中的资源
---@type CS.FairyEditor.FPackageItem
local item = _app.libView:GetSelectedResource()
---检测资源是否满足条件
if item.path:find("/Comps/") == 1 then
---准备复制
local cp_str = ("require(\"UI.%s.Comps.%s\")"):format(item.owner.name,item.name)
---Unity复制操作
CS.UnityEngine.GUIUtility.systemCopyBuffer = cp_str
---弹窗提示
_app.Alert("复制成功")
else
_app.Alert("复制失败")
end
end)
---在弹出的菜单中检测当前选择的资源是否满足条件
libcontextMenu.onPopup:Add(function()
---@type CS.FairyEditor.FPackageItem
local item = _app.libView:GetSelectedResource()
local grayed = true
if item.path:find("/Comps/") == 1 then
-- body
grayed = false
end
libcontextMenu:SetItemGrayed("XiaoCopyAssetPath",grayed)
end)
function onDestroy()
-------do cleanup here-------
toolMenu:RemoveItem("XiaoExportUIType")
toolMenu:RemoveItem("XiaoCopyAssetPath")
end
菜单的操作目前只用到了这两种,后面在实际操作中如果还有,则会继续更新!