【FGUI】自動(dòng)生成UI控件代碼,lua寫的插件

在FGUI中可以自己去寫lua的插件,來(lái)實(shí)現(xiàn)各種功能,最近寫了一個(gè)自動(dòng)生成UI控件的插件,需要的自取

總共分為4個(gè)文件,全部放在FGUI的工程目錄下的plugins文件夾里
CodeGenEntry.lua
CodeGenConfig.lua
HotfixCodeGenHandler.lua
package.json

package.json

{
  "name": "CodeGenerate",
  "displayName": "代碼生成插件",
  "description": "",
  "version": "0.0.1",
  "author": {
    "name": "meta404"
  },
  "icon": "icon.png",
  "main": "CodeGenEntry.lua"
}

CodeGenEntry.lua

local CodeGenEntry = {}

---@type HotfixCodeGenHandler
CodeGenEntry.HotfixCodeGenHandler = require(PluginPath .. '/HotfixCodeGenHandler')
---@type CodeGenConfig
CodeGenEntry.CodeGenConfig = require(PluginPath .. "/CodeGenConfig")

--- 點(diǎn)擊發(fā)布工程時(shí)的回調(diào)
---@param handler CS.FairyEditor.PublishHandler 發(fā)布處理者
function onPublish(handler)
    --- 不勾選生成代碼時(shí),將為其生成熱更層代碼
    if not handler.genCode then
        CodeGenEntry.HotfixCodeGenHandler.Do(handler, CodeGenEntry.CodeGenConfig)
    else
        --- 勾選生成代碼時(shí),將為其生成非熱更層代碼
        CodeGenEntry.ModelCodeGenHandler.Do(handler, CodeGenEntry.CodeGenConfig)
    end
end

return CodeGenEntry

CodeGenConfig.lua

---@class CodeGenConfig 代碼生成配置
local GenerateHotfixCodeConfig = {
    --- 熱更代碼配置
    --- 熱更層命名空間
    HotfixNameSpace = "HotfixUI",
    --- 熱更層代碼輸出目錄
    --HotfixCodeOutPutPath = "../Unity/Assets/ModelView/Demo/FGUI/AutoGeneratedCode/",
    HotfixCodeOutPutPath = "E:/Project/Red/SVN/RedWar/Projects/RedWar/HotUpdateScripts/Game/UI/AutoGeneratedCode/",

    --- 代碼裁剪,即是否為默認(rèn)名稱對(duì)象生成獲取代碼,如果為true,代表不會(huì)生成,否則會(huì)生成,注意如果開啟可能會(huì)導(dǎo)致需要導(dǎo)出的類也沒有導(dǎo)出的情況
    CodeStrip = false,
    
    --- 組件名前綴
    ClassNamePrefix = "FUI_",
    --- 成員名前綴
    MemerVarNamePrefix = "m_"
}

return GenerateHotfixCodeConfig

HotfixCodeGenHandler.lua

---@class HotfixCodeGenHandler 熱更層代碼生成器
local HotfixCodeGenHandler = {}

