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 ); } } }