/*WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW*\ ( ( ) )
|/ \| ) ) _((_
|| (c) Wanzyee Studio < wanzyeestudio.blogspot.com > || ( ( |_ _ |=n
|\ /| _____)) | ! ] U
\.ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ./ (_(__(S) |___*/
using UnityEditor;
using System;
using System.Reflection;
namespace WanzyeeStudio.Editrix.Toolkit{
///
/// Helper to undock and fix current Game view size in pixel unit absolutely.
///
///
///
/// Apply by clicking menu "Window/View/Fix Game View Size".
/// The target window found by the order below:
/// 1. Game view with mouse over.
/// 2. Current focused Game view.
/// 3. The main Game view.
///
///
///
/// It's useful to preview the real size in Game view, pixel by pixel, not ratio scaled.
/// Set window to selected size on the aspect drop-down menu, only for "Fixed Resolution".
/// Use this to easily set size and save presets with the built-in feature.
/// It might be incorrect if the size is too big to close even over the monitor.
///
///
///
/// Note, this works by reflection to access internal classes.
/// We'd try to keep it up-to-date, but can't guarantee.
///
///
/*
* http://answers.unity3d.com/questions/179775/
*/
public static class GameViewHelper{
#region Menu
///
/// Resize game view to selected fixed resolution.
///
[MenuItem("Window/View/Fix Game View Size", false, 205)]
public static void FixGameViewSize(){
if(FixGameViewSizeValid()) FixSize();
else throw new MissingMemberException("Some reflections invalid.");
}
///
/// Check if FixGameViewSize() valid, resizable window existing.
///
/// true, if valid.
[MenuItem("Window/View/Fix Game View Size", true)]
private static bool FixGameViewSizeValid(){
EditorWindow _w;
object _s;
return GetResizable(out _w, out _s);
}
#endregion
#region Fields
///
/// Type of Game view window.
///
private static readonly Type _windowType = Type.GetType("UnityEditor.GameView, UnityEditor");
///
/// Type of UnityEditor.GameViewSize.
/// With custom setting info of game view resolution, not the displayed.
///
private static readonly Type _sizeType = Type.GetType("UnityEditor.GameViewSize, UnityEditor");
///
/// Method info to get main game view.
/// Reflect to UnityEditor.GameView.GetMainGameView().
/// It's a private static method, without params, return UnityEditor.GameView.
///
private static readonly MethodInfo _mainMehtod = new Func(() => {
if(null == _windowType) return null;
var _b = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
var _m = _windowType.GetMethod("GetMainGameView", _b, null, new Type[0], null);
return (_windowType == _m.ReturnType) ? _m : null;
})();
///
/// Property info to get current setting of game view size.
/// Reflect to UnityEditor.GameView.currentGameViewSize.
/// It's a private instance property, without indexer, return UnityEditor.GameViewSize.
///
private static readonly PropertyInfo _sizeProp = (
FindProperty(_windowType, "currentGameViewSize", _sizeType)
);
///
/// Property info to get type of game view size, 0 as AspectRatio, 1 as FixedResolution.
/// Reflect to UnityEditor.GameViewSize.sizeType.
/// It's a public instance property, without indexer, return UnityEditor.GameViewSizeType.
///
private static readonly PropertyInfo _sizeTypeProp = FindProperty(
_sizeType,
"sizeType",
Type.GetType("UnityEditor.GameViewSizeType, UnityEditor")
);
///
/// Property info to get width of game view size.
/// Reflect to UnityEditor.GameViewSize.width.
/// It's a public instance property, without indexer, return int.
///
private static readonly PropertyInfo _widthProp = (
FindProperty(_sizeType, "width", typeof(int))
);
///
/// Property info to get height of game view size.
/// Reflect to UnityEditor.GameViewSize.height.
/// It's a public instance property, without indexer, return int.
///
private static readonly PropertyInfo _heightProp = (
FindProperty(_sizeType, "height", typeof(int))
);
#endregion
#region Methods
///
/// Get the instance property of specific define type by name and return type.
///
/// The game view size property.
/// Define type.
/// Name.
/// Return type.
private static PropertyInfo FindProperty(Type defineType, string name, Type returnType){
if(null == returnType || null == defineType) return null;
var _b = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
return defineType.GetProperty(name, _b, null, returnType, new Type[0], null);
}
///
/// Undock and fix current game view size in pixel unit.
/// Set window size as Aspect Drop-Down menu, only for fixed resolution.
///
private static void FixSize(){
EditorWindow _w;
object _s;
if(!GetResizable(out _w, out _s)) return;
var _p = _w.position; //get origin
_p.width = (int)_widthProp.GetValue(_s, null);
_p.height = (int)_heightProp.GetValue(_s, null) + 17; //plus control bar
_w.position = _p; //first set back, make window out of dock
_w.position = _p; //double set to make sure resize
}
///
/// Get game view and check if able to fix size.
/// Check reflections first, then try to get and check values used.
/// Also valid for FixedResolution only.
///
/// true, if able to fix size.
/// GameView Window.
/// GameViewSize.
private static bool GetResizable(out EditorWindow window, out object size){
window = null;
size = null;
if(null == _mainMehtod || null == _sizeProp) return false;
if(null == _sizeTypeProp || null == _widthProp || null == _heightProp) return false;
window = GetCurrent();
if(null == window) return false;
size = _sizeProp.GetValue(window, null);
return (null != size) && (1 == (int)_sizeTypeProp.GetValue(size, null));
}
///
/// Get the current game view.
/// Window with mouse over first, then focused, otherwise find main.
///
/// The current window.
private static EditorWindow GetCurrent(){
if(_windowType.IsInstanceOfType(EditorWindow.mouseOverWindow)) return EditorWindow.mouseOverWindow;
else if(_windowType.IsInstanceOfType(EditorWindow.focusedWindow)) return EditorWindow.focusedWindow;
else return _mainMehtod.Invoke(null, null) as EditorWindow;
}
#endregion
}
}