feat: controls for pages, better templates, color changing, clear commenting

This commit is contained in:
Chris
2025-08-26 13:27:10 -04:00
parent 2a699019c4
commit 7600a6bb1e
9 changed files with 265 additions and 155 deletions

View File

@@ -0,0 +1,5 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<ui:VisualElement name="SinglePage" style="background-color: rgba(204, 142, 84, 0.31); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; border-left-color: rgba(255, 160, 61, 0.94); border-right-color: rgba(255, 160, 61, 0.94); border-top-color: rgba(255, 160, 61, 0.94); border-bottom-color: rgba(255, 160, 61, 0.94); border-top-width: 7px; border-right-width: 0.5px; border-bottom-width: 0.5px; border-left-width: 0.5px; width: auto; margin-right: 12px; max-width: 175px;">
<ui:Label text="Page Label" name="PageLabel" style="padding-right: 10px; padding-left: 10px; color: rgb(255, 255, 255); -unity-font-style: bold; padding-top: 10px; padding-bottom: 10px; flex-shrink: 1;" />
</ui:VisualElement>
</ui:UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 94d59802c4805cd44b4339b049e4ac06
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -0,0 +1,3 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<ui:VisualElement name="ValuesContainer" style="flex-grow: 1; margin-top: 0; padding-top: 0; padding-right: 20px; padding-bottom: 20px; padding-left: 20px; flex-shrink: 0;" />
</ui:UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 5bbda06c82d8c77478a2f5e7cc4e1f38
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}

View File

@@ -1,3 +1,5 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<ui:VisualElement name="StretchBG" style="width: 100%; height: 100%;" />
<ui:VisualElement name="StretchBG" style="width: 100%; height: auto;">
<ui:VisualElement name="Pages" style="flex-direction: row; padding-top: 20px; padding-right: 20px; padding-bottom: 20px; padding-left: 20px;" />
</ui:VisualElement>
</ui:UXML>

View File

@@ -1,10 +1,12 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<ui:VisualElement name="VisualElement">
<ui:VisualElement style="flex-grow: 1; background-color: rgba(255, 144, 55, 0.47); border-top-left-radius: 2px; border-top-right-radius: 2px;">
<ui:Label text="Label" name="Label" style="font-size: 15px; -unity-font-style: bold; color: rgb(255, 255, 255); padding-top: 1px; padding-right: 1px; padding-bottom: 1px; padding-left: 8px;" />
</ui:VisualElement>
<ui:VisualElement style="background-color: rgba(202, 152, 104, 0.4);">
<ui:Label text="Label" name="Value" style="color: rgb(255, 255, 255); padding-left: 12px; padding-top: 2px; padding-bottom: 2px; border-bottom-right-radius: 2px; border-bottom-left-radius: 2px;" />
<ui:VisualElement style="align-items: flex-start; margin-bottom: 10px;">
<ui:VisualElement name="VisualElement" style="max-width: 400px;">
<ui:VisualElement name="LabelBackground" style="background-color: rgba(255, 144, 55, 0.47); border-top-left-radius: 2px; border-top-right-radius: 2px; padding-right: 10px; padding-left: 10px;">
<ui:Label text="Label" name="Label" style="font-size: 15px; -unity-font-style: bold; color: rgb(255, 255, 255); padding-top: 1px; padding-right: 1px; padding-bottom: 1px; padding-left: 8px;" />
</ui:VisualElement>
<ui:VisualElement enabled="true" name="ValueBackground" style="background-color: rgba(202, 152, 104, 0.4); padding-left: 5px; padding-right: 5px;">
<ui:Label text="Label" name="Value" style="color: rgb(255, 255, 255); padding-left: 12px; padding-top: 2px; padding-bottom: 2px; border-bottom-right-radius: 2px; border-bottom-left-radius: 2px; flex-shrink: 1; width: 103px;" />
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>
</ui:UXML>

View File

@@ -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": "<Gamepad>/select",
"interactions": "",
"processors": "",
"groups": "",
"action": "Debug Previous Page",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "binding",
"id": "de0fea7a-6ba2-46f9-92c0-a24da87da819",
"path": "<Gamepad>/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": "<Gamepad>/select",
"interactions": "",
"processors": "",
"groups": "",
"action": "Debug Next Page",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "binding",
"id": "0d619c6a-35b8-4184-9206-531c20e54c57",
"path": "<Gamepad>/rightShoulder",
"interactions": "",
"processors": "",
"groups": "",
"action": "Debug Next Page",
"isComposite": false,
"isPartOfComposite": true
}
]
}

View File

@@ -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}

View File

@@ -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<GameObject, List<string>> Pages = new(); // Page and value names
[Space(5)]
[ShowInInspector]
public Dictionary<object, Label> 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<GameObject, List<string>> 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<string>());
thisPage.transform.SetParent(Instance.canvasRoot.transform);
thisPage.AddComponent<UIDocument>();
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<GameObject, List<string>> newPage = new(thisPageObject, new List<string>());
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<UIDocument>();
thisDocument.visualTreeAsset = Instance.pageBaseTemplate;
// Then add a button/header to the main container
VisualElement newPageButton = Instance.pageButtonTemplate.Instantiate();
Instance.root.rootVisualElement.Query<VisualElement>("Pages").First().Add(newPageButton);
((Label)newPageButton.Query<VisualElement>("PageLabel").First()).text = pageName;
} else {
thisDocument = thisPageObject.GetComponent<UIDocument>();
}
// If this is the only page, set it to the current page
if (Instance.Pages.Count == 1) {
Instance.currentPage = new KeyValuePair<GameObject, List<string>>(thisPageObject, new List<string>());
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<UIDocument>().rootVisualElement.Add(thisElement);
thisElement.style.alignSelf = new StyleEnum<Align>(Align.Center);
VisualElement thisElement = (Instance.valueTemplate.Instantiate());
thisDocument.rootVisualElement.Query<VisualElement>("ValuesContainer").First().Add(thisElement);
// Set it's label
((Label)thisElement.Query<VisualElement>("Label").First()).text = sourceName;
Instance.values.Add($"{pageName}/{sourceName}", (Label)thisElement.Query<VisualElement>("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<VisualElement>("LabelBackground").First();
VisualElement valueBG = Instance.values[$"{pageName}/{sourceName}"].parent.parent.Query<VisualElement>("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<UIDocument>().rootVisualElement.style.display = new StyleEnum<DisplayStyle>(DisplayStyle.Flex);
} else {
page.Key.GetComponent<UIDocument>().rootVisualElement.style.display = new StyleEnum<DisplayStyle>(DisplayStyle.None);
}
}
// Turn all the page labels into a list
var pageButtons = Instance.root.rootVisualElement.Query<Label>("PageLabel").ToList();
// Iterate through said list and set the opacity of the parent (so everything including the label gets turned down)
foreach (Label page in pageButtons) {
page.parent.style.opacity = .4f;
if (Instance.currentPage.Key.name == $"{Instance.pageNamePrefix}{page.text}") {
page.parent.style.opacity = 1f;
}
}
}
}
}