200 lines
3.9 KiB
C#
200 lines
3.9 KiB
C#
|
|
||
|
using Godot;
|
||
|
using Rokojori;
|
||
|
using System.Collections.Generic;
|
||
|
|
||
|
namespace Rokojori
|
||
|
{
|
||
|
[Tool]
|
||
|
[GlobalClass, Icon("res://Scripts/Rokojori/Rokojori-Action-Library/Icons/Spline.svg") ]
|
||
|
public partial class Spline : Node3D
|
||
|
#if TOOLS
|
||
|
, GizmoDrawer
|
||
|
#endif
|
||
|
|
||
|
{
|
||
|
[Export]
|
||
|
public bool closed = false;
|
||
|
|
||
|
[Export]
|
||
|
public int editorResolution = 20;
|
||
|
|
||
|
[Export]
|
||
|
public bool updateAlways = false;
|
||
|
|
||
|
[Export]
|
||
|
public int xzPathBakeResolution = 50;
|
||
|
|
||
|
SplineCurve splineCurve;
|
||
|
Vector3 min;
|
||
|
Vector3 max;
|
||
|
|
||
|
public Box3 GetBounds()
|
||
|
{
|
||
|
GetCurve();
|
||
|
|
||
|
return Box3.Create( min, max );
|
||
|
}
|
||
|
|
||
|
|
||
|
public SplineCurve GetCurve()
|
||
|
{
|
||
|
if ( splineCurve == null )
|
||
|
{
|
||
|
var splinePoints = Nodes.GetDirectChildren<SplinePoint>( this );
|
||
|
|
||
|
splineCurve = new SplineCurveCreator().Create( splinePoints, closed );
|
||
|
|
||
|
min = splineCurve.MinPointPosition();
|
||
|
max = splineCurve.MaxPointPosition();
|
||
|
}
|
||
|
|
||
|
return splineCurve;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
SplineCurve splineCurveXZ;
|
||
|
|
||
|
public SplineCurve GetCurveXZ()
|
||
|
{
|
||
|
if ( splineCurveXZ == null )
|
||
|
{
|
||
|
var splinePoints = Nodes.GetDirectChildren<SplinePoint>( this );
|
||
|
|
||
|
splineCurveXZ = new SplineCurveCreator().Create( splinePoints, closed ).CloneForXZ( 0 );
|
||
|
}
|
||
|
|
||
|
return splineCurveXZ;
|
||
|
|
||
|
}
|
||
|
|
||
|
Path2 xzPath;
|
||
|
Convex2Group convex2Group;
|
||
|
|
||
|
public Path2 GetXZPath2()
|
||
|
{
|
||
|
if ( xzPath == null )
|
||
|
{
|
||
|
xzPath = Path2.AsXZFrom( GetCurve(), closed, xzPathBakeResolution );
|
||
|
}
|
||
|
|
||
|
return xzPath;
|
||
|
}
|
||
|
|
||
|
public Convex2Group GetConvex2Group()
|
||
|
{
|
||
|
if ( convex2Group == null )
|
||
|
{
|
||
|
convex2Group = Convex2Group.FromPath( GetXZPath2() );
|
||
|
}
|
||
|
|
||
|
return convex2Group;
|
||
|
}
|
||
|
|
||
|
public void ClearCurveCache()
|
||
|
{
|
||
|
splineCurve = null;
|
||
|
splineCurveXZ = null;
|
||
|
xzPath = null;
|
||
|
convex2Group = null;
|
||
|
}
|
||
|
|
||
|
#if TOOLS
|
||
|
|
||
|
public void DrawGizmo( EditorNode3DGizmoPlugin gizmoPlugin, EditorNode3DGizmo gizmo )
|
||
|
{
|
||
|
ClearCurveCache();
|
||
|
|
||
|
var curve = GetCurve();
|
||
|
|
||
|
gizmo.Clear();
|
||
|
|
||
|
var linePoints = new List<Vector3>();
|
||
|
|
||
|
int resolution = editorResolution <= 0 ? 20 : editorResolution;
|
||
|
|
||
|
renderedResolution = editorResolution;
|
||
|
|
||
|
var lastPoint = ToLocal( curve.SampleAt( 0 ) );
|
||
|
|
||
|
for ( int i = 1; i < resolution; i++ )
|
||
|
{
|
||
|
var t = i / (float) (resolution - 1 );
|
||
|
var point = ToLocal( curve.SampleAt( t ) );
|
||
|
|
||
|
linePoints.Add( lastPoint );
|
||
|
linePoints.Add( point );
|
||
|
|
||
|
lastPoint = point;
|
||
|
}
|
||
|
|
||
|
for ( int i = 0; i < curve.points.Count; i++ )
|
||
|
{
|
||
|
var p = curve.points[ i ];
|
||
|
linePoints.Add( ToLocal( p.position ) );
|
||
|
linePoints.Add( ToLocal( p.tangentBefore.position ) );
|
||
|
|
||
|
linePoints.Add( ToLocal( p.position ) );
|
||
|
linePoints.Add( ToLocal( p.tangentNext.position ) );
|
||
|
}
|
||
|
|
||
|
var material = gizmoPlugin.GetMaterial( "main", gizmo );
|
||
|
|
||
|
gizmo.AddLines( linePoints.ToArray(), material, false );
|
||
|
}
|
||
|
|
||
|
List<Vector3> cachedPositions = new List<Vector3>();
|
||
|
|
||
|
|
||
|
int renderedResolution = -100;
|
||
|
|
||
|
public override void _Process( double delta )
|
||
|
{
|
||
|
var changed = updateAlways;
|
||
|
var index = 0;
|
||
|
|
||
|
if ( renderedResolution != editorResolution )
|
||
|
{
|
||
|
changed = true;
|
||
|
}
|
||
|
|
||
|
Nodes.ForEachDirectChild<SplinePoint>( this,
|
||
|
sp =>
|
||
|
{
|
||
|
if ( changed )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( index >= cachedPositions.Count )
|
||
|
{
|
||
|
changed = true;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( cachedPositions[ index ] != sp.GlobalPosition )
|
||
|
{
|
||
|
changed = true;
|
||
|
}
|
||
|
|
||
|
index ++;
|
||
|
}
|
||
|
);
|
||
|
|
||
|
if ( ! changed )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
cachedPositions = Nodes.MapDirectChildren<SplinePoint,Vector3>( this, sp => sp.GlobalPosition );
|
||
|
|
||
|
// RJLog.Log( "Updating gizmos" );
|
||
|
UpdateGizmos();
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
}
|