mirror of
https://github.com/sinai-dev/UnityExplorer.git
synced 2025-06-24 01:12:41 +08:00
Compare commits
27 Commits
Author | SHA1 | Date | |
---|---|---|---|
39d9585f1d | |||
2d414e544b | |||
513fcaa534 | |||
b41f7211e5 | |||
dd6cce1df1 | |||
ad54d2c76b | |||
867370ccee | |||
35eb78ca5d | |||
f1c3771c24 | |||
b012e2305c | |||
e309821743 | |||
56bedc9c6b | |||
59c5b13a05 | |||
b8b6cc1605 | |||
912b1b80ff | |||
6a9c64c2a1 | |||
54deecd312 | |||
403943a41f | |||
e7aa01ebc8 | |||
bf6d526284 | |||
c991cb4b22 | |||
3971e49ce1 | |||
6920ca1129 | |||
748e0cabcb | |||
b4b5f1ec93 | |||
5afaf85859 | |||
b65e417ecb |
132
README.md
132
README.md
@ -12,114 +12,82 @@
|
|||||||
<img src="https://img.shields.io/github/downloads/sinai-dev/Explorer/total.svg" />
|
<img src="https://img.shields.io/github/downloads/sinai-dev/Explorer/total.svg" />
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
- [Current status](#current-status)
|
- [Releases](#releases)
|
||||||
- [How to install](#how-to-install)
|
|
||||||
- [How to use](#how-to-use)
|
|
||||||
- [Mod Config](#mod-config)
|
|
||||||
- [Features](#features)
|
- [Features](#features)
|
||||||
- [Mouse Control](#mouse-control)
|
- [How to install](#how-to-install)
|
||||||
|
- [Mod Config](#mod-config)
|
||||||
|
- [Mouse Control](#mouse-control)
|
||||||
- [Building](#building)
|
- [Building](#building)
|
||||||
- [Credits](#credits)
|
- [Credits](#credits)
|
||||||
|
|
||||||
## Current status
|
## Releases
|
||||||
|
|
||||||
| Mod Loader | Il2Cpp | Mono | Mono (.NET 3.5) |
|
| Mod Loader | Il2Cpp | Mono |
|
||||||
| ----------- | ------ | ---- | ----|
|
| ----------- | ------ | ---- |
|
||||||
| [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) | ✔️ [link](https://github.com/sinai-dev/Explorer/releases/latest/download/Explorer.MelonLoader.Il2Cpp.zip) | ✔️ [link](https://github.com/sinai-dev/Explorer/releases/latest/download/Explorer.MelonLoader.Mono.zip) | ✔️ [link](https://github.com/sinai-dev/Explorer/releases/latest/download/Explorer.MelonLoader.Mono.NET35.zip) |
|
| [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) | ✔️ [link](https://github.com/sinai-dev/Explorer/releases/latest/download/Explorer.MelonLoader.Il2Cpp.zip) | ✔️ [link](https://github.com/sinai-dev/Explorer/releases/latest/download/Explorer.MelonLoader.Mono.zip) |
|
||||||
| [BepInEx](https://github.com/BepInEx/BepInEx) | ❔ [link](https://github.com/sinai-dev/Explorer/releases/latest/download/Explorer.BepInEx.Il2Cpp.zip) | ✔️ [link](https://github.com/sinai-dev/Explorer/releases/latest/download/Explorer.BepInEx.Mono.zip) | ✔️ [link](https://github.com/sinai-dev/Explorer/releases/latest/download/Explorer.BepInEx.Mono.NET35.zip) |
|
| [BepInEx](https://github.com/BepInEx/BepInEx) | ❔ [link](https://github.com/sinai-dev/Explorer/releases/latest/download/Explorer.BepInEx.Il2Cpp.zip) | ✔️ [link](https://github.com/sinai-dev/Explorer/releases/latest/download/Explorer.BepInEx.Mono.zip) |
|
||||||
|
|
||||||
<b>IL2CPP Issues:</b>
|
<b>Il2Cpp Issues:</b>
|
||||||
* .NET 3.5 is not currently supported (Unity 5.6.1 and older), this might change in the future.
|
* Some methods may still fail with a `MissingMethodException`, please let me know if you experience this (with full debug log please).
|
||||||
* Some methods may still fail with a `MissingMethodException`, please let me know if you experience this (with full MelonLoader log please).
|
|
||||||
* Reflection may fail with certain types, see [here](https://github.com/knah/Il2CppAssemblyUnhollower#known-issues) for more details.
|
* Reflection may fail with certain types, see [here](https://github.com/knah/Il2CppAssemblyUnhollower#known-issues) for more details.
|
||||||
* Scrolling with mouse wheel in the Explorer menu may not work on all games at the moment.
|
* Scrolling with mouse wheel in the Explorer menu may not work on all games at the moment.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://raw.githubusercontent.com/sinai-dev/Explorer/master/overview.png">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
* <b>Scene Explorer</b>: Simple menu to traverse the Transform heirarchy of the scene.
|
||||||
|
* <b>GameObject Inspector</b>: Various helpful tools to see and manipulate the GameObject, similar to what you can do in the Editor.
|
||||||
|
* <b>Reflection Inspector</b>: Inspect Properties and Fields. Can also set primitive values and evaluate primitive methods.
|
||||||
|
* <b>Search</b>: Search for UnityEngine.Objects with various filters, or use the helpers for static Instances and Classes.
|
||||||
|
* <b>C# Console</b>: Interactive console for evaluating C# methods on the fly, with some basic helpers.
|
||||||
|
* <b>Inspect-under-mouse</b>: Hover over an object with a collider and inspect it by clicking on it.
|
||||||
|
|
||||||
## How to install
|
## How to install
|
||||||
|
|
||||||
### MelonLoader
|
### MelonLoader
|
||||||
Requires [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) to be installed for your game.
|
Requires [MelonLoader](https://github.com/HerpDerpinstine/MelonLoader) to be installed for your game.
|
||||||
|
|
||||||
1. Download the relevant <b>Explorer_MelonLoader_.zip</b> from above.
|
1. Download the relevant release from above.
|
||||||
2. Unzip the file into the `Mods` folder in your game's installation directory, created by MelonLoader.
|
2. Unzip the file into the `Mods` folder in your game's installation directory, created by MelonLoader.
|
||||||
3. Make sure it's not in a sub-folder, `Explorer.dll` and `mcs.dll` should be directly in the `Mods\` folder.
|
3. Make sure it's not in a sub-folder, `Explorer.dll` should be directly in the `Mods\` folder.
|
||||||
|
|
||||||
### BepInEx
|
### BepInEx
|
||||||
Requires [BepInEx](https://github.com/BepInEx/BepInEx) to be installed for your game.
|
Requires [BepInEx](https://github.com/BepInEx/BepInEx) to be installed for your game.
|
||||||
|
|
||||||
1. Download the relevant <b>Explorer_BepInEx_.zip</b> from above.
|
1. Download the relevant release from above.
|
||||||
2. Unzip the file into the `BepInEx\plugins\` folder in your game's installation directory, created by BepInEx.
|
2. Unzip the file into the `BepInEx\plugins\` folder in your game's installation directory, created by BepInEx.
|
||||||
3. Make sure it's not in a sub-folder, `Explorer.dll` and `mcs.dll` should be directly in the `plugins\` folder.
|
3. Make sure it's not in a sub-folder, `Explorer.dll` should be directly in the `plugins\` folder.
|
||||||
|
|
||||||
## How to use
|
## Mod Config
|
||||||
|
|
||||||
* Press F7 to show or hide the menu.
|
There is a simple Mod Config for the Explorer. You can access the settings via the "Options" page of the main menu.
|
||||||
* Use the Scene Explorer or the Object Search to start Exploring, or the C# Console to test some code.
|
|
||||||
* See below for more specific details.
|
|
||||||
|
|
||||||
### Mod Config
|
`Main Menu Toggle` (KeyCode) | Default: `F7`
|
||||||
|
|
||||||
There is a simple Mod Config for the Explorer, which is generated the first time you run it.
|
|
||||||
|
|
||||||
This config is generated to `[Game_Directory]\Mods\Explorer\config.xml`. Edit the config while the game is closed if you wish to change it.
|
|
||||||
|
|
||||||
`Main_Menu_Toggle` (KeyCode)
|
|
||||||
* Sets the keybinding for the Main Menu toggle (show/hide all Explorer windows)
|
|
||||||
* See [this article](https://docs.unity3d.com/ScriptReference/KeyCode.html) for a full list of all accepted KeyCodes.
|
* See [this article](https://docs.unity3d.com/ScriptReference/KeyCode.html) for a full list of all accepted KeyCodes.
|
||||||
* Default: `F7`
|
|
||||||
|
|
||||||
`Default_Window_Size` (Vector2)
|
`Default Window Size` (Vector2) | Default: `x: 550, y: 700`
|
||||||
* Sets the default width and height for all Explorer windows when created.
|
* Sets the default width and height for all Explorer windows when created.
|
||||||
* `x` is width, `y` is height.
|
|
||||||
* Default: `<x>550</x> <y>700</y>`
|
|
||||||
|
|
||||||
## Features
|
`Default Items per Page` (int) | Default: `20`
|
||||||
[](https://raw.githubusercontent.com/sinai-dev/Explorer/master/overview.png)
|
* Sets the default items per page when viewing lists or search results.
|
||||||
|
|
||||||
<i>An overview of the different Explorer menus.</i>
|
`Enable Bitwise Editing` (bool) | Default: `false`
|
||||||
|
* Whether or not to show the Bitwise Editing helper when inspecting integers
|
||||||
|
|
||||||
### Scene Explorer
|
`Enable Tab View` (bool) | Default: `true`
|
||||||
|
* Whether or not all inspector windows a grouped into a single window with tabs.
|
||||||
|
|
||||||
* A simple menu which allows you to traverse the Transform heirarchy of the scene.
|
`Default Output Path` (string) | Default: `Mods\Explorer`
|
||||||
* Click on a GameObject to set it as the current path, or <b>Inspect</b> it to send it to an Inspector Window.
|
* Where output is generated to, by default (for Texture PNG saving, etc).
|
||||||
|
|
||||||
### Inspectors
|
## Mouse Control
|
||||||
|
|
||||||
Explorer has two main inspector modes: <b>GameObject Inspector</b>, and <b>Reflection Inspector</b>.
|
Explorer can force the mouse to be visible and unlocked when the menu is open, if you have enabled "Force Unlock Mouse" (Left-Alt toggle). Explorer also attempts to prevent clicking-through onto the game behind the Explorer menu.
|
||||||
|
|
||||||
<b>Tips:</b>
|
If you need more mouse control:
|
||||||
* 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
|
|
||||||
|
|
||||||
* Allows you to see the children and components on a GameObject.
|
|
||||||
* Can use some basic GameObject Controls such as translating and rotating the object, destroy it, clone it, etc.
|
|
||||||
|
|
||||||
### Reflection Inspector
|
|
||||||
|
|
||||||
* The Reflection Inspector is used for all other supported objects.
|
|
||||||
* Allows you to inspect Properties, Fields and basic Methods, as well as set primitive values and evaluate primitive methods.
|
|
||||||
* Can search and filter members for the ones you are interested in.
|
|
||||||
|
|
||||||
### Object Search
|
|
||||||
|
|
||||||
* You can search for an `UnityEngine.Object` with the Object Search feature.
|
|
||||||
* Filter by name, type, etc.
|
|
||||||
* For GameObjects and Transforms you can filter which scene they are found in too.
|
|
||||||
|
|
||||||
### C# console
|
|
||||||
|
|
||||||
* A simple C# console, allows you to execute a method body on the fly.
|
|
||||||
|
|
||||||
### Inspect-under-mouse
|
|
||||||
|
|
||||||
* Press Shift+RMB (Right Mouse Button) while the Explorer menu is open to begin Inspect-Under-Mouse.
|
|
||||||
* Hover over your desired object, if you see the name appear then you can click on it to inspect it.
|
|
||||||
* Only objects with Colliders are supported.
|
|
||||||
|
|
||||||
### Mouse Control
|
|
||||||
|
|
||||||
Explorer can force the mouse to be visible and unlocked when the menu is open, if you have enabled "Force Unlock Mouse" (Left-Alt toggle). However, you may also want to prevent the mouse clicking-through onto the game behind Explorer, this is possible but it requires specific patches for that game.
|
|
||||||
|
|
||||||
* For VRChat, use [VRCExplorerMouseControl](https://github.com/sinai-dev/VRCExplorerMouseControl)
|
* For VRChat, use [VRCExplorerMouseControl](https://github.com/sinai-dev/VRCExplorerMouseControl)
|
||||||
* For Hellpoint, use [HPExplorerMouseControl](https://github.com/sinai-dev/Hellpoint-Mods/tree/master/HPExplorerMouseControl/HPExplorerMouseControl)
|
* For Hellpoint, use [HPExplorerMouseControl](https://github.com/sinai-dev/Hellpoint-Mods/tree/master/HPExplorerMouseControl/HPExplorerMouseControl)
|
||||||
@ -130,8 +98,9 @@ For example:
|
|||||||
using Explorer;
|
using Explorer;
|
||||||
using Harmony; // or 'using HarmonyLib;' for BepInEx
|
using Harmony; // or 'using HarmonyLib;' for BepInEx
|
||||||
// ...
|
// ...
|
||||||
[HarmonyPatch(typeof(MyGame.MenuClass), nameof(MyGame.MenuClass.CursorUpdate)]
|
// You will need to figure out the relevant Class and Method for your game using dnSpy.
|
||||||
public class MenuClass_CursorUpdate
|
[HarmonyPatch(typeof(MyGame.InputManager), nameof(MyGame.InputManager.Update)]
|
||||||
|
public class InputManager_Update
|
||||||
{
|
{
|
||||||
[HarmonyPrefix]
|
[HarmonyPrefix]
|
||||||
public static bool Prefix()
|
public static bool Prefix()
|
||||||
@ -144,14 +113,15 @@ public class MenuClass_CursorUpdate
|
|||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
If you'd like to build this yourself, everything you need (other than MelonLoader) is included with this repository, there is no need for recursive cloning etc.
|
If you'd like to build this yourself, you will need to have installed BepInEx and/or MelonLoader for at least one Unity game. If you want to build all 4 versions, you will need at least one Il2Cpp and one Mono game, with BepInEx and MelonLoader installed for both.
|
||||||
|
|
||||||
1. Install MelonLoader for your game.
|
1. Install MelonLoader or BepInEx for your game.
|
||||||
2. Open the `src\Explorer.csproj` file in a text editor.
|
2. Open the `src\Explorer.csproj` file in a text editor.
|
||||||
3. Set the relevant `GameFolder` value(s) for the version(s) you want to build, eg. set `MLCppGameFolder` if you want to build for a MelonLoader Il2Cpp game.
|
3. Set the relevant `GameFolder` values for the versions you want to build, eg. set `MLCppGameFolder` if you want to build for a MelonLoader Il2Cpp game.
|
||||||
4. Open the `src\Explorer.sln` project.
|
4. Open the `src\Explorer.sln` project.
|
||||||
5. Select `Solution 'Explorer' (1 of 1 project)` in the Solution Explorer panel, and set the <b>Active config</b> to the version you want to build, then build it.
|
5. Select `Solution 'Explorer' (1 of 1 project)` in the Solution Explorer panel, and set the <b>Active config</b> property to the version you want to build, then build it.
|
||||||
5. The DLLs are built to the `Release\` folder in the root of the repository.
|
5. The DLLs are built to the `Release\` folder in the root of the repository.
|
||||||
|
6. If ILRepack fails or is missing, use the NuGet package manager to re-install `ILRepack.Lib.MSBuild.Task`, then re-build.
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
BIN
lib/0Harmony.dll
Normal file
BIN
lib/0Harmony.dll
Normal file
Binary file not shown.
BIN
lib/BepInEx.Core.dll
Normal file
BIN
lib/BepInEx.Core.dll
Normal file
Binary file not shown.
BIN
lib/BepInEx.IL2CPP.dll
Normal file
BIN
lib/BepInEx.IL2CPP.dll
Normal file
Binary file not shown.
BIN
lib/BepInEx.dll
Normal file
BIN
lib/BepInEx.dll
Normal file
Binary file not shown.
BIN
lib/MelonLoader.ModHandler.dll
Normal file
BIN
lib/MelonLoader.ModHandler.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
lib/mcs.dll
BIN
lib/mcs.dll
Binary file not shown.
BIN
overview.png
BIN
overview.png
Binary file not shown.
Before Width: | Height: | Size: 479 KiB After Width: | Height: | Size: 392 KiB |
26
src/CacheObject/CacheEnumerated.cs
Normal file
26
src/CacheObject/CacheEnumerated.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Explorer.UI;
|
||||||
|
|
||||||
|
namespace Explorer.CacheObject
|
||||||
|
{
|
||||||
|
public class CacheEnumerated : CacheObjectBase
|
||||||
|
{
|
||||||
|
public int Index { get; set; }
|
||||||
|
public IList RefIList { get; set; }
|
||||||
|
public InteractiveEnumerable ParentEnumeration { get; set; }
|
||||||
|
|
||||||
|
public override bool CanWrite => RefIList != null && ParentEnumeration.OwnerCacheObject.CanWrite;
|
||||||
|
|
||||||
|
public override void SetValue()
|
||||||
|
{
|
||||||
|
RefIList[Index] = IValue.Value;
|
||||||
|
ParentEnumeration.Value = RefIList;
|
||||||
|
|
||||||
|
ParentEnumeration.OwnerCacheObject.SetValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
75
src/CacheObject/CacheFactory.cs
Normal file
75
src/CacheObject/CacheFactory.cs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using Explorer.CacheObject;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Explorer
|
||||||
|
{
|
||||||
|
public static class CacheFactory
|
||||||
|
{
|
||||||
|
public static CacheObjectBase GetCacheObject(object obj)
|
||||||
|
{
|
||||||
|
if (obj == null) return null;
|
||||||
|
|
||||||
|
return GetCacheObject(obj, ReflectionHelpers.GetActualType(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CacheObjectBase GetCacheObject(object obj, Type type)
|
||||||
|
{
|
||||||
|
var ret = new CacheObjectBase();
|
||||||
|
ret.Init(obj, type);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CacheMember GetCacheObject(MemberInfo member, object declaringInstance)
|
||||||
|
{
|
||||||
|
CacheMember ret;
|
||||||
|
|
||||||
|
if (member is MethodInfo mi && CanProcessArgs(mi.GetParameters()))
|
||||||
|
{
|
||||||
|
ret = new CacheMethod();
|
||||||
|
ret.InitMember(mi, declaringInstance);
|
||||||
|
}
|
||||||
|
else if (member is PropertyInfo pi && CanProcessArgs(pi.GetIndexParameters()))
|
||||||
|
{
|
||||||
|
ret = new CacheProperty();
|
||||||
|
ret.InitMember(pi, declaringInstance);
|
||||||
|
}
|
||||||
|
else if (member is FieldInfo fi)
|
||||||
|
{
|
||||||
|
ret = new CacheField();
|
||||||
|
ret.InitMember(fi, declaringInstance);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool CanProcessArgs(ParameterInfo[] parameters)
|
||||||
|
{
|
||||||
|
foreach (var param in parameters)
|
||||||
|
{
|
||||||
|
var pType = param.ParameterType;
|
||||||
|
|
||||||
|
if (pType.IsByRef && pType.HasElementType)
|
||||||
|
{
|
||||||
|
pType = pType.GetElementType();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pType.IsPrimitive || pType == typeof(string))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
src/CacheObject/CacheField.cs
Normal file
43
src/CacheObject/CacheField.cs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Explorer.CacheObject
|
||||||
|
{
|
||||||
|
public class CacheField : CacheMember
|
||||||
|
{
|
||||||
|
public override bool IsStatic => (MemInfo as FieldInfo).IsStatic;
|
||||||
|
|
||||||
|
public override void InitMember(MemberInfo member, object declaringInstance)
|
||||||
|
{
|
||||||
|
base.InitMember(member, declaringInstance);
|
||||||
|
|
||||||
|
base.Init(null, (member as FieldInfo).FieldType);
|
||||||
|
|
||||||
|
UpdateValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void UpdateValue()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var fi = MemInfo as FieldInfo;
|
||||||
|
IValue.Value = fi.GetValue(fi.IsStatic ? null : DeclaringInstance);
|
||||||
|
|
||||||
|
base.UpdateValue();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ReflectionException = ReflectionHelpers.ExceptionToString(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetValue()
|
||||||
|
{
|
||||||
|
var fi = MemInfo as FieldInfo;
|
||||||
|
fi.SetValue(fi.IsStatic ? null : DeclaringInstance, IValue.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
226
src/CacheObject/CacheMember.cs
Normal file
226
src/CacheObject/CacheMember.cs
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityEngine;
|
||||||
|
using Explorer.UI;
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
|
||||||
|
namespace Explorer.CacheObject
|
||||||
|
{
|
||||||
|
public class CacheMember : CacheObjectBase
|
||||||
|
{
|
||||||
|
public MemberInfo MemInfo { get; set; }
|
||||||
|
public Type DeclaringType { get; set; }
|
||||||
|
public object DeclaringInstance { get; set; }
|
||||||
|
|
||||||
|
public virtual bool IsStatic { get; private set; }
|
||||||
|
|
||||||
|
public override bool HasParameters => m_arguments != null && m_arguments.Length > 0;
|
||||||
|
public override bool IsMember => true;
|
||||||
|
|
||||||
|
public string RichTextName => m_richTextName ?? GetRichTextName();
|
||||||
|
private string m_richTextName;
|
||||||
|
|
||||||
|
public override bool CanWrite => m_canWrite ?? GetCanWrite();
|
||||||
|
private bool? m_canWrite;
|
||||||
|
|
||||||
|
public string ReflectionException { get; set; }
|
||||||
|
|
||||||
|
public bool m_evaluated = false;
|
||||||
|
public bool m_isEvaluating;
|
||||||
|
public ParameterInfo[] m_arguments = new ParameterInfo[0];
|
||||||
|
public string[] m_argumentInput = new string[0];
|
||||||
|
|
||||||
|
public virtual void InitMember(MemberInfo member, object declaringInstance)
|
||||||
|
{
|
||||||
|
MemInfo = member;
|
||||||
|
DeclaringInstance = declaringInstance;
|
||||||
|
DeclaringType = member.DeclaringType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void UpdateValue()
|
||||||
|
{
|
||||||
|
base.UpdateValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetValue()
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
public object[] ParseArguments()
|
||||||
|
{
|
||||||
|
if (m_arguments.Length < 1)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var parsedArgs = new List<object>();
|
||||||
|
for (int i = 0; i < m_arguments.Length; i++)
|
||||||
|
{
|
||||||
|
var input = m_argumentInput[i];
|
||||||
|
var type = m_arguments[i].ParameterType;
|
||||||
|
|
||||||
|
if (type.IsByRef)
|
||||||
|
{
|
||||||
|
type = type.GetElementType();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(input))
|
||||||
|
{
|
||||||
|
if (type == typeof(string))
|
||||||
|
{
|
||||||
|
parsedArgs.Add(input);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var arg = type.GetMethod("Parse", new Type[] { typeof(string) })
|
||||||
|
.Invoke(null, new object[] { input });
|
||||||
|
|
||||||
|
parsedArgs.Add(arg);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
ExplorerCore.Log($"Argument #{i} '{m_arguments[i].Name}' ({type.Name}), could not parse input '{input}'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No input, see if there is a default value.
|
||||||
|
if (HasDefaultValue(m_arguments[i]))
|
||||||
|
{
|
||||||
|
parsedArgs.Add(m_arguments[i].DefaultValue);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try add a null arg I guess
|
||||||
|
parsedArgs.Add(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsedArgs.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool HasDefaultValue(ParameterInfo arg) => arg.DefaultValue != DBNull.Value;
|
||||||
|
|
||||||
|
public void DrawArgsInput()
|
||||||
|
{
|
||||||
|
GUILayout.Label($"<b><color=orange>Arguments:</color></b>", new GUILayoutOption[0]);
|
||||||
|
for (int i = 0; i < this.m_arguments.Length; i++)
|
||||||
|
{
|
||||||
|
var name = this.m_arguments[i].Name;
|
||||||
|
var input = this.m_argumentInput[i];
|
||||||
|
var type = this.m_arguments[i].ParameterType.Name;
|
||||||
|
|
||||||
|
var label = $"<color={Syntax.Class_Instance}>{type}</color> ";
|
||||||
|
label += $"<color={Syntax.Local}>{name}</color>";
|
||||||
|
if (HasDefaultValue(this.m_arguments[i]))
|
||||||
|
{
|
||||||
|
label = $"<i>[{label} = {this.m_arguments[i].DefaultValue ?? "null"}]</i>";
|
||||||
|
}
|
||||||
|
|
||||||
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
|
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||||
|
|
||||||
|
GUILayout.Label(i.ToString(), new GUILayoutOption[] { GUILayout.Width(15) });
|
||||||
|
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.EndHorizontal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool GetCanWrite()
|
||||||
|
{
|
||||||
|
if (MemInfo is FieldInfo fi)
|
||||||
|
m_canWrite = !(fi.IsLiteral && !fi.IsInitOnly);
|
||||||
|
else if (MemInfo is PropertyInfo pi)
|
||||||
|
m_canWrite = pi.CanWrite;
|
||||||
|
else
|
||||||
|
m_canWrite = false;
|
||||||
|
|
||||||
|
return (bool)m_canWrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetRichTextName()
|
||||||
|
{
|
||||||
|
string memberColor = "";
|
||||||
|
bool isStatic = false;
|
||||||
|
|
||||||
|
if (MemInfo is FieldInfo fi)
|
||||||
|
{
|
||||||
|
if (fi.IsStatic)
|
||||||
|
{
|
||||||
|
isStatic = true;
|
||||||
|
memberColor = Syntax.Field_Static;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
memberColor = Syntax.Field_Instance;
|
||||||
|
}
|
||||||
|
else if (MemInfo is MethodInfo mi)
|
||||||
|
{
|
||||||
|
if (mi.IsStatic)
|
||||||
|
{
|
||||||
|
isStatic = true;
|
||||||
|
memberColor = Syntax.Method_Static;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
memberColor = Syntax.Method_Instance;
|
||||||
|
}
|
||||||
|
else if (MemInfo is PropertyInfo pi)
|
||||||
|
{
|
||||||
|
if (pi.GetAccessors()[0].IsStatic)
|
||||||
|
{
|
||||||
|
isStatic = true;
|
||||||
|
memberColor = Syntax.Prop_Static;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
memberColor = Syntax.Prop_Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
string classColor;
|
||||||
|
if (MemInfo.DeclaringType.IsValueType)
|
||||||
|
{
|
||||||
|
classColor = Syntax.StructGreen;
|
||||||
|
}
|
||||||
|
else if (MemInfo.DeclaringType.IsAbstract && MemInfo.DeclaringType.IsSealed)
|
||||||
|
{
|
||||||
|
classColor = Syntax.Class_Static;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
classColor = Syntax.Class_Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_richTextName = $"<color={classColor}>{MemInfo.DeclaringType.Name}</color>.";
|
||||||
|
if (isStatic) m_richTextName += "<i>";
|
||||||
|
m_richTextName += $"<color={memberColor}>{MemInfo.Name}</color>";
|
||||||
|
if (isStatic) m_richTextName += "</i>";
|
||||||
|
|
||||||
|
// generic method args
|
||||||
|
if (this is CacheMethod cm && cm.GenericArgs.Length > 0)
|
||||||
|
{
|
||||||
|
m_richTextName += "<";
|
||||||
|
|
||||||
|
var args = "";
|
||||||
|
for (int i = 0; i < cm.GenericArgs.Length; i++)
|
||||||
|
{
|
||||||
|
if (args != "") args += ", ";
|
||||||
|
args += $"<color={Syntax.StructGreen}>{cm.GenericArgs[i].Name}</color>";
|
||||||
|
}
|
||||||
|
m_richTextName += args;
|
||||||
|
|
||||||
|
m_richTextName += ">";
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_richTextName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,23 +3,28 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.CacheObject
|
||||||
{
|
{
|
||||||
public class CacheMethod : CacheObjectBase
|
public class CacheMethod : CacheMember
|
||||||
{
|
{
|
||||||
private CacheObjectBase m_cachedReturnValue;
|
private CacheObjectBase m_cachedReturnValue;
|
||||||
|
|
||||||
public override bool HasParameters => base.HasParameters || GenericArgs.Length > 0;
|
public override bool HasParameters => base.HasParameters || GenericArgs.Length > 0;
|
||||||
|
|
||||||
|
public override bool IsStatic => (MemInfo as MethodInfo).IsStatic;
|
||||||
|
|
||||||
public Type[] GenericArgs { get; private set; }
|
public Type[] GenericArgs { get; private set; }
|
||||||
public Type[][] GenericConstraints { get; private set; }
|
public Type[][] GenericConstraints { get; private set; }
|
||||||
|
|
||||||
public string[] GenericArgInput = new string[0];
|
public string[] GenericArgInput = new string[0];
|
||||||
|
|
||||||
public override void Init()
|
public override void InitMember(MemberInfo member, object declaringInstance)
|
||||||
{
|
{
|
||||||
var mi = (MemInfo as MethodInfo);
|
base.InitMember(member, declaringInstance);
|
||||||
|
|
||||||
|
var mi = MemInfo as MethodInfo;
|
||||||
GenericArgs = mi.GetGenericArguments();
|
GenericArgs = mi.GetGenericArguments();
|
||||||
|
|
||||||
GenericConstraints = GenericArgs.Select(x => x.GetGenericParameterConstraints())
|
GenericConstraints = GenericArgs.Select(x => x.GetGenericParameterConstraints())
|
||||||
@ -27,12 +32,15 @@ namespace Explorer
|
|||||||
|
|
||||||
GenericArgInput = new string[GenericArgs.Length];
|
GenericArgInput = new string[GenericArgs.Length];
|
||||||
|
|
||||||
ValueType = mi.ReturnType;
|
m_arguments = mi.GetParameters();
|
||||||
|
m_argumentInput = new string[m_arguments.Length];
|
||||||
|
|
||||||
|
base.Init(null, mi.ReturnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void UpdateValue()
|
public override void UpdateValue()
|
||||||
{
|
{
|
||||||
//base.UpdateValue();
|
// CacheMethod cannot UpdateValue directly. Need to Evaluate.
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Evaluate()
|
public void Evaluate()
|
||||||
@ -64,7 +72,8 @@ namespace Explorer
|
|||||||
|
|
||||||
if (ret != null)
|
if (ret != null)
|
||||||
{
|
{
|
||||||
m_cachedReturnValue = CacheFactory.GetTypeAndCacheObject(ret);
|
//m_cachedReturnValue = CacheFactory.GetTypeAndCacheObject(ret);
|
||||||
|
m_cachedReturnValue = CacheFactory.GetCacheObject(ret);
|
||||||
m_cachedReturnValue.UpdateValue();
|
m_cachedReturnValue.UpdateValue();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -91,11 +100,11 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
foreach (var constraint in GenericConstraints[i].Where(x => x != null))
|
foreach (var constraint in GenericConstraints[i].Where(x => x != null))
|
||||||
{
|
{
|
||||||
if (!constraint.IsAssignableFrom(t))
|
if (!constraint.IsAssignableFrom(t))
|
||||||
{
|
{
|
||||||
ExplorerCore.LogWarning($"Generic argument #{i}, '{input}' is not assignable from the constraint '{constraint}'!");
|
ExplorerCore.LogWarning($"Generic argument #{i}, '{input}' is not assignable from the constraint '{constraint}'!");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list.Add(t);
|
list.Add(t);
|
||||||
@ -117,15 +126,20 @@ namespace Explorer
|
|||||||
|
|
||||||
// ==== GUI DRAW ====
|
// ==== GUI DRAW ====
|
||||||
|
|
||||||
public override void DrawValue(Rect window, float width)
|
//public override void Draw(Rect window, float width)
|
||||||
|
//{
|
||||||
|
// base.Draw(window, width);
|
||||||
|
//}
|
||||||
|
|
||||||
|
public void DrawValue(Rect window, float width)
|
||||||
{
|
{
|
||||||
string typeLabel = $"<color={UIStyles.Syntax.Class_Instance}>{ValueType.FullName}</color>";
|
string typeLabel = $"<color={Syntax.Class_Instance}>{IValue.ValueType.FullName}</color>";
|
||||||
|
|
||||||
if (m_evaluated)
|
if (m_evaluated)
|
||||||
{
|
{
|
||||||
if (m_cachedReturnValue != null)
|
if (m_cachedReturnValue != null)
|
||||||
{
|
{
|
||||||
m_cachedReturnValue.DrawValue(window, width);
|
m_cachedReturnValue.IValue.DrawValue(window, width);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -137,5 +151,49 @@ namespace Explorer
|
|||||||
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> ({typeLabel})", new GUILayoutOption[0]);
|
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> ({typeLabel})", new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DrawGenericArgsInput()
|
||||||
|
{
|
||||||
|
GUILayout.Label($"<b><color=orange>Generic Arguments:</color></b>", new GUILayoutOption[0]);
|
||||||
|
|
||||||
|
for (int i = 0; i < this.GenericArgs.Length; i++)
|
||||||
|
{
|
||||||
|
string types = "";
|
||||||
|
if (this.GenericConstraints[i].Length > 0)
|
||||||
|
{
|
||||||
|
foreach (var constraint in this.GenericConstraints[i])
|
||||||
|
{
|
||||||
|
if (types != "") types += ", ";
|
||||||
|
|
||||||
|
string type;
|
||||||
|
|
||||||
|
if (constraint == null)
|
||||||
|
type = "Any";
|
||||||
|
else
|
||||||
|
type = constraint.ToString();
|
||||||
|
|
||||||
|
types += $"<color={Syntax.Class_Instance}>{type}</color>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
types = $"<color={Syntax.Class_Instance}>Any</color>";
|
||||||
|
}
|
||||||
|
var input = this.GenericArgInput[i];
|
||||||
|
|
||||||
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
|
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||||
|
GUILayout.Label(
|
||||||
|
$"<color={Syntax.StructGreen}>{this.GenericArgs[i].Name}</color>",
|
||||||
|
new GUILayoutOption[] { GUILayout.Width(15) }
|
||||||
|
);
|
||||||
|
this.GenericArgInput[i] = GUIUnstrip.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
|
||||||
|
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
|
||||||
|
GUILayout.Label(types, new GUILayoutOption[0]);
|
||||||
|
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
116
src/CacheObject/CacheObjectBase.cs
Normal file
116
src/CacheObject/CacheObjectBase.cs
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityEngine;
|
||||||
|
using Explorer.UI;
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
|
||||||
|
namespace Explorer.CacheObject
|
||||||
|
{
|
||||||
|
public class CacheObjectBase
|
||||||
|
{
|
||||||
|
public InteractiveValue IValue;
|
||||||
|
|
||||||
|
public virtual bool CanWrite => false;
|
||||||
|
public virtual bool HasParameters => false;
|
||||||
|
public virtual bool IsMember => false;
|
||||||
|
|
||||||
|
public bool IsStaticClassSearchResult { get; set; }
|
||||||
|
|
||||||
|
public virtual void Init(object obj, Type valueType)
|
||||||
|
{
|
||||||
|
if (valueType == null && obj == null)
|
||||||
|
{
|
||||||
|
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(Texture))
|
||||||
|
{
|
||||||
|
interactive = new InteractiveTexture();
|
||||||
|
}
|
||||||
|
else if (valueType == typeof(Sprite))
|
||||||
|
{
|
||||||
|
interactive = new InteractiveSprite();
|
||||||
|
}
|
||||||
|
else if (valueType.IsPrimitive || valueType == typeof(string))
|
||||||
|
{
|
||||||
|
interactive = new InteractivePrimitive();
|
||||||
|
}
|
||||||
|
else if (valueType.IsEnum)
|
||||||
|
{
|
||||||
|
if (valueType.GetCustomAttributes(typeof(FlagsAttribute), true) is object[] attributes && attributes.Length > 0)
|
||||||
|
{
|
||||||
|
interactive = new InteractiveFlags();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
interactive = new InteractiveEnum();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (valueType == typeof(Vector2) || valueType == typeof(Vector3) || valueType == typeof(Vector4))
|
||||||
|
{
|
||||||
|
interactive = new InteractiveVector();
|
||||||
|
}
|
||||||
|
else if (valueType == typeof(Quaternion))
|
||||||
|
{
|
||||||
|
interactive = new InteractiveQuaternion();
|
||||||
|
}
|
||||||
|
else if (valueType == typeof(Color))
|
||||||
|
{
|
||||||
|
interactive = new InteractiveColor();
|
||||||
|
}
|
||||||
|
else if (valueType == typeof(Rect))
|
||||||
|
{
|
||||||
|
interactive = new InteractiveRect();
|
||||||
|
}
|
||||||
|
// must check this before IsEnumerable
|
||||||
|
else if (ReflectionHelpers.IsDictionary(valueType))
|
||||||
|
{
|
||||||
|
interactive = new InteractiveDictionary();
|
||||||
|
}
|
||||||
|
else if (ReflectionHelpers.IsEnumerable(valueType))
|
||||||
|
{
|
||||||
|
interactive = new InteractiveEnumerable();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
interactive = new InteractiveValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
interactive.Value = obj;
|
||||||
|
interactive.ValueType = valueType;
|
||||||
|
|
||||||
|
this.IValue = interactive;
|
||||||
|
this.IValue.OwnerCacheObject = this;
|
||||||
|
|
||||||
|
UpdateValue();
|
||||||
|
|
||||||
|
this.IValue.Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Draw(Rect window, float width)
|
||||||
|
{
|
||||||
|
IValue.Draw(window, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void UpdateValue()
|
||||||
|
{
|
||||||
|
IValue.UpdateValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void SetValue() => throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
73
src/CacheObject/CacheProperty.cs
Normal file
73
src/CacheObject/CacheProperty.cs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Explorer.CacheObject
|
||||||
|
{
|
||||||
|
public class CacheProperty : CacheMember
|
||||||
|
{
|
||||||
|
public override bool IsStatic => (MemInfo as PropertyInfo).GetAccessors()[0].IsStatic;
|
||||||
|
|
||||||
|
public override void InitMember(MemberInfo member, object declaringInstance)
|
||||||
|
{
|
||||||
|
base.InitMember(member, declaringInstance);
|
||||||
|
|
||||||
|
var pi = member as PropertyInfo;
|
||||||
|
|
||||||
|
this.m_arguments = pi.GetIndexParameters();
|
||||||
|
this.m_argumentInput = new string[m_arguments.Length];
|
||||||
|
|
||||||
|
base.Init(null, pi.PropertyType);
|
||||||
|
|
||||||
|
UpdateValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void UpdateValue()
|
||||||
|
{
|
||||||
|
if (HasParameters && !m_isEvaluating)
|
||||||
|
{
|
||||||
|
// Need to enter parameters first.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var pi = MemInfo as PropertyInfo;
|
||||||
|
|
||||||
|
if (pi.CanRead)
|
||||||
|
{
|
||||||
|
var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
|
||||||
|
|
||||||
|
IValue.Value = pi.GetValue(target, ParseArguments());
|
||||||
|
|
||||||
|
base.UpdateValue();
|
||||||
|
}
|
||||||
|
else // create a dummy value for Write-Only properties.
|
||||||
|
{
|
||||||
|
if (IValue.ValueType == typeof(string))
|
||||||
|
{
|
||||||
|
IValue.Value = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IValue.Value = Activator.CreateInstance(IValue.ValueType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ReflectionException = ReflectionHelpers.ExceptionToString(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetValue()
|
||||||
|
{
|
||||||
|
var pi = MemInfo as PropertyInfo;
|
||||||
|
var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
|
||||||
|
|
||||||
|
pi.SetValue(target, IValue.Value, ParseArguments());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,169 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Explorer
|
|
||||||
{
|
|
||||||
public static class CacheFactory
|
|
||||||
{
|
|
||||||
public static CacheObjectBase GetTypeAndCacheObject(object obj)
|
|
||||||
=> GetTypeAndCacheObject(obj, null, null);
|
|
||||||
|
|
||||||
public static CacheObjectBase GetTypeAndCacheObject(MemberInfo memberInfo, object declarer)
|
|
||||||
=> GetTypeAndCacheObject(null, memberInfo, declarer);
|
|
||||||
|
|
||||||
public static CacheObjectBase GetTypeAndCacheObject(object obj, MemberInfo memberInfo, object declarer)
|
|
||||||
{
|
|
||||||
Type type = null;
|
|
||||||
|
|
||||||
if (memberInfo != null)
|
|
||||||
{
|
|
||||||
if (memberInfo is FieldInfo fi)
|
|
||||||
{
|
|
||||||
type = fi.FieldType;
|
|
||||||
}
|
|
||||||
else if (memberInfo is PropertyInfo pi)
|
|
||||||
{
|
|
||||||
type = pi.PropertyType;
|
|
||||||
}
|
|
||||||
else if (memberInfo is MethodInfo mi)
|
|
||||||
{
|
|
||||||
type = mi.ReturnType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (obj != null)
|
|
||||||
{
|
|
||||||
type = ReflectionHelpers.GetActualType(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetCacheObject(obj, memberInfo, declarer, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CacheObjectBase GetCacheObject(object obj, Type valueType)
|
|
||||||
=> GetCacheObject(obj, null, null, valueType);
|
|
||||||
|
|
||||||
private static CacheObjectBase GetCacheObject(object obj, MemberInfo memberInfo, object declaringInstance, Type valueType)
|
|
||||||
{
|
|
||||||
CacheObjectBase cached;
|
|
||||||
|
|
||||||
var pi = memberInfo as PropertyInfo;
|
|
||||||
var mi = memberInfo as MethodInfo;
|
|
||||||
|
|
||||||
// Check if can process args
|
|
||||||
if ((pi != null && !CanProcessArgs(pi.GetIndexParameters()))
|
|
||||||
|| (mi != null && !CanProcessArgs(mi.GetParameters())))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mi != null)
|
|
||||||
{
|
|
||||||
cached = new CacheMethod();
|
|
||||||
}
|
|
||||||
else if (valueType == typeof(GameObject) || valueType == typeof(Transform))
|
|
||||||
{
|
|
||||||
cached = new CacheGameObject();
|
|
||||||
}
|
|
||||||
else if (valueType.IsPrimitive || valueType == typeof(string))
|
|
||||||
{
|
|
||||||
cached = new CachePrimitive();
|
|
||||||
}
|
|
||||||
else if (valueType.IsEnum)
|
|
||||||
{
|
|
||||||
if (valueType.GetCustomAttributes(typeof(FlagsAttribute), true) is object[] attributes && attributes.Length > 0)
|
|
||||||
{
|
|
||||||
cached = new CacheEnumFlags();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cached = new CacheEnum();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (valueType == typeof(Vector2) || valueType == typeof(Vector3) || valueType == typeof(Vector4))
|
|
||||||
{
|
|
||||||
cached = new CacheVector();
|
|
||||||
}
|
|
||||||
else if (valueType == typeof(Quaternion))
|
|
||||||
{
|
|
||||||
cached = new CacheQuaternion();
|
|
||||||
}
|
|
||||||
else if (valueType == typeof(Color))
|
|
||||||
{
|
|
||||||
cached = new CacheColor();
|
|
||||||
}
|
|
||||||
else if (valueType == typeof(Rect))
|
|
||||||
{
|
|
||||||
cached = new CacheRect();
|
|
||||||
}
|
|
||||||
// must check this before IsEnumerable
|
|
||||||
else if (ReflectionHelpers.IsDictionary(valueType))
|
|
||||||
{
|
|
||||||
cached = new CacheDictionary();
|
|
||||||
}
|
|
||||||
else if (ReflectionHelpers.IsEnumerable(valueType))
|
|
||||||
{
|
|
||||||
cached = new CacheList();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cached = new CacheOther();
|
|
||||||
}
|
|
||||||
|
|
||||||
cached.Value = obj;
|
|
||||||
cached.ValueType = valueType;
|
|
||||||
|
|
||||||
if (memberInfo != null)
|
|
||||||
{
|
|
||||||
cached.MemInfo = memberInfo;
|
|
||||||
cached.DeclaringType = memberInfo.DeclaringType;
|
|
||||||
cached.DeclaringInstance = declaringInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pi != null)
|
|
||||||
{
|
|
||||||
cached.m_arguments = pi.GetIndexParameters();
|
|
||||||
}
|
|
||||||
else if (mi != null)
|
|
||||||
{
|
|
||||||
cached.m_arguments = mi.GetParameters();
|
|
||||||
}
|
|
||||||
|
|
||||||
cached.m_argumentInput = new string[cached.m_arguments.Length];
|
|
||||||
|
|
||||||
cached.UpdateValue();
|
|
||||||
|
|
||||||
cached.Init();
|
|
||||||
|
|
||||||
return cached;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool CanProcessArgs(ParameterInfo[] parameters)
|
|
||||||
{
|
|
||||||
foreach (var param in parameters)
|
|
||||||
{
|
|
||||||
var pType = param.ParameterType;
|
|
||||||
|
|
||||||
if (pType.IsByRef && pType.HasElementType)
|
|
||||||
{
|
|
||||||
pType = pType.GetElementType();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pType.IsPrimitive || pType == typeof(string))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,430 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Explorer
|
|
||||||
{
|
|
||||||
public abstract class CacheObjectBase
|
|
||||||
{
|
|
||||||
public object Value;
|
|
||||||
public Type ValueType;
|
|
||||||
|
|
||||||
public MemberInfo MemInfo { get; set; }
|
|
||||||
public Type DeclaringType { get; set; }
|
|
||||||
public object DeclaringInstance { get; set; }
|
|
||||||
|
|
||||||
public virtual bool HasParameters => m_arguments != null && m_arguments.Length > 0;
|
|
||||||
|
|
||||||
public bool m_evaluated = false;
|
|
||||||
public bool m_isEvaluating;
|
|
||||||
public ParameterInfo[] m_arguments = new ParameterInfo[0];
|
|
||||||
public string[] m_argumentInput = new string[0];
|
|
||||||
|
|
||||||
public string ReflectionException { get; set; }
|
|
||||||
|
|
||||||
public string RichTextName => m_richTextName ?? GetRichTextName();
|
|
||||||
private string m_richTextName;
|
|
||||||
|
|
||||||
public bool CanWrite => m_canWrite ?? GetCanWrite();
|
|
||||||
private bool? m_canWrite;
|
|
||||||
|
|
||||||
public virtual void Init() { }
|
|
||||||
|
|
||||||
public abstract void DrawValue(Rect window, float width);
|
|
||||||
|
|
||||||
public virtual void UpdateValue()
|
|
||||||
{
|
|
||||||
if (MemInfo == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HasParameters && !m_isEvaluating)
|
|
||||||
{
|
|
||||||
// Need to enter parameters first
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (MemInfo.MemberType == MemberTypes.Field)
|
|
||||||
{
|
|
||||||
var fi = MemInfo as FieldInfo;
|
|
||||||
Value = fi.GetValue(fi.IsStatic ? null : DeclaringInstance);
|
|
||||||
}
|
|
||||||
else if (MemInfo.MemberType == MemberTypes.Property)
|
|
||||||
{
|
|
||||||
var pi = MemInfo as PropertyInfo;
|
|
||||||
var target = pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance;
|
|
||||||
|
|
||||||
Value = pi.GetValue(target, ParseArguments());
|
|
||||||
}
|
|
||||||
|
|
||||||
ReflectionException = null;
|
|
||||||
m_evaluated = true;
|
|
||||||
m_isEvaluating = false;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
ReflectionException = ReflectionHelpers.ExceptionToString(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetValue()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (MemInfo.MemberType == MemberTypes.Field)
|
|
||||||
{
|
|
||||||
var fi = MemInfo as FieldInfo;
|
|
||||||
fi.SetValue(fi.IsStatic ? null : DeclaringInstance, Value);
|
|
||||||
}
|
|
||||||
else if (MemInfo.MemberType == MemberTypes.Property)
|
|
||||||
{
|
|
||||||
var pi = MemInfo as PropertyInfo;
|
|
||||||
|
|
||||||
if (HasParameters)
|
|
||||||
{
|
|
||||||
pi.SetValue(pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance, Value, ParseArguments());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pi.SetValue(pi.GetAccessors()[0].IsStatic ? null : DeclaringInstance, Value, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
ExplorerCore.LogWarning($"Error setting value: {e.GetType()}, {e.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public object[] ParseArguments()
|
|
||||||
{
|
|
||||||
var parsedArgs = new List<object>();
|
|
||||||
for (int i = 0; i < m_arguments.Length; i++)
|
|
||||||
{
|
|
||||||
var input = m_argumentInput[i];
|
|
||||||
var type = m_arguments[i].ParameterType;
|
|
||||||
|
|
||||||
if (type.IsByRef)
|
|
||||||
{
|
|
||||||
type = type.GetElementType();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(input))
|
|
||||||
{
|
|
||||||
if (type == typeof(string))
|
|
||||||
{
|
|
||||||
parsedArgs.Add(input);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var arg = type.GetMethod("Parse", new Type[] { typeof(string) })
|
|
||||||
.Invoke(null, new object[] { input });
|
|
||||||
|
|
||||||
parsedArgs.Add(arg);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
ExplorerCore.Log($"Argument #{i} '{m_arguments[i].Name}' ({type.Name}), could not parse input '{input}'.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// No input, see if there is a default value.
|
|
||||||
if (HasDefaultValue(m_arguments[i]))
|
|
||||||
{
|
|
||||||
parsedArgs.Add(m_arguments[i].DefaultValue);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try add a null arg I guess
|
|
||||||
parsedArgs.Add(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return parsedArgs.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool HasDefaultValue(ParameterInfo arg) => arg.DefaultValue != DBNull.Value;
|
|
||||||
|
|
||||||
// ========= Gui Draw ==========
|
|
||||||
|
|
||||||
public const float MAX_LABEL_WIDTH = 400f;
|
|
||||||
public const string EVALUATE_LABEL = "<color=lime>Evaluate</color>";
|
|
||||||
|
|
||||||
public float CalcWhitespace(Rect window)
|
|
||||||
{
|
|
||||||
if (!(this is IExpandHeight)) return 0f;
|
|
||||||
|
|
||||||
float whitespace = (this as IExpandHeight).WhiteSpace;
|
|
||||||
if (whitespace > 0)
|
|
||||||
{
|
|
||||||
ClampLabelWidth(window, ref whitespace);
|
|
||||||
}
|
|
||||||
|
|
||||||
return whitespace;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ClampLabelWidth(Rect window, ref float labelWidth)
|
|
||||||
{
|
|
||||||
float min = window.width * 0.37f;
|
|
||||||
if (min > MAX_LABEL_WIDTH) min = MAX_LABEL_WIDTH;
|
|
||||||
|
|
||||||
labelWidth = Mathf.Clamp(labelWidth, min, MAX_LABEL_WIDTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Draw(Rect window, float labelWidth = 215f)
|
|
||||||
{
|
|
||||||
if (labelWidth > 0)
|
|
||||||
{
|
|
||||||
ClampLabelWidth(window, ref labelWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MemInfo != null)
|
|
||||||
{
|
|
||||||
GUILayout.Label(RichTextName, new GUILayoutOption[] { GUILayout.Width(labelWidth) });
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GUIUnstrip.Space(labelWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
var cm = this as CacheMethod;
|
|
||||||
|
|
||||||
if (HasParameters)
|
|
||||||
{
|
|
||||||
GUILayout.BeginVertical(new GUILayoutOption[0]);
|
|
||||||
|
|
||||||
if (m_isEvaluating)
|
|
||||||
{
|
|
||||||
if (cm != null && cm.GenericArgs.Length > 0)
|
|
||||||
{
|
|
||||||
GUILayout.Label($"<b><color=orange>Generic Arguments:</color></b>", new GUILayoutOption[0]);
|
|
||||||
|
|
||||||
for (int i = 0; i < cm.GenericArgs.Length; i++)
|
|
||||||
{
|
|
||||||
string types = "";
|
|
||||||
if (cm.GenericConstraints[i].Length > 0)
|
|
||||||
{
|
|
||||||
foreach (var constraint in cm.GenericConstraints[i])
|
|
||||||
{
|
|
||||||
if (types != "") types += ", ";
|
|
||||||
|
|
||||||
string type;
|
|
||||||
|
|
||||||
if (constraint == null)
|
|
||||||
type = "Any";
|
|
||||||
else
|
|
||||||
type = constraint.ToString();
|
|
||||||
|
|
||||||
types += $"<color={UIStyles.Syntax.Class_Instance}>{type}</color>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
types = $"<color={UIStyles.Syntax.Class_Instance}>Any</color>";
|
|
||||||
}
|
|
||||||
var input = cm.GenericArgInput[i];
|
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
|
||||||
|
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
|
||||||
GUILayout.Label(
|
|
||||||
$"<color={UIStyles.Syntax.StructGreen}>{cm.GenericArgs[i].Name}</color>",
|
|
||||||
new GUILayoutOption[] { GUILayout.Width(15) }
|
|
||||||
);
|
|
||||||
cm.GenericArgInput[i] = GUIUnstrip.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
|
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
|
|
||||||
GUILayout.Label(types, new GUILayoutOption[0]);
|
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_arguments.Length > 0)
|
|
||||||
{
|
|
||||||
GUILayout.Label($"<b><color=orange>Arguments:</color></b>", new GUILayoutOption[0]);
|
|
||||||
for (int i = 0; i < m_arguments.Length; i++)
|
|
||||||
{
|
|
||||||
var name = m_arguments[i].Name;
|
|
||||||
var input = m_argumentInput[i];
|
|
||||||
var type = m_arguments[i].ParameterType.Name;
|
|
||||||
|
|
||||||
var label = $"<color={UIStyles.Syntax.Class_Instance}>{type}</color> ";
|
|
||||||
label += $"<color={UIStyles.Syntax.Local}>{name}</color>";
|
|
||||||
if (HasDefaultValue(m_arguments[i]))
|
|
||||||
{
|
|
||||||
label = $"<i>[{label} = {m_arguments[i].DefaultValue ?? "null"}]</i>";
|
|
||||||
}
|
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
|
||||||
|
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
|
||||||
GUILayout.Label(i.ToString(), new GUILayoutOption[] { GUILayout.Width(15) });
|
|
||||||
m_argumentInput[i] = GUIUnstrip.TextField(input, new GUILayoutOption[] { GUILayout.Width(150) });
|
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
|
|
||||||
GUILayout.Label(label, new GUILayoutOption[0]);
|
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
|
||||||
if (GUILayout.Button(EVALUATE_LABEL, new GUILayoutOption[] { GUILayout.Width(70) }))
|
|
||||||
{
|
|
||||||
if (cm != null)
|
|
||||||
cm.Evaluate();
|
|
||||||
else
|
|
||||||
UpdateValue();
|
|
||||||
}
|
|
||||||
if (GUILayout.Button("Cancel", new GUILayoutOption[] { GUILayout.Width(70) }))
|
|
||||||
{
|
|
||||||
m_isEvaluating = false;
|
|
||||||
}
|
|
||||||
GUILayout.EndHorizontal();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var lbl = $"Evaluate (";
|
|
||||||
int len = m_arguments.Length;
|
|
||||||
if (cm != null) len += cm.GenericArgs.Length;
|
|
||||||
lbl += len + " params)";
|
|
||||||
|
|
||||||
if (GUILayout.Button(lbl, new GUILayoutOption[] { GUILayout.Width(150) }))
|
|
||||||
{
|
|
||||||
m_isEvaluating = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GUILayout.EndVertical();
|
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
|
||||||
GUIUnstrip.Space(labelWidth);
|
|
||||||
}
|
|
||||||
else if (cm != null)
|
|
||||||
{
|
|
||||||
if (GUILayout.Button(EVALUATE_LABEL, new GUILayoutOption[] { GUILayout.Width(70) }))
|
|
||||||
{
|
|
||||||
cm.Evaluate();
|
|
||||||
}
|
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
|
||||||
GUIUnstrip.Space(labelWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
string typeName = $"<color={UIStyles.Syntax.Class_Instance}>{ValueType.FullName}</color>";
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(ReflectionException))
|
|
||||||
{
|
|
||||||
GUILayout.Label("<color=red>Reflection failed!</color> (" + ReflectionException + ")", new GUILayoutOption[0]);
|
|
||||||
}
|
|
||||||
else if ((HasParameters || this is CacheMethod) && !m_evaluated)
|
|
||||||
{
|
|
||||||
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> ({typeName})", new GUILayoutOption[0]);
|
|
||||||
}
|
|
||||||
else if (Value == null && !(this is CacheMethod))
|
|
||||||
{
|
|
||||||
GUILayout.Label($"<i>null ({typeName})</i>", new GUILayoutOption[0]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DrawValue(window, window.width - labelWidth - 90);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool GetCanWrite()
|
|
||||||
{
|
|
||||||
if (MemInfo is FieldInfo fi)
|
|
||||||
m_canWrite = !(fi.IsLiteral && !fi.IsInitOnly);
|
|
||||||
else if (MemInfo is PropertyInfo pi)
|
|
||||||
m_canWrite = pi.CanWrite;
|
|
||||||
else
|
|
||||||
m_canWrite = false;
|
|
||||||
|
|
||||||
return (bool)m_canWrite;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetRichTextName()
|
|
||||||
{
|
|
||||||
string memberColor = "";
|
|
||||||
bool isStatic = false;
|
|
||||||
|
|
||||||
if (MemInfo is FieldInfo fi)
|
|
||||||
{
|
|
||||||
if (fi.IsStatic)
|
|
||||||
{
|
|
||||||
isStatic = true;
|
|
||||||
memberColor = UIStyles.Syntax.Field_Static;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
memberColor = UIStyles.Syntax.Field_Instance;
|
|
||||||
}
|
|
||||||
else if (MemInfo is MethodInfo mi)
|
|
||||||
{
|
|
||||||
if (mi.IsStatic)
|
|
||||||
{
|
|
||||||
isStatic = true;
|
|
||||||
memberColor = UIStyles.Syntax.Method_Static;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
memberColor = UIStyles.Syntax.Method_Instance;
|
|
||||||
}
|
|
||||||
else if (MemInfo is PropertyInfo pi)
|
|
||||||
{
|
|
||||||
if (pi.GetAccessors()[0].IsStatic)
|
|
||||||
{
|
|
||||||
isStatic = true;
|
|
||||||
memberColor = UIStyles.Syntax.Prop_Static;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
memberColor = UIStyles.Syntax.Prop_Instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
string classColor;
|
|
||||||
if (MemInfo.DeclaringType.IsValueType)
|
|
||||||
{
|
|
||||||
classColor = UIStyles.Syntax.StructGreen;
|
|
||||||
}
|
|
||||||
else if (MemInfo.DeclaringType.IsAbstract && MemInfo.DeclaringType.IsSealed)
|
|
||||||
{
|
|
||||||
classColor = UIStyles.Syntax.Class_Static;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
classColor = UIStyles.Syntax.Class_Instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_richTextName = $"<color={classColor}>{MemInfo.DeclaringType.Name}</color>.";
|
|
||||||
if (isStatic) m_richTextName += "<i>";
|
|
||||||
m_richTextName += $"<color={memberColor}>{MemInfo.Name}</color>";
|
|
||||||
if (isStatic) m_richTextName += "</i>";
|
|
||||||
|
|
||||||
// generic method args
|
|
||||||
if (this is CacheMethod cm && cm.GenericArgs.Length > 0)
|
|
||||||
{
|
|
||||||
m_richTextName += "<";
|
|
||||||
|
|
||||||
var args = "";
|
|
||||||
for (int i = 0; i < cm.GenericArgs.Length; i++)
|
|
||||||
{
|
|
||||||
if (args != "") args += ", ";
|
|
||||||
args += $"<color={UIStyles.Syntax.StructGreen}>{cm.GenericArgs[i].Name}</color>";
|
|
||||||
}
|
|
||||||
m_richTextName += args;
|
|
||||||
|
|
||||||
m_richTextName += ">";
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_richTextName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Explorer
|
|
||||||
{
|
|
||||||
public class CacheGameObject : CacheObjectBase
|
|
||||||
{
|
|
||||||
public override void DrawValue(Rect window, float width)
|
|
||||||
{
|
|
||||||
UIHelpers.GOButton(Value, null, false, width);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void UpdateValue()
|
|
||||||
{
|
|
||||||
base.UpdateValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,80 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Explorer
|
|
||||||
{
|
|
||||||
public class CacheOther : CacheObjectBase
|
|
||||||
{
|
|
||||||
public string ButtonLabel => m_btnLabel ?? GetButtonLabel();
|
|
||||||
private string m_btnLabel;
|
|
||||||
|
|
||||||
public MethodInfo ToStringMethod => m_toStringMethod ?? GetToStringMethod();
|
|
||||||
private MethodInfo m_toStringMethod;
|
|
||||||
|
|
||||||
public override void UpdateValue()
|
|
||||||
{
|
|
||||||
base.UpdateValue();
|
|
||||||
|
|
||||||
GetButtonLabel();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void DrawValue(Rect window, float width)
|
|
||||||
{
|
|
||||||
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
|
||||||
if (GUILayout.Button(ButtonLabel, new GUILayoutOption[] { GUILayout.Width(width - 15) }))
|
|
||||||
{
|
|
||||||
WindowManager.InspectObject(Value, out bool _);
|
|
||||||
}
|
|
||||||
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
|
|
||||||
}
|
|
||||||
|
|
||||||
private MethodInfo GetToStringMethod()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
m_toStringMethod = ReflectionHelpers.GetActualType(Value).GetMethod("ToString", new Type[0])
|
|
||||||
?? typeof(object).GetMethod("ToString", new Type[0]);
|
|
||||||
|
|
||||||
// test invoke
|
|
||||||
m_toStringMethod.Invoke(Value, null);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
m_toStringMethod = typeof(object).GetMethod("ToString", new Type[0]);
|
|
||||||
}
|
|
||||||
return m_toStringMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetButtonLabel()
|
|
||||||
{
|
|
||||||
if (Value == null) return null;
|
|
||||||
|
|
||||||
string label = (string)ToStringMethod?.Invoke(Value, null) ?? Value.ToString();
|
|
||||||
|
|
||||||
var classColor = ValueType.IsAbstract && ValueType.IsSealed
|
|
||||||
? UIStyles.Syntax.Class_Static
|
|
||||||
: UIStyles.Syntax.Class_Instance;
|
|
||||||
|
|
||||||
string typeLabel = $"<color={classColor}>{ValueType.FullName}</color>";
|
|
||||||
|
|
||||||
if (Value is UnityEngine.Object)
|
|
||||||
{
|
|
||||||
label = label.Replace($"({ValueType.FullName})", $"({typeLabel})");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!label.Contains(ValueType.FullName))
|
|
||||||
{
|
|
||||||
label += $" ({typeLabel})";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
label = label.Replace(ValueType.FullName, typeLabel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_btnLabel = label;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,7 +2,7 @@
|
|||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.Config
|
||||||
{
|
{
|
||||||
public class ModConfig
|
public class ModConfig
|
||||||
{
|
{
|
||||||
@ -13,8 +13,13 @@ namespace Explorer
|
|||||||
|
|
||||||
[XmlIgnore] public static ModConfig Instance;
|
[XmlIgnore] public static ModConfig Instance;
|
||||||
|
|
||||||
public KeyCode Main_Menu_Toggle = KeyCode.F7;
|
// Actual configs
|
||||||
|
public KeyCode Main_Menu_Toggle = KeyCode.F7;
|
||||||
public Vector2 Default_Window_Size = new Vector2(550, 700);
|
public Vector2 Default_Window_Size = new Vector2(550, 700);
|
||||||
|
public int Default_Page_Limit = 20;
|
||||||
|
public bool Bitwise_Support = false;
|
||||||
|
public bool Tab_View = true;
|
||||||
|
public string Default_Output_Path = @"Mods\Explorer";
|
||||||
|
|
||||||
public static void OnLoad()
|
public static void OnLoad()
|
||||||
{
|
{
|
||||||
@ -30,9 +35,9 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns true if settings successfully loaded
|
// returns true if settings successfully loaded
|
||||||
public static bool LoadSettings(bool checkExist = true)
|
public static bool LoadSettings()
|
||||||
{
|
{
|
||||||
if (checkExist && !File.Exists(SETTINGS_PATH))
|
if (!File.Exists(SETTINGS_PATH))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -42,7 +47,7 @@ namespace Explorer
|
|||||||
Instance = (ModConfig)Serializer.Deserialize(file);
|
Instance = (ModConfig)Serializer.Deserialize(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -50,9 +55,9 @@ namespace Explorer
|
|||||||
return Instance != null;
|
return Instance != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SaveSettings(bool checkExist = true)
|
public static void SaveSettings()
|
||||||
{
|
{
|
||||||
if (checkExist && File.Exists(SETTINGS_PATH))
|
if (File.Exists(SETTINGS_PATH))
|
||||||
File.Delete(SETTINGS_PATH);
|
File.Delete(SETTINGS_PATH);
|
||||||
|
|
||||||
using (var file = File.Create(SETTINGS_PATH))
|
using (var file = File.Create(SETTINGS_PATH))
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
<DefineConstants>CPP,ML</DefineConstants>
|
<DefineConstants>CPP,ML</DefineConstants>
|
||||||
<IsCpp>true</IsCpp>
|
<IsCpp>true</IsCpp>
|
||||||
<IsMelonLoader>true</IsMelonLoader>
|
<IsMelonLoader>true</IsMelonLoader>
|
||||||
<IsNet35>false</IsNet35>
|
|
||||||
<DebugSymbols>false</DebugSymbols>
|
<DebugSymbols>false</DebugSymbols>
|
||||||
<DebugType>none</DebugType>
|
<DebugType>none</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
@ -27,13 +26,14 @@
|
|||||||
<AssemblyName>Explorer</AssemblyName>
|
<AssemblyName>Explorer</AssemblyName>
|
||||||
<!-- Set this to the MelonLoader Il2Cpp Game folder, without the ending '\' character. -->
|
<!-- Set this to the MelonLoader Il2Cpp Game folder, without the ending '\' character. -->
|
||||||
<MLCppGameFolder>D:\Steam\steamapps\common\Hellpoint</MLCppGameFolder>
|
<MLCppGameFolder>D:\Steam\steamapps\common\Hellpoint</MLCppGameFolder>
|
||||||
<!--<MLCppGameFolder>D:\source\Unity Projects\Test\_BUILD</MLCppGameFolder>-->
|
|
||||||
<!-- Set this to the MelonLoader Mono Game folder, without the ending '\' character. -->
|
<!-- Set this to the MelonLoader Mono Game folder, without the ending '\' character. -->
|
||||||
<MLMonoGameFolder>D:\Steam\steamapps\common\Outward</MLMonoGameFolder>
|
<MLMonoGameFolder>D:\Steam\steamapps\common\Outward</MLMonoGameFolder>
|
||||||
<!-- Set this to the BepInEx Il2Cpp Game folder, without the ending '\' character. -->
|
<!-- Set this to the BepInEx Il2Cpp Game folder, without the ending '\' character. -->
|
||||||
<BIECppGameFolder>D:\Steam\steamapps\common\Outward - Il2Cpp</BIECppGameFolder>
|
<BIECppGameFolder>D:\Steam\steamapps\common\Outward_Il2Cpp</BIECppGameFolder>
|
||||||
<!-- Set this to the BepInEx Mono Game folder, without the ending '\' character. -->
|
<!-- Set this to the BepInEx Mono Game folder, without the ending '\' character. -->
|
||||||
<BIEMonoGameFolder>D:\Steam\steamapps\common\Outward</BIEMonoGameFolder>
|
<BIEMonoGameFolder>D:\Steam\steamapps\common\Outward</BIEMonoGameFolder>
|
||||||
|
<NuGetPackageImportStamp>
|
||||||
|
</NuGetPackageImportStamp>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_ML_Cpp|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_ML_Cpp|AnyCPU' ">
|
||||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||||
@ -41,24 +41,16 @@
|
|||||||
<DefineConstants>CPP,ML</DefineConstants>
|
<DefineConstants>CPP,ML</DefineConstants>
|
||||||
<IsCpp>true</IsCpp>
|
<IsCpp>true</IsCpp>
|
||||||
<IsMelonLoader>true</IsMelonLoader>
|
<IsMelonLoader>true</IsMelonLoader>
|
||||||
<IsNet35>false</IsNet35>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_ML_Mono|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_ML_Mono|AnyCPU' ">
|
||||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||||
<OutputPath>..\Release\Explorer.MelonLoader.Mono\</OutputPath>
|
<OutputPath>..\Release\Explorer.MelonLoader.Mono\</OutputPath>
|
||||||
<DefineConstants>MONO,ML</DefineConstants>
|
<DefineConstants>MONO,ML</DefineConstants>
|
||||||
<Prefer32Bit>false</Prefer32Bit>
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
<IsCpp>false</IsCpp>
|
<IsCpp>false</IsCpp>
|
||||||
<IsMelonLoader>true</IsMelonLoader>
|
<IsMelonLoader>true</IsMelonLoader>
|
||||||
<IsNet35>false</IsNet35>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_ML_Mono_NET35|AnyCPU' ">
|
|
||||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
|
||||||
<OutputPath>..\Release\Explorer.MelonLoader.Mono.NET35\</OutputPath>
|
|
||||||
<DefineConstants>MONO,ML,NET35</DefineConstants>
|
|
||||||
<IsCpp>false</IsCpp>
|
|
||||||
<IsMelonLoader>true</IsMelonLoader>
|
|
||||||
<IsNet35>true</IsNet35>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_BIE_Cpp|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_BIE_Cpp|AnyCPU' ">
|
||||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||||
@ -66,23 +58,15 @@
|
|||||||
<DefineConstants>CPP,BIE</DefineConstants>
|
<DefineConstants>CPP,BIE</DefineConstants>
|
||||||
<IsCpp>true</IsCpp>
|
<IsCpp>true</IsCpp>
|
||||||
<IsMelonLoader>false</IsMelonLoader>
|
<IsMelonLoader>false</IsMelonLoader>
|
||||||
<IsNet35>false</IsNet35>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_BIE_Mono|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_BIE_Mono|AnyCPU' ">
|
||||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||||
<OutputPath>..\Release\Explorer.BepInEx.Mono\</OutputPath>
|
<OutputPath>..\Release\Explorer.BepInEx.Mono\</OutputPath>
|
||||||
<DefineConstants>MONO,BIE</DefineConstants>
|
<DefineConstants>MONO,BIE</DefineConstants>
|
||||||
<IsCpp>false</IsCpp>
|
<IsCpp>false</IsCpp>
|
||||||
<IsMelonLoader>false</IsMelonLoader>
|
<IsMelonLoader>false</IsMelonLoader>
|
||||||
<IsNet35>false</IsNet35>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_BIE_Mono_NET35|AnyCPU' ">
|
|
||||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
|
||||||
<OutputPath>..\Release\Explorer.BepInEx.Mono.NET35\</OutputPath>
|
|
||||||
<DefineConstants>MONO,BIE,NET35</DefineConstants>
|
|
||||||
<IsCpp>false</IsCpp>
|
|
||||||
<IsMelonLoader>false</IsMelonLoader>
|
|
||||||
<IsNet35>true</IsNet35>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
@ -92,13 +76,9 @@
|
|||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
<!-- MCS ref -->
|
<!-- MCS ref -->
|
||||||
<Reference Include="mcs" Condition="'$(IsNet35)'=='false'">
|
<Reference Include="mcs">
|
||||||
<HintPath>..\lib\mcs.dll</HintPath>
|
<HintPath>..\lib\mcs.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>False</Private>
|
||||||
</Reference>
|
|
||||||
<Reference Include="mcs" Condition="'$(IsNet35)'=='true'">
|
|
||||||
<HintPath>..\lib\mcs.NET35.dll</HintPath>
|
|
||||||
<Private>True</Private>
|
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- Universal Mono UnityEngine.dll ref (v5.3) -->
|
<!-- Universal Mono UnityEngine.dll ref (v5.3) -->
|
||||||
@ -221,56 +201,88 @@
|
|||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="CachedObjects\CacheFactory.cs" />
|
<Compile Include="CacheObject\CacheEnumerated.cs" />
|
||||||
<Compile Include="CachedObjects\IExpandHeight.cs" />
|
<Compile Include="CacheObject\CacheFactory.cs" />
|
||||||
<Compile Include="CachedObjects\Struct\CacheColor.cs" />
|
<Compile Include="CacheObject\CacheField.cs" />
|
||||||
<Compile Include="CachedObjects\Object\CacheDictionary.cs" />
|
<Compile Include="CacheObject\CacheMember.cs" />
|
||||||
<Compile Include="CachedObjects\Struct\CacheEnum.cs" />
|
<Compile Include="CacheObject\CacheMethod.cs" />
|
||||||
<Compile Include="CachedObjects\Object\CacheGameObject.cs" />
|
<Compile Include="CacheObject\CacheProperty.cs" />
|
||||||
<Compile Include="CachedObjects\Object\CacheList.cs" />
|
<Compile Include="CacheObject\CacheObjectBase.cs" />
|
||||||
<Compile Include="CachedObjects\Struct\CacheEnumFlags.cs" />
|
<Compile Include="Helpers\Texture2DHelpers.cs" />
|
||||||
<Compile Include="CachedObjects\Struct\CachePrimitive.cs" />
|
<Compile Include="UI\InteractiveValue\InteractiveValue.cs" />
|
||||||
<Compile Include="CachedObjects\Other\CacheOther.cs" />
|
<Compile Include="UI\InteractiveValue\Object\InteractiveDictionary.cs" />
|
||||||
<Compile Include="CachedObjects\Other\CacheMethod.cs" />
|
<Compile Include="UI\InteractiveValue\Object\InteractiveEnumerable.cs" />
|
||||||
<Compile Include="CachedObjects\Struct\CacheQuaternion.cs" />
|
<Compile Include="UI\InteractiveValue\Object\InteractiveGameObject.cs" />
|
||||||
<Compile Include="CachedObjects\Struct\CacheVector.cs" />
|
<Compile Include="UI\InteractiveValue\Object\InteractiveSprite.cs" />
|
||||||
<Compile Include="CachedObjects\Struct\CacheRect.cs" />
|
<Compile Include="UI\InteractiveValue\Object\InteractiveTexture.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" />
|
||||||
|
<Compile Include="UI\InteractiveValue\Struct\InteractiveColor.cs" />
|
||||||
|
<Compile Include="UI\InteractiveValue\Struct\InteractiveEnum.cs" />
|
||||||
|
<Compile Include="UI\InteractiveValue\Struct\InteractiveFlags.cs" />
|
||||||
|
<Compile Include="UI\InteractiveValue\Struct\InteractivePrimitive.cs" />
|
||||||
<Compile Include="Config\ModConfig.cs" />
|
<Compile Include="Config\ModConfig.cs" />
|
||||||
<Compile Include="ExplorerCore.cs" />
|
<Compile Include="ExplorerCore.cs" />
|
||||||
<Compile Include="ExplorerBepInPlugin.cs" />
|
<Compile Include="ExplorerBepInPlugin.cs" />
|
||||||
<Compile Include="ExplorerMelonMod.cs" />
|
<Compile Include="ExplorerMelonMod.cs" />
|
||||||
<Compile Include="Extensions\ReflectionExtensions.cs" />
|
<Compile Include="Extensions\ReflectionExtensions.cs" />
|
||||||
<Compile Include="Helpers\InputHelper.cs" />
|
|
||||||
<Compile Include="Menu\CursorControl.cs" />
|
|
||||||
<Compile Include="Tests\TestClass.cs" />
|
|
||||||
<Compile Include="UnstripFixes\GUIUnstrip.cs" />
|
|
||||||
<Compile Include="UnstripFixes\Internal_LayoutUtility.cs" />
|
|
||||||
<Compile Include="Extensions\UnityExtensions.cs" />
|
<Compile Include="Extensions\UnityExtensions.cs" />
|
||||||
<Compile Include="Helpers\PageHelper.cs" />
|
|
||||||
<Compile Include="Helpers\ReflectionHelpers.cs" />
|
<Compile Include="Helpers\ReflectionHelpers.cs" />
|
||||||
<Compile Include="Menu\UIHelpers.cs" />
|
|
||||||
<Compile Include="Helpers\UnityHelpers.cs" />
|
<Compile Include="Helpers\UnityHelpers.cs" />
|
||||||
<Compile Include="Menu\InspectUnderMouse.cs" />
|
<Compile Include="Input\AbstractInput.cs" />
|
||||||
<Compile Include="CachedObjects\CacheObjectBase.cs" />
|
<Compile Include="Tests\TestClass.cs" />
|
||||||
<Compile Include="UnstripFixes\Internal_ScrollViewState.cs" />
|
<Compile Include="UI\ForceUnlockCursor.cs" />
|
||||||
<Compile Include="UnstripFixes\Internal_SliderHandler.cs" />
|
<Compile Include="Input\InputManager.cs" />
|
||||||
<Compile Include="Menu\ResizeDrag.cs" />
|
<Compile Include="Input\InputSystem.cs" />
|
||||||
<Compile Include="Menu\Windows\TabViewWindow.cs" />
|
<Compile Include="Input\LegacyInput.cs" />
|
||||||
<Compile Include="Menu\Windows\UIWindow.cs" />
|
<Compile Include="Input\NoInput.cs" />
|
||||||
<Compile Include="Menu\MainMenu\Pages\ConsolePage.cs" />
|
<Compile Include="UI\Inspectors\InspectUnderMouse.cs" />
|
||||||
<Compile Include="Menu\MainMenu\Pages\Console\REPL.cs" />
|
<Compile Include="UI\Inspectors\Reflection\InstanceInspector.cs" />
|
||||||
<Compile Include="Menu\MainMenu\Pages\Console\REPLHelper.cs" />
|
<Compile Include="UI\Inspectors\ReflectionInspector.cs" />
|
||||||
<Compile Include="Menu\MainMenu\Pages\WindowPage.cs" />
|
<Compile Include="UI\Inspectors\Reflection\StaticInspector.cs" />
|
||||||
<Compile Include="Menu\Windows\WindowManager.cs" />
|
<Compile Include="UI\MainMenu.cs" />
|
||||||
<Compile Include="Menu\MainMenu\MainMenu.cs" />
|
<Compile Include="UI\Main\ConsolePage.cs" />
|
||||||
<Compile Include="Menu\Windows\GameObjectWindow.cs" />
|
<Compile Include="UI\Main\Console\AutoComplete.cs" />
|
||||||
<Compile Include="Menu\Windows\ReflectionWindow.cs" />
|
<Compile Include="UI\Main\Console\ScriptInteraction.cs" />
|
||||||
<Compile Include="Menu\MainMenu\Pages\ScenePage.cs" />
|
<Compile Include="UI\Main\Console\ScriptEvaluator.cs" />
|
||||||
<Compile Include="Menu\MainMenu\Pages\SearchPage.cs" />
|
<Compile Include="UI\Main\OptionsPage.cs" />
|
||||||
<Compile Include="Menu\UIStyles.cs" />
|
<Compile Include="UI\Main\ScenePage.cs" />
|
||||||
|
<Compile Include="UI\Main\SearchPage.cs" />
|
||||||
|
<Compile Include="UI\Main\BaseMainMenuPage.cs" />
|
||||||
|
<Compile Include="UI\Shared\Buttons.cs" />
|
||||||
|
<Compile Include="UI\Shared\IExpandHeight.cs" />
|
||||||
|
<Compile Include="UI\Shared\PageHelper.cs" />
|
||||||
|
<Compile Include="UI\Shared\ResizeDrag.cs" />
|
||||||
|
<Compile Include="UI\Shared\Syntax.cs" />
|
||||||
|
<Compile Include="UI\Shared\UIStyles.cs" />
|
||||||
|
<Compile Include="UI\Inspectors\GameObjectInspector.cs" />
|
||||||
|
<Compile Include="UI\TabViewWindow.cs" />
|
||||||
|
<Compile Include="UI\WindowBase.cs" />
|
||||||
|
<Compile Include="UI\WindowManager.cs" />
|
||||||
|
<Compile Include="Unstrip\ImageConversion\ImageConversionUnstrip.cs" />
|
||||||
|
<Compile Include="Unstrip\LayerMask\LayerMaskUnstrip.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="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="UnstripFixes\Internal.cs" />
|
<Compile Include="Unstrip\IMGUI\Internal.cs" />
|
||||||
<Compile Include="UnstripFixes\Internal_SliderState.cs" />
|
<Compile Include="Unstrip\IMGUI\Internal_SliderState.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="ILRepack.targets" />
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup />
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<Import Project="packages\ILRepack.Lib.MSBuild.Task.2.0.18.1\build\ILRepack.Lib.MSBuild.Task.targets" Condition="Exists('packages\ILRepack.Lib.MSBuild.Task.2.0.18.1\build\ILRepack.Lib.MSBuild.Task.targets')" />
|
||||||
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Error Condition="!Exists('packages\ILRepack.Lib.MSBuild.Task.2.0.18.1\build\ILRepack.Lib.MSBuild.Task.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\ILRepack.Lib.MSBuild.Task.2.0.18.1\build\ILRepack.Lib.MSBuild.Task.targets'))" />
|
||||||
|
</Target>
|
||||||
</Project>
|
</Project>
|
@ -8,23 +8,17 @@ EndProject
|
|||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Release_BIE_Cpp|Any CPU = Release_BIE_Cpp|Any CPU
|
Release_BIE_Cpp|Any CPU = Release_BIE_Cpp|Any CPU
|
||||||
Release_BIE_Mono_NET35|Any CPU = Release_BIE_Mono_NET35|Any CPU
|
|
||||||
Release_BIE_Mono|Any CPU = Release_BIE_Mono|Any CPU
|
Release_BIE_Mono|Any CPU = Release_BIE_Mono|Any CPU
|
||||||
Release_ML_Cpp|Any CPU = Release_ML_Cpp|Any CPU
|
Release_ML_Cpp|Any CPU = Release_ML_Cpp|Any CPU
|
||||||
Release_ML_Mono_NET35|Any CPU = Release_ML_Mono_NET35|Any CPU
|
|
||||||
Release_ML_Mono|Any CPU = Release_ML_Mono|Any CPU
|
Release_ML_Mono|Any CPU = Release_ML_Mono|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_BIE_Cpp|Any CPU.ActiveCfg = Release_BIE_Cpp|Any CPU
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_BIE_Cpp|Any CPU.ActiveCfg = Release_BIE_Cpp|Any CPU
|
||||||
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_BIE_Cpp|Any CPU.Build.0 = Release_BIE_Cpp|Any CPU
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_BIE_Cpp|Any CPU.Build.0 = Release_BIE_Cpp|Any CPU
|
||||||
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_BIE_Mono_NET35|Any CPU.ActiveCfg = Release_BIE_Mono_NET35|Any CPU
|
|
||||||
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_BIE_Mono_NET35|Any CPU.Build.0 = Release_BIE_Mono_NET35|Any CPU
|
|
||||||
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_BIE_Mono|Any CPU.ActiveCfg = Release_BIE_Mono|Any CPU
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_BIE_Mono|Any CPU.ActiveCfg = Release_BIE_Mono|Any CPU
|
||||||
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_BIE_Mono|Any CPU.Build.0 = Release_BIE_Mono|Any CPU
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_BIE_Mono|Any CPU.Build.0 = Release_BIE_Mono|Any CPU
|
||||||
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Cpp|Any CPU.ActiveCfg = Release_ML_Cpp|Any CPU
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Cpp|Any CPU.ActiveCfg = Release_ML_Cpp|Any CPU
|
||||||
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Cpp|Any CPU.Build.0 = Release_ML_Cpp|Any CPU
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Cpp|Any CPU.Build.0 = Release_ML_Cpp|Any CPU
|
||||||
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Mono_NET35|Any CPU.ActiveCfg = Release_ML_Mono_NET35|Any CPU
|
|
||||||
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Mono_NET35|Any CPU.Build.0 = Release_ML_Mono_NET35|Any CPU
|
|
||||||
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Mono|Any CPU.ActiveCfg = Release_ML_Mono|Any CPU
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Mono|Any CPU.ActiveCfg = Release_ML_Mono|Any CPU
|
||||||
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Mono|Any CPU.Build.0 = Release_ML_Mono|Any CPU
|
{B21DBDE3-5D6F-4726-93AB-CC3CC68BAE7D}.Release_ML_Mono|Any CPU.Build.0 = Release_ML_Mono|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
@ -14,7 +14,7 @@ using BepInEx.IL2CPP;
|
|||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
[BepInPlugin(ExplorerCore.GUID, ExplorerCore.NAME, ExplorerCore.VERSION)]
|
[BepInPlugin(ExplorerCore.GUID, "Explorer", ExplorerCore.VERSION)]
|
||||||
#if CPP
|
#if CPP
|
||||||
public class ExplorerBepInPlugin : BasePlugin
|
public class ExplorerBepInPlugin : BasePlugin
|
||||||
#else
|
#else
|
||||||
@ -62,22 +62,9 @@ namespace Explorer
|
|||||||
SceneManager.activeSceneChanged += DoSceneChange;
|
SceneManager.activeSceneChanged += DoSceneChange;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LoadMCS();
|
|
||||||
|
|
||||||
new ExplorerCore();
|
new ExplorerCore();
|
||||||
|
|
||||||
HarmonyInstance.PatchAll();
|
//HarmonyInstance.PatchAll();
|
||||||
}
|
|
||||||
|
|
||||||
void LoadMCS()
|
|
||||||
{
|
|
||||||
#if NET35
|
|
||||||
var path = @"BepInEx\plugins\mcs.NET35.dll";
|
|
||||||
#else
|
|
||||||
var path = @"BepInEx\plugins\mcs.dll";
|
|
||||||
#endif
|
|
||||||
Assembly.Load(File.ReadAllBytes(path));
|
|
||||||
ExplorerCore.Log("Loaded mcs!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void DoSceneChange(Scene arg0, Scene arg1)
|
internal static void DoSceneChange(Scene arg0, Scene arg1)
|
||||||
|
@ -1,43 +1,55 @@
|
|||||||
using UnityEngine;
|
using Explorer.Config;
|
||||||
|
using Explorer.UI;
|
||||||
|
using Explorer.UI.Inspectors;
|
||||||
|
using Explorer.UI.Main;
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
public class ExplorerCore
|
public class ExplorerCore
|
||||||
{
|
{
|
||||||
public const string NAME = "Explorer (" + PLATFORM + ", " + MODLOADER + ")";
|
public const string NAME = "Explorer " + VERSION + " (" + PLATFORM + ", " + MODLOADER + ")";
|
||||||
public const string VERSION = "1.8.1";
|
public const string VERSION = "2.0.4";
|
||||||
public const string AUTHOR = "Sinai";
|
public const string AUTHOR = "Sinai";
|
||||||
public const string GUID = "com.sinai.explorer";
|
public const string GUID = "com.sinai.explorer";
|
||||||
|
|
||||||
public const string MODLOADER =
|
|
||||||
#if ML
|
|
||||||
"MelonLoader";
|
|
||||||
#else
|
|
||||||
"BepInEx";
|
|
||||||
#endif
|
|
||||||
public const string PLATFORM =
|
public const string PLATFORM =
|
||||||
#if CPP
|
#if CPP
|
||||||
"Il2Cpp";
|
"Il2Cpp";
|
||||||
#else
|
#else
|
||||||
"Mono";
|
"Mono";
|
||||||
#endif
|
#endif
|
||||||
|
public const string MODLOADER =
|
||||||
|
#if ML
|
||||||
|
"MelonLoader";
|
||||||
|
#else
|
||||||
|
"BepInEx";
|
||||||
|
#endif
|
||||||
|
|
||||||
public static ExplorerCore Instance { get; private set; }
|
public static ExplorerCore Instance { get; private set; }
|
||||||
|
|
||||||
public ExplorerCore()
|
public ExplorerCore()
|
||||||
{
|
{
|
||||||
|
if (Instance != null)
|
||||||
|
{
|
||||||
|
Log("An instance of Explorer is already active!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Instance = this;
|
Instance = this;
|
||||||
|
|
||||||
ModConfig.OnLoad();
|
ModConfig.OnLoad();
|
||||||
|
|
||||||
InputHelper.Init();
|
|
||||||
|
|
||||||
new MainMenu();
|
new MainMenu();
|
||||||
new WindowManager();
|
new WindowManager();
|
||||||
|
|
||||||
CursorControl.Init();
|
InputManager.Init();
|
||||||
|
ForceUnlockCursor.Init();
|
||||||
|
|
||||||
Log($"{NAME} {VERSION} initialized.");
|
ShowMenu = true;
|
||||||
|
|
||||||
|
Log($"{NAME} initialized.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool ShowMenu
|
public static bool ShowMenu
|
||||||
@ -50,19 +62,19 @@ namespace Explorer
|
|||||||
private static void SetShowMenu(bool show)
|
private static void SetShowMenu(bool show)
|
||||||
{
|
{
|
||||||
m_showMenu = show;
|
m_showMenu = show;
|
||||||
CursorControl.UpdateCursorControl();
|
ForceUnlockCursor.UpdateCursorControl();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Update()
|
public static void Update()
|
||||||
{
|
{
|
||||||
if (InputHelper.GetKeyDown(ModConfig.Instance.Main_Menu_Toggle))
|
if (InputManager.GetKeyDown(ModConfig.Instance.Main_Menu_Toggle))
|
||||||
{
|
{
|
||||||
ShowMenu = !ShowMenu;
|
ShowMenu = !ShowMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ShowMenu)
|
if (ShowMenu)
|
||||||
{
|
{
|
||||||
CursorControl.Update();
|
ForceUnlockCursor.Update();
|
||||||
InspectUnderMouse.Update();
|
InspectUnderMouse.Update();
|
||||||
|
|
||||||
MainMenu.Instance.Update();
|
MainMenu.Instance.Update();
|
||||||
@ -81,6 +93,11 @@ namespace Explorer
|
|||||||
WindowManager.Instance.OnGUI();
|
WindowManager.Instance.OnGUI();
|
||||||
InspectUnderMouse.OnGUI();
|
InspectUnderMouse.OnGUI();
|
||||||
|
|
||||||
|
if (!ResizeDrag.IsMouseInResizeArea && WindowManager.IsMouseInWindow)
|
||||||
|
{
|
||||||
|
InputManager.ResetInputAxes();
|
||||||
|
}
|
||||||
|
|
||||||
GUI.skin = origSkin;
|
GUI.skin = origSkin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,30 +107,30 @@ namespace Explorer
|
|||||||
SearchPage.Instance?.OnSceneChange();
|
SearchPage.Instance?.OnSceneChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Log(string message)
|
public static void Log(object message)
|
||||||
{
|
{
|
||||||
#if ML
|
#if ML
|
||||||
MelonLoader.MelonLogger.Log(message);
|
MelonLoader.MelonLogger.Log(message.ToString());
|
||||||
#else
|
#else
|
||||||
ExplorerBepInPlugin.Logging?.LogMessage(message);
|
ExplorerBepInPlugin.Logging?.LogMessage(message.ToString());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void LogWarning(string message)
|
public static void LogWarning(object message)
|
||||||
{
|
{
|
||||||
#if ML
|
#if ML
|
||||||
MelonLoader.MelonLogger.LogWarning(message);
|
MelonLoader.MelonLogger.LogWarning(message.ToString());
|
||||||
#else
|
#else
|
||||||
ExplorerBepInPlugin.Logging?.LogWarning(message);
|
ExplorerBepInPlugin.Logging?.LogWarning(message.ToString());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void LogError(string message)
|
public static void LogError(object message)
|
||||||
{
|
{
|
||||||
#if ML
|
#if ML
|
||||||
MelonLoader.MelonLogger.LogError(message);
|
MelonLoader.MelonLogger.LogError(message.ToString());
|
||||||
#else
|
#else
|
||||||
ExplorerBepInPlugin.Logging?.LogError(message);
|
ExplorerBepInPlugin.Logging?.LogError(message.ToString());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,98 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Explorer
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Version-agnostic UnityEngine Input module using Reflection.
|
|
||||||
/// </summary>
|
|
||||||
public static class InputHelper
|
|
||||||
{
|
|
||||||
// If Input module failed to load at all
|
|
||||||
public static bool NO_INPUT;
|
|
||||||
|
|
||||||
// Base UnityEngine.Input class
|
|
||||||
private static Type Input => _input ?? (_input = ReflectionHelpers.GetTypeByName("UnityEngine.Input"));
|
|
||||||
private static Type _input;
|
|
||||||
|
|
||||||
// Cached member infos
|
|
||||||
private static PropertyInfo _mousePosition;
|
|
||||||
private static MethodInfo _getKey;
|
|
||||||
private static MethodInfo _getKeyDown;
|
|
||||||
private static MethodInfo _getMouseButton;
|
|
||||||
private static MethodInfo _getMouseButtonDown;
|
|
||||||
|
|
||||||
public static void Init()
|
|
||||||
{
|
|
||||||
if (Input == null && !TryManuallyLoadInput())
|
|
||||||
{
|
|
||||||
NO_INPUT = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache reflection now that we know Input is loaded
|
|
||||||
|
|
||||||
_mousePosition = Input.GetProperty("mousePosition");
|
|
||||||
|
|
||||||
_getKey = Input.GetMethod("GetKey", new Type[] { typeof(KeyCode) });
|
|
||||||
_getKeyDown = Input.GetMethod("GetKeyDown", new Type[] { typeof(KeyCode) });
|
|
||||||
_getMouseButton = Input.GetMethod("GetMouseButton", new Type[] { typeof(int) });
|
|
||||||
_getMouseButtonDown = Input.GetMethod("GetMouseButtonDown", new Type[] { typeof(int) });
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma warning disable IDE1006 // Camel-case property (Unity style)
|
|
||||||
public static Vector3 mousePosition
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (NO_INPUT) return Vector3.zero;
|
|
||||||
return (Vector3)_mousePosition.GetValue(null, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#pragma warning restore IDE1006
|
|
||||||
|
|
||||||
public static bool GetKeyDown(KeyCode key)
|
|
||||||
{
|
|
||||||
if (NO_INPUT) return false;
|
|
||||||
return (bool)_getKeyDown.Invoke(null, new object[] { key });
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool GetKey(KeyCode key)
|
|
||||||
{
|
|
||||||
if (NO_INPUT) return false;
|
|
||||||
return (bool)_getKey.Invoke(null, new object[] { key });
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <param name="btn">1 = left, 2 = middle, 3 = right, etc</param>
|
|
||||||
public static bool GetMouseButtonDown(int btn)
|
|
||||||
{
|
|
||||||
if (NO_INPUT) return false;
|
|
||||||
return (bool)_getMouseButtonDown.Invoke(null, new object[] { btn });
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <param name="btn">1 = left, 2 = middle, 3 = right, etc</param>
|
|
||||||
public static bool GetMouseButton(int btn)
|
|
||||||
{
|
|
||||||
if (NO_INPUT) return false;
|
|
||||||
return (bool)_getMouseButton.Invoke(null, new object[] { btn });
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool TryManuallyLoadInput()
|
|
||||||
{
|
|
||||||
ExplorerCore.Log("UnityEngine.Input is null, trying to load manually....");
|
|
||||||
|
|
||||||
if ((ReflectionHelpers.LoadModule("UnityEngine.InputLegacyModule") || ReflectionHelpers.LoadModule("UnityEngine.CoreModule"))
|
|
||||||
&& Input != null)
|
|
||||||
{
|
|
||||||
ExplorerCore.Log("Ok!");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ExplorerCore.Log("Could not load Input module!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,11 +19,11 @@ namespace Explorer
|
|||||||
public static BF CommonFlags = BF.Public | BF.Instance | BF.NonPublic | BF.Static;
|
public static BF CommonFlags = BF.Public | BF.Instance | BF.NonPublic | BF.Static;
|
||||||
|
|
||||||
#if CPP
|
#if CPP
|
||||||
public static ILType GameObjectType => Il2CppType.Of<GameObject>();
|
public static ILType GameObjectType => Il2CppType.Of<GameObject>();
|
||||||
public static ILType TransformType => Il2CppType.Of<Transform>();
|
public static ILType TransformType => Il2CppType.Of<Transform>();
|
||||||
public static ILType ObjectType => Il2CppType.Of<UnityEngine.Object>();
|
public static ILType ObjectType => Il2CppType.Of<UnityEngine.Object>();
|
||||||
public static ILType ComponentType => Il2CppType.Of<Component>();
|
public static ILType ComponentType => Il2CppType.Of<Component>();
|
||||||
public static ILType BehaviourType => Il2CppType.Of<Behaviour>();
|
public static ILType BehaviourType => Il2CppType.Of<Behaviour>();
|
||||||
|
|
||||||
private static readonly MethodInfo tryCastMethodInfo = typeof(Il2CppObjectBase).GetMethod("TryCast");
|
private static readonly MethodInfo tryCastMethodInfo = typeof(Il2CppObjectBase).GetMethod("TryCast");
|
||||||
private static readonly Dictionary<Type, MethodInfo> cachedTryCastMethods = new Dictionary<Type, MethodInfo>();
|
private static readonly Dictionary<Type, MethodInfo> cachedTryCastMethods = new Dictionary<Type, MethodInfo>();
|
||||||
@ -131,12 +131,12 @@ namespace Explorer
|
|||||||
return obj.GetType();
|
return obj.GetType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Type[] GetAllBaseTypes(object obj)
|
public static Type[] GetAllBaseTypes(object obj) => GetAllBaseTypes(GetActualType(obj));
|
||||||
|
|
||||||
|
public static Type[] GetAllBaseTypes(Type type)
|
||||||
{
|
{
|
||||||
var list = new List<Type>();
|
var list = new List<Type>();
|
||||||
|
|
||||||
var type = GetActualType(obj);
|
|
||||||
|
|
||||||
while (type != null)
|
while (type != null)
|
||||||
{
|
{
|
||||||
list.Add(type);
|
list.Add(type);
|
||||||
|
194
src/Helpers/Texture2DHelpers.cs
Normal file
194
src/Helpers/Texture2DHelpers.cs
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
#if CPP
|
||||||
|
using Explorer.Unstrip.ImageConversion;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Explorer.Helpers
|
||||||
|
{
|
||||||
|
public static class Texture2DHelpers
|
||||||
|
{
|
||||||
|
#if CPP
|
||||||
|
#else
|
||||||
|
private static bool isNewEncodeMethod = false;
|
||||||
|
private static MethodInfo EncodeToPNGMethod => m_encodeToPNGMethod ?? GetEncodeToPNGMethod();
|
||||||
|
private static MethodInfo m_encodeToPNGMethod;
|
||||||
|
|
||||||
|
private static MethodInfo GetEncodeToPNGMethod()
|
||||||
|
{
|
||||||
|
if (ReflectionHelpers.GetTypeByName("UnityEngine.ImageConversion") is Type imageConversion)
|
||||||
|
{
|
||||||
|
isNewEncodeMethod = true;
|
||||||
|
return m_encodeToPNGMethod = imageConversion.GetMethod("EncodeToPNG", ReflectionHelpers.CommonFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
var method = typeof(Texture2D).GetMethod("EncodeToPNG", ReflectionHelpers.CommonFlags);
|
||||||
|
if (method != null)
|
||||||
|
{
|
||||||
|
return m_encodeToPNGMethod = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExplorerCore.Log("ERROR: Cannot get any EncodeToPNG method!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
public static bool IsReadable(this Texture2D tex)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// This will cause an exception if it's not readable.
|
||||||
|
// Reason for doing it this way is not all Unity versions
|
||||||
|
// ship with the 'Texture.isReadable' property.
|
||||||
|
|
||||||
|
tex.GetPixel(0, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Texture2D Copy(Texture2D other, Rect rect, bool isDTXnmNormal = false)
|
||||||
|
{
|
||||||
|
Color[] pixels;
|
||||||
|
|
||||||
|
if (!other.IsReadable())
|
||||||
|
{
|
||||||
|
other = ForceReadTexture(other, isDTXnmNormal);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixels = other.GetPixels((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
|
||||||
|
|
||||||
|
var _newTex = new Texture2D((int)rect.width, (int)rect.height);
|
||||||
|
_newTex.SetPixels(pixels);
|
||||||
|
|
||||||
|
return _newTex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Texture2D ForceReadTexture(Texture2D tex, bool isDTXnmNormal = false)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var origFilter = tex.filterMode;
|
||||||
|
tex.filterMode = FilterMode.Point;
|
||||||
|
|
||||||
|
RenderTexture rt = RenderTexture.GetTemporary(tex.width, tex.height, 0, RenderTextureFormat.ARGB32);
|
||||||
|
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;
|
||||||
|
|
||||||
|
return _newTex;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExplorerCore.Log("Exception on ForceReadTexture: " + e.ToString());
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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";
|
||||||
|
|
||||||
|
// Fix for non-Readable or Compressed textures.
|
||||||
|
tex = ForceReadTexture(tex, isDTXnmNormal);
|
||||||
|
|
||||||
|
if (isDTXnmNormal)
|
||||||
|
{
|
||||||
|
tex = DTXnmToRGBA(tex);
|
||||||
|
tex.Apply(false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CPP
|
||||||
|
data = tex.EncodeToPNG();
|
||||||
|
#else
|
||||||
|
var method = EncodeToPNGMethod;
|
||||||
|
|
||||||
|
if (isNewEncodeMethod)
|
||||||
|
{
|
||||||
|
data = (byte[])method.Invoke(null, new object[] { tex });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data = (byte[])method.Invoke(tex, new object[0]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
src/ILRepack.targets
Normal file
21
src/ILRepack.targets
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Target Name="ILRepacker" AfterTargets="Build">
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<InputAssemblies Include="$(OutputPath)$(AssemblyName).dll" />
|
||||||
|
<InputAssemblies Include="..\lib\mcs.dll" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ILRepack
|
||||||
|
Parallel="true"
|
||||||
|
Internalize="true"
|
||||||
|
DebugInfo="false"
|
||||||
|
LibraryPath="..\lib\"
|
||||||
|
InputAssemblies="@(InputAssemblies)"
|
||||||
|
TargetKind="Dll"
|
||||||
|
OutputFile="$(OutputPath)$(AssemblyName).dll"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</Target>
|
||||||
|
</Project>
|
21
src/Input/AbstractInput.cs
Normal file
21
src/Input/AbstractInput.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Explorer.Input
|
||||||
|
{
|
||||||
|
public abstract class AbstractInput
|
||||||
|
{
|
||||||
|
public abstract void Init();
|
||||||
|
|
||||||
|
public abstract Vector2 MousePosition { get; }
|
||||||
|
|
||||||
|
public abstract bool GetKeyDown(KeyCode key);
|
||||||
|
public abstract bool GetKey(KeyCode key);
|
||||||
|
|
||||||
|
public abstract bool GetMouseButtonDown(int btn);
|
||||||
|
public abstract bool GetMouseButton(int btn);
|
||||||
|
}
|
||||||
|
}
|
84
src/Input/InputManager.cs
Normal file
84
src/Input/InputManager.cs
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityEngine;
|
||||||
|
using Explorer.Input;
|
||||||
|
#if CPP
|
||||||
|
using UnhollowerBaseLib;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Explorer
|
||||||
|
{
|
||||||
|
public static class InputManager
|
||||||
|
{
|
||||||
|
private static AbstractInput inputModule;
|
||||||
|
|
||||||
|
public static void Init()
|
||||||
|
{
|
||||||
|
if (InputSystem.TKeyboard != null || TryLoadModule("Unity.InputSystem", InputSystem.TKeyboard))
|
||||||
|
{
|
||||||
|
inputModule = new InputSystem();
|
||||||
|
}
|
||||||
|
else if (LegacyInput.TInput != null || TryLoadModule("UnityEngine.InputLegacyModule", LegacyInput.TInput))
|
||||||
|
{
|
||||||
|
inputModule = new LegacyInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputModule == null)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning("Could not find any Input module!");
|
||||||
|
inputModule = new NoInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
inputModule.Init();
|
||||||
|
|
||||||
|
bool TryLoadModule(string dll, Type check) => ReflectionHelpers.LoadModule(dll) && check != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector3 MousePosition => inputModule.MousePosition;
|
||||||
|
|
||||||
|
public static bool GetKeyDown(KeyCode key) => inputModule.GetKeyDown(key);
|
||||||
|
public static bool GetKey(KeyCode key) => inputModule.GetKey(key);
|
||||||
|
|
||||||
|
public static bool GetMouseButtonDown(int btn) => inputModule.GetMouseButtonDown(btn);
|
||||||
|
public static bool GetMouseButton(int btn) => inputModule.GetMouseButton(btn);
|
||||||
|
|
||||||
|
#if CPP
|
||||||
|
internal delegate void d_ResetInputAxes();
|
||||||
|
internal static d_ResetInputAxes ResetInputAxes_iCall =
|
||||||
|
IL2CPP.ResolveICall<d_ResetInputAxes>("UnityEngine.Input::ResetInputAxes");
|
||||||
|
|
||||||
|
public static void ResetInputAxes() => ResetInputAxes_iCall();
|
||||||
|
#else
|
||||||
|
public static void ResetInputAxes() => UnityEngine.Input.ResetInputAxes();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//#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
|
||||||
|
}
|
||||||
|
}
|
109
src/Input/InputSystem.cs
Normal file
109
src/Input/InputSystem.cs
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Explorer.Input
|
||||||
|
{
|
||||||
|
public class InputSystem : AbstractInput
|
||||||
|
{
|
||||||
|
public static Type TKeyboard => _keyboard ?? (_keyboard = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Keyboard"));
|
||||||
|
private static Type _keyboard;
|
||||||
|
|
||||||
|
public static Type TMouse => _mouse ?? (_mouse = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Mouse"));
|
||||||
|
private static Type _mouse;
|
||||||
|
|
||||||
|
public static Type TKey => _key ?? (_key = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Key"));
|
||||||
|
private static Type _key;
|
||||||
|
|
||||||
|
private static PropertyInfo _btnIsPressedProp;
|
||||||
|
private static PropertyInfo _btnWasPressedProp;
|
||||||
|
|
||||||
|
private static object CurrentKeyboard => _currentKeyboard ?? (_currentKeyboard = _kbCurrentProp.GetValue(null, null));
|
||||||
|
private static object _currentKeyboard;
|
||||||
|
private static PropertyInfo _kbCurrentProp;
|
||||||
|
private static PropertyInfo _kbIndexer;
|
||||||
|
|
||||||
|
private static object CurrentMouse => _currentMouse ?? (_currentMouse = _mouseCurrentProp.GetValue(null, null));
|
||||||
|
private static object _currentMouse;
|
||||||
|
private static PropertyInfo _mouseCurrentProp;
|
||||||
|
|
||||||
|
private static object LeftMouseButton => _lmb ?? (_lmb = _leftButtonProp.GetValue(CurrentMouse, null));
|
||||||
|
private static object _lmb;
|
||||||
|
private static PropertyInfo _leftButtonProp;
|
||||||
|
|
||||||
|
private static object RightMouseButton => _rmb ?? (_rmb = _rightButtonProp.GetValue(CurrentMouse, null));
|
||||||
|
private static object _rmb;
|
||||||
|
private static PropertyInfo _rightButtonProp;
|
||||||
|
|
||||||
|
private static object MousePositionInfo => _pos ?? (_pos = _positionProp.GetValue(CurrentMouse, null));
|
||||||
|
private static object _pos;
|
||||||
|
private static PropertyInfo _positionProp;
|
||||||
|
private static MethodInfo _readVector2InputMethod;
|
||||||
|
|
||||||
|
public override Vector2 MousePosition => (Vector2)_readVector2InputMethod.Invoke(MousePositionInfo, new object[0]);
|
||||||
|
|
||||||
|
public override bool GetKeyDown(KeyCode key)
|
||||||
|
{
|
||||||
|
var parsedKey = Enum.Parse(TKey, key.ToString());
|
||||||
|
var actualKey = _kbIndexer.GetValue(CurrentKeyboard, new object[] { parsedKey });
|
||||||
|
|
||||||
|
return (bool)_btnWasPressedProp.GetValue(actualKey, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool GetKey(KeyCode key)
|
||||||
|
{
|
||||||
|
var parsed = Enum.Parse(TKey, key.ToString());
|
||||||
|
var actualKey = _kbIndexer.GetValue(CurrentKeyboard, new object[] { parsed });
|
||||||
|
|
||||||
|
return (bool)_btnIsPressedProp.GetValue(actualKey, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool GetMouseButtonDown(int btn)
|
||||||
|
{
|
||||||
|
switch (btn)
|
||||||
|
{
|
||||||
|
case 0: return (bool)_btnWasPressedProp.GetValue(LeftMouseButton, null);
|
||||||
|
case 1: return (bool)_btnWasPressedProp.GetValue(RightMouseButton, null);
|
||||||
|
// case 2: return (bool)_btnWasPressedProp.GetValue(MiddleMouseButton, null);
|
||||||
|
default: throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool GetMouseButton(int btn)
|
||||||
|
{
|
||||||
|
switch (btn)
|
||||||
|
{
|
||||||
|
case 0: return (bool)_btnIsPressedProp.GetValue(LeftMouseButton, null);
|
||||||
|
case 1: return (bool)_btnIsPressedProp.GetValue(RightMouseButton, null);
|
||||||
|
// case 2: return (bool)_btnIsPressedProp.GetValue(MiddleMouseButton, null);
|
||||||
|
default: throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Init()
|
||||||
|
{
|
||||||
|
ExplorerCore.Log("Initializing new InputSystem support...");
|
||||||
|
|
||||||
|
_kbCurrentProp = TKeyboard.GetProperty("current");
|
||||||
|
_kbIndexer = TKeyboard.GetProperty("Item", new Type[] { TKey });
|
||||||
|
|
||||||
|
var btnControl = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Controls.ButtonControl");
|
||||||
|
_btnIsPressedProp = btnControl.GetProperty("isPressed");
|
||||||
|
_btnWasPressedProp = btnControl.GetProperty("wasPressedThisFrame");
|
||||||
|
|
||||||
|
_mouseCurrentProp = TMouse.GetProperty("current");
|
||||||
|
_leftButtonProp = TMouse.GetProperty("leftButton");
|
||||||
|
_rightButtonProp = TMouse.GetProperty("rightButton");
|
||||||
|
|
||||||
|
_positionProp = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.Pointer")
|
||||||
|
.GetProperty("position");
|
||||||
|
|
||||||
|
_readVector2InputMethod = ReflectionHelpers.GetTypeByName("UnityEngine.InputSystem.InputControl`1")
|
||||||
|
.MakeGenericType(typeof(Vector2))
|
||||||
|
.GetMethod("ReadValue");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
42
src/Input/LegacyInput.cs
Normal file
42
src/Input/LegacyInput.cs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Explorer.Input
|
||||||
|
{
|
||||||
|
public class LegacyInput : AbstractInput
|
||||||
|
{
|
||||||
|
public static Type TInput => _input ?? (_input = ReflectionHelpers.GetTypeByName("UnityEngine.Input"));
|
||||||
|
private static Type _input;
|
||||||
|
|
||||||
|
private static PropertyInfo _mousePositionProp;
|
||||||
|
private static MethodInfo _getKeyMethod;
|
||||||
|
private static MethodInfo _getKeyDownMethod;
|
||||||
|
private static MethodInfo _getMouseButtonMethod;
|
||||||
|
private static MethodInfo _getMouseButtonDownMethod;
|
||||||
|
|
||||||
|
public override Vector2 MousePosition => (Vector3)_mousePositionProp.GetValue(null, null);
|
||||||
|
|
||||||
|
public override bool GetKey(KeyCode key) => (bool)_getKeyMethod.Invoke(null, new object[] { key });
|
||||||
|
|
||||||
|
public override bool GetKeyDown(KeyCode key) => (bool)_getKeyDownMethod.Invoke(null, new object[] { key });
|
||||||
|
|
||||||
|
public override bool GetMouseButton(int btn) => (bool)_getMouseButtonMethod.Invoke(null, new object[] { btn });
|
||||||
|
|
||||||
|
public override bool GetMouseButtonDown(int btn) => (bool)_getMouseButtonDownMethod.Invoke(null, new object[] { btn });
|
||||||
|
|
||||||
|
public override void Init()
|
||||||
|
{
|
||||||
|
ExplorerCore.Log("Initializing Legacy Input support...");
|
||||||
|
|
||||||
|
_mousePositionProp = TInput.GetProperty("mousePosition");
|
||||||
|
_getKeyMethod = TInput.GetMethod("GetKey", new Type[] { typeof(KeyCode) });
|
||||||
|
_getKeyDownMethod = TInput.GetMethod("GetKeyDown", new Type[] { typeof(KeyCode) });
|
||||||
|
_getMouseButtonMethod = TInput.GetMethod("GetMouseButton", new Type[] { typeof(int) });
|
||||||
|
_getMouseButtonDownMethod = TInput.GetMethod("GetMouseButtonDown", new Type[] { typeof(int) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
src/Input/NoInput.cs
Normal file
25
src/Input/NoInput.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Explorer.Input
|
||||||
|
{
|
||||||
|
// Just a stub for games where no Input module was able to load at all.
|
||||||
|
|
||||||
|
public class NoInput : AbstractInput
|
||||||
|
{
|
||||||
|
public override Vector2 MousePosition => Vector2.zero;
|
||||||
|
|
||||||
|
public override bool GetKey(KeyCode key) => false;
|
||||||
|
|
||||||
|
public override bool GetKeyDown(KeyCode key) => false;
|
||||||
|
|
||||||
|
public override bool GetMouseButton(int btn) => false;
|
||||||
|
|
||||||
|
public override bool GetMouseButtonDown(int btn) => false;
|
||||||
|
|
||||||
|
public override void Init() { }
|
||||||
|
}
|
||||||
|
}
|
@ -1,126 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Mono.CSharp;
|
|
||||||
using UnityEngine;
|
|
||||||
using Attribute = System.Attribute;
|
|
||||||
using Object = UnityEngine.Object;
|
|
||||||
|
|
||||||
namespace Explorer
|
|
||||||
{
|
|
||||||
public class REPL : InteractiveBase
|
|
||||||
{
|
|
||||||
static REPL()
|
|
||||||
{
|
|
||||||
var go = new GameObject("UnityREPL");
|
|
||||||
GameObject.DontDestroyOnLoad(go);
|
|
||||||
//go.transform.parent = HPExplorer.Instance.transform;
|
|
||||||
MB = go.AddComponent<ReplHelper>();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Documentation("MB - A dummy MonoBehaviour for accessing Unity.")]
|
|
||||||
public static ReplHelper MB { get; }
|
|
||||||
|
|
||||||
[Documentation("find<T>() - find a UnityEngine.Object of type T.")]
|
|
||||||
public static T find<T>() where T : Object
|
|
||||||
{
|
|
||||||
return MB.Find<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Documentation("findAll<T>() - find all UnityEngine.Object of type T.")]
|
|
||||||
public static T[] findAll<T>() where T : Object
|
|
||||||
{
|
|
||||||
return MB.FindAll<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
//[Documentation("runCoroutine(enumerator) - runs an IEnumerator as a Unity coroutine.")]
|
|
||||||
//public static object runCoroutine(IEnumerator i)
|
|
||||||
//{
|
|
||||||
// return MB.RunCoroutine(i);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//[Documentation("endCoroutine(co) - ends a Unity coroutine.")]
|
|
||||||
//public static void endCoroutine(Coroutine c)
|
|
||||||
//{
|
|
||||||
// MB.EndCoroutine(c);
|
|
||||||
//}
|
|
||||||
|
|
||||||
////[Documentation("type<T>() - obtain type info about a type T. Provides some Reflection helpers.")]
|
|
||||||
////public static TypeHelper type<T>()
|
|
||||||
////{
|
|
||||||
//// return new TypeHelper(typeof(T));
|
|
||||||
////}
|
|
||||||
|
|
||||||
////[Documentation("type(obj) - obtain type info about object obj. Provides some Reflection helpers.")]
|
|
||||||
////public static TypeHelper type(object instance)
|
|
||||||
////{
|
|
||||||
//// return new TypeHelper(instance);
|
|
||||||
////}
|
|
||||||
|
|
||||||
//[Documentation("dir(obj) - lists all available methods and fiels of a given obj.")]
|
|
||||||
//public static string dir(object instance)
|
|
||||||
//{
|
|
||||||
// return type(instance).info();
|
|
||||||
//}
|
|
||||||
|
|
||||||
//[Documentation("dir<T>() - lists all available methods and fields of type T.")]
|
|
||||||
//public static string dir<T>()
|
|
||||||
//{
|
|
||||||
// return type<T>().info();
|
|
||||||
//}
|
|
||||||
|
|
||||||
//[Documentation("findrefs(obj) - find references to the object in currently loaded components.")]
|
|
||||||
//public static Component[] findrefs(object obj)
|
|
||||||
//{
|
|
||||||
// if (obj == null) throw new ArgumentNullException(nameof(obj));
|
|
||||||
|
|
||||||
// var results = new List<Component>();
|
|
||||||
// foreach (var component in Object.FindObjectsOfType<Component>())
|
|
||||||
// {
|
|
||||||
// var type = component.GetType();
|
|
||||||
|
|
||||||
// var nameBlacklist = new[] { "parent", "parentInternal", "root", "transform", "gameObject" };
|
|
||||||
// var typeBlacklist = new[] { typeof(bool) };
|
|
||||||
|
|
||||||
// foreach (var prop in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
|
||||||
// .Where(x => x.CanRead && !nameBlacklist.Contains(x.Name) && !typeBlacklist.Contains(x.PropertyType)))
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// if (Equals(prop.GetValue(component, null), obj))
|
|
||||||
// {
|
|
||||||
// results.Add(component);
|
|
||||||
// goto finish;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// catch { }
|
|
||||||
// }
|
|
||||||
// foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
|
||||||
// .Where(x => !nameBlacklist.Contains(x.Name) && !typeBlacklist.Contains(x.FieldType)))
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// if (Equals(field.GetValue(component), obj))
|
|
||||||
// {
|
|
||||||
// results.Add(component);
|
|
||||||
// goto finish;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// catch { }
|
|
||||||
// }
|
|
||||||
// finish:;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return results.ToArray();
|
|
||||||
//}
|
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property)]
|
|
||||||
private class DocumentationAttribute : Attribute
|
|
||||||
{
|
|
||||||
public DocumentationAttribute(string doc)
|
|
||||||
{
|
|
||||||
Docs = doc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Docs { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
using System;
|
|
||||||
using UnityEngine;
|
|
||||||
using Object = UnityEngine.Object;
|
|
||||||
|
|
||||||
namespace Explorer
|
|
||||||
{
|
|
||||||
public class ReplHelper : MonoBehaviour
|
|
||||||
{
|
|
||||||
#if CPP
|
|
||||||
public ReplHelper(IntPtr intPtr) : base(intPtr) { }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public T Find<T>() where T : Object
|
|
||||||
{
|
|
||||||
return FindObjectOfType<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public T[] FindAll<T>() where T : Object
|
|
||||||
{
|
|
||||||
return FindObjectsOfType<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
//public object RunCoroutine(IEnumerator enumerator)
|
|
||||||
//{
|
|
||||||
// return MelonCoroutines.Start(enumerator);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public void EndCoroutine(Coroutine c)
|
|
||||||
//{
|
|
||||||
// StopCoroutine(c);
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,252 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
using Mono.CSharp;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Explorer
|
|
||||||
{
|
|
||||||
public class ConsolePage : WindowPage
|
|
||||||
{
|
|
||||||
public override string Name { get => "C# Console"; }
|
|
||||||
|
|
||||||
private ScriptEvaluator _evaluator;
|
|
||||||
private readonly StringBuilder _sb = new StringBuilder();
|
|
||||||
|
|
||||||
private Vector2 inputAreaScroll;
|
|
||||||
|
|
||||||
private string MethodInput = "";
|
|
||||||
private string UsingInput = "";
|
|
||||||
|
|
||||||
public static List<string> UsingDirectives;
|
|
||||||
|
|
||||||
private static readonly string[] m_defaultUsing = new string[]
|
|
||||||
{
|
|
||||||
"System",
|
|
||||||
"UnityEngine",
|
|
||||||
"System.Linq",
|
|
||||||
"System.Collections",
|
|
||||||
"System.Collections.Generic",
|
|
||||||
"System.Reflection",
|
|
||||||
#if ML
|
|
||||||
"MelonLoader"
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
public override void Init()
|
|
||||||
{
|
|
||||||
#if CPP
|
|
||||||
UnhollowerRuntimeLib.ClassInjector.RegisterTypeInIl2Cpp<ReplHelper>();
|
|
||||||
#endif
|
|
||||||
try
|
|
||||||
{
|
|
||||||
MethodInput = @"// This is a basic C# console.
|
|
||||||
// Some common using directives are added by default, you can add more below.
|
|
||||||
// If you want to return some output, Debug.Log() or MelonLogger.Log() it.
|
|
||||||
"
|
|
||||||
#if ML
|
|
||||||
+ @"MelonLogger.Log(""hello world"");";
|
|
||||||
#else
|
|
||||||
+ @"Debug.Log(""hello world"");";
|
|
||||||
#endif
|
|
||||||
;
|
|
||||||
|
|
||||||
ResetConsole();
|
|
||||||
|
|
||||||
foreach (var use in m_defaultUsing)
|
|
||||||
{
|
|
||||||
AddUsing(use);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
ExplorerCore.Log($"Error setting up console!\r\nMessage: {e.Message}");
|
|
||||||
MainMenu.SetCurrentPage(0);
|
|
||||||
MainMenu.Pages.Remove(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ResetConsole()
|
|
||||||
{
|
|
||||||
if (_evaluator != null)
|
|
||||||
{
|
|
||||||
_evaluator.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
_evaluator = new ScriptEvaluator(new StringWriter(_sb)) { InteractiveBaseClass = typeof(REPL) };
|
|
||||||
|
|
||||||
UsingDirectives = new List<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string AsmToUsing(string asm, bool richtext = false)
|
|
||||||
{
|
|
||||||
if (richtext)
|
|
||||||
{
|
|
||||||
return $"<color=#569cd6>using</color> {asm};";
|
|
||||||
}
|
|
||||||
return $"using {asm};";
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddUsing(string asm)
|
|
||||||
{
|
|
||||||
if (!UsingDirectives.Contains(asm))
|
|
||||||
{
|
|
||||||
UsingDirectives.Add(asm);
|
|
||||||
Evaluate(AsmToUsing(asm), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public object Evaluate(string str, bool suppressWarning = false)
|
|
||||||
{
|
|
||||||
object ret = VoidType.Value;
|
|
||||||
|
|
||||||
_evaluator.Compile(str, out var compiled);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (compiled == null)
|
|
||||||
{
|
|
||||||
throw new Exception("Mono.Csharp Service was unable to compile the code provided.");
|
|
||||||
}
|
|
||||||
|
|
||||||
compiled.Invoke(ref ret);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
if (!suppressWarning)
|
|
||||||
{
|
|
||||||
ExplorerCore.LogWarning(e.GetType() + ", " + e.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public override void DrawWindow()
|
|
||||||
{
|
|
||||||
GUILayout.Label("<b><size=15><color=cyan>C# Console</color></size></b>", new GUILayoutOption[0]);
|
|
||||||
|
|
||||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
|
||||||
|
|
||||||
GUILayout.Label("Enter code here as though it is a method body:", new GUILayoutOption[0]);
|
|
||||||
|
|
||||||
inputAreaScroll = GUIUnstrip.BeginScrollView(inputAreaScroll, new GUILayoutOption[] { GUILayout.Height(250) });
|
|
||||||
|
|
||||||
MethodInput = GUIUnstrip.TextArea(MethodInput, new GUILayoutOption[] { GUILayout.ExpandHeight(true) });
|
|
||||||
|
|
||||||
GUIUnstrip.EndScrollView();
|
|
||||||
|
|
||||||
if (GUILayout.Button("<color=cyan><b>Execute</b></color>", new GUILayoutOption[0]))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
MethodInput = MethodInput.Trim();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(MethodInput))
|
|
||||||
{
|
|
||||||
var result = Evaluate(MethodInput);
|
|
||||||
|
|
||||||
if (result != null && !Equals(result, VoidType.Value))
|
|
||||||
{
|
|
||||||
ExplorerCore.Log("[Console Output]\r\n" + result.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
ExplorerCore.LogError("Exception compiling!\r\nMessage: " + e.Message + "\r\nStack: " + e.StackTrace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GUILayout.Label("<b>Using directives:</b>", new GUILayoutOption[0]);
|
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
|
||||||
GUILayout.Label("Add namespace:", new GUILayoutOption[] { GUILayout.Width(105) });
|
|
||||||
UsingInput = GUIUnstrip.TextField(UsingInput, new GUILayoutOption[] { GUILayout.Width(150) });
|
|
||||||
if (GUILayout.Button("<b><color=lime>Add</color></b>", new GUILayoutOption[] { GUILayout.Width(120) }))
|
|
||||||
{
|
|
||||||
AddUsing(UsingInput);
|
|
||||||
}
|
|
||||||
if (GUILayout.Button("<b><color=red>Clear All</color></b>", new GUILayoutOption[] { GUILayout.Width(120) }))
|
|
||||||
{
|
|
||||||
ResetConsole();
|
|
||||||
}
|
|
||||||
GUILayout.EndHorizontal();
|
|
||||||
|
|
||||||
foreach (var asm in UsingDirectives)
|
|
||||||
{
|
|
||||||
GUILayout.Label(AsmToUsing(asm, true), new GUILayoutOption[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Update() { }
|
|
||||||
|
|
||||||
private class VoidType
|
|
||||||
{
|
|
||||||
public static readonly VoidType Value = new VoidType();
|
|
||||||
private VoidType() { }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class ScriptEvaluator : Evaluator, IDisposable
|
|
||||||
{
|
|
||||||
private static readonly HashSet<string> StdLib =
|
|
||||||
new HashSet<string>(StringComparer.InvariantCultureIgnoreCase) { "mscorlib", "System.Core", "System", "System.Xml" };
|
|
||||||
|
|
||||||
private readonly TextWriter _logger;
|
|
||||||
|
|
||||||
public ScriptEvaluator(TextWriter logger) : base(BuildContext(logger))
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
|
|
||||||
ImportAppdomainAssemblies(ReferenceAssembly);
|
|
||||||
AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoad;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
AppDomain.CurrentDomain.AssemblyLoad -= OnAssemblyLoad;
|
|
||||||
_logger.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnAssemblyLoad(object sender, AssemblyLoadEventArgs args)
|
|
||||||
{
|
|
||||||
string name = args.LoadedAssembly.GetName().Name;
|
|
||||||
if (StdLib.Contains(name))
|
|
||||||
return;
|
|
||||||
ReferenceAssembly(args.LoadedAssembly);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static CompilerContext BuildContext(TextWriter tw)
|
|
||||||
{
|
|
||||||
var reporter = new StreamReportPrinter(tw);
|
|
||||||
|
|
||||||
var settings = new CompilerSettings
|
|
||||||
{
|
|
||||||
Version = LanguageVersion.Experimental,
|
|
||||||
GenerateDebugInfo = false,
|
|
||||||
StdLib = true,
|
|
||||||
Target = Target.Library,
|
|
||||||
WarningLevel = 0,
|
|
||||||
EnhancedWarnings = false
|
|
||||||
};
|
|
||||||
|
|
||||||
return new CompilerContext(settings, reporter);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ImportAppdomainAssemblies(Action<Assembly> import)
|
|
||||||
{
|
|
||||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
|
||||||
{
|
|
||||||
string name = assembly.GetName().Name;
|
|
||||||
if (StdLib.Contains(name))
|
|
||||||
continue;
|
|
||||||
import(assembly);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,46 +3,57 @@ using System.Collections.Generic;
|
|||||||
using System;
|
using System;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Collections.Specialized;
|
using System.Runtime.InteropServices;
|
||||||
|
using Explorer.UI.Shared;
|
||||||
// used to test multiple generic constraints
|
#if CPP
|
||||||
public class TestGeneric : IComparable<string>
|
using UnhollowerBaseLib;
|
||||||
{
|
using UnityEngine.SceneManagement;
|
||||||
public TestGeneric() { }
|
#endif
|
||||||
|
|
||||||
public int CompareTo(string other) => throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Flags]
|
|
||||||
public enum TestFlags
|
|
||||||
{
|
|
||||||
Red,
|
|
||||||
Green,
|
|
||||||
Blue
|
|
||||||
}
|
|
||||||
|
|
||||||
// test non-flags weird enum
|
|
||||||
public enum WeirdEnum
|
|
||||||
{
|
|
||||||
First = 1,
|
|
||||||
Second,
|
|
||||||
Third = 2,
|
|
||||||
Fourth,
|
|
||||||
Fifth
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Explorer.Tests
|
namespace Explorer.Tests
|
||||||
{
|
{
|
||||||
|
public static class StaticTestClass
|
||||||
|
{
|
||||||
|
public static int StaticProperty => 5;
|
||||||
|
public static int StaticField = 69;
|
||||||
|
public static List<string> StaticList = new List<string>
|
||||||
|
{
|
||||||
|
"one",
|
||||||
|
"two",
|
||||||
|
"three",
|
||||||
|
};
|
||||||
|
public static void StaticMethod() { }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public class TestClass
|
public class TestClass
|
||||||
{
|
{
|
||||||
public static TestFlags testFlags = TestFlags.Blue | TestFlags.Green;
|
|
||||||
public static WeirdEnum testWeird = WeirdEnum.First;
|
|
||||||
|
|
||||||
public static int testBitmask;
|
|
||||||
|
|
||||||
public static TestClass Instance => m_instance ?? (m_instance = new TestClass());
|
public static TestClass Instance => m_instance ?? (m_instance = new TestClass());
|
||||||
private static TestClass m_instance;
|
private static TestClass m_instance;
|
||||||
|
|
||||||
|
public static bool ReadSetOnlyProperty => m_setOnlyProperty;
|
||||||
|
|
||||||
|
public static bool SetOnlyProperty
|
||||||
|
{
|
||||||
|
set => m_setOnlyProperty = value;
|
||||||
|
}
|
||||||
|
private static bool m_setOnlyProperty;
|
||||||
|
|
||||||
|
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
|
#if CPP
|
||||||
public static Il2CppSystem.Collections.Generic.HashSet<string> ILHashSetTest;
|
public static Il2CppSystem.Collections.Generic.HashSet<string> ILHashSetTest;
|
||||||
#endif
|
#endif
|
||||||
@ -50,22 +61,21 @@ namespace Explorer.Tests
|
|||||||
public TestClass()
|
public TestClass()
|
||||||
{
|
{
|
||||||
#if CPP
|
#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 = new Il2CppSystem.Collections.Generic.HashSet<string>();
|
||||||
ILHashSetTest.Add("1");
|
ILHashSetTest.Add("1");
|
||||||
ILHashSetTest.Add("2");
|
ILHashSetTest.Add("2");
|
||||||
ILHashSetTest.Add("3");
|
ILHashSetTest.Add("3");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
testBitmask = 1 | 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int StaticProperty => 5;
|
|
||||||
public static int StaticField = 5;
|
|
||||||
public int NonStaticField;
|
|
||||||
|
|
||||||
public static string TestGeneric<C, T>(string arg0) where C : Component where T : TestGeneric, IComparable<string>
|
|
||||||
{
|
|
||||||
return $"C: '{typeof(C).FullName}', T: '{typeof(T).FullName}', arg0: '{arg0}'";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string TestRefInOutGeneric<T>(ref string arg0, in int arg1, out string arg2)
|
public static string TestRefInOutGeneric<T>(ref string arg0, in int arg1, out string arg2)
|
||||||
@ -75,12 +85,6 @@ namespace Explorer.Tests
|
|||||||
return $"T: '{typeof(T).FullName}', ref arg0: '{arg0}', in arg1: '{arg1}', out arg2: '{arg2}'";
|
return $"T: '{typeof(T).FullName}', ref arg0: '{arg0}', in arg1: '{arg1}', out arg2: '{arg2}'";
|
||||||
}
|
}
|
||||||
|
|
||||||
//// this type of generic is not supported, due to requiring a non-primitive argument.
|
|
||||||
//public static T TestDifferentGeneric<T>(T obj) where T : Component
|
|
||||||
//{
|
|
||||||
// return obj;
|
|
||||||
//}
|
|
||||||
|
|
||||||
// test a non-generic dictionary
|
// test a non-generic dictionary
|
||||||
|
|
||||||
public Hashtable TestNonGenericDict()
|
public Hashtable TestNonGenericDict()
|
||||||
@ -93,18 +97,6 @@ namespace Explorer.Tests
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// IL2CPP HASHTABLE NOT SUPPORTED! Cannot assign Il2CppSystem.Object from primitive struct / string.
|
|
||||||
// Technically they are "supported" but if they contain System types they will not work.
|
|
||||||
|
|
||||||
//public Il2CppSystem.Collections.Hashtable TestIl2CppNonGenericDict()
|
|
||||||
//{
|
|
||||||
// var table = new Il2CppSystem.Collections.Hashtable();
|
|
||||||
// table.Add("One", 1);
|
|
||||||
// table.Add("One", 2);
|
|
||||||
// table.Add("One", 3);
|
|
||||||
// return table;
|
|
||||||
//}
|
|
||||||
|
|
||||||
// test HashSets
|
// test HashSets
|
||||||
|
|
||||||
public static HashSet<string> HashSetTest = new HashSet<string>
|
public static HashSet<string> HashSetTest = new HashSet<string>
|
||||||
|
@ -6,42 +6,36 @@ using Harmony;
|
|||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI
|
||||||
{
|
{
|
||||||
public class CursorControl
|
public class ForceUnlockCursor
|
||||||
{
|
{
|
||||||
public static bool ForceUnlockMouse
|
public static bool Unlock
|
||||||
{
|
{
|
||||||
get => m_forceUnlock;
|
get => m_forceUnlock;
|
||||||
set => SetForceUnlock(value);
|
set => SetForceUnlock(value);
|
||||||
}
|
}
|
||||||
private static bool m_forceUnlock;
|
private static bool m_forceUnlock;
|
||||||
|
|
||||||
|
public static bool ShouldForceMouse => ExplorerCore.ShowMenu && Unlock;
|
||||||
|
|
||||||
private static CursorLockMode m_lastLockMode;
|
private static CursorLockMode m_lastLockMode;
|
||||||
private static bool m_lastVisibleState;
|
private static bool m_lastVisibleState;
|
||||||
|
|
||||||
private static bool m_currentlySettingCursor = false;
|
private static bool m_currentlySettingCursor = false;
|
||||||
|
|
||||||
public static bool ShouldForceMouse => ExplorerCore.ShowMenu && ForceUnlockMouse;
|
private static Type CursorType
|
||||||
|
=> m_cursorType
|
||||||
private static Type CursorType => m_cursorType ?? (m_cursorType = ReflectionHelpers.GetTypeByName("UnityEngine.Cursor"));
|
?? (m_cursorType = ReflectionHelpers.GetTypeByName("UnityEngine.Cursor"));
|
||||||
private static Type m_cursorType;
|
private static Type m_cursorType;
|
||||||
|
|
||||||
public static void Init()
|
public static void Init()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Check if Cursor class is loaded
|
|
||||||
if (CursorType == null)
|
if (CursorType == null)
|
||||||
{
|
{
|
||||||
ExplorerCore.Log("Trying to manually load Cursor module...");
|
throw new Exception("Could not find Type 'UnityEngine.Cursor'!");
|
||||||
|
|
||||||
if (ReflectionHelpers.LoadModule("UnityEngine.CoreModule") && CursorType != null)
|
|
||||||
{
|
|
||||||
ExplorerCore.Log("Ok!");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception("Could not load UnityEngine.Cursor module!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current cursor state and enable cursor
|
// Get current cursor state and enable cursor
|
||||||
@ -49,29 +43,24 @@ namespace Explorer
|
|||||||
m_lastVisibleState = Cursor.visible;
|
m_lastVisibleState = Cursor.visible;
|
||||||
|
|
||||||
// Setup Harmony Patches
|
// Setup Harmony Patches
|
||||||
TryPatch("lockState", new HarmonyMethod(typeof(CursorControl).GetMethod(nameof(Prefix_set_lockState))), true);
|
TryPatch("lockState", new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_set_lockState))), true);
|
||||||
TryPatch("lockState", new HarmonyMethod(typeof(CursorControl).GetMethod(nameof(Postfix_get_lockState))), false);
|
TryPatch("lockState", new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Postfix_get_lockState))), false);
|
||||||
|
|
||||||
TryPatch("visible", new HarmonyMethod(typeof(CursorControl).GetMethod(nameof(Prefix_set_visible))), true);
|
TryPatch("visible", new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Prefix_set_visible))), true);
|
||||||
TryPatch("visible", new HarmonyMethod(typeof(CursorControl).GetMethod(nameof(Postfix_get_visible))), false);
|
TryPatch("visible", new HarmonyMethod(typeof(ForceUnlockCursor).GetMethod(nameof(Postfix_get_visible))), false);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
ExplorerCore.Log($"Exception on CursorControl.Init! {e.GetType()}, {e.Message}");
|
ExplorerCore.Log($"Exception on CursorControl.Init! {e.GetType()}, {e.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable ShowMenu and ForceUnlockMouse
|
Unlock = true;
|
||||||
// (set m_showMenu directly to not call UpdateCursorState twice)
|
|
||||||
ExplorerCore.m_showMenu = true;
|
|
||||||
ForceUnlockMouse = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void TryPatch(string property, HarmonyMethod patch, bool setter)
|
private static void TryPatch(string property, HarmonyMethod patch, bool setter)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// var harmony = ExplorerCore.Instance.harmonyInstance;
|
|
||||||
|
|
||||||
var harmony =
|
var harmony =
|
||||||
#if ML
|
#if ML
|
||||||
ExplorerMelonMod.Instance.harmonyInstance;
|
ExplorerMelonMod.Instance.harmonyInstance;
|
||||||
@ -85,17 +74,18 @@ namespace Explorer
|
|||||||
if (setter)
|
if (setter)
|
||||||
{
|
{
|
||||||
// setter is prefix
|
// setter is prefix
|
||||||
harmony.Patch(prop.GetSetMethod(), patch);
|
harmony.Patch(prop.GetSetMethod(), prefix: patch);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// getter is postfix
|
// getter is postfix
|
||||||
harmony.Patch(prop.GetGetMethod(), null, patch);
|
harmony.Patch(prop.GetGetMethod(), postfix: patch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
ExplorerCore.Log($"[NON-FATAL] Couldn't patch a method: {e.Message}");
|
string s = setter ? "set_" : "get_" ;
|
||||||
|
ExplorerCore.Log($"Unable to patch Cursor.{s}{property}: {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,9 +98,9 @@ namespace Explorer
|
|||||||
public static void Update()
|
public static void Update()
|
||||||
{
|
{
|
||||||
// Check Force-Unlock input
|
// Check Force-Unlock input
|
||||||
if (InputHelper.GetKeyDown(KeyCode.LeftAlt))
|
if (InputManager.GetKeyDown(KeyCode.LeftAlt))
|
||||||
{
|
{
|
||||||
ForceUnlockMouse = !ForceUnlockMouse;
|
Unlock = !Unlock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,21 +1,25 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
using Explorer.UI.Main;
|
||||||
|
using Explorer.Unstrip.LayerMasks;
|
||||||
#if CPP
|
#if CPP
|
||||||
using UnhollowerRuntimeLib;
|
using UnhollowerRuntimeLib;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI.Inspectors
|
||||||
{
|
{
|
||||||
public class GameObjectWindow : UIWindow
|
public class GameObjectInspector : WindowBase
|
||||||
{
|
{
|
||||||
public override string Title => WindowManager.TabView
|
public override string Title => WindowManager.TabView
|
||||||
? $"<color=cyan>[G]</color> {TargetGO.name}"
|
? $"<color=cyan>[G]</color> {TargetGO.name}"
|
||||||
: $"GameObject Inspector ({TargetGO.name})";
|
: $"GameObject Inspector ({TargetGO.name})";
|
||||||
|
|
||||||
public GameObject TargetGO;
|
public GameObject TargetGO;
|
||||||
|
|
||||||
|
public bool pendingDestroy;
|
||||||
|
|
||||||
private static bool m_hideControls;
|
private static bool m_hideControls;
|
||||||
|
|
||||||
// gui element holders
|
// gui element holders
|
||||||
@ -42,6 +46,8 @@ namespace Explorer
|
|||||||
private bool m_autoUpdateTransform;
|
private bool m_autoUpdateTransform;
|
||||||
private bool m_localContext;
|
private bool m_localContext;
|
||||||
|
|
||||||
|
private int m_layer;
|
||||||
|
|
||||||
private readonly List<Component> m_cachedDestroyList = new List<Component>();
|
private readonly List<Component> m_cachedDestroyList = new List<Component>();
|
||||||
private string m_addComponentInput = "";
|
private string m_addComponentInput = "";
|
||||||
|
|
||||||
@ -49,7 +55,7 @@ namespace Explorer
|
|||||||
|
|
||||||
public bool GetObjectAsGameObject()
|
public bool GetObjectAsGameObject()
|
||||||
{
|
{
|
||||||
var targetType = Target.GetType();
|
var targetType = Target?.GetType();
|
||||||
|
|
||||||
if (targetType == typeof(GameObject))
|
if (targetType == typeof(GameObject))
|
||||||
{
|
{
|
||||||
@ -75,8 +81,8 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_name = TargetGO.name;
|
m_name = TargetGO.name;
|
||||||
m_scene = string.IsNullOrEmpty(TargetGO.scene.name)
|
m_scene = string.IsNullOrEmpty(TargetGO.scene.name)
|
||||||
? "None (Asset/Resource)"
|
? "None (Asset/Resource)"
|
||||||
: TargetGO.scene.name;
|
: TargetGO.scene.name;
|
||||||
|
|
||||||
CacheTransformValues();
|
CacheTransformValues();
|
||||||
@ -103,25 +109,17 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (pendingDestroy) return;
|
||||||
|
|
||||||
if (Target == null)
|
if (Target == null)
|
||||||
{
|
{
|
||||||
ExplorerCore.Log("Target is null!");
|
DestroyOnException(new Exception("Target was destroyed."));
|
||||||
DestroyWindow();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (Target is UnityEngine.Object uObj)
|
|
||||||
{
|
|
||||||
if (!uObj)
|
|
||||||
{
|
|
||||||
ExplorerCore.Log("Target was destroyed!");
|
|
||||||
DestroyWindow();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!TargetGO && !GetObjectAsGameObject())
|
if (!TargetGO && !GetObjectAsGameObject())
|
||||||
{
|
{
|
||||||
throw new Exception("Object is null!");
|
DestroyOnException(new Exception("Target was destroyed."));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_freeze)
|
if (m_freeze)
|
||||||
@ -139,6 +137,8 @@ namespace Explorer
|
|||||||
TargetGO.transform.localScale = m_frozenScale;
|
TargetGO.transform.localScale = m_frozenScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_layer = TargetGO.layer;
|
||||||
|
|
||||||
// update child objects
|
// update child objects
|
||||||
var childList = new List<Transform>();
|
var childList = new List<Transform>();
|
||||||
for (int i = 0; i < TargetGO.transform.childCount; i++)
|
for (int i = 0; i < TargetGO.transform.childCount; i++)
|
||||||
@ -170,13 +170,14 @@ namespace Explorer
|
|||||||
private void DestroyOnException(Exception e)
|
private void DestroyOnException(Exception e)
|
||||||
{
|
{
|
||||||
ExplorerCore.Log($"Exception drawing GameObject Window: {e.GetType()}, {e.Message}");
|
ExplorerCore.Log($"Exception drawing GameObject Window: {e.GetType()}, {e.Message}");
|
||||||
|
pendingDestroy = true;
|
||||||
DestroyWindow();
|
DestroyWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InspectGameObject(Transform obj)
|
private void InspectGameObject(Transform obj)
|
||||||
{
|
{
|
||||||
var window = WindowManager.InspectObject(obj, out bool created);
|
var window = WindowManager.InspectObject(obj, out bool created);
|
||||||
|
|
||||||
if (created)
|
if (created)
|
||||||
{
|
{
|
||||||
window.m_rect = new Rect(this.m_rect.x, this.m_rect.y, this.m_rect.width, this.m_rect.height);
|
window.m_rect = new Rect(this.m_rect.x, this.m_rect.y, this.m_rect.width, this.m_rect.height);
|
||||||
@ -189,7 +190,7 @@ namespace Explorer
|
|||||||
#else
|
#else
|
||||||
private void ReflectObject(object obj)
|
private void ReflectObject(object obj)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
var window = WindowManager.InspectObject(obj, out bool created, true);
|
var window = WindowManager.InspectObject(obj, out bool created, true);
|
||||||
|
|
||||||
if (created)
|
if (created)
|
||||||
@ -211,6 +212,8 @@ namespace Explorer
|
|||||||
|
|
||||||
public override void WindowFunction(int windowID)
|
public override void WindowFunction(int windowID)
|
||||||
{
|
{
|
||||||
|
if (pendingDestroy) return;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var rect = WindowManager.TabView ? TabViewWindow.Instance.m_rect : this.m_rect;
|
var rect = WindowManager.TabView ? TabViewWindow.Instance.m_rect : this.m_rect;
|
||||||
@ -223,7 +226,7 @@ namespace Explorer
|
|||||||
|
|
||||||
scroll = GUIUnstrip.BeginScrollView(scroll);
|
scroll = GUIUnstrip.BeginScrollView(scroll);
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label("Scene: <color=cyan>" + (m_scene == "" ? "n/a" : m_scene) + "</color>", new GUILayoutOption[0]);
|
GUILayout.Label("Scene: <color=cyan>" + (m_scene == "" ? "n/a" : m_scene) + "</color>", new GUILayoutOption[0]);
|
||||||
if (m_scene == UnityHelpers.ActiveSceneName)
|
if (m_scene == UnityHelpers.ActiveSceneName)
|
||||||
{
|
{
|
||||||
@ -239,7 +242,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label("Path:", new GUILayoutOption[] { GUILayout.Width(50) });
|
GUILayout.Label("Path:", new GUILayoutOption[] { GUILayout.Width(50) });
|
||||||
string pathlabel = TargetGO.transform.GetGameObjectPath();
|
string pathlabel = TargetGO.transform.GetGameObjectPath();
|
||||||
if (TargetGO.transform.parent != null)
|
if (TargetGO.transform.parent != null)
|
||||||
@ -252,19 +255,21 @@ namespace Explorer
|
|||||||
GUIUnstrip.TextArea(pathlabel, new GUILayoutOption[0]);
|
GUIUnstrip.TextArea(pathlabel, new GUILayoutOption[0]);
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label("Name:", new GUILayoutOption[] { GUILayout.Width(50) });
|
GUILayout.Label("Name:", new GUILayoutOption[] { GUILayout.Width(50) });
|
||||||
GUIUnstrip.TextArea(m_name, new GUILayoutOption[0]);
|
GUIUnstrip.TextArea(m_name, new GUILayoutOption[0]);
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
// --- Horizontal Columns section ---
|
LayerControls();
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
|
||||||
|
|
||||||
GUILayout.BeginVertical(new GUILayoutOption[] { GUILayout.Width(rect.width / 2 - 17) });
|
// --- Horizontal Columns section ---
|
||||||
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
|
GUIUnstrip.BeginVertical(new GUILayoutOption[] { GUILayout.Width(rect.width / 2 - 17) });
|
||||||
TransformList(rect);
|
TransformList(rect);
|
||||||
GUILayout.EndVertical();
|
GUILayout.EndVertical();
|
||||||
|
|
||||||
GUILayout.BeginVertical(new GUILayoutOption[] { GUILayout.Width(rect.width / 2 - 17) });
|
GUIUnstrip.BeginVertical(new GUILayoutOption[] { GUILayout.Width(rect.width / 2 - 17) });
|
||||||
ComponentList(rect);
|
ComponentList(rect);
|
||||||
GUILayout.EndVertical();
|
GUILayout.EndVertical();
|
||||||
|
|
||||||
@ -287,14 +292,42 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void LayerControls()
|
||||||
|
{
|
||||||
|
GUIUnstrip.BeginHorizontal();
|
||||||
|
GUILayout.Label("Layer:", new GUILayoutOption[] { GUILayout.Width(50) });
|
||||||
|
|
||||||
|
if (GUILayout.Button("<", new GUILayoutOption[] { GUILayout.Width(30) }))
|
||||||
|
{
|
||||||
|
if (m_layer > 0)
|
||||||
|
{
|
||||||
|
m_layer--;
|
||||||
|
if (TargetGO) TargetGO.layer = m_layer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (GUILayout.Button(">", new GUILayoutOption[] { GUILayout.Width(30) }))
|
||||||
|
{
|
||||||
|
if (m_layer < 32)
|
||||||
|
{
|
||||||
|
m_layer++;
|
||||||
|
if (TargetGO) TargetGO.layer = m_layer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.Label($"{m_layer} (<color=cyan>{LayerMaskUnstrip.LayerToName(m_layer)}</color>)",
|
||||||
|
new GUILayoutOption[] { GUILayout.Width(200) });
|
||||||
|
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
|
||||||
private void TransformList(Rect m_rect)
|
private void TransformList(Rect m_rect)
|
||||||
{
|
{
|
||||||
GUILayout.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||||
m_transformScroll = GUIUnstrip.BeginScrollView(m_transformScroll);
|
m_transformScroll = GUIUnstrip.BeginScrollView(m_transformScroll);
|
||||||
|
|
||||||
GUILayout.Label("<b><size=15>Children</size></b>", new GUILayoutOption[0]);
|
GUILayout.Label("<b><size=15>Children</size></b>", new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
ChildPages.DrawLimitInputArea();
|
ChildPages.DrawLimitInputArea();
|
||||||
|
|
||||||
if (ChildPages.ItemCount > ChildPages.ItemsPerPage)
|
if (ChildPages.ItemCount > ChildPages.ItemsPerPage)
|
||||||
@ -302,7 +335,7 @@ namespace Explorer
|
|||||||
ChildPages.CurrentPageLabel();
|
ChildPages.CurrentPageLabel();
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
|
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
|
||||||
{
|
{
|
||||||
@ -329,7 +362,7 @@ namespace Explorer
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
UIHelpers.GOButton(obj.gameObject, InspectGameObject, false, m_rect.width / 2 - 80);
|
Buttons.GameObjectButton(obj.gameObject, InspectGameObject, false, m_rect.width / 2 - 80);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -343,11 +376,11 @@ namespace Explorer
|
|||||||
|
|
||||||
private void ComponentList(Rect m_rect)
|
private void ComponentList(Rect m_rect)
|
||||||
{
|
{
|
||||||
GUILayout.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||||
m_compScroll = GUIUnstrip.BeginScrollView(m_compScroll);
|
m_compScroll = GUIUnstrip.BeginScrollView(m_compScroll);
|
||||||
GUILayout.Label("<b><size=15>Components</size></b>", new GUILayoutOption[0]);
|
GUILayout.Label("<b><size=15>Components</size></b>", new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
CompPages.DrawLimitInputArea();
|
CompPages.DrawLimitInputArea();
|
||||||
|
|
||||||
if (CompPages.ItemCount > CompPages.ItemsPerPage)
|
if (CompPages.ItemCount > CompPages.ItemsPerPage)
|
||||||
@ -355,7 +388,7 @@ namespace Explorer
|
|||||||
CompPages.CurrentPageLabel();
|
CompPages.CurrentPageLabel();
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
|
if (GUILayout.Button("< Prev", new GUILayoutOption[] { GUILayout.Width(80) }))
|
||||||
{
|
{
|
||||||
@ -368,7 +401,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
var width = m_rect.width / 2 - 135f;
|
var width = m_rect.width / 2 - 135f;
|
||||||
m_addComponentInput = GUIUnstrip.TextField(m_addComponentInput, new GUILayoutOption[] { GUILayout.Width(width) });
|
m_addComponentInput = GUIUnstrip.TextField(m_addComponentInput, new GUILayoutOption[] { GUILayout.Width(width) });
|
||||||
if (GUILayout.Button("Add Comp", new GUILayoutOption[0]))
|
if (GUILayout.Button("Add Comp", new GUILayoutOption[0]))
|
||||||
@ -417,7 +450,7 @@ namespace Explorer
|
|||||||
#else
|
#else
|
||||||
component.GetType();
|
component.GetType();
|
||||||
#endif
|
#endif
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
if (ReflectionHelpers.BehaviourType.IsAssignableFrom(type))
|
if (ReflectionHelpers.BehaviourType.IsAssignableFrom(type))
|
||||||
{
|
{
|
||||||
#if CPP
|
#if CPP
|
||||||
@ -484,7 +517,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (m_hideControls)
|
if (m_hideControls)
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label("<b><size=15>GameObject Controls</size></b>", new GUILayoutOption[] { GUILayout.Width(200) });
|
GUILayout.Label("<b><size=15>GameObject Controls</size></b>", new GUILayoutOption[] { GUILayout.Width(200) });
|
||||||
if (GUILayout.Button("^ Show ^", new GUILayoutOption[] { GUILayout.Width(75) }))
|
if (GUILayout.Button("^ Show ^", new GUILayoutOption[] { GUILayout.Width(75) }))
|
||||||
{
|
{
|
||||||
@ -495,9 +528,9 @@ namespace Explorer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.BeginVertical(GUIContent.none, GUI.skin.box, new GUILayoutOption[] { GUILayout.Width(520) });
|
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, new GUILayoutOption[] { GUILayout.Width(520) });
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label("<b><size=15>GameObject Controls</size></b>", new GUILayoutOption[] { GUILayout.Width(200) });
|
GUILayout.Label("<b><size=15>GameObject Controls</size></b>", new GUILayoutOption[] { GUILayout.Width(200) });
|
||||||
if (GUILayout.Button("v Hide v", new GUILayoutOption[] { GUILayout.Width(75) }))
|
if (GUILayout.Button("v Hide v", new GUILayoutOption[] { GUILayout.Width(75) }))
|
||||||
{
|
{
|
||||||
@ -505,13 +538,13 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
bool m_active = TargetGO.activeSelf;
|
bool m_active = TargetGO.activeSelf;
|
||||||
m_active = GUILayout.Toggle(m_active, (m_active ? "<color=lime>Enabled " : "<color=red>Disabled") + "</color>",
|
m_active = GUILayout.Toggle(m_active, (m_active ? "<color=lime>Enabled " : "<color=red>Disabled") + "</color>",
|
||||||
new GUILayoutOption[] { GUILayout.Width(80) });
|
new GUILayoutOption[] { GUILayout.Width(80) });
|
||||||
if (TargetGO.activeSelf != m_active) { TargetGO.SetActive(m_active); }
|
if (TargetGO.activeSelf != m_active) { TargetGO.SetActive(m_active); }
|
||||||
|
|
||||||
UIHelpers.InstantiateButton(TargetGO, 100);
|
Buttons.InstantiateButton(TargetGO, 100);
|
||||||
|
|
||||||
if (GUILayout.Button("Set DontDestroyOnLoad", new GUILayoutOption[] { GUILayout.Width(170) }))
|
if (GUILayout.Button("Set DontDestroyOnLoad", new GUILayoutOption[] { GUILayout.Width(170) }))
|
||||||
{
|
{
|
||||||
@ -530,7 +563,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
m_setParentInput = GUIUnstrip.TextField(m_setParentInput, new GUILayoutOption[0]);
|
m_setParentInput = GUIUnstrip.TextField(m_setParentInput, new GUILayoutOption[0]);
|
||||||
if (GUILayout.Button("Set Parent", new GUILayoutOption[] { GUILayout.Width(80) }))
|
if (GUILayout.Button("Set Parent", new GUILayoutOption[] { GUILayout.Width(80) }))
|
||||||
@ -551,13 +584,13 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||||
|
|
||||||
m_cachedInput[0] = TranslateControl(TranslateType.Position, ref m_translateAmount, false);
|
m_cachedInput[0] = TranslateControl(TranslateType.Position, ref m_translateAmount, false);
|
||||||
m_cachedInput[1] = TranslateControl(TranslateType.Rotation, ref m_rotateAmount, true);
|
m_cachedInput[1] = TranslateControl(TranslateType.Rotation, ref m_rotateAmount, true);
|
||||||
m_cachedInput[2] = TranslateControl(TranslateType.Scale, ref m_scaleAmount, false);
|
m_cachedInput[2] = TranslateControl(TranslateType.Scale, ref m_scaleAmount, false);
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
if (GUILayout.Button("<color=lime>Apply to Transform</color>", new GUILayoutOption[0]) || m_autoApplyTransform)
|
if (GUILayout.Button("<color=lime>Apply to Transform</color>", new GUILayoutOption[0]) || m_autoApplyTransform)
|
||||||
{
|
{
|
||||||
if (m_localContext)
|
if (m_localContext)
|
||||||
@ -583,7 +616,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
BoolToggle(ref m_autoApplyTransform, "Auto-apply to Transform?");
|
BoolToggle(ref m_autoApplyTransform, "Auto-apply to Transform?");
|
||||||
BoolToggle(ref m_autoUpdateTransform, "Auto-update from transform?");
|
BoolToggle(ref m_autoUpdateTransform, "Auto-update from transform?");
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
@ -645,8 +678,8 @@ namespace Explorer
|
|||||||
|
|
||||||
private Vector3 TranslateControl(TranslateType mode, ref float amount, bool multByTime)
|
private Vector3 TranslateControl(TranslateType mode, ref float amount, bool multByTime)
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label($"<color=cyan><b>{(m_localContext ? "Local " : "")}{mode}</b></color>:",
|
GUILayout.Label($"<color=cyan><b>{(m_localContext ? "Local " : "")}{mode}</b></color>:",
|
||||||
new GUILayoutOption[] { GUILayout.Width(m_localContext ? 110 : 65) });
|
new GUILayoutOption[] { GUILayout.Width(m_localContext ? 110 : 65) });
|
||||||
|
|
||||||
var transform = TargetGO.transform;
|
var transform = TargetGO.transform;
|
||||||
@ -668,7 +701,7 @@ namespace Explorer
|
|||||||
|
|
||||||
Vector3 input = m_cachedInput[(int)mode];
|
Vector3 input = m_cachedInput[(int)mode];
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleRight;
|
GUI.skin.label.alignment = TextAnchor.MiddleRight;
|
||||||
|
|
||||||
GUILayout.Label("<color=cyan>X:</color>", new GUILayoutOption[] { GUILayout.Width(20) });
|
GUILayout.Label("<color=cyan>X:</color>", new GUILayoutOption[] { GUILayout.Width(20) });
|
||||||
@ -678,7 +711,7 @@ namespace Explorer
|
|||||||
PlusMinusFloat(ref input.y, amount, multByTime);
|
PlusMinusFloat(ref input.y, amount, multByTime);
|
||||||
|
|
||||||
GUILayout.Label("<color=cyan>Z:</color>", new GUILayoutOption[] { GUILayout.Width(20) });
|
GUILayout.Label("<color=cyan>Z:</color>", new GUILayoutOption[] { GUILayout.Width(20) });
|
||||||
PlusMinusFloat(ref input.z, amount, multByTime);
|
PlusMinusFloat(ref input.z, amount, multByTime);
|
||||||
|
|
||||||
GUILayout.Label("+/-:", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label("+/-:", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
var amountInput = amount.ToString("F3");
|
var amountInput = amount.ToString("F3");
|
@ -1,18 +1,18 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI.Inspectors
|
||||||
{
|
{
|
||||||
public class InspectUnderMouse
|
public class InspectUnderMouse
|
||||||
{
|
{
|
||||||
public static bool EnableInspect { get; set; } = false;
|
public static bool EnableInspect { get; set; } = false;
|
||||||
|
|
||||||
private static string m_objUnderMouseName = "";
|
private static string m_objUnderMouseName = "";
|
||||||
|
|
||||||
public static void Update()
|
public static void Update()
|
||||||
{
|
{
|
||||||
if (ExplorerCore.ShowMenu)
|
if (ExplorerCore.ShowMenu)
|
||||||
{
|
{
|
||||||
if (InputHelper.GetKey(KeyCode.LeftShift) && InputHelper.GetMouseButtonDown(1))
|
if (InputManager.GetKey(KeyCode.LeftShift) && InputManager.GetMouseButtonDown(1))
|
||||||
{
|
{
|
||||||
EnableInspect = !EnableInspect;
|
EnableInspect = !EnableInspect;
|
||||||
}
|
}
|
||||||
@ -33,7 +33,7 @@ namespace Explorer
|
|||||||
if (!UnityHelpers.MainCamera)
|
if (!UnityHelpers.MainCamera)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var ray = UnityHelpers.MainCamera.ScreenPointToRay(InputHelper.mousePosition);
|
var ray = UnityHelpers.MainCamera.ScreenPointToRay(InputManager.MousePosition);
|
||||||
|
|
||||||
if (Physics.Raycast(ray, out RaycastHit hit, 1000f))
|
if (Physics.Raycast(ray, out RaycastHit hit, 1000f))
|
||||||
{
|
{
|
||||||
@ -41,7 +41,7 @@ namespace Explorer
|
|||||||
|
|
||||||
m_objUnderMouseName = obj.transform.GetGameObjectPath();
|
m_objUnderMouseName = obj.transform.GetGameObjectPath();
|
||||||
|
|
||||||
if (InputHelper.GetMouseButtonDown(0))
|
if (InputManager.GetMouseButtonDown(0))
|
||||||
{
|
{
|
||||||
EnableInspect = false;
|
EnableInspect = false;
|
||||||
m_objUnderMouseName = "";
|
m_objUnderMouseName = "";
|
||||||
@ -61,7 +61,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (m_objUnderMouseName != "")
|
if (m_objUnderMouseName != "")
|
||||||
{
|
{
|
||||||
var pos = InputHelper.mousePosition;
|
var pos = InputManager.MousePosition;
|
||||||
var rect = new Rect(
|
var rect = new Rect(
|
||||||
pos.x - (Screen.width / 2), // x
|
pos.x - (Screen.width / 2), // x
|
||||||
Screen.height - pos.y - 50, // y
|
Screen.height - pos.y - 50, // y
|
103
src/UI/Inspectors/Reflection/InstanceInspector.cs
Normal file
103
src/UI/Inspectors/Reflection/InstanceInspector.cs
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityEngine;
|
||||||
|
using Explorer.UI;
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
using Explorer.CacheObject;
|
||||||
|
#if CPP
|
||||||
|
using UnhollowerBaseLib;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Explorer.UI.Inspectors
|
||||||
|
{
|
||||||
|
public class InstanceInspector : ReflectionInspector
|
||||||
|
{
|
||||||
|
public override bool IsStaticInspector => false;
|
||||||
|
|
||||||
|
// some extra cast-caching
|
||||||
|
public UnityEngine.Object m_uObj;
|
||||||
|
private Component m_component;
|
||||||
|
|
||||||
|
public override void Init()
|
||||||
|
{
|
||||||
|
// cache the extra cast-caching
|
||||||
|
#if CPP
|
||||||
|
if (!IsStaticInspector && Target is Il2CppSystem.Object ilObject)
|
||||||
|
{
|
||||||
|
var unityObj = ilObject.TryCast<UnityEngine.Object>();
|
||||||
|
if (unityObj)
|
||||||
|
{
|
||||||
|
m_uObj = unityObj;
|
||||||
|
|
||||||
|
var component = ilObject.TryCast<Component>();
|
||||||
|
if (component)
|
||||||
|
{
|
||||||
|
m_component = component;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (!IsStaticInspector)
|
||||||
|
{
|
||||||
|
m_uObj = Target as UnityEngine.Object;
|
||||||
|
m_component = Target as Component;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
base.Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update()
|
||||||
|
{
|
||||||
|
if (Target == null)
|
||||||
|
{
|
||||||
|
ExplorerCore.Log("Target is null!");
|
||||||
|
DestroyWindow();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Target is UnityEngine.Object uObj)
|
||||||
|
{
|
||||||
|
if (!uObj)
|
||||||
|
{
|
||||||
|
ExplorerCore.Log("Target was destroyed!");
|
||||||
|
DestroyWindow();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawInstanceControls(Rect rect)
|
||||||
|
{
|
||||||
|
if (m_uObj)
|
||||||
|
{
|
||||||
|
GUILayout.Label("Name: " + m_uObj.name, new GUILayoutOption[0]);
|
||||||
|
}
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
if (m_uObj)
|
||||||
|
{
|
||||||
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
GUILayout.Label("<b>Tools:</b>", new GUILayoutOption[] { GUILayout.Width(80) });
|
||||||
|
Buttons.InstantiateButton(m_uObj);
|
||||||
|
if (m_component && m_component.gameObject is GameObject obj)
|
||||||
|
{
|
||||||
|
GUI.skin.label.alignment = TextAnchor.MiddleRight;
|
||||||
|
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("<color=#00FF00>" + obj.name + "</color>", new GUILayoutOption[] { GUILayout.Width(labelWidth) }))
|
||||||
|
{
|
||||||
|
WindowManager.InspectObject(obj, out bool _);
|
||||||
|
}
|
||||||
|
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||||
|
}
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
src/UI/Inspectors/Reflection/StaticInspector.cs
Normal file
28
src/UI/Inspectors/Reflection/StaticInspector.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Explorer.CacheObject;
|
||||||
|
|
||||||
|
namespace Explorer.UI.Inspectors
|
||||||
|
{
|
||||||
|
public class StaticInspector : ReflectionInspector
|
||||||
|
{
|
||||||
|
public override bool IsStaticInspector => true;
|
||||||
|
|
||||||
|
public override void Init()
|
||||||
|
{
|
||||||
|
base.Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool ShouldProcessMember(CacheMember holder)
|
||||||
|
{
|
||||||
|
return base.ShouldProcessMember(holder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WindowFunction(int windowID)
|
||||||
|
{
|
||||||
|
base.WindowFunction(windowID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,33 +3,43 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Explorer.UI;
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
using Explorer.CacheObject;
|
||||||
|
using Explorer.UI.Inspectors;
|
||||||
#if CPP
|
#if CPP
|
||||||
using UnhollowerBaseLib;
|
using UnhollowerBaseLib;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI.Inspectors
|
||||||
{
|
{
|
||||||
public class ReflectionWindow : UIWindow
|
public abstract class ReflectionInspector : WindowBase
|
||||||
{
|
{
|
||||||
public override string Title => WindowManager.TabView
|
public override string Title => WindowManager.TabView
|
||||||
? $"<color=cyan>[R]</color> {TargetType.Name}"
|
? $"<color=cyan>[R]</color> {TargetType.Name}"
|
||||||
: $"Reflection Inspector ({TargetType.Name})";
|
: $"Reflection Inspector ({TargetType.Name})";
|
||||||
|
|
||||||
|
public virtual bool IsStaticInspector { get; }
|
||||||
|
|
||||||
public Type TargetType;
|
public Type TargetType;
|
||||||
|
|
||||||
private CacheObjectBase[] m_allCachedMembers;
|
private CacheMember[] m_allCachedMembers;
|
||||||
private CacheObjectBase[] m_cachedMembersFiltered;
|
private CacheMember[] m_cachedMembersFiltered;
|
||||||
|
|
||||||
public PageHelper Pages = new PageHelper();
|
public PageHelper Pages = new PageHelper();
|
||||||
|
|
||||||
private bool m_autoUpdate = false;
|
private bool m_autoUpdate = false;
|
||||||
private string m_search = "";
|
private string m_search = "";
|
||||||
public MemberTypes m_filter = MemberTypes.Property;
|
public MemberTypes m_typeFilter = MemberTypes.Property;
|
||||||
private bool m_hideFailedReflection = false;
|
private bool m_hideFailedReflection = false;
|
||||||
|
|
||||||
// some extra cast-caching
|
private MemberScopes m_scopeFilter;
|
||||||
private UnityEngine.Object m_uObj;
|
private enum MemberScopes
|
||||||
private Component m_component;
|
{
|
||||||
|
Both,
|
||||||
|
Instance,
|
||||||
|
Static
|
||||||
|
}
|
||||||
|
|
||||||
private static readonly HashSet<string> _typeAndMemberBlacklist = new HashSet<string>
|
private static readonly HashSet<string> _typeAndMemberBlacklist = new HashSet<string>
|
||||||
{
|
{
|
||||||
@ -48,47 +58,23 @@ namespace Explorer
|
|||||||
|
|
||||||
public override void Init()
|
public override void Init()
|
||||||
{
|
{
|
||||||
TargetType = ReflectionHelpers.GetActualType(Target);
|
if (!IsStaticInspector)
|
||||||
|
|
||||||
CacheMembers(ReflectionHelpers.GetAllBaseTypes(Target));
|
|
||||||
|
|
||||||
// cache the extra cast-caching
|
|
||||||
#if CPP
|
|
||||||
if (Target is Il2CppSystem.Object ilObject)
|
|
||||||
{
|
{
|
||||||
var unityObj = ilObject.TryCast<UnityEngine.Object>();
|
TargetType = ReflectionHelpers.GetActualType(Target);
|
||||||
if (unityObj)
|
CacheMembers(ReflectionHelpers.GetAllBaseTypes(Target));
|
||||||
{
|
}
|
||||||
m_uObj = unityObj;
|
else
|
||||||
|
{
|
||||||
var component = ilObject.TryCast<Component>();
|
CacheMembers(new Type[] { TargetType });
|
||||||
if (component)
|
|
||||||
{
|
|
||||||
m_component = component;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
m_uObj = Target as UnityEngine.Object;
|
|
||||||
m_component = Target as Component;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
if (Target == null)
|
if (m_allCachedMembers == null)
|
||||||
{
|
{
|
||||||
DestroyWindow();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (Target is UnityEngine.Object uObj)
|
|
||||||
{
|
|
||||||
if (!uObj)
|
|
||||||
{
|
|
||||||
DestroyWindow();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_cachedMembersFiltered = m_allCachedMembers.Where(x => ShouldProcessMember(x)).ToArray();
|
m_cachedMembersFiltered = m_allCachedMembers.Where(x => ShouldProcessMember(x)).ToArray();
|
||||||
|
|
||||||
@ -106,18 +92,28 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ShouldProcessMember(CacheObjectBase holder)
|
public virtual bool ShouldProcessMember(CacheMember holder)
|
||||||
{
|
{
|
||||||
// check MemberTypes filter
|
// check MemberTypes filter
|
||||||
if (m_filter != MemberTypes.All && m_filter != holder.MemInfo?.MemberType)
|
if (m_typeFilter != MemberTypes.All && m_typeFilter != holder.MemInfo?.MemberType)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// check scope filter
|
||||||
|
if (m_scopeFilter == MemberScopes.Instance)
|
||||||
|
{
|
||||||
|
return !holder.IsStatic;
|
||||||
|
}
|
||||||
|
else if (m_scopeFilter == MemberScopes.Static)
|
||||||
|
{
|
||||||
|
return holder.IsStatic;
|
||||||
|
}
|
||||||
|
|
||||||
// hide failed reflection
|
// hide failed reflection
|
||||||
if (!string.IsNullOrEmpty(holder.ReflectionException) && m_hideFailedReflection)
|
if (!string.IsNullOrEmpty(holder.ReflectionException) && m_hideFailedReflection)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// see if we should do name search
|
// see if we should do name search
|
||||||
if (m_search == "" || holder.MemInfo == null)
|
if (m_search == "" || holder.MemInfo == null)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// ok do name search
|
// ok do name search
|
||||||
@ -128,7 +124,7 @@ namespace Explorer
|
|||||||
|
|
||||||
private void CacheMembers(Type[] types)
|
private void CacheMembers(Type[] types)
|
||||||
{
|
{
|
||||||
var list = new List<CacheObjectBase>();
|
var list = new List<CacheMember>();
|
||||||
var cachedSigs = new List<string>();
|
var cachedSigs = new List<string>();
|
||||||
|
|
||||||
foreach (var declaringType in types)
|
foreach (var declaringType in types)
|
||||||
@ -138,7 +134,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
infos = declaringType.GetMembers(ReflectionHelpers.CommonFlags);
|
infos = declaringType.GetMembers(ReflectionHelpers.CommonFlags);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
ExplorerCore.Log($"Exception getting members for type: {declaringType.FullName}");
|
ExplorerCore.Log($"Exception getting members for type: {declaringType.FullName}");
|
||||||
continue;
|
continue;
|
||||||
@ -148,7 +144,7 @@ namespace Explorer
|
|||||||
string exception = null;
|
string exception = null;
|
||||||
|
|
||||||
#if CPP
|
#if CPP
|
||||||
if (target is Il2CppSystem.Object ilObject)
|
if (!IsStaticInspector && target is Il2CppSystem.Object ilObject)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -160,61 +156,80 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
foreach (var member in infos)
|
foreach (var member in infos)
|
||||||
{
|
{
|
||||||
// make sure member type is Field, Method of Property (4 / 8 / 16)
|
|
||||||
int m = (int)member.MemberType;
|
|
||||||
if (m < 4 || m > 16)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// check blacklisted members
|
|
||||||
var sig = $"{member.DeclaringType.Name}.{member.Name}";
|
|
||||||
if (_typeAndMemberBlacklist.Any(it => it == sig))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (_methodStartsWithBlacklist.Any(it => member.Name.StartsWith(it)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (member is MethodInfo mi)
|
|
||||||
{
|
|
||||||
AppendParams(mi.GetParameters());
|
|
||||||
}
|
|
||||||
else if (member is PropertyInfo pi)
|
|
||||||
{
|
|
||||||
AppendParams(pi.GetIndexParameters());
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppendParams(ParameterInfo[] _args)
|
|
||||||
{
|
|
||||||
sig += " (";
|
|
||||||
foreach (var param in _args)
|
|
||||||
{
|
|
||||||
sig += $"{param.ParameterType.Name} {param.Name}, ";
|
|
||||||
}
|
|
||||||
sig += ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cachedSigs.Contains(sig))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExplorerCore.Log($"Trying to cache member {signature}...");
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var cached = CacheFactory.GetTypeAndCacheObject(member, target);
|
// make sure member type is Field, Method or Property (4 / 8 / 16)
|
||||||
if (cached != null)
|
int m = (int)member.MemberType;
|
||||||
|
if (m < 4 || m > 16)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var fi = member as FieldInfo;
|
||||||
|
var pi = member as PropertyInfo;
|
||||||
|
var mi = member as MethodInfo;
|
||||||
|
|
||||||
|
if (IsStaticInspector)
|
||||||
{
|
{
|
||||||
cachedSigs.Add(sig);
|
if (fi != null && !fi.IsStatic) continue;
|
||||||
list.Add(cached);
|
else if (pi != null && !pi.GetAccessors()[0].IsStatic) continue;
|
||||||
cached.ReflectionException = exception;
|
else if (mi != null && !mi.IsStatic) continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// check blacklisted members
|
||||||
|
var sig = $"{member.DeclaringType.Name}.{member.Name}";
|
||||||
|
if (_typeAndMemberBlacklist.Any(it => it == sig))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (_methodStartsWithBlacklist.Any(it => member.Name.StartsWith(it)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (mi != null)
|
||||||
|
{
|
||||||
|
AppendParams(mi.GetParameters());
|
||||||
|
}
|
||||||
|
else if (pi != null)
|
||||||
|
{
|
||||||
|
AppendParams(pi.GetIndexParameters());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AppendParams(ParameterInfo[] _args)
|
||||||
|
{
|
||||||
|
sig += " (";
|
||||||
|
foreach (var param in _args)
|
||||||
|
{
|
||||||
|
sig += $"{param.ParameterType.Name} {param.Name}, ";
|
||||||
|
}
|
||||||
|
sig += ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cachedSigs.Contains(sig))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//ExplorerCore.Log($"Trying to cache member {sig}...");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var cached = CacheFactory.GetCacheObject(member, target);
|
||||||
|
|
||||||
|
if (cached != null)
|
||||||
|
{
|
||||||
|
cachedSigs.Add(sig);
|
||||||
|
list.Add(cached);
|
||||||
|
cached.ReflectionException = exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Exception caching member {sig}!");
|
||||||
|
ExplorerCore.Log(e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
ExplorerCore.LogWarning($"Exception caching member {sig}!");
|
ExplorerCore.LogWarning($"Exception caching member {member.DeclaringType.FullName}.{member.Name}!");
|
||||||
ExplorerCore.Log(e.ToString());
|
ExplorerCore.Log(e.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -239,51 +254,49 @@ namespace Explorer
|
|||||||
GUIUnstrip.BeginArea(new Rect(5, 25, rect.width - 10, rect.height - 35), GUI.skin.box);
|
GUIUnstrip.BeginArea(new Rect(5, 25, rect.width - 10, rect.height - 35), GUI.skin.box);
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
var asInstance = this as InstanceInspector;
|
||||||
GUILayout.Label("<b>Type:</b> <color=cyan>" + TargetType.FullName + "</color>", new GUILayoutOption[] { GUILayout.Width(245f) });
|
|
||||||
if (m_uObj)
|
|
||||||
{
|
|
||||||
GUILayout.Label("Name: " + m_uObj.name, new GUILayoutOption[0]);
|
|
||||||
}
|
|
||||||
GUILayout.EndHorizontal();
|
|
||||||
|
|
||||||
if (m_uObj)
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
var labelWidth = (asInstance != null && asInstance.m_uObj)
|
||||||
|
? new GUILayoutOption[] { GUILayout.Width(245f) }
|
||||||
|
: new GUILayoutOption[0];
|
||||||
|
GUILayout.Label("<b>Type:</b> <color=cyan>" + TargetType.FullName + "</color>", labelWidth);
|
||||||
|
|
||||||
|
if (asInstance != null)
|
||||||
|
{
|
||||||
|
asInstance.DrawInstanceControls(rect);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
|
||||||
GUILayout.Label("<b>Tools:</b>", new GUILayoutOption[] { GUILayout.Width(80) });
|
|
||||||
UIHelpers.InstantiateButton(m_uObj);
|
|
||||||
if (m_component && m_component.gameObject is GameObject obj)
|
|
||||||
{
|
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleRight;
|
|
||||||
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("<color=#00FF00>" + obj.name + "</color>", new GUILayoutOption[] { GUILayout.Width(labelWidth) }))
|
|
||||||
{
|
|
||||||
WindowManager.InspectObject(obj, out bool _);
|
|
||||||
}
|
|
||||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
|
||||||
}
|
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
}
|
}
|
||||||
|
|
||||||
UIStyles.HorizontalLine(Color.grey);
|
UIStyles.HorizontalLine(Color.grey);
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label("<b>Search:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
|
GUILayout.Label("<b>Search:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
|
||||||
m_search = GUIUnstrip.TextField(m_search, new GUILayoutOption[0]);
|
m_search = GUIUnstrip.TextField(m_search, new GUILayoutOption[0]);
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label("<b>Filter:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
|
GUILayout.Label("<b>Filter:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
|
||||||
FilterToggle(MemberTypes.All, "All");
|
FilterTypeToggle(MemberTypes.All, "All");
|
||||||
FilterToggle(MemberTypes.Property, "Properties");
|
FilterTypeToggle(MemberTypes.Property, "Properties");
|
||||||
FilterToggle(MemberTypes.Field, "Fields");
|
FilterTypeToggle(MemberTypes.Field, "Fields");
|
||||||
FilterToggle(MemberTypes.Method, "Methods");
|
FilterTypeToggle(MemberTypes.Method, "Methods");
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
if (this is InstanceInspector)
|
||||||
|
{
|
||||||
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
GUILayout.Label("<b>Scope:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
|
||||||
|
FilterScopeToggle(MemberScopes.Both, "Both");
|
||||||
|
FilterScopeToggle(MemberScopes.Instance, "Instance");
|
||||||
|
FilterScopeToggle(MemberScopes.Static, "Static");
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label("<b>Values:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
|
GUILayout.Label("<b>Values:</b>", new GUILayoutOption[] { GUILayout.Width(75) });
|
||||||
if (GUILayout.Button("Update", new GUILayoutOption[] { GUILayout.Width(100) }))
|
if (GUILayout.Button("Update", new GUILayoutOption[] { GUILayout.Width(100) }))
|
||||||
{
|
{
|
||||||
@ -301,7 +314,7 @@ namespace Explorer
|
|||||||
Pages.ItemCount = m_cachedMembersFiltered.Length;
|
Pages.ItemCount = m_cachedMembersFiltered.Length;
|
||||||
|
|
||||||
// prev/next page buttons
|
// prev/next page buttons
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
Pages.DrawLimitInputArea();
|
Pages.DrawLimitInputArea();
|
||||||
|
|
||||||
@ -329,7 +342,7 @@ namespace Explorer
|
|||||||
|
|
||||||
UIStyles.HorizontalLine(Color.grey);
|
UIStyles.HorizontalLine(Color.grey);
|
||||||
|
|
||||||
GUILayout.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||||
|
|
||||||
var members = this.m_cachedMembersFiltered;
|
var members = this.m_cachedMembersFiltered;
|
||||||
int start = Pages.CalculateOffsetIndex();
|
int start = Pages.CalculateOffsetIndex();
|
||||||
@ -338,12 +351,12 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
var holder = members[j];
|
var holder = members[j];
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[] { GUILayout.Height(25) });
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[] { GUILayout.Height(25) });
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
holder.Draw(rect, 180f);
|
holder.Draw(rect, 180f);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
continue;
|
continue;
|
||||||
@ -377,9 +390,9 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FilterToggle(MemberTypes mode, string label)
|
private void FilterTypeToggle(MemberTypes mode, string label)
|
||||||
{
|
{
|
||||||
if (m_filter == mode)
|
if (m_typeFilter == mode)
|
||||||
{
|
{
|
||||||
GUI.color = Color.green;
|
GUI.color = Color.green;
|
||||||
}
|
}
|
||||||
@ -389,7 +402,26 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(100) }))
|
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(100) }))
|
||||||
{
|
{
|
||||||
m_filter = mode;
|
m_typeFilter = mode;
|
||||||
|
Pages.PageOffset = 0;
|
||||||
|
scroll = Vector2.zero;
|
||||||
|
}
|
||||||
|
GUI.color = Color.white;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FilterScopeToggle(MemberScopes mode, string label)
|
||||||
|
{
|
||||||
|
if (m_scopeFilter == mode)
|
||||||
|
{
|
||||||
|
GUI.color = Color.green;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GUI.color = Color.white;
|
||||||
|
}
|
||||||
|
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Width(100) }))
|
||||||
|
{
|
||||||
|
m_scopeFilter = mode;
|
||||||
Pages.PageOffset = 0;
|
Pages.PageOffset = 0;
|
||||||
scroll = Vector2.zero;
|
scroll = Vector2.zero;
|
||||||
}
|
}
|
234
src/UI/InteractiveValue/InteractiveValue.cs
Normal file
234
src/UI/InteractiveValue/InteractiveValue.cs
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityEngine;
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
using Explorer.CacheObject;
|
||||||
|
|
||||||
|
namespace Explorer.UI
|
||||||
|
{
|
||||||
|
public class InteractiveValue
|
||||||
|
{
|
||||||
|
public const float MAX_LABEL_WIDTH = 400f;
|
||||||
|
public const string EVALUATE_LABEL = "<color=lime>Evaluate</color>";
|
||||||
|
|
||||||
|
public CacheObjectBase OwnerCacheObject;
|
||||||
|
|
||||||
|
public object Value { get; set; }
|
||||||
|
public Type ValueType;
|
||||||
|
|
||||||
|
public string ButtonLabel => m_btnLabel ?? GetButtonLabel();
|
||||||
|
private string m_btnLabel;
|
||||||
|
|
||||||
|
public MethodInfo ToStringMethod => m_toStringMethod ?? GetToStringMethod();
|
||||||
|
private MethodInfo m_toStringMethod;
|
||||||
|
|
||||||
|
public virtual void Init()
|
||||||
|
{
|
||||||
|
UpdateValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void UpdateValue()
|
||||||
|
{
|
||||||
|
GetButtonLabel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float CalcWhitespace(Rect window)
|
||||||
|
{
|
||||||
|
if (!(this is IExpandHeight)) return 0f;
|
||||||
|
|
||||||
|
float whitespace = (this as IExpandHeight).WhiteSpace;
|
||||||
|
if (whitespace > 0)
|
||||||
|
{
|
||||||
|
ClampLabelWidth(window, ref whitespace);
|
||||||
|
}
|
||||||
|
|
||||||
|
return whitespace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ClampLabelWidth(Rect window, ref float labelWidth)
|
||||||
|
{
|
||||||
|
float min = window.width * 0.37f;
|
||||||
|
if (min > MAX_LABEL_WIDTH) min = MAX_LABEL_WIDTH;
|
||||||
|
|
||||||
|
labelWidth = Mathf.Clamp(labelWidth, min, MAX_LABEL_WIDTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw(Rect window, float labelWidth = 215f)
|
||||||
|
{
|
||||||
|
if (labelWidth > 0)
|
||||||
|
{
|
||||||
|
ClampLabelWidth(window, ref labelWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
var cacheMember = OwnerCacheObject as CacheMember;
|
||||||
|
|
||||||
|
if (cacheMember != null && cacheMember.MemInfo != null)
|
||||||
|
{
|
||||||
|
GUILayout.Label(cacheMember.RichTextName, new GUILayoutOption[] { GUILayout.Width(labelWidth) });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GUIUnstrip.Space(labelWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
var cacheMethod = OwnerCacheObject as CacheMethod;
|
||||||
|
|
||||||
|
if (cacheMember != null && cacheMember.HasParameters)
|
||||||
|
{
|
||||||
|
GUIUnstrip.BeginVertical(new GUILayoutOption[] { GUILayout.ExpandHeight(true) } );
|
||||||
|
|
||||||
|
if (cacheMember.m_isEvaluating)
|
||||||
|
{
|
||||||
|
if (cacheMethod != null && cacheMethod.GenericArgs.Length > 0)
|
||||||
|
{
|
||||||
|
cacheMethod.DrawGenericArgsInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cacheMember.m_arguments.Length > 0)
|
||||||
|
{
|
||||||
|
cacheMember.DrawArgsInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
if (GUILayout.Button(EVALUATE_LABEL, new GUILayoutOption[] { GUILayout.Width(70) }))
|
||||||
|
{
|
||||||
|
if (cacheMethod != null)
|
||||||
|
cacheMethod.Evaluate();
|
||||||
|
else
|
||||||
|
cacheMember.UpdateValue();
|
||||||
|
}
|
||||||
|
if (GUILayout.Button("Cancel", new GUILayoutOption[] { GUILayout.Width(70) }))
|
||||||
|
{
|
||||||
|
cacheMember.m_isEvaluating = false;
|
||||||
|
}
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var lbl = $"Evaluate (";
|
||||||
|
int len = cacheMember.m_arguments.Length;
|
||||||
|
if (cacheMethod != null) len += cacheMethod.GenericArgs.Length;
|
||||||
|
lbl += len + " params)";
|
||||||
|
|
||||||
|
if (GUILayout.Button(lbl, new GUILayoutOption[] { GUILayout.Width(150) }))
|
||||||
|
{
|
||||||
|
cacheMember.m_isEvaluating = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
GUIUnstrip.Space(labelWidth);
|
||||||
|
}
|
||||||
|
else if (cacheMethod != null)
|
||||||
|
{
|
||||||
|
if (GUILayout.Button(EVALUATE_LABEL, new GUILayoutOption[] { GUILayout.Width(70) }))
|
||||||
|
{
|
||||||
|
cacheMethod.Evaluate();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
GUIUnstrip.Space(labelWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
string typeName = $"<color={Syntax.Class_Instance}>{ValueType.FullName}</color>";
|
||||||
|
|
||||||
|
if (cacheMember != null && !string.IsNullOrEmpty(cacheMember.ReflectionException))
|
||||||
|
{
|
||||||
|
GUILayout.Label("<color=red>Reflection failed!</color> (" + cacheMember.ReflectionException + ")", new GUILayoutOption[0]);
|
||||||
|
}
|
||||||
|
else if (cacheMember != null && (cacheMember.HasParameters || cacheMember is CacheMethod) && !cacheMember.m_evaluated)
|
||||||
|
{
|
||||||
|
GUILayout.Label($"<color=grey><i>Not yet evaluated</i></color> ({typeName})", new GUILayoutOption[0]);
|
||||||
|
}
|
||||||
|
else if ((Value == null || Value is UnityEngine.Object uObj && !uObj) && !(cacheMember is CacheMethod))
|
||||||
|
{
|
||||||
|
GUILayout.Label($"<i>null ({typeName})</i>", new GUILayoutOption[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float _width = window.width - labelWidth - 90;
|
||||||
|
if (OwnerCacheObject is CacheMethod cm)
|
||||||
|
{
|
||||||
|
cm.DrawValue(window, _width);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DrawValue(window, _width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void DrawValue(Rect window, float width)
|
||||||
|
{
|
||||||
|
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
||||||
|
if (GUILayout.Button(ButtonLabel, new GUILayoutOption[] { GUILayout.Width(width - 15) }))
|
||||||
|
{
|
||||||
|
if (OwnerCacheObject.IsStaticClassSearchResult)
|
||||||
|
{
|
||||||
|
WindowManager.InspectStaticReflection(Value as Type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WindowManager.InspectObject(Value, out bool _);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MethodInfo GetToStringMethod()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_toStringMethod = ReflectionHelpers.GetActualType(Value).GetMethod("ToString", new Type[0])
|
||||||
|
?? typeof(object).GetMethod("ToString", new Type[0]);
|
||||||
|
|
||||||
|
// test invoke
|
||||||
|
m_toStringMethod.Invoke(Value, null);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
m_toStringMethod = typeof(object).GetMethod("ToString", new Type[0]);
|
||||||
|
}
|
||||||
|
return m_toStringMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetButtonLabel()
|
||||||
|
{
|
||||||
|
if (Value == null) return null;
|
||||||
|
|
||||||
|
var valueType = ReflectionHelpers.GetActualType(Value);
|
||||||
|
|
||||||
|
string label = (string)ToStringMethod?.Invoke(Value, null) ?? Value.ToString();
|
||||||
|
|
||||||
|
var classColor = valueType.IsAbstract && valueType.IsSealed
|
||||||
|
? Syntax.Class_Static
|
||||||
|
: Syntax.Class_Instance;
|
||||||
|
|
||||||
|
string typeLabel = $"<color={classColor}>{valueType.FullName}</color>";
|
||||||
|
|
||||||
|
if (Value is UnityEngine.Object)
|
||||||
|
{
|
||||||
|
label = label.Replace($"({valueType.FullName})", $"({typeLabel})");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!label.Contains(valueType.FullName))
|
||||||
|
{
|
||||||
|
label += $" ({typeLabel})";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
label = label.Replace(valueType.FullName, typeLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_btnLabel = label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,18 +5,23 @@ using UnityEngine;
|
|||||||
#if CPP
|
#if CPP
|
||||||
using UnhollowerBaseLib;
|
using UnhollowerBaseLib;
|
||||||
#endif
|
#endif
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
using Explorer.CacheObject;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI
|
||||||
{
|
{
|
||||||
public class CacheDictionary : CacheObjectBase, IExpandHeight
|
// TODO: Re-work class using InteractiveEnumerable or maybe InteractiveCollection for the Keys/Value lists.
|
||||||
|
// Make the keys and values editable.
|
||||||
|
|
||||||
|
public class InteractiveDictionary : InteractiveValue, IExpandHeight
|
||||||
{
|
{
|
||||||
public bool IsExpanded { get; set; }
|
public bool IsExpanded { get; set; }
|
||||||
public float WhiteSpace { get; set; } = 215f;
|
public float WhiteSpace { get; set; } = 215f;
|
||||||
|
|
||||||
public PageHelper Pages = new PageHelper();
|
public PageHelper Pages = new PageHelper();
|
||||||
|
|
||||||
private CacheObjectBase[] m_cachedKeys;
|
private CacheObjectBase[] m_cachedKeys = new CacheObjectBase[0];
|
||||||
private CacheObjectBase[] m_cachedValues;
|
private CacheObjectBase[] m_cachedValues = new CacheObjectBase[0];
|
||||||
|
|
||||||
public Type TypeOfKeys
|
public Type TypeOfKeys
|
||||||
{
|
{
|
||||||
@ -53,11 +58,11 @@ namespace Explorer
|
|||||||
// note: "ValueType" is the Dictionary itself, TypeOfValues is the 'Dictionary.Values' type.
|
// note: "ValueType" is the Dictionary itself, TypeOfValues is the 'Dictionary.Values' type.
|
||||||
|
|
||||||
// get keys and values
|
// get keys and values
|
||||||
var keys = ValueType.GetProperty("Keys") .GetValue(Value, null);
|
var keys = ValueType.GetProperty("Keys").GetValue(Value, null);
|
||||||
var values = ValueType.GetProperty("Values").GetValue(Value, null);
|
var values = ValueType.GetProperty("Values").GetValue(Value, null);
|
||||||
|
|
||||||
// create lists to hold them
|
// create lists to hold them
|
||||||
var keyList = new List<object>();
|
var keyList = new List<object>();
|
||||||
var valueList = new List<object>();
|
var valueList = new List<object>();
|
||||||
|
|
||||||
// store entries with reflection
|
// store entries with reflection
|
||||||
@ -97,8 +102,9 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (ValueType.IsGenericType)
|
if (ValueType.IsGenericType)
|
||||||
{
|
{
|
||||||
m_keysType = ValueType.GetGenericArguments()[0];
|
var generics = ValueType.GetGenericArguments();
|
||||||
m_valuesType = ValueType.GetGenericArguments()[1];
|
m_keysType = generics[0];
|
||||||
|
m_valuesType = generics[1];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -113,12 +119,20 @@ namespace Explorer
|
|||||||
// first make sure we won't run into a TypeInitializationException.
|
// first make sure we won't run into a TypeInitializationException.
|
||||||
if (!EnsureDictionaryIsSupported())
|
if (!EnsureDictionaryIsSupported())
|
||||||
{
|
{
|
||||||
ReflectionException = "Dictionary Type not supported with Reflection!";
|
if (OwnerCacheObject is CacheMember cacheMember)
|
||||||
|
{
|
||||||
|
cacheMember.ReflectionException = "Dictionary Type not supported with Reflection!";
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
base.UpdateValue();
|
base.UpdateValue();
|
||||||
|
|
||||||
|
CacheEntries();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CacheEntries()
|
||||||
|
{
|
||||||
// reset
|
// reset
|
||||||
IDict = null;
|
IDict = null;
|
||||||
|
|
||||||
@ -169,9 +183,9 @@ namespace Explorer
|
|||||||
return Il2CppSystem.Type.internal_from_handle(IL2CPP.il2cpp_class_get_type(ptr)) is Il2CppSystem.Type;
|
return Il2CppSystem.Type.internal_from_handle(IL2CPP.il2cpp_class_get_type(ptr)) is Il2CppSystem.Type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
return false;
|
return false;
|
||||||
@ -190,8 +204,6 @@ namespace Explorer
|
|||||||
|
|
||||||
var whitespace = CalcWhitespace(window);
|
var whitespace = CalcWhitespace(window);
|
||||||
|
|
||||||
int count = m_cachedKeys.Length;
|
|
||||||
|
|
||||||
if (!IsExpanded)
|
if (!IsExpanded)
|
||||||
{
|
{
|
||||||
if (GUILayout.Button("v", new GUILayoutOption[] { GUILayout.Width(25) }))
|
if (GUILayout.Button("v", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||||
@ -209,6 +221,8 @@ namespace Explorer
|
|||||||
|
|
||||||
var negativeWhitespace = window.width - (whitespace + 100f);
|
var negativeWhitespace = window.width - (whitespace + 100f);
|
||||||
|
|
||||||
|
int count = m_cachedKeys.Length;
|
||||||
|
|
||||||
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
||||||
string btnLabel = $"[{count}] <color=#2df7b2>Dictionary<{TypeOfKeys.FullName}, {TypeOfValues.FullName}></color>";
|
string btnLabel = $"[{count}] <color=#2df7b2>Dictionary<{TypeOfKeys.FullName}, {TypeOfValues.FullName}></color>";
|
||||||
if (GUILayout.Button(btnLabel, new GUILayoutOption[] { GUILayout.Width(negativeWhitespace) }))
|
if (GUILayout.Button(btnLabel, new GUILayoutOption[] { GUILayout.Width(negativeWhitespace) }))
|
||||||
@ -226,7 +240,7 @@ namespace Explorer
|
|||||||
if (count > Pages.ItemsPerPage)
|
if (count > Pages.ItemsPerPage)
|
||||||
{
|
{
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
|
|
||||||
@ -256,24 +270,31 @@ namespace Explorer
|
|||||||
|
|
||||||
//collapsing the BeginHorizontal called from ReflectionWindow.WindowFunction or previous array entry
|
//collapsing the BeginHorizontal called from ReflectionWindow.WindowFunction or previous array entry
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
//GUIUnstrip.Space(whitespace);
|
//GUIUnstrip.Space(whitespace);
|
||||||
|
|
||||||
if (key == null || val == null)
|
if (key == null && val == null)
|
||||||
{
|
{
|
||||||
GUILayout.Label($"[{i}] <i><color=grey>(null)</color></i>", new GUILayoutOption[0]);
|
GUILayout.Label($"[{i}] <i><color=grey>(null)</color></i>", new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||||
GUILayout.Label($"[{i}]", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label($"[{i}]", new GUILayoutOption[] { GUILayout.Width(40) });
|
||||||
|
|
||||||
|
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
|
||||||
GUILayout.Label("Key:", new GUILayoutOption[] { GUILayout.Width(40) });
|
GUILayout.Label("Key:", new GUILayoutOption[] { GUILayout.Width(40) });
|
||||||
key.DrawValue(window, (window.width / 2) - 80f);
|
if (key != null)
|
||||||
|
key.IValue.DrawValue(window, (window.width / 2) - 80f);
|
||||||
|
else
|
||||||
|
GUILayout.Label("<i>null</i>", new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUILayout.Label("Value:", new GUILayoutOption[] { GUILayout.Width(40) });
|
GUILayout.Label("Value:", new GUILayoutOption[] { GUILayout.Width(40) });
|
||||||
val.DrawValue(window, (window.width / 2) - 80f);
|
if (val != null)
|
||||||
|
val.IValue.DrawValue(window, (window.width / 2) - 80f);
|
||||||
|
else
|
||||||
|
GUILayout.Label("<i>null</i>", new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,22 +1,25 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
using Explorer.CacheObject;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI
|
||||||
{
|
{
|
||||||
public class CacheList : CacheObjectBase, IExpandHeight
|
public class InteractiveEnumerable : InteractiveValue, IExpandHeight
|
||||||
{
|
{
|
||||||
public bool IsExpanded { get; set; }
|
public bool IsExpanded { get; set; }
|
||||||
public float WhiteSpace { get; set; } = 215f;
|
public float WhiteSpace { get; set; } = 215f;
|
||||||
|
|
||||||
public PageHelper Pages = new PageHelper();
|
public PageHelper Pages = new PageHelper();
|
||||||
|
|
||||||
private CacheObjectBase[] m_cachedEntries;
|
private CacheEnumerated[] m_cachedEntries = new CacheEnumerated[0];
|
||||||
|
|
||||||
// Type of Entries in the Array
|
// Type of Entries in the Array
|
||||||
public Type EntryType
|
public Type EntryType
|
||||||
{
|
{
|
||||||
get => GetEntryType();
|
get => GetEntryType();
|
||||||
set => m_entryType = value;
|
set => m_entryType = value;
|
||||||
@ -170,38 +173,20 @@ namespace Explorer
|
|||||||
|
|
||||||
private Type GetEntryType()
|
private Type GetEntryType()
|
||||||
{
|
{
|
||||||
if (m_entryType == null)
|
if (ValueType.IsGenericType)
|
||||||
{
|
{
|
||||||
if (this.MemInfo != null)
|
var gArgs = ValueType.GetGenericArguments();
|
||||||
{
|
|
||||||
Type memberType = null;
|
|
||||||
switch (this.MemInfo.MemberType)
|
|
||||||
{
|
|
||||||
case MemberTypes.Field:
|
|
||||||
memberType = (MemInfo as FieldInfo).FieldType;
|
|
||||||
break;
|
|
||||||
case MemberTypes.Property:
|
|
||||||
memberType = (MemInfo as PropertyInfo).PropertyType;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (memberType != null && memberType.IsGenericType)
|
if (ValueType.FullName.Contains("ValueCollection"))
|
||||||
{
|
|
||||||
m_entryType = memberType.GetGenericArguments()[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (Value != null)
|
|
||||||
{
|
{
|
||||||
var type = Value.GetType();
|
m_entryType = gArgs[gArgs.Length - 1];
|
||||||
if (type.IsGenericType)
|
}
|
||||||
{
|
else
|
||||||
m_entryType = type.GetGenericArguments()[0];
|
{
|
||||||
}
|
m_entryType = gArgs[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// IList probably won't be able to get any EntryType.
|
|
||||||
if (m_entryType == null)
|
|
||||||
{
|
{
|
||||||
m_entryType = typeof(object);
|
m_entryType = typeof(object);
|
||||||
}
|
}
|
||||||
@ -218,13 +203,19 @@ namespace Explorer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CacheEntries();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CacheEntries()
|
||||||
|
{
|
||||||
var enumerator = Enumerable.GetEnumerator();
|
var enumerator = Enumerable.GetEnumerator();
|
||||||
if (enumerator == null)
|
if (enumerator == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var list = new List<CacheObjectBase>();
|
var list = new List<CacheEnumerated>();
|
||||||
|
int index = 0;
|
||||||
while (enumerator.MoveNext())
|
while (enumerator.MoveNext())
|
||||||
{
|
{
|
||||||
var obj = enumerator.Current;
|
var obj = enumerator.Current;
|
||||||
@ -246,19 +237,18 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (CacheFactory.GetCacheObject(obj, t) is CacheObjectBase cached)
|
//ExplorerCore.Log("Caching enumeration entry " + obj.ToString() + " as " + EntryType.FullName);
|
||||||
{
|
|
||||||
list.Add(cached);
|
var cached = new CacheEnumerated() { Index = index, RefIList = Value as IList, ParentEnumeration = this };
|
||||||
}
|
cached.Init(obj, EntryType);
|
||||||
else
|
list.Add(cached);
|
||||||
{
|
|
||||||
list.Add(null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
list.Add(null);
|
list.Add(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cachedEntries = list.ToArray();
|
m_cachedEntries = list.ToArray();
|
||||||
@ -276,8 +266,6 @@ namespace Explorer
|
|||||||
|
|
||||||
var whitespace = CalcWhitespace(window);
|
var whitespace = CalcWhitespace(window);
|
||||||
|
|
||||||
int count = m_cachedEntries.Length;
|
|
||||||
|
|
||||||
if (!IsExpanded)
|
if (!IsExpanded)
|
||||||
{
|
{
|
||||||
if (GUILayout.Button("v", new GUILayoutOption[] { GUILayout.Width(25) }))
|
if (GUILayout.Button("v", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||||
@ -295,6 +283,8 @@ namespace Explorer
|
|||||||
|
|
||||||
var negativeWhitespace = window.width - (whitespace + 100f);
|
var negativeWhitespace = window.width - (whitespace + 100f);
|
||||||
|
|
||||||
|
int count = m_cachedEntries.Length;
|
||||||
|
|
||||||
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
||||||
string btnLabel = $"[{count}] <color=#2df7b2>{EntryType.FullName}</color>";
|
string btnLabel = $"[{count}] <color=#2df7b2>{EntryType.FullName}</color>";
|
||||||
if (GUILayout.Button(btnLabel, new GUILayoutOption[] { GUILayout.Width(negativeWhitespace) }))
|
if (GUILayout.Button(btnLabel, new GUILayoutOption[] { GUILayout.Width(negativeWhitespace) }))
|
||||||
@ -312,10 +302,10 @@ namespace Explorer
|
|||||||
if (count > Pages.ItemsPerPage)
|
if (count > Pages.ItemsPerPage)
|
||||||
{
|
{
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
|
|
||||||
Pages.CurrentPageLabel();
|
Pages.CurrentPageLabel();
|
||||||
|
|
||||||
// prev/next page buttons
|
// prev/next page buttons
|
||||||
@ -341,11 +331,11 @@ namespace Explorer
|
|||||||
|
|
||||||
//collapsing the BeginHorizontal called from ReflectionWindow.WindowFunction or previous array entry
|
//collapsing the BeginHorizontal called from ReflectionWindow.WindowFunction or previous array entry
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
|
|
||||||
if (entry == null || entry.Value == null)
|
if (entry == null || entry.IValue == null)
|
||||||
{
|
{
|
||||||
GUILayout.Label($"[{i}] <i><color=grey>(null)</color></i>", new GUILayoutOption[0]);
|
GUILayout.Label($"[{i}] <i><color=grey>(null)</color></i>", new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
@ -355,9 +345,9 @@ namespace Explorer
|
|||||||
GUILayout.Label($"[{i}]", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label($"[{i}]", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
|
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
|
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
|
||||||
entry.DrawValue(window, window.width - (whitespace + 85));
|
entry.IValue.DrawValue(window, window.width - (whitespace + 85));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
25
src/UI/InteractiveValue/Object/InteractiveGameObject.cs
Normal file
25
src/UI/InteractiveValue/Object/InteractiveGameObject.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
using Explorer.CacheObject;
|
||||||
|
|
||||||
|
namespace Explorer.UI
|
||||||
|
{
|
||||||
|
public class InteractiveGameObject : InteractiveValue
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
public override void DrawValue(Rect window, float width)
|
||||||
|
{
|
||||||
|
Buttons.GameObjectButton(Value, null, false, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void UpdateValue()
|
||||||
|
{
|
||||||
|
base.UpdateValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
51
src/UI/InteractiveValue/Object/InteractiveSprite.cs
Normal file
51
src/UI/InteractiveValue/Object/InteractiveSprite.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Explorer.Helpers;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Explorer.UI
|
||||||
|
{
|
||||||
|
public class InteractiveSprite : InteractiveTexture2D
|
||||||
|
{
|
||||||
|
private Sprite refSprite;
|
||||||
|
|
||||||
|
public override void UpdateValue()
|
||||||
|
{
|
||||||
|
#if CPP
|
||||||
|
if (Value != null && Value.Il2CppCast(typeof(Sprite)) is Sprite sprite)
|
||||||
|
{
|
||||||
|
refSprite = sprite;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (Value is Sprite sprite)
|
||||||
|
{
|
||||||
|
refSprite = sprite;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
base.UpdateValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void GetTexture2D()
|
||||||
|
{
|
||||||
|
if (refSprite)
|
||||||
|
{
|
||||||
|
currentTex = refSprite.texture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void GetGUIContent()
|
||||||
|
{
|
||||||
|
// Check if the Sprite.textureRect is just the entire texture
|
||||||
|
if (refSprite.textureRect != new Rect(0, 0, currentTex.width, currentTex.height))
|
||||||
|
{
|
||||||
|
// It's not, do a sub-copy.
|
||||||
|
currentTex = Texture2DHelpers.Copy(refSprite.texture, refSprite.textureRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
base.GetGUIContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
30
src/UI/InteractiveValue/Object/InteractiveTexture.cs
Normal file
30
src/UI/InteractiveValue/Object/InteractiveTexture.cs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Explorer.UI
|
||||||
|
{
|
||||||
|
// This class is possibly unnecessary.
|
||||||
|
// It's just for CacheMembers that have 'Texture' as the value type, but is actually a Texture2D.
|
||||||
|
|
||||||
|
public class InteractiveTexture : InteractiveTexture2D
|
||||||
|
{
|
||||||
|
public override 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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
149
src/UI/InteractiveValue/Object/InteractiveTexture2D.cs
Normal file
149
src/UI/InteractiveValue/Object/InteractiveTexture2D.cs
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Explorer.CacheObject;
|
||||||
|
using Explorer.Config;
|
||||||
|
using UnityEngine;
|
||||||
|
using System.IO;
|
||||||
|
using Explorer.Helpers;
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void GetGUIContent()
|
||||||
|
{
|
||||||
|
texContent = new GUIContent
|
||||||
|
{
|
||||||
|
image = currentTex
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void DrawValue(Rect window, float width)
|
||||||
|
{
|
||||||
|
GUIUnstrip.BeginVertical();
|
||||||
|
|
||||||
|
GUIUnstrip.BeginHorizontal();
|
||||||
|
|
||||||
|
if (currentTex && !IsExpanded)
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("v", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||||
|
{
|
||||||
|
IsExpanded = true;
|
||||||
|
GetGUIContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (currentTex)
|
||||||
|
{
|
||||||
|
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) }))
|
||||||
|
{
|
||||||
|
var name = RemoveInvalidFilenameChars(currentTex.name ?? "");
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
{
|
||||||
|
if (OwnerCacheObject is CacheMember cacheMember)
|
||||||
|
{
|
||||||
|
name = cacheMember.MemInfo.Name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
name = "UNTITLED";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture2DHelpers.SaveTextureAsPNG(currentTex, saveFolder, name, false);
|
||||||
|
|
||||||
|
ExplorerCore.Log($@"Saved to {saveFolder}\{name}.png!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string RemoveInvalidFilenameChars(string s)
|
||||||
|
{
|
||||||
|
var invalid = System.IO.Path.GetInvalidFileNameChars();
|
||||||
|
foreach (var c in invalid)
|
||||||
|
{
|
||||||
|
s = s.Replace(c.ToString(), "");
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -3,10 +3,12 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
using Explorer.CacheObject;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI
|
||||||
{
|
{
|
||||||
public class CacheColor : CacheObjectBase, IExpandHeight
|
public class InteractiveColor : InteractiveValue, IExpandHeight
|
||||||
{
|
{
|
||||||
private string r = "0";
|
private string r = "0";
|
||||||
private string g = "0";
|
private string g = "0";
|
||||||
@ -32,7 +34,7 @@ namespace Explorer
|
|||||||
|
|
||||||
public override void DrawValue(Rect window, float width)
|
public override void DrawValue(Rect window, float width)
|
||||||
{
|
{
|
||||||
if (CanWrite)
|
if (OwnerCacheObject.CanWrite)
|
||||||
{
|
{
|
||||||
if (!IsExpanded)
|
if (!IsExpanded)
|
||||||
{
|
{
|
||||||
@ -55,38 +57,38 @@ namespace Explorer
|
|||||||
GUILayout.Label($"<color=#2df7b2>Color:</color> {((Color)Value).ToString()}", new GUILayoutOption[0]);
|
GUILayout.Label($"<color=#2df7b2>Color:</color> {((Color)Value).ToString()}", new GUILayoutOption[0]);
|
||||||
//GUI.color = Color.white;
|
//GUI.color = Color.white;
|
||||||
|
|
||||||
if (CanWrite && IsExpanded)
|
if (OwnerCacheObject.CanWrite && IsExpanded)
|
||||||
{
|
{
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
var whitespace = CalcWhitespace(window);
|
var whitespace = CalcWhitespace(window);
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("R:", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label("R:", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
r = GUIUnstrip.TextField(r, new GUILayoutOption[] { GUILayout.Width(120) });
|
r = GUIUnstrip.TextField(r, new GUILayoutOption[] { GUILayout.Width(120) });
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("G:", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label("G:", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
g = GUIUnstrip.TextField(g, new GUILayoutOption[] { GUILayout.Width(120) });
|
g = GUIUnstrip.TextField(g, new GUILayoutOption[] { GUILayout.Width(120) });
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("B:", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label("B:", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
b = GUIUnstrip.TextField(b, new GUILayoutOption[] { GUILayout.Width(120) });
|
b = GUIUnstrip.TextField(b, new GUILayoutOption[] { GUILayout.Width(120) });
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("A:", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label("A:", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
a = GUIUnstrip.TextField(a, new GUILayoutOption[] { GUILayout.Width(120) });
|
a = GUIUnstrip.TextField(a, new GUILayoutOption[] { GUILayout.Width(120) });
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
// draw set value button
|
// draw set value button
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
|
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
|
||||||
{
|
{
|
||||||
@ -94,7 +96,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +108,7 @@ namespace Explorer
|
|||||||
&& float.TryParse(a, out float fA))
|
&& float.TryParse(a, out float fA))
|
||||||
{
|
{
|
||||||
Value = new Color(fR, fG, fB, fA);
|
Value = new Color(fR, fG, fB, fA);
|
||||||
SetValue();
|
OwnerCacheObject.SetValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,11 +4,15 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
using Explorer.CacheObject;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI
|
||||||
{
|
{
|
||||||
public class CacheEnum : CacheObjectBase
|
public class InteractiveEnum : InteractiveValue
|
||||||
{
|
{
|
||||||
|
internal static Dictionary<Type, string[]> EnumNamesInternalCache = new Dictionary<Type, string[]>();
|
||||||
|
|
||||||
// public Type EnumType;
|
// public Type EnumType;
|
||||||
public string[] EnumNames = new string[0];
|
public string[] EnumNames = new string[0];
|
||||||
|
|
||||||
@ -21,42 +25,55 @@ namespace Explorer
|
|||||||
|
|
||||||
if (ValueType != null)
|
if (ValueType != null)
|
||||||
{
|
{
|
||||||
// using GetValues not GetNames, to catch instances of weird enums (eg CameraClearFlags)
|
GetNames();
|
||||||
var values = Enum.GetValues(ValueType);
|
|
||||||
|
|
||||||
var list = new List<string>();
|
|
||||||
foreach (var value in values)
|
|
||||||
{
|
|
||||||
var v = value.ToString();
|
|
||||||
if (list.Contains(v)) continue;
|
|
||||||
list.Add(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
EnumNames = list.ToArray();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ReflectionException = "Unknown, could not get Enum names.";
|
if (OwnerCacheObject is CacheMember cacheMember)
|
||||||
|
{
|
||||||
|
cacheMember.ReflectionException = "Unknown, could not get Enum names.";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void GetNames()
|
||||||
|
{
|
||||||
|
if (!EnumNamesInternalCache.ContainsKey(ValueType))
|
||||||
|
{
|
||||||
|
// using GetValues not GetNames, to catch instances of weird enums (eg CameraClearFlags)
|
||||||
|
var values = Enum.GetValues(ValueType);
|
||||||
|
|
||||||
|
var set = new HashSet<string>();
|
||||||
|
foreach (var value in values)
|
||||||
|
{
|
||||||
|
var v = value.ToString();
|
||||||
|
if (set.Contains(v)) continue;
|
||||||
|
set.Add(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
EnumNamesInternalCache.Add(ValueType, set.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
EnumNames = EnumNamesInternalCache[ValueType];
|
||||||
|
}
|
||||||
|
|
||||||
public override void DrawValue(Rect window, float width)
|
public override void DrawValue(Rect window, float width)
|
||||||
{
|
{
|
||||||
if (CanWrite)
|
if (OwnerCacheObject.CanWrite)
|
||||||
{
|
{
|
||||||
if (GUILayout.Button("<", new GUILayoutOption[] { GUILayout.Width(25) }))
|
if (GUILayout.Button("<", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||||
{
|
{
|
||||||
SetEnum(-1);
|
SetEnum(-1);
|
||||||
SetValue();
|
OwnerCacheObject.SetValue();
|
||||||
}
|
}
|
||||||
if (GUILayout.Button(">", new GUILayoutOption[] { GUILayout.Width(25) }))
|
if (GUILayout.Button(">", new GUILayoutOption[] { GUILayout.Width(25) }))
|
||||||
{
|
{
|
||||||
SetEnum(1);
|
SetEnum(1);
|
||||||
SetValue();
|
OwnerCacheObject.SetValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.Label(Value.ToString() + $"<color={UIStyles.Syntax.StructGreen}><i> ({ValueType})</i></color>", new GUILayoutOption[0]);
|
GUILayout.Label(Value.ToString() + $"<color={Syntax.StructGreen}><i> ({ValueType})</i></color>", new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetEnum(int change)
|
public void SetEnum(int change)
|
@ -3,10 +3,12 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
using Explorer.CacheObject;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI
|
||||||
{
|
{
|
||||||
public class CacheEnumFlags : CacheEnum, IExpandHeight
|
public class InteractiveFlags : InteractiveEnum, IExpandHeight
|
||||||
{
|
{
|
||||||
public bool[] m_enabledFlags = new bool[0];
|
public bool[] m_enabledFlags = new bool[0];
|
||||||
|
|
||||||
@ -45,7 +47,7 @@ namespace Explorer
|
|||||||
|
|
||||||
public override void DrawValue(Rect window, float width)
|
public override void DrawValue(Rect window, float width)
|
||||||
{
|
{
|
||||||
if (CanWrite)
|
if (OwnerCacheObject.CanWrite)
|
||||||
{
|
{
|
||||||
if (!IsExpanded)
|
if (!IsExpanded)
|
||||||
{
|
{
|
||||||
@ -73,7 +75,7 @@ namespace Explorer
|
|||||||
|
|
||||||
for (int i = 0; i < EnumNames.Length; i++)
|
for (int i = 0; i < EnumNames.Length; i++)
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
|
|
||||||
m_enabledFlags[i] = GUILayout.Toggle(m_enabledFlags[i], EnumNames[i], new GUILayoutOption[0]);
|
m_enabledFlags[i] = GUILayout.Toggle(m_enabledFlags[i], EnumNames[i], new GUILayoutOption[0]);
|
||||||
@ -81,7 +83,7 @@ namespace Explorer
|
|||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
|
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
|
||||||
{
|
{
|
||||||
@ -89,7 +91,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,7 +107,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Value = Enum.Parse(ValueType, val);
|
Value = Enum.Parse(ValueType, val);
|
||||||
SetValue();
|
OwnerCacheObject.SetValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,10 +6,13 @@ using UnityEngine;
|
|||||||
#if CPP
|
#if CPP
|
||||||
using UnhollowerRuntimeLib;
|
using UnhollowerRuntimeLib;
|
||||||
#endif
|
#endif
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
using Explorer.CacheObject;
|
||||||
|
using Explorer.Config;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI
|
||||||
{
|
{
|
||||||
public class CachePrimitive : CacheObjectBase
|
public class InteractivePrimitive : InteractiveValue
|
||||||
{
|
{
|
||||||
private string m_valueToString;
|
private string m_valueToString;
|
||||||
private bool m_isBool;
|
private bool m_isBool;
|
||||||
@ -61,7 +64,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
m_valueToString = Value?.ToString();
|
m_valueToString = Value?.ToString();
|
||||||
|
|
||||||
if (m_canBitwiseOperate)
|
if (m_canBitwiseOperate && Value != null)
|
||||||
{
|
{
|
||||||
var _int = (int)Value;
|
var _int = (int)Value;
|
||||||
m_binaryInput = Convert.ToString(_int, toBase: 2);
|
m_binaryInput = Convert.ToString(_int, toBase: 2);
|
||||||
@ -75,14 +78,15 @@ namespace Explorer
|
|||||||
var b = (bool)Value;
|
var b = (bool)Value;
|
||||||
var label = $"<color={(b ? "lime" : "red")}>{b}</color>";
|
var label = $"<color={(b ? "lime" : "red")}>{b}</color>";
|
||||||
|
|
||||||
if (CanWrite)
|
if (OwnerCacheObject.CanWrite)
|
||||||
{
|
{
|
||||||
b = GUILayout.Toggle(b, label, new GUILayoutOption[0]);
|
Value = GUILayout.Toggle(b, label, new GUILayoutOption[] { GUILayout.Width(60) });
|
||||||
if (b != (bool)Value)
|
DrawApplyButton();
|
||||||
{
|
//if (b != (bool)Value)
|
||||||
Value = b;
|
//{
|
||||||
SetValue();
|
// Value = b;
|
||||||
}
|
// OwnerCacheObject.SetValue();
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -94,22 +98,17 @@ namespace Explorer
|
|||||||
|
|
||||||
// all other non-bool values use TextField
|
// all other non-bool values use TextField
|
||||||
|
|
||||||
GUILayout.BeginVertical(new GUILayoutOption[0]);
|
GUIUnstrip.BeginVertical(new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUILayout.Label("<color=#2df7b2><i>" + ValueType.Name + "</i></color>", new GUILayoutOption[] { GUILayout.Width(50) });
|
GUILayout.Label("<color=#2df7b2><i>" + ValueType.Name + "</i></color>", new GUILayoutOption[] { GUILayout.Width(50) });
|
||||||
|
|
||||||
m_valueToString = GUIUnstrip.TextArea(m_valueToString, new GUILayoutOption[] { GUILayout.ExpandWidth(true) });
|
m_valueToString = GUIUnstrip.TextArea(m_valueToString, new GUILayoutOption[] { GUILayout.ExpandWidth(true) });
|
||||||
if (CanWrite)
|
|
||||||
{
|
|
||||||
if (GUILayout.Button("<color=#00FF00>Apply</color>", new GUILayoutOption[] { GUILayout.Width(60) }))
|
|
||||||
{
|
|
||||||
SetValueFromInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_canBitwiseOperate)
|
DrawApplyButton();
|
||||||
|
|
||||||
|
if (ModConfig.Instance.Bitwise_Support && m_canBitwiseOperate)
|
||||||
{
|
{
|
||||||
m_inBitwiseMode = GUILayout.Toggle(m_inBitwiseMode, "Bitwise?", new GUILayoutOption[0]);
|
m_inBitwiseMode = GUILayout.Toggle(m_inBitwiseMode, "Bitwise?", new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
@ -118,7 +117,7 @@ namespace Explorer
|
|||||||
|
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
if (m_inBitwiseMode)
|
if (ModConfig.Instance.Bitwise_Support && m_inBitwiseMode)
|
||||||
{
|
{
|
||||||
DrawBitwise();
|
DrawBitwise();
|
||||||
}
|
}
|
||||||
@ -126,11 +125,29 @@ namespace Explorer
|
|||||||
GUILayout.EndVertical();
|
GUILayout.EndVertical();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DrawApplyButton()
|
||||||
|
{
|
||||||
|
if (OwnerCacheObject.CanWrite)
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("<color=#00FF00>Apply</color>", new GUILayoutOption[] { GUILayout.Width(60) }))
|
||||||
|
{
|
||||||
|
if (m_isBool)
|
||||||
|
{
|
||||||
|
OwnerCacheObject.SetValue();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetValueFromInput();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void DrawBitwise()
|
private void DrawBitwise()
|
||||||
{
|
{
|
||||||
if (CanWrite)
|
if (OwnerCacheObject.CanWrite)
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleRight;
|
GUI.skin.label.alignment = TextAnchor.MiddleRight;
|
||||||
GUILayout.Label("RHS:", new GUILayoutOption[] { GUILayout.Width(35) });
|
GUILayout.Label("RHS:", new GUILayoutOption[] { GUILayout.Width(35) });
|
||||||
@ -191,10 +208,10 @@ namespace Explorer
|
|||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label($"<color=cyan>Binary:</color>", new GUILayoutOption[] { GUILayout.Width(60) });
|
GUILayout.Label($"<color=cyan>Binary:</color>", new GUILayoutOption[] { GUILayout.Width(60) });
|
||||||
m_binaryInput = GUIUnstrip.TextField(m_binaryInput, new GUILayoutOption[0]);
|
m_binaryInput = GUIUnstrip.TextField(m_binaryInput, new GUILayoutOption[0]);
|
||||||
if (CanWrite)
|
if (OwnerCacheObject.CanWrite)
|
||||||
{
|
{
|
||||||
if (GUILayout.Button("Apply", new GUILayoutOption[0]))
|
if (GUILayout.Button("Apply", new GUILayoutOption[0]))
|
||||||
{
|
{
|
||||||
@ -206,12 +223,6 @@ namespace Explorer
|
|||||||
|
|
||||||
public void SetValueFromInput()
|
public void SetValueFromInput()
|
||||||
{
|
{
|
||||||
if (MemInfo == null)
|
|
||||||
{
|
|
||||||
ExplorerCore.Log("Trying to SetValue but the MemberInfo is null!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_isString)
|
if (m_isString)
|
||||||
{
|
{
|
||||||
Value = m_valueToString;
|
Value = m_valueToString;
|
||||||
@ -228,7 +239,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SetValue();
|
OwnerCacheObject.SetValue();
|
||||||
RefreshToString();
|
RefreshToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,7 +250,7 @@ namespace Explorer
|
|||||||
var method = typeof(Convert).GetMethod($"To{ValueType.Name}", new Type[] { typeof(string), typeof(int) });
|
var method = typeof(Convert).GetMethod($"To{ValueType.Name}", new Type[] { typeof(string), typeof(int) });
|
||||||
Value = method.Invoke(null, new object[] { m_binaryInput, 2 });
|
Value = method.Invoke(null, new object[] { m_binaryInput, 2 });
|
||||||
|
|
||||||
SetValue();
|
OwnerCacheObject.SetValue();
|
||||||
RefreshToString();
|
RefreshToString();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
@ -3,10 +3,12 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
using Explorer.CacheObject;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI
|
||||||
{
|
{
|
||||||
public class CacheQuaternion : CacheObjectBase, IExpandHeight
|
public class InteractiveQuaternion : InteractiveValue, IExpandHeight
|
||||||
{
|
{
|
||||||
private string x = "0";
|
private string x = "0";
|
||||||
private string y = "0";
|
private string y = "0";
|
||||||
@ -30,7 +32,7 @@ namespace Explorer
|
|||||||
|
|
||||||
public override void DrawValue(Rect window, float width)
|
public override void DrawValue(Rect window, float width)
|
||||||
{
|
{
|
||||||
if (CanWrite)
|
if (OwnerCacheObject.CanWrite)
|
||||||
{
|
{
|
||||||
if (!IsExpanded)
|
if (!IsExpanded)
|
||||||
{
|
{
|
||||||
@ -50,32 +52,32 @@ namespace Explorer
|
|||||||
|
|
||||||
GUILayout.Label($"<color=#2df7b2>Quaternion</color>: {((Quaternion)Value).eulerAngles.ToString()}", new GUILayoutOption[0]);
|
GUILayout.Label($"<color=#2df7b2>Quaternion</color>: {((Quaternion)Value).eulerAngles.ToString()}", new GUILayoutOption[0]);
|
||||||
|
|
||||||
if (CanWrite && IsExpanded)
|
if (OwnerCacheObject.CanWrite && IsExpanded)
|
||||||
{
|
{
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
var whitespace = CalcWhitespace(window);
|
var whitespace = CalcWhitespace(window);
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("X:", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label("X:", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
x = GUIUnstrip.TextField(x, new GUILayoutOption[] { GUILayout.Width(120) });
|
x = GUIUnstrip.TextField(x, new GUILayoutOption[] { GUILayout.Width(120) });
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("Y:", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label("Y:", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
y = GUIUnstrip.TextField(y, new GUILayoutOption[] { GUILayout.Width(120) });
|
y = GUIUnstrip.TextField(y, new GUILayoutOption[] { GUILayout.Width(120) });
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("Z:", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label("Z:", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
z = GUIUnstrip.TextField(z, new GUILayoutOption[] { GUILayout.Width(120) });
|
z = GUIUnstrip.TextField(z, new GUILayoutOption[] { GUILayout.Width(120) });
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
// draw set value button
|
// draw set value button
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
|
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
|
||||||
{
|
{
|
||||||
@ -83,7 +85,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +96,7 @@ namespace Explorer
|
|||||||
&& float.TryParse(z, out float fZ))
|
&& float.TryParse(z, out float fZ))
|
||||||
{
|
{
|
||||||
Value = Quaternion.Euler(new Vector3(fX, fY, fZ));
|
Value = Quaternion.Euler(new Vector3(fX, fY, fZ));
|
||||||
SetValue();
|
OwnerCacheObject.SetValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,10 +3,12 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
using Explorer.CacheObject;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI
|
||||||
{
|
{
|
||||||
public class CacheRect : CacheObjectBase, IExpandHeight
|
public class InteractiveRect : InteractiveValue, IExpandHeight
|
||||||
{
|
{
|
||||||
private string x = "0";
|
private string x = "0";
|
||||||
private string y = "0";
|
private string y = "0";
|
||||||
@ -32,7 +34,7 @@ namespace Explorer
|
|||||||
|
|
||||||
public override void DrawValue(Rect window, float width)
|
public override void DrawValue(Rect window, float width)
|
||||||
{
|
{
|
||||||
if (CanWrite)
|
if (OwnerCacheObject.CanWrite)
|
||||||
{
|
{
|
||||||
if (!IsExpanded)
|
if (!IsExpanded)
|
||||||
{
|
{
|
||||||
@ -52,38 +54,38 @@ namespace Explorer
|
|||||||
|
|
||||||
GUILayout.Label($"<color=#2df7b2>Rect</color>: {((Rect)Value).ToString()}", new GUILayoutOption[0]);
|
GUILayout.Label($"<color=#2df7b2>Rect</color>: {((Rect)Value).ToString()}", new GUILayoutOption[0]);
|
||||||
|
|
||||||
if (CanWrite && IsExpanded)
|
if (OwnerCacheObject.CanWrite && IsExpanded)
|
||||||
{
|
{
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
var whitespace = CalcWhitespace(window);
|
var whitespace = CalcWhitespace(window);
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("X:", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label("X:", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
x = GUIUnstrip.TextField(x, new GUILayoutOption[] { GUILayout.Width(120) });
|
x = GUIUnstrip.TextField(x, new GUILayoutOption[] { GUILayout.Width(120) });
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("Y:", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label("Y:", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
y = GUIUnstrip.TextField(y, new GUILayoutOption[] { GUILayout.Width(120) });
|
y = GUIUnstrip.TextField(y, new GUILayoutOption[] { GUILayout.Width(120) });
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("W:", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label("W:", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
w = GUIUnstrip.TextField(w, new GUILayoutOption[] { GUILayout.Width(120) });
|
w = GUIUnstrip.TextField(w, new GUILayoutOption[] { GUILayout.Width(120) });
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("H:", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label("H:", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
h = GUIUnstrip.TextField(h, new GUILayoutOption[] { GUILayout.Width(120) });
|
h = GUIUnstrip.TextField(h, new GUILayoutOption[] { GUILayout.Width(120) });
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
// draw set value button
|
// draw set value button
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
|
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
|
||||||
{
|
{
|
||||||
@ -91,7 +93,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +105,7 @@ namespace Explorer
|
|||||||
&& float.TryParse(h, out float fH))
|
&& float.TryParse(h, out float fH))
|
||||||
{
|
{
|
||||||
Value = new Rect(fX, fY, fW, fH);
|
Value = new Rect(fX, fY, fW, fH);
|
||||||
SetValue();
|
OwnerCacheObject.SetValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,9 +5,9 @@ using System.Text;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI
|
||||||
{
|
{
|
||||||
public class CacheVector : CacheObjectBase, IExpandHeight
|
public class InteractiveVector : InteractiveValue, IExpandHeight
|
||||||
{
|
{
|
||||||
public int VectorSize = 2;
|
public int VectorSize = 2;
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ namespace Explorer
|
|||||||
private string z = "0";
|
private string z = "0";
|
||||||
private string w = "0";
|
private string w = "0";
|
||||||
|
|
||||||
private MethodInfo m_toStringMethod;
|
//private MethodInfo m_toStringMethod;
|
||||||
|
|
||||||
public bool IsExpanded { get; set; }
|
public bool IsExpanded { get; set; }
|
||||||
public float WhiteSpace { get; set; } = 215f;
|
public float WhiteSpace { get; set; } = 215f;
|
||||||
@ -31,18 +31,20 @@ namespace Explorer
|
|||||||
if (ValueType == typeof(Vector2))
|
if (ValueType == typeof(Vector2))
|
||||||
{
|
{
|
||||||
VectorSize = 2;
|
VectorSize = 2;
|
||||||
m_toStringMethod = typeof(Vector2).GetMethod("ToString", new Type[0]);
|
//m_toStringMethod = typeof(Vector2).GetMethod("ToString", new Type[0]);
|
||||||
}
|
}
|
||||||
else if (ValueType == typeof(Vector3))
|
else if (ValueType == typeof(Vector3))
|
||||||
{
|
{
|
||||||
VectorSize = 3;
|
VectorSize = 3;
|
||||||
m_toStringMethod = typeof(Vector3).GetMethod("ToString", new Type[0]);
|
//m_toStringMethod = typeof(Vector3).GetMethod("ToString", new Type[0]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VectorSize = 4;
|
VectorSize = 4;
|
||||||
m_toStringMethod = typeof(Vector4).GetMethod("ToString", new Type[0]);
|
//m_toStringMethod = typeof(Vector4).GetMethod("ToString", new Type[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base.Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void UpdateValue()
|
public override void UpdateValue()
|
||||||
@ -71,7 +73,7 @@ namespace Explorer
|
|||||||
|
|
||||||
public override void DrawValue(Rect window, float width)
|
public override void DrawValue(Rect window, float width)
|
||||||
{
|
{
|
||||||
if (CanWrite)
|
if (OwnerCacheObject.CanWrite)
|
||||||
{
|
{
|
||||||
if (!IsExpanded)
|
if (!IsExpanded)
|
||||||
{
|
{
|
||||||
@ -89,22 +91,22 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.Label($"<color=#2df7b2>Vector{VectorSize}</color>: {(string)m_toStringMethod.Invoke(Value, new object[0])}", new GUILayoutOption[0]);
|
GUILayout.Label($"<color=#2df7b2>Vector{VectorSize}</color>: {(string)ToStringMethod.Invoke(Value, new object[0])}", new GUILayoutOption[0]);
|
||||||
|
|
||||||
if (CanWrite && IsExpanded)
|
if (OwnerCacheObject.CanWrite && IsExpanded)
|
||||||
{
|
{
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
var whitespace = CalcWhitespace(window);
|
var whitespace = CalcWhitespace(window);
|
||||||
|
|
||||||
// always draw x and y
|
// always draw x and y
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("X:", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label("X:", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
x = GUIUnstrip.TextField(x, new GUILayoutOption[] { GUILayout.Width(120) });
|
x = GUIUnstrip.TextField(x, new GUILayoutOption[] { GUILayout.Width(120) });
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("Y:", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label("Y:", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
y = GUIUnstrip.TextField(y, new GUILayoutOption[] { GUILayout.Width(120) });
|
y = GUIUnstrip.TextField(y, new GUILayoutOption[] { GUILayout.Width(120) });
|
||||||
@ -113,7 +115,7 @@ namespace Explorer
|
|||||||
if (VectorSize > 2)
|
if (VectorSize > 2)
|
||||||
{
|
{
|
||||||
// draw z
|
// draw z
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("Z:", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label("Z:", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
z = GUIUnstrip.TextField(z, new GUILayoutOption[] { GUILayout.Width(120) });
|
z = GUIUnstrip.TextField(z, new GUILayoutOption[] { GUILayout.Width(120) });
|
||||||
@ -122,7 +124,7 @@ namespace Explorer
|
|||||||
if (VectorSize > 3)
|
if (VectorSize > 3)
|
||||||
{
|
{
|
||||||
// draw w
|
// draw w
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
GUILayout.Label("W:", new GUILayoutOption[] { GUILayout.Width(30) });
|
GUILayout.Label("W:", new GUILayoutOption[] { GUILayout.Width(30) });
|
||||||
w = GUIUnstrip.TextField(w, new GUILayoutOption[] { GUILayout.Width(120) });
|
w = GUIUnstrip.TextField(w, new GUILayoutOption[] { GUILayout.Width(120) });
|
||||||
@ -130,7 +132,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// draw set value button
|
// draw set value button
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUIUnstrip.Space(whitespace);
|
GUIUnstrip.Space(whitespace);
|
||||||
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
|
if (GUILayout.Button("<color=lime>Apply</color>", new GUILayoutOption[] { GUILayout.Width(155) }))
|
||||||
{
|
{
|
||||||
@ -138,7 +140,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +163,7 @@ namespace Explorer
|
|||||||
if (vector != null)
|
if (vector != null)
|
||||||
{
|
{
|
||||||
Value = vector;
|
Value = vector;
|
||||||
SetValue();
|
OwnerCacheObject.SetValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,8 +1,8 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI.Main
|
||||||
{
|
{
|
||||||
public abstract class WindowPage
|
public abstract class BaseMainMenuPage
|
||||||
{
|
{
|
||||||
public virtual string Name { get; }
|
public virtual string Name { get; }
|
||||||
|
|
56
src/UI/Main/Console/AutoComplete.cs
Normal file
56
src/UI/Main/Console/AutoComplete.cs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
// Thanks to ManlyMarco for this
|
||||||
|
|
||||||
|
namespace Explorer.UI.Main
|
||||||
|
{
|
||||||
|
public struct AutoComplete
|
||||||
|
{
|
||||||
|
public string Full => Prefix + Addition;
|
||||||
|
|
||||||
|
public readonly string Prefix;
|
||||||
|
public readonly string Addition;
|
||||||
|
public readonly Contexts Context;
|
||||||
|
|
||||||
|
public Color TextColor => Context == Contexts.Namespace
|
||||||
|
? Color.gray
|
||||||
|
: Color.white;
|
||||||
|
|
||||||
|
public AutoComplete(string addition, string prefix, Contexts type)
|
||||||
|
{
|
||||||
|
Addition = addition;
|
||||||
|
Prefix = prefix;
|
||||||
|
Context = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Contexts
|
||||||
|
{
|
||||||
|
Namespace,
|
||||||
|
Other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AutoCompleteHelpers
|
||||||
|
{
|
||||||
|
public static HashSet<string> Namespaces => _namespaces ?? GetNamespaces();
|
||||||
|
private static HashSet<string> _namespaces;
|
||||||
|
|
||||||
|
private static HashSet<string> GetNamespaces()
|
||||||
|
{
|
||||||
|
var set = new HashSet<string>(
|
||||||
|
AppDomain.CurrentDomain.GetAssemblies()
|
||||||
|
.SelectMany(GetTypes)
|
||||||
|
.Where(x => x.IsPublic && !string.IsNullOrEmpty(x.Namespace))
|
||||||
|
.Select(x => x.Namespace));
|
||||||
|
|
||||||
|
return _namespaces = set;
|
||||||
|
|
||||||
|
IEnumerable<Type> GetTypes(Assembly asm) => asm.TryGetTypes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
70
src/UI/Main/Console/ScriptEvaluator.cs
Normal file
70
src/UI/Main/Console/ScriptEvaluator.cs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using Mono.CSharp;
|
||||||
|
|
||||||
|
// Thanks to ManlyMarco for this
|
||||||
|
|
||||||
|
namespace Explorer.UI.Main
|
||||||
|
{
|
||||||
|
internal class ScriptEvaluator : Evaluator, IDisposable
|
||||||
|
{
|
||||||
|
private static readonly HashSet<string> StdLib = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase)
|
||||||
|
{
|
||||||
|
"mscorlib", "System.Core", "System", "System.Xml"
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly TextWriter _logger;
|
||||||
|
|
||||||
|
public ScriptEvaluator(TextWriter logger) : base(BuildContext(logger))
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
|
||||||
|
ImportAppdomainAssemblies(ReferenceAssembly);
|
||||||
|
AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoad;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
AppDomain.CurrentDomain.AssemblyLoad -= OnAssemblyLoad;
|
||||||
|
_logger.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAssemblyLoad(object sender, AssemblyLoadEventArgs args)
|
||||||
|
{
|
||||||
|
string name = args.LoadedAssembly.GetName().Name;
|
||||||
|
if (StdLib.Contains(name))
|
||||||
|
return;
|
||||||
|
ReferenceAssembly(args.LoadedAssembly);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CompilerContext BuildContext(TextWriter tw)
|
||||||
|
{
|
||||||
|
var reporter = new StreamReportPrinter(tw);
|
||||||
|
|
||||||
|
var settings = new CompilerSettings
|
||||||
|
{
|
||||||
|
Version = LanguageVersion.Experimental,
|
||||||
|
GenerateDebugInfo = false,
|
||||||
|
StdLib = true,
|
||||||
|
Target = Target.Library,
|
||||||
|
WarningLevel = 0,
|
||||||
|
EnhancedWarnings = false
|
||||||
|
};
|
||||||
|
|
||||||
|
return new CompilerContext(settings, reporter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ImportAppdomainAssemblies(Action<Assembly> import)
|
||||||
|
{
|
||||||
|
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
|
{
|
||||||
|
string name = assembly.GetName().Name;
|
||||||
|
if (StdLib.Contains(name))
|
||||||
|
continue;
|
||||||
|
import(assembly);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
79
src/UI/Main/Console/ScriptInteraction.cs
Normal file
79
src/UI/Main/Console/ScriptInteraction.cs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Explorer.UI.Inspectors;
|
||||||
|
using Mono.CSharp;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Explorer.UI.Main
|
||||||
|
{
|
||||||
|
public class ScriptInteraction : InteractiveBase
|
||||||
|
{
|
||||||
|
public static void Log(object message)
|
||||||
|
{
|
||||||
|
ExplorerCore.Log(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object CurrentTarget()
|
||||||
|
{
|
||||||
|
if (!WindowManager.TabView)
|
||||||
|
{
|
||||||
|
ExplorerCore.Log("CurrentTarget() is only a valid method when in Tab View mode!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return WindowManager.Windows.ElementAt(TabViewWindow.Instance.TargetTabID).Target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object[] AllTargets()
|
||||||
|
{
|
||||||
|
var list = new List<object>();
|
||||||
|
foreach (var window in WindowManager.Windows)
|
||||||
|
{
|
||||||
|
if (window.Target != null)
|
||||||
|
{
|
||||||
|
list.Add(window.Target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Inspect(object obj)
|
||||||
|
{
|
||||||
|
WindowManager.InspectObject(obj, out bool _);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Inspect(Type type)
|
||||||
|
{
|
||||||
|
WindowManager.InspectStaticReflection(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Help()
|
||||||
|
{
|
||||||
|
ExplorerCore.Log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||||
|
ExplorerCore.Log(" C# Console Help ");
|
||||||
|
ExplorerCore.Log("");
|
||||||
|
ExplorerCore.Log("The following helper methods are available:");
|
||||||
|
ExplorerCore.Log("");
|
||||||
|
ExplorerCore.Log("void Log(object message)");
|
||||||
|
ExplorerCore.Log(" prints a message to the console window and debug log");
|
||||||
|
ExplorerCore.Log(" usage: Log(\"hello world\");");
|
||||||
|
ExplorerCore.Log("");
|
||||||
|
ExplorerCore.Log("object CurrentTarget()");
|
||||||
|
ExplorerCore.Log(" returns the target object of the current tab (in tab view mode only)");
|
||||||
|
ExplorerCore.Log(" usage: var target = CurrentTarget();");
|
||||||
|
ExplorerCore.Log("");
|
||||||
|
ExplorerCore.Log("object[] AllTargets()");
|
||||||
|
ExplorerCore.Log(" returns an object[] array containing all currently inspected objects");
|
||||||
|
ExplorerCore.Log(" usage: var targets = AllTargets();");
|
||||||
|
ExplorerCore.Log("");
|
||||||
|
ExplorerCore.Log("void Inspect(object obj)");
|
||||||
|
ExplorerCore.Log(" inspects the provided object in a new window.");
|
||||||
|
ExplorerCore.Log(" usage: Inspect(Camera.main);");
|
||||||
|
ExplorerCore.Log("");
|
||||||
|
ExplorerCore.Log("void Inspect(Type type)");
|
||||||
|
ExplorerCore.Log(" attempts to inspect the provided type with static-only reflection.");
|
||||||
|
ExplorerCore.Log(" usage: Inspect(typeof(Camera));");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
366
src/UI/Main/ConsolePage.cs
Normal file
366
src/UI/Main/ConsolePage.cs
Normal file
@ -0,0 +1,366 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using Mono.CSharp;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.IO;
|
||||||
|
#if CPP
|
||||||
|
using UnhollowerRuntimeLib;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Explorer.UI.Main
|
||||||
|
{
|
||||||
|
public class ConsolePage : BaseMainMenuPage
|
||||||
|
{
|
||||||
|
public static ConsolePage Instance { get; private set; }
|
||||||
|
|
||||||
|
public override string Name { get => "C# Console"; }
|
||||||
|
|
||||||
|
private ScriptEvaluator m_evaluator;
|
||||||
|
|
||||||
|
public const string INPUT_CONTROL_NAME = "consoleInput";
|
||||||
|
private string m_input = "";
|
||||||
|
private string m_prevInput = "";
|
||||||
|
private string m_usingInput = "";
|
||||||
|
|
||||||
|
public static List<AutoComplete> AutoCompletes = new List<AutoComplete>();
|
||||||
|
public static List<string> UsingDirectives;
|
||||||
|
|
||||||
|
private Vector2 inputAreaScroll;
|
||||||
|
private Vector2 autocompleteScroll;
|
||||||
|
public static TextEditor textEditor;
|
||||||
|
private bool shouldRefocus;
|
||||||
|
|
||||||
|
public static GUIStyle AutocompleteStyle => autocompleteStyle ?? GetCompletionStyle();
|
||||||
|
private static GUIStyle autocompleteStyle;
|
||||||
|
|
||||||
|
public static readonly string[] DefaultUsing = new string[]
|
||||||
|
{
|
||||||
|
"System",
|
||||||
|
"UnityEngine",
|
||||||
|
"System.Linq",
|
||||||
|
"System.Collections",
|
||||||
|
"System.Collections.Generic",
|
||||||
|
"System.Reflection"
|
||||||
|
};
|
||||||
|
|
||||||
|
public override void Init()
|
||||||
|
{
|
||||||
|
Instance = this;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_input = @"// For a list of helper methods, execute the 'Help();' method.
|
||||||
|
// Enable the Console Window with your Mod Loader to see log output.
|
||||||
|
|
||||||
|
Help();";
|
||||||
|
ResetConsole();
|
||||||
|
|
||||||
|
foreach (var use in DefaultUsing)
|
||||||
|
{
|
||||||
|
AddUsing(use);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Error setting up console!\r\nMessage: {e.Message}");
|
||||||
|
MainMenu.SetCurrentPage(0);
|
||||||
|
MainMenu.Pages.Remove(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update() { }
|
||||||
|
|
||||||
|
public string AsmToUsing(string asm, bool richtext = false)
|
||||||
|
{
|
||||||
|
if (richtext)
|
||||||
|
{
|
||||||
|
return $"<color=#569cd6>using</color> {asm};";
|
||||||
|
}
|
||||||
|
return $"using {asm};";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddUsing(string asm)
|
||||||
|
{
|
||||||
|
if (!UsingDirectives.Contains(asm))
|
||||||
|
{
|
||||||
|
UsingDirectives.Add(asm);
|
||||||
|
Evaluate(AsmToUsing(asm), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Evaluate(string str, bool suppressWarning = false)
|
||||||
|
{
|
||||||
|
object ret = VoidType.Value;
|
||||||
|
|
||||||
|
m_evaluator.Compile(str, out var compiled);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (compiled == null)
|
||||||
|
{
|
||||||
|
throw new Exception("Mono.Csharp Service was unable to compile the code provided.");
|
||||||
|
}
|
||||||
|
|
||||||
|
compiled.Invoke(ref ret);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
if (!suppressWarning)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning(e.GetType() + ", " + e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetConsole()
|
||||||
|
{
|
||||||
|
if (m_evaluator != null)
|
||||||
|
{
|
||||||
|
m_evaluator.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_evaluator = new ScriptEvaluator(new StringWriter(new StringBuilder())) { InteractiveBaseClass = typeof(ScriptInteraction) };
|
||||||
|
|
||||||
|
UsingDirectives = new List<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override void DrawWindow()
|
||||||
|
{
|
||||||
|
GUILayout.Label("<b><size=15><color=cyan>C# Console</color></size></b>", new GUILayoutOption[0]);
|
||||||
|
|
||||||
|
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||||
|
|
||||||
|
// SCRIPT INPUT
|
||||||
|
|
||||||
|
GUILayout.Label("Enter code here as though it is a method body:", new GUILayoutOption[0]);
|
||||||
|
|
||||||
|
inputAreaScroll = GUIUnstrip.BeginScrollView(
|
||||||
|
inputAreaScroll,
|
||||||
|
new GUILayoutOption[] { GUILayout.Height(250), GUILayout.ExpandHeight(true) }
|
||||||
|
);
|
||||||
|
|
||||||
|
GUI.SetNextControlName(INPUT_CONTROL_NAME);
|
||||||
|
m_input = GUIUnstrip.TextArea(m_input, new GUILayoutOption[] { GUILayout.ExpandHeight(true) });
|
||||||
|
|
||||||
|
GUIUnstrip.EndScrollView();
|
||||||
|
|
||||||
|
// EXECUTE BUTTON
|
||||||
|
|
||||||
|
if (GUILayout.Button("<color=cyan><b>Execute</b></color>", new GUILayoutOption[0]))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_input = m_input.Trim();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(m_input))
|
||||||
|
{
|
||||||
|
Evaluate(m_input);
|
||||||
|
|
||||||
|
//var result = Evaluate(m_input);
|
||||||
|
|
||||||
|
//if (result != null && !Equals(result, VoidType.Value))
|
||||||
|
//{
|
||||||
|
// ExplorerCore.Log("[Console Output]\r\n" + result.ToString());
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ExplorerCore.LogError("Exception compiling!\r\nMessage: " + e.Message + "\r\nStack: " + e.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SUGGESTIONS
|
||||||
|
if (AutoCompletes.Count > 0)
|
||||||
|
{
|
||||||
|
autocompleteScroll = GUIUnstrip.BeginScrollView(autocompleteScroll, new GUILayoutOption[] { GUILayout.Height(150) });
|
||||||
|
|
||||||
|
var origSkin = GUI.skin.button;
|
||||||
|
GUI.skin.button = AutocompleteStyle;
|
||||||
|
|
||||||
|
foreach (var autocomplete in AutoCompletes)
|
||||||
|
{
|
||||||
|
AutocompleteStyle.normal.textColor = autocomplete.TextColor;
|
||||||
|
if (GUILayout.Button(autocomplete.Full, new GUILayoutOption[] { GUILayout.Width(MainMenu.MainRect.width - 50) }))
|
||||||
|
{
|
||||||
|
UseAutocomplete(autocomplete.Addition);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GUI.skin.button = origSkin;
|
||||||
|
|
||||||
|
GUIUnstrip.EndScrollView();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldRefocus)
|
||||||
|
{
|
||||||
|
GUI.FocusControl(INPUT_CONTROL_NAME);
|
||||||
|
shouldRefocus = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// USING DIRECTIVES
|
||||||
|
|
||||||
|
GUILayout.Label("<b>Using directives:</b>", new GUILayoutOption[0]);
|
||||||
|
|
||||||
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
GUILayout.Label("Add namespace:", new GUILayoutOption[] { GUILayout.Width(105) });
|
||||||
|
m_usingInput = GUIUnstrip.TextField(m_usingInput, new GUILayoutOption[] { GUILayout.Width(150) });
|
||||||
|
if (GUILayout.Button("<b><color=lime>Add</color></b>", new GUILayoutOption[] { GUILayout.Width(120) }))
|
||||||
|
{
|
||||||
|
AddUsing(m_usingInput);
|
||||||
|
}
|
||||||
|
if (GUILayout.Button("<b><color=red>Clear All</color></b>", new GUILayoutOption[] { GUILayout.Width(120) }))
|
||||||
|
{
|
||||||
|
ResetConsole();
|
||||||
|
}
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
foreach (var asm in UsingDirectives)
|
||||||
|
{
|
||||||
|
GUILayout.Label(AsmToUsing(asm, true), new GUILayoutOption[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckAutocomplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckAutocomplete()
|
||||||
|
{
|
||||||
|
// Temporary disabling this check in BepInEx Il2Cpp.
|
||||||
|
#if BIE
|
||||||
|
#if CPP
|
||||||
|
#else
|
||||||
|
if (GUI.GetNameOfFocusedControl() != INPUT_CONTROL_NAME)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
if (GUI.GetNameOfFocusedControl() != INPUT_CONTROL_NAME)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CPP
|
||||||
|
textEditor = GUIUtility.GetStateObject(Il2CppType.Of<TextEditor>(), GUIUtility.keyboardControl).TryCast<TextEditor>();
|
||||||
|
#else
|
||||||
|
textEditor = (TextEditor)GUIUtility.GetStateObject(typeof(TextEditor), GUIUtility.keyboardControl);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
var input = m_input;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(input))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var splitChars = new[] { ',', ';', '<', '>', '(', ')', '[', ']', '=', '|', '&' };
|
||||||
|
|
||||||
|
// Credit ManlyMarco
|
||||||
|
// Separate input into parts, grab only the part with cursor in it
|
||||||
|
var cursorIndex = textEditor.cursorIndex;
|
||||||
|
var start = cursorIndex <= 0 ? 0 : input.LastIndexOfAny(splitChars, cursorIndex - 1) + 1;
|
||||||
|
var end = cursorIndex <= 0 ? input.Length : input.IndexOfAny(splitChars, cursorIndex - 1);
|
||||||
|
if (end < 0 || end < start) end = input.Length;
|
||||||
|
input = input.Substring(start, end - start);
|
||||||
|
}
|
||||||
|
catch (ArgumentException) { }
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(input) && input != m_prevInput)
|
||||||
|
{
|
||||||
|
GetAutocompletes(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ClearAutocompletes();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_prevInput = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearAutocompletes()
|
||||||
|
{
|
||||||
|
if (AutoCompletes.Any())
|
||||||
|
{
|
||||||
|
AutoCompletes.Clear();
|
||||||
|
shouldRefocus = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UseAutocomplete(string suggestion)
|
||||||
|
{
|
||||||
|
int cursorIndex = textEditor.cursorIndex;
|
||||||
|
m_input = m_input.Insert(cursorIndex, suggestion);
|
||||||
|
|
||||||
|
ClearAutocompletes();
|
||||||
|
shouldRefocus = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GetAutocompletes(string input)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//ExplorerCore.Log("Fetching suggestions for input " + input);
|
||||||
|
|
||||||
|
// Credit ManylMarco
|
||||||
|
AutoCompletes.Clear();
|
||||||
|
var completions = m_evaluator.GetCompletions(input, out string prefix);
|
||||||
|
if (completions != null)
|
||||||
|
{
|
||||||
|
if (prefix == null)
|
||||||
|
prefix = input;
|
||||||
|
|
||||||
|
AutoCompletes.AddRange(completions
|
||||||
|
.Where(x => !string.IsNullOrEmpty(x))
|
||||||
|
.Select(x => new AutoComplete(x, prefix, AutoComplete.Contexts.Other))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var trimmed = input.Trim();
|
||||||
|
if (trimmed.StartsWith("using"))
|
||||||
|
trimmed = trimmed.Remove(0, 5).Trim();
|
||||||
|
|
||||||
|
var namespaces = AutoCompleteHelpers.Namespaces
|
||||||
|
.Where(x => x.StartsWith(trimmed) && x.Length > trimmed.Length)
|
||||||
|
.Select(x => new AutoComplete(
|
||||||
|
x.Substring(trimmed.Length),
|
||||||
|
x.Substring(0, trimmed.Length),
|
||||||
|
AutoComplete.Contexts.Namespace));
|
||||||
|
|
||||||
|
AutoCompletes.AddRange(namespaces);
|
||||||
|
|
||||||
|
shouldRefocus = true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
ExplorerCore.Log("C# Console error:\r\n" + ex);
|
||||||
|
ClearAutocompletes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Credit ManlyMarco
|
||||||
|
private static GUIStyle GetCompletionStyle()
|
||||||
|
{
|
||||||
|
return autocompleteStyle = new GUIStyle(GUI.skin.button)
|
||||||
|
{
|
||||||
|
border = new RectOffset(0, 0, 0, 0),
|
||||||
|
margin = new RectOffset(0, 0, 0, 0),
|
||||||
|
padding = new RectOffset(0, 0, 0, 0),
|
||||||
|
hover = { background = Texture2D.whiteTexture, textColor = Color.black },
|
||||||
|
normal = { background = null },
|
||||||
|
focused = { background = Texture2D.whiteTexture, textColor = Color.black },
|
||||||
|
active = { background = Texture2D.whiteTexture, textColor = Color.black },
|
||||||
|
alignment = TextAnchor.MiddleLeft,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private class VoidType
|
||||||
|
{
|
||||||
|
public static readonly VoidType Value = new VoidType();
|
||||||
|
private VoidType() { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
145
src/UI/Main/OptionsPage.cs
Normal file
145
src/UI/Main/OptionsPage.cs
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
using Explorer.Config;
|
||||||
|
using Explorer.CacheObject;
|
||||||
|
|
||||||
|
namespace Explorer.UI.Main
|
||||||
|
{
|
||||||
|
public class OptionsPage : BaseMainMenuPage
|
||||||
|
{
|
||||||
|
public override string Name => "Options";
|
||||||
|
|
||||||
|
public string toggleKeyInputString = "";
|
||||||
|
public Vector2 defaultSizeInputVector;
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
toggleKeyInputString = ModConfig.Instance.Main_Menu_Toggle.ToString();
|
||||||
|
toggleKeyInput = CacheFactory.GetCacheObject(typeof(OptionsPage).GetField("toggleKeyInputString"), this);
|
||||||
|
|
||||||
|
defaultSizeInputVector = ModConfig.Instance.Default_Window_Size;
|
||||||
|
defaultSizeInput = CacheFactory.GetCacheObject(typeof(OptionsPage).GetField("defaultSizeInputVector"), this);
|
||||||
|
|
||||||
|
defaultPageLimit = ModConfig.Instance.Default_Page_Limit;
|
||||||
|
defaultPageLimitInput = CacheFactory.GetCacheObject(typeof(OptionsPage).GetField("defaultPageLimit"), this);
|
||||||
|
|
||||||
|
bitwiseSupport = ModConfig.Instance.Bitwise_Support;
|
||||||
|
bitwiseSupportInput = CacheFactory.GetCacheObject(typeof(OptionsPage).GetField("bitwiseSupport"), this);
|
||||||
|
|
||||||
|
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() { }
|
||||||
|
|
||||||
|
public override void DrawWindow()
|
||||||
|
{
|
||||||
|
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||||
|
GUILayout.Label("<color=orange><size=16><b>Options</b></size></color>", new GUILayoutOption[0]);
|
||||||
|
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
|
||||||
|
|
||||||
|
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, new GUILayoutOption[0]);
|
||||||
|
|
||||||
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
GUILayout.Label($"Menu Toggle Key:", new GUILayoutOption[] { GUILayout.Width(215f) });
|
||||||
|
toggleKeyInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
UIStyles.HorizontalLine(Color.black, true);
|
||||||
|
|
||||||
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
GUILayout.Label($"Default Window Size:", new GUILayoutOption[] { GUILayout.Width(215f) });
|
||||||
|
defaultSizeInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
UIStyles.HorizontalLine(Color.black, true);
|
||||||
|
|
||||||
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
GUILayout.Label($"Default Items per Page:", new GUILayoutOption[] { GUILayout.Width(215f) });
|
||||||
|
defaultPageLimitInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
UIStyles.HorizontalLine(Color.black, true);
|
||||||
|
|
||||||
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
GUILayout.Label($"Enable Bitwise Editing:", new GUILayoutOption[] { GUILayout.Width(215f) });
|
||||||
|
bitwiseSupportInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
UIStyles.HorizontalLine(Color.black, true);
|
||||||
|
|
||||||
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
GUILayout.Label($"Enable Tab View:", new GUILayoutOption[] { GUILayout.Width(215f) });
|
||||||
|
tabViewInput.IValue.DrawValue(MainMenu.MainRect, MainMenu.MainRect.width - 215f);
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
UIStyles.HorizontalLine(Color.black, true);
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
|
||||||
|
GUIUnstrip.Space(10f);
|
||||||
|
|
||||||
|
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||||
|
GUILayout.Label("<color=orange><size=16><b>Other</b></size></color>", new GUILayoutOption[0]);
|
||||||
|
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
|
||||||
|
|
||||||
|
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, new GUILayoutOption[0]);
|
||||||
|
|
||||||
|
if (GUILayout.Button("Inspect Test Class", new GUILayoutOption[0]))
|
||||||
|
{
|
||||||
|
WindowManager.InspectObject(Tests.TestClass.Instance, out bool _);
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyAndSave()
|
||||||
|
{
|
||||||
|
if (Enum.Parse(typeof(KeyCode), toggleKeyInputString) is KeyCode key)
|
||||||
|
{
|
||||||
|
ModConfig.Instance.Main_Menu_Toggle = key;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ExplorerCore.LogWarning($"Could not parse '{toggleKeyInputString}' to KeyCode!");
|
||||||
|
}
|
||||||
|
|
||||||
|
ModConfig.Instance.Default_Window_Size = defaultSizeInputVector;
|
||||||
|
ModConfig.Instance.Default_Page_Limit = defaultPageLimit;
|
||||||
|
ModConfig.Instance.Bitwise_Support = bitwiseSupport;
|
||||||
|
|
||||||
|
ModConfig.Instance.Tab_View = tabView;
|
||||||
|
WindowManager.TabView = tabView;
|
||||||
|
|
||||||
|
ModConfig.SaveSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,14 +3,16 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
using Explorer.CacheObject;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI.Main
|
||||||
{
|
{
|
||||||
public class ScenePage : WindowPage
|
public class ScenePage : BaseMainMenuPage
|
||||||
{
|
{
|
||||||
public static ScenePage Instance;
|
public static ScenePage Instance;
|
||||||
|
|
||||||
public override string Name { get => "Scene Explorer"; }
|
public override string Name { get => "Scenes"; }
|
||||||
|
|
||||||
public PageHelper Pages = new PageHelper();
|
public PageHelper Pages = new PageHelper();
|
||||||
|
|
||||||
@ -23,12 +25,12 @@ namespace Explorer
|
|||||||
|
|
||||||
// gameobject list
|
// gameobject list
|
||||||
private Transform m_currentTransform;
|
private Transform m_currentTransform;
|
||||||
private readonly List<GameObjectCache> m_objectList = new List<GameObjectCache>();
|
private readonly List<CacheObjectBase> m_objectList = new List<CacheObjectBase>();
|
||||||
|
|
||||||
// search bar
|
// search bar
|
||||||
private bool m_searching = false;
|
private bool m_searching = false;
|
||||||
private string m_searchInput = "";
|
private string m_searchInput = "";
|
||||||
private List<GameObjectCache> m_searchResults = new List<GameObjectCache>();
|
private List<CacheObjectBase> m_searchResults = new List<CacheObjectBase>();
|
||||||
|
|
||||||
public override void Init()
|
public override void Init()
|
||||||
{
|
{
|
||||||
@ -80,9 +82,9 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<GameObjectCache> SearchSceneObjects(string _search)
|
public List<CacheObjectBase> SearchSceneObjects(string _search)
|
||||||
{
|
{
|
||||||
var matches = new List<GameObjectCache>();
|
var matches = new List<CacheObjectBase>();
|
||||||
|
|
||||||
foreach (var obj in Resources.FindObjectsOfTypeAll(ReflectionHelpers.GameObjectType))
|
foreach (var obj in Resources.FindObjectsOfTypeAll(ReflectionHelpers.GameObjectType))
|
||||||
{
|
{
|
||||||
@ -93,7 +95,7 @@ namespace Explorer
|
|||||||
#endif
|
#endif
|
||||||
if (go.name.ToLower().Contains(_search.ToLower()) && go.scene.name == m_currentScene)
|
if (go.name.ToLower().Contains(_search.ToLower()) && go.scene.name == m_currentScene)
|
||||||
{
|
{
|
||||||
matches.Add(new GameObjectCache(go));
|
matches.Add(CacheFactory.GetCacheObject(go));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +174,7 @@ namespace Explorer
|
|||||||
for (int i = offset; i < offset + Pages.ItemsPerPage && i < Pages.ItemCount; i++)
|
for (int i = offset; i < offset + Pages.ItemsPerPage && i < Pages.ItemCount; i++)
|
||||||
{
|
{
|
||||||
var child = allTransforms[i];
|
var child = allTransforms[i];
|
||||||
m_objectList.Add(new GameObjectCache(child.gameObject));
|
m_objectList.Add(CacheFactory.GetCacheObject(child));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,8 +201,8 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
ExplorerCore.Log("Exception getting root scene objects (manual): "
|
ExplorerCore.Log("Exception getting root scene objects (manual): "
|
||||||
+ e.GetType() + ", " + e.Message + "\r\n"
|
+ e.GetType() + ", " + e.Message + "\r\n"
|
||||||
+ e.StackTrace);
|
+ e.StackTrace);
|
||||||
return new Transform[0];
|
return new Transform[0];
|
||||||
}
|
}
|
||||||
@ -214,7 +216,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
DrawHeaderArea();
|
DrawHeaderArea();
|
||||||
|
|
||||||
GUILayout.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||||
|
|
||||||
DrawPageButtons();
|
DrawPageButtons();
|
||||||
|
|
||||||
@ -240,7 +242,7 @@ namespace Explorer
|
|||||||
|
|
||||||
private void DrawHeaderArea()
|
private void DrawHeaderArea()
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
// Current Scene label
|
// Current Scene label
|
||||||
GUILayout.Label("Current Scene:", new GUILayoutOption[] { GUILayout.Width(120) });
|
GUILayout.Label("Current Scene:", new GUILayoutOption[] { GUILayout.Width(120) });
|
||||||
@ -250,7 +252,7 @@ namespace Explorer
|
|||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
// ----- GameObject Search -----
|
// ----- GameObject Search -----
|
||||||
GUILayout.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
|
GUIUnstrip.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
|
||||||
GUILayout.Label("<b>Search Scene:</b>", new GUILayoutOption[] { GUILayout.Width(100) });
|
GUILayout.Label("<b>Search Scene:</b>", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||||
|
|
||||||
m_searchInput = GUIUnstrip.TextField(m_searchInput, new GUILayoutOption[0]);
|
m_searchInput = GUIUnstrip.TextField(m_searchInput, new GUILayoutOption[0]);
|
||||||
@ -305,7 +307,7 @@ namespace Explorer
|
|||||||
|
|
||||||
private void DrawPageButtons()
|
private void DrawPageButtons()
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
Pages.DrawLimitInputArea();
|
Pages.DrawLimitInputArea();
|
||||||
|
|
||||||
@ -336,7 +338,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (m_currentTransform != null)
|
if (m_currentTransform != null)
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
if (GUILayout.Button("<-", new GUILayoutOption[] { GUILayout.Width(35) }))
|
if (GUILayout.Button("<-", new GUILayoutOption[] { GUILayout.Width(35) }))
|
||||||
{
|
{
|
||||||
TraverseUp();
|
TraverseUp();
|
||||||
@ -347,8 +349,8 @@ namespace Explorer
|
|||||||
new GUILayoutOption[] { GUILayout.Width(MainMenu.MainRect.width - 187f) });
|
new GUILayoutOption[] { GUILayout.Width(MainMenu.MainRect.width - 187f) });
|
||||||
}
|
}
|
||||||
|
|
||||||
UIHelpers.SmallInspectButton(m_currentTransform);
|
Buttons.InspectButton(m_currentTransform);
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -372,28 +374,28 @@ namespace Explorer
|
|||||||
|
|
||||||
if (obj == null) continue;
|
if (obj == null) continue;
|
||||||
|
|
||||||
if (!obj.RefGameObject)
|
try
|
||||||
{
|
{
|
||||||
string label = "<color=red><i>null";
|
var go = obj.IValue.Value as GameObject ?? (obj.IValue.Value as Transform)?.gameObject;
|
||||||
|
|
||||||
if (obj.RefGameObject != null)
|
if (!go)
|
||||||
{
|
{
|
||||||
label += " (Destroyed)";
|
string label = "<color=red><i>null";
|
||||||
}
|
|
||||||
|
|
||||||
label += "</i></color>";
|
if (go != null)
|
||||||
GUILayout.Label(label, new GUILayoutOption[0]);
|
{
|
||||||
}
|
label += " (Destroyed)";
|
||||||
else
|
}
|
||||||
{
|
|
||||||
UIHelpers.GOButton_Impl(obj.RefGameObject,
|
label += "</i></color>";
|
||||||
obj.EnabledColor,
|
GUILayout.Label(label, new GUILayoutOption[0]);
|
||||||
obj.Label,
|
}
|
||||||
obj.RefGameObject.activeSelf,
|
else
|
||||||
SetTransformTarget,
|
{
|
||||||
true,
|
Buttons.GameObjectButton(go, SetTransformTarget, true, MainMenu.MainRect.width - 170f);
|
||||||
MainMenu.MainRect.width - 170);
|
}
|
||||||
}
|
}
|
||||||
|
catch { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -413,17 +415,11 @@ namespace Explorer
|
|||||||
|
|
||||||
for (int i = offset; i < offset + Pages.ItemsPerPage && i < m_searchResults.Count; i++)
|
for (int i = offset; i < offset + Pages.ItemsPerPage && i < m_searchResults.Count; i++)
|
||||||
{
|
{
|
||||||
var obj = m_searchResults[i];
|
var obj = m_searchResults[i].IValue.Value as GameObject;
|
||||||
|
|
||||||
if (obj.RefGameObject)
|
if (obj)
|
||||||
{
|
{
|
||||||
UIHelpers.GOButton_Impl(obj.RefGameObject,
|
Buttons.GameObjectButton(obj, SetTransformTarget, true, MainMenu.MainRect.width - 170);
|
||||||
obj.EnabledColor,
|
|
||||||
obj.Label,
|
|
||||||
obj.RefGameObject.activeSelf,
|
|
||||||
SetTransformTarget,
|
|
||||||
true,
|
|
||||||
MainMenu.MainRect.width - 170);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -436,42 +432,5 @@ namespace Explorer
|
|||||||
GUILayout.Label("<color=red><i>No results found!</i></color>", new GUILayoutOption[0]);
|
GUILayout.Label("<color=red><i>No results found!</i></color>", new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------- Mini GameObjectCache class ---------- //
|
|
||||||
|
|
||||||
public class GameObjectCache
|
|
||||||
{
|
|
||||||
public GameObject RefGameObject;
|
|
||||||
public string Label;
|
|
||||||
public Color EnabledColor;
|
|
||||||
public int ChildCount;
|
|
||||||
|
|
||||||
public GameObjectCache(GameObject obj)
|
|
||||||
{
|
|
||||||
RefGameObject = obj;
|
|
||||||
ChildCount = obj.transform.childCount;
|
|
||||||
|
|
||||||
Label = (ChildCount > 0) ? "[" + obj.transform.childCount + " children] " : "";
|
|
||||||
Label += obj.name;
|
|
||||||
|
|
||||||
bool enabled = obj.activeSelf;
|
|
||||||
int childCount = obj.transform.childCount;
|
|
||||||
if (enabled)
|
|
||||||
{
|
|
||||||
if (childCount > 0)
|
|
||||||
{
|
|
||||||
EnabledColor = Color.green;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EnabledColor = UIStyles.LightGreen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EnabledColor = Color.red;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,14 +4,16 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
using Explorer.CacheObject;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI.Main
|
||||||
{
|
{
|
||||||
public class SearchPage : WindowPage
|
public class SearchPage : BaseMainMenuPage
|
||||||
{
|
{
|
||||||
public static SearchPage Instance;
|
public static SearchPage Instance;
|
||||||
|
|
||||||
public override string Name { get => "Object Search"; }
|
public override string Name { get => "Search"; }
|
||||||
|
|
||||||
private string m_searchInput = "";
|
private string m_searchInput = "";
|
||||||
private string m_typeInput = "";
|
private string m_typeInput = "";
|
||||||
@ -41,7 +43,7 @@ namespace Explorer
|
|||||||
Custom
|
Custom
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Init()
|
public override void Init()
|
||||||
{
|
{
|
||||||
Instance = this;
|
Instance = this;
|
||||||
}
|
}
|
||||||
@ -52,11 +54,9 @@ namespace Explorer
|
|||||||
Pages.PageOffset = 0;
|
Pages.PageOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
public override void Update() { }
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CacheResults(IEnumerable results)
|
private void CacheResults(IEnumerable results, bool isStaticClasses = false)
|
||||||
{
|
{
|
||||||
m_searchResults = new List<CacheObjectBase>();
|
m_searchResults = new List<CacheObjectBase>();
|
||||||
|
|
||||||
@ -76,11 +76,12 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var cache = CacheFactory.GetTypeAndCacheObject(toCache);
|
var cache = CacheFactory.GetCacheObject(toCache);
|
||||||
|
cache.IsStaticClassSearchResult = isStaticClasses;
|
||||||
m_searchResults.Add(cache);
|
m_searchResults.Add(cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pages.ItemCount = m_searchResults.Count;
|
Pages.ItemCount = m_searchResults.Count;
|
||||||
Pages.PageOffset = 0;
|
Pages.PageOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,12 +90,15 @@ namespace Explorer
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// helpers
|
// helpers
|
||||||
GUILayout.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
|
GUIUnstrip.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
|
||||||
GUILayout.Label("<b><color=orange>Helpers</color></b>", new GUILayoutOption[] { GUILayout.Width(70) });
|
GUILayout.Label("<b><color=orange>Helpers</color></b>", new GUILayoutOption[] { GUILayout.Width(70) });
|
||||||
if (GUILayout.Button("Find Static Instances", new GUILayoutOption[] { GUILayout.Width(180) }))
|
if (GUILayout.Button("Find Static Instances", new GUILayoutOption[] { GUILayout.Width(180) }))
|
||||||
{
|
{
|
||||||
//m_searchResults = GetInstanceClassScanner().ToList();
|
CacheResults(GetStaticInstances());
|
||||||
CacheResults(GetInstanceClassScanner());
|
}
|
||||||
|
if (GUILayout.Button("Find Static Classes", new GUILayoutOption[] { GUILayout.Width(180) }))
|
||||||
|
{
|
||||||
|
CacheResults(GetStaticClasses(), true);
|
||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
@ -102,7 +106,7 @@ namespace Explorer
|
|||||||
SearchBox();
|
SearchBox();
|
||||||
|
|
||||||
// results
|
// results
|
||||||
GUILayout.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||||
|
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||||
GUILayout.Label("<b><color=orange>Results </color></b>" + " (" + m_searchResults.Count + ")", new GUILayoutOption[0]);
|
GUILayout.Label("<b><color=orange>Results </color></b>" + " (" + m_searchResults.Count + ")", new GUILayoutOption[0]);
|
||||||
@ -110,7 +114,7 @@ namespace Explorer
|
|||||||
|
|
||||||
int count = m_searchResults.Count;
|
int count = m_searchResults.Count;
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
Pages.DrawLimitInputArea();
|
Pages.DrawLimitInputArea();
|
||||||
|
|
||||||
@ -157,29 +161,36 @@ namespace Explorer
|
|||||||
GUIUnstrip.EndScrollView();
|
GUIUnstrip.EndScrollView();
|
||||||
GUILayout.EndVertical();
|
GUILayout.EndVertical();
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
ExplorerCore.Log("Exception drawing search results!");
|
||||||
|
while (e != null)
|
||||||
|
{
|
||||||
|
ExplorerCore.Log(e);
|
||||||
|
e = e.InnerException;
|
||||||
|
}
|
||||||
|
|
||||||
m_searchResults.Clear();
|
m_searchResults.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SearchBox()
|
private void SearchBox()
|
||||||
{
|
{
|
||||||
GUILayout.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||||
|
|
||||||
// ----- GameObject Search -----
|
// ----- GameObject Search -----
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||||
GUILayout.Label("<b><color=orange>Search</color></b>", new GUILayoutOption[0]);
|
GUILayout.Label("<b><color=orange>Search</color></b>", new GUILayoutOption[0]);
|
||||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUILayout.Label("Name Contains:", new GUILayoutOption[] { GUILayout.Width(100) });
|
GUILayout.Label("Name Contains:", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||||
m_searchInput = GUIUnstrip.TextField(m_searchInput, new GUILayoutOption[] { GUILayout.Width(200) });
|
m_searchInput = GUIUnstrip.TextField(m_searchInput, new GUILayoutOption[] { GUILayout.Width(200) });
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUILayout.Label("Class Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
|
GUILayout.Label("Class Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||||
ClassFilterToggle(TypeFilter.Object, "Object");
|
ClassFilterToggle(TypeFilter.Object, "Object");
|
||||||
@ -189,16 +200,16 @@ namespace Explorer
|
|||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
if (TypeMode == TypeFilter.Custom)
|
if (TypeMode == TypeFilter.Custom)
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleRight;
|
GUI.skin.label.alignment = TextAnchor.MiddleRight;
|
||||||
GUILayout.Label("Custom Class:", new GUILayoutOption[] { GUILayout.Width(250) });
|
GUILayout.Label("Custom Class:", new GUILayoutOption[] { GUILayout.Width(250) });
|
||||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
||||||
m_typeInput = GUIUnstrip.TextField(m_typeInput, new GUILayoutOption[] { GUILayout.Width(250) });
|
m_typeInput = GUIUnstrip.TextField(m_typeInput, new GUILayoutOption[] { GUILayout.Width(250) });
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUILayout.Label("Scene Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
|
GUILayout.Label("Scene Filter:", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||||
SceneFilterToggle(SceneFilter.Any, "Any", 60);
|
SceneFilterToggle(SceneFilter.Any, "Any", 60);
|
||||||
SceneFilterToggle(SceneFilter.This, "This Scene", 100);
|
SceneFilterToggle(SceneFilter.This, "This Scene", 100);
|
||||||
SceneFilterToggle(SceneFilter.DontDestroy, "DontDestroyOnLoad", 140);
|
SceneFilterToggle(SceneFilter.DontDestroy, "DontDestroyOnLoad", 140);
|
||||||
@ -360,7 +371,7 @@ namespace Explorer
|
|||||||
#if CPP
|
#if CPP
|
||||||
if (obj is Il2CppSystem.Object ilObject)
|
if (obj is Il2CppSystem.Object ilObject)
|
||||||
{
|
{
|
||||||
go = ilObject.TryCast<GameObject>() ?? ilObject.TryCast<Component>().gameObject;
|
go = ilObject.TryCast<GameObject>() ?? ilObject.TryCast<Component>().gameObject;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (obj is GameObject || obj is Component)
|
if (obj is GameObject || obj is Component)
|
||||||
@ -395,14 +406,14 @@ namespace Explorer
|
|||||||
private static bool FilterName(string name)
|
private static bool FilterName(string name)
|
||||||
{
|
{
|
||||||
// Don't really want these instances.
|
// Don't really want these instances.
|
||||||
return !name.StartsWith("Mono")
|
return !name.StartsWith("Mono")
|
||||||
&& !name.StartsWith("System")
|
&& !name.StartsWith("System")
|
||||||
&& !name.StartsWith("Il2CppSystem")
|
&& !name.StartsWith("Il2CppSystem")
|
||||||
&& !name.StartsWith("Iced");
|
&& !name.StartsWith("Iced");
|
||||||
}
|
}
|
||||||
|
|
||||||
// credit: ManlyMarco (RuntimeUnityEditor)
|
// credit: ManlyMarco (RuntimeUnityEditor)
|
||||||
public static IEnumerable<object> GetInstanceClassScanner()
|
public static IEnumerable<object> GetStaticInstances()
|
||||||
{
|
{
|
||||||
var query = AppDomain.CurrentDomain.GetAssemblies()
|
var query = AppDomain.CurrentDomain.GetAssemblies()
|
||||||
.SelectMany(t => t.TryGetTypes())
|
.SelectMany(t => t.TryGetTypes())
|
||||||
@ -457,5 +468,41 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IEnumerable GetStaticClasses()
|
||||||
|
{
|
||||||
|
var list = new List<Type>();
|
||||||
|
|
||||||
|
var input = m_searchInput?.ToLower() ?? "";
|
||||||
|
|
||||||
|
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (var type in asm.TryGetTypes())
|
||||||
|
{
|
||||||
|
if (!type.IsAbstract || !type.IsSealed)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(input))
|
||||||
|
{
|
||||||
|
var typename = type.FullName.ToLower();
|
||||||
|
|
||||||
|
if (!typename.Contains(input))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list.Add(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,8 +3,12 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Explorer.Config;
|
||||||
|
using Explorer.UI.Main;
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
using Explorer.UI.Inspectors;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI
|
||||||
{
|
{
|
||||||
public class MainMenu
|
public class MainMenu
|
||||||
{
|
{
|
||||||
@ -17,18 +21,22 @@ namespace Explorer
|
|||||||
Pages.Add(new ScenePage());
|
Pages.Add(new ScenePage());
|
||||||
Pages.Add(new SearchPage());
|
Pages.Add(new SearchPage());
|
||||||
Pages.Add(new ConsolePage());
|
Pages.Add(new ConsolePage());
|
||||||
|
Pages.Add(new OptionsPage());
|
||||||
|
|
||||||
for (int i = 0; i < Pages.Count; i++)
|
for (int i = 0; i < Pages.Count; i++)
|
||||||
{
|
{
|
||||||
var page = Pages[i];
|
var page = Pages[i];
|
||||||
page.Init();
|
page.Init();
|
||||||
|
|
||||||
|
// If page failed to init, it will remove itself from the list. Lower the iterate counter.
|
||||||
|
if (!Pages.Contains(page)) i--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public const int MainWindowID = 5000;
|
public const int MainWindowID = 5000;
|
||||||
public static Rect MainRect = new Rect(5,5, ModConfig.Instance.Default_Window_Size.x,ModConfig.Instance.Default_Window_Size.y);
|
public static Rect MainRect = new Rect(5, 5, ModConfig.Instance.Default_Window_Size.x, ModConfig.Instance.Default_Window_Size.y);
|
||||||
|
|
||||||
public static readonly List<WindowPage> Pages = new List<WindowPage>();
|
public static readonly List<BaseMainMenuPage> Pages = new List<BaseMainMenuPage>();
|
||||||
private static int m_currentPage = 0;
|
private static int m_currentPage = 0;
|
||||||
|
|
||||||
public static void SetCurrentPage(int index)
|
public static void SetCurrentPage(int index)
|
||||||
@ -82,7 +90,7 @@ namespace Explorer
|
|||||||
|
|
||||||
private void MainHeader()
|
private void MainHeader()
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
for (int i = 0; i < Pages.Count; i++)
|
for (int i = 0; i < Pages.Count; i++)
|
||||||
{
|
{
|
||||||
if (m_currentPage == i)
|
if (m_currentPage == i)
|
||||||
@ -97,15 +105,15 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUI.color = Color.white;
|
GUI.color = Color.white;
|
||||||
InspectUnderMouse.EnableInspect = GUILayout.Toggle(InspectUnderMouse.EnableInspect, "Inspect Under Mouse (Shift + RMB)", new GUILayoutOption[0]);
|
InspectUnderMouse.EnableInspect = GUILayout.Toggle(InspectUnderMouse.EnableInspect, "Inspect Under Mouse (Shift + RMB)", new GUILayoutOption[0]);
|
||||||
|
|
||||||
bool mouseState = CursorControl.ForceUnlockMouse;
|
bool mouseState = ForceUnlockCursor.Unlock;
|
||||||
bool setMouse = GUILayout.Toggle(mouseState, "Force Unlock Mouse (Left Alt)", new GUILayoutOption[0]);
|
bool setMouse = GUILayout.Toggle(mouseState, "Force Unlock Mouse (Left Alt)", new GUILayoutOption[0]);
|
||||||
if (setMouse != mouseState) CursorControl.ForceUnlockMouse = setMouse;
|
if (setMouse != mouseState) ForceUnlockCursor.Unlock = setMouse;
|
||||||
|
|
||||||
WindowManager.TabView = GUILayout.Toggle(WindowManager.TabView, "Tab View", new GUILayoutOption[0]);
|
//WindowManager.TabView = GUILayout.Toggle(WindowManager.TabView, "Tab View", new GUILayoutOption[0]);
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
//GUIUnstrip.Space(10);
|
//GUIUnstrip.Space(10);
|
@ -1,34 +1,44 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Object = UnityEngine.Object;
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI.Shared
|
||||||
{
|
{
|
||||||
public class UIHelpers
|
public class Buttons
|
||||||
{
|
{
|
||||||
// helper for "Instantiate" button on UnityEngine.Objects
|
|
||||||
public static void InstantiateButton(Object obj, float width = 100)
|
public static void InstantiateButton(Object obj, float width = 100)
|
||||||
{
|
{
|
||||||
if (GUILayout.Button("Instantiate", new GUILayoutOption[] { GUILayout.Width(width) }))
|
if (GUILayout.Button("Instantiate", new GUILayoutOption[] { GUILayout.Width(width) }))
|
||||||
{
|
{
|
||||||
var newobj = Object.Instantiate(obj);
|
var newobj = Object.Instantiate(obj);
|
||||||
|
|
||||||
WindowManager.InspectObject(newobj, out _);
|
WindowManager.InspectObject(newobj, out _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper for drawing a styled button for a GameObject or Transform
|
public static void InspectButton(object obj)
|
||||||
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;
|
if (GUILayout.Button("Inspect", new GUILayoutOption[0]))
|
||||||
|
{
|
||||||
|
WindowManager.InspectObject(obj, out bool _);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool hasChild = obj.transform.childCount > 0;
|
public static void GameObjectButton(object _obj, Action<Transform> inspectOverride = null, bool showSmallInspect = true, float width = 380)
|
||||||
|
{
|
||||||
|
var go = (_obj as GameObject) ?? (_obj as Transform).gameObject;
|
||||||
|
|
||||||
string label = hasChild ? $"[{obj.transform.childCount} children] " : "";
|
if (!go) return;
|
||||||
label += obj.name;
|
|
||||||
|
|
||||||
bool enabled = obj.activeSelf;
|
bool hasChild = go.transform.childCount > 0;
|
||||||
int childCount = obj.transform.childCount;
|
|
||||||
|
string label = hasChild ? $"[{go.transform.childCount} children] " : "";
|
||||||
|
label += go.name;
|
||||||
|
|
||||||
|
bool enabled = go.activeSelf;
|
||||||
|
int childCount = go.transform.childCount;
|
||||||
Color color;
|
Color color;
|
||||||
|
|
||||||
if (enabled)
|
if (enabled)
|
||||||
@ -47,39 +57,26 @@ namespace Explorer
|
|||||||
color = Color.red;
|
color = Color.red;
|
||||||
}
|
}
|
||||||
|
|
||||||
GOButton_Impl(_obj, color, label, obj.activeSelf, specialInspectMethod, showSmallInspectBtn, width);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (!obj)
|
|
||||||
{
|
|
||||||
GUILayout.Label("<i><color=red>null</color></i>", new GUILayoutOption[0]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------ toggle active button ------
|
// ------ toggle active button ------
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUI.skin.button.alignment = TextAnchor.UpperLeft;
|
GUI.skin.button.alignment = TextAnchor.UpperLeft;
|
||||||
|
|
||||||
GUI.color = activeColor;
|
GUI.color = color;
|
||||||
|
|
||||||
enabled = GUILayout.Toggle(enabled, "", new GUILayoutOption[] { GUILayout.Width(18) });
|
enabled = GUILayout.Toggle(enabled, "", new GUILayoutOption[] { GUILayout.Width(18) });
|
||||||
if (obj.activeSelf != enabled)
|
if (go.activeSelf != enabled)
|
||||||
{
|
{
|
||||||
obj.SetActive(enabled);
|
go.SetActive(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------- actual button ---------
|
// ------- actual button ---------
|
||||||
|
|
||||||
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Height(22), GUILayout.Width(width) }))
|
if (GUILayout.Button(label, new GUILayoutOption[] { GUILayout.Height(22), GUILayout.Width(width) }))
|
||||||
{
|
{
|
||||||
if (specialInspectMethod != null)
|
if (inspectOverride != null)
|
||||||
{
|
{
|
||||||
specialInspectMethod(obj.transform);
|
inspectOverride(go.transform);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -92,20 +89,12 @@ namespace Explorer
|
|||||||
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
|
GUI.skin.button.alignment = TextAnchor.MiddleCenter;
|
||||||
GUI.color = Color.white;
|
GUI.color = Color.white;
|
||||||
|
|
||||||
if (showSmallInspectBtn)
|
if (showSmallInspect)
|
||||||
{
|
{
|
||||||
SmallInspectButton(_obj);
|
InspectButton(_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SmallInspectButton(object obj)
|
|
||||||
{
|
|
||||||
if (GUILayout.Button("Inspect", new GUILayoutOption[0]))
|
|
||||||
{
|
|
||||||
WindowManager.InspectObject(obj, out bool _);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,6 +3,6 @@
|
|||||||
interface IExpandHeight
|
interface IExpandHeight
|
||||||
{
|
{
|
||||||
bool IsExpanded { get; set; }
|
bool IsExpanded { get; set; }
|
||||||
float WhiteSpace { get; set; }
|
float WhiteSpace { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI.Shared
|
||||||
{
|
{
|
||||||
public enum Turn
|
public enum Turn
|
||||||
{
|
{
|
||||||
@ -21,9 +21,9 @@ namespace Explorer
|
|||||||
CalculateMaxOffset();
|
CalculateMaxOffset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private int m_itemsPerPage = 20;
|
private int m_itemsPerPage = Config.ModConfig.Instance.Default_Page_Limit;
|
||||||
|
|
||||||
public int ItemCount
|
public int ItemCount
|
||||||
{
|
{
|
||||||
get => m_count;
|
get => m_count;
|
||||||
set
|
set
|
||||||
@ -61,7 +61,7 @@ namespace Explorer
|
|||||||
{
|
{
|
||||||
if (direction == Turn.Left)
|
if (direction == Turn.Left)
|
||||||
{
|
{
|
||||||
if (PageOffset > 0)
|
if (PageOffset > 0)
|
||||||
{
|
{
|
||||||
PageOffset--;
|
PageOffset--;
|
||||||
scroll = Vector2.zero;
|
scroll = Vector2.zero;
|
@ -4,57 +4,64 @@ using UnhollowerBaseLib;
|
|||||||
#endif
|
#endif
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI.Shared
|
||||||
{
|
{
|
||||||
public class ResizeDrag
|
public class ResizeDrag
|
||||||
{
|
{
|
||||||
#if CPP
|
|
||||||
private static bool RESIZE_FAILED = false;
|
private static bool RESIZE_FAILED = false;
|
||||||
#endif
|
|
||||||
|
public static bool IsResizing = false;
|
||||||
|
public static bool IsMouseInResizeArea = false;
|
||||||
|
|
||||||
private static readonly GUIContent gcDrag = new GUIContent("<-- Drag to resize -->");
|
private static readonly GUIContent gcDrag = new GUIContent("<-- Drag to resize -->");
|
||||||
private static bool isResizing = false;
|
|
||||||
private static Rect m_currentResize;
|
private static Rect m_currentResize;
|
||||||
private static int m_currentWindow;
|
private static int m_currentWindow;
|
||||||
|
|
||||||
public static Rect ResizeWindow(Rect _rect, int ID)
|
public static Rect ResizeWindow(Rect _rect, int ID)
|
||||||
{
|
{
|
||||||
#if CPP
|
|
||||||
if (!RESIZE_FAILED)
|
if (!RESIZE_FAILED)
|
||||||
{
|
{
|
||||||
var origRect = _rect;
|
var origRect = _rect;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
|
GUIUnstrip.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
|
||||||
|
|
||||||
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
|
||||||
#if ML
|
#if BIE
|
||||||
GUILayout.Button(gcDrag, GUI.skin.label, new GUILayoutOption[] { GUILayout.Height(15) });
|
#if CPP // Temporary for BepInEx IL2CPP
|
||||||
|
GUILayout.Button("<-- Drag to resize -->", new GUILayoutOption[] { GUILayout.Height(15) });
|
||||||
#else
|
#else
|
||||||
GUILayout.Button(gcDrag.ToString(), new GUILayoutOption[] { GUILayout.Height(15) });
|
GUILayout.Button(gcDrag, GUI.skin.label, new GUILayoutOption[] { GUILayout.Height(15) });
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
GUILayout.Button(gcDrag, GUI.skin.label, new GUILayoutOption[] { GUILayout.Height(15) });
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//var r = GUILayoutUtility.GetLastRect();
|
var resizeDragArea = GUIUnstrip.GetLastRect();
|
||||||
var r = Internal_LayoutUtility.GetLastRect();
|
var mousePos = InputManager.MousePosition;
|
||||||
|
|
||||||
var mousePos = InputHelper.mousePosition;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var mouse = GUIUnstrip.ScreenToGUIPoint(new Vector2(mousePos.x, Screen.height - mousePos.y));
|
var mouse = GUIUnstrip.ScreenToGUIPoint(new Vector2(mousePos.x, Screen.height - mousePos.y));
|
||||||
if (r.Contains(mouse) && InputHelper.GetMouseButtonDown(0))
|
if (resizeDragArea.Contains(mouse))
|
||||||
{
|
{
|
||||||
isResizing = true;
|
IsMouseInResizeArea = true;
|
||||||
m_currentWindow = ID;
|
|
||||||
m_currentResize = new Rect(mouse.x, mouse.y, _rect.width, _rect.height);
|
if (InputManager.GetMouseButton(0))
|
||||||
|
{
|
||||||
|
IsResizing = true;
|
||||||
|
m_currentWindow = ID;
|
||||||
|
m_currentResize = new Rect(mouse.x, mouse.y, _rect.width, _rect.height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!InputHelper.GetMouseButton(0))
|
else if (!InputManager.GetMouseButton(0))
|
||||||
{
|
{
|
||||||
isResizing = false;
|
IsMouseInResizeArea = false;
|
||||||
|
IsResizing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isResizing && ID == m_currentWindow)
|
if (IsResizing && ID == m_currentWindow)
|
||||||
{
|
{
|
||||||
_rect.width = Mathf.Max(100, m_currentResize.width + (mouse.x - m_currentResize.x));
|
_rect.width = Mathf.Max(100, m_currentResize.width + (mouse.x - m_currentResize.x));
|
||||||
_rect.height = Mathf.Max(100, m_currentResize.height + (mouse.y - m_currentResize.y));
|
_rect.height = Mathf.Max(100, m_currentResize.height + (mouse.y - m_currentResize.y));
|
||||||
@ -62,7 +69,7 @@ namespace Explorer
|
|||||||
_rect.yMax = Mathf.Min(Screen.height, _rect.yMax); // modifying yMax affects height, not y
|
_rect.yMax = Mathf.Min(Screen.height, _rect.yMax); // modifying yMax affects height, not y
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
// throw safe Managed exception
|
// throw safe Managed exception
|
||||||
throw new Exception("");
|
throw new Exception("");
|
||||||
@ -82,12 +89,10 @@ namespace Explorer
|
|||||||
//ExplorerCore.Log(e.StackTrace);
|
//ExplorerCore.Log(e.StackTrace);
|
||||||
return origRect;
|
return origRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
|
|
||||||
GUILayout.Label("Resize window:", new GUILayoutOption[] { GUILayout.Width(100) });
|
GUILayout.Label("Resize window:", new GUILayoutOption[] { GUILayout.Width(100) });
|
||||||
|
|
||||||
@ -112,44 +117,9 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUI.skin.label.alignment = TextAnchor.UpperLeft;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // mono
|
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
|
||||||
|
|
||||||
GUILayout.BeginHorizontal(GUIContent.none, GUI.skin.box, null);
|
|
||||||
|
|
||||||
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 mousePos = InputHelper.mousePosition;
|
|
||||||
|
|
||||||
var mouse = GUIUnstrip.ScreenToGUIPoint(new Vector2(mousePos.x, Screen.height - mousePos.y));
|
|
||||||
if (r.Contains(mouse) && InputHelper.GetMouseButtonDown(0))
|
|
||||||
{
|
|
||||||
isResizing = true;
|
|
||||||
m_currentWindow = ID;
|
|
||||||
m_currentResize = new Rect(mouse.x, mouse.y, _rect.width, _rect.height);
|
|
||||||
}
|
|
||||||
else if (!InputHelper.GetMouseButton(0))
|
|
||||||
{
|
|
||||||
isResizing = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isResizing && ID == m_currentWindow)
|
|
||||||
{
|
|
||||||
_rect.width = Mathf.Max(100, m_currentResize.width + (mouse.x - m_currentResize.x));
|
|
||||||
_rect.height = Mathf.Max(100, m_currentResize.height + (mouse.y - m_currentResize.y));
|
|
||||||
_rect.xMax = Mathf.Min(Screen.width, _rect.xMax); // modifying xMax affects width, not x
|
|
||||||
_rect.yMax = Mathf.Min(Screen.height, _rect.yMax); // modifying yMax affects height, not y
|
|
||||||
}
|
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return _rect;
|
return _rect;
|
||||||
}
|
}
|
26
src/UI/Shared/Syntax.cs
Normal file
26
src/UI/Shared/Syntax.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Explorer.UI.Shared
|
||||||
|
{
|
||||||
|
public class Syntax
|
||||||
|
{
|
||||||
|
public const string Field_Static = "#8d8dc6";
|
||||||
|
public const string Field_Instance = "#c266ff";
|
||||||
|
|
||||||
|
public const string Method_Static = "#b55b02";
|
||||||
|
public const string Method_Instance = "#ff8000";
|
||||||
|
|
||||||
|
public const string Prop_Static = "#588075";
|
||||||
|
public const string Prop_Instance = "#55a38e";
|
||||||
|
|
||||||
|
public const string Class_Static = "#3a8d71";
|
||||||
|
public const string Class_Instance = "#2df7b2";
|
||||||
|
|
||||||
|
public const string Local = "#a6e9e9";
|
||||||
|
|
||||||
|
public const string StructGreen = "#92c470";
|
||||||
|
}
|
||||||
|
}
|
@ -1,29 +1,10 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Object = UnityEngine.Object;
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI.Shared
|
||||||
{
|
{
|
||||||
public class UIStyles
|
public class UIStyles
|
||||||
{
|
{
|
||||||
public class Syntax
|
|
||||||
{
|
|
||||||
public const string Field_Static = "#8d8dc6";
|
|
||||||
public const string Field_Instance = "#c266ff";
|
|
||||||
|
|
||||||
public const string Method_Static = "#b55b02";
|
|
||||||
public const string Method_Instance = "#ff8000";
|
|
||||||
|
|
||||||
public const string Prop_Static = "#588075";
|
|
||||||
public const string Prop_Instance = "#55a38e";
|
|
||||||
|
|
||||||
public const string Class_Static = "#3a8d71";
|
|
||||||
public const string Class_Instance = "#2df7b2";
|
|
||||||
|
|
||||||
public const string Local = "#a6e9e9";
|
|
||||||
|
|
||||||
public const string StructGreen = "#92c470";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Color LightGreen = new Color(Color.green.r - 0.3f, Color.green.g - 0.3f, Color.green.b - 0.3f);
|
public static Color LightGreen = new Color(Color.green.r - 0.3f, Color.green.g - 0.3f, Color.green.b - 0.3f);
|
||||||
|
|
||||||
public static GUISkin WindowSkin
|
public static GUISkin WindowSkin
|
@ -1,15 +1,17 @@
|
|||||||
using UnityEngine;
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
using Explorer.UI.Shared;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI
|
||||||
{
|
{
|
||||||
public class TabViewWindow : UIWindow
|
public class TabViewWindow : WindowBase
|
||||||
{
|
{
|
||||||
public override string Title => $"Tabs ({WindowManager.Windows.Count})";
|
public override string Title => $"Tabs ({WindowManager.Windows.Count})";
|
||||||
|
|
||||||
public static TabViewWindow Instance => m_instance ?? (m_instance = new TabViewWindow());
|
public static TabViewWindow Instance => m_instance ?? (m_instance = new TabViewWindow());
|
||||||
private static TabViewWindow m_instance;
|
private static TabViewWindow m_instance;
|
||||||
|
|
||||||
private UIWindow m_targetWindow;
|
private WindowBase m_targetWindow;
|
||||||
public int TargetTabID = 0;
|
public int TargetTabID = 0;
|
||||||
|
|
||||||
public override bool IsTabViewWindow => true;
|
public override bool IsTabViewWindow => true;
|
||||||
@ -21,7 +23,7 @@ namespace Explorer
|
|||||||
|
|
||||||
public override void Init() { }
|
public override void Init() { }
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
while (TargetTabID >= WindowManager.Windows.Count)
|
while (TargetTabID >= WindowManager.Windows.Count)
|
||||||
{
|
{
|
||||||
@ -35,7 +37,7 @@ namespace Explorer
|
|||||||
|
|
||||||
if (TargetTabID >= 0)
|
if (TargetTabID >= 0)
|
||||||
{
|
{
|
||||||
m_targetWindow = WindowManager.Windows[TargetTabID];
|
m_targetWindow = WindowManager.Windows[TargetTabID];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -61,18 +63,27 @@ namespace Explorer
|
|||||||
|
|
||||||
GUIUnstrip.BeginArea(new Rect(5, 25, m_rect.width - 10, m_rect.height - 35), GUI.skin.box);
|
GUIUnstrip.BeginArea(new Rect(5, 25, m_rect.width - 10, m_rect.height - 35), GUI.skin.box);
|
||||||
|
|
||||||
GUILayout.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
GUIUnstrip.BeginVertical(GUIContent.none, GUI.skin.box, null);
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
GUI.skin.button.alignment = TextAnchor.MiddleLeft;
|
||||||
int tabPerRow = Mathf.FloorToInt((float)((decimal)m_rect.width / 238));
|
int tabPerRow = Mathf.FloorToInt((float)((decimal)m_rect.width / 238));
|
||||||
int rowCount = 0;
|
int rowCount = 0;
|
||||||
for (int i = 0; i < WindowManager.Windows.Count; i++)
|
for (int i = 0; i < WindowManager.Windows.Count; i++)
|
||||||
{
|
{
|
||||||
|
var window = WindowManager.Windows[i];
|
||||||
|
|
||||||
|
// Prevent trying to draw destroyed UnityEngine.Objects
|
||||||
|
// before the WindowManager removes them.
|
||||||
|
if (window.Target is UnityEngine.Object uObj && !uObj)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (rowCount >= tabPerRow)
|
if (rowCount >= tabPerRow)
|
||||||
{
|
{
|
||||||
rowCount = 0;
|
rowCount = 0;
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.BeginHorizontal(new GUILayoutOption[0]);
|
GUIUnstrip.BeginHorizontal(new GUILayoutOption[0]);
|
||||||
}
|
}
|
||||||
rowCount++;
|
rowCount++;
|
||||||
|
|
||||||
@ -80,7 +91,6 @@ namespace Explorer
|
|||||||
string color = focused ? "<color=lime>" : "<color=orange>";
|
string color = focused ? "<color=lime>" : "<color=orange>";
|
||||||
GUI.color = focused ? Color.green : Color.white;
|
GUI.color = focused ? Color.green : Color.white;
|
||||||
|
|
||||||
var window = WindowManager.Windows[i];
|
|
||||||
if (GUILayout.Button(color + window.Title + "</color>", new GUILayoutOption[] { GUILayout.Width(200) }))
|
if (GUILayout.Button(color + window.Title + "</color>", new GUILayoutOption[] { GUILayout.Width(200) }))
|
||||||
{
|
{
|
||||||
TargetTabID = i;
|
TargetTabID = i;
|
||||||
@ -97,15 +107,18 @@ namespace Explorer
|
|||||||
|
|
||||||
m_targetWindow.WindowFunction(m_targetWindow.windowID);
|
m_targetWindow.WindowFunction(m_targetWindow.windowID);
|
||||||
|
|
||||||
try
|
m_rect = ResizeDrag.ResizeWindow(m_rect, windowID);
|
||||||
{
|
|
||||||
m_rect = ResizeDrag.ResizeWindow(m_rect, windowID);
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
|
|
||||||
GUIUnstrip.EndArea();
|
GUIUnstrip.EndArea();
|
||||||
}
|
}
|
||||||
catch { }
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
if (!e.Message.Contains("in a group with only"))
|
||||||
|
{
|
||||||
|
ExplorerCore.Log("Exception drawing Tab View window: " + e.GetType() + ", " + e.Message);
|
||||||
|
ExplorerCore.Log(e.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,16 +1,18 @@
|
|||||||
using System;
|
using System;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Explorer.Config;
|
||||||
|
using Explorer.UI.Inspectors;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI
|
||||||
{
|
{
|
||||||
public abstract class UIWindow
|
public abstract class WindowBase
|
||||||
{
|
{
|
||||||
public abstract string Title { get; }
|
public abstract string Title { get; }
|
||||||
|
|
||||||
public object Target;
|
public object Target;
|
||||||
|
|
||||||
public int windowID;
|
public int windowID;
|
||||||
public Rect m_rect = new Rect(0,0, ModConfig.Instance.Default_Window_Size.x,ModConfig.Instance.Default_Window_Size.y);
|
public Rect m_rect = new Rect(0, 0, ModConfig.Instance.Default_Window_Size.x, ModConfig.Instance.Default_Window_Size.y);
|
||||||
|
|
||||||
public Vector2 scroll = Vector2.zero;
|
public Vector2 scroll = Vector2.zero;
|
||||||
|
|
||||||
@ -20,7 +22,7 @@ namespace Explorer
|
|||||||
public abstract void WindowFunction(int windowID);
|
public abstract void WindowFunction(int windowID);
|
||||||
public abstract void Update();
|
public abstract void Update();
|
||||||
|
|
||||||
public static UIWindow CreateWindow<T>(object target) where T : UIWindow
|
public static WindowBase CreateWindow<T>(object target) where T : WindowBase
|
||||||
{
|
{
|
||||||
var window = Activator.CreateInstance<T>();
|
var window = Activator.CreateInstance<T>();
|
||||||
|
|
||||||
@ -35,6 +37,22 @@ namespace Explorer
|
|||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static StaticInspector CreateWindowStatic(Type type)
|
||||||
|
{
|
||||||
|
var window = new StaticInspector
|
||||||
|
{
|
||||||
|
TargetType = type,
|
||||||
|
windowID = WindowManager.NextWindowID(),
|
||||||
|
m_rect = WindowManager.GetNewWindowRect()
|
||||||
|
};
|
||||||
|
|
||||||
|
WindowManager.Windows.Add(window);
|
||||||
|
|
||||||
|
window.Init();
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
public void DestroyWindow()
|
public void DestroyWindow()
|
||||||
{
|
{
|
||||||
WindowManager.DestroyWindow(this);
|
WindowManager.DestroyWindow(this);
|
@ -1,90 +1,60 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Explorer.UI.Inspectors;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.UI
|
||||||
{
|
{
|
||||||
public class WindowManager
|
public class WindowManager
|
||||||
{
|
{
|
||||||
public static WindowManager Instance;
|
public static WindowManager Instance;
|
||||||
|
|
||||||
public static bool TabView = true;
|
public static bool TabView = Config.ModConfig.Instance.Tab_View;
|
||||||
|
|
||||||
public static List<UIWindow> Windows = new List<UIWindow>();
|
public static bool IsMouseInWindow
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!ExplorerCore.ShowMenu)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var window in Windows)
|
||||||
|
{
|
||||||
|
if (RectContainsMouse(window.m_rect))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return RectContainsMouse(MainMenu.MainRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<WindowBase> Windows = new List<WindowBase>();
|
||||||
public static int CurrentWindowID { get; set; } = 500000;
|
public static int CurrentWindowID { get; set; } = 500000;
|
||||||
private static Rect m_lastWindowRect;
|
private static Rect m_lastWindowRect;
|
||||||
|
|
||||||
private static readonly List<UIWindow> m_windowsToDestroy = new List<UIWindow>();
|
private static readonly List<WindowBase> m_windowsToDestroy = new List<WindowBase>();
|
||||||
|
|
||||||
public WindowManager()
|
public WindowManager()
|
||||||
{
|
{
|
||||||
Instance = this;
|
Instance = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DestroyWindow(UIWindow window)
|
public static void DestroyWindow(WindowBase window)
|
||||||
{
|
{
|
||||||
m_windowsToDestroy.Add(window);
|
m_windowsToDestroy.Add(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update()
|
public static WindowBase InspectObject(object obj, out bool createdNew, bool forceReflection = false)
|
||||||
{
|
|
||||||
if (m_windowsToDestroy.Count > 0)
|
|
||||||
{
|
|
||||||
foreach (var window in m_windowsToDestroy)
|
|
||||||
{
|
|
||||||
if (Windows.Contains(window))
|
|
||||||
{
|
|
||||||
Windows.Remove(window);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_windowsToDestroy.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TabView)
|
|
||||||
{
|
|
||||||
TabViewWindow.Instance.Update();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int i = 0; i < Windows.Count; i++)
|
|
||||||
{
|
|
||||||
var window = Windows[i];
|
|
||||||
if (window != null)
|
|
||||||
{
|
|
||||||
window.Update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnGUI()
|
|
||||||
{
|
|
||||||
if (TabView)
|
|
||||||
{
|
|
||||||
if (Windows.Count > 0)
|
|
||||||
{
|
|
||||||
TabViewWindow.Instance.OnGUI();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var window in Windows)
|
|
||||||
{
|
|
||||||
window.OnGUI();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========= Public Helpers =========
|
|
||||||
|
|
||||||
public static UIWindow InspectObject(object obj, out bool createdNew, bool forceReflection = false)
|
|
||||||
{
|
{
|
||||||
createdNew = false;
|
createdNew = false;
|
||||||
|
|
||||||
if (InputHelper.GetKey(KeyCode.LeftShift))
|
//if (InputManager.GetKey(KeyCode.LeftShift))
|
||||||
{
|
//{
|
||||||
forceReflection = true;
|
// forceReflection = true;
|
||||||
}
|
//}
|
||||||
|
|
||||||
#if CPP
|
#if CPP
|
||||||
Il2CppSystem.Object iObj = null;
|
Il2CppSystem.Object iObj = null;
|
||||||
@ -136,7 +106,7 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void FocusWindow(UIWindow window)
|
private static void FocusWindow(WindowBase window)
|
||||||
{
|
{
|
||||||
if (!TabView)
|
if (!TabView)
|
||||||
{
|
{
|
||||||
@ -149,47 +119,33 @@ namespace Explorer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static UIWindow InspectGameObject(GameObject obj)
|
private static WindowBase InspectGameObject(GameObject obj)
|
||||||
{
|
{
|
||||||
var new_window = UIWindow.CreateWindow<GameObjectWindow>(obj);
|
var new_window = WindowBase.CreateWindow<GameObjectInspector>(obj);
|
||||||
FocusWindow(new_window);
|
FocusWindow(new_window);
|
||||||
|
|
||||||
return new_window;
|
return new_window;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static UIWindow InspectReflection(object obj)
|
private static WindowBase InspectReflection(object obj)
|
||||||
{
|
{
|
||||||
var new_window = UIWindow.CreateWindow<ReflectionWindow>(obj);
|
var new_window = WindowBase.CreateWindow<InstanceInspector>(obj);
|
||||||
FocusWindow(new_window);
|
FocusWindow(new_window);
|
||||||
|
|
||||||
return new_window;
|
return new_window;
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Misc Helpers ===
|
public static StaticInspector InspectStaticReflection(Type type)
|
||||||
|
|
||||||
public static bool IsMouseInWindow
|
|
||||||
{
|
{
|
||||||
get
|
var new_window = WindowBase.CreateWindowStatic(type);
|
||||||
{
|
FocusWindow(new_window);
|
||||||
if (!ExplorerCore.ShowMenu)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var window in Windows)
|
return new_window;
|
||||||
{
|
|
||||||
if (RectContainsMouse(window.m_rect))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return RectContainsMouse(MainMenu.MainRect);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool RectContainsMouse(Rect rect)
|
private static bool RectContainsMouse(Rect rect)
|
||||||
{
|
{
|
||||||
var mousePos = InputHelper.mousePosition;
|
var mousePos = InputManager.MousePosition;
|
||||||
return rect.Contains(new Vector2(mousePos.x, Screen.height - mousePos.y));
|
return rect.Contains(new Vector2(mousePos.x, Screen.height - mousePos.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,5 +178,57 @@ namespace Explorer
|
|||||||
|
|
||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============= instance methods ===============
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
if (m_windowsToDestroy.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var window in m_windowsToDestroy)
|
||||||
|
{
|
||||||
|
if (Windows.Contains(window))
|
||||||
|
{
|
||||||
|
Windows.Remove(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_windowsToDestroy.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TabView)
|
||||||
|
{
|
||||||
|
TabViewWindow.Instance.Update();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Windows.Count; i++)
|
||||||
|
{
|
||||||
|
var window = Windows[i];
|
||||||
|
if (window != null)
|
||||||
|
{
|
||||||
|
window.Update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnGUI()
|
||||||
|
{
|
||||||
|
if (TabView)
|
||||||
|
{
|
||||||
|
if (Windows.Count > 0)
|
||||||
|
{
|
||||||
|
TabViewWindow.Instance.OnGUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var window in Windows)
|
||||||
|
{
|
||||||
|
window.OnGUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,23 +3,61 @@ using System.Collections.Generic;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
#if CPP
|
#if CPP
|
||||||
using Explorer.UnstripInternals;
|
using Explorer.Unstrip.IMGUI;
|
||||||
using UnityEngineInternal;
|
|
||||||
using UnhollowerRuntimeLib;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer
|
||||||
{
|
{
|
||||||
public class GUIUnstrip
|
public class GUIUnstrip
|
||||||
{
|
{
|
||||||
|
public static void BeginHorizontal(params GUILayoutOption[] options)
|
||||||
|
=> BeginHorizontal(GUIContent.none, GUIStyle.none, 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)
|
||||||
|
{
|
||||||
|
#if CPP
|
||||||
|
Internal.BeginLayoutDirection(false, content, style, options);
|
||||||
|
#else
|
||||||
|
GUILayout.BeginHorizontal(content, style, options);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
public static void BeginVertical(GUIContent content, GUIStyle style, params GUILayoutOption[] options)
|
||||||
|
{
|
||||||
|
#if CPP
|
||||||
|
Internal.BeginLayoutDirection(true, content, style, options);
|
||||||
|
#else
|
||||||
|
GUILayout.BeginVertical(content, style, options);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Rect GetLastRect()
|
||||||
|
{
|
||||||
|
#if CPP
|
||||||
|
return Internal_LayoutUtility.GetLastRect();
|
||||||
|
#else
|
||||||
|
return GUILayoutUtility.GetLastRect();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
public static string TextField(string text, GUILayoutOption[] options)
|
public static string TextField(string text, GUILayoutOption[] options)
|
||||||
{
|
{
|
||||||
#if CPP
|
#if CPP
|
||||||
return Internal.TextField(text, options);
|
return Internal.TextField(text, options);
|
||||||
#else
|
#else
|
||||||
return GUIUnstrip.TextField(text, options);
|
return GUILayout.TextField(text, options);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Rect Window(int id, Rect rect, GUI.WindowFunction windowFunc, string title)
|
public static Rect Window(int id, Rect rect, GUI.WindowFunction windowFunc, string title)
|
||||||
{
|
{
|
||||||
@ -75,63 +113,50 @@ namespace Explorer
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool RepeatButton(string text, params GUILayoutOption[] options)
|
||||||
|
{
|
||||||
#if CPP
|
#if CPP
|
||||||
public static bool RepeatButton(string text, params GUILayoutOption[] options)
|
return Internal.DoRepeatButton(GUIContent.Temp(text), GUI.skin.button, options);
|
||||||
{
|
|
||||||
return Internal.DoRepeatButton(GUIContent.Temp(text), GUI.skin.button, options);
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
public static bool RepeatButton(string text, params GUILayoutOption[] args)
|
return GUILayout.RepeatButton(text, options);
|
||||||
{
|
|
||||||
return GUILayout.RepeatButton(text, args);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CPP
|
|
||||||
public static void BeginArea(Rect screenRect, GUIStyle style)
|
|
||||||
{
|
|
||||||
Internal.BeginArea(screenRect, GUIContent.none, style);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void BeginArea(Rect screenRect, GUIStyle style)
|
||||||
|
{
|
||||||
|
#if CPP
|
||||||
|
Internal.BeginArea(screenRect, GUIContent.none, style);
|
||||||
#else
|
#else
|
||||||
public static void BeginArea(Rect rect, GUIStyle skin)
|
GUILayout.BeginArea(screenRect, style);
|
||||||
{
|
|
||||||
GUILayout.BeginArea(rect, skin);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#if CPP
|
|
||||||
static public void EndArea()
|
static public void EndArea()
|
||||||
{
|
{
|
||||||
Internal.EndArea();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
public static void EndArea()
|
|
||||||
{
|
|
||||||
GUILayout.EndArea();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if CPP
|
#if CPP
|
||||||
|
Internal.EndArea();
|
||||||
|
#else
|
||||||
|
GUILayout.EndArea();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static Vector2 BeginScrollView(Vector2 scroll, params GUILayoutOption[] options)
|
public static Vector2 BeginScrollView(Vector2 scroll, params GUILayoutOption[] options)
|
||||||
{
|
{
|
||||||
|
#if CPP
|
||||||
return Internal.BeginScrollView(scroll, options);
|
return Internal.BeginScrollView(scroll, options);
|
||||||
|
#else
|
||||||
|
return GUILayout.BeginScrollView(scroll, options);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void EndScrollView(bool handleScrollWheel = true)
|
public static void EndScrollView(bool handleScrollWheel = true)
|
||||||
{
|
{
|
||||||
|
#if CPP
|
||||||
Internal.EndScrollView(handleScrollWheel);
|
Internal.EndScrollView(handleScrollWheel);
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
public static Vector2 BeginScrollView(Vector2 scroll, params GUILayoutOption[] options)
|
|
||||||
{
|
|
||||||
return GUILayout.BeginScrollView(scroll, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void EndScrollView()
|
|
||||||
{
|
|
||||||
GUILayout.EndScrollView();
|
GUILayout.EndScrollView();
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,7 +6,7 @@ using UnityEngine;
|
|||||||
using UnityEngineInternal;
|
using UnityEngineInternal;
|
||||||
using UnhollowerRuntimeLib;
|
using UnhollowerRuntimeLib;
|
||||||
|
|
||||||
namespace Explorer.UnstripInternals
|
namespace Explorer.Unstrip.IMGUI
|
||||||
{
|
{
|
||||||
public class Internal
|
public class Internal
|
||||||
{
|
{
|
||||||
@ -14,7 +14,7 @@ namespace Explorer.UnstripInternals
|
|||||||
public static int s_ScrollControlId;
|
public static int s_ScrollControlId;
|
||||||
|
|
||||||
public static bool ScrollFailed = false;
|
public static bool ScrollFailed = false;
|
||||||
public static bool ManualUnstripFailed = false;
|
public static bool ManualUnstripFailed = false;
|
||||||
|
|
||||||
public static GenericStack ScrollStack => m_scrollStack ?? GetScrollStack();
|
public static GenericStack ScrollStack => m_scrollStack ?? GetScrollStack();
|
||||||
public static PropertyInfo m_scrollViewStatesInfo;
|
public static PropertyInfo m_scrollViewStatesInfo;
|
||||||
@ -73,7 +73,7 @@ namespace Explorer.UnstripInternals
|
|||||||
|
|
||||||
if (m_stateCacheDict == null) throw new Exception();
|
if (m_stateCacheDict == null) throw new Exception();
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
m_stateCacheDict = new Dictionary<int, Il2CppSystem.Object>();
|
m_stateCacheDict = new Dictionary<int, Il2CppSystem.Object>();
|
||||||
}
|
}
|
||||||
@ -107,8 +107,18 @@ namespace Explorer.UnstripInternals
|
|||||||
|
|
||||||
#region GUILayout Methods
|
#region GUILayout Methods
|
||||||
|
|
||||||
|
public static void BeginLayoutDirection(bool vertical, GUIContent content, GUIStyle style, GUILayoutOption[] options)
|
||||||
|
{
|
||||||
|
var g = GUILayoutUtility.BeginLayoutGroup(style, options, Il2CppType.Of<GUILayoutGroup>());
|
||||||
|
g.isVertical = vertical;
|
||||||
|
if (style != GUIStyle.none || content != GUIContent.none)
|
||||||
|
GUI.Box(g.rect, content, style);
|
||||||
|
}
|
||||||
|
|
||||||
public static string TextField(string text, GUILayoutOption[] options)
|
public static string TextField(string text, GUILayoutOption[] options)
|
||||||
{
|
{
|
||||||
|
text = text ?? string.Empty;
|
||||||
|
|
||||||
int controlID = GUIUtility.GetControlID(FocusType.Keyboard);
|
int controlID = GUIUtility.GetControlID(FocusType.Keyboard);
|
||||||
GUIContent guicontent = GUIContent.Temp(text);
|
GUIContent guicontent = GUIContent.Temp(text);
|
||||||
bool flag = GUIUtility.keyboardControl != controlID;
|
bool flag = GUIUtility.keyboardControl != controlID;
|
||||||
@ -265,9 +275,9 @@ namespace Explorer.UnstripInternals
|
|||||||
GUI.EndGroup();
|
GUI.EndGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Scrolling
|
#region Scrolling
|
||||||
|
|
||||||
private static Il2CppSystem.Object GetStateObject(Il2CppSystem.Type type, int controlID)
|
private static Il2CppSystem.Object GetStateObject(Il2CppSystem.Type type, int controlID)
|
||||||
{
|
{
|
||||||
@ -412,7 +422,7 @@ namespace Explorer.UnstripInternals
|
|||||||
var scrollViewState = GetStateObject(Il2CppType.Of<ScrollViewState>(), controlID)
|
var scrollViewState = GetStateObject(Il2CppType.Of<ScrollViewState>(), controlID)
|
||||||
.TryCast<ScrollViewState>();
|
.TryCast<ScrollViewState>();
|
||||||
|
|
||||||
if (scrollViewState == null)
|
if (scrollViewState == null)
|
||||||
return scrollPosition;
|
return scrollPosition;
|
||||||
|
|
||||||
var scrollExt = Internal_ScrollViewState.FromPointer(scrollViewState.Pointer);
|
var scrollExt = Internal_ScrollViewState.FromPointer(scrollViewState.Pointer);
|
||||||
@ -650,10 +660,12 @@ namespace Explorer.UnstripInternals
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class UnstripExtensions
|
#region Extensions
|
||||||
|
|
||||||
|
public static class Extensions
|
||||||
{
|
{
|
||||||
public static Rect Unstripped_GetLast(this GUILayoutGroup group)
|
public static Rect Unstripped_GetLast(this GUILayoutGroup group)
|
||||||
{
|
{
|
||||||
@ -670,5 +682,7 @@ namespace Explorer.UnstripInternals
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@ -1,8 +1,7 @@
|
|||||||
#if CPP
|
#if CPP
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Explorer.UnstripInternals;
|
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.Unstrip.IMGUI
|
||||||
{
|
{
|
||||||
public class Internal_LayoutUtility
|
public class Internal_LayoutUtility
|
||||||
{
|
{
|
||||||
@ -86,7 +85,7 @@ namespace Explorer
|
|||||||
last = GUILayoutUtility.kDummyRect;
|
last = GUILayoutUtility.kDummyRect;
|
||||||
}
|
}
|
||||||
return last;
|
return last;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@ -3,7 +3,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.Unstrip.IMGUI
|
||||||
{
|
{
|
||||||
public class Internal_ScrollViewState
|
public class Internal_ScrollViewState
|
||||||
{
|
{
|
411
src/Unstrip/IMGUI/Internal_SliderHandler.cs
Normal file
411
src/Unstrip/IMGUI/Internal_SliderHandler.cs
Normal 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
|
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Explorer
|
namespace Explorer.Unstrip.IMGUI
|
||||||
{
|
{
|
||||||
public class Internal_SliderState
|
public class Internal_SliderState
|
||||||
{
|
{
|
51
src/Unstrip/ImageConversion/ImageConversionUnstrip.cs
Normal file
51
src/Unstrip/ImageConversion/ImageConversionUnstrip.cs
Normal 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
|
32
src/Unstrip/LayerMask/LayerMaskUnstrip.cs
Normal file
32
src/Unstrip/LayerMask/LayerMaskUnstrip.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEngine;
|
||||||
|
#if CPP
|
||||||
|
using UnhollowerBaseLib;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Explorer.Unstrip.LayerMasks
|
||||||
|
{
|
||||||
|
public static class LayerMaskUnstrip
|
||||||
|
{
|
||||||
|
#if CPP
|
||||||
|
internal delegate IntPtr d_LayerToName(int layer);
|
||||||
|
internal static d_LayerToName LayerToName_iCall =
|
||||||
|
IL2CPP.ResolveICall<d_LayerToName>("UnityEngine.LayerMask::LayerToName");
|
||||||
|
|
||||||
|
public static string LayerToName(int layer)
|
||||||
|
{
|
||||||
|
var ptr = LayerToName_iCall(layer);
|
||||||
|
|
||||||
|
return IL2CPP.Il2CppStringToManaged(ptr);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
public static string LayerToName(int layer)
|
||||||
|
{
|
||||||
|
return LayerMask.LayerToName(layer);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
39
src/Unstrip/Scene/SceneUnstrip.cs
Normal file
39
src/Unstrip/Scene/SceneUnstrip.cs
Normal 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(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
|
@ -1,413 +0,0 @@
|
|||||||
#if CPP
|
|
||||||
using System;
|
|
||||||
using UnhollowerRuntimeLib;
|
|
||||||
using UnityEngine;
|
|
||||||
using Explorer.UnstripInternals;
|
|
||||||
using Il2CppSystem.Reflection;
|
|
||||||
|
|
||||||
namespace Explorer
|
|
||||||
{
|
|
||||||
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
|
|
4
src/packages.config
Normal file
4
src/packages.config
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="ILRepack.Lib.MSBuild.Task" version="2.0.18.1" targetFramework="net472" />
|
||||||
|
</packages>
|
Reference in New Issue
Block a user