/// <summary> /// 绘制依赖关系 /// </summary> /// <returns>绘制高度</returns> private int OnDependGUI(HTFFunc <string, string> getWord) { int height = 0; GUILayout.BeginHorizontal(); GUIContent gUIContent = new GUIContent(); gUIContent.image = EditorGUIUtility.IconContent("DotFrameDotted").image; gUIContent.tooltip = getWord("Dependent task point"); GUILayout.Box(gUIContent, "InvisibleButton", GUILayout.Width(20), GUILayout.Height(20)); _leftWiredOrigin = GUILayoutUtility.GetLastRect(); GUILayout.FlexibleSpace(); gUIContent.tooltip = getWord("Be dependent task point"); GUILayout.Box(gUIContent, "InvisibleButton", GUILayout.Width(20), GUILayout.Height(20)); _rightWiredOrigin = GUILayoutUtility.GetLastRect(); GUILayout.EndHorizontal(); height += 20; return(height); }
/// <summary> /// 新增拦截条件 /// </summary> /// <param name="conditionName">条件名称</param> /// <param name="interceptCondition">拦截规则</param> public void AddInterceptCondition(string conditionName, HTFFunc <MethodBase, object[], bool> interceptCondition) { if (!InterceptConditions.ContainsKey(conditionName)) { InterceptConditions.Add(conditionName, interceptCondition); } }
/// <summary> /// 绘制基础属性 /// </summary> /// <returns>绘制高度</returns> private int OnBaseGUI(HTFFunc <string, string> getWord, bool isLockID) { int height = 0; GUILayout.BeginHorizontal(); GUILayout.Label(getWord("ID") + ":", GUILayout.Width(50)); if (IsSelected) { GUI.enabled = !isLockID; GUID = EditorGUILayout.TextField(GUID); GUI.enabled = true; } else { EditorGUILayout.LabelField(GUID); } GUILayout.EndHorizontal(); height += 20; GUILayout.BeginHorizontal(); GUILayout.Label(getWord("Name") + ":", GUILayout.Width(50)); if (IsSelected) { Name = EditorGUILayout.TextField(Name); } else { EditorGUILayout.LabelField(Name); } GUILayout.EndHorizontal(); height += 20; GUILayout.BeginHorizontal(); GUILayout.Label(getWord("Details") + ":", GUILayout.Width(50)); if (IsSelected) { Details = EditorGUILayout.TextField(Details); } else { EditorGUILayout.LabelField(Details); } GUILayout.EndHorizontal(); height += 20; TaskGameObject.DrawField(Target, getWord("Target") + ":", 50, Anchor.width, getWord("Copy"), getWord("Paste")); height += 20; return(height); }
/// <summary> /// 新增拦截条件 /// </summary> /// <param name="conditionName">条件名称</param> /// <param name="interceptCondition">拦截规则</param> public void AddInterceptCondition(string conditionName, HTFFunc <MethodBase, object[], bool> interceptCondition) { if (!InterceptConditions.ContainsKey(conditionName)) { InterceptConditions.Add(conditionName, interceptCondition); } else { Log.Warning("新增拦截条件失败:已存在同名拦截条件 " + conditionName + " !"); } }
/// <summary> /// 热修复目标方法 /// </summary> /// <param name="action">目标方法</param> /// <returns>修复后的方法</returns> public HTFFunc <T1, T2, T3, TResult> FixMethod <T1, T2, T3, TResult>(HTFFunc <T1, T2, T3, TResult> action) { Delegate del = FixMethod(HotfixMethodType.HTFFunc_3Arg, action.Target.GetType().FullName + "." + action.Method.Name, typeof(HTFFunc <T1, T2, T3, TResult>)); if (del != null) { return(del as HTFFunc <T1, T2, T3, TResult>); } else { return(action); } }
/// <summary> /// 从当前类型中获取所有属性 /// </summary> /// <param name="type">类型</param> /// <param name="filter">属性筛选器</param> /// <returns>所有属性集合</returns> public static List <PropertyInfo> GetProperties(this Type type, HTFFunc <PropertyInfo, bool> filter) { List <PropertyInfo> properties = new List <PropertyInfo>(); PropertyInfo[] infos = type.GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); for (int i = 0; i < infos.Length; i++) { if (filter(infos[i])) { properties.Add(infos[i]); } } return(properties); }
/// <summary> /// 从当前类型中获取所有字段 /// </summary> /// <param name="type">类型</param> /// <param name="filter">字段筛选器</param> /// <returns>所有字段集合</returns> public static List <FieldInfo> GetFields(this Type type, HTFFunc <FieldInfo, bool> filter) { List <FieldInfo> fields = new List <FieldInfo>(); FieldInfo[] infos = type.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); for (int i = 0; i < infos.Length; i++) { if (filter(infos[i])) { fields.Add(infos[i]); } } return(fields); }
/// <summary> /// 绘制收起时GUI /// </summary> /// <returns>绘制高度</returns> private int OnCollapseGUI(HTFFunc <string, string> getWord) { int height = 0; GUILayout.BeginHorizontal(); GUILayout.Label(getWord("Name") + ":", GUILayout.Width(50)); EditorGUILayout.LabelField(Name); GUILayout.EndHorizontal(); height += 20; return(height); }
/// <summary> /// 从当前程序域的所有程序集中获取所有类型 /// </summary> /// <param name="filter">类型筛选器</param> /// <returns>所有类型集合</returns> public static List <Type> GetTypesInAllAssemblies(HTFFunc <Type, bool> filter) { List <Type> types = new List <Type>(); Assembly[] assemblys = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblys.Length; i++) { Type[] ts = assemblys[i].GetTypes(); foreach (var t in ts) { if (filter(t)) { types.Add(t); } } } return(types); }
protected override void OnEnable() { base.OnEnable(); _background = AssetDatabase.LoadAssetAtPath <Texture>("Assets/HTFramework/Editor/Main/Texture/Grid.png"); _addGC = new GUIContent(); _addGC.image = EditorGUIUtility.IconContent("d_Toolbar Plus More").image; _addGC.tooltip = "Add Task Content"; _editGC = new GUIContent(); _editGC.image = EditorGUIUtility.IconContent("d_editicon.sml").image; _editGC.tooltip = "Edit Content Script"; _deleteGC = new GUIContent(); _deleteGC.image = EditorGUIUtility.IconContent("TreeEditor.Trash").image; _deleteGC.tooltip = "Delete"; _getWord = GetWord; EditorApplication.playModeStateChanged += OnPlayModeStateChange; }
/// <summary> /// 绘制基础属性 /// </summary> /// <returns>绘制高度</returns> private int OnBaseGUI(HTFFunc <string, string> getWord, bool isLockID) { int height = 0; GUILayout.BeginHorizontal(); GUILayout.Label(getWord("ID") + ":", GUILayout.Width(50)); GUI.enabled = !isLockID; GUID = EditorGUILayout.TextField(GUID); GUI.enabled = true; GUILayout.EndHorizontal(); height += 20; GUILayout.BeginHorizontal(); GUILayout.Label(getWord("Name") + ":", GUILayout.Width(50)); Name = EditorGUILayout.TextField(Name); GUILayout.EndHorizontal(); height += 20; GUILayout.BeginHorizontal(); GUILayout.Label(getWord("Details") + ":", GUILayout.Width(50)); Details = EditorGUILayout.TextField(Details); GUILayout.EndHorizontal(); height += 20; GUILayout.BeginHorizontal(); GUILayout.Label(getWord("Points") + ":", GUILayout.Width(50)); GUILayout.Label(Points.Count.ToString()); GUILayout.EndHorizontal(); height += 20; TaskGameObject.DrawField(Target, getWord("Target") + ":", 50, _width, getWord("Copy"), getWord("Paste")); height += 20; return(height); }
/// <summary> /// 绘制编辑器GUI /// </summary> internal void OnEditorGUI(TaskContentAsset asset, HTFFunc <string, string> getWord, bool isLockID) { GUILayout.BeginVertical("ChannelStripBg", GUILayout.Width(_width), GUILayout.Height(_height)); GUILayout.BeginHorizontal(); GUILayout.Label(getWord("Task Content Property") + ":"); GUILayout.EndHorizontal(); GUILayout.Space(5); int height = 20; height += OnBaseGUI(getWord, isLockID); height += OnPropertyGUI(); if (_height != height) { _height = height; GUI.changed = true; } GUILayout.EndVertical(); }
/// <summary> /// 热修复目标方法 /// </summary> /// <param name="action">目标方法</param> /// <returns>修复后的方法</returns> public HTFFunc <T1, T2, T3, TResult> FixMethod <T1, T2, T3, TResult>(HTFFunc <T1, T2, T3, TResult> action) { return(_helper.FixMethod(action)); }
/// <summary> /// 新增拦截条件 /// </summary> /// <param name="conditionName">条件名称</param> /// <param name="interceptCondition">拦截规则</param> public void AddInterceptCondition(string conditionName, HTFFunc <MethodBase, object[], bool> interceptCondition) { _helper.AddInterceptCondition(conditionName, interceptCondition); }
/// <summary> /// 事件处理 /// </summary> internal void OnPointEventHandle(Event e, TaskContentAsset asset, TaskContentBase content, HTFFunc <string, string> getWord) { switch (e.type) { case EventType.MouseDown: if (e.button == 0) { _leftWiredOrigin.x += Anchor.x; _leftWiredOrigin.y += Anchor.y; _rightWiredOrigin.x += Anchor.x; _rightWiredOrigin.y += Anchor.y; if (_leftWiredOrigin.Contains(e.mousePosition)) { _isWired = true; _isWiredRight = false; e.Use(); } else if (_rightWiredOrigin.Contains(e.mousePosition)) { _isWired = true; _isWiredRight = true; e.Use(); } else if (Anchor.Contains(e.mousePosition)) { IsDraging = true; IsSelected = true; GUI.changed = true; GUI.FocusControl(null); e.Use(); } else { IsSelected = false; GUI.changed = true; } } else if (e.button == 1) { if (IsSelected) { _leftWiredOrigin.x += Anchor.x; _leftWiredOrigin.y += Anchor.y; _rightWiredOrigin.x += Anchor.x; _rightWiredOrigin.y += Anchor.y; if (_leftWiredOrigin.Contains(e.mousePosition)) { GenericMenu gm = new GenericMenu(); int index = content.Points.IndexOf(this); for (int i = 0; i < content.Points.Count; i++) { if (i != index) { int m = i; bool isExist = content.IsExistDepend(index, m); gm.AddItem(new GUIContent(content.Points[m].Name), isExist, () => { if (isExist) { content.DisconnectDepend(index, m); } else { content.ConnectDepend(index, m); } e.Use(); }); } } gm.ShowAsContext(); } else if (_rightWiredOrigin.Contains(e.mousePosition)) { GenericMenu gm = new GenericMenu(); int index = content.Points.IndexOf(this); for (int i = 0; i < content.Points.Count; i++) { if (i != index) { int m = i; bool isExist = content.IsExistDepend(m, index); gm.AddItem(new GUIContent(content.Points[m].Name), isExist, () => { if (isExist) { content.DisconnectDepend(m, index); } else { content.ConnectDepend(m, index); } e.Use(); }); } } gm.ShowAsContext(); } else if (Anchor.Contains(e.mousePosition)) { GenericMenu gm = new GenericMenu(); gm.AddItem(new GUIContent(getWord("Edit Point Script")), false, () => { MonoScript monoScript = MonoScript.FromScriptableObject(this); AssetDatabase.OpenAsset(monoScript); e.Use(); }); gm.AddItem(new GUIContent(getWord("Delete Point")), false, () => { if (EditorUtility.DisplayDialog("Delete Task Point", "Are you sure you want to delete task point [" + Name + "]?", "Yes", "No")) { DeletePoint(asset, content); GUI.changed = true; e.Use(); } }); OnRightClickMenu(gm); gm.ShowAsContext(); } } } break; case EventType.MouseUp: if (_isWired) { int chooseIndex; if (ChoosePoint(e.mousePosition, content, out chooseIndex)) { int originIndex = content.Points.IndexOf(this); if (originIndex != chooseIndex) { if (_isWiredRight) { if (content.IsExistDepend(chooseIndex, originIndex)) { content.DisconnectDepend(chooseIndex, originIndex); } else { content.ConnectDepend(chooseIndex, originIndex); } } else { if (content.IsExistDepend(originIndex, chooseIndex)) { content.DisconnectDepend(originIndex, chooseIndex); } else { content.ConnectDepend(originIndex, chooseIndex); } } } e.Use(); } _isWired = false; GUI.changed = true; } IsDraging = false; break; case EventType.MouseDrag: if (_isWired) { GUI.changed = true; } else if (IsDraging) { OnDrag(e.delta); GUI.changed = true; } break; case EventType.KeyDown: switch (e.keyCode) { case KeyCode.Delete: if (IsSelected) { if (EditorUtility.DisplayDialog("Delete Task Point", "Are you sure you want to delete task point [" + Name + "]?", "Yes", "No")) { DeletePoint(asset, content); GUI.changed = true; } } break; } break; } }
/// <summary> /// 从模板创建脚本 /// </summary> /// <param name="prefsKey">脚本配置路径Key</param> /// <param name="scriptType">脚本类型</param> /// <param name="templateName">脚本模板名称</param> /// <param name="handler">自定义处理者</param> /// <param name="replace">脚本替换字段</param> /// <returns>脚本名称</returns> public static string CreateScriptFormTemplate(string prefsKey, string scriptType, string templateName, HTFFunc <string, string> handler, params string[] replace) { string directory = EditorPrefs.GetString(prefsKey, ""); string fullPath = Application.dataPath + directory; if (!Directory.Exists(fullPath)) { fullPath = Application.dataPath; } string path = EditorUtility.SaveFilePanel("Create " + scriptType + " Class", fullPath, "New" + scriptType, "cs"); if (!string.IsNullOrEmpty(path)) { if (!path.Contains(Application.dataPath)) { Log.Error("新建 " + scriptType + " 失败:创建路径必须在当前项目的 Assets 路径下!"); return("<None>"); } string className = path.Substring(path.LastIndexOf("/") + 1).Replace(".cs", ""); if (!File.Exists(path)) { TextAsset asset = AssetDatabase.LoadAssetAtPath(EditorPrefsTable.ScriptTemplateFolder + templateName + ".txt", typeof(TextAsset)) as TextAsset; if (asset) { string code = asset.text; code = code.Replace("#SCRIPTNAME#", className); if (replace != null && replace.Length > 0) { for (int i = 0; i < replace.Length; i++) { code = code.Replace(replace[i], className); } } if (handler != null) { code = handler(code); } File.AppendAllText(path, code, Encoding.UTF8); asset = null; AssetDatabase.Refresh(); string assetPath = path.Substring(path.LastIndexOf("Assets")); TextAsset csFile = AssetDatabase.LoadAssetAtPath(assetPath, typeof(TextAsset)) as TextAsset; EditorGUIUtility.PingObject(csFile); Selection.activeObject = csFile; AssetDatabase.OpenAsset(csFile); EditorPrefs.SetString(prefsKey, path.Substring(0, path.LastIndexOf("/")).Replace(Application.dataPath, "")); return(className); } else { Log.Error("新建 " + scriptType + " 失败:丢失脚本模板文件!"); } } else { Log.Error("新建 " + scriptType + " 失败:已存在类文件 " + className); } } return("<None>"); }
/// <summary> /// 绘制编辑器GUI /// </summary> internal void OnEditorGUI(TaskContentAsset asset, TaskContentBase content, HTFFunc <string, string> getWord, bool isLockID) { if (IsComplete) { GUI.backgroundColor = Color.green; } else if (!IsEnable) { GUI.backgroundColor = Color.gray; } else { GUI.backgroundColor = IsSelected ? Color.yellow : Color.white; } GUILayout.BeginArea(Anchor, ShowName, "Window"); GUI.backgroundColor = Color.white; int height = 25; height += OnDependGUI(getWord); if (IsExpand) { height += OnToolbarGUI(asset, content); height += OnBaseGUI(getWord, isLockID); height += OnPropertyGUI(); } else { height += OnCollapseGUI(getWord); } Anchor.width = _width; if ((int)Anchor.height != height) { Anchor.height = height; GUI.changed = true; } GUILayout.EndArea(); string icon = IsEnable ? "animationvisibilitytoggleon" : "animationvisibilitytoggleoff"; GUIContent gUIContent = new GUIContent(); gUIContent.image = EditorGUIUtility.IconContent(icon).image; gUIContent.tooltip = IsEnable ? "Enable" : "Disable"; if (GUI.Button(new Rect(Anchor.x + Anchor.width - 40, Anchor.y - 2, 20, 20), gUIContent, "InvisibleButton")) { IsEnable = !IsEnable; GUI.changed = true; } gUIContent.image = EditorGUIUtility.IconContent("LookDevPaneOption").image; gUIContent.tooltip = IsExpand ? "Expand" : "Collapse"; if (GUI.Button(new Rect(Anchor.x + Anchor.width - 25, Anchor.y, 20, 20), gUIContent, "InvisibleButton")) { IsExpand = !IsExpand; GUI.changed = true; } OnWiredGUI(); }
/// <summary> /// 注册【新建任务点脚本】时的自定义处理者 /// </summary> /// <param name="handler">自定义处理者</param> public static void RegisterNewTaskPointScriptHandler(HTFFunc <string, string> handler) { NewTaskPointScriptHandler = handler; }