Fix editor drag feedback and surface overlays
This commit is contained in:
@@ -266,7 +266,7 @@ public sealed partial class MainWindow
|
||||
m_EditorFeedback = string.Empty;
|
||||
m_LastPaintedCell = null;
|
||||
if (!m_IsPanning && m_SelectedTool.Tool == EEditorTool.Cursor && TryGetGridPosition(point.Position, out var position))
|
||||
StartCursorDrag(position);
|
||||
m_CursorDragStartCell = position;
|
||||
else if (!m_IsPanning && IsDragPaintTool(m_SelectedTool.Tool) && TryGetGridPosition(point.Position, out position))
|
||||
{
|
||||
m_LastPaintedCell = position;
|
||||
@@ -306,7 +306,7 @@ public sealed partial class MainWindow
|
||||
}
|
||||
else if (m_CursorDragStartCell is not null && m_DragExceededClickThreshold && TryGetGridPosition(point.Position, out var destination))
|
||||
{
|
||||
m_DragPreviewDestination = destination;
|
||||
UpdateCursorDragPreview(destination);
|
||||
LevelCanvas.Invalidate();
|
||||
}
|
||||
|
||||
@@ -322,7 +322,7 @@ public sealed partial class MainWindow
|
||||
{
|
||||
LevelCanvas.Invalidate();
|
||||
}
|
||||
else if (m_CursorDragStartCell is { } source && m_DragExceededClickThreshold && TryGetGridPosition(point.Position, out var destination))
|
||||
else if (m_CursorDragStartCell is { } source && m_DragExceededClickThreshold && !m_CursorDragStartRejected && TryGetGridPosition(point.Position, out var destination))
|
||||
{
|
||||
var result = LevelEditor.TryMoveOccupant(m_Level, source, destination);
|
||||
m_Level = result.Level;
|
||||
@@ -343,6 +343,7 @@ public sealed partial class MainWindow
|
||||
}
|
||||
}
|
||||
|
||||
var clearRejectedDragFeedback = m_CursorDragStartRejected;
|
||||
m_LeftPointerDown = false;
|
||||
m_IsPanning = false;
|
||||
m_CursorDragStartCell = null;
|
||||
@@ -350,6 +351,13 @@ public sealed partial class MainWindow
|
||||
m_DragPreviewDestination = null;
|
||||
m_LastPaintedCell = null;
|
||||
m_DragExceededClickThreshold = false;
|
||||
if (clearRejectedDragFeedback)
|
||||
{
|
||||
ClearDragFeedback();
|
||||
RefreshInspector();
|
||||
LevelCanvas.Invalidate();
|
||||
}
|
||||
|
||||
LevelCanvas.ReleasePointerCapture(e.Pointer);
|
||||
e.Handled = true;
|
||||
}
|
||||
@@ -363,6 +371,9 @@ public sealed partial class MainWindow
|
||||
m_DragPreviewDestination = null;
|
||||
m_LastPaintedCell = null;
|
||||
m_DragExceededClickThreshold = false;
|
||||
ClearDragFeedback();
|
||||
RefreshInspector();
|
||||
LevelCanvas.Invalidate();
|
||||
}
|
||||
|
||||
private void LevelCanvas_PointerWheelChanged(object sender, PointerRoutedEventArgs e)
|
||||
@@ -415,22 +426,34 @@ public sealed partial class MainWindow
|
||||
return tool is EEditorTool.Floor or EEditorTool.Wall or EEditorTool.Underground;
|
||||
}
|
||||
|
||||
private void StartCursorDrag(GridPosition position)
|
||||
private void UpdateCursorDragPreview(GridPosition destination)
|
||||
{
|
||||
m_SelectedCell = position;
|
||||
if (HasMovableAt(position))
|
||||
if (m_CursorDragStartCell is not { } source)
|
||||
return;
|
||||
|
||||
if (m_CursorDragStartRejected)
|
||||
return;
|
||||
|
||||
if (!HasMovableAt(source))
|
||||
{
|
||||
m_CursorDragStartCell = position;
|
||||
m_CursorDragStartRejected = true;
|
||||
m_DragPreviewDestination = null;
|
||||
m_InvalidDragCell = source;
|
||||
m_EditorFeedback = "No movable robot, prop, source, or leak starts here.";
|
||||
RefreshInspector();
|
||||
LevelCanvas.Invalidate();
|
||||
return;
|
||||
}
|
||||
|
||||
m_CursorDragStartRejected = true;
|
||||
m_InvalidDragCell = position;
|
||||
m_EditorFeedback = "No movable robot, prop, source, or leak starts here.";
|
||||
m_DragPreviewDestination = destination;
|
||||
m_InvalidDragCell = null;
|
||||
m_EditorFeedback = string.Empty;
|
||||
RefreshInspector();
|
||||
LevelCanvas.Invalidate();
|
||||
}
|
||||
|
||||
private void ClearDragFeedback()
|
||||
{
|
||||
m_InvalidDragCell = null;
|
||||
m_EditorFeedback = string.Empty;
|
||||
}
|
||||
|
||||
private void ClearAt(Point point)
|
||||
@@ -613,23 +636,39 @@ public sealed partial class MainWindow
|
||||
{
|
||||
var surface = m_Level.GetSurface(position);
|
||||
var rect = layout.CellRect(position);
|
||||
FillHazard(drawing, rect, surface.Fuel, c_FuelColor, 0.08, opacity);
|
||||
FillHazard(drawing, rect, surface.Coolant, c_CoolantColor, 0.18, opacity);
|
||||
FillHazard(drawing, rect, surface.Electricity, c_ElectricityColor, 0.28, opacity);
|
||||
if (surface.Heat > 0)
|
||||
DrawImage(drawing, m_HeatSprite, Inset(rect, 0.18), Math.Clamp(surface.Heat / Balancing.Current.MaxValue, 0.25f, 0.9f) * opacity);
|
||||
FillHazard(drawing, rect, surface.Fuel, c_FuelColor, 0.08, opacity, Balancing.Current.FuelCaution, Balancing.Current.FuelCritical);
|
||||
FillHazard(drawing, rect, surface.Coolant, c_CoolantColor, 0.18, opacity, Balancing.Current.CoolantCaution, Balancing.Current.CoolantCritical);
|
||||
FillHazard(drawing, rect, surface.Electricity, c_ElectricityColor, 0.28, opacity, Balancing.Current.ElectricityCaution, Balancing.Current.ElectricityCritical);
|
||||
|
||||
var heatOpacity = SurfaceOverlayOpacity(surface.Heat, Balancing.Current.HeatCaution, Balancing.Current.HeatCritical);
|
||||
if (heatOpacity > 0)
|
||||
DrawImage(drawing, m_HeatSprite, Inset(rect, 0.18), heatOpacity * opacity);
|
||||
}
|
||||
}
|
||||
|
||||
private static void FillHazard(CanvasDrawingSession drawing, Rect rect, float amount, Color color, double inset, float opacity)
|
||||
private static void FillHazard(CanvasDrawingSession drawing, Rect rect, float amount, Color color, double inset, float opacity, float caution, float critical)
|
||||
{
|
||||
if (amount <= 0)
|
||||
var overlayOpacity = SurfaceOverlayOpacity(amount, caution, critical);
|
||||
if (overlayOpacity <= 0)
|
||||
return;
|
||||
|
||||
var alpha = (byte)Math.Clamp((40 + (amount / Balancing.Current.MaxValue * 130)) * opacity, 0, 170);
|
||||
var alpha = (byte)Math.Clamp(170 * overlayOpacity * opacity, 0, 170);
|
||||
drawing.FillRectangle(Inset(rect, inset), ColorHelper.FromArgb(alpha, color.R, color.G, color.B));
|
||||
}
|
||||
|
||||
private static float SurfaceOverlayOpacity(float amount, float caution, float critical)
|
||||
{
|
||||
if (amount < caution)
|
||||
return 0;
|
||||
|
||||
if (amount >= critical)
|
||||
return 0.9f;
|
||||
|
||||
var cautionRange = Math.Max(0.001f, critical - caution);
|
||||
var t = (amount - caution) / cautionRange;
|
||||
return 0.3f + (t * 0.35f);
|
||||
}
|
||||
|
||||
private void DrawDoors(CanvasDrawingSession drawing, CanvasLayout layout, float opacity)
|
||||
{
|
||||
foreach (var position in AllPositions())
|
||||
@@ -805,7 +844,7 @@ public sealed partial class MainWindow
|
||||
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)"),
|
||||
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)),
|
||||
@@ -822,13 +861,13 @@ public sealed partial class MainWindow
|
||||
ServicesGrid.ItemsSource = new[] {
|
||||
new InspectorItemViewModel("Fuel", prop.FuelServiceState.ToString()),
|
||||
new InspectorItemViewModel("Coolant", prop.CoolantServiceState.ToString()),
|
||||
new InspectorItemViewModel("Electricity", prop.ElectricityServiceState.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()),
|
||||
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);
|
||||
@@ -1267,7 +1306,7 @@ public sealed partial class MainWindow
|
||||
{
|
||||
m_Level = m_Level with { Forecasts = m_Simulation.Forecast(m_Level) };
|
||||
}
|
||||
|
||||
|
||||
public GridPosition? HoverCell { get; private set; }
|
||||
|
||||
private const double c_MinZoom = 0.5;
|
||||
|
||||
Reference in New Issue
Block a user