--- 執(zhí)行生成熱更層代碼
---@param handler CS.FairyEditor.PublishHandler
---@param codeGenConfig CodeGenConfig
function HotfixCodeGenHandler.Do(handler, codeGenConfig)
    
    fprint("開始生成Hotfix代碼")

    local codePkgName = handler:ToFilename(handler.pkg.name); --convert chinese to pinyin, remove special chars etc.

    --- 從自定義配置中讀取路徑和命名空間
    local exportCodePath = codeGenConfig.HotfixCodeOutPutPath .. '/' .. codePkgName
    local namespaceName = codeGenConfig.HotfixNameSpace

    --- 初始化自定義組件名前綴
    local classNamePrefix = codeGenConfig.ClassNamePrefix
    --- 初始化自定義成員變量名前綴
    local memberVarNamePrefix = codeGenConfig.MemerVarNamePrefix
    
    --- 從FGUI編輯器中讀取配置
    ---@type CS.FairyEditor.GlobalPublishSettings.CodeGenerationConfig
    local settings = handler.project:GetSettings("Publish").codeGeneration
    local getMemberByName = settings.getMemberByName

    --- 所有將要導(dǎo)出的類(當(dāng)前包的所有設(shè)置為導(dǎo)出的組件,以及當(dāng)前包所有被引用的組件)
    ---@type CS.FairyEditor.PublishHandler.ClassInfo[]
    local classes = handler:CollectClasses(codeGenConfig.CodeStrip, codeGenConfig.CodeStrip, nil)
    handler:SetupCodeFolder(exportCodePath, "cs") --check if target folder exists, and delete old files

    fprint("找到" .. classes.Count .. "個(gè)classes的數(shù)量")

    local classCnt = classes.Count
    local writer = CodeWriter.new()

    local mainPanelIndex = 0
    for i = 0, classCnt - 1 do
        local className = classes[i].className
        fprint("class name: " .. className)
        if(string.find(className, 'Panel') ~= nil) then
            mainPanelIndex = i
            break;
        end
    end

    --for i = 0, classCnt - 1 do
    for i = mainPanelIndex, mainPanelIndex do
        local classInfo = classes[i]
        local members = classInfo.members
        writer:reset()

        writer:writeln('/** ============================================================================== **/')
        writer:writeln('/** ============================Auto Generate Class=============================== **/')
        writer:writeln('/** ============================================================================== **/')

        writer:writeln()
        writer:writeln('using FairyGUI;')
        writer:writeln('using FUIFW;')
        writer:writeln()
        writer:writeln('namespace %s', namespaceName)
        writer:startBlock()

        --- 組裝自定義組件前綴
        local className = classNamePrefix .. classInfo.className

        writer:writeln([[public partial class %s : FUIBase
    {   
            ]], codePkgName, codePkgName, classInfo.resName, classInfo.superClassName)


        local memberCnt = members.Count
        fprint("找到了" .. memberCnt .. " 個(gè)成員變量")

        -- 是否為自定義類型組件標(biāo)記數(shù)組
        local customComponentFlagsArray = {}
        -- 是否為跨包組件標(biāo)記數(shù)組
        local crossPackageFlagsArray = {}

        for j = 0, memberCnt - 1
        do
            local memberInfo = members[j]
            customComponentFlagsArray[j] = false
            crossPackageFlagsArray[j] = false

            -- 判斷是不是我們自定義類型組件
            local typeName = memberInfo.type
            for k = 0, classCnt - 1
            do
                if typeName == classes[k].className
                then
                    typeName = classNamePrefix .. classes[k].className
                    customComponentFlagsArray[j] = true
                    break
                end
            end

            -- 判斷是不是跨包類型組件
            if memberInfo.res ~= nil then
                --- 組裝自定義組件前綴
                typeName = classNamePrefix .. memberInfo.res.name
                crossPackageFlagsArray[j] = true
            end
            
            --- 組裝自定義成員前綴
            writer:writeln('\tpublic %s %s;', typeName, memberVarNamePrefix .. memberInfo.varName)
        end

        
        writer:writeln()
        writer:writeln([[
    public void Init(GObject go)
        {
            if(go == null)
            {
                return;
            }
            
            var com = go.asCom;
                
            if(com != null)
            {   
                ]], classInfo.superClassName)

        for j = 0, memberCnt - 1
        do
            local memberInfo = members[j]
            --- 組裝自定義成員前綴
            local memberVarName = memberVarNamePrefix .. memberInfo.varName
            if memberInfo.group == 0
            then
                if getMemberByName
                then
                    if customComponentFlagsArray[j]
                    then
                        --- 組裝自定義組件前綴
                        writer:writeln('\t\t\t%s = new %s(com.GetChildAt(%s));', memberVarName, classNamePrefix .. memberInfo.type, memberInfo.name)
                    elseif crossPackageFlagsArray[j]
                    then
                        --- 組裝自定義組件前綴
                        writer:writeln('\t\t\t%s = new %s(com.GetChildAt(%s));', memberVarName, classNamePrefix .. memberInfo.res.name, memberInfo.name)
                    else
                        writer:writeln('\t\t\t%s = (%s)com.GetChild("%s");', memberVarName, memberInfo.type, memberInfo.name)
                    end

                else
                    if customComponentFlagsArray[j]
                    then
                        --- 組裝自定義組件前綴
                        writer:writeln('\t\t\t%s = new %s(com.GetChildAt(%s));', memberVarName, classNamePrefix .. memberInfo.type, memberInfo.index)
                    elseif crossPackageFlagsArray[j]
                    then
                        --- 組裝自定義組件前綴
                        writer:writeln('\t\t\t%s = new %s(com.GetChildAt(%s));', memberVarName, classNamePrefix .. memberInfo.res.name, memberInfo.index)
                    else
                        writer:writeln('\t\t\t%s = (%s)com.GetChildAt(%s);', memberVarName, memberInfo.type, memberInfo.index)
                    end
                end
            elseif memberInfo.group == 1
            then
                if getMemberByName
                then
                    writer:writeln('\t\t\t%s = com.GetController("%s");', memberVarName, memberInfo.name)
                else
                    writer:writeln('\t\t\t%s = com.GetControllerAt(%s);', memberVarName, memberInfo.index)
                end
            else
                if getMemberByName
                then
                    writer:writeln('\t\t\t%s = com.GetTransition("%s");', memberVarName, memberInfo.name)
                else
                    writer:writeln('\t\t\t%s = com.GetTransitionAt(%s);', memberVarName, memberInfo.index)
                end
            end
        end
        writer:writeln('\t\t}')

        writer:writeln('\t}')
        writer:writeln()






        local classCntSub = classes.Count
        fprint('找到了' .. classCntSub - 1 .. '個(gè)子對(duì)象')
        for m = 0, classCntSub - 1 do
            if(m ~= mainPanelIndex) then

            local classInfoSub = classes[m]
            local membersSub = classInfoSub.members
            local classNameSub = classNamePrefix .. classInfoSub.className

            writer:writeln([[
    public class %s
        {   
                    ]], classNameSub)

            local memberCntSub = membersSub.Count
            -- 是否為自定義類型組件標(biāo)記數(shù)組
            local customComponentFlagsArraySub = {}
            -- 是否為跨包組件標(biāo)記數(shù)組
            local crossPackageFlagsArraySub = {}
    
            for n = 0, memberCntSub - 1
            do
                local memberInfoSub = membersSub[n]
                customComponentFlagsArraySub[n] = false
                crossPackageFlagsArraySub[n] = false
    
                -- 判斷是不是我們自定義類型組件
                local typeNameSub = memberInfoSub.type
                for k = 0, classCntSub - 1
                do
                    if typeNameSub == classes[m].className
                    then
                        typeNameSub = classNamePrefix .. classes[m].className
                        customComponentFlagsArraySub[n] = true
                        break
                    end
                end
    
                -- 判斷是不是跨包類型組件
                if memberInfoSub.res ~= nil then
                    --- 組裝自定義組件前綴
                    typeNameSub = classNamePrefix .. memberInfoSub.res.name
                    crossPackageFlagsArraySub[n] = true
                end
                
                --- 組裝自定義成員前綴
                writer:writeln('\t\tpublic %s %s;', typeNameSub, memberVarNamePrefix .. memberInfoSub.varName)
            end



            writer:writeln()
            writer:writeln([[
        public %s(GObject go)
            {
                if(go == null)
                {
                    return;
                }
                
                var com = go.asCom;
                    
                if(com != null)
                {   
                    ]], classNameSub)
    
            for j = 0, memberCntSub - 1
            do
                local memberInfoSub = membersSub[j]
                --- 組裝自定義成員前綴
                local memberVarNameSub = memberVarNamePrefix .. memberInfoSub.varName
                if memberInfoSub.group == 0
                then
                    if getMemberByNameSub
                    then
                        if customComponentFlagsArraySub[j]
                        then
                            --- 組裝自定義組件前綴
                            writer:writeln('\t\t\t\t%s = new %s(com.GetChildAt(%s));', memberVarNameSub, classNamePrefix .. memberInfoSub.type, memberInfoSub.name)
                        elseif crossPackageFlagsArraySub[j]
                        then
                            --- 組裝自定義組件前綴
                            writer:writeln('\t\t\t\t%s = new %s(com.GetChildAt(%s));', memberVarNameSub, classNamePrefix .. memberInfoSub.res.name, memberInfoSub.name)
                        else
                            writer:writeln('\t\t\t\t%s = (%s)com.GetChild("%s");', memberVarNameSub, memberInfoSub.type, memberInfoSub.name)
                        end
    
                    else
                        if customComponentFlagsArraySub[j]
                        then
                            --- 組裝自定義組件前綴
                            writer:writeln('\t\t\t\t%s = new %s(com.GetChildAt(%s));', memberVarNameSub, classNamePrefix .. memberInfoSub.type, memberInfoSub.index)
                        elseif crossPackageFlagsArraySub[j]
                        then
                            --- 組裝自定義組件前綴
                            writer:writeln('\t\t\t\t%s = new %s(com.GetChildAt(%s));', memberVarNameSub, classNamePrefix .. memberInfoSub.res.name, memberInfoSub.index)
                        else
                            writer:writeln('\t\t\t\t%s = (%s)com.GetChildAt(%s);', memberVarNameSub, memberInfoSub.type, memberInfoSub.index)
                        end
                    end
                elseif memberInfoSub.group == 1
                then
                    if getMemberByNameSub
                    then
                        writer:writeln('\t\t\t\t%s = com.GetController("%s");', memberVarNameSub, memberInfoSub.name)
                    else
                        writer:writeln('\t\t\t\t%s = com.GetControllerAt(%s);', memberVarNameSub, memberInfoSub.index)
                    end
                else
                    if getMemberByNameSub
                    then
                        writer:writeln('\t\t\t\t%s = com.GetTransition("%s");', memberVarNameSub, memberInfoSub.name)
                    else
                        writer:writeln('\t\t\t\t%s = com.GetTransitionAt(%s);', memberVarNameSub, memberInfoSub.index)
                    end
                end
            end
            writer:writeln('\t\t\t}')
    
            writer:writeln('\t\t}')

            writer:writeln('\t}')
            writer:writeln()

        end
        end

        writer:writeln('}')
        writer:endBlock()

        path = exportCodePath .. '/' .. codePkgName .. '.cs'
        writer:save(path)
        fprint("生成代碼完畢:" .. path)
    end

end

return HotfixCodeGenHandler

最后看下生成的效果

/** This is an automatically generated class by FairyGUI. Please do not modify it. **/

/** ============================================================================== **/
/** ============================Auto Generate Class=============================== **/
/** ============================================================================== **/

using FairyGUI;
using FUIFW;

namespace HotfixUI
{
    public partial class UI_ThisIsExample : FUIBase
    {   
            
        public GList m_list_Labels;
        public GGraph m_graph_Mask;
        public GTextField m_text_Exa;
        public FUI_Clone m_clone_Test;
        public FUI_Label1 m_label_t;

        public void Init(GObject go)
        {
            if(go == null)
            {
                return;
            }
            
            var com = go.asCom;
                
            if(com != null)
            {   
                
                m_list_Labels = (GList)com.GetChildAt(0);
                m_graph_Mask = (GGraph)com.GetChildAt(1);
                m_text_Exa = (GTextField)com.GetChildAt(2);
                m_clone_Test = new FUI_Clone(com.GetChildAt(3));
                m_label_t = new FUI_Label1(com.GetChildAt(4));
            }
        }

        public class FUI_Label1
        {   
                    
            public GTextField m_title;

            public FUI_Label1(GObject go)
            {
                if(go == null)
                {
                    return;
                }
                
                var com = go.asCom;
                    
                if(com != null)
                {   
                    
                    m_title = (GTextField)com.GetChildAt(0);
                }
            }
        }

        public class FUI_Button1
        {   
                    
            public Controller m_button;
            public GGraph m_n0;
            public GGraph m_n1;
            public GGraph m_n2;

            public FUI_Button1(GObject go)
            {
                if(go == null)
                {
                    return;
                }
                
                var com = go.asCom;
                    
                if(com != null)
                {   
                    
                    m_button = com.GetControllerAt(0);
                    m_n0 = (GGraph)com.GetChildAt(0);
                    m_n1 = (GGraph)com.GetChildAt(1);
                    m_n2 = (GGraph)com.GetChildAt(2);
                }
            }
        }

        public class FUI_Clone
        {   
                    
            public GTextField m_text_Content;

            public FUI_Clone(GObject go)
            {
                if(go == null)
                {
                    return;
                }
                
                var com = go.asCom;
                    
                if(com != null)
                {   
                    
                    m_text_Content = (GTextField)com.GetChildAt(0);
                }
            }
        }

    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,401評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,069評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,635評(píng)論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,128評(píng)論 1 323
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,365評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,881評(píng)論 1 334
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,733評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,935評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,172評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評(píng)論 1 282
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,595評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,908評(píng)論 2 372

推薦閱讀更多精彩內(nèi)容