StarSim

StarSim.git
git clone git://git.lenczewski.org/StarSim.git
Log | Files | Refs | README | LICENSE

commit e03310b51cc316b7c13e690e57bae5b699f41db1
parent db021ef349798040b57ffacaedad13fa1df5da3c
Author: Mikolaj Lenczewski <33129490+EnderRifter@users.noreply.github.com>
Date:   Tue, 13 Aug 2019 14:20:22 +0200

Finished simulation view model/

Diffstat:
AStarSim/StarSimGui/Source/BodyDummy.cs | 147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MStarSim/StarSimGui/StarSimGui.csproj | 8++++++++
MStarSim/StarSimGui/ViewModels/DatabaseViewModel.cs | 8++++++++
MStarSim/StarSimGui/ViewModels/MainWindowViewModel.cs | 7+++++++
MStarSim/StarSimGui/ViewModels/OverviewViewModel.cs | 11+++++++++--
MStarSim/StarSimGui/ViewModels/SimulationViewModel.cs | 279++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
MStarSim/StarSimGui/ViewModels/UserLoginViewModel.cs | 22++++++++++++++++++++--
MStarSim/StarSimGui/Views/Database.xaml | 11++++++++++-
MStarSim/StarSimGui/Views/Overview.xaml | 19+++++++++++++++----
MStarSim/StarSimGui/Views/Simulation.xaml | 47++++++++++++++++++++++++++++++++++++++++++++++-
MStarSim/StarSimLib/Constants.cs | 5+++++
MStarSim/StarSimLib/Data Structures/Body.cs | 25+++++++++----------------
MStarSim/StarSimLib/Data Structures/Vector4.cs | 16++++++----------
MStarSim/StarSimLib/StarSimLib.xml | 27++++++++++++++++-----------
MStarSim/StarSimLib/UI/Screen.cs | 8++++++++
15 files changed, 591 insertions(+), 49 deletions(-)

