using UnityEngine;
// Shapes © Freya Holmér - https://twitter.com/FreyaHolmer/
// Website & Documentation - https://acegikmo.com/shapes/
namespace Shapes {
/// A Line segment shape component
[ExecuteAlways]
[AddComponentMenu( "Shapes/Line" )]
public partial class Line : ShapeRenderer, IDashable {
/// The color modes for line shapes
public enum LineColorMode {
/// A single color across the whole line
Single,
/// Separate start and end colors
Double
}
/// Get or set the start/end point by index (0 = start, 1 = end)
public Vector3 this[ int i ] {
get => i > 0 ? End : Start;
set => _ = i > 0 ? End = value : Start = value;
}
// also called alignment for 2D lines
[SerializeField] LineGeometry geometry = LineGeometry.Billboard;
/// Get or set the type of geometry used (flat, billboarded, volumetric)
public LineGeometry Geometry {
get => geometry;
set {
geometry = value;
SetIntNow( ShapesMaterialUtils.propAlignment, (int)geometry );
UpdateMesh( true );
UpdateMaterial();
ApplyProperties();
}
}
[SerializeField] LineColorMode colorMode = LineColorMode.Single;
/// Whether or not to use one a single color or two colors, one at each end of the line
public LineColorMode ColorMode {
get => colorMode;
set => SetColorNow( ShapesMaterialUtils.propColorEnd, ( colorMode = value ) == LineColorMode.Double ? colorEnd : base.Color );
}
/// The color of this shape. The alpha channel is used for opacity/intensity in all blend modes
public override Color Color {
get => color;
set {
SetColor( ShapesMaterialUtils.propColor, color = value );
SetColorNow( ShapesMaterialUtils.propColorEnd, colorEnd = value );
}
}
/// The color to use at the start of the line (when ColorMode is set to Double)
public Color ColorStart {
get => color;
set => SetColorNow( ShapesMaterialUtils.propColor, color = value );
}
[SerializeField] [ShapesColorField( true )] Color colorEnd = Color.white;
/// The color to use at the end of the line (when ColorMode is set to Double)
public Color ColorEnd {
get => colorEnd;
set => SetColorNow( ShapesMaterialUtils.propColorEnd, colorEnd = value );
}
[SerializeField] Vector3 start = Vector3.zero;
/// The start point of this line in local space
public Vector3 Start {
get => start;
set => SetVector3Now( ShapesMaterialUtils.propPointStart, start = value );
}
[SerializeField] Vector3 end = Vector3.right;
/// The endpoint of this line in local space
public Vector3 End {
get => end;
set => SetVector3Now( ShapesMaterialUtils.propPointEnd, end = value );
}
[SerializeField] float thickness = 0.125f;
/// The thickness of this line in the given ThicknessSpace
public float Thickness {
get => thickness;
set {
SetFloatNow( ShapesMaterialUtils.propThickness, thickness = value );
if( dashed && dashStyle.space == DashSpace.Relative )
SetAllDashValues( now: true );
}
}
[SerializeField] ThicknessSpace thicknessSpace = Shapes.ThicknessSpace.Meters;
/// The space in which Thickness is defined
public ThicknessSpace ThicknessSpace {
get => thicknessSpace;
set => SetIntNow( ShapesMaterialUtils.propThicknessSpace, (int)( thicknessSpace = value ) );
}
[SerializeField] LineEndCap endCaps = LineEndCap.Round;
/// What end caps to use
public LineEndCap EndCaps {
get => endCaps;
set {
endCaps = value;
UpdateMaterial();
}
}
private protected override void SetAllMaterialProperties() {
SetVector3( ShapesMaterialUtils.propPointStart, start );
SetVector3( ShapesMaterialUtils.propPointEnd, end );
SetFloat( ShapesMaterialUtils.propThickness, thickness );
SetInt( ShapesMaterialUtils.propThicknessSpace, (int)thicknessSpace );
SetInt( ShapesMaterialUtils.propAlignment, (int)geometry );
SetColor( ShapesMaterialUtils.propColorEnd, colorMode == LineColorMode.Double ? colorEnd : base.Color );
SetAllDashValues( now: false );
}
private protected override Bounds GetBounds_Internal() {
// presume 0 world space padding when pixels or noots are used
float padding = thicknessSpace == ThicknessSpace.Meters ? thickness : 0f;
Vector3 center = ( start + end ) / 2f;
Vector3 size = ShapesMath.Abs( start - end ) + new Vector3( padding, padding, padding );
return new Bounds( center, size );
}
private protected override Material[] GetMaterials() => new[] { ShapesMaterialUtils.GetLineMat( geometry, endCaps )[BlendMode] };
private protected override Mesh GetInitialMeshAsset() => ShapesMeshUtils.GetLineMesh( geometry, endCaps, detailLevel );
internal override bool HasDetailLevels => true;
private protected override void ShapeClampRanges() {
thickness = Mathf.Max( 0, thickness );
DashSpacing = DashSpace == DashSpace.FixedCount ? Mathf.Clamp01( DashSpacing ) : Mathf.Max( 0f, DashSpacing );
}
}
}