Merge remote-tracking branch 'origin/master' into 1.9

# Conflicts:
#	Source/Engine/UI/GUI/Common/Button.cs
This commit is contained in:
Wojtek Figat
2024-09-23 14:11:05 +02:00
59 changed files with 675 additions and 319 deletions

View File

@@ -8,7 +8,7 @@ namespace FlaxEngine.GUI
/// Button control
/// </summary>
[ActorToolbox("GUI")]
public class Button : ContainerControl
public class Button : Label
{
/// <summary>
/// The default height for the buttons.
@@ -20,65 +20,16 @@ namespace FlaxEngine.GUI
/// </summary>
protected bool _isPressed;
/// <summary>
/// The font.
/// </summary>
protected FontReference _font;
/// <summary>
/// The text.
/// </summary>
protected LocalizedString _text = new LocalizedString();
/// <summary>
/// Button text property.
/// </summary>
[EditorOrder(10), Tooltip("The button label text.")]
public LocalizedString Text
{
get => _text;
set => _text = value;
}
/// <summary>
/// Gets or sets the font used to draw button text.
/// </summary>
[EditorDisplay("Text Style"), EditorOrder(2022), ExpandGroups]
public FontReference Font
{
get => _font;
set => _font = value;
}
/// <summary>
/// Gets or sets the custom material used to render the text. It must has domain set to GUI and have a public texture parameter named Font used to sample font atlas texture with font characters data.
/// [Deprecated on 18.09.2024, expires on 18.09.2026]
/// </summary>
[EditorDisplay("Text Style"), EditorOrder(2021), Tooltip("Custom material used to render the text. It must has domain set to GUI and have a public texture parameter named Font used to sample font atlas texture with font characters data.")]
public MaterialBase TextMaterial { get; set; }
/// <summary>
/// Gets or sets the color used to draw button text.
/// </summary>
[EditorDisplay("Text Style"), EditorOrder(2020)]
public Color TextColor;
/// <summary>
/// Gets or sets the horizontal text alignment within the control bounds.
/// </summary>
[EditorDisplay("Text Style"), EditorOrder(2027)]
public TextAlignment HorizontalAlignment { get; set; } = TextAlignment.Center;
/// <summary>
/// Gets or sets the vertical text alignment within the control bounds.
/// </summary>
[EditorDisplay("Text Style"), EditorOrder(2028)]
public TextAlignment VerticalAlignment { get; set; } = TextAlignment.Center;
/// <summary>
/// Gets or sets the brush used for background drawing.
/// </summary>
[EditorDisplay("Background Style"), EditorOrder(1999), Tooltip("The brush used for background drawing."), ExpandGroups]
public IBrush BackgroundBrush { get; set; }
[Serialize, Obsolete("Use Material property instead."), NoUndo]
public MaterialBase TextMaterial
{
get => Material;
set => Material = value;
}
/// <summary>
/// Gets or sets the background color when button is highlighted.
@@ -97,7 +48,7 @@ namespace FlaxEngine.GUI
/// </summary>
[EditorDisplay("Border Style"), EditorOrder(2010), ExpandGroups]
public bool HasBorder { get; set; } = true;
/// <summary>
/// Gets or sets the border thickness.
/// </summary>
@@ -165,6 +116,7 @@ namespace FlaxEngine.GUI
public Button(float x, float y, float width = 120, float height = DefaultHeight)
: base(x, y, width, height)
{
AutoFocus = true;
var style = Style.Current;
if (style != null)
{
@@ -242,17 +194,14 @@ namespace FlaxEngine.GUI
/// <inheritdoc />
public override void DrawSelf()
{
// Cache data
Rectangle clientRect = new Rectangle(Float2.Zero, Size);
bool enabled = EnabledInHierarchy;
Color backgroundColor = BackgroundColor;
Color borderColor = BorderColor;
Color textColor = TextColor;
if (!enabled)
{
backgroundColor *= 0.5f;
borderColor *= 0.5f;
textColor *= 0.6f;
}
else if (_isPressed)
{
@@ -274,7 +223,10 @@ namespace FlaxEngine.GUI
Render2D.DrawRectangle(clientRect, borderColor, BorderThickness);
// Draw text
Render2D.DrawText(_font?.GetFont(), TextMaterial, _text, clientRect, textColor, HorizontalAlignment, VerticalAlignment);
backgroundColor = BackgroundColor;
BackgroundColor = Color.Transparent; // Skip background drawing in Control
base.DrawSelf();
BackgroundColor = backgroundColor;
}
/// <inheritdoc />
@@ -339,7 +291,7 @@ namespace FlaxEngine.GUI
OnClick();
return true;
}
if (button == MouseButton.Left && !_isPressed)
{
OnPressBegin();

View File

@@ -135,5 +135,14 @@ namespace FlaxEngine.GUI
return false;
}
/// <inheritdoc />
public override void OnSubmit()
{
base.OnSubmit();
// Execute default user interaction via mouse click
Clicked?.Invoke(this, MouseButton.Left);
}
}
}

View File

@@ -42,6 +42,7 @@ namespace FlaxEngine.GUI
private bool _autoFitText;
private Float2 _textSize;
private Float2 _autoFitTextRange = new Float2(0.1f, 100.0f);
private Margin _margin;
/// <summary>
/// The font.
@@ -57,9 +58,9 @@ namespace FlaxEngine.GUI
get => _text;
set
{
if (_text != value)
_text = value;
if (_autoWidth || _autoHeight || _autoFitText)
{
_text = value;
_textSize = Float2.Zero;
PerformLayout();
}
@@ -129,15 +130,11 @@ namespace FlaxEngine.GUI
get => _font;
set
{
if (_font != value)
_font = value;
if (_autoWidth || _autoHeight || _autoFitText)
{
_font = value;
if (_autoWidth || _autoHeight || _autoFitText)
{
_textSize = Float2.Zero;
PerformLayout();
}
_textSize = Float2.Zero;
PerformLayout();
}
}
}
@@ -152,7 +149,18 @@ namespace FlaxEngine.GUI
/// Gets or sets the margin for the text within the control bounds.
/// </summary>
[EditorOrder(70), Tooltip("The margin for the text within the control bounds.")]
public Margin Margin { get; set; }
public Margin Margin
{
get => _margin;
set
{
_margin = value;
if (_autoWidth || _autoHeight)
{
PerformLayout();
}
}
}
/// <summary>
/// Gets or sets a value indicating whether clip text during rendering.
@@ -161,9 +169,9 @@ namespace FlaxEngine.GUI
public bool ClipText { get; set; }
/// <summary>
/// Gets or sets a value indicating whether set automatic width based on text contents.
/// Gets or sets a value indicating whether set automatic width based on text contents. Control size is modified relative to the Pivot.
/// </summary>
[EditorOrder(85), DefaultValue(false), Tooltip("If checked, the control width will be based on text contents.")]
[EditorOrder(85), DefaultValue(false), Tooltip("If checked, the control width will be based on text contents. Control size is modified relative to the Pivot.")]
public bool AutoWidth
{
get => _autoWidth;
@@ -178,9 +186,9 @@ namespace FlaxEngine.GUI
}
/// <summary>
/// Gets or sets a value indicating whether set automatic height based on text contents.
/// Gets or sets a value indicating whether set automatic height based on text contents. Control size is modified relative to the Pivot.
/// </summary>
[EditorOrder(90), DefaultValue(false), Tooltip("If checked, the control height will be based on text contents.")]
[EditorOrder(90), DefaultValue(false), Tooltip("If checked, the control height will be based on text contents. Control size is modified relative to the Pivot.")]
public bool AutoHeight
{
get => _autoHeight;
@@ -226,13 +234,8 @@ namespace FlaxEngine.GUI
/// Initializes a new instance of the <see cref="Label"/> class.
/// </summary>
public Label()
: base(0, 0, 100, 20)
: this(0, 0, 100, 20)
{
AutoFocus = false;
var style = Style.Current;
Font = new FontReference(style.FontMedium);
TextColor = style.Foreground;
TextColorHighlighted = style.Foreground;
}
/// <inheritdoc />
@@ -241,9 +244,12 @@ namespace FlaxEngine.GUI
{
AutoFocus = false;
var style = Style.Current;
Font = new FontReference(style.FontMedium);
TextColor = style.Foreground;
TextColorHighlighted = style.Foreground;
if (style != null)
{
Font = new FontReference(style.FontMedium);
TextColor = style.Foreground;
TextColorHighlighted = style.Foreground;
}
}
/// <inheritdoc />
@@ -251,31 +257,24 @@ namespace FlaxEngine.GUI
{
base.DrawSelf();
var rect = new Rectangle(new Float2(Margin.Left, Margin.Top), Size - Margin.Size);
if (ClipText)
Render2D.PushClip(new Rectangle(Float2.Zero, Size));
var rect = new Rectangle(new Float2(Margin.Left, Margin.Top), Size - Margin.Size);
var color = IsMouseOver || IsNavFocused ? TextColorHighlighted : TextColor;
if (!EnabledInHierarchy)
color *= 0.6f;
var scale = 1.0f;
var hAlignment = HorizontalAlignment;
var wAlignment = VerticalAlignment;
if (_autoFitText)
if (_autoFitText && !_textSize.IsZero)
{
if (!_textSize.IsZero)
{
scale = (rect.Size / _textSize).MinValue;
scale = Mathf.Clamp(scale, _autoFitTextRange.X, _autoFitTextRange.Y);
}
scale = (rect.Size / _textSize).MinValue;
scale = Mathf.Clamp(scale, _autoFitTextRange.X, _autoFitTextRange.Y);
}
Font font = GetFont();
var text = ConvertedText();
Render2D.DrawText(font, Material, text, rect, color, hAlignment, wAlignment, Wrapping, BaseLinesGapScale, scale);
if (ClipText)
@@ -336,7 +335,9 @@ namespace FlaxEngine.GUI
size.X = _textSize.X + Margin.Width;
if (_autoHeight)
size.Y = _textSize.Y + Margin.Height;
var pivotRelative = PivotRelative;
Size = size;
PivotRelative = pivotRelative;
}
}
}

