new pacejka implementation (car not working)
This commit is contained in:
90
Editor/Wheel/PacejkaWidget.cs
Normal file
90
Editor/Wheel/PacejkaWidget.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
using Editor;
|
||||
using Sandbox;
|
||||
|
||||
namespace VeloX;
|
||||
|
||||
[CustomEditor( typeof( Pacejka ) )]
|
||||
public class PacejkaWidget : ControlObjectWidget
|
||||
{
|
||||
public override bool SupportsMultiEdit => false;
|
||||
public override bool IncludeLabel => false;
|
||||
|
||||
[CustomEditor( typeof( Pacejka.LateralForce ) )]
|
||||
private class LateralForceWidget : ControlObjectWidget
|
||||
{
|
||||
public LateralForceWidget( SerializedProperty property ) : base( property, true )
|
||||
{
|
||||
Layout = Layout.Column();
|
||||
Layout.Margin = 8f;
|
||||
Layout.Spacing = 8;
|
||||
foreach ( var item in TypeLibrary.GetType<Pacejka.LateralForce>().Fields )
|
||||
{
|
||||
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.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>().Fields )
|
||||
{
|
||||
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>().Fields )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
|
||||
var obj = SerializedObject;
|
||||
Pacejka = obj.ParentProperty.GetValue<Pacejka>();
|
||||
|
||||
Layout = Layout.Column();
|
||||
Layout.Margin = 8f;
|
||||
Layout.Add( new Label.Body( $" {ToolTip}" ) { Color = Color.White } );
|
||||
var tabs = Layout.Add( new TabWidget( null ) );
|
||||
tabs.AddPage( nameof( Pacejka.Lateral ), null,
|
||||
Layout.Add( Create( obj.GetProperty( nameof( Pacejka.Lateral ) ) ) )
|
||||
);
|
||||
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 ) ) ) )
|
||||
);
|
||||
}
|
||||
}
|
||||
70
Editor/Wheel/TirePresetEditor.cs
Normal file
70
Editor/Wheel/TirePresetEditor.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
188
Editor/Wheel/TirePresetPreview.cs
Normal file
188
Editor/Wheel/TirePresetPreview.cs
Normal file
@@ -0,0 +1,188 @@
|
||||
using Editor;
|
||||
using Editor.Assets;
|
||||
using Editor.Inspectors;
|
||||
using Editor.ShaderGraph.Nodes;
|
||||
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 maxforce ) / load;
|
||||
float xval = width * (x - x0) / (xn - x0);
|
||||
yval /= ymax - ymin;
|
||||
yval = (yval + 1.0f) * 0.5f;
|
||||
yval = 1.0f - yval;
|
||||
yval *= height;
|
||||
if ( x == x0 )
|
||||
pointCache.Add( new( xval, yval ) );
|
||||
else
|
||||
pointCache.Add( new( xval, yval ) );
|
||||
}
|
||||
|
||||
Paint.DrawLine( pointCache );
|
||||
}
|
||||
|
||||
{ // draw longitudinal 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;
|
||||
if ( x == x0 )
|
||||
pointCache.Add( new( xval, yval ) );
|
||||
else
|
||||
pointCache.Add( new( xval, yval ) );
|
||||
}
|
||||
Paint.DrawLine( pointCache );
|
||||
}
|
||||
|
||||
{ // draw aligning 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 ) / load;
|
||||
float xval = width * (x - x0) / (xn - x0);
|
||||
yval /= ymax - ymin;
|
||||
yval = (yval + 1.0f) * 0.5f;
|
||||
yval = 1.0f - yval;
|
||||
yval *= height;
|
||||
if ( x == x0 )
|
||||
pointCache.Add( new( xval, yval ) );
|
||||
else
|
||||
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();
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user