Deformer Normals Update + Smoothing
This commit is contained in:
parent
acfed9eda6
commit
3ca59f8dab
|
@ -19,7 +19,6 @@ namespace Rokojori
|
||||||
_OnTrigger();
|
_OnTrigger();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override void _OnTrigger()
|
protected override void _OnTrigger()
|
||||||
{
|
{
|
||||||
if ( source == null || target == null )
|
if ( source == null || target == null )
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Text;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
[Tool]
|
||||||
|
[GlobalClass]
|
||||||
|
public partial class Follow:Node
|
||||||
|
{
|
||||||
|
[Export]
|
||||||
|
public Node3D source;
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public Node3D target;
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public Smoothing positionSmoothing;
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public TimeLine timeline;
|
||||||
|
|
||||||
|
float _lastCoefficient = 0;
|
||||||
|
int _lastFrames = -1;
|
||||||
|
|
||||||
|
public override void _Process( double delta )
|
||||||
|
{
|
||||||
|
if ( positionSmoothing != null && positionSmoothing is ExpSmoothing exp )
|
||||||
|
{
|
||||||
|
if ( _lastCoefficient != exp.coefficient )
|
||||||
|
{
|
||||||
|
_lastCoefficient = exp.coefficient;
|
||||||
|
|
||||||
|
var duration = exp.ComputeDuration();
|
||||||
|
|
||||||
|
var framesOn60hz = duration / ( 1f / 60f );
|
||||||
|
|
||||||
|
this.LogInfo( "Duration:", duration._FFF(), "seconds or", framesOn60hz._FF(), "frames", "For coefficient:", _lastCoefficient );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( positionSmoothing != null && positionSmoothing is FrameSmoothing fra )
|
||||||
|
{
|
||||||
|
if ( _lastFrames != fra.frames )
|
||||||
|
{
|
||||||
|
_lastFrames = fra.frames;
|
||||||
|
|
||||||
|
var coefficient = fra.GetCoefficientForFrames( fra.frames );
|
||||||
|
|
||||||
|
var framesOn60hz = fra.frames * ( 1f / 60f );
|
||||||
|
|
||||||
|
this.LogInfo( "Frames:", fra.frames, "Seconds", framesOn60hz._FF(), "Coefficient:", coefficient );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( source == null || target == null || Engine.IsEditorHint() )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tl = TimeLine.IfNull_ReplaceByGameTime( timeline );
|
||||||
|
target.GlobalPosition = Smoothing.Apply( positionSmoothing, source.GlobalPosition, tl.delta );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
[Tool]
|
||||||
|
[GlobalClass]
|
||||||
|
public partial class ExpSmoothing: Smoothing
|
||||||
|
{
|
||||||
|
[Export( PropertyHint.Range, "0,200")]
|
||||||
|
public float coefficient = 1;
|
||||||
|
|
||||||
|
protected override float _ComputeInterpolationAmount( float delta )
|
||||||
|
{
|
||||||
|
return 1f - Mathf.Exp( -coefficient * delta );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float GetDurationForCoefficient( float coefficient )
|
||||||
|
{
|
||||||
|
var exp = new ExpSmoothing();
|
||||||
|
exp.coefficient = coefficient;
|
||||||
|
return exp.ComputeDuration();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
[Tool]
|
||||||
|
[GlobalClass]
|
||||||
|
public partial class FrameSmoothing: Smoothing
|
||||||
|
{
|
||||||
|
[Export( PropertyHint.Range, "0,600")]
|
||||||
|
public int frames = 10;
|
||||||
|
|
||||||
|
static Dictionary<int,float> _framesToCoefficient = new Dictionary<int, float>();
|
||||||
|
|
||||||
|
protected override float _ComputeInterpolationAmount( float delta )
|
||||||
|
{
|
||||||
|
if ( frames <= 0 )
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var coefficient = GetCoefficientForFrames( frames );
|
||||||
|
return 1f - Mathf.Exp( -coefficient * delta );
|
||||||
|
}
|
||||||
|
|
||||||
|
public float GetCoefficientForFrames( int frames )
|
||||||
|
{
|
||||||
|
if ( ! _framesToCoefficient.ContainsKey( frames ) )
|
||||||
|
{
|
||||||
|
_framesToCoefficient[ frames ] = ComputeCoefficientForFrames( frames );
|
||||||
|
}
|
||||||
|
|
||||||
|
return _framesToCoefficient[ frames ];
|
||||||
|
}
|
||||||
|
|
||||||
|
static float ComputeCoefficientForFrames( int numFrames, float treshold = 1f/60f * 0.1f )
|
||||||
|
{
|
||||||
|
|
||||||
|
var framesDuration = numFrames * 1/60f;
|
||||||
|
|
||||||
|
|
||||||
|
var minMaxSearch = new MinMaxSearch<float>(
|
||||||
|
( a, b, t ) => Mathf.Lerp( a, b, t ),
|
||||||
|
( c ) => ExpSmoothing.GetDurationForCoefficient( c )
|
||||||
|
);
|
||||||
|
|
||||||
|
var lowDurationCoefficient = 100000f;
|
||||||
|
var highDurationCoefficient = 0.1f;
|
||||||
|
|
||||||
|
|
||||||
|
RJLog.Log( "Finding coefficient for frames", numFrames, ">>", framesDuration, "s" );
|
||||||
|
|
||||||
|
var coefficient = minMaxSearch.Find( framesDuration, lowDurationCoefficient, highDurationCoefficient, treshold );
|
||||||
|
|
||||||
|
RJLog.Log( "Found coefficient:", coefficient, ">> duration", ExpSmoothing.GetDurationForCoefficient( coefficient )._FF(), "s" );
|
||||||
|
|
||||||
|
return coefficient;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
[Tool]
|
||||||
|
[GlobalClass]
|
||||||
|
public partial class Smoothing: Resource
|
||||||
|
{
|
||||||
|
float _currentFloat = 0;
|
||||||
|
Vector2 _currentVector2 = Vector2.Zero;
|
||||||
|
Vector3 _currentVector3 = Vector3.Zero;
|
||||||
|
Vector4 _currentVector4 = Vector4.Zero;
|
||||||
|
Quaternion _currentQuaternion = Quaternion.Identity;
|
||||||
|
Color _currentColor = Colors.Black;
|
||||||
|
|
||||||
|
|
||||||
|
public float Smooth( float nextValue, float delta )
|
||||||
|
{
|
||||||
|
_currentFloat = Mathf.Lerp( _currentFloat, nextValue, _ComputeInterpolationAmount( delta ) );
|
||||||
|
|
||||||
|
return _currentFloat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float Apply( Smoothing sm, float value, float delta )
|
||||||
|
{
|
||||||
|
if ( sm == null ){ return value; }
|
||||||
|
return sm.Smooth( value, delta );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 Smooth( Vector2 nextValue, float delta )
|
||||||
|
{
|
||||||
|
_currentVector2 = _currentVector2.Lerp( nextValue, _ComputeInterpolationAmount( delta ) );
|
||||||
|
|
||||||
|
return _currentVector2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector2 Apply( Smoothing sm, Vector2 value, float delta )
|
||||||
|
{
|
||||||
|
if ( sm == null ){ return value; }
|
||||||
|
return sm.Smooth( value, delta );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 Smooth( Vector3 nextValue, float delta )
|
||||||
|
{
|
||||||
|
_currentVector3 = _currentVector3.Lerp( nextValue, _ComputeInterpolationAmount( delta ) );
|
||||||
|
|
||||||
|
return _currentVector3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector3 Apply( Smoothing sm, Vector3 value, float delta )
|
||||||
|
{
|
||||||
|
if ( sm == null ){ return value; }
|
||||||
|
return sm.Smooth( value, delta );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector4 Smooth( Vector4 nextValue, float delta )
|
||||||
|
{
|
||||||
|
_currentVector4 = _currentVector4.Lerp( nextValue, _ComputeInterpolationAmount( delta ) );
|
||||||
|
|
||||||
|
return _currentVector4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector4 Apply( Smoothing sm, Vector4 value, float delta )
|
||||||
|
{
|
||||||
|
if ( sm == null ){ return value; }
|
||||||
|
return sm.Smooth( value, delta );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Quaternion Smooth( Quaternion nextValue, float delta )
|
||||||
|
{
|
||||||
|
_currentQuaternion = _currentQuaternion.Slerp( nextValue, _ComputeInterpolationAmount( delta ) );
|
||||||
|
|
||||||
|
return _currentQuaternion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Quaternion Apply( Smoothing sm, Quaternion value, float delta )
|
||||||
|
{
|
||||||
|
if ( sm == null ){ return value; }
|
||||||
|
return sm.Smooth( value, delta );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color Smooth( Color nextValue, float delta )
|
||||||
|
{
|
||||||
|
_currentColor = _currentColor.Lerp( nextValue, _ComputeInterpolationAmount( delta ) );
|
||||||
|
|
||||||
|
return _currentColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color Apply( Smoothing sm, Color value, float delta )
|
||||||
|
{
|
||||||
|
if ( sm == null ){ return value; }
|
||||||
|
return sm.Smooth( value, delta );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual float _ComputeInterpolationAmount( float delta )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual float ComputeDuration( float delta = 1f/240f, float tresholdValue = 0.05f )
|
||||||
|
{
|
||||||
|
var cached = _currentFloat;
|
||||||
|
|
||||||
|
var value = 1f;
|
||||||
|
_currentFloat = 1f;
|
||||||
|
|
||||||
|
var duration = 0f;
|
||||||
|
var lastValue = value;
|
||||||
|
|
||||||
|
var maxDuration = 30;
|
||||||
|
|
||||||
|
while ( value > tresholdValue && duration < maxDuration )
|
||||||
|
{
|
||||||
|
lastValue = value;
|
||||||
|
value = Smooth( 0, delta );
|
||||||
|
|
||||||
|
duration += delta;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
_currentFloat = cached;
|
||||||
|
|
||||||
|
return MathX.RemapClamped( tresholdValue, lastValue, value, duration - delta, duration );
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ namespace Rokojori
|
||||||
public class MappingData
|
public class MappingData
|
||||||
{
|
{
|
||||||
public Vector3 localPosition;
|
public Vector3 localPosition;
|
||||||
|
public Vector3 localNormal;
|
||||||
public float normalizedSplineParameter;
|
public float normalizedSplineParameter;
|
||||||
public float weight;
|
public float weight;
|
||||||
}
|
}
|
||||||
|
@ -74,7 +75,7 @@ namespace Rokojori
|
||||||
MappingData[] deformerMappings;
|
MappingData[] deformerMappings;
|
||||||
MeshGeometry meshGeometry;
|
MeshGeometry meshGeometry;
|
||||||
|
|
||||||
MappingData CreateSourceMapping( Spline s, Vector3 worldPosition )
|
MappingData CreateSourceMapping( Spline s, Vector3 worldPosition, Vector3 worldNormal )
|
||||||
{
|
{
|
||||||
var curve = s.GetCurve();
|
var curve = s.GetCurve();
|
||||||
var closestParameter = curve.GetClosestParameterTo( worldPosition, splineMappingResolution, splineMappingDepth );
|
var closestParameter = curve.GetClosestParameterTo( worldPosition, splineMappingResolution, splineMappingDepth );
|
||||||
|
@ -82,10 +83,12 @@ namespace Rokojori
|
||||||
var pose = curve.GetPoseByPointIndex( pointIndex );
|
var pose = curve.GetPoseByPointIndex( pointIndex );
|
||||||
|
|
||||||
var localPosition = pose.ApplyInverse( worldPosition );
|
var localPosition = pose.ApplyInverse( worldPosition );
|
||||||
|
var localNormal = pose.rotation.Inverse() * worldNormal;
|
||||||
|
|
||||||
var mappingData = new MappingData();
|
var mappingData = new MappingData();
|
||||||
|
|
||||||
mappingData.localPosition = localPosition;
|
mappingData.localPosition = localPosition;
|
||||||
|
mappingData.localNormal = localNormal;
|
||||||
mappingData.normalizedSplineParameter = closestParameter;
|
mappingData.normalizedSplineParameter = closestParameter;
|
||||||
mappingData.weight = 0;
|
mappingData.weight = 0;
|
||||||
|
|
||||||
|
@ -112,7 +115,8 @@ namespace Rokojori
|
||||||
for ( int j = 0; j < sourceSplines.Length; j++ )
|
for ( int j = 0; j < sourceSplines.Length; j++ )
|
||||||
{
|
{
|
||||||
var vertex = meshGeometry.vertices[ i ];
|
var vertex = meshGeometry.vertices[ i ];
|
||||||
var mapping = CreateSourceMapping( sourceSplines[ j ], vertex );
|
var normal = meshGeometry.normals[ i ];
|
||||||
|
var mapping = CreateSourceMapping( sourceSplines[ j ], vertex, normal );
|
||||||
var curve = sourceSplines[ j ].GetCurve();
|
var curve = sourceSplines[ j ].GetCurve();
|
||||||
var distance = curve.PositionAt( mapping.normalizedSplineParameter ) - vertex;
|
var distance = curve.PositionAt( mapping.normalizedSplineParameter ) - vertex;
|
||||||
var inverseWeight = MathX.NormalizeClamped( distance.Length(), splineMinDistance, splineMaxDistance );
|
var inverseWeight = MathX.NormalizeClamped( distance.Length(), splineMinDistance, splineMaxDistance );
|
||||||
|
@ -140,7 +144,8 @@ namespace Rokojori
|
||||||
|
|
||||||
for ( int i = 0; i < cloned.vertices.Count; i++ )
|
for ( int i = 0; i < cloned.vertices.Count; i++ )
|
||||||
{
|
{
|
||||||
var vertexPosition = Vector3.Zero;
|
var vertex = Vector3.Zero;
|
||||||
|
var normal = Vector3.Zero;
|
||||||
|
|
||||||
for ( int j = 0; j < deformerSplines.Length; j++ )
|
for ( int j = 0; j < deformerSplines.Length; j++ )
|
||||||
{
|
{
|
||||||
|
@ -151,19 +156,22 @@ namespace Rokojori
|
||||||
{
|
{
|
||||||
var pose = curve.SmoothedPoseAt( mapping.normalizedSplineParameter, targetSmoothing * 0.5f, 2, targetSmoothing );
|
var pose = curve.SmoothedPoseAt( mapping.normalizedSplineParameter, targetSmoothing * 0.5f, 2, targetSmoothing );
|
||||||
pose.ApplyTwist( curve.TwistAt( mapping.normalizedSplineParameter ) );
|
pose.ApplyTwist( curve.TwistAt( mapping.normalizedSplineParameter ) );
|
||||||
vertexPosition += pose.Apply( mapping.localPosition ) * mapping.weight;
|
vertex += pose.Apply( mapping.localPosition ) * mapping.weight;
|
||||||
|
normal += pose.rotation * mapping.localNormal * mapping.weight;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var pose = curve.PoseAt( mapping.normalizedSplineParameter );
|
var pose = curve.PoseAt( mapping.normalizedSplineParameter );
|
||||||
pose.ApplyTwist( curve.TwistAt( mapping.normalizedSplineParameter ) );
|
pose.ApplyTwist( curve.TwistAt( mapping.normalizedSplineParameter ) );
|
||||||
vertexPosition += pose.Apply( mapping.localPosition ) * mapping.weight;
|
vertex += pose.Apply( mapping.localPosition ) * mapping.weight;
|
||||||
|
normal += pose.rotation * mapping.localNormal * mapping.weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cloned.vertices[ i ] = vertexPosition;
|
cloned.vertices[ i ] = vertex;
|
||||||
|
cloned.normals[ i ] = normal.Normalized();
|
||||||
}
|
}
|
||||||
|
|
||||||
// RJLog.Log( cloned.vertices.Count );
|
// RJLog.Log( cloned.vertices.Count );
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
using Godot;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
[Tool]
|
||||||
|
[GlobalClass]
|
||||||
|
public partial class SphericalParticleMesh : Mesh
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace Rokojori
|
||||||
|
{
|
||||||
|
public class MinMaxSearch<T>
|
||||||
|
{
|
||||||
|
Func<T,T,float,T> lerp;
|
||||||
|
Func<T,float> getValue;
|
||||||
|
Func<T,T,bool> validateLimits;
|
||||||
|
|
||||||
|
public bool cacheValues = true;
|
||||||
|
public float interpolationAmount = 1f;
|
||||||
|
|
||||||
|
Dictionary<T,float> _cachedValues = new Dictionary<T, float>();
|
||||||
|
|
||||||
|
public MinMaxSearch( Func<T,T,float,T> lerp, Func<T,float> getValue, Func<T,T,bool> validateLimits = null)
|
||||||
|
{
|
||||||
|
this.lerp = lerp;
|
||||||
|
this.getValue = getValue;
|
||||||
|
this.validateLimits = validateLimits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Find( float searchValue, T low, T high, float treshold )
|
||||||
|
{
|
||||||
|
if ( validateLimits != null && ! validateLimits( low, high ) )
|
||||||
|
{
|
||||||
|
throw new Exception( "Limit validation failed" );
|
||||||
|
}
|
||||||
|
|
||||||
|
var tweened = GetTweened( searchValue, low, high );
|
||||||
|
var tweenedValue = GetValue( tweened );
|
||||||
|
var tweenedDifference = searchValue - tweenedValue;
|
||||||
|
|
||||||
|
Safe.While ( () => Mathf.Abs( tweenedDifference ) > treshold ,
|
||||||
|
()=>
|
||||||
|
{
|
||||||
|
if ( searchValue > tweenedValue )
|
||||||
|
{
|
||||||
|
low = tweened;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
high = tweened;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( validateLimits != null && ! validateLimits( low, high ) )
|
||||||
|
{
|
||||||
|
throw new Exception( "Limit validation failed" );
|
||||||
|
}
|
||||||
|
|
||||||
|
tweened = GetTweened( searchValue, low, high );
|
||||||
|
tweenedValue = GetValue( tweened );
|
||||||
|
tweenedDifference = searchValue - tweenedValue;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return tweened;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetTweened( float value, T low, T high )
|
||||||
|
{
|
||||||
|
var lowValue = getValue( low );
|
||||||
|
var highValue = getValue( high );
|
||||||
|
|
||||||
|
var position = MathX.Normalize( value, lowValue, highValue );
|
||||||
|
position = Mathf.Lerp( 0.5f, position, interpolationAmount );
|
||||||
|
|
||||||
|
return lerp( low, high, position );
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetValue( T t )
|
||||||
|
{
|
||||||
|
if ( ! cacheValues )
|
||||||
|
{
|
||||||
|
return getValue( t );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( _cachedValues.ContainsKey( t ) )
|
||||||
|
{
|
||||||
|
return _cachedValues[ t ];
|
||||||
|
}
|
||||||
|
|
||||||
|
_cachedValues[ t ] = getValue( t );
|
||||||
|
|
||||||
|
return _cachedValues[ t ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ using Godot;
|
||||||
|
|
||||||
namespace Rokojori
|
namespace Rokojori
|
||||||
{
|
{
|
||||||
public class RegexUtility
|
public static class RegexUtility
|
||||||
{
|
{
|
||||||
public static Regex MakeSticky( Regex regex )
|
public static Regex MakeSticky( Regex regex )
|
||||||
{
|
{
|
||||||
|
@ -61,6 +61,23 @@ namespace Rokojori
|
||||||
return "0";
|
return "0";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string _F( this float value )
|
||||||
|
{
|
||||||
|
return value.ToString( "0.0", CultureInfo.InvariantCulture );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string _FF( this float value )
|
||||||
|
{
|
||||||
|
return value.ToString( "0.00", CultureInfo.InvariantCulture );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string _FFF( this float value )
|
||||||
|
{
|
||||||
|
return value.ToString( "0.000", CultureInfo.InvariantCulture );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static double ParseDouble( string source, double alternative = 0 )
|
public static double ParseDouble( string source, double alternative = 0 )
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -37,5 +37,28 @@ namespace Rokojori
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static TimeLine IfNull_ReplaceByGameTime( TimeLine other )
|
||||||
|
{
|
||||||
|
if ( other != null )
|
||||||
|
{
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tm = Unique<TimeLineManager>.Get();
|
||||||
|
return tm.gameTimeTimeLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TimeLine IfNull_ReplaceByRealTime( TimeLine other )
|
||||||
|
{
|
||||||
|
if ( other != null )
|
||||||
|
{
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tm = Unique<TimeLineManager>.Get();
|
||||||
|
return tm.realTimeTimeLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,7 +16,7 @@ namespace Rokojori
|
||||||
public TimeLine[] timeLines;
|
public TimeLine[] timeLines;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
public TimeLine engineTimeScale;
|
public TimeLine gameTimeTimeLine;
|
||||||
|
|
||||||
[Export]
|
[Export]
|
||||||
public TimeLine realTimeTimeLine;
|
public TimeLine realTimeTimeLine;
|
||||||
|
@ -52,9 +52,9 @@ namespace Rokojori
|
||||||
{
|
{
|
||||||
UpdateRealTime( delta );
|
UpdateRealTime( delta );
|
||||||
|
|
||||||
if ( engineTimeScale != null )
|
if ( gameTimeTimeLine != null )
|
||||||
{
|
{
|
||||||
Engine.TimeScale = GetModulatedSpeed( engineTimeScale );
|
Engine.TimeScale = GetModulatedSpeed( gameTimeTimeLine );
|
||||||
}
|
}
|
||||||
|
|
||||||
_runners.ForEach( r => r.UpdateTimeLine( unscaledTimeDelta, this ) );
|
_runners.ForEach( r => r.UpdateTimeLine( unscaledTimeDelta, this ) );
|
||||||
|
|
|
@ -12,6 +12,11 @@ namespace Rokojori
|
||||||
|
|
||||||
public static void While( Func<bool> condition, System.Action action, System.Action onTooManyIterations = null )
|
public static void While( Func<bool> condition, System.Action action, System.Action onTooManyIterations = null )
|
||||||
{
|
{
|
||||||
|
if ( condition == null || action == null )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var it = 0;
|
var it = 0;
|
||||||
|
|
||||||
while ( it < Safe.maxWhileIterations && condition() )
|
while ( it < Safe.maxWhileIterations && condition() )
|
||||||
|
|
Loading…
Reference in New Issue