<|start_filename|>Assets/Game/Scripts/Editor/XLua/XLuaExportEditor.cs<|end_filename|>
﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
using XLua;
using System.Reflection;
using System.Linq;
using System.IO;
using System.Text;
using LitJson;
using UnityEngine.Advertisements;

namespace Wanderer.GameFramework
{
    /// <summary>
    /// lua导出配置文件
    /// </summary>
    public static class XLuaExportSettings
    {
        private const string _settingName= "XLuaExportSettings.json";
        private const string _assemblyKey = "Assembly";
        private const string _nameSpaceKey = "NameSpace";
        private const string _excludeTypeKey = "ExcludeType";
        private const string _doNotGenKey = "DoNotGen";
        private const string _blackListKey = "BlackList";

        private static JsonData _config;
        public static JsonData Config
        {
            get 
            {
                if (_config == null)
                {
                    _config=ProjectSettingsConfig.LoadJsonData(_settingName);
                    if (_config == null)
                    {
                        _config = new JsonData();
                        //namespace
                        JsonData nsData = new JsonData();
                        nsData.SetJsonType(JsonType.Array);
						foreach (var item in _nameSpaces)
						{
                            nsData.Add(item);
                        }
                        _config[_nameSpaceKey] = nsData;
                        //Assembly
                        JsonData caData = new JsonData();
                        caData.SetJsonType(JsonType.Array);
                        foreach (var item in _customAssemblies)
                        {
                            caData.Add(item);
                        }
                        _config[_assemblyKey] = caData;
                    }
                }
                return _config;
            }
        }

        /// <summary>
        /// 保存数据
        /// </summary>
        public static void Save()
        {
            ProjectSettingsConfig.SaveJsonData(_settingName, Config);
        }

        private static HashSet<string> _nameSpaces = new HashSet<string>()
        {
            "UnityEngine",
            "UnityEngine.UI"
        };
        private static HashSet<string> _customAssemblies = new HashSet<string>() {
            "Assembly-CSharp",
            "GameFramework"
        };

        /// <summary>
        /// 获取所有的命名空间
        /// </summary>
        /// <returns></returns>
        public static List<string> GetNamespaces()
        {
            return GetData(_nameSpaceKey);
        }

        /// <summary>
        /// 获取所有的程序集
        /// </summary>
        /// <returns></returns>
        public static List<string> GetAssemblies()
        {
            return GetData(_assemblyKey);
        }

        /// <summary>
        /// 获取排除在外的类型
        /// </summary>
        /// <returns></returns>
        public static List<string> GetExcludeTypes()
        {
            return GetData(_excludeTypeKey);
        }

        /// <summary>
        /// DoNotGen
        /// </summary>
        /// <returns></returns>
        public static List<string> GetDoNotGen()
        {
            return GetData(_doNotGenKey);
        }

        /// <summary>
        /// BlackList
        /// </summary>
        /// <returns></returns>
        public static List<string> GetBlackList()
        {
            return GetData(_blackListKey);
        }


        /// <summary>
        /// 获取数据
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static List<string> GetData(string key)
        {
            if (Config.Keys.Contains(key))
            {
                List<string> datas = new List<string>();
                JsonData caData = Config[key];
                for (int i = 0; i < caData.Count; i++)
                {
                    datas.Add((string)caData[i]);
                }
                return datas;
            }
            return null;
        }


        /// <summary>
        /// 更新命名空间
        /// </summary>
        /// <param name="data"></param>
        public static void UpdateNamespaces(List<string> data)
        {
            UpdateData(_nameSpaceKey, data);
        }


        /// <summary>
        /// 更新程序集
        /// </summary>
        /// <param name="data"></param>
        public static void UpdateAssemblies(List<string> data)
        {
            UpdateData(_assemblyKey, data);
        }

        /// <summary>
        /// 更新数据
        /// </summary>
        /// <param name="key"></param>
        /// <param name="data"></param>
        public static void UpdateData(string key, List<string> data)
        {
            if (data != null && data.Count > 0)
            {
                JsonData jsonData = Config[key];
                jsonData.Clear();
                foreach (var item in data)
                {
                    jsonData.Add(item);
                }
            }
        }
    }

    public class XLuaExportEditor : EditorWindow
    {
        private Vector2 _nameSpaceScrollPos = Vector2.zero;
        private Vector2 _customScrollPos = Vector2.zero;
        private Vector2 _excludeTypesScrollPos = Vector2.zero;
        private Vector2 _xluaDoNotGenScrollPos = Vector2.zero;
        private Vector2 _xluaBlackListScrollPos = Vector2.zero;
        // 命名空间 自定义程序集
        private HashSet<string> _allUnityNamespaces = new HashSet<string>();
        private List<string> _selectNamespace = new List<string>();
        private HashSet<string> _allCustomAssembly = new HashSet<string>();
        private List<string> _customAssembly = new List<string>();
        //other
        //private List<string> _excludeTypes = new List<string>();
        //private List<string> _doNotGen = new List<string>();
        //private List<string> _blackList = new List<string>();

        //     private List<string> 
        //  private string _newAssembly = "";

        [MenuItem("Tools/XLua Export Editor")]
        static void Main()
        {
            GetWindow<XLuaExportEditor>("XLuaExportEditor");
        }

        void OnEnable()
        {
            _selectNamespace = XLuaExportSettings.GetNamespaces();
            _customAssembly = XLuaExportSettings.GetAssemblies();
            //XLuaExportSettings.GetExcludeTypes();
            //XLuaExportSettings.GetDoNotGen();
            //XLuaExportSettings.GetBlackList();

            _allUnityNamespaces.Clear();
            var unityNamespaces = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
                                   where !(assembly.ManifestModule is System.Reflection.Emit.ModuleBuilder)
                                   from type in assembly.GetExportedTypes()
                                   where type.Namespace != null
                                   select type.Namespace);
            foreach (var item in unityNamespaces)
            {
                _allUnityNamespaces.Add(item);
            }

            // var temp = from assembly in AppDomain.CurrentDomain.GetAssemblies()
            //            where !(assembly.ManifestModule is System.Reflection.Emit.ModuleBuilder) && !assembly.FullName.StartsWith("Unity")
            //            select assembly;

            _allCustomAssembly.Clear();
            var compilationAssemblies = UnityEditor.Compilation.CompilationPipeline.GetAssemblies();
            foreach (var item in compilationAssemblies)
            {
                if (item.flags != UnityEditor.Compilation.AssemblyFlags.EditorAssembly)
                {
                    _allCustomAssembly.Add(item.name);
                }
            }


        }

        void OnDisable()
        {

        }

        void OnGUI()
        {
            //xlua的生成工具
            GUILayout.BeginHorizontal();
            if (GUILayout.Button("Clear Generated Code"))
            {
                CSObjectWrapEditor.Generator.ClearAll();
            }
            if (GUILayout.Button("Generate Code"))
            {
                CSObjectWrapEditor.Generator.GenAll();
            }
            GUILayout.EndHorizontal();
            //保存数据
			GUILayout.BeginHorizontal();
			GUILayout.FlexibleSpace();
			if (GUILayout.Button("Apply", GUILayout.Width(100)))
			{
                XLuaExportSettings.UpdateNamespaces(_selectNamespace);
                XLuaExportSettings.UpdateAssemblies(_customAssembly);
                XLuaExportSettings.Save();
                EditorUtility.DisplayDialog("Tip", "Save data", "OK");
			}
			GUILayout.EndHorizontal();

			GUILayout.BeginVertical();
            //xlua生成筛选
            GUILayout.BeginHorizontal();
            //需要包含的命名空间
            NamespaceDraw();
            //自定义的程序集
            CustomAssemblyDraw();
            GUILayout.EndHorizontal();

           
            GUILayout.BeginHorizontal(GUILayout.Height(Screen.height*0.33f));
            //排除类型
            ExcludeTypesDraw();
            //xlua DoNotGen
            XLuaDoNotGenDraw();
            //xlua BlackList
            XLuaBlackListDraw();
            GUILayout.EndHorizontal();

            GUILayout.EndVertical();
        }

        //需要包含的命名空间
        void NamespaceDraw()
        {
            GUILayout.BeginVertical("helpbox", GUILayout.Width(Screen.width * 0.66f));
            GUILayout.Label("Include Namespace", EditorStyles.boldLabel);
   //         GUILayout.BeginHorizontal();
   //         GUILayout.FlexibleSpace();
			//if (GUILayout.Button("Apply", GUILayout.Width(100)))
			//{
			//	XLuaExportSettings.SaveNamespaces(_selectNamespace);
			//}
			//GUILayout.EndHorizontal();
            _nameSpaceScrollPos = GUILayout.BeginScrollView(_nameSpaceScrollPos, "helpbox");

            foreach (var item in _allUnityNamespaces)
            {
                bool select = _selectNamespace.Contains(item);
                bool result = GUILayout.Toggle(select, item);
                if (select != result)
                {
                    if (result)
                    {
                        _selectNamespace.Add(item);
                    }
                    else
                    {
                        _selectNamespace.Remove(item);
                    }
                }
            }

            GUILayout.EndScrollView();

            GUILayout.EndVertical();
        }


