Merge remote-tracking branch 'origin/master' into 1.11
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FlaxEditor.Content.Settings;
|
||||
using FlaxEngine;
|
||||
@@ -16,6 +15,11 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
{
|
||||
private int _layersCount;
|
||||
private List<CheckBox> _checkBoxes;
|
||||
private VerticalPanel _upperRightCell;
|
||||
private VerticalPanel _bottomLeftCell;
|
||||
private UniformGridPanel _grid;
|
||||
private Border _horizontalHighlight;
|
||||
private Border _verticalHighlight;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override DisplayStyle Style => DisplayStyle.InlineIntoParent;
|
||||
@@ -37,12 +41,29 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
Parent = panel,
|
||||
};
|
||||
|
||||
var style = FlaxEngine.GUI.Style.Current;
|
||||
_horizontalHighlight = new Border()
|
||||
{
|
||||
Parent = panel,
|
||||
BorderColor = style.Foreground,
|
||||
BorderWidth = 1.0f,
|
||||
Visible = false,
|
||||
};
|
||||
|
||||
_verticalHighlight = new Border()
|
||||
{
|
||||
Parent = panel,
|
||||
BorderColor = style.Foreground,
|
||||
BorderWidth = 1.0f,
|
||||
Visible = false,
|
||||
};
|
||||
|
||||
var upperLeftCell = new Label
|
||||
{
|
||||
Parent = gridPanel,
|
||||
};
|
||||
|
||||
var upperRightCell = new VerticalPanel
|
||||
_upperRightCell = new VerticalPanel
|
||||
{
|
||||
ClipChildren = false,
|
||||
Pivot = new Float2(0.00001f, 0.0f),
|
||||
@@ -54,7 +75,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
Parent = gridPanel,
|
||||
};
|
||||
|
||||
var bottomLeftCell = new VerticalPanel
|
||||
_bottomLeftCell = new VerticalPanel
|
||||
{
|
||||
Pivot = Float2.Zero,
|
||||
Spacing = 0,
|
||||
@@ -63,7 +84,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
Parent = gridPanel,
|
||||
};
|
||||
|
||||
var grid = new UniformGridPanel(0)
|
||||
_grid = new UniformGridPanel(0)
|
||||
{
|
||||
SlotsHorizontally = layersCount,
|
||||
SlotsVertically = layersCount,
|
||||
@@ -74,13 +95,13 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
int layerIndex = 0;
|
||||
for (; layerIndex < layerNames.Length; layerIndex++)
|
||||
{
|
||||
upperRightCell.AddChild(new Label
|
||||
_upperRightCell.AddChild(new Label
|
||||
{
|
||||
Height = labelsHeight,
|
||||
Text = layerNames[layerNames.Length - layerIndex - 1],
|
||||
HorizontalAlignment = TextAlignment.Near,
|
||||
});
|
||||
bottomLeftCell.AddChild(new Label
|
||||
_bottomLeftCell.AddChild(new Label
|
||||
{
|
||||
Height = labelsHeight,
|
||||
Text = layerNames[layerIndex],
|
||||
@@ -90,13 +111,13 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
for (; layerIndex < layersCount; layerIndex++)
|
||||
{
|
||||
string name = "Layer " + layerIndex;
|
||||
upperRightCell.AddChild(new Label
|
||||
_upperRightCell.AddChild(new Label
|
||||
{
|
||||
Height = labelsHeight,
|
||||
Text = name,
|
||||
HorizontalAlignment = TextAlignment.Near,
|
||||
});
|
||||
bottomLeftCell.AddChild(new Label
|
||||
_bottomLeftCell.AddChild(new Label
|
||||
{
|
||||
Height = labelsHeight,
|
||||
Text = name,
|
||||
@@ -118,7 +139,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
var box = new CheckBox(0, 0, true)
|
||||
{
|
||||
Tag = new Float2(_layersCount - column - 1, row),
|
||||
Parent = grid,
|
||||
Parent = _grid,
|
||||
Checked = GetBit(column, row),
|
||||
};
|
||||
box.StateChanged += OnCheckBoxChanged;
|
||||
@@ -126,7 +147,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
}
|
||||
for (; column < layersCount; column++)
|
||||
{
|
||||
grid.AddChild(new Label());
|
||||
_grid.AddChild(new Label());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,6 +162,18 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
/// <inheritdoc />
|
||||
public override void Refresh()
|
||||
{
|
||||
int selectedColumn = -1;
|
||||
int selectedRow = -1;
|
||||
var style = FlaxEngine.GUI.Style.Current;
|
||||
bool mouseOverGrid = _grid.IsMouseOver;
|
||||
|
||||
// Only hide highlights if mouse is not over the grid to reduce flickering
|
||||
if (!mouseOverGrid)
|
||||
{
|
||||
_horizontalHighlight.Visible = false;
|
||||
_verticalHighlight.Visible = false;
|
||||
}
|
||||
|
||||
// Sync check boxes
|
||||
for (int i = 0; i < _checkBoxes.Count; i++)
|
||||
{
|
||||
@@ -148,6 +181,39 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
int column = (int)((Float2)box.Tag).X;
|
||||
int row = (int)((Float2)box.Tag).Y;
|
||||
box.Checked = GetBit(column, row);
|
||||
|
||||
if (box.IsMouseOver)
|
||||
{
|
||||
selectedColumn = column;
|
||||
selectedRow = row;
|
||||
|
||||
_horizontalHighlight.X = _grid.X - _bottomLeftCell.Width;
|
||||
_horizontalHighlight.Y = _grid.Y + box.Y;
|
||||
_horizontalHighlight.Width = _bottomLeftCell.Width + box.Width + box.X;
|
||||
_horizontalHighlight.Height = box.Height;
|
||||
_horizontalHighlight.Visible = true;
|
||||
|
||||
_verticalHighlight.X = _grid.X + box.X;
|
||||
_verticalHighlight.Y = _grid.Y - _upperRightCell.Height;
|
||||
_verticalHighlight.Width = box.Width;
|
||||
_verticalHighlight.Height = _upperRightCell.Height + box.Height + box.Y;
|
||||
_verticalHighlight.Visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < _checkBoxes.Count; i++)
|
||||
{
|
||||
var box = _checkBoxes[i];
|
||||
int column = (int)((Float2)box.Tag).X;
|
||||
int row = (int)((Float2)box.Tag).Y;
|
||||
|
||||
if (!mouseOverGrid)
|
||||
box.ImageColor = style.BorderSelected;
|
||||
else if (selectedColumn > -1 && selectedRow > -1)
|
||||
{
|
||||
bool isRowOrColumn = column == selectedColumn || row == selectedRow;
|
||||
box.ImageColor = style.BorderSelected * (isRowOrColumn ? 1.2f : 0.75f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -670,6 +670,8 @@ namespace FlaxEditor
|
||||
{
|
||||
FlaxEngine.Networking.NetworkManager.Stop(); // Shutdown any multiplayer from playmode
|
||||
PlayModeEnding?.Invoke();
|
||||
for (int i = 0; i < _modules.Count; i++)
|
||||
_modules[i].OnPlayEnding();
|
||||
}
|
||||
|
||||
internal void OnPlayEnd()
|
||||
|
||||
@@ -299,6 +299,7 @@ namespace FlaxEditor.GUI
|
||||
{
|
||||
// Select asset
|
||||
Editor.Instance.Windows.ContentWin.Select(Validator.SelectedItem);
|
||||
Editor.Instance.Windows.ContentWin.ClearItemsSearch();
|
||||
}
|
||||
}
|
||||
else if (Button1Rect.Contains(location))
|
||||
@@ -312,6 +313,7 @@ namespace FlaxEditor.GUI
|
||||
{
|
||||
// Select asset
|
||||
Editor.Instance.Windows.ContentWin.Select(Validator.SelectedItem);
|
||||
Editor.Instance.Windows.ContentWin.ClearItemsSearch();
|
||||
}
|
||||
else if (Button3Rect.Contains(location))
|
||||
{
|
||||
|
||||
@@ -563,8 +563,17 @@ namespace FlaxEditor.GUI
|
||||
case KeyboardKeys.Escape:
|
||||
Hide();
|
||||
return true;
|
||||
case KeyboardKeys.Backspace:
|
||||
// Alow the user to quickly focus the searchbar
|
||||
if (_searchBox != null && !_searchBox.IsFocused)
|
||||
{
|
||||
_searchBox.Focus();
|
||||
_searchBox.SelectAll();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case KeyboardKeys.ArrowDown:
|
||||
{
|
||||
case KeyboardKeys.ArrowUp:
|
||||
if (RootWindow.FocusedControl == null)
|
||||
{
|
||||
// Focus search box if nothing is focused
|
||||
@@ -572,39 +581,17 @@ namespace FlaxEditor.GUI
|
||||
return true;
|
||||
}
|
||||
|
||||
// Focus the first visible item or then next one
|
||||
// Get the next item
|
||||
var items = GetVisibleItems();
|
||||
var focusedIndex = items.IndexOf(focusedItem);
|
||||
if (focusedIndex == -1)
|
||||
focusedIndex = -1;
|
||||
if (focusedIndex + 1 < items.Count)
|
||||
{
|
||||
var item = items[focusedIndex + 1];
|
||||
item.Focus();
|
||||
_scrollPanel.ScrollViewTo(item);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KeyboardKeys.ArrowUp:
|
||||
if (focusedItem != null)
|
||||
{
|
||||
// Focus the previous visible item or the search box
|
||||
var items = GetVisibleItems();
|
||||
var focusedIndex = items.IndexOf(focusedItem);
|
||||
if (focusedIndex == 0)
|
||||
{
|
||||
_searchBox?.Focus();
|
||||
}
|
||||
else if (focusedIndex > 0)
|
||||
{
|
||||
var item = items[focusedIndex - 1];
|
||||
item.Focus();
|
||||
_scrollPanel.ScrollViewTo(item);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
int delta = key == KeyboardKeys.ArrowDown ? -1 : 1;
|
||||
int nextIndex = Mathf.Wrap(focusedIndex - delta, 0, items.Count - 1);
|
||||
var nextItem = items[nextIndex];
|
||||
|
||||
// Focus the next item
|
||||
nextItem.Focus();
|
||||
_scrollPanel.ScrollViewTo(nextItem);
|
||||
return true;
|
||||
case KeyboardKeys.Return:
|
||||
if (focusedItem != null)
|
||||
{
|
||||
|
||||
@@ -266,6 +266,19 @@ namespace FlaxEditor.GUI
|
||||
return AddChild(new MainMenuButton(text));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or adds a button.
|
||||
/// </summary>
|
||||
/// <param name="text">The button text</param>
|
||||
/// <returns>The existing or created button control.</returns>
|
||||
public MainMenuButton GetOrAddButton(string text)
|
||||
{
|
||||
MainMenuButton result = GetButton(text);
|
||||
if (result == null)
|
||||
result = AddButton(text);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the button.
|
||||
/// </summary>
|
||||
|
||||
@@ -122,6 +122,14 @@ namespace FlaxEditor.GUI
|
||||
return this;
|
||||
}
|
||||
|
||||
private void OnClicked()
|
||||
{
|
||||
if (AutoCheck)
|
||||
Checked = !Checked;
|
||||
Clicked?.Invoke();
|
||||
(Parent as ToolStrip)?.OnButtonClicked(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Draw()
|
||||
{
|
||||
@@ -196,11 +204,7 @@ namespace FlaxEditor.GUI
|
||||
if (button == MouseButton.Left && _primaryMouseDown)
|
||||
{
|
||||
_primaryMouseDown = false;
|
||||
if (AutoCheck)
|
||||
Checked = !Checked;
|
||||
Clicked?.Invoke();
|
||||
(Parent as ToolStrip)?.OnButtonClicked(this);
|
||||
|
||||
OnClicked();
|
||||
return true;
|
||||
}
|
||||
if (button == MouseButton.Right && _secondaryMouseDown)
|
||||
@@ -215,6 +219,18 @@ namespace FlaxEditor.GUI
|
||||
return base.OnMouseUp(location, button);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
|
||||
{
|
||||
if (button == MouseButton.Left)
|
||||
{
|
||||
OnClicked();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnMouseLeave()
|
||||
{
|
||||
|
||||
@@ -73,6 +73,11 @@ namespace FlaxEditor.GUI.Tree
|
||||
/// </summary>
|
||||
public bool DrawRootTreeLine = true;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the deferred layout operation was performed.
|
||||
/// </summary>
|
||||
public event Action AfterDeferredLayout;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the margin for the child tree nodes.
|
||||
/// </summary>
|
||||
@@ -375,6 +380,7 @@ namespace FlaxEditor.GUI.Tree
|
||||
if (_deferLayoutUpdate)
|
||||
{
|
||||
base.PerformLayout();
|
||||
AfterDeferredLayout?.Invoke();
|
||||
_deferLayoutUpdate = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -76,6 +76,13 @@ namespace FlaxEditor.Modules
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when Editor will leave the play mode.
|
||||
/// </summary>
|
||||
public virtual void OnPlayEnding()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when Editor leaves the play mode.
|
||||
/// </summary>
|
||||
|
||||
@@ -1223,6 +1223,13 @@ namespace FlaxEditor.Modules
|
||||
Windows[i].OnPlayBegin();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnPlayEnding()
|
||||
{
|
||||
for (int i = 0; i < Windows.Count; i++)
|
||||
Windows[i].OnPlayEnding();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnPlayEnd()
|
||||
{
|
||||
|
||||
@@ -139,6 +139,10 @@ namespace FlaxEditor.Options
|
||||
[EditorDisplay("Common"), EditorOrder(240)]
|
||||
public InputBinding ToggleFullscreen = new InputBinding(KeyboardKeys.F11);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "Ctrl+BackQuote")]
|
||||
[EditorDisplay("Common"), EditorOrder(250)]
|
||||
public InputBinding FocusConsoleCommand = new InputBinding(KeyboardKeys.BackQuote, KeyboardKeys.Control);
|
||||
|
||||
#endregion
|
||||
|
||||
#region File
|
||||
@@ -647,5 +651,45 @@ namespace FlaxEditor.Options
|
||||
public InputBinding VisualScriptDebuggerWindow = new InputBinding(KeyboardKeys.None);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Node editors
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "Shift+W")]
|
||||
[EditorDisplay("Node editors"), EditorOrder(4500)]
|
||||
public InputBinding NodesAlignTop = new InputBinding(KeyboardKeys.W, KeyboardKeys.Shift);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "Shift+A")]
|
||||
[EditorDisplay("Node editors"), EditorOrder(4510)]
|
||||
public InputBinding NodesAlignLeft = new InputBinding(KeyboardKeys.A, KeyboardKeys.Shift);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "Shift+S")]
|
||||
[EditorDisplay("Node editors"), EditorOrder(4520)]
|
||||
public InputBinding NodesAlignBottom = new InputBinding(KeyboardKeys.S, KeyboardKeys.Shift);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "Shift+D")]
|
||||
[EditorDisplay("Node editors"), EditorOrder(4530)]
|
||||
public InputBinding NodesAlignRight = new InputBinding(KeyboardKeys.D, KeyboardKeys.Shift);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "Alt+Shift+W")]
|
||||
[EditorDisplay("Node editors"), EditorOrder(4540)]
|
||||
public InputBinding NodesAlignMiddle = new InputBinding(KeyboardKeys.W, KeyboardKeys.Shift, KeyboardKeys.Alt);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "Alt+Shift+S")]
|
||||
[EditorDisplay("Node editors"), EditorOrder(4550)]
|
||||
public InputBinding NodesAlignCenter = new InputBinding(KeyboardKeys.S, KeyboardKeys.Shift, KeyboardKeys.Alt);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "Q")]
|
||||
[EditorDisplay("Node editors"), EditorOrder(4560)]
|
||||
public InputBinding NodesAutoFormat = new InputBinding(KeyboardKeys.Q);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "None")]
|
||||
[EditorDisplay("Node editors"), EditorOrder(4570)]
|
||||
public InputBinding NodesDistributeHorizontal = new InputBinding(KeyboardKeys.None);
|
||||
|
||||
[DefaultValue(typeof(InputBinding), "None")]
|
||||
[EditorDisplay("Node editors"), EditorOrder(4580)]
|
||||
public InputBinding NodesDistributeVertical = new InputBinding(KeyboardKeys.None);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
43
Source/Editor/Surface/NodeAlignmentType.cs
Normal file
43
Source/Editor/Surface/NodeAlignmentType.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||
|
||||
using FlaxEngine;
|
||||
|
||||
namespace FlaxEditor.Surface
|
||||
{
|
||||
/// <summary>
|
||||
/// Node Alignment type
|
||||
/// </summary>
|
||||
[HideInEditor]
|
||||
public enum NodeAlignmentType
|
||||
{
|
||||
/// <summary>
|
||||
/// Align nodes vertically to top, matching top-most node
|
||||
/// </summary>
|
||||
Top,
|
||||
|
||||
/// <summary>
|
||||
/// Align nodes vertically to middle, using average of all nodes
|
||||
/// </summary>
|
||||
Middle,
|
||||
|
||||
/// <summary>
|
||||
/// Align nodes vertically to bottom, matching bottom-most node
|
||||
/// </summary>
|
||||
Bottom,
|
||||
|
||||
/// <summary>
|
||||
/// Align nodes horizontally to left, matching left-most node
|
||||
/// </summary>
|
||||
Left,
|
||||
|
||||
/// <summary>
|
||||
/// Align nodes horizontally to center, using average of all nodes
|
||||
/// </summary>
|
||||
Center,
|
||||
|
||||
/// <summary>
|
||||
/// Align nodes horizontally to right, matching right-most node
|
||||
/// </summary>
|
||||
Right,
|
||||
}
|
||||
}
|
||||
@@ -912,7 +912,7 @@ namespace FlaxEditor.Surface
|
||||
/// <inheritdoc />
|
||||
public override bool OnTestTooltipOverControl(ref Float2 location)
|
||||
{
|
||||
return _headerRect.Contains(ref location) && ShowTooltip;
|
||||
return _headerRect.Contains(ref location) && ShowTooltip && !Surface.IsConnecting && !Surface.IsBoxSelecting;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -1070,7 +1070,7 @@ namespace FlaxEditor.Surface
|
||||
|
||||
// Header
|
||||
var headerColor = style.BackgroundHighlighted;
|
||||
if (_headerRect.Contains(ref _mousePosition))
|
||||
if (_headerRect.Contains(ref _mousePosition) && !Surface.IsConnecting && !Surface.IsBoxSelecting)
|
||||
headerColor *= 1.07f;
|
||||
Render2D.FillRectangle(_headerRect, headerColor);
|
||||
Render2D.DrawText(style.FontLarge, Title, _headerRect, style.Foreground, TextAlignment.Center, TextAlignment.Center);
|
||||
@@ -1078,7 +1078,8 @@ namespace FlaxEditor.Surface
|
||||
// Close button
|
||||
if ((Archetype.Flags & NodeFlags.NoCloseButton) == 0 && Surface.CanEdit)
|
||||
{
|
||||
Render2D.DrawSprite(style.Cross, _closeButtonRect, _closeButtonRect.Contains(_mousePosition) ? style.Foreground : style.ForegroundGrey);
|
||||
bool highlightClose = _closeButtonRect.Contains(_mousePosition) && !Surface.IsConnecting && !Surface.IsBoxSelecting;
|
||||
Render2D.DrawSprite(style.Cross, _closeButtonRect, highlightClose ? style.Foreground : style.ForegroundGrey);
|
||||
}
|
||||
|
||||
// Footer
|
||||
@@ -1123,8 +1124,9 @@ namespace FlaxEditor.Surface
|
||||
if (base.OnMouseUp(location, button))
|
||||
return true;
|
||||
|
||||
// Close
|
||||
if (button == MouseButton.Left && (Archetype.Flags & NodeFlags.NoCloseButton) == 0 && _closeButtonRect.Contains(ref location))
|
||||
// Close/ delete
|
||||
bool canDelete = !Surface.IsConnecting && !Surface.WasBoxSelecting && !Surface.WasMovingSelection;
|
||||
if (button == MouseButton.Left && canDelete && (Archetype.Flags & NodeFlags.NoCloseButton) == 0 && _closeButtonRect.Contains(ref location))
|
||||
{
|
||||
Surface.Delete(this);
|
||||
return true;
|
||||
|
||||
@@ -191,7 +191,16 @@ namespace FlaxEditor.Surface
|
||||
|
||||
private ContextMenuButton _cmCopyButton;
|
||||
private ContextMenuButton _cmDuplicateButton;
|
||||
private ContextMenuChildMenu _cmFormatNodesMenu;
|
||||
private ContextMenuButton _cmFormatNodesConnectionButton;
|
||||
private ContextMenuButton _cmAlignNodesTopButton;
|
||||
private ContextMenuButton _cmAlignNodesMiddleButton;
|
||||
private ContextMenuButton _cmAlignNodesBottomButton;
|
||||
private ContextMenuButton _cmAlignNodesLeftButton;
|
||||
private ContextMenuButton _cmAlignNodesCenterButton;
|
||||
private ContextMenuButton _cmAlignNodesRightButton;
|
||||
private ContextMenuButton _cmDistributeNodesHorizontallyButton;
|
||||
private ContextMenuButton _cmDistributeNodesVerticallyButton;
|
||||
private ContextMenuButton _cmRemoveNodeConnectionsButton;
|
||||
private ContextMenuButton _cmRemoveBoxConnectionsButton;
|
||||
private readonly Float2 ContextMenuOffset = new Float2(5);
|
||||
@@ -399,8 +408,24 @@ namespace FlaxEditor.Surface
|
||||
}
|
||||
menu.AddSeparator();
|
||||
|
||||
_cmFormatNodesConnectionButton = menu.AddButton("Format node(s)", () => { FormatGraph(SelectedNodes); });
|
||||
_cmFormatNodesConnectionButton.Enabled = CanEdit && HasNodesSelection;
|
||||
_cmFormatNodesMenu = menu.AddChildMenu("Format node(s)");
|
||||
_cmFormatNodesMenu.Enabled = CanEdit && HasNodesSelection;
|
||||
|
||||
_cmFormatNodesConnectionButton = _cmFormatNodesMenu.ContextMenu.AddButton("Auto format", Editor.Instance.Options.Options.Input.NodesAutoFormat, () => { FormatGraph(SelectedNodes); });
|
||||
|
||||
_cmFormatNodesMenu.ContextMenu.AddSeparator();
|
||||
_cmAlignNodesTopButton = _cmFormatNodesMenu.ContextMenu.AddButton("Align top", Editor.Instance.Options.Options.Input.NodesAlignTop, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Top); });
|
||||
_cmAlignNodesMiddleButton = _cmFormatNodesMenu.ContextMenu.AddButton("Align middle", Editor.Instance.Options.Options.Input.NodesAlignMiddle, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Middle); });
|
||||
_cmAlignNodesBottomButton = _cmFormatNodesMenu.ContextMenu.AddButton("Align bottom", Editor.Instance.Options.Options.Input.NodesAlignBottom, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Bottom); });
|
||||
|
||||
_cmFormatNodesMenu.ContextMenu.AddSeparator();
|
||||
_cmAlignNodesLeftButton = _cmFormatNodesMenu.ContextMenu.AddButton("Align left", Editor.Instance.Options.Options.Input.NodesAlignLeft, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Left); });
|
||||
_cmAlignNodesCenterButton = _cmFormatNodesMenu.ContextMenu.AddButton("Align center", Editor.Instance.Options.Options.Input.NodesAlignCenter, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Center); });
|
||||
_cmAlignNodesRightButton = _cmFormatNodesMenu.ContextMenu.AddButton("Align right", Editor.Instance.Options.Options.Input.NodesAlignRight, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Right); });
|
||||
|
||||
_cmFormatNodesMenu.ContextMenu.AddSeparator();
|
||||
_cmDistributeNodesHorizontallyButton = _cmFormatNodesMenu.ContextMenu.AddButton("Distribute horizontally", Editor.Instance.Options.Options.Input.NodesDistributeHorizontal, () => { DistributeNodes(SelectedNodes, false); });
|
||||
_cmDistributeNodesVerticallyButton = _cmFormatNodesMenu.ContextMenu.AddButton("Distribute vertically", Editor.Instance.Options.Options.Input.NodesDistributeVertical, () => { DistributeNodes(SelectedNodes, true); });
|
||||
|
||||
_cmRemoveNodeConnectionsButton = menu.AddButton("Remove all connections to that node(s)", () =>
|
||||
{
|
||||
|
||||
@@ -225,7 +225,7 @@ namespace FlaxEditor.Surface
|
||||
|
||||
_rootControl.DrawComments();
|
||||
|
||||
if (IsSelecting)
|
||||
if (IsBoxSelecting)
|
||||
{
|
||||
DrawSelection();
|
||||
}
|
||||
|
||||
@@ -282,5 +282,122 @@ namespace FlaxEditor.Surface
|
||||
|
||||
return maxOffset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Align given nodes on a graph using the given alignment type.
|
||||
/// Ignores any potential overlap.
|
||||
/// </summary>
|
||||
/// <param name="nodes">List of nodes</param>
|
||||
/// <param name="alignmentType">Alignemnt type</param>
|
||||
public void AlignNodes(List<SurfaceNode> nodes, NodeAlignmentType alignmentType)
|
||||
{
|
||||
if(nodes.Count <= 1)
|
||||
return;
|
||||
|
||||
var undoActions = new List<MoveNodesAction>();
|
||||
var boundingBox = GetNodesBounds(nodes);
|
||||
for(int i = 0; i < nodes.Count; i++)
|
||||
{
|
||||
var centerY = boundingBox.Center.Y - (nodes[i].Height / 2);
|
||||
var centerX = boundingBox.Center.X - (nodes[i].Width / 2);
|
||||
|
||||
var newLocation = alignmentType switch
|
||||
{
|
||||
NodeAlignmentType.Top => new Float2(nodes[i].Location.X, boundingBox.Top),
|
||||
NodeAlignmentType.Middle => new Float2(nodes[i].Location.X, centerY),
|
||||
NodeAlignmentType.Bottom => new Float2(nodes[i].Location.X, boundingBox.Bottom - nodes[i].Height),
|
||||
|
||||
NodeAlignmentType.Left => new Float2(boundingBox.Left, nodes[i].Location.Y),
|
||||
NodeAlignmentType.Center => new Float2(centerX, nodes[i].Location.Y),
|
||||
NodeAlignmentType.Right => new Float2(boundingBox.Right - nodes[i].Width, nodes[i].Location.Y),
|
||||
|
||||
_ => throw new NotImplementedException($"Unsupported node alignment type: {alignmentType}"),
|
||||
};
|
||||
|
||||
var locationDelta = newLocation - nodes[i].Location;
|
||||
nodes[i].Location = newLocation;
|
||||
|
||||
if(Undo != null)
|
||||
undoActions.Add(new MoveNodesAction(Context, new[] { nodes[i].ID }, locationDelta));
|
||||
}
|
||||
|
||||
MarkAsEdited(false);
|
||||
Undo?.AddAction(new MultiUndoAction(undoActions, $"Align nodes ({alignmentType})"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Distribute the given nodes as equally as possible inside the bounding box, if no fit can be done it will use a default pad of 10 pixels between nodes.
|
||||
/// </summary>
|
||||
/// <param name="nodes">List of nodes</param>
|
||||
/// <param name="vertically">If false will be done horizontally, if true will be done vertically</param>
|
||||
public void DistributeNodes(List<SurfaceNode> nodes, bool vertically)
|
||||
{
|
||||
if(nodes.Count <= 1)
|
||||
return;
|
||||
|
||||
var undoActions = new List<MoveNodesAction>();
|
||||
var boundingBox = GetNodesBounds(nodes);
|
||||
float padding = 10;
|
||||
float totalSize = 0;
|
||||
for (int i = 0; i < nodes.Count; i++)
|
||||
{
|
||||
if (vertically)
|
||||
{
|
||||
totalSize += nodes[i].Height;
|
||||
}
|
||||
else
|
||||
{
|
||||
totalSize += nodes[i].Width;
|
||||
}
|
||||
}
|
||||
|
||||
if(vertically)
|
||||
{
|
||||
nodes.Sort((leftValue, rightValue) => { return leftValue.Y.CompareTo(rightValue.Y); });
|
||||
|
||||
float position = boundingBox.Top;
|
||||
if(totalSize < boundingBox.Height)
|
||||
{
|
||||
padding = (boundingBox.Height - totalSize) / nodes.Count;
|
||||
}
|
||||
|
||||
for(int i = 0; i < nodes.Count; i++)
|
||||
{
|
||||
var newLocation = new Float2(nodes[i].X, position);
|
||||
var locationDelta = newLocation - nodes[i].Location;
|
||||
nodes[i].Location = newLocation;
|
||||
|
||||
position += nodes[i].Height + padding;
|
||||
|
||||
if (Undo != null)
|
||||
undoActions.Add(new MoveNodesAction(Context, new[] { nodes[i].ID }, locationDelta));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nodes.Sort((leftValue, rightValue) => { return leftValue.X.CompareTo(rightValue.X); });
|
||||
|
||||
float position = boundingBox.Left;
|
||||
if(totalSize < boundingBox.Width)
|
||||
{
|
||||
padding = (boundingBox.Width - totalSize) / nodes.Count;
|
||||
}
|
||||
|
||||
for(int i = 0; i < nodes.Count; i++)
|
||||
{
|
||||
var newLocation = new Float2(position, nodes[i].Y);
|
||||
var locationDelta = newLocation - nodes[i].Location;
|
||||
nodes[i].Location = newLocation;
|
||||
|
||||
position += nodes[i].Width + padding;
|
||||
|
||||
if (Undo != null)
|
||||
undoActions.Add(new MoveNodesAction(Context, new[] { nodes[i].ID }, locationDelta));
|
||||
}
|
||||
}
|
||||
|
||||
MarkAsEdited(false);
|
||||
Undo?.AddAction(new MultiUndoAction(undoActions, vertically ? "Distribute nodes vertically" : "Distribute nodes horizontally"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace FlaxEditor.Surface
|
||||
private Float2 _movingNodesDelta;
|
||||
private Float2 _gridRoundingDelta;
|
||||
private HashSet<SurfaceNode> _movingNodes;
|
||||
private HashSet<SurfaceNode> _temporarySelectedNodes;
|
||||
private readonly Stack<InputBracket> _inputBrackets = new Stack<InputBracket>();
|
||||
|
||||
private class InputBracket
|
||||
@@ -130,13 +131,34 @@ namespace FlaxEditor.Surface
|
||||
if (_rootControl.Children[i] is SurfaceControl control)
|
||||
{
|
||||
var select = control.IsSelectionIntersecting(ref selectionRect);
|
||||
if (select != control.IsSelected)
|
||||
|
||||
if (Root.GetKey(KeyboardKeys.Shift))
|
||||
{
|
||||
control.IsSelected = select;
|
||||
selectionChanged = true;
|
||||
if (select == control.IsSelected && _temporarySelectedNodes.Contains(control))
|
||||
{
|
||||
control.IsSelected = !select;
|
||||
selectionChanged = true;
|
||||
}
|
||||
}
|
||||
else if (Root.GetKey(KeyboardKeys.Control))
|
||||
{
|
||||
if (select != control.IsSelected && !_temporarySelectedNodes.Contains(control))
|
||||
{
|
||||
control.IsSelected = select;
|
||||
selectionChanged = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (select != control.IsSelected)
|
||||
{
|
||||
control.IsSelected = select;
|
||||
selectionChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selectionChanged)
|
||||
SelectionChanged?.Invoke();
|
||||
}
|
||||
@@ -461,6 +483,19 @@ namespace FlaxEditor.Surface
|
||||
// Cache data
|
||||
_isMovingSelection = false;
|
||||
_mousePos = location;
|
||||
if(_temporarySelectedNodes == null)
|
||||
_temporarySelectedNodes = new HashSet<SurfaceNode>();
|
||||
else
|
||||
_temporarySelectedNodes.Clear();
|
||||
|
||||
for (int i = 0; i < _rootControl.Children.Count; i++)
|
||||
{
|
||||
if (_rootControl.Children[i] is SurfaceNode node && node.IsSelected)
|
||||
{
|
||||
_temporarySelectedNodes.Add(node);
|
||||
}
|
||||
}
|
||||
|
||||
if (button == MouseButton.Left)
|
||||
{
|
||||
_leftMouseDown = true;
|
||||
@@ -488,9 +523,11 @@ namespace FlaxEditor.Surface
|
||||
// Check if user is pressing control
|
||||
if (Root.GetKey(KeyboardKeys.Control))
|
||||
{
|
||||
// Add/remove from selection
|
||||
controlUnderMouse.IsSelected = !controlUnderMouse.IsSelected;
|
||||
SelectionChanged?.Invoke();
|
||||
AddToSelection(controlUnderMouse);
|
||||
}
|
||||
else if (Root.GetKey(KeyboardKeys.Shift))
|
||||
{
|
||||
RemoveFromSelection(controlUnderMouse);
|
||||
}
|
||||
// Check if node isn't selected
|
||||
else if (!controlUnderMouse.IsSelected)
|
||||
@@ -500,10 +537,14 @@ namespace FlaxEditor.Surface
|
||||
}
|
||||
|
||||
// Start moving selected nodes
|
||||
StartMouseCapture();
|
||||
_movingSelectionViewPos = _rootControl.Location;
|
||||
_movingNodesDelta = Float2.Zero;
|
||||
OnGetNodesToMove();
|
||||
if (!Root.GetKey(KeyboardKeys.Shift))
|
||||
{
|
||||
StartMouseCapture();
|
||||
_movingSelectionViewPos = _rootControl.Location;
|
||||
_movingNodesDelta = Float2.Zero;
|
||||
OnGetNodesToMove();
|
||||
}
|
||||
|
||||
Focus();
|
||||
return true;
|
||||
}
|
||||
@@ -515,7 +556,12 @@ namespace FlaxEditor.Surface
|
||||
{
|
||||
// Start selecting or commenting
|
||||
StartMouseCapture();
|
||||
ClearSelection();
|
||||
|
||||
if (!Root.GetKey(KeyboardKeys.Control) && !Root.GetKey(KeyboardKeys.Shift))
|
||||
{
|
||||
ClearSelection();
|
||||
}
|
||||
|
||||
Focus();
|
||||
return true;
|
||||
}
|
||||
@@ -544,6 +590,9 @@ namespace FlaxEditor.Surface
|
||||
// Cache flags and state
|
||||
if (_leftMouseDown && button == MouseButton.Left)
|
||||
{
|
||||
WasBoxSelecting = IsBoxSelecting;
|
||||
WasMovingSelection = _isMovingSelection;
|
||||
|
||||
_leftMouseDown = false;
|
||||
EndMouseCapture();
|
||||
Cursor = CursorType.Default;
|
||||
|
||||
@@ -232,15 +232,25 @@ namespace FlaxEditor.Surface
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether user is selecting nodes.
|
||||
/// Gets a value indicating whether user is box selecting nodes.
|
||||
/// </summary>
|
||||
public bool IsSelecting => _leftMouseDown && !_isMovingSelection && _connectionInstigator == null;
|
||||
public bool IsBoxSelecting => _leftMouseDown && !_isMovingSelection && _connectionInstigator == null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether user was previously box selecting nodes.
|
||||
/// </summary>
|
||||
public bool WasBoxSelecting { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether user is moving selected nodes.
|
||||
/// </summary>
|
||||
public bool IsMovingSelection => _leftMouseDown && _isMovingSelection && _connectionInstigator == null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether user was previously moving selected nodes.
|
||||
/// </summary>
|
||||
public bool WasMovingSelection { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether user is connecting nodes.
|
||||
/// </summary>
|
||||
@@ -405,6 +415,15 @@ namespace FlaxEditor.Surface
|
||||
new InputActionsContainer.Binding(options => options.Paste, Paste),
|
||||
new InputActionsContainer.Binding(options => options.Cut, Cut),
|
||||
new InputActionsContainer.Binding(options => options.Duplicate, Duplicate),
|
||||
new InputActionsContainer.Binding(options => options.NodesAutoFormat, () => { FormatGraph(SelectedNodes); }),
|
||||
new InputActionsContainer.Binding(options => options.NodesAlignTop, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Top); }),
|
||||
new InputActionsContainer.Binding(options => options.NodesAlignMiddle, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Middle); }),
|
||||
new InputActionsContainer.Binding(options => options.NodesAlignBottom, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Bottom); }),
|
||||
new InputActionsContainer.Binding(options => options.NodesAlignLeft, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Left); }),
|
||||
new InputActionsContainer.Binding(options => options.NodesAlignCenter, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Center); }),
|
||||
new InputActionsContainer.Binding(options => options.NodesAlignRight, () => { AlignNodes(SelectedNodes, NodeAlignmentType.Right); }),
|
||||
new InputActionsContainer.Binding(options => options.NodesDistributeHorizontal, () => { DistributeNodes(SelectedNodes, false); }),
|
||||
new InputActionsContainer.Binding(options => options.NodesDistributeVertical, () => { DistributeNodes(SelectedNodes, true); }),
|
||||
});
|
||||
|
||||
Context.ControlSpawned += OnSurfaceControlSpawned;
|
||||
@@ -710,6 +729,18 @@ namespace FlaxEditor.Surface
|
||||
SelectionChanged?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the specified control from the selection.
|
||||
/// </summary>
|
||||
/// <param name="control">The control.</param>
|
||||
public void RemoveFromSelection(SurfaceControl control)
|
||||
{
|
||||
if (!control.IsSelected)
|
||||
return;
|
||||
control.IsSelected = false;
|
||||
SelectionChanged?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selects the specified control.
|
||||
/// </summary>
|
||||
|
||||
@@ -1518,6 +1518,7 @@ namespace FlaxEditor.Utilities
|
||||
inputActions.Add(options => options.OpenScriptsProject, () => Editor.Instance.CodeEditing.OpenSolution());
|
||||
inputActions.Add(options => options.GenerateScriptsProject, () => Editor.Instance.ProgressReporting.GenerateScriptsProjectFiles.RunAsync());
|
||||
inputActions.Add(options => options.RecompileScripts, ScriptsBuilder.Compile);
|
||||
inputActions.Add(options => options.FocusConsoleCommand, () => Editor.Instance.Windows.OutputLogWin.FocusCommand());
|
||||
}
|
||||
|
||||
internal static string ToPathProject(string path)
|
||||
|
||||
@@ -236,6 +236,7 @@ namespace FlaxEditor.Windows.Assets
|
||||
var group = layout.Group("General");
|
||||
|
||||
var minScreenSize = group.FloatValue("Min Screen Size", "The minimum screen size to draw model (the bottom limit). Used to cull small models. Set to 0 to disable this feature.");
|
||||
minScreenSize.ValueBox.SlideSpeed = 0.005f;
|
||||
minScreenSize.ValueBox.MinValue = 0.0f;
|
||||
minScreenSize.ValueBox.MaxValue = 1.0f;
|
||||
minScreenSize.ValueBox.Value = proxy.Asset.MinScreenSize;
|
||||
@@ -476,12 +477,12 @@ namespace FlaxEditor.Windows.Assets
|
||||
}
|
||||
}
|
||||
|
||||
[EditorOrder(1), EditorDisplay(null, "LOD"), Limit(0, Model.MaxLODs), VisibleIf("ShowUVs")]
|
||||
[Tooltip("Level Of Detail index to preview UVs layout.")]
|
||||
[EditorOrder(1), EditorDisplay(null, "LOD"), Limit(0, Model.MaxLODs, 0.01f), VisibleIf("ShowUVs")]
|
||||
[Tooltip("Level Of Detail index to preview UVs layout at.")]
|
||||
public int LOD = 0;
|
||||
|
||||
[EditorOrder(2), EditorDisplay(null, "Mesh"), Limit(-1, 1000000), VisibleIf("ShowUVs")]
|
||||
[Tooltip("Mesh index to preview UVs layout. Use -1 for all meshes")]
|
||||
[EditorOrder(2), EditorDisplay(null, "Mesh"), Limit(-1, 1000000, 0.01f), VisibleIf("ShowUVs")]
|
||||
[Tooltip("Mesh index to show UVs layout for. Use -1 to display all UVs of all meshes")]
|
||||
public int Mesh = -1;
|
||||
|
||||
private bool ShowUVs => _uvChannel != UVChannel.None;
|
||||
|
||||
@@ -81,6 +81,7 @@ namespace FlaxEditor.Windows.Assets
|
||||
}
|
||||
|
||||
var resolution = group.FloatValue("Resolution Scale", Window.Editor.CodeDocs.GetTooltip(typeof(ModelTool.Options), nameof(ModelImportSettings.Settings.SDFResolution)));
|
||||
resolution.ValueBox.SlideSpeed = 0.001f;
|
||||
resolution.ValueBox.MinValue = 0.0001f;
|
||||
resolution.ValueBox.MaxValue = 100.0f;
|
||||
resolution.ValueBox.Value = sdf.Texture != null ? sdf.ResolutionScale : 1.0f;
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FlaxEditor.Content;
|
||||
using FlaxEditor.CustomEditors;
|
||||
using FlaxEditor.GUI;
|
||||
using FlaxEditor.Scripting;
|
||||
using FlaxEditor.Surface;
|
||||
using FlaxEditor.Viewport.Previews;
|
||||
@@ -114,6 +115,7 @@ namespace FlaxEditor.Windows.Assets
|
||||
|
||||
private readonly PropertiesProxy _properties;
|
||||
private Tab _previewTab;
|
||||
private ToolStripButton _showSourceCodeButton;
|
||||
|
||||
/// <inheritdoc />
|
||||
public ParticleEmitterWindow(Editor editor, AssetItem item)
|
||||
@@ -146,7 +148,8 @@ namespace FlaxEditor.Windows.Assets
|
||||
|
||||
// Toolstrip
|
||||
SurfaceUtils.PerformCommonSetup(this, _toolstrip, _surface, out _saveButton, out _undoButton, out _redoButton);
|
||||
_toolstrip.AddButton(editor.Icons.Code64, ShowSourceCode).LinkTooltip("Show generated shader source code");
|
||||
_showSourceCodeButton = _toolstrip.AddButton(editor.Icons.Code64, ShowSourceCode);
|
||||
_showSourceCodeButton.LinkTooltip("Show generated shader source code");
|
||||
_toolstrip.AddSeparator();
|
||||
_toolstrip.AddButton(editor.Icons.Docs64, () => Platform.OpenUrl(Utilities.Constants.DocsUrl + "manual/particles/index.html")).LinkTooltip("See documentation to learn more");
|
||||
}
|
||||
@@ -285,5 +288,15 @@ namespace FlaxEditor.Windows.Assets
|
||||
|
||||
/// <inheritdoc />
|
||||
public SearchAssetTypes AssetType => SearchAssetTypes.ParticleEmitter;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
base.Update(deltaTime);
|
||||
|
||||
if (_asset == null)
|
||||
return;
|
||||
_showSourceCodeButton.Enabled = _asset.HasShaderCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,10 +97,7 @@ namespace FlaxEditor.Windows.Assets
|
||||
|
||||
// For single node selected scroll view so user can see it
|
||||
if (nodes.Count == 1)
|
||||
{
|
||||
nodes[0].ExpandAllParents(true);
|
||||
ScrollViewTo(nodes[0]);
|
||||
}
|
||||
ScrollToSelectedNode();
|
||||
}
|
||||
|
||||
// Update properties editor
|
||||
|
||||
@@ -318,7 +318,7 @@ namespace FlaxEditor.Windows
|
||||
private Color _colorWarning;
|
||||
private Color _colorError;
|
||||
private bool _colorDebugLogText;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DebugLogWindow"/> class.
|
||||
/// </summary>
|
||||
@@ -352,24 +352,12 @@ namespace FlaxEditor.Windows
|
||||
editor.Options.Apply(editor.Options.Options);
|
||||
}).SetAutoCheck(true).LinkTooltip("Performs auto pause on error");
|
||||
toolstrip.AddSeparator();
|
||||
_groupButtons[0] = (ToolStripButton)toolstrip.AddButton(editor.Icons.Error32, () =>
|
||||
{
|
||||
UpdateLogTypeVisibility(LogGroup.Error, _groupButtons[0].Checked);
|
||||
editor.Options.Options.Interface.DebugLogShowErrorMessages = _groupButtons[0].Checked;
|
||||
editor.Options.Apply(editor.Options.Options);
|
||||
}).SetAutoCheck(true).LinkTooltip("Shows/hides error messages");
|
||||
_groupButtons[1] = (ToolStripButton)toolstrip.AddButton(editor.Icons.Warning32, () =>
|
||||
{
|
||||
UpdateLogTypeVisibility(LogGroup.Warning, _groupButtons[1].Checked);
|
||||
editor.Options.Options.Interface.DebugLogShowWarningMessages = _groupButtons[1].Checked;
|
||||
editor.Options.Apply(editor.Options.Options);
|
||||
}).SetAutoCheck(true).LinkTooltip("Shows/hides warning messages");
|
||||
_groupButtons[2] = (ToolStripButton)toolstrip.AddButton(editor.Icons.Info32, () =>
|
||||
{
|
||||
UpdateLogTypeVisibility(LogGroup.Info, _groupButtons[2].Checked);
|
||||
editor.Options.Options.Interface.DebugLogShowInfoMessages = _groupButtons[2].Checked;
|
||||
editor.Options.Apply(editor.Options.Options);
|
||||
}).SetAutoCheck(true).LinkTooltip("Shows/hides info messages");
|
||||
_groupButtons[0] = (ToolStripButton)toolstrip.AddButton(editor.Icons.Error32, () => { OnGroupButtonPressed(0); })
|
||||
.SetAutoCheck(true).LinkTooltip("Shows/hides error messages");
|
||||
_groupButtons[1] = (ToolStripButton)toolstrip.AddButton(editor.Icons.Warning32, () => { OnGroupButtonPressed(1); })
|
||||
.SetAutoCheck(true).LinkTooltip("Shows/hides warning messages");
|
||||
_groupButtons[2] = (ToolStripButton)toolstrip.AddButton(editor.Icons.Info32, () => { OnGroupButtonPressed(2); })
|
||||
.SetAutoCheck(true).LinkTooltip("Shows/hides info messages");
|
||||
UpdateCount();
|
||||
|
||||
// Split panel
|
||||
@@ -418,6 +406,27 @@ namespace FlaxEditor.Windows
|
||||
OnEditorOptionsChanged(Editor.Options.Options);
|
||||
}
|
||||
|
||||
private void OnGroupButtonPressed(int index)
|
||||
{
|
||||
UpdateLogTypeVisibility((LogGroup)index, _groupButtons[index].Checked);
|
||||
if (Input.GetKey(KeyboardKeys.Shift))
|
||||
{
|
||||
for (int i = 0; i < (int)LogGroup.Max; i++)
|
||||
{
|
||||
if (i == index)
|
||||
continue;
|
||||
_groupButtons[i].Checked = !_groupButtons[index].Checked;
|
||||
UpdateLogTypeVisibility((LogGroup)i, _groupButtons[i].Checked);
|
||||
}
|
||||
}
|
||||
|
||||
var options = Editor.Options.Options.Interface;
|
||||
options.DebugLogShowErrorMessages = _groupButtons[0].Checked;
|
||||
options.DebugLogShowWarningMessages = _groupButtons[1].Checked;
|
||||
options.DebugLogShowInfoMessages = _groupButtons[2].Checked;
|
||||
Editor.Options.Apply(Editor.Options.Options);
|
||||
}
|
||||
|
||||
private void OnEditorOptionsChanged(EditorOptions options)
|
||||
{
|
||||
_timestampsFormats = options.Interface.DebugLogTimestampsFormat;
|
||||
@@ -455,15 +464,9 @@ namespace FlaxEditor.Windows
|
||||
// Create new entry
|
||||
switch (_timestampsFormats)
|
||||
{
|
||||
case InterfaceOptions.TimestampsFormats.Utc:
|
||||
desc.Title = $"[{DateTime.UtcNow}] {desc.Title}";
|
||||
break;
|
||||
case InterfaceOptions.TimestampsFormats.LocalTime:
|
||||
desc.Title = $"[{DateTime.Now}] {desc.Title}";
|
||||
break;
|
||||
case InterfaceOptions.TimestampsFormats.TimeSinceStartup:
|
||||
desc.Title = string.Format("[{0:g}] ", TimeSpan.FromSeconds(Time.TimeSinceStartup)) + desc.Title;
|
||||
break;
|
||||
case InterfaceOptions.TimestampsFormats.Utc: desc.Title = $"[{DateTime.UtcNow}] {desc.Title}"; break;
|
||||
case InterfaceOptions.TimestampsFormats.LocalTime: desc.Title = $"[{DateTime.Now}] {desc.Title}"; break;
|
||||
case InterfaceOptions.TimestampsFormats.TimeSinceStartup: desc.Title = string.Format("[{0:g}] ", TimeSpan.FromSeconds(Time.TimeSinceStartup)) + desc.Title; break;
|
||||
}
|
||||
var newEntry = new LogEntry(this, ref desc);
|
||||
|
||||
|
||||
@@ -219,6 +219,13 @@ namespace FlaxEditor.Windows
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when Editor will leave the play mode.
|
||||
/// </summary>
|
||||
public virtual void OnPlayEnding()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when Editor leaves the play mode.
|
||||
/// </summary>
|
||||
|
||||
@@ -405,6 +405,7 @@ namespace FlaxEditor.Windows
|
||||
return;
|
||||
Editor.Instance.SceneEditing.Delete();
|
||||
});
|
||||
InputActions.Add(options => options.FocusConsoleCommand, () => Editor.Instance.Windows.OutputLogWin.FocusCommand());
|
||||
}
|
||||
|
||||
private void ChangeViewportRatio(ViewportScaleOptions v)
|
||||
|
||||
@@ -830,6 +830,15 @@ namespace FlaxEditor.Windows
|
||||
OnOutputTextChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Focus the debug command line and ensure that the output log window is visible.
|
||||
/// </summary>
|
||||
public void FocusCommand()
|
||||
{
|
||||
FocusOrShow();
|
||||
_commandLineBox.Focus();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
|
||||
@@ -34,6 +34,7 @@ namespace FlaxEditor.Windows
|
||||
private DragScriptItems _dragScriptItems;
|
||||
private DragHandlers _dragHandlers;
|
||||
private bool _isDropping = false;
|
||||
private bool _forceScrollNodeToView = false;
|
||||
|
||||
/// <summary>
|
||||
/// Scene tree panel.
|
||||
@@ -91,6 +92,15 @@ namespace FlaxEditor.Windows
|
||||
_tree.SelectedChanged += Tree_OnSelectedChanged;
|
||||
_tree.RightClick += OnTreeRightClick;
|
||||
_tree.Parent = _sceneTreePanel;
|
||||
_tree.AfterDeferredLayout += () =>
|
||||
{
|
||||
if (_forceScrollNodeToView)
|
||||
{
|
||||
_forceScrollNodeToView = false;
|
||||
ScrollToSelectedNode();
|
||||
}
|
||||
};
|
||||
|
||||
headerPanel.Parent = this;
|
||||
|
||||
// Setup input actions
|
||||
@@ -142,6 +152,16 @@ namespace FlaxEditor.Windows
|
||||
root.TreeNode.UpdateFilter(query);
|
||||
|
||||
_tree.UnlockChildrenRecursive();
|
||||
|
||||
// When keep the selected nodes in a view
|
||||
var nodeSelection = _tree.Selection;
|
||||
if (nodeSelection.Count != 0)
|
||||
{
|
||||
var node = nodeSelection[nodeSelection.Count - 1];
|
||||
node.Expand(true);
|
||||
_forceScrollNodeToView = true;
|
||||
}
|
||||
|
||||
PerformLayout();
|
||||
PerformLayout();
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace FlaxEditor.Windows.Search
|
||||
if (value == _selectedItem || (value != null && !_matchedItems.Contains(value)))
|
||||
return;
|
||||
|
||||
// Restore the previous selected item to the non-selected color
|
||||
if (_selectedItem != null)
|
||||
{
|
||||
_selectedItem.BackgroundColor = Color.Transparent;
|
||||
@@ -54,6 +55,7 @@ namespace FlaxEditor.Windows.Search
|
||||
_selectedItem.BackgroundColor = Style.Current.BackgroundSelected;
|
||||
if (_matchedItems.Count > VisibleItemCount)
|
||||
{
|
||||
_selectedItem.Focus();
|
||||
_resultPanel.ScrollViewTo(_selectedItem, true);
|
||||
}
|
||||
}
|
||||
@@ -180,39 +182,17 @@ namespace FlaxEditor.Windows.Search
|
||||
switch (key)
|
||||
{
|
||||
case KeyboardKeys.ArrowDown:
|
||||
{
|
||||
if (_matchedItems.Count == 0)
|
||||
return true;
|
||||
int currentPos;
|
||||
if (_selectedItem != null)
|
||||
{
|
||||
currentPos = _matchedItems.IndexOf(_selectedItem) + 1;
|
||||
if (currentPos >= _matchedItems.Count)
|
||||
currentPos--;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentPos = 0;
|
||||
}
|
||||
SelectedItem = _matchedItems[currentPos];
|
||||
return true;
|
||||
}
|
||||
case KeyboardKeys.ArrowUp:
|
||||
{
|
||||
if (_matchedItems.Count == 0)
|
||||
return true;
|
||||
int currentPos;
|
||||
if (_selectedItem != null)
|
||||
{
|
||||
currentPos = _matchedItems.IndexOf(_selectedItem) - 1;
|
||||
if (currentPos < 0)
|
||||
currentPos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentPos = 0;
|
||||
}
|
||||
SelectedItem = _matchedItems[currentPos];
|
||||
|
||||
var focusedIndex = _matchedItems.IndexOf(_selectedItem);
|
||||
int delta = key == KeyboardKeys.ArrowDown ? -1 : 1;
|
||||
int nextIndex = Mathf.Wrap(focusedIndex - delta, 0, _matchedItems.Count - 1);
|
||||
var nextItem = _matchedItems[nextIndex];
|
||||
|
||||
SelectedItem = nextItem;
|
||||
return true;
|
||||
}
|
||||
case KeyboardKeys.Return:
|
||||
@@ -234,6 +214,17 @@ namespace FlaxEditor.Windows.Search
|
||||
Hide();
|
||||
return true;
|
||||
}
|
||||
case KeyboardKeys.Backspace:
|
||||
{
|
||||
// Alow the user to quickly focus the searchbar
|
||||
if (_searchBox != null && !_searchBox.IsFocused)
|
||||
{
|
||||
_searchBox.Focus();
|
||||
_searchBox.SelectAll();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return base.OnKeyDown(key);
|
||||
|
||||
Reference in New Issue
Block a user