velox/Editor/Wheel/TirePresetPreview.cs
2025-06-15 21:59:42 +07:00

179 lines
4.0 KiB
C#

using Editor;
using Editor.Assets;
using Editor.Inspectors;
using Sandbox;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace VeloX;
[AssetPreview( "tire" )]
class TirePresetPreview( Asset asset ) : PixmapAssetPreview( asset )
{
private TirePreset Tire = asset.LoadResource<TirePreset>();
public AssetPreviewWidget Widget { get; private set; }
[Range( 100, 10000 )] private float Load { get; set; } = 2500f;
[Range( 0, 1 )] private float Zoom { get; set; } = 0;
[Range( -10, 10 )] private float Camber { get; set; } = 0;
public override Widget CreateWidget( Widget parent )
{
Widget = parent as AssetPreviewWidget;
Task.Run( async () =>
{
while ( Widget != null )
{
await MainThread.Wait();
await Widget.UpdatePixmap();
await Task.Delay( 100 );
}
} );
return null;
}
public override Widget CreateToolbar()
{
var info = new IconButton( "settings" );
info.Layout = Layout.Row();
info.MinimumSize = 16;
info.MouseLeftPress = () => OpenSettings( info );
return info;
}
static List<Vector2> pointCache = [];
private void DrawPacejka()
{
float load = Load * 0.001f;
float zoom = (1.0f - Zoom) * 4.0f + 0.1f;
var tire = Tire.Pacejka;
var width = Paint.LocalRect.Width;
var height = Paint.LocalRect.Height;
{ // draw lateral line
pointCache.Clear();
Paint.SetPen( Color.Red, 1 );
float x0 = -zoom * 0.5f * 20.0f;
float xn = zoom * 0.5f * 20.0f;
float ymin = -1000.0f;
float ymax = 1000.0f;
int points = 500;
for ( float x = x0; x <= xn; x += (xn - x0) / points )
{
float yval = tire.PacejkaFy( x, load, Camber, 1.0f, out float _ ) / load;
float xval = width * (x - x0) / (xn - x0);
yval /= ymax - ymin;
yval = (yval + 1.0f) * 0.5f;
yval = 1.0f - yval;
yval *= height;
pointCache.Add( new( xval, yval ) );
}
Paint.DrawLine( pointCache );
}
{ // draw longitudinal line
pointCache.Clear();
Paint.SetPen( Color.Green, 1 );
float x0 = -zoom * 0.5f;
float xn = zoom * 0.5f;
float ymin = -1000.0f;
float ymax = 1000.0f;
int points = 500;
for ( float x = x0; x <= xn; x += (xn - x0) / points )
{
float yval = tire.PacejkaFx( x, load, 1.0f, out var _ ) / load;
float xval = width * (x - x0) / (xn - x0);
yval /= ymax - ymin;
yval = (yval + 1.0f) * 0.5f;
yval = 1.0f - yval;
yval *= height;
pointCache.Add( new( xval, yval ) );
}
Paint.DrawLine( pointCache );
}
{ // draw aligning line
pointCache.Clear();
Paint.SetPen( Color.Blue, 1 );
float x0 = -zoom * 0.5f * 10.0f;
float xn = zoom * 0.5f * 10.0f;
float ymin = -60.0f;
float ymax = 60.0f;
int points = 500;
for ( float x = x0; x <= xn; x += (xn - x0) / points )
{
float yval = tire.PacejkaMz( x, load, Camber * (180.0f / MathF.PI), 1.0f ) / load;
float xval = width * (x - x0) / (xn - x0);
yval /= ymax - ymin;
yval = (yval + 1.0f) * 0.5f;
yval = 1.0f - yval;
yval *= height;
pointCache.Add( new( xval, yval ) );
}
Paint.DrawLine( pointCache );
}
pointCache.Clear();
}
public override Task RenderToPixmap( Pixmap pixmap )
{
Paint.ToPixmap( pixmap );
Paint.Antialiasing = true;
Paint.SetBrush( Color.Gray );
Paint.DrawRect( Paint.LocalRect );
Paint.ClearBrush();
Paint.SetPen( Color.Black, 1 );
var width = Paint.LocalRect.Width;
var height = Paint.LocalRect.Height;
float xc = width / 2;
float yc = height / 2;
Paint.DrawLine( new( xc, 0 ), new( xc, yc * 2 ) );
Paint.DrawLine( new( 0, yc ), new( xc * 2, yc ) );
DrawPacejka();
return Task.CompletedTask;
}
public void OpenSettings( Widget parent )
{
var popup = new PopupWidget( parent )
{
IsPopup = true,
Layout = Layout.Column()
};
popup.Layout.Margin = 16;
var ps = new ControlSheet();
ps.AddProperty( this, x => x.Load );
ps.AddProperty( this, x => x.Zoom );
ps.AddProperty( this, x => x.Camber );
popup.Layout.Add( ps );
popup.MaximumWidth = 300;
popup.Show();
popup.Position = parent.ScreenRect.TopRight - popup.Size;
popup.ConstrainToScreen();
}
}