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(); 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 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(); } }