EditorWindow居中显示实现/获取Unity主窗口的区域信息
简介
在编辑EditorWindow的时候,某些情况下,我们希望打开的窗口相对于Unity编辑器来说居中显示,一般情况下通过new Rect(0, 0, Screen.currentResolution.width, Screen.currentResolution.height)获得的是主显示器窗口的尺寸,但是如果Unity窗口非全屏或者使用多个显示器做开发,则无法得到正确的位置。
本文将介绍一种通过反射方式可以得到Unity主窗口位置信息的方法,同时也会提供对应的扩展实现以简化将EditorWindow居中显示
声明
本文中的内容属于个人总结整理而来,个人水平有限,对于部分细节难免有理解错误及遗漏之处,如果您在阅读过程中有所发现,希望您能指正,同时文章中的部分内容也参考了其它大神的文章,如果文章中的内容侵犯了您的权益,表示非常歉意,请您指出,我将尽快修改。
如果您进行转载,请标明出处。
Unity技术 EditorWindow居中显示实现/获取Unity主窗口的区域信息(http://www.liyubin.com/articles/2020/11/16/1605527665480.html)
获取Unity主窗口所在的区域信息
-
通过反射的方式获取需要的指定类型的所有的子类。
public static class ReflectionUtility { public static Type[] GetAllChildClasses(Type baseType, bool allowInvisible = false, bool allowAbstract = false) { var types = new List<Type>(); var assemblies = AppDomain.CurrentDomain.GetAssemblies(); var isSubclass = baseType.IsGenericType ? (Func<Type, bool>) ((type) => IsSubclassOfRawGeneric(type,baseType)) : ((type) => type.IsSubclassOf(baseType)); foreach (var assembly in assemblies) { foreach (var type in assembly.GetTypes()) { if (!isSubclass(type) ||(!type.IsVisible&&!allowInvisible) || (!allowAbstract && type.IsAbstract)) { continue; } types.Add(type); } } return types.ToArray(); } }
GetAllChildClasses函数参数说明:
- baseType:指定的基类
- allowInvisible:是否获取隐藏的类型(比如使用private,interval修饰的类型)
- allowAbstract:是否获取虚类型
-
通过反射的方式获取Unity主窗口的位置信息
public static class AppExtension { private static Rect GetEditorMainWindowPos() { var containerWinType = ReflectionUtility.GetAllChildClasses(typeof(ScriptableObject),true).Where(t => t.Name == "ContainerWindow").FirstOrDefault(); if (containerWinType == null) throw new System.MissingMemberException("Can't find internal type ContainerWindow. Maybe something has changed inside Unity"); var showModeField = containerWinType.GetField("m_ShowMode", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); var positionProperty = containerWinType.GetProperty("position", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); if (showModeField == null || positionProperty == null) throw new System.MissingFieldException("Can't find internal fields 'm_ShowMode' or 'position'. Maybe something has changed inside Unity"); var windows = Resources.FindObjectsOfTypeAll(containerWinType); foreach (var win in windows) { var showmode = (int)showModeField.GetValue(win); if (showmode == 4) // main window { var pos = (Rect)positionProperty.GetValue(win, null); return pos; } } throw new System.NotSupportedException("Can't find internal main window. Maybe something has changed inside Unity"); } }
EditorWindow窗口居中显示
我们使用扩展函数来实现窗口居中。
public static class EditorWindowExtension
{
public static void CenterOnMainWin(this EditorWindow win)
{
var main = AppExtension.GetEditorMainWindowPos();
var pos = win.position;
float w = (main.width - pos.width) * 0.5f;
float h = (main.height - pos.height) * 0.5f;
pos.x = main.x + w;
pos.y = main.y + h;
win.position = pos;
}
}
使用方式
public class LogViewer : EditorWindow
{
[MenuItem("Game/Log/Viewer")]
public static void ShowWin()
{
var viewer = GetWindow<LogViewer>();
viewer.titleContent = new GUIContent("Log Viewer");
viewer.CenterOnMainWin();
viewer.Show();
}
}
参考资料
标题:EditorWindow居中显示实现/获取Unity主窗口的区域信息
作者:liyubin
地址:http://www.liyubin.com/articles/2020/11/16/1605527665480.html