using Godot; using Rokojori; namespace Rokojori { [Tool] [GlobalClass] public partial class UINumber : Resource { [Export] public float value = 0; [Export] public string unit = ""; public bool IsNone => unit == "none"; public float Compute( Control control, float alternative ) { return UINumber.Compute( control, this, alternative ); } public static bool IsNullOrNone( UINumber number ) { if ( number == null ) { return true; } return number.IsNone; } 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; static float em() { return _ui == null ? 12 : _ui.X_computedFontSizePixels; } public static float Compute( 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(); return number.value / 100f * ( parent == null ? width : parent.Size.X ); } case "ph": { var parent = control.GetParent(); return number.value / 100f * ( parent == null ? height : parent.Size.Y ); } case "px": 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", "px", "relative", "value" } ); if ( Error.Ok != parseResult ) { return 0; } var parentControl = control.GetParent(); 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 ); 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() ; } } }