using System.Collections; using System.Collections.Generic; using Godot; using System.Text; using System; namespace Rokojori { public class MathX { public const float fps120Delta = 1/120f; public static float Clamp01( float value ) { return Mathf.Clamp( value, 0, 1 ); } public static float Normalize( float value, float min, float max ) { return ( value - min ) / ( max - min ); } public static float NormalizeClamped( float value, float min, float max ) { return MathX.Clamp01( Normalize( value, min, max ) ); } public static float Map( float value, float inputMin, float inputMax, float outputMin, float outputMax ) { var normalized = Normalize( value, inputMin, inputMax ); return normalized * ( outputMax - outputMin ) + outputMin; } public static float MapPositive( float value, float inputMax, float outputMax ) { return Map( value, 0, inputMax, 0, outputMax ); } public static float MapClamped( float value, float inputMin, float inputMax, float outputMin, float outputMax ) { var normalized = NormalizeClamped( value, inputMin, inputMax ); return normalized * ( outputMax - outputMin ) + outputMin; } public static float Map01( float value, float outputMin, float outputMax ) { return value * ( outputMax - outputMin ) + outputMin; } public static float MapPolar( float value, float min, float max ) { return Map01( value * 0.5f + 0.5f, min, max ); } public static float MapPolarTo01( float value) { return value * 0.5f + 0.5f; } public static float Repeat( float value, float length ) { while ( value > length ) { value -=length; } while ( value < 0 ) { value += length; } return value; } public static float Triangle( float value ) { value = MathX.Repeat( value, 1 ) * 2; if ( value > 1 ) { value = 2 - value; } return value; } public static float EaseSine( float value ) { return Mathf.Sin( Mathf.Pi * ( value * 0.5f + 1.5f ) ) + 1; } public static int Sign( int value ) { return value == 0 ? 0 : value < 0 ? -1 : 1; } public static T LerpList( List data, float t, Func lerpElementsFunction, int dataFillSize = -1 ) { dataFillSize = dataFillSize == -1 ? data.Count : dataFillSize; var floatIndex = t * dataFillSize; if ( floatIndex <= 0 ) { return data[ 0 ]; } if ( floatIndex >= ( dataFillSize - 1 ) ) { return data[ dataFillSize - 1 ]; } var flooredIndex = Mathf.FloorToInt( floatIndex ); var ceiledIndex = flooredIndex + 1; var flooredValue = data[ flooredIndex ]; var ceiledValue = data[ ceiledIndex ]; var interpolationAmount = floatIndex - flooredIndex; return lerpElementsFunction( flooredValue, ceiledValue, interpolationAmount ); } public static float PolarTriangle( float value ) { return Triangle( value ) * 2f - 1f; } public static float Step( float phase, float phaseStart, float phaseEnd ) { if ( phase < phaseStart ) { return 0; } if ( phase >= phaseEnd ) { return 1; } return ( phase - phaseStart ) / ( phaseStart - phaseEnd ); } public static int Repeat( int value, int range ) { while ( value < 0 ) { value += range; } while ( value >= range ) { value -= range; } return value; } public static float PolarRepeat( float value, float range ) { while ( value < -range ) { value += range * 2; } while ( value >= range ) { value -= range * 2; } return value; } public static float Exponent( float base_, float power ) { return Mathf.Log( power ) / Mathf.Log( base_ ); } public static float Base( float exponent, float power ) { return Mathf.Pow( power, 1f / exponent ); } public static float SmoothingCoefficient( float ms, float reachingTarget = 0.1f, float frameDurationMS = MathX.fps120Delta ) { return 1f - Base( ms / frameDurationMS, reachingTarget ); } public static float SmoothValue( float oldValue, float newValue, float ms, float reachingTarget = 0.1f, float frameDurationMS = MathX.fps120Delta ) { return oldValue + SmoothingCoefficient( ms, reachingTarget, frameDurationMS ) * ( newValue - oldValue ); } public static float SmoothDegrees( float oldValue, float newValue, float ms, float reachingTarget = 0.1f, float frameDurationMS = MathX.fps120Delta ) { oldValue = Mathf.Wrap( oldValue, 0, 360 ); newValue = Mathf.Wrap( newValue, 0, 360 ); var difference = newValue - oldValue; if ( Mathf.Abs( difference ) > 180 ) { if ( newValue > oldValue ) { oldValue += 360; } else { newValue += 360; } } return oldValue + SmoothingCoefficient( ms, reachingTarget, frameDurationMS ) * ( newValue - oldValue ); } public static Vector3 SmoothVector3( Vector3 oldValue, Vector3 newValue, float ms, float reachingTarget = 0.1f, float frameDurationMS = 8.33333333333f ) { return oldValue + SmoothingCoefficient( ms, reachingTarget, frameDurationMS ) * ( newValue - oldValue ); } public static float TimeLerp( float from, float to, float t, float timeDelta ) { return Mathf.Lerp( from, to, 1f - Mathf.Pow( t, timeDelta ) ); } public static float PolarAxis( bool negative, bool positive ) { return ( negative ? -1 : 0 ) + ( positive ? 1 : 0 ); } } }