【FGUI】自动生成UI控件代码,lua写的插件

在FGUI中可以自己去写lua的插件,来实现各种功能,最近写了一个自动生成UI控件的插件,需要的自取

总共分为4个文件,全部放在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")

--- 点击发布工程时的回调
---@param handler CS.FairyEditor.PublishHandler 发布处理者
function onPublish(handler)
    --- 不勾选生成代码时,将为其生成热更层代码
    if not handler.genCode then
        CodeGenEntry.HotfixCodeGenHandler.Do(handler, CodeGenEntry.CodeGenConfig)
    else
        --- 勾选生成代码时,将为其生成非热更层代码
        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/",

    --- 代码裁剪,即是否为默认名称对象生成获取代码,如果为true,代表不会生成,否则会生成,注意如果开启可能会导致需要导出的类也没有导出的情况
    CodeStrip = false,
    
    --- 组件名前缀
    ClassNamePrefix = "FUI_",
    --- 成员名前缀
    MemerVarNamePrefix = "m_"
}

return GenerateHotfixCodeConfig

HotfixCodeGenHandler.lua

---@class HotfixCodeGenHandler 热更层代码生成器
local HotfixCodeGenHandler = {}

--- 执行生成热更层代码
---@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

    --- 所有将要导出的类(当前包的所有设置为导出的组件,以及当前包所有被引用的组件)
    ---@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 .. "个classes的数量")

    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 .. " 个成员变量")

        -- 是否为自定义类型组件标记数组
        local customComponentFlagsArray = {}
        -- 是否为跨包组件标记数组
        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 .. '个子对象')
        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
            -- 是否为自定义类型组件标记数组
            local customComponentFlagsArraySub = {}
            -- 是否为跨包组件标记数组
            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);
                }
            }
        }

    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容