🔍 s&box Package Code Search

Search C# source code, UI razor templates, shaders, and configs across s&box packages.

Showing code results for query: * (1 total matches found)
facepunch.motionpath / Code/MotionPath.cs
Game library
using Sandbox;
using System;
using System.Linq;

/// <summary>
/// Move an object around a path.
/// </summary>
[Title( "Motion Path" )]
public class MotionPath : Component, Component.ExecuteInEditor
{
	/// <summary>
	/// The object that moves around this path.
	/// </summary>
	[Property]
	public GameObject Target { get; set; }

	/// <summary>
	/// Normalized time between 0 and 1 for how far the target is on this path.
	/// </summary>
	[Property, Range( 0.0f, 1.0f )]
	public float Time { get; set; }

	/// <summary>
	/// Rotate the target using the rotation of points, otherwise use the curvature of the path.
	/// </summary>
	[Property]
	public bool UsePointRotation { get; set; }

	/// <summary>
	/// Time is controlled manually.
	/// </summary>
	[Property]
	public bool Manual { get; set; }

	/// <summary>
	/// How long the path takes to complete.
	/// </summary>
	[Property, ShowIf( nameof( Manual ), false )]
	public float Duration { get; set; } = 10;

	public enum SplineType
	{
		Tcb,
		CatmullRom
	};

	[Title( "Mode" ), Group( "Spline" )]
	[Property] public SplineType SplineMode { get; set; }

	[Title( "Tension" ), Group( "Spline" ), ShowIf( nameof( SplineMode ), SplineType.Tcb )]
	[Property, Range( -1, 1 )] public float SplineTension { get; set; }

	[Title( "Continuity" ), Group( "Spline" ), ShowIf( nameof( SplineMode ), SplineType.Tcb )]
	[Property, Range( -1, 1 )] public float SplineContinuity { get; set; }

	[Title( "Bias" ), Group( "Spline" ), ShowIf( nameof( SplineMode ), SplineType.Tcb )]
	[Property, Range( -1, 1 )] public float SplineBias { get; set; }

	private Vector3[] _previewPoints;

	protected override void OnStart()
	{
		base.OnStart();

		if ( Scene.IsEditor )
		{
			if ( !GameObject.GetAllObjects( true )
				.Select( x => x.Components.Get<MotionPathPoint>() )
				.Where( x => x.IsValid() )
				.Any() )
			{
				var go = new GameObject( true, "Point" );
				go.SetParent( GameObject, false );
				go.Components.Create<MotionPathPoint>( true );
			}
		}
	}

	protected override void DrawGizmos()
	{
		base.DrawGizmos();

		if ( _previewPoints is null )
			return;

		using ( Gizmo.Hitbox.LineScope() )
		{
			for ( var i = 0; i < _previewPoints.Length - 1; i++ )
			{
				var pointA = Transform.World.PointToLocal( _previewPoints[i] );
				var pointB = Transform.World.PointToLocal( _previewPoints[i + 1] );
				Gizmo.Draw.Color = Gizmo.IsSelected ? Gizmo.Colors.Active : Gizmo.IsHovered ? Gizmo.Colors.Hovered : Color.White.WithAlpha( 0.5f );
				Gizmo.Draw.LineThickness = Gizmo.IsHovered || Gizmo.IsSelected ? 2 : 1;
				Gizmo.Draw.Line( pointA, pointB );
			}
		}

		if ( Target.IsValid() )
		{
			Gizmo.Draw.Color = Gizmo.Colors.Forward;
			var pointA = Transform.World.PointToLocal( Target.Transform.Position );
			var pointB = Transform.World.NormalToLocal( Target.Transform.Rotation.Forward ) * 5;
			Gizmo.Draw.SolidCone( pointA, pointB, 2 );
		}
	}

