diff --git a/src/Config/InternalConfigHandler.cs b/src/Config/InternalConfigHandler.cs index 9d79da1..6514e4c 100644 --- a/src/Config/InternalConfigHandler.cs +++ b/src/Config/InternalConfigHandler.cs @@ -48,6 +48,9 @@ namespace UnityExplorer.Config TomlDocument document = TomlParser.ParseFile(CONFIG_PATH); foreach (string key in document.Keys) { + if (!Enum.IsDefined(typeof(UIManager.Panels), key)) + continue; + UIManager.Panels panelKey = (UIManager.Panels)Enum.Parse(typeof(UIManager.Panels), key); ConfigManager.GetPanelSaveData(panelKey).Value = document.GetString(key); } diff --git a/src/UI/Panels/FreeCamPanel.cs b/src/UI/Panels/FreeCamPanel.cs new file mode 100644 index 0000000..b61f5a1 --- /dev/null +++ b/src/UI/Panels/FreeCamPanel.cs @@ -0,0 +1,263 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; +using UnityEngine.EventSystems; +using UnityEngine.UI; +using UniverseLib; +using UniverseLib.Input; +using UniverseLib.UI; +using UniverseLib.UI.Models; +using UniverseLib.Utility; + +namespace UnityExplorer.UI.Panels +{ + internal class FreeCamPanel : UEPanel + { + public FreeCamPanel(UIBase owner) : base(owner) + { + } + + public override string Name => "Freecam"; + public override UIManager.Panels PanelType => UIManager.Panels.Freecam; + + public override int MinWidth => 400; + public override int MinHeight => 300; + 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; + + bool inFreeCamMode; + Camera ourCamera; + Camera lastMainCamera; + Vector3 lastCameraMainPos; + Quaternion lastCameraMainRot; + + float desiredMoveSpeed = 10f; + Vector3 previousMousePosition; + + ButtonRef toggleButton; + InputFieldRef positionInput; + InputFieldRef moveSpeedInput; + ButtonRef inspectButton; + + void BeginFreecam() + { + inFreeCamMode = true; + + previousMousePosition = InputManager.MousePosition; + + Camera currentMain = Camera.main; + if (currentMain) + { + lastMainCamera = currentMain; + lastCameraMainPos = currentMain.transform.position; + lastCameraMainRot = currentMain.transform.rotation; + lastMainCamera.enabled = false; + } + else + lastCameraMainRot = Quaternion.identity; + + if (!ourCamera) + { + ourCamera = new GameObject("UE_Freecam").AddComponent(); + ourCamera.gameObject.tag = "MainCamera"; + GameObject.DontDestroyOnLoad(ourCamera.gameObject); + ourCamera.gameObject.hideFlags = HideFlags.HideAndDontSave; + } + + ourCamera.gameObject.SetActive(true); + ourCamera.transform.position = lastCameraMainPos; + ourCamera.transform.rotation = lastCameraMainRot; + + inspectButton.GameObject.SetActive(true); + } + + void EndFreecam() + { + inFreeCamMode = false; + + if (ourCamera) + ourCamera.gameObject.SetActive(false); + else + inspectButton.GameObject.SetActive(false); + + if (lastMainCamera) + lastMainCamera.enabled = true; + } + + void SetToggleButtonState() + { + if (inFreeCamMode) + { + RuntimeHelper.SetColorBlockAuto(toggleButton.Component, new(0.4f, 0.2f, 0.2f)); + toggleButton.ButtonText.text = "End Freecam"; + } + else + { + RuntimeHelper.SetColorBlockAuto(toggleButton.Component, new(0.2f, 0.4f, 0.2f)); + toggleButton.ButtonText.text = "Begin Freecam"; + } + } + + public override void Update() + { + if (inFreeCamMode) + { + Transform transform = ourCamera.transform; + + float moveSpeed = desiredMoveSpeed * Time.deltaTime; + + if (InputManager.GetKey(KeyCode.LeftShift) || InputManager.GetKey(KeyCode.RightShift)) + moveSpeed *= 10f; + + if (InputManager.GetKey(KeyCode.LeftArrow) || InputManager.GetKey(KeyCode.A)) + transform.position += transform.right * -1 * moveSpeed; + + if (InputManager.GetKey(KeyCode.RightArrow) || InputManager.GetKey(KeyCode.D)) + transform.position += transform.right * moveSpeed; + + if (InputManager.GetKey(KeyCode.UpArrow) || InputManager.GetKey(KeyCode.W)) + transform.position += transform.forward * moveSpeed; + + if (InputManager.GetKey(KeyCode.DownArrow) || InputManager.GetKey(KeyCode.S)) + transform.position += transform.forward * -1 * moveSpeed; + + if (InputManager.GetKey(KeyCode.Space) || InputManager.GetKey(KeyCode.PageUp)) + transform.position += transform.up * moveSpeed; + + if (InputManager.GetKey(KeyCode.LeftControl) || InputManager.GetKey(KeyCode.PageDown)) + transform.position += transform.up * -1 * moveSpeed; + + if (InputManager.GetMouseButton(1)) + { + Vector3 mouseDelta = InputManager.MousePosition - previousMousePosition; + + float newRotationX = transform.localEulerAngles.y + mouseDelta.x * 0.3f; + float newRotationY = transform.localEulerAngles.x - mouseDelta.y * 0.3f; + transform.localEulerAngles = new Vector3(newRotationY, newRotationX, 0f); + } + + UpdatePositionInput(); + + previousMousePosition = InputManager.MousePosition; + } + } + + Vector3 lastSetCameraPosition; + + void SetCameraPosition(Vector3 pos) + { + if (!ourCamera || lastSetCameraPosition == pos) + return; + + ourCamera.transform.position = pos; + lastSetCameraPosition = pos; + } + + void UpdatePositionInput() + { + if (!ourCamera) + return; + + lastSetCameraPosition = ourCamera.transform.position; + positionInput.Text = ParseUtility.ToStringForInput(lastSetCameraPosition); + } + + protected override void ConstructPanelContent() + { + toggleButton = UIFactory.CreateButton(ContentRoot, "ToggleButton", "Freecam"); + UIFactory.SetLayoutElement(toggleButton.GameObject, minWidth: 150, minHeight: 25, flexibleWidth: 9999); + toggleButton.OnClick += ToggleButton_OnClick; + SetToggleButtonState(); + + AddSpacer(5); + AddInputField("Position", "Camera Pos:", "eg. 0 0 0", out positionInput, PositionInput_OnEndEdit); + + AddSpacer(5); + AddInputField("MoveSpeed", "Move Speed:", "Default: 1", out moveSpeedInput, MoveSpeedInput_OnEndEdit); + moveSpeedInput.Text = desiredMoveSpeed.ToString(); + + string instructions = @"Controls: +- WASD/Arrows: Movement +- Space/PgUp: Move up +- LeftControl/PgDown: Move down +- Right Mouse Button: Free look +- Left Shift: Super speed"; + + AddSpacer(5); + Text instructionsText = UIFactory.CreateLabel(ContentRoot, "Instructions", instructions, TextAnchor.UpperLeft); + UIFactory.SetLayoutElement(instructionsText.gameObject, flexibleWidth: 9999, flexibleHeight: 9999); + + AddSpacer(5); + inspectButton = UIFactory.CreateButton(ContentRoot, "InspectButton", "Inspect Free Camera"); + UIFactory.SetLayoutElement(inspectButton.GameObject, flexibleWidth: 9999, minHeight: 25); + inspectButton.OnClick += () => { InspectorManager.Inspect(ourCamera); }; + inspectButton.GameObject.SetActive(false); + + AddSpacer(5); + } + + void AddSpacer(int height) + { + GameObject obj = UIFactory.CreateUIObject("Spacer", ContentRoot); + UIFactory.SetLayoutElement(obj, minHeight: height, flexibleHeight: 0); + } + + GameObject AddInputField(string name, string labelText, string placeHolder, out InputFieldRef inputField, Action onInputEndEdit) + { + GameObject row = UIFactory.CreateHorizontalGroup(ContentRoot, $"{name}_Group", false, false, true, true, 3, default, new(1, 1, 1, 0)); + + Text posLabel = UIFactory.CreateLabel(row, $"{name}_Label", labelText); + UIFactory.SetLayoutElement(posLabel.gameObject, minWidth: 100, minHeight: 25); + + inputField = UIFactory.CreateInputField(row, $"{name}_Input", placeHolder); + UIFactory.SetLayoutElement(inputField.GameObject, minWidth: 125, minHeight: 25, flexibleWidth: 9999); + inputField.Component.GetOnEndEdit().AddListener(onInputEndEdit); + + return row; + } + + void ToggleButton_OnClick() + { + InputManager.SetSelectedEventSystemGameObject(null); + + if (inFreeCamMode) + EndFreecam(); + else + BeginFreecam(); + + SetToggleButtonState(); + } + + private void PositionInput_OnEndEdit(string input) + { + InputManager.SetSelectedEventSystemGameObject(null); + + if (!ParseUtility.TryParse(input, out Vector3 parsed, out Exception parseEx)) + { + ExplorerCore.LogWarning($"Could not parse position to Vector3: {parseEx.ReflectionExToString()}"); + UpdatePositionInput(); + return; + } + + SetCameraPosition(parsed); + } + + private void MoveSpeedInput_OnEndEdit(string input) + { + InputManager.SetSelectedEventSystemGameObject(null); + + if (!ParseUtility.TryParse(input, out float parsed, out Exception parseEx)) + { + ExplorerCore.LogWarning($"Could not parse value: {parseEx.ReflectionExToString()}"); + moveSpeedInput.Text = desiredMoveSpeed.ToString(); + return; + } + + desiredMoveSpeed = parsed; + } + } +} diff --git a/src/UI/UIManager.cs b/src/UI/UIManager.cs index 190cab3..458def3 100644 --- a/src/UI/UIManager.cs +++ b/src/UI/UIManager.cs @@ -26,10 +26,11 @@ namespace UnityExplorer.UI Options, ConsoleLog, AutoCompleter, - MouseInspector, + //MouseInspector, UIInspectorResults, HookManager, - Clipboard + Clipboard, + Freecam } public enum VerticalAnchor @@ -99,11 +100,14 @@ 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.Freecam, new FreeCamPanel(UiBase)); UIPanels.Add(Panels.Clipboard, new ClipboardPanel(UiBase)); UIPanels.Add(Panels.ConsoleLog, new LogPanel(UiBase)); UIPanels.Add(Panels.Options, new OptionsPanel(UiBase)); UIPanels.Add(Panels.UIInspectorResults, new MouseInspectorResultsPanel(UiBase)); - UIPanels.Add(Panels.MouseInspector, new MouseInspector(UiBase)); + + MouseInspector.inspectorUIBase = UniversalUI.RegisterUI(MouseInspector.UIBaseGUID, null); + new MouseInspector(MouseInspector.inspectorUIBase); // Call some initialize methods Notification.Init(); @@ -285,9 +289,9 @@ namespace UnityExplorer.UI // UnityExplorer title - string titleTxt = $"{ExplorerCore.NAME} {ExplorerCore.VERSION}"; - Text title = UIFactory.CreateLabel(navbarPanel, "Title", titleTxt, TextAnchor.MiddleLeft, default, true, 17); - UIFactory.SetLayoutElement(title.gameObject, minWidth: 170, flexibleWidth: 0); + string titleTxt = $"UE {ExplorerCore.VERSION}"; + Text title = UIFactory.CreateLabel(navbarPanel, "Title", titleTxt, TextAnchor.MiddleCenter, default, true, 14); + UIFactory.SetLayoutElement(title.gameObject, minWidth: 75, flexibleWidth: 0); // panel tabs