game: gameplay + database interim
This commit is contained in:
parent
b88f6499cc
commit
cc79a5b1a0
|
@ -143,7 +143,7 @@ GameObject:
|
||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
m_StaticEditorFlags: 0
|
m_StaticEditorFlags: 0
|
||||||
m_IsActive: 1
|
m_IsActive: 0
|
||||||
--- !u!114 &133964671
|
--- !u!114 &133964671
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -258,7 +258,7 @@ GameObject:
|
||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
m_StaticEditorFlags: 0
|
m_StaticEditorFlags: 0
|
||||||
m_IsActive: 1
|
m_IsActive: 0
|
||||||
--- !u!4 &447905427
|
--- !u!4 &447905427
|
||||||
Transform:
|
Transform:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -476,7 +476,7 @@ GameObject:
|
||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
m_StaticEditorFlags: 0
|
m_StaticEditorFlags: 0
|
||||||
m_IsActive: 1
|
m_IsActive: 0
|
||||||
--- !u!114 &1204483825
|
--- !u!114 &1204483825
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -505,6 +505,37 @@ Transform:
|
||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!1 &1680304394
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 1680304395}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: GameObject
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!4 &1680304395
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1680304394}
|
||||||
|
serializedVersion: 2
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
|
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!1660057539 &9223372036854775807
|
--- !u!1660057539 &9223372036854775807
|
||||||
SceneRoots:
|
SceneRoots:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -514,3 +545,4 @@ SceneRoots:
|
||||||
- {fileID: 133964672}
|
- {fileID: 133964672}
|
||||||
- {fileID: 447905427}
|
- {fileID: 447905427}
|
||||||
- {fileID: 1204483826}
|
- {fileID: 1204483826}
|
||||||
|
- {fileID: 1680304395}
|
||||||
|
|
|
@ -18,12 +18,12 @@ public class AccountUI : MonoBehaviour
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// default text colour
|
/// default text colour
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly Color _defaultInputFieldValueTextColour = new(5.88f, 5.1f, 10.59f);
|
private readonly StyleColor _defaultInputFieldValueTextColour = new(new Color(0.0588f, 0.051f, 0.1059f));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// error text colour
|
/// error text colour
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly Color _errorInputFieldValueTextColour = new(1f, 50.59f, 50.2f);
|
private readonly StyleColor _errorInputFieldValueTextColour = new Color(1f, 0.5059f, 0.502f);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// accompanying text for the account input fields, used when an error/notice is needed
|
/// accompanying text for the account input fields, used when an error/notice is needed
|
||||||
|
|
|
@ -519,6 +519,19 @@ public void GetRecentScores(Action<DatabaseTransactionResult, List<LocalPlayerDa
|
||||||
callback(DatabaseTransactionResult.Error, new List<LocalPlayerData.Score>(0));
|
callback(DatabaseTransactionResult.Error, new List<LocalPlayerData.Score>(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// abstraction function to get the user's best scores from the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback">
|
||||||
|
/// callback function that takes in a <c>DatabaseTransactionResult</c> enum and a
|
||||||
|
/// <c>List<LocalPlayerData.Score></c>
|
||||||
|
/// </param>
|
||||||
|
public void GetBestScores(Action<DatabaseTransactionResult, List<LocalPlayerData.Score>> callback)
|
||||||
|
{
|
||||||
|
// TODO: implement this
|
||||||
|
callback(DatabaseTransactionResult.Error, new List<LocalPlayerData.Score>(0));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// abstraction function to submit a score to the database
|
/// abstraction function to submit a score to the database
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -528,7 +541,29 @@ public void GetRecentScores(Action<DatabaseTransactionResult, List<LocalPlayerDa
|
||||||
LocalPlayerData.Score score,
|
LocalPlayerData.Score score,
|
||||||
Action<DatabaseTransactionResult> callback)
|
Action<DatabaseTransactionResult> callback)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
if (!Status.Equals(FirebaseConnectionStatus.Connected)) return;
|
||||||
|
|
||||||
|
if (_user == null)
|
||||||
|
{
|
||||||
|
callback(DatabaseTransactionResult.Unauthenticated);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_db.Child("scores")
|
||||||
|
.Push()
|
||||||
|
.SetValueAsync(score.ToDictionary())
|
||||||
|
.ContinueWithOnMainThread(task =>
|
||||||
|
{
|
||||||
|
if (task.IsCompletedSuccessfully)
|
||||||
|
{
|
||||||
|
callback(DatabaseTransactionResult.Ok);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError(task.Exception);
|
||||||
|
callback(DatabaseTransactionResult.Error);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -542,16 +577,42 @@ public void GetRecentScores(Action<DatabaseTransactionResult, List<LocalPlayerDa
|
||||||
public void CalculateUserRating(
|
public void CalculateUserRating(
|
||||||
Action<DatabaseTransactionResult, float> callback)
|
Action<DatabaseTransactionResult, float> callback)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
GetRecentScores((recentRes, recentScores) =>
|
||||||
|
{
|
||||||
|
if (recentRes == DatabaseTransactionResult.Error)
|
||||||
|
{
|
||||||
|
Debug.Log("failed to get recent scores");
|
||||||
|
callback(DatabaseTransactionResult.Error, 0f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var recentScoreQueue = GameManager.Instance.Data.RecentOnlineScores;
|
||||||
|
foreach (var score in recentScores) recentScoreQueue.Enqueue(score);
|
||||||
|
while (recentScoreQueue.Count > LocalPlayerData.MaxBestOnlineScores) recentScoreQueue.Dequeue();
|
||||||
|
|
||||||
|
GetBestScores((bestRes, bestScores) =>
|
||||||
|
{
|
||||||
|
if (bestRes == DatabaseTransactionResult.Error)
|
||||||
|
{
|
||||||
|
Debug.Log("failed to get recent scores");
|
||||||
|
callback(DatabaseTransactionResult.Error, 0f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bestScoreQueue = GameManager.Instance.Data.BestOnlineScores;
|
||||||
|
foreach (var score in recentScores) bestScoreQueue.Enqueue(score);
|
||||||
|
while (bestScoreQueue.Count > LocalPlayerData.MaxBestOnlineScores) bestScoreQueue.Dequeue();
|
||||||
|
|
||||||
|
callback(DatabaseTransactionResult.Ok, GameManager.Instance.Data.CalculateUserRating());
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// abstraction function to update the user's rating in the database
|
/// abstraction function to update the user's rating in the database
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="newRating">new user rating value as a float</param>
|
|
||||||
/// <param name="callback">callback function that takes in a <c>DatabaseTransactionResult</c> enum </param>
|
/// <param name="callback">callback function that takes in a <c>DatabaseTransactionResult</c> enum </param>
|
||||||
public void UpdateUserRating(
|
public void UpdateUserRating(
|
||||||
float newRating,
|
|
||||||
Action<DatabaseTransactionResult> callback)
|
Action<DatabaseTransactionResult> callback)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
|
|
|
@ -3,10 +3,58 @@
|
||||||
|
|
||||||
public static class Colorimetry
|
public static class Colorimetry
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// calculate a 0-100% distance/accuracy between two unity rgba colour objects
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="template">the template colour to compare against</param>
|
||||||
|
/// <param name="response">the response colour to compare</param>
|
||||||
|
/// <returns>a <c>DeltaLabCHE</c> struct</returns>
|
||||||
|
public static DeltaLabCHE CalculateDistance(Color template, Color response)
|
||||||
|
{
|
||||||
|
// rgb to oklab
|
||||||
|
var templateOklab = linear_srgb_to_oklab(new RGB(
|
||||||
|
(float)srgb_nonlinear_transform_f_inv(template.r),
|
||||||
|
(float)srgb_nonlinear_transform_f_inv(template.g),
|
||||||
|
(float)srgb_nonlinear_transform_f_inv(template.b)));
|
||||||
|
|
||||||
|
var responseOklab = linear_srgb_to_oklab(new RGB(
|
||||||
|
(float)srgb_nonlinear_transform_f_inv(response.r),
|
||||||
|
(float)srgb_nonlinear_transform_f_inv(response.g),
|
||||||
|
(float)srgb_nonlinear_transform_f_inv(response.b)));
|
||||||
|
|
||||||
|
// https://en.wikipedia.org/wiki/Oklab_color_space#Color_differences
|
||||||
|
// ... "The perceptual color difference in Oklab is calculated as the Euclidean
|
||||||
|
// ... distance between the (L, a, b) coordinates."
|
||||||
|
// https://github.com/svgeesus/svgeesus.github.io/blob/master/Color/OKLab-notes.md#color-difference-metric
|
||||||
|
// ... ΔL = L1 - L2
|
||||||
|
// ... C1 = √(a1² + b1²) -> chroma values
|
||||||
|
// ... C2 = √(a2² + b2²) -> chroma values
|
||||||
|
// ... ΔC = C1 - C2 -> chroma difference
|
||||||
|
// ... Δa = a1 - a2
|
||||||
|
// ... Δb = b1 - b2
|
||||||
|
// ... ΔH = √(Δa² + Δb² - ΔC²) -> hue difference
|
||||||
|
// ... ΔE = √(ΔL² + ΔC² + ΔH²) -> final difference
|
||||||
|
|
||||||
|
float l1, a1, b1, l2, a2, b2;
|
||||||
|
(l1, a1, b1) = (templateOklab.L, templateOklab.a, templateOklab.b);
|
||||||
|
(l2, a2, b2) = (responseOklab.L, responseOklab.a, responseOklab.b);
|
||||||
|
|
||||||
|
var deltaL = l1 - l2;
|
||||||
|
var c1 = Math.Sqrt(a1 * a1 + b1 * b1);
|
||||||
|
var c2 = Math.Sqrt(a2 * a2 + b2 * b2);
|
||||||
|
var deltaC = c1 - c2;
|
||||||
|
var deltaA = a1 - a2;
|
||||||
|
var deltaB = b1 - b2;
|
||||||
|
var deltaH = Math.Max(0d, Math.Sqrt(deltaA * deltaA + deltaB * deltaB - deltaC * deltaC));
|
||||||
|
var deltaE = Math.Sqrt(deltaL * deltaL + deltaC * deltaC + deltaH * deltaH);
|
||||||
|
|
||||||
|
return new DeltaLabCHE(deltaL, deltaA, deltaB, deltaC, deltaH, deltaE);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// convert the oklch colour to a unity rgba colour object
|
/// convert the oklch colour to a unity rgba colour object
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>a unity rgba color object</returns>
|
/// <returns>a unity rgba <c>Color</c> object</returns>
|
||||||
public static Color RawLchToColor(double lightness, double chroma, double hue)
|
public static Color RawLchToColor(double lightness, double chroma, double hue)
|
||||||
{
|
{
|
||||||
// clamp values
|
// clamp values
|
||||||
|
@ -55,7 +103,7 @@ public static double srgb_nonlinear_transform_f_inv(double x)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// clips a color to the sRGB gamut while preserving chroma
|
/// clips a colour to the sRGB gamut while preserving chroma
|
||||||
/// </summary>
|
/// </summary>
|
||||||
// https://bottosson.github.io/posts/gamutclipping/ (MIT)
|
// https://bottosson.github.io/posts/gamutclipping/ (MIT)
|
||||||
public static RGB gamut_clip_preserve_chroma(RGB rgb)
|
public static RGB gamut_clip_preserve_chroma(RGB rgb)
|
||||||
|
@ -331,6 +379,48 @@ public static float compute_max_saturation(float a, float b)
|
||||||
return maxSaturation;
|
return maxSaturation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public struct DeltaLabCHE
|
||||||
|
{
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public double dL;
|
||||||
|
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public double da;
|
||||||
|
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public double db;
|
||||||
|
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public double dC;
|
||||||
|
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public double dH;
|
||||||
|
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public double dE;
|
||||||
|
|
||||||
|
public DeltaLabCHE(
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
double L,
|
||||||
|
double a,
|
||||||
|
double b,
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
double C,
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
double H,
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
double E)
|
||||||
|
{
|
||||||
|
dL = L;
|
||||||
|
da = a;
|
||||||
|
db = b;
|
||||||
|
dC = C;
|
||||||
|
dH = H;
|
||||||
|
dE = E;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public readonly struct Lab
|
public readonly struct Lab
|
||||||
{
|
{
|
||||||
public readonly float L;
|
public readonly float L;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UIElements;
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
|
@ -34,7 +35,7 @@ public class GameManager : MonoBehaviour
|
||||||
public Backend Backend;
|
public Backend Backend;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// read-only property for accessing the local player data outside of this class
|
/// read-only property for accessing the local player data outside this class
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public LocalPlayerData Data => _data;
|
public LocalPlayerData Data => _data;
|
||||||
|
|
||||||
|
@ -112,11 +113,11 @@ private void OnEnable()
|
||||||
{
|
{
|
||||||
Debug.Log($"post-fcStatus change, deciding to show/hide buttons based on new status: {status}");
|
Debug.Log($"post-fcStatus change, deciding to show/hide buttons based on new status: {status}");
|
||||||
ui.UI.Q<Button>("LeaderboardButton").style.display =
|
ui.UI.Q<Button>("LeaderboardButton").style.display =
|
||||||
(status == Backend.FirebaseConnectionStatus.Connected)
|
status == Backend.FirebaseConnectionStatus.Connected
|
||||||
? DisplayStyle.Flex
|
? DisplayStyle.Flex
|
||||||
: DisplayStyle.None;
|
: DisplayStyle.None;
|
||||||
ui.UI.Q<Button>("AccountButton").style.display =
|
ui.UI.Q<Button>("AccountButton").style.display =
|
||||||
(status == Backend.FirebaseConnectionStatus.Connected)
|
status == Backend.FirebaseConnectionStatus.Connected
|
||||||
? DisplayStyle.Flex
|
? DisplayStyle.Flex
|
||||||
: DisplayStyle.None;
|
: DisplayStyle.None;
|
||||||
});
|
});
|
||||||
|
@ -158,4 +159,120 @@ private void FireLocalPlayerDataChangeCallbacks(LocalPlayerData data)
|
||||||
Debug.LogError($"error invoking LocalPlayerDataChangeCallback: {e.Message}");
|
Debug.LogError($"error invoking LocalPlayerDataChangeCallback: {e.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SignalGameEnd(List<Gameplay.RoundInfo> playedRounds)
|
||||||
|
{
|
||||||
|
Debug.Log("signalling game end");
|
||||||
|
|
||||||
|
// calculate historical averages
|
||||||
|
var historicalLightnessAcc = 0f;
|
||||||
|
var historicalChromaAcc = 0f;
|
||||||
|
var historicalHueAcc = 0f;
|
||||||
|
|
||||||
|
foreach (var localScore in _data.RecentLocalScores)
|
||||||
|
{
|
||||||
|
historicalLightnessAcc += localScore.AvgLightnessAccuracy;
|
||||||
|
historicalChromaAcc += localScore.AvgChromaAccuracy;
|
||||||
|
historicalHueAcc += localScore.AvgHueAccuracy;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var onlineScore in _data.RecentOnlineScores)
|
||||||
|
{
|
||||||
|
historicalLightnessAcc += onlineScore.AvgLightnessAccuracy;
|
||||||
|
historicalChromaAcc += onlineScore.AvgChromaAccuracy;
|
||||||
|
historicalHueAcc += onlineScore.AvgHueAccuracy;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var onlineScore in _data.BestOnlineScores)
|
||||||
|
{
|
||||||
|
historicalLightnessAcc += onlineScore.AvgLightnessAccuracy;
|
||||||
|
historicalChromaAcc += onlineScore.AvgChromaAccuracy;
|
||||||
|
historicalHueAcc += onlineScore.AvgHueAccuracy;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate round averages
|
||||||
|
var roundLightnessAcc = 0d;
|
||||||
|
var roundChromaAcc = 0d;
|
||||||
|
var roundHueAcc = 0d;
|
||||||
|
|
||||||
|
var maxDistance = Colorimetry.CalculateDistance(Color.black, Color.white);
|
||||||
|
|
||||||
|
foreach (var distance in playedRounds.Select(round =>
|
||||||
|
Colorimetry.CalculateDistance(round.TemplateColour, round.ResponseColour)))
|
||||||
|
{
|
||||||
|
roundLightnessAcc += distance.dL / maxDistance.dL;
|
||||||
|
roundChromaAcc += distance.dC / maxDistance.dC;
|
||||||
|
roundHueAcc += distance.dH / maxDistance.dH;
|
||||||
|
}
|
||||||
|
|
||||||
|
roundLightnessAcc /= playedRounds.Count;
|
||||||
|
roundChromaAcc /= playedRounds.Count;
|
||||||
|
roundHueAcc /= playedRounds.Count;
|
||||||
|
|
||||||
|
var roundAcc = (roundLightnessAcc + roundChromaAcc + roundHueAcc) / 3;
|
||||||
|
|
||||||
|
// make comparison texts
|
||||||
|
var lAccDeltaText = (roundLightnessAcc > historicalLightnessAcc ? "+" : "-") +
|
||||||
|
Math.Abs(roundLightnessAcc - historicalLightnessAcc).ToString("P");
|
||||||
|
var cAccDeltaText = (roundChromaAcc > historicalChromaAcc ? "+" : "-") +
|
||||||
|
Math.Abs(roundChromaAcc - historicalChromaAcc).ToString("P");
|
||||||
|
var hAccDeltaText = (roundHueAcc > historicalHueAcc ? "+" : "-") +
|
||||||
|
Math.Abs(roundHueAcc - historicalHueAcc).ToString("P");
|
||||||
|
|
||||||
|
var score = new LocalPlayerData.Score(DateTime.Now,
|
||||||
|
playedRounds.Count,
|
||||||
|
(float)roundLightnessAcc,
|
||||||
|
(float)roundChromaAcc,
|
||||||
|
(float)roundHueAcc);
|
||||||
|
|
||||||
|
_data.RegisterLocalScore(score);
|
||||||
|
Backend.SubmitScore(score,
|
||||||
|
submitRes =>
|
||||||
|
{
|
||||||
|
if (submitRes != Backend.DatabaseTransactionResult.Ok)
|
||||||
|
{
|
||||||
|
Debug.Log("couldn't submit score");
|
||||||
|
TransitionToResultsView(_data.CalculateUserRating());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Backend.CalculateUserRating((urcRes, userRating) =>
|
||||||
|
{
|
||||||
|
if (urcRes != Backend.DatabaseTransactionResult.Ok)
|
||||||
|
{
|
||||||
|
Debug.Log("couldn't calculate user rating");
|
||||||
|
TransitionToResultsView(_data.CalculateUserRating());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Backend.UpdateUserRating(updateRes =>
|
||||||
|
{
|
||||||
|
if (updateRes != Backend.DatabaseTransactionResult.Ok)
|
||||||
|
{
|
||||||
|
Debug.Log("calculated user rating but couldn't update it");
|
||||||
|
TransitionToResultsView(userRating);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TransitionToResultsView(userRating);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
void TransitionToResultsView(float rating)
|
||||||
|
{
|
||||||
|
var ratingText = rating >= 0 ? $"\nYour rating is {rating}" : "\nYour rating could not be calculated.";
|
||||||
|
|
||||||
|
// build the result text and show the results view
|
||||||
|
ui.UI.Q<Label>("ResultsText").text = string.Join(Environment.NewLine, $"Over {playedRounds.Count} rounds,",
|
||||||
|
$"you were {roundAcc} accurate.", "",
|
||||||
|
$"Lightness was {roundLightnessAcc}% accurate. ({lAccDeltaText} from your average)",
|
||||||
|
$"Chroma was {roundChromaAcc}% accurate. ({cAccDeltaText} from your average)",
|
||||||
|
$"Hue was {roundHueAcc}% accurate. ({hAccDeltaText} from your average)") + ratingText;
|
||||||
|
|
||||||
|
ui.SetDisplayState(UIManager.DisplayState.ResultsView);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
153
ColourMeOKGame/Assets/Scripts/Gameplay.cs
Normal file
153
ColourMeOKGame/Assets/Scripts/Gameplay.cs
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
using Random = System.Random;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// gameplay behaviour class
|
||||||
|
/// </summary>
|
||||||
|
public class Gameplay
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// countdown text label for showing the countdown
|
||||||
|
/// </summary>
|
||||||
|
private readonly Label _countdownText;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// list of played rounds
|
||||||
|
/// </summary>
|
||||||
|
private readonly List<RoundInfo> _playedRounds = new(5);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// response colour for the player to match
|
||||||
|
/// </summary>
|
||||||
|
private readonly VisualElement _responseColour;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// round text label for showing the current round
|
||||||
|
/// </summary>
|
||||||
|
private readonly Label _roundText;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// template colour for the player to match
|
||||||
|
/// </summary>
|
||||||
|
private readonly VisualElement _templateColour;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// game countdown timer
|
||||||
|
/// </summary>
|
||||||
|
private DateTime _countdownDatetime;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// game round counter
|
||||||
|
/// </summary>
|
||||||
|
private int _round = -1;
|
||||||
|
|
||||||
|
public int RoundsPerGame = 5;
|
||||||
|
public double SecondsPerRound = 15d;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// constructor for the gameplay class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ui">the visual element object for the ui document with the GameView</param>
|
||||||
|
private Gameplay(VisualElement ui)
|
||||||
|
{
|
||||||
|
_roundText = ui.Q<Label>("RoundText");
|
||||||
|
_countdownText = ui.Q<Label>("TimeText");
|
||||||
|
_templateColour = ui.Q<VisualElement>("TemplateColour");
|
||||||
|
_responseColour = ui.Q<VisualElement>("ResponseColour");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// function for starting the game
|
||||||
|
/// </summary>
|
||||||
|
private void StartGame()
|
||||||
|
{
|
||||||
|
_round = 0;
|
||||||
|
AdvanceToNextRound();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// called once per frame
|
||||||
|
/// </summary>
|
||||||
|
private void Update()
|
||||||
|
{
|
||||||
|
if (_round < 1) return;
|
||||||
|
if (_countdownDatetime < DateTime.Now) AdvanceToNextRound();
|
||||||
|
Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// function for advancing to the next round
|
||||||
|
/// </summary>
|
||||||
|
private void AdvanceToNextRound()
|
||||||
|
{
|
||||||
|
if (_round > 0) StoreRoundInfo();
|
||||||
|
GenerateNewTemplateColour();
|
||||||
|
|
||||||
|
if (_round < RoundsPerGame)
|
||||||
|
{
|
||||||
|
_round++;
|
||||||
|
_countdownDatetime = DateTime.Now.AddSeconds(SecondsPerRound);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// end game
|
||||||
|
_round = -1;
|
||||||
|
GameManager.Instance.SignalGameEnd(_playedRounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// function for storing the round information
|
||||||
|
/// </summary>
|
||||||
|
private void StoreRoundInfo()
|
||||||
|
{
|
||||||
|
_playedRounds.Add(new RoundInfo
|
||||||
|
{
|
||||||
|
TemplateColour = _templateColour.style.backgroundColor.value,
|
||||||
|
ResponseColour = _responseColour.style.backgroundColor.value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// function for generating a new template colour
|
||||||
|
/// (a random colour that isn't hard to visually match)
|
||||||
|
/// </summary>
|
||||||
|
private void GenerateNewTemplateColour()
|
||||||
|
{
|
||||||
|
var r = new Random();
|
||||||
|
|
||||||
|
// - lightness: 0.4-0.8
|
||||||
|
// - chroma: 0.0-0.2
|
||||||
|
// - hue: all (0-360)
|
||||||
|
|
||||||
|
var colour = Colorimetry.RawLchToColor(
|
||||||
|
Math.Clamp(r.NextDouble() * 0.4d + 0.4d, 0.4d, 0.8d),
|
||||||
|
Math.Clamp(r.NextDouble() * 0.2d, 0d, 0.2d),
|
||||||
|
Math.Clamp(r.NextDouble() * 360d, 0d, 360d)
|
||||||
|
);
|
||||||
|
|
||||||
|
_templateColour.style.backgroundColor = new StyleColor(colour);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// function for rendering the game state
|
||||||
|
/// </summary>
|
||||||
|
private void Render()
|
||||||
|
{
|
||||||
|
var remaining = (_countdownDatetime - DateTime.Now).TotalSeconds;
|
||||||
|
_roundText.text = $"{_round}/{RoundsPerGame}";
|
||||||
|
_countdownText.text = $"{remaining:F}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// struct for storing round information
|
||||||
|
/// </summary>
|
||||||
|
public struct RoundInfo
|
||||||
|
{
|
||||||
|
public Color TemplateColour;
|
||||||
|
public Color ResponseColour;
|
||||||
|
}
|
||||||
|
}
|
11
ColourMeOKGame/Assets/Scripts/Gameplay.cs.meta
Normal file
11
ColourMeOKGame/Assets/Scripts/Gameplay.cs.meta
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ac045ae5da8a0794496e2eb879e3b175
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
|
@ -5,11 +5,21 @@
|
||||||
|
|
||||||
public class LocalPlayerData
|
public class LocalPlayerData
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// maximum number of the best online scores to keep track of
|
||||||
|
/// </summary>
|
||||||
|
public const int MaxBestOnlineScores = 10;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// maximum number of recent local scores to keep track of
|
||||||
|
/// </summary>
|
||||||
|
public const int MaxRecentLocalScores = 10;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// queue of the best online scores,
|
/// queue of the best 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> BestOnlineScores = new(30);
|
public Queue<Score> BestOnlineScores = new(20);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// last known email used
|
/// last known email used
|
||||||
|
@ -77,7 +87,8 @@ public void LoadFromTheWorld(Action<LocalPlayerData> callback)
|
||||||
// if any of the values are invalid, don't add the score
|
// if any of the values are invalid, don't add the score
|
||||||
if (noOfRounds < 0 || l < 0 || c < 0 || h < 0) continue;
|
if (noOfRounds < 0 || l < 0 || c < 0 || h < 0) continue;
|
||||||
|
|
||||||
RegisterLocalScore(new Score(timestamp, noOfRounds, l, c, h));
|
RegisterLocalScore(new Score(timestamp, Math.Max(1, noOfRounds), Math.Clamp(l, 0f, 100f),
|
||||||
|
Math.Clamp(c, 0f, 100f), Math.Clamp(h, 0f, 100f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// load online scores
|
// load online scores
|
||||||
|
@ -92,6 +103,7 @@ public void LoadFromTheWorld(Action<LocalPlayerData> callback)
|
||||||
|
|
||||||
Debug.Log(
|
Debug.Log(
|
||||||
$"loaded lpdata from the world ({LastKnownUsername} <{LastKnownEmail}> with RLS.Count={RecentLocalScores.Count}, ROS.Count={RecentOnlineScores.Count}");
|
$"loaded lpdata from the world ({LastKnownUsername} <{LastKnownEmail}> with RLS.Count={RecentLocalScores.Count}, ROS.Count={RecentOnlineScores.Count}");
|
||||||
|
|
||||||
callback(this);
|
callback(this);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -125,10 +137,59 @@ public void SaveToTheWorld()
|
||||||
/// <param name="score">the score to register</param>
|
/// <param name="score">the score to register</param>
|
||||||
public void RegisterLocalScore(Score score)
|
public void RegisterLocalScore(Score score)
|
||||||
{
|
{
|
||||||
if (RecentLocalScores.Count > 10) RecentLocalScores.Dequeue();
|
while (RecentLocalScores.Count >= MaxRecentLocalScores) RecentLocalScores.Dequeue();
|
||||||
RecentLocalScores.Enqueue(score);
|
RecentLocalScores.Enqueue(score);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// calculates the user rating based on whatever local data is available
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>the user rating (0-100f)</returns>
|
||||||
|
public float CalculateUserRating()
|
||||||
|
{
|
||||||
|
// user rating is like CHUNITHM's rating system
|
||||||
|
// where best + recent scores are averaged out
|
||||||
|
// in this case 20 best scores, and 10 recent scores are used
|
||||||
|
|
||||||
|
// ensure the scores don't exceed their arbitrary limits
|
||||||
|
while (RecentOnlineScores.Count > MaxRecentLocalScores) RecentOnlineScores.Dequeue();
|
||||||
|
while (RecentLocalScores.Count > MaxRecentLocalScores) RecentLocalScores.Dequeue();
|
||||||
|
while (BestOnlineScores.Count > MaxBestOnlineScores) BestOnlineScores.Dequeue();
|
||||||
|
|
||||||
|
// if online scores are available, use them
|
||||||
|
var recentScores = RecentOnlineScores.Count > 0 ? RecentOnlineScores : RecentLocalScores;
|
||||||
|
var bestScores = BestOnlineScores;
|
||||||
|
|
||||||
|
var scores = 0;
|
||||||
|
var totalRating = 0d;
|
||||||
|
|
||||||
|
foreach (var score in recentScores)
|
||||||
|
{
|
||||||
|
scores++;
|
||||||
|
var dL = score.AvgLightnessAccuracy;
|
||||||
|
var dC = score.AvgChromaAccuracy;
|
||||||
|
var dH = score.AvgHueAccuracy;
|
||||||
|
var dE = Math.Sqrt(score.AvgLightnessAccuracy * score.AvgLightnessAccuracy
|
||||||
|
+ score.AvgChromaAccuracy * score.AvgChromaAccuracy
|
||||||
|
+ score.AvgHueAccuracy * score.AvgHueAccuracy);
|
||||||
|
totalRating = (dL + dC + dH + dE) / 4d;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var score in bestScores)
|
||||||
|
{
|
||||||
|
scores++;
|
||||||
|
var dL = score.AvgLightnessAccuracy;
|
||||||
|
var dC = score.AvgChromaAccuracy;
|
||||||
|
var dH = score.AvgHueAccuracy;
|
||||||
|
var dE = Math.Sqrt(score.AvgLightnessAccuracy * score.AvgLightnessAccuracy
|
||||||
|
+ score.AvgChromaAccuracy * score.AvgChromaAccuracy
|
||||||
|
+ score.AvgHueAccuracy * score.AvgHueAccuracy);
|
||||||
|
totalRating = (dL + dC + dH + dE) / 4d;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.Clamp((float)(totalRating / scores), 0f, 100f);
|
||||||
|
}
|
||||||
|
|
||||||
public struct Score
|
public struct Score
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -139,22 +200,22 @@ public struct Score
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// number of rounds played (0-100)
|
/// number of rounds played (0-100)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int NoOfRounds;
|
public readonly int NoOfRounds;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// average lightness accuracy across all rounds (0-100)
|
/// average lightness accuracy across all rounds (0-100)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float AvgLightnessAccuracy;
|
public readonly float AvgLightnessAccuracy;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// average chroma accuracy across all rounds (0-100)
|
/// average chroma accuracy across all rounds (0-100)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float AvgChromaAccuracy;
|
public readonly float AvgChromaAccuracy;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// average hue accuracy across all rounds (0-100)
|
/// average hue accuracy across all rounds (0-100)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float AvgHueAccuracy;
|
public readonly float AvgHueAccuracy;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// constructor for the score struct
|
/// constructor for the score struct
|
||||||
|
@ -173,5 +234,42 @@ public struct Score
|
||||||
AvgChromaAccuracy = c;
|
AvgChromaAccuracy = c;
|
||||||
AvgHueAccuracy = h;
|
AvgHueAccuracy = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// dict-based constructor for the score struct
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data">dictionary of the score data</param>
|
||||||
|
public Score(Dictionary<string, object> data)
|
||||||
|
{
|
||||||
|
// try to safely construct the score from a backend-provided dictionary
|
||||||
|
// for each value, if it's not found, or not a valid value, set it to a default value
|
||||||
|
Timestamp = data.ContainsKey("timestamp") && data["timestamp"] is long t
|
||||||
|
? DateTimeOffset.FromUnixTimeSeconds(t).DateTime
|
||||||
|
: DateTime.MinValue;
|
||||||
|
NoOfRounds = data.ContainsKey("noOfRounds") && data["noOfRounds"] is int n ? n : 1;
|
||||||
|
AvgLightnessAccuracy = data.ContainsKey("avgLightnessAccuracy") && data["avgLightnessAccuracy"] is float l
|
||||||
|
? l
|
||||||
|
: 100.0f;
|
||||||
|
AvgChromaAccuracy = data.ContainsKey("avgChromaAccuracy") && data["avgChromaAccuracy"] is float c
|
||||||
|
? c
|
||||||
|
: 100.0f;
|
||||||
|
AvgHueAccuracy = data.ContainsKey("avgHueAccuracy") && data["avgHueAccuracy"] is float h ? h : 100.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// converts the score struct to a dictionary safe for the backend
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Dictionary<string, object> ToDictionary()
|
||||||
|
{
|
||||||
|
return new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "timestamp", new DateTimeOffset(Timestamp).ToUnixTimeSeconds() },
|
||||||
|
{ "noOfRounds", NoOfRounds },
|
||||||
|
{ "avgLightnessAccuracy", AvgLightnessAccuracy },
|
||||||
|
{ "avgChromaAccuracy", AvgChromaAccuracy },
|
||||||
|
{ "avgHueAccuracy", AvgHueAccuracy }
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -58,14 +58,6 @@ private void Awake()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// initialise variables and register callbacks
|
|
||||||
/// </summary>
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
|
||||||
UI = GetComponent<UIDocument>().rootVisualElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// modify state of initial variables
|
/// modify state of initial variables
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -74,6 +66,14 @@ private void Start()
|
||||||
SetDisplayState(DisplayState.DefaultView);
|
SetDisplayState(DisplayState.DefaultView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// initialise variables and register callbacks
|
||||||
|
/// </summary>
|
||||||
|
private void OnEnable()
|
||||||
|
{
|
||||||
|
UI = GetComponent<UIDocument>().rootVisualElement;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// function to show a menu based on the enum passed,
|
/// function to show a menu based on the enum passed,
|
||||||
/// and any other necessary actions
|
/// and any other necessary actions
|
||||||
|
@ -140,11 +140,11 @@ public void SetDisplayState(DisplayState newDisplayState)
|
||||||
// if we're not in the game view, show everything!
|
// if we're not in the game view, show everything!
|
||||||
UI.Q<Button>("PlayButton").style.display = DisplayStyle.Flex;
|
UI.Q<Button>("PlayButton").style.display = DisplayStyle.Flex;
|
||||||
UI.Q<Button>("LeaderboardButton").style.display =
|
UI.Q<Button>("LeaderboardButton").style.display =
|
||||||
(GameManager.Instance.Backend.Status == Backend.FirebaseConnectionStatus.Connected)
|
GameManager.Instance.Backend.Status == Backend.FirebaseConnectionStatus.Connected
|
||||||
? DisplayStyle.Flex
|
? DisplayStyle.Flex
|
||||||
: DisplayStyle.None;
|
: DisplayStyle.None;
|
||||||
UI.Q<Button>("AccountButton").style.display =
|
UI.Q<Button>("AccountButton").style.display =
|
||||||
(GameManager.Instance.Backend.Status == Backend.FirebaseConnectionStatus.Connected)
|
GameManager.Instance.Backend.Status == Backend.FirebaseConnectionStatus.Connected
|
||||||
? DisplayStyle.Flex
|
? DisplayStyle.Flex
|
||||||
: DisplayStyle.None;
|
: DisplayStyle.None;
|
||||||
UI.Q<VisualElement>("AccountSection").style.display = DisplayStyle.Flex;
|
UI.Q<VisualElement>("AccountSection").style.display = DisplayStyle.Flex;
|
||||||
|
|
|
@ -1,130 +1,242 @@
|
||||||
<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">
|
<ui:UXML xmlns:ui="UnityEngine.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
<Style src="project://database/Assets/UI/GameUI.uss?fileID=7433441132597879392&guid=2c7ff79f21a3e8e408e76d75944d575b&type=3#GameUI" />
|
engine="UnityEngine.UIElements" editor="UnityEditor.UIElements"
|
||||||
<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;">
|
noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
|
||||||
<ui:VisualElement name="SideView" style="flex-grow: 0; background-color: rgb(15, 13, 27); flex-shrink: 0; width: 25%; justify-content: space-between;">
|
<Style src="project://database/Assets/UI/GameUI.uss?fileID=7433441132597879392&guid=2c7ff79f21a3e8e408e76d75944d575b&type=3#GameUI"/>
|
||||||
<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:VisualElement name="Root"
|
||||||
<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;" />
|
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="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 name="SideView"
|
||||||
|
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" style="flex-grow: 0; padding-right: 10%; padding-bottom: 10%; padding-left: 10%;">
|
<ui:VisualElement name="Content"
|
||||||
<ui:Button text="Play ↗" parse-escape-sequences="true" display-tooltip-when-elided="true" name="PlayButton" style="display: none;" />
|
style="flex-grow: 0; padding-right: 10%; padding-bottom: 10%; padding-left: 10%;">
|
||||||
<ui:Button text="Leaderboard ↗" parse-escape-sequences="true" display-tooltip-when-elided="true" name="LeaderboardButton" style="display: none;" />
|
<ui:Button text="Play ↗" parse-escape-sequences="true" display-tooltip-when-elided="true"
|
||||||
<ui:Button text="Account ↗" parse-escape-sequences="true" display-tooltip-when-elided="true" name="AccountButton" style="display: none;" />
|
name="PlayButton" style="display: none;"/>
|
||||||
<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; border-bottom-width: 1px; display: flex;">
|
<ui:Button text="Leaderboard ↗" parse-escape-sequences="true" display-tooltip-when-elided="true"
|
||||||
<ui:VisualElement name="PlayerDetails" style="flex-grow: 1; flex-direction: row; align-items: stretch; justify-content: space-between; font-size: 10px; align-self: stretch;">
|
name="LeaderboardButton" style="display: none;"/>
|
||||||
|
<ui:Button text="Account ↗" parse-escape-sequences="true" display-tooltip-when-elided="true"
|
||||||
|
name="AccountButton" style="display: none;"/>
|
||||||
|
<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; border-bottom-width: 1px; display: flex;">
|
||||||
|
<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" display-tooltip-when-elided="true" name="PlayerHeader" style="-unity-font-style: normal; font-size: 14px; padding-bottom: 0; -unity-text-align: lower-left;" />
|
<ui:Label tabindex="-1" text="Player" parse-escape-sequences="true"
|
||||||
<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;" />
|
display-tooltip-when-elided="true" name="PlayerHeader"
|
||||||
|
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" display-tooltip-when-elided="true" name="RatingHeader" style="-unity-font-style: normal; font-size: 14px; padding-bottom: 0; -unity-text-align: lower-right;" />
|
<ui:Label tabindex="-1" text="Rating" parse-escape-sequences="true"
|
||||||
<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;" />
|
display-tooltip-when-elided="true" name="RatingHeader"
|
||||||
|
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" 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="AccuracyDetails"
|
||||||
|
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 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;" />
|
<ui:Label tabindex="-1" text="Lightness Accuracy" parse-escape-sequences="true"
|
||||||
<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;" />
|
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;"/>
|
||||||
|
<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 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;" />
|
<ui:Label tabindex="-1" text="Chroma Accuracy" parse-escape-sequences="true"
|
||||||
<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;" />
|
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;"/>
|
||||||
|
<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 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;" />
|
<ui:Label tabindex="-1" text="Hue Accuracy" parse-escape-sequences="true"
|
||||||
<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;" />
|
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;"/>
|
||||||
|
<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="ConnectionStatus" style="flex-grow: 0; border-top-color: rgb(208, 152, 194); margin-top: 0; margin-right: 0; margin-bottom: 0; margin-left: 0; border-bottom-color: rgb(208, 152, 194); padding-bottom: 12px; display: flex; border-bottom-width: 1px;">
|
<ui:VisualElement name="ConnectionStatus"
|
||||||
<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; display: flex;" />
|
style="flex-grow: 0; border-top-color: rgb(208, 152, 194); margin-top: 0; margin-right: 0; margin-bottom: 0; margin-left: 0; border-bottom-color: rgb(208, 152, 194); padding-bottom: 12px; display: flex; border-bottom-width: 1px;">
|
||||||
|
<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; display: flex;"/>
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
<ui:VisualElement name="MainView" style="flex-grow: 0; flex-shrink: 0; width: 75%; justify-content: space-between;">
|
<ui:VisualElement name="MainView"
|
||||||
<ui:VisualElement name="DefaultView" style="flex-grow: 0; justify-content: space-around; height: 100%; align-self: stretch; display: none;">
|
style="flex-grow: 0; flex-shrink: 0; width: 75%; justify-content: space-between;">
|
||||||
<ui:VisualElement name="DemoResponseColour" style="flex-grow: 1; background-color: rgb(0, 0, 0); align-self: stretch; justify-content: center;">
|
<ui:VisualElement name="DefaultView"
|
||||||
<ui:VisualElement name="DemoResponseSliderContainer" style="flex-grow: 0; margin-top: 3.25%; margin-right: 3.25%; margin-bottom: 3.25%; margin-left: 3.25%; padding-top: 2%; padding-right: 2%; padding-bottom: 2%; padding-left: 2%; border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-right-radius: 8px; border-bottom-left-radius: 8px; background-color: rgb(208, 152, 194);">
|
style="flex-grow: 0; justify-content: space-around; height: 100%; align-self: stretch; display: none;">
|
||||||
<ui:Slider label="Lightness" high-value="100" name="DemoResponseLightnessSlider" class="lch-slider" />
|
<ui:VisualElement name="DemoResponseColour"
|
||||||
<ui:Slider label="Chroma" high-value="0.5" name="DemoResponseChromaSlider" class="lch-slider" />
|
style="flex-grow: 1; background-color: rgb(0, 0, 0); align-self: stretch; justify-content: center;">
|
||||||
<ui:Slider label="Hue" high-value="360" name="DemoResponseHueSlider" class="lch-slider" />
|
<ui:VisualElement name="DemoResponseSliderContainer"
|
||||||
|
style="flex-grow: 0; margin-top: 3.25%; margin-right: 3.25%; margin-bottom: 3.25%; margin-left: 3.25%; padding-top: 2%; padding-right: 2%; padding-bottom: 2%; padding-left: 2%; border-top-left-radius: 8px; border-top-right-radius: 8px; border-bottom-right-radius: 8px; border-bottom-left-radius: 8px; background-color: rgb(208, 152, 194);">
|
||||||
|
<ui:Slider label="Lightness" high-value="100" name="DemoResponseLightnessSlider"
|
||||||
|
class="lch-slider"/>
|
||||||
|
<ui:Slider label="Chroma" high-value="0.5" name="DemoResponseChromaSlider" class="lch-slider"/>
|
||||||
|
<ui:Slider label="Hue" high-value="360" name="DemoResponseHueSlider" class="lch-slider"/>
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
<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" 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="ColourPreview"
|
||||||
<ui:VisualElement name="TemplatePreview" style="flex-grow: 0; flex-shrink: 0; height: 100%; width: 49%;">
|
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: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="TemplatePreview"
|
||||||
<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);" />
|
style="flex-grow: 0; flex-shrink: 0; height: 100%; width: 49%;">
|
||||||
|
<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" style="flex-grow: 0; flex-shrink: 0; height: 100%; width: 49%;">
|
<ui:VisualElement name="ResponsePreview"
|
||||||
<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;" />
|
style="flex-grow: 0; flex-shrink: 0; height: 100%; width: 49%;">
|
||||||
<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: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: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="ResultsView" style="flex-grow: 1; display: flex; margin-top: 3.25%; margin-right: 3.25%; margin-bottom: 3.25%; margin-left: 3.25%; justify-content: space-between;">
|
<ui:VisualElement name="ResultsView"
|
||||||
<ui:VisualElement name="ColourShowcase" style="flex-grow: 1; 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; padding-top: 2%; padding-right: 2%; padding-bottom: 2%; padding-left: 2%; margin-bottom: 2%; margin-top: 0; margin-right: 0; margin-left: 0;">
|
style="flex-grow: 1; display: flex; margin-top: 3.25%; margin-right: 3.25%; margin-bottom: 3.25%; margin-left: 3.25%; justify-content: space-between;">
|
||||||
<ui:Label tabindex="-1" text="Templates" parse-escape-sequences="true" display-tooltip-when-elided="true" name="ShowcaseTemplatesText" style="-unity-text-align: upper-center; margin-top: 0; margin-right: 0; margin-bottom: 0; margin-left: 0; padding-top: 0; padding-right: 0; padding-bottom: 2%; padding-left: 0;" />
|
<ui:VisualElement name="ColourShowcase"
|
||||||
|
style="flex-grow: 1; 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; padding-top: 2%; padding-right: 2%; padding-bottom: 2%; padding-left: 2%; margin-bottom: 2%; margin-top: 0; margin-right: 0; margin-left: 0;">
|
||||||
|
<ui:Label tabindex="-1" text="Templates" parse-escape-sequences="true"
|
||||||
|
display-tooltip-when-elided="true" name="ShowcaseTemplatesText"
|
||||||
|
style="-unity-text-align: upper-center; margin-top: 0; margin-right: 0; margin-bottom: 0; margin-left: 0; padding-top: 0; padding-right: 0; padding-bottom: 2%; padding-left: 0;"/>
|
||||||
<ui:VisualElement name="Gallery" style="flex-grow: 1; flex-direction: row;">
|
<ui:VisualElement name="Gallery" style="flex-grow: 1; flex-direction: row;">
|
||||||
<ui:VisualElement name="ShowcasePair1" style="flex-grow: 1;">
|
<ui:VisualElement name="ShowcasePair1" style="flex-grow: 1;">
|
||||||
<ui:VisualElement name="ShowcasePair1TemplateColour" style="flex-grow: 1; background-color: rgb(15, 13, 27); border-top-left-radius: 8px;" />
|
<ui:VisualElement name="ShowcasePair1TemplateColour"
|
||||||
<ui:VisualElement name="ShowcasePair1ResponseColour" style="flex-grow: 1; border-bottom-left-radius: 8px; border-left-color: rgb(26, 22, 40); border-right-color: rgb(26, 22, 40); border-top-color: rgb(26, 22, 40); border-bottom-color: rgb(26, 22, 40); background-color: rgb(26, 22, 40);" />
|
style="flex-grow: 1; background-color: rgb(15, 13, 27); border-top-left-radius: 8px; border-bottom-left-radius: 8px;"/>
|
||||||
|
<ui:Label tabindex="-1" text="100% 100% 100% (100%)" parse-escape-sequences="true"
|
||||||
|
display-tooltip-when-elided="true" name="ShowcasePair1Info"
|
||||||
|
style="-unity-text-align: upper-center; font-size: 18px;"/>
|
||||||
|
<ui:VisualElement name="ShowcasePair1ResponseColour"
|
||||||
|
style="flex-grow: 1; border-bottom-left-radius: 8px; border-left-color: rgb(26, 22, 40); border-right-color: rgb(26, 22, 40); border-top-color: rgb(26, 22, 40); border-bottom-color: rgb(26, 22, 40); background-color: rgb(26, 22, 40); border-top-left-radius: 8px;"/>
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
<ui:VisualElement name="ShowcasePair2" style="flex-grow: 1;">
|
<ui:VisualElement name="ShowcasePair2" style="flex-grow: 1;">
|
||||||
<ui:VisualElement name="ShowcasePair2TemplateColour" style="flex-grow: 1; background-color: rgb(42, 33, 56);" />
|
<ui:VisualElement name="ShowcasePair2TemplateColour"
|
||||||
<ui:VisualElement name="ShowcasePair2ResponseColour" style="flex-grow: 1; background-color: rgb(63, 48, 76);" />
|
style="flex-grow: 1; background-color: rgb(42, 33, 56);"/>
|
||||||
|
<ui:Label tabindex="-1" text="100% 100% 100% (100%)" parse-escape-sequences="true"
|
||||||
|
display-tooltip-when-elided="true" name="ShowcasePair2Info"
|
||||||
|
style="-unity-text-align: upper-center; font-size: 18px;"/>
|
||||||
|
<ui:VisualElement name="ShowcasePair2ResponseColour"
|
||||||
|
style="flex-grow: 1; background-color: rgb(63, 48, 76);"/>
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
<ui:VisualElement name="ShowcasePair3" style="flex-grow: 1;">
|
<ui:VisualElement name="ShowcasePair3" style="flex-grow: 1;">
|
||||||
<ui:VisualElement name="ShowcasePair3TemplateColour" style="flex-grow: 1; background-color: rgb(63, 48, 76);" />
|
<ui:VisualElement name="ShowcasePair3TemplateColour"
|
||||||
<ui:VisualElement name="ShowcasePair3ResponseColour" style="flex-grow: 1; background-color: rgb(89, 67, 100);" />
|
style="flex-grow: 1; background-color: rgb(63, 48, 76);"/>
|
||||||
|
<ui:Label tabindex="-1" text="100% 100% 100% (100%)" parse-escape-sequences="true"
|
||||||
|
display-tooltip-when-elided="true" name="ShowcasePair3Info"
|
||||||
|
style="-unity-text-align: upper-center; font-size: 18px;"/>
|
||||||
|
<ui:VisualElement name="ShowcasePair3ResponseColour"
|
||||||
|
style="flex-grow: 1; background-color: rgb(89, 67, 100);"/>
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
<ui:VisualElement name="ShowcasePair4" style="flex-grow: 1;">
|
<ui:VisualElement name="ShowcasePair4" style="flex-grow: 1;">
|
||||||
<ui:VisualElement name="ShowcasePair4TemplateColour" style="flex-grow: 1; background-color: rgb(89, 67, 100);" />
|
<ui:VisualElement name="ShowcasePair4TemplateColour"
|
||||||
<ui:VisualElement name="ShowcasePair4ResponseColour" style="flex-grow: 1; background-color: rgb(122, 90, 126);" />
|
style="flex-grow: 1; background-color: rgb(89, 67, 100);"/>
|
||||||
|
<ui:Label tabindex="-1" text="100% 100% 100% (100%)" parse-escape-sequences="true"
|
||||||
|
display-tooltip-when-elided="true" name="ShowcasePair4Info"
|
||||||
|
style="-unity-text-align: upper-center; font-size: 18px;"/>
|
||||||
|
<ui:VisualElement name="ShowcasePair4ResponseColour"
|
||||||
|
style="flex-grow: 1; background-color: rgb(122, 90, 126);"/>
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
<ui:VisualElement name="ShowcasePair5" style="flex-grow: 1;">
|
<ui:VisualElement name="ShowcasePair5" style="flex-grow: 1;">
|
||||||
<ui:VisualElement name="ShowcasePair5TemplateColour" style="flex-grow: 1; background-color: rgb(162, 118, 158); border-top-right-radius: 8px;" />
|
<ui:VisualElement name="ShowcasePair5TemplateColour"
|
||||||
<ui:VisualElement name="ShowcasePair5ResponseColour" style="flex-grow: 1; background-color: rgb(208, 152, 194); border-bottom-right-radius: 8px;" />
|
style="flex-grow: 1; background-color: rgb(162, 118, 158); border-top-right-radius: 8px; border-bottom-right-radius: 8px;"/>
|
||||||
|
<ui:Label tabindex="-1" text="100% 100% 100% (100%)" parse-escape-sequences="true"
|
||||||
|
display-tooltip-when-elided="true" name="ShowcasePair5Info"
|
||||||
|
style="-unity-text-align: upper-center; font-size: 18px;"/>
|
||||||
|
<ui:VisualElement name="ShowcasePair5ResponseColour"
|
||||||
|
style="flex-grow: 1; background-color: rgb(208, 152, 194); border-top-right-radius: 8px; border-bottom-right-radius: 8px;"/>
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
<ui:Label tabindex="-1" text="Responses" parse-escape-sequences="true" display-tooltip-when-elided="true" name="ShowcaseResponsesText" style="-unity-text-align: upper-center; padding-top: 1.5%; padding-right: 0; padding-bottom: 0; padding-left: 0; margin-top: 0; margin-right: 0; margin-bottom: 0; margin-left: 0;" />
|
<ui:Label tabindex="-1" text="Responses" parse-escape-sequences="true"
|
||||||
|
display-tooltip-when-elided="true" name="ShowcaseResponsesText"
|
||||||
|
style="-unity-text-align: upper-center; padding-top: 1.5%; padding-right: 0; padding-bottom: 0; padding-left: 0; margin-top: 0; margin-right: 0; margin-bottom: 0; margin-left: 0;"/>
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
<ui:Label tabindex="-1" text="Over n rounds, you were 100.00% accurate. Lightness was 100.00% accurate. (+100.00% from your average) Chroma was 100.00% accurate. (+100.00% from your average) Hue was 100.00% accurate. (+100.00% from your average) Your RATING has increased by 100.00%." parse-escape-sequences="true" display-tooltip-when-elided="true" name="ResultsText" style="flex-grow: 0; font-size: 32px; margin-top: 2%; margin-right: 0; margin-bottom: 0; margin-left: 0; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0;" />
|
<ui:Label tabindex="-1"
|
||||||
|
text="Over n rounds, you were 100.00% accurate. Lightness was 100.00% accurate. (+100.00% from your average) Chroma was 100.00% accurate. (+100.00% from your average) Hue was 100.00% accurate. (+100.00% from your average) Your RATING has increased by 100.00%."
|
||||||
|
parse-escape-sequences="true" display-tooltip-when-elided="true" name="ResultsText"
|
||||||
|
style="flex-grow: 0; margin-top: 2%; margin-right: 0; margin-bottom: 0; margin-left: 0; padding-top: 0; padding-right: 0; padding-bottom: 0; padding-left: 0;"/>
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
<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;">
|
<ui:VisualElement name="LeaderboardView"
|
||||||
<ui:Label tabindex="-1" text="Leaderboard" parse-escape-sequences="true" display-tooltip-when-elided="true" name="LeaderboardHeader" style="font-size: 58px; -unity-font-style: normal;" />
|
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:ListView name="LeaderboardListView" />
|
<ui:Label tabindex="-1" text="Leaderboard" parse-escape-sequences="true"
|
||||||
|
display-tooltip-when-elided="true" name="LeaderboardHeader"
|
||||||
|
style="font-size: 58px; -unity-font-style: normal;"/>
|
||||||
|
<ui:ListView name="LeaderboardListView"/>
|
||||||
</ui:VisualElement>
|
</ui:VisualElement>
|
||||||
<ui:VisualElement name="AccountView" 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:VisualElement name="AccountView"
|
||||||
<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;" />
|
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="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" style="flex-grow: 1; flex-direction: row; justify-content: space-between;">
|
<ui:VisualElement name="UsernameContainer"
|
||||||
<ui:TextField picking-mode="Ignore" label="Username" name="UsernameField" />
|
style="flex-grow: 1; flex-direction: row; justify-content: space-between;">
|
||||||
<ui:Button text="Update" parse-escape-sequences="true" display-tooltip-when-elided="true" name="UsernameUpdateButton" />
|
<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:VisualElement>
|
</ui:VisualElement>
|
||||||
<ui:VisualElement name="EmailContainer" style="flex-grow: 1; flex-direction: row; justify-content: space-between;">
|
<ui:VisualElement name="EmailContainer"
|
||||||
<ui:TextField picking-mode="Ignore" label="Email" name="EmailField" keyboard-type="EmailAddress" />
|
style="flex-grow: 1; flex-direction: row; justify-content: space-between;">
|
||||||
<ui:Button text="Update" parse-escape-sequences="true" display-tooltip-when-elided="true" name="EmailUpdateButton" />
|
<ui:TextField picking-mode="Ignore" label="Email" name="EmailField"
|
||||||
|
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" style="flex-grow: 1; flex-direction: row; justify-content: space-between;">
|
<ui:VisualElement name="PasswordContainer"
|
||||||
<ui:TextField picking-mode="Ignore" label="Password" name="PasswordField" password="true" />
|
style="flex-grow: 1; flex-direction: row; justify-content: space-between;">
|
||||||
<ui:Button text="Update" parse-escape-sequences="true" display-tooltip-when-elided="true" name="PasswordUpdateButton" />
|
<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:VisualElement>
|
</ui:VisualElement>
|
||||||
<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;" />
|
<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;"/>
|
||||||
</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" 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;" />
|
<ui:Button text="Primary Action Button →" parse-escape-sequences="true"
|
||||||
<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;" />
|
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;"/>
|
||||||
|
<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>
|
||||||
|
|
Reference in a new issue