	private Vector3 GetPointOnSpline( Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float delta )
	{
		if ( SplineMode == SplineType.Tcb )
			return Vector3.TcbSpline( p0, p1, p2, p3, SplineTension, SplineContinuity, SplineBias, delta );
		else if ( SplineMode == SplineType.CatmullRom )
			return Vector3.CatmullRomSpline( p0, p1, p2, p3, delta );

		return default;
	}

	protected override void OnUpdate()
	{
		base.OnUpdate();

		var motionPoints = GameObject.GetAllObjects( true )
			.Select( x => x.Components.Get<MotionPathPoint>() )
			.Where( x => x.IsValid() )
			.ToArray();

		var points = motionPoints.Select( x => x.Transform.Position )
			.ToArray();

		if ( SplineMode == SplineType.Tcb )
			_previewPoints = points.TcbSpline( 32, SplineTension, SplineContinuity, SplineBias ).ToArray();
		else if ( SplineMode == SplineType.CatmullRom )
			_previewPoints = points.CatmullRomSpline( 32 ).ToArray();

		if ( points.Length < 2 )
			return;

		if ( points.Length == 2 )
			_previewPoints = new Vector3[2] { points[0], points[1] };

		if ( Target.IsValid() )
		{
			var pointCount = points.Length;

			if ( !Manual && !Duration.AlmostEqual( 0.0f ) )
				Time = Sandbox.Time.Now % Duration / Duration;

			var time = Time.Clamp( 0.0f, 1.0f );

			var segmentIndex = (int)((pointCount - 1) * time);
			segmentIndex = Math.Min( segmentIndex, pointCount - 2 );
			var delta = ((pointCount - 1) * time) - segmentIndex;

			var p0 = segmentIndex > 0 ? points[segmentIndex - 1] : points[0];
			var p1 = points[segmentIndex];
			var p2 = segmentIndex < pointCount - 1 ? points[segmentIndex + 1] : points[pointCount - 1];
			var p3 = segmentIndex < pointCount - 2 ? points[segmentIndex + 2] : points[pointCount - 1];

			var offset = time.AlmostEqual( 1.0f ) ? -0.01f : 0.01f;
			var positionA = GetPointOnSpline( p0, p1, p2, p3, delta );

			if ( UsePointRotation )
			{
				var r1 = motionPoints[segmentIndex];
				var r2 = segmentIndex < pointCount - 1 ? motionPoints[segmentIndex + 1] : motionPoints[pointCount - 1];
				var rotationStart = r1.Transform.Rotation;
				var rotationEnd = r2.Transform.Rotation;

				if ( r1.LookAt.IsValid() )
					rotationStart = Rotation.LookAt( (r1.LookAt.Transform.Position - r1.Transform.Position).Normal );

				if ( r2.LookAt.IsValid() )
					rotationEnd = Rotation.LookAt( (r2.LookAt.Transform.Position - r2.Transform.Position).Normal );

				Target.Transform.Rotation = Rotation.Slerp( rotationStart, rotationEnd, delta );
			}
			else
			{
				var positionB = GetPointOnSpline( p0, p1, p2, p3, delta + offset );
				var forward = (positionB - positionA).Normal * MathF.Sign( offset );
				var right = forward.Cross( Vector3.Up ).Normal;
				var up = right.Cross( forward ).Normal;

				Target.Transform.Rotation = Rotation.LookAt( forward, up );
			}

			Target.Transform.Position = positionA;
		}
	}
}

public class MotionPathPoint : Component, Component.ExecuteInEditor
{
	/// <summary>
	/// Look at this object.
	/// </summary>
	[Property]
	public GameObject LookAt { get; set; }

