mirror of
https://github.com/originalnicodr/CinematicUnityExplorer.git
synced 2026-10-10 13:03:15 +08:00
Added misc panel with HUD toggle and screenshot support. Added more hotkeys and changed the order of panels in the navbar.
This commit is contained in:
@@ -102,6 +102,7 @@ namespace UnityExplorer
|
||||
// Continous checks and actions
|
||||
stopFrameSkip();
|
||||
maybeForcePause();
|
||||
UIManager.GetPanel<UnityExplorer.UI.Panels.Misc>(UIManager.Panels.Misc).MaybeTakeScreenshot();
|
||||
|
||||
if (InputManager.GetKeyDown(KeyCode.Pause))
|
||||
{
|
||||
@@ -116,6 +117,26 @@ namespace UnityExplorer
|
||||
frameSkip = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (InputManager.GetKeyDown(KeyCode.F12))
|
||||
{
|
||||
UIManager.GetPanel<UnityExplorer.UI.Panels.Misc>(UIManager.Panels.Misc).screenshotStatus = UnityExplorer.UI.Panels.Misc.ScreenshotState.TurnOffUI;
|
||||
}
|
||||
|
||||
if (InputManager.GetKeyDown(KeyCode.Delete))
|
||||
{
|
||||
UIManager.GetPanel<UnityExplorer.UI.Panels.Misc>(UIManager.Panels.Misc).ToggleHUDElements();
|
||||
}
|
||||
|
||||
if (InputManager.GetKeyDown(KeyCode.Insert))
|
||||
{
|
||||
FreeCamPanel.StartStopButton_OnClick();
|
||||
}
|
||||
|
||||
if (InputManager.GetKeyDown(KeyCode.Home))
|
||||
{
|
||||
FreeCamPanel.blockFreecamMovementToggle.isOn = !FreeCamPanel.blockFreecamMovementToggle.isOn;
|
||||
}
|
||||
}
|
||||
|
||||
void stopFrameSkip(){
|
||||
|
||||
@@ -311,7 +311,7 @@ namespace UnityExplorer.UI.Panels
|
||||
return row;
|
||||
}
|
||||
|
||||
void StartStopButton_OnClick()
|
||||
public static void StartStopButton_OnClick()
|
||||
{
|
||||
EventSystemHelper.SetSelectedGameObject(null);
|
||||
|
||||
@@ -342,7 +342,7 @@ namespace UnityExplorer.UI.Panels
|
||||
}
|
||||
}
|
||||
|
||||
void SetToggleButtonState()
|
||||
static void SetToggleButtonState()
|
||||
{
|
||||
if (inFreeCamMode)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
using UnityExplorer.CacheObject;
|
||||
using UnityExplorer.Inspectors;
|
||||
using UnityExplorer.ObjectExplorer;
|
||||
using UniverseLib.UI;
|
||||
using UniverseLib.UI.Models;
|
||||
using UniverseLib.UI.ObjectPool;
|
||||
#if UNHOLLOWER
|
||||
using UnhollowerRuntimeLib;
|
||||
#endif
|
||||
#if INTEROP
|
||||
using Il2CppInterop.Runtime.Injection;
|
||||
#endif
|
||||
|
||||
namespace UnityExplorer.UI.Panels
|
||||
{
|
||||
public class Misc : UEPanel
|
||||
{
|
||||
public enum ScreenshotState
|
||||
{
|
||||
DoNothing,
|
||||
TurnOffUI,
|
||||
TakeScreenshot,
|
||||
TurnOnUI,
|
||||
}
|
||||
|
||||
public class UIElement
|
||||
{
|
||||
public UIElement(object obj)
|
||||
{
|
||||
Object = obj;
|
||||
|
||||
ReflectionInspector inspector = Pool<ReflectionInspector>.Borrow();
|
||||
inspector.Target = obj.TryCast();
|
||||
Type objType = obj is Type type ? type : obj.GetActualType();
|
||||
List<CacheMember> members = CacheMemberFactory.GetCacheMembers(objType, inspector);
|
||||
|
||||
foreach (CacheMember member in members){
|
||||
if (member.NameForFiltering.EndsWith(".enabled")){
|
||||
member.Evaluate();
|
||||
Enabled = member;
|
||||
}
|
||||
|
||||
if (member.NameForFiltering.EndsWith(".name")){
|
||||
member.Evaluate();
|
||||
Name = member;
|
||||
}
|
||||
|
||||
if (Enabled != null && Name != null) break;
|
||||
}
|
||||
}
|
||||
|
||||
public object Object { get; }
|
||||
public CacheMember Enabled { get; }
|
||||
public CacheMember Name { get; }
|
||||
|
||||
public override string ToString() => $"{Object}";
|
||||
}
|
||||
|
||||
public Misc(UIBase owner) : base(owner)
|
||||
{
|
||||
captureScreenshotFunction = null;
|
||||
FindCaptureScreenshotFunction();
|
||||
superSizeValue = 2;
|
||||
hud = new List<UIElement>();
|
||||
|
||||
screenshotStatus = ScreenshotState.DoNothing;
|
||||
}
|
||||
|
||||
public override string Name => "Misc";
|
||||
public override UIManager.Panels PanelType => UIManager.Panels.Misc;
|
||||
public override int MinWidth => 275;
|
||||
public override int MinHeight => 100;
|
||||
public override Vector2 DefaultAnchorMin => new(0.4f, 0.4f);
|
||||
public override Vector2 DefaultAnchorMax => new(0.6f, 0.6f);
|
||||
public override bool NavButtonWanted => true;
|
||||
public override bool ShouldSaveActiveState => true;
|
||||
|
||||
List<UIElement> hud;
|
||||
Toggle HUDToggle;
|
||||
|
||||
CacheMethod captureScreenshotFunction;
|
||||
int superSizeValue;
|
||||
public ScreenshotState screenshotStatus;
|
||||
|
||||
private void LoadHUDElements(){
|
||||
List<object> currentResults = SearchProvider.UnityObjectSearch("", "UnityEngine.Canvas", ChildFilter.Any, SceneFilter.Any);
|
||||
if (hud.Count > 0){
|
||||
SetValueHUDElements(true);
|
||||
HUDToggle.isOn = true;
|
||||
hud.Clear();
|
||||
}
|
||||
|
||||
foreach (object obj in currentResults){
|
||||
UIElement entry = new UIElement(obj);
|
||||
// Ignore non-enabled objects and objects without a name, since those tend to be irrelevant
|
||||
if ((bool) entry.Enabled.Value && entry.Name.Value.ToString() != ""){
|
||||
hud.Add(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetValueHUDElements(bool value){
|
||||
// If its the first time changing the HUD, we look up for UI elements.
|
||||
if (hud.Count == 0){
|
||||
LoadHUDElements();
|
||||
}
|
||||
|
||||
foreach (UIElement elem in hud){
|
||||
elem.Enabled.TrySetUserValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
public void ToggleHUDElements(){
|
||||
HUDToggle.isOn = !HUDToggle.isOn;
|
||||
SetValueHUDElements(HUDToggle.isOn);
|
||||
}
|
||||
|
||||
private void TakeScreenshot(){
|
||||
MethodInfo methodInfo = captureScreenshotFunction.MethodInfo;
|
||||
string filename = DateTime.Now.ToString("yyyy-M-d HH-mm-ss");
|
||||
|
||||
ExplorerCore.LogWarning(filename);
|
||||
|
||||
string screenshotsPath = Path.Combine(ExplorerCore.ExplorerFolder, "Screenshots");
|
||||
System.IO.Directory.CreateDirectory(screenshotsPath);
|
||||
|
||||
object[] args = {$"{screenshotsPath}\\{filename}.png", superSizeValue};
|
||||
|
||||
methodInfo.Invoke(captureScreenshotFunction.DeclaringInstance, args);
|
||||
}
|
||||
|
||||
private void FindCaptureScreenshotFunction(){
|
||||
List<object> results = SearchProvider.ClassSearch("UnityEngine.ScreenCapture");
|
||||
// We assume it's the first for now. Come back if we need to do something else to get it.
|
||||
object obj = results[0];
|
||||
Type objType = obj is Type type ? type : obj.GetActualType();
|
||||
ReflectionInspector inspector = Pool<ReflectionInspector>.Borrow();
|
||||
List<CacheMember> members = CacheMemberFactory.GetCacheMembers(objType, inspector);
|
||||
foreach (CacheMember member in members){
|
||||
if (member is CacheMethod methodMember && methodMember.NameForFiltering == "ScreenCapture.CaptureScreenshot(string, int)"){
|
||||
captureScreenshotFunction = methodMember;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We use an enum to walk a series of steps in each frame, so we can take the screenshot without UnityExplorer UI.
|
||||
public void MaybeTakeScreenshot(){
|
||||
switch (screenshotStatus){
|
||||
case ScreenshotState.TurnOffUI:
|
||||
screenshotStatus = ScreenshotState.TakeScreenshot;
|
||||
UIManager.ShowMenu = false;
|
||||
break;
|
||||
case ScreenshotState.TakeScreenshot:
|
||||
TakeScreenshot();
|
||||
screenshotStatus = ScreenshotState.TurnOnUI;
|
||||
break;
|
||||
case ScreenshotState.TurnOnUI:
|
||||
screenshotStatus = ScreenshotState.DoNothing;
|
||||
UIManager.ShowMenu = true;
|
||||
break;
|
||||
case ScreenshotState.DoNothing:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ~~~~~~~~ UI construction / callbacks ~~~~~~~~
|
||||
|
||||
protected override void ConstructPanelContent()
|
||||
{
|
||||
// HUD toggle
|
||||
GameObject HUDhoriGroup = UIFactory.CreateHorizontalGroup(ContentRoot, "HUDhoriGroup", false, false, true, true, 3,
|
||||
default, new Color(1, 1, 1, 0), TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(HUDhoriGroup, minHeight: 25, flexibleWidth: 9999);
|
||||
|
||||
ButtonRef loadHUDElements = UIFactory.CreateButton(HUDhoriGroup, "HideUI", "Load HUD elements");
|
||||
UIFactory.SetLayoutElement(loadHUDElements.GameObject, minWidth: 150, minHeight: 25);
|
||||
loadHUDElements.OnClick += LoadHUDElements;
|
||||
|
||||
HUDToggle = new Toggle();
|
||||
GameObject HUDToggleObj = UIFactory.CreateToggle(HUDhoriGroup, "Toggle HUD", out HUDToggle, out Text toggleText);
|
||||
UIFactory.SetLayoutElement(HUDToggleObj, minHeight: 25);
|
||||
HUDToggle.onValueChanged.AddListener(SetValueHUDElements);
|
||||
HUDToggle.isOn = true; // we picked up only the active effects
|
||||
toggleText.text = "Toggle HUD";
|
||||
|
||||
// Screenshot function
|
||||
GameObject TakeScreenshotHoriGroup = UIFactory.CreateHorizontalGroup(ContentRoot, "Take screenshot", false, false, true, true, 3,
|
||||
default, new Color(1, 1, 1, 0), TextAnchor.MiddleLeft);
|
||||
UIFactory.SetLayoutElement(TakeScreenshotHoriGroup, minHeight: 25, flexibleWidth: 9999);
|
||||
|
||||
ButtonRef takeScreenshot = UIFactory.CreateButton(TakeScreenshotHoriGroup, "TakeScreenshot", "Take screenshot");
|
||||
UIFactory.SetLayoutElement(takeScreenshot.GameObject, minWidth: 150, minHeight: 25);
|
||||
takeScreenshot.OnClick += () => screenshotStatus = ScreenshotState.TurnOffUI;
|
||||
|
||||
AddInputField(TakeScreenshotHoriGroup, "Supersize", "Supersize:", $"{2}", SuperSize_OnEndEdit);
|
||||
}
|
||||
|
||||
GameObject AddInputField(GameObject parent, string name, string labelText, string placeHolder, Action<string> onInputEndEdit)
|
||||
{
|
||||
Text posLabel = UIFactory.CreateLabel(parent, $"{name}_Label", labelText);
|
||||
UIFactory.SetLayoutElement(posLabel.gameObject, minWidth: 75, minHeight: 25);
|
||||
|
||||
InputFieldRef inputField = UIFactory.CreateInputField(parent, $"{name}_Input", placeHolder);
|
||||
UIFactory.SetLayoutElement(inputField.GameObject, minWidth: 25, minHeight: 25);
|
||||
inputField.Component.GetOnEndEdit().AddListener(onInputEndEdit);
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
void SuperSize_OnEndEdit(string input)
|
||||
{
|
||||
if (!ParseUtility.TryParse(input, out int parsed, out Exception parseEx))
|
||||
{
|
||||
ExplorerCore.LogWarning($"Could not parse value: {parseEx.ReflectionExToString()}");
|
||||
return;
|
||||
}
|
||||
|
||||
superSizeValue = parsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-4
@@ -25,7 +25,8 @@ namespace UnityExplorer.UI
|
||||
Freecam,
|
||||
LightsManager,
|
||||
CamPaths,
|
||||
PostProcessingPanel
|
||||
PostProcessingPanel,
|
||||
Misc,
|
||||
}
|
||||
|
||||
public enum VerticalAnchor
|
||||
@@ -47,7 +48,7 @@ namespace UnityExplorer.UI
|
||||
|
||||
public static RectTransform NavBarRect;
|
||||
public static GameObject NavbarTabButtonHolder;
|
||||
private static readonly Vector2 NAVBAR_DIMENSIONS = new(1400f, 35f);
|
||||
private static readonly Vector2 NAVBAR_DIMENSIONS = new(1500f, 35f);
|
||||
|
||||
private static ButtonRef closeBtn;
|
||||
private static TimeScaleWidget timeScaleWidget;
|
||||
@@ -92,12 +93,13 @@ namespace UnityExplorer.UI
|
||||
UIPanels.Add(Panels.Inspector, new InspectorPanel(UiBase));
|
||||
UIPanels.Add(Panels.CSConsole, new CSConsolePanel(UiBase));
|
||||
UIPanels.Add(Panels.HookManager, new HookManagerPanel(UiBase));
|
||||
UIPanels.Add(Panels.Clipboard, new ClipboardPanel(UiBase));
|
||||
UIPanels.Add(Panels.ConsoleLog, new LogPanel(UiBase));
|
||||
UIPanels.Add(Panels.Freecam, new FreeCamPanel(UiBase));
|
||||
UIPanels.Add(Panels.LightsManager, new LightsManager(UiBase));
|
||||
UIPanels.Add(Panels.CamPaths, new CamPaths(UiBase));
|
||||
UIPanels.Add(Panels.PostProcessingPanel, new PostProcessingPanel(UiBase));
|
||||
UIPanels.Add(Panels.Clipboard, new ClipboardPanel(UiBase));
|
||||
UIPanels.Add(Panels.ConsoleLog, new LogPanel(UiBase));
|
||||
UIPanels.Add(Panels.Misc, new UnityExplorer.UI.Panels.Misc(UiBase));
|
||||
UIPanels.Add(Panels.Options, new OptionsPanel(UiBase));
|
||||
UIPanels.Add(Panels.UIInspectorResults, new MouseInspectorResultsPanel(UiBase));
|
||||
|
||||
|
||||
@@ -228,12 +228,13 @@ namespace UnityExplorer.CatmullRom
|
||||
|
||||
bool closedLoopFinalPoint = (closedLoop && currentPoint == splinePoints.Length - 1);
|
||||
|
||||
//Had tu add "splinePoints.Length" because C# mod doesnt work well with negative values
|
||||
// Had tu add "splinePoints.Length" because C# mod doesnt work well with negative values
|
||||
int previousPoint = closedLoop ? (currentPoint + splinePoints.Length - 1)%(splinePoints.Length) : System.Math.Max(currentPoint - 1, 0);
|
||||
int endSegmentPoint = closedLoop ? (currentPoint + 1)%(splinePoints.Length) : System.Math.Min(currentPoint + 1, splinePoints.Length - 1);
|
||||
int nextPoint = closedLoop ? (currentPoint + 2)%(splinePoints.Length) : System.Math.Min(currentPoint + 2, splinePoints.Length - 1);
|
||||
|
||||
if (d >= 1) return closedLoop ? splinePoints[0] : splinePoints[splinePoints.Length - 1]; //Ideally we should really loop over tho, maybe d % 1.
|
||||
// Ideally we should really loop over tho.
|
||||
if (d >= 1) return closedLoop ? splinePoints[0] : splinePoints[splinePoints.Length - 1];
|
||||
|
||||
p0 = splinePoints[previousPoint].position;
|
||||
r0 = CatmullRomPoint.QuaternionToVector4(splinePoints[previousPoint].rotation);
|
||||
@@ -247,7 +248,7 @@ namespace UnityExplorer.CatmullRom
|
||||
p3 = splinePoints[nextPoint].position;
|
||||
r3 = CatmullRomPoint.QuaternionToVector4(splinePoints[nextPoint].rotation);
|
||||
|
||||
//Check if we are using the shortest path on the rotation. If not, change each rotation to represent that shortest path.
|
||||
// Check if we are using the shortest path on the rotation. If not, change each rotation to represent that shortest path.
|
||||
if (Vector4.Dot(r0, r1) < 0)
|
||||
r1 = - r1;
|
||||
|
||||
@@ -277,7 +278,7 @@ namespace UnityExplorer.CatmullRom
|
||||
return new CatmullRomPoint(position, rotation, fov);
|
||||
}
|
||||
|
||||
//Implementation from: https://qroph.github.io/2018/07/30/smooth-paths-using-catmull-rom-splines.html
|
||||
// Implementation from: https://qroph.github.io/2018/07/30/smooth-paths-using-catmull-rom-splines.html
|
||||
private Vector3 CatmullRomInterpolation(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t){
|
||||
float tension = 0;
|
||||
float alpha = 0.5f;
|
||||
|
||||
Reference in New Issue
Block a user