From 68eeee353e3d97c5568853183cd5237a383f0de1 Mon Sep 17 00:00:00 2001
From: sinaioutlander <49360850+sinaioutlander@users.noreply.github.com>
Date: Sun, 30 Aug 2020 01:08:48 +1000
Subject: [PATCH] 1.4.5 (pre-release) - Implement Tab View
* Implemented Tab View
---
src/CachedObjects/CacheMethod.cs | 67 +++++++++++++++++++++--
src/CppExplorer.cs | 54 +++++++++----------
src/CppExplorer.csproj | 1 +
src/MainMenu/MainMenu.cs | 2 +
src/Windows/GameObjectWindow.cs | 35 +++++++-----
src/Windows/ReflectionWindow.cs | 63 ++++++++++++++--------
src/Windows/ResizeDrag.cs | 9 ++++
src/Windows/TabViewWindow.cs | 91 ++++++++++++++++++++++++++++++++
src/Windows/UIWindow.cs | 21 +++++---
src/Windows/WindowManager.cs | 44 ++++++++++++---
10 files changed, 303 insertions(+), 84 deletions(-)
create mode 100644 src/Windows/TabViewWindow.cs
diff --git a/src/CachedObjects/CacheMethod.cs b/src/CachedObjects/CacheMethod.cs
index 30d4518..14659e6 100644
--- a/src/CachedObjects/CacheMethod.cs
+++ b/src/CachedObjects/CacheMethod.cs
@@ -9,30 +9,71 @@ using MelonLoader;
namespace Explorer
{
+ // TODO implement methods with primitive arguments
+
public class CacheMethod : CacheObjectBase
{
private bool m_evaluated = false;
private CacheObjectBase m_cachedReturnValue;
+ public bool HasParameters
+ {
+ get
+ {
+ if (m_hasParams == null)
+ {
+ m_hasParams = (MemberInfo as MethodInfo).GetParameters().Length > 0;
+ }
+ return (bool)m_hasParams;
+ }
+ }
+ private bool? m_hasParams;
+
+ // ======= TODO =======
+ private bool m_isEvaluating;
+ private string[] m_argumentNames;
+ private Type[] m_argumentTypes;
+ private string[] m_argumentInput;
+ // =====================
+
public static bool CanEvaluate(MethodInfo mi)
{
- if (mi.GetParameters().Length > 0 || mi.GetGenericArguments().Length > 0)
+ // generic type args not supported yet
+ if (mi.GetGenericArguments().Length > 0)
{
- // Currently methods with arguments are not supported (no good way to input them).
return false;
}
+ // TODO primitive params (commented out impl below)
+ if (mi.GetParameters().Length > 0)
+ {
+ return false;
+ }
+
+ //// only primitive and string args supported
+ //foreach (var param in mi.GetParameters())
+ //{
+ // if (!param.ParameterType.IsPrimitive && param.ParameterType != typeof(string))
+ // {
+ // return false;
+ // }
+ //}
+
return true;
}
public override void Init()
{
base.Init();
+
+ // TODO cache params
}
public override void UpdateValue()
{
base.UpdateValue();
+
+ // TODO update params (?)
}
private void Evaluate()
@@ -40,7 +81,18 @@ namespace Explorer
m_evaluated = true;
var mi = MemberInfo as MethodInfo;
- var ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, new object[0]);
+
+ object ret;
+
+ if (!HasParameters)
+ {
+ ret = mi.Invoke(mi.IsStatic ? null : DeclaringInstance, new object[0]);
+ }
+ else
+ {
+ // TODO parse params, invoke if valid
+ throw new NotImplementedException("TODO");
+ }
if (ret != null)
{
@@ -65,7 +117,14 @@ namespace Explorer
GUILayout.BeginHorizontal(null);
if (GUILayout.Button("Evaluate", new GUILayoutOption[] { GUILayout.Width(70) }))
{
- Evaluate();
+ if (HasParameters)
+ {
+ throw new NotImplementedException("TODO");
+ }
+ else
+ {
+ Evaluate();
+ }
}
GUI.skin.label.wordWrap = false;
GUILayout.Label($"{ValueType}", null);
diff --git a/src/CppExplorer.cs b/src/CppExplorer.cs
index bd66eb3..fa24cc6 100644
--- a/src/CppExplorer.cs
+++ b/src/CppExplorer.cs
@@ -99,8 +99,6 @@ namespace Explorer
public override void OnGUI()
{
- base.OnGUI();
-
MainMenu.Instance.OnGUI();
WindowManager.Instance.OnGUI();
InspectUnderMouse.OnGUI();
@@ -170,34 +168,32 @@ namespace Explorer
}
}
- // Temporarily disabled this because I don't think it's actually useful, and may in fact cause problems instead
+ // Make it appear as though UnlockMouse is disabled to the rest of the application.
- //// Make it appear as though UnlockMouse is disabled to the rest of the application.
+ [HarmonyPatch(typeof(Cursor), nameof(Cursor.visible), MethodType.Getter)]
+ public class Cursor_get_visible
+ {
+ [HarmonyPostfix]
+ public static void Postfix(ref bool __result)
+ {
+ if (ShouldForceMouse)
+ {
+ __result = m_lastVisibleState;
+ }
+ }
+ }
- //[HarmonyPatch(typeof(Cursor), nameof(Cursor.visible), MethodType.Getter)]
- //public class Cursor_get_visible
- //{
- // [HarmonyPostfix]
- // public static void Postfix(ref bool __result)
- // {
- // if (ShouldForceMouse)
- // {
- // __result = m_lastVisibleState;
- // }
- // }
- //}
-
- //[HarmonyPatch(typeof(Cursor), nameof(Cursor.lockState), MethodType.Getter)]
- //public class Cursor_get_lockState
- //{
- // [HarmonyPostfix]
- // public static void Postfix(ref CursorLockMode __result)
- // {
- // if (ShouldForceMouse)
- // {
- // __result = m_lastLockMode;
- // }
- // }
- //}
+ [HarmonyPatch(typeof(Cursor), nameof(Cursor.lockState), MethodType.Getter)]
+ public class Cursor_get_lockState
+ {
+ [HarmonyPostfix]
+ public static void Postfix(ref CursorLockMode __result)
+ {
+ if (ShouldForceMouse)
+ {
+ __result = m_lastLockMode;
+ }
+ }
+ }
}
}
diff --git a/src/CppExplorer.csproj b/src/CppExplorer.csproj
index 4b446cd..d8784ad 100644
--- a/src/CppExplorer.csproj
+++ b/src/CppExplorer.csproj
@@ -136,6 +136,7 @@
+
diff --git a/src/MainMenu/MainMenu.cs b/src/MainMenu/MainMenu.cs
index 68c1609..5081f67 100644
--- a/src/MainMenu/MainMenu.cs
+++ b/src/MainMenu/MainMenu.cs
@@ -110,6 +110,8 @@ namespace Explorer
bool mouseState = CppExplorer.ForceUnlockMouse;
bool setMouse = GUILayout.Toggle(mouseState, "Force Unlock Mouse (Left Alt)", null);
if (setMouse != mouseState) CppExplorer.ForceUnlockMouse = setMouse;
+
+ WindowManager.TabView = GUILayout.Toggle(WindowManager.TabView, "Tab View", null);
GUILayout.EndHorizontal();
GUILayout.Space(10);
diff --git a/src/Windows/GameObjectWindow.cs b/src/Windows/GameObjectWindow.cs
index b70f8c9..40043bd 100644
--- a/src/Windows/GameObjectWindow.cs
+++ b/src/Windows/GameObjectWindow.cs
@@ -11,7 +11,9 @@ namespace Explorer
{
public class GameObjectWindow : UIWindow
{
- public override string Name { get => $"GameObject Inspector ({m_object.name})"; }
+ public override string Title => WindowManager.TabView
+ ? m_object.name
+ : $"GameObject Inspector ({m_object.name})";
public GameObject m_object;
@@ -144,9 +146,13 @@ namespace Explorer
{
try
{
- Header();
+ var rect = WindowManager.TabView ? TabViewWindow.Instance.m_rect : this.m_rect;
- GUILayout.BeginArea(new Rect(5, 25, m_rect.width - 10, m_rect.height - 35), GUI.skin.box);
+ if (!WindowManager.TabView)
+ {
+ Header();
+ GUILayout.BeginArea(new Rect(5, 25, rect.width - 10, rect.height - 35), GUI.skin.box);
+ }
scroll = GUILayout.BeginScrollView(scroll, GUI.skin.scrollView);
@@ -183,12 +189,12 @@ namespace Explorer
// --- Horizontal Columns section ---
GUILayout.BeginHorizontal(null);
- GUILayout.BeginVertical(new GUILayoutOption[] { GUILayout.Width(m_rect.width / 2 - 17) });
- TransformList();
+ GUILayout.BeginVertical(new GUILayoutOption[] { GUILayout.Width(rect.width / 2 - 17) });
+ TransformList(rect);
GUILayout.EndVertical();
- GUILayout.BeginVertical(new GUILayoutOption[] { GUILayout.Width(m_rect.width / 2 - 17) });
- ComponentList();
+ GUILayout.BeginVertical(new GUILayoutOption[] { GUILayout.Width(rect.width / 2 - 17) });
+ ComponentList(rect);
GUILayout.EndVertical();
GUILayout.EndHorizontal(); // end horiz columns
@@ -197,9 +203,12 @@ namespace Explorer
GUILayout.EndScrollView();
- m_rect = ResizeDrag.ResizeWindow(m_rect, windowID);
+ if (!WindowManager.TabView)
+ {
+ m_rect = ResizeDrag.ResizeWindow(rect, windowID);
- GUILayout.EndArea();
+ GUILayout.EndArea();
+ }
}
catch (Exception e)
{
@@ -207,7 +216,7 @@ namespace Explorer
}
}
- private void TransformList()
+ private void TransformList(Rect m_rect)
{
GUILayout.BeginVertical(GUI.skin.box, null); // new GUILayoutOption[] { GUILayout.Height(250) });
m_transformScroll = GUILayout.BeginScrollView(m_transformScroll, GUI.skin.scrollView);
@@ -222,7 +231,7 @@ namespace Explorer
GUILayout.Label("null", null);
continue;
}
- UIHelpers.GameobjButton(obj.gameObject, InspectGameObject, false, this.m_rect.width / 2 - 60);
+ UIHelpers.GameobjButton(obj.gameObject, InspectGameObject, false, m_rect.width / 2 - 60);
}
foreach (var obj in m_children.Where(x => x.childCount == 0))
{
@@ -231,7 +240,7 @@ namespace Explorer
GUILayout.Label("null", null);
continue;
}
- UIHelpers.GameobjButton(obj.gameObject, InspectGameObject, false, this.m_rect.width / 2 - 60);
+ UIHelpers.GameobjButton(obj.gameObject, InspectGameObject, false, m_rect.width / 2 - 60);
}
}
else
@@ -244,7 +253,7 @@ namespace Explorer
}
- private void ComponentList()
+ private void ComponentList(Rect m_rect)
{
GUILayout.BeginVertical(GUI.skin.box, null); // new GUILayoutOption[] { GUILayout.Height(250) });
m_compScroll = GUILayout.BeginScrollView(m_compScroll, GUI.skin.scrollView);
diff --git a/src/Windows/ReflectionWindow.cs b/src/Windows/ReflectionWindow.cs
index 76f9c33..30bef67 100644
--- a/src/Windows/ReflectionWindow.cs
+++ b/src/Windows/ReflectionWindow.cs
@@ -12,7 +12,9 @@ namespace Explorer
{
public class ReflectionWindow : UIWindow
{
- public override string Name { get => $"Reflection Inspector ({ObjectType.Name})"; }
+ public override string Title => WindowManager.TabView
+ ? ObjectType.Name
+ : $"Reflection Inspector ({ObjectType.Name})";
public Type ObjectType;
@@ -172,12 +174,16 @@ namespace Explorer
{
try
{
- Header();
+ var rect = WindowManager.TabView ? TabViewWindow.Instance.m_rect : this.m_rect;
- GUILayout.BeginArea(new Rect(5, 25, m_rect.width - 10, m_rect.height - 35), GUI.skin.box);
+ if (!WindowManager.TabView)
+ {
+ Header();
+ GUILayout.BeginArea(new Rect(5, 25, rect.width - 10, rect.height - 35), GUI.skin.box);
+ }
GUILayout.BeginHorizontal(null);
- GUILayout.Label("Type: " + ObjectType.FullName + "", null);
+ GUILayout.Label("Type: " + ObjectType.FullName + "", new GUILayoutOption[] { GUILayout.Width(245f) });
if (m_uObj)
{
GUILayout.Label("Name: " + m_uObj.name, null);
@@ -192,8 +198,11 @@ namespace Explorer
if (m_component && m_component.gameObject is GameObject obj)
{
GUI.skin.label.alignment = TextAnchor.MiddleRight;
- GUILayout.Label("GameObject:", null);
- if (GUILayout.Button("" + obj.name + "", new GUILayoutOption[] { GUILayout.MaxWidth(m_rect.width - 350) }))
+ GUILayout.Label("GameObject:", new GUILayoutOption[] { GUILayout.Width(135) });
+ var charWidth = obj.name.Length * 15;
+ var maxWidth = rect.width - 350;
+ var labelWidth = charWidth < maxWidth ? charWidth : maxWidth;
+ if (GUILayout.Button("" + obj.name + "", new GUILayoutOption[] { GUILayout.Width(labelWidth) }))
{
WindowManager.InspectObject(obj, out bool _);
}
@@ -206,14 +215,7 @@ namespace Explorer
GUILayout.BeginHorizontal(null);
GUILayout.Label("Search:", new GUILayoutOption[] { GUILayout.Width(75) });
- m_search = GUILayout.TextField(m_search, null);
- GUILayout.Label("Limit per page:", new GUILayoutOption[] { GUILayout.Width(125) });
- var limitString = m_limitPerPage.ToString();
- limitString = GUILayout.TextField(limitString, new GUILayoutOption[] { GUILayout.Width(60) });
- if (int.TryParse(limitString, out int i))
- {
- m_limitPerPage = i;
- }
+ m_search = GUILayout.TextField(m_search, null);
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(null);
@@ -239,28 +241,38 @@ namespace Explorer
GUILayout.Space(10);
- int count = m_cachedMemberFiltered.Length;
+ // prev/next page buttons
+ GUILayout.BeginHorizontal(null);
+ GUILayout.Label("Limit per page:", new GUILayoutOption[] { GUILayout.Width(125) });
+ var limitString = m_limitPerPage.ToString();
+ limitString = GUILayout.TextField(limitString, new GUILayoutOption[] { GUILayout.Width(60) });
+ if (int.TryParse(limitString, out int i))
+ {
+ m_limitPerPage = i;
+ }
+
+ int count = m_cachedMemberFiltered.Length;
if (count > m_limitPerPage)
{
- // prev/next page buttons
- GUILayout.BeginHorizontal(null);
int maxOffset = (int)Mathf.Ceil((float)(count / (decimal)m_limitPerPage)) - 1;
- if (GUILayout.Button("< Prev", null))
+ if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
{
if (m_pageOffset > 0) m_pageOffset--;
scroll = Vector2.zero;
}
+ GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label($"Page {m_pageOffset + 1}/{maxOffset + 1}", new GUILayoutOption[] { GUILayout.Width(80) });
+ GUI.skin.label.alignment = TextAnchor.UpperLeft;
- if (GUILayout.Button("Next >", null))
+ if (GUILayout.Button("Next >", new GUILayoutOption[] { GUILayout.Width(80) }))
{
if (m_pageOffset < maxOffset) m_pageOffset++;
scroll = Vector2.zero;
}
- GUILayout.EndHorizontal();
}
+ GUILayout.EndHorizontal();
scroll = GUILayout.BeginScrollView(scroll, GUI.skin.scrollView);
@@ -270,9 +282,12 @@ namespace Explorer
GUILayout.EndScrollView();
- m_rect = ResizeDrag.ResizeWindow(m_rect, windowID);
+ if (!WindowManager.TabView)
+ {
+ m_rect = ResizeDrag.ResizeWindow(rect, windowID);
- GUILayout.EndArea();
+ GUILayout.EndArea();
+ }
}
catch (Exception e)
{
@@ -299,6 +314,8 @@ namespace Explorer
return;
}
+ var rect = WindowManager.TabView ? TabViewWindow.Instance.m_rect : this.m_rect;
+
UIStyles.HorizontalLine(Color.grey);
GUILayout.Label($"{title}", null);
@@ -320,7 +337,7 @@ namespace Explorer
GUILayout.BeginHorizontal(new GUILayoutOption[] { GUILayout.Height(25) });
try
{
- holder.Draw(this.m_rect, 180f);
+ holder.Draw(rect, 180f);
}
catch // (Exception e)
{
diff --git a/src/Windows/ResizeDrag.cs b/src/Windows/ResizeDrag.cs
index 7b8e3d0..e1d0f7d 100644
--- a/src/Windows/ResizeDrag.cs
+++ b/src/Windows/ResizeDrag.cs
@@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using MelonLoader;
+using UnhollowerBaseLib;
namespace Explorer
{
@@ -21,6 +22,8 @@ namespace Explorer
{
if (RESIZE_FAILED) return _rect;
+ var origRect = _rect;
+
try
{
GUILayout.BeginHorizontal(GUI.skin.box, null);
@@ -53,10 +56,16 @@ namespace Explorer
GUILayout.EndHorizontal();
}
+ catch (Il2CppException e) when (e.Message.StartsWith("System.ArgumentException"))
+ {
+ // suppress
+ return origRect;
+ }
catch (Exception e)
{
RESIZE_FAILED = true;
MelonLogger.Log("Exception on GuiResize: " + e.GetType() + ", " + e.Message);
+ return origRect;
}
GUI.skin.label.alignment = TextAnchor.UpperLeft;
diff --git a/src/Windows/TabViewWindow.cs b/src/Windows/TabViewWindow.cs
new file mode 100644
index 0000000..7008f6d
--- /dev/null
+++ b/src/Windows/TabViewWindow.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+
+namespace Explorer
+{
+ public class TabViewWindow : UIWindow
+ {
+ public override string Title => "Tab View";
+
+ public static TabViewWindow Instance => m_instance ?? (m_instance = new TabViewWindow());
+ private static TabViewWindow m_instance;
+
+ public int TargetTabID = 0;
+
+ public override bool IsTabViewWindow => true;
+
+ public TabViewWindow()
+ {
+ m_rect = new Rect(570, 0, 550, 700);
+ }
+
+ public override void Init() { }
+ public override void Update() { }
+
+ public override void WindowFunction(int windowID)
+ {
+ try
+ {
+ Header();
+
+ GUILayout.BeginArea(new Rect(5, 25, m_rect.width - 10, m_rect.height - 35), GUI.skin.box);
+
+ GUILayout.BeginVertical(GUI.skin.box, null);
+ GUILayout.BeginHorizontal(null);
+ GUI.skin.button.alignment = TextAnchor.MiddleLeft;
+ int tabPerRow = Mathf.FloorToInt((float)((decimal)m_rect.width / 238));
+ int rowCount = 0;
+ for (int i = 0; i < WindowManager.Windows.Count; i++)
+ {
+ if (rowCount >= tabPerRow)
+ {
+ rowCount = 0;
+ GUILayout.EndHorizontal();
+ GUILayout.BeginHorizontal(null);
+ }
+ rowCount++;
+
+ bool focused = i == TargetTabID;
+ string color = focused ? "" : "";
+
+ var window = WindowManager.Windows[i];
+ if (GUILayout.Button(color + window.Title + "", new GUILayoutOption[] { GUILayout.Width(200) }))
+ {
+ TargetTabID = i;
+ }
+ if (GUILayout.Button("X", new GUILayoutOption[] { GUILayout.Width(22) }))
+ {
+ window.DestroyWindow();
+ }
+ }
+ GUILayout.EndHorizontal();
+ GUILayout.EndVertical();
+ GUI.skin.button.alignment = TextAnchor.MiddleCenter;
+
+ while (TargetTabID >= WindowManager.Windows.Count)
+ {
+ TargetTabID--;
+ }
+
+ if (TargetTabID >= 0)
+ {
+ var window = WindowManager.Windows[TargetTabID];
+ window.WindowFunction(window.windowID);
+ }
+
+ try
+ {
+ m_rect = ResizeDrag.ResizeWindow(m_rect, windowID);
+ }
+ catch { }
+
+ GUILayout.EndArea();
+ }
+ catch { }
+ }
+ }
+}
diff --git a/src/Windows/UIWindow.cs b/src/Windows/UIWindow.cs
index e6df846..9bc6cc0 100644
--- a/src/Windows/UIWindow.cs
+++ b/src/Windows/UIWindow.cs
@@ -14,7 +14,7 @@ namespace Explorer
{
public abstract class UIWindow
{
- public abstract string Name { get; }
+ public abstract string Title { get; }
public object Target;
@@ -23,6 +23,8 @@ namespace Explorer
public Vector2 scroll = Vector2.zero;
+ public virtual bool IsTabViewWindow => false;
+
public abstract void Init();
public abstract void WindowFunction(int windowID);
public abstract void Update();
@@ -62,7 +64,7 @@ namespace Explorer
var origSkin = GUI.skin;
GUI.skin = UIStyles.WindowSkin;
- m_rect = GUI.Window(windowID, m_rect, (GUI.WindowFunction)WindowFunction, Name);
+ m_rect = GUI.Window(windowID, m_rect, (GUI.WindowFunction)WindowFunction, Title);
GUI.skin = origSkin;
}
@@ -70,12 +72,17 @@ namespace Explorer
public void Header()
{
- GUI.DragWindow(new Rect(0, 0, m_rect.width - 90, 20));
-
- if (GUI.Button(new Rect(m_rect.width - 90, 2, 80, 20), "X"))
+ if (!WindowManager.TabView || IsTabViewWindow)
{
- DestroyWindow();
- return;
+ GUI.DragWindow(new Rect(0, 0, m_rect.width - 90, 20));
+ }
+ if (!WindowManager.TabView)
+ {
+ if (GUI.Button(new Rect(m_rect.width - 90, 2, 80, 20), "X"))
+ {
+ DestroyWindow();
+ return;
+ }
}
}
}
diff --git a/src/Windows/WindowManager.cs b/src/Windows/WindowManager.cs
index 4f215d1..0afc67c 100644
--- a/src/Windows/WindowManager.cs
+++ b/src/Windows/WindowManager.cs
@@ -16,6 +16,8 @@ namespace Explorer
{
public static WindowManager Instance;
+ public static bool TabView = true;
+
public static List Windows = new List();
public static int CurrentWindowID { get; set; } = 500000;
private static Rect m_lastWindowRect;
@@ -27,17 +29,31 @@ namespace Explorer
public void Update()
{
- foreach (var window in Windows)
+ for (int i = 0; i < Windows.Count; i++)
{
- window.Update();
+ var window = Windows[i];
+ if (window != null)
+ {
+ window.Update();
+ }
}
}
public void OnGUI()
{
- foreach (var window in Windows)
+ if (TabView)
{
- window.OnGUI();
+ if (Windows.Count > 0)
+ {
+ TabViewWindow.Instance.OnGUI();
+ }
+ }
+ else
+ {
+ foreach (var window in Windows)
+ {
+ window.OnGUI();
+ }
}
}
@@ -119,8 +135,7 @@ namespace Explorer
if (equals)
{
- GUI.BringWindowToFront(window.windowID);
- GUI.FocusWindow(window.windowID);
+ FocusWindow(window);
return window;
}
}
@@ -136,10 +151,23 @@ namespace Explorer
}
}
+ private static void FocusWindow(UIWindow window)
+ {
+ if (!TabView)
+ {
+ GUI.BringWindowToFront(window.windowID);
+ GUI.FocusWindow(window.windowID);
+ }
+ else
+ {
+ TabViewWindow.Instance.TargetTabID = Windows.IndexOf(window);
+ }
+ }
+
private static UIWindow InspectGameObject(GameObject obj)
{
var new_window = UIWindow.CreateWindow(obj);
- GUI.FocusWindow(new_window.windowID);
+ FocusWindow(new_window);
return new_window;
}
@@ -147,7 +175,7 @@ namespace Explorer
public static UIWindow InspectReflection(object obj)
{
var new_window = UIWindow.CreateWindow(obj);
- GUI.FocusWindow(new_window.windowID);
+ FocusWindow(new_window);
return new_window;
}