velox/Code/Base/VeloXBase.Engine.cs
2025-11-25 19:16:40 +07:00

128 lines
3.4 KiB
C#

using Sandbox;
using System;
using System.Collections.Generic;
namespace VeloX;
public abstract partial class VeloXBase
{
[Property, Feature( "Powertrain" )] public Engine Engine { get; set; }
[Property, Feature( "Powertrain" )] public Clutch Clutch { get; set; }
[Property, Feature( "Powertrain" )] public Transmission Transmission { get; set; }
[Property, Feature( "Powertrain" )] public Differential Differential { get; set; }
[Property, Feature( "Powertrain" )] public List<VeloXWheel> MotorWheels { get; set; }
private GameObject powertrainGameObject;
[Button, Feature( "Powertrain" )]
internal void CreatePowertrain()
{
using var undoScope = Scene.Editor?.UndoScope( "Create Powertrain" ).WithComponentCreations().WithGameObjectCreations().Push();
if ( !powertrainGameObject.IsValid() )
{
powertrainGameObject = null;
}
powertrainGameObject ??= new GameObject( true, "Powertrain" );
if ( !Engine.IsValid() )
Engine = new GameObject( powertrainGameObject, true, "Engine" ).GetOrAddComponent<Engine>();
Engine.Controller = this;
Engine.Inertia = 0.25f;
if ( !Clutch.IsValid() )
Clutch = new GameObject( Engine.GameObject, true, "Clutch" ).GetOrAddComponent<Clutch>();
Clutch.Controller = this;
Clutch.Inertia = 0.02f;
Engine.Output = Clutch;
if ( !Transmission.IsValid() )
Transmission = new GameObject( Clutch.GameObject, true, "Transmission" ).GetOrAddComponent<Transmission>();
Transmission.Controller = this;
Transmission.Inertia = 0.01f;
Clutch.Output = Transmission;
Differential = new TreeBuilder( Transmission, MotorWheels ).Root.Diff;
Transmission.Output = Differential;
//PowertrainWheels = Differential.Components.GetAll<WheelPowertrain>( FindMode.InDescendants ).ToList();
}
}
internal class TreeNode
{
internal TreeNode Left { get; set; }
internal TreeNode Right { get; set; }
public WheelPowertrain Item { get; set; }
public Differential Diff { get; set; }
public bool IsLeaf => Left == null && Right == null;
}
internal class TreeBuilder
{
internal TreeNode Root { get; private set; }
internal TreeBuilder( PowertrainComponent parent, List<VeloXWheel> items )
{
if ( items == null || items.Count == 0 )
throw new ArgumentException( "Items list cannot be null or empty." );
Root = BuildTree( parent, items, 0, items.Count - 1 );
}
private static TreeNode BuildTree( PowertrainComponent parent, List<VeloXWheel> items, int start, int end )
{
if ( start > end )
return null;
if ( start == end )
{
var leaf = new TreeNode() { Item = new GameObject( parent.GameObject, true, $"Wheel {items[start].GameObject.Name}" ).GetOrAddComponent<WheelPowertrain>() };
leaf.Item.Controller = parent.Controller;
leaf.Item.Wheel = items[start];
leaf.Item.Inertia = 0.01f;
var parentd = parent as Differential;
if ( (start + 1) % 2 == 0 )
{
GameTask.RunInThreadAsync( () =>
{
parentd.OutputB = leaf.Item;
} );
}
else
{
GameTask.RunInThreadAsync( () =>
{
parent.Output = leaf.Item;
} );
}
return leaf;
}
int mid = (start + end) / 2;
var diff = new GameObject( parent.GameObject, true, "Differential" ).GetOrAddComponent<Differential>();
diff.Controller = parent.Controller;
diff.Inertia = 0.1f;
var node = new TreeNode
{
Left = BuildTree( diff, items, start, mid ),
Right = BuildTree( diff, items, mid + 1, end ),
Diff = diff
};
diff.Output = node.Left.Diff;
diff.OutputB = node.Right.Diff;
return node;
}
}