diff --git a/Source/Editor/CustomEditors/Editors/FlaxObjectRefEditor.cs b/Source/Editor/CustomEditors/Editors/FlaxObjectRefEditor.cs
index fd367d21f..386d8d518 100644
--- a/Source/Editor/CustomEditors/Editors/FlaxObjectRefEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/FlaxObjectRefEditor.cs
@@ -7,6 +7,7 @@ using FlaxEditor.CustomEditors.Elements;
using FlaxEditor.GUI;
using FlaxEditor.GUI.Drag;
using FlaxEditor.SceneGraph;
+using FlaxEditor.SceneGraph.GUI;
using FlaxEditor.Scripting;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -23,6 +24,7 @@ namespace FlaxEditor.CustomEditors.Editors
public class FlaxObjectRefPickerControl : Control
{
private ScriptType _type;
+ private ActorTreeNode _linkedTreeNode;
private Object _value;
private string _valueName;
private bool _supportsPickDropDown;
@@ -300,7 +302,43 @@ namespace FlaxEditor.CustomEditors.Editors
// Picker dropdown menu
if (_supportsPickDropDown && (isSelected ? button2Rect : button1Rect).Contains(ref location))
+ {
ShowDropDownMenu();
+ return true;
+ }
+
+ if (button == MouseButton.Left)
+ {
+ _isMouseDown = false;
+
+ // Highlight actor or script reference
+ if (!_hasValidDragOver && !IsDragOver)
+ {
+ Actor actor = _value as Actor;
+ if (actor == null && _value is Script script)
+ actor = script.Actor;
+ if (actor != null)
+ {
+ if (_linkedTreeNode != null && _linkedTreeNode.Actor == actor)
+ {
+ _linkedTreeNode.ExpandAllParents();
+ _linkedTreeNode.StartHighlight();
+ }
+ else
+ {
+ _linkedTreeNode = Editor.Instance.Scene.GetActorNode(actor).TreeNode;
+ _linkedTreeNode.ExpandAllParents();
+ Editor.Instance.Windows.SceneWin.SceneTreePanel.ScrollViewTo(_linkedTreeNode, true);
+ _linkedTreeNode.StartHighlight();
+ }
+ return true;
+ }
+ }
+
+ // Reset valid drag over if still true at this point
+ if (_hasValidDragOver)
+ _hasValidDragOver = false;
+ }
return base.OnMouseUp(location, button);
}
@@ -326,6 +364,12 @@ namespace FlaxEditor.CustomEditors.Editors
// Check if has object selected
if (_value != null)
{
+ if (_linkedTreeNode != null)
+ {
+ _linkedTreeNode.StopHighlight();
+ _linkedTreeNode = null;
+ }
+
// Select object
if (_value is Actor actor)
Editor.Instance.SceneEditing.Select(actor);
@@ -469,6 +513,7 @@ namespace FlaxEditor.CustomEditors.Editors
_value = null;
_type = ScriptType.Null;
_valueName = null;
+ _linkedTreeNode = null;
base.OnDestroy();
}
diff --git a/Source/Editor/GUI/Tree/TreeNode.cs b/Source/Editor/GUI/Tree/TreeNode.cs
index 9bb9d2038..90639cebc 100644
--- a/Source/Editor/GUI/Tree/TreeNode.cs
+++ b/Source/Editor/GUI/Tree/TreeNode.cs
@@ -23,10 +23,19 @@ namespace FlaxEditor.GUI.Tree
///
public const float DefaultNodeOffsetY = 0;
+ private const float _targetHighlightScale = 1.25f;
+ private const float _highlightScaleAnimDuration = 0.85f;
+
private Tree _tree;
private bool _opened, _canChangeOrder;
private float _animationProgress, _cachedHeight;
+ private bool _isHightlighted;
+ private float _targetHighlightTimeSec;
+ private float _currentHighlightTimeSec;
+ // Used to prevent showing highlight on double mouse click
+ private float _debounceHighlightTime;
+ private float _highlightScale;
private bool _mouseOverArrow, _mouseOverHeader;
private float _xOffset, _textWidth;
private float _headerHeight = 16.0f;
@@ -605,9 +614,47 @@ namespace FlaxEditor.GUI.Tree
}
}
+ ///
+ /// Adds a box around the text to highlight the node.
+ ///
+ /// The duration of the highlight in seconds.
+ public void StartHighlight(float durationSec = 3)
+ {
+ _isHightlighted = true;
+ _targetHighlightTimeSec = durationSec;
+ _currentHighlightTimeSec = 0;
+ _debounceHighlightTime = 0;
+ _highlightScale = 2f;
+ }
+
+ ///
+ /// Stops any current highlight.
+ ///
+ public void StopHighlight()
+ {
+ _isHightlighted = false;
+ _targetHighlightTimeSec = 0;
+ _currentHighlightTimeSec = 0;
+ _debounceHighlightTime = 0;
+ }
+
///
public override void Update(float deltaTime)
{
+ // Highlight animations
+ if (_isHightlighted)
+ {
+ _debounceHighlightTime += deltaTime;
+ _currentHighlightTimeSec += deltaTime;
+
+ // In the first second, animate the highlight to shrink into it's resting position
+ if (_currentHighlightTimeSec < _highlightScaleAnimDuration)
+ _highlightScale = Mathf.Lerp(_highlightScale, _targetHighlightScale, _currentHighlightTimeSec);
+
+ if (_currentHighlightTimeSec >= _targetHighlightTimeSec)
+ _isHightlighted = false;
+ }
+
// Drop/down animation
if (_animationProgress < 1.0f)
{
@@ -676,6 +723,18 @@ namespace FlaxEditor.GUI.Tree
textRect.Width -= 18.0f;
}
+ float textWidth = TextFont.GetFont().MeasureText(_text).X;
+ Rectangle trueTextRect = textRect;
+ trueTextRect.Width = textWidth;
+ trueTextRect.Scale(_highlightScale);
+
+ if (_isHightlighted && _debounceHighlightTime > 0.1f)
+ {
+ Color highlightBackgroundColor = Editor.Instance.Options.Options.Visual.HighlightColor;
+ highlightBackgroundColor = highlightBackgroundColor.AlphaMultiplied(0.3f);
+ Render2D.FillRectangle(trueTextRect, highlightBackgroundColor);
+ }
+
// Draw text
Color textColor = CacheTextColor();
Render2D.DrawText(TextFont.GetFont(), _text, textRect, textColor, TextAlignment.Near, TextAlignment.Center);
@@ -730,6 +789,12 @@ namespace FlaxEditor.GUI.Tree
}
}
+ if (_isHightlighted && _debounceHighlightTime > 0.1f)
+ {
+ // Draw highlights
+ Render2D.DrawRectangle(trueTextRect, Editor.Instance.Options.Options.Visual.HighlightColor, 3);
+ }
+
// Base
if (_opened)
{