"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.fuiCodeGenerator = void 0; const csharp_1 = require("csharp"); const CodeGenConfig_1 = require("./CodeGenConfig"); const CodeWriter_1 = require("./CodeWriter"); class FUICodeGenerator { settings; codePkgName; classes; handler; // save path hotfixViewExportCodePath; modelViewExportCodePath; hotfixViewLogicExportCodePath; modelViewLogicExportCodePath; // 动态加载的Item的类生成路径 itemClassExportCodePath; Handle(handler) { let settings = handler.project.GetSettings("Publish").codeGeneration; let codePkgName = handler.ToFilename(handler.pkg.name); //convert chinese to pinyin, remove special chars etc. this.settings = settings; this.codePkgName = codePkgName; this.handler = handler; // 从自定义配置中读取路径和命名空间 this.hotfixViewExportCodePath = CodeGenConfig_1.CodeGenConfig.HotfixViewCodeOutputPath + '/' + codePkgName; this.modelViewExportCodePath = CodeGenConfig_1.CodeGenConfig.ModelViewCodeOutputPath + '/' + codePkgName; this.hotfixViewLogicExportCodePath = CodeGenConfig_1.CodeGenConfig.HotfixViewLogicCodeOutputPath + "/" + codePkgName; this.modelViewLogicExportCodePath = CodeGenConfig_1.CodeGenConfig.ModelViewLogicCodeOutputPath + "/" + codePkgName; this.itemClassExportCodePath = CodeGenConfig_1.CodeGenConfig.ModelViewCodeOutputPath + '/' + codePkgName; //CollectClasses(stripeMember, stripeClass, fguiNamespace) let classes = handler.CollectClasses(settings.ignoreNoname, settings.ignoreNoname, null); this.classes = classes; handler.SetupCodeFolder(this.hotfixViewExportCodePath, "cs"); //check if target folder exists, and delete old files handler.SetupCodeFolder(this.modelViewExportCodePath, "cs"); //check if target folder exists, and delete old files let classCnt = classes.Count; let codeWriter = new CodeWriter_1.default(); for (let i = 0; i < classCnt; i++) { let classInfo = classes.get_Item(i); // 是否为自定义类型组件标记数组 let customComponentFlagsArray = []; // 是否为跨包组件标记数组 let crossPackageFlagsArray = []; this.generateModelViewCode(classInfo, codeWriter, customComponentFlagsArray, crossPackageFlagsArray); this.generateHotfixViewCode(classInfo, codeWriter, customComponentFlagsArray, crossPackageFlagsArray); this.generateLogicCode(classInfo, codeWriter, customComponentFlagsArray, crossPackageFlagsArray); this.generateItemCode(classInfo, codeWriter); } } // 判断是不是我们自定义类型组件 isCustomClass(typeName) { let classes = this.classes; let count = this.classes.Count; for (let k = 0; k < count; k++) { if (typeName === classes.get_Item(k).className) { return true; } } return false; } getCustomClassName(className) { return CodeGenConfig_1.CodeGenConfig.ClassNamePrefix + className; } generateModelViewCode(classInfo, modelViewCodeWriter, customComponentFlagsArray, crossPackageFlagsArray) { let codePkgName = this.codePkgName; let modelViewExportCodePath = this.modelViewExportCodePath; let namespaceName = CodeGenConfig_1.CodeGenConfig.ModelViewNameSpace; // 初始化自定义成员变量名前缀 let memberVarNamePrefix = CodeGenConfig_1.CodeGenConfig.MemberVarNamePrefix; // 组装自定义组件前缀 let className = this.getCustomClassName(classInfo.className); let members = classInfo.members; modelViewCodeWriter.reset(); modelViewCodeWriter.writeln('using FairyGUI;'); modelViewCodeWriter.writeln(); modelViewCodeWriter.writeln('namespace %s', namespaceName); modelViewCodeWriter.startBlock(); // pakage namespace modelViewCodeWriter.writeln('namespace %s', CodeGenConfig_1.CodeGenConfig.NameSpacePrefix + codePkgName); modelViewCodeWriter.startBlock(); // 用const 在ILRuntime中的反射获取Field会得不到值,所以改用static modelViewCodeWriter.writeln(`[ComponentOf(typeof(FUI))] public sealed class %s : Entity, IAwake, IDestroy { public static string UIPackageName = "%s"; public static string UIResName = "%s"; /// /// {uiResName}的组件类型(GComponent、GButton、GProcessBar等),它们都是GObject的子类。 /// public %s FGComp; `, className, codePkgName, classInfo.resName, classInfo.superClassName); let memberCnt = members.Count; for (let j = 0; j < memberCnt; j++) { let memberInfo = members.get_Item(j); customComponentFlagsArray[j] = false; crossPackageFlagsArray[j] = false; // 判断是不是我们自定义类型组件 let typeName = memberInfo.type; if (this.isCustomClass(typeName)) { typeName = this.getCustomClassName(typeName); customComponentFlagsArray[j] = true; } // 判断是不是跨包类型组件 if (memberInfo && memberInfo.res) { // 组装自定义组件前缀 typeName = this.getCustomClassName(memberInfo.res.name); crossPackageFlagsArray[j] = true; } // 组装自定义成员前缀 modelViewCodeWriter.writeln('\tpublic %s %s;', typeName, memberVarNamePrefix + memberInfo.varName); } modelViewCodeWriter.writeln('\tpublic const string URL = "ui://%s%s";', this.handler.pkg.id, classInfo.resId); modelViewCodeWriter.writeln(); // modelViewCodeWriter.writeln(` // public override void Dispose() // { // if(IsDisposed) // { // return; // } // base.Dispose(); // FGComp.Remove(); // FGComp = null; // `) // for (let j = 0; j < memberCnt; j++) // { // let memberInfo = members.get_Item(j); // // 组装自定义成员前缀 // let memberVarName = memberVarNamePrefix + memberInfo.varName; // if (memberInfo.group === 0) // { // if (customComponentFlagsArray[j] || crossPackageFlagsArray[j]) // { // modelViewCodeWriter.writeln('\t\t%s.Dispose();', memberVarName) // } // } // modelViewCodeWriter.writeln('\t\t%s = null;', memberVarName) // } // modelViewCodeWriter.writeln('\t}'); modelViewCodeWriter.writeln(` public bool Visible { get { if (FGComp == null) { return false; } return FGComp.visible; } set { if (FGComp == null) { return; } FGComp.visible = value; } }`); modelViewCodeWriter.writeln('}'); modelViewCodeWriter.endBlock(); // package namespace modelViewCodeWriter.endBlock(); // topmost namespace modelViewCodeWriter.save(modelViewExportCodePath + '/' + className + '.cs'); ///////////////// // 写入fuipackage ///////////////// modelViewCodeWriter.reset(); modelViewCodeWriter.writeln('namespace %s', namespaceName); modelViewCodeWriter.startBlock(); modelViewCodeWriter.writeln('public static partial class FUIPackage'); modelViewCodeWriter.startBlock(); modelViewCodeWriter.writeln('public const string %s = "%s";', codePkgName, codePkgName); for (let i = 0; i < this.classes.Count; i++) { let classInfo = this.classes.get_Item(i); modelViewCodeWriter.writeln('public const string %s_%s = "ui://%s/%s";', codePkgName, classInfo.resName, codePkgName, classInfo.resName); } modelViewCodeWriter.endBlock(); // class modelViewCodeWriter.endBlock(); let binderPackageName = 'Package' + codePkgName; modelViewCodeWriter.save(modelViewExportCodePath + '/' + binderPackageName + '.cs'); } generateHotfixViewCode(classInfo, hotfixViewCodeWriter, customComponentFlagsArray, crossPackageFlagsArray) { let hotfixViewExportCodePath = this.hotfixViewExportCodePath; let namespaceName = CodeGenConfig_1.CodeGenConfig.HotfixViewNameSpace; let getMemberByName = this.settings.getMemberByName; // 初始化自定义组件名前缀 let classNamePrefix = CodeGenConfig_1.CodeGenConfig.ClassNamePrefix; // 初始化自定义成员变量名前缀 let memberVarNamePrefix = CodeGenConfig_1.CodeGenConfig.MemberVarNamePrefix; // 组装自定义组件前缀 let className = this.getCustomClassName(classInfo.className); let systemName = className + "System"; let members = classInfo.members; hotfixViewCodeWriter.reset(); hotfixViewCodeWriter.writeln('using FairyGUI;'); hotfixViewCodeWriter.writeln('using System.Threading.Tasks;'); hotfixViewCodeWriter.writeln(); hotfixViewCodeWriter.writeln('namespace %s', namespaceName); hotfixViewCodeWriter.startBlock(); hotfixViewCodeWriter.writeln('namespace %s', CodeGenConfig_1.CodeGenConfig.NameSpacePrefix + this.codePkgName); hotfixViewCodeWriter.startBlock(); // writer.writeln('public partial class %s : %s', classInfo.className, classInfo.superClassName); // writer.startBlock(); // awake system hotfixViewCodeWriter.writeln(`public class %sAwakeSystem : AwakeSystem<%s> { public override void Awake(%s self) { self.Awake(); } } `, className, className, className); // destroy system hotfixViewCodeWriter.writeln(`public class %sDestroySystem : DestroySystem<%s> { public override void Destroy(%s self) { self.Destroy(); } } `, className, className, className); hotfixViewCodeWriter.writeln('[FriendClass(typeof(FUI))]'); hotfixViewCodeWriter.writeln(`[FriendClass(typeof(%s))]`, className); // add component system hotfixViewCodeWriter.writeln(`public static class %s {`, systemName); hotfixViewCodeWriter.writeln(` public static void Awake(this %s self) { var fui = self.GetParent(); if(fui.GObject == null) { return; } self.FGComp = (%s)fui.GObject; self.FGComp.Add(fui); var com = fui.GObject.asCom; if(com != null) { `, className, classInfo.superClassName); let memberCnt = members.Count; for (let j = 0; j < memberCnt; j++) { let memberInfo = members.get_Item(j); // 组装自定义成员前缀 let memberVarName = memberVarNamePrefix + memberInfo.varName; if (memberInfo.group === 0) { if (getMemberByName) { if (customComponentFlagsArray[j]) { // 组装自定义组件前缀 hotfixViewCodeWriter.writeln('\t\t\tself.%s = FUIHelper.Create<%s>(self, com.GetChild("%s"));', memberVarName, this.getCustomClassName(memberInfo.type), memberInfo.name); } else if (crossPackageFlagsArray[j]) { // 组装自定义组件前缀 hotfixViewCodeWriter.writeln('\t\t\tself.%s = FUIHelper.Create<%s>(self, com.GetChild("%s"));', memberVarName, this.getCustomClassName(memberInfo.res.name), memberInfo.name); } else { hotfixViewCodeWriter.writeln('\t\t\tself.%s = (%s)com.GetChild("%s");', memberVarName, memberInfo.type, memberInfo.name); } } else { if (customComponentFlagsArray[j]) { // 组装自定义组件前缀 hotfixViewCodeWriter.writeln('\t\t\tself.%s = FUIHelper.Create<%s>(self, com.GetChildAt(%s));', memberVarName, this.getCustomClassName(memberInfo.type), memberInfo.index); } else if (crossPackageFlagsArray[j]) { // 组装自定义组件前缀 hotfixViewCodeWriter.writeln('\t\t\tself.%s = FUIHelper.Create<%s>(self, com.GetChildAt(%s));', memberVarName, this.getCustomClassName(memberInfo.res.name), memberInfo.index); } else { hotfixViewCodeWriter.writeln('\t\t\tself.%s = (%s)com.GetChildAt(%s);', memberVarName, memberInfo.type, memberInfo.index); } } } else if (memberInfo.group == 1) { if (getMemberByName) { hotfixViewCodeWriter.writeln('\t\t\tself.%s = com.GetController("%s");', memberVarName, memberInfo.name); } else { hotfixViewCodeWriter.writeln('\t\t\tself.%s = com.GetControllerAt(%s);', memberVarName, memberInfo.index); } } else { if (getMemberByName) { hotfixViewCodeWriter.writeln('\t\t\tself.%s = com.GetTransition("%s");', memberVarName, memberInfo.name); } else { hotfixViewCodeWriter.writeln('\t\t\tself.%s = com.GetTransitionAt(%s);', memberVarName, memberInfo.index); } } } hotfixViewCodeWriter.writeln('\t\t}'); // end of if hotfixViewCodeWriter.writeln('\t}'); // end of awake function hotfixViewCodeWriter.writeln(` public static void Destroy(this %s self) { if(self.IsDisposed) { return; } self.FGComp.Remove(); self.FGComp = null; `, className); for (let j = 0; j < memberCnt; j++) { let memberInfo = members.get_Item(j); // 组装自定义成员前缀 let memberVarName = memberVarNamePrefix + memberInfo.varName; if (memberInfo.group === 0) { if (customComponentFlagsArray[j] || crossPackageFlagsArray[j]) { hotfixViewCodeWriter.writeln('\t\tself.%s.Dispose();', memberVarName); } } hotfixViewCodeWriter.writeln('\t\tself.%s = null;', memberVarName); } hotfixViewCodeWriter.writeln('\t}'); // end of Destroy function hotfixViewCodeWriter.writeln('}'); hotfixViewCodeWriter.endBlock(); // package namespace hotfixViewCodeWriter.endBlock(); // topmost namespace hotfixViewCodeWriter.save(hotfixViewExportCodePath + '/' + className + '.cs'); } isBanAutoGenerateClass(className) { return CodeGenConfig_1.CodeGenConfig.BanClassOfAutoGenerate.includes(className); } generateLogicCode(classInfo, logicCodeWriter, customComponentFlagsArray, crossPackageFlagsArray) { // 只关注需要导出的类 if (classInfo.res.exported && !this.needGenCompClass(classInfo.className)) { let modelViewLogicExportCodePath = this.modelViewLogicExportCodePath; let hotfixViewLogicExportCodePath = this.hotfixViewLogicExportCodePath; let namespaceName = CodeGenConfig_1.CodeGenConfig.ModelViewNameSpace; let classNamePrefix = CodeGenConfig_1.CodeGenConfig.ClassNamePrefix; let compClassName = classNamePrefix + classInfo.className; let compPropName = "FUI" + classInfo.className; let logicClassNamePrefix = CodeGenConfig_1.CodeGenConfig.LogicClassNamePrefix; let logicComponentClassName = logicClassNamePrefix + classInfo.className + "Component"; let logicSystemClassName = logicComponentClassName + "System"; let logicComponentClassFilePath = modelViewLogicExportCodePath + "/" + logicComponentClassName + '.cs'; let logicSystemClassFilePath = hotfixViewLogicExportCodePath + "/" + logicSystemClassName + '.cs'; // 生成打FriendClass的Attribute的partial类 let friendClassCodePath = this.hotfixViewExportCodePath + "/" + "Friend"; let friendClassFilePath = friendClassCodePath + "/" + logicSystemClassName + 'Friend.cs'; if (!csharp_1.System.IO.Directory.Exists(friendClassCodePath)) { csharp_1.System.IO.Directory.CreateDirectory(friendClassCodePath); } logicCodeWriter.reset(); logicCodeWriter.writeln('namespace %s', namespaceName); logicCodeWriter.startBlock(); logicCodeWriter.writeln('using %s;', CodeGenConfig_1.CodeGenConfig.NameSpacePrefix + this.codePkgName); let members = classInfo.members; let memberCnt = members.Count; for (let j = 0; j < memberCnt; j++) { let memberInfo = members.get_Item(j); if (memberInfo.group === 0) { if ((customComponentFlagsArray[j] || crossPackageFlagsArray[j])) { logicCodeWriter.writeln(`[FriendClass(typeof(%s))]`, this.getCustomClassName(memberInfo.type)); } } } if (!this.isBanAutoGenerateClass(classInfo.className)) { logicCodeWriter.writeln(` [FriendClass(typeof(%s))]`, logicComponentClassName); } logicCodeWriter.writeln(` [FriendClass(typeof(%s))]`, compClassName); logicCodeWriter.writeln(` public static partial class %s { } `, logicSystemClassName); logicCodeWriter.endBlock(); // end of namespace logicCodeWriter.save(friendClassFilePath); let isWindow = false; if (classInfo.className.endsWith("Window")) { isWindow = true; } if (!csharp_1.System.IO.Directory.Exists(modelViewLogicExportCodePath)) { csharp_1.System.IO.Directory.CreateDirectory(modelViewLogicExportCodePath); } // 生成Component代码 if (!csharp_1.System.IO.File.Exists(logicComponentClassFilePath) && !this.isBanAutoGenerateClass(classInfo.className)) { logicCodeWriter.reset(); logicCodeWriter.writeln('namespace %s', namespaceName); logicCodeWriter.startBlock(); logicCodeWriter.writeln('using %s;', CodeGenConfig_1.CodeGenConfig.NameSpacePrefix + this.codePkgName); if (isWindow) { logicCodeWriter.writeln('using FairyGUI;'); logicCodeWriter.writeln(` public class %s : Entity, IAwake, IDestroy, IFUIWindow { public Window Window { get; set; } public %s %s; } `, logicComponentClassName, compClassName, compPropName); } else { logicCodeWriter.writeln(` public class %s : Entity, IAwake, IDestroy { public %s %s; } `, logicComponentClassName, compClassName, compPropName); } logicCodeWriter.endBlock(); logicCodeWriter.save(logicComponentClassFilePath); } if (!csharp_1.System.IO.Directory.Exists(hotfixViewLogicExportCodePath)) { csharp_1.System.IO.Directory.CreateDirectory(hotfixViewLogicExportCodePath); } // 生成System代码 if (!csharp_1.System.IO.File.Exists(logicSystemClassFilePath) && !this.isBanAutoGenerateClass(classInfo.className)) { let logicAwakeSystemName = logicComponentClassName + "AwakeSystem"; logicCodeWriter.reset(); if (isWindow) { logicCodeWriter.writeln('using FairyGUI;'); } logicCodeWriter.writeln('namespace %s', namespaceName); logicCodeWriter.startBlock(); logicCodeWriter.writeln('using %s;', CodeGenConfig_1.CodeGenConfig.NameSpacePrefix + this.codePkgName); logicCodeWriter.writeln(` public class %s : AwakeSystem<%s> { public override void Awake(%s self) { self.Awake(); } } `, logicAwakeSystemName, logicComponentClassName, logicComponentClassName); if (isWindow) { logicCodeWriter.writeln(` public static partial class %s { public static void Awake(this %s self) { self.%s = self.Parent.GetComponent<%s>(); self.Window = new Window(); self.Window.contentPane = self.%s.FGComp; } } `, logicSystemClassName, logicComponentClassName, compPropName, compClassName, compPropName); } else { logicCodeWriter.writeln(` public static partial class %s { public static void Awake(this %s self) { self.%s = self.Parent.GetComponent<%s>(); } } `, logicSystemClassName, logicComponentClassName, compPropName, compClassName); } logicCodeWriter.endBlock(); logicCodeWriter.save(logicSystemClassFilePath); } } } needGenCompClass(className) { if (className.endsWith("Item") || className.endsWith("CheckBox")) { return true; } return false; } generateItemCode(classInfo, writer) { // 只关注需要导出的类 if (classInfo.res.exported) { if (!this.needGenCompClass(classInfo.className)) { return; } let getMemberByName = this.settings.getMemberByName; let className = classInfo.className; let members = classInfo.members; writer.reset(); writer.writeln('using FairyGUI;'); writer.writeln('using FairyGUI.Utils;'); writer.writeln(); writer.writeln('namespace %s', CodeGenConfig_1.CodeGenConfig.ModelViewNameSpace); writer.startBlock(); writer.writeln('namespace %s', CodeGenConfig_1.CodeGenConfig.NameSpacePrefix + this.codePkgName); writer.startBlock(); writer.writeln('public partial class %s : %s', className, classInfo.superClassName); writer.startBlock(); let memberCnt = members.Count; for (let j = 0; j < memberCnt; j++) { let memberInfo = members.get_Item(j); let memberType = memberInfo.type; let typeName = memberType; writer.writeln('public %s %s;', typeName, memberInfo.varName); } writer.writeln('public const string URL = "ui://%s%s";', this.handler.pkg.id, classInfo.resId); writer.writeln(); writer.writeln('public override void ConstructFromXML(XML xml)'); writer.startBlock(); writer.writeln('base.ConstructFromXML(xml);'); writer.writeln(); for (let j = 0; j < memberCnt; j++) { let memberInfo = members.get_Item(j); if (memberInfo.group == 0) { let memberType = memberInfo.type; let typeName = memberType; if (getMemberByName) writer.writeln('%s = (%s)GetChild("%s");', memberInfo.varName, typeName, memberInfo.name); else writer.writeln('%s = (%s)GetChildAt(%s);', memberInfo.varName, typeName, memberInfo.index); } else if (memberInfo.group == 1) { if (getMemberByName) writer.writeln('%s = GetController("%s");', memberInfo.varName, memberInfo.name); else writer.writeln('%s = GetControllerAt(%s);', memberInfo.varName, memberInfo.index); } else { if (getMemberByName) writer.writeln('%s = GetTransition("%s");', memberInfo.varName, memberInfo.name); else writer.writeln('%s = GetTransitionAt(%s);', memberInfo.varName, memberInfo.index); } } writer.endBlock(); writer.endBlock(); // class writer.endBlock(); // sub namespace writer.endBlock(); // root namespace writer.save(this.itemClassExportCodePath + '/' + className + '.cs'); } } } const fuiCodeGenerator = new FUICodeGenerator(); exports.fuiCodeGenerator = fuiCodeGenerator;