UI + Procedural Geometry
This commit is contained in:
		
							parent
							
								
									9a07e22b05
								
							
						
					
					
						commit
						575431f868
					
				|  | @ -0,0 +1,89 @@ | ||||||
|  | using System.Collections; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System; | ||||||
|  | 
 | ||||||
|  | namespace Rokojori | ||||||
|  | { | ||||||
|  |   public abstract class GraphWalker<N> where N:class | ||||||
|  |   { | ||||||
|  |     public virtual int NumConnectedFrom( N node ){ return 0;} | ||||||
|  |     public virtual N GetConnectedFrom( N node, int index ){ return default(N);} | ||||||
|  | 
 | ||||||
|  |     public abstract int NumConnectedTo( N node ); | ||||||
|  |     public abstract N GetConnectedTo( N node, int index ); | ||||||
|  | 
 | ||||||
|  |     public int NumConnectedAll( N node ) | ||||||
|  |     { | ||||||
|  |       return NumConnectedTo( node ) + NumConnectedFrom( node ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public N GetConnected( N node, int index ) | ||||||
|  |     { | ||||||
|  |       var fromConnections = NumConnectedFrom( node ); | ||||||
|  | 
 | ||||||
|  |       return index < fromConnections ? GetConnectedFrom( node, index ) : GetConnectedTo( node, index - fromConnections ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     public bool IsConnectedTo( N source, N destination ) | ||||||
|  |     { | ||||||
|  |       var processed = new HashSet<N>(); | ||||||
|  |       var toDo = new List<N>(); | ||||||
|  | 
 | ||||||
|  |       toDo.Add( source ); | ||||||
|  | 
 | ||||||
|  |       while ( toDo.Count > 0 ) | ||||||
|  |       { | ||||||
|  |         var current = Lists.RemoveFirst( toDo ); | ||||||
|  |          | ||||||
|  |         if ( processed.Contains( current ) ) | ||||||
|  |         { | ||||||
|  |           continue; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         processed.Add( current ); | ||||||
|  | 
 | ||||||
|  |         var numConnected = NumConnectedTo( current ); | ||||||
|  |          | ||||||
|  |         for ( int i = 0; i < numConnected; i++ ) | ||||||
|  |         { | ||||||
|  |           var connected = GetConnected( current, i ); | ||||||
|  |            | ||||||
|  |           if ( connected == destination ) | ||||||
|  |           { | ||||||
|  |             return true; | ||||||
|  |           } | ||||||
|  | 
 | ||||||
|  |           if ( ! processed.Contains( connected ) ) | ||||||
|  |           { | ||||||
|  |             toDo.Add( connected ); | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |      | ||||||
|  | 
 | ||||||
|  |     public bool IsDirectlyConnectedTo( N node, N other ) | ||||||
|  |     { | ||||||
|  |       if ( node == null || other == null ) | ||||||
|  |       { | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       var connected = NumConnectedTo( node ); | ||||||
|  | 
 | ||||||
|  |       for ( int i = 0; i < connected; i++ ) | ||||||
|  |       { | ||||||
|  |         if ( GetConnected( node, i ) == other )  | ||||||
|  |         { | ||||||
|  |           return true; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -240,7 +240,7 @@ namespace Rokojori | ||||||
|       return NextNonChild( node ); |       return NextNonChild( node ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public N GetParent( N node, Func<N,bool> predicate ) |     public N GetInParents( N node, Func<N,bool> predicate ) | ||||||
|     { |     { | ||||||
|       var p = Parent( node ); |       var p = Parent( node ); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -42,6 +42,13 @@ namespace Rokojori | ||||||
|       GD.PrintRich( trace ); |       GD.PrintRich( trace ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     static void LogMessageWithFullTrace( string message ) | ||||||
|  |     { | ||||||
|  |       var trace = GetFullTrace(); | ||||||
|  |       GD.PrintRich("\n[b]" +  message + "[/b]"); | ||||||
|  |       GD.PrintRich( trace ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     static void LogErrorMessage( string message ) |     static void LogErrorMessage( string message ) | ||||||
|     { |     { | ||||||
|       var trace = GetTrace(); |       var trace = GetTrace(); | ||||||
|  | @ -49,6 +56,11 @@ namespace Rokojori | ||||||
|       GD.PrintRich( trace ); |       GD.PrintRich( trace ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     static string GetFullTrace() | ||||||
|  |     { | ||||||
|  |       return ( new System.Diagnostics.StackTrace( true ) ).ToString(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     static string GetTrace() |     static string GetTrace() | ||||||
|     { |     { | ||||||
|       var stackTrace = new System.Diagnostics.StackTrace( true ); |       var stackTrace = new System.Diagnostics.StackTrace( true ); | ||||||
|  | @ -86,6 +98,23 @@ namespace Rokojori | ||||||
|       return "[color=gray]  " + trace + "[/color]" ; |       return "[color=gray]  " + trace + "[/color]" ; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public static void LogWithFullTrace( params object[] objects) | ||||||
|  |     { | ||||||
|  |       var sb = new StringBuilder(); | ||||||
|  | 
 | ||||||
|  |       for ( int i = 0; i < objects.Length; i++ ) | ||||||
|  |       { | ||||||
|  |         if ( i != 0 ) | ||||||
|  |         { | ||||||
|  |           sb.Append( " " );  | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         Stringify( objects[ i ], sb ); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       LogMessageWithFullTrace( sb.ToString() ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public static void Log( params object[] objects) |     public static void Log( params object[] objects) | ||||||
|     { |     { | ||||||
|       var sb = new StringBuilder(); |       var sb = new StringBuilder(); | ||||||
|  |  | ||||||
|  | @ -0,0 +1,44 @@ | ||||||
|  | using Godot; | ||||||
|  | using System.Collections; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | 
 | ||||||
|  | namespace Rokojori | ||||||
|  | { | ||||||
|  | 	public class Capsule3 | ||||||
|  | 	{ | ||||||
|  |     public Vector3 start = Vector3.Zero; | ||||||
|  |     public Vector3 end = Vector3.Zero; | ||||||
|  |     public float radius = 1; | ||||||
|  | 
 | ||||||
|  |     public Capsule3( Vector3 start, Vector3 end, float radius ) | ||||||
|  |     { | ||||||
|  |       this.start = start; | ||||||
|  |       this.end = end; | ||||||
|  |       this.radius = radius; | ||||||
|  |     }     | ||||||
|  | 
 | ||||||
|  |     public Capsule3 Copy() | ||||||
|  |     { | ||||||
|  |       return new Capsule3( start, end, radius ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Vector3 center | ||||||
|  |     { | ||||||
|  |       get { return start.Lerp( end, 0.5f ); } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Line3 centerLine | ||||||
|  |     { | ||||||
|  |       get { return new Line3( start, end ); } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public float DistanceToPoint( Vector3 p ) | ||||||
|  |     { | ||||||
|  |       var lineDistance = centerLine.DistanceToPoint( p ); | ||||||
|  |       return Mathf.Max( 0, lineDistance - radius ); | ||||||
|  |     }  | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @ -0,0 +1,77 @@ | ||||||
|  | using Godot; | ||||||
|  | using System.Collections; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | 
 | ||||||
|  | namespace Rokojori | ||||||
|  | { | ||||||
|  | 	public abstract class Curve3 | ||||||
|  | 	{ | ||||||
|  |     float _gradientSamplingRange = Mathf.Pow( 10f, -13f ); | ||||||
|  |     public abstract Vector3 SampleAt( float t ); | ||||||
|  |      | ||||||
|  |     public virtual void SampleMultiple( int numSamples, List<Vector3> output ) | ||||||
|  |     { | ||||||
|  |       SampleMultiple( new Range( 0, 1 ), numSamples, output ); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     public virtual void SampleMultiple( Range range, int numSamples, List<Vector3> output ) | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |       var diff = range.length / ( numSamples - 1 ) ; | ||||||
|  |        | ||||||
|  |       for ( var i = 0 ; i < numSamples; i++ ) | ||||||
|  |       { | ||||||
|  |         var t = range.min + i * diff; | ||||||
|  |         output.Add( SampleAt( t ) ); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public virtual Vector3 GradientAt( float t ) | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |       return SampleAt( t + _gradientSamplingRange ) - SampleAt( t - _gradientSamplingRange ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public virtual float ComputeLength( int numSamples ) | ||||||
|  |     { | ||||||
|  |       return ComputeSubLength( Range.Of_01 , numSamples ); | ||||||
|  |     }     | ||||||
|  | 
 | ||||||
|  |     public virtual float ComputeSubLength( Range range, int numSamples ) | ||||||
|  |     { | ||||||
|  |       var diff = range.length / ( numSamples - 1 ) ; | ||||||
|  |       var it = SampleAt( range.min ); | ||||||
|  |       var length = 0f; | ||||||
|  | 
 | ||||||
|  |       for ( var i = 1 ; i < numSamples; i++ ) | ||||||
|  |       { | ||||||
|  |         var t = range.min + i * diff; | ||||||
|  |         var next = SampleAt( t ); | ||||||
|  |         length += ( next - it ).Length(); | ||||||
|  |         it = next; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       return length; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     public virtual int ComputeNumSamplesFor( Range range, | ||||||
|  |     float minimumDistance, int minSamples = 2,  | ||||||
|  |     int numSamplesForLengthComputation = -1 ) | ||||||
|  |     { | ||||||
|  |       if ( minSamples < 2 ) | ||||||
|  |       { minSamples = 2; } | ||||||
|  |        | ||||||
|  |       if ( numSamplesForLengthComputation <= 0  ) | ||||||
|  |       { numSamplesForLengthComputation = minSamples * 4; } | ||||||
|  | 
 | ||||||
|  |       float distance = ComputeSubLength( range, numSamplesForLengthComputation ); | ||||||
|  |       float numFloatingCuts = distance / minimumDistance; | ||||||
|  |       int numSamples = Mathf.CeilToInt( numFloatingCuts ); | ||||||
|  | 
 | ||||||
|  |       return Mathf.Max( minSamples, numSamples ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |          | ||||||
|  |          | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,117 @@ | ||||||
|  | using Godot; | ||||||
|  | using System.Collections; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | 
 | ||||||
|  | namespace Rokojori | ||||||
|  | { | ||||||
|  | 	public class Distance | ||||||
|  | 	{ | ||||||
|  |      | ||||||
|  |     /* | ||||||
|  |      | ||||||
|  |     P = Point,  | ||||||
|  |     S = Sphere | ||||||
|  |     L = Line, | ||||||
|  |     C = Capsule | ||||||
|  | 
 | ||||||
|  |      | ||||||
|  |       P S L C    | ||||||
|  |     P y y y y    | ||||||
|  |     S   y y y       | ||||||
|  |     L     y y       | ||||||
|  |     C       y   | ||||||
|  | 
 | ||||||
|  |     */ | ||||||
|  | 
 | ||||||
|  |     public static float Of( Vector3 a, Vector3 b ) | ||||||
|  |     { | ||||||
|  |       return ( a - b ).Length(); | ||||||
|  |     }     | ||||||
|  | 
 | ||||||
|  |     public static float Of( Vector3 a, Sphere b ) | ||||||
|  |     { | ||||||
|  |       return b.DistanceToPoint( a ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static float Of( Sphere a, Vector3 b ) | ||||||
|  |     { | ||||||
|  |       return Of( b, a ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static float Of( Vector3 a, Line3 b ) | ||||||
|  |     { | ||||||
|  |       return b.DistanceToPoint( a ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static float Of( Line3 b, Vector3 a ) | ||||||
|  |     { | ||||||
|  |       return Of( a, b ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static float Of( Vector3 a, Capsule3 b ) | ||||||
|  |     { | ||||||
|  |       return b.DistanceToPoint( a ); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     public static float Of( Capsule3 a, Vector3 b ) | ||||||
|  |     { | ||||||
|  |       return Of( b, a ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static float Of( Sphere a, Sphere b ) | ||||||
|  |     { | ||||||
|  |       return a.DistanceToSphere( b ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static float Of( Sphere a, Line3 b ) | ||||||
|  |     { | ||||||
|  |       var centerDistance = Of( a.center, b ); | ||||||
|  |       return Mathf.Max( centerDistance - a.radius, 0 );  | ||||||
|  |     }  | ||||||
|  | 
 | ||||||
|  |     public static float Of( Line3 a, Sphere b ) | ||||||
|  |     { | ||||||
|  |       return Of( b, a ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static float Of( Sphere a, Capsule3 b ) | ||||||
|  |     { | ||||||
|  |       var centerDistance = Of( a.center, b ); | ||||||
|  |       return Mathf.Max( centerDistance - a.radius, 0 );  | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static float Of( Capsule3 a, Sphere b ) | ||||||
|  |     { | ||||||
|  |       return Of( b, a ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static float Of( Line3 a, Line3 b ) | ||||||
|  |     { | ||||||
|  |       return a.DistanceToLine( b ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static float Of( Line3 a, Capsule3 b ) | ||||||
|  |     { | ||||||
|  |       var lineDistance = Of( a, b.centerLine ); | ||||||
|  |       return Mathf.Max( 0, lineDistance - b.radius ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static float Of( Capsule3 a, Line3 b ) | ||||||
|  |     { | ||||||
|  |       return Of( b, a ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static float Of( Capsule3 a, Capsule3 b ) | ||||||
|  |     { | ||||||
|  |       var lineDistance = Of( a.centerLine, b.centerLine ); | ||||||
|  |       return Mathf.Max( 0, lineDistance - ( a.radius + b.radius ) ); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |      | ||||||
|  | 
 | ||||||
|  |      | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @ -0,0 +1,249 @@ | ||||||
|  | using System.Collections; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using Godot; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | namespace Rokojori | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  |   public class SubdivisionData | ||||||
|  |   { | ||||||
|  |     public Vector3 point; | ||||||
|  |     public bool isCorner; | ||||||
|  |     public Vector3 direction; | ||||||
|  | 
 | ||||||
|  |     public SubdivisionData( Vector3 p, Vector3 d, bool corner = false ) | ||||||
|  |     { | ||||||
|  |       point = p; | ||||||
|  |       direction = d; | ||||||
|  |       isCorner = corner; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   public class LerpCurveClosestToPointResult | ||||||
|  |   { | ||||||
|  |     public float parameter; | ||||||
|  |     public float distance; | ||||||
|  |     public Vector3 point; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | 	public class LerpCurve3:Curve3 | ||||||
|  | 	{ | ||||||
|  |     List<Vector3> list; | ||||||
|  |      | ||||||
|  |     public LerpCurve3( List<Vector3> list ) | ||||||
|  |     { | ||||||
|  |       this.list = list; | ||||||
|  |        | ||||||
|  |       if ( list.Count == 0 ) | ||||||
|  |       { | ||||||
|  |         RJLog.Log( "LERP CURVE WITH EMPTY LIST" ); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public override float ComputeLength( int numSamples ) | ||||||
|  |     { | ||||||
|  |       var length = 0f; | ||||||
|  |       var end = list.Count - 1; | ||||||
|  | 
 | ||||||
|  |       for ( int i = 0; i < end; i++ ) | ||||||
|  |       { | ||||||
|  |         var p0  = list[ i ]; | ||||||
|  |         var p1  = list[ i + 1 ]; | ||||||
|  | 
 | ||||||
|  |         length += p0.DistanceTo( p1 ); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       return length; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public float UndistortParameter( float parameter ) | ||||||
|  |     { | ||||||
|  |       var completeLength = ComputeLength( 0 ); | ||||||
|  | 
 | ||||||
|  |       var end = list.Count - 1; | ||||||
|  |       var normalizer = 1f / ( list.Count - 1 ); | ||||||
|  | 
 | ||||||
|  |       var length = 0f; | ||||||
|  | 
 | ||||||
|  |       for ( int i = 0; i < end; i++ ) | ||||||
|  |       { | ||||||
|  |         var p0  = list[ i ]; | ||||||
|  |         var p1  = list[ i + 1 ]; | ||||||
|  |         var t0  = i * normalizer; | ||||||
|  |         var t1  = ( i + 1 ) * normalizer; | ||||||
|  |         var distance = p0.DistanceTo( p1 ); | ||||||
|  | 
 | ||||||
|  |         if ( t0 <= parameter && parameter <= t1 ) | ||||||
|  |         { | ||||||
|  |           length += distance * ( parameter - t0 );  | ||||||
|  |           return length / completeLength; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         length += distance; | ||||||
|  | 
 | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       return 1; | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public List<SubdivisionData> Subdivide( float distance, bool close ) | ||||||
|  |     { | ||||||
|  |       var output = new List<SubdivisionData>(); | ||||||
|  | 
 | ||||||
|  |       var num = list.Count - 1; | ||||||
|  | 
 | ||||||
|  |       if ( close ) | ||||||
|  |       { | ||||||
|  |         num ++; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       for ( var i = 0; i < num; i++ ) | ||||||
|  |       { | ||||||
|  |         var start = list[ i ]; | ||||||
|  |         var end   = list[ i == list.Count ? 0 : i + 1 ]; | ||||||
|  | 
 | ||||||
|  |         var dir = ( end - start ); | ||||||
|  |         var length = dir.Length(); | ||||||
|  |         var samples = Mathf.CeilToInt( length / distance ); | ||||||
|  | 
 | ||||||
|  |         output.Add( new SubdivisionData( start, dir, true ) ); | ||||||
|  | 
 | ||||||
|  |         for ( int j = 1; j < samples; j++ ) | ||||||
|  |         { | ||||||
|  |           var samplePoint = j / (float) samples; | ||||||
|  |           var point = start.Lerp( end, samplePoint ); | ||||||
|  |           output.Add( new SubdivisionData( point, dir ) ); | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |       } | ||||||
|  |        | ||||||
|  | 
 | ||||||
|  |       if ( ! close ) | ||||||
|  |       { | ||||||
|  |         var start = list[ list.Count - 2]; | ||||||
|  |         var end   = list[ list.Count - 1]; | ||||||
|  | 
 | ||||||
|  |         var dir = ( end - start ); | ||||||
|  | 
 | ||||||
|  |         output.Add( new SubdivisionData( end, dir, true ) ); | ||||||
|  |          | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |       var dirCount = close ? output.Count : ( output.Count - 1 ); | ||||||
|  | 
 | ||||||
|  |       for ( int i = 0; i < dirCount; i++ ) | ||||||
|  |       { | ||||||
|  |         var next = i == output.Count ? 0 : i + 1; | ||||||
|  |         output[ i ].direction = output[ next ].point - output[ i ].point; | ||||||
|  |       } | ||||||
|  |        | ||||||
|  | 
 | ||||||
|  |        | ||||||
|  | 
 | ||||||
|  |       return output; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public override Vector3 SampleAt( float t ) | ||||||
|  |     { | ||||||
|  |       if ( t < 0 ) | ||||||
|  |       { | ||||||
|  |         return list[ 0 ]; | ||||||
|  |       } | ||||||
|  |        | ||||||
|  |       if ( t >= 1 ) | ||||||
|  |       { | ||||||
|  |         return list[ list.Count - 1 ]; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if ( list.Count == 1 ) | ||||||
|  |       { | ||||||
|  |         return list[ 0 ]; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |      | ||||||
|  | 
 | ||||||
|  |       var listIndex = t * ( list.Count - 1 ); | ||||||
|  |       var flooredIndex = (int) Mathf.Floor( listIndex ); | ||||||
|  | 
 | ||||||
|  |       var lerpAmount = listIndex - flooredIndex; | ||||||
|  | 
 | ||||||
|  |       if ( flooredIndex < 0 ||  ( flooredIndex >= list.Count - 1 ) ) | ||||||
|  |       { | ||||||
|  |         RJLog.Log( "Out of range index:",flooredIndex, " t:", t, " listIndex", listIndex, "Count:", list.Count ); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       var lower = list[ flooredIndex ]; | ||||||
|  |       var upper = list[ flooredIndex + 1 ]; | ||||||
|  | 
 | ||||||
|  |       return Math3D.LerpUnclamped( lower, upper, lerpAmount ); | ||||||
|  |        | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public LerpCurve3 FromRange( Curve3 curve, Range range, int numSamples ) | ||||||
|  |     { | ||||||
|  |       var points = new List<Vector3>(); | ||||||
|  |       curve.SampleMultiple( range, numSamples, points ); | ||||||
|  |       return new LerpCurve3( points ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public LerpCurve3 From( Curve3 curve, int numSamples ) | ||||||
|  |     { | ||||||
|  |       return FromRange( curve, Range.Of_01, numSamples ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static LerpCurve3 FromPoints( Vector3 first, Vector3 second, params Vector3[] others ) | ||||||
|  |     { | ||||||
|  |       var points = new List<Vector3>(); | ||||||
|  |       points.Add( first ); | ||||||
|  |       points.Add( second ); | ||||||
|  |       points.AddRange( others ); | ||||||
|  | 
 | ||||||
|  |       return new LerpCurve3( points ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Line3 line; | ||||||
|  | 
 | ||||||
|  |     public void GetClosest( Vector3 point, LerpCurveClosestToPointResult result ) | ||||||
|  |     { | ||||||
|  |       var closestDistance = float.MaxValue; | ||||||
|  |       Vector3 closestPoint    = Vector3.Zero;  | ||||||
|  |       var closestParameter  = 0f; | ||||||
|  | 
 | ||||||
|  |       if ( line == null ) | ||||||
|  |       { | ||||||
|  |         line = new Line3( Vector3.Zero, Vector3.Zero ); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       var end = list.Count - 1; | ||||||
|  |        | ||||||
|  |       var parameterNormalizer = 1f / ( list.Count - 1f ); | ||||||
|  | 
 | ||||||
|  |       for ( int i = 0; i < end; i++ ) | ||||||
|  |       {         | ||||||
|  |         line.start = list[ i ]; | ||||||
|  |         line.end   = list[ i + 1 ]; | ||||||
|  | 
 | ||||||
|  |         var currentParameter = line.ClostestParameterToPoint( point ); | ||||||
|  |         var currentClosestPoint = line.GetPointAtParameter( currentParameter ); | ||||||
|  |         var currentDistance = ( point - currentClosestPoint ).LengthSquared(); | ||||||
|  | 
 | ||||||
|  |         if ( currentDistance < closestDistance ) | ||||||
|  |         { | ||||||
|  |           closestDistance = currentDistance; | ||||||
|  |           closestPoint = currentClosestPoint; | ||||||
|  |           closestParameter = ( currentParameter + i ) * parameterNormalizer; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       result.distance = Mathf.Sqrt( closestDistance ); | ||||||
|  |       result.point = closestPoint; | ||||||
|  |       result.parameter = closestParameter; | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  |          | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,198 @@ | ||||||
|  | using Godot; | ||||||
|  | using System.Collections; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | 
 | ||||||
|  | namespace Rokojori | ||||||
|  | { | ||||||
|  |   public class Line3:Curve3 | ||||||
|  |   { | ||||||
|  |     public Vector3 start = Vector3.Zero; | ||||||
|  |     public Vector3 end = Vector3.Zero; | ||||||
|  | 
 | ||||||
|  |     public Line3( Vector3 start, Vector3 end ) | ||||||
|  |     { | ||||||
|  |       this.start = start; | ||||||
|  |       this.end = end; | ||||||
|  |     }  | ||||||
|  | 
 | ||||||
|  |     public override Vector3 SampleAt( float t ) | ||||||
|  |     { | ||||||
|  |       return start.Lerp( end, t ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Line3 Copy( ) | ||||||
|  |     { | ||||||
|  |       return new Line3( start, end ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Vector3 direction { get { return end - start; } } | ||||||
|  | 
 | ||||||
|  |     public float length { get { return direction.Length();  } } | ||||||
|  |      | ||||||
|  |     public Vector3 GetPointAtParameter( float t ) | ||||||
|  |     { | ||||||
|  |       return start + direction * t; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Vector3 center{ get { return ( start + end ) * 0.5f; } } | ||||||
|  | 
 | ||||||
|  |     public Line3 ScaleFromCenter( float scale ) | ||||||
|  |     { | ||||||
|  |       var lineCenter = center; | ||||||
|  |       var halfDirection = direction * ( 0.5f * scale ); | ||||||
|  | 
 | ||||||
|  |       var scaledStart = lineCenter - halfDirection; | ||||||
|  |       var scaledEnd   = lineCenter + halfDirection; | ||||||
|  | 
 | ||||||
|  |       return new Line3( scaledStart, scaledEnd );   | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Line3 ChangeLengthFromCenter( float lengthChange ) | ||||||
|  |     { | ||||||
|  |       var lineCenter = center; | ||||||
|  |       var halfDirection = direction * 0.5f; | ||||||
|  |       var length = halfDirection.Length(); | ||||||
|  |       length += lengthChange * 0.5f; | ||||||
|  | 
 | ||||||
|  |       halfDirection = halfDirection.Normalized() * length;       | ||||||
|  | 
 | ||||||
|  |       var scaledStart = lineCenter - halfDirection; | ||||||
|  |       var scaledEnd   = lineCenter + halfDirection; | ||||||
|  | 
 | ||||||
|  |       return new Line3( scaledStart, scaledEnd );   | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Line3 SetLengthFromCenter( float length ) | ||||||
|  |     { | ||||||
|  |       var lineCenter = center; | ||||||
|  |       var halfDirection = direction.Normalized() * ( length * 0.5f );      | ||||||
|  | 
 | ||||||
|  |       var scaledStart = lineCenter - halfDirection; | ||||||
|  |       var scaledEnd   = lineCenter + halfDirection; | ||||||
|  | 
 | ||||||
|  |       return new Line3( scaledStart, scaledEnd );   | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |       | ||||||
|  |     public Vector3 ClosestPointToPoint( Vector3 point ) | ||||||
|  |     { | ||||||
|  |       var parameter = MathX.Clamp01( ClostestParameterToPoint( point ) ); | ||||||
|  |       return GetPointAtParameter( parameter ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public float ClostestParameterToPoint( Vector3 point ) | ||||||
|  |     { | ||||||
|  |       var startP = point - start; | ||||||
|  |       var startEnd = end - start; | ||||||
|  |       var startEnd2 = startEnd.Dot( startEnd ); | ||||||
|  |       var startEnd_startP = startEnd.Dot( startP ); | ||||||
|  | 
 | ||||||
|  |       if ( startEnd2 == 0 ) | ||||||
|  |       { | ||||||
|  |         return 0; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       var t = startEnd_startP / startEnd2; | ||||||
|  | 
 | ||||||
|  |       return t; | ||||||
|  |          | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public float DistanceToPoint( Vector3 point ) | ||||||
|  |     { | ||||||
|  |       return ( point - ClosestPointToPoint( point ) ).Length(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     public float DistanceToLine( Line3 s ) | ||||||
|  |     { | ||||||
|  |       var points = ClosestPointsToLine( s ); | ||||||
|  |       return ( points[ 1 ] - points[ 0 ] ).Length(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Vector3[] ClosestPointsToLine( Line3 s ) | ||||||
|  |     { | ||||||
|  |       var parameters = ClosestParametersToLine( s ); | ||||||
|  |       var x = this.GetPointAtParameter( parameters.X ); | ||||||
|  |       var y = s.GetPointAtParameter( parameters.Y ); | ||||||
|  | 
 | ||||||
|  |       return new Vector3[]{ x, y };   | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Vector2 ClosestParametersToLine( Line3 s ) | ||||||
|  |     {      | ||||||
|  |       float epsilon = 0.00000001f; | ||||||
|  | 
 | ||||||
|  |       var u = this.direction; | ||||||
|  |       var v = s.direction; | ||||||
|  |       var w = start - s.start; | ||||||
|  |      | ||||||
|  |       var a = u.Dot( u ); | ||||||
|  |       var b = u.Dot( v ); | ||||||
|  |       var c = v.Dot( v ); | ||||||
|  |       var d = u.Dot( w ); | ||||||
|  |       var e = v.Dot( w ); | ||||||
|  | 
 | ||||||
|  |       var DD = a * c - b * b; | ||||||
|  | 
 | ||||||
|  |       var sc = 0f; | ||||||
|  |       var sN = 0f; | ||||||
|  |       var sD = 0f; | ||||||
|  | 
 | ||||||
|  |       var tc = 0f; | ||||||
|  |       var tN = 0f; | ||||||
|  |       var tD = 0f; | ||||||
|  | 
 | ||||||
|  |       sD = DD; | ||||||
|  |       tD = DD; | ||||||
|  | 
 | ||||||
|  |       if ( DD < epsilon )  | ||||||
|  |       { | ||||||
|  |         sN = 0.0f; | ||||||
|  |         sD = 1.0f; | ||||||
|  |         tN = e; | ||||||
|  |         tD = c; | ||||||
|  |       } | ||||||
|  |       else | ||||||
|  |       { | ||||||
|  |         sN = b * e - c * d ; | ||||||
|  |         tN = a * e - b * d ; | ||||||
|  | 
 | ||||||
|  |         if ( sN < 0.0f ) | ||||||
|  |         { | ||||||
|  |           sN = 0.0f; | ||||||
|  |           tN = e; | ||||||
|  |           tD = c; | ||||||
|  |         } | ||||||
|  |         else if ( sN > sD )  | ||||||
|  |         { | ||||||
|  |           sN = sD; | ||||||
|  |           tN = e + b; | ||||||
|  |           tD = c; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if ( tN < 0f || tN > tD ) | ||||||
|  |       { | ||||||
|  |         var tN_bigger_tD = tN >= 0f && tN > tD; | ||||||
|  | 
 | ||||||
|  |         tN = tN_bigger_tD ? tD : 0f; | ||||||
|  | 
 | ||||||
|  |         var inbetween = tN_bigger_tD ? ( -d + b ) : ( -d ); | ||||||
|  |         var isSmaller = inbetween < 0; | ||||||
|  |         var isBigger  = inbetween > a; | ||||||
|  | 
 | ||||||
|  |         sN = isSmaller ? 0f : isBigger ? sD : inbetween;  | ||||||
|  |         sD = ! isSmaller && ! isBigger ?  a : sD; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       sc = Mathf.Abs( sN ) < epsilon ? 0f : sN / sD; | ||||||
|  |       tc = Mathf.Abs( tN ) < epsilon ? 0f : tN / tD; | ||||||
|  | 
 | ||||||
|  |       return new Vector2( sc, tc );  | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @ -0,0 +1,53 @@ | ||||||
|  | using System.Collections; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using Godot; | ||||||
|  | 
 | ||||||
|  | namespace Rokojori | ||||||
|  | { | ||||||
|  | 	public class Sphere | ||||||
|  | 	{ | ||||||
|  |     public Vector3 center = Vector3.Zero; | ||||||
|  |     public float radius = 1; | ||||||
|  | 
 | ||||||
|  |     public Sphere( Vector3 center, float radius ) | ||||||
|  |     { | ||||||
|  |       this.center = center; | ||||||
|  |       this.radius = radius; | ||||||
|  |     }     | ||||||
|  | 
 | ||||||
|  |     public Sphere Copy() | ||||||
|  |     { | ||||||
|  |       return new Sphere( center, radius ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public float DistanceToPoint( Vector3 point ) | ||||||
|  |     { | ||||||
|  |       return Mathf.Max( 0, ( point - center ).Length() - radius ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public bool ContainsPoint( Vector3 point ) | ||||||
|  |     { | ||||||
|  |       return DistanceToPoint( point ) <= 0;  | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public float DistanceToSphere( Sphere sphere ) | ||||||
|  |     { | ||||||
|  |       var distance = sphere.center - center; | ||||||
|  |       var radiusBoth = sphere.radius + radius; | ||||||
|  |       return Mathf.Max( 0, distance.Length() - radiusBoth );  | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public bool IntersectsSphere( Sphere sphere ) | ||||||
|  |     { | ||||||
|  |       return DistanceToSphere( sphere ) <= 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Box3 CreateBox() | ||||||
|  |     { | ||||||
|  |       var offset = radius * Vector3.One; | ||||||
|  |       return Box3.Create( center -offset, center + offset ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @ -0,0 +1,96 @@ | ||||||
|  | using Godot; | ||||||
|  | using System.Collections; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | namespace Rokojori | ||||||
|  | { | ||||||
|  |   public enum TriangleSide | ||||||
|  |   { | ||||||
|  |     AB, | ||||||
|  |     BC, | ||||||
|  |     CA | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   public class TriangleSides | ||||||
|  |   { | ||||||
|  |     public static readonly TriangleSide[] ALL =  | ||||||
|  |     { | ||||||
|  |       TriangleSide.AB, | ||||||
|  |       TriangleSide.BC, | ||||||
|  |       TriangleSide.CA | ||||||
|  |     }; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   public class Triangle3 | ||||||
|  |   {    | ||||||
|  |     public Vector3 a; | ||||||
|  |     public Vector3 b; | ||||||
|  |     public Vector3 c; | ||||||
|  | 
 | ||||||
|  |     public Triangle3( Vector3 a, Vector3 b, Vector3 c ) | ||||||
|  |     { | ||||||
|  |       this.a = a; | ||||||
|  |       this.b = b; | ||||||
|  |       this.c = c; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public float perimeter | ||||||
|  |     { | ||||||
|  |       get | ||||||
|  |       { | ||||||
|  |         var sideA = ( b - a ).Length(); | ||||||
|  |         var sideB = ( c - b ).Length(); | ||||||
|  |         var sideC = ( a - c ).Length(); | ||||||
|  |        | ||||||
|  |         return sideA + sideB + sideC; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public float semiperimeter | ||||||
|  |     { | ||||||
|  |       get | ||||||
|  |       { | ||||||
|  |         return perimeter * 0.5f; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static float ComputeTriangleArea( Vector3 a, Vector3 b, Vector3 c ) | ||||||
|  |     { | ||||||
|  |       var sideA = ( b - a ).Length(); | ||||||
|  |       var sideB = ( c - b ).Length(); | ||||||
|  |       var sideC = ( a - c ).Length(); | ||||||
|  |      | ||||||
|  | 
 | ||||||
|  |       var perimeter = sideA + sideB + sideC; | ||||||
|  |       var semiperimeter = 0.5f * perimeter; | ||||||
|  |       var areaValue = Mathf.Sqrt( semiperimeter * ( semiperimeter - sideA )  | ||||||
|  |                                                 * ( semiperimeter - sideB )  | ||||||
|  |                                                 * ( semiperimeter - sideC )) ; | ||||||
|  | 
 | ||||||
|  |       return areaValue;    | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public float area | ||||||
|  |     { | ||||||
|  |       get | ||||||
|  |       { | ||||||
|  |         return ComputeTriangleArea( a, b, c ); | ||||||
|  |       }      | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     public Line3 GetSide( TriangleSide side ) | ||||||
|  |     {  | ||||||
|  |       switch ( side ) | ||||||
|  |       { | ||||||
|  |         case TriangleSide.AB: return new Line3( a, b ); | ||||||
|  |         case TriangleSide.BC: return new Line3( b, c  ); | ||||||
|  |         case TriangleSide.CA: return new Line3( c, a ); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       return null; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -8,6 +8,16 @@ namespace Rokojori | ||||||
| { | { | ||||||
|   public class Math3D |   public class Math3D | ||||||
|   { |   { | ||||||
|  |     public static Vector3 LerpUnclamped( Vector3 a, Vector3 b, float amount ) | ||||||
|  |     { | ||||||
|  |       return a + amount * ( b - a ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static Vector3 LerpClamped( Vector3 a, Vector3 b, float amount ) | ||||||
|  |     { | ||||||
|  |       return LerpUnclamped( a, b, MathX.Clamp01( amount ) ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public static Quaternion GetGlobalRotation( Node3D node ) |     public static Quaternion GetGlobalRotation( Node3D node ) | ||||||
|     { |     { | ||||||
|       return node.GlobalBasis.GetRotationQuaternion(); |       return node.GlobalBasis.GetRotationQuaternion(); | ||||||
|  |  | ||||||
|  | @ -0,0 +1,104 @@ | ||||||
|  | using System.Collections; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using Godot; | ||||||
|  | 
 | ||||||
|  | namespace Rokojori | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  |   public class RationalCubicBezier | ||||||
|  |   { | ||||||
|  |     public static float Compute( | ||||||
|  |       float t,  | ||||||
|  |       float p0, float p1, float p2, float p3,  | ||||||
|  |       float w0, float w1, float w2, float w3 | ||||||
|  |     ) | ||||||
|  |     { | ||||||
|  |       var bp0 = ( 1 - t ) * ( 1 - t ) * ( 1 - t ) * w0; | ||||||
|  |       var bp1 = 3 * ( 1 - t ) * ( 1 - t ) * t * w1; | ||||||
|  |       var bp2 = 3 * ( 1 - t ) * t * t * w2; | ||||||
|  |       var bp3 = t * t * t * w3; | ||||||
|  | 
 | ||||||
|  |       var weighted = p0 * bp0 + p1 * bp1 + p2 * bp2 + p3 * bp3; | ||||||
|  | 
 | ||||||
|  |       var projection = bp0 + bp1 + bp2 + bp3; | ||||||
|  | 
 | ||||||
|  |       return weighted / projection; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static Vector2 Compute( | ||||||
|  |       float t,  | ||||||
|  |       Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3,  | ||||||
|  |       float w0, float w1, float w2, float w3 | ||||||
|  |     ) | ||||||
|  |     { | ||||||
|  |       var bp0 = ( 1 - t ) * ( 1 - t ) * ( 1 - t ) * w0; | ||||||
|  |       var bp1 = 3 * ( 1 - t ) * ( 1 - t ) * t * w1; | ||||||
|  |       var bp2 = 3 * ( 1 - t ) * t * t * w2; | ||||||
|  |       var bp3 = t * t * t * w3; | ||||||
|  | 
 | ||||||
|  |       var weighted = p0 * bp0 + p1 * bp1 + p2 * bp2 + p3 * bp3; | ||||||
|  | 
 | ||||||
|  |       var projection = bp0 + bp1 + bp2 + bp3; | ||||||
|  | 
 | ||||||
|  |       return weighted / projection; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static Vector3 Compute( | ||||||
|  |       float t,  | ||||||
|  |       Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3,  | ||||||
|  |       float w0, float w1, float w2, float w3 | ||||||
|  |     ) | ||||||
|  |     { | ||||||
|  |       var bp0 = ( 1 - t ) * ( 1 - t ) * ( 1 - t ) * w0; | ||||||
|  |       var bp1 = 3 * ( 1 - t ) * ( 1 - t ) * t * w1; | ||||||
|  |       var bp2 = 3 * ( 1 - t ) * t * t * w2; | ||||||
|  |       var bp3 = t * t * t * w3; | ||||||
|  | 
 | ||||||
|  |       var weighted = p0 * bp0 + p1 * bp1 + p2 * bp2 + p3 * bp3; | ||||||
|  | 
 | ||||||
|  |       var projection = bp0 + bp1 + bp2 + bp3; | ||||||
|  | 
 | ||||||
|  |       return weighted / projection; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     public static Vector2 Compute( float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3 ) | ||||||
|  |     { | ||||||
|  |       var bp0 = ( 1 - t ) * ( 1 - t ) * ( 1 - t ) * p0.Z; | ||||||
|  |       var bp1 = 3 * ( 1 - t ) * ( 1 - t ) * t * p1.Z; | ||||||
|  |       var bp2 = 3 * ( 1 - t ) * t * t * p2.Z; | ||||||
|  |       var bp3 = t * t * t * p3.Z; | ||||||
|  | 
 | ||||||
|  |       var weighted = p0 * bp0 + p1 * bp1 + p2 * bp2 + p3 * bp3; | ||||||
|  | 
 | ||||||
|  |       var projection = bp0 + bp1 + bp2 + bp3; | ||||||
|  | 
 | ||||||
|  |       var result = weighted / projection; | ||||||
|  | 
 | ||||||
|  |       return new Vector2( result.X, result.Y ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static Vector3 Compute( float t, Vector4 p0, Vector4 p1, Vector4 p2, Vector4 p3 ) | ||||||
|  |     { | ||||||
|  |       var bp0 = ( 1 - t ) * ( 1 - t ) * ( 1 - t ) * p0.W; | ||||||
|  |       var bp1 = 3 * ( 1 - t ) * ( 1 - t ) * t * p1.W; | ||||||
|  |       var bp2 = 3 * ( 1 - t ) * t * t * p2.W; | ||||||
|  |       var bp3 = t * t * t * p3.W; | ||||||
|  | 
 | ||||||
|  |       var weighted = p0 * bp0 + p1 * bp1 + p2 * bp2 + p3 * bp3; | ||||||
|  | 
 | ||||||
|  |       var projection = bp0 + bp1 + bp2 + bp3; | ||||||
|  | 
 | ||||||
|  |       var result = weighted / projection; | ||||||
|  | 
 | ||||||
|  |       return new Vector3( result.X, result.Y, result.Z ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |      | ||||||
|  | 
 | ||||||
|  |      | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,20 @@ | ||||||
|  | Match:   \.magnitude | ||||||
|  | Replace: .Length() | ||||||
|  | 
 | ||||||
|  | Match:   \.normalized | ||||||
|  | Replace: .Normalized() | ||||||
|  | 
 | ||||||
|  | Match:   Vector3\.(Lerp|Dot)\(\s*(\w+)\s*,\s* | ||||||
|  | Replace: $2.$1(  | ||||||
|  | 
 | ||||||
|  | Match:   Vector3\.Distance\(\s*(\w+)\s*,\s* | ||||||
|  | Replace: $1.DistanceTo(  | ||||||
|  | 
 | ||||||
|  | Match:   \.x | ||||||
|  | Replace: .X | ||||||
|  | 
 | ||||||
|  | Match:   \.Y | ||||||
|  | Replace: .Y | ||||||
|  | 
 | ||||||
|  | Match:   \.z | ||||||
|  | Replace: .Z | ||||||
|  | @ -0,0 +1,138 @@ | ||||||
|  | using System.Collections; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using Godot; | ||||||
|  | using System; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | namespace Rokojori | ||||||
|  | { | ||||||
|  |   public class MeshGeometry | ||||||
|  |   { | ||||||
|  |     public List<Vector3> vertices; | ||||||
|  |     public List<int> indices; | ||||||
|  | 
 | ||||||
|  |     public List<Vector3> normals; | ||||||
|  |     public List<Vector2> uvs; | ||||||
|  |     public List<Vector2> uv2s; | ||||||
|  |     public List<Color> colors; | ||||||
|  |    | ||||||
|  | 
 | ||||||
|  |     public void Initialize( bool normals = true, bool uvs = true, bool colors = false, bool uvs2 = false) | ||||||
|  |     { | ||||||
|  |       this.vertices = new List<Vector3>(); | ||||||
|  |       this.indices = new List<int>(); | ||||||
|  |        | ||||||
|  |       this.normals = normals ? new List<Vector3>() : null; | ||||||
|  |       this.uvs = uvs ? new List<Vector2>() : null; | ||||||
|  |       this.uv2s = uvs2 ? new List<Vector2>() : null; | ||||||
|  |       this.colors = colors ? new List<Color>() : null;       | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void AddTriangle(  | ||||||
|  |       Vector3 va, Vector3 vb, Vector3 vc,  | ||||||
|  |       Vector3 na, Vector3 nb, Vector3 nc, | ||||||
|  |       Vector2 uva, Vector2 uvb, Vector2 uvc | ||||||
|  |     ) | ||||||
|  |     { | ||||||
|  |       var index = vertices.Count; | ||||||
|  |       Lists.Add( vertices, va, vb, vc ); | ||||||
|  |       Lists.Add( normals, na, nb, nc ); | ||||||
|  |       Lists.Add( uvs, uva, uvb, uvc ); | ||||||
|  |       Lists.Add( indices, index, index + 1, index + 2 ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void AddQuad( | ||||||
|  |       Vector3 va, Vector3 vb, Vector3 vc, Vector3 vd, | ||||||
|  |       Vector3 na, Vector3 nb, Vector3 nc, Vector3 nd,  | ||||||
|  |       Vector2 uva, Vector2 uvb, Vector2 uvc, Vector2 uvd | ||||||
|  |     ) | ||||||
|  |     { | ||||||
|  |       AddTriangle( va, vb, vc,  na, nb, nc,  uva, uvb, uvc ); | ||||||
|  |       AddTriangle( vc, vd, va,  nc, nd, na,  uvc, uvd, uva ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void AddTriangle(  | ||||||
|  |       Vector3 va, Vector3 vb, Vector3 vc,  | ||||||
|  |       Vector2 uva, Vector2 uvb, Vector2 uvc | ||||||
|  |     ) | ||||||
|  |     { | ||||||
|  |       var n = Vector3.Up; | ||||||
|  | 
 | ||||||
|  |       AddTriangle( va, vb, vc,  | ||||||
|  |                    n, n, n, | ||||||
|  |                    uva, uvb, uvc ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void AddQuad( | ||||||
|  |       Vector3 va, Vector3 vb, Vector3 vc, Vector3 vd, | ||||||
|  |       Vector2 uva, Vector2 uvb, Vector2 uvc, Vector2 uvd | ||||||
|  |     ) | ||||||
|  |     { | ||||||
|  | 
 | ||||||
|  |       AddTriangle( va, vb, vc, uva, uvb, uvc ); | ||||||
|  |       AddTriangle( vc, vd, va, uvc, uvd, uva ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void AddTriangle( Vector3 va, Vector3 vb, Vector3 vc )     | ||||||
|  |     { | ||||||
|  |       var n  = Vector3.Up; | ||||||
|  |       var uv = Vector2.Zero; | ||||||
|  | 
 | ||||||
|  |       AddTriangle( va, vb, vc,  n, n, n, uv, uv, uv ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void AddQuad(  Vector3 va, Vector3 vb, Vector3 vc, Vector3 vd  ) | ||||||
|  |     { | ||||||
|  |       AddTriangle( va, vb, vc ); | ||||||
|  |       AddTriangle( vc, vd, va ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     public ArrayMesh Generate( Mesh.PrimitiveType type = Mesh.PrimitiveType.Triangles, ArrayMesh arrayMesh = null ) | ||||||
|  |     { | ||||||
|  |       if ( arrayMesh == null ) | ||||||
|  |       { | ||||||
|  |         arrayMesh = new ArrayMesh(); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       var surfaceArray = new Godot.Collections.Array(); | ||||||
|  |       surfaceArray.Resize( (int) Mesh.ArrayType.Max ); | ||||||
|  | 
 | ||||||
|  |       if ( vertices != null ) | ||||||
|  |       { | ||||||
|  |         surfaceArray[ (int) Mesh.ArrayType.Vertex ] = vertices.ToArray(); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if ( normals != null ) | ||||||
|  |       { | ||||||
|  |         surfaceArray[ (int) Mesh.ArrayType.Normal ] = normals.ToArray(); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if ( uvs != null ) | ||||||
|  |       { | ||||||
|  |         surfaceArray[ (int) Mesh.ArrayType.TexUV ] = uvs.ToArray(); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if ( uv2s != null ) | ||||||
|  |       { | ||||||
|  |         surfaceArray[ (int) Mesh.ArrayType.TexUV2 ] = uv2s.ToArray(); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if ( colors != null ) | ||||||
|  |       { | ||||||
|  |         surfaceArray[ (int) Mesh.ArrayType.Color ] = colors.ToArray(); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if ( indices != null ) | ||||||
|  |       { | ||||||
|  |         surfaceArray[ (int) Mesh.ArrayType.Index ] = indices.ToArray(); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       arrayMesh.AddSurfaceFromArrays( Mesh.PrimitiveType.Triangles, surfaceArray ); | ||||||
|  | 
 | ||||||
|  |       return arrayMesh; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -7,7 +7,7 @@ using System; | ||||||
| 
 | 
 | ||||||
| namespace Rokojori | namespace Rokojori | ||||||
| { | { | ||||||
|    public abstract class RandomEngine |   public abstract class RandomEngine | ||||||
|   { |   { | ||||||
|     public abstract float Next(); |     public abstract float Next(); | ||||||
|          |          | ||||||
|  | @ -208,6 +208,106 @@ namespace Rokojori | ||||||
|        |        | ||||||
|       return list[ index ]; |       return list[ index ]; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     public T RemoveFrom<T>( List<T> list ) | ||||||
|  |     { | ||||||
|  |       if ( list.Count == 0 ) | ||||||
|  |       { | ||||||
|  |         return default ( T ); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       var index = this.IntegerExclusive( 0, list.Count ); | ||||||
|  |        | ||||||
|  |       var item = list[ index ]; | ||||||
|  | 
 | ||||||
|  |       list.RemoveAt( index ); | ||||||
|  |       return item;   | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public List<T> RemoveMutlipleFrom<T>( List<T> list, int amount ) | ||||||
|  |     { | ||||||
|  |       if ( amount >= list.Count ) | ||||||
|  |       { | ||||||
|  |         return list; | ||||||
|  |       } | ||||||
|  |        | ||||||
|  |       var items = new List<T>(); | ||||||
|  | 
 | ||||||
|  |       for ( int i = 0; i < amount; i++ ) | ||||||
|  |       { | ||||||
|  |         var itemIndex = this.IntegerExclusive( 0, list.Count ); | ||||||
|  |         var item = list[ itemIndex ]; | ||||||
|  |         list.RemoveAt( itemIndex ); | ||||||
|  |         items.Add( item ); | ||||||
|  |       }       | ||||||
|  | 
 | ||||||
|  |       return items; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public T RemoveWeightedFrom<T>( List<T> list, List<float> weights ) | ||||||
|  |     { | ||||||
|  |       if ( list == null || list.Count == 0 ) | ||||||
|  |       { | ||||||
|  |         return default(T); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if ( list.Count == 1 ) | ||||||
|  |       { | ||||||
|  |         return list[ 0 ]; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       var weightedSelection = RemoveMultipleWeightedFrom( list, weights, 1 ); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |       return weightedSelection[ 0 ]; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public List<T> RemoveMultipleWeightedFrom<T>( List<T> list, List<float> weights, int amount ) | ||||||
|  |     { | ||||||
|  |       if ( amount >= list.Count ) | ||||||
|  |       { | ||||||
|  |         return list; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       var sumWeights = 0f; | ||||||
|  | 
 | ||||||
|  |       weights.ForEach( w => sumWeights += w ); | ||||||
|  | 
 | ||||||
|  |       var selection = new List<T>(); | ||||||
|  | 
 | ||||||
|  |       for ( int i = 0; i < amount; i++ ) | ||||||
|  |       { | ||||||
|  |         var number = Range( 0, sumWeights ); | ||||||
|  | 
 | ||||||
|  |         var index = _FindElementIndexWithWeights( weights, Range( 0, sumWeights ) ); | ||||||
|  |         var element = list[ index ]; | ||||||
|  |         var weight = weights[ index ]; | ||||||
|  |         list.RemoveAt( index ); | ||||||
|  |         sumWeights -= weight; | ||||||
|  |         selection.Add( element ); | ||||||
|  |       }  | ||||||
|  | 
 | ||||||
|  |       return selection; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     int _FindElementIndexWithWeights( List<float> weights, float value ) | ||||||
|  |     { | ||||||
|  |       var limit = 0f; | ||||||
|  | 
 | ||||||
|  |       for ( int i = 0; i < weights.Count; i++ ) | ||||||
|  |       { | ||||||
|  |         var before = limit; | ||||||
|  |         limit += weights[ i ]; | ||||||
|  | 
 | ||||||
|  |         if ( before <= value && value < limit ) | ||||||
|  |         { | ||||||
|  |           return i; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       return weights.Count - 1; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   public abstract class SeedableRandomEngine:RandomEngine |   public abstract class SeedableRandomEngine:RandomEngine | ||||||
|  |  | ||||||
|  | @ -0,0 +1,10 @@ | ||||||
|  | 
 | ||||||
|  | vec3 localToWorld( vec3 _VERTEX, mat4 _MODEL_MATRIX ) | ||||||
|  | { | ||||||
|  |   return ( _MODEL_MATRIX * vec4( _VERTEX, 1.0 ) ).xyz;   | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | vec3 worldToLocal( vec3 _VERTEX, mat4 _MODEL_MATRIX ) | ||||||
|  | { | ||||||
|  |   return ( inverse( _MODEL_MATRIX ) * vec4( _VERTEX, 1.0 ) ).xyz;   | ||||||
|  | } | ||||||
|  | @ -36,6 +36,28 @@ namespace Rokojori | ||||||
|       return list.IndexOf( item ) != - 1; |       return list.IndexOf( item ) != - 1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public static T RemoveAt<T>( List<T> list, int index ) | ||||||
|  |     { | ||||||
|  |       if ( list.Count == 0 || index < 0 ||  ( index > ( list.Count - 1 ) ) ) | ||||||
|  |       {  | ||||||
|  |         return default(T);  | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       var first = list[ index ]; | ||||||
|  |       list.RemoveAt( index ); | ||||||
|  |       return first; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static T RemoveFirst<T>( List<T> list ) | ||||||
|  |     { | ||||||
|  |       return RemoveAt( list, 0 ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static T RemoveLast<T>( List<T> list ) | ||||||
|  |     { | ||||||
|  |       return RemoveAt( list, list.Count - 1 ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public static T Pop<T>( List<T> list ) |     public static T Pop<T>( List<T> list ) | ||||||
|     { |     { | ||||||
|       if ( list.Count == 0 ){ return default(T); } |       if ( list.Count == 0 ){ return default(T); } | ||||||
|  | @ -143,6 +165,23 @@ namespace Rokojori | ||||||
|       return copy; |       return copy; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public static List<U> FilterAndMap<T,U>( List<T> list, Func<T,int,bool> filter, Func<T,U> map) | ||||||
|  |     { | ||||||
|  |       var mapped = new List<U>(); | ||||||
|  |        | ||||||
|  |       for ( int i = 0; i < list.Count; i++ ) | ||||||
|  |       { | ||||||
|  |         if ( ! filter( list[ i ], i ) ) | ||||||
|  |         { | ||||||
|  |           continue; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         mapped.Add( map( list[ i ] ) );  | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       return mapped; | ||||||
|  |     }  | ||||||
|  | 
 | ||||||
|     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++ ) | ||||||
|  | @ -164,7 +203,7 @@ namespace Rokojori | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| 
 |      | ||||||
|     public static List<T> Filter<T>( List<T> inputList, Func<T,bool> filter ) |     public static List<T> Filter<T>( List<T> inputList, Func<T,bool> filter ) | ||||||
|     {       |     {       | ||||||
|       var list = new List<T>(); |       var list = new List<T>(); | ||||||
|  | @ -198,6 +237,24 @@ namespace Rokojori | ||||||
|       ); |       ); | ||||||
| 
 | 
 | ||||||
|       return list; |       return list; | ||||||
|  |     }  | ||||||
|  | 
 | ||||||
|  |     public static void Add<T>( List<T> list, params T[] entries ) | ||||||
|  |     { | ||||||
|  |       list.AddRange( entries ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static void Insert<T>( List<T> list, T item, int index ) | ||||||
|  |     { | ||||||
|  |       if ( index >= list.Count ) | ||||||
|  |       { | ||||||
|  |         list.Add( item ); | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       index = index < 0 ? 0 : index; | ||||||
|  | 
 | ||||||
|  |       list.Insert( index, item ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static T Find<T>( List<T> list, Func<T,bool> callback ) |     public static T Find<T>( List<T> list, Func<T,bool> callback ) | ||||||
|  |  | ||||||
|  | @ -0,0 +1,36 @@ | ||||||
|  | using System.Collections; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System; | ||||||
|  | using System.Reflection; | ||||||
|  | using System.Text.RegularExpressions; | ||||||
|  | 
 | ||||||
|  | namespace Rokojori | ||||||
|  | { | ||||||
|  |   public class Safe | ||||||
|  |   { | ||||||
|  |     static readonly int maxWhileIterations = 1000 * 1000; | ||||||
|  | 
 | ||||||
|  |     public static void While( Func<bool> condition, Action action, Action onTooManyIterations = null ) | ||||||
|  |     { | ||||||
|  |       var it = 0; | ||||||
|  | 
 | ||||||
|  |       while ( it < Safe.maxWhileIterations && condition() ) | ||||||
|  |       { | ||||||
|  |         action(); | ||||||
|  |         it++; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if ( it >= Safe.maxWhileIterations ) | ||||||
|  |       { | ||||||
|  |         RJLog.LogWithFullTrace( "Loop with too many iterations" ); | ||||||
|  | 
 | ||||||
|  |         if ( onTooManyIterations != null ) | ||||||
|  |         { | ||||||
|  |           onTooManyIterations(); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -67,13 +67,13 @@ namespace Rokojori | ||||||
|       var maxWidth = 0f; |       var maxWidth = 0f; | ||||||
|       var maxHeight = 0f; |       var maxHeight = 0f; | ||||||
| 
 | 
 | ||||||
|       if ( UINumber.IsNullOrNone( region.width ) ) |       if ( UINumber.IsNullOrNone( UIStyle.Width( region ) ) ) | ||||||
|       { |       { | ||||||
|         lines.ForEach( l => { maxWidth = Mathf.Max( maxWidth, l.maxX ); } ); |         lines.ForEach( l => { maxWidth = Mathf.Max( maxWidth, l.maxX ); } ); | ||||||
|       } |       } | ||||||
|       else |       else | ||||||
|       { |       { | ||||||
|         maxWidth = UINumber.Compute( region, region.width );  |         maxWidth = UINumber.Compute( region, UIStyle.Width( region ) );  | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       if ( lines.Count > 0 ) |       if ( lines.Count > 0 ) | ||||||
|  | @ -81,12 +81,12 @@ namespace Rokojori | ||||||
|         maxHeight = lines[ lines.Count - 1 ].maxY; |         maxHeight = lines[ lines.Count - 1 ].maxY; | ||||||
|       }   |       }   | ||||||
| 
 | 
 | ||||||
|       var margin     = UINumber.Compute( region, region.margin, 0 ); |       var margin     = UINumber.Compute( region, UIStyle.Margin( region ), 0 ); | ||||||
|       var marginLeft = margin + UINumber.Compute( region, region.marginLeft, 0 ); |       var marginLeft = margin + UINumber.Compute( region, UIStyle.MarginLeft( region ), 0 ); | ||||||
|       var marginTop  = margin + UINumber.Compute( region, region.marginTop, 0 );  |       var marginTop  = margin + UINumber.Compute( region, UIStyle.MarginTop( region ), 0 );  | ||||||
| 
 | 
 | ||||||
|       var marginRight = margin + UINumber.Compute( region, region.marginRight, 0 ); |       var marginRight = margin + UINumber.Compute( region, UIStyle.MarginRight( region ), 0 ); | ||||||
|       var marginBottom = margin + UINumber.Compute( region, region.marginBottom, 0 );  |       var marginBottom = margin + UINumber.Compute( region, UIStyle.MarginBottom( region ), 0 );  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|       var marginOffset = new Vector2( marginLeft, marginTop ); |       var marginOffset = new Vector2( marginLeft, marginTop ); | ||||||
|  | @ -98,46 +98,38 @@ namespace Rokojori | ||||||
| 
 | 
 | ||||||
|       region.Size = new Vector2( maxWidth + horizontalMargins, maxHeight + verticalMargins ); |       region.Size = new Vector2( maxWidth + horizontalMargins, maxHeight + verticalMargins ); | ||||||
| 
 | 
 | ||||||
|       if ( region.position == UIPosition.Parent_Anchor ) |       if ( UIStyle.Position( region ) == UIPosition.Parent_Anchor ) | ||||||
|       { |       { | ||||||
|         var p = NodesWalker.Get().Parent( region ) as Control; |         UILayouting.SetPositionInParentAnchor( region ); | ||||||
| 
 |  | ||||||
|         if ( p != null ) |  | ||||||
|         { |  | ||||||
|           var pWidth = UILayouting.GetWidth( p ); |  | ||||||
|           var pHeight = UILayouting.GetHeight( p );    |  | ||||||
|            |  | ||||||
|           var x = p.Position.X; |  | ||||||
|           var y = p.Position.Y; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|           if ( ! UINumber.IsNullOrNone( region.left )) |  | ||||||
|           { |  | ||||||
|             var left  = UINumber.Compute( region, region.left, 0 ); |  | ||||||
|             x = left; |  | ||||||
|           } |  | ||||||
|           else if ( ! UINumber.IsNullOrNone( region.right ) ) |  | ||||||
|           { |  | ||||||
|             var right  = UINumber.Compute( region, region.right, 0 ); |  | ||||||
|             x = ( pWidth - UILayouting.GetWidth( region ) ) - right; |  | ||||||
|           } |  | ||||||
| 
 |  | ||||||
|           UILayouting.SetPosition( region, new Vector2( x, y ) ); |  | ||||||
| 
 |  | ||||||
|         } |  | ||||||
|          |  | ||||||
|       } |       } | ||||||
|  | 
 | ||||||
|  |       Nodes.ForEachDirectChild<Control>( region, | ||||||
|  |         child => | ||||||
|  |         { | ||||||
|  |            | ||||||
|  |           var styleContainer = child as UIStylePropertyContainer; | ||||||
|  | 
 | ||||||
|  |           if ( styleContainer == null || UIStyle.Position( styleContainer ) != UIPosition.Parent_Anchor ) | ||||||
|  |           { | ||||||
|  |             return; | ||||||
|  |           } | ||||||
|  | 
 | ||||||
|  |           UILayouting.UpdateChild( child ); | ||||||
|  |           UILayouting.SetPositionInParentAnchor( styleContainer ); | ||||||
|  |            | ||||||
|  |         } | ||||||
|  |       ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     static List<Line> CreateLines( UIRegion region ) |     static List<Line> CreateLines( UIRegion region ) | ||||||
|     { |     { | ||||||
|       var x = 0f; |       var x = 0f; | ||||||
|       var width = UINumber.Compute( region, region.width, 100000000f ); |       var width = UINumber.Compute( region, UIStyle.Width( region ), 100000000f ); | ||||||
| 
 | 
 | ||||||
|       var lines = new List<Line>(); |       var lines = new List<Line>(); | ||||||
|       var currentLine = new Line(); |       var currentLine = new Line(); | ||||||
| 
 | 
 | ||||||
|       var elementSpacing = UINumber.Compute( region, region.elementSpacing, 0f ); |       var elementSpacing = UINumber.Compute( region, UIStyle.ElementSpacing( region ), 0f ); | ||||||
| 
 | 
 | ||||||
|       Nodes.ForEachDirectChild<Control>( region, c => UILayouting.UpdateChild( c ) ); |       Nodes.ForEachDirectChild<Control>( region, c => UILayouting.UpdateChild( c ) ); | ||||||
|        |        | ||||||
|  | @ -146,6 +138,13 @@ namespace Rokojori | ||||||
|         child => |         child => | ||||||
|         { |         { | ||||||
|            |            | ||||||
|  |           var styleContainer = child as UIStylePropertyContainer; | ||||||
|  | 
 | ||||||
|  |           if ( styleContainer != null && UIStyle.Position( styleContainer ) == UIPosition.Parent_Anchor ) | ||||||
|  |           { | ||||||
|  |             return; | ||||||
|  |           } | ||||||
|  |            | ||||||
|           var cWidth  = UILayouting.GetWidth( child ); |           var cWidth  = UILayouting.GetWidth( child ); | ||||||
|           var cHeight = UILayouting.GetHeight( child ); |           var cHeight = UILayouting.GetHeight( child ); | ||||||
| 
 | 
 | ||||||
|  | @ -193,13 +192,13 @@ namespace Rokojori | ||||||
| 
 | 
 | ||||||
|       lines.ForEach(  line => AdjustVerticalAlignment( region, line, verticalAlignment ) ); |       lines.ForEach(  line => AdjustVerticalAlignment( region, line, verticalAlignment ) ); | ||||||
| 
 | 
 | ||||||
|       if ( UINumber.IsNullOrNone( region.width ) ) |       if ( UINumber.IsNullOrNone( UIStyle.Width( region ) ) ) | ||||||
|       { |       { | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       var horizontalAlignment = UINumber.Compute( region, region.horizontalAlignment, 0.5f, 1 ); |       var horizontalAlignment = UINumber.Compute( region, region.horizontalAlignment, 0.5f, 1 ); | ||||||
|       var maxWidth = UINumber.Compute( region, region.width, 0 ); |       var maxWidth = UINumber.Compute( region, UIStyle.Width( region ), 0 ); | ||||||
| 
 | 
 | ||||||
|       lines.ForEach( line => AdjustHorizontalAlignment( region, line, horizontalAlignment, maxWidth ) ); |       lines.ForEach( line => AdjustHorizontalAlignment( region, line, horizontalAlignment, maxWidth ) ); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -40,6 +40,45 @@ namespace Rokojori | ||||||
|       UILayouting.UpdatePivot( control ); |       UILayouting.UpdatePivot( control ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public static void SetPositionInParentAnchor( UIStylePropertyContainer region ) | ||||||
|  |     { | ||||||
|  |       var control = (Control) region; | ||||||
|  |       var p = NodesWalker.Get().Parent( control ) as Control; | ||||||
|  |        | ||||||
|  |       var pWidth  = p == null ? UI.GetWindowWidth( control ) : UILayouting.GetWidth( p ); | ||||||
|  |       var pHeight = p == null ? UI.GetWindowHeight( control ) : UILayouting.GetHeight( p );    | ||||||
|  |        | ||||||
|  |       var x = p.Position.X; | ||||||
|  |       var y = p.Position.Y; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |       if ( ! UINumber.IsNullOrNone( UIStyle.Left( region ) )) | ||||||
|  |       { | ||||||
|  |         var left  = UINumber.Compute( control, UIStyle.Left( region ), 0 ); | ||||||
|  |         x = left; | ||||||
|  |       } | ||||||
|  |       else if ( ! UINumber.IsNullOrNone( UIStyle.Right( region ) ) ) | ||||||
|  |       { | ||||||
|  |         var right  = UINumber.Compute( control, UIStyle.Right( region ), 0 ); | ||||||
|  |         x = ( pWidth - UILayouting.GetWidth( control ) ) - right; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       if ( ! UINumber.IsNullOrNone( UIStyle.Top( region ) )) | ||||||
|  |       { | ||||||
|  |         var top  = UINumber.Compute( control, UIStyle.Top( region ), 0 ); | ||||||
|  |         y = top; | ||||||
|  |       } | ||||||
|  |       else if ( ! UINumber.IsNullOrNone( UIStyle.Bottom( region ) ) ) | ||||||
|  |       { | ||||||
|  |         var bottom  = UINumber.Compute( control, UIStyle.Bottom( region ), 0 ); | ||||||
|  |         y = ( pHeight - UILayouting.GetHeight( control ) ) - bottom; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       UILayouting.SetPosition( control, new Vector2( x, y ) ); | ||||||
|  | 
 | ||||||
|  |        | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public static void UpdatePivot( Control c ) |     public static void UpdatePivot( Control c ) | ||||||
|     { |     { | ||||||
|       if ( ! ( c is UIImage || c is UIRegion || c is UIText ) ) |       if ( ! ( c is UIImage || c is UIRegion || c is UIText ) ) | ||||||
|  | @ -49,8 +88,8 @@ namespace Rokojori | ||||||
| 
 | 
 | ||||||
|       var container = c as UIStylePropertyContainer; |       var container = c as UIStylePropertyContainer; | ||||||
| 
 | 
 | ||||||
|       var pivotX  = UINumber.Compute( c, UIStyle.PivotX( container ), 0, c.Size.X ); |       var pivotX  = UINumber.Compute( c, UIStyle.PivotX( container ), 0.5f * c.Size.X, c.Size.X ); | ||||||
|       var pivotY  = UINumber.Compute( c, UIStyle.PivotY( container ), 0, c.Size.Y ); |       var pivotY  = UINumber.Compute( c, UIStyle.PivotY( container ), 0.5f * c.Size.Y, c.Size.Y ); | ||||||
| 
 | 
 | ||||||
|       c.PivotOffset = new Vector2( pivotX, pivotY ); |       c.PivotOffset = new Vector2( pivotX, pivotY ); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,6 +8,9 @@ namespace Rokojori | ||||||
|   [GlobalClass] |   [GlobalClass] | ||||||
|   public partial class UIImage:TextureRect, UIStylePropertyContainer |   public partial class UIImage:TextureRect, UIStylePropertyContainer | ||||||
|   {  |   {  | ||||||
|  |     [Export] | ||||||
|  |     public UIStyle parentStyle; | ||||||
|  | 
 | ||||||
|     [ExportCategory("Size & Margins")] |     [ExportCategory("Size & Margins")] | ||||||
|     [Export] |     [Export] | ||||||
|     public UINumber width; |     public UINumber width; | ||||||
|  | @ -60,6 +63,16 @@ namespace Rokojori | ||||||
|     public UINumber scaleY; |     public UINumber scaleY; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |     public UIStyle GetUIStyleParent() | ||||||
|  |     { | ||||||
|  |       return parentStyle; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public UIPosition GetUIPosition() | ||||||
|  |     { | ||||||
|  |       return position; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public UINumber GetUIStyleNumberProperty( UIStyleNumberProperty property ) |     public UINumber GetUIStyleNumberProperty( UIStyleNumberProperty property ) | ||||||
|     { |     { | ||||||
|       switch ( property ) |       switch ( property ) | ||||||
|  |  | ||||||
|  | @ -8,9 +8,9 @@ namespace Rokojori | ||||||
|   public partial class UIRegion : Control, UIStylePropertyContainer |   public partial class UIRegion : Control, UIStylePropertyContainer | ||||||
|   {    |   {    | ||||||
|     [Export] |     [Export] | ||||||
|     public UIStyle parent; |     public UIStyle parentStyle; | ||||||
| 
 | 
 | ||||||
|     [ExportCategory("Layout")] |     [ExportCategory( "Layout" )] | ||||||
|     [Export] |     [Export] | ||||||
|     public UILayout layout;         |     public UILayout layout;         | ||||||
| 
 | 
 | ||||||
|  | @ -25,7 +25,7 @@ namespace Rokojori | ||||||
|     public UINumber lineSpacing; |     public UINumber lineSpacing; | ||||||
| 
 | 
 | ||||||
|      |      | ||||||
|     [ExportCategory("Size & Margins")] |     [ExportCategory( "Size & Margins" )] | ||||||
|     [Export] |     [Export] | ||||||
|     public UINumber width; |     public UINumber width; | ||||||
|     [Export] |     [Export] | ||||||
|  | @ -44,7 +44,27 @@ namespace Rokojori | ||||||
|     [Export]  |     [Export]  | ||||||
|     public UINumber marginBottom; |     public UINumber marginBottom; | ||||||
| 
 | 
 | ||||||
|     [ExportCategory("Position")] |     [ExportCategory( "Font" )] | ||||||
|  |     [Export] | ||||||
|  |     public Font font; | ||||||
|  |     [Export] | ||||||
|  |     public UINumber fontSize; | ||||||
|  |     [Export] | ||||||
|  |     public UIColor fontColor; | ||||||
|  | 
 | ||||||
|  |     [Export] | ||||||
|  |     public UINumber outlineSize; | ||||||
|  |     [Export] | ||||||
|  |     public UIColor outlineColor; | ||||||
|  | 
 | ||||||
|  |     [Export] | ||||||
|  |     public UINumber shadowSize; | ||||||
|  |     [Export] | ||||||
|  |     public UIColor shadowColor; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     [ExportCategory( "Position" )] | ||||||
|     [Export] |     [Export] | ||||||
|     public UIPosition position; |     public UIPosition position; | ||||||
|     [Export] |     [Export] | ||||||
|  | @ -57,6 +77,16 @@ namespace Rokojori | ||||||
|     public UINumber bottom; |     public UINumber bottom; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |     public UIStyle GetUIStyleParent() | ||||||
|  |     { | ||||||
|  |       return parentStyle; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public UIPosition GetUIPosition() | ||||||
|  |     { | ||||||
|  |       return position; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public UINumber GetUIStyleNumberProperty( UIStyleNumberProperty property ) |     public UINumber GetUIStyleNumberProperty( UIStyleNumberProperty property ) | ||||||
|     { |     { | ||||||
|       switch ( property ) |       switch ( property ) | ||||||
|  | @ -69,6 +99,10 @@ namespace Rokojori | ||||||
|         case UIStyleNumberProperty.Width:  return width; |         case UIStyleNumberProperty.Width:  return width; | ||||||
|         case UIStyleNumberProperty.Height: return height; |         case UIStyleNumberProperty.Height: return height; | ||||||
| 
 | 
 | ||||||
|  |          | ||||||
|  |         case UIStyleNumberProperty.ElementSpacing: return elementSpacing; | ||||||
|  |         case UIStyleNumberProperty.LineSpacing:    return lineSpacing; | ||||||
|  | 
 | ||||||
|         case UIStyleNumberProperty.Margin:       return margin; |         case UIStyleNumberProperty.Margin:       return margin; | ||||||
| 
 | 
 | ||||||
|         case UIStyleNumberProperty.MarginLeft:   return marginLeft; |         case UIStyleNumberProperty.MarginLeft:   return marginLeft; | ||||||
|  |  | ||||||
|  | @ -8,6 +8,12 @@ namespace Rokojori | ||||||
|   [GlobalClass] |   [GlobalClass] | ||||||
|   public partial class UIText:Label,UIStylePropertyContainer |   public partial class UIText:Label,UIStylePropertyContainer | ||||||
|   { |   { | ||||||
|  |     [Export] | ||||||
|  |     public UIStyle parentStyle; | ||||||
|  | 
 | ||||||
|  |     [Export] | ||||||
|  |     public UINumber fontSize; | ||||||
|  | 
 | ||||||
|     [ExportCategory("Size & Margins")] |     [ExportCategory("Size & Margins")] | ||||||
|     [Export] |     [Export] | ||||||
|     public UINumber width; |     public UINumber width; | ||||||
|  | @ -59,6 +65,15 @@ namespace Rokojori | ||||||
|     [Export] |     [Export] | ||||||
|     public UINumber scaleY; |     public UINumber scaleY; | ||||||
| 
 | 
 | ||||||
|  |     public UIStyle GetUIStyleParent() | ||||||
|  |     { | ||||||
|  |       return parentStyle; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public UIPosition GetUIPosition() | ||||||
|  |     { | ||||||
|  |       return position; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     public UINumber GetUIStyleNumberProperty( UIStyleNumberProperty property ) |     public UINumber GetUIStyleNumberProperty( UIStyleNumberProperty property ) | ||||||
|     { |     { | ||||||
|  |  | ||||||
|  | @ -0,0 +1,15 @@ | ||||||
|  | 
 | ||||||
|  | using Godot; | ||||||
|  | using Rokojori; | ||||||
|  |   | ||||||
|  | namespace Rokojori | ||||||
|  | {  | ||||||
|  | 
 | ||||||
|  |   [Tool] | ||||||
|  |   [GlobalClass]  | ||||||
|  |   public partial class UIColor : Resource | ||||||
|  |   {  | ||||||
|  |     [Export] | ||||||
|  |     public Color color; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -34,6 +34,7 @@ namespace Rokojori | ||||||
|       return number.IsNone; |       return number.IsNone; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |      | ||||||
|     public static float Compute( Control control, UINumber number, float alternative = 0, float relative = 100 ) |     public static float Compute( Control control, UINumber number, float alternative = 0, float relative = 100 ) | ||||||
|     { |     { | ||||||
|       if ( number == null || control == null || number.IsNone ) |       if ( number == null || control == null || number.IsNone ) | ||||||
|  | @ -41,19 +42,9 @@ namespace Rokojori | ||||||
|         return alternative; |         return alternative; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       var width = 0; |       var width  = UI.GetWindowWidth( control ); | ||||||
|       var height = 0; |       var height = UI.GetWindowHeight( control ); | ||||||
| 
 | 
 | ||||||
|       if ( Engine.IsEditorHint() ) |  | ||||||
|       { |  | ||||||
|         width  = ProjectSettings.GetSetting( "display/window/size/viewport_width" ).AsInt32(); |  | ||||||
|         height = ProjectSettings.GetSetting( "display/window/size/viewport_height" ).AsInt32(); |  | ||||||
|       } |  | ||||||
|       else |  | ||||||
|       { |  | ||||||
|         width  = control.GetWindow().Size.X; |  | ||||||
|         height = control.GetWindow().Size.Y; |  | ||||||
|       } |  | ||||||
| 
 | 
 | ||||||
|       return Compute( control, number, width, height, relative ); |       return Compute( control, number, width, height, relative ); | ||||||
|        |        | ||||||
|  | @ -75,7 +66,7 @@ namespace Rokojori | ||||||
| 
 | 
 | ||||||
|       if ( _ui == null ) |       if ( _ui == null ) | ||||||
|       { |       { | ||||||
|        // _ui = NodesWalker.Get().GetParent( control, n => n is UI ) as UI; |         _ui = NodesWalker.Get().GetInParents( control, n => n is UI ) as UI; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       switch ( number.unit ) |       switch ( number.unit ) | ||||||
|  | @ -95,6 +86,18 @@ namespace Rokojori | ||||||
|           return number.value * height / 100f; |           return number.value * height / 100f; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         case "pw": | ||||||
|  |         { | ||||||
|  |           var parent = control.GetParent<Control>(); | ||||||
|  |           return number.value / 100f * ( parent == null ?  width : parent.Size.X ); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         case "ph": | ||||||
|  |         { | ||||||
|  |           var parent = control.GetParent<Control>(); | ||||||
|  |           return number.value / 100f * ( parent == null ?  height : parent.Size.Y ); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         case "px": case "": |         case "px": case "": | ||||||
|         { |         { | ||||||
|           return number.value; |           return number.value; | ||||||
|  | @ -110,17 +113,25 @@ namespace Rokojori | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|       var expressionText = number.unit == null ? "" : RegexUtility.Replace( number.unit, "%", " * relative " );  |       var expressionText = number.unit == null ? "" : RegexUtility.Replace( number.unit, "%", " * relative " );  | ||||||
|       var parseResult = expression.Parse( expressionText, new string[]{ "em","vw", "vh", "px", "relative", "value" } ); |       var parseResult = expression.Parse( expressionText,  | ||||||
|  |         new string[] | ||||||
|  |         {  | ||||||
|  |           "em","vw", "vh", "pw", "ph", "px", "relative", "value" }  | ||||||
|  |         ); | ||||||
| 
 | 
 | ||||||
|       if ( Error.Ok != parseResult ) |       if ( Error.Ok != parseResult ) | ||||||
|       { |       { | ||||||
|         return 0; |         return 0; | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|  |       var parentControl = control.GetParent<Control>(); | ||||||
|  | 
 | ||||||
|       var inputs = new Godot.Collections.Array(); |       var inputs = new Godot.Collections.Array(); | ||||||
|       inputs.Add( em() ); |       inputs.Add( em() ); | ||||||
|       inputs.Add( width / 100f ); |       inputs.Add( width / 100f ); | ||||||
|       inputs.Add( height / 100f ); |       inputs.Add( height / 100f ); | ||||||
|  |       inputs.Add( ( parentControl == null ? width : parentControl.Size.X ) / 100f ); | ||||||
|  |       inputs.Add( ( parentControl == null ? height : parentControl.Size.Y ) / 100f ); | ||||||
|       inputs.Add( 1 );       |       inputs.Add( 1 );       | ||||||
|       inputs.Add( relative / 100f ); |       inputs.Add( relative / 100f ); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ namespace Rokojori | ||||||
| {  | {  | ||||||
|   public enum UIPosition |   public enum UIPosition | ||||||
|   { |   { | ||||||
|  |     ___, | ||||||
|     From_Layout, |     From_Layout, | ||||||
|     Parent_Anchor |     Parent_Anchor | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -7,106 +7,236 @@ namespace Rokojori | ||||||
| 
 | 
 | ||||||
|   [Tool] |   [Tool] | ||||||
|   [GlobalClass]  |   [GlobalClass]  | ||||||
|   public partial class UIStyle:Resource |   public partial class UIStyle:Resource, UIStylePropertyContainer | ||||||
|   { |   { | ||||||
|     [Export] |     [Export] | ||||||
|     public UIStyle parent; |     public UIStyle parentStyle; | ||||||
|    |  | ||||||
|     [Export] |  | ||||||
|     public UILayout layoutType; |  | ||||||
| 
 | 
 | ||||||
|     [ExportCategory("Width")] |     [ExportCategory( "Layout" )] | ||||||
|     [Export] |     [Export] | ||||||
|     public float widthValue = 1; |     public UILayout layout;         | ||||||
|     [Export] |  | ||||||
|     public string widthUnit = "vw"; |  | ||||||
| 
 | 
 | ||||||
|     [ExportCategory("Height")] |  | ||||||
|     [Export] |     [Export] | ||||||
|     public float heightValue = 1; |     public UINumber horizontalAlignment; | ||||||
|     [Export] |     [Export] | ||||||
|     public string heightUnit = "vw"; |     public UINumber verticalAlignment; | ||||||
| 
 | 
 | ||||||
|     [ExportCategory("LineSpacing")] |  | ||||||
|     [Export] |     [Export] | ||||||
|     public float lineSpacingValue = 1; |     public UINumber elementSpacing; | ||||||
|     [Export] |     [Export] | ||||||
|     public string ineSpacingtUnit = "vw"; |     public UINumber lineSpacing; | ||||||
|  | 
 | ||||||
|  |      | ||||||
|  |     [ExportCategory( "Size & Margins" )] | ||||||
|  |     [Export] | ||||||
|  |     public UINumber width; | ||||||
|  |     [Export] | ||||||
|  |     public UINumber height; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     [Export]  | ||||||
|  |     public UINumber margin; | ||||||
|  | 
 | ||||||
|  |     [Export]  | ||||||
|  |     public UINumber marginLeft; | ||||||
|  |     [Export]  | ||||||
|  |     public UINumber marginTop; | ||||||
|  |     [Export]  | ||||||
|  |     public UINumber marginRight; | ||||||
|  |     [Export]  | ||||||
|  |     public UINumber marginBottom; | ||||||
|  | 
 | ||||||
|  |     [ExportCategory( "Font" )] | ||||||
|  |     [Export] | ||||||
|  |     public Font font; | ||||||
|  |     [Export] | ||||||
|  |     public UINumber fontSize; | ||||||
|  |     [Export] | ||||||
|  |     public UIColor fontColor; | ||||||
|  | 
 | ||||||
|  |     [Export] | ||||||
|  |     public UINumber outlineSize; | ||||||
|  |     [Export] | ||||||
|  |     public UIColor outlineColor; | ||||||
|  | 
 | ||||||
|  |     [Export] | ||||||
|  |     public UINumber shadowSize; | ||||||
|  |     [Export] | ||||||
|  |     public UIColor shadowColor; | ||||||
|  | 
 | ||||||
|  |     [ExportCategory( "Position" )] | ||||||
|  |     [Export] | ||||||
|  |     public UIPosition position; | ||||||
|  |     [Export] | ||||||
|  |     public UINumber left; | ||||||
|  |     [Export] | ||||||
|  |     public UINumber top; | ||||||
|  |     [Export] | ||||||
|  |     public UINumber right; | ||||||
|  |     [Export] | ||||||
|  |     public UINumber bottom; | ||||||
|     |     | ||||||
|  |     public UIStyle GetUIStyleParent() | ||||||
|  |     { | ||||||
|  |       return parentStyle; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public UIPosition GetUIPosition() | ||||||
|  |     { | ||||||
|  |       return position; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public UINumber GetUIStyleNumberProperty( UIStyleNumberProperty property ) | ||||||
|  |     { | ||||||
|  |       switch ( property ) | ||||||
|  |       { | ||||||
|  |         case UIStyleNumberProperty.Left:   return left; | ||||||
|  |         case UIStyleNumberProperty.Right:  return right; | ||||||
|  |         case UIStyleNumberProperty.Top:    return top; | ||||||
|  |         case UIStyleNumberProperty.Bottom: return bottom; | ||||||
|  | 
 | ||||||
|  |         case UIStyleNumberProperty.ElementSpacing: return elementSpacing; | ||||||
|  |         case UIStyleNumberProperty.LineSpacing:    return lineSpacing; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         case UIStyleNumberProperty.Width:  return width; | ||||||
|  |         case UIStyleNumberProperty.Height: return height; | ||||||
|  | 
 | ||||||
|  |         case UIStyleNumberProperty.Margin:       return margin; | ||||||
|  | 
 | ||||||
|  |         case UIStyleNumberProperty.MarginLeft:   return marginLeft; | ||||||
|  |         case UIStyleNumberProperty.MarginRight:  return marginRight; | ||||||
|  |         case UIStyleNumberProperty.MarginTop:    return marginTop; | ||||||
|  |         case UIStyleNumberProperty.MarginBottom: return marginBottom; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       return null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static UINumber GetReferenceableNumberProperty( UIStylePropertyContainer container, UIStyleNumberProperty property ) | ||||||
|  |     { | ||||||
|  |       if ( container == null ) | ||||||
|  |       { | ||||||
|  |         return null; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       var ownProperty = container.GetUIStyleNumberProperty( property ); | ||||||
|  | 
 | ||||||
|  |       if ( ownProperty != null ) | ||||||
|  |       { | ||||||
|  |         return ownProperty; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       var style = container.GetUIStyleParent(); | ||||||
|  | 
 | ||||||
|  |       return GetReferenceableNumberProperty( style, property ); | ||||||
|  |     }  | ||||||
|  | 
 | ||||||
|  |     public static UIPosition Position( UIStylePropertyContainer container ) | ||||||
|  |     { | ||||||
|  |       var ownProperty = container.GetUIPosition(); | ||||||
|  | 
 | ||||||
|  |       if ( ownProperty != UIPosition.___ ) | ||||||
|  |       { | ||||||
|  |         return ownProperty; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       return container.GetUIPosition(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static UINumber Width( UIStylePropertyContainer container ) | ||||||
|  |     { | ||||||
|  |       return GetReferenceableNumberProperty( container, UIStyleNumberProperty.Width ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static UINumber Height( UIStylePropertyContainer container ) | ||||||
|  |     { | ||||||
|  |       return GetReferenceableNumberProperty( container, UIStyleNumberProperty.Height ); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     public static UINumber Left( UIStylePropertyContainer container ) |     public static UINumber Left( UIStylePropertyContainer container ) | ||||||
|     { |     { | ||||||
|       return container.GetUIStyleNumberProperty( UIStyleNumberProperty.Left ); |       return GetReferenceableNumberProperty( container, UIStyleNumberProperty.Left ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static UINumber Right( UIStylePropertyContainer container ) |     public static UINumber Right( UIStylePropertyContainer container ) | ||||||
|     { |     { | ||||||
|       return container.GetUIStyleNumberProperty( UIStyleNumberProperty.Right ); |       return GetReferenceableNumberProperty( container, UIStyleNumberProperty.Right ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static UINumber Top( UIStylePropertyContainer container ) |     public static UINumber Top( UIStylePropertyContainer container ) | ||||||
|     { |     { | ||||||
|       return container.GetUIStyleNumberProperty( UIStyleNumberProperty.Top ); |       return GetReferenceableNumberProperty( container, UIStyleNumberProperty.Top ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static UINumber Bottom( UIStylePropertyContainer container ) |     public static UINumber Bottom( UIStylePropertyContainer container ) | ||||||
|     { |     { | ||||||
|       return container.GetUIStyleNumberProperty( UIStyleNumberProperty.Bottom ); |       return GetReferenceableNumberProperty( container, UIStyleNumberProperty.Bottom ); | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     public static UINumber Margin( UIStylePropertyContainer container ) |     public static UINumber Margin( UIStylePropertyContainer container ) | ||||||
|     { |     { | ||||||
|       return container.GetUIStyleNumberProperty( UIStyleNumberProperty.Margin ); |       return GetReferenceableNumberProperty( container, UIStyleNumberProperty.Margin ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static UINumber MarginLeft( UIStylePropertyContainer container ) |     public static UINumber MarginLeft( UIStylePropertyContainer container ) | ||||||
|     { |     { | ||||||
|       return container.GetUIStyleNumberProperty( UIStyleNumberProperty.MarginLeft ); |       return GetReferenceableNumberProperty( container, UIStyleNumberProperty.MarginLeft ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static UINumber MarginRight( UIStylePropertyContainer container ) |     public static UINumber MarginRight( UIStylePropertyContainer container ) | ||||||
|     { |     { | ||||||
|       return container.GetUIStyleNumberProperty( UIStyleNumberProperty.MarginRight ); |       return GetReferenceableNumberProperty( container, UIStyleNumberProperty.MarginRight ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static UINumber MarginTop( UIStylePropertyContainer container ) |     public static UINumber MarginTop( UIStylePropertyContainer container ) | ||||||
|     { |     { | ||||||
|       return container.GetUIStyleNumberProperty( UIStyleNumberProperty.MarginTop ); |       return GetReferenceableNumberProperty( container, UIStyleNumberProperty.MarginTop ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static UINumber MarginBottom( UIStylePropertyContainer container ) |     public static UINumber MarginBottom( UIStylePropertyContainer container ) | ||||||
|     { |     { | ||||||
|       return container.GetUIStyleNumberProperty( UIStyleNumberProperty.MarginBottom ); |       return GetReferenceableNumberProperty( container, UIStyleNumberProperty.MarginBottom ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static UINumber PivotX( UIStylePropertyContainer container ) |     public static UINumber PivotX( UIStylePropertyContainer container ) | ||||||
|     { |     { | ||||||
|       return container.GetUIStyleNumberProperty( UIStyleNumberProperty.PivotX ); |       return GetReferenceableNumberProperty( container, UIStyleNumberProperty.PivotX ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static UINumber PivotY( UIStylePropertyContainer container ) |     public static UINumber PivotY( UIStylePropertyContainer container ) | ||||||
|     { |     { | ||||||
|       return container.GetUIStyleNumberProperty( UIStyleNumberProperty.PivotY ); |       return GetReferenceableNumberProperty( container, UIStyleNumberProperty.PivotY ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static UINumber Rotation( UIStylePropertyContainer container ) |     public static UINumber Rotation( UIStylePropertyContainer container ) | ||||||
|     { |     { | ||||||
|       return container.GetUIStyleNumberProperty( UIStyleNumberProperty.Rotation ); |       return GetReferenceableNumberProperty( container, UIStyleNumberProperty.Rotation ); | ||||||
|     } |     } | ||||||
|   |   | ||||||
|     public static UINumber Scale( UIStylePropertyContainer container ) |     public static UINumber Scale( UIStylePropertyContainer container ) | ||||||
|     { |     { | ||||||
|       return container.GetUIStyleNumberProperty( UIStyleNumberProperty.Scale ); |       return GetReferenceableNumberProperty( container, UIStyleNumberProperty.Scale ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static UINumber ScaleX( UIStylePropertyContainer container ) |     public static UINumber ScaleX( UIStylePropertyContainer container ) | ||||||
|     { |     { | ||||||
|       return container.GetUIStyleNumberProperty( UIStyleNumberProperty.ScaleX ); |       return GetReferenceableNumberProperty( container, UIStyleNumberProperty.ScaleX ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static UINumber ScaleY( UIStylePropertyContainer container ) |     public static UINumber ScaleY( UIStylePropertyContainer container ) | ||||||
|     { |     { | ||||||
|       return container.GetUIStyleNumberProperty( UIStyleNumberProperty.ScaleY ); |       return GetReferenceableNumberProperty( container, UIStyleNumberProperty.ScaleY ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static UINumber ElementSpacing( UIStylePropertyContainer container ) | ||||||
|  |     { | ||||||
|  |       return GetReferenceableNumberProperty( container, UIStyleNumberProperty.ElementSpacing ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static UINumber LineSpacing( UIStylePropertyContainer container ) | ||||||
|  |     { | ||||||
|  |       return GetReferenceableNumberProperty( container, UIStyleNumberProperty.LineSpacing ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -14,6 +14,9 @@ namespace Rokojori | ||||||
|     Width, |     Width, | ||||||
|     Height, |     Height, | ||||||
| 
 | 
 | ||||||
|  |     ElementSpacing, | ||||||
|  |     LineSpacing, | ||||||
|  | 
 | ||||||
|     Margin, |     Margin, | ||||||
|     MarginLeft, |     MarginLeft, | ||||||
|     MarginRight, |     MarginRight, | ||||||
|  | @ -27,6 +30,17 @@ namespace Rokojori | ||||||
| 
 | 
 | ||||||
|     Scale, |     Scale, | ||||||
|     ScaleX, |     ScaleX, | ||||||
|     ScaleY |     ScaleY, | ||||||
|  | 
 | ||||||
|  |     FontSize, | ||||||
|  |     FontOutlineSize, | ||||||
|  |     FontShadowSize | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   public enum UIStyleColorProperty | ||||||
|  |   { | ||||||
|  |     FontColor, | ||||||
|  |     FontOutlineColor, | ||||||
|  |     FontShadowColor | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | @ -6,6 +6,9 @@ namespace Rokojori | ||||||
| {  | {  | ||||||
|   public interface UIStylePropertyContainer |   public interface UIStylePropertyContainer | ||||||
|   { |   { | ||||||
|  |     UIStyle GetUIStyleParent(); | ||||||
|  | 
 | ||||||
|  |     UIPosition GetUIPosition(); | ||||||
|     UINumber GetUIStyleNumberProperty( UIStyleNumberProperty property ); |     UINumber GetUIStyleNumberProperty( UIStyleNumberProperty property ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | @ -29,7 +29,7 @@ namespace Rokojori | ||||||
|       UpdateUIElements(); |       UpdateUIElements(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|          | 
 | ||||||
| 
 | 
 | ||||||
|     void UpdateFontSize() |     void UpdateFontSize() | ||||||
|     { |     { | ||||||
|  | @ -53,6 +53,30 @@ namespace Rokojori | ||||||
|       Nodes.ForEachDirectChild<UIRegion>( this, r => r.Layout() ); |       Nodes.ForEachDirectChild<UIRegion>( this, r => r.Layout() ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  |     public static float GetWindowWidth( Control control ) | ||||||
|  |     { | ||||||
|  |       if ( Engine.IsEditorHint() ) | ||||||
|  |       { | ||||||
|  |         return ProjectSettings.GetSetting( "display/window/size/viewport_width" ).AsInt32(); | ||||||
|  |       } | ||||||
|  |       else | ||||||
|  |       { | ||||||
|  |         return control.GetWindow().Size.X; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static float GetWindowHeight( Control control ) | ||||||
|  |     { | ||||||
|  |       if ( Engine.IsEditorHint() ) | ||||||
|  |       { | ||||||
|  |         return ProjectSettings.GetSetting( "display/window/size/viewport_height" ).AsInt32(); | ||||||
|  |       } | ||||||
|  |       else | ||||||
|  |       { | ||||||
|  |         return control.GetWindow().Size.Y; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|      |      | ||||||
| 
 | 
 | ||||||
|   } |   } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Josef
						Josef