diff --git a/Source/Editor/GUI/Docking/DockPanelProxy.cs b/Source/Editor/GUI/Docking/DockPanelProxy.cs index fbc9d7bee..2bed8251b 100644 --- a/Source/Editor/GUI/Docking/DockPanelProxy.cs +++ b/Source/Editor/GUI/Docking/DockPanelProxy.cs @@ -42,7 +42,7 @@ namespace FlaxEditor.GUI.Docking /// /// The mouse position. /// - public Vector2 MousePosition; + public Vector2 MousePosition = Vector2.Minimum; /// /// 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 /// 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 /// public override void OnMouseEnter(Vector2 location) { - // Cache mouse MousePosition = location; base.OnMouseEnter(location); @@ -403,10 +402,7 @@ namespace FlaxEditor.GUI.Docking /// 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 /// 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(); } diff --git a/Source/Editor/GUI/Tree/TreeNode.cs b/Source/Editor/GUI/Tree/TreeNode.cs index 7fdc1c746..d65848589 100644 --- a/Source/Editor/GUI/Tree/TreeNode.cs +++ b/Source/Editor/GUI/Tree/TreeNode.cs @@ -889,19 +889,16 @@ namespace FlaxEditor.GUI.Tree /// 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); } - /// - public override void OnParentResized() - { - base.OnParentResized(); - - Width = Parent.Width; - } - /// public override DragDropEffect OnDragEnter(ref Vector2 location, DragData data) { @@ -1018,56 +1015,82 @@ namespace FlaxEditor.GUI.Tree /// 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(); + } + + /// + 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(); } /// 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)); } /// diff --git a/Source/Editor/Modules/SceneModule.cs b/Source/Editor/Modules/SceneModule.cs index d144c5a7e..ffbd876fe 100644 --- a/Source/Editor/Modules/SceneModule.cs +++ b/Source/Editor/Modules/SceneModule.cs @@ -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)) diff --git a/Source/Editor/SceneGraph/ActorNode.cs b/Source/Editor/SceneGraph/ActorNode.cs index a9720a7d5..b7dcee312 100644 --- a/Source/Editor/SceneGraph/ActorNode.cs +++ b/Source/Editor/SceneGraph/ActorNode.cs @@ -14,7 +14,7 @@ namespace FlaxEditor.SceneGraph /// It's part of the Scene Graph. /// /// - /// + /// [HideInEditor] public class ActorNode : SceneGraphNode { @@ -228,6 +228,7 @@ namespace FlaxEditor.SceneGraph set => _actor.Transform = value; } +#if false /// public override SceneGraphNode ParentNode { @@ -238,6 +239,7 @@ namespace FlaxEditor.SceneGraph base.ParentNode = value; } } +#endif /// 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 /// 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; + } } /// diff --git a/Source/Engine/Core/Math/Math.h b/Source/Engine/Core/Math/Math.h index b5320dd35..936623385 100644 --- a/Source/Engine/Core/Math/Math.h +++ b/Source/Engine/Core/Math/Math.h @@ -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/ diff --git a/Source/Engine/Core/Math/Vector2.cs b/Source/Engine/Core/Math/Vector2.cs index bc193a034..c93c0c275 100644 --- a/Source/Engine/Core/Math/Vector2.cs +++ b/Source/Engine/Core/Math/Vector2.cs @@ -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); } /// @@ -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); } /// @@ -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); } /// @@ -1965,11 +1965,9 @@ namespace FlaxEngine /// 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); } } } diff --git a/Source/Engine/Core/Math/Vector3.cs b/Source/Engine/Core/Math/Vector3.cs index 2674b30e6..7ef13c344 100644 --- a/Source/Engine/Core/Math/Vector3.cs +++ b/Source/Engine/Core/Math/Vector3.cs @@ -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); } /// @@ -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); } /// @@ -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); } /// @@ -2172,10 +2172,9 @@ namespace FlaxEngine /// true if the specified is equal to this instance; otherwise, false. 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); } } } diff --git a/Source/Engine/Core/Math/Vector4.cs b/Source/Engine/Core/Math/Vector4.cs index 6d1521e85..f7d605a8f 100644 --- a/Source/Engine/Core/Math/Vector4.cs +++ b/Source/Engine/Core/Math/Vector4.cs @@ -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); } /// @@ -1692,11 +1692,9 @@ namespace FlaxEngine /// 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); } } } diff --git a/Source/Engine/UI/GUI/ContainerControl.cs b/Source/Engine/UI/GUI/ContainerControl.cs index 0b02d0c21..9d27851dc 100644 --- a/Source/Engine/UI/GUI/ContainerControl.cs +++ b/Source/Engine/UI/GUI/ContainerControl.cs @@ -23,12 +23,21 @@ namespace FlaxEngine.GUI [NoSerialize] protected bool _containsFocus; + /// + /// The layout locking flag. + /// + [NoSerialize] + protected bool _isLayoutLocked; + + private bool _clipChildren = true; + private bool _cullChildren = true; + /// /// Initializes a new instance of the class. /// public ContainerControl() { - IsLayoutLocked = true; + _isLayoutLocked = true; } /// @@ -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; } /// @@ -46,14 +55,14 @@ namespace FlaxEngine.GUI public ContainerControl(Vector2 location, Vector2 size) : base(location, size) { - IsLayoutLocked = true; + _isLayoutLocked = true; } /// public ContainerControl(Rectangle bounds) : base(bounds) { - IsLayoutLocked = true; + _isLayoutLocked = true; } /// @@ -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). /// [HideInEditor, NoSerialize] - public bool IsLayoutLocked { get; set; } + public bool IsLayoutLocked + { + get => _isLayoutLocked; + set => _isLayoutLocked = value; + } /// /// Gets or sets a value indicating whether apply clipping mask on children during rendering. /// [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; + } /// /// Gets or sets a value indicating whether perform view culling on children during rendering. /// [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; + } /// /// Locks all child controls layout and itself. /// [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. /// [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 /// 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(); } - /// - 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; - } - } - /// 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 /// 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(); diff --git a/Source/Engine/UI/GUI/Control.Bounds.cs b/Source/Engine/UI/GUI/Control.Bounds.cs index 1fe4117f8..b4b612bf6 100644 --- a/Source/Engine/UI/GUI/Control.Bounds.cs +++ b/Source/Engine/UI/GUI/Control.Bounds.cs @@ -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); + } } /// @@ -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); + } } /// @@ -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); + } } /// @@ -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); + } } /// @@ -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(); } diff --git a/Source/Engine/UI/GUI/Panels/Panel.cs b/Source/Engine/UI/GUI/Panels/Panel.cs index eff9e99b8..946e3e9e4 100644 --- a/Source/Engine/UI/GUI/Panels/Panel.cs +++ b/Source/Engine/UI/GUI/Panels/Panel.cs @@ -177,15 +177,15 @@ namespace FlaxEngine.GUI /// 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 /// True of scroll to the item quickly without smoothing. 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);