Fix some bugs and add TestLogicGate

This commit is contained in:
Stone_Red
2023-10-04 12:29:18 +02:00
parent 05a8a72158
commit f1992193e9
9 changed files with 71 additions and 28 deletions
@@ -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
+3 -1
View File
@@ -36,6 +36,8 @@ internal class Srls : Game
public Settings Settings { get; set; } public Settings Settings { get; set; }
public const ushort CurrentSaveVersion = 1;
public Srls() public Srls()
{ {
Content.RootDirectory = "Content"; Content.RootDirectory = "Content";
@@ -162,7 +164,7 @@ internal class Srls : Game
FileAssetResolver assetResolver = new FileAssetResolver(Paths.GetContentPath()); FileAssetResolver assetResolver = new FileAssetResolver(Paths.GetContentPath());
AssetManager = new AssetManager(assetResolver); AssetManager = new AssetManager(assetResolver);
LogicGatesManager = new LogicGatesManager(); LogicGatesManager = new LogicGatesManager(GraphicsDevice);
LogicGatesManager.LoadLogicGates(); LogicGatesManager.LoadLogicGates();
LoadScreen<StartScreen>(); LoadScreen<StartScreen>();
@@ -49,8 +49,8 @@ internal class LoadingScreen : SrlsScreen<VerticalStackPanel>
} }
else else
{ {
srls.ShowWindow(new InfoDialog(string.Join(',', result.Errors.Select(e => e.Message))));
srls.LoadScreen<StartScreen>(); srls.LoadScreen<StartScreen>();
srls.ShowWindow(new InfoDialog(string.Join(',', result.Errors.Select(e => e.Message))));
} }
}); });
} }
@@ -55,7 +55,7 @@ internal class WorldScreen : SrlsScreen<Grid>
public WorldScreen() public WorldScreen()
{ {
simulator = new LogicGateSimulator(Enumerable.Empty<LogicGate>()); simulator = new LogicGateSimulator(Enumerable.Empty<LogicGate>());
worldData = new WorldData(Enumerable.Empty<LogicGate>(), 1, string.Empty); worldData = new WorldData(Enumerable.Empty<LogicGate>(), Srls.CurrentSaveVersion, string.Empty);
} }
protected override void Initialize() protected override void Initialize()
@@ -173,7 +173,7 @@ internal class WorldScreen : SrlsScreen<Grid>
} }
fpsLabel.Text = $"FPS: {Math.Round(fps)}"; 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)}"; 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(); simulator.TargetTicksPerSecond = (int)frequency.Value.GetValueOrDefault();
@@ -222,8 +222,15 @@ internal class WorldScreen : SrlsScreen<Grid>
{ {
selectedLogicGate.WorldData.Position /= srls.Scale; selectedLogicGate.WorldData.Position /= srls.Scale;
simulator.AddLogicGate(selectedLogicGate); simulator.AddLogicGate(selectedLogicGate);
selectedLogicGate = null;
nativeComponentsListBox.SelectedIndex = -1; if (keyboardState.IsShiftDown())
{
SelectLogicGate();
}
else
{
UnSelectLogicGate();
}
} }
else else
{ {
@@ -236,12 +243,12 @@ internal class WorldScreen : SrlsScreen<Grid>
if (keyboardState.IsKeyDown(Keys.C)) if (keyboardState.IsKeyDown(Keys.C))
{ {
connectionContext = null; UnSelectLogicGate();
selectedLogicGate = null;
} }
if (keyboardState.IsKeyDown(Keys.Q)) if (keyboardState.IsKeyDown(Keys.Q))
{ {
UnSelectLogicGate();
worldData.LogicGates = simulator.GetLogicGates(); worldData.LogicGates = simulator.GetLogicGates();
srls.ShowWindow(new QuickMenu(worldData)); srls.ShowWindow(new QuickMenu(worldData));
} }
@@ -278,7 +285,7 @@ internal class WorldScreen : SrlsScreen<Grid>
return r < 0 ? r + m : r; return r < 0 ? r + m : r;
} }
private void NativeComponentsListBox_SelectedIndexChanged(object? sender, EventArgs e) private void SelectLogicGate()
{ {
if (nativeComponentsListBox.SelectedItem is not null) if (nativeComponentsListBox.SelectedItem is not null)
{ {
@@ -288,6 +295,19 @@ internal class WorldScreen : SrlsScreen<Grid>
} }
} }
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) private void ShowConnectionContextMenu(LogicGate logicGate, Point position, bool showInputs)
{ {
showInputs = logicGate.OutputCount <= 0 || (showInputs && logicGate.InputCount > 0); showInputs = logicGate.OutputCount <= 0 || (showInputs && logicGate.InputCount > 0);
@@ -59,13 +59,13 @@ internal class LogicGatesManager
return logicGate; return logicGate;
} }
public string GetTypeName(Type type) public static string GetTypeLogicGateName(Type type)
{ {
LogicGateNameAttribute nameAttribute = (LogicGateNameAttribute)type.GetCustomAttributes(typeof(LogicGateNameAttribute), false)[0]; LogicGateNameAttribute nameAttribute = (LogicGateNameAttribute)type.GetCustomAttributes(typeof(LogicGateNameAttribute), false)[0];
return nameAttribute.Name; 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) if (type.GetCustomAttributes(typeof(LogicGateNameAttribute), false).FirstOrDefault() is not LogicGateNameAttribute nameAttribute)
{ {
@@ -8,11 +8,11 @@ internal class WorldData
{ {
public IEnumerable<LogicGate> LogicGates { get; set; } public IEnumerable<LogicGate> LogicGates { get; set; }
public int SaveVersion { get; set; } public ushort SaveVersion { get; set; }
public string SaveName { get; set; } public string SaveName { get; set; }
public WorldData(IEnumerable<LogicGate> logicGates, int saveVersion, string saveName) public WorldData(IEnumerable<LogicGate> logicGates, ushort saveVersion, string saveName)
{ {
LogicGates = logicGates; LogicGates = logicGates;
SaveVersion = saveVersion; SaveVersion = saveVersion;
@@ -40,7 +40,7 @@ internal class WorldReaderV1 : IWorldReader
progress.Report(new(0, "Opening file")); progress.Report(new(0, "Opening file"));
reader = new BinaryReader(File.OpenRead(Paths.GetWorldSaveFilePath(saveName))); reader = new BinaryReader(File.OpenRead(Paths.GetWorldSaveFilePath(saveName)));
int saveVersion = reader.ReadUInt16(); ushort saveVersion = reader.ReadUInt16();
int numberOfLogicGates = reader.ReadInt32(); int numberOfLogicGates = reader.ReadInt32();
@@ -9,18 +9,16 @@ namespace StoneRed.LogicSimulator.WorldSaveSystem;
internal class WorldSaver internal class WorldSaver
{ {
private readonly Srls srls; public WorldSaver(Srls _)
public WorldSaver(Srls srls)
{ {
this.srls = srls;
} }
public Task<Result> SaveWorld(WorldData worldData, IProgress<WorldSaveLoadProgress> progress) public Task<Result> SaveWorld(WorldData worldData, IProgress<WorldSaveLoadProgress> progress)
{ {
IWorldWriter? worldWriter = worldData.SaveVersion switch IWorldWriter? worldWriter = worldData.SaveVersion switch
{ {
1 => new WorldWriterV1(srls), 1 => new WorldWriterV1(),
_ => null _ => null
}; };
@@ -3,6 +3,7 @@
using StoneRed.LogicSimulator.Misc; using StoneRed.LogicSimulator.Misc;
using StoneRed.LogicSimulator.Simulation.LogicGates.Attributes; using StoneRed.LogicSimulator.Simulation.LogicGates.Attributes;
using StoneRed.LogicSimulator.Simulation.LogicGates.Interfaces; using StoneRed.LogicSimulator.Simulation.LogicGates.Interfaces;
using StoneRed.LogicSimulator.Utilities;
using System; using System;
using System.IO; using System.IO;
@@ -13,13 +14,6 @@ namespace StoneRed.LogicSimulator.WorldSaveSystem.WorldWriters;
internal class WorldWriterV1 : IWorldWriter internal class WorldWriterV1 : IWorldWriter
{ {
private readonly Srls srls;
public WorldWriterV1(Srls srls)
{
this.srls = srls;
}
public Task<Result> WriteWorld(WorldData worldData, IProgress<WorldSaveLoadProgress> progress) public Task<Result> WriteWorld(WorldData worldData, IProgress<WorldSaveLoadProgress> progress)
{ {
return Task.Run(() => InternalWriteWorld(worldData, progress)); return Task.Run(() => InternalWriteWorld(worldData, progress));
@@ -39,14 +33,14 @@ internal class WorldWriterV1 : IWorldWriter
int numberOfLogicGates = worldData.LogicGates.Count(); int numberOfLogicGates = worldData.LogicGates.Count();
writer.Write((short)1); // Write file version writer.Write((ushort)1); // Write file version
writer.Write(numberOfLogicGates); writer.Write(numberOfLogicGates);
foreach (LogicGate logicGate in worldData.LogicGates) foreach (LogicGate logicGate in worldData.LogicGates)
{ {
writer.Write(logicGate.Id); 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!"); return Result.Fail($"Logic gate type \"{logicGate.GetType().FullName}\" has no \"{nameof(LogicGateNameAttribute)}\" attribute!");
} }