Compare commits

...

3 Commits
2.0.0 ... 2.0.2

Author SHA1 Message Date
dd6cce1df1 2.0.2 2020-10-10 20:20:10 +11:00
ad54d2c76b 2.0.2
* Added support for viewing Texture2D (and Sprite) from the Inspector, and exporting them to PNG
* Fixed an issue with generic methods not showing their return value type
* Fixed an issue where destroyed UnityEngine.Objects would cause issues in the inspector
* Fixed an issue when caching a ValueCollection of a Dictionary (the generic argument for the Entry Type is the last arg, not the first as with other Enumerables)
2020-10-10 20:19:56 +11:00
867370ccee 2.0.1
* Added unstrip fix for GetRootSceneObjects using Il2CPP internal call
2020-10-09 21:11:15 +11:00
25 changed files with 915 additions and 486 deletions

View File

@ -38,8 +38,6 @@ namespace Explorer.CacheObject
{
var fi = MemInfo as FieldInfo;
fi.SetValue(fi.IsStatic ? null : DeclaringInstance, IValue.Value);
base.SetValue();
}
}
}

View File

@ -126,10 +126,12 @@ namespace Explorer.CacheObject
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label(i.ToString(), new GUILayoutOption[] { GUILayout.Width(15) });
this.m_argumentInput[i] = GUIUnstrip.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
GUILayout.Label(label, new GUILayoutOption[] { GUILayout.ExpandWidth(false) });
this.m_argumentInput[i] = GUIUnstrip.TextField(input, new GUILayoutOption[] { GUILayout.ExpandWidth(true) });
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
GUILayout.Label(label, new GUILayoutOption[0]);
GUILayout.EndHorizontal();
}

View File

@ -73,7 +73,7 @@ namespace Explorer.CacheObject
if (ret != null)
{
//m_cachedReturnValue = CacheFactory.GetTypeAndCacheObject(ret);
m_cachedReturnValue = CacheFactory.GetCacheObject(ret, IValue.ValueType);
m_cachedReturnValue = CacheFactory.GetCacheObject(ret);
m_cachedReturnValue.UpdateValue();
}
else

View File

@ -25,12 +25,22 @@ namespace Explorer.CacheObject
return;
}
//ExplorerCore.Log("Initializing InteractiveValue of type " + valueType.FullName);
InteractiveValue interactive;
if (valueType == typeof(GameObject) || valueType == typeof(Transform))
{
interactive = new InteractiveGameObject();
}
else if (valueType == typeof(Texture2D))
{
interactive = new InteractiveTexture2D();
}
else if (valueType == typeof(Sprite))
{
interactive = new InteractiveSprite();
}
else if (valueType.IsPrimitive || valueType == typeof(string))
{
interactive = new InteractivePrimitive();

View File

@ -53,8 +53,6 @@ namespace Explorer.CacheObject
var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
pi.SetValue(target, IValue.Value, ParseArguments());
base.SetValue();
}
}
}

View File

