This commit is contained in:
Valera
2025-07-18 16:05:48 +07:00
parent 55a178e8c5
commit 0905876b99
9 changed files with 347 additions and 752 deletions

View File

@@ -9,7 +9,7 @@ public class PacejkaWidget : ControlObjectWidget
public override bool SupportsMultiEdit => false;
public override bool IncludeLabel => false;
[CustomEditor( typeof( Pacejka.LateralForce ) )]
[CustomEditor( typeof( Pacejka.PacejkaPreset ) )]
private class LateralForceWidget : ControlObjectWidget
{
public LateralForceWidget( SerializedProperty property ) : base( property, true )
@@ -17,7 +17,7 @@ public class PacejkaWidget : ControlObjectWidget
Layout = Layout.Column();
Layout.Margin = 8f;
Layout.Spacing = 8;
foreach ( var item in TypeLibrary.GetType<Pacejka.LateralForce>().Properties )
foreach ( var item in TypeLibrary.GetType<Pacejka.PacejkaPreset>().Properties )
{
var row = Layout.AddRow();
row.Spacing = 8;
@@ -27,45 +27,6 @@ public class PacejkaWidget : ControlObjectWidget
}
}
}
[CustomEditor( typeof( Pacejka.LongitudinalForce ) )]
private class LongitudinalForceWidget : ControlObjectWidget
{
public LongitudinalForceWidget( SerializedProperty property ) : base( property, true )
{
Layout = Layout.Column();
Layout.Margin = 8f;
Layout.Spacing = 8;
foreach ( var item in TypeLibrary.GetType<Pacejka.LongitudinalForce>().Properties )
{
var row = Layout.AddRow();
row.Spacing = 8;
var propetry = SerializedObject.GetProperty( item.Name );
row.Add( new Label( propetry.Name ) );
row.Add( Create( propetry ) );
}
}
}
[CustomEditor( typeof( Pacejka.AligningMoment ) )]
private class AligningMomentWidget : ControlObjectWidget
{
public AligningMomentWidget( SerializedProperty property ) : base( property, true )
{
Layout = Layout.Column();
Layout.Margin = 8f;
Layout.Spacing = 8;
foreach ( var item in TypeLibrary.GetType<Pacejka.AligningMoment>().Properties )
{
var row = Layout.AddRow();
row.Spacing = 8;
var propetry = SerializedObject.GetProperty( item.Name );
row.Add( new Label( propetry.Name ) );
row.Add( Create( propetry ) );
}
}
}
private Pacejka Pacejka;
public PacejkaWidget( SerializedProperty property ) : base( property, true )
{
@@ -83,8 +44,5 @@ public class PacejkaWidget : ControlObjectWidget
tabs.AddPage( nameof( Pacejka.Longitudinal ), null,
Layout.Add( Create( obj.GetProperty( nameof( Pacejka.Longitudinal ) ) ) )
);
tabs.AddPage( nameof( Pacejka.Aligning ), null,
Layout.Add( Create( obj.GetProperty( nameof( Pacejka.Aligning ) ) ) )
);
}
}

View File

@@ -1,70 +0,0 @@
using Editor;
using Editor.Assets;
using Editor.Inspectors;
using Sandbox;
using static Editor.Inspectors.AssetInspector;
namespace VeloX;
[CanEdit( "asset:tire" )]
public class TirePresetEditor : Widget, IAssetInspector
{
TirePreset Tire;
ControlSheet MainSheet;
TirePresetPreview TirePreview;
public TirePresetEditor( Widget parent ) : base( parent )
{
Layout = Layout.Column();
Layout.Margin = 4;
Layout.Spacing = 4;
// Create a ontrolSheet that will display all our Properties
MainSheet = new ControlSheet();
Layout.Add( MainSheet );
//// Add a randomize button below the ControlSheet
//var button = Layout.Add( new Button( "Randomize", "casino", this ) );
//button.Clicked += () =>
//{
// foreach ( var prop in Test.GetSerialized() )
// {
// // Randomize all the float values from 0-100
// if ( prop.PropertyType != typeof( float ) ) continue;
// prop.SetValue( Random.Shared.Float( 0, 100 ) );
// }
//};
Layout.AddStretchCell();
RebuildSheet();
Focus();
}
[EditorEvent.Hotload]
void RebuildSheet()
{
if ( Tire is null ) return;
if ( MainSheet is null ) return;
MainSheet.Clear( true );
var so = Tire.GetSerialized();
so.OnPropertyChanged += x =>
{
Tire.StateHasChanged();
TirePreview.Widget.UpdatePixmap();
};
MainSheet.AddObject( so );
}
void IAssetInspector.SetAssetPreview( AssetPreview preview )
{
TirePreview = preview as TirePresetPreview;
}
public void SetAsset( Asset asset )
{
Tire = asset.LoadResource<TirePreset>();
RebuildSheet();
}
}

