Optimize UI in Editor
This commit is contained in:
@@ -42,7 +42,7 @@ namespace FlaxEditor.GUI.Docking
|
||||
/// <summary>
|
||||
/// The mouse position.
|
||||
/// </summary>
|
||||
public Vector2 MousePosition;
|
||||
public Vector2 MousePosition = Vector2.Minimum;
|
||||
|
||||
/// <summary>
|
||||
/// The start drag asynchronous window.
|
||||
@@ -192,7 +192,7 @@ namespace FlaxEditor.GUI.Docking
|
||||
var tab = _panel.GetTab(0);
|
||||
|
||||
// Draw header
|
||||
bool isMouseOver = IsMouseOver && headerRect.Contains(MousePosition);
|
||||
bool isMouseOver = headerRect.Contains(MousePosition);
|
||||
Render2D.FillRectangle(headerRect, containsFocus ? style.BackgroundSelected : isMouseOver ? style.BackgroundHighlighted : style.LightBackground);
|
||||
|
||||
float iconWidth = tab.Icon.IsValid ? DockPanel.DefaultButtonsSize + DockPanel.DefaultLeftTextMargin : 0;
|
||||
@@ -238,7 +238,7 @@ namespace FlaxEditor.GUI.Docking
|
||||
var iconWidth = tab.Icon.IsValid ? DockPanel.DefaultButtonsSize + DockPanel.DefaultLeftTextMargin : 0;
|
||||
var width = titleSize.X + DockPanel.DefaultButtonsSize + 2 * DockPanel.DefaultButtonsMargin + DockPanel.DefaultLeftTextMargin + DockPanel.DefaultRightTextMargin + iconWidth;
|
||||
var tabRect = new Rectangle(x, 0, width, DockPanel.DefaultHeaderHeight);
|
||||
var isMouseOver = IsMouseOver && tabRect.Contains(MousePosition);
|
||||
var isMouseOver = tabRect.Contains(MousePosition);
|
||||
var isSelected = _panel.SelectedTab == tab;
|
||||
|
||||
// Check if tab is selected
|
||||
@@ -294,11 +294,11 @@ namespace FlaxEditor.GUI.Docking
|
||||
/// <inheritdoc />
|
||||
public override void OnLostFocus()
|
||||
{
|
||||
// Clear
|
||||
IsMouseLeftButtonDown = false;
|
||||
IsMouseRightButtonDown = false;
|
||||
IsMouseMiddleButtonDown = false;
|
||||
MouseDownWindow = null;
|
||||
MousePosition = Vector2.Minimum;
|
||||
|
||||
base.OnLostFocus();
|
||||
}
|
||||
@@ -306,7 +306,6 @@ namespace FlaxEditor.GUI.Docking
|
||||
/// <inheritdoc />
|
||||
public override void OnMouseEnter(Vector2 location)
|
||||
{
|
||||
// Cache mouse
|
||||
MousePosition = location;
|
||||
|
||||
base.OnMouseEnter(location);
|
||||
@@ -403,10 +402,7 @@ namespace FlaxEditor.GUI.Docking
|
||||
/// <inheritdoc />
|
||||
public override void OnMouseMove(Vector2 location)
|
||||
{
|
||||
// Cache mouse
|
||||
MousePosition = location;
|
||||
|
||||
// Check if mouse is down
|
||||
if (IsMouseLeftButtonDown)
|
||||
{
|
||||
// Check if mouse is outside the header
|
||||
@@ -453,10 +449,8 @@ namespace FlaxEditor.GUI.Docking
|
||||
/// <inheritdoc />
|
||||
public override void OnMouseLeave()
|
||||
{
|
||||
// Check if mouse is down
|
||||
if (IsMouseLeftButtonDown)
|
||||
{
|
||||
// Clear flag
|
||||
IsMouseLeftButtonDown = false;
|
||||
|
||||
// Check tabs under mouse position
|
||||
@@ -466,6 +460,7 @@ namespace FlaxEditor.GUI.Docking
|
||||
}
|
||||
IsMouseRightButtonDown = false;
|
||||
IsMouseMiddleButtonDown = false;
|
||||
MousePosition = Vector2.Minimum;
|
||||
|
||||
base.OnMouseLeave();
|
||||
}
|
||||
|
||||
@@ -889,19 +889,16 @@ namespace FlaxEditor.GUI.Tree
|
||||
/// <inheritdoc />
|
||||
public override void OnChildResized(Control control)
|
||||
{
|
||||
// Optimize if child is tree node that is not visible
|
||||
if (!_opened && control is TreeNode)
|
||||
return;
|
||||
|
||||
PerformLayout();
|
||||
ParentTree.UpdateSize();
|
||||
|
||||
base.OnChildResized(control);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnParentResized()
|
||||
{
|
||||
base.OnParentResized();
|
||||
|
||||
Width = Parent.Width;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DragDropEffect OnDragEnter(ref Vector2 location, DragData data)
|
||||
{
|
||||
@@ -1018,56 +1015,82 @@ namespace FlaxEditor.GUI.Tree
|
||||
/// <inheritdoc />
|
||||
public override void PerformLayout(bool force = false)
|
||||
{
|
||||
// Check if update is locked
|
||||
if (IsLayoutLocked && !force)
|
||||
if (_isLayoutLocked && !force)
|
||||
return;
|
||||
|
||||
// Update the nodes nesting level before the actual positioning
|
||||
float xOffset = _xOffset + ChildrenIndent;
|
||||
for (int i = 0; i < _children.Count; i++)
|
||||
bool wasLocked = _isLayoutLocked;
|
||||
if (!wasLocked)
|
||||
LockChildrenRecursive();
|
||||
|
||||
// Optimize layout logic if node is collapsed
|
||||
if (_opened || _animationProgress < 1.0f)
|
||||
{
|
||||
if (_children[i] is TreeNode node && node.Visible)
|
||||
node._xOffset = xOffset;
|
||||
PerformLayoutBeforeChildren();
|
||||
for (int i = 0; i < _children.Count; i++)
|
||||
_children[i].PerformLayout(true);
|
||||
PerformLayoutAfterChildren();
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: perform layout for any non-TreeNode controls
|
||||
_cachedHeight = _headerHeight;
|
||||
_cachedTextColor = CacheTextColor();
|
||||
Size = new Vector2(Parent?.Width ?? Width, _headerHeight);
|
||||
}
|
||||
|
||||
base.PerformLayout(force);
|
||||
if (!wasLocked)
|
||||
UnlockChildrenRecursive();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void PerformLayoutBeforeChildren()
|
||||
{
|
||||
if (_opened)
|
||||
{
|
||||
// Update the nodes nesting level before the actual positioning
|
||||
float xOffset = _xOffset + ChildrenIndent;
|
||||
for (int i = 0; i < _children.Count; i++)
|
||||
{
|
||||
if (_children[i] is TreeNode node)
|
||||
node._xOffset = xOffset;
|
||||
}
|
||||
}
|
||||
|
||||
base.PerformLayoutBeforeChildren();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void PerformLayoutAfterChildren()
|
||||
{
|
||||
_cachedTextColor = CacheTextColor();
|
||||
|
||||
// Prepare
|
||||
float y = _headerHeight;
|
||||
float height = _headerHeight;
|
||||
float xOffset = _xOffset + ChildrenIndent;
|
||||
y -= _cachedHeight * (_opened ? 1.0f - _animationProgress : _animationProgress);
|
||||
|
||||
// Arrange children
|
||||
for (int i = 0; i < _children.Count; i++)
|
||||
// Skip full layout if it's fully collapsed
|
||||
if (_opened || _animationProgress < 1.0f)
|
||||
{
|
||||
if (_children[i] is TreeNode node && node.Visible)
|
||||
y -= _cachedHeight * (_opened ? 1.0f - _animationProgress : _animationProgress);
|
||||
|
||||
// Arrange children
|
||||
for (int i = 0; i < _children.Count; i++)
|
||||
{
|
||||
node._xOffset = xOffset;
|
||||
node.Location = new Vector2(0, y);
|
||||
float nodeHeight = node.Height + DefaultNodeOffsetY;
|
||||
y += nodeHeight;
|
||||
height += nodeHeight;
|
||||
if (_children[i] is TreeNode node && node.Visible)
|
||||
{
|
||||
node._xOffset = xOffset;
|
||||
node.Location = new Vector2(0, y);
|
||||
float nodeHeight = node.Height + DefaultNodeOffsetY;
|
||||
y += nodeHeight;
|
||||
height += nodeHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cache calculated height
|
||||
// Cache data
|
||||
_cachedHeight = height;
|
||||
_cachedTextColor = CacheTextColor();
|
||||
|
||||
// Force to be closed
|
||||
if (_animationProgress >= 1.0f && !_opened)
|
||||
{
|
||||
y = _headerHeight;
|
||||
}
|
||||
|
||||
// Set height
|
||||
Height = Mathf.Max(_headerHeight, y);
|
||||
// Set bounds
|
||||
Size = new Vector2(Parent?.Width ?? Width, Mathf.Max(_headerHeight, y));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -486,7 +486,6 @@ namespace FlaxEditor.Modules
|
||||
var node = SceneGraphFactory.BuildActorNode(actor);
|
||||
if (node != null)
|
||||
{
|
||||
node.TreeNode.UnlockChildrenRecursive();
|
||||
node.ParentNode = parentNode;
|
||||
}
|
||||
}
|
||||
@@ -544,13 +543,8 @@ namespace FlaxEditor.Modules
|
||||
return;
|
||||
|
||||
// Get the new parent node (may be missing)
|
||||
if (parentNode != null)
|
||||
{
|
||||
// Change parent
|
||||
node.TreeNode.UnlockChildrenRecursive();
|
||||
node.ParentNode = parentNode;
|
||||
}
|
||||
else
|
||||
node.ParentNode = parentNode;
|
||||
if (parentNode == null)
|
||||
{
|
||||
// Check if actor is selected in editor
|
||||
if (Editor.SceneEditing.Selection.Contains(node))
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace FlaxEditor.SceneGraph
|
||||
/// It's part of the Scene Graph.
|
||||
/// </summary>
|
||||
/// <seealso cref="SceneGraphNode" />
|
||||
/// <seealso cref="Actor" />
|
||||
/// <seealso cref="FlaxEngine.Actor" />
|
||||
[HideInEditor]
|
||||
public class ActorNode : SceneGraphNode
|
||||
{
|
||||
@@ -228,6 +228,7 @@ namespace FlaxEditor.SceneGraph
|
||||
set => _actor.Transform = value;
|
||||
}
|
||||
|
||||
#if false
|
||||
/// <inheritdoc />
|
||||
public override SceneGraphNode ParentNode
|
||||
{
|
||||
@@ -238,6 +239,7 @@ namespace FlaxEditor.SceneGraph
|
||||
base.ParentNode = value;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object EditableObject => _actor;
|
||||
@@ -250,7 +252,7 @@ namespace FlaxEditor.SceneGraph
|
||||
// Skip actors that should not be selected
|
||||
if (hit != null && _actor != null && (_actor.HideFlags & HideFlags.DontSelect) == HideFlags.DontSelect)
|
||||
{
|
||||
hit = ParentNode;
|
||||
hit = parentNode;
|
||||
}
|
||||
|
||||
return hit;
|
||||
@@ -306,22 +308,43 @@ namespace FlaxEditor.SceneGraph
|
||||
/// <inheritdoc />
|
||||
protected override void OnParentChanged()
|
||||
{
|
||||
// Update UI node connections
|
||||
_treeNode.Parent = (ParentNode as ActorNode)?.TreeNode;
|
||||
|
||||
// Check if it's a new node and parent has been already ready
|
||||
// (eg. we build new node for spawned actor and link it to the game)
|
||||
if (_treeNode.Parent != null && !_treeNode.Parent.IsLayoutLocked)
|
||||
{
|
||||
_treeNode.IndexInParent = _actor.OrderInParent;
|
||||
_treeNode.Parent.SortChildren();
|
||||
|
||||
// Update UI
|
||||
_treeNode.IsLayoutLocked = false;
|
||||
_treeNode.PerformLayout();
|
||||
}
|
||||
|
||||
base.OnParentChanged();
|
||||
|
||||
// Update UI (special case if actor is spawned and added to existing scene tree)
|
||||
var parentTreeNode = (parentNode as ActorNode)?.TreeNode;
|
||||
if (parentTreeNode != null && !parentTreeNode.IsLayoutLocked)
|
||||
{
|
||||
parentTreeNode.IsLayoutLocked = true;
|
||||
_treeNode.Parent = parentTreeNode;
|
||||
_treeNode.IndexInParent = _actor.OrderInParent;
|
||||
parentTreeNode.IsLayoutLocked = false;
|
||||
|
||||
// Skip UI update if node won't be in a view
|
||||
if (parentTreeNode.IsCollapsed)
|
||||
{
|
||||
TreeNode.UnlockChildrenRecursive();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to perform layout at the level where it makes it the most performant (the least computations)
|
||||
var tree = parentTreeNode.ParentTree;
|
||||
if (tree != null)
|
||||
{
|
||||
if (tree.Parent is FlaxEngine.GUI.Panel treeParent)
|
||||
treeParent.PerformLayout();
|
||||
else
|
||||
tree.PerformLayout();
|
||||
}
|
||||
else
|
||||
{
|
||||
parentTreeNode.PerformLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_treeNode.Parent = parentTreeNode;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -489,7 +489,7 @@ namespace Math
|
||||
static bool NearEqual(float a, float b)
|
||||
{
|
||||
// Check if the numbers are really close - needed when comparing numbers near zero
|
||||
if (Abs(a) < ZeroTolerance)
|
||||
if (Abs(a - b) < ZeroTolerance)
|
||||
return true;
|
||||
|
||||
// Original from Bruce Dawson: http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
|
||||
|
||||
@@ -1816,7 +1816,7 @@ namespace FlaxEngine
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator ==(Vector2 left, Vector2 right)
|
||||
{
|
||||
return left.Equals(ref right);
|
||||
return Mathf.NearEqual(left.X, left.X) && Mathf.NearEqual(left.Y, right.Y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1831,7 +1831,7 @@ namespace FlaxEngine
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator !=(Vector2 left, Vector2 right)
|
||||
{
|
||||
return !left.Equals(ref right);
|
||||
return !Mathf.NearEqual(left.X, left.X) || !Mathf.NearEqual(left.Y, right.Y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1953,7 +1953,7 @@ namespace FlaxEngine
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Equals(Vector2 other)
|
||||
{
|
||||
return Equals(ref other);
|
||||
return Mathf.NearEqual(X, X) && Mathf.NearEqual(other.Y, other.Y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1965,11 +1965,9 @@ namespace FlaxEngine
|
||||
/// </returns>
|
||||
public override bool Equals(object value)
|
||||
{
|
||||
if (!(value is Vector2))
|
||||
if (!(value is Vector2 other))
|
||||
return false;
|
||||
|
||||
var strongValue = (Vector2)value;
|
||||
return Equals(ref strongValue);
|
||||
return Mathf.NearEqual(X, X) && Mathf.NearEqual(other.Y, other.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2049,7 +2049,7 @@ namespace FlaxEngine
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator ==(Vector3 left, Vector3 right)
|
||||
{
|
||||
return left.Equals(ref right);
|
||||
return Mathf.NearEqual(left.X, right.X) && Mathf.NearEqual(left.Y, right.Y) && Mathf.NearEqual(left.Z, right.Z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -2061,7 +2061,7 @@ namespace FlaxEngine
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator !=(Vector3 left, Vector3 right)
|
||||
{
|
||||
return !left.Equals(ref right);
|
||||
return !Mathf.NearEqual(left.X, right.X) || !Mathf.NearEqual(left.Y, right.Y) || !Mathf.NearEqual(left.Z, right.Z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -2162,7 +2162,7 @@ namespace FlaxEngine
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Equals(Vector3 other)
|
||||
{
|
||||
return Equals(ref other);
|
||||
return Mathf.NearEqual(other.X, X) && Mathf.NearEqual(other.Y, Y) && Mathf.NearEqual(other.Z, Z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -2172,10 +2172,9 @@ namespace FlaxEngine
|
||||
/// <returns><c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.</returns>
|
||||
public override bool Equals(object value)
|
||||
{
|
||||
if (!(value is Vector3))
|
||||
if (!(value is Vector3 other))
|
||||
return false;
|
||||
var strongValue = (Vector3)value;
|
||||
return Equals(ref strongValue);
|
||||
return Mathf.NearEqual(other.X, X) && Mathf.NearEqual(other.Y, Y) && Mathf.NearEqual(other.Z, Z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1680,7 +1680,7 @@ namespace FlaxEngine
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Equals(Vector4 other)
|
||||
{
|
||||
return Equals(ref other);
|
||||
return Mathf.NearEqual(other.X, X) && Mathf.NearEqual(other.Y, Y) && Mathf.NearEqual(other.Z, Z) && Mathf.NearEqual(other.W, W);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1692,11 +1692,9 @@ namespace FlaxEngine
|
||||
/// </returns>
|
||||
public override bool Equals(object value)
|
||||
{
|
||||
if (!(value is Vector4))
|
||||
if (!(value is Vector4 other))
|
||||
return false;
|
||||
|
||||
var strongValue = (Vector4)value;
|
||||
return Equals(ref strongValue);
|
||||
return Mathf.NearEqual(other.X, X) && Mathf.NearEqual(other.Y, Y) && Mathf.NearEqual(other.Z, Z) && Mathf.NearEqual(other.W, W);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,12 +23,21 @@ namespace FlaxEngine.GUI
|
||||
[NoSerialize]
|
||||
protected bool _containsFocus;
|
||||
|
||||
/// <summary>
|
||||
/// The layout locking flag.
|
||||
/// </summary>
|
||||
[NoSerialize]
|
||||
protected bool _isLayoutLocked;
|
||||
|
||||
private bool _clipChildren = true;
|
||||
private bool _cullChildren = true;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContainerControl"/> class.
|
||||
/// </summary>
|
||||
public ContainerControl()
|
||||
{
|
||||
IsLayoutLocked = true;
|
||||
_isLayoutLocked = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -37,7 +46,7 @@ namespace FlaxEngine.GUI
|
||||
public ContainerControl(float x, float y, float width, float height)
|
||||
: base(x, y, width, height)
|
||||
{
|
||||
IsLayoutLocked = true;
|
||||
_isLayoutLocked = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -46,14 +55,14 @@ namespace FlaxEngine.GUI
|
||||
public ContainerControl(Vector2 location, Vector2 size)
|
||||
: base(location, size)
|
||||
{
|
||||
IsLayoutLocked = true;
|
||||
_isLayoutLocked = true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ContainerControl(Rectangle bounds)
|
||||
: base(bounds)
|
||||
{
|
||||
IsLayoutLocked = true;
|
||||
_isLayoutLocked = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -80,30 +89,39 @@ namespace FlaxEngine.GUI
|
||||
/// True if automatic updates for control layout are locked (useful when creating a lot of GUI control to prevent lags).
|
||||
/// </summary>
|
||||
[HideInEditor, NoSerialize]
|
||||
public bool IsLayoutLocked { get; set; }
|
||||
public bool IsLayoutLocked
|
||||
{
|
||||
get => _isLayoutLocked;
|
||||
set => _isLayoutLocked = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether apply clipping mask on children during rendering.
|
||||
/// </summary>
|
||||
[EditorOrder(530), Tooltip("If checked, control will apply clipping mask on children during rendering.")]
|
||||
public bool ClipChildren { get; set; } = true;
|
||||
public bool ClipChildren
|
||||
{
|
||||
get => _clipChildren;
|
||||
set => _clipChildren = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether perform view culling on children during rendering.
|
||||
/// </summary>
|
||||
[EditorOrder(540), Tooltip("If checked, control will perform view culling on children during rendering.")]
|
||||
public bool CullChildren { get; set; } = true;
|
||||
public bool CullChildren
|
||||
{
|
||||
get => _cullChildren;
|
||||
set => _cullChildren = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Locks all child controls layout and itself.
|
||||
/// </summary>
|
||||
[NoAnimate]
|
||||
public virtual void LockChildrenRecursive()
|
||||
public void LockChildrenRecursive()
|
||||
{
|
||||
// Itself
|
||||
IsLayoutLocked = true;
|
||||
|
||||
// Every child container control
|
||||
_isLayoutLocked = true;
|
||||
for (int i = 0; i < _children.Count; i++)
|
||||
{
|
||||
if (_children[i] is ContainerControl child)
|
||||
@@ -115,12 +133,9 @@ namespace FlaxEngine.GUI
|
||||
/// Unlocks all the child controls layout and itself.
|
||||
/// </summary>
|
||||
[NoAnimate]
|
||||
public virtual void UnlockChildrenRecursive()
|
||||
public void UnlockChildrenRecursive()
|
||||
{
|
||||
// Itself
|
||||
IsLayoutLocked = false;
|
||||
|
||||
// Every child container control
|
||||
_isLayoutLocked = false;
|
||||
for (int i = 0; i < _children.Count; i++)
|
||||
{
|
||||
if (_children[i] is ContainerControl child)
|
||||
@@ -134,8 +149,8 @@ namespace FlaxEngine.GUI
|
||||
[NoAnimate]
|
||||
public virtual void RemoveChildren()
|
||||
{
|
||||
bool wasLayoutLocked = IsLayoutLocked;
|
||||
IsLayoutLocked = true;
|
||||
bool wasLayoutLocked = _isLayoutLocked;
|
||||
_isLayoutLocked = true;
|
||||
|
||||
// Delete children
|
||||
while (_children.Count > 0)
|
||||
@@ -143,7 +158,7 @@ namespace FlaxEngine.GUI
|
||||
_children[0].Parent = null;
|
||||
}
|
||||
|
||||
IsLayoutLocked = wasLayoutLocked;
|
||||
_isLayoutLocked = wasLayoutLocked;
|
||||
PerformLayout();
|
||||
}
|
||||
|
||||
@@ -152,8 +167,8 @@ namespace FlaxEngine.GUI
|
||||
/// </summary>
|
||||
public virtual void DisposeChildren()
|
||||
{
|
||||
bool wasLayoutLocked = IsLayoutLocked;
|
||||
IsLayoutLocked = true;
|
||||
bool wasLayoutLocked = _isLayoutLocked;
|
||||
_isLayoutLocked = true;
|
||||
|
||||
// Delete children
|
||||
while (_children.Count > 0)
|
||||
@@ -161,7 +176,7 @@ namespace FlaxEngine.GUI
|
||||
_children[0].Dispose();
|
||||
}
|
||||
|
||||
IsLayoutLocked = wasLayoutLocked;
|
||||
_isLayoutLocked = wasLayoutLocked;
|
||||
PerformLayout();
|
||||
}
|
||||
|
||||
@@ -253,7 +268,6 @@ namespace FlaxEngine.GUI
|
||||
return;
|
||||
_children.RemoveAt(oldIndex);
|
||||
|
||||
// Check if index is invalid
|
||||
if (newIndex < 0 || newIndex >= _children.Count)
|
||||
{
|
||||
// Append at the end
|
||||
@@ -279,8 +293,6 @@ namespace FlaxEngine.GUI
|
||||
for (int i = _children.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var child = _children[i];
|
||||
|
||||
// Check collision
|
||||
if (IntersectsChildContent(child, point, out var childLocation))
|
||||
{
|
||||
result = i;
|
||||
@@ -499,10 +511,7 @@ namespace FlaxEngine.GUI
|
||||
// Check if state has been changed
|
||||
if (result != _containsFocus)
|
||||
{
|
||||
// Cache flag
|
||||
_containsFocus = result;
|
||||
|
||||
// Fire event
|
||||
if (result)
|
||||
{
|
||||
OnStartContainsFocus();
|
||||
@@ -563,24 +572,6 @@ namespace FlaxEngine.GUI
|
||||
_children.Clear();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsMouseOver
|
||||
{
|
||||
get
|
||||
{
|
||||
if (base.IsMouseOver)
|
||||
return true;
|
||||
|
||||
for (int i = 0; i < _children.Count && _children.Count > 0; i++)
|
||||
{
|
||||
if (_children[i].IsMouseOver)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsTouchOver
|
||||
{
|
||||
@@ -619,7 +610,7 @@ namespace FlaxEngine.GUI
|
||||
{
|
||||
DrawSelf();
|
||||
|
||||
if (ClipChildren)
|
||||
if (_clipChildren)
|
||||
{
|
||||
GetDesireClientArea(out var clientArea);
|
||||
Render2D.PushClip(ref clientArea);
|
||||
@@ -646,7 +637,7 @@ namespace FlaxEngine.GUI
|
||||
protected virtual void DrawChildren()
|
||||
{
|
||||
// Draw all visible child controls
|
||||
if (CullChildren)
|
||||
if (_cullChildren)
|
||||
{
|
||||
Render2D.PeekClip(out var globalClipping);
|
||||
Render2D.PeekTransform(out var globalTransform);
|
||||
@@ -684,10 +675,10 @@ namespace FlaxEngine.GUI
|
||||
/// <inheritdoc />
|
||||
public override void PerformLayout(bool force = false)
|
||||
{
|
||||
if (IsLayoutLocked && !force)
|
||||
if (_isLayoutLocked && !force)
|
||||
return;
|
||||
|
||||
bool wasLocked = IsLayoutLocked;
|
||||
bool wasLocked = _isLayoutLocked;
|
||||
if (!wasLocked)
|
||||
LockChildrenRecursive();
|
||||
|
||||
@@ -711,7 +702,6 @@ namespace FlaxEngine.GUI
|
||||
var child = _children[i];
|
||||
if (child.Visible && child.Enabled)
|
||||
{
|
||||
// Fire event
|
||||
if (IntersectsChildContent(child, location, out var childLocation))
|
||||
{
|
||||
// Enter
|
||||
@@ -732,7 +722,6 @@ namespace FlaxEngine.GUI
|
||||
var child = _children[i];
|
||||
if (child.Visible && child.Enabled)
|
||||
{
|
||||
// Fire events
|
||||
if (IntersectsChildContent(child, location, out var childLocation))
|
||||
{
|
||||
if (child.IsMouseOver)
|
||||
@@ -1035,7 +1024,6 @@ namespace FlaxEngine.GUI
|
||||
var child = _children[i];
|
||||
if (child.Visible && child.Enabled)
|
||||
{
|
||||
// Fire event
|
||||
if (IntersectsChildContent(child, location, out var childLocation))
|
||||
{
|
||||
// Enter
|
||||
@@ -1061,7 +1049,6 @@ namespace FlaxEngine.GUI
|
||||
var child = _children[i];
|
||||
if (child.Visible && child.Enabled)
|
||||
{
|
||||
// Fire events
|
||||
if (IntersectsChildContent(child, location, out var childLocation))
|
||||
{
|
||||
if (child.IsDragOver)
|
||||
@@ -1120,7 +1107,6 @@ namespace FlaxEngine.GUI
|
||||
var child = _children[i];
|
||||
if (child.Visible && child.Enabled)
|
||||
{
|
||||
// Fire event
|
||||
if (IntersectsChildContent(child, location, out var childLocation))
|
||||
{
|
||||
// Enter
|
||||
@@ -1138,10 +1124,9 @@ namespace FlaxEngine.GUI
|
||||
protected override void OnSizeChanged()
|
||||
{
|
||||
// Lock updates to prevent additional layout calculations
|
||||
bool wasLayoutLocked = IsLayoutLocked;
|
||||
IsLayoutLocked = true;
|
||||
bool wasLayoutLocked = _isLayoutLocked;
|
||||
_isLayoutLocked = true;
|
||||
|
||||
// Base
|
||||
base.OnSizeChanged();
|
||||
|
||||
// Fire event
|
||||
@@ -1151,7 +1136,7 @@ namespace FlaxEngine.GUI
|
||||
}
|
||||
|
||||
// Restore state
|
||||
IsLayoutLocked = wasLayoutLocked;
|
||||
_isLayoutLocked = wasLayoutLocked;
|
||||
|
||||
// Arrange child controls
|
||||
PerformLayout();
|
||||
|
||||
@@ -150,7 +150,13 @@ namespace FlaxEngine.GUI
|
||||
public Vector2 Location
|
||||
{
|
||||
get => _bounds.Location;
|
||||
set => Bounds = new Rectangle(value, _bounds.Size);
|
||||
set
|
||||
{
|
||||
if (_bounds.Location.Equals(ref value))
|
||||
return;
|
||||
var bounds = new Rectangle(value, _bounds.Size);
|
||||
SetBounds(ref bounds);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -170,7 +176,13 @@ namespace FlaxEngine.GUI
|
||||
public float Width
|
||||
{
|
||||
get => _bounds.Size.X;
|
||||
set => Bounds = new Rectangle(_bounds.Location, value, _bounds.Size.Y);
|
||||
set
|
||||
{
|
||||
if (Mathf.NearEqual(_bounds.Size.X, value))
|
||||
return;
|
||||
var bounds = new Rectangle(_bounds.Location, value, _bounds.Size.Y);
|
||||
SetBounds(ref bounds);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -180,7 +192,13 @@ namespace FlaxEngine.GUI
|
||||
public float Height
|
||||
{
|
||||
get => _bounds.Size.Y;
|
||||
set => Bounds = new Rectangle(_bounds.Location, _bounds.Size.X, value);
|
||||
set
|
||||
{
|
||||
if (Mathf.NearEqual(_bounds.Size.Y, value))
|
||||
return;
|
||||
var bounds = new Rectangle(_bounds.Location, _bounds.Size.X, value);
|
||||
SetBounds(ref bounds);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -190,7 +208,13 @@ namespace FlaxEngine.GUI
|
||||
public Vector2 Size
|
||||
{
|
||||
get => _bounds.Size;
|
||||
set => Bounds = new Rectangle(_bounds.Location, value);
|
||||
set
|
||||
{
|
||||
if (_bounds.Size.Equals(ref value))
|
||||
return;
|
||||
var bounds = new Rectangle(_bounds.Location, value);
|
||||
SetBounds(ref bounds);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -425,12 +449,12 @@ namespace FlaxEngine.GUI
|
||||
UpdateTransform();
|
||||
|
||||
// Handle location/size changes
|
||||
if (_bounds.Location != prevBounds.Location)
|
||||
if (!_bounds.Location.Equals(ref prevBounds.Location))
|
||||
{
|
||||
OnLocationChanged();
|
||||
}
|
||||
|
||||
if (_bounds.Size != prevBounds.Size)
|
||||
if (!_bounds.Size.Equals(ref prevBounds.Size))
|
||||
{
|
||||
OnSizeChanged();
|
||||
}
|
||||
|
||||
@@ -177,15 +177,15 @@ namespace FlaxEngine.GUI
|
||||
/// <inheritdoc />
|
||||
protected override void SetViewOffset(ref Vector2 value)
|
||||
{
|
||||
bool wasLocked = IsLayoutLocked;
|
||||
IsLayoutLocked = true;
|
||||
bool wasLocked = _isLayoutLocked;
|
||||
_isLayoutLocked = true;
|
||||
|
||||
if (HScrollBar != null)
|
||||
HScrollBar.Value = -value.X;
|
||||
if (VScrollBar != null)
|
||||
VScrollBar.Value = -value.Y;
|
||||
|
||||
IsLayoutLocked = wasLocked;
|
||||
_isLayoutLocked = wasLocked;
|
||||
base.SetViewOffset(ref value);
|
||||
}
|
||||
|
||||
@@ -239,15 +239,15 @@ namespace FlaxEngine.GUI
|
||||
/// <param name="fastScroll">True of scroll to the item quickly without smoothing.</param>
|
||||
public void ScrollViewTo(Rectangle bounds, bool fastScroll = false)
|
||||
{
|
||||
bool wasLocked = IsLayoutLocked;
|
||||
IsLayoutLocked = true;
|
||||
bool wasLocked = _isLayoutLocked;
|
||||
_isLayoutLocked = true;
|
||||
|
||||
if (HScrollBar != null && HScrollBar.Enabled)
|
||||
HScrollBar.ScrollViewTo(bounds.Left, bounds.Right, fastScroll);
|
||||
if (VScrollBar != null && VScrollBar.Enabled)
|
||||
VScrollBar.ScrollViewTo(bounds.Top, bounds.Bottom, fastScroll);
|
||||
|
||||
IsLayoutLocked = wasLocked;
|
||||
_isLayoutLocked = wasLocked;
|
||||
PerformLayout();
|
||||
}
|
||||
|
||||
@@ -406,14 +406,14 @@ namespace FlaxEngine.GUI
|
||||
return;
|
||||
_layoutUpdateLock++;
|
||||
|
||||
if (!IsLayoutLocked)
|
||||
if (!_isLayoutLocked)
|
||||
{
|
||||
_layoutChanged = false;
|
||||
}
|
||||
|
||||
base.PerformLayout(force);
|
||||
|
||||
if (!IsLayoutLocked && _layoutChanged)
|
||||
if (!_isLayoutLocked && _layoutChanged)
|
||||
{
|
||||
_layoutChanged = false;
|
||||
PerformLayout(true);
|
||||
|
||||
Reference in New Issue
Block a user