	protected override void DrawGizmos()
	{
		base.DrawGizmos();

		const float radius = 2.0f;
		Gizmo.Hitbox.DepthBias = 0.1f;
		Gizmo.Hitbox.Sphere( new Sphere( 0, radius ) );
		Gizmo.Draw.Color = Gizmo.IsSelected ? Gizmo.Colors.Active : Gizmo.IsHovered ? Gizmo.Colors.Hovered : Color.White;
		Gizmo.Draw.SolidSphere( 0, radius );

		if ( Gizmo.IsSelected || Gizmo.IsHovered )
		{
			var end = LookAt.IsValid() ? Transform.World.PointToLocal( LookAt.Transform.Position ) : Vector3.Forward * 6;
			Gizmo.Draw.Color = Gizmo.Colors.Forward;
			Gizmo.Draw.Arrow( 0, end, 2, 1 );
		}
	}
}
Debug: View Raw JSON Response
{
    "TotalCount": 1,
    "Files": [
        {
            "Ident": "facepunch.motionpath",
            "Path": "Code/MotionPath.cs",
            "FileName": "MotionPath.cs",
            "PackageType": "library",
            "CodeKind": "Game",
            "AssetVersionId": 56584,
            "Code": "using Sandbox;\r\nusing System;\r\nusing System.Linq;\r\n\r\n/// <summary>\r\n/// Move an object around a path.\r\n/// </summary>\r\n[Title( \"Motion Path\" )]\r\npublic class MotionPath : Component, Component.ExecuteInEditor\r\n{\r\n\t/// <summary>\r\n\t/// The object that moves around this path.\r\n\t/// </summary>\r\n\t[Property]\r\n\tpublic GameObject Target { get; set; }\r\n\r\n\t/// <summary>\r\n\t/// Normalized time between 0 and 1 for how far the target is on this path.\r\n\t/// </summary>\r\n\t[Property, Range( 0.0f, 1.0f )]\r\n\tpublic float Time { get; set; }\r\n\r\n\t/// <summary>\r\n\t/// Rotate the target using the rotation of points, otherwise use the curvature of the path.\r\n\t/// </summary>\r\n\t[Property]\r\n\tpublic bool UsePointRotation { get; set; }\r\n\r\n\t/// <summary>\r\n\t/// Time is controlled manually.\r\n\t/// </summary>\r\n\t[Property]\r\n\tpublic bool Manual { get; set; }\r\n\r\n\t/// <summary>\r\n\t/// How long the path takes to complete.\r\n\t/// </summary>\r\n\t[Property, ShowIf( nameof( Manual ), false )]\r\n\tpublic float Duration { get; set; } = 10;\r\n\r\n\tpublic enum SplineType\r\n\t{\r\n\t\tTcb,\r\n\t\tCatmullRom\r\n\t};\r\n\r\n\t[Title( \"Mode\" ), Group( \"Spline\" )]\r\n\t[Property] public SplineType SplineMode { get; set; }\r\n\r\n\t[Title( \"Tension\" ), Group( \"Spline\" ), ShowIf( nameof( SplineMode ), SplineType.Tcb )]\r\n\t[Property, Range( -1, 1 )] public float SplineTension { get; set; }\r\n\r\n\t[Title( \"Continuity\" ), Group( \"Spline\" ), ShowIf( nameof( SplineMode ), SplineType.Tcb )]\r\n\t[Property, Range( -1, 1 )] public float SplineContinuity { get; set; }\r\n\r\n\t[Title( \"Bias\" ), Group( \"Spline\" ), ShowIf( nameof( SplineMode ), SplineType.Tcb )]\r\n\t[Property, Range( -1, 1 )] public float SplineBias { get; set; }\r\n\r\n\tprivate Vector3[] _previewPoints;\r\n\r\n\tprotected override void OnStart()\r\n\t{\r\n\t\tbase.OnStart();\r\n\r\n\t\tif ( Scene.IsEditor )\r\n\t\t{\r\n\t\t\tif ( !GameObject.GetAllObjects( true )\r\n\t\t\t\t.Select( x => x.Components.Get<MotionPathPoint>() )\r\n\t\t\t\t.Where( x => x.IsValid() )\r\n\t\t\t\t.Any() )\r\n\t\t\t{\r\n\t\t\t\tvar go = new GameObject( true, \"Point\" );\r\n\t\t\t\tgo.SetParent( GameObject, false );\r\n\t\t\t\tgo.Components.Create<MotionPathPoint>( true );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tprotected override void DrawGizmos()\r\n\t{\r\n\t\tbase.DrawGizmos();\r\n\r\n\t\tif ( _previewPoints is null )\r\n\t\t\treturn;\r\n\r\n\t\tusing ( Gizmo.Hitbox.LineScope() )\r\n\t\t{\r\n\t\t\tfor ( var i = 0; i < _previewPoints.Length - 1; i++ )\r\n\t\t\t{\r\n\t\t\t\tvar pointA = Transform.World.PointToLocal( _previewPoints[i] );\r\n\t\t\t\tvar pointB = Transform.World.PointToLocal( _previewPoints[i + 1] );\r\n\t\t\t\tGizmo.Draw.Color = Gizmo.IsSelected ? Gizmo.Colors.Active : Gizmo.IsHovered ? Gizmo.Colors.Hovered : Color.White.WithAlpha( 0.5f );\r\n\t\t\t\tGizmo.Draw.LineThickness = Gizmo.IsHovered || Gizmo.IsSelected ? 2 : 1;\r\n\t\t\t\tGizmo.Draw.Line( pointA, pointB );\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif ( Target.IsValid() )\r\n\t\t{\r\n\t\t\tGizmo.Draw.Color = Gizmo.Colors.Forward;\r\n\t\t\tvar pointA = Transform.World.PointToLocal( Target.Transform.Position );\r\n\t\t\tvar pointB = Transform.World.NormalToLocal( Target.Transform.Rotation.Forward ) * 5;\r\n\t\t\tGizmo.Draw.SolidCone( pointA, pointB, 2 );\r\n\t\t}\r\n\t}\r\n\r\n\tprivate Vector3 GetPointOnSpline( Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float delta )\r\n\t{\r\n\t\tif ( SplineMode == SplineType.Tcb )\r\n\t\t\treturn Vector3.TcbSpline( p0, p1, p2, p3, SplineTension, SplineContinuity, SplineBias, delta );\r\n\t\telse if ( SplineMode == SplineType.CatmullRom )\r\n\t\t\treturn Vector3.CatmullRomSpline( p0, p1, p2, p3, delta );\r\n\r\n\t\treturn default;\r\n\t}\r\n\r\n\tprotected override void OnUpdate()\r\n\t{\r\n\t\tbase.OnUpdate();\r\n\r\n\t\tvar motionPoints = GameObject.GetAllObjects( true )\r\n\t\t\t.Select( x => x.Components.Get<MotionPathPoint>() )\r\n\t\t\t.Where( x => x.IsValid() )\r\n\t\t\t.ToArray();\r\n\r\n\t\tvar points = motionPoints.Select( x => x.Transform.Position )\r\n\t\t\t.ToArray();\r\n\r\n\t\tif ( SplineMode == SplineType.Tcb )\r\n\t\t\t_previewPoints = points.TcbSpline( 32, SplineTension, SplineContinuity, SplineBias ).ToArray();\r\n\t\telse if ( SplineMode == SplineType.CatmullRom )\r\n\t\t\t_previewPoints = points.CatmullRomSpline( 32 ).ToArray();\r\n\r\n\t\tif ( points.Length < 2 )\r\n\t\t\treturn;\r\n\r\n\t\tif ( points.Length == 2 )\r\n\t\t\t_previewPoints = new Vector3[2] { points[0], points[1] };\r\n\r\n\t\tif ( Target.IsValid() )\r\n\t\t{\r\n\t\t\tvar pointCount = points.Length;\r\n\r\n\t\t\tif ( !Manual && !Duration.AlmostEqual( 0.0f ) )\r\n\t\t\t\tTime = Sandbox.Time.Now % Duration / Duration;\r\n\r\n\t\t\tvar time = Time.Clamp( 0.0f, 1.0f );\r\n\r\n\t\t\tvar segmentIndex = (int)((pointCount - 1) * time);\r\n\t\t\tsegmentIndex = Math.Min( segmentIndex, pointCount - 2 );\r\n\t\t\tvar delta = ((pointCount - 1) * time) - segmentIndex;\r\n\r\n\t\t\tvar p0 = segmentIndex > 0 ? points[segmentIndex - 1] : points[0];\r\n\t\t\tvar p1 = points[segmentIndex];\r\n\t\t\tvar p2 = segmentIndex < pointCount - 1 ? points[segmentIndex + 1] : points[pointCount - 1];\r\n\t\t\tvar p3 = segmentIndex < pointCount - 2 ? points[segmentIndex + 2] : points[pointCount - 1];\r\n\r\n\t\t\tvar offset = time.AlmostEqual( 1.0f ) ? -0.01f : 0.01f;\r\n\t\t\tvar positionA = GetPointOnSpline( p0, p1, p2, p3, delta );\r\n\r\n\t\t\tif ( UsePointRotation )\r\n\t\t\t{\r\n\t\t\t\tvar r1 = motionPoints[segmentIndex];\r\n\t\t\t\tvar r2 = segmentIndex < pointCount - 1 ? motionPoints[segmentIndex + 1] : motionPoints[pointCount - 1];\r\n\t\t\t\tvar rotationStart = r1.Transform.Rotation;\r\n\t\t\t\tvar rotationEnd = r2.Transform.Rotation;\r\n\r\n\t\t\t\tif ( r1.LookAt.IsValid() )\r\n\t\t\t\t\trotationStart = Rotation.LookAt( (r1.LookAt.Transform.Position - r1.Transform.Position).Normal );\r\n\r\n\t\t\t\tif ( r2.LookAt.IsValid() )\r\n\t\t\t\t\trotationEnd = Rotation.LookAt( (r2.LookAt.Transform.Position - r2.Transform.Position).Normal );\r\n\r\n\t\t\t\tTarget.Transform.Rotation = Rotation.Slerp( rotationStart, rotationEnd, delta );\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tvar positionB = GetPointOnSpline( p0, p1, p2, p3, delta + offset );\r\n\t\t\t\tvar forward = (positionB - positionA).Normal * MathF.Sign( offset );\r\n\t\t\t\tvar right = forward.Cross( Vector3.Up ).Normal;\r\n\t\t\t\tvar up = right.Cross( forward ).Normal;\r\n\r\n\t\t\t\tTarget.Transform.Rotation = Rotation.LookAt( forward, up );\r\n\t\t\t}\r\n\r\n\t\t\tTarget.Transform.Position = positionA;\r\n\t\t}\r\n\t}\r\n}\r\n\r\npublic class MotionPathPoint : Component, Component.ExecuteInEditor\r\n{\r\n\t/// <summary>\r\n\t/// Look at this object.\r\n\t/// </summary>\r\n\t[Property]\r\n\tpublic GameObject LookAt { get; set; }\r\n\r\n\tprotected override void DrawGizmos()\r\n\t{\r\n\t\tbase.DrawGizmos();\r\n\r\n\t\tconst float radius = 2.0f;\r\n\t\tGizmo.Hitbox.DepthBias = 0.1f;\r\n\t\tGizmo.Hitbox.Sphere( new Sphere( 0, radius ) );\r\n\t\tGizmo.Draw.Color = Gizmo.IsSelected ? Gizmo.Colors.Active : Gizmo.IsHovered ? Gizmo.Colors.Hovered : Color.White;\r\n\t\tGizmo.Draw.SolidSphere( 0, radius );\r\n\r\n\t\tif ( Gizmo.IsSelected || Gizmo.IsHovered )\r\n\t\t{\r\n\t\t\tvar end = LookAt.IsValid() ? Transform.World.PointToLocal( LookAt.Transform.Position ) : Vector3.Forward * 6;\r\n\t\t\tGizmo.Draw.Color = Gizmo.Colors.Forward;\r\n\t\t\tGizmo.Draw.Arrow( 0, end, 2, 1 );\r\n\t\t}\r\n\t}\r\n}\r\n"
        }
    ]
}