diff --git a/src/ReactorMaintenance.Win2D/MainWindow.xaml b/src/ReactorMaintenance.Win2D/MainWindow.xaml index aa76577..20c4533 100644 --- a/src/ReactorMaintenance.Win2D/MainWindow.xaml +++ b/src/ReactorMaintenance.Win2D/MainWindow.xaml @@ -93,21 +93,23 @@ - - + + + + + + + - - - - - - - + + + + + + + + @@ -134,23 +136,77 @@ - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -169,10 +225,8 @@ - - + + diff --git a/src/ReactorMaintenance.Win2D/MainWindow.xaml.cs b/src/ReactorMaintenance.Win2D/MainWindow.xaml.cs index 9194d57..0295d4e 100644 --- a/src/ReactorMaintenance.Win2D/MainWindow.xaml.cs +++ b/src/ReactorMaintenance.Win2D/MainWindow.xaml.cs @@ -44,7 +44,7 @@ public sealed partial class MainWindow } private sealed record ForecastViewModel(string Message); - private sealed record InspectorItemViewModel(string Label, string Value, string Description); + private sealed record InspectorItemViewModel(string Label, string Value); private sealed record NetworkInspectionViewModel(string Carrier, string State, string Amount, string Intensity, string Integrity); private sealed class EditorToolViewModel(EditorToolCommand command, string label) : INotifyPropertyChanged @@ -171,7 +171,6 @@ public sealed partial class MainWindow m_Level = loaded with { Forecasts = m_Simulation.Forecast(loaded) }; m_CurrentFile = file; m_SelectedCell = null; - m_SelectedReactorId = m_Level.Reactors.FirstOrDefault()?.ReactorId; RefreshInspector(); LevelCanvas.Invalidate(); } @@ -332,7 +331,6 @@ public sealed partial class MainWindow m_EditorFeedback = result.Reason; if (result.Success) { - SelectReactorFromCell(destination); RefreshForecasts(); } @@ -388,10 +386,6 @@ public sealed partial class MainWindow { ApplySelectedTool(position); } - else - { - SelectReactorFromCell(position); - } RefreshInspector(); LevelCanvas.Invalidate(); @@ -408,11 +402,12 @@ public sealed partial class MainWindow private void UpdateHoverCell(Point point) { var nextHover = TryGetGridPosition(point, out var position) ? position : null; - if (nextHover == m_HoverCell) + if (nextHover == HoverCell) return; - m_HoverCell = nextHover; + HoverCell = nextHover; LevelCanvas.Invalidate(); + RefreshInspector(); } private static bool IsDragPaintTool(EEditorTool tool) @@ -695,7 +690,7 @@ public sealed partial class MainWindow DrawStatusBadge(drawing, rect, m_EditorFeedback); } - if (m_HoverCell is { } hover && m_SelectedTool.Tool != EEditorTool.Cursor) + if (HoverCell is { } hover && m_SelectedTool.Tool != EEditorTool.Cursor) { var rect = layout.CellRect(hover); var size = Math.Max(26, rect.Width * 0.42); @@ -806,31 +801,49 @@ public sealed partial class MainWindow StatusText.Text = string.IsNullOrWhiteSpace(m_EditorFeedback) ? $"{m_Level.Global.LevelState}: {m_Level.Global.Status}" : $"{m_Level.Global.LevelState}: {m_EditorFeedback}"; - var doorCount = m_Level.Props.Count(prop => prop.Type == EPropType.Door); - GlobalGrid.ItemsSource = new[] { - new InspectorItemViewModel("Inventory", $"F {m_Level.Robot.FuelNeutralizers} / C {m_Level.Robot.CoolantNeutralizers} / E {m_Level.Robot.ElectricityNeutralizers} / H {m_Level.Robot.HeatShields}", "Remedies carried by the robot."), - new InspectorItemViewModel("Heat Shield", m_Level.Robot.HeatImmunitySteps.ToString(CultureInfo.InvariantCulture), "Remaining protected movement steps."), - new InspectorItemViewModel("Objects", $"R {m_Level.Reactors.Count} / L {m_Level.Leaks.Count} / D {doorCount}", "Reactors, active leaks, and doors.") + InventoryGrid.ItemsSource = new[] { + new InspectorItemViewModel("Fuel", $"{m_Level.Robot.FuelNeutralizers}"), + new InspectorItemViewModel("Coolant", $"{m_Level.Robot.CoolantNeutralizers}"), + new InspectorItemViewModel("Electricity", $"{m_Level.Robot.ElectricityNeutralizers}"), + new InspectorItemViewModel("Heat", $"{m_Level.Robot.HeatShields} ({m_Level.Robot.HeatImmunitySteps.ToString(CultureInfo.InvariantCulture)} steps)"), }; RequiredGrid.ItemsSource = new[] { - new InspectorItemViewModel("Fuel", m_Level.RequiredFuelConsumers.ToString(CultureInfo.InvariantCulture), "Producing consumers needed for readiness."), - new InspectorItemViewModel("Coolant", m_Level.RequiredCoolantConsumers.ToString(CultureInfo.InvariantCulture), "Producing consumers needed for readiness."), - new InspectorItemViewModel("Electric", m_Level.RequiredElectricityConsumers.ToString(CultureInfo.InvariantCulture), "Producing consumers needed for readiness.") + new InspectorItemViewModel("Fuel", m_Level.RequiredFuelConsumers.ToString(CultureInfo.InvariantCulture)), + new InspectorItemViewModel("Coolant", m_Level.RequiredCoolantConsumers.ToString(CultureInfo.InvariantCulture)), + new InspectorItemViewModel("Electric", m_Level.RequiredElectricityConsumers.ToString(CultureInfo.InvariantCulture)) }; if (m_SelectedCell is { } position && m_Level.InBounds(position)) { - SelectedCellTitleText.Text = SelectedCellTitle(position); - CellGrid.ItemsSource = CellInspectionItems(position); + SelectedCellText.Text = $"Selected cell: {position.X}, {position.Y}"; + TerrainText.Text = m_Level.GetTerrain(position).ToString(); + var prop = m_Level.GetProp(position); + PropText.Text = prop.Type != EPropType.None ? $"{prop.Type} {prop.SwitchState}" : "(none)"; + ServicesGrid.ItemsSource = new[] { + new InspectorItemViewModel("Fuel", prop.FuelServiceState.ToString()), + new InspectorItemViewModel("Coolant", prop.CoolantServiceState.ToString()), + new InspectorItemViewModel("Electricity", prop.ElectricityServiceState.ToString()), + }; + var surface = m_Level.GetSurface(position); + ConsumersGrid.ItemsSource = new[] { + new InspectorItemViewModel("Fuel", surface.FuelBlockTurns.ToString()), + new InspectorItemViewModel("Coolant", surface.CoolantBlockTurns.ToString()), + new InspectorItemViewModel("Electricity", surface.ElectricityBlockTurns.ToString()), + }; + LeaksGrid.ItemsSource = m_Level.Leaks.Select(leak => new InspectorItemViewModel(leak.Carrier.ToString(), $"{leak.UndergroundPosition.X}, {leak.UndergroundPosition.Y}")); SurfaceGrid.ItemsSource = SurfaceInspectionItems(position); NetworkGrid.ItemsSource = NetworkInspectionItems(position); } else { - SelectedCellTitleText.Text = "None"; - CellGrid.ItemsSource = new[] { new InspectorItemViewModel("Selection", "None", "Select a grid cell to inspect it.") }; - SurfaceGrid.ItemsSource = Array.Empty(); - NetworkGrid.ItemsSource = Array.Empty(); + SelectedCellText.Text = "Selected cell: (none)"; + TerrainText.Text = string.Empty; + PropText.Text = string.Empty; + ServicesGrid.ItemsSource = null; + ConsumersGrid.ItemsSource = null; + LeaksGrid.ItemsSource = null; + SurfaceGrid.ItemsSource = null; + NetworkGrid.ItemsSource = null; } ForecastList.ItemsSource = m_Level.Forecasts.Select(forecast => new ForecastViewModel($"{forecast.Turns}: {forecast.Message}")).ToArray(); @@ -849,7 +862,6 @@ public sealed partial class MainWindow break; default: m_Level = LevelEditor.Apply(m_Level, position, m_SelectedTool); - SelectReactorFromCell(position); RefreshForecasts(); break; } @@ -861,27 +873,14 @@ public sealed partial class MainWindow RefreshForecasts(); } - private InspectorItemViewModel[] CellInspectionItems(GridPosition position) - { - var prop = m_Level.GetProp(position); - var surface = m_Level.GetSurface(position); - return [ - new("Position", $"{position.X},{position.Y}", "Grid coordinate."), - new("Terrain", m_Level.GetTerrain(position).ToString(), "Static surface cell type."), - new("Prop", $"{prop.Type} {prop.SwitchState}", "Placed surface object and switch state."), - new("Services F/C/E", $"{prop.FuelServiceState}/{prop.CoolantServiceState}/{prop.ElectricityServiceState}", "Consumer service status."), - new("Blocks F/C/E", $"{surface.FuelBlockTurns}/{surface.CoolantBlockTurns}/{surface.ElectricityBlockTurns}", "Temporary remedy entry blocks.") - ]; - } - private InspectorItemViewModel[] SurfaceInspectionItems(GridPosition position) { var surface = m_Level.GetSurface(position); return [ - new("Fuel", Format(surface.Fuel), "Visible fuel hazard."), - new("Coolant", Format(surface.Coolant), "Visible coolant hazard."), - new("Electric", Format(surface.Electricity), "Visible electricity hazard."), - new("Heat", Format(surface.Heat), "Visible heat.") + new("Fuel", Format(surface.Fuel)), + new("Coolant", Format(surface.Coolant)), + new("Electric", Format(surface.Electricity)), + new("Heat", Format(surface.Heat)) ]; } @@ -1264,17 +1263,12 @@ public sealed partial class MainWindow return command.Carrier == activeCarrier && command.Tool is EEditorTool.Underground or EEditorTool.Flow or EEditorTool.Leak; } - private void SelectReactorFromCell(GridPosition position) - { - var prop = m_Level.GetProp(position); - if (prop is { Type: EPropType.ReactorControl, ReactorId: > 0 }) - m_SelectedReactorId = prop.ReactorId; - } - private void RefreshForecasts() { m_Level = m_Level with { Forecasts = m_Simulation.Forecast(m_Level) }; } + + public GridPosition? HoverCell { get; private set; } private const double c_MinZoom = 0.5; private const double c_MaxZoom = 4; @@ -1301,7 +1295,6 @@ public sealed partial class MainWindow private GridPosition? m_DragPreviewDestination; private string m_EditorFeedback = string.Empty; private CanvasBitmap? m_HeatSprite; - private GridPosition? m_HoverCell; private GridPosition? m_InvalidDragCell; private bool m_IsPanning; private GridPosition? m_LastPaintedCell; @@ -1313,7 +1306,6 @@ public sealed partial class MainWindow private double m_PanX; private double m_PanY; private GridPosition? m_SelectedCell; - private int? m_SelectedReactorId = 1; private EditorToolCommand m_SelectedTool = new() { Tool = EEditorTool.Cursor }; private CanvasBitmap? m_TerrainTilemap; private double m_Zoom = 1;