382 lines
9.9 KiB
C#
382 lines
9.9 KiB
C#
|
|
using Godot;
|
|
using Rokojori;
|
|
|
|
namespace Rokojori
|
|
{
|
|
|
|
[Tool]
|
|
[GlobalClass]
|
|
public partial class UINumber : Resource
|
|
{
|
|
[Export]
|
|
public float value = 0;
|
|
|
|
[Export]
|
|
public string unit = "";
|
|
|
|
[ExportGroup("Animation")]
|
|
|
|
[Export]
|
|
public bool isAnimated;
|
|
|
|
[Export]
|
|
public Curve animationCurve;
|
|
|
|
[Export]
|
|
public float animationDuration;
|
|
|
|
[Export]
|
|
public float animationOffset;
|
|
|
|
[Export]
|
|
public RJTimeLine timeLine;
|
|
|
|
public bool IsNone => unit == "none";
|
|
|
|
public float ComputeRaw( Control control, float alternative )
|
|
{
|
|
return UINumber.Compute( control, this, alternative );
|
|
}
|
|
|
|
|
|
public static bool IsNullOrNone( UIStylePropertyContainer container, UIStyleNumberProperty property )
|
|
{
|
|
return IsNullOrNone( UIStyle.GetUINumberProperty( container, property ) );
|
|
}
|
|
|
|
public static bool IsNullOrNone( UINumber number )
|
|
{
|
|
if ( number == null )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return number.IsNone;
|
|
}
|
|
|
|
public static int ComputeInt( Control control, UINumber number, float alternative = 0, float relative = 100 )
|
|
{
|
|
return Mathf.RoundToInt( Compute( control, number, alternative, relative ) );
|
|
}
|
|
|
|
public static int ComputeInt( Control control, UIStyleNumberProperty property, float alternative = 0, float relative = 100 )
|
|
{
|
|
return Mathf.RoundToInt( Compute( control, property, alternative, relative ) );
|
|
}
|
|
|
|
public bool Equals( UINumber other )
|
|
{
|
|
if ( other == this )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if ( other == null )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ( other.value != value )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ( other.unit != unit )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ( other.isAnimated != isAnimated )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ( other.animationCurve != animationCurve )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ( other.animationDuration != animationDuration )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ( other.animationOffset != animationOffset )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ( other.timeLine != timeLine )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
public void CopyForm( UINumber other )
|
|
{
|
|
if ( other == this )
|
|
{
|
|
return;
|
|
}
|
|
|
|
value = other.value;
|
|
unit = other.unit;
|
|
isAnimated = other.isAnimated;
|
|
animationCurve = other.animationCurve;
|
|
animationDuration = other.animationDuration;
|
|
animationOffset = other.animationOffset;
|
|
timeLine = other.timeLine;
|
|
}
|
|
|
|
public static float Compute( Control control, UIStyleNumberProperty property, float alternative = 0, float relative = 100 )
|
|
{
|
|
var container = control as UIStylePropertyContainer;
|
|
var transition = UIStyle.GetTransition( container, property );
|
|
|
|
var number = UIStyle.GetUINumberProperty( control as UIStylePropertyContainer, property );
|
|
var computedValue = Compute( control, number, alternative, relative );
|
|
|
|
var allSettings = UIStyle.GetTransitionSettingsAll( container );
|
|
|
|
var usesTransition = transition != null || allSettings != null && allSettings.transitionAllProperties;
|
|
|
|
if ( ! usesTransition )
|
|
{
|
|
return computedValue;
|
|
}
|
|
|
|
var activeNumberTransitions = container.GetActiveUINumberTransitions();
|
|
|
|
var propertyTransition = activeNumberTransitions.Find( t => t != null && t.propertyType == property );
|
|
|
|
if ( propertyTransition == null )
|
|
{
|
|
propertyTransition = new ActiveStyleTransition<UINumber, UIStyleNumberProperty>();
|
|
propertyTransition.propertyType = property;
|
|
propertyTransition.value = number;
|
|
propertyTransition.transitioning = false;
|
|
|
|
activeNumberTransitions.Add( propertyTransition );
|
|
|
|
return computedValue;
|
|
}
|
|
else
|
|
{
|
|
if ( propertyTransition.value != number && ! propertyTransition.transitioning && UIStyle.GetTransitionSettings( container, property ) != null )
|
|
{
|
|
var transitionSettings = UIStyle.GetTransitionSettings( container, property );
|
|
propertyTransition.timeLine = transitionSettings.timeLine;
|
|
propertyTransition.start = TimeLineManager.GetPosition( transitionSettings.timeLine );
|
|
propertyTransition.end = propertyTransition.start + transitionSettings.duration;
|
|
propertyTransition.transitioning = true;
|
|
propertyTransition.curve = transitionSettings.curve;
|
|
}
|
|
}
|
|
|
|
if ( propertyTransition.value == number )
|
|
{
|
|
propertyTransition.transitioning = false;
|
|
return computedValue;
|
|
}
|
|
|
|
var computedTransitionValue = Compute( control, propertyTransition.value, alternative, relative );
|
|
|
|
var transitionPhase = TimeLineManager.GetRangePhase( propertyTransition.timeLine, propertyTransition.start, propertyTransition.end );
|
|
|
|
if ( transitionPhase >= 1 )
|
|
{
|
|
activeNumberTransitions.Remove( propertyTransition );
|
|
}
|
|
|
|
var amount = MathX.Clamp01( transitionPhase );
|
|
var curveAmount = amount;
|
|
|
|
if ( propertyTransition.curve != null )
|
|
{
|
|
curveAmount = propertyTransition.curve.Sample( curveAmount );
|
|
}
|
|
|
|
return Mathf.Lerp( computedTransitionValue, computedValue, curveAmount );
|
|
}
|
|
|
|
|
|
public static float Compute( Control control, UINumber number, float alternative = 0, float relative = 100 )
|
|
{
|
|
if ( number == null || control == null || number.IsNone )
|
|
{
|
|
return alternative;
|
|
}
|
|
|
|
var width = UI.GetWindowWidth( control );
|
|
var height = UI.GetWindowHeight( control );
|
|
|
|
|
|
return Compute( control, number, width, height, relative );
|
|
|
|
}
|
|
|
|
static UI _ui;
|
|
|
|
public static float em()
|
|
{
|
|
return _ui == null ? 12 : _ui.X_computedFontSizePixels;
|
|
}
|
|
|
|
public static float Compute( Control control, UINumber number, float width, float height, float relative )
|
|
{
|
|
var value = ComputeWithoutAnimation( control, number, width, height, relative );
|
|
|
|
if ( ! number.isAnimated || number.animationCurve == null )
|
|
{
|
|
return value;
|
|
}
|
|
|
|
var phase = TimeLineManager.GetPhase( number.timeLine, number.animationDuration, number.animationOffset );
|
|
|
|
return number.animationCurve.Sample( phase ) * value;
|
|
|
|
}
|
|
|
|
static float ComputeWithoutAnimation( Control control, UINumber number, float width, float height, float relative )
|
|
{
|
|
if ( number == null )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if ( _ui == null )
|
|
{
|
|
_ui = NodesWalker.Get().GetInParents( control, n => n is UI ) as UI;
|
|
}
|
|
|
|
switch ( number.unit )
|
|
{
|
|
case "em":
|
|
{
|
|
return number.value * em();
|
|
}
|
|
|
|
case "vw":
|
|
{
|
|
return number.value * width / 100f;
|
|
}
|
|
|
|
case "vh":
|
|
{
|
|
return number.value * height / 100f;
|
|
}
|
|
|
|
case "pw":
|
|
{
|
|
var parent = control.GetParent<Control>();
|
|
return number.value / 100f * ( parent == null ? width : parent.Size.X );
|
|
}
|
|
|
|
case "cw":
|
|
{
|
|
var parent = control.GetParent<Control>();
|
|
return number.value / 100f * ( parent == null ? width : UILayouting.GetContentSize( parent ).X );
|
|
}
|
|
|
|
case "ch":
|
|
{
|
|
var parent = control.GetParent<Control>();
|
|
return number.value / 100f * ( parent == null ? height : UILayouting.GetContentSize( parent ).Y );
|
|
}
|
|
|
|
case "cx":
|
|
{
|
|
var parent = control.GetParent<Control>();
|
|
return number.value / 100f * ( parent == null ? 0 : UILayouting.GetContentOffset( parent ).X );
|
|
}
|
|
|
|
case "cy":
|
|
{
|
|
var parent = control.GetParent<Control>();
|
|
return number.value / 100f * ( parent == null ? 0 : UILayouting.GetContentOffset( parent ).Y );
|
|
}
|
|
|
|
case "ph":
|
|
{
|
|
var parent = control.GetParent<Control>();
|
|
return number.value / 100f * ( parent == null ? height : parent.Size.Y );
|
|
}
|
|
|
|
case "":
|
|
{
|
|
return number.value;
|
|
}
|
|
|
|
case "%":
|
|
{
|
|
return number.value * relative / 100f;
|
|
}
|
|
}
|
|
|
|
var expression = new Expression();
|
|
|
|
var expressionText = number.unit == null ? "" : RegexUtility.Replace( number.unit, "%", " * relative " );
|
|
var parseResult = expression.Parse( expressionText,
|
|
new string[]
|
|
{
|
|
"em",
|
|
|
|
"vw", "vh",
|
|
"pw", "ph",
|
|
|
|
"cw","ch",
|
|
"cx","cy",
|
|
|
|
"relative",
|
|
"value"
|
|
}
|
|
);
|
|
|
|
if ( Error.Ok != parseResult )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
var parentControl = control.GetParent<Control>();
|
|
|
|
var inputs = new Godot.Collections.Array();
|
|
inputs.Add( em() );
|
|
|
|
// vw, vh
|
|
inputs.Add( width / 100f ); inputs.Add( height / 100f );
|
|
|
|
// pw, ph
|
|
inputs.Add( ( parentControl == null ? width : parentControl.Size.X ) / 100f );
|
|
inputs.Add( ( parentControl == null ? height : parentControl.Size.Y ) / 100f );
|
|
|
|
// cw, ch
|
|
inputs.Add( ( parentControl == null ? width : UILayouting.GetContentSize( parentControl ).X ) / 100f );
|
|
inputs.Add( ( parentControl == null ? width : UILayouting.GetContentSize( parentControl ).Y ) / 100f );
|
|
|
|
// cx, cy
|
|
inputs.Add( ( parentControl == null ? 0 : UILayouting.GetContentOffset( parentControl ).X ) / 100f );
|
|
inputs.Add( ( parentControl == null ? 0 : UILayouting.GetContentOffset( parentControl ).Y ) / 100f );
|
|
|
|
// "relative"
|
|
inputs.Add( relative / 100f );
|
|
|
|
// value
|
|
if ( number.unit.IndexOf( "value" ) == -1 )
|
|
{
|
|
inputs.Add( 0 );
|
|
return number.value * (float) expression.Execute( inputs ).AsDouble() ;
|
|
}
|
|
|
|
inputs.Add( number.value );
|
|
|
|
return (float) expression.Execute( inputs ).AsDouble() ;
|
|
}
|
|
|
|
}
|
|
|
|
}
|