Merge branch 'master' into ImprovementSlider
This commit is contained in:
+1
-1
@@ -26,7 +26,7 @@ Go check out our [Trello](https://trello.com/b/NQjLXRCP/flax-roadmap).
|
||||
* For feature PR's the first thing you should evaluate is the value of your contribution, as in, what would it bring to this engine? Is it really required?
|
||||
If its a small change you could preferably suggest it to us on our discord, else feel free to open up a PR for it.
|
||||
|
||||
* Ensure when creating a PR that your contribution is well explained with a adequate description and title.
|
||||
* Ensure when creating a PR that your contribution is well explained with an adequate description and title.
|
||||
|
||||
* Generally, good code quality is expected, make sure your contribution works as intended and is appropriately commented where necessary.
|
||||
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
"Major": 1,
|
||||
"Minor": 12,
|
||||
"Revision": 0,
|
||||
"Build": 6914
|
||||
"Build": 6915
|
||||
},
|
||||
"Company": "Flax",
|
||||
"Copyright": "Copyright (c) 2012-2026 Wojciech Figat. All rights reserved.",
|
||||
|
||||
@@ -8,6 +8,7 @@ using FlaxEditor.Scripting;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
using FlaxEngine.Utilities;
|
||||
using FlaxEditor.CustomEditors.GUI;
|
||||
|
||||
namespace FlaxEditor.CustomEditors
|
||||
{
|
||||
@@ -244,10 +245,15 @@ namespace FlaxEditor.CustomEditors
|
||||
protected readonly RootEditor Editor;
|
||||
|
||||
/// <summary>
|
||||
/// The selected objects list (read-only).
|
||||
/// The current selection.
|
||||
/// </summary>
|
||||
public readonly ValueContainer Selection = new ValueContainer(ScriptMemberInfo.Null);
|
||||
|
||||
/// <summary>
|
||||
/// The current properties search query.
|
||||
/// </summary>
|
||||
public string SearchText = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The undo object used by this editor.
|
||||
/// </summary>
|
||||
@@ -529,6 +535,256 @@ namespace FlaxEditor.CustomEditors
|
||||
Editor?.RefreshInternal();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies search filter query to the presenter layout controls.
|
||||
/// </summary>
|
||||
public void ApplySearchFilter(string query)
|
||||
{
|
||||
SearchText = query;
|
||||
if (Root == null)
|
||||
return;
|
||||
|
||||
var isQueryEmpty = string.IsNullOrEmpty(query);
|
||||
var groupMatchCache = new Dictionary<DropPanel, bool>();
|
||||
UpdateFilter(Root, query, isQueryEmpty, groupMatchCache);
|
||||
UpdatePropertiesListsVisibility(Panel, query);
|
||||
UpdateGroupsVisibility(Panel, query);
|
||||
Panel.PerformLayout();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the visibility of properties lists and drop panels based on the current search query.
|
||||
/// </summary>
|
||||
public void UpdateGroupsAndListsVisibility()
|
||||
{
|
||||
if (string.IsNullOrEmpty(SearchText))
|
||||
{
|
||||
RestoreVisibilities(Panel);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdatePropertiesListsVisibility(Panel, SearchText);
|
||||
UpdateGroupsVisibility(Panel, SearchText);
|
||||
}
|
||||
Panel.PerformLayout();
|
||||
}
|
||||
|
||||
private void RestoreVisibilities(Control control)
|
||||
{
|
||||
if (control is DropPanel dropPanel)
|
||||
{
|
||||
dropPanel.SearchText = string.Empty;
|
||||
dropPanel.Visible = true;
|
||||
}
|
||||
else if (control is PropertiesList list)
|
||||
{
|
||||
list.Visible = true;
|
||||
}
|
||||
|
||||
if (control is ContainerControl container)
|
||||
{
|
||||
for (int i = 0; i < container.ChildrenCount; i++)
|
||||
{
|
||||
RestoreVisibilities(container.GetChild(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePropertiesListsVisibility(Control control, string query)
|
||||
{
|
||||
if (control is PropertiesList list)
|
||||
{
|
||||
if (string.IsNullOrEmpty(query))
|
||||
{
|
||||
list.Visible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool anyVisible = false;
|
||||
foreach (var label in list.Element.Labels)
|
||||
{
|
||||
if (label.Visible)
|
||||
{
|
||||
anyVisible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
list.Visible = anyVisible;
|
||||
}
|
||||
}
|
||||
|
||||
if (control is ContainerControl container)
|
||||
{
|
||||
for (int i = 0; i < container.ChildrenCount; i++)
|
||||
{
|
||||
UpdatePropertiesListsVisibility(container.GetChild(i), query);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateGroupsVisibility(Control control, string query)
|
||||
{
|
||||
if (control is DropPanel dropPanel)
|
||||
{
|
||||
dropPanel.SearchText = query;
|
||||
for (int i = 0; i < dropPanel.ChildrenCount; i++)
|
||||
{
|
||||
UpdateGroupsVisibility(dropPanel.GetChild(i), query);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(query))
|
||||
{
|
||||
dropPanel.Visible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
dropPanel.Visible = HasVisibleDescendants(dropPanel);
|
||||
}
|
||||
}
|
||||
else if (control is ContainerControl container)
|
||||
{
|
||||
for (int i = 0; i < container.ChildrenCount; i++)
|
||||
{
|
||||
UpdateGroupsVisibility(container.GetChild(i), query);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasVisibleDescendants(ContainerControl container)
|
||||
{
|
||||
for (int i = 0; i < container.ChildrenCount; i++)
|
||||
{
|
||||
var child = container.GetChild(i);
|
||||
if (child is PropertyNameLabel label && label.Visible)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (child is DropPanel dropPanel && dropPanel.Visible)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (child is ContainerControl subContainer && subContainer.Visible && HasVisibleDescendants(subContainer))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsInMatchingGroup(Control control, string query, Dictionary<DropPanel, bool> groupMatchCache)
|
||||
{
|
||||
if (string.IsNullOrEmpty(query))
|
||||
return false;
|
||||
|
||||
var p = control.Parent;
|
||||
while (p != null)
|
||||
{
|
||||
if (p is DropPanel dropPanel)
|
||||
{
|
||||
if (!groupMatchCache.TryGetValue(dropPanel, out bool matches))
|
||||
{
|
||||
var headerText = dropPanel.HeaderText;
|
||||
matches = headerText != null && headerText.IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0;
|
||||
groupMatchCache[dropPanel] = matches;
|
||||
}
|
||||
if (matches)
|
||||
return true;
|
||||
}
|
||||
p = p.Parent;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool UpdateFilter(CustomEditor editor, string query, bool forceVisible, Dictionary<DropPanel, bool> groupMatchCache)
|
||||
{
|
||||
bool isVisible = false;
|
||||
|
||||
bool labelMatches = false;
|
||||
if (editor.LinkedLabel != null)
|
||||
{
|
||||
editor.LinkedLabel.SearchText = query;
|
||||
if (forceVisible)
|
||||
{
|
||||
labelMatches = true;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(query))
|
||||
{
|
||||
var labelText = editor.LinkedLabel.Text.ToString();
|
||||
if (labelText.IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
{
|
||||
labelMatches = true;
|
||||
}
|
||||
else if (IsInMatchingGroup(editor.LinkedLabel, query, groupMatchCache))
|
||||
{
|
||||
labelMatches = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isThisEditorVisible = forceVisible || labelMatches;
|
||||
|
||||
bool anyChildVisible = false;
|
||||
bool forceChildrenVisible = isThisEditorVisible;
|
||||
|
||||
foreach (var child in editor.ChildrenEditors)
|
||||
{
|
||||
if (UpdateFilter(child, query, forceChildrenVisible, groupMatchCache))
|
||||
{
|
||||
anyChildVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
isVisible = isThisEditorVisible || anyChildVisible;
|
||||
|
||||
if (editor.LinkedLabel != null)
|
||||
{
|
||||
SetLabelAndControlsVisible(editor.LinkedLabel, isVisible);
|
||||
}
|
||||
|
||||
if (editor.Style == DisplayStyle.Group && editor.Layout != null && editor.Layout.Control != null)
|
||||
{
|
||||
editor.Layout.Control.Visible = isVisible;
|
||||
}
|
||||
|
||||
return isVisible;
|
||||
}
|
||||
|
||||
private void SetLabelAndControlsVisible(PropertyNameLabel label, bool visible)
|
||||
{
|
||||
label.Visible = visible;
|
||||
var container = label.FirstChildControlContainer ?? label.Parent as PropertiesList;
|
||||
if (container != null)
|
||||
{
|
||||
int startIndex = label.FirstChildControlIndex;
|
||||
if (startIndex >= 0)
|
||||
{
|
||||
int endIndex = container.Children.Count;
|
||||
var labels = container.Element.Labels;
|
||||
int labelIndex = labels.IndexOf(label);
|
||||
if (labelIndex >= 0 && labelIndex < labels.Count - 1)
|
||||
{
|
||||
for (int i = labelIndex + 1; i < labels.Count; i++)
|
||||
{
|
||||
var nextContainer = labels[i].FirstChildControlContainer ?? labels[i].Parent as PropertiesList;
|
||||
if (nextContainer == container)
|
||||
{
|
||||
endIndex = labels[i].FirstChildControlIndex - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = startIndex; i < endIndex; i++)
|
||||
{
|
||||
if (i < container.Children.Count)
|
||||
{
|
||||
container.Children[i].Visible = visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override ContainerControl ContainerControl => Panel;
|
||||
}
|
||||
|
||||
@@ -868,6 +868,28 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
if (c.LabelIndex != -1 && c.PropertiesList != null && c.PropertiesList.Labels.Count > c.LabelIndex)
|
||||
{
|
||||
var label = c.PropertiesList.Labels[c.LabelIndex];
|
||||
if (visible && Presenter != null && !string.IsNullOrEmpty(Presenter.SearchText))
|
||||
{
|
||||
bool match = label.Text.ToString().IndexOf(Presenter.SearchText, StringComparison.OrdinalIgnoreCase) >= 0;
|
||||
if (!match)
|
||||
{
|
||||
var p = label.Parent;
|
||||
while (p != null)
|
||||
{
|
||||
if (p is DropPanel dropPanel)
|
||||
{
|
||||
var headerText = dropPanel.HeaderText;
|
||||
if (headerText != null && headerText.IndexOf(Presenter.SearchText, StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
{
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
p = p.Parent;
|
||||
}
|
||||
}
|
||||
visible = match;
|
||||
}
|
||||
label.Visible = visible;
|
||||
for (int j = label.FirstChildControlIndex; j < c.PropertiesList.Properties.Children.Count; j++)
|
||||
{
|
||||
@@ -908,6 +930,10 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
_visibleIfCaches = null;
|
||||
}
|
||||
}
|
||||
if (Presenter != null && !string.IsNullOrEmpty(Presenter.SearchText))
|
||||
{
|
||||
Presenter.UpdateGroupsAndListsVisibility();
|
||||
}
|
||||
|
||||
base.Refresh();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||
|
||||
using FlaxEditor.GUI.ContextMenu;
|
||||
using FlaxEditor.Utilities;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
|
||||
@@ -45,6 +46,34 @@ namespace FlaxEditor.CustomEditors.GUI
|
||||
/// </summary>
|
||||
public Color HighlightStripColor;
|
||||
|
||||
/// <summary>
|
||||
/// The active search text query used to highlight matching parts of the label.
|
||||
/// </summary>
|
||||
public string SearchText = string.Empty;
|
||||
|
||||
private string _lastSearchText;
|
||||
private string _lastText;
|
||||
private QueryFilterHelper.Range[] _highlightRanges;
|
||||
|
||||
private void UpdateHighlights()
|
||||
{
|
||||
var text = Text?.ToString() ?? string.Empty;
|
||||
if (_lastSearchText == SearchText && _lastText == text)
|
||||
return;
|
||||
|
||||
_lastSearchText = SearchText;
|
||||
_lastText = text;
|
||||
|
||||
if (!string.IsNullOrEmpty(SearchText))
|
||||
{
|
||||
QueryFilterHelper.Match(SearchText, text, out _highlightRanges);
|
||||
}
|
||||
else
|
||||
{
|
||||
_highlightRanges = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when label creates the context menu popup for th property. Can be used to add some custom logic per property editor.
|
||||
/// </summary>
|
||||
@@ -83,6 +112,31 @@ namespace FlaxEditor.CustomEditors.GUI
|
||||
{
|
||||
Render2D.FillRectangle(new Rectangle(0, 0, 2, Height), HighlightStripColor);
|
||||
}
|
||||
|
||||
UpdateHighlights();
|
||||
|
||||
if (_highlightRanges != null && _highlightRanges.Length > 0)
|
||||
{
|
||||
var text = Text.ToString();
|
||||
var font = Font?.GetFont();
|
||||
if (font != null)
|
||||
{
|
||||
var style = Style.Current;
|
||||
var color = style.ProgressNormal * 0.6f;
|
||||
var margin = Margin;
|
||||
var textSize = font.MeasureText(text);
|
||||
var textX = margin.Left;
|
||||
var textY = margin.Top + (Height - margin.Height - textSize.Y) * 0.5f;
|
||||
|
||||
for (int i = 0; i < _highlightRanges.Length; i++)
|
||||
{
|
||||
var start = font.GetCharPosition(text, _highlightRanges[i].StartIndex);
|
||||
var end = font.GetCharPosition(text, _highlightRanges[i].EndIndex);
|
||||
var highlightRect = new Rectangle(start.X + textX, textY, end.X - start.X, textSize.Y);
|
||||
Render2D.FillRectangle(highlightRect, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -1337,10 +1337,7 @@ namespace FlaxEditor
|
||||
{
|
||||
var scenes = Level.Scenes;
|
||||
for (int i = 0; i < scenes.Length; i++)
|
||||
{
|
||||
scenes[i].ClearLightmaps();
|
||||
}
|
||||
|
||||
Scene.MarkSceneEdited(scenes);
|
||||
}
|
||||
|
||||
@@ -1384,6 +1381,7 @@ namespace FlaxEditor
|
||||
var scenes = Level.Scenes;
|
||||
Navigation.BuildNavMesh();
|
||||
Scene.MarkSceneEdited(scenes);
|
||||
ProgressReporting.NavMeshBuilding.DirtyScenesOnEnd = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -82,6 +82,53 @@ namespace FlaxEditor.GUI
|
||||
}
|
||||
}
|
||||
|
||||
private bool _alternateRows = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether alternate row background colors should be applied.
|
||||
/// </summary>
|
||||
public bool AlternateRows
|
||||
{
|
||||
get => _alternateRows;
|
||||
set
|
||||
{
|
||||
if (_alternateRows != value)
|
||||
{
|
||||
_alternateRows = value;
|
||||
PerformLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Color? _rowColorEven;
|
||||
private Color? _rowColorOdd;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the background color of even rows.
|
||||
/// </summary>
|
||||
public Color RowColorEven
|
||||
{
|
||||
get => _rowColorEven ?? Color.Transparent;
|
||||
set
|
||||
{
|
||||
_rowColorEven = value;
|
||||
PerformLayout();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the background color of odd rows.
|
||||
/// </summary>
|
||||
public Color RowColorOdd
|
||||
{
|
||||
get => _rowColorOdd ?? (Style.Current != null ? Style.Current.Background * 1.4f : Color.Transparent);
|
||||
set
|
||||
{
|
||||
_rowColorOdd = value;
|
||||
PerformLayout();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Table"/> class.
|
||||
/// </summary>
|
||||
@@ -250,6 +297,7 @@ namespace FlaxEditor.GUI
|
||||
|
||||
// Arrange rows
|
||||
float y = _headerHeight;
|
||||
int visibleRowIndex = 0;
|
||||
for (int i = 0; i < Children.Count; i++)
|
||||
{
|
||||
var c = Children[i];
|
||||
@@ -260,6 +308,12 @@ namespace FlaxEditor.GUI
|
||||
bounds.Y = y;
|
||||
c.Bounds = bounds;
|
||||
y += bounds.Height + 1;
|
||||
|
||||
if (_alternateRows && c is Row row)
|
||||
{
|
||||
row.BackgroundColor = visibleRowIndex % 2 == 1 ? RowColorOdd : RowColorEven;
|
||||
visibleRowIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ namespace FlaxEditor.Progress.Handlers
|
||||
{
|
||||
private bool _isActive;
|
||||
|
||||
internal bool DirtyScenesOnEnd;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="NavMeshBuildingProgress"/> class.
|
||||
/// </summary>
|
||||
@@ -34,6 +36,11 @@ namespace FlaxEditor.Progress.Handlers
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DirtyScenesOnEnd)
|
||||
{
|
||||
DirtyScenesOnEnd = false;
|
||||
Editor.Instance.Scene.MarkAllScenesEdited();
|
||||
}
|
||||
OnEnd();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,14 @@ namespace FlaxEditor.States
|
||||
{
|
||||
StateMachine.GoToState<EndState>();
|
||||
}
|
||||
|
||||
protected void ConditionalDirtyScenes()
|
||||
{
|
||||
if (((SubStateMachine)StateMachine).States.Any(x => ((SubState)x).DirtyScenes))
|
||||
{
|
||||
Editor.Instance.Scene.MarkAllScenesEdited();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class BeginState : SubState
|
||||
@@ -83,18 +91,12 @@ namespace FlaxEditor.States
|
||||
{
|
||||
public override void OnEnter()
|
||||
{
|
||||
var stateMachine = (SubStateMachine)StateMachine;
|
||||
var scenesDirty = false;
|
||||
foreach (var state in stateMachine.States)
|
||||
var states = ((SubStateMachine)StateMachine).States;
|
||||
foreach (var state in states)
|
||||
{
|
||||
((SubState)state).Before();
|
||||
scenesDirty |= ((SubState)state).DirtyScenes;
|
||||
}
|
||||
if (scenesDirty)
|
||||
{
|
||||
foreach (var scene in Level.Scenes)
|
||||
Editor.Instance.Scene.MarkSceneEdited(scene);
|
||||
}
|
||||
ConditionalDirtyScenes();
|
||||
Done();
|
||||
}
|
||||
}
|
||||
@@ -262,6 +264,7 @@ namespace FlaxEditor.States
|
||||
{
|
||||
public override void OnEnter()
|
||||
{
|
||||
ConditionalDirtyScenes();
|
||||
Editor.Instance.StateMachine.GoToState<EditingSceneState>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,12 @@ namespace FlaxEditor.Surface
|
||||
/// </summary>
|
||||
IEnumerable<ScriptType> NewParameterTypes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Index of the parameter to start renaming once the properties panel is next rebuilt, or -1 if none.
|
||||
/// Used to auto-start renaming of a freshly added parameter.
|
||||
/// </summary>
|
||||
int ParamToRename { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Event called when surface gets loaded (eg. after opening the window).
|
||||
/// </summary>
|
||||
@@ -589,6 +595,7 @@ namespace FlaxEditor.Surface
|
||||
if (Utilities.Utils.OnAssetProperties(layout, asset))
|
||||
return;
|
||||
var parameters = window.VisjectSurface.Parameters;
|
||||
ParameterPropertyNameLabel labelToRename = null;
|
||||
CustomEditors.Editors.GenericEditor.OnGroupsBegin();
|
||||
for (int i = 0; i < parameters.Count; i++)
|
||||
{
|
||||
@@ -643,6 +650,8 @@ namespace FlaxEditor.Surface
|
||||
tooltipText += '\n' + tooltip.Text;
|
||||
propertyLabel.MouseLeftDoubleClick += (label, location) => StartParameterRenaming(pIndex, label);
|
||||
propertyLabel.SetupContextMenu += OnPropertyLabelSetupContextMenu;
|
||||
if (pIndex == window.ParamToRename)
|
||||
labelToRename = propertyLabel;
|
||||
var property = itemLayout.AddPropertyItem(propertyLabel, tooltipText);
|
||||
property.Property("Value", propertyValue);
|
||||
}
|
||||
@@ -657,6 +666,21 @@ namespace FlaxEditor.Surface
|
||||
newParam.Button.ButtonClicked += OnAddParameterButtonClicked;
|
||||
layout.Space(10);
|
||||
}
|
||||
// Defer renaming a newly added param once its label is built and laid out
|
||||
// Adding a param can rebuild the panel more than once (disposing earlier labels)
|
||||
// Because of this every rebuild recaptures the current label, only the surviving one actually calls StartParameterRenaming
|
||||
if (labelToRename != null)
|
||||
{
|
||||
var index = window.ParamToRename;
|
||||
var label = labelToRename;
|
||||
FlaxEngine.Scripting.InvokeOnUpdate(() =>
|
||||
{
|
||||
if (label.IsDisposing)
|
||||
return; // A latter rebuild replaced this label, its own callback will handle it
|
||||
window.ParamToRename = -1;
|
||||
StartParameterRenaming(index, label);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAddParameterButtonClicked(Button button)
|
||||
@@ -695,6 +719,7 @@ namespace FlaxEditor.Surface
|
||||
};
|
||||
window.VisjectSurface.Undo.AddAction(action);
|
||||
action.Do();
|
||||
window.ParamToRename = action.Index;
|
||||
}
|
||||
|
||||
private DragData OnDragParameter(DraggablePropertyNameLabel label)
|
||||
@@ -1276,6 +1301,9 @@ namespace FlaxEditor.Surface
|
||||
/// <inheritdoc />
|
||||
public abstract IEnumerable<ScriptType> NewParameterTypes { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public int ParamToRename { get; set; } = -1;
|
||||
|
||||
/// <inheritdoc />
|
||||
public event Action SurfaceLoaded;
|
||||
|
||||
|
||||
@@ -148,8 +148,7 @@ namespace FlaxEditor.Actions
|
||||
// Prefab links are broken by the C++ backend on actor reparenting
|
||||
|
||||
// Mark scenes as edited
|
||||
foreach (var scene in scenes)
|
||||
Editor.Instance.Scene.MarkSceneEdited(scene);
|
||||
Editor.Instance.Scene.MarkSceneEdited(scenes);
|
||||
}
|
||||
|
||||
public void Undo()
|
||||
|
||||
@@ -602,6 +602,9 @@ namespace FlaxEditor.Windows.Assets
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<ScriptType> NewParameterTypes => Editor.CodeEditing.VisualScriptPropertyTypes.Get();
|
||||
|
||||
/// <inheritdoc />
|
||||
public int ParamToRename { get; set; } = -1;
|
||||
|
||||
/// <inheritdoc />
|
||||
public event Action SurfaceLoaded;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ using FlaxEditor.Content;
|
||||
using FlaxEditor.CustomEditors;
|
||||
using FlaxEditor.GUI;
|
||||
using FlaxEditor.GUI.ContextMenu;
|
||||
using FlaxEditor.GUI.Input;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
using FlaxEngine.Json;
|
||||
@@ -67,6 +68,8 @@ namespace FlaxEditor.Windows.Assets
|
||||
}
|
||||
|
||||
private readonly CustomEditorPresenter _presenter;
|
||||
private SearchBox _searchBox;
|
||||
private Panel _scrollingPanel;
|
||||
private readonly ToolStripButton _saveButton;
|
||||
private readonly ToolStripButton _undoButton;
|
||||
private readonly ToolStripButton _redoButton;
|
||||
@@ -100,18 +103,35 @@ namespace FlaxEditor.Windows.Assets
|
||||
_undoButton = _toolstrip.AddButton(Editor.Icons.Undo64, _undo.PerformUndo).LinkTooltip("Undo", ref inputOptions.Undo);
|
||||
_redoButton = _toolstrip.AddButton(Editor.Icons.Redo64, _undo.PerformRedo).LinkTooltip("Redo", ref inputOptions.Redo);
|
||||
|
||||
// Panel
|
||||
var panel = new Panel(ScrollBars.Vertical)
|
||||
// Header panel for search
|
||||
var headerPanel = new ContainerControl
|
||||
{
|
||||
AnchorPreset = AnchorPresets.HorizontalStretchTop,
|
||||
BackgroundColor = Style.Current.Background,
|
||||
IsScrollable = false,
|
||||
Offsets = new Margin(0, 0, _toolstrip.Bottom, 18 + 6),
|
||||
Parent = this,
|
||||
};
|
||||
_searchBox = new SearchBox
|
||||
{
|
||||
AnchorPreset = AnchorPresets.HorizontalStretchMiddle,
|
||||
Parent = headerPanel,
|
||||
Bounds = new Rectangle(4, 4, headerPanel.Width - 8, 18),
|
||||
};
|
||||
_searchBox.TextChanged += ApplySearchFilter;
|
||||
|
||||
_scrollingPanel = new Panel(ScrollBars.Vertical)
|
||||
{
|
||||
AnchorPreset = AnchorPresets.StretchAll,
|
||||
Offsets = new Margin(0, 0, _toolstrip.Bottom, 0),
|
||||
Parent = this
|
||||
Offsets = new Margin(0, 0, headerPanel.Bottom, 0),
|
||||
Parent = this,
|
||||
};
|
||||
|
||||
// Properties
|
||||
_presenter = new CustomEditorPresenter(_undo, "Loading...");
|
||||
_presenter.Panel.Parent = panel;
|
||||
_presenter.Panel.Parent = _scrollingPanel;
|
||||
_presenter.Modified += MarkAsEdited;
|
||||
_presenter.AfterLayout += OnPresenterAfterLayout;
|
||||
|
||||
// Setup input actions
|
||||
InputActions.Add(options => options.Undo, _undo.PerformUndo);
|
||||
@@ -349,5 +369,15 @@ namespace FlaxEditor.Windows.Assets
|
||||
_optionsCM?.Dispose();
|
||||
_typeText = null;
|
||||
}
|
||||
|
||||
private void OnPresenterAfterLayout(LayoutElementsContainer layout)
|
||||
{
|
||||
ApplySearchFilter();
|
||||
}
|
||||
|
||||
private void ApplySearchFilter()
|
||||
{
|
||||
_presenter.ApplySearchFilter(_searchBox.Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||
using System.Xml;
|
||||
using FlaxEditor.Content;
|
||||
using FlaxEditor.CustomEditors;
|
||||
using FlaxEditor.CustomEditors.GUI;
|
||||
using FlaxEditor.Gizmo;
|
||||
using FlaxEditor.GUI;
|
||||
using FlaxEditor.GUI.Input;
|
||||
@@ -29,6 +30,8 @@ namespace FlaxEditor.Windows.Assets
|
||||
private readonly PrefabTree _tree;
|
||||
private readonly PrefabWindowViewport _viewport;
|
||||
private readonly CustomEditorPresenter _propertiesEditor;
|
||||
private SearchBox _propertiesSearchBox;
|
||||
private Panel _propertiesScrollingPanel;
|
||||
|
||||
private readonly ToolStripButton _saveButton;
|
||||
private readonly ToolStripButton _toolStripUndo;
|
||||
@@ -142,7 +145,7 @@ namespace FlaxEditor.Windows.Assets
|
||||
};
|
||||
|
||||
// Split Panel 2
|
||||
_split2 = new SplitPanel(Orientation.Horizontal, ScrollBars.None, ScrollBars.Vertical)
|
||||
_split2 = new SplitPanel(Orientation.Horizontal, ScrollBars.None, ScrollBars.None)
|
||||
{
|
||||
AnchorPreset = AnchorPresets.StretchAll,
|
||||
Offsets = Margin.Zero,
|
||||
@@ -197,9 +200,33 @@ namespace FlaxEditor.Windows.Assets
|
||||
_viewport.TransformGizmo.ModeChanged += UpdateToolstrip;
|
||||
|
||||
// Prefab properties editor
|
||||
var propHeaderPanel = new ContainerControl
|
||||
{
|
||||
AnchorPreset = AnchorPresets.HorizontalStretchTop,
|
||||
BackgroundColor = Style.Current.Background,
|
||||
IsScrollable = false,
|
||||
Offsets = new Margin(0, 0, 0, 18 + 6),
|
||||
Parent = _split2.Panel2,
|
||||
};
|
||||
_propertiesSearchBox = new SearchBox
|
||||
{
|
||||
AnchorPreset = AnchorPresets.HorizontalStretchMiddle,
|
||||
Parent = propHeaderPanel,
|
||||
Bounds = new Rectangle(4, 4, propHeaderPanel.Width - 8, 18),
|
||||
};
|
||||
_propertiesSearchBox.TextChanged += ApplyPropertiesSearchFilter;
|
||||
|
||||
_propertiesScrollingPanel = new Panel(ScrollBars.Vertical)
|
||||
{
|
||||
AnchorPreset = AnchorPresets.StretchAll,
|
||||
Offsets = new Margin(0, 0, propHeaderPanel.Bottom, 0),
|
||||
Parent = _split2.Panel2,
|
||||
};
|
||||
|
||||
_propertiesEditor = new CustomEditorPresenter(_undo, null, this);
|
||||
_propertiesEditor.Panel.Parent = _split2.Panel2;
|
||||
_propertiesEditor.Panel.Parent = _propertiesScrollingPanel;
|
||||
_propertiesEditor.Modified += MarkAsEdited;
|
||||
_propertiesEditor.AfterLayout += OnPresenterAfterLayout;
|
||||
|
||||
// Toolstrip
|
||||
_saveButton = _toolstrip.AddButton(Editor.Icons.Save64, Save).LinkTooltip("Save", ref inputOptions.Save);
|
||||
@@ -580,6 +607,16 @@ namespace FlaxEditor.Windows.Assets
|
||||
/// <inheritdoc />
|
||||
public EditorViewport PresenterViewport => _viewport;
|
||||
|
||||
private void OnPresenterAfterLayout(LayoutElementsContainer layout)
|
||||
{
|
||||
ApplyPropertiesSearchFilter();
|
||||
}
|
||||
|
||||
private void ApplyPropertiesSearchFilter()
|
||||
{
|
||||
_propertiesEditor.ApplySearchFilter(_propertiesSearchBox.Text);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
EditorViewport ISceneEditingContext.Viewport => Viewport;
|
||||
}
|
||||
|
||||
@@ -1398,6 +1398,9 @@ namespace FlaxEditor.Windows.Assets
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<ScriptType> NewParameterTypes => Editor.CodeEditing.VisualScriptPropertyTypes.Get();
|
||||
|
||||
/// <inheritdoc />
|
||||
public int ParamToRename { get; set; } = -1;
|
||||
|
||||
/// <inheritdoc />
|
||||
public event Action SurfaceLoaded;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using FlaxEditor.CustomEditors;
|
||||
using FlaxEditor.GUI;
|
||||
using FlaxEditor.GUI.Input;
|
||||
using FlaxEditor.GUI.Tabs;
|
||||
using FlaxEditor.Options;
|
||||
using FlaxEngine;
|
||||
@@ -25,6 +26,7 @@ namespace FlaxEditor.Windows
|
||||
private ToolStripButton _saveButton;
|
||||
private readonly Undo _undo;
|
||||
private readonly List<Tab> _customTabs = new List<Tab>();
|
||||
private SearchBox _searchBox;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EditorOptionsWindow"/> class.
|
||||
@@ -48,15 +50,33 @@ namespace FlaxEditor.Windows
|
||||
_saveButton = (ToolStripButton)toolstrip.AddButton(editor.Icons.Save64, SaveData).LinkTooltip("Save.");
|
||||
_saveButton.Enabled = false;
|
||||
|
||||
// Header panel for search
|
||||
var headerPanel = new ContainerControl
|
||||
{
|
||||
AnchorPreset = AnchorPresets.HorizontalStretchTop,
|
||||
BackgroundColor = Style.Current.Background,
|
||||
IsScrollable = false,
|
||||
Offsets = new Margin(0, 0, toolstrip.Bottom, 18 + 6),
|
||||
Parent = this,
|
||||
};
|
||||
_searchBox = new SearchBox
|
||||
{
|
||||
AnchorPreset = AnchorPresets.HorizontalStretchMiddle,
|
||||
Parent = headerPanel,
|
||||
Bounds = new Rectangle(4, 4, headerPanel.Width - 8, 18),
|
||||
};
|
||||
_searchBox.TextChanged += ApplySearchFilter;
|
||||
|
||||
_tabs = new Tabs
|
||||
{
|
||||
Orientation = Orientation.Vertical,
|
||||
AnchorPreset = AnchorPresets.StretchAll,
|
||||
Offsets = new Margin(0, 0, toolstrip.Bottom, 0),
|
||||
Offsets = new Margin(0, 0, headerPanel.Bottom, 0),
|
||||
TabsSize = new Float2(120, 32),
|
||||
UseScroll = true,
|
||||
Parent = this
|
||||
};
|
||||
_tabs.SelectedTabChanged += OnSelectedTabChanged;
|
||||
|
||||
CreateTab("General", () => _options.General);
|
||||
CreateTab("Interface", () => _options.Interface);
|
||||
@@ -94,6 +114,13 @@ namespace FlaxEditor.Windows
|
||||
settings.Panel.Parent = panel;
|
||||
settings.Panel.Tag = getValue;
|
||||
settings.Modified += MarkAsEdited;
|
||||
settings.AfterLayout += layout =>
|
||||
{
|
||||
if (_tabs.SelectedTab == tab)
|
||||
{
|
||||
ApplySearchFilter();
|
||||
}
|
||||
};
|
||||
|
||||
return tab;
|
||||
}
|
||||
@@ -280,5 +307,25 @@ namespace FlaxEditor.Windows
|
||||
|
||||
return base.OnClosing(reason);
|
||||
}
|
||||
|
||||
private void OnSelectedTabChanged(Tabs tabs)
|
||||
{
|
||||
ApplySearchFilter();
|
||||
}
|
||||
|
||||
private CustomEditorPresenter GetTabPresenter(Tab tab)
|
||||
{
|
||||
if (tab == null)
|
||||
return null;
|
||||
var panel = tab.GetChild<Panel>();
|
||||
var settingsPanel = panel?.GetChild<CustomEditorPresenter.PresenterPanel>();
|
||||
return settingsPanel?.Presenter;
|
||||
}
|
||||
|
||||
private void ApplySearchFilter()
|
||||
{
|
||||
var presenter = GetTabPresenter(_tabs.SelectedTab);
|
||||
presenter?.ApplySearchFilter(_searchBox.Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,8 @@ namespace FlaxEditor.Windows.Profiler
|
||||
var textColor = style.Foreground;
|
||||
_table = new Table
|
||||
{
|
||||
RowColorEven = Color.Transparent,
|
||||
RowColorOdd = style.Background * 1.4f,
|
||||
Columns = new[]
|
||||
{
|
||||
new ColumnDefinition
|
||||
@@ -242,8 +244,6 @@ namespace FlaxEditor.Windows.Profiler
|
||||
var resourcesOrdered = resources.OrderByDescending(x => x.MemoryUsage);
|
||||
|
||||
// Add rows
|
||||
var rowColor2 = Style.Current.Background * 1.4f;
|
||||
int rowIndex = 0;
|
||||
foreach (var e in resourcesOrdered)
|
||||
{
|
||||
ClickableRow row;
|
||||
@@ -271,9 +271,7 @@ namespace FlaxEditor.Windows.Profiler
|
||||
|
||||
// Add row to the table
|
||||
row.Width = _table.Width;
|
||||
row.BackgroundColor = rowIndex % 2 == 1 ? rowColor2 : Color.Transparent;
|
||||
row.Parent = _table;
|
||||
rowIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -106,6 +106,8 @@ namespace FlaxEditor.Windows.Profiler
|
||||
var textColor = style.Foreground;
|
||||
_table = new Table
|
||||
{
|
||||
RowColorEven = Color.Transparent,
|
||||
RowColorOdd = style.Background * 1.4f,
|
||||
Columns = new[]
|
||||
{
|
||||
new ColumnDefinition
|
||||
@@ -464,7 +466,6 @@ namespace FlaxEditor.Windows.Profiler
|
||||
float totalTimeMs = _mainChart.SelectedSample;
|
||||
|
||||
// Add rows
|
||||
var rowColor2 = Style.Current.Background * 1.4f;
|
||||
for (int j = 0; j < data.Length; j++)
|
||||
{
|
||||
var events = data[j].Events;
|
||||
@@ -540,7 +541,6 @@ namespace FlaxEditor.Windows.Profiler
|
||||
row.Depth = e.Depth;
|
||||
row.Width = _table.Width;
|
||||
row.Visible = e.Depth < 2;
|
||||
row.BackgroundColor = i % 2 == 1 ? rowColor2 : Color.Transparent;
|
||||
row.Parent = _table;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,6 +83,8 @@ namespace FlaxEditor.Windows.Profiler
|
||||
var textColor = style.Foreground;
|
||||
_table = new Table
|
||||
{
|
||||
RowColorEven = Color.Transparent,
|
||||
RowColorOdd = style.Background * 1.4f,
|
||||
Columns = new[]
|
||||
{
|
||||
new ColumnDefinition
|
||||
@@ -339,7 +341,6 @@ namespace FlaxEditor.Windows.Profiler
|
||||
float totalTimeMs = _drawTimeGPU.SelectedSample;
|
||||
|
||||
// Add rows
|
||||
var rowColor2 = Style.Current.Background * 1.4f;
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
var e = data[i];
|
||||
@@ -386,7 +387,6 @@ namespace FlaxEditor.Windows.Profiler
|
||||
row.Depth = e.Depth;
|
||||
row.Width = _table.Width;
|
||||
row.Visible = e.Depth < 3;
|
||||
row.BackgroundColor = i % 2 == 1 ? rowColor2 : Color.Transparent;
|
||||
row.Parent = _table;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,6 +84,8 @@ namespace FlaxEditor.Windows.Profiler
|
||||
var textColor = style.Foreground;
|
||||
_table = new Table
|
||||
{
|
||||
RowColorEven = Color.Transparent,
|
||||
RowColorOdd = style.Background * 1.4f,
|
||||
Columns = new[]
|
||||
{
|
||||
new ColumnDefinition
|
||||
@@ -236,7 +238,6 @@ namespace FlaxEditor.Windows.Profiler
|
||||
});
|
||||
|
||||
// Add rows
|
||||
var rowColor2 = Style.Current.Background * 1.4f;
|
||||
for (int i = 0; i < (int)ProfilerMemory.Groups.MAX; i++)
|
||||
{
|
||||
var group = _groupOrder[i];
|
||||
@@ -278,7 +279,6 @@ namespace FlaxEditor.Windows.Profiler
|
||||
row.BackgroundColors[3] = Color.Red.AlphaMultiplied(Mathf.Min(1, (float)groupCount / totalCount) * 0.5f);
|
||||
}
|
||||
row.Width = _table.Width;
|
||||
row.BackgroundColor = i % 2 == 1 ? rowColor2 : Color.Transparent;
|
||||
row.Parent = _table;
|
||||
|
||||
var useBackground = group != (int)ProfilerMemory.Groups.Total &&
|
||||
|
||||
@@ -81,6 +81,8 @@ namespace FlaxEditor.Windows.Profiler
|
||||
var textColor = style.Foreground;
|
||||
_table = new Table
|
||||
{
|
||||
RowColorEven = Color.Transparent,
|
||||
RowColorOdd = style.Background * 1.4f,
|
||||
Columns = new[]
|
||||
{
|
||||
new ColumnDefinition
|
||||
@@ -299,8 +301,6 @@ namespace FlaxEditor.Windows.Profiler
|
||||
var resourcesOrdered = resources.OrderByDescending(x => x?.MemoryUsage ?? 0);
|
||||
|
||||
// Add rows
|
||||
var rowColor2 = Style.Current.Background * 1.4f;
|
||||
int rowIndex = 0;
|
||||
foreach (var e in resourcesOrdered)
|
||||
{
|
||||
if (e == null)
|
||||
@@ -335,9 +335,7 @@ namespace FlaxEditor.Windows.Profiler
|
||||
|
||||
// Add row to the table
|
||||
row.Width = _table.Width;
|
||||
row.BackgroundColor = rowIndex % 2 == 1 ? rowColor2 : Color.Transparent;
|
||||
row.Parent = _table;
|
||||
rowIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -190,7 +190,6 @@ namespace FlaxEditor.Windows.Profiler
|
||||
var rowCount = Int2.Zero;
|
||||
if (events != null && events.Length != 0)
|
||||
{
|
||||
var rowColor2 = Style.Current.Background * 1.4f;
|
||||
for (int i = 0; i < events.Length; i++)
|
||||
{
|
||||
var e = events[i];
|
||||
@@ -230,7 +229,6 @@ namespace FlaxEditor.Windows.Profiler
|
||||
|
||||
var table = isRpc ? _tableRpc : _tableRep;
|
||||
row.Width = table.Width;
|
||||
row.BackgroundColor = rowCount[isRpc ? 0 : 1] % 2 == 1 ? rowColor2 : Color.Transparent;
|
||||
row.Parent = table;
|
||||
if (isRpc)
|
||||
rowCount.X++;
|
||||
@@ -266,6 +264,8 @@ namespace FlaxEditor.Windows.Profiler
|
||||
var textColor = style.Foreground;
|
||||
var table = new Table
|
||||
{
|
||||
RowColorEven = Color.Transparent,
|
||||
RowColorOdd = style.Background * 1.4f,
|
||||
Columns = new[]
|
||||
{
|
||||
new ColumnDefinition
|
||||
|
||||
@@ -5,6 +5,9 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using FlaxEditor.CustomEditors;
|
||||
using FlaxEditor.CustomEditors.Elements;
|
||||
using FlaxEditor.CustomEditors.GUI;
|
||||
using FlaxEditor.GUI.Input;
|
||||
using FlaxEditor.SceneGraph;
|
||||
using FlaxEditor.Viewport;
|
||||
using FlaxEngine;
|
||||
@@ -23,6 +26,8 @@ namespace FlaxEditor.Windows
|
||||
|
||||
private readonly Dictionary<Guid, float> _actorScrollValues = new Dictionary<Guid, float>();
|
||||
private bool _lockObjects = false;
|
||||
private SearchBox _searchBox;
|
||||
private Panel _scrollingPanel;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool UseLayoutData => true;
|
||||
@@ -66,18 +71,42 @@ namespace FlaxEditor.Windows
|
||||
/// </summary>
|
||||
/// <param name="editor">The editor.</param>
|
||||
public PropertiesWindow(Editor editor)
|
||||
: base(editor, true, ScrollBars.Vertical)
|
||||
: base(editor, true, ScrollBars.None)
|
||||
{
|
||||
Title = "Properties";
|
||||
Icon = editor.Icons.Build64;
|
||||
AutoFocus = true;
|
||||
|
||||
var headerPanel = new ContainerControl
|
||||
{
|
||||
AnchorPreset = AnchorPresets.HorizontalStretchTop,
|
||||
BackgroundColor = Style.Current.Background,
|
||||
IsScrollable = false,
|
||||
Offsets = new Margin(0, 0, 0, 18 + 6),
|
||||
Parent = this,
|
||||
};
|
||||
_searchBox = new SearchBox
|
||||
{
|
||||
AnchorPreset = AnchorPresets.HorizontalStretchMiddle,
|
||||
Parent = headerPanel,
|
||||
Bounds = new Rectangle(4, 4, headerPanel.Width - 8, 18),
|
||||
};
|
||||
_searchBox.TextChanged += ApplySearchFilter;
|
||||
|
||||
_scrollingPanel = new Panel(ScrollBars.Vertical)
|
||||
{
|
||||
AnchorPreset = AnchorPresets.StretchAll,
|
||||
Offsets = new Margin(0, 0, headerPanel.Bottom, 0),
|
||||
Parent = this,
|
||||
};
|
||||
|
||||
Presenter = new CustomEditorPresenter(editor.Undo, null, this);
|
||||
Presenter.Panel.Parent = this;
|
||||
Presenter.Panel.Parent = _scrollingPanel;
|
||||
Presenter.GetUndoObjects += GetUndoObjects;
|
||||
Presenter.Features |= FeatureFlags.CacheExpandedGroups;
|
||||
Presenter.AfterLayout += OnPresenterAfterLayout;
|
||||
|
||||
VScrollBar.ValueChanged += OnScrollValueChanged;
|
||||
_scrollingPanel.VScrollBar.ValueChanged += OnScrollValueChanged;
|
||||
Editor.SceneEditing.SelectionChanged += OnSelectionChanged;
|
||||
}
|
||||
|
||||
@@ -115,7 +144,8 @@ namespace FlaxEditor.Windows
|
||||
}
|
||||
}
|
||||
|
||||
_actorScrollValues[Editor.SceneEditing.Selection[0].ID] = VScrollBar.TargetValue;
|
||||
if (_scrollingPanel.VScrollBar != null)
|
||||
_actorScrollValues[Editor.SceneEditing.Selection[0].ID] = _scrollingPanel.VScrollBar.TargetValue;
|
||||
}
|
||||
|
||||
private IEnumerable<object> GetUndoObjects(CustomEditorPresenter customEditorPresenter)
|
||||
@@ -135,8 +165,18 @@ namespace FlaxEditor.Windows
|
||||
Presenter.Select(objects);
|
||||
|
||||
// Set scroll value of window if it exists
|
||||
if (Editor.SceneEditing.SelectionCount == 1)
|
||||
VScrollBar.TargetValue = _actorScrollValues.GetValueOrDefault(Editor.SceneEditing.Selection[0].ID, 0);
|
||||
if (Editor.SceneEditing.SelectionCount == 1 && _scrollingPanel.VScrollBar != null)
|
||||
_scrollingPanel.VScrollBar.TargetValue = _actorScrollValues.GetValueOrDefault(Editor.SceneEditing.Selection[0].ID, 0);
|
||||
}
|
||||
|
||||
private void OnPresenterAfterLayout(LayoutElementsContainer layout)
|
||||
{
|
||||
ApplySearchFilter();
|
||||
}
|
||||
|
||||
private void ApplySearchFilter()
|
||||
{
|
||||
Presenter.ApplySearchFilter(_searchBox.Text);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -909,7 +909,7 @@ void Foliage::RebuildClusters()
|
||||
_box = BoundingBox(_transform.Translation, _transform.Translation);
|
||||
_sphere = BoundingSphere(_transform.Translation, 0.0f);
|
||||
if (_sceneRenderingKey != -1)
|
||||
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey);
|
||||
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, ISceneRenderingListener::Bounds);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -372,7 +372,7 @@ void ParticleEffect::UpdateBounds()
|
||||
_box = bounds;
|
||||
BoundingSphere::FromBox(bounds, _sphere);
|
||||
if (_sceneRenderingKey != -1)
|
||||
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey);
|
||||
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, ISceneRenderingListener::Bounds);
|
||||
}
|
||||
|
||||
void ParticleEffect::Sync()
|
||||
|
||||
@@ -404,8 +404,17 @@ public:
|
||||
// Dirty static objects to redraw when changed (eg. material modification)
|
||||
if (a->HasStaticFlag(StaticFlags::Shadow))
|
||||
{
|
||||
DirtyStaticBounds(prevBounds);
|
||||
DirtyStaticBounds(a->GetSphere());
|
||||
// TODO: skip actors that don't cast shadows (eg. particles)
|
||||
BoundingSphere bounds = a->GetSphere();
|
||||
if (bounds != prevBounds)
|
||||
{
|
||||
// Avoid dirtying twice when bounds are close to each other
|
||||
if (BoundingSphere::NearEqual(bounds, prevBounds, METERS_TO_UNITS_SCALE))
|
||||
BoundingSphere::Merge(bounds, prevBounds, bounds);
|
||||
else
|
||||
DirtyStaticBounds(prevBounds);
|
||||
}
|
||||
DirtyStaticBounds(bounds);
|
||||
}
|
||||
else if (flags & StaticFlags)
|
||||
{
|
||||
|
||||
@@ -72,6 +72,33 @@ namespace FlaxEngine.GUI
|
||||
[EditorOrder(10), Tooltip("The text to show on a panel header.")]
|
||||
public string HeaderText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The active search text query used to highlight matching parts of the header text.
|
||||
/// </summary>
|
||||
public string SearchText = string.Empty;
|
||||
|
||||
private string _lastSearchText;
|
||||
private string _lastHeaderText;
|
||||
private int _highlightIndex = -1;
|
||||
|
||||
private void UpdateHighlights()
|
||||
{
|
||||
if (_lastSearchText == SearchText && _lastHeaderText == HeaderText)
|
||||
return;
|
||||
|
||||
_lastSearchText = SearchText;
|
||||
_lastHeaderText = HeaderText;
|
||||
|
||||
if (!string.IsNullOrEmpty(SearchText) && !string.IsNullOrEmpty(HeaderText))
|
||||
{
|
||||
_highlightIndex = HeaderText.IndexOf(SearchText, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
else
|
||||
{
|
||||
_highlightIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the height of the header.
|
||||
/// </summary>
|
||||
@@ -411,6 +438,21 @@ namespace FlaxEngine.GUI
|
||||
|
||||
Render2D.PushClip(textRect);
|
||||
Render2D.DrawText(HeaderTextFont.GetFont(), HeaderTextMaterial, HeaderText, textRect, textColor, TextAlignment.Near, TextAlignment.Center);
|
||||
UpdateHighlights();
|
||||
if (_highlightIndex >= 0)
|
||||
{
|
||||
var font = HeaderTextFont.GetFont();
|
||||
if (font != null)
|
||||
{
|
||||
var highlightColor = Style.Current.ProgressNormal * 0.6f;
|
||||
var textSize = font.MeasureText(HeaderText);
|
||||
var textY = (HeaderHeight - textSize.Y) * 0.5f;
|
||||
var start = font.GetCharPosition(HeaderText, _highlightIndex);
|
||||
var end = font.GetCharPosition(HeaderText, _highlightIndex + SearchText.Length);
|
||||
var highlightRect = new Rectangle(start.X + textRect.X, textY, end.X - start.X, textSize.Y);
|
||||
Render2D.FillRectangle(highlightRect, highlightColor);
|
||||
}
|
||||
}
|
||||
Render2D.PopClip();
|
||||
|
||||
if (!_isClosed && EnableContainmentLines)
|
||||
|
||||
@@ -86,7 +86,8 @@ public:
|
||||
StringAsUTF8(const Char* text, int32 length)
|
||||
{
|
||||
int32 lengthUtf8;
|
||||
if (length + 1 < InlinedSize)
|
||||
// UTF-8 can use up to 3 bytes per UTF-16 code unit
|
||||
if (length * 3 + 1 < InlinedSize)
|
||||
{
|
||||
StringUtils::ConvertUTF162UTF8(text, this->_inlined, length, lengthUtf8);
|
||||
this->_inlined[lengthUtf8] = 0;
|
||||
|
||||
Reference in New Issue
Block a user