View File

@@ -291,24 +291,7 @@ namespace FlaxEngine.GUI
{
float alpha = Mathf.Saturate(Mathf.Cos(_animateTime * CaretFlashSpeed) * 0.5f + 0.7f);
alpha = alpha * alpha * alpha * alpha * alpha * alpha;
if (CaretPosition == 0)
{
var bounds = CaretBounds;
if (_layout.VerticalAlignment == TextAlignment.Center)
bounds.Y = _layout.Bounds.Y + _layout.Bounds.Height * 0.5f - bounds.Height * 0.5f;
else if (_layout.VerticalAlignment == TextAlignment.Far)
bounds.Y = _layout.Bounds.Y + _layout.Bounds.Height - bounds.Height;
if (_layout.HorizontalAlignment == TextAlignment.Center)
bounds.X = _layout.Bounds.X + _layout.Bounds.Width * 0.5f - bounds.Width * 0.5f;
else if (_layout.HorizontalAlignment == TextAlignment.Far)
bounds.X = _layout.Bounds.X + _layout.Bounds.Width - bounds.Width;
Render2D.FillRectangle(bounds, CaretColor * alpha);
}
else
{
Render2D.FillRectangle(CaretBounds, CaretColor * alpha);
}
Render2D.FillRectangle(CaretBounds, CaretColor * alpha);
}

