fish-station/Content.Client/UserInterface/Controls/MapGridControl.xaml.cs
Vigers Ray 95d7d4d348
ыыыыы, месенжер макс, ихихяхя (#3789)
Co-authored-by: Daniel <77834935+Orvex07@users.noreply.github.com>
2026-01-26 22:44:54 +03:00

244 lines
7.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Numerics;
using System.Text.RegularExpressions;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
using Robust.Client.ResourceManagement;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Input;
using Robust.Shared.Timing;
namespace Content.Client.UserInterface.Controls;
/// <summary>
/// Handles generic grid-drawing data, with zoom and dragging.
/// </summary>
[GenerateTypedNameReferences]
[Virtual]
public partial class MapGridControl : LayoutContainer
{
[Dependency] protected readonly IEntityManager EntManager = default!;
[Dependency] protected readonly IGameTiming Timing = default!;
protected static readonly Color BackingColor = new Color(0.08f, 0.08f, 0.08f);
private Font _largerFont;
/* Dragging */
protected virtual bool Draggable { get; } = false;
/// <summary>
/// Control offset from whatever is being tracked.
/// </summary>
public Vector2 Offset;
/// <summary>
/// If the control is being recentered what is the target offset to reach.
/// </summary>
public Vector2 TargetOffset;
private bool _draggin;
protected Vector2 StartDragPosition;
protected bool Recentering;
protected const float ScrollSensitivity = 8f;
protected float RecenterMinimum = 0.05f;
/// <summary>
/// UI pixel radius.
/// </summary>
public const int UIDisplayRadius = 320;
protected const int MinimapMargin = 4;
protected float WorldMinRange;
protected float WorldMaxRange;
public float WorldRange;
public Vector2 WorldRangeVector => new Vector2(WorldRange, WorldRange);
/// <summary>
/// We'll lerp between the radarrange and actual range
/// </summary>
protected float ActualRadarRange;
protected float CornerRadarRange => MathF.Sqrt(ActualRadarRange * ActualRadarRange + ActualRadarRange * ActualRadarRange) * 1.1f;
/// <summary>
/// Controls the maximum distance that will display.
/// </summary>
public float MaxRadarRange { get; private set; } = 256f * 10f;
public Vector2 MaxRadarRangeVector => new Vector2(MaxRadarRange, MaxRadarRange);
protected Vector2 MidPointVector => new Vector2(MidPoint, MidPoint);
protected int MidPoint => SizeFull / 2;
protected int SizeFull => (int) ((UIDisplayRadius + MinimapMargin) * 2 * UIScale);
protected int ScaledMinimapRadius => (int) (UIDisplayRadius * UIScale);
protected float MinimapScale => WorldRange != 0 ? ScaledMinimapRadius / WorldRange : 0f;
public event Action<float>? WorldRangeChanged;
public MapGridControl() : this(32f, 32f, 32f) {}
public MapGridControl(float minRange, float maxRange, float range)
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
MinSize = new Vector2(MathF.Round(SizeFull / 2f), SizeFull - 68); // Sunrise-Edit: Я не ебу как это сделать без хардкода
RectClipContent = true;
MouseFilter = MouseFilterMode.Stop;
ActualRadarRange = WorldRange;
WorldMinRange = minRange;
WorldMaxRange = maxRange;
WorldRange = range;
ActualRadarRange = range;
var cache = IoCManager.Resolve<IResourceCache>();
_largerFont = new VectorFont(cache.GetResource<FontResource>("/EngineFonts/NotoSans/NotoSans-Regular.ttf"), 16);
}
public void ForceRecenter()
{
Recentering = true;
}
protected override void KeyBindDown(GUIBoundKeyEventArgs args)
{
base.KeyBindDown(args);
if (!Draggable)
return;
if (args.Function == EngineKeyFunctions.Use)
{
StartDragPosition = args.PointerLocation.Position;
_draggin = true;
}
}
protected override void KeyBindUp(GUIBoundKeyEventArgs args)
{
if (!Draggable)
return;
if (args.Function == EngineKeyFunctions.Use)
_draggin = false;
}
protected override void MouseMove(GUIMouseMoveEventArgs args)
{
base.MouseMove(args);
if (!_draggin)
return;
Recentering = false;
Offset -= new Vector2(args.Relative.X, -args.Relative.Y) / MidPoint * WorldRange;
}
protected override void MouseWheel(GUIMouseWheelEventArgs args)
{
base.MouseWheel(args);
AddRadarRange(-args.Delta.Y * 1f / ScrollSensitivity * ActualRadarRange);
}
public void AddRadarRange(float value)
{
ActualRadarRange = Math.Clamp(ActualRadarRange + value, WorldMinRange, WorldMaxRange);
}
/// <summary>
/// Converts map coordinates to the local control.
/// </summary>
protected Vector2 ScalePosition(Vector2 value)
{
return ScalePosition(value, MinimapScale, MidPointVector);
}
protected static Vector2 ScalePosition(Vector2 value, float minimapScale, Vector2 midpointVector)
{
return value * minimapScale + midpointVector;
}
/// <summary>
/// Converts local coordinates on the control to map coordinates.
/// </summary>
protected Vector2 InverseMapPosition(Vector2 value)
{
var inversePos = (value - MidPointVector) / MinimapScale;
inversePos = inversePos with { Y = -inversePos.Y };
inversePos = Vector2.Transform(inversePos, Matrix3Helpers.CreateTransform(Offset, Angle.Zero));
return inversePos;
}
/// <summary>
/// Handles re-centering the control's offset.
/// </summary>
/// <returns></returns>
public bool DrawRecenter()
{
// Map re-centering
if (Recentering)
{
var frameTime = Timing.FrameTime;
var diff = (TargetOffset - Offset) * (float) frameTime.TotalSeconds;
if (Offset.LengthSquared() < RecenterMinimum)
{
Offset = TargetOffset;
Recentering = false;
}
else
{
Offset += diff * 5f;
return false;
}
}
return Offset == TargetOffset;
}
protected void DrawBacking(DrawingHandleScreen handle)
{
var backing = BackingColor;
handle.DrawRect(PixelSizeBox, backing);
}
protected void DrawNoSignal(DrawingHandleScreen handle)
{
var greyColor = Color.FromHex("#474F52");
// Draw funny lines
var lineCount = 4f;
for (var i = 0; i < lineCount; i++)
{
var angle = Angle.FromDegrees(45 + i * 360f / lineCount);
var distance = Width / 2f;
var start = MidPointVector + angle.RotateVec(new Vector2(0f, 2.5f * distance / 4f));
var end = MidPointVector + angle.RotateVec(new Vector2(0f, 4f * distance / 4f));
handle.DrawLine(start, end, greyColor);
}
var signalText = Loc.GetString("shuttle-console-no-signal");
var dimensions = handle.GetDimensions(_largerFont, signalText, 1f);
var position = MidPointVector - dimensions / 2f;
handle.DrawString(_largerFont, position, Loc.GetString("shuttle-console-no-signal"), greyColor);
}
protected override void Draw(DrawingHandleScreen handle)
{
base.Draw(handle);
if (!ActualRadarRange.Equals(WorldRange))
{
var diff = ActualRadarRange - WorldRange;
const float lerpRate = 10f;
WorldRange += (float) Math.Clamp(diff, -lerpRate * MathF.Abs(diff) * Timing.FrameTime.TotalSeconds, lerpRate * MathF.Abs(diff) * Timing.FrameTime.TotalSeconds);
WorldRangeChanged?.Invoke(WorldRange);
}
}
}