105 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C#
		
	
	
	
			
		
		
	
	
			105 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C#
		
	
	
	
 | 
						|
using Godot;
 | 
						|
using Rokojori;
 | 
						|
using System.Collections.Generic;
 | 
						|
 | 
						|
namespace Rokojori
 | 
						|
{  
 | 
						|
  [Tool]
 | 
						|
  [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Spline.svg") ]
 | 
						|
  public partial class TubeShape:Node
 | 
						|
  { 
 | 
						|
    [Export]
 | 
						|
    public Spline spline;
 | 
						|
 | 
						|
    [Export]
 | 
						|
    public Node3D pivotPose;
 | 
						|
 | 
						|
    [Export]
 | 
						|
    public float tubePosition;
 | 
						|
 | 
						|
    [Export]
 | 
						|
    public float scale = 1f;
 | 
						|
    
 | 
						|
    [Export]
 | 
						|
    public float widthScale = 1f;
 | 
						|
 | 
						|
    [Export]
 | 
						|
    public float heightScale = 1f;
 | 
						|
 | 
						|
    [Export]
 | 
						|
    public ShapeOrientationMode shapeOrientationMode = ShapeOrientationMode.Auto;
 | 
						|
 | 
						|
    bool cached = false;
 | 
						|
 | 
						|
    bool shapeForward = true;
 | 
						|
    SplineCurve radialShape;
 | 
						|
    
 | 
						|
 | 
						|
    public void ClearCache()
 | 
						|
    {
 | 
						|
      cached = false;
 | 
						|
    }
 | 
						|
 | 
						|
    public Pose GetPose( bool undistort, int splineSegments, int radialSegments, Pose pose, Vector2 uv, Vector3 scale, Quaternion twistRotation )
 | 
						|
    {
 | 
						|
      if ( ! cached )
 | 
						|
      {
 | 
						|
        radialShape = spline.GetCurve();
 | 
						|
        shapeForward = true;
 | 
						|
        
 | 
						|
        if ( pivotPose != null )
 | 
						|
        {
 | 
						|
          radialShape = radialShape.ApplyPose( Pose.InverseFrom( pivotPose ) );
 | 
						|
        }
 | 
						|
 | 
						|
        radialShape = radialShape.CloneForXY();        
 | 
						|
 | 
						|
        if  ( ShapeOrientationMode.Original != shapeOrientationMode )
 | 
						|
        {
 | 
						|
          if ( ShapeOrientationMode.Auto == shapeOrientationMode )
 | 
						|
          {
 | 
						|
            var path = radialShape.SampleXYPath( radialSegments );
 | 
						|
            shapeForward = path.isClockwise;
 | 
						|
          }
 | 
						|
 | 
						|
          if ( ShapeOrientationMode.Reverse == shapeOrientationMode )
 | 
						|
          {
 | 
						|
            shapeForward = false;
 | 
						|
          }
 | 
						|
          
 | 
						|
        }
 | 
						|
 | 
						|
        cached = true;
 | 
						|
      }
 | 
						|
      
 | 
						|
 | 
						|
      scale.X *= widthScale * this.scale;
 | 
						|
      scale.Y *= heightScale * this.scale;
 | 
						|
 | 
						|
      var radialT = ! shapeForward ? uv.X : ( 1f - uv.X );
 | 
						|
      radialT = undistort ? 
 | 
						|
                  radialShape.UtoT( radialT, splineSegments ) : 
 | 
						|
                  radialT;  
 | 
						|
 | 
						|
      var shapePosition = radialShape.PositionAt( radialT ) * scale;
 | 
						|
      var shapeTangent  = radialShape.TangentAt( radialT, 1f / radialSegments ) * scale; 
 | 
						|
 | 
						|
 | 
						|
      shapePosition = twistRotation * shapePosition;
 | 
						|
      shapeTangent  = twistRotation * shapeTangent;
 | 
						|
 | 
						|
      var angle = Math3D.AngleXY( shapeTangent ) + Mathf.Pi;
 | 
						|
      var rotation = Math3D.RotateZ( angle );
 | 
						|
        
 | 
						|
      var combinedRotation = pose.rotation * rotation;
 | 
						|
 | 
						|
      var rotatedShapePosition = Vector3.Zero;
 | 
						|
 | 
						|
      rotatedShapePosition = pose.rotation * shapePosition;            
 | 
						|
 | 
						|
      return Pose.Create( rotatedShapePosition + pose.position, combinedRotation );
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
} |