View File

@@ -234,6 +234,11 @@ namespace FlaxEngine.GUI
if (_bounds.Size.Equals(ref value))
return;
var bounds = new Rectangle(_bounds.Location, value);
if (_pivotRelativeSizing)
{
var delta = _bounds.Size - value;
bounds.Location += delta * Pivot;
}
SetBounds(ref bounds);
}
}
@@ -566,7 +571,7 @@ namespace FlaxEngine.GUI
}
/// <summary>
/// Sets the anchor preset for the control. Can be use to auto-place the control for a given preset or can preserve the current control bounds.
/// Sets the anchor preset for the control. Can be used to auto-place the control for a given preset or can preserve the current control bounds.
/// </summary>
/// <param name="anchorPreset">The anchor preset to set.</param>
/// <param name="preserveBounds">True if preserve current control bounds, otherwise will align control position accordingly to the anchor location.</param>

View File

@@ -81,6 +81,7 @@ namespace FlaxEngine.GUI
// Style
private Color _backgroundColor = Color.Transparent;
private IBrush _backgroundBrush = null;
// Tooltip
@@ -174,6 +175,25 @@ namespace FlaxEngine.GUI
set => _backgroundColor = value;
}
/// <summary>
/// Gets or sets control background brush used to fill the contents. Uses Background Color property as tint color.
/// </summary>
[EditorDisplay("Background Style"), EditorOrder(2001)]
public IBrush BackgroundBrush
{
get => _backgroundBrush;
set
{
_backgroundBrush = value;
#if FLAX_EDITOR
// Auto-reset background color so brush is visible as it uses it for tint
if (value != null && _backgroundColor == Color.Transparent && FlaxEditor.CustomEditors.CustomEditor.IsSettingValue)
_backgroundColor = Color.White;
#endif
}
}
/// <summary>
/// Gets or sets the anchor preset used by the control anchors (based on <see cref="AnchorMin"/> and <see cref="AnchorMax"/>).
/// </summary>
@@ -416,9 +436,14 @@ namespace FlaxEngine.GUI
public virtual void Draw()
{
// Paint Background
if (_backgroundColor.A > 0.0f)
var rect = new Rectangle(Float2.Zero, _bounds.Size);
if (BackgroundBrush != null)
{
Render2D.FillRectangle(new Rectangle(Float2.Zero, Size), _backgroundColor);
BackgroundBrush.Draw(rect, _backgroundColor);
}
else if (_backgroundColor.A > 0.0f)
{
Render2D.FillRectangle(rect, _backgroundColor);
}
}
@@ -614,6 +639,18 @@ namespace FlaxEngine.GUI
case NavDirection.Down: return NavTargetDown;
case NavDirection.Left: return NavTargetLeft;
case NavDirection.Right: return NavTargetRight;
case NavDirection.Next:
if (NavTargetRight != null)
return NavTargetRight;
if (NavTargetDown != null)
return NavTargetDown;
return null;
case NavDirection.Previous:
if (NavTargetLeft != null)
return NavTargetLeft;
if (NavTargetUp != null)
return NavTargetUp;
return null;
default: return null;
}
}

