public override void OnInspectorGUI() { serializedObject.Update(); _classBinds.DoLayoutList(); serializedObject.ApplyModifiedProperties(); GUILayout.Space(5); Setting.MakeHorizontal(50, () => { if (GUILayout.Button(Setting.GetString(SettingString.ClassBindGetAllField), GUILayout.Height(30))) { DoConvert(target as ClassBind); } }); GUILayout.Space(5); Setting.MakeHorizontal(50, () => { if (GUILayout.Button(Setting.GetString(SettingString.ClassBindGetAllType), GUILayout.Height(30))) { DoFieldType(target as ClassBind); } }); GUILayout.Space(15); }
public static async void DoFieldType(ClassBind instance, bool toast = true) { int affectCounts = 0; foreach (var data in instance.scriptsToBind) //遍历 { string className = $"{data.classNamespace}.{data.className}"; Assembly hotCode = Assembly .LoadFile(_dllPath); Type t = hotCode.GetType(className); //加载热更类 if (t == null) { EditorUtility.DisplayDialog(Setting.GetString(SettingString.ClassBindErrorTitle), String.Format(Setting.GetString(SettingString.ClassBindErrorContent), className), "OK"); return; } foreach (var field in data.fields) { var fieldType = t.GetField(field.fieldName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)?.FieldType ?? t.GetProperty(field.fieldName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)?.PropertyType; if (fieldType == null) { Log.PrintError(String.Format(Setting.GetString(SettingString.ClassBindInvalidField), className, field.fieldName)); } SetType(field, fieldType, hotCode); affectCounts++; EditorUtility.DisplayProgressBar(Setting.GetString(SettingString.ClassBindProgress), String.Format(Setting.GetString(SettingString.ClassBindProgressContentForGetField), field.fieldName, data.fields.IndexOf(field), data.fields.Length), data.fields.IndexOf(field) / (float)data.fields.Length); await Task.Delay(50); //延迟一下,动画更丝滑 } } EditorUtility.ClearProgressBar(); TrySave(instance, toast, String.Format(Setting.GetString(SettingString.ClassBindResultContentForGetType), affectCounts, instance.name), Setting.GetString(SettingString.ClassBindResultTitle), Setting.GetString(SettingString.Done)); }
private static void SetVal(ref ClassField cf, Type type, Assembly hotCode, object value, GameObject instance) { if (type != typeof(Object) || !type.IsSubclassOf(hotCode.GetType("JEngine.Core.JBehaviour"))) { try { if (type == typeof(String)) { value = ""; } cf.value = value.ToString(); } catch { Log.PrintWarning(String.Format(Setting.GetString(SettingString.ClassBindUnableSetFieldValue), instance.name, type.Name, cf.fieldName)); } } }
void DoSearchField(Rect rect, bool asToolbar) { if (searchField == null) { searchField = new SearchField(); searchField.downOrUpArrowKeyPressed += OnDownOrUpArrowKeyPressed; } if (searchString != "") { var result = asToolbar ? searchField.OnToolbarGUI(rect, searchString) : searchField.OnGUI(rect, searchString); if (result != searchString && onInputChanged != null) { onInputChanged(result); selectedIndex = -1; showResults = true; } searchString = result; } else { var s = asToolbar ? searchField.OnToolbarGUI(rect, Setting.GetString(Setting.SCENE_FILTER)) : searchField.OnGUI(rect, Setting.GetString(Setting.SCENE_FILTER)); searchString = ""; } if (HasSearchbarFocused()) { RepaintFocusedWindow(); } }
public static bool SerializeJBehaviourType(AnimBool[] fadeGroup, ILTypeInstance instance) { //如果JBehaviour var jBehaviourType = InitJEngine.Appdomain.LoadedTypes["JEngine.Core.JBehaviour"]; var t = instance.Type.ReflectionType; if (t.IsSubclassOf(jBehaviourType.ReflectionType)) { var f = t.GetField("_instanceID", BindingFlags.NonPublic); if (!(f is null)) { GUI.enabled = false; var id = f.GetValue(instance).ToString(); EditorGUILayout.TextField("InstanceID", id); GUI.enabled = true; } string frameModeStr = "FrameMode"; string frequencyStr = "Frequency"; string pausedStr = "Paused"; string totalTimeStr = "TotalTime"; string loopDeltaTimeStr = "LoopDeltaTime"; string loopCountsStr = "LoopCounts"; string timeScaleStr = "TimeScale"; fadeGroup[0].target = EditorGUILayout.Foldout(fadeGroup[0].target, "JBehaviour Stats", true); if (EditorGUILayout.BeginFadeGroup(fadeGroup[0].faded)) { var fm = t.GetField(frameModeStr, BindingFlags.Public); bool frameMode = !(fm is null) && EditorGUILayout.Toggle(frameModeStr, (bool)fm.GetValue(instance)); fm?.SetValue(instance, frameMode); var fq = t.GetField(frequencyStr, BindingFlags.Public); if (!(fq is null)) { int frequency = EditorGUILayout.IntField(frequencyStr, (int)fq.GetValue(instance)); fq.SetValue(instance, frequency); } GUI.enabled = false; var paused = t.GetField(pausedStr, BindingFlags.NonPublic); if (!(paused is null)) { EditorGUILayout.Toggle(pausedStr, (bool)paused.GetValue(instance)); } var totalTime = t.GetField(totalTimeStr, BindingFlags.Public); if (!(totalTime is null)) { EditorGUILayout.FloatField(totalTimeStr, (float)totalTime.GetValue(instance)); } var loopDeltaTime = t.GetField(loopDeltaTimeStr, BindingFlags.Public); if (!(loopDeltaTime is null)) { EditorGUILayout.FloatField(loopDeltaTimeStr, (float)loopDeltaTime.GetValue(instance)); } var loopCounts = t.GetField(loopCountsStr, BindingFlags.Public); if (!(loopCounts is null)) { EditorGUILayout.LongField(loopCountsStr, (long)loopCounts.GetValue(instance)); } GUI.enabled = true; var timeScale = t.GetField(timeScaleStr, BindingFlags.Public); if (!(timeScale is null)) { var ts = EditorGUILayout.FloatField(timeScaleStr, (float)timeScale.GetValue(instance)); timeScale.SetValue(instance, ts); } } EditorGUILayout.EndFadeGroup(); if (instance.Type.FieldMapping.Count > 0) { EditorGUILayout.Space(10); EditorGUILayout.HelpBox(String.Format(Setting.GetString(SettingString.MemberVariables), t.Name), MessageType.Info); } return(true); } return(false); }
public static async void CleanFields(ClassBind instance, bool toast = true) { int affectCounts = 0; foreach (var data in instance.scriptsToBind) //遍历 { string className = $"{data.classNamespace + (string.IsNullOrEmpty(data.classNamespace) ? "" : ".")}{data.className}"; Type t = HotAssembly.GetType(className); //加载热更类 if (t == null) { EditorUtility.DisplayDialog(Setting.GetString(SettingString.ClassBindErrorTitle), String.Format(Setting.GetString(SettingString.ClassBindErrorContent), className), "OK"); return; } for (int i = 0; i < data.fields.Count; i++) { var field = data.fields[i]; var fieldType = t.GetField(field.fieldName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)?.FieldType ?? t.GetProperty(field.fieldName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)?.PropertyType; if (fieldType == null) { Log.PrintError(String.Format(Setting.GetString(SettingString.ClassBindInvalidFieldDeleted), className, field.fieldName)); data.fields.RemoveAt(i); continue; } affectCounts++; EditorUtility.DisplayProgressBar(Setting.GetString(SettingString.ClassBindProgress), String.Format(Setting.GetString(SettingString.ClassBindRearrange), field.fieldName, data.fields.IndexOf(field), data.fields.Length), data.fields.IndexOf(field) / (float)data.fields.Length); await Task.Delay(50); //延迟一下,动画更丝滑 } var f = data.fields.OrderBy(s => s.fieldName); FieldList newF = new FieldList(); foreach (var cf in f) { newF.Add(cf); } data.fields = newF; } EditorUtility.ClearProgressBar(); TrySave(instance, toast, String.Format(Setting.GetString(SettingString.ClassBindRearrangeResult), affectCounts, instance.name), Setting.GetString(SettingString.ClassBindResultTitle), Setting.GetString(SettingString.Done)); }
public static async void DoConvert(ClassBind instance, bool toast = true) { int affectCounts = 0; foreach (var data in instance.scriptsToBind) //遍历 { string className = $"{data.classNamespace + (string.IsNullOrEmpty(data.classNamespace) ? "" : ".")}{data.className}"; Type t = HotAssembly.GetType(className); //加载热更类 if (t == null) { EditorUtility.DisplayDialog(Setting.GetString(SettingString.ClassBindErrorTitle), String.Format(Setting.GetString(SettingString.ClassBindErrorContent), className), "OK"); return; } //热更实例 object hotInstance = null; if (!t.IsSubclassOf(typeof(MonoBehaviour))) //JBehaviour/MonoBehaviour派生类不构造对象,不进行赋值 { Type tBase = t.BaseType; while (tBase != null) { if (tBase.BaseType != typeof(System.Object)) { tBase = tBase.BaseType; } else { break; } } if (tBase?.FullName != "JEngine.Core.JBehaviour") { hotInstance = Activator.CreateInstance(t); } } var fieldsInCb = data.fields.Select(f => f.fieldName).ToList(); //全部已经设置的字段 var members = new List <MemberInfo>(0); if (Setting.ClassBindIgnorePrivate) { members.AddRange(t.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public)); members.AddRange(t.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public)); } else { members.AddRange(t.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)); members.AddRange(t.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)); } foreach (var field in members) { //跳过标签的 if (Setting.ClassBindIgnoreHideInInspector) { var attr = field.GetCustomAttributes(typeof(HideInInspector), false); if (attr.Length > 0) { continue; } } //遍历字段 EditorUtility.DisplayProgressBar(Setting.GetString(SettingString.ClassBindProgress), String.Format(Setting.GetString(SettingString.ClassBindProgressContentForGetType), $"{t.Name}:{field.Name}", members.ToList().IndexOf(field), members.Count), members.ToList().IndexOf(field) / (float)members.Count); if (!fieldsInCb.Contains(field.Name)) { ClassField cf = new ClassField(); string fieldName = field.Name; cf.fieldName = fieldName; Type fieldType = (field is PropertyInfo) ? ((PropertyInfo)field).PropertyType : ((FieldInfo)field).FieldType; SetType(cf, fieldType, HotAssembly); SetVal(ref cf, field, HotAssembly, hotInstance, instance.gameObject); data.fields.Add(cf); affectCounts++; } await Task.Delay(10); //延迟一下,动画更丝滑 } } await Task.Delay(50); //延迟一下,动画更丝滑 EditorUtility.ClearProgressBar(); TrySave(instance, toast, String.Format(Setting.GetString(SettingString.ClassBindResultContentForSetField), affectCounts, instance.name), Setting.GetString(SettingString.ClassBindResultTitle), Setting.GetString(SettingString.Done)); }
public static void Update() { if (!_isDone || EditorApplication.isPlaying) { return; } if (!HiddenDirectory.Exists) //DLL导入到隐藏文件夹,防止每次加载浪费时间 { HiddenDirectory.Create(); } if (!File.Exists(DLLMgr.DllPath)) //没热更dll就返回 { return; } //有的话比较日期 DateTime lastModified = File.GetLastWriteTime(DLLMgr.DllPath); string lastModifiedStr = lastModified.ToString(Setting.GetString(SettingString.DateFormat)); if (Setting.LastDLLCleanUpTime != lastModifiedStr) //不一样再处理 { var files = HiddenDirectory.GetFiles(); int counts = 0; List <string> fileNames = Directory.GetFiles("Assets/", "*.dll", SearchOption.AllDirectories).ToList(); var watch = new Stopwatch(); watch.Start(); DLLMgr.MakeBytes(); watch.Stop(); if (watch.ElapsedMilliseconds > 0) { Log.Print(String.Format(Setting.GetString(SettingString.DLLConvertLog), watch.ElapsedMilliseconds)); } AssetDatabase.Refresh(); Setting.LastDLLCleanUpTime = lastModifiedStr; _isDone = false; fileNames = fileNames.FindAll(x => !x.Contains("~")); watch.Start(); foreach (var file in files) { var name = file.Name; var success = true; if (!File.Exists(LibraryDirectory.FullName + "/" + name) && !name.Contains("netstandard") && !name.Contains(HotProjectName) && !name.Contains("Unity") && !name.Contains("System") && ((name.Contains(".pdb") || name.Contains(".dll")))) { if (fileNames.Find(x => x.Contains(name)) == null) //不存在就添加 { success = false; } else //存在就删了 { DLLMgr.Delete(file.FullName); counts++; } } else if (!name.Contains(HotProjectName)) { try { DLLMgr.Delete(file.FullName); counts++; } catch { Log.Print(String.Format( Setting.GetString(SettingString.DeleteErrorLog), file.Name)); success = false; } } if (!success) { if (file.Directory != null) { DirectoryInfo newPath = new DirectoryInfo(file.Directory.FullName)?.Parent?.Parent?.Parent; if (newPath != null) { File.Move(file.FullName, newPath.FullName + "/" + file.Name); Log.Print(String.Format( Setting.GetString(SettingString.DLLNewReferenceLog), newPath.FullName + "/" + file.Name)); } } } } watch.Stop(); if (counts > 0) //如果删除过东西,就代表DLL更新了,就需要生成文件 { Log.Print(String.Format(Setting.GetString(SettingString.DLLCleanLog), counts, watch.ElapsedMilliseconds)); } _isDone = true; } if (!HotFile.Exists) { _isDone = false; var watch = new Stopwatch(); watch.Start(); DLLMgr.MakeBytes(); watch.Stop(); Log.Print(String.Format(Setting.GetString(SettingString.DLLConvertLog), watch.ElapsedMilliseconds)); AssetDatabase.Refresh(); _isDone = true; } }
public static void Update() { if (!isDone || EditorApplication.isPlaying) { return; } if (!Directory.Exists("Assets/HotUpdateResources/Dll/Hidden~")) //DLL导入到隐藏文件夹,防止每次加载浪费时间 { Directory.CreateDirectory("Assets/HotUpdateResources/Dll/Hidden~"); } if (!File.Exists(DLLMgr.DllPath)) //没热更dll就返回 { return; } //有的话比较日期 DateTime lastModified = File.GetLastWriteTime(DLLMgr.DllPath); string lastModifiedStr = lastModified.ToString(Setting.GetString(Setting.DATE_FORMAT)); if (Setting.LastDLLCleanUpTime != lastModifiedStr) //不一样再处理 { var files = di.GetFiles(); var watch = new Stopwatch(); int counts = 0; List <string> fileNames = Directory.GetFiles("Assets/", "*.dll", SearchOption.AllDirectories).ToList(); DLLMgr.Delete("Assets/HotUpdateResources/Dll/HotUpdateScripts.bytes"); watch = new Stopwatch(); DLLMgr.MakeBytes(); watch.Stop(); if (watch.ElapsedMilliseconds > 0) { Log.Print("Convert DLL in: " + watch.ElapsedMilliseconds + " ms."); } AssetDatabase.Refresh(); Setting.LastDLLCleanUpTime = lastModifiedStr; isDone = false; fileNames = fileNames.FindAll((x) => !x.Contains("~")); watch.Start(); foreach (var file in files) { var name = file.Name; if (!File.Exists(library.FullName + "/" + name) && !name.Contains("netstandard") && !name.Contains("HotUpdateScripts") && !name.Contains("Unity") && !name.Contains("System") && ((name.Contains(".pdb") || name.Contains(".dll")))) { if (fileNames.Find(x => x.Contains(name)) == null) //不存在就添加 { DLLMgr.Delete(file.FullName.Replace("Hidden~", "../Dll")); File.Move(file.FullName, file.FullName.Replace("Hidden~", "../Dll")); Log.Print( $"Find new referenced dll `{name}`, note that your hot update code may not be able " + $"to run without rebuild application\n" + $"发现新的引用DLL`{name}`,请注意,游戏可能需要重新打包,否则热更代码无法将有可能运行"); } else //存在就删了 { DLLMgr.Delete(file.FullName); counts++; } } else if (!name.Contains("HotUpdateScripts")) { DLLMgr.Delete(file.FullName); counts++; } else { if (!name.Contains("HotUpdateScripts")) { Log.PrintError($"无法删除{file.FullName},请手动删除"); } } } watch.Stop(); if (counts > 0) //如果删除过东西,就代表DLL更新了,就需要生成文件 { Log.Print("Cleaned: " + counts + " files in: " + watch.ElapsedMilliseconds + " ms."); } isDone = true; } if (!File.Exists("Assets/HotUpdateResources/Dll/HotUpdateScripts.bytes")) { isDone = false; var watch = new Stopwatch(); DLLMgr.MakeBytes(); watch.Stop(); Log.Print("Convert DLL in: " + watch.ElapsedMilliseconds + " ms."); AssetDatabase.Refresh(); isDone = true; } }
public static async void DoFieldType(ClassBind instance, bool toast = true) { int affectCounts = 0; foreach (var data in instance.scriptsToBind) //遍历 { string className = $"{data.classNamespace}.{data.className}"; Assembly hotCode = Assembly .LoadFile(_dllPath); Type t = hotCode.GetType(className); //加载热更类 if (t == null) { EditorUtility.DisplayDialog(Setting.GetString(SettingString.ClassBindErrorTitle), String.Format(Setting.GetString(SettingString.ClassBindErrorContent), className), "OK"); return; } foreach (var field in data.fields) { var fieldType = t.GetField(field.fieldName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)?.FieldType ?? t.GetProperty(field.fieldName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)?.PropertyType; if (fieldType == null) { Log.PrintError(String.Format(Setting.GetString(SettingString.ClassBindInvalidField), className, field.fieldName)); } SetType(field, fieldType, hotCode); affectCounts++; EditorUtility.DisplayProgressBar(Setting.GetString(SettingString.ClassBindProgress), String.Format(Setting.GetString(SettingString.ClassBindProgressContentForGetField), field.fieldName, data.fields.IndexOf(field), data.fields.Length), data.fields.IndexOf(field) / (float)data.fields.Length); await Task.Delay(50); //延迟一下,动画更丝滑 } } EditorUtility.ClearProgressBar(); //转换后保存场景 try { PrefabUtility.SavePrefabAsset(instance.gameObject, out _); } catch { try { EditorSceneManager.SaveOpenScenes(); } catch { try { var scene = SceneManager.GetActiveScene(); EditorSceneManager.SaveScene(scene, scene.path); } catch { //ignored } } } AssetDatabase.SaveAssets(); EditorUtility.ClearProgressBar(); if (toast) { EditorUtility.DisplayDialog(Setting.GetString(SettingString.ClassBindResultTitle), String.Format(Setting.GetString(SettingString.ClassBindResultContentForGetType), affectCounts, instance.name), Setting.GetString(SettingString.Done)); } else { Log.Print(String.Format(Setting.GetString(SettingString.ClassBindResultContentForGetType), affectCounts, instance.name)); } }
public static async void DoConvert(ClassBind instance, bool toast = true) { int affectCounts = 0; foreach (var data in instance.scriptsToBind) //遍历 { string className = $"{data.classNamespace}.{data.className}"; Assembly hotCode = Assembly .LoadFile(_dllPath); Type t = hotCode.GetType(className); //加载热更类 if (t == null) { EditorUtility.DisplayDialog(Setting.GetString(SettingString.ClassBindErrorTitle), String.Format(Setting.GetString(SettingString.ClassBindErrorContent), className), "OK"); return; } //热更实例 object hotInstance = null; if (!t.IsSubclassOf(hotCode.GetType("JEngine.Core.JBehaviour")) && !t.IsSubclassOf(typeof(MonoBehaviour))) //JBehaviour/MonoBehaviour派生类不构造对象,不进行赋值 { hotInstance = Activator.CreateInstance(t); } var fieldsInCb = data.fields.Select(f => f.fieldName).ToList(); //全部已经设置的字段 var members = new List <MemberInfo>(0); if (Setting.ClassBindIgnorePrivate) { members.AddRange(t.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public)); members.AddRange(t.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public)); } else { members.AddRange(t.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)); members.AddRange(t.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)); } foreach (var field in members) { //跳过标签的 if (Setting.ClassBindIgnoreHideInInspector) { var attr = field.GetCustomAttributes(typeof(HideInInspector), false); if (attr.Length > 0) { continue; } } //遍历字段 EditorUtility.DisplayProgressBar(Setting.GetString(SettingString.ClassBindProgress), String.Format(Setting.GetString(SettingString.ClassBindProgressContentForGetType), $"{t.Name}:{field.Name}", members.ToList().IndexOf(field), members.Count), members.ToList().IndexOf(field) / (float)members.Count); if (!fieldsInCb.Contains(field.Name)) { ClassField cf = new ClassField(); string fieldName = field.Name; cf.fieldName = fieldName; Type fieldType = (field is PropertyInfo) ? ((PropertyInfo)field).PropertyType : ((FieldInfo)field).FieldType; SetType(cf, fieldType, hotCode); SetVal(ref cf, field, hotCode, hotInstance, instance.gameObject); data.fields.Add(cf); affectCounts++; } await Task.Delay(10); //延迟一下,动画更丝滑 } } await Task.Delay(50); //延迟一下,动画更丝滑 EditorUtility.ClearProgressBar(); //转换后保存场景 try { PrefabUtility.SavePrefabAsset(instance.gameObject, out _); } catch { try { EditorSceneManager.SaveOpenScenes(); } catch { try { var scene = SceneManager.GetActiveScene(); EditorSceneManager.SaveScene(scene, scene.path); } catch { //ignored } } } AssetDatabase.SaveAssets(); EditorUtility.ClearProgressBar(); if (toast) { EditorUtility.DisplayDialog(Setting.GetString(SettingString.ClassBindResultTitle), String.Format(Setting.GetString(SettingString.ClassBindResultContentForSetField), affectCounts, instance.name), Setting.GetString(SettingString.Done)); } else { Log.Print(String.Format(Setting.GetString(SettingString.ClassBindResultContentForSetField), affectCounts, instance.name)); } }