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

This commit is contained in:
Wojtek Figat
2023-09-27 17:32:47 +02:00
40 changed files with 710 additions and 164 deletions

View File

@@ -84,17 +84,23 @@ namespace FlaxEngine.GUI
/// </summary>
[EditorDisplay("Border Style"), EditorOrder(2010), ExpandGroups]
public bool HasBorder { get; set; } = true;
/// <summary>
/// Gets or sets the border thickness.
/// </summary>
[EditorDisplay("Border Style"), EditorOrder(2011), Limit(0)]
public float BorderThickness { get; set; } = 1.0f;
/// <summary>
/// Gets or sets the color of the border.
/// </summary>
[EditorDisplay("Border Style"), EditorOrder(2011), ExpandGroups]
[EditorDisplay("Border Style"), EditorOrder(2012)]
public Color BorderColor { get; set; }
/// <summary>
/// Gets or sets the border color when button is highlighted.
/// </summary>
[EditorDisplay("Border Style"), EditorOrder(2012)]
[EditorDisplay("Border Style"), EditorOrder(2013)]
public Color BorderColorHighlighted { get; set; }
/// <summary>
@@ -252,7 +258,7 @@ namespace FlaxEngine.GUI
else
Render2D.FillRectangle(clientRect, backgroundColor);
if (HasBorder)
Render2D.DrawRectangle(clientRect, borderColor);
Render2D.DrawRectangle(clientRect, borderColor, BorderThickness);
// Draw text
Render2D.DrawText(_font?.GetFont(), TextMaterial, _text, clientRect, textColor, TextAlignment.Center, TextAlignment.Center);

View File

@@ -107,17 +107,29 @@ namespace FlaxEngine.GUI
CacheBox();
}
}
/// <summary>
/// Gets or sets whether to have a border.
/// </summary>
[EditorDisplay("Border Style"), EditorOrder(2010), Tooltip("Whether to have a border."), ExpandGroups]
public bool HasBorder { get; set; } = true;
/// <summary>
/// Gets or sets the border thickness.
/// </summary>
[EditorDisplay("Border Style"), EditorOrder(2011), Tooltip("The thickness of the border."), Limit(0)]
public float BorderThickness { get; set; } = 1.0f;
/// <summary>
/// Gets or sets the color of the border.
/// </summary>
[EditorDisplay("Border Style"), EditorOrder(2010), ExpandGroups]
[EditorDisplay("Border Style"), EditorOrder(2012)]
public Color BorderColor { get; set; }
/// <summary>
/// Gets or sets the border color when checkbox is hovered.
/// </summary>
[EditorDisplay("Border Style"), EditorOrder(2011)]
[EditorDisplay("Border Style"), EditorOrder(2013)]
public Color BorderColorHighlighted { get; set; }
/// <summary>
@@ -221,12 +233,15 @@ namespace FlaxEngine.GUI
bool enabled = EnabledInHierarchy;
// Border
Color borderColor = BorderColor;
if (!enabled)
borderColor *= 0.5f;
else if (_isPressed || _mouseOverBox || IsNavFocused)
borderColor = BorderColorHighlighted;
Render2D.DrawRectangle(_box.MakeExpanded(-2.0f), borderColor);
if (HasBorder)
{
Color borderColor = BorderColor;
if (!enabled)
borderColor *= 0.5f;
else if (_isPressed || _mouseOverBox || IsNavFocused)
borderColor = BorderColorHighlighted;
Render2D.DrawRectangle(_box.MakeExpanded(-2.0f), borderColor, BorderThickness);
}
// Icon
if (_state != CheckBoxState.Default)

View File