View File

@@ -22,6 +22,8 @@ namespace FlaxEngine.GUI
base.PerformLayoutBeforeChildren();
// Pre-set height of all controls
if (!ControlChildSize)
return;
float h = Height - _margin.Height;
for (int i = 0; i < _children.Count; i++)
{
@@ -40,6 +42,7 @@ namespace FlaxEngine.GUI
float left = _margin.Left;
float right = _margin.Right;
float h = Height - _margin.Height;
float maxHeight = h;
bool hasAnyLeft = false, hasAnyRight = false;
for (int i = 0; i < _children.Count; i++)
{
@@ -47,18 +50,20 @@ namespace FlaxEngine.GUI
if (c.Visible)
{
var w = c.Width;
var ch = ControlChildSize ? h : c.Height;
if (Mathf.IsZero(c.AnchorMin.X) && Mathf.IsZero(c.AnchorMax.X))
{
c.Bounds = new Rectangle(left + _offset.X, _margin.Top + _offset.Y, w, h);
c.Bounds = new Rectangle(left + _offset.X, _margin.Top + _offset.Y, w, ch);
left = c.Right + _spacing;
hasAnyLeft = true;
}
else if (Mathf.IsOne(c.AnchorMin.X) && Mathf.IsOne(c.AnchorMax.X))
{
right += w + _spacing;
c.Bounds = new Rectangle(Width - right + _offset.X, _margin.Top + _offset.Y, w, h);
c.Bounds = new Rectangle(Width - right + _offset.X, _margin.Top + _offset.Y, w, ch);
hasAnyRight = true;
}
maxHeight = Mathf.Max(maxHeight, ch);
}
}
if (hasAnyLeft)
@@ -68,7 +73,13 @@ namespace FlaxEngine.GUI
// Update size
if (_autoSize)
Width = left + right;
{
var size = Size;
size.X = left + right;
if (!ControlChildSize)
size.Y = maxHeight;
Size = size;
}
}
}
}