@ -19,7 +19,7 @@ namespace Explorer.Config
public int Default_Page_Limit = 20;
public bool Bitwise_Support = false;
public bool Tab_View = true;
//public bool Main_Toggle_Global = true;
public string Default_Output_Path = @"Mods\Explorer";
public static void OnLoad()
{

View File

@ -41,6 +41,7 @@
<DefineConstants>CPP,ML</DefineConstants>
<IsCpp>true</IsCpp>
<IsMelonLoader>true</IsMelonLoader>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_ML_Mono|AnyCPU' ">
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
@ -49,6 +50,7 @@
<Prefer32Bit>false</Prefer32Bit>
<IsCpp>false</IsCpp>
<IsMelonLoader>true</IsMelonLoader>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_BIE_Cpp|AnyCPU' ">
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
@ -56,6 +58,7 @@
<DefineConstants>CPP,BIE</DefineConstants>
<IsCpp>true</IsCpp>
<IsMelonLoader>false</IsMelonLoader>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_BIE_Mono|AnyCPU' ">
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
@ -63,6 +66,7 @@
<DefineConstants>MONO,BIE</DefineConstants>
<IsCpp>false</IsCpp>
<IsMelonLoader>false</IsMelonLoader>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
@ -208,6 +212,8 @@
<Compile Include="UI\InteractiveValue\Object\InteractiveDictionary.cs" />
<Compile Include="UI\InteractiveValue\Object\InteractiveEnumerable.cs" />
<Compile Include="UI\InteractiveValue\Object\InteractiveGameObject.cs" />
<Compile Include="UI\InteractiveValue\Object\InteractiveSprite.cs" />
<Compile Include="UI\InteractiveValue\Object\InteractiveTexture2D.cs" />
<Compile Include="UI\InteractiveValue\Struct\InteractiveQuaternion.cs" />
<Compile Include="UI\InteractiveValue\Struct\InteractiveRect.cs" />
<Compile Include="UI\InteractiveValue\Struct\InteractiveVector.cs" />
@ -230,7 +236,6 @@
<Compile Include="Input\InputSystem.cs" />
<Compile Include="Input\LegacyInput.cs" />
<Compile Include="Input\NoInput.cs" />
<Compile Include="Tests\TestClass.cs" />
<Compile Include="UI\Inspectors\InspectUnderMouse.cs" />
<Compile Include="UI\Inspectors\Reflection\InstanceInspector.cs" />
<Compile Include="UI\Inspectors\ReflectionInspector.cs" />
@ -254,13 +259,15 @@
<Compile Include="UI\TabViewWindow.cs" />
<Compile Include="UI\WindowBase.cs" />
<Compile Include="UI\WindowManager.cs" />
<Compile Include="UnstripFixes\GUIUnstrip.cs" />
<Compile Include="UnstripFixes\Internal_LayoutUtility.cs" />
<Compile Include="UnstripFixes\Internal_ScrollViewState.cs" />
<Compile Include="UnstripFixes\Internal_SliderHandler.cs" />
<Compile Include="Unstrip\ImageConversion\ImageConversionUnstrip.cs" />
<Compile Include="Unstrip\Scene\SceneUnstrip.cs" />
<Compile Include="Unstrip\IMGUI\GUIUnstrip.cs" />
<Compile Include="Unstrip\IMGUI\Internal_LayoutUtility.cs" />
<Compile Include="Unstrip\IMGUI\Internal_ScrollViewState.cs" />
<Compile Include="Unstrip\IMGUI\Internal_SliderHandler.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UnstripFixes\Internal.cs" />
<Compile Include="UnstripFixes\Internal_SliderState.cs" />
<Compile Include="Unstrip\IMGUI\Internal.cs" />
<Compile Include="Unstrip\IMGUI\Internal_SliderState.cs" />
</ItemGroup>
<ItemGroup>
<None Include="ILRepack.targets" />

View File

@ -10,7 +10,7 @@ namespace Explorer
public class ExplorerCore
{
public const string NAME = "Explorer " + VERSION + " (" + PLATFORM + ", " + MODLOADER + ")";
public const string VERSION = "2.0.0";
public const string VERSION = "2.0.2";
public const string AUTHOR = "Sinai";
public const string GUID = "com.sinai.explorer";
@ -68,7 +68,7 @@ namespace Explorer
if (ShowMenu)
{
//CursorControl.Update();
ForceUnlockCursor.Update();
InspectUnderMouse.Update();
MainMenu.Instance.Update();

View File

@ -2,6 +2,9 @@
using System.Reflection;
using UnityEngine;
using Explorer.Input;
#if CPP
using UnhollowerBaseLib;
#endif
namespace Explorer
{
@ -15,7 +18,7 @@ namespace Explorer
{
inputModule = new InputSystem();
}
else if (LegacyInput.TInput != null || TryLoadModule("UnityEngine.Input", LegacyInput.TInput))
else if (LegacyInput.TInput != null || TryLoadModule("UnityEngine.InputLegacyModule", LegacyInput.TInput))
{
inputModule = new LegacyInput();
}
@ -38,5 +41,34 @@ namespace Explorer
public static bool GetMouseButtonDown(int btn) => inputModule.GetMouseButtonDown(btn);
public static bool GetMouseButton(int btn) => inputModule.GetMouseButton(btn);
//#if CPP
//#pragma warning disable IDE1006
// // public extern static string compositionString { get; }
// internal delegate string get_compositionString_delegate();
// internal static get_compositionString_delegate get_compositionString_iCall =
// IL2CPP.ResolveICall<get_compositionString_delegate>("UnityEngine.Input::get_compositionString");
// public static string compositionString => get_compositionString_iCall();
// // public extern static Vector2 compositionCursorPos { get; set; }
// internal delegate Vector2 get_compositionCursorPos_delegate();
// internal static get_compositionCursorPos_delegate get_compositionCursorPos_iCall =
// IL2CPP.ResolveICall<get_compositionCursorPos_delegate>("UnityEngine.Input::get_compositionCursorPos");
// internal delegate void set_compositionCursorPos_delegate(Vector2 value);
// internal static set_compositionCursorPos_delegate set_compositionCursorPos_iCall =
// IL2CPP.ResolveICall<set_compositionCursorPos_delegate>("UnityEngine.Input::set_compositionCursorPos");
// public static Vector2 compositionCursorPos
// {
// get => get_compositionCursorPos_iCall();
// set => set_compositionCursorPos_iCall(value);
// }
//#pragma warning restore IDE1006
//#endif
}
}
}

View File

@ -3,6 +3,12 @@ using System.Collections.Generic;
using System;
using UnityEngine;
using System.Reflection;
using System.Runtime.InteropServices;
using Explorer.UI.Shared;
#if CPP
using UnhollowerBaseLib;
using UnityEngine.SceneManagement;
#endif
namespace Explorer.Tests
{
@ -28,10 +34,21 @@ namespace Explorer.Tests
public static TestClass Instance => m_instance ?? (m_instance = new TestClass());
private static TestClass m_instance;
public Texture2D TestTexture = UIStyles.MakeTex(200, 200, Color.white);
public static Sprite TestSprite;
public static int StaticProperty => 5;
public static int StaticField = 5;
public int NonStaticField;
#if CPP
public static IntPtr FindICall(string name) => il2cpp_resolve_icall(name);
[DllImport("GameAssembly", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern IntPtr il2cpp_resolve_icall([MarshalAs(UnmanagedType.LPStr)] string name);
#endif
#if CPP
public static Il2CppSystem.Collections.Generic.HashSet<string> ILHashSetTest;
#endif
@ -39,6 +56,16 @@ namespace Explorer.Tests
public TestClass()
{
#if CPP
TestTexture.name = "TestTexture";
var r = new Rect(0, 0, TestTexture.width, TestTexture.height);
var v2 = Vector2.zero;
var v4 = Vector4.zero;
TestSprite = Sprite.CreateSprite_Injected(TestTexture, ref r, ref v2, 100f, 0u, SpriteMeshType.Tight, ref v4, false);
GameObject.DontDestroyOnLoad(TestTexture);
GameObject.DontDestroyOnLoad(TestSprite);
ILHashSetTest = new Il2CppSystem.Collections.Generic.HashSet<string>();
ILHashSetTest.Add("1");
ILHashSetTest.Add("2");

View File

@ -160,7 +160,7 @@ namespace Explorer.UI.Inspectors
{
try
{
// make sure member type is Field, Method of Property (4 / 8 / 16)
// make sure member type is Field, Method or Property (4 / 8 / 16)
int m = (int)member.MemberType;
if (m < 4 || m > 16)
continue;

View File

@ -146,7 +146,7 @@ namespace Explorer.UI
{
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> ({typeName})", new GUILayoutOption[0]);
}
else if (Value == null && !(cacheMember is CacheMethod))
else if ((Value == null || Value is UnityEngine.Object uObj && !uObj) && !(cacheMember is CacheMethod))
{
GUILayout.Label($"<i>null ({typeName})</i>", new GUILayoutOption[0]);
}

View File

@ -173,38 +173,20 @@ namespace Explorer.UI
private Type GetEntryType()
{
if (m_entryType == null)
if (ValueType.IsGenericType)
{
if (OwnerCacheObject is CacheMember cacheMember && cacheMember.MemInfo != null)
{
Type memberType = null;
switch (cacheMember.MemInfo.MemberType)
{
case MemberTypes.Field:
memberType = (cacheMember.MemInfo as FieldInfo).FieldType;
break;
case MemberTypes.Property:
memberType = (cacheMember.MemInfo as PropertyInfo).PropertyType;
break;
}
var gArgs = ValueType.GetGenericArguments();
if (memberType != null && memberType.IsGenericType)
{
m_entryType = memberType.GetGenericArguments()[0];
}
}
else if (Value != null)
if (ValueType.FullName.Contains("ValueCollection"))
{
var type = Value.GetType();
if (type.IsGenericType)
{
m_entryType = type.GetGenericArguments()[0];
}
m_entryType = gArgs[gArgs.Length - 1];
}
else
{
m_entryType = gArgs[0];
}
}
// use System.Object for non-generic.
if (m_entryType == null)
else
{
m_entryType = typeof(object);
}
@ -255,18 +237,11 @@ namespace Explorer.UI
}
#endif
//ExplorerCore.Log("Caching enumeration entry " + obj.ToString() + " as " + EntryType.FullName);
var cached = new CacheEnumerated() { Index = index, RefIList = Value as IList, ParentEnumeration = this };
cached.Init(obj, EntryType);
list.Add(cached);
//if (CacheFactory.GetCacheObject(obj, t) is CacheObjectBase cached)
//{
// list.Add(cached);
//}
//else
//{
// list.Add(null);
//}
}
else
{

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace Explorer.UI
{
public class InteractiveSprite : InteractiveTexture2D
{
public override void GetTexture2D()
{
#if CPP
if (Value != null && Value.Il2CppCast(typeof(Sprite)) is Sprite sprite)
#else
if (Value is Sprite sprite)
#endif
{
currentTex = sprite.texture;
texContent = new GUIContent
{
image = currentTex
};
}
}
}
}

View File

@ -0,0 +1,254 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Explorer.CacheObject;
using Explorer.Config;
using UnityEngine;
using System.IO;
#if CPP
using Explorer.Unstrip.ImageConversion;
#endif
namespace Explorer.UI
{
public class InteractiveTexture2D : InteractiveValue, IExpandHeight
{
public bool IsExpanded { get; set; }
public float WhiteSpace { get; set; } = 215f;
public Texture2D currentTex;
public GUIContent texContent;
private string saveFolder = ModConfig.Instance.Default_Output_Path;
public override void Init()
{
base.Init();
}
public override void UpdateValue()
{
base.UpdateValue();
GetTexture2D();
}
public virtual void GetTexture2D()
{
#if CPP
if (Value != null && Value.Il2CppCast(typeof(Texture2D)) is Texture2D tex)
#else
if (Value is Texture2D tex)
#endif
{
currentTex = tex;
texContent = new GUIContent
{
image = currentTex
};
}
}
public override void DrawValue(Rect window, float width)
{
GUIUnstrip.BeginVertical();
GUIUnstrip.BeginHorizontal();
if (currentTex)
{
if (!IsExpanded)
{
if (GUILayout.Button("v", new GUILayoutOption[] { GUILayout.Width(25) }))
{
IsExpanded = true;
}
}
else
{
if (GUILayout.Button("^", new GUILayoutOption[] { GUILayout.Width(25) }))
{
IsExpanded = false;
}
}
}
base.DrawValue(window, width);
GUILayout.EndHorizontal();
if (currentTex && IsExpanded)
{
DrawTextureControls();
DrawTexture();
}
GUILayout.EndVertical();
}
// Temporarily disabled in BepInEx IL2CPP.
private void DrawTexture()
{
#if CPP
#if BIE
#else
GUILayout.Label(texContent, new GUILayoutOption[0]);
#endif
#else
GUILayout.Label(texContent, new GUILayoutOption[0]);
#endif
}
private void DrawTextureControls()
{
GUIUnstrip.BeginHorizontal();
GUILayout.Label("Save folder:", new GUILayoutOption[] { GUILayout.Width(80f) });
saveFolder = GUIUnstrip.TextField(saveFolder, new GUILayoutOption[0]);
GUIUnstrip.Space(10f);
GUILayout.EndHorizontal();
if (GUILayout.Button("Save to PNG", new GUILayoutOption[] { GUILayout.Width(100f) }))
{
if (currentTex)
{
var name = RemoveInvalidFilenameChars(currentTex.name ?? "");
if (string.IsNullOrEmpty(name))
{
if (OwnerCacheObject is CacheMember cacheMember)
{
name = cacheMember.MemInfo.Name;
}
else
{
name = "UNTITLED";
}
}
SaveTextureAsPNG(currentTex, saveFolder, name, false);
ExplorerCore.Log($@"Saved to {saveFolder}\{name}.png!");
}
else
{
ExplorerCore.Log("Cannot save a null texture!");
}
}
}
private string RemoveInvalidFilenameChars(string s)
{
var invalid = System.IO.Path.GetInvalidFileNameChars();
foreach (var c in invalid)
{
s = s.Replace(c.ToString(), "");
}
return s;
}
public static void SaveTextureAsPNG(Texture2D tex, string dir, string name, bool isDTXnmNormal = false)
{
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
byte[] data;
var savepath = dir + @"\" + name + ".png";
try
{
if (isDTXnmNormal)
{
tex = DTXnmToRGBA(tex);
tex.Apply(false, false);
}
data = tex.EncodeToPNG();
if (data == null)
{
ExplorerCore.Log("Couldn't get data with EncodeToPNG (probably ReadOnly?), trying manually...");
throw new Exception();
}
}
catch
{
var origFilter = tex.filterMode;
tex.filterMode = FilterMode.Point;
RenderTexture rt = RenderTexture.GetTemporary(tex.width, tex.height);
rt.filterMode = FilterMode.Point;
RenderTexture.active = rt;
Graphics.Blit(tex, rt);
Texture2D _newTex = new Texture2D(tex.width, tex.height, TextureFormat.RGBA32, false);
_newTex.ReadPixels(new Rect(0, 0, tex.width, tex.height), 0, 0);
if (isDTXnmNormal)
{
_newTex = DTXnmToRGBA(_newTex);
}
_newTex.Apply(false, false);
RenderTexture.active = null;
tex.filterMode = origFilter;
data = _newTex.EncodeToPNG();
//data = _newTex.GetRawTextureData();
}
if (data == null || data.Length < 1)
{
ExplorerCore.LogWarning("Couldn't get any data for the texture!");
}
else
{
#if CPP
// The IL2CPP method will return invalid byte data.
// However, we can just iterate into safe C# byte[] array.
byte[] safeData = new byte[data.Length];
for (int i = 0; i < data.Length; i++)
{
safeData[i] = (byte)data[i]; // not sure if cast is needed
}
File.WriteAllBytes(savepath, safeData);
#else
File.WriteAllBytes(savepath, data);
#endif
}
}
// Converts DTXnm-format Normal Map to RGBA-format Normal Map.
public static Texture2D DTXnmToRGBA(Texture2D tex)
{
Color[] colors = tex.GetPixels();
for (int i = 0; i < colors.Length; i++)
{
Color c = colors[i];
c.r = c.a * 2 - 1; // red <- alpha
c.g = c.g * 2 - 1; // green is always the same
Vector2 rg = new Vector2(c.r, c.g); //this is the red-green vector
c.b = Mathf.Sqrt(1 - Mathf.Clamp01(Vector2.Dot(rg, rg))); //recalculate the blue channel
colors[i] = new Color(
(c.r * 0.5f) + 0.5f,
(c.g * 0.5f) + 0.25f,
(c.b * 0.5f) + 0.5f
);
}
var newtex = new Texture2D(tex.width, tex.height, TextureFormat.RGBA32, false);
newtex.SetPixels(colors);
return newtex;
}
}
}

View File

@ -18,12 +18,14 @@ namespace Explorer.UI.Main
public int defaultPageLimit;
public bool bitwiseSupport;
public bool tabView;
public string defaultOutputPath;
private CacheObjectBase toggleKeyInput;
private CacheObjectBase defaultSizeInput;
private CacheObjectBase defaultPageLimitInput;
private CacheObjectBase bitwiseSupportInput;
private CacheObjectBase tabViewInput;
private CacheObjectBase defaultOutputPathInput;
public override void Init()
{
@ -41,6 +43,9 @@ namespace Explorer.UI.Main
tabView = ModConfig.Instance.Tab_View;
tabViewInput = CacheFactory.GetCacheObject(typeof(OptionsPage).GetField("tabView"), this);
defaultOutputPath = ModConfig.Instance.Default_Output_Path;
defaultOutputPathInput = CacheFactory.GetCacheObject(typeof(OptionsPage).GetField("defaultOutputPath"), this);
}
public override void Update() { }
@ -78,6 +83,11 @@ namespace Explorer.UI.Main
tabViewInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
GUILayout.EndHorizontal();
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
GUILayout.Label($"Default Output Path:", new GUILayoutOption[] { GUILayout.Width(215f) });
defaultOutputPathInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
GUILayout.EndHorizontal();
if (GUILayout.Button("<color=lime><b>Apply and Save</b></color>", new GUILayoutOption[0]))
{
ApplyAndSave();

View File

@ -3,17 +3,17 @@ using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
#if CPP
using Explorer.UnstripInternals;
using Explorer.Unstrip.IMGUI;
#endif
namespace Explorer
{
public class GUIUnstrip
{
public static void BeginHorizontal(params GUILayoutOption[] options)
public static void BeginHorizontal(params GUILayoutOption[] options)
=> BeginHorizontal(GUIContent.none, GUIStyle.none, options);
public static void BeginHorizontal(GUIStyle style, params GUILayoutOption[] options)
public static void BeginHorizontal(GUIStyle style, params GUILayoutOption[] options)
=> BeginHorizontal(GUIContent.none, style, options);
public static void BeginHorizontal(GUIContent content, GUIStyle style, params GUILayoutOption[] options)
@ -25,11 +25,11 @@ namespace Explorer
#endif
}
public static void BeginVertical(params GUILayoutOption[] options)
public static void BeginVertical(params GUILayoutOption[] options)
=> BeginVertical(GUIContent.none, GUIStyle.none, options);
public static void BeginVertical(GUIStyle style, params GUILayoutOption[] options)
=> BeginVertical(GUIContent.none, style, options);
=> BeginVertical(GUIContent.none, style, options);
public static void BeginVertical(GUIContent content, GUIStyle style, params GUILayoutOption[] options)
{

View File

@ -6,7 +6,7 @@ using UnityEngine;
using UnityEngineInternal;
using UnhollowerRuntimeLib;
namespace Explorer.UnstripInternals
namespace Explorer.Unstrip.IMGUI
{
public class Internal
{
@ -14,7 +14,7 @@ namespace Explorer.UnstripInternals
public static int s_ScrollControlId;
public static bool ScrollFailed = false;
public static bool ManualUnstripFailed = false;
public static bool ManualUnstripFailed = false;
public static GenericStack ScrollStack => m_scrollStack ?? GetScrollStack();
public static PropertyInfo m_scrollViewStatesInfo;
@ -73,7 +73,7 @@ namespace Explorer.UnstripInternals
if (m_stateCacheDict == null) throw new Exception();
}
catch
catch
{
m_stateCacheDict = new Dictionary<int, Il2CppSystem.Object>();
}
@ -117,7 +117,7 @@ namespace Explorer.UnstripInternals
public static string TextField(string text, GUILayoutOption[] options)
{
text = text ?? "";
text = text ?? string.Empty;
int controlID = GUIUtility.GetControlID(FocusType.Keyboard);
GUIContent guicontent = GUIContent.Temp(text);
@ -275,7 +275,7 @@ namespace Explorer.UnstripInternals
GUI.EndGroup();
}
#endregion
#endregion
#region Scrolling
@ -422,7 +422,7 @@ namespace Explorer.UnstripInternals
var scrollViewState = GetStateObject(Il2CppType.Of<ScrollViewState>(), controlID)
.TryCast<ScrollViewState>();
if (scrollViewState == null)
if (scrollViewState == null)
return scrollPosition;
var scrollExt = Internal_ScrollViewState.FromPointer(scrollViewState.Pointer);
@ -660,7 +660,7 @@ namespace Explorer.UnstripInternals
return result;
}
#endregion
#endregion
}
#region Extensions

View File

@ -1,7 +1,7 @@
#if CPP
using UnityEngine;
namespace Explorer.UnstripInternals
namespace Explorer.Unstrip.IMGUI
{
public class Internal_LayoutUtility
{
@ -85,7 +85,7 @@ namespace Explorer.UnstripInternals
last = GUILayoutUtility.kDummyRect;
}
return last;
}
}
}
}
#endif

View File

@ -3,7 +3,7 @@ using System;
using System.Collections.Generic;
using UnityEngine;
namespace Explorer.UnstripInternals
namespace Explorer.Unstrip.IMGUI
{
public class Internal_ScrollViewState
{

View File

@ -0,0 +1,411 @@
#if CPP
using System;
using UnhollowerRuntimeLib;
using UnityEngine;
namespace Explorer.Unstrip.IMGUI
{
public struct Internal_SliderHandler
{
public static int ScrollTroughSide
{
get
{
if (!m_getScrollTroughSideFailed)
{
try
{
return GUI.scrollTroughSide;
}
catch
{
m_getScrollTroughSideFailed = true;
}
}
return m_manualScrollTrough;
}
set
{
if (!m_setScrollTroughSideFailed)
{
try
{
GUI.scrollTroughSide = value;
return;
}
catch
{
m_setScrollTroughSideFailed = true;
}
}
m_manualScrollTrough = value;
}
}
private static bool m_getScrollTroughSideFailed;
private static bool m_setScrollTroughSideFailed;
private static int m_manualScrollTrough;
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 Internal_SliderHandler(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
{
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())
{
var ext = Internal_SliderState.FromPointer(GetSliderState().Pointer);
ext.isDragging = false;
Internal.nextScrollStepTime = DateTime.Now.AddMilliseconds(250.0);
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
{
var ext = Internal_SliderState.FromPointer(GetSliderState().Pointer);
if (!ext.isDragging)
{
result = this.currentValue;
}
else
{
GUI.changed = true;
this.CurrentEvent().Use();
float num = this.MousePosition() - ext.dragStartPos;
float value = ext.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 (ScrollTroughSide != 0)
{
GUIUtility.hotControl = 0;
}
result = this.currentValue;
}
else
{
GUI.InternalRepaintEditorWindow();
if (DateTime.Now < Internal.nextScrollStepTime)
{
result = this.currentValue;
}
else if (this.CurrentScrollTroughSide() != ScrollTroughSide)
{
result = this.currentValue;
}
else
{
Internal.nextScrollStepTime = DateTime.Now.AddMilliseconds(30.0);
if (this.SupportsPageMovements())
{
Internal_SliderState.FromPointer(GetSliderState().Pointer).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)
{
var ext = Internal_SliderState.FromPointer(GetSliderState().Pointer);
ext.dragStartPos = this.MousePosition();
ext.dragStartValue = dragStartValue;
ext.isDragging = true;
}
private SliderState GetSliderState()
{
return 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);
}
}
}
#endif

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Explorer.UnstripInternals
namespace Explorer.Unstrip.IMGUI
{
public class Internal_SliderState
{

View File

@ -0,0 +1,51 @@
#if CPP
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnhollowerBaseLib;
using UnityEngine;
using System.IO;
namespace Explorer.Unstrip.ImageConversion
{
public static class ImageConversionUnstrip
{
// byte[] ImageConversion.EncodeToPNG(this Texture2D image);
public static byte[] EncodeToPNG(this Texture2D tex)
{
return EncodeToPNG_iCall(tex.Pointer);
}
internal delegate byte[] EncodeToPNG_delegate(IntPtr tex);
internal static EncodeToPNG_delegate EncodeToPNG_iCall =
IL2CPP.ResolveICall<EncodeToPNG_delegate>("UnityEngine.ImageConversion::EncodeToPNG");
// bool ImageConversion.LoadImage(this Texture2D tex, byte[] data, bool markNonReadable);
public static bool LoadImage(this Texture2D tex, byte[] data, bool markNonReadable)
{
return LoadImage_iCall(tex.Pointer, data, markNonReadable);
}
internal delegate bool LoadImage_delegate(IntPtr tex, byte[] data, bool markNonReadable);
internal static LoadImage_delegate LoadImage_iCall =
IL2CPP.ResolveICall<LoadImage_delegate>("UnityEngine.ImageConversion::LoadImage");
// Helper for LoadImage
public static bool LoadImage(this Texture2D tex, string filePath, bool markNonReadable)
{
if (!File.Exists(filePath))
{
return false;
}
var data = File.ReadAllBytes(filePath);
return tex.LoadImage(data, markNonReadable);
}
}
}
#endif

View File

@ -0,0 +1,39 @@
#if CPP
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnhollowerBaseLib;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Explorer.Unstrip.Scenes
{
public class SceneUnstrip
{
//Scene.GetRootGameObjects();
public static GameObject[] GetRootGameObjects(Scene scene)
{
var list = new Il2CppSystem.Collections.Generic.List<GameObject>(GetRootCount_Internal(scene));
GetRootGameObjectsInternal_iCall(scene.handle, list.Pointer);
return list.ToArray();
}
internal delegate void GetRootGameObjectsInternal_delegate(int handle, IntPtr list);
internal static GetRootGameObjectsInternal_delegate GetRootGameObjectsInternal_iCall =
IL2CPP.ResolveICall<GetRootGameObjectsInternal_delegate>("UnityEngine.SceneManagement.Scene::GetRootGameObjectsInternal");
//Scene.rootCount;
public static int GetRootCount_Internal(UnityEngine.SceneManagement.Scene scene)
{
return GetRootCountInternal_iCall(scene.handle);
}
internal delegate int GetRootCountInternal_delegate(int handle);
internal static GetRootCountInternal_delegate GetRootCountInternal_iCall =
IL2CPP.ResolveICall<GetRootCountInternal_delegate>("UnityEngine.SceneManagement.Scene::GetRootCountInternal");
}
}
#endif

View File

@ -1,413 +0,0 @@
#if CPP
using System;
using UnhollowerRuntimeLib;
using UnityEngine;
using Explorer.UnstripInternals;
using Il2CppSystem.Reflection;
namespace Explorer.UnstripInternals
{
public struct Internal_SliderHandler
{
public static int ScrollTroughSide
{
get
{
if (!m_getScrollTroughSideFailed)
{
try
{
return GUI.scrollTroughSide;
}
catch
{
m_getScrollTroughSideFailed = true;
}
}
return m_manualScrollTrough;
}
set
{
if (!m_setScrollTroughSideFailed)
{
try
{
GUI.scrollTroughSide = value;
return;
}
catch
{
m_setScrollTroughSideFailed = true;
}
}
m_manualScrollTrough = value;
}
}
private static bool m_getScrollTroughSideFailed;
private static bool m_setScrollTroughSideFailed;
private static int m_manualScrollTrough;
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 Internal_SliderHandler(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
{
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())
{
var ext = Internal_SliderState.FromPointer(GetSliderState().Pointer);
ext.isDragging = false;
Internal.nextScrollStepTime = DateTime.Now.AddMilliseconds(250.0);
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
{
var ext = Internal_SliderState.FromPointer(GetSliderState().Pointer);
if (!ext.isDragging)
{
result = this.currentValue;
}
else
{
GUI.changed = true;
this.CurrentEvent().Use();
float num = this.MousePosition() - ext.dragStartPos;
float value = ext.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 (ScrollTroughSide != 0)
{
GUIUtility.hotControl = 0;
}
result = this.currentValue;
}
else
{
GUI.InternalRepaintEditorWindow();
if (DateTime.Now < Internal.nextScrollStepTime)
{
result = this.currentValue;
}
else if (this.CurrentScrollTroughSide() != ScrollTroughSide)
{
result = this.currentValue;
}
else
{
Internal.nextScrollStepTime = DateTime.Now.AddMilliseconds(30.0);
if (this.SupportsPageMovements())
{
Internal_SliderState.FromPointer(GetSliderState().Pointer).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)
{
var ext = Internal_SliderState.FromPointer(GetSliderState().Pointer);
ext.dragStartPos = this.MousePosition();
ext.dragStartValue = dragStartValue;
ext.isDragging = true;
}
private SliderState GetSliderState()
{
return 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);
}
}
}
#endif