146 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C#
		
	
	
	
		
		
			
		
	
	
			146 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C#
		
	
	
	
|   | using Godot; | ||
|  | using System; | ||
|  | using System.Collections.Generic; | ||
|  | 
 | ||
|  | namespace Rokojori | ||
|  | {   | ||
|  | 
 | ||
|  |   public enum SVGPathInstructionType | ||
|  |   { | ||
|  |     MoveTo, | ||
|  |     LineTo, | ||
|  |     QuadraticBezierTo, | ||
|  |     CubicBezierTo, | ||
|  |     ArcTo, | ||
|  |     Close     | ||
|  |   } | ||
|  | 
 | ||
|  |   public class SVGPathInstruction | ||
|  |   { | ||
|  |     public SVGPathCommand sourceCommand; | ||
|  |     public int sourceCommandIndex; | ||
|  |     public SVGPathInstructionType type = SVGPathInstructionType.MoveTo; | ||
|  |     public Vector2 startPoint = Vector2.Zero; | ||
|  |     public Vector2 controlPoint1 = Vector2.Zero; | ||
|  |     public Vector2 controlPoint2 = Vector2.Zero; | ||
|  |     public Vector2 endPoint = Vector2.Zero; | ||
|  |     public Vector2 radius = Vector2.Zero; | ||
|  |     public float angle = 0; | ||
|  |     public bool largeArcFlag = false; | ||
|  |     public bool sweepFlag = false; | ||
|  | 
 | ||
|  |     public override string ToString() | ||
|  |     { | ||
|  |       return GetInfo(); | ||
|  |     } | ||
|  | 
 | ||
|  |     public void AddPoints( List<Vector2> pathPoints, float resolution = 1, int maxPoints = 1000 ) | ||
|  |     { | ||
|  |       if ( SVGPathInstructionType.MoveTo == type ) | ||
|  |       { | ||
|  |         pathPoints.Add( startPoint ); | ||
|  |       } | ||
|  |       else if (  | ||
|  |         SVGPathInstructionType.LineTo == type || | ||
|  |         SVGPathInstructionType.Close == type | ||
|  |       ) | ||
|  |       { | ||
|  |         pathPoints.Add( endPoint ); | ||
|  |       } | ||
|  |       else if ( SVGPathInstructionType.ArcTo == type ) | ||
|  |       { | ||
|  |         var centerPosition = new Vector2(); | ||
|  |         var centerRadius   = new Vector2(); | ||
|  |         var centerAngles   = new Vector2(); | ||
|  |          | ||
|  | 
 | ||
|  |         SVGArc.EndpointToCenterArc( | ||
|  |           startPoint, endPoint, radius, angle, largeArcFlag, sweepFlag, | ||
|  |           out centerPosition, out centerRadius, out centerAngles );  | ||
|  | 
 | ||
|  | 
 | ||
|  |         var arcResolution = Math.Max( centerRadius.X, centerRadius.Y ) / resolution; | ||
|  | 
 | ||
|  |         arcResolution = Mathf.Clamp( arcResolution, 1, maxPoints );  | ||
|  |          | ||
|  |         RJLog.Log( "Arc Resolution", arcResolution ); | ||
|  | 
 | ||
|  | 
 | ||
|  |         for ( int i = 1; i < arcResolution - 1; i++ ) | ||
|  |         { | ||
|  |           var t = centerAngles.Y * ( (float)i / ( arcResolution - 1 ) ); | ||
|  |           var arcPoint = SVGArc.GetPointOnCenterArc( centerRadius, centerAngles.X, t ) + centerPosition; | ||
|  | 
 | ||
|  |           pathPoints.Add( arcPoint ); | ||
|  |         } | ||
|  | 
 | ||
|  |         pathPoints.Add( endPoint ); | ||
|  | 
 | ||
|  |       } | ||
|  |       else if (  | ||
|  |         SVGPathInstructionType.QuadraticBezierTo == type ||  | ||
|  |         SVGPathInstructionType.CubicBezierTo == type | ||
|  |        ) | ||
|  |       { | ||
|  |         var isQuadratic = SVGPathInstructionType.QuadraticBezierTo == type; | ||
|  | 
 | ||
|  |         var curve = isQuadratic ? | ||
|  |           new CustomCurve2( t => QuadraticBezier.Compute( t, startPoint, controlPoint1, endPoint ) ) : | ||
|  |           new CustomCurve2( t => CubicBezier.Compute( t, startPoint, controlPoint1, controlPoint2, endPoint ) ) | ||
|  |         ; | ||
|  | 
 | ||
|  |         var length = curve.ComputeLength( isQuadratic ? 4 : 6 ); | ||
|  | 
 | ||
|  |         var numPoints = Mathf.Clamp( Mathf.RoundToInt( length / resolution ), 1, maxPoints );  | ||
|  | 
 | ||
|  |         for ( int i = 1; i < numPoints - 1; i++ ) | ||
|  |         { | ||
|  |           var t = (float) i / ( numPoints - 1 ); | ||
|  |           pathPoints.Add( curve.SampleAt( t ) ); | ||
|  |         } | ||
|  | 
 | ||
|  |         pathPoints.Add( curve.SampleAt( 1 ) ); | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  |     public string GetInfo() | ||
|  |     { | ||
|  |       var infos = new List<object>(); | ||
|  |       infos.Add( type ); | ||
|  | 
 | ||
|  |       if ( SVGPathInstructionType.MoveTo == type ) | ||
|  |       { | ||
|  |         infos.Add( endPoint ); | ||
|  |       } | ||
|  |       else if ( SVGPathInstructionType.LineTo == type ) | ||
|  |       { | ||
|  |         infos.Add( startPoint ); | ||
|  |         infos.Add( endPoint ); | ||
|  |       } | ||
|  |       else if ( SVGPathInstructionType.QuadraticBezierTo == type ) | ||
|  |       { | ||
|  |         infos.Add( startPoint ); | ||
|  |         infos.Add( controlPoint1 ); | ||
|  |         infos.Add( endPoint ); | ||
|  |       } | ||
|  |       else if ( SVGPathInstructionType.CubicBezierTo == type ) | ||
|  |       { | ||
|  |         infos.Add( startPoint ); | ||
|  |         infos.Add( controlPoint1 ); | ||
|  |         infos.Add( controlPoint2 ); | ||
|  |         infos.Add( endPoint ); | ||
|  |       } | ||
|  |       else if ( SVGPathInstructionType.ArcTo == type ) | ||
|  |       { | ||
|  |         infos.Add( startPoint ); | ||
|  |         infos.Add( radius ); | ||
|  |         infos.Add( angle ); | ||
|  |         infos.Add( largeArcFlag ); | ||
|  |         infos.Add( sweepFlag ); | ||
|  |         infos.Add( endPoint ); | ||
|  |       } | ||
|  | 
 | ||
|  |       return RJLog.GetLogString( infos.ToArray() ); | ||
|  |     } | ||
|  |   } | ||
|  | } |