View File

@@ -1,5 +1,7 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System.ComponentModel;
namespace FlaxEngine.GUI
{
/// <summary>
@@ -133,7 +135,7 @@ namespace FlaxEngine.GUI
/// <summary>
/// Gets or sets the value indicating whenever the panel size will be based on a children dimensions.
/// </summary>
[EditorOrder(30), Tooltip("If checked, the panel size will be based on a children dimensions.")]
[EditorOrder(30), DefaultValue(true), Tooltip("If checked, the panel size will be based on a children dimensions.")]
public bool AutoSize
{
get => _autoSize;
@@ -147,6 +149,12 @@ namespace FlaxEngine.GUI
}
}
/// <summary>
/// Gets or sets the value indicating whenever the panel can resize children controls (eg. auto-fit width/height).
/// </summary>
[EditorOrder(35), DefaultValue(true), Tooltip("If checked, the panel can resize children controls (eg. auto-fit width/height).")]
public bool ControlChildSize { get; set; } = true;
/// <summary>
/// Gets or sets the panel area margin.
/// </summary>

View File

@@ -22,6 +22,8 @@ namespace FlaxEngine.GUI
base.PerformLayoutBeforeChildren();
// Pre-set width of all controls
if (!ControlChildSize)
return;
float w = Width - _margin.Width;
for (int i = 0; i < _children.Count; i++)
{
@@ -40,6 +42,7 @@ namespace FlaxEngine.GUI
float top = _margin.Top;
float bottom = _margin.Bottom;
float w = Width - _margin.Width;
float maxWidth = w;
bool hasAnyTop = false, hasAnyBottom = false;
for (int i = 0; i < _children.Count; i++)
{
@@ -47,18 +50,20 @@ namespace FlaxEngine.GUI
if (c.Visible)
{
var h = c.Height;
var cw = ControlChildSize ? w : c.Width;
if (Mathf.IsZero(c.AnchorMin.Y) && Mathf.IsZero(c.AnchorMax.Y))
{
c.Bounds = new Rectangle(_margin.Left + _offset.X, top + _offset.Y, w, h);
c.Bounds = new Rectangle(_margin.Left + _offset.X, top + _offset.Y, cw, h);
top = c.Bottom + _spacing;
hasAnyTop = true;
}
else if (Mathf.IsOne(c.AnchorMin.Y) && Mathf.IsOne(c.AnchorMax.Y))
{
bottom += h + _spacing;
c.Bounds = new Rectangle(_margin.Left + _offset.X, Height - bottom + _offset.Y, w, h);
c.Bounds = new Rectangle(_margin.Left + _offset.X, Height - bottom + _offset.Y, cw, h);
hasAnyBottom = true;
}
maxWidth = Mathf.Max(maxWidth, cw);
}
}
if (hasAnyTop)
@@ -68,7 +73,13 @@ namespace FlaxEngine.GUI
// Update size
if (_autoSize)
Height = top + bottom;
{
var size = Size;
size.Y = top + bottom;
if (!ControlChildSize)
size.X = maxWidth;
Size = size;
}
}
}
}