@@ -268,7 +268,7 @@ public class Slider : ContainerControl
// Draw track fill
if (FillTrack)
{
var fillLineRect = new Rectangle(_thumbSize.X / 2, (Height - TrackHeight - 2) / 2, Width - (Width - _thumbCenter) - _thumbSize.X / 2, TrackHeight + 2);
var fillLineRect = new Rectangle(_thumbSize.X / 2 - 1, (Height - TrackHeight - 2) / 2, Width - (Width - _thumbCenter) - _thumbSize.X / 2, TrackHeight + 2);
Render2D.PushClip(ref fillLineRect);
if (FillTrackBrush != null)
FillTrackBrush.Draw(lineRect, TrackFillLineColor);

View File

@@ -155,7 +155,8 @@ namespace FlaxEngine.GUI
if (IsMouseOver || IsNavFocused)
backColor = BackgroundSelectedColor;
Render2D.FillRectangle(rect, backColor);
Render2D.DrawRectangle(rect, IsFocused ? BorderSelectedColor : BorderColor);
if (HasBorder)
Render2D.DrawRectangle(rect, IsFocused ? BorderSelectedColor : BorderColor, BorderThickness);
// Apply view offset and clip mask
if (ClipText)

View File

@@ -11,6 +11,11 @@ namespace FlaxEngine.GUI
/// </summary>
public abstract class TextBoxBase : ContainerControl
{
/// <summary>
/// The delete control character (used for text filtering).
/// </summary>
protected const char DelChar = (char)0x7F;
/// <summary>
/// The text separators (used for words skipping).
/// </summary>
@@ -270,16 +275,28 @@ namespace FlaxEngine.GUI
[EditorDisplay("Background Style"), EditorOrder(2002), Tooltip("The speed of the selection background flashing animation.")]
public float BackgroundSelectedFlashSpeed { get; set; } = 6.0f;
/// <summary>
/// Gets or sets whether to have a border.
/// </summary>
[EditorDisplay("Border Style"), EditorOrder(2010), Tooltip("Whether to have a border."), ExpandGroups]
public bool HasBorder { get; set; } = true;
/// <summary>
/// Gets or sets the border thickness.
/// </summary>
[EditorDisplay("Border Style"), EditorOrder(2011), Tooltip("The thickness of the border."), Limit(0)]
public float BorderThickness { get; set; } = 1.0f;
/// <summary>
/// Gets or sets the color of the border (Transparent if not used).
/// </summary>
[EditorDisplay("Border Style"), EditorOrder(2010), Tooltip("The color of the border (Transparent if not used)."), ExpandGroups]
[EditorDisplay("Border Style"), EditorOrder(2012), Tooltip("The color of the border (Transparent if not used).")]
public Color BorderColor { get; set; }
/// <summary>
/// Gets or sets the color of the border when control is focused (Transparent if not used).
/// </summary>
[EditorDisplay("Border Style"), EditorOrder(2011), Tooltip("The color of the border when control is focused (Transparent if not used)")]
[EditorDisplay("Border Style"), EditorOrder(2013), Tooltip("The color of the border when control is focused (Transparent if not used)")]
public Color BorderSelectedColor { get; set; }
/// <summary>
@@ -351,6 +368,10 @@ namespace FlaxEngine.GUI
if (value.IndexOf('\r') != -1)
value = value.Replace("\r", "");
// Filter text (handle backspace control character)
if (value.IndexOf(DelChar) != -1)
value = value.Replace(DelChar.ToString(), "");
// Clamp length
if (value.Length > MaxLength)
value = value.Substring(0, MaxLength);
@@ -673,6 +694,8 @@ namespace FlaxEngine.GUI
// Filter text
if (str.IndexOf('\r') != -1)
str = str.Replace("\r", "");
if (str.IndexOf(DelChar) != -1)
str = str.Replace(DelChar.ToString(), "");
if (!IsMultiline && str.IndexOf('\n') != -1)
str = str.Replace("\n", "");
@@ -1327,6 +1350,15 @@ namespace FlaxEngine.GUI
if (IsReadOnly)
return true;
if (ctrDown)
{
int prevWordBegin = FindPrevWordBegin();
_text = _text.Remove(prevWordBegin, CaretPosition - prevWordBegin);
SetSelection(prevWordBegin);
OnTextChanged();
return true;
}
int left = SelectionLeft;
if (HasSelection)
{

View File

@@ -360,7 +360,7 @@ namespace FlaxEngine.GUI
{
var containerControl = child as ContainerControl;
var childAtRecursive = containerControl?.GetChildAtRecursive(childLocation);
if (childAtRecursive != null)
if (childAtRecursive != null && childAtRecursive.Visible)
{
child = childAtRecursive;
}
@@ -507,15 +507,19 @@ namespace FlaxEngine.GUI
// Perform automatic navigation based on the layout
var result = NavigationRaycast(direction, location, visited);
if (result == null && direction == NavDirection.Next)
var rightMostLocation = location;
if (result == null && (direction == NavDirection.Next || direction == NavDirection.Previous))
{
// Try wrap the navigation over the layout based on the direction
var visitedWrap = new List<Control>(visited);
result = NavigationWrap(direction, location, visitedWrap);
result = NavigationWrap(direction, location, visitedWrap, out rightMostLocation);
}
if (result != null)
{
result = result.OnNavigate(direction, result.PointFromParent(location), this, visited);
// HACK: only the 'previous' direction needs the rightMostLocation so i used a ternary conditional operator.
// The rightMostLocation can probably become a 'desired raycast origin' that gets calculated correctly in the NavigationWrap method.
var useLocation = direction == NavDirection.Previous ? rightMostLocation : location;
result = result.OnNavigate(direction, result.PointFromParent(useLocation), this, visited);
if (result != null)
return result;
}
@@ -551,8 +555,9 @@ namespace FlaxEngine.GUI
/// <param name="direction">The navigation direction.</param>
/// <param name="location">The navigation start location (in the control-space).</param>
/// <param name="visited">The list with visited controls. Used to skip recursive navigation calls when doing traversal across the UI hierarchy.</param>
/// <param name="rightMostLocation">Returns the rightmost location of the parent container for the raycast used by the child container</param>
/// <returns>The target navigation control or null if didn't performed any navigation.</returns>
protected virtual Control NavigationWrap(NavDirection direction, Float2 location, List<Control> visited)
protected virtual Control NavigationWrap(NavDirection direction, Float2 location, List<Control> visited, out Float2 rightMostLocation)
{
// This searches form a child that calls this navigation event (see Control.OnNavigate) to determinate the layout wrapping size based on that child size
var currentChild = RootWindow?.FocusedControl;
@@ -566,15 +571,22 @@ namespace FlaxEngine.GUI
case NavDirection.Next:
predictedLocation = new Float2(0, location.Y + layoutSize.Y);
break;
case NavDirection.Previous:
predictedLocation = new Float2(Size.X, location.Y - layoutSize.Y);
break;
}
if (new Rectangle(Float2.Zero, Size).Contains(ref predictedLocation))
{
var result = NavigationRaycast(direction, predictedLocation, visited);
if (result != null)
return result;
{
rightMostLocation = predictedLocation;
return result;
}
}
}
return Parent?.NavigationWrap(direction, PointToParent(ref location), visited);
rightMostLocation = location;
return Parent?.NavigationWrap(direction, PointToParent(ref location), visited, out rightMostLocation);
}
private static bool CanGetAutoFocus(Control c)
@@ -613,6 +625,10 @@ namespace FlaxEngine.GUI
uiDir1 = new Float2(1, 0);
uiDir2 = new Float2(0, 1);
break;
case NavDirection.Previous:
uiDir1 = new Float2(-1, 0);
uiDir2 = new Float2(0, -1);
break;
}
Control result = null;
var minDistance = float.MaxValue;

View File

@@ -634,6 +634,7 @@ namespace FlaxEngine.GUI
case NavDirection.Left: return new Float2(0, size.Y * 0.5f);
case NavDirection.Right: return new Float2(size.X, size.Y * 0.5f);
case NavDirection.Next: return Float2.Zero;
case NavDirection.Previous: return size;
default: return size * 0.5f;
}
}

View File

@@ -202,5 +202,10 @@ namespace FlaxEngine.GUI
/// The next item (right with layout wrapping).
/// </summary>
Next,
/// <summary>
/// The previous item (left with layout wrapping).
/// </summary>
Previous,
}
}