Docs Generator + Biquad/Smoother
This commit is contained in:
parent
c3d7848d30
commit
375a05336a
|
@ -169,8 +169,8 @@ namespace Rokojori
|
||||||
}
|
}
|
||||||
|
|
||||||
float reloadDuration = 2;
|
float reloadDuration = 2;
|
||||||
DateTime lastUpdateTime = DateTime.Now;
|
DateTimeOffset lastUpdateTime = DateTime.Now;
|
||||||
DateTime lastDisposalTime = DateTime.Now;
|
DateTimeOffset lastDisposalTime = DateTime.Now;
|
||||||
|
|
||||||
public void SaveCache( string relativeCachePath, object data )
|
public void SaveCache( string relativeCachePath, object data )
|
||||||
{
|
{
|
||||||
|
|
|
@ -170,9 +170,9 @@ namespace Rokojori
|
||||||
var smoothStrength = rawSmooth * 250f;
|
var smoothStrength = rawSmooth * 250f;
|
||||||
|
|
||||||
var current = TransformData.From( targets[ i ], shakeEffect.globalPosition, shakeEffect.globalRotation );
|
var current = TransformData.From( targets[ i ], shakeEffect.globalPosition, shakeEffect.globalRotation );
|
||||||
combined.position = Smoother.SmoothTimeInvariant( current.position, combined.position, delta, smoothStrength );
|
combined.position = Smoother.SmoothTimeVariant( current.position, combined.position, delta, smoothStrength );
|
||||||
combined.rotation = Smoother.SmoothTimeInvariant( current.rotation, combined.rotation, delta, smoothStrength );
|
combined.rotation = Smoother.SmoothTimeVariant( current.rotation, combined.rotation, delta, smoothStrength );
|
||||||
combined.scale = Smoother.SmoothTimeInvariant( current.scale, combined.scale, delta, smoothStrength );
|
combined.scale = Smoother.SmoothTimeVariant( current.scale, combined.scale, delta, smoothStrength );
|
||||||
}
|
}
|
||||||
|
|
||||||
combined.Set( targets[ i ], shakeEffect.globalPosition, shakeEffect.globalRotation );
|
combined.Set( targets[ i ], shakeEffect.globalPosition, shakeEffect.globalRotation );
|
||||||
|
|
|
@ -118,6 +118,14 @@ namespace Rokojori
|
||||||
return rp;
|
return rp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string absolutePath
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return fullPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string absoluteParentPath
|
public string absoluteParentPath
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
public enum BiquadType
|
||||||
|
{
|
||||||
|
LowPass,
|
||||||
|
BandPass,
|
||||||
|
HighPass,
|
||||||
|
Peak,
|
||||||
|
LowShelf,
|
||||||
|
HighShelf,
|
||||||
|
Notch
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Biquad
|
||||||
|
{
|
||||||
|
|
||||||
|
public float a0 = 0;
|
||||||
|
public float a1 = 0;
|
||||||
|
public float a2 = 0;
|
||||||
|
public float a3 = 0;
|
||||||
|
public float a4 = 0;
|
||||||
|
|
||||||
|
public float x1 = 0;
|
||||||
|
public float x2 = 0;
|
||||||
|
public float y1 = 0;
|
||||||
|
public float y2 = 0;
|
||||||
|
|
||||||
|
float process( float inputSample )
|
||||||
|
{
|
||||||
|
var result = this.a0 * inputSample +
|
||||||
|
this.a1 * this.x1 +
|
||||||
|
this.a2 * this.x2 -
|
||||||
|
this.a3 * this.y1 -
|
||||||
|
this.a4 * this.y2;
|
||||||
|
|
||||||
|
this.x2 = this.x1;
|
||||||
|
this.x1 = inputSample;
|
||||||
|
|
||||||
|
this.y2 = this.y1;
|
||||||
|
this.y1 = result;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Biquad Create( BiquadType filterType, float gainDB, float frequency, float bandwidth, float sampleRate )
|
||||||
|
{
|
||||||
|
var filter = new Biquad();
|
||||||
|
float A= 0, omega= 0, sn= 0, cs= 0, alpha= 0, beta = 0;
|
||||||
|
float a0= 0, a1= 0, a2= 0, b0= 0, b1= 0, b2 = 0;
|
||||||
|
|
||||||
|
var M_LN2 = 0.69314718055994530942f;
|
||||||
|
|
||||||
|
A = Mathf.Pow( 10, gainDB / 40 );
|
||||||
|
omega = 2 * Mathf.Pi * frequency / sampleRate;
|
||||||
|
sn = Mathf.Sin( omega );
|
||||||
|
cs = Mathf.Cos( omega );
|
||||||
|
alpha = ( sn * Mathf.Sinh( M_LN2 / 2 * bandwidth * omega / sn ) );
|
||||||
|
beta = Mathf.Sqrt(A + A);
|
||||||
|
|
||||||
|
switch ( filterType )
|
||||||
|
{
|
||||||
|
case BiquadType.LowPass:
|
||||||
|
{
|
||||||
|
b0 = (1 - cs) /2;
|
||||||
|
b1 = 1 - cs;
|
||||||
|
b2 = (1 - cs) /2;
|
||||||
|
a0 = 1 + alpha;
|
||||||
|
a1 = -2 * cs;
|
||||||
|
a2 = 1 - alpha;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BiquadType.HighPass:
|
||||||
|
{
|
||||||
|
b0 = (1 + cs) /2;
|
||||||
|
b1 = -(1 + cs);
|
||||||
|
b2 = (1 + cs) /2;
|
||||||
|
a0 = 1 + alpha;
|
||||||
|
a1 = -2 * cs;
|
||||||
|
a2 = 1 - alpha;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BiquadType.BandPass:
|
||||||
|
{
|
||||||
|
b0 = alpha;
|
||||||
|
b1 = 0;
|
||||||
|
b2 = -alpha;
|
||||||
|
a0 = 1 + alpha;
|
||||||
|
a1 = -2 * cs;
|
||||||
|
a2 = 1 - alpha;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BiquadType.Notch:
|
||||||
|
{
|
||||||
|
b0 = 1;
|
||||||
|
b1 = -2 * cs;
|
||||||
|
b2 = 1;
|
||||||
|
a0 = 1 + alpha;
|
||||||
|
a1 = -2 * cs;
|
||||||
|
a2 = 1 - alpha;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BiquadType.Peak:
|
||||||
|
{
|
||||||
|
b0 = 1 + (alpha * A);
|
||||||
|
b1 = -2 * cs;
|
||||||
|
b2 = 1 - (alpha * A);
|
||||||
|
a0 = 1 + (alpha /A);
|
||||||
|
a1 = -2 * cs;
|
||||||
|
a2 = 1 - (alpha /A);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BiquadType.LowShelf:
|
||||||
|
{
|
||||||
|
b0 = A * ((A + 1) - (A - 1) * cs + beta * sn);
|
||||||
|
b1 = 2 * A * ((A - 1) - (A + 1) * cs);
|
||||||
|
b2 = A * ((A + 1) - (A - 1) * cs - beta * sn);
|
||||||
|
a0 = (A + 1) + (A - 1) * cs + beta * sn;
|
||||||
|
a1 = -2 * ((A - 1) + (A + 1) * cs);
|
||||||
|
a2 = (A + 1) + (A - 1) * cs - beta * sn;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BiquadType.HighShelf:
|
||||||
|
{
|
||||||
|
b0 = A * ((A + 1) + (A - 1) * cs + beta * sn);
|
||||||
|
b1 = -2 * A * ((A - 1) + (A + 1) * cs);
|
||||||
|
b2 = A * ((A + 1) + (A - 1) * cs - beta * sn);
|
||||||
|
a0 = (A + 1) - (A - 1) * cs + beta * sn;
|
||||||
|
a1 = 2 * ((A - 1) - (A + 1) * cs);
|
||||||
|
a2 = (A + 1) - (A - 1) * cs - beta * sn;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
filter.a0 = b0 / a0;
|
||||||
|
filter.a1 = b1 / a0;
|
||||||
|
filter.a2 = b2 / a0;
|
||||||
|
filter.a3 = a1 / a0;
|
||||||
|
filter.a4 = a2 / a0;
|
||||||
|
|
||||||
|
filter.x1 = filter.x2 = 0;
|
||||||
|
filter.y1 = filter.y2 = 0;
|
||||||
|
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float filter( float inputSample, float[] coefficients, float[] buffer )
|
||||||
|
{
|
||||||
|
var result = coefficients[ 0 ] * inputSample +
|
||||||
|
coefficients[ 1 ] * buffer[ 0 ] +
|
||||||
|
coefficients[ 2 ] * buffer[ 1 ] -
|
||||||
|
coefficients[ 3 ] * buffer[ 2 ] -
|
||||||
|
coefficients[ 4 ] * buffer[ 3 ];
|
||||||
|
|
||||||
|
buffer[ 1 ] = buffer[ 0 ];
|
||||||
|
buffer[ 0 ] = inputSample;
|
||||||
|
|
||||||
|
buffer[ 3 ] = buffer[ 2 ];
|
||||||
|
buffer[ 2 ] = result;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,6 @@ using Godot;
|
||||||
|
|
||||||
namespace Rokojori
|
namespace Rokojori
|
||||||
{
|
{
|
||||||
[System.Serializable]
|
|
||||||
public class Range
|
public class Range
|
||||||
{
|
{
|
||||||
public float min;
|
public float min;
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
public class RangeI
|
||||||
|
{
|
||||||
|
public int min;
|
||||||
|
public int max;
|
||||||
|
|
||||||
|
public RangeI( int min, int max )
|
||||||
|
{
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EnsureCorrectness()
|
||||||
|
{
|
||||||
|
if ( max < min )
|
||||||
|
{
|
||||||
|
var b = max; max = min; min = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains( int value )
|
||||||
|
{
|
||||||
|
return min <= value && value <= max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Overlaps( RangeI other )
|
||||||
|
{
|
||||||
|
if ( other.max < min ) { return false; }
|
||||||
|
if ( other.min > max ) { return false; }
|
||||||
|
|
||||||
|
if ( other.Contains( min ) || other.Contains( max ) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( Contains( other.min ) || Contains( other.max ) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RangeI Copy()
|
||||||
|
{
|
||||||
|
return new RangeI( min, max );
|
||||||
|
}
|
||||||
|
|
||||||
|
public int center { get { return ( max + min ) / 2; } }
|
||||||
|
public int range { get { return max - min; } }
|
||||||
|
public int length { get { return max - min; } }
|
||||||
|
|
||||||
|
public static bool Contains( float min, float max, float value )
|
||||||
|
{
|
||||||
|
return min <= value && value <= max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ContainsExclusive( float min, float max, float value )
|
||||||
|
{
|
||||||
|
return min < value && value < max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ContainsExclusiveMax( float min, float max, float value )
|
||||||
|
{
|
||||||
|
return min <= value && value < max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Overlap( float minA, float maxA, float minB, float maxB )
|
||||||
|
{
|
||||||
|
if ( maxB < minA ) { return false; }
|
||||||
|
if ( minB > maxA ) { return false; }
|
||||||
|
|
||||||
|
if ( Contains( minB, maxB, minA ) || Contains( minB, maxB, maxA ) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( Contains( minA, maxA, minB ) || Contains( minA, maxA, maxB ) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
uid://bfe6pnhqcnw1q
|
|
@ -8,19 +8,19 @@ namespace Rokojori
|
||||||
{
|
{
|
||||||
float overflowDelta = 0;
|
float overflowDelta = 0;
|
||||||
|
|
||||||
public static float SmoothTimeInvariant( float value, float nextValue, float delta, float coefficient )
|
public static float SmoothTimeVariant( float value, float nextValue, float delta, float coefficient )
|
||||||
{
|
{
|
||||||
var lerpAmount = Mathf.Exp( -coefficient * delta );
|
var lerpAmount = Mathf.Exp( -coefficient * delta );
|
||||||
return Mathf.Lerp( nextValue, value, lerpAmount );
|
return Mathf.Lerp( nextValue, value, lerpAmount );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vector2 SmoothTimeInvariant( Vector2 value, Vector2 nextValue, float delta, float coefficient )
|
public static Vector2 SmoothTimeVariant( Vector2 value, Vector2 nextValue, float delta, float coefficient )
|
||||||
{
|
{
|
||||||
var lerpAmount = Mathf.Exp( -coefficient * delta );
|
var lerpAmount = Mathf.Exp( -coefficient * delta );
|
||||||
return Math2D.Lerp( nextValue, value, lerpAmount );
|
return Math2D.Lerp( nextValue, value, lerpAmount );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vector3 SmoothTimeInvariant( Vector3 value, Vector3 nextValue, float delta, float coefficient )
|
public static Vector3 SmoothTimeVariant( Vector3 value, Vector3 nextValue, float delta, float coefficient )
|
||||||
{
|
{
|
||||||
var lerpAmount = Mathf.Exp( -coefficient * delta );
|
var lerpAmount = Mathf.Exp( -coefficient * delta );
|
||||||
return Math3D.Lerp( nextValue, value, lerpAmount );
|
return Math3D.Lerp( nextValue, value, lerpAmount );
|
||||||
|
|
|
@ -19,12 +19,12 @@ namespace Rokojori
|
||||||
public int seed = 1984;
|
public int seed = 1984;
|
||||||
|
|
||||||
|
|
||||||
[Export]
|
[ExportToolButton( "Create")]
|
||||||
public bool update;
|
public Callable createButton => Callable.From( ()=>
|
||||||
|
{
|
||||||
[Export]
|
CreatePatch();
|
||||||
public bool updateAlways;
|
}
|
||||||
|
);
|
||||||
[Export]
|
[Export]
|
||||||
public Material material;
|
public Material material;
|
||||||
|
|
||||||
|
@ -252,34 +252,6 @@ namespace Rokojori
|
||||||
[Export]
|
[Export]
|
||||||
public Curve highCurve = MathX.Curve( 0, 1 );
|
public Curve highCurve = MathX.Curve( 0, 1 );
|
||||||
|
|
||||||
// SerializedGodotObject _cached;
|
|
||||||
|
|
||||||
public override void _Process( double delta )
|
|
||||||
{
|
|
||||||
if ( ! ( update || updateAlways ) )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
update = false;
|
|
||||||
|
|
||||||
|
|
||||||
/*var current = SerializedGodotObject.Create( this );
|
|
||||||
|
|
||||||
var isEquals = _cached != null && _cached.Equals( current );
|
|
||||||
|
|
||||||
if ( _cached != null && _cached.Equals( current ) )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CreatePatch();
|
|
||||||
|
|
||||||
// _cached = current;
|
|
||||||
}
|
|
||||||
|
|
||||||
float _maxWidth = 0;
|
float _maxWidth = 0;
|
||||||
|
|
||||||
Vector3 _patchOffset = Vector3.Zero;
|
Vector3 _patchOffset = Vector3.Zero;
|
||||||
|
|
|
@ -132,6 +132,19 @@ namespace Rokojori
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsAnyOf( params LexerMatcher[] matchers )
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < matchers.Length; i++ )
|
||||||
|
{
|
||||||
|
if ( Is( matchers[ i ] ) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsAny( LexerMatcher matcher, params string[] matches )
|
public bool IsAny( LexerMatcher matcher, params string[] matches )
|
||||||
{
|
{
|
||||||
if ( matches == null || matches.Length == 0 )
|
if ( matches == null || matches.Length == 0 )
|
||||||
|
@ -160,6 +173,9 @@ namespace Rokojori
|
||||||
public class FindResult
|
public class FindResult
|
||||||
{
|
{
|
||||||
public FindResultType type = FindResultType.NotFound;
|
public FindResultType type = FindResultType.NotFound;
|
||||||
|
|
||||||
|
public bool found => FindResultType.Found == type;
|
||||||
|
|
||||||
public int index;
|
public int index;
|
||||||
|
|
||||||
|
|
||||||
|
@ -225,11 +241,66 @@ namespace Rokojori
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FindResult Find( List<LexerEvent> tokens, int offset, System.Func<LexerEvent,FindResultType> evaluator )
|
public static List<List<LexerEvent>> FindSequences( List<LexerEvent> tokens, System.Func<int,bool,Trillean> matcher )
|
||||||
|
{
|
||||||
|
var sequences = new List<List<LexerEvent>>();
|
||||||
|
|
||||||
|
List<LexerEvent> currentSequence = null;
|
||||||
|
|
||||||
|
for ( int i = 0; i < tokens.Count; i++ )
|
||||||
|
{
|
||||||
|
var token = tokens[ i ];
|
||||||
|
var result = matcher( i, currentSequence != null );
|
||||||
|
|
||||||
|
if ( currentSequence != null )
|
||||||
|
{
|
||||||
|
if ( Trillean.True == result )
|
||||||
|
{
|
||||||
|
currentSequence.Add( token );
|
||||||
|
}
|
||||||
|
else if ( Trillean.False == result )
|
||||||
|
{
|
||||||
|
currentSequence.Add( token );
|
||||||
|
|
||||||
|
sequences.Add( currentSequence );
|
||||||
|
currentSequence = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( Trillean.True == result )
|
||||||
|
{
|
||||||
|
currentSequence = new List<LexerEvent>();
|
||||||
|
currentSequence.Add( token );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( Trillean.False == result )
|
||||||
|
{
|
||||||
|
sequences.Add( new List<LexerEvent>(){ tokens[ i ] } );
|
||||||
|
sequences.Add( null );
|
||||||
|
return sequences;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return sequences;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FindResult ReverseFind( List<LexerEvent> tokens, int offset, System.Func<LexerEvent,FindResultType> evaluator )
|
||||||
|
{
|
||||||
|
return Find( tokens, offset, evaluator, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FindResult Find( List<LexerEvent> tokens, int offset, System.Func<LexerEvent,FindResultType> evaluator, bool forward = true )
|
||||||
{
|
{
|
||||||
var result = new FindResult();
|
var result = new FindResult();
|
||||||
|
|
||||||
for ( int i = offset; i < tokens.Count; i++ )
|
var increment = forward ? 1 : -1;
|
||||||
|
var end = forward ? tokens.Count : -1;
|
||||||
|
|
||||||
|
for ( int i = offset; i != end && i >= 0 && i < tokens.Count; i += increment )
|
||||||
{
|
{
|
||||||
var tokenResult = evaluator( tokens[ i ] );
|
var tokenResult = evaluator( tokens[ i ] );
|
||||||
|
|
||||||
|
@ -289,11 +360,12 @@ namespace Rokojori
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static List<string> openTypes = new List<string>(){ "(","[","{" };
|
||||||
|
static List<string> closingTypes = new List<string>(){ ")","]","}" };
|
||||||
|
|
||||||
public static FindResult FindClosingBracket( List<LexerEvent> tokens, int offset )
|
public static FindResult FindClosingBracket( List<LexerEvent> tokens, int offset )
|
||||||
{
|
{
|
||||||
var openTypes = new List<string>(){ "(","[","{" };
|
|
||||||
var closingTypes = new List<string>(){ ")","]","}" };
|
|
||||||
|
|
||||||
var token = tokens[ offset ];
|
var token = tokens[ offset ];
|
||||||
|
|
||||||
var bracketIndex = openTypes.IndexOf( token.match );
|
var bracketIndex = openTypes.IndexOf( token.match );
|
||||||
|
@ -325,11 +397,13 @@ namespace Rokojori
|
||||||
return FindCloser( tokens, offset, counter );
|
return FindCloser( tokens, offset, counter );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FindResult FindCloser( List<LexerEvent> tokens, int offset, System.Func<LexerEvent,int> counter )
|
public static FindResult FindCloser( List<LexerEvent> tokens, int offset, System.Func<LexerEvent,int> counter, bool forward = true )
|
||||||
{
|
{
|
||||||
var result = new FindResult();
|
var result = new FindResult();
|
||||||
var currentValue = 0;
|
var currentValue = 0;
|
||||||
|
|
||||||
|
if ( forward )
|
||||||
|
{
|
||||||
for ( int i = offset; i < tokens.Count; i++ )
|
for ( int i = offset; i < tokens.Count; i++ )
|
||||||
{
|
{
|
||||||
var countResult = counter( tokens[ i ] );
|
var countResult = counter( tokens[ i ] );
|
||||||
|
@ -343,8 +417,115 @@ namespace Rokojori
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for ( int i = offset; i >= 0; i-- )
|
||||||
|
{
|
||||||
|
var countResult = counter( tokens[ i ] );
|
||||||
|
|
||||||
|
currentValue += countResult;
|
||||||
|
|
||||||
|
if ( currentValue == 0 )
|
||||||
|
{
|
||||||
|
result.type = FindResultType.Found;
|
||||||
|
result.index = i;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FindResult FindOpeningBracket( List<LexerEvent> tokens, int offset, string blockBracket = "{" )
|
||||||
|
{
|
||||||
|
var result = Find( tokens, offset,
|
||||||
|
( le ) =>
|
||||||
|
{
|
||||||
|
return le.Is( LexerMatcherLibrary.BracketMatcher, blockBracket ) ? FindResultType.Found : FindResultType.KeepSearching;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FindResult ReverseFindOpeningBracket( List<LexerEvent> tokens, int offset )
|
||||||
|
{
|
||||||
|
|
||||||
|
var token = tokens[ offset ];
|
||||||
|
|
||||||
|
var bracketIndex = closingTypes.IndexOf( token.match );
|
||||||
|
|
||||||
|
if ( bracketIndex == -1 )
|
||||||
|
{
|
||||||
|
var result = new FindResult( FindResultType.NotFound, offset );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
var opener = openTypes[ bracketIndex ];
|
||||||
|
var closer = closingTypes[ bracketIndex ];
|
||||||
|
|
||||||
|
var counter = ( LexerEvent le ) =>
|
||||||
|
{
|
||||||
|
if ( le.Is( LexerMatcherLibrary.BracketMatcher, closer ) )
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( le.Is( LexerMatcherLibrary.BracketMatcher, opener ) )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
return FindCloser( tokens, offset, counter, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static List<RangeI> GetBlocks( List<LexerEvent> tokens )
|
||||||
|
{
|
||||||
|
var index = 0;
|
||||||
|
List<RangeI> blocks = new List<RangeI>();
|
||||||
|
|
||||||
|
while ( index < tokens.Count )
|
||||||
|
{
|
||||||
|
var openResult = FindOpeningBracket( tokens, index );
|
||||||
|
|
||||||
|
if ( ! openResult.found || openResult.index < index )
|
||||||
|
{
|
||||||
|
// RJLog.Log( "No OpeningBracket after", index );
|
||||||
|
|
||||||
|
if ( index == 0 )
|
||||||
|
{
|
||||||
|
RJLog.Log( tokens.Map( t => t.type + ": '" + t.match + "'" ).Join( "\n" ) );
|
||||||
|
}
|
||||||
|
return blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var closeResult = FindClosingBracket( tokens, openResult.index );
|
||||||
|
|
||||||
|
if ( ! closeResult.found || closeResult.index <= openResult.index )
|
||||||
|
{
|
||||||
|
// RJLog.Log( "No ClosingBracket after", index );
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var range = new RangeI( openResult.index, closeResult.index );
|
||||||
|
blocks.Add( range );
|
||||||
|
|
||||||
|
index = closeResult.index + 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,6 +20,39 @@ namespace Rokojori
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<List<LexerEvent>> GetAllObjectDefinitions( string source )
|
||||||
|
{
|
||||||
|
var tokens = Lex( source ).Filter( e => ! ( e.isDone || e.isError ) );
|
||||||
|
|
||||||
|
var sequences = LexerEvent.FindSequences( tokens,
|
||||||
|
( int index, bool inSequence ) =>
|
||||||
|
{
|
||||||
|
var le = tokens[ index ];
|
||||||
|
|
||||||
|
if (
|
||||||
|
|
||||||
|
le.Is( LexerMatcherLibrary.ClassMatcher ) ||
|
||||||
|
le.Is( LexerMatcherLibrary.StructMatcher ) ||
|
||||||
|
le.Is( LexerMatcherLibrary.InterfaceMatcher ) ||
|
||||||
|
le.Is( LexerMatcherLibrary.RecordMatcher ) ||
|
||||||
|
le.Is( LexerMatcherLibrary.EnumMatcher )
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return Trillean.True;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( inSequence && le.Is( LexerMatcherLibrary.CwordMatcher ) )
|
||||||
|
{
|
||||||
|
return Trillean.False;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Trillean.Any;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return sequences;
|
||||||
|
}
|
||||||
|
|
||||||
public CSharpLexer()
|
public CSharpLexer()
|
||||||
{
|
{
|
||||||
AddAllMatchers(
|
AddAllMatchers(
|
||||||
|
@ -37,6 +70,10 @@ namespace Rokojori
|
||||||
LexerMatcherLibrary.BracketMatcher,
|
LexerMatcherLibrary.BracketMatcher,
|
||||||
LexerMatcherLibrary.AccessModifierMatcher,
|
LexerMatcherLibrary.AccessModifierMatcher,
|
||||||
LexerMatcherLibrary.ClassMatcher,
|
LexerMatcherLibrary.ClassMatcher,
|
||||||
|
LexerMatcherLibrary.EnumMatcher,
|
||||||
|
LexerMatcherLibrary.StructMatcher,
|
||||||
|
LexerMatcherLibrary.InterfaceMatcher,
|
||||||
|
LexerMatcherLibrary.RecordMatcher,
|
||||||
LexerMatcherLibrary.OperatorMatcher,
|
LexerMatcherLibrary.OperatorMatcher,
|
||||||
LexerMatcherLibrary.CFunctionMatcher,
|
LexerMatcherLibrary.CFunctionMatcher,
|
||||||
LexerMatcherLibrary.CwordMatcher,
|
LexerMatcherLibrary.CwordMatcher,
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
public class GDShaderLexer:Lexer
|
||||||
|
{
|
||||||
|
public static List<LexerEvent> Lex( string source )
|
||||||
|
{
|
||||||
|
var lexer = new GDShaderLexer();
|
||||||
|
var events = lexer.LexToList( source );
|
||||||
|
|
||||||
|
if ( lexer.hasError )
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
events.ForEach( ev => { ev.GrabMatch( source ); } );
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly LexerMatcher RenderSettingsFlagMatcher =
|
||||||
|
new LexerMatcher( "RenderSettingsFlag", @"\b(?:shader_type|render_mode)\b" );
|
||||||
|
|
||||||
|
public static readonly LexerMatcher TypeMatcher =
|
||||||
|
new LexerMatcher( "ShaderType", @"\b(?:spatial|canvas_item|particles|sky|fog)\b" );
|
||||||
|
|
||||||
|
public static readonly LexerMatcher UsageMatcher =
|
||||||
|
new LexerMatcher( "Usage", @"\b(?:uniform|varying)\b" );
|
||||||
|
|
||||||
|
public static readonly LexerMatcher InOutMatcher =
|
||||||
|
new LexerMatcher( "InOut", @"\b(?:inout|in|out)\b" );
|
||||||
|
// public static readonly LexerMatcher RenderModeMatcher =
|
||||||
|
// new LexerMatcher( "RenderMode", @"\b(?:spatial|canvas|particles)\b" );
|
||||||
|
|
||||||
|
public static LexerMatcher[] ignore =
|
||||||
|
[
|
||||||
|
LexerMatcherLibrary.SingleLineCommentMatcher,
|
||||||
|
LexerMatcherLibrary.MultiLineCommentMatcher,
|
||||||
|
LexerMatcherLibrary.BreakMatcher,
|
||||||
|
LexerMatcherLibrary.WhiteSpaceMatcher
|
||||||
|
];
|
||||||
|
|
||||||
|
public GDShaderLexer()
|
||||||
|
{
|
||||||
|
AddAllMatchers(
|
||||||
|
LexerMatcherLibrary.SingleLineCommentMatcher,
|
||||||
|
LexerMatcherLibrary.MultiLineCommentMatcher,
|
||||||
|
LexerMatcherLibrary.DoubleQuotedStringMatcher,
|
||||||
|
LexerMatcherLibrary.CInstructionMatcher,
|
||||||
|
RenderSettingsFlagMatcher,
|
||||||
|
TypeMatcher,
|
||||||
|
UsageMatcher,
|
||||||
|
InOutMatcher,
|
||||||
|
LexerMatcherLibrary.NumberMatcher,
|
||||||
|
LexerMatcherLibrary.BoolMatcher,
|
||||||
|
LexerMatcherLibrary.BreakMatcher,
|
||||||
|
LexerMatcherLibrary.WhiteSpaceMatcher,
|
||||||
|
LexerMatcherLibrary.LogicMatcher,
|
||||||
|
LexerMatcherLibrary.BracketMatcher,
|
||||||
|
LexerMatcherLibrary.AccessModifierMatcher,
|
||||||
|
LexerMatcherLibrary.StructMatcher,
|
||||||
|
LexerMatcherLibrary.OperatorMatcher,
|
||||||
|
LexerMatcherLibrary.CFunctionMatcher,
|
||||||
|
LexerMatcherLibrary.CwordMatcher,
|
||||||
|
LexerMatcherLibrary.AnySymbolMatcher
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
uid://dpsvkg6t4s7js
|
|
@ -0,0 +1,132 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
public class LexerList
|
||||||
|
{
|
||||||
|
protected List<LexerEvent> _events;
|
||||||
|
|
||||||
|
public List<LexerEvent> events => _events;
|
||||||
|
|
||||||
|
public LexerList Filter( System.Predicate<LexerEvent> le )
|
||||||
|
{
|
||||||
|
return Create( events.Filter( e => le( e ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public LexerList GetAll( LexerMatcher lexerMatcher )
|
||||||
|
{
|
||||||
|
return Create( events.Filter( e => e.Is( lexerMatcher ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RangeI> Seperate( int start, int end, LexerMatcher[] ignore = null )
|
||||||
|
{
|
||||||
|
return Seperate( ",", start, end, ignore );
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RangeI> Seperate( string seperator, int start, int end, LexerMatcher[] ignore = null )
|
||||||
|
{
|
||||||
|
var list = new List<RangeI>();
|
||||||
|
|
||||||
|
var currentStart = -1;
|
||||||
|
|
||||||
|
for ( int i = start; i <= end; i++ )
|
||||||
|
{
|
||||||
|
if ( _events[ i ].MatchIs( seperator ) )
|
||||||
|
{
|
||||||
|
if ( currentStart != -1 )
|
||||||
|
{
|
||||||
|
list.Add( new RangeI( currentStart, i - 1 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
currentStart = -1;
|
||||||
|
}
|
||||||
|
else if ( ignore != null && _events[ i ].IsAnyOf( ignore ) )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if ( currentStart == -1 )
|
||||||
|
{
|
||||||
|
currentStart = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( currentStart != -1 )
|
||||||
|
{
|
||||||
|
list.Add( new RangeI( currentStart, end ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ForEach( LexerMatcher lexerMatcher, System.Action<LexerEvent> action )
|
||||||
|
{
|
||||||
|
events.ForEach(
|
||||||
|
( e )=>
|
||||||
|
{
|
||||||
|
if ( ! e.Is( lexerMatcher ) )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
action( e );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LexerEvent.FindResult FindOpeningBracket( int offset, string blockBracket = "{" )
|
||||||
|
{
|
||||||
|
return LexerEvent.FindOpeningBracket( _events, offset, blockBracket );
|
||||||
|
}
|
||||||
|
|
||||||
|
public LexerEvent.FindResult ReverseFindOpeningBracket( int offset )
|
||||||
|
{
|
||||||
|
return LexerEvent.ReverseFindOpeningBracket( _events, offset );
|
||||||
|
}
|
||||||
|
|
||||||
|
public LexerEvent.FindResult ReverseFind( int offset, System.Func<LexerEvent,LexerEvent.FindResultType> evaluator )
|
||||||
|
{
|
||||||
|
return LexerEvent.Find( _events, offset, evaluator, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
public LexerEvent.FindResult Find( int offset, System.Func<LexerEvent,LexerEvent.FindResultType> evaluator )
|
||||||
|
{
|
||||||
|
return LexerEvent.Find( _events, offset, evaluator, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<List<LexerEvent>> FindSequences( System.Func<int,bool,Trillean> matcher )
|
||||||
|
{
|
||||||
|
return LexerEvent.FindSequences( _events, matcher );
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RangeI> GetBlocks()
|
||||||
|
{
|
||||||
|
return LexerEvent.GetBlocks( _events );
|
||||||
|
}
|
||||||
|
|
||||||
|
public LexerList Range( RangeI range )
|
||||||
|
{
|
||||||
|
return Range( range.min, range.max );
|
||||||
|
}
|
||||||
|
|
||||||
|
public LexerList Range( int start, int end = -1 )
|
||||||
|
{
|
||||||
|
if ( end == -1 )
|
||||||
|
{
|
||||||
|
end = _events.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Create( _events.Sub( start, end - start + 1 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LexerList Create( List<LexerEvent> lexerEvents )
|
||||||
|
{
|
||||||
|
var list = new LexerList();
|
||||||
|
list._events = lexerEvents;
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -72,8 +72,20 @@ namespace Rokojori
|
||||||
public static readonly LexerMatcher ClassMatcher =
|
public static readonly LexerMatcher ClassMatcher =
|
||||||
new LexerMatcher( "Class", @"\bclass\b" );
|
new LexerMatcher( "Class", @"\bclass\b" );
|
||||||
|
|
||||||
|
public static readonly LexerMatcher EnumMatcher =
|
||||||
|
new LexerMatcher( "Enum", @"\benum\b" );
|
||||||
|
|
||||||
|
public static readonly LexerMatcher InterfaceMatcher =
|
||||||
|
new LexerMatcher( "Interface", @"\binterface\b" );
|
||||||
|
|
||||||
|
public static readonly LexerMatcher StructMatcher =
|
||||||
|
new LexerMatcher( "Struct", @"\bstruct\b" );
|
||||||
|
|
||||||
|
public static readonly LexerMatcher RecordMatcher =
|
||||||
|
new LexerMatcher( "Record", @"\brecord\b" );
|
||||||
|
|
||||||
public static readonly LexerMatcher AccessModifierMatcher =
|
public static readonly LexerMatcher AccessModifierMatcher =
|
||||||
new LexerMatcher( "AccessModifier", @"\b(?:public|protected|private)\b" );
|
new LexerMatcher( "AccessModifier", @"\b(?:public|protected|private|const)\b" );
|
||||||
|
|
||||||
public static readonly LexerMatcher SingleLineCommentMatcher =
|
public static readonly LexerMatcher SingleLineCommentMatcher =
|
||||||
new LexerMatcher( "SingleLineComment", @"//.*" );
|
new LexerMatcher( "SingleLineComment", @"//.*" );
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
|
||||||
namespace Rokojori
|
namespace Rokojori
|
||||||
|
@ -24,5 +25,43 @@ namespace Rokojori
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string Replace( this string source, Regex regex, string replacement )
|
||||||
|
{
|
||||||
|
return regex.Replace( source, replacement );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string SubstringAfterMatching( this string source, string match )
|
||||||
|
{
|
||||||
|
var index = source.IndexOf( match );
|
||||||
|
|
||||||
|
return index == -1 ? source : source.Substring( index + match.Length );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long ToLong( this string source )
|
||||||
|
{
|
||||||
|
return long.Parse( source );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ReplaceStart( this string source, string start, string replacement = "" )
|
||||||
|
{
|
||||||
|
if ( source.StartsWith( start ) )
|
||||||
|
{
|
||||||
|
return replacement + source.Substring( start.Length );
|
||||||
|
}
|
||||||
|
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ReplaceEnd( this string source, string ending, string replacement = "" )
|
||||||
|
{
|
||||||
|
if ( source.EndsWith( ending ) )
|
||||||
|
{
|
||||||
|
return source.Substring( 0, source.Length - ending.Length ) + replacement;
|
||||||
|
}
|
||||||
|
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
[GlobalClass]
|
||||||
|
[Tool]
|
||||||
|
public partial class Date:Resource
|
||||||
|
{
|
||||||
|
public int year = 1;
|
||||||
|
public int month = 1;
|
||||||
|
public int day = 1;
|
||||||
|
|
||||||
|
public int hours = 0;
|
||||||
|
public int minutes = 0;
|
||||||
|
public int second = 0;
|
||||||
|
public float milliseconds = 0;
|
||||||
|
|
||||||
|
public int utcHoursOffset = 0;
|
||||||
|
public int utcMinutesOffset = 0;
|
||||||
|
public float utcMillisecondsOffset = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
uid://cvl5k8x7rrybt
|
|
@ -11,15 +11,20 @@ namespace Rokojori
|
||||||
public static class DateMath
|
public static class DateMath
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public static bool IsNewerThan( this DateTimeOffset a, DateTimeOffset b )
|
||||||
|
{
|
||||||
|
var difference = GetDifference( a, b );
|
||||||
|
return difference > 0;
|
||||||
|
}
|
||||||
|
|
||||||
public static float GetDifference( this DateTime a, DateTime b )
|
public static float GetDifference( this DateTimeOffset a, DateTimeOffset b )
|
||||||
{
|
{
|
||||||
return (float) ( ( a - b ).TotalSeconds );
|
return (float) ( ( a - b ).TotalSeconds );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool HasExpired( this DateTime oldTime, float duration )
|
public static bool HasExpired( this DateTimeOffset oldTime, float duration )
|
||||||
{
|
{
|
||||||
var difference = GetDifference( DateTime.Now, oldTime );
|
var difference = GetDifference( DateTimeOffset.Now, oldTime );
|
||||||
|
|
||||||
return difference >= duration;
|
return difference >= duration;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System;
|
using System;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Rokojori
|
namespace Rokojori
|
||||||
{
|
{
|
||||||
|
@ -458,6 +459,11 @@ namespace Rokojori
|
||||||
return GetLast( list );
|
return GetLast( list );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static T ReverseAt<T>( this List<T> list, int index )
|
||||||
|
{
|
||||||
|
return list[ list.Count - 1 - index ];
|
||||||
|
}
|
||||||
|
|
||||||
public static void RemoveIncreasingSortedIndices<T>( List<T> list, List<int> increasinglySortedRemovals )
|
public static void RemoveIncreasingSortedIndices<T>( List<T> list, List<int> increasinglySortedRemovals )
|
||||||
{
|
{
|
||||||
for ( var i = increasinglySortedRemovals.Count - 1; i >= 0; i-- )
|
for ( var i = increasinglySortedRemovals.Count - 1; i >= 0; i-- )
|
||||||
|
@ -658,6 +664,27 @@ namespace Rokojori
|
||||||
return mapped;
|
return mapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<List<T>> FilterAsync<T>( this List<T> list, Func<T,Task<bool>> filter )
|
||||||
|
{
|
||||||
|
var outputList = new List<T>();
|
||||||
|
|
||||||
|
var index = 0;
|
||||||
|
|
||||||
|
foreach ( var it in list )
|
||||||
|
{
|
||||||
|
var result = await filter( it );
|
||||||
|
|
||||||
|
if ( result )
|
||||||
|
{
|
||||||
|
outputList.Add( it );
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return outputList;
|
||||||
|
}
|
||||||
|
|
||||||
public static void Filter<T>( List<T> inputList, List<T> list, Func<T,int,bool> filter )
|
public static void Filter<T>( List<T> inputList, List<T> list, Func<T,int,bool> filter )
|
||||||
{
|
{
|
||||||
for ( int i = 0; i < inputList.Count; i++ )
|
for ( int i = 0; i < inputList.Count; i++ )
|
||||||
|
|
|
@ -15,6 +15,11 @@ namespace Rokojori
|
||||||
|
|
||||||
public static class TrilleanLogic
|
public static class TrilleanLogic
|
||||||
{
|
{
|
||||||
|
public static Trillean FromBool( bool value )
|
||||||
|
{
|
||||||
|
return value ? Trillean.True : Trillean.False;
|
||||||
|
}
|
||||||
|
|
||||||
public static bool ToBool( Trillean value, bool any = true )
|
public static bool ToBool( Trillean value, bool any = true )
|
||||||
{
|
{
|
||||||
if ( Trillean.Any == value )
|
if ( Trillean.Any == value )
|
||||||
|
|
120
Tools/Git/Git.cs
120
Tools/Git/Git.cs
|
@ -4,6 +4,7 @@ using Rokojori;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Rokojori.Tools
|
namespace Rokojori.Tools
|
||||||
{
|
{
|
||||||
|
@ -15,6 +16,125 @@ namespace Rokojori.Tools
|
||||||
|
|
||||||
public class Git
|
public class Git
|
||||||
{
|
{
|
||||||
|
public static async Task<System.DateTimeOffset?> GetFileChangedTime( string path )
|
||||||
|
{
|
||||||
|
var arguments = new List<string>()
|
||||||
|
{
|
||||||
|
"log -1 --format=\"%ct\" -- " + path.EscapeAsPathForCommandLine()
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await Run( arguments, RegexUtility.ParentPath( path ) );
|
||||||
|
|
||||||
|
if ( response.exitCode != 0 )
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var time = System.DateTimeOffset.FromUnixTimeSeconds( response.rawResponse.ToLong() );
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
catch( System.Exception e )
|
||||||
|
{
|
||||||
|
RJLog.Error( e );
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<bool> IsFileNewerThan( string path, System.DateTimeOffset time )
|
||||||
|
{
|
||||||
|
var _fileChangedTime = await GetFileChangedTime( path );
|
||||||
|
|
||||||
|
if ( _fileChangedTime == null )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileChangedTime = (DateTimeOffset) _fileChangedTime;
|
||||||
|
|
||||||
|
|
||||||
|
return fileChangedTime.IsNewerThan( time );
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<GitResponse> Run( List<string> arguments, string workingDirectory = null )
|
||||||
|
{
|
||||||
|
var response = new GitResponse();
|
||||||
|
|
||||||
|
var joinedArgs = arguments.Join( " ");
|
||||||
|
|
||||||
|
RJLog.Log( "GIT", joinedArgs );
|
||||||
|
|
||||||
|
var process = new Process
|
||||||
|
{
|
||||||
|
StartInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = "git",
|
||||||
|
Arguments = joinedArgs,
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
RedirectStandardError = true,
|
||||||
|
UseShellExecute = false,
|
||||||
|
CreateNoWindow = true
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( workingDirectory != null )
|
||||||
|
{
|
||||||
|
process.StartInfo.WorkingDirectory = workingDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
process.Start();
|
||||||
|
|
||||||
|
var outputResult = new List<string>();
|
||||||
|
var errorResult = new List<string>();
|
||||||
|
|
||||||
|
process.OutputDataReceived += (sender, e) =>
|
||||||
|
{
|
||||||
|
if ( e.Data == null )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RJLog.Log( e.Data );
|
||||||
|
outputResult.Add( e.Data );
|
||||||
|
};
|
||||||
|
|
||||||
|
process.ErrorDataReceived += (sender, e) =>
|
||||||
|
{
|
||||||
|
if ( e.Data == null )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RJLog.Error( e.Data );
|
||||||
|
errorResult.Add( e.Data );
|
||||||
|
};
|
||||||
|
|
||||||
|
process.BeginOutputReadLine();
|
||||||
|
process.BeginErrorReadLine();
|
||||||
|
|
||||||
|
|
||||||
|
await process.WaitForExitAsync();
|
||||||
|
|
||||||
|
|
||||||
|
response.exitCode = process.ExitCode;
|
||||||
|
|
||||||
|
if ( process.ExitCode == 0 )
|
||||||
|
{
|
||||||
|
response.rawResponse = outputResult.Join( "" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response.rawResponse = errorResult.Join( "" );
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
public static async Task<GitResponse> GetStatus( string path )
|
public static async Task<GitResponse> GetStatus( string path )
|
||||||
{
|
{
|
||||||
var process = new Process
|
var process = new Process
|
||||||
|
|
|
@ -4,6 +4,7 @@ using Rokojori;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Rokojori.Tools
|
namespace Rokojori.Tools
|
||||||
{
|
{
|
||||||
|
@ -12,7 +13,7 @@ namespace Rokojori.Tools
|
||||||
public partial class GitTest:Node
|
public partial class GitTest:Node
|
||||||
{
|
{
|
||||||
[ExportToolButton("Status")]
|
[ExportToolButton("Status")]
|
||||||
public Callable StatusButton => Callable.From(
|
public Callable statusButton => Callable.From(
|
||||||
()=>
|
()=>
|
||||||
{
|
{
|
||||||
GetStatus();
|
GetStatus();
|
||||||
|
@ -23,8 +24,38 @@ namespace Rokojori.Tools
|
||||||
{
|
{
|
||||||
var response = await Git.GetStatus( ProjectSettings.GlobalizePath( "res://") );
|
var response = await Git.GetStatus( ProjectSettings.GlobalizePath( "res://") );
|
||||||
this.LogInfo( response.exitCode, ">>", response.rawResponse );
|
this.LogInfo( response.exitCode, ">>", response.rawResponse );
|
||||||
|
}
|
||||||
|
|
||||||
|
[ExportGroup( "File")]
|
||||||
|
[Export]
|
||||||
|
public string filePath;
|
||||||
|
|
||||||
|
[ExportToolButton("Get Change Time")]
|
||||||
|
public Callable changeTimeButton => Callable.From(
|
||||||
|
()=>
|
||||||
|
{
|
||||||
|
GetTime();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
async void GetTime()
|
||||||
|
{
|
||||||
|
var optionalTime = await Git.GetFileChangedTime( ProjectSettings.GlobalizePath( filePath ) );
|
||||||
|
|
||||||
|
if ( optionalTime != null )
|
||||||
|
{
|
||||||
|
var time = (DateTimeOffset) optionalTime;
|
||||||
|
this.LogInfo( "LOCAL:", time.ToLocalTime(), " || UTC:", time,"\n>>", filePath );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.LogInfo( "Could not receive time info" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
|
@ -79,12 +79,25 @@ namespace Rokojori.Tools
|
||||||
|
|
||||||
process.OutputDataReceived += (sender, e) =>
|
process.OutputDataReceived += (sender, e) =>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
if ( e.Data == null )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
RJLog.Log( e.Data );
|
RJLog.Log( e.Data );
|
||||||
outputResult.Add( e.Data );
|
outputResult.Add( e.Data );
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
process.ErrorDataReceived += (sender, e) =>
|
process.ErrorDataReceived += (sender, e) =>
|
||||||
{
|
{
|
||||||
|
if ( e.Data == null )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
RJLog.Error( e.Data );
|
RJLog.Error( e.Data );
|
||||||
errorResult.Add( e.Data );
|
errorResult.Add( e.Data );
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Rokojori.DocGenerator
|
namespace Rokojori.DocGenerator
|
||||||
{
|
{
|
||||||
|
@ -40,23 +41,32 @@ namespace Rokojori.DocGenerator
|
||||||
return "CSharp.svg";
|
return "CSharp.svg";
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassDocInfo Create( string filePath, Type type, List<string> icons )
|
public ClassDocInfo Create( string filePath, Type classType, string definitionType, List<string> icons )
|
||||||
{
|
{
|
||||||
var data = filePath == null ? "" : FilesSync.LoadUTF8( filePath );
|
var data = filePath == null ? "" : FilesSync.LoadUTF8( filePath );
|
||||||
var comments = new DocComments();
|
var comments = new DocComments();
|
||||||
comments.Grab( data );
|
comments.Grab( data );
|
||||||
|
|
||||||
RJLog.Log( type.Name, "Comments:", comments.entries.Count );
|
var typeName = GetDocsType.Of( classType );
|
||||||
|
var baseTypeName = classType.BaseType;
|
||||||
|
var typeNameSpace = classType.Namespace;
|
||||||
|
|
||||||
info.name = type.Name;
|
RJLog.Log( typeName, "Comments:", comments.entries.Count );
|
||||||
info.csNameSpace = type.Namespace;
|
|
||||||
|
|
||||||
info.doc = comments.FindDoc( "class", type.Name );
|
|
||||||
|
|
||||||
info.generics = Lists.Map( type.GenericTypeArguments, t => t + "" );
|
info.name = typeName;
|
||||||
|
info.csNameSpace = typeNameSpace;
|
||||||
|
info.definitionType = definitionType;
|
||||||
|
info.sourcePath = filePath.SubstringAfterMatching( "addons/rokojori_action_library/");
|
||||||
|
|
||||||
|
info.doc = comments.FindDoc( "class", typeName );
|
||||||
|
|
||||||
|
var genericArguments = classType.GetGenericArguments().ToList();
|
||||||
|
info.generics = genericArguments.Map( t => t.Name );
|
||||||
|
info.interfaces = classType.GetInterfaces().ToList().Map( i => GetDocsType.Of( i ) );
|
||||||
|
|
||||||
var allBindings = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly;
|
var allBindings = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly;
|
||||||
var fields = Lists.ToList( type.GetFields( allBindings ) );
|
var fields = Lists.ToList( classType.GetFields( allBindings ) );
|
||||||
fields = Lists.Filter( fields, f => ! f.IsPrivate );
|
fields = Lists.Filter( fields, f => ! f.IsPrivate );
|
||||||
|
|
||||||
var godotTypes = new List<string>()
|
var godotTypes = new List<string>()
|
||||||
|
@ -67,7 +77,7 @@ namespace Rokojori.DocGenerator
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var it = type.BaseType;
|
var it = baseTypeName;
|
||||||
|
|
||||||
while ( it != null )
|
while ( it != null )
|
||||||
{
|
{
|
||||||
|
@ -86,7 +96,7 @@ namespace Rokojori.DocGenerator
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
info.extendingClasses.Add( it.Name );
|
info.extendingClasses.Add( GetDocsType.Of( it ) );
|
||||||
it = it.BaseType;
|
it = it.BaseType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,14 +105,59 @@ namespace Rokojori.DocGenerator
|
||||||
|
|
||||||
info.icon = GetIcon( data, info.name, info.extendingClasses, icons );
|
info.icon = GetIcon( data, info.name, info.extendingClasses, icons );
|
||||||
|
|
||||||
|
var constructors = Lists.ToList( classType.GetConstructors( allBindings ) );
|
||||||
|
constructors = Lists.Filter( constructors, m => ! m.IsPrivate );
|
||||||
|
|
||||||
|
constructors.ForEach(
|
||||||
|
( con ) =>
|
||||||
|
{
|
||||||
|
var memberInfo = MemberInfo.CreateConstructor();
|
||||||
|
|
||||||
|
memberInfo.name = typeName;
|
||||||
|
memberInfo.dataType = typeName;
|
||||||
|
|
||||||
|
memberInfo.csNameSpace = typeNameSpace;
|
||||||
|
// memberInfo.generics = info.generics;
|
||||||
|
// memberInfo.doc = comments.FindDoc( "constructor", con.Name );
|
||||||
|
|
||||||
|
memberInfo.modifiers.Add( con.IsPublic ? "public" : "protected" );
|
||||||
|
|
||||||
|
var parameters = Lists.ToList( con.GetParameters() );
|
||||||
|
parameters.ForEach(
|
||||||
|
( p )=>
|
||||||
|
{
|
||||||
|
var parameterType = new ParameterType();
|
||||||
|
parameterType.name = p.Name;
|
||||||
|
parameterType.type = GetDocsType.Of( p.ParameterType );
|
||||||
|
parameterType.csNameSpace = p.ParameterType.Namespace;
|
||||||
|
parameterType.generics = Lists.Map( p.ParameterType.GetGenericArguments(), t => t + "" );
|
||||||
|
|
||||||
|
memberInfo.parameters.Add( parameterType );
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
info.memberInfos.Add( memberInfo );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
fields.ForEach(
|
fields.ForEach(
|
||||||
( f )=>
|
( f )=>
|
||||||
{
|
{
|
||||||
|
if ( f.Name == "value__" )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
var memberInfo = MemberInfo.CreateField();
|
var memberInfo = MemberInfo.CreateField();
|
||||||
|
|
||||||
memberInfo.name = f.Name;
|
memberInfo.name = f.Name;
|
||||||
|
|
||||||
|
|
||||||
memberInfo.csNameSpace = f.FieldType.Namespace;
|
memberInfo.csNameSpace = f.FieldType.Namespace;
|
||||||
memberInfo.dataType = f.FieldType.Name;
|
memberInfo.dataType = GetDocsType.Of( f.FieldType );
|
||||||
memberInfo.generics = Lists.Map( f.FieldType.GetGenericArguments(), t => t + "" );
|
memberInfo.generics = Lists.Map( f.FieldType.GetGenericArguments(), t => t + "" );
|
||||||
memberInfo.doc = comments.FindDoc( "field", f.Name );
|
memberInfo.doc = comments.FindDoc( "field", f.Name );
|
||||||
|
|
||||||
|
@ -119,7 +174,7 @@ namespace Rokojori.DocGenerator
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
var methods = Lists.ToList( type.GetMethods( allBindings ) );
|
var methods = Lists.ToList( classType.GetMethods( allBindings ) );
|
||||||
methods = Lists.Filter( methods, m => ! m.IsPrivate );
|
methods = Lists.Filter( methods, m => ! m.IsPrivate );
|
||||||
|
|
||||||
var godotInternalMethods = new List<string>()
|
var godotInternalMethods = new List<string>()
|
||||||
|
@ -132,7 +187,8 @@ namespace Rokojori.DocGenerator
|
||||||
"GetGodotPropertyList",
|
"GetGodotPropertyList",
|
||||||
"GetGodotPropertyDefaultValues",
|
"GetGodotPropertyDefaultValues",
|
||||||
"SaveGodotObjectData",
|
"SaveGodotObjectData",
|
||||||
"RestoreGodotObjectData"
|
"RestoreGodotObjectData",
|
||||||
|
"InvokeGodotClassStaticMethod"
|
||||||
};
|
};
|
||||||
|
|
||||||
methods.ForEach(
|
methods.ForEach(
|
||||||
|
@ -145,8 +201,10 @@ namespace Rokojori.DocGenerator
|
||||||
|
|
||||||
var memberInfo = MemberInfo.CreateMethod();
|
var memberInfo = MemberInfo.CreateMethod();
|
||||||
|
|
||||||
|
memberInfo.isAccessor = GetDocsType.isAccessorMethod( m );
|
||||||
memberInfo.name = m.Name;
|
memberInfo.name = m.Name;
|
||||||
memberInfo.dataType = m.ReturnType.Name;
|
memberInfo.dataType = GetDocsType.Of( m.ReturnType );
|
||||||
|
|
||||||
memberInfo.csNameSpace = m.ReturnType.Namespace;
|
memberInfo.csNameSpace = m.ReturnType.Namespace;
|
||||||
memberInfo.generics = Lists.Map( m.GetGenericArguments(), t => t + "" );
|
memberInfo.generics = Lists.Map( m.GetGenericArguments(), t => t + "" );
|
||||||
memberInfo.doc = comments.FindDoc( "method", m.Name );
|
memberInfo.doc = comments.FindDoc( "method", m.Name );
|
||||||
|
@ -164,9 +222,9 @@ namespace Rokojori.DocGenerator
|
||||||
{
|
{
|
||||||
var parameterType = new ParameterType();
|
var parameterType = new ParameterType();
|
||||||
parameterType.name = p.Name;
|
parameterType.name = p.Name;
|
||||||
parameterType.type = p.ParameterType.Name;
|
parameterType.type = GetDocsType.Of( p.ParameterType );
|
||||||
parameterType.csNameSpace = p.ParameterType.Namespace;
|
parameterType.csNameSpace = p.ParameterType.Namespace;
|
||||||
parameterType.generics = Lists.Map( p.ParameterType.GenericTypeArguments, t => t + "" );
|
parameterType.generics = Lists.Map( p.ParameterType.GetGenericArguments(), t => t + "" );
|
||||||
|
|
||||||
memberInfo.parameters.Add( parameterType );
|
memberInfo.parameters.Add( parameterType );
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
uid://ddfpf66np8qpk
|
|
@ -9,7 +9,8 @@ namespace Rokojori.DocGenerator
|
||||||
public string name;
|
public string name;
|
||||||
public string type;
|
public string type;
|
||||||
public string csNameSpace;
|
public string csNameSpace;
|
||||||
public List<string> generics;
|
public List<string> modifiers = [];
|
||||||
|
public List<string> generics = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MemberInfo
|
public class MemberInfo
|
||||||
|
@ -19,6 +20,11 @@ namespace Rokojori.DocGenerator
|
||||||
public string name;
|
public string name;
|
||||||
public string dataType;
|
public string dataType;
|
||||||
public string csNameSpace;
|
public string csNameSpace;
|
||||||
|
public string path;
|
||||||
|
public bool isAccessor;
|
||||||
|
public List<string> attributes = new List<string>();
|
||||||
|
public int lineIndex;
|
||||||
|
public int lineOffset;
|
||||||
|
|
||||||
public List<string> modifiers = new List<string>();
|
public List<string> modifiers = new List<string>();
|
||||||
public List<string> generics;
|
public List<string> generics;
|
||||||
|
@ -26,6 +32,9 @@ namespace Rokojori.DocGenerator
|
||||||
|
|
||||||
public static readonly string Field = "Field";
|
public static readonly string Field = "Field";
|
||||||
public static readonly string Method = "Method";
|
public static readonly string Method = "Method";
|
||||||
|
public static readonly string Constructor = "Constructor";
|
||||||
|
public static readonly string Uniform = "Uniform";
|
||||||
|
public static readonly string Varying = "Varying";
|
||||||
|
|
||||||
public static MemberInfo Create( string memberType )
|
public static MemberInfo Create( string memberType )
|
||||||
{
|
{
|
||||||
|
@ -43,6 +52,21 @@ namespace Rokojori.DocGenerator
|
||||||
{
|
{
|
||||||
return MemberInfo.Create( MemberInfo.Method );
|
return MemberInfo.Create( MemberInfo.Method );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static MemberInfo CreateConstructor()
|
||||||
|
{
|
||||||
|
return MemberInfo.Create( MemberInfo.Constructor );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MemberInfo CreateUniform()
|
||||||
|
{
|
||||||
|
return MemberInfo.Create( MemberInfo.Uniform );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MemberInfo CreateVarying()
|
||||||
|
{
|
||||||
|
return MemberInfo.Create( MemberInfo.Varying );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ClassDocInfo
|
public class ClassDocInfo
|
||||||
|
@ -51,8 +75,14 @@ namespace Rokojori.DocGenerator
|
||||||
public string name ="";
|
public string name ="";
|
||||||
public string doc;
|
public string doc;
|
||||||
public string icon;
|
public string icon;
|
||||||
|
public string sourcePath;
|
||||||
|
public string definitionType;
|
||||||
|
|
||||||
public List<string> generics = new List<string>();
|
public List<string> generics = new List<string>();
|
||||||
|
public List<string> interfaces = new List<string>();
|
||||||
public List<string> extendingClasses = new List<string>();
|
public List<string> extendingClasses = new List<string>();
|
||||||
public List<MemberInfo> memberInfos = new List<MemberInfo>();
|
public List<MemberInfo> memberInfos = new List<MemberInfo>();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
uid://cogfo5xxdtqo5
|
|
@ -2,6 +2,7 @@
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Rokojori.DocGenerator
|
namespace Rokojori.DocGenerator
|
||||||
{
|
{
|
||||||
|
@ -29,6 +30,21 @@ namespace Rokojori.DocGenerator
|
||||||
[Export]
|
[Export]
|
||||||
public string outputPath ="res://addons/rokojori_action_library/Tools/docs/output";
|
public string outputPath ="res://addons/rokojori_action_library/Tools/docs/output";
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public bool clearDirectory = false;
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public bool c_sharp = true;
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public bool shaders = true;
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public bool processOnlyNewerThanCheckTime = true;
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public float hoursCheckTime;
|
||||||
|
|
||||||
[ExportToolButton( "Create")]
|
[ExportToolButton( "Create")]
|
||||||
public Callable createButton => Callable.From( ()=>{ Generate(); } );
|
public Callable createButton => Callable.From( ()=>{ Generate(); } );
|
||||||
|
|
||||||
|
@ -47,11 +63,21 @@ namespace Rokojori.DocGenerator
|
||||||
|
|
||||||
void Generate()
|
void Generate()
|
||||||
{
|
{
|
||||||
|
|
||||||
var absoluteLibraryPath = ProjectSettings.GlobalizePath( "res://addons/rokojori_action_library/Runtime" );
|
var absoluteLibraryPath = ProjectSettings.GlobalizePath( "res://addons/rokojori_action_library/Runtime" );
|
||||||
var absoluteIconPath = ProjectSettings.GlobalizePath( "res://addons/rokojori_action_library/Icons" );
|
var absoluteIconPath = ProjectSettings.GlobalizePath( "res://addons/rokojori_action_library/Icons" );
|
||||||
var absoluteOutputPath = ProjectSettings.GlobalizePath( outputPath );
|
var absoluteOutputPath = ProjectSettings.GlobalizePath( outputPath );
|
||||||
|
|
||||||
|
if ( clearDirectory )
|
||||||
|
{
|
||||||
|
FilesSync.Delete( absoluteOutputPath );
|
||||||
|
FilesSync.EnsureDirectoryExists( absoluteOutputPath );
|
||||||
|
}
|
||||||
|
|
||||||
var generator = new DocGenerator();
|
var generator = new DocGenerator();
|
||||||
|
generator.shaders = shaders;
|
||||||
|
generator.cSharp = c_sharp;
|
||||||
|
|
||||||
var icons = Lists.Map( FilesSync.GetFiles( absoluteIconPath, ( fp => fp.fileExtension == ".svg" ) ), fp => fp.fullFileName );
|
var icons = Lists.Map( FilesSync.GetFiles( absoluteIconPath, ( fp => fp.fileExtension == ".svg" ) ), fp => fp.fullFileName );
|
||||||
generator.Generate( absoluteLibraryPath, absoluteOutputPath, icons );
|
generator.Generate( absoluteLibraryPath, absoluteOutputPath, icons );
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
uid://cwvi31krqm3ik
|
|
@ -4,40 +4,81 @@ using Godot;
|
||||||
using Rokojori;
|
using Rokojori;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System;
|
using System;
|
||||||
|
using Microsoft.VisualBasic;
|
||||||
|
using Rokojori.Tools;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Rokojori.DocGenerator
|
namespace Rokojori.DocGenerator
|
||||||
{
|
{
|
||||||
public class ClassTypeEntry
|
public class ClassTypeEntry
|
||||||
{
|
{
|
||||||
public Type type;
|
public Type type;
|
||||||
|
public string definitionType;
|
||||||
public string path;
|
public string path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ShaderTypeEntry
|
||||||
|
{
|
||||||
|
public string path;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public class DocGenerator
|
public class DocGenerator
|
||||||
{
|
{
|
||||||
string path = "";
|
string path = "";
|
||||||
string outputPath = "";
|
string outputPath = "";
|
||||||
List<string> icons = new List<string>();
|
List<string> icons = new List<string>();
|
||||||
|
|
||||||
|
public bool checkChangeTime = false;
|
||||||
|
public DateTimeOffset changeTime;
|
||||||
|
|
||||||
public List<FilePath> classFiles = new List<FilePath>();
|
public List<FilePath> classFiles = new List<FilePath>();
|
||||||
public List<ClassTypeEntry> classTypes = new List<ClassTypeEntry>();
|
public List<ClassTypeEntry> classTypes = new List<ClassTypeEntry>();
|
||||||
|
public List<ShaderTypeEntry> shaderTypes = new List<ShaderTypeEntry>();
|
||||||
|
|
||||||
|
public bool shaders = true;
|
||||||
|
public bool cSharp = true;
|
||||||
|
|
||||||
|
|
||||||
public void Generate( string path, string outputPath, List<string> icons )
|
public async void Generate( string path, string outputPath, List<string> icons )
|
||||||
{
|
{
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.outputPath = outputPath;
|
this.outputPath = outputPath;
|
||||||
this.icons = icons;
|
this.icons = icons;
|
||||||
|
|
||||||
GetFiles();
|
await GetFiles();
|
||||||
CreateTypesFromFiles();
|
CreateTypesFromFiles();
|
||||||
IncludeDefaultTypes();
|
// IncludeDefaultTypes();
|
||||||
GenerateDocsFromTypes();
|
GenerateDocsFromTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetFiles()
|
async Task GetFiles()
|
||||||
{
|
{
|
||||||
classFiles = FilesSync.GetFiles( path, f => f.fileExtension == ".cs", true );
|
classFiles = FilesSync.GetFiles( path,
|
||||||
|
f =>
|
||||||
|
{
|
||||||
|
var isCS = f.fileExtension == ".cs";
|
||||||
|
var isShader = f.fileExtension == ".gdshader" || f.fileExtension == ".gdshaderinc";
|
||||||
|
|
||||||
|
if ( isShader )
|
||||||
|
{
|
||||||
|
RJLog.Log( "SHADER: FILE", f.absolutePath );
|
||||||
|
}
|
||||||
|
|
||||||
|
return ( cSharp && isCS ) || ( shaders && isShader );
|
||||||
|
},
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( checkChangeTime )
|
||||||
|
{
|
||||||
|
classFiles = await classFiles.FilterAsync(
|
||||||
|
async ( f ) =>
|
||||||
|
{
|
||||||
|
return await Git.IsFileNewerThan( f.absolutePath, changeTime );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IncludeDefaultTypes()
|
void IncludeDefaultTypes()
|
||||||
|
@ -74,6 +115,42 @@ namespace Rokojori.DocGenerator
|
||||||
( cf )=>
|
( cf )=>
|
||||||
{
|
{
|
||||||
var name = cf.fileName;
|
var name = cf.fileName;
|
||||||
|
|
||||||
|
if ( cf.fileExtension == ".cs" )
|
||||||
|
{
|
||||||
|
var fileContent = FilesSync.LoadUTF8( cf.fullPath );
|
||||||
|
var definitions = CSharpLexer.GetAllObjectDefinitions( fileContent );
|
||||||
|
|
||||||
|
RJLog.Log( cf.fileName, ">>", definitions.Join( "," ) );
|
||||||
|
|
||||||
|
for ( int i = 0; i < definitions.Count; i++ )
|
||||||
|
{
|
||||||
|
var sequence = definitions[ i ];
|
||||||
|
var definitionType = sequence[ 0 ];
|
||||||
|
var definitionName = sequence[ 1 ];
|
||||||
|
|
||||||
|
RJLog.Log( "Adding definition:", definitionName.match );
|
||||||
|
AddCSharpsClassType( cf, definitionName.match, definitionType.match, namespaceLabel, assembly );
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( cf.fileExtension == ".gdshader" || cf.fileExtension == ".gdshaderinc" )
|
||||||
|
{
|
||||||
|
var shaderType = new ShaderTypeEntry();
|
||||||
|
shaderType.path = cf.absolutePath;
|
||||||
|
shaderTypes.Add( shaderType );
|
||||||
|
|
||||||
|
RJLog.Log( "SHADER: Adding definition:", cf.absolutePath );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddCSharpsClassType( FilePath cf, string name, string definitionType, string namespaceLabel, System.Reflection.Assembly assembly )
|
||||||
|
{
|
||||||
|
// var name = cf.fileName;
|
||||||
var type = ReflectionHelper.GetTypeByName( namespaceLabel + "." + name );
|
var type = ReflectionHelper.GetTypeByName( namespaceLabel + "." + name );
|
||||||
|
|
||||||
if ( type == null )
|
if ( type == null )
|
||||||
|
@ -81,31 +158,61 @@ namespace Rokojori.DocGenerator
|
||||||
type = ReflectionHelper.GetTypeByNameFromAssembly( name, assembly );
|
type = ReflectionHelper.GetTypeByNameFromAssembly( name, assembly );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( type != null )
|
if ( type == null )
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var entry = new ClassTypeEntry();
|
var entry = new ClassTypeEntry();
|
||||||
entry.type = type;
|
entry.type = type;
|
||||||
entry.path = cf.fullPath;
|
entry.path = cf.fullPath;
|
||||||
|
entry.definitionType = definitionType;
|
||||||
|
|
||||||
classTypes.Add( entry);
|
classTypes.Add( entry);
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GenerateDocsFromTypes()
|
void GenerateDocsFromTypes()
|
||||||
{
|
{
|
||||||
|
FilesSync.EnsureDirectoryExists( outputPath );
|
||||||
|
|
||||||
classTypes.ForEach(
|
classTypes.ForEach(
|
||||||
( c )=>
|
( c )=>
|
||||||
{
|
{
|
||||||
var cdg = new ClassDocGenerator();
|
var cdg = new ClassDocGenerator();
|
||||||
var cinfo = cdg.Create( c.path, c.type, icons );
|
var cinfo = cdg.Create( c.path, c.type, c.definitionType, icons );
|
||||||
|
var outputPathName = cinfo.name.Replace( "`", "-" ).Replace( "<", "-" ).Replace( ">", "-" );
|
||||||
|
|
||||||
var outputPath = FilePath.Join( this.outputPath, cinfo.name + ".json" );
|
var outputPath = FilePath.Join( this.outputPath, outputPathName + ".json" );
|
||||||
FilesSync.SaveJSON( outputPath, cinfo );
|
FilesSync.SaveJSON( outputPath, cinfo );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
RJLog.Log( "SHADER: shaderTypes", shaderTypes.Count );
|
||||||
|
|
||||||
|
shaderTypes.ForEach(
|
||||||
|
( s ) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RJLog.Log( "SHADER: DOC", s.path );
|
||||||
|
var sdg = new ShaderDocGenerator();
|
||||||
|
var cinfo = sdg.Create( s.path );
|
||||||
|
var prefix = cinfo.definitionType + "." ;
|
||||||
|
var outputPathName = prefix + cinfo.name;
|
||||||
|
|
||||||
|
var outputPath = FilePath.Join( this.outputPath, outputPathName + ".json" );
|
||||||
|
RJLog.Log( "SHADER: SAVING", s.path, ">>", outputPathName );
|
||||||
|
FilesSync.SaveJSON( outputPath, cinfo );
|
||||||
|
}
|
||||||
|
catch ( System.Exception e )
|
||||||
|
{
|
||||||
|
RJLog.Error( s.path );
|
||||||
|
RJLog.Error( e );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
uid://cgosf8d75v54v
|
|
@ -0,0 +1,57 @@
|
||||||
|
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
using Rokojori;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Linq;
|
||||||
|
namespace Rokojori.DocGenerator
|
||||||
|
{
|
||||||
|
public static class GetDocsType
|
||||||
|
{
|
||||||
|
public static bool isAccessorMethod( System.Reflection.MethodInfo m )
|
||||||
|
{
|
||||||
|
var isSetAccessor = m.DeclaringType.GetProperties().Any( prop => prop.GetSetMethod() == m );
|
||||||
|
|
||||||
|
if ( isSetAccessor )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var isGetAccessor = m.DeclaringType.GetProperties().Any( prop => prop.GetGetMethod() == m );
|
||||||
|
|
||||||
|
return isGetAccessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string,string> replacements = new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ "Int32", "int" },
|
||||||
|
{ "Single", "float" },
|
||||||
|
{ "Boolean", "bool" }
|
||||||
|
};
|
||||||
|
public static string Of( Type type )
|
||||||
|
{
|
||||||
|
var docType = type.Name;
|
||||||
|
|
||||||
|
if ( replacements.ContainsKey( docType ) )
|
||||||
|
{
|
||||||
|
docType = replacements[ docType ];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( docType.Contains( "Action" ) && type.Namespace.Contains( "System" ) )
|
||||||
|
{
|
||||||
|
docType = docType.Replace( "Action", "System.Action" );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( docType.Contains( "`" ) )
|
||||||
|
{
|
||||||
|
var generics = Lists.Map( type.GetGenericArguments(), t => Of( t ) );
|
||||||
|
var replacement = "<" + generics.Join( "," ) + ">";
|
||||||
|
docType = docType.Replace( new Regex( "`.*$" ), replacement );
|
||||||
|
}
|
||||||
|
|
||||||
|
return docType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
uid://dt5vmpng5n2qb
|
|
@ -0,0 +1,262 @@
|
||||||
|
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
using Rokojori;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Rokojori.DocGenerator
|
||||||
|
{
|
||||||
|
public class ShaderDocGenerator
|
||||||
|
{
|
||||||
|
public static readonly string GDShaderExtension = ".gdshader";
|
||||||
|
public static readonly string GDShaderIncludeExtension = ".gdshaderinc";
|
||||||
|
|
||||||
|
ClassDocInfo info = new ClassDocInfo();
|
||||||
|
|
||||||
|
List<LexerEvent> _lexerEvents;
|
||||||
|
LexerList tokens;
|
||||||
|
|
||||||
|
public ClassDocInfo Create( string filePath )
|
||||||
|
{
|
||||||
|
var fileContent = FilesSync.LoadUTF8( filePath );
|
||||||
|
_lexerEvents = GDShaderLexer.Lex( fileContent );
|
||||||
|
tokens = LexerList.Create( _lexerEvents );
|
||||||
|
|
||||||
|
if ( filePath.EndsWith( GDShaderIncludeExtension ) )
|
||||||
|
{
|
||||||
|
info.definitionType = "GDShaderInclude";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info.definitionType = "GDShader";
|
||||||
|
}
|
||||||
|
|
||||||
|
info.name = RegexUtility.TrimToLastPathFragment( filePath ).ReplaceEnd( GDShaderIncludeExtension, "" ).ReplaceEnd( GDShaderExtension, "" );
|
||||||
|
|
||||||
|
GetIncludes();
|
||||||
|
GetUniforms();
|
||||||
|
GetBlocks();
|
||||||
|
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetIncludes()
|
||||||
|
{
|
||||||
|
var includePrexix = "#include ";
|
||||||
|
|
||||||
|
RJLog.Log( "Processing includes:", tokens.GetAll( LexerMatcherLibrary.CInstructionMatcher ).events.Count );
|
||||||
|
|
||||||
|
tokens.ForEach( LexerMatcherLibrary.CInstructionMatcher,
|
||||||
|
( t )=>
|
||||||
|
{
|
||||||
|
|
||||||
|
var match = t.match;
|
||||||
|
|
||||||
|
RJLog.Log( "Processing include:", match );
|
||||||
|
|
||||||
|
if ( ! match.StartsWith( includePrexix ) )
|
||||||
|
{
|
||||||
|
RJLog.Log( "Processing include:", match );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var path = match.ReplaceStart( includePrexix, "" );
|
||||||
|
path = path.Substring( 1, path.Length - 2 );
|
||||||
|
var name = RegexUtility.TrimToLastPathFragment( path ).TrimSuffix( ".gdshaderinc");
|
||||||
|
|
||||||
|
|
||||||
|
var memberInfo = MemberInfo.Create( "ShaderInclude" );
|
||||||
|
memberInfo.name = name;
|
||||||
|
memberInfo.path = path;
|
||||||
|
memberInfo.dataType = "GDShaderInclude";
|
||||||
|
|
||||||
|
info.memberInfos.Add( memberInfo );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetUniforms()
|
||||||
|
{
|
||||||
|
var sequences = tokens.FindSequences(
|
||||||
|
( int tokenIndex, bool inSequence ) =>
|
||||||
|
{
|
||||||
|
var token = tokens.events[ tokenIndex ];
|
||||||
|
|
||||||
|
if ( ! inSequence )
|
||||||
|
{
|
||||||
|
if ( token.Is( GDShaderLexer.UsageMatcher ) )
|
||||||
|
{
|
||||||
|
return Trillean.True;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Trillean.Any;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return TrilleanLogic.FromBool( ! token.Is( LexerMatcherLibrary.OperatorMatcher, ";" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// RJLog.Log( "Uniforms/Varyings:", sequences.Count );
|
||||||
|
|
||||||
|
sequences.ForEach(
|
||||||
|
( s )=>
|
||||||
|
{
|
||||||
|
if ( s == null )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var filtered = s.Filter( s => ! s.IsAnyOf( GDShaderLexer.ignore ) );
|
||||||
|
|
||||||
|
// RJLog.Log( "'" + filtered.Map( s => s.match ).Join( "', '") + "'" );
|
||||||
|
|
||||||
|
if ( filtered.Count < 3 )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var first = filtered[ 0 ];
|
||||||
|
var isUniform = first.MatchIs( "uniform" );
|
||||||
|
var memberInfo = isUniform ? MemberInfo.CreateUniform() : MemberInfo.CreateVarying();
|
||||||
|
|
||||||
|
memberInfo.dataType = filtered[ 1 ].match;
|
||||||
|
memberInfo.name = filtered[ 2 ].match;
|
||||||
|
|
||||||
|
// LINE INFO
|
||||||
|
|
||||||
|
info.memberInfos.Add( memberInfo );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetBlocks()
|
||||||
|
{
|
||||||
|
var blocks = tokens.GetBlocks();
|
||||||
|
|
||||||
|
if ( blocks == null )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RJLog.Log( "Num blocks:", blocks.Count );
|
||||||
|
blocks.ForEach( b => ProcessBlock( b ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessBlock( RangeI blockRange )
|
||||||
|
{
|
||||||
|
var blockStart = blockRange.min;
|
||||||
|
|
||||||
|
var firstTokenBeforeResult = tokens.ReverseFind( blockStart - 1,
|
||||||
|
( t ) =>
|
||||||
|
{
|
||||||
|
// RJLog.Log( "Token type:", t );
|
||||||
|
|
||||||
|
if ( t.IsAnyOf( GDShaderLexer.ignore ) )
|
||||||
|
{
|
||||||
|
return LexerEvent.FindResultType.KeepSearching;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !
|
||||||
|
(
|
||||||
|
t.Is( LexerMatcherLibrary.BracketMatcher, ")" ) ||
|
||||||
|
t.Is( LexerMatcherLibrary.CwordMatcher )
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// RJLog.Log( "Invalid token type:", t );
|
||||||
|
return LexerEvent.FindResultType.Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LexerEvent.FindResultType.Found;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( ! firstTokenBeforeResult.found )
|
||||||
|
{
|
||||||
|
// RJLog.Log( "No first token before block found!" );
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var firstToken = _lexerEvents[ firstTokenBeforeResult.index ];
|
||||||
|
var isMethod = firstToken.Is( LexerMatcherLibrary.BracketMatcher, ")" );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if ( isMethod )
|
||||||
|
{
|
||||||
|
var closeBracketResult = firstTokenBeforeResult;
|
||||||
|
var openBracketResult = tokens.ReverseFindOpeningBracket( closeBracketResult.index );
|
||||||
|
|
||||||
|
if ( ! openBracketResult.found )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var nameToken = tokens.ReverseFind( openBracketResult.index,
|
||||||
|
( t ) =>
|
||||||
|
{
|
||||||
|
return t.Is( LexerMatcherLibrary.CFunctionMatcher ) ? LexerEvent.FindResultType.Found : LexerEvent.FindResultType.KeepSearching;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( ! nameToken.found )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var typeToken = tokens.ReverseFind( nameToken.index - 1,
|
||||||
|
( t ) =>
|
||||||
|
{
|
||||||
|
return t.Is( LexerMatcherLibrary.CwordMatcher ) ? LexerEvent.FindResultType.Found : LexerEvent.FindResultType.KeepSearching;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
var memberInfo = MemberInfo.CreateMethod();
|
||||||
|
memberInfo.name = tokens.events[ nameToken.index ].match;
|
||||||
|
memberInfo.dataType = tokens.events[ typeToken.index ].match;
|
||||||
|
|
||||||
|
var parameters = tokens.Seperate( openBracketResult.index + 1, closeBracketResult.index - 1, GDShaderLexer.ignore );
|
||||||
|
|
||||||
|
parameters.ForEach(
|
||||||
|
( p )=>
|
||||||
|
{
|
||||||
|
var pValues = tokens.Range( p ).Filter( t => ! t.IsAnyOf( GDShaderLexer.ignore ) );
|
||||||
|
|
||||||
|
var parameterType = new ParameterType();
|
||||||
|
parameterType.name = pValues.events.ReverseAt( 0 ).match;
|
||||||
|
parameterType.type = pValues.events.ReverseAt( 1 ).match;
|
||||||
|
|
||||||
|
if ( pValues.events.Count > 2 )
|
||||||
|
{
|
||||||
|
parameterType.modifiers.Add( pValues.events.ReverseAt( 2 ).match );
|
||||||
|
}
|
||||||
|
|
||||||
|
memberInfo.parameters.Add( parameterType );
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
info.memberInfos.Add( memberInfo );
|
||||||
|
|
||||||
|
// RJLog.Log( "Method found!", memberInfo.memberType, memberInfo.name );
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// RJLog.Log( "No method found!", firstToken );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
uid://btne55wgtelrw
|
Loading…
Reference in New Issue