        //自定义的程序集
        void CustomAssemblyDraw()
        {
            GUILayout.BeginVertical("helpbox");
            GUILayout.Label("Custom Assembly", EditorStyles.boldLabel);
            if (_customAssembly != null && _customAssembly.Count > 0)
            {
                //GUILayout.BeginHorizontal();
                //GUILayout.FlexibleSpace();
                //if (GUILayout.Button("Apply", GUILayout.Width(100)))
                //{
                //    XLuaExportSettings.SaveAssembly(_customAssembly);
                //}
                //GUILayout.EndHorizontal();

                _customScrollPos = GUILayout.BeginScrollView(_customScrollPos, "helpbox");

                foreach (var item in _allCustomAssembly)
                {
                    bool select = _customAssembly.Contains(item);
                    bool result = GUILayout.Toggle(select, item);
                    if (select != result)
                    {
                        if (result)
                        {
                            _customAssembly.Add(item);
                        }
                        else
                        {
                            _customAssembly.Remove(item);
                        }
                    }
                }
                GUILayout.EndScrollView();
            }

            GUILayout.EndVertical();
        }

    
        //排除类型
        void ExcludeTypesDraw()
        {
            GUILayout.BeginVertical("helpbox");
            GUILayout.Label("Exclude Types", EditorStyles.boldLabel);
            _excludeTypesScrollPos = GUILayout.BeginScrollView(_excludeTypesScrollPos, "helpbox");
            //    GUILayout.SelectionGrid
            GUILayout.Label("Waiting for development...");
            GUILayout.EndScrollView();

            GUILayout.EndVertical();
        }
        //xlua DoNotGen
        void XLuaDoNotGenDraw()
        {
            GUILayout.BeginVertical("helpbox");
            GUILayout.Label("DoNotGen", EditorStyles.boldLabel);

            _xluaDoNotGenScrollPos = GUILayout.BeginScrollView(_xluaDoNotGenScrollPos, "helpbox");
            GUILayout.Label("Waiting for development...");
            GUILayout.EndScrollView();

            GUILayout.EndVertical();
        }
        //xlua BlackList
        void XLuaBlackListDraw()
        {
            GUILayout.BeginVertical("helpbox");
            GUILayout.Label("Black List", EditorStyles.boldLabel);

            _xluaBlackListScrollPos = GUILayout.BeginScrollView(_xluaBlackListScrollPos, "helpbox");
            GUILayout.Label("Waiting for development...");
            GUILayout.EndScrollView();

            GUILayout.EndVertical();
        }



    }


    /// <summary>
    /// xlua导出配置
    /// </summary>
    public static class XLuaExportConfig
    {
        /***************如果你全lua编程，可以参考这份自动化配置***************/
        //--------------begin 纯lua编程配置参考----------------------------
        static List<string> exclude = new List<string> {
            "HideInInspector", "ExecuteInEditMode",
            "AddComponentMenu", "ContextMenu",
            "RequireComponent", "DisallowMultipleComponent",
            "SerializeField", "AssemblyIsEditorAssembly",
            "Attribute", "Types",
            "UnitySurrogateSelector", "TrackedReference",
            "TypeInferenceRules", "UnityEngine.FFTWindow",
            "RPC", "Network", "MasterServer",
            "BitStream", "HostData",
            "ConnectionTesterStatus", "UnityEngine.GUI", "UnityEngine.EventType",
            "EventModifiers", "FontStyle", "TextAlignment",
            "TextEditor", "TextEditorDblClickSnapping",
            "TextGenerator", "TextClipping", "Gizmos",
            "ADBannerView", "ADInterstitialAd",
            "Android", "Tizen", "jvalue",
            "iPhone", "iOS", "Windows", "CalendarIdentifier",
            "CalendarUnit", "CalendarUnit",
            "ClusterInput", "FullScreenMovieControlMode",
            "FullScreenMovieScalingMode", "Handheld",
            "LocalNotification", "NotificationServices",
            "RemoteNotificationType", "RemoteNotification",
            "SamsungTV", "TextureCompressionQuality",
            "TouchScreenKeyboardType", "TouchScreenKeyboard",
            "MovieTexture", "UnityEngineInternal",
            "Terrain", "Tree", "SplatPrototype",
            "DetailPrototype", "DetailRenderMode",
            "MeshSubsetCombineUtility", "AOT", "Social", "Enumerator",
            "SendMouseEvents", "Cursor", "Flash", "ActionScript",
            "OnRequestRebuild", "Ping",
            "ShaderVariantCollection", "SimpleJson.Reflection",
            "CoroutineTween", "GraphicRebuildTracker",
            "Advertisements", "UnityEditor", "WSA",
            "EventProvider", "Apple",
            "ClusterInput", "Motion",
            "UnityEngine.UI.ReflectionMethodsCache", "NativeLeakDetection",
            "NativeLeakDetectionMode", "WWWAudioExtensions", "UnityEngine.Experimental",
            "EditorAssetsHelper","UnityEngine.CanvasRenderer.OnRequestRebuild","EditorCall"
        };

        //是否属于当前的类
        static bool isExcluded(Type type)
        {
            var fullName = type.FullName==null? type.Name: type.FullName;
            for (int i = 0; i < exclude.Count; i++)
            {
                if (fullName.Contains(exclude[i]))
                {
                    return true;
                }
            }
            return false;
        }

        [LuaCallCSharp]
        public static IEnumerable<Type> LuaCallCSharp
        {
            get
            {
                // List<string> namespaces = new List<string>() // 在这里添加名字空间
                // {
                //     "UnityEngine",
                //     "UnityEngine.UI"
                // };
                List<string> namespaces = XLuaExportSettings.GetNamespaces();
                var unityTypes = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
                                  where !(assembly.ManifestModule is System.Reflection.Emit.ModuleBuilder)
                                  from type in assembly.GetExportedTypes()
                                  where (type.Namespace != null && namespaces.Contains(type.Namespace)) && !isExcluded(type)
                                          && type.BaseType != typeof(MulticastDelegate) && !type.IsInterface && !type.IsEnum
                                  select type);

                // string[] customAssemblys = new string[] {
                //     "Assembly-CSharp",
                //     "GameFramework",
                //     "Libraries",
                // };

                List<string> customAssemblys = XLuaExportSettings.GetAssemblies();
                var customTypes = (from assembly in customAssemblys.Select(s => Assembly.Load(s))
                                   from type in assembly.GetExportedTypes()
                                   where (type.Namespace == null || !type.Namespace.StartsWith("XLua")) && !isExcluded(type)
                                         && type.BaseType != typeof(MulticastDelegate)
                                   select type);
                return unityTypes.Concat(customTypes);
            }
        }

        //自动把LuaCallCSharp涉及到的delegate加到CSharpCallLua列表，后续可以直接用lua函数做callback
        [CSharpCallLua]
        public static List<Type> CSharpCallLua
        {
            get
            {
                var lua_call_csharp = LuaCallCSharp;
                var delegate_types = new List<Type>();
                var flag = BindingFlags.Public | BindingFlags.Instance
                    | BindingFlags.Static | BindingFlags.IgnoreCase | BindingFlags.DeclaredOnly;
                foreach (var field in (from type in lua_call_csharp select type).SelectMany(type => type.GetFields(flag)))
                {
                    if (typeof(Delegate).IsAssignableFrom(field.FieldType) && !isExcluded(field.FieldType))
                    {
                        delegate_types.Add(field.FieldType);
                    }
                }

                foreach (var method in (from type in lua_call_csharp select type).SelectMany(type => type.GetMethods(flag)))
                {
                    if (typeof(Delegate).IsAssignableFrom(method.ReturnType) && !isExcluded(method.ReturnType))
                    {
                        delegate_types.Add(method.ReturnType);
                    }
                    foreach (var param in method.GetParameters())
                    {
                        var paramType = param.ParameterType.IsByRef ? param.ParameterType.GetElementType() : param.ParameterType;

                        if (typeof(Delegate).IsAssignableFrom(paramType) && !isExcluded(paramType))
                        {
                            delegate_types.Add(paramType);
                        }
                    }
                }
                return delegate_types.Where(t => t.BaseType == typeof(MulticastDelegate) && !hasGenericParameter(t) && !delegateHasEditorRef(t)).Distinct().ToList();
            }
        }

        // CSharpCallLua 静态列表
		[CSharpCallLua]
		public static List<Type> CSharpCallLuaAction = new List<Type>() {
				typeof(Action),
				typeof(Action<int>),
				typeof(Action<float>),
				typeof(Action<double>),
                typeof(Action<string>),
                typeof(Action<Vector2>),
				typeof(Action<Vector3>),
                typeof(Action<ShowResult>),
                typeof(Action<RectTransform>),
				typeof(UnityEngine.Events.UnityAction),
				typeof(UnityEngine.Events.UnityAction<int>),
				typeof(UnityEngine.Events.UnityAction<float>),
				typeof(UnityEngine.Events.UnityAction<double>),
                typeof(UnityEngine.Events.UnityAction<string>),
                typeof(UnityEngine.Events.UnityAction<Vector2>),
				typeof(UnityEngine.Events.UnityAction<Vector3>),
				typeof(System.Collections.IEnumerator),
	};

    // LuaCallCsharp 静态列表
    [LuaCallCSharp]
    public static List<Type> LuaCallCSharpTypes = new List<Type>() {
            typeof(System.DateTime)
    };

        [DoNotGen]
    public static Dictionary<Type, List<string>> XLuaDoNotGen
    {
		get
		{
            Dictionary<Type, List<string>> dtl = new Dictionary<Type, List<string>>();
            //dtl.Add(typeof(UnityEngine.CanvasRenderer), new List<string>() { "OnRequestRebuild", "onRequestRebuild" });
            return dtl;
        }
    }

        //--------------end 纯lua编程配置参考----------------------------

        /***************热补丁可以参考这份自动化配置***************/
        //[Hotfix]
        //static IEnumerable<Type> HotfixInject
        //{
        //    get
        //    {
        //        return (from type in Assembly.Load("Assembly-CSharp").GetTypes()
        //                where type.Namespace == null || !type.Namespace.StartsWith("XLua")
        //                select type);
        //    }
        //}
        //--------------begin 热补丁自动化配置-------------------------
        static bool hasGenericParameter(Type type)
        {
            if (type.IsGenericTypeDefinition) return true;
            if (type.IsGenericParameter) return true;
            if (type.IsByRef || type.IsArray)
            {
                return hasGenericParameter(type.GetElementType());
            }
            if (type.IsGenericType)
            {
                foreach (var typeArg in type.GetGenericArguments())
                {
                    if (hasGenericParameter(typeArg))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        static bool typeHasEditorRef(Type type)
        {
            if (type.Namespace != null && (type.Namespace == "UnityEditor" || type.Namespace.StartsWith("UnityEditor.")))
            {
                return true;
            }
            if (type.IsNested)
            {
                return typeHasEditorRef(type.DeclaringType);
            }
            if (type.IsByRef || type.IsArray)
            {
                return typeHasEditorRef(type.GetElementType());
            }
            if (type.IsGenericType)
            {
                foreach (var typeArg in type.GetGenericArguments())
                {
                    if (typeHasEditorRef(typeArg))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        static bool delegateHasEditorRef(Type delegateType)
        {
            if (typeHasEditorRef(delegateType)) return true;
            var method = delegateType.GetMethod("Invoke");
            if (method == null)
            {
                return false;
            }
            if (typeHasEditorRef(method.ReturnType)) return true;
            return method.GetParameters().Any(pinfo => typeHasEditorRef(pinfo.ParameterType));
        }

        // 配置某Assembly下所有涉及到的delegate到CSharpCallLua下，Hotfix下拿不准那些delegate需要适配到lua function可以这么配置
        //[CSharpCallLua]
        //static IEnumerable<Type> AllDelegate
        //{
        //    get
        //    {
        //        BindingFlags flag = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
        //        List<Type> allTypes = new List<Type>();
        //        var allAssemblys = new Assembly[]
        //        {
        //            Assembly.Load("Assembly-CSharp")
        //        };
        //        foreach (var t in (from assembly in allAssemblys from type in assembly.GetTypes() select type))
        //        {
        //            var p = t;
        //            while (p != null)
        //            {
        //                allTypes.Add(p);
        //                p = p.BaseType;
        //            }
        //        }
        //        allTypes = allTypes.Distinct().ToList<string>;
        //        var allMethods = from type in allTypes
        //                         from method in type.GetMethods(flag)
        //                         select method;
        //        var returnTypes = from method in allMethods
        //                          select method.ReturnType;
        //        var paramTypes = allMethods.SelectMany(m => m.GetParameters()).Select(pinfo => pinfo.ParameterType.IsByRef ? pinfo.ParameterType.GetElementType() : pinfo.ParameterType);
        //        var fieldTypes = from type in allTypes
        //                         from field in type.GetFields(flag)
        //                         select field.FieldType;
        //        return (returnTypes.Concat(paramTypes).Concat(fieldTypes)).Where(t => t.BaseType == typeof(MulticastDelegate) && !hasGenericParameter(t) && !delegateHasEditorRef(t)).Distinct();
        //    }
        //}
        //--------------end 热补丁自动化配置-------------------------


        //黑名单
        [BlackList]
        public static List<List<string>> BlackList  {
            get
            {
                List<List<string>> bl = new List<List<string>>()  
                {
                    new List<string>{"UnityEngine.UI.Text", "OnRebuildRequested"},
                    new List<string>{"UnityEngine.UI.Graphic", "OnRebuildRequested"},
                    new List<string>{"UnityEngine.AnimatorControllerParameter", "name"},
                    new List<string>{"UnityEngine.AudioSettings", "GetSpatializerPluginNames"},
                    new List<string>{"UnityEngine.AudioSettings", "SetSpatializerPluginName", "System.String"},
                    new List<string>{"UnityEngine.DrivenRectTransformTracker", "StopRecordingUndo"},
                    new List<string>{"UnityEngine.DrivenRectTransformTracker", "StartRecordingUndo"},
                    new List<string>{"UnityEngine.Caching", "SetNoBackupFlag", "UnityEngine.CachedAssetBundle"},
                    new List<string>{"UnityEngine.Caching", "ResetNoBackupFlag", "UnityEngine.CachedAssetBundle"},
                    new List<string>{"UnityEngine.Caching", "SetNoBackupFlag", "System.String", "UnityEngine.Hash128"},
                    new List<string>{"UnityEngine.Caching", "ResetNoBackupFlag", "System.String", "UnityEngine.Hash128"},
                    new List<string>{"UnityEngine.Input", "IsJoystickPreconfigured", "System.String"},
                    new List<string>{"UnityEngine.LightProbeGroup", "dering"},
                    new List<string>{"UnityEngine.LightProbeGroup", "probePositions"},
                    new List<string>{"UnityEngine.Light", "SetLightDirty"},
                    new List<string>{"UnityEngine.Light", "shadowRadius"},
                    new List<string>{"UnityEngine.Light", "shadowAngle"},
                    new List<string>{"UnityEngine.ParticleSystemForceField", "FindAll"},
                    new List<string>{"UnityEngine.QualitySettings", "streamingMipmapsRenderersPerFrame"},
                    new List<string>{"UnityEngine.Texture", "imageContentsHash"},
                    new List<string>{ "UnityEngine.AssetBundle", "SetAssetBundleDecryptKey" ,"System.String"},
                    new List<string>{ "UnityEngine.BuildCompression", "enableProtect" },
                    new List<string>{ "UnityEngine.MeshRenderer", "scaleInLightmap" },
                    new List<string>{ "UnityEngine.MeshRenderer", "receiveGI" },
                    new List<string>{ "UnityEngine.MeshRenderer", "stitchLightmapSeams" },
                    new List<string>{ "UnityEngine.ParticleSystemRenderer", "supportsMeshInstancing" },
                    new List<string>{ "UnityEngine.UI.DefaultControls", "factory" },
                    new List<string>(){ "RenderHeads.Media.AVProVideo.MediaPlayer", "SaveFrameToPng"},
                    new List<string>(){ "RenderHeads.Media.AVProVideo.MediaPlayer", "GetPlatformOptions","RenderHeads.Media.AVProVideo.Platform"},
					new List<string>(){ "RenderHeads.Media.AVProVideo.MediaPlayer", "GetPlatformOptionsVariable", "RenderHeads.Media.AVProVideo.Platform"},
					new List<string>(){ "RenderHeads.Media.AVProVideo.MediaPlayer", "GetPath", "RenderHeads.Media.AVProVideo.MediaPlayer.FileLocation"},
					new List<string>(){ "RenderHeads.Media.AVProVideo.MediaPlayer", "GetFilePath", "System.String", "RenderHeads.Media.AVProVideo.MediaPlayer.FileLocation"},
					new List<string>(){ "Wanderer.GameFramework.MathLevelItem", "LevelItem"},
					new List<string>(){ "Wanderer.GameFramework.MathLevelItem", "newStr"},
					new List<string>(){ "Wanderer.GameFramework.MathLevelItem", "newTypeName"},
					new List<string>(){ "Wanderer.GameFramework.MathLevelItem", "typeNameOne"},
                };
                return bl;
            }
        }

    }
}


<|start_filename|>Assets/Game/Scripts/XLua/LuaBehaviour.cs<|end_filename|>
﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;

namespace Wanderer.GameFramework
{
    public class LuaBehaviour : MonoBehaviour
    {
        [SerializeField]
        private TextAsset _luaScript;

        [SerializeField]
        private UnityEngine.Object[] _injections;

        private Action _luaOnStart;
        private Action _luaOnDestroy;
        private Action _luaOnUpdate;
        private Action _luaOnEnable;
        private Action _luaOnDisable;

        private LuaTable _scriptEnv;

        public Action<string> OnLuaCallCSharp;


		private void Awake()
		{
            //创建table
            _scriptEnv = GameMode.XLua.NewTable(this);
            //外部参数
            foreach (var item in _injections)
			{
                _scriptEnv.Set(item.name, item);
            }
            //运行lua脚本
            GameMode.XLua.DoString(_luaScript.text,$"LuaBehaviour_{name}_{_luaScript.name}", _scriptEnv);
            //事件回调
            Action luaOnAwake = _scriptEnv.Get<Action>("OnAwake");
            _scriptEnv.Get("OnStart", out _luaOnStart);
            _scriptEnv.Get("OnDestroy", out _luaOnDestroy);
            _scriptEnv.Get("OnUpdate", out _luaOnUpdate);
            _scriptEnv.Get("OnEnable", out _luaOnEnable);
            _scriptEnv.Get("OnDisable", out _luaOnDisable);

            //初始画回调
            luaOnAwake?.Invoke();
        }

		// Start is called before the first frame update
		void Start()
        {
          //  GetComponent<RenderHeads.Media.AVProVideo.MediaPlayer>().OpenVideoFromFile(RenderHeads.Media.AVProVideo.MediaPlayer.FileLocation.RelativeToStreamingAssetsFolder,true);
            _luaOnStart?.Invoke();
        }

        // Update is called once per frame
        void Update()
        {
            _luaOnUpdate?.Invoke();
        }

		private void OnDisable()
		{
            _luaOnDisable?.Invoke();
        }
		private void OnEnable()
		{
            _luaOnEnable?.Invoke();
        }

		private void OnDestroy()
		{
            OnLuaCallCSharp = null;
            _luaOnUpdate = null;
            _luaOnStart = null;
            _luaOnEnable = null;
            _luaOnDisable = null;
            _luaOnDestroy?.Invoke();
            _luaOnDestroy = null;
        }

        /// <summary>
        /// lua 调用 csharp
        /// </summary>
        /// <param name="data"></param>
        public void LuaCallCSharp(string data)
        {
            OnLuaCallCSharp?.Invoke(data);
        }
    }
}

<|start_filename|>Assets/Game/Scripts/MiniGame/Kingdoms/KingdomsUnityEditor.cs<|end_filename|>
﻿#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;

namespace Wanderer.GameFramework
{
    public class KingdomsUnityEditor : MonoBehaviour
    {
        public KingdomsConfig Config;

        public int SelectLevel = -1;

        public bool ShowBgRuntime = true;

        // public string DynamicSpritePath { get; private set; } = $"Assets/Game/MiniGames/KingdomsUIView/DynamicSprite";
        //prefab
        public string DynamicPrafabPath { get; private set; } = $"Assets/Game/MiniGames/KingdomsUIView/Prefabs";


        private void Start()
        {
            if (ShowBgRuntime)
            {
                var bgGO = new GameObject("BG").AddComponent<RectTransform>();
                bgGO.transform.SetParent(transform.parent);
                bgGO.transform.localScale = Vector3.one;
                bgGO.transform.localPosition = Vector3.zero;
                bgGO.transform.SetAsFirstSibling();
                bgGO.anchoredPosition3D = Vector3.zero;
                var gridLayout = bgGO.gameObject.AddComponent<GridLayoutGroup>();
                gridLayout.cellSize = Vector2.one * Config.Size;
                gridLayout.childAlignment = TextAnchor.MiddleCenter;
                gridLayout.constraint = GridLayoutGroup.Constraint.FixedColumnCount;
                gridLayout.constraintCount = Config.Column;
                int size = Config.Row * Config.Column;
                for (int i = 0; i < Config.Row; i++)
                {
                    for (int j = 0; j < Config.Column; j++)
                    {
                        GameObject bgItem = new GameObject($"{i}_{j}");
                        bgItem.transform.SetParent(bgGO);
                        bgItem.transform.localScale = Vector3.one;
                        bgItem.transform.localPosition = Vector3.zero;
                        bgItem.AddComponent<Image>();
                        var outline = bgItem.AddComponent<Outline>();
                        outline.effectDistance = Vector2.one * 5;
                        outline.effectColor = Color.black;
                    }
                }
            }
        }

        private void OnValidate()
        {
            Resize();
        }

        private void OnDrawGizmos()
        {
            if(EditorApplication.isPlaying)
            return;

            //外框
            Gizmos.color = Color.green;
            var bounds = GetComponent<RectTransform>().GetBounds();
            Gizmos.DrawWireCube(bounds.center, bounds.size);
            //分割线
            Vector3 miniPoint = bounds.center - bounds.size * 0.5f;
            float hightInterval = bounds.size.y / (float)Config.Row;
            for (int i = 0; i < Config.Row; i++)
            {
                Vector3 startPos = miniPoint + new Vector3(0, i * hightInterval, 0);
                Vector3 endPos = miniPoint + new Vector3(bounds.size.x, i * hightInterval, 0);
                Gizmos.DrawLine(startPos, endPos);
            }
            float widthInterval = bounds.size.x / (float)Config.Column;
            for (int i = 0; i < Config.Column; i++)
            {
                Vector3 startPos = miniPoint + new Vector3(i * widthInterval, 0, 0);
                Vector3 endPos = miniPoint + new Vector3(i * widthInterval, bounds.size.y, 0);
                Gizmos.DrawLine(startPos, endPos);
            }
            //绘制组件
            Vector2 cellInterval = new Vector2(widthInterval, hightInterval);
            if (SelectLevel >= 0 && SelectLevel < Config.Levels.Count)
            {
                Gizmos.color = Color.red;
                var levelConfig = Config.Levels[SelectLevel];
                foreach (var item in levelConfig.Items)
                {
                    Vector3 center = miniPoint + (Vector3)((item.Point + Vector2.one * 0.5f) * cellInterval);
                    Vector3 size = item.Size * cellInterval;
                    Gizmos.DrawWireCube(center, size);
                    //prefab
                    string prefabPath = GetPrafabPath(item.Sprite);
                    GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
                    //prefab
                    if (prefab != null)
                    {
                        Vector2 texturePoint = new Vector2(center.x - size.x * 0.5f, center.y - size.y * 0.5f);
                        Rect textureRect = new Rect(texturePoint, size);
                        Sprite sprite = prefab.transform.Find("Image").GetComponent<Image>().sprite;
                        Gizmos.DrawGUITexture(textureRect, sprite.texture);
                    }
                }
            }
        }

        public void Resize()
        {
            Vector2 halfOne = Vector2.one * 0.5f;
            RectTransform targetRectTrans = GetComponent<RectTransform>();
            targetRectTrans.anchorMin = halfOne;
            targetRectTrans.anchorMax = halfOne;
            targetRectTrans.pivot = halfOne;
            targetRectTrans.localScale = Vector3.one;
            targetRectTrans.localRotation = Quaternion.identity;
            targetRectTrans.anchoredPosition = Vector2.zero;
            targetRectTrans.sizeDelta = new Vector2(Config.Size * Config.Column, Config.Size * Config.Row);
        }

        //prefab
        public string GetPrafabPath(string praFabName)
        {
            string prefabPath = $"{DynamicPrafabPath}/{praFabName}.prefab";
            return prefabPath;
        }
        [System.Serializable]
        public struct KingdomsConfig
        {
            /// <summary>
            /// 大小
            /// </summary>
            public int Size;
            /// <summary>
            /// 行数
            /// </summary>
            public int Row;
            /// <summary>
            /// 列数
            /// </summary>
            public int Column;
            /// <summary>
            /// 关卡信息
            /// </summary>
            public List<KingdomsLevelConfig> Levels;
        }

        [System.Serializable]
        public struct KingdomsLevelConfig
        {
            /// <summary>
            /// 关卡名称
            /// </summary>
            public string LevelName;
            /// <summary>
            /// 角色组件
            /// </summary>
            public string Player;
            /// <summary>
            /// 胜利组件
            /// </summary>
            public string Victory;
            /// <summary>
            /// 组件
            /// </summary>
            public List<KingdomsLevelItemConfig> Items;
        }

        [System.Serializable]
        public struct KingdomsLevelItemConfig
        {
            public string Name;
            public string Sprite;
            public Vector2 Size;
            public Vector2 Point;
        }

    }

    [CustomEditor(typeof(KingdomsUnityEditor))]
    public class KingdomsUnityEditorWindowsEditor : Editor
    {
        KingdomsUnityEditor _target;
        private const string _configPath = "Assets/Game/MiniGames/KingdomsUIView/Config/config.txt";
        private string[] _prefabNames;
        public void OnEnable()
        {
            _target = (KingdomsUnityEditor)target;
            var prefabGuids = AssetDatabase.FindAssets("t:Prefab", new string[] { _target.DynamicPrafabPath });
            if (prefabGuids != null && prefabGuids.Length > 0)
            {
                _prefabNames = new string[prefabGuids.Length];
                for (int i = 0; i < prefabGuids.Length; i++)
                {
                    string spriteName = AssetDatabase.GUIDToAssetPath(prefabGuids[i]);
                    spriteName = Path.GetFileNameWithoutExtension(spriteName);
                    _prefabNames[i] = (spriteName);
                }
            }
            var configText = AssetDatabase.LoadAssetAtPath<TextAsset>(_configPath);
            if (configText != null)
            {
                _target.Config = JsonUtility.FromJson<KingdomsUnityEditor.KingdomsConfig>(configText.text);
                if (_target.Config.Levels.Count > 0)
                {
                    if (_target.SelectLevel == -1)
                    {
                        _target.SelectLevel = 0;
                    }
                }
                else
                {
                    _target.SelectLevel = -1;
                }
            }
            else
            {
                _target.Config.Size = 200;
                _target.Config.Row = 4;
                _target.Config.Column = 7;
                _target.SelectLevel = -1;
                SaveData();
            }
            _target.Resize();
        }



        public override void OnInspectorGUI()
        {
            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Apply", GUILayout.Width(60)))
            {
                //bool save = true;
                //foreach (var item in _target.Config.Levels)
                //{
                //	if (string.IsNullOrEmpty(item.LevelName))
                //	{
                //		save = false;
                //		EditorUtility.DisplayDialog("保证关卡")
                //	}
                //}
                SaveData();
                EditorUtility.DisplayDialog("保存数据", "保存数据", "ok");
            }
            GUILayout.EndHorizontal();

            GUILayout.BeginVertical("helpbox");
            GUILayout.Label("全局配置", EditorStyles.boldLabel);
            _target.Config.Size = EditorGUILayout.IntField("单位大小", _target.Config.Size);
            _target.Config.Row = EditorGUILayout.IntField("行数", _target.Config.Row);
            _target.Config.Column = EditorGUILayout.IntField("列数", _target.Config.Column);
            bool showBg = EditorGUILayout.Toggle("运行时显示背景", _target.ShowBgRuntime);
            if (showBg != _target.ShowBgRuntime)
            {
                _target.ShowBgRuntime = showBg;
                EditorUtility.SetDirty(_target);
            }
            GUILayout.EndVertical();

            GUILayout.BeginVertical("helpbox");
            GUILayout.Label($"关卡配置 ({_target.SelectLevel + 1}/{_target.Config.Levels.Count})", EditorStyles.boldLabel);
            if (_target.Config.Levels.Count > 0)
            {
                if (_target.SelectLevel < 0 || _target.SelectLevel >= _target.Config.Levels.Count)
                {
                    _target.SelectLevel = 0;
                    EditorUtility.SetDirty(_target);
                    //return;
                }

                string[] levelNames = new string[_target.Config.Levels.Count];
                for (int i = 0; i < _target.Config.Levels.Count; i++)
                {
                    levelNames[i] = _target.Config.Levels[i].LevelName;
                }
                int selectLevel = EditorGUILayout.Popup("选择关卡", _target.SelectLevel, levelNames);
                if (selectLevel != _target.SelectLevel)
                {
                    _target.SelectLevel = selectLevel;
                    EditorUtility.SetDirty(_target);
                }


                var levelConfig = _target.Config.Levels[_target.SelectLevel];

                GUILayout.BeginVertical("Box");
                levelConfig.LevelName = EditorGUILayout.TextField("关卡名称", levelConfig.LevelName);
                //删除当前关卡
                GUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                if (GUILayout.Button("删除当前关卡", GUILayout.Width(100)))
                {
                    if (EditorUtility.DisplayDialog("警告", $"是否删除当前关卡:{levelConfig.LevelName}", "ok", "cancel"))
                    {
                        _target.Config.Levels.RemoveAt(_target.SelectLevel);
                        //_target.SelectLevel--;
                        GUIUtility.ExitGUI();
                        return;
                    }
                }
                GUILayout.EndHorizontal();
                //渲染组件
                if (levelConfig.Items != null && levelConfig.Items.Count > 0)
                {
                    int playerItem = -1;
                    int victoryItem = -1;
                    string[] itemNames = new string[levelConfig.Items.Count];
                    for (int i = 0; i < levelConfig.Items.Count; i++)
                    {
                        itemNames[i] = levelConfig.Items[i].Name;
                        if (itemNames[i].Equals(levelConfig.Player))
                        {
                            playerItem = i;
                        }
                        if (itemNames[i].Equals(levelConfig.Victory))
                        {
                            victoryItem = i;
                        }
                    }
                    int newItem = EditorGUILayout.Popup("角色组件", playerItem, itemNames);
                    if (newItem != playerItem && newItem >= 0)
                    {
                        if (newItem < itemNames.Length)
                            levelConfig.Player = itemNames[newItem];
                    }
                    newItem = EditorGUILayout.Popup("胜利组件", victoryItem, itemNames);
                    if (newItem != playerItem && newItem >= 0)
                    {
                        if (newItem < itemNames.Length)
                            levelConfig.Victory = itemNames[newItem];
                    }

                    GUILayout.Label($"组件 ({levelConfig.Items.Count})");
                    for (int i = 0; i < levelConfig.Items.Count; i++)
                    {
                        GUILayout.BeginHorizontal();
                        GUILayout.FlexibleSpace();
                        if (GUILayout.Button("x", GUILayout.Width(30)))
                        {
                            if (EditorUtility.DisplayDialog("警告", $"是否删除当前组件:{levelConfig.Items[i].Name}", "ok", "cancel"))
                            {
                                _target.Config.Levels[_target.SelectLevel].Items.RemoveAt(i);
                                //levelConfig.Items.RemoveAt(i);
                               
                                GUIUtility.ExitGUI();
                                return;
                            }
                        }
                        GUILayout.EndHorizontal();
                        levelConfig.Items[i] = DrawLevelItem(levelConfig.Items[i]);
                    }
                }
                if (GUILayout.Button("添加组件"))
                {
                    if (levelConfig.Items == null)
                    {
                        levelConfig.Items = new List<KingdomsUnityEditor.KingdomsLevelItemConfig>();
                    }
                    KingdomsUnityEditor.KingdomsLevelItemConfig itemConfig;
                    if (levelConfig.Items.Count > 0)
                    {
                        itemConfig = levelConfig.Items[levelConfig.Items.Count - 1];
                    }
                    else
                    {
                        itemConfig = new KingdomsUnityEditor.KingdomsLevelItemConfig();
                    }
                    itemConfig.Name = System.Guid.NewGuid().ToString().Substring(0, 6);
                    levelConfig.Items.Add(itemConfig);
                }
                GUILayout.EndVertical();

                _target.Config.Levels[_target.SelectLevel] = levelConfig;
            }
            if (GUILayout.Button("添加关卡"))
            {
                KingdomsUnityEditor.KingdomsLevelConfig levelConfig;
                if (_target.Config.Levels.Count > 0)
                {
                    levelConfig = _target.Config.Levels[_target.Config.Levels.Count - 1];
                }
                else
                {
                    levelConfig = new KingdomsUnityEditor.KingdomsLevelConfig();
                }
                levelConfig.LevelName = System.Guid.NewGuid().ToString().Substring(0, 10);
                _target.Config.Levels.Add(levelConfig);
                _target.SelectLevel = _target.Config.Levels.Count - 1;
            }
            GUILayout.EndVertical();
            //base.OnInspectorGUI();

            
            if (GUILayout.Button("Apply", GUILayout.Width(60)))
            {
                //bool save = true;
                //foreach (var item in _target.Config.Levels)
                //{
                //	if (string.IsNullOrEmpty(item.LevelName))
                //	{
                //		save = false;
                //		EditorUtility.DisplayDialog("保证关卡")
                //	}
                //}
                SaveData();
                EditorUtility.DisplayDialog("保存数据", "保存数据", "ok");
            }
        }



        //绘制小组件
        private KingdomsUnityEditor.KingdomsLevelItemConfig DrawLevelItem(KingdomsUnityEditor.KingdomsLevelItemConfig itemConfig)
        {
            if (_prefabNames == null)
                return itemConfig;
            GUILayout.BeginHorizontal("box");
            GUILayout.BeginVertical();

            itemConfig.Name = EditorGUILayout.TextField("名称", itemConfig.Name);
            int selectSprite = -1;
            if (_prefabNames != null)
            {
                for (int i = 0; i < _prefabNames.Length; i++)
                {
                    if (_prefabNames[i].Equals(itemConfig.Sprite))
                    {
                        selectSprite = i;
                        break;
                    }
                }
            }

            int newSelectSprite = EditorGUILayout.Popup("图片", selectSprite, _prefabNames);
            if (newSelectSprite != selectSprite)
            {
                itemConfig.Sprite = _prefabNames[newSelectSprite];
            }


            //itemConfig.Sprite = EditorGUILayout.TextField("图片",itemConfig.Sprite);
            itemConfig.Size = EditorGUILayout.Vector2Field("大小", itemConfig.Size);
            itemConfig.Point = EditorGUILayout.Vector2Field("位置", itemConfig.Point);
            GUILayout.EndVertical();


            int iconSize = 100;
            string prefabPath = _target.GetPrafabPath(itemConfig.Sprite);
            GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
            if (prefab != null)
            {
                GUILayout.Label("", GUILayout.Width(iconSize), GUILayout.Height(iconSize));
                Rect lastRect = GUILayoutUtility.GetLastRect();
                GUI.DrawTexture(new Rect(lastRect.position, Vector2.one * iconSize), prefab.transform.Find("Image").GetComponent<Image>().sprite.texture, ScaleMode.ScaleToFit);
            }
            GUILayout.EndHorizontal();
            return itemConfig;
        }

        //保存数据
        private void SaveData()
        {
            string configContent = JsonUtility.ToJson(_target.Config);
            File.WriteAllText(_configPath, configContent);
            AssetDatabase.Refresh();
        }

    }

}
#endif

<|start_filename|>ProjectSettings/AssetBundleEditor.json<|end_filename|>
[{"AssetBundleName":"DataTable","Annotation":"","Variant":"","Filter":131072,"SearchInFolders":["Assets/Game/DataTable"],"Split":false,"SplitCount":1,"ForceUpdate":true,"Preload":false},{"AssetBundleName":"updateview","Annotation":"","Variant":"","Filter":1024,"SearchInFolders":["Assets/Game/Update"],"Split":false,"SplitCount":1,"ForceUpdate":true,"Preload":false},{"AssetBundleName":"XLua","Annotation":"","Variant":"","Filter":131072,"SearchInFolders":["Assets/Game/XLua"],"Split":false,"SplitCount":1,"ForceUpdate":true,"Preload":false},{"AssetBundleName":"UIView","Annotation":"","Variant":"","Filter":1024,"SearchInFolders":["Assets/Game/UI"],"Split":false,"SplitCount":1,"ForceUpdate":true,"Preload":false},{"AssetBundleName":"GoBangForm","Variant":"","Filter":17410,"Split":false,"SplitCount":1,"ForceUpdate":false,"Preload":false,"SearchInFolders":["Assets/Game/MiniGames/GoBangForm"],"Annotation":"\u4E94\u5B50\u68CB"},{"AssetBundleName":"KingdomsUIView","Variant":"","Filter":148482,"Split":false,"SplitCount":1,"ForceUpdate":false,"Preload":false,"SearchInFolders":["Assets/Game/MiniGames/KingdomsUIView"],"Annotation":"\u534E\u5BB9\u9053"},{"AssetBundleName":"GameIcons","Annotation":"\u6E38\u620F\u56FE\u6807","Variant":"","Filter":32768,"SearchInFolders":["Assets/Game/Texture/Icon_MiniGames"],"Split":false,"SplitCount":1,"ForceUpdate":true,"Preload":false},{"AssetBundleName":"Tetris","Variant":"","Filter":17410,"Split":false,"SplitCount":1,"ForceUpdate":false,"Preload":false,"SearchInFolders":["Assets/Game/MiniGames/Tetris"],"Annotation":"\u4FC4\u7F57\u65AF\u65B9\u5757"},{"AssetBundleName":"CrazyCards","Variant":"","Filter":148482,"Split":false,"SplitCount":1,"ForceUpdate":false,"Preload":false,"SearchInFolders":["Assets/Game/MiniGames/CrazyCards"],"Annotation":"\u75AF\u72C2\u5361\u724C"},{"AssetBundleName":"Watermelon","Annotation":"\u5408\u6210\u5927\u897F\u74DC","Variant":"","Filter":17410,"Split":false,"SplitCount":1,"ForceUpdate":false,"Preload":false,"SearchInFolders":["Assets/Game/MiniGames/Watermelon"]},{"AssetBundleName":"Audio","Annotation":"","Variant":"","Filter":1026,"SearchInFolders":["Assets/Game/Audio"],"Split":false,"SplitCount":1,"ForceUpdate":true,"Preload":false},{"AssetBundleName":"RubikCube","Variant":"","Filter":17410,"Split":false,"SplitCount":1,"ForceUpdate":false,"Preload":false,"SearchInFolders":["Assets/Game/MiniGames/RubikCube"],"Annotation":"\u9B54\u65B9"},{"AssetBundleName":"GuessColor","Annotation":"\u731C\u989C\u8272","Variant":"","Filter":17474,"Split":false,"SplitCount":1,"ForceUpdate":false,"Preload":false,"SearchInFolders":["Assets/Game/MiniGames/GuessColor"]}]

<|start_filename|>Assets/Game/Scripts/Extension/UGUIExtension.cs<|end_filename|>
﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Wanderer.GameFramework;
using UnityEngine.EventSystems;
using UnityEngine.Events;

public static class UGUIExtension
{
    public static Toggle GetToggle(this Transform transform, string toggleName)
    {
        Transform[] allTransform =TransformExtension.GetAllTransform(transform);
        for (int i = 0; i < allTransform.Length; i++)
        {
            Transform item = allTransform[i];
            if (item.name == toggleName)
            {
                return item.GetComponent<Toggle>();
            }
        }
        return null;
    }
    //设置精灵图片。
    public static void SetSprite(this UnityEngine.UI.Image img, string name)
    {
        GameMode.Resource.Asset.LoadAsset<Sprite>(name, (sprite) =>
        {
            img.sprite = sprite;
        });
    }
    public static InputField GetInput(this Transform transform, string name)
    {
        Transform[] allTransform =TransformExtension.GetAllTransform(transform);
        for (int i = 0; i < allTransform.Length; i++)
        {
            Transform item = allTransform[i];
            if (item.name == name)
            {
                return item.GetComponent<InputField>();
            }
        }
        return null;
    }

    public static RawImage GetRawImg(this Transform transform, string name)
    {
        Transform[] allTransform =TransformExtension.GetAllTransform(transform);
        for (int i = 0; i < allTransform.Length; i++)
        {
            Transform item = allTransform[i];
            if (item.name == name)
            {
                return item.GetComponent<RawImage>();
            }
        }
        return null;
    }

    public static Slider GetSlider(this Transform transform, string name)
    {
        Transform[] allTransform =TransformExtension.GetAllTransform(transform);
        for (int i = 0; i < allTransform.Length; i++)
        {
            Transform item = allTransform[i];
            if (item.name == name)
            {
                return item.GetComponent<Slider>();
            }
        }
        return null;
    }

    //按钮事件回调
    public static void OnClick(this Button button, UnityAction callback)
    {
        button.onClick.RemoveAllListeners();
        button.onClick.AddListener(callback);
    }

    //按钮事件回调
    public static void OnClick(this GameObject target, UnityAction callback)
    {
        target.GetComponent<Button>()?.OnClick(callback); 
    }

    //按钮事件回调
    public static void OnClick(this Transform target, UnityAction callback)
    {
        target.GetComponent<Button>()?.OnClick(callback);
    }

    //按钮事件回调
    public static void OnClick(this Image target, UnityAction callback)
    {
        target.GetComponent<Button>()?.OnClick(callback);
    }


    #region InputExtension

    /// <summary>
    /// 检测当前平台是否点击UI
    /// </summary>
    /// <param name="mousePosition"></param>
    /// <returns></returns>
    public static bool IsPointerOverGameObject()
    {
        //移动端
#if UNITY_ANDROID || UNITY_IPHONE
            if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
            {
                if (IsPointerOverUI(Input.GetTouch(0).position))
                {
                    return true;
                }
            }
#else
        if (Input.GetMouseButtonDown(0))
        {
            if (IsPointerOverUI(Input.mousePosition))
            {
                return true;
            }
        }
#endif
        return false;
    }

    /// <summary>
    /// 是否点击UI
    /// </summary>
    /// <param name="mousePosition"></param>
    /// <returns></returns>
    private static bool IsPointerOverUI(Vector2 mousePosition)
    {
        //创建一个点击事件
        PointerEventData eventData = new PointerEventData(EventSystem.current)
        {
            position = mousePosition
        };
        List<RaycastResult> raycastResults = new List<RaycastResult>();
        //向点击位置发射一条射线，检测是否点击UI
        EventSystem.current.RaycastAll(eventData, raycastResults);
        if (raycastResults.Count > 0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    /// <summary>
    /// 世界坐标转屏幕坐标
    /// </summary>
    /// <param name="worldPoint"></param>
    /// <returns></returns>
    public static Vector3 WorldToScreenPoint(Vector3 worldPoint)
    {
        Vector3 screenPoint = Camera.main.WorldToScreenPoint(worldPoint);
        return screenPoint;
    }

    /// <summary>
    /// 屏幕坐标转世界坐标
    /// </summary>
    /// <param name="worldPoint"></param>
    /// <returns></returns>
    public static Vector3 ScreenToWorldPoint(Vector3 screenPoint)
    {
        Vector3 worldPoint = Camera.main.ScreenToWorldPoint(screenPoint);
        return worldPoint;
    }

    /// <summary>
    /// 求两向量夹角
    /// </summary>
    /// <param name="pos1"></param>
    /// <param name="pos2"></param>
    /// <returns></returns>
    public static float CaluatureAngle(Vector3 pos1, Vector3 pos2)
    {
        Vector3 cross = Vector3.Cross(pos1, pos2);
        float angle = Vector2.Angle(pos1, pos2);
        return cross.z > 0 ? -angle : angle;
    }

    #endregion
}


<|start_filename|>Assets/Game/Scripts/XLua/Coroutine_Runner.cs<|end_filename|>
using UnityEngine;
using XLua;
using System.Collections.Generic;
using System.Collections;
using System;

public class Coroutine_Runner : MonoBehaviour
{
	public IEnumerator Test()
	{
		yield return null;
	}

	public IEnumerator Create()
	{
		return Test();
	}

}


//public static class CoroutineConfig
//{
//    [LuaCallCSharp]
//    public static List<Type> LuaCallCSharp
//    {
//        get
//        {
//            return new List<Type>()
//            {
//                typeof(WaitForSeconds),
//                typeof(WWW)
//            };
//        }
//    }
//}


<|start_filename|>Assets/Game/Scripts/State/PreloadState_Partial.cs<|end_filename|>
﻿using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Wanderer.GameFramework
{
    public partial class PreloadState
    {
        public override void OnEnter(FSM<GameStateContext> fsm)
        {
            base.OnEnter(fsm);
            Debug.Log("PreloadState");
            //if (Camera.main.Raycast(out RaycastHit hit))
            //{
            //    RectTransformUtility.ScreenPointToLocalPointInRectangle
            //    GameObject.Find("").GetComponent<RectTransform>().anchoredPosition
            //}
            //GameObject.Find("").transform.DOLocalMove(Vector3.zero, 0.5f);
        }
        public override void OnExit(FSM<GameStateContext> fsm)
        {
            base.OnExit(fsm);
        }

        public override void OnInit(FSM<GameStateContext> fsm)
        {
            base.OnInit(fsm);
        }

        public override void OnUpdate(FSM<GameStateContext> fsm)
        {
            base.OnUpdate(fsm);
            ChangeState<DoLuaState>(fsm);
        }
    }
}



<|start_filename|>Assets/Game/Base/DefaultConfig.json<|end_filename|>
{"ResourceUpdateType":0,"DebugEnable":true,"PathType":1,"ResTestUpdatePath":"暂不停供阿里云OSS文件服务测试地址","ResOfficialUpdatePath":"暂不停供阿里云OSS文件服务测试地址","DefaultInStreamingAsset":false,"LogFileEnable":false,"DebugLogMaxLine":100,"AppVersion":"0.1"}

<|start_filename|>Assets/Game/Scripts/Base/GameMode_Partial.cs<|end_filename|>
﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Wanderer.GameFramework;

namespace Wanderer.GameFramework
{
    public partial class GameMode
    {

        public static XLuaManager XLua;
        public static AdsManager Ads;

        [RuntimeInitializeOnLoadMethod]
        private static void OnAwakeAfter()
        {
            Debug.Log($"GameMode OnAwakeAfter");
            XLua = GameFrameworkMode.GetModule<XLuaManager>();
            Ads = GameFrameworkMode.GetModule<AdsManager>();
        }
    }
}



<|start_filename|>Assets/Game/Scripts/State/LaunchOverStartState.cs<|end_filename|>
﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cysharp.Threading.Tasks;
using UniRx;
using System;
using System.IO;
using UnityEngine.Networking;
using Wanderer.GameFramework;
using GF = Wanderer.GameFramework;
using DG.Tweening;

[FSM(FSMStateType.OverStart)]
public class LaunchOverStartState : FSMState<GameStateContext>
{
    private string _updateAssetbundleName = "updateview";
    private string _updateAssetPath = "Assets/Game/Update/Canvas_UpdateView.prefab";
    private LuaBehaviour _updateViewInstance;
    private string _changeFlag;
    private AssetBundle _updateAB;

    public override void OnInit(FSM<GameStateContext> fsm)
    {
        base.OnInit(fsm);
    }

    public override void OnEnter(FSM<GameStateContext> fsm)
    {
        base.OnEnter(fsm);

        _changeFlag = null;
        LoadAsset(_updateAssetPath, (updateView) =>
        {
            _updateViewInstance = updateView.GetComponent<LuaBehaviour>();
            _updateViewInstance.OnLuaCallCSharp += OnLuaCallCSharp;

           // GameMode.Debugger.GetWindow<ProfilerWindow>().AutoTakeSample();
        });
    }

    public override void OnExit(FSM<GameStateContext> fsm)
    {
        if (_updateViewInstance != null)
        {
            var t = Input.gyro.attitude * Quaternion.Euler(0, 0, 0);
            _updateViewInstance.OnLuaCallCSharp -= OnLuaCallCSharp;
            GameObject.Destroy(_updateViewInstance.gameObject);
            _updateViewInstance = null;
        }
        //卸载ab包
        if (_updateAB != null)
        {
            _updateAB.Unload(true);
        }
        base.OnExit(fsm);
    }


    public override void OnUpdate(FSM<GameStateContext> fsm)
    {
        if (string.IsNullOrEmpty(_changeFlag))
            return;

        base.OnUpdate(fsm);

		//选择更新 | 读取本地 | 编辑器
		switch (GameMode.Resource.ResUpdateType)
		{
			case ResourceUpdateType.None:
				ChangeState<DoLuaState>(fsm);
				break;
			case ResourceUpdateType.Update:
				ChangeState<DoLuaState>(fsm);
				break;
			case ResourceUpdateType.Local:
				ChangeState<DoLuaState>(fsm);
				break;
			case ResourceUpdateType.Editor:
//#if UNITY_EDITOR
//				GameMode.Resource.SetResourceHelper(new EditorAssetsHelper());
//#else
//        		//如果在非编辑器模式下选择了Editor，使用本地文件
//                throw new GameException("Please select the correct resource type, not ResourceUpdateType.Editor!");
//#endif
                ChangeState<DoLuaState>(fsm);
                break;
		}
	}


    #region 事件回调
    //lua调用c#的函数
    private void OnLuaCallCSharp(string data)
    {
        _changeFlag = data;
    }
	#endregion

	#region 内部函数
	//加载资源
	private async void LoadAsset(string asset,Action<GameObject> callback)
    {
        GameObject updateView = null;
        if (GameMode.Resource.ResUpdateType == ResourceUpdateType.Editor)
        {
#if UNITY_EDITOR
            updateView = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>(asset);
#endif
        }
        else if (GameMode.Resource.ResUpdateType == ResourceUpdateType.Update)
        {
            string assetPath = Path.Combine(Application.persistentDataPath, _updateAssetbundleName);
            Log.Info($"Load updateview assetbundle. {assetPath}");
            if (!File.Exists(assetPath))
            {
                //加载ab包
                await LoadAssetbundle((ab) =>
                {
                    updateView = ab.LoadAsset<GameObject>(asset);
                    _updateAB = ab;
                });
            }
            else
            {
                using (var stream = new EncryptFileStream(assetPath, FileMode.Open, FileAccess.Read, FileShare.None, 1024 * 4, false))
                {
                    _updateAB = AssetBundle.LoadFromStream(stream);
                    updateView = _updateAB.LoadAsset<GameObject>(asset);
                }
            }
		}

        if (updateView != null)
        {
            callback.Invoke(GameObject.Instantiate(updateView));
        }
        else
        {
            throw new GameException($"Can't find updateview gameobject !!");
        }
    }

    /// <summary>
    /// 加载ab包
    /// </summary>
    /// <param name="assetPath"></param>
    /// <param name="callback"></param>
    /// <returns></returns>
    private IEnumerator LoadAssetbundle(Action<AssetBundle> callback)
    {
        string assetPath ;
#if TEST
        assetPath = GameMode.Resource.ResTestUpdatePath;
#else
        assetPath = GameMode.Resource.ResOfficialUpdatePath;
#endif
        assetPath = $"{assetPath}{GF.Utility.GetRuntimePlatformName()}/{_updateAssetbundleName}";

        using (UnityWebRequest request = new UnityWebRequest(assetPath))
        {
            request.downloadHandler = new DownloadHandlerBuffer();
            yield return request.SendWebRequest();
            if (request.isNetworkError)
            {
                throw new GameException($"Can't read assetbundle file from streamingasset: {assetPath} error: {request.error}");
            }
            yield return null;
            AssetBundle ab;
            byte[] buffer = request.downloadHandler.data;
            using (MemoryStream stream = new EncryptMemoryStream(buffer))
            {
                ab = AssetBundle.LoadFromStream(stream);
                if (ab == null)
                {
                    throw new GameException($"Can't read assetbundle file from streamingasset: {assetPath} error: {request.error}");
                }
                callback?.Invoke(ab);
            }
        }
    }
#endregion

}


<|start_filename|>ProjectSettings/AssetBundleEditorConifg.json<|end_filename|>
{"Version":114,"BuildPath":"build/asset","CompressOptions":1,"UseAssetBundleEditor":true,"Copy2StreamingAssets":false,"BuildTarget":13,"OtherResources":"","IsEncrypt":true,"SupportOldAppVersions":"","OldResourceUrl":"","ForceUpdate":true}

<|start_filename|>Assets/Game/Scripts/XLua/XLuaManager.cs<|end_filename|>
﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;

namespace Wanderer.GameFramework
{
	public class XLuaManager : GameFrameworkModule, IUpdate
	{
		public override int Priority => 10000;

		//lua的环境变量
		private LuaEnv _luaEnv;
		public LuaEnv LuaEnv
		{
			get
			{
				return _luaEnv;
			}
		}

		internal float _lastGCTime = 0;
		internal const float _gcInterval = 1;//1 second
		//lua main入口
		private LuaTable _loadMainLua;
		// lua 更新函数
		private Action<float> _luaOnUpdate;
		//lua 关闭函数
		private Action _luaOnClose;
		//资源管理器
		private ResourceManager _resource;
		//所有的lua脚本
		private readonly Dictionary<string, byte[]> _luaScripts = new Dictionary<string, byte[]>();
		//lua路径前缀
		private const string _luaPathPrefix = "Assets/Game/XLua";
		//所有的lua的资源路径
		private List<string> _allLuaAssetPaths;
		//csharp call lua的事件绑定
		private Dictionary<Type, ICSharpCallXLua> _allCsharpCallXLua;


		public XLuaManager()
		{
			_resource = GameFrameworkMode.GetModule<ResourceManager>();
			_luaEnv = new LuaEnv();
			_luaEnv.AddLoader(CustomLoader);

			_allCsharpCallXLua = new Dictionary<Type, ICSharpCallXLua>();
		}

		public override void OnInit()
		{
			base.OnInit();
		}

		/// <summary>
		/// 运行 main lua
		/// </summary>
		public void DoMainLua(string main = "main")
		{
			if (_loadMainLua == null)
			{
				//获取所有的lua脚本路径
				GetAllLuaAssetsPath();

				_loadMainLua = _luaEnv.NewTable();

				// 为每个脚本设置一个独立的环境，可一定程度上防止脚本间全局变量、函数冲突
				LuaTable meta = _luaEnv.NewTable();
				meta.Set("__index", _luaEnv.Global);
				_loadMainLua.SetMetaTable(meta);
				meta.Dispose();

				_loadMainLua.Set("self", this);
				_luaEnv.DoString($"require \"{main}\"", main, _loadMainLua);
				Action onLuaStart = _loadMainLua.Get<Action>("OnStart");
				_loadMainLua.Get("OnUpdate", out _luaOnUpdate);
				_loadMainLua.Get("OnClose", out _luaOnClose);

				//事件绑定
				CSharpCallXLuaBind();

				//lua 开始
				onLuaStart?.Invoke();
			}
		}

		/// <summary>
		/// 获取lua事件
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="path"></param>
		/// <returns></returns>
		public T GetInPath<T>(string path)
		{
			return _luaEnv.Global.GetInPath<T>(path);
		}

		/// <summary>
		/// 调用事件
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <returns></returns>
		public T CallLua<T>() where T : ICSharpCallXLua
		{
			//先调用了Close
			if (_allCsharpCallXLua == null)
				return default(T);

			if (_allCsharpCallXLua.TryGetValue(typeof(T), out ICSharpCallXLua callXLua))
			{
				return (T)callXLua;
			}
			else
			{
				Debug.LogWarning($"The CSharpCallXLua adapter could not be found.  {typeof(T).FullName}");
				//throw new GameException($"The CSharpCallXLua adapter could not be found.  {typeof(T).FullName}");
			}
			return default(T);
		}

		/// <summary>
		/// 创建新的lua table
		/// </summary>
		/// <typeparam name="TValue"></typeparam>
		/// <param name="value"></param>
		/// <returns></returns>
		public LuaTable NewTable<TValue>(TValue value)
		{
			LuaTable newTable = _luaEnv.NewTable();
			// 为每个脚本设置一个独立的环境，可一定程度上防止脚本间全局变量、函数冲突
			LuaTable meta = _luaEnv.NewTable();
			meta.Set("__index", _luaEnv.Global);
			newTable.SetMetaTable(meta);
			meta.Dispose();
			newTable.Set("self", value);
			return newTable;
		}

		/// <summary>
		/// 运行lua脚本的内容
		/// </summary>
		/// <param name="chunk"></param>
		/// <param name="chunkName"></param>
		/// <param name="env"></param>
		/// <returns></returns>
		public object[] DoString(string chunk, string chunkName = "chunk", LuaTable env = null)
		{
			return _luaEnv.DoString(chunk, chunkName, env);
		}

		//渲染函数
		public void OnUpdate()
		{
			_luaOnUpdate?.Invoke(Time.deltaTime);
			if (Time.time - _lastGCTime > _gcInterval)
			{
				_luaEnv.Tick(); 
				_lastGCTime = Time.time;
			}
		}

		/// <summary>
		/// 关闭
		/// </summary>
		public override void OnClose()
		{
			_luaScripts.Clear();
			//清理所有的绑定事件
			if (_allCsharpCallXLua != null)
			{
				foreach (var item in _allCsharpCallXLua)
				{
					item.Value.Clear();
				}
				_allCsharpCallXLua.Clear();
				_allCsharpCallXLua = null;
			}
			//清理绑定事件
			_luaOnUpdate = null;
			_luaOnClose?.Invoke();
			_luaOnClose = null;
			_loadMainLua?.Dispose();
			_loadMainLua = null;
		}


		#region 内部函数
		//自定义加载
		private byte[] CustomLoader(ref string filePath)
		{
			byte[] data;
			if (!_luaScripts.TryGetValue(filePath, out data))
			{
				string luaPath = GetLuaAssetPath(filePath);
				if (!string.IsNullOrEmpty(luaPath))
				{
					TextAsset textAsset = _resource.Asset.LoadAsset<TextAsset>(luaPath);
					data = textAsset.bytes;
					_luaScripts.Add(filePath, data);
				}
				else
				{
					throw new GameException($"Can't find lua script! {filePath} {luaPath}#");
				}
			}
			return data;
		}

		// 事件绑定
		private void CSharpCallXLuaBind()
		{
			UGUIViewCallXLua uGUIViewCallXLua = new UGUIViewCallXLua();
			uGUIViewCallXLua.Bind("UIAdpterSystem");
			_allCsharpCallXLua.Add((typeof(UGUIViewCallXLua)),uGUIViewCallXLua);
		}

		//获取所有的lua脚本的路径
		private void GetAllLuaAssetsPath()
		{
			string luaPathPrefix = _luaPathPrefix.ToLower();
			_allLuaAssetPaths =GameFrameworkMode.GetModule<ResourceManager>().Asset.AllAssetPaths.FindAll(x => x.StartsWith(luaPathPrefix));
		}

		//获取lua的脚本路径
		private string GetLuaAssetPath(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return null;
			}
			name = $"/{name.ToLower()}.lua.txt";
			string assetPath= _allLuaAssetPaths.Find(x => x.EndsWith(name));
			return assetPath;
		}

		#endregion

	}
}

<|start_filename|>Assets/Game/Scripts/XLua/XLuaUIViewRunInUnityEditor.cs<|end_filename|>
﻿#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Wanderer.GameFramework
{
	public class XLuaUIViewRunInUnityEditor:MonoBehaviour
	{
		private XLuaUGUIView _uiView;
		private UIContextBase _uiContext;

		[SerializeField]
		private string _prefixPath = "Assets/Game/UI";

		public bool RunInEditor = true;

		private void Awake()
		{
			if (!RunInEditor)
			{
				Destroy(this);
			}

			_uiView = GetComponent<XLuaUGUIView>();
			if (_uiView == null)
			{
				throw new GameException($"Can't GetComponent XLuaUGUIView!");
			}

			//资源和lua的代码执行
			GameMode.Resource = GameFrameworkMode.GetModule<ResourceManager>();
			GameMode.Audio = GameFrameworkMode.GetModule<AudioManager>();
			GameFrameworkMode.GetModule<ResourceManager>().SetResourceHelper(new EditorAssetsHelper());
		}

		private void Start()
		{
			if (!RunInEditor)
			{
				return;
			}

			//设置默认UI
			_uiContext = new UIContextBase() { AssetPath = $"{_prefixPath}/{name}.prefab", Name = $"{name}", Multiple = false };
			//加载UIAdpterSystem
			GameFrameworkMode.GetModule<XLuaManager>().DoMainLua("UIAdpterSystem");
			//添加一些默认的全局变量
			GameFrameworkMode.GetModule<XLuaManager>().DoString(
				$"require \"class\"\n" +
				$"json = require \"json\"\n" +
				$"require \"UIView\"\n" +
				$"cs_coroutine = require \"cs_coroutine\"\n" +
				$"require \"SpineSystem\"\n" +
				$"Vector2 = CS.UnityEngine.Vector2\n" +
				$"Vector3 = CS.UnityEngine.Vector3\n" +
				$"Color = CS.UnityEngine.Color\n" +
				$"Input = CS.UnityEngine.Input\n" +
				$"RectTransform = CS.UnityEngine.RectTransform\n" +
				$"GameObject = CS.UnityEngine.GameObject\n" +
				$"Transform = CS.UnityEngine.Transform\n"+
				$"GE =  CS.UnityEngine\n" +
				$"UGUI =  CS.UnityEngine.UI\n" +
				$"GF = CS.Wanderer.GameFramework\n" +
				$"GameMode = GF.GameMode\n"+
				$"RectTransformUtility = CS.UnityEngine.RectTransformUtility\n" +
				$"require \"Resource\"\n" +
				$"Image = CS.UnityEngine.UI.Image\n"+
				$"require \"Utility\"\n"+
				$"require \"AudioSystem\"\n"+
				$"", "XLuaUIViewRunInUnityEditor_PreRequire");
			//UIView的生命周期回调
			_uiView.OnInit(_uiContext);
			_uiView.OnEnter(_uiContext, null, null);
		}

		private void OnDestroy()
		{
			if (!RunInEditor)
			{
				return;
			}

			_uiView.OnExit(_uiContext);
			GameFrameworkMode.GetModule<XLuaManager>().OnClose();
			GameFrameworkMode.GetModule<ResourceManager>().OnClose();
		}

		private void Update()
		{
			if (!RunInEditor)
			{
				return;
			}

			if (_uiContext != null)
			{
				_uiView.OnUpdate(_uiContext, Time.deltaTime);
			}
		}

	}
}
#endif

<|start_filename|>Assets/Game/Scripts/UI/XLuaEventTrigger.cs<|end_filename|>
﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

namespace Wanderer.GameFramework
{
	public class XLuaEventTrigger : EventTrigger
	{
		private XLuaUGUIView _xluaUGUIView;

		private readonly Dictionary<EventTriggerType,string> _triggerTypes = new Dictionary<EventTriggerType,string>();

		//是否拖拽
		private bool _isDrag = false;

		private void OnEnable()
		{
			_triggerTypes.Clear();
			for (int i = 0; i < triggers.Count; i++)
			{
				EventTriggerType triggerType = triggers[i].eventID;
				_triggerTypes[triggerType] = $"On{triggerType}";
			}
			_isDrag = false;
		}

		public override void OnPointerEnter(PointerEventData eventData)
		{
			base.OnPointerEnter(eventData);
			ExecuteXLuaEventTrigger(EventTriggerType.PointerEnter, eventData);
		}
		public override void OnPointerExit(PointerEventData eventData)
		{
			base.OnPointerExit(eventData);
			ExecuteXLuaEventTrigger(EventTriggerType.PointerExit, eventData);
		}
		public override void OnPointerDown(PointerEventData eventData)
		{
			base.OnPointerDown(eventData);
			ExecuteXLuaEventTrigger(EventTriggerType.PointerDown, eventData);
		}
		public override void OnPointerUp(PointerEventData eventData)
		{
			base.OnPointerUp(eventData);
			ExecuteXLuaEventTrigger(EventTriggerType.PointerUp, eventData);

			//EndDrag  要比PointerUp晚
			if (_isDrag)
			{
				OnEndDrag(eventData);
			}
		}
		public override void OnPointerClick(PointerEventData eventData)
		{
			base.OnPointerClick(eventData);
			ExecuteXLuaEventTrigger(EventTriggerType.PointerClick, eventData);
		}
		public override void OnDrag(PointerEventData eventData)
		{
			base.OnDrag(eventData);
			ExecuteXLuaEventTrigger(EventTriggerType.Drag, eventData);
		}
		public override void OnDrop(PointerEventData eventData)
		{
			base.OnDrop(eventData);
			ExecuteXLuaEventTrigger(EventTriggerType.Drop, eventData);
		}
		public override void OnScroll(PointerEventData eventData)
		{
			base.OnScroll(eventData);
			ExecuteXLuaEventTrigger(EventTriggerType.Scroll, eventData);
		}
		public override void OnUpdateSelected(BaseEventData eventData)
		{
			base.OnUpdateSelected(eventData);
			ExecuteXLuaEventTrigger(EventTriggerType.UpdateSelected, eventData);
		}
		public override void OnSelect(BaseEventData eventData)
		{
			base.OnSelect(eventData);
			ExecuteXLuaEventTrigger(EventTriggerType.Select, eventData);
		}
		public override void OnDeselect(BaseEventData eventData)
		{
			base.OnDeselect(eventData);
			ExecuteXLuaEventTrigger(EventTriggerType.Deselect, eventData);
		}
		public override void OnMove(AxisEventData eventData)
		{
			base.OnMove(eventData);
			ExecuteXLuaEventTrigger(EventTriggerType.Move, eventData);
		}
		public override void OnInitializePotentialDrag(PointerEventData eventData)
		{
			base.OnInitializePotentialDrag(eventData);
			ExecuteXLuaEventTrigger(EventTriggerType.InitializePotentialDrag, eventData);
		}
		public override void OnBeginDrag(PointerEventData eventData)
		{
			base.OnBeginDrag(eventData);
			ExecuteXLuaEventTrigger(EventTriggerType.BeginDrag, eventData);
			_isDrag = true;
		}
		public override void OnEndDrag(PointerEventData eventData)
		{
			if (_isDrag)
			{
				base.OnEndDrag(eventData);
				ExecuteXLuaEventTrigger(EventTriggerType.EndDrag, eventData);
				_isDrag = false;
			}
		}
		public override void OnSubmit(BaseEventData eventData)
		{
			base.OnSubmit(eventData);
			ExecuteXLuaEventTrigger(EventTriggerType.Submit, eventData);
		}
		public override void OnCancel(BaseEventData eventData)
		{
			base.OnCancel(eventData);
			ExecuteXLuaEventTrigger(EventTriggerType.Cancel, eventData);
		}
	

		#region 内部函数

		//触发xlua的EventTrigger
		private void ExecuteXLuaEventTrigger(EventTriggerType triggerType, BaseEventData eventData)
		{
			if (_triggerTypes.ContainsKey(triggerType))
			{
				GetXLuaUGUIView()?.OnEventTrigger(transform, _triggerTypes[triggerType], eventData);
			}
		}

		//获取XLuaUGUIView
		private XLuaUGUIView GetXLuaUGUIView()
		{
			if (_xluaUGUIView == null)
			{
				_xluaUGUIView = GetComponentInParent<XLuaUGUIView>();
			}
			return _xluaUGUIView;
		}
		#endregion

	}
}

<|start_filename|>Assets/Spine/Editor/spine-unity/Editor/Components/SkeletonAnimationInspector.cs<|end_filename|>
/******************************************************************************
 * Spine Runtimes License Agreement
 * Last updated January 1, 2020. Replaces all prior versions.
 *
 * Copyright (c) 2013-2020, Esoteric Software LLC
 *
 * Integration of the Spine Runtimes into software or otherwise creating
 * derivative works of the Spine Runtimes is permitted under the terms and
 * conditions of Section 2 of the Spine Editor License Agreement:
 * http://esotericsoftware.com/spine-editor-license
 *
 * Otherwise, it is permitted to integrate the Spine Runtimes into software
 * or otherwise create derivative works of the Spine Runtimes (collectively,
 * "Products"), provided that each user of the Products must obtain their own
 * Spine Editor license and redistribution of the Products in any form must
 * include this license and copyright notice.
 *
 * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
 * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *****************************************************************************/

using UnityEditor;
using UnityEngine;
using Spine;

namespace Spine.Unity.Editor {

	[CustomEditor(typeof(SkeletonAnimation))]
	[CanEditMultipleObjects]
	public class SkeletonAnimationInspector : SkeletonRendererInspector {
		protected SerializedProperty animationName, loop, timeScale, autoReset;
		protected bool requireRepaint;
		readonly GUIContent LoopLabel = new GUIContent("Loop", "Whether or not .AnimationName should loop. This only applies to the initial animation specified in the inspector, or any subsequent Animations played through .AnimationName. Animations set through state.SetAnimation are unaffected.");
		readonly GUIContent TimeScaleLabel = new GUIContent("Time Scale", "The rate at which animations progress over time. 1 means normal speed. 0.5 means 50% speed.");

		protected override void OnEnable () {
			base.OnEnable();
			animationName = serializedObject.FindProperty("_animationName");
			loop = serializedObject.FindProperty("loop");
			timeScale = serializedObject.FindProperty("timeScale");
		}

		protected override void DrawInspectorGUI (bool multi) {
			base.DrawInspectorGUI(multi);
			if (!TargetIsValid) return;
			bool sameData = SpineInspectorUtility.TargetsUseSameData(serializedObject);

			foreach (var o in targets)
				TrySetAnimation(o as SkeletonAnimation);

			EditorGUILayout.Space();
			if (!sameData) {
				EditorGUILayout.DelayedTextField(animationName);
			} else {
				EditorGUILayout.PropertyField(animationName);
			}
			EditorGUILayout.PropertyField(loop, LoopLabel);
			EditorGUILayout.PropertyField(timeScale, TimeScaleLabel);
			foreach (var o in targets) {
				var component = o as SkeletonAnimation;
				component.timeScale = Mathf.Max(component.timeScale, 0);
			}

			EditorGUILayout.Space();
			SkeletonRootMotionParameter();

			serializedObject.ApplyModifiedProperties();

			if (!isInspectingPrefab) {
				if (requireRepaint) {
					UnityEditorInternal.InternalEditorUtility.RepaintAllViews();
					requireRepaint = false;
				}
			}
		}

		protected void TrySetAnimation (SkeletonAnimation skeletonAnimation) {
			if (skeletonAnimation == null) return;
			if (!skeletonAnimation.valid)
				return;

			TrackEntry current = skeletonAnimation.AnimationState.GetCurrent(0);
			if (!isInspectingPrefab) {
				string activeAnimation = (current != null) ? current.Animation.Name : null;
				bool wasAnimationNameChanged = activeAnimation != animationName.stringValue;
				if (wasAnimationNameChanged) {
					var skeleton = skeletonAnimation.Skeleton;
					var state = skeletonAnimation.AnimationState;

					if (!Application.isPlaying) {
						if (state != null) state.ClearTrack(0);
						skeleton.SetToSetupPose();
					}

					Spine.Animation animationToUse = skeleton.Data.FindAnimation(animationName.stringValue);

					if (!Application.isPlaying) {
						if (animationToUse != null) {
							skeletonAnimation.AnimationState.SetAnimation(0, animationToUse, loop.boolValue);
						}
						skeletonAnimation.Update(0);
						skeletonAnimation.LateUpdate();
						requireRepaint = true;
					} else {
						if (animationToUse != null)
							state.SetAnimation(0, animationToUse, loop.boolValue);
						else
							state.ClearTrack(0);
					}
				}

				// Reflect animationName serialized property in the inspector even if SetAnimation API was used.
				if (Application.isPlaying) {
					if (current != null && current.Animation != null) {
						if (skeletonAnimation.AnimationName != animationName.stringValue)
							animationName.stringValue = current.Animation.Name;
					}
				}
			}
		}
	}
}


<|start_filename|>Assets/Game/Scripts/Editor/GameTemplate/CreatingGameTemplateEditor.cs<|end_filename|>
﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using LitJson;

namespace Wanderer.GameFramework
{
    public class CreatingGameTemplateEditor : EditorWindow
    {
        static string _miniGamePath = Application.dataPath + "/Game/MiniGames/";
        static string _spinePath = Application.dataPath + "/Game/SpineResources/";
        static string _luaFilePath = Application.dataPath + "/Game/XLua/MiniGame/";
        static string _prefabPath = Application.dataPath + "/Game/Scripts/Editor/GameTemplate/GameTemplatePrefab.prefab";
        static string _luaScriptPath = Application.dataPath + "/Game/Scripts/Editor/GameTemplate/LuaGameScriptTemplate.lua.txt";
        static string _configName = "AssetBundleEditor.json";

        List<string> gameFolderList = new List<string>();
        List<string> deleteList = new List<string>();
        Vector2 scrollPos = Vector2.zero;

        bool createSpine = false;
        string gamePrefabName = "";
        string gameChineseName = "";
        float lineInterval = 10;
        float modeInterval = 15;

        [MenuItem("Tools/Creating Game Template")]
        static void Main()
        {
            GetWindow<CreatingGameTemplateEditor>("Creating Game Window");
        }

        private void OnEnable()
        {
            LoadGameList();
        }

        private void OnDisable()
        {

        }

        private void OnGUI()
        {
            //创建游戏
            GUILayout.BeginVertical("helpbox", GUILayout.Height(Screen.height * 0.3f));
            GUILayout.Space(lineInterval);
            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            GUILayout.Label("Createing Game Template", EditorStyles.boldLabel);
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();
            GUILayout.Space(lineInterval);
            GUILayout.Label("Game Prefab Name", EditorStyles.boldLabel);
            gamePrefabName = GUILayout.TextField(gamePrefabName);
            GUILayout.Space(lineInterval);
            GUILayout.Label("Game Chinese Name", EditorStyles.boldLabel);
            gameChineseName = GUILayout.TextField(gameChineseName);
            GUILayout.Space(lineInterval);
            createSpine = GUILayout.Toggle(createSpine, "Create Spine Folder");
            GUILayout.Space(lineInterval);
            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Create", GUILayout.Width(Screen.width * 0.5f)))
            {
                CreateGameFile();
                LoadGameList();
                GUIUtility.ExitGUI();
            }
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();
            GUILayout.Space(lineInterval);
            GUILayout.EndVertical();
            GUILayout.Space(modeInterval);

            ///删除游戏
            GUILayout.BeginVertical("helpbox", GUILayout.Height(Screen.height * 0.7f));
            GUILayout.Space(lineInterval);
            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            GUILayout.Label("Deleteing Game Template", EditorStyles.boldLabel);
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();

            GUILayout.Space(lineInterval);
            ShowGameList();
            GUILayout.Space(lineInterval);

            GUILayout.BeginHorizontal();
            GUILayout.FlexibleSpace();
            if (GUILayout.Button("Delete", GUILayout.Width(Screen.width * 0.5f)))
            {
                DeleteGameFile();
                LoadGameList();
                GUIUtility.ExitGUI();
            }
            GUILayout.FlexibleSpace();
            GUILayout.EndHorizontal();
            GUILayout.Space(lineInterval);
            GUILayout.EndVertical();
        }

        void LoadGameList()
        {
            gameFolderList = new List<string>();
            string[] folders = Directory.GetDirectories(_miniGamePath);
            for (int i = 0; i < folders.Length; i++)
            {
                string str = folders[i].Split('/')[folders[i].Split('/').Length - 1];
                gameFolderList.Add(str);
            }
        }

        void ShowGameList()
        {
            scrollPos = GUILayout.BeginScrollView(scrollPos, "helpbox", GUILayout.Height(Screen.height * 0.45f));
            if (gameFolderList != null && gameFolderList.Count > 0)
            {
                foreach (var item in gameFolderList)
                {
                    bool select = deleteList.Contains(item);
                    bool result = GUILayout.Toggle(select, item);
                    if (select != result)
                    {
                        if (result)
                        {
                            deleteList.Add(item);
                        }
                        else
                        {
                            deleteList.Remove(item);
                        }
                    }
                }
            }
            GUILayout.EndScrollView();
        }

        void CreateGameFile()
        {
            if (!string.IsNullOrEmpty(gamePrefabName))
            {
                //游戏AB包路径
                string path = _miniGamePath + gamePrefabName;
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                    Directory.CreateDirectory(path + "/Audio");
                    Directory.CreateDirectory(path + "/Audio/Music");
                    Directory.CreateDirectory(path + "/Audio/Sound");
                    Directory.CreateDirectory(path + "/Audio/UISound");
                    Directory.CreateDirectory(path + "/DynamicSprite");
                    File.Copy(_prefabPath, path + $"/{gamePrefabName}.prefab");
                    Debug.Log("Game ABPath: " + path);
                    Debug.Log("Game AB Audio Path: " + path + "/Audio/Music");

                }
                else
                {
                    EditorUtility.DisplayDialog("Message", "游戏目录已经存在", "OK");
                    return;
                }

                //Spine资源路径
                if (createSpine)
                {
                    path = _spinePath + gamePrefabName;
                    if (!Directory.Exists(path))
                    {
                        Directory.CreateDirectory(path);
                        Debug.Log("Game SpineAsset Path: " + path);
                    }
                    else
                    {
                        EditorUtility.DisplayDialog("Message", "Spine文件目录已经存在", "OK");
                        return;
                    }
                }

                //游戏脚本路径
                path = _luaFilePath + gamePrefabName;
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                    string fileStr = File.ReadAllText(_luaScriptPath, System.Text.Encoding.UTF8);
                    string newStr = fileStr.Replace("Template", gamePrefabName);
                    File.WriteAllText(path + $"/{gamePrefabName}.lua.txt", newStr, System.Text.Encoding.UTF8);
                    Debug.Log("Game LuaSprite Path: " + path);
                }
                else
                {
                    EditorUtility.DisplayDialog("Message", "Lua脚本文件目录已经存在", "OK");
                    return;
                }
                AssetDatabase.Refresh();
                //更新AB配置文件
                AddInfoToAssetBundleConfig();
                EditorUtility.DisplayDialog("Message", "游戏目录创建成功", "OK");
            }
        }

        void DeleteGameFile()
        {
            if (deleteList.Count > 0)
            {
                if (EditorUtility.DisplayDialog("Message", "确定删除选中的游戏？", "确定", "取消"))
                {
                    if (EditorUtility.DisplayDialog("Message", "真的确定要删除选中的游戏？", "确定", "取消"))
                    {
                        //删除游戏文件
                        for (int i = 0; i < deleteList.Count; i++)
                        {
                            if (Directory.Exists(_miniGamePath + deleteList[i]))
                            {
                                Directory.Delete(_miniGamePath + deleteList[i], true);
                            }
                            if (Directory.Exists(_spinePath + deleteList[i]))
                            {
                                Directory.Delete(_spinePath + deleteList[i], true);
                            }
                            if (Directory.Exists(_luaFilePath + deleteList[i]))
                            {
                                Directory.Delete(_luaFilePath + deleteList[i], true);
                            }
                        }

                        //修改json配置文件
                        DeleteInfoToAssetBundleConfig();
                        AssetDatabase.Refresh();
                        EditorUtility.DisplayDialog("Message", "删除游戏成功", "OK");
                    }
                }
            }
            else
            {
                EditorUtility.DisplayDialog("Message", "未选择需要删除的游戏", "OK");
                return;
            }
        }

        void AddInfoToAssetBundleConfig()
        {
            JsonData jd = ProjectSettingsConfig.LoadJsonData(_configName);
            if (jd != null && jd.Count > 0)
            {
                JsonData data = new JsonData();
                data["AssetBundleName"] = gamePrefabName;
                data["Annotation"] = gameChineseName;
                data["Variant"] = "";
                data["Filter"] = 17410;
                data["Split"] = false;
                data["SplitCount"] = 1;
                data["ForceUpdate"] = false;
                data["Preload"] = false;
                data["SearchInFolders"] = new JsonData();
                data["SearchInFolders"].SetJsonType(JsonType.Array);
                data["SearchInFolders"].Add("Assets/Game/MiniGames/" + gamePrefabName);
                jd.Add(data);
                ProjectSettingsConfig.SaveJsonData(_configName, jd);
                gamePrefabName = "";
                gameChineseName = "";
            }
        }

        void DeleteInfoToAssetBundleConfig()
        {
            JsonData jd = ProjectSettingsConfig.LoadJsonData(_configName);
            List<JsonData> tempList = new List<JsonData>();
            if (jd != null && jd.Count > 0)
            {
                for (int i = 0; i < jd.Count; i++)
                {
                    for (int j = 0; j < deleteList.Count; j++)
                    {
                        if ((string)jd[i]["AssetBundleName"] == deleteList[j])
                        {
                            tempList.Add(jd[i]);
                        }
                    }
                }
            }

            if (tempList.Count > 0)
            {
                for (int i = 0; i < tempList.Count; i++)
                {
                    jd.Remove(tempList[i]);
                }
            }
            ProjectSettingsConfig.SaveJsonData(_configName, jd);
        }
    }
}



<|start_filename|>Assets/Game/Scripts/Editor/MiniGamesToABEditor.cs<|end_filename|>
﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using LitJson;
using System.IO;

namespace Wanderer.GameFramework
{
	public class MiniGamesToABEditor 
	{
		private const string _configName = "AssetBundleEditor.json";

		[MenuItem("Tools/Asset Bundle/Update MiniGames")]
		public static void Main()
		{
			JsonData config = ProjectSettingsConfig.LoadJsonData(_configName);
			if (config != null&& config.Count>0)
			{
				List<JsonData> datas = new List<JsonData>();
				for (int i = 0; i < config.Count; i++)
				{
					datas.Add(config[i]);
				}
				bool update = false;
				var folders = Directory.GetDirectories("Assets/Game/MiniGames");
				for (int i = 0; i < folders.Length; i++)
				{
					EditorUtility.DisplayProgressBar("MiniGames To AssetBundleEditor", folders[i], i /(folders.Length-1.0f));
					string abName = Path.GetFileNameWithoutExtension(folders[i]);
					JsonData getData = datas.Find(x => (abName.Equals((string)x["AssetBundleName"])));
					if (getData == null)
					{
						getData = new JsonData();
						getData["AssetBundleName"] = abName;
						getData["Variant"] = "";
						getData["Filter"] = 17410;
						getData["Split"] = false;
						getData["SplitCount"] = 1;
						getData["ForceUpdate"] = false;
						getData["Preload"] = false;
						getData["SearchInFolders"] = new JsonData();
						getData["SearchInFolders"].SetJsonType(JsonType.Array);
						getData["SearchInFolders"].Add(folders[i].Replace("\\","/"));
						datas.Add(getData);
						config.Add(getData);
						update = true;
					}
				}
				EditorUtility.ClearProgressBar();
				if (update)
				{
					ProjectSettingsConfig.SaveJsonData(_configName, config);
					EditorUtility.DisplayDialog("数据保存成功", _configName, "ok");
				}
			}
		}
	}
}

<|start_filename|>Assets/Game/Scripts/XLua/ICSharpCallXLua.cs<|end_filename|>
﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Wanderer.GameFramework
{
	public interface ICSharpCallXLua
	{
		void Bind(string luaName);

		void Clear();
	}
}


<|start_filename|>Assets/Game/Scripts/Extension/UnityExtension.cs<|end_filename|>
﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public static class UnityExtension
{
    /// <summary>
    /// 摄像机射线获取
    /// </summary>
    /// <param name="camera"></param>
    /// <param name="hit"></param>
    /// <returns></returns>
    public static bool Raycast(this Camera camera,out RaycastHit hit)
    {
        Ray ray = camera.ScreenPointToRay(Input.mousePosition);
        return Physics.Raycast(ray, out hit);
    }

    /// <summary>
    /// 摄像机ScreenPosition转RectTransform
    /// </summary>
    /// <param name="camera"></param>
    /// <param name="rect"></param>
    /// <param name="screenPos"></param>
    /// <param name="point"></param>
    /// <returns></returns>
    public static bool ScreenPointToLocalPointInRectangle(this Camera camera,RectTransform rect,Vector2 screenPos, out Vector2 point)
    {
       return RectTransformUtility.ScreenPointToLocalPointInRectangle(rect, screenPos, camera,out point);
    }
}


<|start_filename|>Assets/Game/Scripts/Extension/TransformExtension.cs<|end_filename|>
﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public static class TransformExtension
{
    /// <summary>
    /// 获取十六进制数据对应的颜色
    /// </summary>
    /// <param name="colorValue"></param>
    /// <returns></returns>
    public static Color ParseHtmlString(string colorValue)
    {
        Color outcolor = Color.white;
        ColorUtility.TryParseHtmlString(colorValue, out outcolor);
        return outcolor;
    }

    public static Vector3 GetTargetTransLocalPos(this Transform transform, Vector3 targetTransPos)
    {
        Vector3 returnValue = transform.worldToLocalMatrix.MultiplyPoint(targetTransPos);
        return returnValue;
    }
    public static void PauseGame()
    {
        Time.timeScale = 0.0001f;
    }
    public static void UnPauseGame()
    {
        Time.timeScale = 1f;
    }
    public static void SetMulitTouchEnable(bool b)
    {
        Input.multiTouchEnabled = b;
    }

    public static Vector2 GetRectOffsetMin(this GameObject go)
    {
        return go.transform.GetComponent<RectTransform>().offsetMin;
    }

    public static Vector2 GetRectOffsetMax(this GameObject go)
    {
        return go.transform.GetComponent<RectTransform>().offsetMax;
    }

    public static void SetRectOffsetMin(this GameObject go, Vector2 ofm)
    {
        go.transform.GetComponent<RectTransform>().offsetMin = ofm;
    }

    public static void SetRectOffsetMax(this GameObject go, Vector2 ofm)
    {
        go.transform.GetComponent<RectTransform>().offsetMax = ofm;
    }


    public static GameObject SetName(this GameObject selfObj, string setName)
    {
        selfObj.name = setName;
        return selfObj;
    }
    /// <summary>
    /// 只包含所有子节点的Transform组件 不包括自己和 孙物体
    /// </summary>
    /// <param name="transformParnt"></param>
    /// <returns></returns>
    public static Transform[] GetChilTransforms(Transform transformParnt)
    {
        Transform[] chileTransforms = new Transform[transformParnt.childCount];
        for (int i = 0; i < transformParnt.childCount; i++)
        {
            chileTransforms[i] = transformParnt.GetChild(i);

        }
        return chileTransforms;
    }
    //获取父节点下面所有的 Transform 组件。
    public static Transform[] GetAllTransform(Transform transform)
    {
        Transform[] allTransform = transform.GetComponentsInChildren<Transform>(true);

        return allTransform;
    }
    public static Transform GetActiveTransform(this Transform transform, string tranName)
    {
        Transform[] allTransform = transform.GetComponentsInChildren<Transform>(false);
        for (int i = 0; i < allTransform.Length; i++)
        {
            Transform item = allTransform[i];
            if (item.name == tranName)
            {
                return item;
            }
        }
        return null;
    }
    public static Transform GetTransform(this Transform transform, string tranName)
    {
        Transform[] allTransform = GetAllTransform(transform);
        for (int i = 0; i < allTransform.Length; i++)
        {
            Transform item = allTransform[i];
            if (item.name == tranName)
            {
                return item;
            }
        }
        return null;
    }
    public static GameObject GetGameObject(this Transform transform, string objName)
    {
        Transform[] allTransform = GetAllTransform(transform);
        for (int i = 0; i < allTransform.Length; i++)
        {
            Transform item = allTransform[i];
            if (item.name == objName)
            {
                return item.gameObject;
            }
        }
        return null;
    }

    public static GameObject GetWorldGameObject(string objName)
    {
        return GameObject.Find(objName);
    }

    /// <summary>
    /// 查找层级界面的游戏物体
    /// </summary>
    /// <param name="transName"></param>
    /// <returns></returns>
    public static Transform GetHierarchyTrans(string transName)
    {
        Transform trans = null;
        trans = GameObject.Find(transName).transform;
        return trans;
    }

    public static GameObject Clone(Transform prefab, string objectName = null)
    {
        GameObject mCloneObj = GameObject.Instantiate(prefab).gameObject;

        if (objectName != null)
        {
            mCloneObj.name = objectName;
        }
        return mCloneObj;
    }
    public static GameObject Clone(Transform prefab, Transform parent, string objectName = null)
    {
        GameObject mCloneObj = GameObject.Instantiate(prefab).gameObject;

        if (objectName != null)
        {
            mCloneObj.name = objectName;
        }

        mCloneObj.transform.SetParent(parent, false);

        return mCloneObj;
    }
    public static GameObject Clone(this GameObject prefab, Transform parent, string objectName = null)
    {
        GameObject mCloneObj = GameObject.Instantiate(prefab).gameObject;

        if (objectName != null)
        {
            mCloneObj.name = objectName;
        }

        mCloneObj.transform.SetParent(parent, false);

        return mCloneObj;
    }

    #region Random
    public static int GetRandomInt(int min, int max)
    {
        return UnityEngine.Random.Range(min, max);
    }
    public static float GetRandomfloat(float min, float max)
    {
        return UnityEngine.Random.Range(min, max);
    }
    #endregion

    #region Transform Extension
    /// <summary>
    /// 缓存的一些变量,免得每次声明
    /// </summary>
    private static Vector3 mLocalPos;
    private static Vector3 mScale;
    private static Vector3 mPos;

    public static Vector3 GetLocalPosition(this Transform transform)
    {
        return transform.localPosition;
    }
    public static Quaternion GetLocalRotation(this Transform transform)
    {
        return transform.localRotation;
    }
    public static Quaternion GetRotation(this Transform transform)
    {
        return transform.rotation;
    }
    public static Vector3 GetLocalScale(this Transform transform)
    {
        return transform.localScale;
    }
    public static Vector3 GetPosition(this Transform transform)
    {
        return transform.position;
    }
    public static Vector3 GetGlobalScale(this Transform transform)
    {

        return transform.lossyScale;
    }
    public static Vector3 GetScale(this Transform transform)
    {
        return transform.lossyScale;
    }
    public static Vector3 GetWorldScale(this Transform transform)
    {
        return transform.lossyScale;
    }
    public static Vector3 GetLossyScale(this Transform transform)
    {
        return transform.lossyScale;
    }

    public static Transform Parent(this Transform transform, Transform parent)
    {
        transform.SetParent(parent == null ? null : parent);
        return transform;
    }
    public static Transform AsRootTransform(this Transform transform)
    {
        transform.SetParent(null);
        return transform;
    }
    public static Transform LocalIdentity(this Transform transform)
    {
        transform.localPosition = Vector3.zero;
        transform.localRotation = Quaternion.identity;
        transform.localScale = Vector3.one;
        return transform;
    }
    public static Transform LocalPosition(this Transform transform, Vector3 localPos)
    {
        transform.localPosition = localPos;
        return transform;
    }
    public static Transform LocalEulerAngles(this Transform transform, float x, float y, float z)
    {
        transform.localEulerAngles = new Vector3(x, y, z);
        return transform;
    }
    public static Transform LocalPosition(this Transform transform, float x, float y, float z)
    {
        transform.localPosition = new Vector3(x, y, z);
        return transform;
    }
    public static Transform LocalPosition(this Transform transform, float x, float y)
    {
        mLocalPos = transform.localPosition;
        mLocalPos.x = x;
        mLocalPos.y = y;
        transform.localPosition = mLocalPos;
        return transform;
    }
    public static Transform LocalPositionX(this Transform transform, float x)
    {
        mLocalPos = transform.localPosition;
        mLocalPos.x = x;
        transform.localPosition = mLocalPos;
        return transform;
    }
    public static Transform LocalPositionY(this Transform transform, float y)
    {
        mLocalPos = transform.localPosition;
        mLocalPos.y = y;
        transform.localPosition = mLocalPos;
        return transform;
    }
    public static Transform LocalPositionZ(this Transform transform, float z)
    {
        mLocalPos = transform.localPosition;
        mLocalPos.z = z;
        transform.localPosition = mLocalPos;
        return transform;
    }
    public static Transform LocalPositionIdentity(this Transform transform)
    {
        transform.localPosition = Vector3.zero;
        return transform;
    }
    public static Transform LocalRotation(this Transform transform, Quaternion localRotation)
    {
        transform.localRotation = localRotation;
        return transform;
    }
    public static Transform LocalRotationIdentity(this Transform transform)
    {
        transform.localRotation = Quaternion.identity;
        return transform;
    }
    public static Transform LocalScale(this Transform transform, Vector3 scale)
    {
        transform.localScale = scale;
        return transform;
    }
    public static Transform LocalScale(this Transform transform, float xyz)
    {
        transform.localScale = Vector3.one * xyz;
        return transform;
    }
    public static Transform LocalScale(this Transform transform, float x, float y, float z)
    {
        mScale = transform.localScale;
        mScale.x = x;
        mScale.y = y;
        mScale.z = z;
        transform.localScale = mScale;
        return transform;
    }
    public static Transform LocalScale(this Transform transform, float x, float y)
    {
        mScale = transform.localScale;
        mScale.x = x;
        mScale.y = y;
        transform.localScale = mScale;
        return transform;
    }
    public static Transform LocalScaleX(this Transform transform, float x)
    {
        mScale = transform.localScale;
        mScale.x = x;
        transform.localScale = mScale;
        return transform;
    }
    public static Transform LocalScaleY(this Transform transform, float y)
    {
        mScale = transform.localScale;
        mScale.y = y;
        transform.localScale = mScale;
        return transform;
    }
    public static Transform LocalScaleZ(this Transform transform, float z)
    {
        mScale = transform.localScale;
        mScale.z = z;
        transform.localScale = mScale;
        return transform;
    }
    public static Transform LocalScaleIdentity(this Transform transform)
    {
        transform.localScale = Vector3.one;
        return transform;
    }
    public static Transform Identity(this Transform transform)
    {
        transform.position = Vector3.zero;
        transform.rotation = Quaternion.identity;
        transform.localScale = Vector3.one;
        return transform;
    }
    public static Transform Position(this Transform transform, Vector3 position)
    {
        transform.position = position;
        return transform;
    }
    public static Transform Position(this Transform transform, float x, float y, float z)
    {
        transform.position = new Vector3(x, y, z);
        return transform;
    }
    public static Transform Position(this Transform transform, float x, float y)
    {
        mPos = transform.position;
        mPos.x = x;
        mPos.y = y;
        transform.position = mPos;
        return transform;
    }
    public static Transform PositionIdentity(this Transform transform)
    {
        transform.position = Vector3.zero;
        return transform;
    }
    public static Transform PositionX(this Transform transform, float x)
    {
        mPos = transform.position;
        mPos.x = x;
        transform.position = mPos;
        return transform;
    }
    public static Transform PositionX(this Transform transform, Func<float, float> xSetter)
    {
        mPos = transform.position;
        mPos.x = xSetter(mPos.x);
        transform.position = mPos;
        return transform;
    }
    public static Transform PositionY(this Transform transform, float y)
    {
        mPos = transform.position;
        mPos.y = y;
        transform.position = mPos;
        return transform;
    }
    public static Transform PositionY(this Transform transform, Func<float, float> ySetter)
    {
        mPos = transform.position;
        mPos.y = ySetter(mPos.y);
        transform.position = mPos;
        return transform;
    }
    public static Transform PositionZ(this Transform transform, float z)
    {
        mPos = transform.position;
        mPos.z = z;
        transform.position = mPos;
        return transform;
    }
    public static Transform PositionZ(this Transform transform, Func<float, float> zSetter)
    {
        mPos = transform.position;
        mPos.z = zSetter(mPos.z);
        transform.position = mPos;
        return transform;
    }
    public static Transform RotationIdentity(this Transform transform)
    {
        transform.rotation = Quaternion.identity;
        return transform;
    }
    public static Transform Rotation(this Transform transform, Quaternion rotation)
    {
        transform.rotation = rotation;
        return transform;
    }
    public static Transform DestroyAllChild(this Transform transform)
    {
        var childCount = transform.childCount;
        for (var i = 0; i < childCount; i++)
        {
            UnityEngine.Object.Destroy(transform.GetChild(i).gameObject);
        }
        return transform;
    }
    public static Transform AsLastSibling(this Transform transform)
    {
        transform.SetAsLastSibling();
        return transform;
    }
    public static Transform AsFirstSibling(this Transform transform)
    {
        transform.SetAsFirstSibling();
        return transform;
    }
    public static Transform SiblingIndex(this Transform transform, int index)
    {
        transform.SetSiblingIndex(index);
        return transform;
    }
    public static Transform FindByPath(this Transform selfTrans, string path)
    {
        return selfTrans.Find(path.Replace(".", "/"));
    }
    public static Transform SeekTrans(this Transform selfTransform, string uniqueName)
    {
        var childTrans = selfTransform.Find(uniqueName);

        if (null != childTrans)
            return childTrans;

        foreach (Transform trans in selfTransform)
        {
            childTrans = trans.SeekTrans(uniqueName);

            if (null != childTrans)
                return childTrans;
        }

        return null;
    }
    public static void CopyDataFromTrans(this Transform selfTrans, Transform fromTrans)
    {
        selfTrans.SetParent(fromTrans.parent);
        selfTrans.localPosition = fromTrans.localPosition;
        selfTrans.localRotation = fromTrans.localRotation;
        selfTrans.localScale = fromTrans.localScale;
    }
    /// <summary>
    /// 递归遍历子物体，并调用函数
    /// </summary>
    /// <param name="tfParent"></param>
    /// <param name="action"></param>
    public static void ActionRecursion(this Transform tfParent, Action<Transform> action)
    {
        action(tfParent);
        foreach (Transform tfChild in tfParent)
        {
            tfChild.ActionRecursion(action);
        }
    }
    /// <summary>
    /// 递归遍历查找指定的名字的子物体
    /// </summary>
    /// <param name="tfParent">当前Transform</param>
    /// <param name="name">目标名</param>
    /// <param name="stringComparison">字符串比较规则</param>
    /// <returns></returns>
    public static Transform FindChildRecursion(this Transform tfParent, string name, StringComparison stringComparison = StringComparison.Ordinal)
    {
        if (tfParent.name.Equals(name, stringComparison))
        {
            //Debug.Log("Hit " + tfParent.name);
            return tfParent;
        }

        foreach (Transform tfChild in tfParent)
        {
            Transform tfFinal = null;
            tfFinal = tfChild.FindChildRecursion(name, stringComparison);
            if (tfFinal)
            {
                return tfFinal;
            }
        }

        return null;
    }
    /// <summary>
    /// 递归遍历查找相应条件的子物体
    /// </summary>
    /// <param name="tfParent">当前Transform</param>
    /// <param name="predicate">条件</param>
    /// <returns></returns>
    public static Transform FindChildRecursion(this Transform tfParent, Func<Transform, bool> predicate)
    {
        if (predicate(tfParent))
        {
            Debug.Log("Hit " + tfParent.name);
            return tfParent;
        }

        foreach (Transform tfChild in tfParent)
        {
            Transform tfFinal = null;
            tfFinal = tfChild.FindChildRecursion(predicate);
            if (tfFinal)
            {
                return tfFinal;
            }
        }

        return null;
    }
    public static string GetPath(this Transform transform)
    {
        var sb = new System.Text.StringBuilder();
        var t = transform;
        while (true)
        {
            sb.Insert(0, t.name);
            t = t.parent;
            if (t)
            {
                sb.Insert(0, "/");
            }
            else
            {
                return sb.ToString();
            }
        }
    }
    #endregion

    #region RectTransformExtension
    public static Vector2 GetPosInRootTrans(this RectTransform selfRectTransform, Transform rootTrans)
    {
        return RectTransformUtility.CalculateRelativeRectTransformBounds(rootTrans, selfRectTransform).center;
    }

    /// <summary>
    /// 获取RectTransform的真实Bounds
    /// </summary>
    /// <param name="rectTrans"></param>
    /// <returns></returns>
    public static Bounds GetBounds(this RectTransform rectTrans)
    {
        var bounds = RectTransformUtility.CalculateRelativeRectTransformBounds(rectTrans);
        bounds.center += rectTrans.position;
        bounds.size = new Vector3(bounds.size.x * rectTrans.lossyScale.x, bounds.size.y * rectTrans.lossyScale.y, bounds.size.z * rectTrans.lossyScale.z);
        return bounds;
    }

    public static RectTransform AnchorPosX(this RectTransform selfRectTrans, float anchorPosX)
    {
        var anchorPos = selfRectTrans.anchoredPosition;
        anchorPos.x = anchorPosX;
        selfRectTrans.anchoredPosition = anchorPos;
        return selfRectTrans;
    }
    public static RectTransform AnchorPosY(this RectTransform selfRectTrans, float anchorPosY)
    {
        var anchorPos = selfRectTrans.anchoredPosition;
        anchorPos.y = anchorPosY;
        selfRectTrans.anchoredPosition = anchorPos;
        return selfRectTrans;
    }
    public static RectTransform SetSizeWidth(this RectTransform selfRectTrans, float sizeWidth)
    {
        var sizeDelta = selfRectTrans.sizeDelta;
        sizeDelta.x = sizeWidth;
        selfRectTrans.sizeDelta = sizeDelta;
        return selfRectTrans;
    }
    public static RectTransform SetSizeHeight(this RectTransform selfRectTrans, float sizeHeight)
    {
        var sizeDelta = selfRectTrans.sizeDelta;
        sizeDelta.y = sizeHeight;
        selfRectTrans.sizeDelta = sizeDelta;
        return selfRectTrans;
    }
    public static Vector2 GetWorldSize(this RectTransform selfRectTrans)
    {
        return RectTransformUtility.CalculateRelativeRectTransformBounds(selfRectTrans).size;
    }
    #endregion

    #region UGUI Extension

    public static CanvasGroup GetCanvasGroup(this Transform transform, string groupName = null)
    {
        if (groupName != null)
        {
            Transform[] allTransform = GetAllTransform(transform);
            for (int i = 0; i < allTransform.Length; i++)
            {
                Transform item = allTransform[i];
                if (item.name == groupName)
                {
                    return item.GetComponent<CanvasGroup>();
                }
            }
        }
        else if (groupName == null)
        {

            return transform.GetComponent<CanvasGroup>();
        }

        return null;
    }


    //button
    public static Button GetButton(this Transform transform, string btnName)
    {
        Transform[] allTransform = GetAllTransform(transform);
        for (int i = 0; i < allTransform.Length; i++)
        {
            Transform item = allTransform[i];
            if (item.name == btnName)
            {
                return item.GetComponent<Button>();
            }
        }
        return null;
    }
    public static Button GetButton(this GameObject gameObject, string btnName)
    {
        Transform[] allTransform = GetAllTransform(gameObject.transform);
        for (int i = 0; i < allTransform.Length; i++)
        {
            Transform item = allTransform[i];
            if (item.name == btnName)
            {
                return item.GetComponent<Button>();
            }
        }

        return null;
    }
    public static Button GetButton(this Transform transform)
    {
        return transform.GetComponent<Button>();
    }
    public static Button GetButton(this GameObject gameObject)
    {
        return gameObject.GetComponent<Button>();
    }
    public static Button[] GetButtonsInChildren(this Transform transform)
    {
        return transform.GetComponentsInChildren<Button>(true);
    }
    //Text
    public static Text GetText(this Transform transform, string txtName)
    {
        Transform[] allTransform = GetAllTransform(transform);
        for (int i = 0; i < allTransform.Length; i++)
        {
            Transform item = allTransform[i];
            if (item.name == txtName)
            {
                return item.GetComponent<Text>();
            }
        }
        return null;
    }
    public static Text GetText(this GameObject gameObject, string txtName)
    {
        Transform[] allTransform = GetAllTransform(gameObject.transform);
        for (int i = 0; i < allTransform.Length; i++)
        {
            Transform item = allTransform[i];
            if (item.name == txtName)
            {
                return item.GetComponent<Text>();
            }
        }
        return null;
    }
    public static Text GetText(this Transform transform)
    {
        return transform.GetComponent<Text>();
    }
    public static Text GetText(this GameObject gameObject)
    {
        return gameObject.GetComponent<Text>();
    }
    public static Text[] GetTextsInChildren(this Transform transform)
    {
        return transform.GetComponentsInChildren<Text>(true);
    }
    //Image
    public static Image GetImage(this Transform transform, string imgName)
    {
        Transform[] allTransform = GetAllTransform(transform);
        for (int i = 0; i < allTransform.Length; i++)
        {
            Transform item = allTransform[i];
            if (item.name == imgName)
            {
                return item.GetComponent<Image>();
            }
        }
        return null;
    }
    public static Image GetImage(this GameObject gameObject, string imgName)
    {
        Transform[] allTransform = GetAllTransform(gameObject.transform);
        for (int i = 0; i < allTransform.Length; i++)
        {
            Transform item = allTransform[i];
            if (item.name == imgName)
            {
                return item.GetComponent<Image>();
            }
        }
        return null;
    }
    public static Image GetImage(this Transform transform)
    {
        return transform.GetComponent<Image>();
    }
    public static Image GetImage(this GameObject gameObject)
    {
        return gameObject.GetComponent<Image>();
    }
    public static Image FillAmount(this Image selfImage, float fillamount)
    {
        selfImage.fillAmount = fillamount;
        return selfImage;
    }
    public static Image[] GetImagesInChildren(this Transform transform)
    {
        return transform.GetComponentsInChildren<Image>(true);
    }


    ////ScrollRocker
    //public static ScrollRocker GetScrollRocker(this Transform transform, string animatorName)
    //{
    //    Transform[] allTransform = GetAllTransform(transform);
    //    for (int i = 0; i < allTransform.Length; i++)
    //    {
    //        Transform item = allTransform[i];
    //        if (item.name == animatorName)
    //        {
    //            return item.GetComponent<ScrollRocker>();
    //        }
    //    }
    //    return null;
    //}
    //public static ScrollRocker GetScrollRocker(this GameObject gameObject, string animatorName)
    //{
    //    Transform[] allTransform = GetAllTransform(gameObject.transform);
    //    for (int i = 0; i < allTransform.Length; i++)
    //    {
    //        Transform item = allTransform[i];
    //        if (item.name == animatorName)
    //        {
    //            return item.GetComponent<ScrollRocker>();
    //        }
    //    }
    //    return null;
    //}
    //public static ScrollRocker GetScrollRocker(this Transform transform)
    //{
    //    return transform.GetComponent<ScrollRocker>();
    //}
    //public static ScrollRocker GetScrollRocker(this GameObject gameObject)
    //{
    //    return gameObject.GetComponent<ScrollRocker>();
    //}





    #endregion

    //rhapsody code


    public static Transform SetHide(this Transform selfTransform)
    {
        selfTransform.gameObject.SetActive(false);
        return selfTransform;
    }

    public static Transform SetShow(this Transform selfTransform)
    {
        selfTransform.gameObject.SetActive(true);
        return selfTransform;
    }

    public static GameObject Show(this GameObject selfObj)
    {
        selfObj.SetActive(true);
        return selfObj;
    }

    public static GameObject Hide(this GameObject selfObj)
    {
        selfObj.SetActive(false);
        return selfObj;
    }



}


<|start_filename|>Assets/Game/Scripts/UI/XLuaUIAnimation.cs<|end_filename|>
﻿using Cysharp.Threading.Tasks;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;

namespace Wanderer.GameFramework
{
	public class XLuaUIAnimation:IUIAnimation
	{
		public UIView TargetUIView { get; set; }

		private Tween _dotweenTweener;
		private IEnumerator _enumerator;

		public void SetTarget(GameObject target)
		{
			TargetUIView.GetComponent<CanvasGroup>().blocksRaycasts = false;
			//target.GetComponent<RectTransform>().anchoredPosition=.DOAnchorPos(Vector2.zero,0.5f)
		}

		public async UniTask<int> Run()
		{
			if (_dotweenTweener != null)
			{
				await _dotweenTweener;
			}
			if (_enumerator != null)
			{
				await _enumerator;
			}
			return 1;
		}

		public XLuaUIAnimation SetTargetUIView(UIView targetUIView)
		{
			TargetUIView = targetUIView;
			return this;
		}
		/// <summary>
		/// 优先支持dotween动画
		/// </summary>
		/// <param name="tweener"></param>
		/// <returns></returns>
		public XLuaUIAnimation SetAnimation(Tween tweener)
		{
			_dotweenTweener = tweener;
			return this;
		}
		/// <summary>
		/// 支持协程动画
		/// </summary>
		/// <param name="enumerator"></param>
		/// <returns></returns>
		public XLuaUIAnimation SetAnimation(IEnumerator enumerator)
		{
			_enumerator = enumerator;
			return this;
		}

		public void Flush()
		{
			_dotweenTweener = null;
			_enumerator = null;
			TargetUIView = null;
		}

		public void OnUITweenComplete()
		{
			Flush();
			XLuaUIAnimPool.Release(this);
		}
	}

	public class XLuaUIAnimPool
	{
		private static ObjectPool<XLuaUIAnimation> _xluaAnimPool = new ObjectPool<XLuaUIAnimation>(null, null);

		public static XLuaUIAnimation Get()
		{
			return _xluaAnimPool.Get();
		}

		public static void Release(XLuaUIAnimation animation)
		{
			animation.Flush();
			_xluaAnimPool.Release(animation);
		}

		public static void Release(XLuaUIAnimation[] animations)
		{
			if (animations != null)
			{
				foreach (var item in animations)
				{
					item.Flush();
					_xluaAnimPool.Release(item);
				}
			}
		}
	}
}

<|start_filename|>tools/ossutil64/ossutil-backup.bat<|end_filename|>
@ECHO OFF 
cmd /k cd /d .
set PATH=.;%PATH%

<|start_filename|>Assets/Game/Scripts/UI/XLuaColliderTrigger.cs<|end_filename|>
﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Wanderer.GameFramework
{
	public class XLuaColliderTrigger : MonoBehaviour
	{
		#region field
		[SerializeField]
		private bool _enableTriggerEnter2D=true;

		[SerializeField]
		private bool _enableTriggerStay2D=true;

		[SerializeField]
		private bool _enableTriggerExit2D = true;

		[SerializeField]
		private bool _enableCollisionEnter2D = true;

		[SerializeField]
		private bool _enableCollisionStay2D = true;

		[SerializeField]
		private bool _enableCollisionExit2D = true;
		#endregion

		private XLuaUGUIView _xluaUGUIView;
		//获取XLuaUGUIView
		private XLuaUGUIView GetXLuaUGUIView()
		{
			if (_xluaUGUIView == null)
			{
				_xluaUGUIView = GetComponentInParent<XLuaUGUIView>();
			}
			return _xluaUGUIView;
		}

		private void OnTriggerEnter2D(Collider2D collision)
		{
			if (!_enableTriggerEnter2D)
				return;
			GetXLuaUGUIView()?.OnColliderTrigger("OnTriggerEnter2D", transform, collision.transform);
			// Vector2
		}

		private void OnTriggerStay2D(Collider2D collision)
		{
			if (!_enableTriggerStay2D)
				return;
			GetXLuaUGUIView()?.OnColliderTrigger("OnTriggerStay2D", transform, collision.transform);
		}

		private void OnTriggerExit2D(Collider2D collision)
		{
			if (!_enableTriggerExit2D)
				return;
			GetXLuaUGUIView()?.OnColliderTrigger("OnTriggerExit2D", transform, collision.transform);
		}


		private void OnCollisionEnter2D(Collision2D collision)
		{
			if (!_enableCollisionEnter2D)
				return;
			GetXLuaUGUIView()?.OnColliderTrigger("OnCollisionEnter2D", transform, collision.transform);
		}

		private void OnCollisionStay2D(Collision2D collision)
		{
			if (!_enableCollisionStay2D)
				return;
			GetXLuaUGUIView()?.OnColliderTrigger("OnCollisionStay2D", transform, collision.transform);
		}

		private void OnCollisionExit2D(Collision2D collision)
		{
			if (!_enableCollisionExit2D)
				return;
			GetXLuaUGUIView()?.OnColliderTrigger("OnCollisionExit2D", transform, collision.transform);
		}
	}
}

<|start_filename|>Assets/Game/Scripts/State/DoLuaState.cs<|end_filename|>
﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Wanderer.GameFramework
{
	public class DoLuaState : FSMState<GameStateContext>
	{
        public override void OnEnter(FSM<GameStateContext> fsm)
        {
            base.OnEnter(fsm);
            GameMode.XLua.DoMainLua();
        }
    }
}

<|start_filename|>ProjectSettings/XLuaExportSettings.json<|end_filename|>
{"NameSpace":["UnityEngine","UnityEngine.UI","DG.Tweening"],"Assembly":["Assembly-CSharp","GameFramework","Libraries"]}

<|start_filename|>Assets/Game/Scripts/XLua/UGUIViewCallXLua.cs<|end_filename|>
﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

namespace Wanderer.GameFramework
{
    public class UGUIViewCallXLua : ICSharpCallXLua
    {
        //ui初始化
        public delegate void OnInit(Transform transform, IUIContext uiContext);
        public OnInit LuaOnInit;

        //ui销毁
        public delegate void OnFree(Transform transform, IUIContext uiContext);
        public OnFree LuaOnFree;

        //更新
        public delegate void OnUpdate(IUIContext uiContext, float deltaTime);
        public OnUpdate LuaOnUpdate;

        //进入
        public delegate void OnEnter(Transform transform, IUIContext uiContext, Action<string> callback, object userData);
        public OnEnter LuaOnEnter;

        //退出
        public delegate void OnExit(IUIContext uiContext);
        public OnExit LuaOnExit;

        //暂停
        public delegate void OnPause(IUIContext uiContext);
        public OnPause LuaPause;

        //恢复
        public delegate void OnResume(IUIContext uiContext);
        public OnResume LuaOnResume;

        //动画开始
        public delegate void OnAnimationStart(IUIContext uiContext, IUIAnimation uiAnimation);
        public OnAnimationStart LuaOnAnimationStart;

        //动画结束
        public delegate void OnAnimationComplete(IUIContext uiContext, IUIAnimation uiAnimation);
        public OnAnimationComplete LuaOnAnimationComplete;

        //UI事件
        public delegate void OnEventTrigger(IUIContext uiContext, Transform target, string callMethod, BaseEventData eventData);
        public OnEventTrigger LuaOnEventTrigger;

        //物理碰撞事件
        public delegate void OnColliderTrigger(IUIContext uIContext, string callMethod, Transform self, Transform other);
        public OnColliderTrigger LuaOnColliderTrigger;

        public void Bind(string luaName)
		{
            LuaOnInit = GameMode.XLua.GetInPath<OnInit>($"{luaName}.OnInit");
            LuaOnFree = GameMode.XLua.GetInPath<OnFree>($"{luaName}.OnFree");
            LuaOnUpdate = GameMode.XLua.GetInPath<OnUpdate>($"{luaName}.OnUpdate");
            LuaOnEnter = GameMode.XLua.GetInPath<OnEnter>($"{luaName}.OnEnter");
            LuaOnExit = GameMode.XLua.GetInPath<OnExit>($"{luaName}.OnExit");
            LuaPause = GameMode.XLua.GetInPath<OnPause>($"{luaName}.OnPause");
            LuaOnResume = GameMode.XLua.GetInPath<OnResume>($"{luaName}.OnResume");
            LuaOnAnimationStart = GameMode.XLua.GetInPath<OnAnimationStart>($"{luaName}.OnAnimationStart");
            LuaOnAnimationComplete = GameMode.XLua.GetInPath<OnAnimationComplete>($"{luaName}.OnAnimationComplete");
            LuaOnEventTrigger = GameMode.XLua.GetInPath<OnEventTrigger>($"{luaName}.OnEventTrigger");
            LuaOnColliderTrigger = GameMode.XLua.GetInPath<OnColliderTrigger>($"{luaName}.OnColliderTrigger");
        }

        public void Clear()
        {
            LuaOnInit = null;
            LuaOnFree = null;
            LuaOnUpdate = null;
            LuaOnEnter = null;
            LuaOnExit = null;
            LuaPause = null;
            LuaOnResume = null;
            LuaOnAnimationStart = null;
            LuaOnAnimationComplete = null;
            LuaOnEventTrigger = null;
            LuaOnColliderTrigger = null;
        }
	}
}

<|start_filename|>Assets/Game/Scripts/XLua/LuaItemContent.cs<|end_filename|>
﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Wanderer.GameFramework
{
	public class LuaItemContent : MonoBehaviour
	{
		/// <summary>
		/// 尽量为Json数据
		/// </summary>
		public string Content;
	}
}


<|start_filename|>Assets/Game/Scripts/UI/XLuaUGUIView.cs<|end_filename|>
﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

namespace Wanderer.GameFramework
{
    public class XLuaUGUIView : UGUIView
    {
        private IUIContext _uiContext;

        public override void OnInit(IUIContext uiContext)
		{
			base.OnInit(uiContext);
            _uiContext = uiContext;
            //初始化
            GameMode.XLua.CallLua<UGUIViewCallXLua>().LuaOnInit(transform, uiContext);
        }


        /// <summary>
        /// 销毁
        /// </summary>
        /// <param name="uiContext"></param>
        public override void OnFree(IUIContext uiContext)
        {
            base.OnFree(uiContext);
            //初始化
            GameMode.XLua.CallLua<UGUIViewCallXLua>()?.LuaOnFree(transform, uiContext);
        }

        /// <summary>
        /// 更新界面
        /// </summary>
        /// <param name="uiContext"></param>
        public override void OnUpdate(IUIContext uiContext, float deltaTime)
        {
            base.OnUpdate(uiContext, deltaTime);
            GameMode.XLua.CallLua<UGUIViewCallXLua>().LuaOnUpdate(uiContext, Time.deltaTime);
        }

        /// <summary>
        /// 打开界面
        /// </summary>
        /// <param name="parameters">不确定参数</param>
        public override void OnEnter(IUIContext uiConext, Action<string> callBack = null, params object[] parameters)
        {
            base.OnEnter(uiConext, callBack, parameters);
            GameMode.XLua.CallLua<UGUIViewCallXLua>().LuaOnEnter(transform,uiConext, callBack, parameters);
        }
        /// <summary>
        /// 退出界面
        /// </summary>
        public override void OnExit(IUIContext uiConext)
        {
            base.OnExit(uiConext);
            GameMode.XLua.CallLua<UGUIViewCallXLua>().LuaOnExit(uiConext);
        }
        /// <summary>
        /// 暂停界面
        /// </summary>
        public override void OnPause(IUIContext uiConext)
        {
            base.OnPause(uiConext);
            GameMode.XLua.CallLua<UGUIViewCallXLua>().LuaPause(uiConext);
        }
        /// <summary>
        /// 恢复界面
        /// </summary>
        public override void OnResume(IUIContext uiConext)
        {
            base.OnResume(uiConext);
            GameMode.XLua.CallLua<UGUIViewCallXLua>().LuaOnResume(uiConext);
        }

        /// <summary>
        /// 动画开始
        /// </summary>
        /// <param name="uiAnim"></param>
        public override void OnAnimationStart(IUIAnimation uiAnim)
        {
            base.OnAnimationStart(uiAnim);
            GameMode.XLua.CallLua<UGUIViewCallXLua>().LuaOnAnimationStart(_uiContext, uiAnim);
        }
        /// <summary>
        /// 动画结束
        /// </summary>
        /// <param name="uiAnim"></param>
        public override void OnAnimationComplete(IUIAnimation uiAnim)
        {
            base.OnAnimationComplete(uiAnim);
            GameMode.XLua.CallLua<UGUIViewCallXLua>().LuaOnAnimationComplete(_uiContext, uiAnim);
        }

        /// <summary>
        /// 设置深度
        /// </summary>
        /// <param name="depth"></param>
		public override void SetDepth(int depth)
        {
            base.SetDepth(depth);
        }

        #region UI Event  
        /// <summary>
        /// XLua Event Trigger事件
        /// </summary>
        /// <param name="target"></param>
        /// <param name="callMethod"></param>
        /// <param name="eventData"></param>
        public void OnEventTrigger(Transform target, string callMethod, BaseEventData eventData)
        {
            GameMode.XLua.CallLua<UGUIViewCallXLua>().LuaOnEventTrigger(_uiContext, target, callMethod, eventData);
        }
        #endregion

        #region Physics Event
        /// <summary>
        /// 物理触发事件， 触发器 和 碰撞事件
        /// </summary>
        /// <param name="callMethod"></param>
        /// <param name="self"></param>
        /// <param name="other"></param>
        public void OnColliderTrigger(string callMethod,Transform self, Transform other)
        {
            GameMode.XLua.CallLua<UGUIViewCallXLua>().LuaOnColliderTrigger(_uiContext, callMethod, self, other);
        }        
		#endregion

	}
}


<|start_filename|>Assets/Game/Scripts/Editor/CommandBuild.cs<|end_filename|>
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor.SceneManagement;
using UnityEditor;
using System.IO;
using SD = System.Diagnostics;
using UnityEngine.Networking;
using System.Net;
using marijnz.EditorCoroutines;

namespace Wanderer.GameFramework
{
    public class CommandBuild
    {
        #region menu item

        [MenuItem("Tools/Build/Asset/EditorTarget")]
        static void BuildEditorTargetAsset()
        {
            BuildAsset(EditorUserBuildSettings.activeBuildTarget);
        }

        [MenuItem("Tools/Build/Asset/[Auto Upload] EditorTarget &#P")]
        static void BuildEditorTargetAssetUpload()
        {
            BuildAsset(EditorUserBuildSettings.activeBuildTarget, true);
        }

        [MenuItem("Tools/Build/Asset/Android")]
        static void BuildAndroidAsset()
        {
            BuildAsset(BuildTarget.Android);
        }
        [MenuItem("Tools/Build/Asset/iOS")]
        static void BuildIOSAsset()
        {
            BuildAsset(BuildTarget.iOS);
        }

        [MenuItem("Tools/Build/Asset/[Auto Upload] Android %&#A")]
        static void BuildAndroidAssetUpload()
        {
            BuildAsset(BuildTarget.Android, true);
        }
        [MenuItem("Tools/Build/Asset/[Auto Upload] iOS %&#I")]
        static void BuildIOSAssetUpload()
        {
            BuildAsset(BuildTarget.iOS, true);
        }

        [MenuItem("Tools/Build/Official/[Auto Upload] Android Asset")]
        static void BuildOfficialAndroidAssetUpload()
        {
            bool result = EditorUtility.DisplayDialog("Waring!!!!!!!!!!!!!!", "Official release!", "ok", "cancel");
            if (result)
            {
                BuildAsset(BuildTarget.Android, true);
            }
        }

        [MenuItem("Tools/Build/Official/[Auto Upload] iOS Asset")]
        static void BuildOfficialIOSAssetUpload()
        {
            bool result = EditorUtility.DisplayDialog("Waring!!!!!!!!!!!!!!", "Official release!", "ok", "cancel");
            if (result)
            {
                BuildAsset(BuildTarget.iOS, true);
            }
        }

        [MenuItem("Tools/Build/Apk")]
        public static void BuildAndroidApk()
        {
            CSObjectWrapEditor.Generator.ClearAll();
            AssetDatabase.Refresh();
            //gen xlua
            CSObjectWrapEditor.Generator.GenAll();
            AssetDatabase.Refresh();

            //设置场景的场景的参数
            string launchScenePath = "Assets/Game/Scenes/main.unity";
            UnityEngine.SceneManagement.Scene activeScene = EditorSceneManager.OpenScene(launchScenePath);
            if (activeScene != null)
            {
                EditorSceneManager.SetActiveScene(activeScene);
                foreach (var item in activeScene.GetRootGameObjects())
                {
                    if (item.name.Equals("GameMode"))
                    {
                        GameMode gameMode = item.GetComponent<GameMode>();
                        gameMode.ConfigJsonData["ResourceUpdateType"] = (int)ResourceUpdateType.Update;
                        string configPath = AssetDatabase.GetAssetPath(gameMode.ConfigAsset);
                        File.WriteAllText(configPath, gameMode.ConfigJsonData.ToJson());
                        AssetDatabase.Refresh();
                        EditorUtility.SetDirty(gameMode);
                        EditorSceneManager.SaveOpenScenes();
                        AssetDatabase.Refresh();
                        break;
                    }
                }
            }

            //android keystore
            string path = Path.GetDirectoryName(Application.dataPath);
            string keyStorePath = Path.Combine(path, "tools/user.keystore");
            PlayerSettings.Android.keystoreName = keyStorePath;
            PlayerSettings.Android.keystorePass = "********";
            PlayerSettings.Android.keyaliasName = "********";
            PlayerSettings.Android.keyaliasPass = "********";

            //build apk
            BuildPlayerOptions playerOptions = new BuildPlayerOptions();
            playerOptions.scenes = EditorBuildSettingsScene.GetActiveSceneList(EditorBuildSettings.scenes);
            // playerOptions.scenes = new string[] { "Assets/Core/Scenes/SampleScene.unity" };
            playerOptions.target = BuildTarget.Android;
            playerOptions.locationPathName = "build/Android/mini.apk";

            BuildPipeline.BuildPlayer(playerOptions);
            Debug.Log("build sccuess!");
        }

        #endregion

        #region 内部函数
        private static BuildTarget StringToBuildTarget(string buildTarget)
        {
            BuildTarget target = BuildTarget.StandaloneWindows;
            if (buildTarget.Contains("mac") || buildTarget.Contains("osx"))
            {
                target = BuildTarget.StandaloneOSX;
            }
            else if (buildTarget.Contains("linux"))
            {
                target = BuildTarget.StandaloneLinux64;
            }
            else if (buildTarget.Contains("android"))
            {
                target = BuildTarget.Android;
            }
            return target;
        }

        public static void BuildPlayer()
        {
            string[] args = System.Environment.GetCommandLineArgs();
            for (int i = 0; i < args.Length; i++)
            {
                if (args[i].Contains("-customBuildTarget"))
                {
                    string buildTarget = args[++i].Trim();
                    BuildTarget target = StringToBuildTarget(buildTarget);
                    BuildPlayer(target);
                    return;
                }
            }
        }

        private static void BuildPlayer(BuildTarget buildTarget)
        {
            CSObjectWrapEditor.Generator.ClearAll();
            AssetDatabase.Refresh();
            //gen xlua
            CSObjectWrapEditor.Generator.GenAll();
            AssetDatabase.Refresh();

            //设置场景的场景的参数
            string launchScenePath = "Assets/Game/Scenes/main.unity";
            UnityEngine.SceneManagement.Scene activeScene = EditorSceneManager.OpenScene(launchScenePath);
            if (activeScene != null)
            {
                EditorSceneManager.SetActiveScene(activeScene);
                foreach (var item in activeScene.GetRootGameObjects())
                {
                    if (item.name.Equals("GameMode"))
                    {
                        GameMode gameMode = item.GetComponent<GameMode>();
                        gameMode.ConfigJsonData["ResourceUpdateType"] = (int)ResourceUpdateType.Update;
                        string configPath = AssetDatabase.GetAssetPath(gameMode.ConfigAsset);
                        File.WriteAllText(configPath, gameMode.ConfigJsonData.ToJson());
                        AssetDatabase.Refresh();
                        EditorUtility.SetDirty(gameMode);
                        EditorSceneManager.SaveOpenScenes();
                        AssetDatabase.Refresh();
                        break;
                    }
                }
            }

            if (buildTarget == BuildTarget.Android)
            {
                //android keystore
                string path = Path.GetDirectoryName(Application.dataPath);
                string keyStorePath = Path.Combine(path, "tools/user.keystore");
                PlayerSettings.Android.keystoreName = keyStorePath;
                PlayerSettings.Android.keystorePass = "********";
                PlayerSettings.Android.keyaliasName = "********";
                PlayerSettings.Android.keyaliasPass = "********";
            }

            //build
            BuildPlayerOptions playerOptions = new BuildPlayerOptions();
            playerOptions.scenes = EditorBuildSettingsScene.GetActiveSceneList(EditorBuildSettings.scenes);
            // playerOptions.scenes = new string[] { "Assets/Core/Scenes/SampleScene.unity" };
            playerOptions.target = buildTarget;
            var buildTargetPath = $"build/{AssetBundleBuildEditor.BuildTargetToString(buildTarget)}";
            if (!Directory.Exists(buildTargetPath))
            {
                Directory.CreateDirectory(buildTargetPath);
            }

            if (buildTarget == BuildTarget.Android)
            {
                buildTargetPath = $"{buildTargetPath}/{Application.productName}.apk";
            }
            else if (buildTarget == BuildTarget.StandaloneWindows)
            {
                buildTargetPath = $"{buildTargetPath}/{Application.productName}.exe";
            }
            else if (buildTarget == BuildTarget.StandaloneLinux64)
            {
                buildTargetPath = $"{buildTargetPath}/{Application.productName}.x86_64";
            }
            else if (buildTarget == BuildTarget.StandaloneOSX)
            {
                buildTargetPath = $"{buildTargetPath}/{Application.productName}";
            }
            playerOptions.locationPathName = buildTargetPath;

            BuildPipeline.BuildPlayer(playerOptions);
            Debug.Log("build sccuess!");
        }
        public static void BuildAsset()
        {
            string[] args = System.Environment.GetCommandLineArgs();
            for (int i = 0; i < args.Length; i++)
            {
                if (args[i].Contains("-customBuildTarget"))
                {
                    string buildTarget = args[++i].Trim();
                    BuildTarget target = StringToBuildTarget(buildTarget);
                    BuildAsset(target);
                    return;
                }
            }
        }
        //打包资源
        private static void BuildAsset(BuildTarget buildTarget, bool autoUpload = false, string remotePath = "oss://unity-res-mini-games")
        {
            string buildPath = AssetBundleBuildEditor.BuildAssetBundles(buildTarget);
            if (autoUpload)
            {
                //获取完整的路径
                buildPath = Path.GetFullPath(buildPath);

                string directoryPath = Path.GetFullPath(Path.GetDirectoryName(Application.dataPath));
                if (!buildPath.Contains(directoryPath))
                {
                    buildPath = Path.Combine(directoryPath, buildPath);
                }
                //上传服务器
                remotePath = $"{remotePath}/{AssetBundleBuildEditor.BuildTargetToString(buildTarget)}";
                OssFolderUpload(buildPath, remotePath);

                //string targetName = AssetBundleBuildEditor.BuildTargetToString(buildTarget).ToLower();
                ////开始协程
                //FileUpload fileUpload = new FileUpload();
                //EditorCoroutines.StartCoroutine(fileUpload.FilesUpload(buildPath, targetName, "http://127.0.0.1:19321/"), fileUpload) ;
            }
        }

        //oss 文件上传
        private static void OssFolderUpload(string localPath, string remotePath)
        {
            SD.Process proc = new SD.Process();
            string dataPath = Path.GetDirectoryName(Application.dataPath);
            proc.StartInfo.FileName = Path.Combine(dataPath, "tools/ossutil64/ossutil.bat");
            //proc.StartInfo.Arguments=$"{Path.Combine(dataPath,"build/Full/1_1_5_69/Android")} oss://qwe-0811/Android";
            proc.StartInfo.Arguments = $"{localPath} {remotePath}";
            proc.Start();
            proc.WaitForExit();

            Debug.Log("Oss upload to complete!");
        }

        //class FileUpload
        //{
        //	//文件上传
        //	public IEnumerator FilesUpload(string buildPath,string targetName, string url)
        //	{
        //		string[] files = Directory.GetFiles(buildPath);
        //		WWWForm form = new WWWForm();
        //		foreach (var item in files)
        //		{
        //			string fileName = $"{targetName}/{Path.GetFileName(item)}";
        //			form.AddBinaryData(fileName, File.ReadAllBytes(item));
        //		}

        //		var webRequest = UnityWebRequest.Post(url, form);
        //		yield return webRequest.SendWebRequest();
        //		Debug.Log($"上传完成: {webRequest.downloadHandler.text}");
        //	}
        //}


        #endregion
    }
}

<|start_filename|>tools/ossutil64/ossutil.bat<|end_filename|>
@echo off

echo %1 %2

set CURRENTPATH=%~dp0
echo %CURRENTPATH%

set RUNEXE=%CURRENTPATH%ossutil64.exe
rem echo %RUNEXE%

set CONFIGPATH=%CURRENTPATH%.ossutilconfig
rem echo %configPath%

rem echo Waiting for delete files ...
rem %RUNEXE% rm %2 -r

echo Waiting for upload ...

%RUNEXE% cp -r %1 %2 --config-file %CONFIGPATH% -u

rem pause

<|start_filename|>Assets/Game/Scripts/UI/XLuaUIComponentExtension.cs<|end_filename|>
﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

namespace Wanderer.GameFramework
{
    public static class XLuaUIComponentExtension
    {
        /// <summary>
        /// 1 竖屏
        /// 3 横屏
        /// </summary>
        /// <param name="ui"></param>
        /// <param name="orientation"></param>
        public static void SetOrientation(this UIManager ui, int orientation)
        {
            Screen.orientation = (ScreenOrientation)orientation;
            var referenceResolution = orientation == 1 ? new Vector2(1080, 1920) : new Vector2(1920, 1080);
            GameObject.FindObjectOfType<UIComponent>().GetComponent<CanvasScaler>().referenceResolution = referenceResolution;
        }
    }

}


<|start_filename|>Assets/Game/Scripts/Ads/AdsManager.cs<|end_filename|>
﻿using Cysharp.Threading.Tasks;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Advertisements;

namespace Wanderer.GameFramework
{
    public class AdsManager : GameFrameworkModule,IUnityAdsListener
    {
        private string _appleId = "3982834";
        private string _androidId = "3982835";

        HashSet<string> _readyIds = new HashSet<string>();

        private Dictionary<string, List<Action>> _onAdsStart = new Dictionary<string, List<Action>>();
        private Dictionary<string, List<Action<ShowResult>>> _onAdsFinish = new Dictionary<string, List<Action<ShowResult>>>();

        private bool _testMode = false;

        public AdsManager()
        {
        }

        public override void OnInit()
        {
            base.OnInit();

            Advertisement.AddListener(this);

#if UNITY_EDITOR || TEST
            _testMode = true;
#endif

#if UNITY_ANDROID
            Advertisement.Initialize(_androidId, _testMode,true);
#elif UNITY_IOS
            Advertisement.Initialize(_appleId, _testMode,true);
#endif
        }


        public override void OnClose()
        {
            Advertisement.RemoveListener(this);
        }

        public async void Show(string id, Action onStart=null, Action<ShowResult> OnFinish=null,bool isBanner=false,BannerPosition bannerPosition= BannerPosition.BOTTOM_CENTER)
        {
            if (_testMode)
                return;

            await PlayAds(id, onStart, OnFinish, isBanner, bannerPosition);
        }

        IEnumerator PlayAds(string id, Action onStart,Action<ShowResult> onFinish, bool isBanner , BannerPosition bannerPosition)
        {
            while (!Advertisement.isInitialized)
            {
                yield return null;
            }

           

            if (isBanner)
            {
                Advertisement.Banner.Load(id);
                while(!Advertisement.IsReady(id))
                {
                    yield return null;
                }

                while (!_readyIds.Contains(id))
                {
                    yield return null;
                }

                if (onStart != null)
                {
                    _onAdsStart[id].Add(onStart);
                }
                if (onFinish != null)
                {
                    _onAdsFinish[id].Add(onFinish);
                }

                Advertisement.Banner.SetPosition(bannerPosition);
                Advertisement.Banner.Show(id);
            }
            else
            {
                Advertisement.Load(id);
                while (!Advertisement.IsReady(id))
                {
                    yield return null;
                }

                while (!_readyIds.Contains(id))
                {
                    yield return null;
                }

                if (onStart != null)
                {
                    _onAdsStart[id].Add(onStart);
                }
                if (onFinish != null)
                {
                    _onAdsFinish[id].Add(onFinish);
                }
                Advertisement.Show(id);
            }
        }

        //public void ShowGameStart()
        //{
        //    Show("GameStart");
        //}

        //public void ShowLoading()
        //{
        //    Show("Loading");
        //}

        //public void ShowGameSelect()
        //{
        //    Show("GameSelect");
        //}

        public void OnUnityAdsDidError(string message)
        {
            Debug.LogWarning($"ads OnUnityAdsDidError: {message}");
        }

        public void OnUnityAdsDidFinish(string placementId, ShowResult showResult)
        {
            Debug.Log($"ads OnUnityAdsDidFinish: {placementId}");

            if (!_onAdsFinish.ContainsKey(placementId))
                return;

            var onFinishCallback = _onAdsFinish[placementId];


            if (onFinishCallback.Count > 0)
            {
                for (int i = 0; i < onFinishCallback.Count; i++)
                {
                    onFinishCallback[i].Invoke(showResult);
                }
                onFinishCallback.Clear();
            }
        }

        public void OnUnityAdsDidStart(string placementId)
        {
            Debug.Log($"ads OnUnityAdsDidStart: {placementId}");

            if (!_onAdsStart.ContainsKey(placementId))
                return;

            var onStartCallback = _onAdsStart[placementId];


            if (onStartCallback.Count > 0)
            {
                for (int i = 0; i < onStartCallback.Count; i++)
                {
                    onStartCallback[i].Invoke();
                }
                onStartCallback.Clear();
            }
        }

        public void OnUnityAdsReady(string id)
        {
            if (!_onAdsStart.ContainsKey(id))
            {
                _onAdsStart.Add(id, new List<Action>());
            }
            if (!_onAdsFinish.ContainsKey(id))
            {
                _onAdsFinish.Add(id, new List<Action<ShowResult>>());
            }
            _readyIds.Add(id);

            Debug.Log($"ads OnUnityAdsReady: {id}");
        }
    }
}
