本文涉及到的軟件有: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.allPackagesfor i = 1, allPackages.Count do---C#索引從0開始---@type CS.FairyEditor.FPackagelocal package = allPackages[i - 1]---獲取當前包中的所有子項,返回值是列表local items = package.itemsfor i = 1, items.Count do---@type CS.FairyEditor.FPackageItemlocal item = items[i - 1]---記錄所有UI開頭的子項if string.find(item.name,"UI") == 1 thenlocal uiType = string.format("%s = %s_%s,\n\t",item.name,package.name,item.name)_classField = _classField .. uiTypeendendend---輸出日志打印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.FPackageItemlocal 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.FPackageItemlocal item = _app.libView:GetSelectedResource()local grayed = trueif item.path:find("/Comps/") == 1 then-- bodygrayed = falseendlibcontextMenu: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.allPackagesfor i = 1, allPackages.Count do---C#索引從0開始---@type CS.FairyEditor.FPackagelocal package = allPackages[i - 1]---獲取當前包中的所有子項,返回值是列表local items = package.itemsfor i = 1, items.Count do---@type CS.FairyEditor.FPackageItemlocal item = items[i - 1]---記錄所有UI開頭的子項if string.find(item.name,"UI") == 1 thenlocal uiType = string.format("%s = %s_%s,\n\t",item.name,package.name,item.name)_classField = _classField .. uiTypeendendend---輸出日志打印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.FPackageItemlocal 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.FPackageItemlocal item = _app.libView:GetSelectedResource()local grayed = trueif item.path:find("/Comps/") == 1 then-- bodygrayed = falseendlibcontextMenu:SetItemGrayed("XiaoCopyAssetPath",grayed)
end)function onDestroy()
-------do cleanup here-------toolMenu:RemoveItem("XiaoExportUIType")toolMenu:RemoveItem("XiaoCopyAssetPath")
end
菜單的操作目前只用到了這兩種,后面在實際操作中如果還有,則會繼續更新!