Files
Fishing2/FGUIProject/plugins/nbc-puerts-plugins/GenCode_CSharp.ts
2026-02-04 18:55:28 +08:00

683 lines
23 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import FairyGUI = CS.FairyGUI;
import FairyEditor = CS.FairyEditor;
import System = CS.System;
import CodeWriter, { ICodeWriterConfig } from './CodeWriter';
import genSetting, { ComponentData, MemberData } from './GenCodeSettings'
import languageSetting, { LanguageComponentChildData } from './LanguageSettings'
// Tween 使用运行时 require避免跨项目编译输出位置错乱本地定义最小类型接口
interface TweenComponentChildData { id: string; key: string; useable: number }
// 注意:运行时从相对路径加载已编译的 JSCustomAttributer/TweenSettings.js
declare const require: any;
const tweenSetting: any = (function(){
try { return require('../whoot-tween/TweenSettings').default || require('../whoot-tween/TweenSettings'); } catch { return null; }
})();
const File = System.IO.File;
const Directory = System.IO.Directory;
const App = FairyEditor.App;
var allSuperClassNameByUrl = {}
var allCustomNameByUrl = {}
var namespaceName = "";
var setNamespaceName = false
var exportCodePath = ""
var existScriptPaths = {};
var packageName = ''
//获取所有的文件的路径
function getAllDirector(path: string, list: Array<string>) {
let dirs = Directory.GetDirectories(path)
for (let index = 0; index < dirs.Length; index++) {
let dir = dirs.get_Item(index);
getAllFile(dir, list)
let dirs2 = Directory.GetDirectories(dir)
if (dirs2.Length > 0) {
getAllDirector(dir, list)
}
}
}
function getAllFile(dir: string, list: Array<string>) {
let files = Directory.GetFiles(dir, "*.cs")
for (let f = 0; f < files.Length; f++) {
list.push(files.get_Item(f))
}
}
class WhootCodeWriterConfig implements ICodeWriterConfig {
blockStart?: string;
blockEnd?: string;
blockFromNewLine?: boolean;
usingTabs?: boolean;
endOfLine?: string;
fileMark?: string;
}
function genCSCode(handler: FairyEditor.PublishHandler) {
console.log("gencode==========--------------========")
let settings = (<FairyEditor.GlobalPublishSettings>handler.project.GetSettings("Publish")).codeGeneration;
let codePkgName = handler.ToFilename(handler.pkg.name);
exportCodePath = handler.exportCodePath // + '/' + codePkgName;
console.log("exportCodePath=", exportCodePath)
let pkgId = handler.pkg.id;
packageName = handler.pkg.name
existScriptPaths = {};
let list: Array<string> = []
getAllFile(exportCodePath, list)
//开始前,先遍历整个生成目录。找寻所有文件。用以判断生成的文件存放地址
getAllDirector(exportCodePath, list);
for (let index = 0; index < list.length; index++) {
let path = list[index];
var newPath = path.replace(/\\/g, '/');
let arrs = newPath.split('/')
let key = arrs[arrs.length - 1]
existScriptPaths[key] = path
}
namespaceName = "";
setNamespaceName = false
if (settings.packageName) {
namespaceName = settings.packageName
setNamespaceName = true
}
let classes = handler.CollectClasses(settings.ignoreNoname, settings.ignoreNoname, null);
let getMemberByName = true;//默认使用名称获取对象//settings.getMemberByName;
console.log(codePkgName, namespaceName, getMemberByName)
let classCnt = classes.Count;
allCustomNameByUrl = {}
allSuperClassNameByUrl = {}
let dependPackages: Array<string> = []
//因为没有文档,同时返回内容限制,先保存子类基类关系。用于后续判断是否使用自定义类
for (let i: number = 0; i < classCnt; i++) {
let classInfo = classes.get_Item(i);
let url = classInfo.res.GetURL();
allSuperClassNameByUrl[url] = classInfo.superClassName
let config: ComponentData = genSetting.getComponentSetting(url)
if (config != null) {
if (config.isCustomName) {
allCustomNameByUrl[url] = settings.classNamePrefix + config.customName
}
}
//获取依赖的包
for (let index = 0; index < classInfo.members.Count; index++) {
let element = classInfo.members.get_Item(index);
if (element.res != null && element.res.owner != null) {
let pname = element.res.owner.name;
if (dependPackages.indexOf(pname) < 0 && pname != codePkgName) {
dependPackages.push(pname)
}
}
}
}
let componentClassNameArr: Array<string> = []
for (let i: number = 0; i < classCnt; i++) {
let classInfo = classes.get_Item(i);
let url = classInfo.res.GetURL();
let config: ComponentData = genSetting.getComponentSetting(url)
if (config != null) {
console.log(config.name, config.scriptType)
if (config.scriptType == "panel") {
genPanelCode(classInfo, config, codePkgName, pkgId, dependPackages);
} else if (config.scriptType == "component") {
let ComponentClassName = genComponentCode(classInfo, config, codePkgName, pkgId)
componentClassNameArr.push(ComponentClassName)
}
} else {
console.log(classInfo.resName + "未配置导出,忽略")
}
}
console.log("生成Binder,count="+componentClassNameArr.length)
genBinder(codePkgName, componentClassNameArr);
genLanguage();
// 生成动效配置
genTween();
}
function getScriptName(className: string, comUrl: string) {
if (allCustomNameByUrl.hasOwnProperty(comUrl)) {
className = allCustomNameByUrl[comUrl]
}
return className
}
function genPanelCode(classInfo: FairyEditor.PublishHandler.ClassInfo, config: ComponentData, codePkgName: string, pkgId: string, dependPackages?: Array<string>) {
let codeConfig: WhootCodeWriterConfig = new WhootCodeWriterConfig();
codeConfig.fileMark = "/**本脚本为自动生成每次生成会覆盖请勿手动修改生成插件文档及项目地址https://git.whoot.com/whoot-games/whoot.fguieditorplugin**/"
let comUrl = classInfo.res.GetURL();
//先生成 .Designer部分
let writer = new CodeWriter(codeConfig);
writer.writeln('using FairyGUI;');
writer.writeln('using FairyGUI.Utils;');
writer.writeln('using NBC;');
writer.writeln('using System.Collections.Generic;');
writer.writeln();
let className = getScriptName(classInfo.className, comUrl)
if (setNamespaceName) {
writer.writeln('namespace %s', namespaceName);
writer.startBlock();
writer.writeln("/// <summary> %s </summary>", config.annotation);
writer.writeln('public partial class %s', className);
writer.startBlock();
} else {
writer.writeln("/// <summary> %s </summary>", config.annotation);
writer.writeln('public partial class %s', className);
writer.startBlock();
}
writer.writeln("public GObject this[string aKey] => ContentPane.GetChild(aKey);");
writer.writeln('public override string UIPackName => "%s";', codePkgName);
writer.writeln('public override string UIResName => "%s";', classInfo.res.name);
writer.writeln();
let members = classInfo.members;
let memberCnt = members.Count
for (let j: number = 0; j < memberCnt; j++) {
let memberInfo = members.get_Item(j);
if (memberInfo.res != null) {
let superClassName = getComponentUseClassName(memberInfo, comUrl)
writer.writeln('[AutoFind(Name = "%s")]', memberInfo.name)
//判断配置,是否需要使用生成的类
writer.writeln('public %s %s;', superClassName, memberInfo.varName);
} else {
writer.writeln('[AutoFind(Name = "%s")]', memberInfo.name)
writer.writeln('public %s %s;', memberInfo.type, memberInfo.varName);
}
}
let url = `ui://${pkgId}${classInfo.resId}`
if (dependPackages != null) {
let str = "";
let len = dependPackages.length - 1;
for (let index = 0; index <= len; index++) {
let pname = dependPackages[index];
str += `"${pname}"`;
if (index < len) {
str += ",";
}
}
writer.writeln(`public override string[] GetDependPackages(){ return new string[] {${str}}; }`)
writer.writeln();
}
writer.writeln(`public static void Show(object param = null){ UI.Inst.OpenUI<${className}>(param); }`)
writer.writeln();
writer.writeln(`public static void Hide(){ UI.Inst.HideUI<${className}>(); }`)
writer.writeln();
writer.writeln(`public static void Del(){ UI.Inst.DestroyUI<${className}>(); }`)
writer.writeln();
writer.endBlock();
if (setNamespaceName) {
writer.endBlock();
}
let fileName = className + ".Designer" + '.cs'
let savePath = exportCodePath + '/' + fileName
if (existScriptPaths.hasOwnProperty(fileName)) {
console.log("脚本已经有同名的,替换地址=", fileName, existScriptPaths[fileName])
savePath = existScriptPaths[fileName]
}
writer.save(savePath);
// 判断模块脚本是否存在。如果不存在,创建默认模板脚本
let defFileName = className + '.cs'
if (!existScriptPaths.hasOwnProperty(defFileName)) {
let mainSavePath = exportCodePath + '/' + defFileName
console.log("Panel的主脚本不存在生成默认=", mainSavePath)
writer.reset();
codeConfig.fileMark = "// 本脚本只在不存在时会生成一次。已存在不会再次生成覆盖"
writer = new CodeWriter(codeConfig);
writer.writeln('using UnityEngine;');
writer.writeln('using NBC;');
writer.writeln();
if (setNamespaceName) {
writer.writeln('namespace %s', namespaceName);
writer.startBlock();
writer.writeln('public partial class %s : UIPanel', className);
writer.startBlock();
} else {
writer.writeln('public partial class %s : UIPanel', className);
writer.startBlock();
}
// writer.writeln('protected override void OnInit()');
// writer.startBlock();
// writer.writeln('base.OnInit();');
// writer.endBlock();
// writer.writeln();
// writer.writeln('protected override void OnShow()');
// writer.startBlock();
// writer.writeln('base.OnShow();');
// writer.endBlock();
// writer.writeln();
// writer.writeln('protected override void OnHide()');
// writer.startBlock();
// writer.writeln('base.OnHide();');
// writer.endBlock();
// writer.writeln();
// writer.writeln('protected override void OnDestroy()');
// writer.startBlock();
// writer.writeln('base.OnDestroy();');
// writer.endBlock();
writer.endBlock();
if (setNamespaceName) {
writer.endBlock();
}
writer.save(mainSavePath);
}
}
function getComponentUseClassName(memberInfo: FairyEditor.PublishHandler.MemberInfo, comUrl: string) {
let name = memberInfo.type
let useCustomScript = false
if (memberInfo.res != null) {
let comUrl = memberInfo.res.GetURL();
//是自定义组件,改为使用原生,不适用自定义
let superClassName = allSuperClassNameByUrl[comUrl]
let config: ComponentData = genSetting.getComponentSetting(comUrl)
if (config != null && config.scriptType == "component") {
superClassName = memberInfo.res.name
useCustomScript = true
}
if (superClassName == null || superClassName == undefined) {
superClassName = memberInfo.type
}
name = superClassName
}
return name;//{ name: name, useCustomScript: useCustomScript }
}
function genComponentCode(classInfo: FairyEditor.PublishHandler.ClassInfo, config: ComponentData, codePkgName: string, pkgId: string) {
let codeConfig: WhootCodeWriterConfig = new WhootCodeWriterConfig();
codeConfig.fileMark = "/**本脚本为自动生成每次生成会覆盖请勿手动修改生成插件文档及项目地址https://git.whoot.com/whoot-games/whoot.fguieditorplugin**/"
let comUrl = classInfo.res.GetURL();
let className = getScriptName(classInfo.className, comUrl)
let writer = new CodeWriter(codeConfig);
writer.writeln();
writer.writeln('using FairyGUI;');
writer.writeln('using FairyGUI.Utils;');
writer.writeln('using NBC;');
writer.writeln();
if (setNamespaceName) {
writer.writeln('namespace %s', namespaceName);
writer.startBlock();
writer.writeln('public partial class %s', className);
writer.startBlock();
} else {
writer.writeln('public partial class %s', className);
writer.startBlock();
}
writer.writeln('public const string URL = "ui://%s%s";', pkgId, classInfo.resId);
writer.writeln();
//生成成员变量
let members = classInfo.members;
let memberCnt = members.Count
for (let j: number = 0; j < memberCnt; j++) {
let memberInfo = members.get_Item(j);
if (memberInfo.res != null) {
let superClassName = getComponentUseClassName(memberInfo, comUrl)
writer.writeln('public %s %s;', superClassName, memberInfo.varName);
} else {
writer.writeln('public %s %s;', memberInfo.type, memberInfo.varName);
}
}
writer.writeln();
writer.writeln('public override void ConstructFromXML(XML xml)');
writer.startBlock();
writer.writeln('base.ConstructFromXML(xml);');
writer.writeln();
for (let j: number = 0; j < memberCnt; j++) {
let memberInfo = members.get_Item(j);
if (memberInfo.group == 0) {
let superClassName = memberInfo.type
let useExtend = false
if (memberInfo.res != null) {
superClassName = getComponentUseClassName(memberInfo, comUrl)
}
writer.writeln('%s = (%s)GetChild("%s");', memberInfo.varName, superClassName, memberInfo.name);
}
else if (memberInfo.group == 1) {
writer.writeln('%s = GetController("%s");', memberInfo.varName, memberInfo.name);
}
else {
writer.writeln('%s = GetTransition("%s");', memberInfo.varName, memberInfo.name);
}
}
writer.writeln('OnInited();');
writer.writeln('UILanguage.TrySetComponentLanguage(this);');
writer.endBlock();
writer.endBlock();
if (setNamespaceName) {
writer.endBlock();
}
let fileName = className + ".Designer" + '.cs'
let savePath = exportCodePath + '/' + fileName
if (existScriptPaths.hasOwnProperty(fileName)) {
console.log("脚本已经有同名的,替换地址=", fileName, existScriptPaths[fileName])
savePath = existScriptPaths[fileName]
}
writer.save(savePath);
// 判断模块脚本是否存在。如果不存在,创建默认模板脚本
let defFileName = className + '.cs'
if (!existScriptPaths.hasOwnProperty(defFileName)) {
let mainSavePath = exportCodePath + '/' + defFileName
console.log("Component的主脚本不存在生成默认")
writer.reset();
codeConfig.fileMark = "// 本脚本只在不存在时会生成一次。组件逻辑写在当前脚本内。已存在不会再次生成覆盖 "
writer = new CodeWriter(codeConfig);
writer.writeln('using UnityEngine;');
writer.writeln('using FairyGUI;');
writer.writeln('using NBC;');
writer.writeln();
if (setNamespaceName) {
writer.writeln('namespace %s', namespaceName);
writer.startBlock();
writer.writeln('public partial class %s : %s', className, classInfo.superClassName);
writer.startBlock();
} else {
writer.writeln('public partial class %s : %s', className, classInfo.superClassName);
writer.startBlock();
}
writer.writeln('private void OnInited()');
writer.startBlock();
writer.endBlock();
writer.endBlock();
if (setNamespaceName) {
writer.endBlock();
}
writer.save(mainSavePath);
}
return className
}
/**
* 生成自定义脚本绑定关系
* @param codePkgName
* @param componentClassNameArr
*/
function genBinder(codePkgName: string, componentClassNameArr: Array<string>) {
let binderName = codePkgName + 'Binder';
let codeConfig: WhootCodeWriterConfig = new WhootCodeWriterConfig();
codeConfig.fileMark = "/**注册组件绑定关系。本脚本为自动生成每次生成会覆盖请勿手动修改生成插件文档及项目地址https://git.whoot.com/whoot-games/whoot.fguieditorplugin**/"
let writer = new CodeWriter(codeConfig);
writer.reset();
writer.writeln('using FairyGUI;');
writer.writeln();
if (setNamespaceName) {
writer.writeln('namespace %s', namespaceName);
writer.startBlock();
}
writer.writeln('public static class %s', binderName);
writer.startBlock();
writer.writeln('[UIExtensionAutoBind]');
writer.writeln('public static void BindAll()');
writer.startBlock();
for (let i: number = 0; i < componentClassNameArr.length; i++) {
//let classInfo = classes.get_Item(i);
let name = componentClassNameArr[i]
writer.writeln('UIObjectFactory.SetPackageItemExtension(%s.URL, typeof(%s));', name, name);
}
writer.endBlock(); //bindall
writer.endBlock(); //class
if (setNamespaceName) {
writer.endBlock(); //namespace
}
let fileName = binderName + '.cs'
let savePath = exportCodePath + '/' + fileName
console.log("生成binder 1=", fileName)
if (existScriptPaths.hasOwnProperty(fileName)) {
savePath = existScriptPaths[fileName]
}
writer.save(savePath);
}
/**
* 生成多语言
*/
function genLanguage() {
let binderName = 'UILangeageConfig';
let languageMap = languageSetting.getAllPackage()
//getPackage
let codeConfig: WhootCodeWriterConfig = new WhootCodeWriterConfig();
codeConfig.fileMark = "/**注册组件多语言绑定。本脚本为自动生成每次生成会覆盖请勿手动修改生成插件文档及项目地址https://git.whoot.com/whoot-games/whoot.fguieditorplugin**/"
let writer = new CodeWriter(codeConfig);
writer.reset();
writer.writeln('using System.Collections.Generic;');
writer.writeln('using FairyGUI;');
writer.writeln('using NBC;');
writer.writeln();
if (setNamespaceName) {
writer.writeln('namespace %s', namespaceName);
writer.startBlock();
}
writer.writeln('public class %s : UIComponentLanguagePack', binderName);
writer.startBlock();
writer.writeln('public UILangeageConfig()');
writer.startBlock();
writer.writeln('AddData();');
writer.endBlock();
writer.writeln('private void AddData()');
writer.startBlock();
let keys = languageMap.keys();
for (let key of keys) {
let pack = languageMap.get(key);
let languageData = pack.components;
for (let comUrl in languageData) {
let comObj = languageData[comUrl];
if (comObj == undefined) continue;
writer.writeln('Add("%s", new UIComponentLanguage()', comUrl);
writer.startBlock();
for (let key2 in comObj) {
var cfg = comObj[key2]
let useable = cfg['useable']
let languageKey = cfg["key"]
if (useable != 1) continue;
writer.writeln('{ "%s", "%s" },', key2, languageKey);
}
writer.endBlock();
writer.writeln(');');
}
writer.writeln();
}
// for (let comUrl in languageData) {
// let comObj = languageData[comUrl];
// if (comObj != undefined) {
// for (let key in comObj) {
// var cfg = comObj[key]
// let useable = cfg['useable']
// let languageKey = cfg["key"]
// if (useable == 1) {
// console.log("comurl:" + comUrl + " key:" + key + " lan:" + languageKey)
// }
// }
// }
// }
writer.endBlock(); //bindall
writer.endBlock(); //class
if (setNamespaceName) {
writer.endBlock(); //namespace
}
let fileName = binderName + '.cs'
let savePath = exportCodePath + '/' + fileName
console.log("生成 language=", fileName)
if (existScriptPaths.hasOwnProperty(fileName)) {
savePath = existScriptPaths[fileName]
}
writer.save(savePath);
}
/**
* 生成动效配置
* 结构参考多语言生成:按包 -> 组件URL -> 子项id写入 C# 配置类
*/
function genTween() {
let binderName = 'UITweenConfig';
if (!tweenSetting || !tweenSetting.getAllPackage) {
console.warn('UITweenConfig 生成被跳过:未找到 ../whoot-tween/TweenSettings.js 或接口不完整');
return;
}
let tweenMap = tweenSetting.getAllPackage();
let codeConfig: WhootCodeWriterConfig = new WhootCodeWriterConfig();
codeConfig.fileMark = "/**注册组件动效绑定。本脚本为自动生成每次生成会覆盖请勿手动修改生成插件文档及项目地址https://git.whoot.com/whoot-games/whoot.fguieditorplugin**/"
let writer = new CodeWriter(codeConfig);
writer.reset();
writer.writeln('using System.Collections.Generic;');
writer.writeln('using FairyGUI;');
writer.writeln('using NBC;');
writer.writeln();
if (setNamespaceName) {
writer.writeln('namespace %s', namespaceName);
writer.startBlock();
}
writer.writeln('public class %s : UIComponentTweenPack', binderName);
writer.startBlock();
writer.writeln('public %s()', binderName);
writer.startBlock();
writer.writeln('AddData();');
writer.endBlock();
writer.writeln();
writer.writeln('private void AddData()');
writer.startBlock();
let keys = tweenMap.keys();
for (let key of keys) {
let pack = tweenMap.get(key);
let tweenData = pack.components;
for (let comUrl in tweenData) {
let comObj = tweenData[comUrl];
if (comObj == undefined) continue;
writer.writeln('// %s', key);
writer.writeln('Add("%s", new UIComponentTween()', comUrl);
writer.startBlock();
for (let childId in comObj) {
var cfg = comObj[childId] as TweenComponentChildData | any;
let useable = cfg['useable'];
let tweenKey = cfg['key'];
if (useable != 1) continue;
writer.writeln('{ "%s", "%s" },', childId, tweenKey);
}
writer.endBlock();
writer.writeln(');');
}
writer.writeln();
}
writer.endBlock(); // AddData
writer.endBlock(); // class
if (setNamespaceName) {
writer.endBlock(); // namespace
}
let fileName = binderName + '.cs'
let savePath = exportCodePath + '/' + fileName
console.log("生成 tween=", fileName)
if (existScriptPaths.hasOwnProperty(fileName)) {
savePath = existScriptPaths[fileName]
}
writer.save(savePath);
}
export { genCSCode };