Docs Generator + Biquad/Smoother
This commit is contained in:
parent
c3d7848d30
commit
375a05336a
|
@ -169,8 +169,8 @@ namespace Rokojori
|
|||
}
|
||||
|
||||
float reloadDuration = 2;
|
||||
DateTime lastUpdateTime = DateTime.Now;
|
||||
DateTime lastDisposalTime = DateTime.Now;
|
||||
DateTimeOffset lastUpdateTime = DateTime.Now;
|
||||
DateTimeOffset lastDisposalTime = DateTime.Now;
|
||||
|
||||
public void SaveCache( string relativeCachePath, object data )
|
||||
{
|
||||
|
|
|
@ -170,9 +170,9 @@ namespace Rokojori
|
|||
var smoothStrength = rawSmooth * 250f;
|
||||
|
||||
var current = TransformData.From( targets[ i ], shakeEffect.globalPosition, shakeEffect.globalRotation );
|
||||
combined.position = Smoother.SmoothTimeInvariant( current.position, combined.position, delta, smoothStrength );
|
||||
combined.rotation = Smoother.SmoothTimeInvariant( current.rotation, combined.rotation, delta, smoothStrength );
|
||||
combined.scale = Smoother.SmoothTimeInvariant( current.scale, combined.scale, delta, smoothStrength );
|
||||
combined.position = Smoother.SmoothTimeVariant( current.position, combined.position, delta, smoothStrength );
|
||||
combined.rotation = Smoother.SmoothTimeVariant( current.rotation, combined.rotation, delta, smoothStrength );
|
||||
combined.scale = Smoother.SmoothTimeVariant( current.scale, combined.scale, delta, smoothStrength );
|
||||
}
|
||||
|
||||
combined.Set( targets[ i ], shakeEffect.globalPosition, shakeEffect.globalRotation );
|
||||
|
|
|
@ -118,6 +118,14 @@ namespace Rokojori
|
|||
return rp;
|
||||
}
|
||||
|
||||
public string absolutePath
|
||||
{
|
||||
get
|
||||
{
|
||||
return fullPath;
|
||||
}
|
||||
}
|
||||
|
||||
public string absoluteParentPath
|
||||
{
|
||||
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
|
||||
{
|
||||
[System.Serializable]
|
||||
public class Range
|
||||
{
|
||||
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;
|
||||
|
||||
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 );
|
||||
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 );
|
||||
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 );
|
||||
return Math3D.Lerp( nextValue, value, lerpAmount );
|
||||
|
|
|
@ -19,12 +19,12 @@ namespace Rokojori
|
|||
public int seed = 1984;
|
||||
|
||||
|
||||
[Export]
|
||||
public bool update;
|
||||
|
||||
[Export]
|
||||
public bool updateAlways;
|
||||
|
||||
[ExportToolButton( "Create")]
|
||||
public Callable createButton => Callable.From( ()=>
|
||||
{
|
||||
CreatePatch();
|
||||
}
|
||||
);
|
||||
[Export]
|
||||
public Material material;
|
||||
|
||||
|
@ -252,34 +252,6 @@ namespace Rokojori
|
|||
[Export]
|
||||
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;
|
||||
|
||||
Vector3 _patchOffset = Vector3.Zero;
|
||||
|
|
|
@ -132,6 +132,19 @@ namespace Rokojori
|
|||
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 )
|
||||
{
|
||||
if ( matches == null || matches.Length == 0 )
|
||||
|
@ -160,6 +173,9 @@ namespace Rokojori
|
|||
public class FindResult
|
||||
{
|
||||
public FindResultType type = FindResultType.NotFound;
|
||||
|
||||
public bool found => FindResultType.Found == type;
|
||||
|
||||
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();
|
||||
|
||||
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 ] );
|
||||
|
||||
|
@ -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 )
|
||||
{
|
||||
var openTypes = new List<string>(){ "(","[","{" };
|
||||
var closingTypes = new List<string>(){ ")","]","}" };
|
||||
|
||||
var token = tokens[ offset ];
|
||||
|
||||
var bracketIndex = openTypes.IndexOf( token.match );
|
||||
|
@ -325,11 +397,13 @@ namespace Rokojori
|
|||
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 currentValue = 0;
|
||||
|
||||
if ( forward )
|
||||
{
|
||||
for ( int i = offset; i < tokens.Count; i++ )
|
||||
{
|
||||
var countResult = counter( tokens[ i ] );
|
||||
|
@ -343,8 +417,115 @@ namespace Rokojori
|
|||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
AddAllMatchers(
|
||||
|
@ -37,6 +70,10 @@ namespace Rokojori
|
|||
LexerMatcherLibrary.BracketMatcher,
|
||||
LexerMatcherLibrary.AccessModifierMatcher,
|
||||
LexerMatcherLibrary.ClassMatcher,
|
||||
LexerMatcherLibrary.EnumMatcher,
|
||||
LexerMatcherLibrary.StructMatcher,
|
||||
LexerMatcherLibrary.InterfaceMatcher,
|
||||
LexerMatcherLibrary.RecordMatcher,
|
||||
LexerMatcherLibrary.OperatorMatcher,
|
||||
LexerMatcherLibrary.CFunctionMatcher,
|
||||
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 =
|
||||
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 =
|
||||
new LexerMatcher( "AccessModifier", @"\b(?:public|protected|private)\b" );
|
||||
new LexerMatcher( "AccessModifier", @"\b(?:public|protected|private|const)\b" );
|
||||
|
||||
public static readonly LexerMatcher SingleLineCommentMatcher =
|
||||
new LexerMatcher( "SingleLineComment", @"//.*" );
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
|
||||
namespace Rokojori
|
||||
|
@ -24,5 +25,43 @@ namespace Rokojori
|
|||
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 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 );
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.Text;
|
||||
using System;
|
||||
using Godot;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
|
@ -458,6 +459,11 @@ namespace Rokojori
|
|||
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 )
|
||||
{
|
||||
for ( var i = increasinglySortedRemovals.Count - 1; i >= 0; i-- )
|
||||
|
@ -658,6 +664,27 @@ namespace Rokojori
|
|||
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 )
|
||||
{
|
||||
for ( int i = 0; i < inputList.Count; i++ )
|
||||
|
|
|
@ -15,6 +15,11 @@ namespace Rokojori
|
|||
|
||||
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 )
|
||||
{
|
||||
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.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
|
||||
namespace Rokojori.Tools
|
||||
{
|
||||
|
@ -15,6 +16,125 @@ namespace Rokojori.Tools
|
|||
|
||||
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 )
|
||||
{
|
||||
var process = new Process
|
||||
|
|
|
@ -4,6 +4,7 @@ using Rokojori;
|
|||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
|
||||
namespace Rokojori.Tools
|
||||
{
|
||||
|
@ -12,7 +13,7 @@ namespace Rokojori.Tools
|
|||
public partial class GitTest:Node
|
||||
{
|
||||
[ExportToolButton("Status")]
|
||||
public Callable StatusButton => Callable.From(
|
||||
public Callable statusButton => Callable.From(
|
||||
()=>
|
||||
{
|
||||
GetStatus();
|
||||
|
@ -23,8 +24,38 @@ namespace Rokojori.Tools
|
|||
{
|
||||
var response = await Git.GetStatus( ProjectSettings.GlobalizePath( "res://") );
|
||||
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
|
|
@ -79,12 +79,25 @@ namespace Rokojori.Tools
|
|||
|
||||
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 );
|
||||
};
|
||||
|
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Linq;
|
||||
|
||||
namespace Rokojori.DocGenerator
|
||||
{
|
||||
|
@ -40,23 +41,32 @@ namespace Rokojori.DocGenerator
|
|||
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 comments = new DocComments();
|
||||
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;
|
||||
info.csNameSpace = type.Namespace;
|
||||
RJLog.Log( typeName, "Comments:", comments.entries.Count );
|
||||
|
||||
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 fields = Lists.ToList( type.GetFields( allBindings ) );
|
||||
var fields = Lists.ToList( classType.GetFields( allBindings ) );
|
||||
fields = Lists.Filter( fields, f => ! f.IsPrivate );
|
||||
|
||||
var godotTypes = new List<string>()
|
||||
|
@ -67,7 +77,7 @@ namespace Rokojori.DocGenerator
|
|||
|
||||
|
||||
|
||||
var it = type.BaseType;
|
||||
var it = baseTypeName;
|
||||
|
||||
while ( it != null )
|
||||
{
|
||||
|
@ -86,7 +96,7 @@ namespace Rokojori.DocGenerator
|
|||
}
|
||||
else
|
||||
{
|
||||
info.extendingClasses.Add( it.Name );
|
||||
info.extendingClasses.Add( GetDocsType.Of( it ) );
|
||||
it = it.BaseType;
|
||||
}
|
||||
|
||||
|
@ -95,14 +105,59 @@ namespace Rokojori.DocGenerator
|
|||
|
||||
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(
|
||||
( f )=>
|
||||
{
|
||||
if ( f.Name == "value__" )
|
||||
{
|
||||
return;
|
||||
}
|
||||
var memberInfo = MemberInfo.CreateField();
|
||||
|
||||
memberInfo.name = f.Name;
|
||||
|
||||
|
||||
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.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 );
|
||||
|
||||
var godotInternalMethods = new List<string>()
|
||||
|
@ -132,7 +187,8 @@ namespace Rokojori.DocGenerator
|
|||
"GetGodotPropertyList",
|
||||
"GetGodotPropertyDefaultValues",
|
||||
"SaveGodotObjectData",
|
||||
"RestoreGodotObjectData"
|
||||
"RestoreGodotObjectData",
|
||||
"InvokeGodotClassStaticMethod"
|
||||
};
|
||||
|
||||
methods.ForEach(
|
||||
|
@ -145,8 +201,10 @@ namespace Rokojori.DocGenerator
|
|||
|
||||
var memberInfo = MemberInfo.CreateMethod();
|
||||
|
||||
memberInfo.isAccessor = GetDocsType.isAccessorMethod( m );
|
||||
memberInfo.name = m.Name;
|
||||
memberInfo.dataType = m.ReturnType.Name;
|
||||
memberInfo.dataType = GetDocsType.Of( m.ReturnType );
|
||||
|
||||
memberInfo.csNameSpace = m.ReturnType.Namespace;
|
||||
memberInfo.generics = Lists.Map( m.GetGenericArguments(), t => t + "" );
|
||||
memberInfo.doc = comments.FindDoc( "method", m.Name );
|
||||
|
@ -164,9 +222,9 @@ namespace Rokojori.DocGenerator
|
|||
{
|
||||
var parameterType = new ParameterType();
|
||||
parameterType.name = p.Name;
|
||||
parameterType.type = p.ParameterType.Name;
|
||||
parameterType.type = GetDocsType.Of( p.ParameterType );
|
||||
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 );
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
uid://ddfpf66np8qpk
|
|
@ -9,7 +9,8 @@ namespace Rokojori.DocGenerator
|
|||
public string name;
|
||||
public string type;
|
||||
public string csNameSpace;
|
||||
public List<string> generics;
|
||||
public List<string> modifiers = [];
|
||||
public List<string> generics = [];
|
||||
}
|
||||
|
||||
public class MemberInfo
|
||||
|
@ -19,6 +20,11 @@ namespace Rokojori.DocGenerator
|
|||
public string name;
|
||||
public string dataType;
|
||||
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> generics;
|
||||
|
@ -26,6 +32,9 @@ namespace Rokojori.DocGenerator
|
|||
|
||||
public static readonly string Field = "Field";
|
||||
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 )
|
||||
{
|
||||
|
@ -43,6 +52,21 @@ namespace Rokojori.DocGenerator
|
|||
{
|
||||
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
|
||||
|
@ -51,8 +75,14 @@ namespace Rokojori.DocGenerator
|
|||
public string name ="";
|
||||
public string doc;
|
||||
public string icon;
|
||||
public string sourcePath;
|
||||
public string definitionType;
|
||||
|
||||
public List<string> generics = new List<string>();
|
||||
public List<string> interfaces = new List<string>();
|
||||
public List<string> extendingClasses = new List<string>();
|
||||
public List<MemberInfo> memberInfos = new List<MemberInfo>();
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
uid://cogfo5xxdtqo5
|
|
@ -2,6 +2,7 @@
|
|||
using Godot;
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
|
||||
namespace Rokojori.DocGenerator
|
||||
{
|
||||
|
@ -29,6 +30,21 @@ namespace Rokojori.DocGenerator
|
|||
[Export]
|
||||
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")]
|
||||
public Callable createButton => Callable.From( ()=>{ Generate(); } );
|
||||
|
||||
|
@ -47,11 +63,21 @@ namespace Rokojori.DocGenerator
|
|||
|
||||
void Generate()
|
||||
{
|
||||
|
||||
var absoluteLibraryPath = ProjectSettings.GlobalizePath( "res://addons/rokojori_action_library/Runtime" );
|
||||
var absoluteIconPath = ProjectSettings.GlobalizePath( "res://addons/rokojori_action_library/Icons" );
|
||||
var absoluteOutputPath = ProjectSettings.GlobalizePath( outputPath );
|
||||
|
||||
if ( clearDirectory )
|
||||
{
|
||||
FilesSync.Delete( absoluteOutputPath );
|
||||
FilesSync.EnsureDirectoryExists( absoluteOutputPath );
|
||||
}
|
||||
|
||||
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 );
|
||||
generator.Generate( absoluteLibraryPath, absoluteOutputPath, icons );
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
uid://cwvi31krqm3ik
|
|
@ -4,40 +4,81 @@ using Godot;
|
|||
using Rokojori;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using Microsoft.VisualBasic;
|
||||
using Rokojori.Tools;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Rokojori.DocGenerator
|
||||
{
|
||||
public class ClassTypeEntry
|
||||
{
|
||||
public Type type;
|
||||
public string definitionType;
|
||||
public string path;
|
||||
}
|
||||
|
||||
public class ShaderTypeEntry
|
||||
{
|
||||
public string path;
|
||||
}
|
||||
|
||||
|
||||
public class DocGenerator
|
||||
{
|
||||
string path = "";
|
||||
string outputPath = "";
|
||||
List<string> icons = new List<string>();
|
||||
|
||||
public bool checkChangeTime = false;
|
||||
public DateTimeOffset changeTime;
|
||||
|
||||
public List<FilePath> classFiles = new List<FilePath>();
|
||||
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.outputPath = outputPath;
|
||||
this.icons = icons;
|
||||
|
||||
GetFiles();
|
||||
await GetFiles();
|
||||
CreateTypesFromFiles();
|
||||
IncludeDefaultTypes();
|
||||
// IncludeDefaultTypes();
|
||||
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()
|
||||
|
@ -74,6 +115,42 @@ namespace Rokojori.DocGenerator
|
|||
( cf )=>
|
||||
{
|
||||
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 );
|
||||
|
||||
if ( type == null )
|
||||
|
@ -81,31 +158,61 @@ namespace Rokojori.DocGenerator
|
|||
type = ReflectionHelper.GetTypeByNameFromAssembly( name, assembly );
|
||||
}
|
||||
|
||||
if ( type != null )
|
||||
if ( type == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var entry = new ClassTypeEntry();
|
||||
entry.type = type;
|
||||
entry.path = cf.fullPath;
|
||||
entry.definitionType = definitionType;
|
||||
|
||||
classTypes.Add( entry);
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void GenerateDocsFromTypes()
|
||||
{
|
||||
FilesSync.EnsureDirectoryExists( outputPath );
|
||||
|
||||
classTypes.ForEach(
|
||||
( c )=>
|
||||
{
|
||||
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 );
|
||||
}
|
||||
);
|
||||
|
||||
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