using System.Collections; using System.Collections.Generic; using System; using System.Reflection; using System.Text.RegularExpressions; using Godot; namespace Rokojori { public class MinMaxSearch { Func lerp; Func getValue; Func validateLimits; public bool cacheValues = true; public float interpolationAmount = 1f; Dictionary _cachedValues = new Dictionary(); public MinMaxSearch( Func lerp, Func getValue, Func 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 ]; } } }