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 );
|
||||
}
|
||||
|
||||
public N GetParent( N node, Func<N,bool> predicate )
|
||||
public N GetInParents( N node, Func<N,bool> predicate )
|
||||
{
|
||||
var p = Parent( node );
|
||||
|
||||
|
|
|
@ -42,6 +42,13 @@ namespace Rokojori
|
|||
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 )
|
||||
{
|
||||
var trace = GetTrace();
|
||||
|
@ -49,6 +56,11 @@ namespace Rokojori
|
|||
GD.PrintRich( trace );
|
||||
}
|
||||
|
||||
static string GetFullTrace()
|
||||
{
|
||||
return ( new System.Diagnostics.StackTrace( true ) ).ToString();
|
||||
}
|
||||
|
||||
static string GetTrace()
|
||||
{
|
||||
var stackTrace = new System.Diagnostics.StackTrace( true );
|
||||
|
@ -86,6 +98,23 @@ namespace Rokojori
|
|||
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)
|
||||
{
|
||||
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 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 )
|
||||
{
|
||||
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
|
||||
{
|
||||
public abstract class RandomEngine
|
||||
public abstract class RandomEngine
|
||||
{
|
||||
public abstract float Next();
|
||||
|
||||
|
@ -208,6 +208,106 @@ namespace Rokojori
|
|||
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
if ( list.Count == 0 ){ return default(T); }
|
||||
|
@ -143,6 +165,23 @@ namespace Rokojori
|
|||
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 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
var list = new List<T>();
|
||||
|
@ -198,6 +237,24 @@ namespace Rokojori
|
|||
);
|
||||
|
||||
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 )
|
||||
|
|
|
@ -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 maxHeight = 0f;
|
||||
|
||||
if ( UINumber.IsNullOrNone( region.width ) )
|
||||
if ( UINumber.IsNullOrNone( UIStyle.Width( region ) ) )
|
||||
{
|
||||
lines.ForEach( l => { maxWidth = Mathf.Max( maxWidth, l.maxX ); } );
|
||||
}
|
||||
else
|
||||
{
|
||||
maxWidth = UINumber.Compute( region, region.width );
|
||||
maxWidth = UINumber.Compute( region, UIStyle.Width( region ) );
|
||||
}
|
||||
|
||||
if ( lines.Count > 0 )
|
||||
|
@ -81,12 +81,12 @@ namespace Rokojori
|
|||
maxHeight = lines[ lines.Count - 1 ].maxY;
|
||||
}
|
||||
|
||||
var margin = UINumber.Compute( region, region.margin, 0 );
|
||||
var marginLeft = margin + UINumber.Compute( region, region.marginLeft, 0 );
|
||||
var marginTop = margin + UINumber.Compute( region, region.marginTop, 0 );
|
||||
var margin = UINumber.Compute( region, UIStyle.Margin( region ), 0 );
|
||||
var marginLeft = margin + UINumber.Compute( region, UIStyle.MarginLeft( region ), 0 );
|
||||
var marginTop = margin + UINumber.Compute( region, UIStyle.MarginTop( region ), 0 );
|
||||
|
||||
var marginRight = margin + UINumber.Compute( region, region.marginRight, 0 );
|
||||
var marginBottom = margin + UINumber.Compute( region, region.marginBottom, 0 );
|
||||
var marginRight = margin + UINumber.Compute( region, UIStyle.MarginRight( region ), 0 );
|
||||
var marginBottom = margin + UINumber.Compute( region, UIStyle.MarginBottom( region ), 0 );
|
||||
|
||||
|
||||
var marginOffset = new Vector2( marginLeft, marginTop );
|
||||
|
@ -98,46 +98,38 @@ namespace Rokojori
|
|||
|
||||
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;
|
||||
|
||||
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 ) );
|
||||
|
||||
}
|
||||
|
||||
UILayouting.SetPositionInParentAnchor( region );
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
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 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 ) );
|
||||
|
||||
|
@ -146,6 +138,13 @@ namespace Rokojori
|
|||
child =>
|
||||
{
|
||||
|
||||
var styleContainer = child as UIStylePropertyContainer;
|
||||
|
||||
if ( styleContainer != null && UIStyle.Position( styleContainer ) == UIPosition.Parent_Anchor )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var cWidth = UILayouting.GetWidth( child );
|
||||
var cHeight = UILayouting.GetHeight( child );
|
||||
|
||||
|
@ -193,13 +192,13 @@ namespace Rokojori
|
|||
|
||||
lines.ForEach( line => AdjustVerticalAlignment( region, line, verticalAlignment ) );
|
||||
|
||||
if ( UINumber.IsNullOrNone( region.width ) )
|
||||
if ( UINumber.IsNullOrNone( UIStyle.Width( region ) ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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 ) );
|
||||
|
||||
|
|
|
@ -40,6 +40,45 @@ namespace Rokojori
|
|||
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 )
|
||||
{
|
||||
if ( ! ( c is UIImage || c is UIRegion || c is UIText ) )
|
||||
|
@ -49,8 +88,8 @@ namespace Rokojori
|
|||
|
||||
var container = c as UIStylePropertyContainer;
|
||||
|
||||
var pivotX = UINumber.Compute( c, UIStyle.PivotX( container ), 0, c.Size.X );
|
||||
var pivotY = UINumber.Compute( c, UIStyle.PivotY( container ), 0, c.Size.Y );
|
||||
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.5f * c.Size.Y, c.Size.Y );
|
||||
|
||||
c.PivotOffset = new Vector2( pivotX, pivotY );
|
||||
|
||||
|
|
|
@ -8,6 +8,9 @@ namespace Rokojori
|
|||
[GlobalClass]
|
||||
public partial class UIImage:TextureRect, UIStylePropertyContainer
|
||||
{
|
||||
[Export]
|
||||
public UIStyle parentStyle;
|
||||
|
||||
[ExportCategory("Size & Margins")]
|
||||
[Export]
|
||||
public UINumber width;
|
||||
|
@ -60,6 +63,16 @@ namespace Rokojori
|
|||
public UINumber scaleY;
|
||||
|
||||
|
||||
public UIStyle GetUIStyleParent()
|
||||
{
|
||||
return parentStyle;
|
||||
}
|
||||
|
||||
public UIPosition GetUIPosition()
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
public UINumber GetUIStyleNumberProperty( UIStyleNumberProperty property )
|
||||
{
|
||||
switch ( property )
|
||||
|
|
|
@ -8,9 +8,9 @@ namespace Rokojori
|
|||
public partial class UIRegion : Control, UIStylePropertyContainer
|
||||
{
|
||||
[Export]
|
||||
public UIStyle parent;
|
||||
public UIStyle parentStyle;
|
||||
|
||||
[ExportCategory("Layout")]
|
||||
[ExportCategory( "Layout" )]
|
||||
[Export]
|
||||
public UILayout layout;
|
||||
|
||||
|
@ -25,7 +25,7 @@ namespace Rokojori
|
|||
public UINumber lineSpacing;
|
||||
|
||||
|
||||
[ExportCategory("Size & Margins")]
|
||||
[ExportCategory( "Size & Margins" )]
|
||||
[Export]
|
||||
public UINumber width;
|
||||
[Export]
|
||||
|
@ -44,7 +44,27 @@ namespace Rokojori
|
|||
[Export]
|
||||
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]
|
||||
public UIPosition position;
|
||||
[Export]
|
||||
|
@ -57,6 +77,16 @@ namespace Rokojori
|
|||
public UINumber bottom;
|
||||
|
||||
|
||||
public UIStyle GetUIStyleParent()
|
||||
{
|
||||
return parentStyle;
|
||||
}
|
||||
|
||||
public UIPosition GetUIPosition()
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
public UINumber GetUIStyleNumberProperty( UIStyleNumberProperty property )
|
||||
{
|
||||
switch ( property )
|
||||
|
@ -69,6 +99,10 @@ namespace Rokojori
|
|||
case UIStyleNumberProperty.Width: return width;
|
||||
case UIStyleNumberProperty.Height: return height;
|
||||
|
||||
|
||||
case UIStyleNumberProperty.ElementSpacing: return elementSpacing;
|
||||
case UIStyleNumberProperty.LineSpacing: return lineSpacing;
|
||||
|
||||
case UIStyleNumberProperty.Margin: return margin;
|
||||
|
||||
case UIStyleNumberProperty.MarginLeft: return marginLeft;
|
||||
|
|
|
@ -8,6 +8,12 @@ namespace Rokojori
|
|||
[GlobalClass]
|
||||
public partial class UIText:Label,UIStylePropertyContainer
|
||||
{
|
||||
[Export]
|
||||
public UIStyle parentStyle;
|
||||
|
||||
[Export]
|
||||
public UINumber fontSize;
|
||||
|
||||
[ExportCategory("Size & Margins")]
|
||||
[Export]
|
||||
public UINumber width;
|
||||
|
@ -59,6 +65,15 @@ namespace Rokojori
|
|||
[Export]
|
||||
public UINumber scaleY;
|
||||
|
||||
public UIStyle GetUIStyleParent()
|
||||
{
|
||||
return parentStyle;
|
||||
}
|
||||
|
||||
public UIPosition GetUIPosition()
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
public static float Compute( Control control, UINumber number, float alternative = 0, float relative = 100 )
|
||||
{
|
||||
if ( number == null || control == null || number.IsNone )
|
||||
|
@ -41,19 +42,9 @@ namespace Rokojori
|
|||
return alternative;
|
||||
}
|
||||
|
||||
var width = 0;
|
||||
var height = 0;
|
||||
var width = UI.GetWindowWidth( control );
|
||||
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 );
|
||||
|
||||
|
@ -75,7 +66,7 @@ namespace Rokojori
|
|||
|
||||
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 )
|
||||
|
@ -95,6 +86,18 @@ namespace Rokojori
|
|||
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 "":
|
||||
{
|
||||
return number.value;
|
||||
|
@ -110,17 +113,25 @@ namespace Rokojori
|
|||
|
||||
|
||||
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 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var parentControl = control.GetParent<Control>();
|
||||
|
||||
var inputs = new Godot.Collections.Array();
|
||||
inputs.Add( em() );
|
||||
inputs.Add( width / 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( relative / 100f );
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace Rokojori
|
|||
{
|
||||
public enum UIPosition
|
||||
{
|
||||
___,
|
||||
From_Layout,
|
||||
Parent_Anchor
|
||||
}
|
||||
|
|
|
@ -7,106 +7,236 @@ namespace Rokojori
|
|||
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class UIStyle:Resource
|
||||
public partial class UIStyle:Resource, UIStylePropertyContainer
|
||||
{
|
||||
[Export]
|
||||
public UIStyle parent;
|
||||
|
||||
[Export]
|
||||
public UILayout layoutType;
|
||||
public UIStyle parentStyle;
|
||||
|
||||
[ExportCategory("Width")]
|
||||
[ExportCategory( "Layout" )]
|
||||
[Export]
|
||||
public float widthValue = 1;
|
||||
[Export]
|
||||
public string widthUnit = "vw";
|
||||
public UILayout layout;
|
||||
|
||||
[ExportCategory("Height")]
|
||||
[Export]
|
||||
public float heightValue = 1;
|
||||
public UINumber horizontalAlignment;
|
||||
[Export]
|
||||
public string heightUnit = "vw";
|
||||
public UINumber verticalAlignment;
|
||||
|
||||
[ExportCategory("LineSpacing")]
|
||||
[Export]
|
||||
public float lineSpacingValue = 1;
|
||||
public UINumber elementSpacing;
|
||||
[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 )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.Left );
|
||||
return GetReferenceableNumberProperty( container, UIStyleNumberProperty.Left );
|
||||
}
|
||||
|
||||
public static UINumber Right( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.Right );
|
||||
return GetReferenceableNumberProperty( container, UIStyleNumberProperty.Right );
|
||||
}
|
||||
|
||||
public static UINumber Top( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.Top );
|
||||
return GetReferenceableNumberProperty( container, UIStyleNumberProperty.Top );
|
||||
}
|
||||
|
||||
public static UINumber Bottom( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.Bottom );
|
||||
return GetReferenceableNumberProperty( container, UIStyleNumberProperty.Bottom );
|
||||
}
|
||||
|
||||
public static UINumber Margin( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.Margin );
|
||||
return GetReferenceableNumberProperty( container, UIStyleNumberProperty.Margin );
|
||||
}
|
||||
|
||||
public static UINumber MarginLeft( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.MarginLeft );
|
||||
return GetReferenceableNumberProperty( container, UIStyleNumberProperty.MarginLeft );
|
||||
}
|
||||
|
||||
public static UINumber MarginRight( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.MarginRight );
|
||||
return GetReferenceableNumberProperty( container, UIStyleNumberProperty.MarginRight );
|
||||
}
|
||||
|
||||
public static UINumber MarginTop( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.MarginTop );
|
||||
return GetReferenceableNumberProperty( container, UIStyleNumberProperty.MarginTop );
|
||||
}
|
||||
|
||||
public static UINumber MarginBottom( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.MarginBottom );
|
||||
return GetReferenceableNumberProperty( container, UIStyleNumberProperty.MarginBottom );
|
||||
}
|
||||
|
||||
public static UINumber PivotX( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.PivotX );
|
||||
return GetReferenceableNumberProperty( container, UIStyleNumberProperty.PivotX );
|
||||
}
|
||||
|
||||
public static UINumber PivotY( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.PivotY );
|
||||
return GetReferenceableNumberProperty( container, UIStyleNumberProperty.PivotY );
|
||||
}
|
||||
|
||||
public static UINumber Rotation( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.Rotation );
|
||||
return GetReferenceableNumberProperty( container, UIStyleNumberProperty.Rotation );
|
||||
}
|
||||
|
||||
public static UINumber Scale( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.Scale );
|
||||
return GetReferenceableNumberProperty( container, UIStyleNumberProperty.Scale );
|
||||
}
|
||||
|
||||
public static UINumber ScaleX( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.ScaleX );
|
||||
return GetReferenceableNumberProperty( container, UIStyleNumberProperty.ScaleX );
|
||||
}
|
||||
|
||||
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,
|
||||
Height,
|
||||
|
||||
ElementSpacing,
|
||||
LineSpacing,
|
||||
|
||||
Margin,
|
||||
MarginLeft,
|
||||
MarginRight,
|
||||
|
@ -27,6 +30,17 @@ namespace Rokojori
|
|||
|
||||
Scale,
|
||||
ScaleX,
|
||||
ScaleY
|
||||
ScaleY,
|
||||
|
||||
FontSize,
|
||||
FontOutlineSize,
|
||||
FontShadowSize
|
||||
}
|
||||
|
||||
public enum UIStyleColorProperty
|
||||
{
|
||||
FontColor,
|
||||
FontOutlineColor,
|
||||
FontShadowColor
|
||||
}
|
||||
}
|
|
@ -6,6 +6,9 @@ namespace Rokojori
|
|||
{
|
||||
public interface UIStylePropertyContainer
|
||||
{
|
||||
UIStyle GetUIStyleParent();
|
||||
|
||||
UIPosition GetUIPosition();
|
||||
UINumber GetUIStyleNumberProperty( UIStyleNumberProperty property );
|
||||
}
|
||||
}
|
|
@ -29,7 +29,7 @@ namespace Rokojori
|
|||
UpdateUIElements();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void UpdateFontSize()
|
||||
{
|
||||
|
@ -53,6 +53,30 @@ namespace Rokojori
|
|||
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