View File

@@ -9,29 +9,17 @@ using System.Threading.Tasks;
namespace VeloX;
[AssetPreview( "tire" )]
class TirePresetPreview( Asset asset ) : PixmapAssetPreview( asset )
class TirePresetPreview : AssetPreview
{
private TirePreset Tire = asset.LoadResource<TirePreset>();
private Texture texture;
public override bool IsAnimatedPreview => false;
[Range( 0.01f, 1 )] private float Zoom { get; set; } = 1;
private TirePreset Tire;
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()
@@ -42,116 +30,6 @@ class TirePresetPreview( Asset asset ) : PixmapAssetPreview( asset )
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 )
@@ -164,9 +42,7 @@ class TirePresetPreview( Asset asset ) : PixmapAssetPreview( asset )
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;
@@ -175,4 +51,99 @@ class TirePresetPreview( Asset asset ) : PixmapAssetPreview( asset )
popup.ConstrainToScreen();
}
public override async Task InitializeAsset()
{
await Task.Yield();
using ( Scene.Push() )
{
PrimaryObject = new()
{
WorldTransform = Transform.Zero
};
var plane = PrimaryObject.AddComponent<ModelRenderer>();
plane.Model = Model.Plane;
plane.LocalScale = new Vector3( 1, 1, 1 );
plane.MaterialOverride = Material.Load( "materials/dev/reflectivity_30.vmat" );
plane.Tint = new Color( 0.02f, 0.04f, 0.03f );
var bounds = PrimaryObject.GetBounds();
SceneCenter = bounds.Center;
SceneSize = bounds.Size;
}
return;
}
public override void UpdateScene( float cycle, float timeStep )
{
if ( !Widget.IsValid() )
return;
Camera.WorldPosition = Vector3.Up * 300;
Camera.Orthographic = true;
Camera.WorldRotation = new Angles( 90, 0, 0 );
var bitmap = new Bitmap( 512, 512 );
Draw( bitmap );
texture.Clear( Color.Black );
//texture.Update( bitmap );
DebugOverlaySystem.Current.Texture( texture, new Rect( 0, Widget.Size ) );
FrameScene();
}
private readonly List<Vector2> pointCache = [];
public TirePresetPreview( Asset asset ) : base( asset )
{
texture = Texture.CreateRenderTarget().WithDynamicUsage().WithScreenFormat().WithSize( 512, 512 ).Create();
Tire = Asset.LoadResource<TirePreset>();
}
private void DrawPacejka( Bitmap bitmap )
{
var tire = Tire.Pacejka;
var width = bitmap.Width;
var height = bitmap.Height;
{ // draw lateral line
pointCache.Clear();
bitmap.SetPen( Color.Red, 1 );
for ( float x = 0; x <= 1; x += 0.01f )
{
float val = tire.PacejkaFy( x ) * Zoom;
pointCache.Add( new( width * x, height - height * val ) );
}
bitmap.DrawLines( pointCache.ToArray() );
}
{ // draw longitudinal line
pointCache.Clear();
bitmap.SetPen( Color.Green, 1 );
for ( float x = 0; x <= 1; x += 0.01f )
{
float val = tire.PacejkaFx( x ) * Zoom;
pointCache.Add( new( width * x, height - height * val ) );
}
bitmap.DrawLines( pointCache.ToArray() );
}
pointCache.Clear();
}
private void Draw( Bitmap bitmap )
{
bitmap.Clear( Color.Black );
bitmap.SetAntialias( true );
DrawPacejka( bitmap );
}
}