using Godot; using System; using System.Collections.Generic; using Vim.Math3d; [Tool] public class OrbitSystem : Node, IPointMass { [Export] private NodePath[] _pointMassPaths; private double _semiMajorAxis; [Export] private double SemiMajorAxis { get => _semiMajorAxis; set { _semiMajorAxis = value; if (!Engine.EditorHint) return; InvalidateGeometry(); } } private double _eccentricity; [Export(PropertyHint.Range, "0,1")] private double Eccentricity { get => _eccentricity; set { _eccentricity = value; if (!Engine.EditorHint) return; InvalidateGeometry(); } } private IPointMass[] _pointMasses; public IPointMass[] Orbiters { get { if (_pointMasses == null) { _pointMasses = new IPointMass[_pointMassPaths.Length]; // give each body an orbit around ourselves for (int i = 0; i < _pointMassPaths.Length; i++) { _pointMasses[i] = GetNode(_pointMassPaths[i]); } } return _pointMasses; } } public double Mass { get { double mass = 0; foreach (var pointMass in _pointMasses) { mass += pointMass.Mass; } return mass; } } public DVector3 Position { get; set; } private Orbit _orbit = null; private Orbit Orbit { get { if (_orbit == null) { _orbit = new Orbit(); } return _orbit; } } private ImmediateGeometry _orbitGeometry = null; public ImmediateGeometry OrbitGeometry { get { if (_orbitGeometry == null) { _orbitGeometry = new ImmediateGeometry(); var m = new SpatialMaterial(); m.VertexColorUseAsAlbedo = true; m.FlagsUnshaded = true; _orbitGeometry.MaterialOverride = m; AddChild(_orbitGeometry); } return _orbitGeometry; } } private float _time = 0; [Export] private float _speed = 3f; public override void _Process(float delta) { _time += delta * _speed; InvalidateGeometry(); } private void InvalidateGeometry() { Orbit.Ellipse = new Ellipse(SemiMajorAxis, Eccentricity); Orbit.Draw(OrbitGeometry); Orbiter.Position = Orbit.GetPosition(_time); } }