game: back 2 square 1 (of them)

This commit is contained in:
Mark Joshwel 2024-11-17 22:05:04 +08:00
parent 5a0159c929
commit 685fbe961d
10 changed files with 278 additions and 227 deletions

View file

@ -132,6 +132,7 @@ GameObject:
m_Component: m_Component:
- component: {fileID: 133964672} - component: {fileID: 133964672}
- component: {fileID: 133964671} - component: {fileID: 133964671}
- component: {fileID: 133964676}
- component: {fileID: 133964673} - component: {fileID: 133964673}
- component: {fileID: 133964674} - component: {fileID: 133964674}
- component: {fileID: 133964675} - component: {fileID: 133964675}
@ -213,6 +214,19 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 6351b7620d84e2d43bc4f59c5f3f8b5c, type: 3} m_Script: {fileID: 11500000, guid: 6351b7620d84e2d43bc4f59c5f3f8b5c, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
--- !u!114 &133964676
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 133964670}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ac64716d16f44bd596798277ddc5eaaf, type: 3}
m_Name:
m_EditorClassIdentifier:
state: 0
--- !u!1 &447905425 --- !u!1 &447905425
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -459,6 +473,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 0cfc0b50e9003a0468ebdc186439c53b, type: 3} m_Script: {fileID: 11500000, guid: 0cfc0b50e9003a0468ebdc186439c53b, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
ui: {fileID: 0}
--- !u!4 &1204483826 --- !u!4 &1204483826
Transform: Transform:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View file

@ -116,6 +116,10 @@ public void OnEnable()
_secondaryActionButton.clicked += OnSecondaryActionButtonClick; _secondaryActionButton.clicked += OnSecondaryActionButtonClick;
TransitionStateTo(State.NotSignedIn); TransitionStateTo(State.NotSignedIn);
}
private void Awake()
{
GameManager.Instance.Backend.RegisterOnSignInCallback(OnSignInCallback); GameManager.Instance.Backend.RegisterOnSignInCallback(OnSignInCallback);
} }
@ -216,12 +220,12 @@ private void TransitionStateTo(State newState, bool keepAccompanyingText = false
state = newState; state = newState;
} }
private void ValidateUsername() private void ValidateUsername(TextField usernameField)
{ {
// just has to be min. 5 characters // just has to be min. 5 characters
_usernameField.style.color = _defaultInputFieldValueTextColour; usernameField.style.color = _defaultInputFieldValueTextColour;
if (_usernameField.value.Length >= 5) return; if (usernameField.value.Length >= 5) return;
_usernameField.style.color = _errorInputFieldValueTextColour; usernameField.style.color = _errorInputFieldValueTextColour;
throw new Exception("Username must be at least 5 characters long."); throw new Exception("Username must be at least 5 characters long.");
} }
@ -279,18 +283,18 @@ private void ValidateFields(TextField emailField, TextField passwordField)
try try
{ {
ValidateEmailField(_emailField); ValidateEmailField(emailField);
} }
catch (Exception _) catch (Exception)
{ {
invalidEmail = true; invalidEmail = true;
} }
try try
{ {
ValidatePasswordField(_passwordField); ValidatePasswordField(passwordField);
} }
catch (Exception _) catch (Exception)
{ {
invalidPassword = true; invalidPassword = true;
} }
@ -321,27 +325,27 @@ private void ValidateFields(TextField emailField, TextField passwordField, TextF
try try
{ {
ValidateEmailField(_emailField); ValidateEmailField(emailField);
} }
catch (Exception _) catch (Exception)
{ {
invalidEmail = true; invalidEmail = true;
} }
try try
{ {
ValidatePasswordField(_passwordField); ValidatePasswordField(passwordField);
} }
catch (Exception _) catch (Exception)
{ {
invalidPassword = true; invalidPassword = true;
} }
try try
{ {
ValidateUsername(); ValidateUsername(usernameField);
} }
catch (Exception _) catch (Exception)
{ {
invalidUsername = true; invalidUsername = true;
} }
@ -369,7 +373,7 @@ private void OnUsernameUpdateButtonClick()
{ {
try try
{ {
ValidateUsername(); ValidateUsername(_usernameField);
} }
catch (Exception e) catch (Exception e)
{ {

View file

@ -62,6 +62,7 @@ public static RGB gamut_clip_preserve_chroma(RGB rgb)
/// a and b must be normalized so a^2 + b^2 == 1 /// a and b must be normalized so a^2 + b^2 == 1
/// </summary> /// </summary>
// https://bottosson.github.io/posts/gamutclipping/ (MIT) // https://bottosson.github.io/posts/gamutclipping/ (MIT)
// ReSharper disable once MemberCanBePrivate.Global
public static float find_gamut_intersection( public static float find_gamut_intersection(
float a, float a,
float b, float b,
@ -164,6 +165,7 @@ public static RGB gamut_clip_preserve_chroma(RGB rgb)
/// a and b must be normalized so a^2 + b^2 == 1 /// a and b must be normalized so a^2 + b^2 == 1
/// </summary> /// </summary>
// https://bottosson.github.io/posts/gamutclipping/ (MIT) // https://bottosson.github.io/posts/gamutclipping/ (MIT)
// ReSharper disable once MemberCanBePrivate.Global
public static LC find_cusp(float a, float b) public static LC find_cusp(float a, float b)
{ {
// First, find the maximum saturation (saturation S = C/L) // First, find the maximum saturation (saturation S = C/L)
@ -178,7 +180,7 @@ public static LC find_cusp(float a, float b)
} }
// https://bottosson.github.io/posts/oklab/#converting-from-linear-srgb-to-oklab (public domain) // https://bottosson.github.io/posts/oklab/#converting-from-linear-srgb-to-oklab (public domain)
// ReSharper disable once MemberCanBePrivate.Global
public static Lab linear_srgb_to_oklab(RGB c) public static Lab linear_srgb_to_oklab(RGB c)
{ {
var l = 0.4122214708f * c.r + 0.5363325363f * c.g + 0.0514459929f * c.b; var l = 0.4122214708f * c.r + 0.5363325363f * c.g + 0.0514459929f * c.b;
@ -220,6 +222,7 @@ public static RGB oklab_to_linear_srgb(Lab c)
/// a and b must be normalized so a^2 + b^2 == 1 /// a and b must be normalized so a^2 + b^2 == 1
/// </summary> /// </summary>
// https://bottosson.github.io/posts/gamutclipping/ (MIT) // https://bottosson.github.io/posts/gamutclipping/ (MIT)
// ReSharper disable once MemberCanBePrivate.Global
public static float compute_max_saturation(float a, float b) public static float compute_max_saturation(float a, float b)
{ {
// Max saturation will be when one of r, g or b goes below zero. // Max saturation will be when one of r, g or b goes below zero.

View file

@ -1,47 +1,29 @@
using UnityEngine; using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UIElements;
/// <summary> /// <summary>
/// singleton for a single source of truth game state and flow management /// singleton for a single source of truth game state and flow management
/// </summary> /// </summary>
public class GameManager : MonoBehaviour public class GameManager : MonoBehaviour
{ {
/// <summary>
/// enum for available menus in the game, for use with <c>ShowMenu()</c>
/// </summary>
public enum DisplayState
{
Nothing,
PlayView,
LeaderboardView,
AccountView,
}
/// <summary> /// <summary>
/// singleton pattern: define instance field for accessing the singleton elsewhere /// singleton pattern: define instance field for accessing the singleton elsewhere
/// </summary> /// </summary>
public static GameManager Instance; public static GameManager Instance;
/// <summary>
/// the current display state of the game
/// </summary>
[SerializeField] private DisplayState state = DisplayState.Nothing;
/// <summary> /// <summary>
/// the visual element object for game ui (hud/prompts/tooltips) /// the local player data object for storing player data
/// </summary> /// </summary>
private VisualElement _ui; private LocalPlayerData _localPlayerData;
/// <summary> /// <summary>
/// backend object for handling communication with the firebase backend /// backend object for handling communication with the firebase backend
/// </summary> /// </summary>
public Backend Backend; public Backend Backend;
/// <summary> /// <summary>
/// the local player data object for storing player data /// ui manager object for handling ui state and flow
/// </summary> /// </summary>
private LocalPlayerData _localPlayerData; public UIManager ui;
/// <summary> /// <summary>
/// enforces singleton behaviour; sets doesn't destroy on load and checks for multiple instances /// enforces singleton behaviour; sets doesn't destroy on load and checks for multiple instances
@ -61,30 +43,27 @@ private void Awake()
Debug.Log("awake as non-singleton instance, destroying self"); Debug.Log("awake as non-singleton instance, destroying self");
Destroy(gameObject); Destroy(gameObject);
} }
}
private void Start()
{
SetDisplayState(DisplayState.PlayView);
// load the local player data and refresh the ui
_localPlayerData = new LocalPlayerData();
_localPlayerData.LoadFromTheWorld();
// register a callback to refresh the ui when the player signs in
Backend.RegisterOnSignInCallback(_ =>
{
_localPlayerData.LoadFromTheWorld();
});
} }
/// <summary> /// <summary>
/// called when the game object is enabled /// called when the game object is enabled, initialises variables
/// </summary> /// </summary>
private void OnEnable() private void OnEnable()
{ {
Backend = new Backend(); Backend = new Backend();
Backend.Initialise(); Backend.Initialise();
ui = UIManager.Instance;
}
private void Start()
{
// load the local player data and refresh the ui
_localPlayerData = new LocalPlayerData();
_localPlayerData.LoadFromTheWorld();
// register a callback to refresh the ui when the player signs in
Backend.RegisterOnSignInCallback(_ => { _localPlayerData.LoadFromTheWorld(); });
} }
/// <summary> /// <summary>
@ -94,13 +73,4 @@ private void OnDestroy()
{ {
Backend.Cleanup(); Backend.Cleanup();
} }
/// <summary>
/// function to show a menu based on the enum passed,
/// and any other necessary actions
/// </summary>
/// <param name="newDisplayState">the game menu to show</param>
public void SetDisplayState(DisplayState newDisplayState)
{
}
} }

View file

@ -4,7 +4,7 @@ MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2
defaultReferences: [] defaultReferences: []
executionOrder: 0 executionOrder: -10
icon: {instanceID: 0} icon: {instanceID: 0}
userData: userData:
assetBundleName: assetBundleName:

View file

@ -5,32 +5,32 @@
public class LocalPlayerData public class LocalPlayerData
{ {
/// <summary>
/// queue of the best online scores,
/// used in user rating calculation and accuracy display stats
/// </summary>
public Queue<Score> BestOnlineScores = new(30);
/// <summary> /// <summary>
/// last known email used /// last known email used
/// </summary> /// </summary>
public string LastKnownEmail = ""; public string LastKnownEmail = "";
/// <summary> /// <summary>
/// last known username used /// last known username used
/// </summary> /// </summary>
public string LastKnownUsername = "Guest"; public string LastKnownUsername = "Guest";
/// <summary> /// <summary>
/// queue of the 10 most recent local scores /// queue of the 10 most recent local scores
/// </summary> /// </summary>
public Queue<Score> RecentLocalScores = new(10); public Queue<Score> RecentLocalScores = new(10);
/// <summary> /// <summary>
/// queue of the 10 most recent online scores, /// queue of the 10 most recent online scores,
/// used in user rating calculation and accuracy display stats /// used in user rating calculation and accuracy display stats
/// </summary> /// </summary>
public Queue<Score> RecentOnlineScores = new(10); public Queue<Score> RecentOnlineScores = new(10);
/// <summary>
/// queue of the best online scores,
/// used in user rating calculation and accuracy display stats
/// </summary>
public Queue<Score> BestOnlineScores = new(30);
/// <summary> /// <summary>
/// loads player data from player prefs and database /// loads player data from player prefs and database
@ -46,6 +46,7 @@ public void LoadFromTheWorld()
currentKnownEmail = possibleUser.Email; currentKnownEmail = possibleUser.Email;
currentKnownUsername = GameManager.Instance.Backend.GetUsername(); currentKnownUsername = GameManager.Instance.Backend.GetUsername();
} }
var lastStoredEmail = PlayerPrefs.GetString("LastKnownEmail", ""); var lastStoredEmail = PlayerPrefs.GetString("LastKnownEmail", "");
var lastStoredUsername = PlayerPrefs.GetString("LastKnownUsername", "Guest"); var lastStoredUsername = PlayerPrefs.GetString("LastKnownUsername", "Guest");
LastKnownEmail = string.IsNullOrEmpty(currentKnownEmail) ? lastStoredEmail : currentKnownEmail; LastKnownEmail = string.IsNullOrEmpty(currentKnownEmail) ? lastStoredEmail : currentKnownEmail;
@ -78,27 +79,19 @@ public void LoadFromTheWorld()
RegisterLocalScore(new Score(timestamp, noOfRounds, l, c, h)); RegisterLocalScore(new Score(timestamp, noOfRounds, l, c, h));
} }
// load online scores // load online scores
RecentOnlineScores.Clear(); RecentOnlineScores.Clear();
GameManager.Instance.Backend.GetRecentScores((dtr, recentOnlineScores) => GameManager.Instance.Backend.GetRecentScores((_, recentOnlineScores) =>
{ {
foreach (var onlineScore in recentOnlineScores) foreach (var onlineScore in recentOnlineScores)
{ {
if (RecentOnlineScores.Count > 10) RecentOnlineScores.Dequeue(); if (RecentOnlineScores.Count > 10) RecentOnlineScores.Dequeue();
RecentOnlineScores.Enqueue(onlineScore); RecentOnlineScores.Enqueue(onlineScore);
} }
});
}
/// <summary> Debug.Log("loaded online scores from backend");
/// registers a score to the player's local data });
/// </summary>
/// <param name="score">the score to register</param>
public void RegisterLocalScore(Score score)
{
if (RecentLocalScores.Count > 10) RecentLocalScores.Dequeue();
RecentLocalScores.Enqueue(score);
} }
/// <summary> /// <summary>
@ -121,9 +114,21 @@ public void SaveToTheWorld()
idx++; idx++;
} }
Debug.Log("saved lpdata to playerprefs");
// online scores are already saved in the backend // online scores are already saved in the backend
} }
/// <summary>
/// registers a score to the player's local data
/// </summary>
/// <param name="score">the score to register</param>
public void RegisterLocalScore(Score score)
{
if (RecentLocalScores.Count > 10) RecentLocalScores.Dequeue();
RecentLocalScores.Enqueue(score);
}
public struct Score public struct Score
{ {
/// <summary> /// <summary>

View file

@ -74,7 +74,7 @@ private void OnEnable()
private void RenderFromPlayerData(LocalPlayerData localPlayerData) private void RenderFromPlayerData(LocalPlayerData localPlayerData)
{ {
// calculate averages from both recent local scores and online scores // calculate averages from both recent local scores and online scores
var totalLightessAcc = 0f; var totalLightnessAcc = 0f;
var totalChromaAcc = 0f; var totalChromaAcc = 0f;
var totalHueAcc = 0f; var totalHueAcc = 0f;
var totalRounds = 0; var totalRounds = 0;
@ -83,7 +83,7 @@ private void RenderFromPlayerData(LocalPlayerData localPlayerData)
foreach (var localScore in localPlayerData.RecentLocalScores) foreach (var localScore in localPlayerData.RecentLocalScores)
{ {
totalLightessAcc += localScore.AvgLightnessAccuracy; totalLightnessAcc += localScore.AvgLightnessAccuracy;
totalChromaAcc += localScore.AvgChromaAccuracy; totalChromaAcc += localScore.AvgChromaAccuracy;
totalHueAcc += localScore.AvgHueAccuracy; totalHueAcc += localScore.AvgHueAccuracy;
totalRounds += localScore.NoOfRounds; totalRounds += localScore.NoOfRounds;
@ -91,26 +91,26 @@ private void RenderFromPlayerData(LocalPlayerData localPlayerData)
foreach (var onlineScore in localPlayerData.RecentOnlineScores) foreach (var onlineScore in localPlayerData.RecentOnlineScores)
{ {
totalLightessAcc += onlineScore.AvgLightnessAccuracy; totalLightnessAcc += onlineScore.AvgLightnessAccuracy;
totalChromaAcc += onlineScore.AvgChromaAccuracy; totalChromaAcc += onlineScore.AvgChromaAccuracy;
totalHueAcc += onlineScore.AvgHueAccuracy; totalHueAcc += onlineScore.AvgHueAccuracy;
totalRounds += onlineScore.NoOfRounds; totalRounds += onlineScore.NoOfRounds;
} }
foreach (var onlineScore in localPlayerData.BestOnlineScores) foreach (var onlineScore in localPlayerData.BestOnlineScores)
{ {
totalLightessAcc += onlineScore.AvgLightnessAccuracy; totalLightnessAcc += onlineScore.AvgLightnessAccuracy;
totalChromaAcc += onlineScore.AvgChromaAccuracy; totalChromaAcc += onlineScore.AvgChromaAccuracy;
totalHueAcc += onlineScore.AvgHueAccuracy; totalHueAcc += onlineScore.AvgHueAccuracy;
totalRounds += onlineScore.NoOfRounds; totalRounds += onlineScore.NoOfRounds;
} }
// finally, set the labels // finally, set the labels
_playerNameText.text = GameManager.Instance.Backend.GetUsername(); _playerNameText.text = GameManager.Instance.Backend.GetUsername();
_lightnessAccuracyText.text = $"{(totalLightessAcc / totalRounds):F}"; _lightnessAccuracyText.text = $"{totalLightnessAcc / totalRounds:F}";
_hueAccuracyText.text = $"{(totalHueAcc / totalRounds):F}"; _hueAccuracyText.text = $"{totalHueAcc / totalRounds:F}";
_chromaAccuracyText.text = $"{(totalChromaAcc / totalRounds):F}"; _chromaAccuracyText.text = $"{totalChromaAcc / totalRounds:F}";
// and set the player rating, but after we get it from the backend // and set the player rating, but after we get it from the backend
// (god I LOVE async (I am LYING out of my teeth)) // (god I LOVE async (I am LYING out of my teeth))
GameManager.Instance.Backend.CalculateUserRating((dtr, rating) => GameManager.Instance.Backend.CalculateUserRating((dtr, rating) =>
@ -125,7 +125,7 @@ private void RenderFromPlayerData(LocalPlayerData localPlayerData)
/// </summary> /// </summary>
private static void OnPlayButtonClicked() private static void OnPlayButtonClicked()
{ {
GameManager.Instance.SetDisplayState(GameManager.DisplayState.PlayView); GameManager.Instance.ui.SetDisplayState(UIManager.DisplayState.PlayView);
} }
/// <summary> /// <summary>
@ -133,7 +133,7 @@ private static void OnPlayButtonClicked()
/// </summary> /// </summary>
private static void OnLeaderboardButtonClicked() private static void OnLeaderboardButtonClicked()
{ {
GameManager.Instance.SetDisplayState(GameManager.DisplayState.LeaderboardView); GameManager.Instance.ui.SetDisplayState(UIManager.DisplayState.LeaderboardView);
} }
/// <summary> /// <summary>
@ -141,6 +141,6 @@ private static void OnLeaderboardButtonClicked()
/// </summary> /// </summary>
private static void OnAccountButtonClicked() private static void OnAccountButtonClicked()
{ {
GameManager.Instance.SetDisplayState(GameManager.DisplayState.AccountView); GameManager.Instance.ui.SetDisplayState(UIManager.DisplayState.AccountView);
} }
} }

View file

@ -0,0 +1,113 @@
using System;
using UnityEngine;
using UnityEngine.UIElements;
public class UIManager : MonoBehaviour
{
/// <summary>
/// singleton pattern: define instance field for accessing the singleton elsewhere
/// </summary>
public static UIManager Instance;
/// <summary>
/// enum for available menus in the game, for use with <c>ShowMenu()</c>
/// </summary>
public enum DisplayState
{
UnassociatedState,
Nothing,
PlayView,
LeaderboardView,
AccountView
}
/// <summary>
/// the current display state of the game
/// </summary>
[SerializeField] private DisplayState state = DisplayState.UnassociatedState;
/// <summary>
/// the visual element object for game ui
/// </summary>
public VisualElement UI;
/// <summary>
/// enforces singleton behaviour; sets doesn't destroy on load and checks for multiple instances
/// </summary>
private void Awake()
{
// check if instance hasn't been set yet
if (Instance == null)
{
Debug.Log("awake as singleton instance, setting self as the forever-alive instance");
Instance = this;
DontDestroyOnLoad(gameObject);
}
// check if instance is already set and it's not this instance
else if (Instance != null && Instance != this)
{
Debug.Log("awake as non-singleton instance, destroying self");
Destroy(gameObject);
}
}
private void OnEnable()
{
UI = GetComponent<UIDocument>().rootVisualElement;
SetDisplayState(DisplayState.Nothing);
}
/// <summary>
/// function to show a menu based on the enum passed,
/// and any other necessary actions
/// </summary>
/// <param name="newDisplayState">the game menu to show</param>
public void SetDisplayState(DisplayState newDisplayState)
{
var currentDisplayState = state;
// if the new state is the same as the current state, do nothing
if (currentDisplayState == newDisplayState)
{
Debug.Log($"staying at {currentDisplayState} (illogical transition)");
return;
}
Debug.Log($"switching from {currentDisplayState} to {newDisplayState}");
var gameView = UI.Q<VisualElement>("GameView");
var leaderboardView = UI.Q<VisualElement>("LeaderboardView");
var accountView = UI.Q<VisualElement>("AccountView");
switch (newDisplayState)
{
case DisplayState.Nothing:
gameView.style.display = DisplayStyle.None;
leaderboardView.style.display = DisplayStyle.None;
accountView.style.display = DisplayStyle.None;
break;
case DisplayState.PlayView:
gameView.style.display = DisplayStyle.Flex;
leaderboardView.style.display = DisplayStyle.None;
accountView.style.display = DisplayStyle.None;
break;
case DisplayState.LeaderboardView:
gameView.style.display = DisplayStyle.None;
leaderboardView.style.display = DisplayStyle.Flex;
accountView.style.display = DisplayStyle.None;
break;
case DisplayState.AccountView:
gameView.style.display = DisplayStyle.None;
leaderboardView.style.display = DisplayStyle.None;
accountView.style.display = DisplayStyle.Flex;
break;
case DisplayState.UnassociatedState:
default:
throw new ArgumentOutOfRangeException(nameof(newDisplayState), newDisplayState, null);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ac64716d16f44bd596798277ddc5eaaf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: -15
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -1,162 +1,92 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" <ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" <Style src="project://database/Assets/UI/GameUI.uss?fileID=7433441132597879392&amp;guid=2c7ff79f21a3e8e408e76d75944d575b&amp;type=3#GameUI" />
noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False"> <ui:VisualElement name="Root" style="flex-grow: 1; background-color: rgb(208, 152, 194); justify-content: space-around; align-items: stretch; align-self: stretch; flex-direction: row;">
<Style src="project://database/Assets/UI/GameUI.uss?fileID=7433441132597879392&amp;guid=2c7ff79f21a3e8e408e76d75944d575b&amp;type=3#GameUI"/> <ui:VisualElement name="SideView" style="flex-grow: 0; background-color: rgb(15, 13, 27); flex-shrink: 0; width: 25%; justify-content: space-between;">
<ui:VisualElement name="Root" <ui:VisualElement name="Header" style="flex-grow: 0; margin-top: 10%; margin-right: 10%; margin-bottom: 0; margin-left: 10%; justify-content: space-between; align-items: flex-start; flex-direction: column;">
style="flex-grow: 1; background-color: rgb(208, 152, 194); justify-content: space-around; align-items: stretch; align-self: stretch; flex-direction: row;"> <ui:Label tabindex="-1" text="Colour Me OK" parse-escape-sequences="true" display-tooltip-when-elided="true" name="Name" style="color: rgb(208, 152, 194); -unity-font-style: bold; font-size: 58px; white-space: normal;" />
<ui:VisualElement name="SideView" <ui:Label tabindex="-1" text="Color Me OK is a colour-matching game using the coordinates of the OKLCh colour model on the OKLab perceptually uniform colour space." parse-escape-sequences="true" display-tooltip-when-elided="true" name="Description" style="font-size: 16px; white-space: normal; text-overflow: clip; color: rgb(208, 152, 194);" />
style="flex-grow: 0; background-color: rgb(15, 13, 27); flex-shrink: 0; width: 25%; justify-content: space-between;">
<ui:VisualElement name="Header"
style="flex-grow: 0; margin-top: 10%; margin-right: 10%; margin-bottom: 0; margin-left: 10%; justify-content: space-between; align-items: flex-start; flex-direction: column;">
<ui:Label tabindex="-1" text="Colour Me OK" parse-escape-sequences="true"
display-tooltip-when-elided="true" name="Name"
style="color: rgb(208, 152, 194); -unity-font-style: bold; font-size: 58px; white-space: normal;"/>
<ui:Label tabindex="-1"
text="Color Me OK is a colour-matching game using the coordinates of the OKLCh colour model on the OKLab perceptually uniform colour space."
parse-escape-sequences="true" display-tooltip-when-elided="true" name="Description"
style="font-size: 16px; white-space: normal; text-overflow: clip; color: rgb(208, 152, 194);"/>
</ui:VisualElement> </ui:VisualElement>
<ui:VisualElement name="Content" <ui:VisualElement name="Content" style="flex-grow: 0; padding-right: 10%; padding-bottom: 10%; padding-left: 10%;">
style="flex-grow: 0; padding-right: 10%; padding-bottom: 10%; padding-left: 10%;"> <ui:Button text="Play ↗" parse-escape-sequences="true" display-tooltip-when-elided="true" name="PlayButton" />
<ui:Button text="Play ↗" parse-escape-sequences="true" display-tooltip-when-elided="true" <ui:Button text="Leaderboard ↗" parse-escape-sequences="true" display-tooltip-when-elided="true" name="LeaderboardButton" />
name="PlayButton"/> <ui:Button text="Account ↗" parse-escape-sequences="true" display-tooltip-when-elided="true" name="AccountButton" />
<ui:Button text="Leaderboard ↗" parse-escape-sequences="true" display-tooltip-when-elided="true" <ui:VisualElement name="AccountSection" style="flex-grow: 0; border-top-color: rgb(208, 152, 194); margin-top: 0; border-top-width: 1px; margin-right: 0; margin-bottom: 0; margin-left: 0; border-bottom-color: rgb(208, 152, 194); padding-bottom: 12px;">
name="LeaderboardButton"/> <ui:VisualElement name="PlayerDetails" style="flex-grow: 1; flex-direction: row; align-items: stretch; justify-content: space-between; font-size: 10px; align-self: stretch;">
<ui:Button text="Account ↗" parse-escape-sequences="true" display-tooltip-when-elided="true"
name="AccountButton"/>
<ui:VisualElement name="AccountSection"
style="flex-grow: 0; border-top-color: rgb(208, 152, 194); margin-top: 0; border-top-width: 1px; margin-right: 0; margin-bottom: 0; margin-left: 0; border-bottom-color: rgb(208, 152, 194); border-bottom-width: 1px; padding-bottom: 12px;">
<ui:VisualElement name="PlayerDetails"
style="flex-grow: 1; flex-direction: row; align-items: stretch; justify-content: space-between; font-size: 10px; align-self: stretch;">
<ui:VisualElement name="PlayerNameDetail" style="flex-grow: 1;"> <ui:VisualElement name="PlayerNameDetail" style="flex-grow: 1;">
<ui:Label tabindex="-1" text="Player" parse-escape-sequences="true" <ui:Label tabindex="-1" text="Player" parse-escape-sequences="true" display-tooltip-when-elided="true" name="PlayerHeader" style="-unity-font-style: normal; font-size: 14px; padding-bottom: 0; -unity-text-align: lower-left;" />
display-tooltip-when-elided="true" name="PlayerHeader" <ui:Label tabindex="-1" text="Not Signed In" parse-escape-sequences="true" display-tooltip-when-elided="true" name="PlayerText" style="-unity-font-style: normal; font-size: 18px; padding-top: 6px;" />
style="-unity-font-style: normal; font-size: 14px; padding-bottom: 0; -unity-text-align: lower-left;"/>
<ui:Label tabindex="-1" text="Not Signed In" parse-escape-sequences="true"
display-tooltip-when-elided="true" name="PlayerText"
style="-unity-font-style: normal; font-size: 18px; padding-top: 6px;"/>
</ui:VisualElement> </ui:VisualElement>
<ui:VisualElement name="PlayerRatingDetail" style="flex-grow: 0;"> <ui:VisualElement name="PlayerRatingDetail" style="flex-grow: 0;">
<ui:Label tabindex="-1" text="Rating" parse-escape-sequences="true" <ui:Label tabindex="-1" text="Rating" parse-escape-sequences="true" display-tooltip-when-elided="true" name="RatingHeader" style="-unity-font-style: normal; font-size: 14px; padding-bottom: 0; -unity-text-align: lower-right;" />
display-tooltip-when-elided="true" name="RatingHeader" <ui:Label tabindex="-1" text="00.00%" parse-escape-sequences="true" display-tooltip-when-elided="true" name="RatingText" style="-unity-font-style: normal; font-size: 18px; padding-top: 6px; -unity-text-align: upper-right;" />
style="-unity-font-style: normal; font-size: 14px; padding-bottom: 0; -unity-text-align: lower-right;"/>
<ui:Label tabindex="-1" text="00.00%" parse-escape-sequences="true"
display-tooltip-when-elided="true" name="RatingText"
style="-unity-font-style: normal; font-size: 18px; padding-top: 6px; -unity-text-align: upper-right;"/>
</ui:VisualElement> </ui:VisualElement>
</ui:VisualElement> </ui:VisualElement>
<ui:VisualElement name="AccuracyDetails" <ui:VisualElement name="AccuracyDetails" style="flex-grow: 1; flex-direction: row; align-items: stretch; justify-content: space-between; font-size: 10px; align-self: stretch; padding-top: 4px;">
style="flex-grow: 1; flex-direction: row; align-items: stretch; justify-content: space-between; font-size: 10px; align-self: stretch; padding-top: 4px;">
<ui:VisualElement name="LightnessAccuracyDetail" style="flex-grow: 0;"> <ui:VisualElement name="LightnessAccuracyDetail" style="flex-grow: 0;">
<ui:Label tabindex="-1" text="Lightness&#10;Accuracy" parse-escape-sequences="true" <ui:Label tabindex="-1" text="Lightness&#10;Accuracy" parse-escape-sequences="true" display-tooltip-when-elided="true" name="LightnessAccuracyHeader" style="-unity-font-style: normal; font-size: 14px; padding-bottom: 0; -unity-text-align: lower-left; padding-top: 0;" />
display-tooltip-when-elided="true" name="LightnessAccuracyHeader" <ui:Label tabindex="-1" text="00.0%" parse-escape-sequences="true" display-tooltip-when-elided="true" name="LightnessAccuracyText" style="-unity-font-style: normal; font-size: 18px; padding-top: 6px; padding-bottom: 0;" />
style="-unity-font-style: normal; font-size: 14px; padding-bottom: 0; -unity-text-align: lower-left; padding-top: 0;"/>
<ui:Label tabindex="-1" text="00.0%" parse-escape-sequences="true"
display-tooltip-when-elided="true" name="LightnessAccuracyText"
style="-unity-font-style: normal; font-size: 18px; padding-top: 6px; padding-bottom: 0;"/>
</ui:VisualElement> </ui:VisualElement>
<ui:VisualElement name="ChromaAccuracyDetail" style="flex-grow: 0;"> <ui:VisualElement name="ChromaAccuracyDetail" style="flex-grow: 0;">
<ui:Label tabindex="-1" text="Chroma&#10;Accuracy" parse-escape-sequences="true" <ui:Label tabindex="-1" text="Chroma&#10;Accuracy" parse-escape-sequences="true" display-tooltip-when-elided="true" name="ChromaAccuracyHeader" style="-unity-font-style: normal; font-size: 14px; padding-bottom: 0; -unity-text-align: lower-center; padding-top: 0;" />
display-tooltip-when-elided="true" name="ChromaAccuracyHeader" <ui:Label tabindex="-1" text="00.0%" parse-escape-sequences="true" display-tooltip-when-elided="true" name="ChromaAccuracyText" style="-unity-font-style: normal; font-size: 18px; padding-top: 6px; -unity-text-align: upper-center; padding-bottom: 0;" />
style="-unity-font-style: normal; font-size: 14px; padding-bottom: 0; -unity-text-align: lower-center; padding-top: 0;"/>
<ui:Label tabindex="-1" text="00.0%" parse-escape-sequences="true"
display-tooltip-when-elided="true" name="ChromaAccuracyText"
style="-unity-font-style: normal; font-size: 18px; padding-top: 6px; -unity-text-align: upper-center; padding-bottom: 0;"/>
</ui:VisualElement> </ui:VisualElement>
<ui:VisualElement name="HueAccuracyDetail" style="flex-grow: 0;"> <ui:VisualElement name="HueAccuracyDetail" style="flex-grow: 0;">
<ui:Label tabindex="-1" text="Hue&#10;Accuracy" parse-escape-sequences="true" <ui:Label tabindex="-1" text="Hue&#10;Accuracy" parse-escape-sequences="true" display-tooltip-when-elided="true" name="HueAccuracyHeader" style="-unity-font-style: normal; font-size: 14px; padding-bottom: 0; -unity-text-align: lower-right; padding-top: 0;" />
display-tooltip-when-elided="true" name="HueAccuracyHeader" <ui:Label tabindex="-1" text="00.0%" parse-escape-sequences="true" display-tooltip-when-elided="true" name="HueAccuracyText" style="-unity-font-style: normal; font-size: 18px; padding-top: 6px; -unity-text-align: upper-right; padding-bottom: 0;" />
style="-unity-font-style: normal; font-size: 14px; padding-bottom: 0; -unity-text-align: lower-right; padding-top: 0;"/>
<ui:Label tabindex="-1" text="00.0%" parse-escape-sequences="true"
display-tooltip-when-elided="true" name="HueAccuracyText"
style="-unity-font-style: normal; font-size: 18px; padding-top: 6px; -unity-text-align: upper-right; padding-bottom: 0;"/>
</ui:VisualElement> </ui:VisualElement>
</ui:VisualElement> </ui:VisualElement>
</ui:VisualElement> </ui:VisualElement>
<ui:VisualElement name="ConnectionStatusText" style="flex-grow: 0; border-top-color: rgb(208, 152, 194); margin-top: 0; border-top-width: 1px; margin-right: 0; margin-bottom: 0; margin-left: 0; border-bottom-color: rgb(208, 152, 194); border-bottom-width: 1px; padding-bottom: 12px;">
<ui:Label tabindex="-1" text="Status: Unknown" parse-escape-sequences="true" display-tooltip-when-elided="true" name="ConnectionStatusText" style="-unity-font-style: normal; font-size: 14px; padding-bottom: 0; -unity-text-align: lower-left;" />
</ui:VisualElement>
</ui:VisualElement> </ui:VisualElement>
</ui:VisualElement> </ui:VisualElement>
<ui:VisualElement name="MainView" <ui:VisualElement name="MainView" style="flex-grow: 0; flex-shrink: 0; width: 75%; justify-content: space-between;">
style="flex-grow: 0; flex-shrink: 0; width: 75%; justify-content: space-between;"> <ui:VisualElement name="GameView" style="flex-grow: 0; margin-top: 3.25%; margin-right: 3.25%; margin-bottom: 3.25%; margin-left: 3.25%; justify-content: space-between; height: 100%; align-self: stretch; display: none;">
<ui:VisualElement name="GameView" <ui:VisualElement name="GameHeader" style="flex-grow: 0; flex-direction: row; justify-content: space-between; align-self: stretch;">
style="flex-grow: 0; margin-top: 3.25%; margin-right: 3.25%; margin-bottom: 3.25%; margin-left: 3.25%; justify-content: space-between; height: 100%; align-self: stretch; display: none;"> <ui:Label tabindex="-1" text="1/5" parse-escape-sequences="true" display-tooltip-when-elided="true" name="RoundText" style="font-size: 58px; -unity-font-style: normal;" />
<ui:VisualElement name="GameHeader" <ui:Label tabindex="-1" text="0.00s" parse-escape-sequences="true" display-tooltip-when-elided="true" name="TimeText" style="-unity-text-align: lower-right; font-size: 58px;" />
style="flex-grow: 0; flex-direction: row; justify-content: space-between; align-self: stretch;">
<ui:Label tabindex="-1" text="1/5" parse-escape-sequences="true" display-tooltip-when-elided="true"
name="RoundText" style="font-size: 58px; -unity-font-style: normal;"/>
<ui:Label tabindex="-1" text="0.00s" parse-escape-sequences="true"
display-tooltip-when-elided="true" name="TimeText"
style="-unity-text-align: lower-right; font-size: 58px;"/>
</ui:VisualElement> </ui:VisualElement>
<ui:VisualElement name="ColourPreview" <ui:VisualElement name="ColourPreview" style="flex-grow: 0; height: 50%; background-color: rgb(255, 255, 255); border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-right-radius: 8px; border-bottom-left-radius: 8px; flex-direction: row; padding-top: 2%; padding-right: 2%; padding-bottom: 2%; padding-left: 2%; justify-content: space-between;">
style="flex-grow: 0; height: 50%; background-color: rgb(255, 255, 255); border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-right-radius: 8px; border-bottom-left-radius: 8px; flex-direction: row; padding-top: 2%; padding-right: 2%; padding-bottom: 2%; padding-left: 2%; justify-content: space-between;"> <ui:VisualElement name="TemplatePreview" style="flex-grow: 0; flex-shrink: 0; height: 100%; width: 49%;">
<ui:VisualElement name="TemplatePreview" <ui:Label tabindex="-1" text="Template" parse-escape-sequences="true" display-tooltip-when-elided="true" name="TemplateText" style="margin-bottom: 12px; margin-top: 0; -unity-font-style: normal;" />
style="flex-grow: 0; flex-shrink: 0; height: 100%; width: 49%;"> <ui:VisualElement name="TemplateColour" style="flex-grow: 1; border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-right-radius: 8px; border-bottom-left-radius: 8px; background-color: rgb(0, 0, 0);" />
<ui:Label tabindex="-1" text="Template" parse-escape-sequences="true"
display-tooltip-when-elided="true" name="TemplateText"
style="margin-bottom: 12px; margin-top: 0; -unity-font-style: normal;"/>
<ui:VisualElement name="TemplateColour"
style="flex-grow: 1; border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-right-radius: 8px; border-bottom-left-radius: 8px; background-color: rgb(0, 0, 0);"/>
</ui:VisualElement> </ui:VisualElement>
<ui:VisualElement name="ResponsePreview" <ui:VisualElement name="ResponsePreview" style="flex-grow: 0; flex-shrink: 0; height: 100%; width: 49%;">
style="flex-grow: 0; flex-shrink: 0; height: 100%; width: 49%;"> <ui:Label tabindex="-1" text="Response" parse-escape-sequences="true" display-tooltip-when-elided="true" name="ResponseText" style="margin-bottom: 12px; margin-top: 0; -unity-font-style: normal; -unity-text-align: upper-right;" />
<ui:Label tabindex="-1" text="Response" parse-escape-sequences="true" <ui:VisualElement name="ResponseColour" style="flex-grow: 1; border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-right-radius: 8px; border-bottom-left-radius: 8px; background-color: rgb(0, 0, 0);" />
display-tooltip-when-elided="true" name="ResponseText"
style="margin-bottom: 12px; margin-top: 0; -unity-font-style: normal; -unity-text-align: upper-right;"/>
<ui:VisualElement name="ResponseColour"
style="flex-grow: 1; border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-right-radius: 8px; border-bottom-left-radius: 8px; background-color: rgb(0, 0, 0);"/>
</ui:VisualElement> </ui:VisualElement>
</ui:VisualElement> </ui:VisualElement>
<ui:VisualElement name="ResponseSliders" style="flex-grow: 0; display: flex;"> <ui:VisualElement name="ResponseSliders" style="flex-grow: 0; display: flex;">
<ui:Slider label="Lightness" high-value="100" name="ResponseLightnessSlider" class="lch-slider"/> <ui:Slider label="Lightness" high-value="100" name="ResponseLightnessSlider" class="lch-slider" />
<ui:Slider label="Chroma" high-value="0.5" name="ResponseChromaSlider" class="lch-slider"/> <ui:Slider label="Chroma" high-value="0.5" name="ResponseChromaSlider" class="lch-slider" />
<ui:Slider label="Hue" high-value="360" name="ResponseHueSlider" class="lch-slider"/> <ui:Slider label="Hue" high-value="360" name="ResponseHueSlider" class="lch-slider" />
</ui:VisualElement> </ui:VisualElement>
</ui:VisualElement> </ui:VisualElement>
<ui:VisualElement name="LeaderboardView" <ui:VisualElement name="LeaderboardView" style="flex-grow: 1; display: none; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; margin-top: 3.25%; margin-right: 3.25%; margin-bottom: 3.25%; margin-left: 3.25%; flex-direction: column; justify-content: space-between;">
style="flex-grow: 1; display: none; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; margin-top: 3.25%; margin-right: 3.25%; margin-bottom: 3.25%; margin-left: 3.25%; flex-direction: column; justify-content: space-between;"> <ui:Label tabindex="-1" text="Leaderboard" parse-escape-sequences="true" display-tooltip-when-elided="true" name="RoundText" style="font-size: 58px; -unity-font-style: normal;" />
<ui:VisualElement name="LeaderboardHeader" style="flex-grow: 0;"> <ui:ListView name="LeaderboardListView" />
<ui:Label tabindex="-1" text="Leaderboard" parse-escape-sequences="true"
display-tooltip-when-elided="true" name="RoundText"
style="font-size: 58px; -unity-font-style: bold;"/>
</ui:VisualElement>
<ui:ListView name="LeaderboardListView"/>
</ui:VisualElement> </ui:VisualElement>
<ui:VisualElement name="AccountView" <ui:VisualElement name="AccountView" style="flex-grow: 1; display: flex; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; margin-top: 3.25%; margin-right: 3.25%; margin-bottom: 3.25%; margin-left: 3.25%; flex-direction: column; justify-content: space-between;">
style="flex-grow: 1; display: flex; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; margin-top: 3.25%; margin-right: 3.25%; margin-bottom: 3.25%; margin-left: 3.25%; flex-direction: column; justify-content: space-between;"> <ui:Label tabindex="-1" text="You are not signed in." parse-escape-sequences="true" display-tooltip-when-elided="true" name="AccountHeader" style="font-size: 58px; -unity-font-style: normal;" />
<ui:Label tabindex="-1" text="You are not signed in." parse-escape-sequences="true"
display-tooltip-when-elided="true" name="AccountHeader"
style="font-size: 58px; -unity-font-style: normal;"/>
<ui:VisualElement name="AccountFields" style="flex-grow: 0;"> <ui:VisualElement name="AccountFields" style="flex-grow: 0;">
<ui:VisualElement name="UsernameContainer" <ui:VisualElement name="UsernameContainer" style="flex-grow: 1; flex-direction: row; justify-content: space-between;">
style="flex-grow: 1; flex-direction: row; justify-content: space-between;"> <ui:TextField picking-mode="Ignore" label="Username" name="UsernameField" />
<ui:TextField picking-mode="Ignore" label="Username" name="UsernameField"/> <ui:Button text="Update" parse-escape-sequences="true" display-tooltip-when-elided="true" name="UsernameUpdateButton" />
<ui:Button text="Update" parse-escape-sequences="true" display-tooltip-when-elided="true"
name="UsernameUpdateButton"/>
</ui:VisualElement> </ui:VisualElement>
<ui:VisualElement name="EmailContainer" <ui:VisualElement name="EmailContainer" style="flex-grow: 1; flex-direction: row; justify-content: space-between;">
style="flex-grow: 1; flex-direction: row; justify-content: space-between;"> <ui:TextField picking-mode="Ignore" label="Email" name="EmailField" keyboard-type="EmailAddress" />
<ui:TextField picking-mode="Ignore" label="Email" name="EmailField" <ui:Button text="Update" parse-escape-sequences="true" display-tooltip-when-elided="true" name="EmailUpdateButton" />
keyboard-type="EmailAddress"/>
<ui:Button text="Update" parse-escape-sequences="true" display-tooltip-when-elided="true"
name="EmailUpdateButton"/>
</ui:VisualElement> </ui:VisualElement>
<ui:VisualElement name="PasswordContainer" <ui:VisualElement name="PasswordContainer" style="flex-grow: 1; flex-direction: row; justify-content: space-between;">
style="flex-grow: 1; flex-direction: row; justify-content: space-between;"> <ui:TextField picking-mode="Ignore" label="Password" name="PasswordField" password="true" />
<ui:TextField picking-mode="Ignore" label="Password" name="PasswordField" password="true"/> <ui:Button text="Update" parse-escape-sequences="true" display-tooltip-when-elided="true" name="PasswordUpdateButton" />
<ui:Button text="Update" parse-escape-sequences="true" display-tooltip-when-elided="true"
name="PasswordUpdateButton"/>
</ui:VisualElement> </ui:VisualElement>
<ui:Label tabindex="-1" text="A verification email has been sent. Check your inbox." <ui:Label tabindex="-1" text="A verification email has been sent. Check your inbox." parse-escape-sequences="true" display-tooltip-when-elided="true" name="AccompanyingText" style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; margin-top: 1.5%; margin-right: 0; margin-bottom: 0.75%; margin-left: 0; -unity-text-align: upper-left; display: none;" />
parse-escape-sequences="true" display-tooltip-when-elided="true" name="AccompanyingText"
style="padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0; margin-top: 1.5%; margin-right: 0; margin-bottom: 0.75%; margin-left: 0; -unity-text-align: upper-left; display: none;"/>
</ui:VisualElement> </ui:VisualElement>
<ui:VisualElement name="AccountButtons" style="flex-grow: 0; align-items: flex-start;"> <ui:VisualElement name="AccountButtons" style="flex-grow: 0; align-items: flex-start;">
<ui:Button text="Primary Action Button →" parse-escape-sequences="true" <ui:Button text="Primary Action Button →" parse-escape-sequences="true" display-tooltip-when-elided="true" name="PrimaryActionButton" style="-unity-text-align: middle-center; margin-bottom: 1%; margin-right: 1%; margin-top: 1%; -unity-font-style: bold;" />
display-tooltip-when-elided="true" name="PrimaryActionButton" <ui:Button text="Secondary Action Button →" parse-escape-sequences="true" display-tooltip-when-elided="true" name="SecondaryActionButton" style="margin-top: 1%; margin-right: 1%; -unity-font-style: bold;" />
style="-unity-text-align: middle-center; margin-bottom: 1%; margin-right: 1%; margin-top: 1%; -unity-font-style: bold;"/>
<ui:Button text="Secondary Action Button →" parse-escape-sequences="true"
display-tooltip-when-elided="true" name="SecondaryActionButton"
style="margin-top: 1%; margin-right: 1%; -unity-font-style: bold;"/>
</ui:VisualElement> </ui:VisualElement>
</ui:VisualElement> </ui:VisualElement>
</ui:VisualElement> </ui:VisualElement>