using System.Linq; using UnityEngine; using UnityEngine.UIElements; namespace BITKit.UX { // An element that displays progress inside a partially filled circle public class ComplexRadialProgress : VisualElement { public new class UxmlTraits : VisualElement.UxmlTraits { // The progress property is exposed to UXML. private readonly UxmlStringAttributeDescription m_ProgressAttribute = new UxmlStringAttributeDescription() { name = "progress" }; // Use the Init method to assign the value of the progress UXML attribute to the C# progress property. public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc) { base.Init(ve, bag, cc); ((ComplexRadialProgress)ve).progress = m_ProgressAttribute.GetValueFromBag(bag, cc); } } // Define a factory class to expose this control to UXML. public new class UxmlFactory : UxmlFactory { } // These are USS class names for the control overall and the label. public static readonly string ussClassName = "radial-progress"; public static readonly string ussLabelClassName = "radial-progress__label"; private Color[] m_ProgressColor = new Color[] { Color.red, Color.yellow, Color.blue, Color.green, Color.cyan, Color.magenta, Color.white, Color.blue, }; // This is the label that displays the percentage. private Label m_Label; // This is the number that the Label displays as a percentage. private string m_Progress; // A value between 0 and 100 public string progress { // The progress property is exposed in C#. get => m_Progress; set { // Whenever the progress property changes, MarkDirtyRepaint() is named. This causes a call to the // generateVisualContents callback. m_Progress = value; MarkDirtyRepaint(); } } // This default constructor is RadialProgress's only constructor. public ComplexRadialProgress() { // Add the USS class name for the overall control. AddToClassList(ussClassName); // Register a callback after custom style resolution. RegisterCallback(evt => CustomStylesResolved(evt)); // Register a callback to generate the visual content of the control. generateVisualContent += GenerateVisualContent; progress = string.Empty; } private static void CustomStylesResolved(CustomStyleResolvedEvent evt) { ComplexRadialProgress element = (ComplexRadialProgress)evt.currentTarget; element.UpdateCustomStyles(); } // After the custom colors are resolved, this method uses them to color the meshes and (if necessary) repaint // the control. private void UpdateCustomStyles() { for (var i = 0; i < 8; i++) { if (customStyle.TryGetValue(new CustomStyleProperty($"--progress-color--{i}"), out var color)) { m_ProgressColor[i] = color; } else { m_ProgressColor[i] = Color.red; } } MarkDirtyRepaint(); } private void GenerateVisualContent(MeshGenerationContext context) { var width = contentRect.width; var height = contentRect.height; var painter = context.painter2D; painter.lineWidth = 4.0f; painter.lineCap = LineCap.Butt; var tempColor = m_ProgressColor.First(); // // Draw the track // painter.strokeColor = m_TrackColor; // painter.BeginPath(); // painter.Arc(new Vector2(width * 0.5f, height * 0.5f), width * 0.5f - 5 , 0.0f, 360.0f); // painter.Stroke(); var lastEndAngle = -90f; var index = 0; foreach (var str in progress.Split(",")) { if(float.TryParse(str,out var nextProgress) is false)continue; if (nextProgress <= 0) continue; var startAngle =lastEndAngle; //startAngle = Mathf.Lerp(-90f, 480f, nextProgress); var endAngle = 360.0f * (nextProgress) + startAngle; lastEndAngle = endAngle; startAngle +=2; endAngle -= 2; // Draw the progress Out painter.strokeColor = m_ProgressColor[index]; painter.BeginPath(); painter.Arc(new Vector2(width * 0.5f, height * 0.5f), width * 0.5f, startAngle,endAngle ); painter.Stroke(); // Draw the progress Middle tempColor = m_ProgressColor[index]; tempColor.a = tempColor.a / 3f * 2f; painter.strokeColor = tempColor; painter.BeginPath(); painter.Arc(new Vector2(width * 0.5f, height * 0.5f), width * 0.5f -4f, startAngle, endAngle); painter.Stroke(); // Draw the progress Inner tempColor = m_ProgressColor[index]; tempColor.a = tempColor.a / 3f * 1f; painter.strokeColor = tempColor; painter.BeginPath(); painter.Arc(new Vector2(width * 0.5f, height * 0.5f), width * 0.5f-8f, startAngle, endAngle); painter.Stroke(); index++; } } } }