Unity3D 3.x現在のアクティブなウィンドウの取得

最近、私たちのチームはかなり単純なタスクに直面しました。 インベントリから他のウィンドウ(装備、チェスト)に物をドラッグする必要がありました。 2つのウィンドウが互いの上にある場合、物はより高いウィンドウに落ちるはずです。



GUIクラスのプロパティのリストをざっと見てみると、適切なものが見つかりませんでした。次に、GUIUtilityを調べ、さらにGUILayoutを調べました。 一般的に、そのようなプロパティはどこにもありませんでした。 このリクエストをグーグルで検索すると、Q&Aでいくつかの質問が発生し、オフの時点でわずかな投稿がいくつかあります。 「これはできませんが、クリックされたウィンドウを手動で追跡し、アクティブなウィンドウ変数を自分で入力する」というスタイルの回答で終わるフォーラム。

そこで提供されたものから何も得られませんでしたが、1人の男が私に興味深い考えを与えました。 C#でコードを記述します。つまり、C#Reflectionを含むこの言語のすべての利点を使用できます。



ガッツ


お気に入りのDis#をダウンロードした後、すぐにGUI関数コードにアクセスしました。



public static Rect Window(int id, Rect clientRect, GUI.WindowFunction func, string text) { return GUI.DoWindow(id, clientRect, func, GUIContent.Temp(text), GUI.skin.window, true); } internal static Rect DoWindow(int id, Rect clientRect, GUI.WindowFunction func, GUIContent title, GUIStyle style, bool forceRectOnLayout) { GUIUtility.CheckOnGUI(); GUI._Window _window = (GUI._Window)GUI._WindowList.instance.windows[id]; if (_window == null) { _window = new GUI._Window(id); GUI._WindowList.instance.windows[id] = _window; GUI.s_LayersChanged = true; } if (!_window.moved) _window.rect = clientRect; _window.moved = false; _window.opacity = 1.0F; _window.style = style; _window.title.text = title.text; _window.title.image = title.image; _window.title.tooltip = title.tooltip; _window.func = func; _window.used = true; _window.enabled = GUI.enabled; _window.color = GUI.color; _window.backgroundColor = GUI.backgroundColor; _window.matrix = GUI.matrix; _window.skin = GUI.skin; _window.contentColor = GUI.contentColor; _window.forceRect = forceRectOnLayout; return _window.rect; }
      
      





ええ、それはウィンドウのリストがあることを意味しますが、どの順序で描画されているかを調べるのは、 GUI関数を見るためです。



  public static void BringWindowToFront(int windowID) { GUIUtility.CheckOnGUI(); GUI._Window _window1 = GUI._WindowList.instance.Get(windowID); if (_window1 != null) { int i = 0; foreach (GUI._Window _window2 in GUI._WindowList.instance.windows.Values) { if (_window2.depth < i) i = _window2.depth; } _window1.depth = i - 1; GUI.s_LayersChanged = true; } }
      
      







GUIクラスには、ウィンドウのリストを持つシングルトンクラス_WindowListがあります。 各ウィンドウにはDepthがあります。 レンダリングはDepthの降順で行われます。 残っているのは、これがどのタイプのリストであるかを調べることです。



  internal sealed class _WindowList { internal Hashtable windows; internal static GUI._WindowList instance; .......
      
      





だから私たちは見つけた:)



良いものを選ぶための関数を書く


関数はよくコメントされており、うまくいけば説明は不要です。

  /// <summary> ///        /// </summary> /// <returns> /// ID    /// </returns> /// <param name='id_list'> ///  ID  /// </param> int GetTopmostId(List<int> id_list) { //  GUI Type guiType = typeof(GUI); //    Type windowListType = guiType.Assembly.GetType("UnityEngine.GUI+_WindowList"); //  instance ,      ( ) FieldInfo windowListInstanceField = windowListType.GetField("instance", BindingFlags.NonPublic | BindingFlags.Static); //  ,      object windowListInstance = windowListInstanceField.GetValue(null); //     FieldInfo windowsField = windowListType.GetField("windows", BindingFlags.NonPublic | BindingFlags.Instance); //     Hashtable Hashtable hashtable = windowsField.GetValue(windowListInstance) as Hashtable; //      int min = -1; int window_id = -1; foreach(DictionaryEntry entry in hashtable) { int key = (int)entry.Key; if (id_list.Contains(key)) //       { //      int depth = (int)entry.Value.GetType().GetField("depth", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(entry.Value); if (min < 0 || depth < min) { min = depth; window_id = key; } } } return window_id; }
      
      





注:各OnGUI()イベント関数を呼び出す場合は、それを2つの部分に分割し、 Hashtableをクラス変数に格納することをお勧めします。これにより、多くのタイプとフィールドを把握するのに時間を無駄にしないようにします。



マイナスの場合:このソリューションに代わるものはありません。ウィンドウの現在のレベルを調べる必要がある場合、これが唯一の方法です



All Articles