diff --git a/StarSim/StarSimGui/Source/BodyDummy.cs b/StarSim/StarSimGui/Source/BodyDummy.cs @@ -0,0 +1,146 @@ +using System.ComponentModel; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using StarSimLib; +using StarSimLib.Data_Structures; + +namespace StarSimGui.Source +{ + /// <summary> + /// Represents the editable fields in a <see cref="Body"/> instance. + /// </summary> + public class BodyDummy : INotifyPropertyChanged + { + /// <summary> + /// The underlying mass. + /// </summary> + private double mass; + + /// <summary> + /// The underlying position vector. + /// </summary> + private Vector4 positionVector; + + /// <summary> + /// The underlying velocity vector. + /// </summary> + private Vector4 velocityVector; + + /// <summary> + /// Initialises a new instance of the <see cref="BodyDummy"/> class. + /// </summary> + public BodyDummy() + { + } + + /// <summary> + /// Initialises a new instance of the <see cref="BodyDummy"/> class. + /// </summary> + /// <param name="body">The <see cref="Body"/> instance around which to construct a dummy.</param> + public BodyDummy(Body body) + { + Generation = body.Generation; + Id = body.Id; + mass = body.Mass; + positionVector = body.Position; + velocityVector = body.Velocity; + } + + /// <summary> + /// Signals that a property on this instance has changed. + /// </summary> + public event PropertyChangedEventHandler PropertyChanged; + + /// <summary> + /// The generation of this instance. + /// </summary> + public uint Generation { get; set; } + + /// <summary> + /// The id of this instance. + /// </summary> + public uint Id { get; set; } + + /// <summary> + /// The starting mass of this instance. + /// </summary> + public double Mass + { + get { return mass; } + set { mass = value; } + } + + /// <summary> + /// The starting position X component of this instance. + /// </summary> + public double PosX + { + get { return positionVector.X; } + set { positionVector.X = value; } + } + + /// <summary> + /// The starting position Y component of this instance. + /// </summary> + public double PosY + { + get { return positionVector.Y; } + set { positionVector.Y = value; } + } + + /// <summary> + /// The starting position Z component of this instance. + /// </summary> + public double PosZ + { + get { return positionVector.Z; } + set { positionVector.Z = value; } + } + + /// <summary> + /// The starting velocity X component of this instance. + /// </summary> + public double VelX + { + get { return velocityVector.X; } + set { velocityVector.X = value; } + } + + /// <summary> + /// The starting velocity Y component of this instance. + /// </summary> + public double VelY + { + get { return velocityVector.Y; } + set { velocityVector.Y = value; } + } + + /// <summary> + /// The starting velocity Z component of this instance. + /// </summary> + public double VelZ + { + get { return velocityVector.Z; } + set { velocityVector.Z = value; } + } + + /// <summary> + /// Invokes the <see cref="PropertyChanged"/> event with the name of the caller property that changed. + /// </summary> + /// <param name="propertyName"></param> + [NotifyPropertyChangedInvocator] + private void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + /// <summary> + /// Implements an explicit conversion between a <see cref="BodyDummy"/> instance to a <see cref="Body"/> instance. + /// </summary> + /// <param name="instance">The <see cref="BodyDummy"/> instance to convert.</param> + public static explicit operator Body(BodyDummy instance) + { + return new Body(instance.positionVector, instance.velocityVector, instance.Mass, instance.Generation, instance.Id); + } + } +} +\ No newline at end of file diff --git a/StarSim/StarSimGui/StarSimGui.csproj b/StarSim/StarSimGui/StarSimGui.csproj @@ -6,6 +6,14 @@ <Platforms>AnyCPU;x64;x86</Platforms> </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|netcoreapp2.1|AnyCPU'"> + <AllowUnsafeBlocks>false</AllowUnsafeBlocks> + </PropertyGroup> + + <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|netcoreapp2.1|AnyCPU'"> + <AllowUnsafeBlocks>false</AllowUnsafeBlocks> + </PropertyGroup> + <ItemGroup> <Folder Include="Models\" /> <Compile Update="**\*.xaml.cs"> diff --git a/StarSim/StarSimGui/ViewModels/DatabaseViewModel.cs b/StarSim/StarSimGui/ViewModels/DatabaseViewModel.cs @@ -52,6 +52,14 @@ namespace StarSimGui.ViewModels } /// <summary> + /// Whether the currently logged in user has administrator privileges. + /// </summary> + public bool IsAdmin + { + get { return (currentUser.Privileges & UserPrivileges.Admin) == UserPrivileges.Admin; } + } + + /// <summary> /// Handles the <see cref="UserLoginViewModel.LoggedIn"/> event. /// </summary> /// <param name="newUser">The user which logged in.</param> diff --git a/StarSim/StarSimGui/ViewModels/MainWindowViewModel.cs b/StarSim/StarSimGui/ViewModels/MainWindowViewModel.cs @@ -38,6 +38,13 @@ namespace StarSimGui.ViewModels UserLoginViewModel.LoggedOut += DatabaseViewModel.HandleLogout; UserLoginViewModel.LoggedOut += OverviewViewModel.HandleLogout; UserLoginViewModel.LoggedOut += SimulationViewModel.HandleLogout; + +#if DEBUG + // simulate a login to accelerate development of the application, as the implemented cryptographic features + // of the login system make it slow to solve for the password hash. furthermore loading the database takes + // a relatively long time as well - this wastes development time + UserLoginViewModel.DebugSimulateLogin(new User(0, "Debug User", UserPrivileges.Admin, "debug@application.net")); +#endif } /// <summary> diff --git a/StarSim/StarSimGui/ViewModels/OverviewViewModel.cs b/StarSim/StarSimGui/ViewModels/OverviewViewModel.cs @@ -1,4 +1,11 @@ -using ReactiveUI; +using System.IO; +using Avalonia; +using Avalonia.Media; +using Avalonia.Media.Imaging; +using Avalonia.Platform; +using Avalonia.Skia; +using ReactiveUI; +using StarSimGui.Source; using StarSimLib.Contexts; using StarSimLib.Models; @@ -15,7 +22,7 @@ namespace StarSimGui.ViewModels private readonly SimulatorContext dbContext; /// <summary> - /// The currently logged in user. + /// The backing field for the <see cref="CurrentUser"/> property. /// </summary> private User currentUser; diff --git a/StarSim/StarSimGui/ViewModels/SimulationViewModel.cs b/StarSim/StarSimGui/ViewModels/SimulationViewModel.cs @@ -1,6 +1,20 @@ -using ReactiveUI; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Windows.Input; +using DynamicData; +using DynamicData.Binding; +using DynamicData.Cache.Internal; +using ReactiveUI; +using SFML.Graphics; +using SFML.Window; +using StarSimGui.Source; +using StarSimLib; using StarSimLib.Contexts; using StarSimLib.Models; +using StarSimLib.Physics; +using StarSimLib.UI; +using Body = StarSimLib.Data_Structures.Body; namespace StarSimGui.ViewModels { @@ -10,16 +24,66 @@ namespace StarSimGui.ViewModels public class SimulationViewModel : ViewModelBase { /// <summary> + /// The delegate method to use to derive the colour of a body's shape from the body's mass. + /// </summary> + private readonly MassToColourDelegate bodyMassToColourDelegate = BodyGenerator.DefaultColourDelegate; + + /// <summary> + /// The delegate method to use to derive the radius of a body's shape from the body's mass. + /// </summary> + private readonly MassToRadiusDelegate bodyMassToRadiusDelegate = BodyGenerator.DefaultRadiusDelegate; + + /// <summary> /// The program database. /// </summary> private readonly SimulatorContext dbContext; /// <summary> - /// The currently logged in user. + /// The body position update delegate to use in the simulation. + /// </summary> + private readonly UpdateDelegate simulationBodyUpdateDelegate = BodyUpdater.UpdateBodiesBarnesHut; + + /// <summary> + /// The dummy body holding the field values for the generated <see cref="Body"/> instance. + /// </summary> + private BodyDummy currentBodyDummy; + + /// <summary> + /// The current simulation. + /// </summary> + private SimulationScreen currentSimulation; + + /// <summary> + /// The backing field for the <see cref="CurrentUser"/> property. /// </summary> private User currentUser; /// <summary> + /// The backing field for the <see cref="SelectedItemIndex"/> property. + /// </summary> + private int selectedItemIndex = 0; + + /// <summary> + /// The bodies that will participate in the simulation. + /// </summary> + private List<Body> simulatedBodies; + + /// <summary> + /// The backing field for the <see cref="SimulatedBodies"/> property. + /// </summary> + private IObservableCollection<Body> simulatedBodiesObservable; + + /// <summary> + /// The backing field for the <see cref="SimulatedBodyCount"/> property. + /// </summary> + private int simulatedBodyCount = Constants.BodyCount; + + /// <summary> + /// Maps the bodies participating in the simulation to their shapes that will be rendered to represent them. + /// </summary> + private Dictionary<Body, CircleShape> simulatedBodyShapes; + + /// <summary> /// Initialises a new instance of the <see cref="SimulationViewModel"/> class. /// </summary> public SimulationViewModel() : this(null) @@ -33,6 +97,54 @@ namespace StarSimGui.ViewModels public SimulationViewModel(SimulatorContext context) { dbContext = context; + + simulatedBodies = new List<Body>(); + + simulatedBodiesObservable = new ObservableCollectionExtended<Body>(simulatedBodies); + + IObservable<bool> canAddBody = + this.WhenAnyValue(x => x.CurrentBody, selector: body => !body?.Equals(new BodyDummy()) ?? false); + + AddBodyCommand = ReactiveCommand.Create(AddBodyCommandImpl, canAddBody); + + IObservable<bool> canDeleteBody = + this.WhenAnyValue(x => x.CurrentBody, selector: body => !body?.Equals(new BodyDummy()) ?? false); + + DeleteBodyCommand = ReactiveCommand.Create(DeleteBodyCommandImpl, canDeleteBody); + + GenerateBodiesCommand = ReactiveCommand.Create(GenerateBodiesCommandImpl); + + IObservable<bool> currentSimulationInactive = + this.WhenAnyValue(x => x.currentSimulation, selector: screen => screen == null); + + StartSimulationCommand = + ReactiveCommand.CreateFromTask(StartSimulationCommandImpl, currentSimulationInactive); + + IObservable<bool> canUpdateBody = this.WhenAnyValue(x => x.CurrentBody, x => x.SelectedItemIndex, + (body, selectedIndex) => (!body?.Equals(new BodyDummy()) ?? false) && selectedIndex >= 0 && selectedIndex < 10_000); + + UpdateBodyCommand = ReactiveCommand.Create(UpdateBodyCommandImpl, canUpdateBody); + } + + /// <summary> + /// Command invoked whenever the currently inspected body should be added to the <see cref="simulatedBodies"/> collection. + /// </summary> + public ICommand AddBodyCommand { get; } + + /// <summary> + /// The <see cref="Body"/> instance currently selected for editing or viewing. + /// </summary> + public BodyDummy CurrentBody + { + get + { + return currentBodyDummy; + } + set + { + currentBodyDummy = value; + this.RaisePropertyChanged(); + } } /// <summary> @@ -52,6 +164,160 @@ namespace StarSimGui.ViewModels } /// <summary> + /// Command invoked whenever the currently inspected body should be deleted from the <see cref="simulatedBodies"/> collection. + /// </summary> + public ICommand DeleteBodyCommand { get; } + + /// <summary> + /// Command invoked whenever the user wants to generate a new collection. + /// </summary> + public ICommand GenerateBodiesCommand { get; } + + /// <summary> + /// The index of the currently selected item in the <see cref="SimulatedBodies"/> collection. + /// </summary> + public int SelectedItemIndex + { + get + { + return selectedItemIndex; + } + set + { + selectedItemIndex = value; + this.RaisePropertyChanged(); + + if (selectedItemIndex >= 0) + { + currentBodyDummy = new BodyDummy(simulatedBodiesObservable?[selectedItemIndex]); + this.RaisePropertyChanged(nameof(CurrentBody)); + } + } + } + + /// <summary> + /// Whether to simulate a central attractor. + /// </summary> + public bool SimulateCentralAttractor { get; set; } = true; + + /// <summary> + /// The bodies that will participate in the simulation. + /// </summary> + public IObservableCollection<Body> SimulatedBodies + { + get + { + return simulatedBodiesObservable; + } + set + { + simulatedBodiesObservable = value; + this.RaisePropertyChanged(); + } + } + + /// <summary> + /// The number of bodies to generate. + /// </summary> + public int SimulatedBodyCount + { + get + { + return simulatedBodyCount; + } + set + { + simulatedBodyCount = value; + this.RaisePropertyChanged(); + } + } + + /// <summary> + /// Command invoked whenever a simulation should be started. + /// </summary> + public ICommand StartSimulationCommand { get; } + + /// <summary> + /// Command invoked whenever the user wants to update the currently edited body. + /// </summary> + public ICommand UpdateBodyCommand { get; } + + /// <summary> + /// Invoked whenever the user wants to add the currently edited body to the simulation. + /// </summary> + private void AddBodyCommandImpl() + { + CurrentBody.Generation = BodyGenerator.CurrentGeneration; + CurrentBody.Id = simulatedBodiesObservable[simulatedBodiesObservable.Count - 1].Id + 1; + + Body currentBody = (Body)CurrentBody; + + simulatedBodies.Add(currentBody); + simulatedBodiesObservable.Add(currentBody); + } + + /// <summary> + /// Invoked whenever the user wants to delete the currently edited body from the simulation. + /// </summary> + private void DeleteBodyCommandImpl() + { + simulatedBodies.RemoveAt(selectedItemIndex); + simulatedBodiesObservable.RemoveAt(selectedItemIndex); + + CurrentBody = new BodyDummy(); + } + + /// <summary> + /// Invoked whenever the user wants to generate a new set of bodies to simulate. + /// </summary> + private void GenerateBodiesCommandImpl() + { + if (SimulatedBodyCount < 0 || SimulatedBodyCount > 10_000) + { + // we cannot generate a negative number of bodies, and we cannot reliably simulate more than 10 000 bodies + return; + } + + simulatedBodies = new List<Body>(BodyGenerator.GenerateBodies(SimulatedBodyCount, SimulateCentralAttractor)); + + simulatedBodiesObservable.Load(simulatedBodies); + + simulatedBodyShapes = + BodyGenerator.GenerateShapes(simulatedBodies, bodyMassToRadiusDelegate, bodyMassToColourDelegate); + } + + /// <summary> + /// Invoked whenever the user wants to start a new simulation. + /// </summary> + private async Task StartSimulationCommandImpl() + { + Body[] simulatedBodiesArr = simulatedBodies.ToArray(); + + IInputHandler simulationInputHandler = new SimulationInputHandler(ref simulatedBodiesArr); + + ContextSettings customContextSettings = new ContextSettings + { + AntialiasingLevel = 8, + DepthBits = 24, + StencilBits = 8 + }; + + await Task.Factory.StartNew(contextSettingsObj => + { + using (RenderWindow window = new RenderWindow(VideoMode.DesktopMode, "N-Body Simulation: FPS ", + Styles.Default, (ContextSettings)contextSettingsObj)) + { + currentSimulation = new SimulationScreen(window, simulationInputHandler, + ref simulatedBodiesArr, ref simulatedBodyShapes, simulationBodyUpdateDelegate); + + currentSimulation.Run(); + } + }, customContextSettings); + + currentSimulation = null; + } + + /// <summary> /// Handles the <see cref="UserLoginViewModel.LoggedIn"/> event. /// </summary> /// <param name="newUser">The user which logged in.</param> @@ -67,5 +333,14 @@ namespace StarSimGui.ViewModels { CurrentUser = null; } + + /// <summary> + /// Invoked whenever the user wants to update the currently edited body. + /// </summary> + public void UpdateBodyCommandImpl() + { + simulatedBodies[selectedItemIndex] = (Body)CurrentBody; + simulatedBodiesObservable[selectedItemIndex] = (Body)CurrentBody; + } } } \ No newline at end of file diff --git a/StarSim/StarSimGui/ViewModels/UserLoginViewModel.cs b/StarSim/StarSimGui/ViewModels/UserLoginViewModel.cs @@ -213,7 +213,7 @@ namespace StarSimGui.ViewModels /// Invokes the <see cref="LoggedIn"/> event. /// </summary> /// <param name="user">The <see cref="User"/> who successfully logged in.</param> - private void OnLoggedIn(User user) + protected void OnLoggedIn(User user) { LoggedIn?.Invoke(user); } @@ -221,9 +221,27 @@ namespace StarSimGui.ViewModels /// <summary> /// Invokes the <see cref="LoggedOut"/> event. /// </summary> - private void OnLoggedOut() + protected void OnLoggedOut() { LoggedOut?.Invoke(); } + +#if DEBUG + + /// <summary> + /// Simulates a user logging in irrespective of the view. + /// </summary> + /// <param name="debugUser">The debug user to substitute a real user.</param> + public void DebugSimulateLogin(User debugUser) + { + Username = debugUser.Username; + Password = debugUser.Username; + + IsLoggedIn = true; + LoginFeedback = new LoginAttemptResult(LoginResult.Success, "Successful login"); + OnLoggedIn(debugUser); + } + +#endif } } \ No newline at end of file diff --git a/StarSim/StarSimGui/Views/Database.xaml b/StarSim/StarSimGui/Views/Database.xaml @@ -13,6 +13,15 @@ </Design.DataContext> <Border BorderBrush="Gray" BorderThickness="2" CornerRadius="2" Margin="2"> - <TextBlock Text="Database" HorizontalAlignment="Center" VerticalAlignment="Center" /> + <TabControl> + <TabItem Header="Create Users" IsVisible="{Binding IsAdmin}"></TabItem> + <TabItem Header="Create Bodies/Systems"></TabItem> + <TabItem Header="View Users"></TabItem> + <TabItem Header="View Bodies/Systems"></TabItem> + <TabItem Header="Update Users"></TabItem> + <TabItem Header="Update Bodies/Systems"></TabItem> + <TabItem Header="Delete Users" IsVisible="{Binding IsAdmin}"></TabItem> + <TabItem Header="Delete Bodies/Systems"></TabItem> + </TabControl> </Border> </UserControl> \ No newline at end of file diff --git a/StarSim/StarSimGui/Views/Overview.xaml b/StarSim/StarSimGui/Views/Overview.xaml @@ -13,12 +13,23 @@ </Design.DataContext> <Border BorderBrush="Gray" BorderThickness="2" CornerRadius="2" Margin="2"> - <Grid RowDefinitions="Auto,Auto,Auto" ColumnDefinitions="Auto,Auto,Auto"> - <Border BorderBrush="Beige" BorderThickness="2"> + <Grid ColumnDefinitions="*,*,*,*" RowDefinitions="*,*,*,*"> + <Border BorderBrush="Beige" BorderThickness="2" Grid.Column="0" Grid.ColumnSpan="1" Grid.Row="0" Grid.RowSpan="4"> + <Grid ColumnDefinitions="*,*" RowDefinitions="*,*,*,*"> + <TextBlock Grid.Column="0" Grid.Row="0">Username:</TextBlock> + <TextBlock Grid.Column="1" Grid.Row="0" Text="{Binding CurrentUser.Username}" /> + <TextBlock Grid.Column="0" Grid.Row="1">Email:</TextBlock> + <TextBlock Grid.Column="1" Grid.Row="1" Text="{Binding CurrentUser.Email}" /> + <TextBlock Grid.Column="0" Grid.Row="2">Privileges:</TextBlock> + <TextBlock Grid.Column="1" Grid.Row="2" Text="{Binding CurrentUser.Privileges}" /> + <TextBlock Grid.Column="0" Grid.Row="3">Extra Details:</TextBlock> + <TextBlock Grid.Column="1" Grid.Row="3" Text="{Binding CurrentUser.Id}" /> + </Grid> + </Border> + <Border BorderBrush="Beige" BorderThickness="2" Grid.Column="1" Grid.ColumnSpan="3" Grid.Row="0" Grid.RowSpan="3"> <TextBlock>Hello World</TextBlock> </Border> - - <Border BorderBrush="Beige" BorderThickness="2" Grid.Row="1" Grid.Column="1"> + <Border BorderBrush="Beige" BorderThickness="2" Grid.Column="1" Grid.ColumnSpan="3" Grid.Row="3" Grid.RowSpan="1"> <TextBlock>Hello World</TextBlock> </Border> </Grid> diff --git a/StarSim/StarSimGui/Views/Simulation.xaml b/StarSim/StarSimGui/Views/Simulation.xaml @@ -13,6 +13,51 @@ </Design.DataContext> <Border BorderBrush="Gray" BorderThickness="2" CornerRadius="2" Margin="2"> - <TextBlock Text="Simulation" HorizontalAlignment="Center" VerticalAlignment="Center" /> + <Grid ColumnDefinitions="*,*,*,*" RowDefinitions="*,*,*,*"> + <Border BorderBrush="Gray" BorderThickness="2" Margin="2" Grid.Column="0" Grid.ColumnSpan="1" Grid.Row="0" Grid.RowSpan="1"> + <StackPanel> + <StackPanel Orientation="Horizontal"> + <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center">Have Central Attractor:</TextBlock> + <CheckBox VerticalAlignment="Center" HorizontalAlignment="Center" IsChecked="{Binding SimulateCentralAttractor, Mode=TwoWay}"></CheckBox> + <Separator Margin="2" /> + <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center">Simulated Body Count:</TextBlock> + <TextBox VerticalAlignment="Center" HorizontalAlignment="Center" Text="{Binding SimulatedBodyCount, Mode=TwoWay}"></TextBox> + </StackPanel> + <Button Command="{Binding StartSimulationCommand}" Content="Start Simulation" HorizontalAlignment="Stretch" VerticalAlignment="Center" /> + <Button Command="{Binding AddBodyCommand}" Content="Add Selected Body" HorizontalAlignment="Stretch" VerticalAlignment="Center" /> + <Button Command="{Binding DeleteBodyCommand}" Content="Delete Selected Body" HorizontalAlignment="Stretch" VerticalAlignment="Center" /> + <Button Command="{Binding GenerateBodiesCommand}" Content="Generate Random Bodies" HorizontalAlignment="Stretch" VerticalAlignment="Center" /> + </StackPanel> + </Border> + <Border BorderBrush="Gray" BorderThickness="2" Margin="2" Grid.Column="0" Grid.ColumnSpan="1" Grid.Row="1" Grid.RowSpan="3"> + <StackPanel Margin="2" DataContext="{Binding CurrentBody}"> + <TextBlock HorizontalAlignment="Center">Mass (Kilograms)</TextBlock> + <TextBox HorizontalAlignment="Stretch" Text="{Binding Mass, Mode=TwoWay}"></TextBox> + <TextBlock HorizontalAlignment="Center">Position (Metres)</TextBlock> + <TextBlock Text="X:"></TextBlock> + <TextBox HorizontalAlignment="Stretch" Text="{Binding PosX, Mode=TwoWay}"></TextBox> + <TextBlock Text="Y:"></TextBlock> + <TextBox HorizontalAlignment="Stretch" Text="{Binding PosY, Mode=TwoWay}"></TextBox> + <TextBlock Text="Z:"></TextBlock> + <TextBox HorizontalAlignment="Stretch" Text="{Binding PosZ, Mode=TwoWay}"></TextBox> + <Separator Margin="2" /> + <TextBlock HorizontalAlignment="Center">Velocity (Metres per Second)</TextBlock> + <TextBlock Text="X:"></TextBlock> + <TextBox HorizontalAlignment="Stretch" Text="{Binding VelX, Mode=TwoWay}"></TextBox> + <TextBlock Text="Y:"></TextBlock> + <TextBox HorizontalAlignment="Stretch" Text="{Binding VelY, Mode=TwoWay}"></TextBox> + <TextBlock Text="Z:"></TextBlock> + <TextBox HorizontalAlignment="Stretch" Text="{Binding VelZ, Mode=TwoWay}"></TextBox> + <Separator Margin="2" /> + <Button Command="{Binding $parent[1].DataContext.UpdateBodyCommand}" Content="Update Edited Body" HorizontalAlignment="Stretch" VerticalAlignment="Center" /> + </StackPanel> + </Border> + <Border BorderBrush="Gray" BorderThickness="2" Margin="2" Grid.Column="1" Grid.ColumnSpan="1" Grid.Row="0" Grid.RowSpan="4"> + <ListBox Items="{Binding SimulatedBodies}" SelectedIndex="{Binding SelectedItemIndex, Mode=TwoWay}"> + </ListBox> + </Border> + <Border BorderBrush="Gray" BorderThickness="2" Margin="2" Grid.Column="2" Grid.ColumnSpan="2" Grid.Row="0" Grid.RowSpan="4"> + </Border> + </Grid> </Border> </UserControl> \ No newline at end of file diff --git a/StarSim/StarSimLib/Constants.cs b/StarSim/StarSimLib/Constants.cs @@ -8,6 +8,11 @@ namespace StarSimLib public static class Constants { /// <summary> + /// Definition of an astronomical unit. + /// </summary> + public const double AstronomicalUnit = 1.495979e11; + + /// <summary> /// The amount of bodies that are rendered by default. /// </summary> public const int BodyCount = 25; diff --git a/StarSim/StarSimLib/Data Structures/Body.cs b/StarSim/StarSimLib/Data Structures/Body.cs @@ -8,12 +8,6 @@ namespace StarSimLib.Data_Structures public class Body { /// <summary> - /// Describes how the <see cref="Body"/> instance should be formatted as a <see cref="string"/>. - /// </summary> - private const string BodyFormatString = - "Body {0,2}.{1,-4}: Pos-{2}, Vel-{3} Mass-{4,3}"; - - /// <summary> /// The orbit tracers for this instance. /// </summary> private readonly OrbitTracer orbitTracer; @@ -243,6 +237,15 @@ namespace StarSimLib.Data_Structures force.Z = 0; } + /// <inheritdoc /> + public override string ToString() + { + return $"Body {Generation,2:D}.{Id,-4:D}: " + + $"Pos-[{Position.X:E2}, {Position.Y:E2}, {Position.Z:E2}], " + + $"Vel-[{Velocity.X:E2}, {Velocity.Y:E2}, {Velocity.Z:E2}], " + + $"Mass-{Mass:E2}"; + } + /// <summary> /// Updates the <see cref="Position"/> of the current body using the internal force vector and the given time step. /// </summary> @@ -275,15 +278,5 @@ namespace StarSimLib.Data_Structures position += deltaTime * velocity; } - - #region Overrides of Object - - /// <inheritdoc /> - public override string ToString() - { - return string.Format(BodyFormatString, Generation, Id, Position, Velocity, Mass); - } - - #endregion Overrides of Object } } \ No newline at end of file diff --git a/StarSim/StarSimLib/Data Structures/Vector4.cs b/StarSim/StarSimLib/Data Structures/Vector4.cs @@ -412,6 +412,12 @@ namespace StarSimLib.Data_Structures return Abs(); } + /// <inheritdoc /> + public override string ToString() + { + return $"[{X}, {Y}, {Z}, {W}]"; + } + /// <summary> /// Holds unit vectors. /// </summary> @@ -447,15 +453,5 @@ namespace StarSimLib.Data_Structures /// </summary> public static readonly Vector4 Up = new Vector4(0, 1, 0); } - - #region Overrides of ValueType - - /// <inheritdoc /> - public override string ToString() - { - return $"[{X}, {Y}, {Z}, {W}]"; - } - - #endregion Overrides of ValueType } } \ No newline at end of file diff --git a/StarSim/StarSimLib/StarSimLib.xml b/StarSim/StarSimLib/StarSimLib.xml @@ -9,6 +9,11 @@ Holds common constants and helper functions. </summary> </member> + <member name="F:StarSimLib.Constants.AstronomicalUnit"> + <summary> + Definition of an astronomical unit. + </summary> + </member> <member name="F:StarSimLib.Constants.BodyCount"> <summary> The amount of bodies that are rendered by default. @@ -213,11 +218,6 @@ Represents a stellar body. </summary> </member> - <member name="F:StarSimLib.Data_Structures.Body.BodyFormatString"> - <summary> - Describes how the <see cref="T:StarSimLib.Data_Structures.Body"/> instance should be formatted as a <see cref="T:System.String"/>. - </summary> - </member> <member name="F:StarSimLib.Data_Structures.Body.orbitTracer"> <summary> The orbit tracers for this instance. @@ -351,6 +351,9 @@ Resets the internal force vector. </summary> </member> + <member name="M:StarSimLib.Data_Structures.Body.ToString"> + <inheritdoc /> + </member> <member name="M:StarSimLib.Data_Structures.Body.Update(System.Double)"> <summary> Updates the <see cref="P:StarSimLib.Data_Structures.Body.Position"/> of the current body using the internal force vector and the given time step. @@ -364,9 +367,6 @@ <param name="forceVector">The sum vector of all forces due to other <see cref="T:StarSimLib.Data_Structures.Body"/>s.</param> <param name="deltaTime">The time step.</param> </member> - <member name="M:StarSimLib.Data_Structures.Body.ToString"> - <inheritdoc /> - </member> <member name="T:StarSimLib.Data_Structures.EulerAngle"> <summary> Represents a set of 3 angles, that together describe a 3D rotation. @@ -1038,6 +1038,9 @@ </summary> <returns>The magnitude (absolute value) of this <see cref="T:StarSimLib.Data_Structures.Vector4"/>, as a <see cref="T:System.Double"/>.</returns> </member> + <member name="M:StarSimLib.Data_Structures.Vector4.ToString"> + <inheritdoc /> + </member> <member name="T:StarSimLib.Data_Structures.Vector4.UnitVectors"> <summary> Holds unit vectors. @@ -1073,9 +1076,6 @@ The positive unit vector for the Y axis. </summary> </member> - <member name="M:StarSimLib.Data_Structures.Vector4.ToString"> - <inheritdoc /> - </member> <member name="T:StarSimLib.Graphics.RotationDirection"> <summary> Enumerates all possible rotation directions (i.e. north, east, south, west, clockwise, anticlockwise). @@ -1794,6 +1794,11 @@ Displays the screen until it is closed. </summary> </member> + <member name="M:StarSimLib.UI.Screen.Stop"> + <summary> + Safely closes the screen if it is open. + </summary> + </member> <member name="T:StarSimLib.UI.SimulationInputHandler"> <summary> Provides user input handling functions for the simulation. diff --git a/StarSim/StarSimLib/UI/Screen.cs b/StarSim/StarSimLib/UI/Screen.cs @@ -94,5 +94,13 @@ namespace StarSimLib.UI // allows custom screen cleanup code CleanupScreen(renderWindow, RenderStates.Default); } + + /// <summary> + /// Safely closes the screen if it is open. + /// </summary> + public void Stop() + { + renderWindow?.Close(); + } } } \ No newline at end of file