diff --git a/StoneRed.LogicSimulator/Simulation/LogicGates/TestLogicGate.cs b/StoneRed.LogicSimulator/Simulation/LogicGates/TestLogicGate.cs new file mode 100644 index 0000000..32e15fc --- /dev/null +++ b/StoneRed.LogicSimulator/Simulation/LogicGates/TestLogicGate.cs @@ -0,0 +1,29 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +using StoneRed.LogicSimulator.Simulation.LogicGates.Attributes; +using StoneRed.LogicSimulator.Simulation.LogicGates.Interfaces; + +namespace StoneRed.LogicSimulator.Simulation.LogicGates; + +#if DEBUG + +[LogicGateName("Test")] +internal class TestLogicGate : LogicGate, Interfaces.IDrawable +{ + public override int OutputCount { get; set; } = 1; + public override int InputCount { get; set; } = 1; + + public Texture2D Texture => CreateTexture(1, 1); + + protected override void Execute() + { + Texture.SetData(new Color[] { Color.Red }); + + for (int i = 0; i < InputCount; i++) + { + SetOutputBit(GetInputBit(i), i); + } + } +} +#endif \ No newline at end of file diff --git a/StoneRed.LogicSimulator/Srls.cs b/StoneRed.LogicSimulator/Srls.cs index 57e4828..ff773f2 100644 --- a/StoneRed.LogicSimulator/Srls.cs +++ b/StoneRed.LogicSimulator/Srls.cs @@ -36,6 +36,8 @@ internal class Srls : Game public Settings Settings { get; set; } + public const ushort CurrentSaveVersion = 1; + public Srls() { Content.RootDirectory = "Content"; @@ -162,7 +164,7 @@ internal class Srls : Game FileAssetResolver assetResolver = new FileAssetResolver(Paths.GetContentPath()); AssetManager = new AssetManager(assetResolver); - LogicGatesManager = new LogicGatesManager(); + LogicGatesManager = new LogicGatesManager(GraphicsDevice); LogicGatesManager.LoadLogicGates(); LoadScreen(); diff --git a/StoneRed.LogicSimulator/UserInterface/Screens/LoadingScreen.cs b/StoneRed.LogicSimulator/UserInterface/Screens/LoadingScreen.cs index 565428b..fd7fbaf 100644 --- a/StoneRed.LogicSimulator/UserInterface/Screens/LoadingScreen.cs +++ b/StoneRed.LogicSimulator/UserInterface/Screens/LoadingScreen.cs @@ -49,8 +49,8 @@ internal class LoadingScreen : SrlsScreen } else { - srls.ShowWindow(new InfoDialog(string.Join(',', result.Errors.Select(e => e.Message)))); srls.LoadScreen(); + srls.ShowWindow(new InfoDialog(string.Join(',', result.Errors.Select(e => e.Message)))); } }); } diff --git a/StoneRed.LogicSimulator/UserInterface/Screens/WorldScreen.cs b/StoneRed.LogicSimulator/UserInterface/Screens/WorldScreen.cs index c815e4e..6f410d6 100644 --- a/StoneRed.LogicSimulator/UserInterface/Screens/WorldScreen.cs +++ b/StoneRed.LogicSimulator/UserInterface/Screens/WorldScreen.cs @@ -55,7 +55,7 @@ internal class WorldScreen : SrlsScreen public WorldScreen() { simulator = new LogicGateSimulator(Enumerable.Empty()); - worldData = new WorldData(Enumerable.Empty(), 1, string.Empty); + worldData = new WorldData(Enumerable.Empty(), Srls.CurrentSaveVersion, string.Empty); } protected override void Initialize() @@ -173,7 +173,7 @@ internal class WorldScreen : SrlsScreen } fpsLabel.Text = $"FPS: {Math.Round(fps)}"; - upsLabel.Text = $"FRQ: {FrequencyCalculator.CalculateFrequency(simulator.ActualTicksPerSecond)}/{FrequencyCalculator.CalculateFrequency(simulator.TargetTicksPerSecond)}{(simulator.HighPerformanceClock ? "*" : string.Empty)} {(simulator.ClockCalibrating ? $"[Calibrating... {calibrationPercentage}%]" : string.Empty)}"; + upsLabel.Text = $"FRQ: {FrequencyCalculator.CalculateFrequency(simulator.ActualTicksPerSecond)}/{FrequencyCalculator.CalculateFrequency(simulator.TargetTicksPerSecond)}{(simulator.HighPerformanceClock ? "*" : string.Empty)} {(simulator.ClockCalibrating && simulator.HighPerformanceClock ? $"[Calibrating... {calibrationPercentage}%]" : string.Empty)}"; positionLabel.Text = $"X/Y: {(long)Math.Round(camera.Position.X / logicGateSize.X / srls.Scale)}/{(long)Math.Round(camera.Position.Y / logicGateSize.Y / srls.Scale)}"; simulator.TargetTicksPerSecond = (int)frequency.Value.GetValueOrDefault(); @@ -222,8 +222,15 @@ internal class WorldScreen : SrlsScreen { selectedLogicGate.WorldData.Position /= srls.Scale; simulator.AddLogicGate(selectedLogicGate); - selectedLogicGate = null; - nativeComponentsListBox.SelectedIndex = -1; + + if (keyboardState.IsShiftDown()) + { + SelectLogicGate(); + } + else + { + UnSelectLogicGate(); + } } else { @@ -236,12 +243,12 @@ internal class WorldScreen : SrlsScreen if (keyboardState.IsKeyDown(Keys.C)) { - connectionContext = null; - selectedLogicGate = null; + UnSelectLogicGate(); } if (keyboardState.IsKeyDown(Keys.Q)) { + UnSelectLogicGate(); worldData.LogicGates = simulator.GetLogicGates(); srls.ShowWindow(new QuickMenu(worldData)); } @@ -278,7 +285,7 @@ internal class WorldScreen : SrlsScreen return r < 0 ? r + m : r; } - private void NativeComponentsListBox_SelectedIndexChanged(object? sender, EventArgs e) + private void SelectLogicGate() { if (nativeComponentsListBox.SelectedItem is not null) { @@ -288,6 +295,19 @@ internal class WorldScreen : SrlsScreen } } + private void UnSelectLogicGate() + { + connectionContext = null; + selectedLogicGate = null; + nativeComponentsListBox.SelectedIndex = -1; + nativeComponentsListBox.SelectedItem = null; + } + + private void NativeComponentsListBox_SelectedIndexChanged(object? sender, EventArgs e) + { + SelectLogicGate(); + } + private void ShowConnectionContextMenu(LogicGate logicGate, Point position, bool showInputs) { showInputs = logicGate.OutputCount <= 0 || (showInputs && logicGate.InputCount > 0); diff --git a/StoneRed.LogicSimulator/Utilities/LogicGatesManager.cs b/StoneRed.LogicSimulator/Utilities/LogicGatesManager.cs index 40e6f3a..7d42a97 100644 --- a/StoneRed.LogicSimulator/Utilities/LogicGatesManager.cs +++ b/StoneRed.LogicSimulator/Utilities/LogicGatesManager.cs @@ -59,13 +59,13 @@ internal class LogicGatesManager return logicGate; } - public string GetTypeName(Type type) + public static string GetTypeLogicGateName(Type type) { LogicGateNameAttribute nameAttribute = (LogicGateNameAttribute)type.GetCustomAttributes(typeof(LogicGateNameAttribute), false)[0]; return nameAttribute.Name; } - public bool TryGetTypeName(Type type, [NotNullWhen(true)] out string? typeName) + public static bool TryGetTypeLogicGateName(Type type, [NotNullWhen(true)] out string? typeName) { if (type.GetCustomAttributes(typeof(LogicGateNameAttribute), false).FirstOrDefault() is not LogicGateNameAttribute nameAttribute) { diff --git a/StoneRed.LogicSimulator/WorldSaveSystem/WorldData.cs b/StoneRed.LogicSimulator/WorldSaveSystem/WorldData.cs index 04133fa..fb90946 100644 --- a/StoneRed.LogicSimulator/WorldSaveSystem/WorldData.cs +++ b/StoneRed.LogicSimulator/WorldSaveSystem/WorldData.cs @@ -8,11 +8,11 @@ internal class WorldData { public IEnumerable LogicGates { get; set; } - public int SaveVersion { get; set; } + public ushort SaveVersion { get; set; } public string SaveName { get; set; } - public WorldData(IEnumerable logicGates, int saveVersion, string saveName) + public WorldData(IEnumerable logicGates, ushort saveVersion, string saveName) { LogicGates = logicGates; SaveVersion = saveVersion; diff --git a/StoneRed.LogicSimulator/WorldSaveSystem/WorldReaders/WorldReaderV1.cs b/StoneRed.LogicSimulator/WorldSaveSystem/WorldReaders/WorldReaderV1.cs index 230e665..7dbb690 100644 --- a/StoneRed.LogicSimulator/WorldSaveSystem/WorldReaders/WorldReaderV1.cs +++ b/StoneRed.LogicSimulator/WorldSaveSystem/WorldReaders/WorldReaderV1.cs @@ -40,7 +40,7 @@ internal class WorldReaderV1 : IWorldReader progress.Report(new(0, "Opening file")); reader = new BinaryReader(File.OpenRead(Paths.GetWorldSaveFilePath(saveName))); - int saveVersion = reader.ReadUInt16(); + ushort saveVersion = reader.ReadUInt16(); int numberOfLogicGates = reader.ReadInt32(); diff --git a/StoneRed.LogicSimulator/WorldSaveSystem/WorldSaver.cs b/StoneRed.LogicSimulator/WorldSaveSystem/WorldSaver.cs index 6665ce2..73304ec 100644 --- a/StoneRed.LogicSimulator/WorldSaveSystem/WorldSaver.cs +++ b/StoneRed.LogicSimulator/WorldSaveSystem/WorldSaver.cs @@ -9,18 +9,16 @@ namespace StoneRed.LogicSimulator.WorldSaveSystem; internal class WorldSaver { - private readonly Srls srls; - - public WorldSaver(Srls srls) + public WorldSaver(Srls _) { - this.srls = srls; + } public Task SaveWorld(WorldData worldData, IProgress progress) { IWorldWriter? worldWriter = worldData.SaveVersion switch { - 1 => new WorldWriterV1(srls), + 1 => new WorldWriterV1(), _ => null }; diff --git a/StoneRed.LogicSimulator/WorldSaveSystem/WorldWriters/WorldWriterV1.cs b/StoneRed.LogicSimulator/WorldSaveSystem/WorldWriters/WorldWriterV1.cs index 8fdb15e..95577a0 100644 --- a/StoneRed.LogicSimulator/WorldSaveSystem/WorldWriters/WorldWriterV1.cs +++ b/StoneRed.LogicSimulator/WorldSaveSystem/WorldWriters/WorldWriterV1.cs @@ -3,6 +3,7 @@ using StoneRed.LogicSimulator.Misc; using StoneRed.LogicSimulator.Simulation.LogicGates.Attributes; using StoneRed.LogicSimulator.Simulation.LogicGates.Interfaces; +using StoneRed.LogicSimulator.Utilities; using System; using System.IO; @@ -13,13 +14,6 @@ namespace StoneRed.LogicSimulator.WorldSaveSystem.WorldWriters; internal class WorldWriterV1 : IWorldWriter { - private readonly Srls srls; - - public WorldWriterV1(Srls srls) - { - this.srls = srls; - } - public Task WriteWorld(WorldData worldData, IProgress progress) { return Task.Run(() => InternalWriteWorld(worldData, progress)); @@ -39,14 +33,14 @@ internal class WorldWriterV1 : IWorldWriter int numberOfLogicGates = worldData.LogicGates.Count(); - writer.Write((short)1); // Write file version + writer.Write((ushort)1); // Write file version writer.Write(numberOfLogicGates); foreach (LogicGate logicGate in worldData.LogicGates) { writer.Write(logicGate.Id); - if (!srls.LogicGatesManager.TryGetTypeName(logicGate.GetType(), out string? typeName)) + if (!LogicGatesManager.TryGetTypeLogicGateName(logicGate.GetType(), out string? typeName)) { return Result.Fail($"Logic gate type \"{logicGate.GetType().FullName}\" has no \"{nameof(LogicGateNameAttribute)}\" attribute!"); }