Compare commits

..

6 Commits
1.5.2 ... 1.5.5

Author SHA1 Message Date
d20461fa0e 1.5.5
* Fix for GetRootSceneObjects
* Tidy ups
2020-09-04 23:49:43 +10:00
72ec34090d 1.5.4 cleanup 2020-09-04 21:51:38 +10:00
883a8705c3 Update README.md 2020-09-04 21:42:09 +10:00
6adaaf5500 1.5.4
* Implemented manual unstripping for ScrollView and Resize, should now work on any Unity 2018 or 2019 game.
* Fixed a bug with page view on the Scene Explorer
* Back-end cleanups
2020-09-04 21:36:40 +10:00
5de771389e 1.5.3
* Added exception handling for scrollview when unstripping fails
* Added some better logging in some places
2020-09-04 01:27:44 +10:00
51cfbe524e Update README.md 2020-09-03 20:59:54 +10:00
18 changed files with 1010 additions and 91 deletions

View File

@ -15,9 +15,9 @@
</p>
### Known issue
Some games are experiencing `MissingMethodException`s or exceptions about failed unstripping, which prevent the CppExplorer menu from showing properly or at all. This is a bug with [Il2CppAssemblyUnhollower](https://github.com/knah/Il2CppAssemblyUnhollower) and there isn't much I can do about it myself.
Due to limitations with [Il2CppAssemblyUnhollower](https://github.com/knah/Il2CppAssemblyUnhollower)'s Unstripping, CppExplorer may encounter a `MissingMethodException` when trying to use certain UnityEngine methods.
If you're familiar with C# and Unity, one possibility for now is making a fork of this repo and manually fixing all the broken methods to ones which aren't broken (if possible). There may be another overload of the same method which wasn't stripped or was unstripped successfully, which you can use instead.
Since version [1.5.4](https://github.com/sinai-dev/CppExplorer/releases/tag/1.5.4), CppExplorer manually unstrips most of these methods itself. If you encounter more methods which failed unstripping, please let me know by opening an issue and I will do my best to fix it.
## Features
* Scene hierarchy explorer
@ -51,7 +51,9 @@ Requires [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) to be ins
CppExplorer has two main inspector modes: <b>GameObject Inspector</b>, and <b>Reflection Inspector</b>.
<b>Tip:</b> when in Tab View, GameObjects are denoted by a [G] prefix, and Reflection objects are denoted by a [R] prefix.
<b>Tips:</b>
* When in Tab View, GameObjects are denoted by a [G] prefix, and Reflection objects are denoted by a [R] prefix.
* Hold <b>Left Shift</b> when you click the Inspect button to force Reflection mode for GameObjects and Transforms.
### GameObject Inspector

View File

@ -12,7 +12,7 @@ namespace Explorer
{
public override void DrawValue(Rect window, float width)
{
UIHelpers.GameobjButton(Value, null, false, width);
UIHelpers.GOButton(Value, null, false, width);
}
public override void UpdateValue()

View File

@ -279,19 +279,15 @@ namespace Explorer
ClampLabelWidth(window, ref whitespace);
}
Pages.Count = count;
Pages.ItemCount = count;
if (count > Pages.PageLimit)
if (count > Pages.ItemsPerPage)
{
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal(null);
GUILayout.Space(whitespace);
//int maxOffset = (int)Mathf.Ceil((float)(count / (decimal)ArrayLimit)) - 1;
Pages.CalculateMaxOffset();
//GUILayout.Label($"Page {PH.ArrayOffset + 1}/{maxOffset + 1}", new GUILayoutOption[] { GUILayout.Width(80) });
Pages.CurrentPageLabel();
// prev/next page buttons
@ -317,7 +313,7 @@ namespace Explorer
//}
int offset = Pages.CalculateOffsetIndex();
for (int i = offset; i < offset + Pages.PageLimit && i < count; i++)
for (int i = offset; i < offset + Pages.ItemsPerPage && i < count; i++)
{
var entry = m_cachedEntries[i];

View File

@ -12,7 +12,7 @@ namespace Explorer
public class CppExplorer : MelonMod
{
public const string GUID = "com.sinai.cppexplorer";
public const string VERSION = "1.5.2";
public const string VERSION = "1.5.5";
public const string AUTHOR = "Sinai";
public const string NAME = "CppExplorer"
@ -99,6 +99,8 @@ namespace Explorer
public override void OnGUI()
{
if (!ShowMenu) return;
MainMenu.Instance.OnGUI();
WindowManager.Instance.OnGUI();
InspectUnderMouse.OnGUI();

View File

@ -18,8 +18,8 @@
<DebugSymbols>false</DebugSymbols>
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\Release\</OutputPath>
<DefineConstants>DEBUG</DefineConstants>
<OutputPath>..\Release\2019\</OutputPath>
<DefineConstants>Release_2019</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x64</PlatformTarget>
@ -30,7 +30,7 @@
<DebugSymbols>false</DebugSymbols>
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\Release\</OutputPath>
<OutputPath>..\Release\2018\</OutputPath>
<DefineConstants>Release_Unity2018</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
@ -44,7 +44,7 @@
</Reference>
<Reference Include="mcs">
<HintPath>..\lib\mcs.dll</HintPath>
<Private>False</Private>
<Private>True</Private>
</Reference>
<Reference Include="MelonLoader.ModHandler">
<HintPath>..\..\..\..\..\Steam\steamapps\common\Hellpoint\MelonLoader\MelonLoader.ModHandler.dll</HintPath>
@ -129,6 +129,8 @@
<Compile Include="CachedObjects\CacheMethod.cs" />
<Compile Include="CppExplorer.cs" />
<Compile Include="Extensions\ReflectionExtensions.cs" />
<Compile Include="Unstripping\GUIUnstrip.cs" />
<Compile Include="Unstripping\ScrollViewStateUnstrip.cs" />
<Compile Include="Extensions\UnityExtensions.cs" />
<Compile Include="Helpers\PageHelper.cs" />
<Compile Include="Helpers\ReflectionHelpers.cs" />
@ -136,6 +138,8 @@
<Compile Include="Helpers\UnityHelpers.cs" />
<Compile Include="MainMenu\InspectUnderMouse.cs" />
<Compile Include="CachedObjects\CacheObjectBase.cs" />
<Compile Include="Unstripping\SliderHandlerUnstrip.cs" />
<Compile Include="Unstripping\UnstripExtensions.cs" />
<Compile Include="Windows\ResizeDrag.cs" />
<Compile Include="Windows\TabViewWindow.cs" />
<Compile Include="Windows\UIWindow.cs" />

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnhollowerBaseLib;
using UnityEngine;
namespace Explorer

View File

@ -16,13 +16,23 @@ namespace Explorer
public class PageHelper
{
public int PageOffset { get; set; }
public int PageLimit { get; set; } = 20;
public int Count { get; set; }
public int MaxOffset { get; set; } = -1;
public int CalculateMaxOffset()
public int ItemsPerPage { get; set; } = 20;
public int ItemCount
{
return MaxOffset = (int)Mathf.Ceil((float)(Count / (decimal)PageLimit)) - 1;
get => m_count;
set
{
m_count = value;
CalculateMaxOffset();
}
}
private int m_count;
public int MaxPageOffset { get; private set; } = -1;
private int CalculateMaxOffset()
{
return MaxPageOffset = (int)Mathf.Ceil((float)(ItemCount / (decimal)ItemsPerPage)) - 1;
}
public void CurrentPageLabel()
@ -30,7 +40,7 @@ namespace Explorer
var orig = GUI.skin.label.alignment;
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label($"Page {PageOffset + 1}/{MaxOffset + 1}", new GUILayoutOption[] { GUILayout.Width(80) });
GUILayout.Label($"Page {PageOffset + 1}/{MaxPageOffset + 1}", new GUILayoutOption[] { GUILayout.Width(80) });
GUI.skin.label.alignment = orig;
}
@ -53,7 +63,7 @@ namespace Explorer
}
else
{
if (PageOffset < MaxOffset)
if (PageOffset < MaxPageOffset)
{
PageOffset++;
scroll = Vector2.zero;
@ -63,9 +73,9 @@ namespace Explorer
public int CalculateOffsetIndex()
{
int offset = PageOffset * PageLimit;
int offset = PageOffset * ItemsPerPage;
if (offset >= Count)
if (offset >= ItemCount)
{
offset = 0;
PageOffset = 0;
@ -77,11 +87,11 @@ namespace Explorer
public void DrawLimitInputArea()
{
GUILayout.Label("Limit: ", new GUILayoutOption[] { GUILayout.Width(50) });
var limit = this.PageLimit.ToString();
var limit = this.ItemsPerPage.ToString();
limit = GUILayout.TextField(limit, new GUILayoutOption[] { GUILayout.Width(50) });
if (limit != PageLimit.ToString() && int.TryParse(limit, out int i))
if (limit != ItemsPerPage.ToString() && int.TryParse(limit, out int i))
{
PageLimit = i;
ItemsPerPage = i;
}
}
}

View File

@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using UnhollowerRuntimeLib;
using UnityEngine;
using Object = UnityEngine.Object;
@ -22,13 +24,13 @@ namespace Explorer
}
// helper for drawing a styled button for a GameObject or Transform
public static void GameobjButton(object _obj, Action<Transform> specialInspectMethod = null, bool showSmallInspectBtn = true, float width = 380)
public static void GOButton(object _obj, Action<Transform> specialInspectMethod = null, bool showSmallInspectBtn = true, float width = 380)
{
var obj = (_obj as GameObject) ?? (_obj as Transform).gameObject;
bool children = obj.transform.childCount > 0;
bool hasChild = obj.transform.childCount > 0;
string label = children ? "[" + obj.transform.childCount + " children] " : "";
string label = hasChild ? $"[{obj.transform.childCount} children] " : "";
label += obj.name;
bool enabled = obj.activeSelf;
@ -51,10 +53,10 @@ namespace Explorer
color = Color.red;
}
FastGameobjButton(_obj, color, label, obj.activeSelf, specialInspectMethod, showSmallInspectBtn, width);
GOButton_Impl(_obj, color, label, obj.activeSelf, specialInspectMethod, showSmallInspectBtn, width);
}
public static void FastGameobjButton(object _obj, Color activeColor, string label, bool enabled, Action<Transform> specialInspectMethod = null, bool showSmallInspectBtn = true, float width = 380)
public static void GOButton_Impl(object _obj, Color activeColor, string label, bool enabled, Action<Transform> specialInspectMethod = null, bool showSmallInspectBtn = true, float width = 380)
{
var obj = _obj as GameObject ?? (_obj as Transform).gameObject;

View File

@ -51,15 +51,12 @@ namespace Explorer
public void OnGUI()
{
if (CppExplorer.ShowMenu)
{
var origSkin = GUI.skin;
GUI.skin = UIStyles.WindowSkin;
var origSkin = GUI.skin;
GUI.skin = UIStyles.WindowSkin;
MainRect = GUI.Window(MainWindowID, MainRect, (GUI.WindowFunction)MainWindow, CppExplorer.NAME);
MainRect = GUI.Window(MainWindowID, MainRect, (GUI.WindowFunction)MainWindow, CppExplorer.NAME);
GUI.skin = origSkin;
}
GUI.skin = origSkin;
}
private void MainWindow(int id)
@ -77,9 +74,12 @@ namespace Explorer
MainHeader();
var page = Pages[m_currentPage];
page.scroll = GUILayout.BeginScrollView(page.scroll, GUI.skin.scrollView);
page.scroll = GUIUnstrip.BeginScrollView(page.scroll);
page.DrawWindow();
GUILayout.EndScrollView();
GUIUnstrip.EndScrollView();
MainRect = ResizeDrag.ResizeWindow(MainRect, MainWindowID);

View File

@ -75,22 +75,27 @@ namespace Explorer
else
{
var scene = SceneManager.GetSceneByName(m_currentScene);
var rootObjects = scene.GetRootGameObjects();
foreach (var obj in rootObjects)
var list = new Il2CppSystem.Collections.Generic.List<GameObject>
{
Capacity = scene.rootCount
};
Scene.GetRootGameObjectsInternal(scene.handle, list);
foreach (var obj in list)
{
allTransforms.Add(obj.transform);
}
}
Pages.Count = allTransforms.Count;
Pages.ItemCount = allTransforms.Count;
int offset = Pages.CalculateOffsetIndex();
// sort by childcount
allTransforms.Sort((a, b) => b.childCount.CompareTo(a.childCount));
for (int i = offset; i < offset + Pages.PageLimit && i < Pages.Count; i++)
for (int i = offset; i < offset + Pages.ItemsPerPage && i < Pages.ItemCount; i++)
{
var child = allTransforms[i];
m_objectList.Add(new GameObjectCache(child.gameObject));
@ -124,7 +129,7 @@ namespace Explorer
{
m_searchResults = SearchSceneObjects(m_searchInput);
m_searching = true;
Pages.Count = m_searchResults.Count;
Pages.ItemCount = m_searchResults.Count;
}
public void CancelSearch()
@ -240,11 +245,13 @@ namespace Explorer
Pages.DrawLimitInputArea();
if (Pages.Count > Pages.PageLimit)
if (Pages.ItemCount > Pages.ItemsPerPage)
{
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
{
Pages.TurnPage(Turn.Left, ref this.scroll);
m_timeOfLastUpdate = -1f;
Update();
}
@ -253,6 +260,8 @@ namespace Explorer
if (GUILayout.Button("Next >", new GUILayoutOption[] { GUILayout.Width(80) }))
{
Pages.TurnPage(Turn.Right, ref this.scroll);
m_timeOfLastUpdate = -1f;
Update();
}
}
@ -303,7 +312,7 @@ namespace Explorer
}
else
{
UIHelpers.FastGameobjButton(obj.RefGameObject,
UIHelpers.GOButton_Impl(obj.RefGameObject,
obj.EnabledColor,
obj.Label,
obj.RefGameObject.activeSelf,
@ -328,13 +337,13 @@ namespace Explorer
{
int offset = Pages.CalculateOffsetIndex();
for (int i = offset; i < offset + Pages.PageLimit && i < m_searchResults.Count; i++)
for (int i = offset; i < offset + Pages.ItemsPerPage && i < m_searchResults.Count; i++)
{
var obj = m_searchResults[i];
if (obj.RefGameObject)
{
UIHelpers.FastGameobjButton(obj.RefGameObject,
UIHelpers.GOButton_Impl(obj.RefGameObject,
obj.EnabledColor,
obj.Label,
obj.RefGameObject.activeSelf,

View File

@ -75,7 +75,7 @@ namespace Explorer
m_searchResults.Add(cache);
}
Pages.Count = m_searchResults.Count;
Pages.ItemCount = m_searchResults.Count;
Pages.PageOffset = 0;
}
@ -104,17 +104,16 @@ namespace Explorer
GUI.skin.label.alignment = TextAnchor.UpperLeft;
int count = m_searchResults.Count;
Pages.CalculateMaxOffset();
GUILayout.BeginHorizontal(null);
Pages.DrawLimitInputArea();
if (count > Pages.PageLimit)
if (count > Pages.ItemsPerPage)
{
// prev/next page buttons
if (Pages.Count > Pages.PageLimit)
if (Pages.ItemCount > Pages.ItemsPerPage)
{
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
{
@ -132,7 +131,7 @@ namespace Explorer
GUILayout.EndHorizontal();
resultsScroll = GUILayout.BeginScrollView(resultsScroll, GUI.skin.scrollView);
resultsScroll = GUIUnstrip.BeginScrollView(resultsScroll);
var _temprect = new Rect(MainMenu.MainRect.x, MainMenu.MainRect.y, MainMenu.MainRect.width + 160, MainMenu.MainRect.height);
@ -142,7 +141,7 @@ namespace Explorer
//if (offset >= count) m_pageOffset = 0;
int offset = Pages.CalculateOffsetIndex();
for (int i = offset; i < offset + Pages.PageLimit && i < count; i++)
for (int i = offset; i < offset + Pages.ItemsPerPage && i < count; i++)
{
m_searchResults[i].Draw(MainMenu.MainRect, 0f);
//m_searchResults[i].DrawValue(MainMenu.MainRect);
@ -153,7 +152,7 @@ namespace Explorer
GUILayout.Label("<color=red><i>No results found!</i></color>", null);
}
GUILayout.EndScrollView();
GUIUnstrip.EndScrollView();
GUILayout.EndVertical();
}
catch

View File

@ -0,0 +1,427 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using MelonLoader;
using UnhollowerBaseLib;
using UnhollowerRuntimeLib;
using System.Reflection;
using UnityEngineInternal;
using Harmony;
namespace Explorer
{
// This is a copy+paste of UnityEngine source code, fixed for Il2Cpp.
// Taken from dnSpy output using Unity 2018.4.20.
// Subject to Unity's License and ToS.
// https://unity3d.com/legal/terms-of-service
// https://unity3d.com/legal/terms-of-service/software
public class GUIUnstrip
{
public static int s_ScrollControlId;
public static bool ScrollFailed = false;
public static bool ManualUnstripFailed = false;
private static GenericStack ScrollStack
{
get
{
#if Release_2019
return GUI.scrollViewStates;
#else
return GUI.s_ScrollViewStates;
#endif
}
}
// ======= public methods ======= //
// Fix for GUILayoutUtility.GetLastRect().
// Calls UnstripExtensions.GetLastUnstripped().
public static Rect GetLastRect()
{
EventType type = Event.current.type;
Rect last;
if (type != EventType.Layout && type != EventType.Used)
{
last = GUILayoutUtility.current.topLevel.GetLastUnstripped();
}
else
{
last = GUILayoutUtility.kDummyRect;
}
return last;
}
// Simple unstrips for HorizontalScrollbar and VerticalScrollbar, they just call the Scroller unstrip.
public static float HorizontalScrollbar(Rect position, float value, float size, float leftValue, float rightValue, GUIStyle style)
{
return Scroller_Impl(position, value, size, leftValue, rightValue, style,
GUI.skin.GetStyle(style.name + "thumb"),
GUI.skin.GetStyle(style.name + "leftbutton"),
GUI.skin.GetStyle(style.name + "rightbutton"),
true);
}
public static float VerticalScrollbar(Rect position, float value, float size, float topValue, float bottomValue, GUIStyle style)
{
return Scroller_Impl(position, value, size, topValue, bottomValue, style,
GUI.skin.GetStyle(style.name + "thumb"),
GUI.skin.GetStyle(style.name + "upbutton"),
GUI.skin.GetStyle(style.name + "downbutton"),
false);
}
// Fix for BeginScrollView.
// Uses several manually unstripped methods.
public static Vector2 BeginScrollView(Vector2 scroll, params GUILayoutOption[] options)
{
// First, just try normal way, may not have been stripped or was unstripped successfully.
if (!ScrollFailed)
{
try
{
return GUILayout.BeginScrollView(scroll, options);
}
catch
{
ScrollFailed = true;
return scroll;
}
}
// Try manual unstripping implementation.
if (!ManualUnstripFailed)
{
try
{
return BeginScrollView_ImplLayout(scroll, false, false, GUI.skin.horizontalScrollbar, GUI.skin.verticalScrollbar, GUI.skin.scrollView, options);
}
catch (Exception e)
{
MelonLogger.Log("Exception on GUIUnstrip.BeginScrollView_Impl: " + e.GetType() + ", " + e.Message + "\r\n" + e.StackTrace);
ManualUnstripFailed = true;
return scroll;
}
}
// Sorry! No scrolling for you.
return scroll;
}
public static void EndScrollView(bool handleScrollWheel = true)
{
// Only end the scroll view for the relevant BeginScrollView option, if any.
if (!ScrollFailed)
{
GUILayout.EndScrollView();
}
else if (!ManualUnstripFailed)
{
GUILayoutUtility.EndLayoutGroup();
EndScrollView_Impl(handleScrollWheel);
}
}
// ======= private methods ======= //
// Actual unstrip of GUILayout.BeginScrollView()
private static Vector2 BeginScrollView_ImplLayout(Vector2 scrollPosition, bool alwaysShowHorizontal, bool alwaysShowVertical,
GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, GUIStyle background, params GUILayoutOption[] options)
{
GUIUtility.CheckOnGUI();
var guiscrollGroup = GUILayoutUtility.BeginLayoutGroup(background, null, Il2CppType.Of<GUIScrollGroup>())
.TryCast<GUIScrollGroup>();
EventType type = Event.current.type;
if (type == EventType.Layout)
{
guiscrollGroup.resetCoords = true;
guiscrollGroup.isVertical = true;
guiscrollGroup.stretchWidth = 1;
guiscrollGroup.stretchHeight = 1;
guiscrollGroup.verticalScrollbar = verticalScrollbar;
guiscrollGroup.horizontalScrollbar = horizontalScrollbar;
guiscrollGroup.needsVerticalScrollbar = alwaysShowVertical;
guiscrollGroup.needsHorizontalScrollbar = alwaysShowHorizontal;
guiscrollGroup.ApplyOptions(options);
}
return BeginScrollView_Impl(guiscrollGroup.rect,
scrollPosition,
new Rect(0f, 0f, guiscrollGroup.clientWidth, guiscrollGroup.clientHeight),
alwaysShowHorizontal,
alwaysShowVertical,
horizontalScrollbar,
verticalScrollbar,
background
);
}
// Actual unstrip of GUI.BeginScrollView()
private static Vector2 BeginScrollView_Impl(Rect position, Vector2 scrollPosition, Rect viewRect, bool alwaysShowHorizontal,
bool alwaysShowVertical, GUIStyle horizontalScrollbar, GUIStyle verticalScrollbar, GUIStyle background)
{
GUIUtility.CheckOnGUI();
int controlID = GUIUtility.GetControlID(GUI.s_ScrollviewHash, FocusType.Passive);
var scrollViewState = GUIUtility.GetStateObject(Il2CppType.Of<ScrollViewState>(), controlID).TryCast<ScrollViewState>();
var scrollExt = ScrollViewStateUnstrip.FromPointer(scrollViewState.Pointer);
if (scrollExt == null) throw new Exception($"Could not get scrollExt for pointer '{scrollViewState.Pointer}'!");
bool apply = scrollExt.apply;
if (apply)
{
scrollPosition = scrollExt.scrollPosition;
scrollExt.apply = false;
}
scrollExt.position = position;
scrollExt.scrollPosition = scrollPosition;
scrollExt.visibleRect = scrollExt.viewRect = viewRect;
var rect = scrollExt.visibleRect;
rect.width = position.width;
rect.height = position.height;
ScrollStack.Push(scrollViewState);
Rect screenRect = new Rect(position);
EventType type = Event.current.type;
if (type != EventType.Layout)
{
if (type != EventType.Used)
{
bool flag = alwaysShowVertical;
bool flag2 = alwaysShowHorizontal;
if (flag2 || viewRect.width > screenRect.width)
{
rect.height = position.height - horizontalScrollbar.fixedHeight + (float)horizontalScrollbar.margin.top;
screenRect.height -= horizontalScrollbar.fixedHeight + (float)horizontalScrollbar.margin.top;
flag2 = true;
}
if (flag || viewRect.height > screenRect.height)
{
rect.width = position.width - verticalScrollbar.fixedWidth + (float)verticalScrollbar.margin.left;
screenRect.width -= verticalScrollbar.fixedWidth + (float)verticalScrollbar.margin.left;
flag = true;
if (!flag2 && viewRect.width > screenRect.width)
{
rect.height = position.height - horizontalScrollbar.fixedHeight + (float)horizontalScrollbar.margin.top;
screenRect.height -= horizontalScrollbar.fixedHeight + (float)horizontalScrollbar.margin.top;
flag2 = true;
}
}
if (Event.current.type == EventType.Repaint && background != GUIStyle.none)
{
background.Draw(position, position.Contains(Event.current.mousePosition), false, flag2 && flag, false);
}
if (flag2 && horizontalScrollbar != GUIStyle.none)
{
scrollPosition.x = HorizontalScrollbar(
new Rect(
position.x,
position.yMax - horizontalScrollbar.fixedHeight,
screenRect.width,
horizontalScrollbar.fixedHeight),
scrollPosition.x,
Mathf.Min(screenRect.width, viewRect.width),
0f,
viewRect.width,
horizontalScrollbar
);
}
else
{
GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
scrollPosition.x = ((horizontalScrollbar == GUIStyle.none) ? Mathf.Clamp(scrollPosition.x, 0f, Mathf.Max(viewRect.width - position.width, 0f)) : 0f);
}
if (flag && verticalScrollbar != GUIStyle.none)
{
scrollPosition.y = VerticalScrollbar(
new Rect(
screenRect.xMax + (float)verticalScrollbar.margin.left,
screenRect.y,
verticalScrollbar.fixedWidth,
screenRect.height),
scrollPosition.y,
Mathf.Min(screenRect.height, viewRect.height),
0f,
viewRect.height,
verticalScrollbar
);
}
else
{
GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
scrollPosition.y = ((verticalScrollbar == GUIStyle.none) ? Mathf.Clamp(scrollPosition.y, 0f, Mathf.Max(viewRect.height - position.height, 0f)) : 0f);
}
}
}
else
{
GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
GUIUtility.GetControlID(GUI.s_RepeatButtonHash, FocusType.Passive);
}
GUIClip.Push(screenRect, new Vector2(Mathf.Round(-scrollPosition.x - viewRect.x), Mathf.Round(-scrollPosition.y - viewRect.y)), Vector2.zero, false);
return scrollPosition;
}
// Actual unstrip of GUI.EndScrollView()
private static void EndScrollView_Impl(bool handleScrollWheel)
{
GUIUtility.CheckOnGUI();
if (ScrollStack.Count <= 0) return;
var state = ScrollStack.Peek().TryCast<ScrollViewState>();
var scrollExt = ScrollViewStateUnstrip.FromPointer(state.Pointer);
if (scrollExt == null) throw new Exception("Could not get scrollExt!");
GUIClip.Pop();
ScrollStack.Pop();
var position = scrollExt.position;
if (handleScrollWheel && Event.current.type == EventType.ScrollWheel && position.Contains(Event.current.mousePosition))
{
var pos = scrollExt.scrollPosition;
pos.x = Mathf.Clamp(scrollExt.scrollPosition.x + Event.current.delta.x * 20f, 0f, scrollExt.viewRect.width - scrollExt.visibleRect.width);
pos.y = Mathf.Clamp(scrollExt.scrollPosition.y + Event.current.delta.y * 20f, 0f, scrollExt.viewRect.height - scrollExt.visibleRect.height);
if (scrollExt.scrollPosition.x < 0f)
{
pos.x = 0f;
}
if (pos.y < 0f)
{
pos.y = 0f;
}
scrollExt.apply = true;
Event.current.Use();
}
}
// Actual unstrip of GUI.Scroller
private static float Scroller_Impl(Rect position, float value, float size, float leftValue, float rightValue, GUIStyle slider, GUIStyle thumb, GUIStyle leftButton, GUIStyle rightButton, bool horiz)
{
GUIUtility.CheckOnGUI();
int controlID = GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive, position);
Rect position2;
Rect rect;
Rect rect2;
if (horiz)
{
position2 = new Rect(position.x + leftButton.fixedWidth, position.y, position.width - leftButton.fixedWidth - rightButton.fixedWidth, position.height);
rect = new Rect(position.x, position.y, leftButton.fixedWidth, position.height);
rect2 = new Rect(position.xMax - rightButton.fixedWidth, position.y, rightButton.fixedWidth, position.height);
}
else
{
position2 = new Rect(position.x, position.y + leftButton.fixedHeight, position.width, position.height - leftButton.fixedHeight - rightButton.fixedHeight);
rect = new Rect(position.x, position.y, position.width, leftButton.fixedHeight);
rect2 = new Rect(position.x, position.yMax - rightButton.fixedHeight, position.width, rightButton.fixedHeight);
}
value = Slider(position2, value, size, leftValue, rightValue, slider, thumb, horiz, controlID);
bool flag = Event.current.type == EventType.MouseUp;
if (ScrollerRepeatButton_Impl(controlID, rect, leftButton))
{
value -= 10f * ((leftValue >= rightValue) ? -1f : 1f);
}
if (ScrollerRepeatButton_Impl(controlID, rect2, rightButton))
{
value += 10f * ((leftValue >= rightValue) ? -1f : 1f);
}
if (flag && Event.current.type == EventType.Used)
{
s_ScrollControlId = 0;
}
if (leftValue < rightValue)
{
value = Mathf.Clamp(value, leftValue, rightValue - size);
}
else
{
value = Mathf.Clamp(value, rightValue, leftValue - size);
}
return value;
}
// Actual unstrip of GUI.Slider
public static float Slider(Rect position, float value, float size, float start, float end, GUIStyle slider, GUIStyle thumb, bool horiz, int id)
{
if (id == 0)
{
id = GUIUtility.GetControlID(GUI.s_SliderHash, FocusType.Passive, position);
}
var sliderHandler = new SliderHandlerUnstrip(position, value, size, start, end, slider, thumb, horiz, id);
return sliderHandler.Handle();
}
// Actual unstrip of GUI.ScrollerRepeatButton
private static bool ScrollerRepeatButton_Impl(int scrollerID, Rect rect, GUIStyle style)
{
bool result = false;
if (GUI.DoRepeatButton(rect, GUIContent.none, style, FocusType.Passive))
{
bool flag = s_ScrollControlId != scrollerID;
s_ScrollControlId = scrollerID;
if (flag)
{
result = true;
GUI.nextScrollStepTime = Il2CppSystem.DateTime.Now.AddMilliseconds(250.0);
}
else if (Il2CppSystem.DateTime.Now >= GUI.nextScrollStepTime)
{
result = true;
GUI.nextScrollStepTime = Il2CppSystem.DateTime.Now.AddMilliseconds(30.0);
}
if (Event.current.type == EventType.Repaint)
{
GUI.InternalRepaintEditorWindow();
}
}
return result;
}
}
}

View File

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Harmony;
using MelonLoader;
using UnityEngine;
namespace Explorer
{
// This is a copy+paste of UnityEngine source code, fixed for Il2Cpp.
// Taken from dnSpy output using Unity 2018.4.20.
// Subject to Unity's License and ToS.
// https://unity3d.com/legal/terms-of-service
// https://unity3d.com/legal/terms-of-service/software
public class ScrollViewStateUnstrip
{
public Rect position;
public Rect visibleRect;
public Rect viewRect;
public Vector2 scrollPosition;
public bool apply;
// The code below is not unstripped.
// This is a custom dictionary to allow for the manual implementation.
public static Dictionary<IntPtr, ScrollViewStateUnstrip> Dict = new Dictionary<IntPtr, ScrollViewStateUnstrip>();
public static ScrollViewStateUnstrip FromPointer(IntPtr ptr)
{
if (!Dict.ContainsKey(ptr))
{
Dict.Add(ptr, new ScrollViewStateUnstrip());
}
return Dict[ptr];
}
}
}

View File

@ -0,0 +1,378 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnhollowerRuntimeLib;
namespace Explorer
{
// This is a copy+paste of UnityEngine source code, fixed for Il2Cpp.
// Taken from dnSpy output using Unity 2018.4.20.
// Subject to Unity's License and ToS.
// https://unity3d.com/legal/terms-of-service
// https://unity3d.com/legal/terms-of-service/software
public struct SliderHandlerUnstrip
{
private readonly Rect position;
private readonly float currentValue;
private readonly float size;
private readonly float start;
private readonly float end;
private readonly GUIStyle slider;
private readonly GUIStyle thumb;
private readonly bool horiz;
private readonly int id;
public SliderHandlerUnstrip(Rect position, float currentValue, float size, float start, float end, GUIStyle slider, GUIStyle thumb, bool horiz, int id)
{
this.position = position;
this.currentValue = currentValue;
this.size = size;
this.start = start;
this.end = end;
this.slider = slider;
this.thumb = thumb;
this.horiz = horiz;
this.id = id;
}
public float Handle()
{
float result;
if (this.slider == null || this.thumb == null)
{
result = this.currentValue;
}
else
{
switch (this.CurrentEventType())
{
case EventType.MouseDown:
return this.OnMouseDown();
case EventType.MouseUp:
return this.OnMouseUp();
case EventType.MouseDrag:
return this.OnMouseDrag();
case EventType.Repaint:
return this.OnRepaint();
}
result = this.currentValue;
}
return result;
}
private float OnMouseDown()
{
float result;
if (!this.position.Contains(this.CurrentEvent().mousePosition) || this.IsEmptySlider())
{
result = this.currentValue;
}
else
{
GUI.scrollTroughSide = 0;
GUIUtility.hotControl = this.id;
this.CurrentEvent().Use();
if (this.ThumbSelectionRect().Contains(this.CurrentEvent().mousePosition))
{
this.StartDraggingWithValue(this.ClampedCurrentValue());
result = this.currentValue;
}
else
{
GUI.changed = true;
if (this.SupportsPageMovements())
{
this.SliderState().isDragging = false;
GUI.nextScrollStepTime = SystemClock.now.AddMilliseconds(250.0);
GUI.scrollTroughSide = this.CurrentScrollTroughSide();
result = this.PageMovementValue();
}
else
{
float num = this.ValueForCurrentMousePosition();
this.StartDraggingWithValue(num);
result = this.Clamp(num);
}
}
}
return result;
}
private float OnMouseDrag()
{
float result;
if (GUIUtility.hotControl != this.id)
{
result = this.currentValue;
}
else
{
SliderState sliderState = this.SliderState();
if (!sliderState.isDragging)
{
result = this.currentValue;
}
else
{
GUI.changed = true;
this.CurrentEvent().Use();
float num = this.MousePosition() - sliderState.dragStartPos;
float value = sliderState.dragStartValue + num / this.ValuesPerPixel();
result = this.Clamp(value);
}
}
return result;
}
private float OnMouseUp()
{
if (GUIUtility.hotControl == this.id)
{
this.CurrentEvent().Use();
GUIUtility.hotControl = 0;
}
return this.currentValue;
}
private float OnRepaint()
{
this.slider.Draw(this.position, GUIContent.none, this.id);
if (!this.IsEmptySlider() && this.currentValue >= this.MinValue() && this.currentValue <= this.MaxValue())
{
this.thumb.Draw(this.ThumbRect(), GUIContent.none, this.id);
}
float result;
if (GUIUtility.hotControl != this.id || !this.position.Contains(this.CurrentEvent().mousePosition) || this.IsEmptySlider())
{
result = this.currentValue;
}
else if (this.ThumbRect().Contains(this.CurrentEvent().mousePosition))
{
if (GUI.scrollTroughSide != 0)
{
GUIUtility.hotControl = 0;
}
result = this.currentValue;
}
else
{
GUI.InternalRepaintEditorWindow();
if (SystemClock.now < GUI.nextScrollStepTime)
{
result = this.currentValue;
}
else if (this.CurrentScrollTroughSide() != GUI.scrollTroughSide)
{
result = this.currentValue;
}
else
{
GUI.nextScrollStepTime = SystemClock.now.AddMilliseconds(30.0);
if (this.SupportsPageMovements())
{
this.SliderState().isDragging = false;
GUI.changed = true;
result = this.PageMovementValue();
}
else
{
result = this.ClampedCurrentValue();
}
}
}
return result;
}
private EventType CurrentEventType()
{
return this.CurrentEvent().GetTypeForControl(this.id);
}
private int CurrentScrollTroughSide()
{
float num = (!this.horiz) ? this.CurrentEvent().mousePosition.y : this.CurrentEvent().mousePosition.x;
float num2 = (!this.horiz) ? this.ThumbRect().y : this.ThumbRect().x;
return (num <= num2) ? -1 : 1;
}
private bool IsEmptySlider()
{
return this.start == this.end;
}
private bool SupportsPageMovements()
{
return this.size != 0f && GUI.usePageScrollbars;
}
private float PageMovementValue()
{
float num = this.currentValue;
int num2 = (this.start <= this.end) ? 1 : -1;
if (this.MousePosition() > this.PageUpMovementBound())
{
num += this.size * (float)num2 * 0.9f;
}
else
{
num -= this.size * (float)num2 * 0.9f;
}
return this.Clamp(num);
}
private float PageUpMovementBound()
{
float result;
if (this.horiz)
{
result = this.ThumbRect().xMax - this.position.x;
}
else
{
result = this.ThumbRect().yMax - this.position.y;
}
return result;
}
private Event CurrentEvent()
{
return Event.current;
}
private float ValueForCurrentMousePosition()
{
float result;
if (this.horiz)
{
result = (this.MousePosition() - this.ThumbRect().width * 0.5f) / this.ValuesPerPixel() + this.start - this.size * 0.5f;
}
else
{
result = (this.MousePosition() - this.ThumbRect().height * 0.5f) / this.ValuesPerPixel() + this.start - this.size * 0.5f;
}
return result;
}
private float Clamp(float value)
{
return Mathf.Clamp(value, this.MinValue(), this.MaxValue());
}
private Rect ThumbSelectionRect()
{
return this.ThumbRect();
}
private void StartDraggingWithValue(float dragStartValue)
{
SliderState sliderState = this.SliderState();
sliderState.dragStartPos = this.MousePosition();
sliderState.dragStartValue = dragStartValue;
sliderState.isDragging = true;
}
private SliderState SliderState()
{
return (SliderState)GUIUtility.GetStateObject(Il2CppType.Of<SliderState>(), this.id).TryCast<SliderState>();
}
private Rect ThumbRect()
{
return (!this.horiz) ? this.VerticalThumbRect() : this.HorizontalThumbRect();
}
private Rect VerticalThumbRect()
{
float num = this.ValuesPerPixel();
Rect result;
if (this.start < this.end)
{
result = new Rect(this.position.x + (float)this.slider.padding.left, (this.ClampedCurrentValue() - this.start) * num + this.position.y + (float)this.slider.padding.top, this.position.width - (float)this.slider.padding.horizontal, this.size * num + this.ThumbSize());
}
else
{
result = new Rect(this.position.x + (float)this.slider.padding.left, (this.ClampedCurrentValue() + this.size - this.start) * num + this.position.y + (float)this.slider.padding.top, this.position.width - (float)this.slider.padding.horizontal, this.size * -num + this.ThumbSize());
}
return result;
}
private Rect HorizontalThumbRect()
{
float num = this.ValuesPerPixel();
Rect result;
if (this.start < this.end)
{
result = new Rect((this.ClampedCurrentValue() - this.start) * num + this.position.x + (float)this.slider.padding.left, this.position.y + (float)this.slider.padding.top, this.size * num + this.ThumbSize(), this.position.height - (float)this.slider.padding.vertical);
}
else
{
result = new Rect((this.ClampedCurrentValue() + this.size - this.start) * num + this.position.x + (float)this.slider.padding.left, this.position.y, this.size * -num + this.ThumbSize(), this.position.height);
}
return result;
}
private float ClampedCurrentValue()
{
return this.Clamp(this.currentValue);
}
private float MousePosition()
{
float result;
if (this.horiz)
{
result = this.CurrentEvent().mousePosition.x - this.position.x;
}
else
{
result = this.CurrentEvent().mousePosition.y - this.position.y;
}
return result;
}
private float ValuesPerPixel()
{
float result;
if (this.horiz)
{
result = (this.position.width - (float)this.slider.padding.horizontal - this.ThumbSize()) / (this.end - this.start);
}
else
{
result = (this.position.height - (float)this.slider.padding.vertical - this.ThumbSize()) / (this.end - this.start);
}
return result;
}
private float ThumbSize()
{
float result;
if (this.horiz)
{
result = ((this.thumb.fixedWidth == 0f) ? ((float)this.thumb.padding.horizontal) : this.thumb.fixedWidth);
}
else
{
result = ((this.thumb.fixedHeight == 0f) ? ((float)this.thumb.padding.vertical) : this.thumb.fixedHeight);
}
return result;
}
private float MaxValue()
{
return Mathf.Max(this.start, this.end) - this.size;
}
private float MinValue()
{
return Mathf.Min(this.start, this.end);
}
}
}

View File

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace Explorer
{
// This is a copy+paste of UnityEngine source code, fixed for Il2Cpp.
// Taken from dnSpy output using Unity 2018.4.20.
// Subject to Unity's License and ToS.
// https://unity3d.com/legal/terms-of-service
// https://unity3d.com/legal/terms-of-service/software
public static class UnstripExtensions
{
// This is a manual unstrip of GUILayoutGroup.GetLast().
// I'm using it as an Extension because it's easier this way.
public static Rect GetLastUnstripped(this GUILayoutGroup group)
{
Rect result;
if (group.m_Cursor == 0)
{
Debug.LogError("You cannot call GetLast immediately after beginning a group.");
result = GUILayoutEntry.kDummyRect;
}
else if (group.m_Cursor <= group.entries.Count)
{
GUILayoutEntry guilayoutEntry = group.entries[group.m_Cursor - 1];
result = guilayoutEntry.rect;
}
else
{
Debug.LogError(string.Concat(new object[]
{
"Getting control ",
group.m_Cursor,
"'s position in a group with only ",
group.entries.Count,
" controls when doing ",
Event.current.type
}));
result = GUILayoutEntry.kDummyRect;
}
return result;
}
}
}

View File

@ -73,8 +73,8 @@ namespace Explorer
m_name = m_object.name;
m_scene = string.IsNullOrEmpty(m_object.scene.name)
? "None"
: m_object.scene.name;
? "None"
: m_object.scene.name;
Update();
}
@ -96,7 +96,7 @@ namespace Explorer
list.Sort((a, b) => b.childCount.CompareTo(a.childCount));
m_children = list.ToArray();
ChildPages.Count = m_children.Length;
ChildPages.ItemCount = m_children.Length;
var list2 = new List<Component>();
foreach (var comp in m_object.GetComponents(ReflectionHelpers.ComponentType))
@ -111,7 +111,7 @@ namespace Explorer
}
m_components = list2.ToArray();
CompPages.Count = m_components.Length;
CompPages.ItemCount = m_components.Length;
}
catch (Exception e)
{
@ -121,7 +121,7 @@ namespace Explorer
private void DestroyOnException(Exception e)
{
MelonLogger.Log($"{e.GetType()}, {e.Message}");
MelonLogger.Log($"Exception drawing GameObject Window: {e.GetType()}, {e.Message}");
DestroyWindow();
}
@ -169,7 +169,7 @@ namespace Explorer
GUILayout.BeginArea(new Rect(5, 25, rect.width - 10, rect.height - 35), GUI.skin.box);
}
scroll = GUILayout.BeginScrollView(scroll, GUI.skin.scrollView);
scroll = GUIUnstrip.BeginScrollView(scroll);
GUILayout.BeginHorizontal(null);
GUILayout.Label("Scene: <color=cyan>" + (m_scene == "" ? "n/a" : m_scene) + "</color>", null);
@ -220,7 +220,7 @@ namespace Explorer
GameObjectControls();
GUILayout.EndScrollView();
GUIUnstrip.EndScrollView();
if (!WindowManager.TabView)
{
@ -237,18 +237,16 @@ namespace Explorer
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);
GUILayout.BeginVertical(GUI.skin.box, null);
m_transformScroll = GUIUnstrip.BeginScrollView(m_transformScroll);
GUILayout.Label("<b><size=15>Children</size></b>", null);
GUILayout.BeginHorizontal(null);
ChildPages.DrawLimitInputArea();
if (ChildPages.Count > ChildPages.PageLimit)
if (ChildPages.ItemCount > ChildPages.ItemsPerPage)
{
ChildPages.CalculateMaxOffset();
ChildPages.CurrentPageLabel();
GUILayout.EndHorizontal();
@ -269,7 +267,7 @@ namespace Explorer
{
int start = ChildPages.CalculateOffsetIndex();
for (int j = start; (j < start + ChildPages.PageLimit && j < ChildPages.Count); j++)
for (int j = start; (j < start + ChildPages.ItemsPerPage && j < ChildPages.ItemCount); j++)
{
var obj = m_children[j];
@ -279,7 +277,7 @@ namespace Explorer
continue;
}
UIHelpers.GameobjButton(obj.gameObject, InspectGameObject, false, m_rect.width / 2 - 80);
UIHelpers.GOButton(obj.gameObject, InspectGameObject, false, m_rect.width / 2 - 80);
}
}
else
@ -287,23 +285,21 @@ namespace Explorer
GUILayout.Label("<i>None</i>", null);
}
GUILayout.EndScrollView();
GUIUnstrip.EndScrollView();
GUILayout.EndVertical();
}
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);
GUILayout.BeginVertical(GUI.skin.box, null);
m_compScroll = GUIUnstrip.BeginScrollView(m_compScroll);
GUILayout.Label("<b><size=15>Components</size></b>", null);
GUILayout.BeginHorizontal(null);
CompPages.DrawLimitInputArea();
if (CompPages.Count > CompPages.PageLimit)
if (CompPages.ItemCount > CompPages.ItemsPerPage)
{
CompPages.CalculateMaxOffset();
CompPages.CurrentPageLabel();
GUILayout.EndHorizontal();
@ -330,7 +326,7 @@ namespace Explorer
{
int start = CompPages.CalculateOffsetIndex();
for (int j = start; (j < start + CompPages.PageLimit && j < CompPages.Count); j++)
for (int j = start; (j < start + CompPages.ItemsPerPage && j < CompPages.ItemCount); j++)
{
var component = m_components[j];
@ -369,7 +365,7 @@ namespace Explorer
}
}
GUILayout.EndScrollView();
GUIUnstrip.EndScrollView();
GUILayout.EndVertical();
}

View File

@ -256,17 +256,15 @@ namespace Explorer
GUILayout.Space(10);
Pages.Count = m_cachedMembersFiltered.Length;
Pages.ItemCount = m_cachedMembersFiltered.Length;
// prev/next page buttons
GUILayout.BeginHorizontal(null);
Pages.DrawLimitInputArea();
if (Pages.Count > Pages.PageLimit)
if (Pages.ItemCount > Pages.ItemsPerPage)
{
Pages.CalculateMaxOffset();
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
{
Pages.TurnPage(Turn.Left, ref this.scroll);
@ -283,7 +281,7 @@ namespace Explorer
// ====== BODY ======
scroll = GUILayout.BeginScrollView(scroll, GUI.skin.scrollView);
scroll = GUIUnstrip.BeginScrollView(scroll);
GUILayout.Space(10);
@ -294,7 +292,7 @@ namespace Explorer
var members = this.m_cachedMembersFiltered;
int start = Pages.CalculateOffsetIndex();
for (int j = start; (j < start + Pages.PageLimit && j < members.Length); j++)
for (int j = start; (j < start + Pages.ItemsPerPage && j < members.Length); j++)
{
var holder = members[j];
@ -311,12 +309,12 @@ namespace Explorer
GUILayout.EndHorizontal();
// if not last element
if (!(j == (start + Pages.PageLimit - 1) || j == (members.Length - 1)))
if (!(j == (start + Pages.ItemsPerPage - 1) || j == (members.Length - 1)))
UIStyles.HorizontalLine(new Color(0.07f, 0.07f, 0.07f), true);
}
GUILayout.EndVertical();
GUILayout.EndScrollView();
GUIUnstrip.EndScrollView();
if (!WindowManager.TabView)
{

View File

@ -31,7 +31,8 @@ namespace Explorer
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Button(gcDrag, GUI.skin.label, new GUILayoutOption[] { GUILayout.Height(15) });
var r = GUILayoutUtility.GetLastRect();
//var r = GUILayoutUtility.GetLastRect();
var r = GUIUnstrip.GetLastRect();
Vector2 mouse = GUIUtility.ScreenToGUIPoint(new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y));
@ -65,6 +66,7 @@ namespace Explorer
{
RESIZE_FAILED = true;
MelonLogger.Log("Exception on GuiResize: " + e.GetType() + ", " + e.Message);
MelonLogger.Log(e.StackTrace);
return origRect;
}