namespace NodeWar.scripts; using Godot; [Tool] [GlobalClass] public partial class LinePath2D : Path2D { private const bool ShouldCreateDefaultCurve = true; private const bool ShouldCreateDefaultProfile = true; // Size in pixels of the default curve private const int DefaultCurveSize = 400; // Size in pixels of the default curve width private const float DefaultCurveWidth = 25.0f; private Line2D _line = new(); [ExportCategory("LinePath2D")] [Export] public Curve2D LinePathCurve { get => Curve; set { if (Curve != null) Curve.Changed -= BuildLine; Curve = value; if (Curve != null) Curve.Changed += BuildLine; BuildLine(); } } /// /// Sets the width of the curve. /// [Export] public float Width { get => _line?.Width ?? DefaultCurveWidth; set { if (_line == null) return; _line.Width = value; } } /// /// Use this Curve to modify the line width profile. /// [Export] public Curve WidthProfile { get => _line?.WidthCurve; set { if (_line == null) return; _line.WidthCurve = value; } } [ExportGroup("Fill", "Fill")] [Export] public Color FillDefaultColor { get => _line?.DefaultColor ?? Colors.White; set { if (_line != null) _line.DefaultColor = value; } } /// /// Fill the path with a gradient. /// [Export] public Gradient FillGradient { get => _line?.Gradient; set { if (_line != null) _line.Gradient = value; } } /// /// Fill the path with a texture. /// [Export] public Texture2D FillTexture { get => _line?.Texture; set { if (_line != null) _line.Texture = value; } } /// /// Change the texture fill mode. /// [Export] public Line2D.LineTextureMode FillTextureMode { get => _line?.TextureMode ?? Line2D.LineTextureMode.None; set { if (_line != null) _line.TextureMode = value; } } [ExportGroup("Capping", "Cap")] [Export] public Line2D.LineJointMode CapJointMode { get => _line?.JointMode ?? Line2D.LineJointMode.Sharp; set { if (_line != null) _line.JointMode = value; } } /// /// The style of the beginning of the polyline. /// [Export] public Line2D.LineCapMode CapBeginCap { get => _line?.BeginCapMode ?? Line2D.LineCapMode.None; set { if (_line != null) _line.BeginCapMode = value; } } /// /// The style of the ending of the polyline. /// [Export] public Line2D.LineCapMode CapEndCap { get => _line?.EndCapMode ?? Line2D.LineCapMode.None; set { if (_line != null) _line.EndCapMode = value; } } /// /// If true and the polyline has more than two segments, /// the first and the last point will be connected by a segment. /// [Export] public bool CapCloseCurve { get => _line?.Closed ?? false; set { if (_line != null) _line.Closed = value; } } [ExportGroup("Border", "Border")] [Export] public float BorderSharpLimit { get => _line?.SharpLimit ?? 2.0f; set { if (_line != null) _line.SharpLimit = value; } } /// /// The smoothness of the rounded joints and caps. /// [Export] public int BorderRoundPrecision { get => _line?.RoundPrecision ?? 8; set { if (_line != null) _line.RoundPrecision = value; } } /// /// If true the polyline border will be antialiased. /// Note: Antialiased polylines are not accelerated by batching. /// [Export] public bool BorderAntialiased { get => _line?.Antialiased ?? false; set { if (_line != null) _line.Antialiased = value; } } public override void _Ready() { ClearDuplicatedInternalChildren(); _line.SetMeta("__lp2d_internal__", true); AddChild(_line); if (Curve == null || Curve.PointCount < 2) Curve = CreateDefaultCurve(DefaultCurveSize); _line.WidthCurve ??= CreateDefaultProfile(DefaultCurveWidth); BuildLine(); if (Curve != null) { Curve.Changed -= BuildLine; Curve.Changed += BuildLine; } } public override void _ExitTree() { if (Curve != null) Curve.Changed -= BuildLine; } private Curve2D CreateDefaultCurve(int size) { if (!ShouldCreateDefaultCurve) return null; var curve = new Curve2D(); curve.AddPoint(Vector2.Zero, Vector2.Zero, new Vector2(size, 0)); curve.AddPoint(new Vector2(size, size), new Vector2(-size, 0), Vector2.Zero); return curve; } private static Curve CreateDefaultProfile(float size) { if (!ShouldCreateDefaultProfile) return null; var curve = new Curve(); curve.AddPoint(Vector2.Zero); curve.AddPoint(new Vector2(0.5f, 1.0f)); curve.AddPoint(new Vector2(1.0f, 0.0f)); return curve; } private void BuildLine() { if (_line == null) return; if (Curve == null || Curve.PointCount < 2) { _line.ClearPoints(); return; } _line.Points = Curve.GetBakedPoints(); } private void ClearDuplicatedInternalChildren() { foreach (var child in GetChildren()) { if (child.GetMeta("__lp2d_internal__", false).AsBool()) child.QueueFree(); } } }