Added UI Toolkit Progress
This commit is contained in:
parent
21b4f9091a
commit
d502501b27
|
@ -0,0 +1,55 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
|
||||
namespace BITKit
|
||||
{
|
||||
public static class DisplayAttributeExtensions
|
||||
{
|
||||
public static string GetDisplayName(this PropertyInfo self)
|
||||
{
|
||||
if (self.GetCustomAttribute<DisplayNameAttribute>() is not { } displayNameAttribute) return self.Name;
|
||||
var name = displayNameAttribute.DisplayName;
|
||||
return string.IsNullOrEmpty(name) ? self.Name : name;
|
||||
}
|
||||
public static string GetDisplayName(this FieldInfo self)
|
||||
{
|
||||
if (self.GetCustomAttribute<DisplayNameAttribute>() is not { } displayNameAttribute) return self.Name;
|
||||
var name = displayNameAttribute.DisplayName;
|
||||
return string.IsNullOrEmpty(name) ? self.Name : name;
|
||||
}
|
||||
public static string GetDisplayName(this object self)
|
||||
{
|
||||
{
|
||||
if (self.GetType().GetCustomAttribute<DisplayNameAttribute>() is { } displayNameAttribute)
|
||||
{
|
||||
return displayNameAttribute.DisplayName;
|
||||
}
|
||||
|
||||
if (self.GetType().GetCustomAttribute<DisplayAttribute>() is { } displayAttribute)
|
||||
{
|
||||
return displayAttribute.Name;
|
||||
}
|
||||
}
|
||||
{
|
||||
if (self is Enum)
|
||||
{
|
||||
var field = self.GetType().GetField(self.ToString()!);
|
||||
|
||||
if (field.GetCustomAttribute<DisplayNameAttribute>() is DisplayNameAttribute displayNameAttribute)
|
||||
{
|
||||
return displayNameAttribute.DisplayName;
|
||||
}
|
||||
|
||||
if (field.GetCustomAttribute<DisplayAttribute>() is DisplayAttribute displayAttribute)
|
||||
{
|
||||
return displayAttribute.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return self.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,6 +11,10 @@ namespace BITKit
|
|||
public static async UniTask<string> PostJsonAsync(this HttpClient self, string requestUrl, object value , CancellationToken cancellationToken=default)
|
||||
{
|
||||
var json = JsonConvert.SerializeObject(value);
|
||||
if (value is string j)
|
||||
{
|
||||
json = j;
|
||||
}
|
||||
var content = new StringContent(json, Encoding.UTF8, "application/json");
|
||||
var response =await self.PostAsync(requestUrl, content, cancellationToken);
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Timers;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace BITKit
|
||||
{
|
||||
|
@ -34,6 +39,16 @@ namespace BITKit
|
|||
void ManualTick(float delta);
|
||||
}
|
||||
/// <summary>
|
||||
/// 异步循环
|
||||
/// </summary>
|
||||
public interface IAsyncTicker
|
||||
{
|
||||
ulong TickCount { get; }
|
||||
int TickRate { get; set; }
|
||||
bool IsConcurrent { get; set; }
|
||||
event Func<float, UniTask> OnTickAsync;
|
||||
}
|
||||
/// <summary>
|
||||
/// 主线程循环
|
||||
/// </summary>
|
||||
public interface IMainTicker : ITicker { }
|
||||
|
@ -53,7 +68,106 @@ namespace BITKit
|
|||
/// </summary>
|
||||
public interface IFixedTicker : ITicker{}
|
||||
#endif
|
||||
|
||||
public class AsyncTicker : IAsyncTicker,IDisposable
|
||||
{
|
||||
private readonly ILogger<AsyncTicker> _logger;
|
||||
private readonly Timer _timer=new();
|
||||
private bool _isDisposed;
|
||||
private readonly Stopwatch _stopwatch=new();
|
||||
|
||||
public AsyncTicker(ILogger<AsyncTicker> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
if (TickRate <= 0)
|
||||
{
|
||||
TickRate = 1;
|
||||
}
|
||||
|
||||
_timer.Elapsed += OnElapsed;
|
||||
|
||||
if (_isDisposed is false)
|
||||
_timer.Start();
|
||||
|
||||
_logger.LogInformation($"异步循环就绪,TickRate:{TickRate}");
|
||||
}
|
||||
#if UNITY_5_3_OR_NEWER
|
||||
[UnityEngine.HideInCallstack]
|
||||
#endif
|
||||
private async void OnElapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(_isDisposed)return;
|
||||
|
||||
if (IsSyncContext)
|
||||
{
|
||||
await BITApp.SwitchToMainThread();
|
||||
if(_isDisposed)return;
|
||||
}
|
||||
|
||||
var deltaTime = 1f / TickRate;
|
||||
if (_stopwatch.IsRunning)
|
||||
{
|
||||
deltaTime = (float)_stopwatch.Elapsed.TotalSeconds;
|
||||
_stopwatch.Reset();
|
||||
}
|
||||
|
||||
_stopwatch.Start();
|
||||
|
||||
if (IsConcurrent)
|
||||
{
|
||||
var tasks = OnTickAsync.CastAsFunc().ToArray();
|
||||
|
||||
foreach (var func in tasks)
|
||||
{
|
||||
if (_isDisposed) return;
|
||||
|
||||
try
|
||||
{
|
||||
await func.Invoke(deltaTime);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_logger.LogCritical(exception,exception.Message);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
await OnTickAsync.UniTaskFunc(deltaTime);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_logger.LogCritical(exception,exception.Message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
_logger.LogCritical(exception,exception.Message);
|
||||
}
|
||||
TickCount++;
|
||||
|
||||
if(_isDisposed)return;
|
||||
_timer.Start();
|
||||
}
|
||||
|
||||
public bool IsSyncContext { get; set; } = true;
|
||||
public ulong TickCount { get; set; }
|
||||
public int TickRate { get; set; }
|
||||
public bool IsConcurrent { get; set; }
|
||||
public event Func<float, UniTask> OnTickAsync;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class Ticker : ITicker
|
||||
{
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace BITKit
|
|||
public void Dispose()
|
||||
{
|
||||
_stopwatch.Stop();
|
||||
_logger.LogInformation($"已完成:{_message},耗时{_stopwatch.Elapsed}");
|
||||
_logger.LogInformation($"已完成:{_message},耗时{_stopwatch.ElapsedMilliseconds}ms");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -95,7 +95,10 @@ namespace BITKit
|
|||
stopwatch.Start();
|
||||
DontDestroyOnLoad(gameObject);
|
||||
// 初始化资源系统
|
||||
YooAssets.Initialize();
|
||||
if (YooAssets.Initialized is false)
|
||||
YooAssets.Initialize();
|
||||
|
||||
|
||||
|
||||
// 创建默认的资源包
|
||||
var package = YooAssets.TryGetPackage(packageName.Value) ?? YooAssets.CreatePackage(packageName.Value);
|
||||
|
@ -103,12 +106,25 @@ namespace BITKit
|
|||
// 设置该资源包为默认的资源包,可以使用YooAssets相关加载接口加载该资源包内容。
|
||||
YooAssets.SetDefaultPackage(package);
|
||||
|
||||
if (package.InitializeStatus is EOperationStatus.Succeed)
|
||||
{
|
||||
YooAssets.DestroyPackage(package.PackageName);
|
||||
}
|
||||
|
||||
|
||||
InitializeParameters initParameters = new HostPlayModeParameters
|
||||
{
|
||||
BuildinQueryServices = buildinQueryServices,
|
||||
RemoteServices = remoteServices
|
||||
};
|
||||
if (Application.platform is RuntimePlatform.WebGLPlayer)
|
||||
{
|
||||
initParameters = new WebPlayModeParameters()
|
||||
{
|
||||
BuildinQueryServices = buildinQueryServices,
|
||||
RemoteServices = remoteServices
|
||||
};
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
if (IsEditorSimulateMode)
|
||||
{
|
||||
|
@ -120,8 +136,21 @@ namespace BITKit
|
|||
EditorSimulateModeHelper.SimulateBuild("ScriptableBuildPipeline", packageName.Value)
|
||||
};
|
||||
initParameters = editorParameters;
|
||||
}else
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (UnityEditor.EditorUserBuildSettings.activeBuildTarget)
|
||||
{
|
||||
case UnityEditor.BuildTarget.WebGL:
|
||||
initParameters = new WebPlayModeParameters()
|
||||
{
|
||||
BuildinQueryServices = buildinQueryServices,
|
||||
RemoteServices = remoteServices
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (isOffline)
|
||||
{
|
||||
initParameters = new OfflinePlayModeParameters();
|
||||
|
@ -304,6 +333,9 @@ namespace BITKit
|
|||
|
||||
SceneManager.LoadScene(1);
|
||||
}
|
||||
|
||||
if (document)
|
||||
Destroy(document);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -311,13 +343,14 @@ namespace BITKit
|
|||
_progressBar.value =0;
|
||||
_progressLabel.text = e.Message;
|
||||
}
|
||||
if (document)
|
||||
Destroy(document);
|
||||
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
YooAssets.Destroy();
|
||||
#if UNITY_EDITOR
|
||||
YooAssets.Destroy();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
"GUID:d525ad6bd40672747bde77962f1c401e",
|
||||
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b",
|
||||
"GUID:6de01b04fa4e14662b03fa46366da151",
|
||||
"GUID:f19bbd83e3c264a5680926bf75d7e494",
|
||||
"GUID:1c2aa13aa706ffc49a1a0044cad55436"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
|
@ -17,9 +15,7 @@
|
|||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [
|
||||
"_SkiaSharp"
|
||||
],
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
|
@ -5,14 +5,13 @@ using System.Globalization;
|
|||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using SkiaSharp;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
|
||||
namespace BITKit.UX
|
||||
{
|
||||
public class SkiaChart : VisualElement
|
||||
public class LineChart : VisualElement
|
||||
{
|
||||
public new class UxmlTraits : VisualElement.UxmlTraits
|
||||
{
|
||||
|
@ -30,27 +29,21 @@ namespace BITKit.UX
|
|||
public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
|
||||
{
|
||||
base.Init(ve, bag, cc);
|
||||
var x = (SkiaChart)ve;
|
||||
var x = (LineChart)ve;
|
||||
x.Json = m_JsonAttribute.GetValueFromBag(bag, cc);
|
||||
x.AllowWarning = m_allowWarningsAttribute.GetValueFromBag(bag, cc);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public new class UxmlFactory : UxmlFactory<SkiaChart, UxmlTraits>
|
||||
public new class UxmlFactory : UxmlFactory<LineChart, UxmlTraits>
|
||||
{
|
||||
}
|
||||
|
||||
public SkiaChart()
|
||||
public LineChart()
|
||||
{
|
||||
RegisterCallback<GeometryChangedEvent>(x =>
|
||||
{
|
||||
if (visible)
|
||||
{
|
||||
Rebuild();
|
||||
}
|
||||
});
|
||||
RegisterCallback<CustomStyleResolvedEvent>(OnCustomStyleResolved);
|
||||
|
||||
|
||||
style.flexDirection = FlexDirection.Row;
|
||||
_dataContainer = this.Create<VisualElement>();
|
||||
|
@ -61,6 +54,26 @@ namespace BITKit.UX
|
|||
|
||||
_dataContainer.name = "Data";
|
||||
_chartContainer.name = "Chart";
|
||||
|
||||
_chartContainer.generateVisualContent+= GenerateVisualContent;
|
||||
|
||||
_chartContainer.style.marginBottom = 0;
|
||||
_chartContainer.style.marginLeft = 8;
|
||||
_chartContainer.style.marginRight = 8;
|
||||
_chartContainer.style.marginTop = 0 ;
|
||||
|
||||
pickingMode = PickingMode.Ignore;
|
||||
_dataContainer.pickingMode = PickingMode.Ignore;
|
||||
|
||||
_chartContainer.style.flexDirection = FlexDirection.RowReverse;
|
||||
_dataContainer.style.flexDirection = FlexDirection.ColumnReverse;
|
||||
|
||||
_chartContainer.RegisterCallback<PointerMoveEvent>(OnPointerMove);
|
||||
}
|
||||
|
||||
private void OnPointerMove(PointerMoveEvent evt)
|
||||
{
|
||||
//_chartContainer.tooltip = evt.localPosition.ToString();
|
||||
}
|
||||
|
||||
private void OnCustomStyleResolved(CustomStyleResolvedEvent evt)
|
||||
|
@ -71,7 +84,16 @@ namespace BITKit.UX
|
|||
_secondaryColor = helpLineColor;
|
||||
}
|
||||
|
||||
Rebuild();
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (evt.customStyle.TryGetValue(new CustomStyleProperty<Color>($"--chart-line-color--{i}"),
|
||||
out var lineColor))
|
||||
{
|
||||
_lineColors[i] = lineColor;
|
||||
}
|
||||
}
|
||||
|
||||
MarkDirtyRepaint();
|
||||
}
|
||||
|
||||
public string Json
|
||||
|
@ -80,7 +102,7 @@ namespace BITKit.UX
|
|||
set
|
||||
{
|
||||
_json = value;
|
||||
Rebuild();
|
||||
GenerateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,7 +115,7 @@ namespace BITKit.UX
|
|||
set
|
||||
{
|
||||
_secondaryColor = value;
|
||||
Rebuild();
|
||||
GenerateLayout();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,12 +124,76 @@ namespace BITKit.UX
|
|||
private readonly VisualElement _dataContainer;
|
||||
private readonly VisualElement _chartContainer;
|
||||
|
||||
private void Rebuild()
|
||||
private readonly Color[] _lineColors = new[]
|
||||
{
|
||||
Color.red,
|
||||
Color.red,
|
||||
Color.red,
|
||||
Color.red,
|
||||
Color.red,
|
||||
Color.red,
|
||||
Color.red,
|
||||
Color.red,
|
||||
};
|
||||
|
||||
private void GenerateLayout()
|
||||
{
|
||||
JArray[] array;
|
||||
float[] data;
|
||||
try
|
||||
{
|
||||
array = JsonConvert.DeserializeObject<JArray[]>(Json);
|
||||
data = array.SelectMany(x => x.ToObject<float[]>()).ToArray();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (AllowWarning)
|
||||
Debug.LogException(e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data is null or { Length: 0 })
|
||||
{
|
||||
if (AllowWarning)
|
||||
BIT4Log.Log<LineChart>("Data is null or empty");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//假如min是x,max是y,将中间的差用data.Length划分
|
||||
var max = data.Max();
|
||||
var min = data.Min();
|
||||
|
||||
var difference = max - min;
|
||||
|
||||
var maxLength = array.Select(x => x.Count).Max();
|
||||
|
||||
max += difference / maxLength;
|
||||
min -= difference / maxLength;
|
||||
|
||||
//Debug.Log($"min:{min} max:{max} difference:{difference} max:{max}");
|
||||
|
||||
_dataContainer.Clear();
|
||||
for (var i = 0; i <= maxLength; i++)
|
||||
{
|
||||
var label = _dataContainer.Create<Label>();
|
||||
|
||||
//var value = (max - min) / (data.Length - 1) * i + min;
|
||||
|
||||
var t = (float)i / maxLength;
|
||||
var value = Mathf.Lerp(min, max, t);
|
||||
label.text = Math.Round(value, 2).ToString();
|
||||
}
|
||||
MarkDirtyRepaint();
|
||||
}
|
||||
|
||||
private void GenerateVisualContent(MeshGenerationContext context)
|
||||
{
|
||||
|
||||
if (float.IsNaN(layout.width) || float.IsNaN(layout.height))
|
||||
{
|
||||
if (AllowWarning)
|
||||
BIT4Log.Log<SkiaChart>("Width or height is NaN");
|
||||
BIT4Log.Log<LineChart>("Width or height is NaN");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -128,139 +214,82 @@ namespace BITKit.UX
|
|||
if (data is null or { Length: 0 })
|
||||
{
|
||||
if (AllowWarning)
|
||||
BIT4Log.Log<SkiaChart>("Data is null or empty");
|
||||
BIT4Log.Log<LineChart>("Data is null or empty");
|
||||
return;
|
||||
}
|
||||
|
||||
_dataContainer.Clear();
|
||||
_chartContainer.Clear();
|
||||
// _chartContainer.style.marginBottom = 8;
|
||||
// _chartContainer.style.marginLeft = 8;
|
||||
// _chartContainer.style.marginRight = 8;
|
||||
// _chartContainer.style.marginTop = 8;
|
||||
_dataContainer.style.flexDirection = FlexDirection.ColumnReverse;
|
||||
|
||||
//假如min是x,max是y,将中间的差用data.Length划分
|
||||
var max = data.Max();
|
||||
var min = data.Min();
|
||||
|
||||
var difference = max - min;
|
||||
|
||||
|
||||
var maxLength = array.Select(x => x.Count).Max();
|
||||
|
||||
max = max + difference / maxLength;
|
||||
min = min - difference / maxLength;
|
||||
max += difference / maxLength;
|
||||
min -= difference / maxLength;
|
||||
difference = max - min;
|
||||
|
||||
|
||||
|
||||
//Debug.Log($"min:{min} max:{max} difference:{difference} max:{max}");
|
||||
|
||||
for (var i = 0; i <= maxLength; i++)
|
||||
{
|
||||
var label = _dataContainer.Create<Label>();
|
||||
|
||||
//var value = (max - min) / (data.Length - 1) * i + min;
|
||||
|
||||
var t = (float)i / maxLength;
|
||||
var value = Mathf.Lerp(min,max,t);
|
||||
label.text = Math.Round(value, 2).ToString();
|
||||
}
|
||||
|
||||
|
||||
if (_chartContainer.layout.width is float.NaN or < 10 || _chartContainer.layout.height is float.NaN or < 10)
|
||||
{
|
||||
if (AllowWarning)
|
||||
BIT4Log.Log<SkiaChart>("Width or height is NaN or less than 10");
|
||||
BIT4Log.Log<LineChart>("Width or height is NaN or less than 10");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var info = new SKImageInfo(
|
||||
width: (int)_chartContainer.layout.width,
|
||||
height: (int)_chartContainer.layout.height,
|
||||
colorType: SKColorType.Rgba8888,
|
||||
alphaType: SKAlphaType.Premul
|
||||
);
|
||||
|
||||
using var surface = SKSurface.Create(info);
|
||||
|
||||
using var canvas = surface.Canvas;
|
||||
|
||||
using var linePaint = new SKPaint();
|
||||
|
||||
linePaint.StrokeWidth = resolvedStyle.unityTextOutlineWidth;
|
||||
linePaint.IsAntialias = true;
|
||||
linePaint.Style = SKPaintStyle.Stroke;
|
||||
|
||||
using var helpLinePaint = new SKPaint();
|
||||
helpLinePaint.Color = resolvedStyle.unityTextOutlineColor.ToSKColor();
|
||||
helpLinePaint.StrokeWidth = 1;
|
||||
helpLinePaint.Style = SKPaintStyle.Stroke;
|
||||
|
||||
using var fillPaint = new SKPaint();
|
||||
fillPaint.Color = new SKColor(200, 200, 200, 200);
|
||||
fillPaint.Style = SKPaintStyle.Fill;
|
||||
|
||||
|
||||
var linePaint = context.painter2D;
|
||||
linePaint.lineWidth = resolvedStyle.unityTextOutlineWidth;
|
||||
var width = contentRect.width;
|
||||
var height = contentRect.height;
|
||||
|
||||
|
||||
for (var index = 0; index < array.Length; index++)
|
||||
{
|
||||
var _array = array[index];
|
||||
DoubleBuffer<SKPoint> buffer = new();
|
||||
var row = array[index];
|
||||
DoubleBuffer<Vector2> buffer = new();
|
||||
|
||||
data = row.ToObject<float[]>();
|
||||
|
||||
data = _array.ToObject<float[]>();
|
||||
var lastWidth = 0f;
|
||||
|
||||
var path = new SKPath { FillType = SKPathFillType.EvenOdd };
|
||||
linePaint.strokeColor = _lineColors[index];
|
||||
var tempColor = _lineColors[index];
|
||||
tempColor.a *= 0.2f;
|
||||
linePaint.fillColor = tempColor;
|
||||
|
||||
path.MoveTo(0, 0);
|
||||
path.LineTo(0, 0);
|
||||
|
||||
if (_array.Count is not 1 && customStyle.TryGetValue(new CustomStyleProperty<Color>($"--color-{index}"),
|
||||
out var _myStyle))
|
||||
linePaint.BeginPath();
|
||||
|
||||
linePaint.MoveTo(new(0,height));
|
||||
linePaint.lineJoin = LineJoin.Round;
|
||||
|
||||
for (var i = 0; i < data.Length; i++)
|
||||
{
|
||||
linePaint.Color = _myStyle.ToSKColor();
|
||||
}
|
||||
else
|
||||
{
|
||||
linePaint.Color = resolvedStyle.color.ToSKColor();
|
||||
}
|
||||
|
||||
for (var i = 1; i <= data.Length; i++)
|
||||
{
|
||||
var value = data[i-1];
|
||||
var posX = (float)info.Width / data.Length * (i);
|
||||
var value = data[i];
|
||||
var posX = width / data.Length * i;
|
||||
var p = (value - min) / difference;
|
||||
var poxY = info.Height * p;
|
||||
var poxY = height-height * p;
|
||||
|
||||
var currentPoint = new SKPoint(posX, poxY);
|
||||
var currentPoint = new Vector2(posX, poxY);
|
||||
if (buffer.TryGetRelease(out var previousPoint))
|
||||
{
|
||||
canvas.DrawLine(previousPoint, currentPoint, linePaint);
|
||||
linePaint.LineTo(previousPoint);
|
||||
}
|
||||
|
||||
if (i == data.Length)
|
||||
{
|
||||
var label = _chartContainer.Create<Label>();
|
||||
label.text = Math.Round(value, 2).ToString(CultureInfo.InvariantCulture);
|
||||
label.style.position = Position.Absolute;
|
||||
label.style.left = posX; //-label.layout.width/2;
|
||||
label.style.bottom = poxY; //- label.layout.height/2;
|
||||
//label.transform.position = new Vector3(-label.layout.width/2, poxY, 0);
|
||||
}
|
||||
|
||||
|
||||
canvas.DrawLine(posX, 0, posX, poxY, helpLinePaint);
|
||||
|
||||
path.LineTo(posX, poxY);
|
||||
|
||||
linePaint.LineTo(currentPoint);
|
||||
|
||||
buffer.Release(currentPoint);
|
||||
|
||||
if(i == data.Length-1)
|
||||
{
|
||||
lastWidth = posX;
|
||||
}
|
||||
}
|
||||
|
||||
path.LineTo(info.Width, 0);
|
||||
path.Close();
|
||||
linePaint.LineTo(new (lastWidth,height));
|
||||
linePaint.ClosePath();
|
||||
linePaint.Stroke();
|
||||
linePaint.Fill();
|
||||
}
|
||||
|
||||
var texture = info.ToTexture2D(surface);
|
||||
|
||||
_chartContainer.style.backgroundImage = texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
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<ComplexRadialProgress, UxmlTraits> { }
|
||||
|
||||
// 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<CustomStyleResolvedEvent>(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<Color>($"--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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0306eb6f9b5c390428511ff889a48535
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,101 @@
|
|||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace BITKit.UX
|
||||
{
|
||||
|
||||
// An element that displays progress inside a partially filled circle
|
||||
public class DashBoardProgress : VisualElement
|
||||
{
|
||||
public new class UxmlTraits : VisualElement.UxmlTraits
|
||||
{
|
||||
// The progress property is exposed to UXML.
|
||||
private readonly UxmlFloatAttributeDescription m_ProgressAttribute = new UxmlFloatAttributeDescription()
|
||||
{
|
||||
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);
|
||||
|
||||
((DashBoardProgress)ve).progress = m_ProgressAttribute.GetValueFromBag(bag, cc);
|
||||
}
|
||||
}
|
||||
|
||||
// Define a factory class to expose this control to UXML.
|
||||
public new class UxmlFactory : UxmlFactory<DashBoardProgress, UxmlTraits> { }
|
||||
|
||||
// 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;
|
||||
|
||||
// This is the label that displays the percentage.
|
||||
private Label m_Label;
|
||||
|
||||
// This is the number that the Label displays as a percentage.
|
||||
private float m_Progress;
|
||||
|
||||
// A value between 0 and 100
|
||||
public float 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 DashBoardProgress()
|
||||
{
|
||||
// Add the USS class name for the overall control.
|
||||
AddToClassList(ussClassName);
|
||||
|
||||
// Register a callback to generate the visual content of the control.
|
||||
generateVisualContent += GenerateVisualContent;
|
||||
|
||||
progress = 0.5f;
|
||||
}
|
||||
|
||||
private void GenerateVisualContent(MeshGenerationContext context)
|
||||
{
|
||||
var width = contentRect.width;
|
||||
var height = contentRect.height;
|
||||
|
||||
var painter = context.painter2D;
|
||||
painter.lineWidth = resolvedStyle.unityTextOutlineWidth;
|
||||
painter.lineCap = LineCap.Butt;
|
||||
|
||||
var startAngle = -220f;
|
||||
|
||||
//startAngle = Mathf.Lerp(-90f, 480f, nextProgress);
|
||||
|
||||
//var endAngle = 360.0f * (progress) + startAngle - 30;
|
||||
var endAngle = 40f;
|
||||
|
||||
endAngle = Mathf.Lerp(startAngle, endAngle, progress);
|
||||
//计算progress
|
||||
|
||||
// Draw the track
|
||||
painter.strokeColor = resolvedStyle.unityTextOutlineColor;
|
||||
painter.BeginPath();
|
||||
painter.Arc(new Vector2(width * 0.5f, height * 0.5f), width*0.5f - painter.lineWidth/2f, startAngle, 40f);
|
||||
painter.Stroke();
|
||||
|
||||
// Draw the progress Out
|
||||
painter.strokeColor = resolvedStyle.color;
|
||||
painter.BeginPath();
|
||||
painter.Arc(new Vector2(width * 0.5f, height * 0.5f), width*0.5f - painter.lineWidth/2f, startAngle, endAngle);
|
||||
painter.Stroke();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ca5c3b80f12254f41a3be68eec8d4ce2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -66,6 +66,10 @@ namespace BITKit.UX
|
|||
{
|
||||
_tabBar.OnTabChanged += OnTabChanged;
|
||||
}
|
||||
if (_index <=0)
|
||||
{
|
||||
_index = 1;
|
||||
}
|
||||
OnTabChanged(_index);
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ namespace BITKit.UX
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BIT4Log.Warning<UXUtils>(field!.Name);
|
||||
BIT4Log.Warning<UXUtils>(fieldInfo!.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
"GUID:d525ad6bd40672747bde77962f1c401e",
|
||||
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b",
|
||||
"GUID:6de01b04fa4e14662b03fa46366da151",
|
||||
"GUID:f19bbd83e3c264a5680926bf75d7e494"
|
||||
"GUID:6de01b04fa4e14662b03fa46366da151"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
|
Loading…
Reference in New Issue