【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);
                }
            }
        }

    }
}

你可能感兴趣的:(【FGUI】自动生成UI控件代码,lua写的插件)