This page documents the internal architecture of the Progress Bar system. Use this guide when you need to:
The Progress Bar system uses a separation of concerns architecture:
Pure data container holding all state and configuration. UI-agnostic—can be used with any rendering system.
public class ProgressBarData
{
// Animation settings
public bool InstantPositive { get; set; }
public bool InstantNegative { get; set; }
public long UpdateFrequency { get; set; }
public float Step { get; set; }
public long FirstDelay { get; set; }
public long SecondDelay { get; set; }
// Progress segments
public ProgressBarNode[] Segments { get; set; }
public ProgressBarNode Indicator { get; set; }
// Indicator appearance
public bool IndicatorAutoColor { get; set; }
public Color IndicatorColorPositive { get; set; }
public Color IndicatorColorNegative { get; set; }
}Represents a single progress segment with current/target values and color.
public class ProgressBarNode
{
public float CurrentValue { get; set; } // 0-1, actual displayed value
public float TargetValue { get; set; } // 0-1, value animating toward
public Color Color { get; set; }
// Silent setters (no events)
public void SetCurrentValueSilent(float value);
public void SetTargetValueSilent(float value);
}Generic animation orchestrator that works with any UI element type. Handles:
public class ProgressBarController<TElement> : IDisposable
{
public ProgressBarController(
TElement element,
Func<TElement, ProgressBarData> dataGetter,
IProgressBarAnimator animator,
IProgressBarNodeUpdater nodeUpdater,
IProgressBarVisualUpdater<TElement> visualUpdater
);
public void PlayProgress();
public void PlayIndicator();
public void Dispose();
}Controls animation scheduling. Default implementation uses IVisualElementScheduledItem.
public interface IProgressBarAnimator
{
void Start(long delayMs, long intervalMs, Action<TimerState> callback);
void Stop();
}Updates a single node's CurrentValue toward TargetValue.
public interface IProgressBarNodeUpdater
{
/// <summary>
/// Updates node's CurrentValue toward TargetValue.
/// Returns true when animation is complete.
/// </summary>
bool Update(ProgressBarNode node, float step);
}Applies data changes to the actual UI element.
public interface IProgressBarVisualUpdater<TElement>
{
void UpdateSegmentVisual(TElement element, int index, ProgressBarNode node);
void UpdateIndicatorVisual(TElement element, ProgressBarNode indicator, bool isPositive);
}public class MyCustomProgressBar : VisualElement
{
// Your custom rendering logic
private ProgressBarData _data;
private ProgressBarController<MyCustomProgressBar> _controller;
public MyCustomProgressBar()
{
_data = new ProgressBarData
{
Segments = new[] { new ProgressBarNode() },
Indicator = new ProgressBarNode()
};
}
}public class MyCustomVisualUpdater : IProgressBarVisualUpdater<MyCustomProgressBar>
{
public void UpdateSegmentVisual(MyCustomProgressBar element, int index, ProgressBarNode node)
{
// Your custom rendering logic
// e.g., update shader parameters, move sprites, etc.
}
public void UpdateIndicatorVisual(MyCustomProgressBar element, ProgressBarNode indicator, bool isPositive)
{
// Update indicator appearance
}
}public class MyCustomProgressBar : VisualElement
{
public MyCustomProgressBar()
{
_data = new ProgressBarData { /* ... */ };
_controller = new ProgressBarController<MyCustomProgressBar>(
this,
el => el._data,
new ProgressBarScheduledAnimator(this),
new DefaultProgressBarNodeUpdater(),
new MyCustomVisualUpdater()
);
}
public void PlayProgress() => _controller.PlayProgress();
public void PlayIndicator() => _controller.PlayIndicator();
}When PlayProgress() is called:
width style propertyMeshGenerationContext for custom arc renderingProgressBar/
├── Core/
│ ├── ProgressBarData.cs # Pure data container
│ ├── ProgressBarNode.cs # Single segment data
│ └── ProgressBarController.cs # Animation orchestration
├── Interfaces/
│ ├── IProgressBarAnimator.cs # Animation scheduling
│ ├── IProgressBarNodeUpdater.cs # Value interpolation
│ └── IProgressBarVisualUpdater.cs # Visual rendering
└── UIToolkit/
├── ProgressBar.cs # Rectangular implementation
├── RadialProgressBar.cs # Circular implementation
├── Animators/
│ └── ProgressBarScheduledAnimator.cs
├── NodeUpdaters/
│ └── DefaultProgressBarNodeUpdater.cs
└── VisualUpdaters/
├── ProgressBarVisualUpdater.cs
└── RadialProgressBarVisualUpdater.csProgressBarData for all state managementIDisposable pattern in controllersInstant* to true during initialization, then falsePlayProgress() and PlayIndicator() after changing valuesCurrentValue directly—use TargetValueRebuildSegments() after changing segment countSettings
Theme
Light
Contrast
Material
Dark
Dim
Material Dark
System
Sidebar(Light & Contrast only)
Font Family
DM Sans
Wix
Inclusive Sans
AR One Sans
Direction