Godot UI
This commit is contained in:
parent
52b46024cc
commit
9a07e22b05
|
@ -240,6 +240,24 @@ namespace Rokojori
|
|||
return NextNonChild( node );
|
||||
}
|
||||
|
||||
public N GetParent( N node, Func<N,bool> predicate )
|
||||
{
|
||||
var p = Parent( node );
|
||||
|
||||
while ( p != null )
|
||||
{
|
||||
if ( predicate( p ) )
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
p = Parent( p );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public int GetDepth( N node, Dictionary<N, int> depthMap = null )
|
||||
{
|
||||
if ( depthMap == null )
|
||||
|
|
|
@ -0,0 +1,235 @@
|
|||
|
||||
using Godot;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
public class UIFlowLayout
|
||||
{
|
||||
public class ControlPlacement
|
||||
{
|
||||
public Control control;
|
||||
public float offset;
|
||||
public float width;
|
||||
public float height;
|
||||
|
||||
public float yOffset = 0;
|
||||
|
||||
public float maxX => offset + width;
|
||||
|
||||
public void AlignVertically( float maxHeight, float alignment )
|
||||
{
|
||||
var bottomAlignement = maxHeight - height;
|
||||
|
||||
yOffset = Mathf.Lerp( 0, bottomAlignement, alignment );
|
||||
}
|
||||
|
||||
public void Apply( Vector2 parentOffset )
|
||||
{
|
||||
if ( UIStyling.CanPosition( control ) )
|
||||
{
|
||||
var container = (UIStylePropertyContainer) control;
|
||||
|
||||
var left = UIStyle.Left( container );
|
||||
var right = UIStyle.Right( container );
|
||||
var top = UIStyle.Top( container );
|
||||
var bottom = UIStyle.Bottom( container );
|
||||
|
||||
var offsetX = UINumber.Compute( control, left, 0 ) - UINumber.Compute( control, right, 0 );
|
||||
var offsetY = UINumber.Compute( control, top, 0 ) - UINumber.Compute( control, bottom, 0 );
|
||||
|
||||
UILayouting.SetPosition( control, parentOffset + new Vector2( offset + offsetX, yOffset + offsetY ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
control.Position = parentOffset + new Vector2( offset, yOffset );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Line
|
||||
{
|
||||
public float y;
|
||||
public float size;
|
||||
public float xOffset;
|
||||
public List<ControlPlacement> placements = new List<ControlPlacement>();
|
||||
|
||||
public float maxY => y + size;
|
||||
public float maxX => placements.Count == 0 ? 0 : placements[ placements.Count -1 ].maxX ;
|
||||
}
|
||||
|
||||
public static void Apply( UIRegion region )
|
||||
{
|
||||
var lines = CreateLines( region );
|
||||
|
||||
AdjustLines( region, lines );
|
||||
|
||||
var maxWidth = 0f;
|
||||
var maxHeight = 0f;
|
||||
|
||||
if ( UINumber.IsNullOrNone( region.width ) )
|
||||
{
|
||||
lines.ForEach( l => { maxWidth = Mathf.Max( maxWidth, l.maxX ); } );
|
||||
}
|
||||
else
|
||||
{
|
||||
maxWidth = UINumber.Compute( region, region.width );
|
||||
}
|
||||
|
||||
if ( lines.Count > 0 )
|
||||
{
|
||||
maxHeight = lines[ lines.Count - 1 ].maxY;
|
||||
}
|
||||
|
||||
var margin = UINumber.Compute( region, region.margin, 0 );
|
||||
var marginLeft = margin + UINumber.Compute( region, region.marginLeft, 0 );
|
||||
var marginTop = margin + UINumber.Compute( region, region.marginTop, 0 );
|
||||
|
||||
var marginRight = margin + UINumber.Compute( region, region.marginRight, 0 );
|
||||
var marginBottom = margin + UINumber.Compute( region, region.marginBottom, 0 );
|
||||
|
||||
|
||||
var marginOffset = new Vector2( marginLeft, marginTop );
|
||||
|
||||
PlaceControls( region, lines, marginOffset );
|
||||
|
||||
var verticalMargins = marginTop + marginBottom;
|
||||
var horizontalMargins = marginLeft + marginRight;
|
||||
|
||||
region.Size = new Vector2( maxWidth + horizontalMargins, maxHeight + verticalMargins );
|
||||
|
||||
if ( region.position == UIPosition.Parent_Anchor )
|
||||
{
|
||||
var p = NodesWalker.Get().Parent( region ) as Control;
|
||||
|
||||
if ( p != null )
|
||||
{
|
||||
var pWidth = UILayouting.GetWidth( p );
|
||||
var pHeight = UILayouting.GetHeight( p );
|
||||
|
||||
var x = p.Position.X;
|
||||
var y = p.Position.Y;
|
||||
|
||||
|
||||
if ( ! UINumber.IsNullOrNone( region.left ))
|
||||
{
|
||||
var left = UINumber.Compute( region, region.left, 0 );
|
||||
x = left;
|
||||
}
|
||||
else if ( ! UINumber.IsNullOrNone( region.right ) )
|
||||
{
|
||||
var right = UINumber.Compute( region, region.right, 0 );
|
||||
x = ( pWidth - UILayouting.GetWidth( region ) ) - right;
|
||||
}
|
||||
|
||||
UILayouting.SetPosition( region, new Vector2( x, y ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static List<Line> CreateLines( UIRegion region )
|
||||
{
|
||||
var x = 0f;
|
||||
var width = UINumber.Compute( region, region.width, 100000000f );
|
||||
|
||||
var lines = new List<Line>();
|
||||
var currentLine = new Line();
|
||||
|
||||
var elementSpacing = UINumber.Compute( region, region.elementSpacing, 0f );
|
||||
|
||||
Nodes.ForEachDirectChild<Control>( region, c => UILayouting.UpdateChild( c ) );
|
||||
|
||||
|
||||
Nodes.ForEachDirectChild<Control>( region,
|
||||
child =>
|
||||
{
|
||||
|
||||
var cWidth = UILayouting.GetWidth( child );
|
||||
var cHeight = UILayouting.GetHeight( child );
|
||||
|
||||
var nextEndX = x + cWidth + elementSpacing;
|
||||
|
||||
if ( nextEndX > width )
|
||||
{
|
||||
lines.Add( currentLine );
|
||||
currentLine = new Line();
|
||||
x = 0;
|
||||
currentLine.y = lines[ lines.Count - 1 ].maxY;
|
||||
nextEndX = cWidth + elementSpacing;
|
||||
}
|
||||
|
||||
var placement = new ControlPlacement();
|
||||
placement.offset = x;
|
||||
placement.width = cWidth;
|
||||
placement.height = cHeight;
|
||||
placement.control = child;
|
||||
|
||||
currentLine.placements.Add( placement );
|
||||
|
||||
currentLine.size = Mathf.Max( currentLine.size, cHeight );
|
||||
|
||||
x = nextEndX;
|
||||
}
|
||||
);
|
||||
|
||||
if ( lines.Count > 0 )
|
||||
{
|
||||
currentLine.y = lines[ lines.Count - 1 ].maxY;
|
||||
}
|
||||
|
||||
lines.Add( currentLine );
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void AdjustLines( UIRegion region, List<Line> lines )
|
||||
{
|
||||
var verticalAlignment = UINumber.Compute( region, region.verticalAlignment, 0.5f, 1 );
|
||||
|
||||
lines.ForEach( line => AdjustVerticalAlignment( region, line, verticalAlignment ) );
|
||||
|
||||
if ( UINumber.IsNullOrNone( region.width ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var horizontalAlignment = UINumber.Compute( region, region.horizontalAlignment, 0.5f, 1 );
|
||||
var maxWidth = UINumber.Compute( region, region.width, 0 );
|
||||
|
||||
lines.ForEach( line => AdjustHorizontalAlignment( region, line, horizontalAlignment, maxWidth ) );
|
||||
|
||||
}
|
||||
|
||||
static void AdjustVerticalAlignment( UIRegion region, Line line, float verticalAlignment )
|
||||
{
|
||||
line.placements.ForEach( p => p.AlignVertically( line.size, verticalAlignment ) );
|
||||
}
|
||||
|
||||
static void AdjustHorizontalAlignment( UIRegion region, Line line, float horizontalAlignment, float maxWidth )
|
||||
{
|
||||
var lineWidth = line.maxX;
|
||||
var maxOffset = maxWidth - lineWidth;
|
||||
|
||||
line.xOffset = horizontalAlignment * maxOffset;
|
||||
}
|
||||
|
||||
|
||||
static void PlaceControls( UIRegion region, List<Line> lines, Vector2 marginOffset )
|
||||
{
|
||||
lines.ForEach(
|
||||
line =>
|
||||
{
|
||||
var offset = new Vector2( line.xOffset, line.y ) + marginOffset;
|
||||
line.placements.ForEach( p => p.Apply( offset ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
using Godot;
|
||||
using Rokojori;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
public enum UILayout
|
||||
{
|
||||
Flow_Left_Top
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
|
||||
using Godot;
|
||||
using Rokojori;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
public class UILayouting
|
||||
{
|
||||
public static void UpdateChild( Control control )
|
||||
{
|
||||
if ( control is UIRegion )
|
||||
{
|
||||
var childUIRegion = (UIRegion) control;
|
||||
childUIRegion.Layout();
|
||||
}
|
||||
else if ( control is UIImage )
|
||||
{
|
||||
var uiImage = (UIImage) control;
|
||||
|
||||
if ( uiImage.Texture == null )
|
||||
{
|
||||
uiImage.Size = new Vector2( 0, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
var tw = uiImage.Texture.GetWidth();
|
||||
var th = uiImage.Texture.GetHeight();
|
||||
|
||||
var w = UINumber.Compute( control, uiImage.width, tw, tw / 100f );
|
||||
var h = UINumber.Compute( control, uiImage.height, th, th / 100f );
|
||||
|
||||
uiImage.Size = new Vector2( w, h );
|
||||
}
|
||||
else
|
||||
{
|
||||
control.UpdateMinimumSize();
|
||||
control.Size = control.GetMinimumSize();
|
||||
}
|
||||
|
||||
UILayouting.UpdatePivot( control );
|
||||
}
|
||||
|
||||
public static void UpdatePivot( Control c )
|
||||
{
|
||||
if ( ! ( c is UIImage || c is UIRegion || c is UIText ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var container = c as UIStylePropertyContainer;
|
||||
|
||||
var pivotX = UINumber.Compute( c, UIStyle.PivotX( container ), 0, c.Size.X );
|
||||
var pivotY = UINumber.Compute( c, UIStyle.PivotY( container ), 0, c.Size.Y );
|
||||
|
||||
c.PivotOffset = new Vector2( pivotX, pivotY );
|
||||
|
||||
c.Rotation = UINumber.Compute( c, UIStyle.Rotation( container ), 0 );
|
||||
|
||||
var scale = UINumber.Compute( c, UIStyle.Scale( container ), 1, 1 );
|
||||
|
||||
c.Scale = new Vector2(
|
||||
UINumber.Compute( c, UIStyle.ScaleX( container ), 1, 1 ) ,
|
||||
UINumber.Compute( c, UIStyle.ScaleY( container ), 1, 1 )
|
||||
) * scale;
|
||||
|
||||
}
|
||||
|
||||
public static void SetPosition( Control c, Vector2 position )
|
||||
{
|
||||
if ( UIStyling.HasInnerMargins( c ) )
|
||||
{
|
||||
var container = c as UIStylePropertyContainer;
|
||||
|
||||
var margin = UINumber.Compute( c, UIStyle.Margin( container ), 0 );
|
||||
var marginLeft = margin + UINumber.Compute( c, UIStyle.MarginLeft( container ), 0 );
|
||||
var marginTop = margin + UINumber.Compute( c, UIStyle.MarginTop( container ), 0 );
|
||||
|
||||
position.X += marginLeft;
|
||||
position.Y += marginTop;
|
||||
|
||||
}
|
||||
|
||||
c.Position = position;
|
||||
}
|
||||
|
||||
public static float GetWidth( Control c )
|
||||
{
|
||||
if ( UIStyling.HasInnerMargins( c ) )
|
||||
{
|
||||
var container = c as UIStylePropertyContainer;
|
||||
|
||||
var margin = UINumber.Compute( c, UIStyle.Margin( container ), 0 );
|
||||
var marginLeft = margin + UINumber.Compute( c, UIStyle.MarginLeft( container ), 0 );
|
||||
var marginRight = margin + UINumber.Compute( c, UIStyle.MarginRight( container ), 0 );
|
||||
|
||||
return c.Size.X + marginLeft + marginRight;
|
||||
|
||||
}
|
||||
|
||||
return c.Size.X;
|
||||
}
|
||||
|
||||
public static float GetHeight( Control c )
|
||||
{
|
||||
if ( UIStyling.HasInnerMargins( c ) )
|
||||
{
|
||||
var container = c as UIStylePropertyContainer;
|
||||
|
||||
var margin = UINumber.Compute( c, UIStyle.Margin( container ), 0 );
|
||||
var marginTop = margin + UINumber.Compute( c, UIStyle.MarginTop( container ), 0 );
|
||||
var marginBottom = margin + UINumber.Compute( c, UIStyle.MarginBottom( container ), 0 );
|
||||
|
||||
return c.Size.Y + marginTop + marginBottom;
|
||||
|
||||
}
|
||||
|
||||
return c.Size.Y;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
|
||||
using Godot;
|
||||
using Rokojori;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class UIImage:TextureRect, UIStylePropertyContainer
|
||||
{
|
||||
[ExportCategory("Size & Margins")]
|
||||
[Export]
|
||||
public UINumber width;
|
||||
|
||||
[Export]
|
||||
public UINumber height;
|
||||
|
||||
|
||||
[Export]
|
||||
public UINumber margin;
|
||||
|
||||
[Export]
|
||||
public UINumber marginLeft;
|
||||
[Export]
|
||||
public UINumber marginTop;
|
||||
[Export]
|
||||
public UINumber marginRight;
|
||||
[Export]
|
||||
public UINumber marginBottom;
|
||||
|
||||
|
||||
[ExportCategory("Position")]
|
||||
[Export]
|
||||
public UIPosition position;
|
||||
[Export]
|
||||
public UINumber left;
|
||||
[Export]
|
||||
public UINumber top;
|
||||
[Export]
|
||||
public UINumber right;
|
||||
[Export]
|
||||
public UINumber bottom;
|
||||
|
||||
|
||||
[ExportCategory("Rotation & Scale")]
|
||||
[Export]
|
||||
public UINumber pivotX;
|
||||
[Export]
|
||||
public UINumber pivotY;
|
||||
|
||||
[Export]
|
||||
public UINumber rotation;
|
||||
|
||||
[Export]
|
||||
public UINumber scale;
|
||||
|
||||
[Export]
|
||||
public UINumber scaleX;
|
||||
[Export]
|
||||
public UINumber scaleY;
|
||||
|
||||
|
||||
public UINumber GetUIStyleNumberProperty( UIStyleNumberProperty property )
|
||||
{
|
||||
switch ( property )
|
||||
{
|
||||
case UIStyleNumberProperty.Width: return width;
|
||||
case UIStyleNumberProperty.Height: return height;
|
||||
|
||||
case UIStyleNumberProperty.Margin: return margin;
|
||||
|
||||
case UIStyleNumberProperty.MarginLeft: return marginLeft;
|
||||
case UIStyleNumberProperty.MarginRight: return marginRight;
|
||||
case UIStyleNumberProperty.MarginTop: return marginTop;
|
||||
case UIStyleNumberProperty.MarginBottom: return marginBottom;
|
||||
|
||||
|
||||
case UIStyleNumberProperty.Left: return left;
|
||||
case UIStyleNumberProperty.Right: return right;
|
||||
case UIStyleNumberProperty.Top: return top;
|
||||
case UIStyleNumberProperty.Bottom: return bottom;
|
||||
|
||||
case UIStyleNumberProperty.PivotX: return pivotX;
|
||||
case UIStyleNumberProperty.PivotY: return pivotY;
|
||||
case UIStyleNumberProperty.Rotation: return rotation;
|
||||
|
||||
case UIStyleNumberProperty.Scale: return scale;
|
||||
case UIStyleNumberProperty.ScaleX: return scaleX;
|
||||
case UIStyleNumberProperty.ScaleY: return scaleY;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
|
||||
using Godot;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class UIRegion : Control, UIStylePropertyContainer
|
||||
{
|
||||
[Export]
|
||||
public UIStyle parent;
|
||||
|
||||
[ExportCategory("Layout")]
|
||||
[Export]
|
||||
public UILayout layout;
|
||||
|
||||
[Export]
|
||||
public UINumber horizontalAlignment;
|
||||
[Export]
|
||||
public UINumber verticalAlignment;
|
||||
|
||||
[Export]
|
||||
public UINumber elementSpacing;
|
||||
[Export]
|
||||
public UINumber lineSpacing;
|
||||
|
||||
|
||||
[ExportCategory("Size & Margins")]
|
||||
[Export]
|
||||
public UINumber width;
|
||||
[Export]
|
||||
public UINumber height;
|
||||
|
||||
|
||||
[Export]
|
||||
public UINumber margin;
|
||||
|
||||
[Export]
|
||||
public UINumber marginLeft;
|
||||
[Export]
|
||||
public UINumber marginTop;
|
||||
[Export]
|
||||
public UINumber marginRight;
|
||||
[Export]
|
||||
public UINumber marginBottom;
|
||||
|
||||
[ExportCategory("Position")]
|
||||
[Export]
|
||||
public UIPosition position;
|
||||
[Export]
|
||||
public UINumber left;
|
||||
[Export]
|
||||
public UINumber top;
|
||||
[Export]
|
||||
public UINumber right;
|
||||
[Export]
|
||||
public UINumber bottom;
|
||||
|
||||
|
||||
public UINumber GetUIStyleNumberProperty( UIStyleNumberProperty property )
|
||||
{
|
||||
switch ( property )
|
||||
{
|
||||
case UIStyleNumberProperty.Left: return left;
|
||||
case UIStyleNumberProperty.Right: return right;
|
||||
case UIStyleNumberProperty.Top: return top;
|
||||
case UIStyleNumberProperty.Bottom: return bottom;
|
||||
|
||||
case UIStyleNumberProperty.Width: return width;
|
||||
case UIStyleNumberProperty.Height: return height;
|
||||
|
||||
case UIStyleNumberProperty.Margin: return margin;
|
||||
|
||||
case UIStyleNumberProperty.MarginLeft: return marginLeft;
|
||||
case UIStyleNumberProperty.MarginRight: return marginRight;
|
||||
case UIStyleNumberProperty.MarginTop: return marginTop;
|
||||
case UIStyleNumberProperty.MarginBottom: return marginBottom;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public void Layout()
|
||||
{
|
||||
switch ( layout )
|
||||
{
|
||||
case UILayout.Flow_Left_Top: UIFlowLayout.Apply( this ); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
|
||||
using Godot;
|
||||
using Rokojori;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class UIText:Label,UIStylePropertyContainer
|
||||
{
|
||||
[ExportCategory("Size & Margins")]
|
||||
[Export]
|
||||
public UINumber width;
|
||||
|
||||
[Export]
|
||||
public UINumber height;
|
||||
|
||||
|
||||
[Export]
|
||||
public UINumber margin;
|
||||
|
||||
[Export]
|
||||
public UINumber marginLeft;
|
||||
[Export]
|
||||
public UINumber marginTop;
|
||||
[Export]
|
||||
public UINumber marginRight;
|
||||
[Export]
|
||||
public UINumber marginBottom;
|
||||
|
||||
|
||||
[ExportCategory("Position")]
|
||||
[Export]
|
||||
public UIPosition position;
|
||||
[Export]
|
||||
public UINumber left;
|
||||
[Export]
|
||||
public UINumber top;
|
||||
[Export]
|
||||
public UINumber right;
|
||||
[Export]
|
||||
public UINumber bottom;
|
||||
|
||||
|
||||
[ExportCategory("Rotation & Scale")]
|
||||
[Export]
|
||||
public UINumber pivotX;
|
||||
[Export]
|
||||
public UINumber pivotY;
|
||||
|
||||
[Export]
|
||||
public UINumber rotation;
|
||||
|
||||
[Export]
|
||||
public UINumber scale;
|
||||
|
||||
[Export]
|
||||
public UINumber scaleX;
|
||||
[Export]
|
||||
public UINumber scaleY;
|
||||
|
||||
|
||||
public UINumber GetUIStyleNumberProperty( UIStyleNumberProperty property )
|
||||
{
|
||||
switch ( property )
|
||||
{
|
||||
case UIStyleNumberProperty.Width: return width;
|
||||
case UIStyleNumberProperty.Height: return height;
|
||||
|
||||
case UIStyleNumberProperty.Margin: return margin;
|
||||
|
||||
case UIStyleNumberProperty.MarginLeft: return marginLeft;
|
||||
case UIStyleNumberProperty.MarginRight: return marginRight;
|
||||
case UIStyleNumberProperty.MarginTop: return marginTop;
|
||||
case UIStyleNumberProperty.MarginBottom: return marginBottom;
|
||||
|
||||
|
||||
case UIStyleNumberProperty.Left: return left;
|
||||
case UIStyleNumberProperty.Right: return right;
|
||||
case UIStyleNumberProperty.Top: return top;
|
||||
case UIStyleNumberProperty.Bottom: return bottom;
|
||||
|
||||
case UIStyleNumberProperty.PivotX: return pivotX;
|
||||
case UIStyleNumberProperty.PivotY: return pivotY;
|
||||
case UIStyleNumberProperty.Rotation: return rotation;
|
||||
|
||||
case UIStyleNumberProperty.Scale: return scale;
|
||||
case UIStyleNumberProperty.ScaleX: return scaleX;
|
||||
case UIStyleNumberProperty.ScaleY: return scaleY;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
|
||||
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 = 0;
|
||||
var height = 0;
|
||||
|
||||
if ( Engine.IsEditorHint() )
|
||||
{
|
||||
width = ProjectSettings.GetSetting( "display/window/size/viewport_width" ).AsInt32();
|
||||
height = ProjectSettings.GetSetting( "display/window/size/viewport_height" ).AsInt32();
|
||||
}
|
||||
else
|
||||
{
|
||||
width = control.GetWindow().Size.X;
|
||||
height = control.GetWindow().Size.Y;
|
||||
}
|
||||
|
||||
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().GetParent( 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 "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", "px", "relative", "value" } );
|
||||
|
||||
if ( Error.Ok != parseResult )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
var inputs = new Godot.Collections.Array();
|
||||
inputs.Add( em() );
|
||||
inputs.Add( width / 100f );
|
||||
inputs.Add( height / 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() ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
using Godot;
|
||||
using Rokojori;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
public enum UIPosition
|
||||
{
|
||||
From_Layout,
|
||||
Parent_Anchor
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
|
||||
using Godot;
|
||||
using Rokojori;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class UIStyle:Resource
|
||||
{
|
||||
[Export]
|
||||
public UIStyle parent;
|
||||
|
||||
[Export]
|
||||
public UILayout layoutType;
|
||||
|
||||
[ExportCategory("Width")]
|
||||
[Export]
|
||||
public float widthValue = 1;
|
||||
[Export]
|
||||
public string widthUnit = "vw";
|
||||
|
||||
[ExportCategory("Height")]
|
||||
[Export]
|
||||
public float heightValue = 1;
|
||||
[Export]
|
||||
public string heightUnit = "vw";
|
||||
|
||||
[ExportCategory("LineSpacing")]
|
||||
[Export]
|
||||
public float lineSpacingValue = 1;
|
||||
[Export]
|
||||
public string ineSpacingtUnit = "vw";
|
||||
|
||||
|
||||
public static UINumber Left( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.Left );
|
||||
}
|
||||
|
||||
public static UINumber Right( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.Right );
|
||||
}
|
||||
|
||||
public static UINumber Top( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.Top );
|
||||
}
|
||||
|
||||
public static UINumber Bottom( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.Bottom );
|
||||
}
|
||||
|
||||
public static UINumber Margin( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.Margin );
|
||||
}
|
||||
|
||||
public static UINumber MarginLeft( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.MarginLeft );
|
||||
}
|
||||
|
||||
public static UINumber MarginRight( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.MarginRight );
|
||||
}
|
||||
|
||||
public static UINumber MarginTop( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.MarginTop );
|
||||
}
|
||||
|
||||
public static UINumber MarginBottom( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.MarginBottom );
|
||||
}
|
||||
|
||||
public static UINumber PivotX( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.PivotX );
|
||||
}
|
||||
|
||||
public static UINumber PivotY( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.PivotY );
|
||||
}
|
||||
|
||||
public static UINumber Rotation( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.Rotation );
|
||||
}
|
||||
|
||||
public static UINumber Scale( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.Scale );
|
||||
}
|
||||
|
||||
public static UINumber ScaleX( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.ScaleX );
|
||||
}
|
||||
|
||||
public static UINumber ScaleY( UIStylePropertyContainer container )
|
||||
{
|
||||
return container.GetUIStyleNumberProperty( UIStyleNumberProperty.ScaleY );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
using Godot;
|
||||
using Rokojori;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
public enum UIStyleNumberProperty
|
||||
{
|
||||
Left,
|
||||
Right,
|
||||
Bottom,
|
||||
Top,
|
||||
|
||||
Width,
|
||||
Height,
|
||||
|
||||
Margin,
|
||||
MarginLeft,
|
||||
MarginRight,
|
||||
MarginTop,
|
||||
MarginBottom,
|
||||
|
||||
PivotX,
|
||||
PivotY,
|
||||
|
||||
Rotation,
|
||||
|
||||
Scale,
|
||||
ScaleX,
|
||||
ScaleY
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
using Godot;
|
||||
using Rokojori;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
public interface UIStylePropertyContainer
|
||||
{
|
||||
UINumber GetUIStyleNumberProperty( UIStyleNumberProperty property );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
using Godot;
|
||||
using Rokojori;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
public class UIStyling
|
||||
{
|
||||
public static bool CanPosition( Control control )
|
||||
{
|
||||
if ( control is UIRegion || control is UIImage || control is UIText )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool HasInnerMargins( Control control )
|
||||
{
|
||||
return control is UIImage || control is UIText;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
|
||||
using Godot;
|
||||
|
||||
namespace Rokojori
|
||||
{
|
||||
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class UI : Control
|
||||
{
|
||||
[Export]
|
||||
public UINumber fontSize;
|
||||
|
||||
[Export]
|
||||
public float fontZoom = 1;
|
||||
|
||||
[Export]
|
||||
public float X_computedFontSizePixels = 1;
|
||||
|
||||
[Export]
|
||||
public bool updateFlag = false;
|
||||
|
||||
[Export]
|
||||
public bool updateAlways = true;
|
||||
|
||||
public override void _Process( double delta )
|
||||
{
|
||||
UpdateFontSize();
|
||||
UpdateUIElements();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void UpdateFontSize()
|
||||
{
|
||||
X_computedFontSizePixels = UINumber.Compute( this, fontSize ) * fontZoom;
|
||||
|
||||
if ( Theme != null )
|
||||
{
|
||||
Theme.DefaultFontSize = Mathf.RoundToInt( X_computedFontSizePixels );
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateUIElements()
|
||||
{
|
||||
if ( ! ( updateFlag || updateAlways ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
updateFlag = false;
|
||||
|
||||
Nodes.ForEachDirectChild<UIRegion>( this, r => r.Layout() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue