From 7600a6bb1e3471f20602c0f82bfe6a4dfd63dfdd Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 26 Aug 2025 13:27:10 -0400 Subject: [PATCH] feat: controls for pages, better templates, color changing, clear commenting --- .../DebugOverlayPageButtonTemplate.uxml | 5 + .../DebugOverlayPageButtonTemplate.uxml.meta | 10 ++ .../Layouts/DebugOverlayPageTemplate.uxml | 3 + .../DebugOverlayPageTemplate.uxml.meta | 10 ++ .../UI/In-Game/Layouts/DebugOverlayRoot.uxml | 4 +- .../Layouts/DebugOverlayValueTemplate.uxml | 14 +- Assets/Player/Input/PlayerInputs.inputactions | 84 +++++++++ Assets/Scenes/DebugOverlay.unity | 128 +------------- .../Scripts/Core/Tools/DebugOverlayDrawer.cs | 162 +++++++++++++++--- 9 files changed, 265 insertions(+), 155 deletions(-) create mode 100644 Assets/Core/UI/In-Game/Layouts/DebugOverlayPageButtonTemplate.uxml create mode 100644 Assets/Core/UI/In-Game/Layouts/DebugOverlayPageButtonTemplate.uxml.meta create mode 100644 Assets/Core/UI/In-Game/Layouts/DebugOverlayPageTemplate.uxml create mode 100644 Assets/Core/UI/In-Game/Layouts/DebugOverlayPageTemplate.uxml.meta diff --git a/Assets/Core/UI/In-Game/Layouts/DebugOverlayPageButtonTemplate.uxml b/Assets/Core/UI/In-Game/Layouts/DebugOverlayPageButtonTemplate.uxml new file mode 100644 index 0000000..a3ac686 --- /dev/null +++ b/Assets/Core/UI/In-Game/Layouts/DebugOverlayPageButtonTemplate.uxml @@ -0,0 +1,5 @@ + + + + + diff --git a/Assets/Core/UI/In-Game/Layouts/DebugOverlayPageButtonTemplate.uxml.meta b/Assets/Core/UI/In-Game/Layouts/DebugOverlayPageButtonTemplate.uxml.meta new file mode 100644 index 0000000..26a5713 --- /dev/null +++ b/Assets/Core/UI/In-Game/Layouts/DebugOverlayPageButtonTemplate.uxml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 94d59802c4805cd44b4339b049e4ac06 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} diff --git a/Assets/Core/UI/In-Game/Layouts/DebugOverlayPageTemplate.uxml b/Assets/Core/UI/In-Game/Layouts/DebugOverlayPageTemplate.uxml new file mode 100644 index 0000000..1132041 --- /dev/null +++ b/Assets/Core/UI/In-Game/Layouts/DebugOverlayPageTemplate.uxml @@ -0,0 +1,3 @@ + + + diff --git a/Assets/Core/UI/In-Game/Layouts/DebugOverlayPageTemplate.uxml.meta b/Assets/Core/UI/In-Game/Layouts/DebugOverlayPageTemplate.uxml.meta new file mode 100644 index 0000000..00c534a --- /dev/null +++ b/Assets/Core/UI/In-Game/Layouts/DebugOverlayPageTemplate.uxml.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 5bbda06c82d8c77478a2f5e7cc4e1f38 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} diff --git a/Assets/Core/UI/In-Game/Layouts/DebugOverlayRoot.uxml b/Assets/Core/UI/In-Game/Layouts/DebugOverlayRoot.uxml index 6718e32..9d98b8d 100644 --- a/Assets/Core/UI/In-Game/Layouts/DebugOverlayRoot.uxml +++ b/Assets/Core/UI/In-Game/Layouts/DebugOverlayRoot.uxml @@ -1,3 +1,5 @@ - + + + diff --git a/Assets/Core/UI/In-Game/Layouts/DebugOverlayValueTemplate.uxml b/Assets/Core/UI/In-Game/Layouts/DebugOverlayValueTemplate.uxml index 6c94862..d208f80 100644 --- a/Assets/Core/UI/In-Game/Layouts/DebugOverlayValueTemplate.uxml +++ b/Assets/Core/UI/In-Game/Layouts/DebugOverlayValueTemplate.uxml @@ -1,10 +1,12 @@ - - - - - - + + + + + + + + diff --git a/Assets/Player/Input/PlayerInputs.inputactions b/Assets/Player/Input/PlayerInputs.inputactions index f4a6647..43d65f4 100644 --- a/Assets/Player/Input/PlayerInputs.inputactions +++ b/Assets/Player/Input/PlayerInputs.inputactions @@ -76,6 +76,24 @@ "processors": "", "interactions": "", "initialStateCheck": false + }, + { + "name": "Debug Previous Page", + "type": "Button", + "id": "a41421f9-b1f7-458a-ba3b-a944f5d51822", + "expectedControlType": "", + "processors": "", + "interactions": "", + "initialStateCheck": false + }, + { + "name": "Debug Next Page", + "type": "Button", + "id": "38dbde33-5f5e-45d3-8bd2-0e4b5514ab26", + "expectedControlType": "", + "processors": "", + "interactions": "", + "initialStateCheck": false } ], "bindings": [ @@ -221,6 +239,72 @@ "action": "Stick", "isComposite": false, "isPartOfComposite": false + }, + { + "name": "One Modifier", + "id": "c27cc4dc-9bef-427c-958c-5ce8fa9cb188", + "path": "OneModifier", + "interactions": "", + "processors": "", + "groups": "", + "action": "Debug Previous Page", + "isComposite": true, + "isPartOfComposite": false + }, + { + "name": "modifier", + "id": "2c93d991-353f-4e90-bda4-a4095009b19b", + "path": "/select", + "interactions": "", + "processors": "", + "groups": "", + "action": "Debug Previous Page", + "isComposite": false, + "isPartOfComposite": true + }, + { + "name": "binding", + "id": "de0fea7a-6ba2-46f9-92c0-a24da87da819", + "path": "/leftShoulder", + "interactions": "", + "processors": "", + "groups": "", + "action": "Debug Previous Page", + "isComposite": false, + "isPartOfComposite": true + }, + { + "name": "One Modifier", + "id": "882c75bb-101d-4f31-8e34-f5b560d6e4ad", + "path": "OneModifier", + "interactions": "", + "processors": "", + "groups": "", + "action": "Debug Next Page", + "isComposite": true, + "isPartOfComposite": false + }, + { + "name": "modifier", + "id": "d3ff805f-9408-4e6a-b723-ccb3742757ac", + "path": "/select", + "interactions": "", + "processors": "", + "groups": "", + "action": "Debug Next Page", + "isComposite": false, + "isPartOfComposite": true + }, + { + "name": "binding", + "id": "0d619c6a-35b8-4184-9206-531c20e54c57", + "path": "/rightShoulder", + "interactions": "", + "processors": "", + "groups": "", + "action": "Debug Next Page", + "isComposite": false, + "isPartOfComposite": true } ] } diff --git a/Assets/Scenes/DebugOverlay.unity b/Assets/Scenes/DebugOverlay.unity index 6c9898a..e630026 100644 --- a/Assets/Scenes/DebugOverlay.unity +++ b/Assets/Scenes/DebugOverlay.unity @@ -4172,124 +4172,6 @@ Transform: m_Children: [] m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &846582215 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 846582218} - - component: {fileID: 846582220} - - component: {fileID: 846582216} - - component: {fileID: 846582219} - m_Layer: 0 - m_Name: Network Manager - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!114 &846582216 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 846582215} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 6960e84d07fb87f47956e7a81d71c4e6, type: 3} - m_Name: - m_EditorClassIdentifier: - m_ProtocolType: 1 - m_UseWebSockets: 0 - m_UseEncryption: 0 - m_MaxPacketQueueSize: 128 - m_MaxPayloadSize: 6144 - m_HeartbeatTimeoutMS: 500 - m_ConnectTimeoutMS: 1000 - m_MaxConnectAttempts: 60 - m_DisconnectTimeoutMS: 30000 - ConnectionData: - Address: 127.0.0.1 - Port: 7777 - ServerListenAddress: 127.0.0.1 - DebugSimulator: - PacketDelayMS: 0 - PacketJitterMS: 0 - PacketDropRate: 0 ---- !u!4 &846582218 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 846582215} - serializedVersion: 2 - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 9.256327, y: -15.74262, z: 7.6148796} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 0} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &846582219 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 846582215} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 31709e0224b48e24b8e5311541392a97, type: 3} - m_Name: - m_EditorClassIdentifier: ---- !u!114 &846582220 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 846582215} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 593a2fe42fa9d37498c96f9a383b6521, type: 3} - m_Name: - m_EditorClassIdentifier: - NetworkManagerExpanded: 0 - NetworkConfig: - ProtocolVersion: 0 - NetworkTransport: {fileID: 846582216} - PlayerPrefab: {fileID: 0} - Prefabs: - NetworkPrefabsLists: - - {fileID: 11400000, guid: 935babab2affb8f4683610c7e463c3ad, type: 2} - TickRate: 30 - ClientConnectionBufferTimeout: 10 - ConnectionApproval: 0 - ConnectionData: - EnableTimeResync: 0 - TimeResyncInterval: 30 - EnsureNetworkVariableLengthSafety: 0 - EnableSceneManagement: 1 - ForceSamePrefabs: 1 - RecycleNetworkIds: 1 - NetworkIdRecycleDelay: 120 - RpcHashSize: 0 - LoadSceneTimeOut: 120 - SpawnTimeout: 10 - EnableNetworkLogs: 1 - NetworkTopology: 0 - UseCMBService: 0 - AutoSpawnPlayerPrefabClientSide: 1 - NetworkMessageMetrics: 1 - NetworkProfilingMetrics: 1 - OldPrefabList: [] - RunInBackground: 1 - LogLevel: 1 --- !u!1 &928657077 GameObject: m_ObjectHideFlags: 0 @@ -5396,11 +5278,12 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: bef2d32c8ac26b643851a4c8f18dacca, type: 3} m_Name: m_EditorClassIdentifier: - pageNamePrefix: 'Debug Page: ' - template: {fileID: 9197481963319205126, guid: 2ed11dc6647802148ba04f07e76c987f, type: 3} + valueTemplate: {fileID: 9197481963319205126, guid: 2ed11dc6647802148ba04f07e76c987f, type: 3} + pageBaseTemplate: {fileID: 9197481963319205126, guid: 5bbda06c82d8c77478a2f5e7cc4e1f38, type: 3} + pageButtonTemplate: {fileID: 9197481963319205126, guid: 94d59802c4805cd44b4339b049e4ac06, type: 3} root: {fileID: 601434327} - canvasRoot: {fileID: 601434326} - currentPage: {fileID: 0} + canvasRootGameObject: {fileID: 601434326} + pageNamePrefix: 'Debug Page: ' --- !u!4 &1229349417 Transform: m_ObjectHideFlags: 0 @@ -7357,7 +7240,6 @@ SceneRoots: m_ObjectHideFlags: 0 m_Roots: - {fileID: 13380929} - - {fileID: 846582218} - {fileID: 1164382988} - {fileID: 410087041} - {fileID: 832575519} diff --git a/Assets/Scripts/Core/Tools/DebugOverlayDrawer.cs b/Assets/Scripts/Core/Tools/DebugOverlayDrawer.cs index 2494a53..6891606 100644 --- a/Assets/Scripts/Core/Tools/DebugOverlayDrawer.cs +++ b/Assets/Scripts/Core/Tools/DebugOverlayDrawer.cs @@ -3,24 +3,36 @@ using System.Collections.Generic; using System.Linq; using Sirenix.OdinInspector; using UnityEngine; +using UnityEngine.Serialization; using UnityEngine.UIElements; +// ReSharper disable UsageOfDefaultStructEquality, to disable the warnings about IndexOf(currentPage). It's fine. namespace Reset.Core.Tools{ public class DebugOverlayDrawer : MonoBehaviour{ + + [Header("Asset References")] + [BoxGroup("References")] public VisualTreeAsset valueTemplate; + [BoxGroup("References")] public VisualTreeAsset pageBaseTemplate; + [BoxGroup("References")] public VisualTreeAsset pageButtonTemplate; + [Header("Scene References")] + [BoxGroup("References")][ShowInInspector] public UIDocument root; + [BoxGroup("References")]public GameObject canvasRootGameObject; + + [Space(10)] [ShowInInspector] public Dictionary> Pages = new(); // Page and value names + [Space(5)] [ShowInInspector] public Dictionary values = new(); // Value name and value value (lol) + [Space] public string pageNamePrefix = "Debug Page: "; - public VisualTreeAsset template; - [ShowInInspector] public UIDocument root; - public GameObject canvasRoot; - - public GameObject currentPage; - + private static float defaultLabelAlpha; + // Private variables + [ShowInInspector] + public KeyValuePair> currentPage; public enum DebugOverlayAnchor{ TopLeft, @@ -37,61 +49,161 @@ namespace Reset.Core.Tools{ Instance = this; } - + + void Start(){ + SetCurrentPageVisible(); + + Debug.Log(valueTemplate.Instantiate().resolvedStyle.backgroundColor); + + defaultLabelAlpha = valueTemplate.Instantiate().style.backgroundColor.value.a; + } + public static DebugOverlayDrawer Instance; public static void AddOnOverlay(string pageName, string sourceName, Vector3 position){ // Make sure the page exists. If it does, use it. If not, create it - GameObject thisPage = null; + GameObject thisPageObject = null; bool alreadyExisted = false; // This checks for a gameobject with the page name. Sets it if it finds it foreach (var page in Instance.Pages) { if (page.Key.name == $"{Instance.pageNamePrefix}{pageName}") { - thisPage = page.Key; + thisPageObject = page.Key; alreadyExisted = true; break; } } // Otherwise, this will make a new one and add it - if (thisPage == null) { - thisPage = new GameObject(name: $"{Instance.pageNamePrefix}{pageName}"); - Instance.Pages.Add(thisPage, new List()); - thisPage.transform.SetParent(Instance.canvasRoot.transform); - thisPage.AddComponent(); + UIDocument thisDocument = null; + + if (thisPageObject == null) { + // Create a new object + thisPageObject = new GameObject(name: $"{Instance.pageNamePrefix}{pageName}"); + + // Add it to the list of page objects and set it's transform + KeyValuePair> newPage = new(thisPageObject, new List()); + Instance.Pages.Add(newPage.Key, newPage.Value); + thisPageObject.transform.SetParent(Instance.canvasRootGameObject.transform); + + // Add a UI Document for it, give it the base template + thisDocument = thisPageObject.AddComponent(); + thisDocument.visualTreeAsset = Instance.pageBaseTemplate; + + // Then add a button/header to the main container + VisualElement newPageButton = Instance.pageButtonTemplate.Instantiate(); + Instance.root.rootVisualElement.Query("Pages").First().Add(newPageButton); + ((Label)newPageButton.Query("PageLabel").First()).text = pageName; + } else { + thisDocument = thisPageObject.GetComponent(); + } + + // If this is the only page, set it to the current page + if (Instance.Pages.Count == 1) { + Instance.currentPage = new KeyValuePair>(thisPageObject, new List()); + SetCurrentPageVisible(); } - // Warning for the page being null for whatever reason - if (thisPage == null) { + // Warning for the page being null for whatever reason by this point + if (thisPageObject == null) { Debug.LogError( $"Debug Overlay Manager never found a page named: {sourceName}. It failed to create one and aborted."); return; } // Now, iterate through this page and see if the variable is already tracked - if (alreadyExisted && Instance.Pages[thisPage].Contains(sourceName)) { + if (alreadyExisted && Instance.Pages[thisPageObject].Contains(sourceName)) { return; } // Since it doesn't exist, add it to the list of tracked variables - Instance.Pages[thisPage].Add(sourceName); + Instance.Pages[thisPageObject].Add(sourceName); // Then create a new on-screen element for this variable - VisualElement thisElement = (Instance.template.Instantiate()); - thisPage.GetComponent().rootVisualElement.Add(thisElement); - thisElement.style.alignSelf = new StyleEnum(Align.Center); - + VisualElement thisElement = (Instance.valueTemplate.Instantiate()); + thisDocument.rootVisualElement.Query("ValuesContainer").First().Add(thisElement); + // Set it's label ((Label)thisElement.Query("Label").First()).text = sourceName; - Instance.values.Add($"{pageName}/{sourceName}", (Label)thisElement.Query("Value")); - } + // Publicly accessible method to change the value public static void ChangeValue(string pageName, string sourceName, string newValue){ Instance.values[$"{pageName}/{sourceName}"].text = newValue; - } + } + + // Publicly accessible method to change the color + public static void ChangeColor(string pageName, string sourceName, Color newColor){ + VisualElement labelBG = Instance.values[$"{pageName}/{sourceName}"].parent.parent.Query("LabelBackground").First(); + VisualElement valueBG = Instance.values[$"{pageName}/{sourceName}"].parent.parent.Query("ValueBackground").First(); + + labelBG.style.backgroundColor = (newColor * .7f).Alpha(labelBG.resolvedStyle.backgroundColor.a); + valueBG.style.backgroundColor = (newColor * .6f).Alpha(valueBG.resolvedStyle.backgroundColor.a); + } + + // Back a page + public static void PreviousPage(){ + // Do nothing if there's only one page + if (Instance.Pages.Count == 1) { + return; + } + + // Get the index of the current page + int currentIndex = Instance.Pages.ToList().IndexOf(Instance.currentPage); + + // Change the page with wrapping + if (Instance.Pages.First().Key == Instance.currentPage.Key) { + Instance.currentPage = Instance.Pages.Last(); + } else { + Instance.currentPage = Instance.Pages.ElementAt(currentIndex - 1); + } + + // Set visibility + SetCurrentPageVisible(); + } + + public static void NextPage(){ + // Do nothing if there's only one page + if (Instance.Pages.Count == 1) { + return; + } + + // Get the index of the current page + int currentIndex = Instance.Pages.ToList().IndexOf(Instance.currentPage); + + // Change the page with wrapping + if (Instance.Pages.Last().Key == Instance.currentPage.Key) { + Instance.currentPage = Instance.Pages.First(); + } else { + Instance.currentPage = Instance.Pages.ElementAt(currentIndex + 1); + } + + // Set visibility + SetCurrentPageVisible(); + } + + static void SetCurrentPageVisible(){ + // Set the display property for the page to enable/disable them + foreach (var page in Instance.Pages) { + if (page.Key == Instance.currentPage.Key) { + page.Key.GetComponent().rootVisualElement.style.display = new StyleEnum(DisplayStyle.Flex); + } else { + page.Key.GetComponent().rootVisualElement.style.display = new StyleEnum(DisplayStyle.None); + } + } + + // Turn all the page labels into a list + var pageButtons = Instance.root.rootVisualElement.Query