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 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.Controller = this; Engine.Inertia = 0.25f; if ( !Clutch.IsValid() ) Clutch = new GameObject( Engine.GameObject, true, "Clutch" ).GetOrAddComponent(); Clutch.Controller = this; Clutch.Inertia = 0.02f; Engine.Output = Clutch; if ( !Transmission.IsValid() ) Transmission = new GameObject( Clutch.GameObject, true, "Transmission" ).GetOrAddComponent(); Transmission.Controller = this; Transmission.Inertia = 0.01f; Clutch.Output = Transmission; Differential = new TreeBuilder( Transmission, MotorWheels ).Root.Diff; Transmission.Output = Differential; //PowertrainWheels = Differential.Components.GetAll( 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 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 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() }; 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(); 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; } }