Code/RoadComponent/RoadComponent.Crosswalks.cs
using System.Linq;
using Sandbox;
namespace RedSnail.RoadTool;
public enum CrosswalkConfig
{
Start,
End,
Both
}
public partial class RoadComponent
{
private bool m_DoesCrosswalksNeedsRebuild = false;
[Property, FeatureEnabled("Crosswalks", Icon = "menu", Tint = EditorTint.Pink), Change] private bool HasCrosswalks { get; set; } = false;
[Property(Title = "Config"), Feature("Crosswalks")] public CrosswalkConfig CrosswalkConfig { get; set { field = value; m_DoesCrosswalksNeedsRebuild = true; } } = CrosswalkConfig.Both;
[Property(Title = "Decal Definition"), Feature("Crosswalks")] public DecalDefinition CrosswalkDefinition { get; set { field = value; m_DoesCrosswalksNeedsRebuild = true; } }
[Property(Title = "Decal Size"), Feature("Crosswalks"), Range(0.1f, 10.0f)] private Vector2 CrosswalkSize { get; set { field = value; m_DoesCrosswalksNeedsRebuild = true; } } = Vector2.One;
private void OnHasCrosswalksChanged(bool _OldValue, bool _NewValue)
{
m_DoesCrosswalksNeedsRebuild = true;
}
private void CreateCrosswalks()
{
RemoveCrosswalks();
if (!HasCrosswalks || !CrosswalkDefinition.IsValid())
return;
BuildCrosswalks();
}
private void RemoveCrosswalks()
{
GameObject containerObject = GameObject.Children.FirstOrDefault(x => x.Name == "Crosswalks");
if (containerObject.IsValid())
{
containerObject.Destroy();
}
}
private void UpdateCrosswalks()
{
if (m_DoesCrosswalksNeedsRebuild)
{
CreateCrosswalks();
m_DoesCrosswalksNeedsRebuild = false;
}
}
private void BuildCrosswalks()
{
GameObject containerObject = new GameObject(GameObject, true, "Crosswalks");
containerObject.Flags |= GameObjectFlags.NotSaved;
GetSplineFrameData(out var frames, out _, DecalSpacing);
if (CrosswalkConfig is CrosswalkConfig.Start or CrosswalkConfig.Both)
{
Transform roadStart = frames.FirstOrDefault();
Vector3 position = roadStart.Position;
Rotation rotation = Rotation.LookAt(-roadStart.Rotation.Up, roadStart.Rotation.Forward);
CreateCrosswalk(containerObject, position, rotation);
}
if (CrosswalkConfig is CrosswalkConfig.End or CrosswalkConfig.Both)
{
Transform roadEnd = frames.LastOrDefault();
Vector3 position = roadEnd.Position;
Rotation rotation = Rotation.LookAt(-roadEnd.Rotation.Up, roadEnd.Rotation.Forward);
CreateCrosswalk(containerObject, position, rotation);
}
}
private void CreateCrosswalk(GameObject _GameObject, Vector3 _Position, Rotation _Rotation)
{
GameObject gameObject = new GameObject(_GameObject, true, "Crosswalk Decal")
{
LocalPosition = _Position,
LocalRotation = _Rotation
};
gameObject.Flags |= GameObjectFlags.NotSaved;
Decal decal = gameObject.AddComponent<Decal>();
decal.Decals = [CrosswalkDefinition];
decal.Rotation = new ParticleFloat(0.0f, 0.0f);
decal.Size = CrosswalkSize;
decal.Depth = 4.0f;
decal.AttenuationAngle = 1.0f;
}
}