Merge remote-tracking branch 'origin/master' into 1.7

This commit is contained in:
Wojtek Figat
2023-09-27 17:32:47 +02:00
40 changed files with 710 additions and 164 deletions

View File

@@ -25,9 +25,20 @@ namespace FlaxEditor.CustomEditors.Dedicated
get
{
// All selected particle effects use the same system
var effect = (ParticleEffect)Values[0];
var system = effect.ParticleSystem;
return system != null && Values.TrueForAll(x => (x as ParticleEffect)?.ParticleSystem == system);
var effect = Values[0] as ParticleEffect;
var system = effect ? effect.ParticleSystem : null;
if (system && Values.TrueForAll(x => x is ParticleEffect fx && fx && fx.ParticleSystem == system))
{
// All parameters can be accessed
var parameters = effect.Parameters;
foreach (var parameter in parameters)
{
if (!parameter)
return false;
}
return true;
}
return false;
}
}

View File

@@ -1,8 +1,10 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System.Collections.Generic;
using FlaxEditor.CustomEditors.GUI;
using FlaxEditor.GUI;
using FlaxEditor.GUI.ContextMenu;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEditor.CustomEditors.Editors
{
@@ -12,7 +14,7 @@ namespace FlaxEditor.CustomEditors.Editors
[CustomEditor(typeof(InputEvent)), DefaultEditor]
public class InputEventEditor : CustomEditor
{
private Dropdown _dropdown;
private ComboBox _comboBox;
/// <inheritdoc />
public override DisplayStyle Style => DisplayStyle.Inline;
@@ -20,23 +22,30 @@ namespace FlaxEditor.CustomEditors.Editors
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
var dropdownElement = layout.Custom<Dropdown>();
_dropdown = dropdownElement.CustomControl;
var names = new List<LocalizedString>();
LinkedLabel.SetupContextMenu += OnSetupContextMenu;
var comboBoxElement = layout.ComboBox();
_comboBox = comboBoxElement.ComboBox;
var names = new List<string>();
foreach (var mapping in Input.ActionMappings)
{
if (!names.Contains(mapping.Name))
names.Add(mapping.Name);
}
_dropdown.Items = names;
_comboBox.Items = names;
if (Values[0] is InputEvent inputEvent && names.Contains(inputEvent.Name))
_dropdown.SelectedItem = inputEvent.Name;
_dropdown.SelectedIndexChanged += OnSelectedIndexChanged;
_comboBox.SelectedItem = inputEvent.Name;
_comboBox.SelectedIndexChanged += OnSelectedIndexChanged;
}
private void OnSelectedIndexChanged(Dropdown dropdown)
private void OnSetupContextMenu(PropertyNameLabel label, ContextMenu menu, CustomEditor linkededitor)
{
SetValue(new InputEvent(dropdown.SelectedItem));
var button = menu.AddButton("Set to null");
button.Clicked += () => _comboBox.SelectedItem = null;
}
private void OnSelectedIndexChanged(ComboBox comboBox)
{
SetValue(comboBox.SelectedItem == null ? null : new InputEvent(comboBox.SelectedItem));
}
/// <inheritdoc />
@@ -49,17 +58,21 @@ namespace FlaxEditor.CustomEditors.Editors
}
else
{
if (Values[0] is InputEvent inputEvent && _dropdown.Items.Contains(inputEvent.Name))
_dropdown.SelectedItem = inputEvent.Name;
if (Values[0] is InputEvent inputEvent && _comboBox.Items.Contains(inputEvent.Name))
_comboBox.SelectedItem = inputEvent.Name;
else
_comboBox.SelectedItem = null;
}
}
/// <inheritdoc />
protected override void Deinitialize()
{
if (_dropdown != null)
_dropdown.SelectedIndexChanged -= OnSelectedIndexChanged;
_dropdown = null;
if (LinkedLabel != null)
LinkedLabel.SetupContextMenu -= OnSetupContextMenu;
if (_comboBox != null)
_comboBox.SelectedIndexChanged -= OnSelectedIndexChanged;
_comboBox = null;
}
}
@@ -69,7 +82,7 @@ namespace FlaxEditor.CustomEditors.Editors
[CustomEditor(typeof(InputAxis)), DefaultEditor]
public class InputAxisEditor : CustomEditor
{
private Dropdown _dropdown;
private ComboBox _comboBox;
/// <inheritdoc />
public override DisplayStyle Style => DisplayStyle.Inline;
@@ -77,23 +90,30 @@ namespace FlaxEditor.CustomEditors.Editors
/// <inheritdoc />
public override void Initialize(LayoutElementsContainer layout)
{
var dropdownElement = layout.Custom<Dropdown>();
_dropdown = dropdownElement.CustomControl;
var names = new List<LocalizedString>();
LinkedLabel.SetupContextMenu += OnSetupContextMenu;
var comboBoxElement = layout.ComboBox();
_comboBox = comboBoxElement.ComboBox;
var names = new List<string>();
foreach (var mapping in Input.AxisMappings)
{
if (!names.Contains(mapping.Name))
names.Add(mapping.Name);
}
_dropdown.Items = names;
_comboBox.Items = names;
if (Values[0] is InputAxis inputAxis && names.Contains(inputAxis.Name))
_dropdown.SelectedItem = inputAxis.Name;
_dropdown.SelectedIndexChanged += OnSelectedIndexChanged;
_comboBox.SelectedItem = inputAxis.Name;
_comboBox.SelectedIndexChanged += OnSelectedIndexChanged;
}
private void OnSelectedIndexChanged(Dropdown dropdown)
private void OnSetupContextMenu(PropertyNameLabel label, ContextMenu menu, CustomEditor linkededitor)
{
SetValue(new InputAxis(dropdown.SelectedItem));
var button = menu.AddButton("Set to null");
button.Clicked += () => _comboBox.SelectedItem = null;
}
private void OnSelectedIndexChanged(ComboBox comboBox)
{
SetValue(comboBox.SelectedItem == null ? null : new InputAxis(comboBox.SelectedItem));
}
/// <inheritdoc />
@@ -106,17 +126,21 @@ namespace FlaxEditor.CustomEditors.Editors
}
else
{
if (Values[0] is InputAxis inputAxis && _dropdown.Items.Contains(inputAxis.Name))
_dropdown.SelectedItem = inputAxis.Name;
if (Values[0] is InputAxis inputAxis && _comboBox.Items.Contains(inputAxis.Name))
_comboBox.SelectedItem = inputAxis.Name;
else
_comboBox.SelectedItem = null;
}
}
/// <inheritdoc />
protected override void Deinitialize()
{
if (_dropdown != null)
_dropdown.SelectedIndexChanged -= OnSelectedIndexChanged;
_dropdown = null;
if (LinkedLabel != null)
LinkedLabel.SetupContextMenu -= OnSetupContextMenu;
if (_comboBox != null)
_comboBox.SelectedIndexChanged -= OnSelectedIndexChanged;
_comboBox = null;
}
}
}

View File

@@ -674,9 +674,9 @@ namespace FlaxEditor.CustomEditors.Editors
}
set
{
if (Values[0] is Tag[])
if (Values[0] is Tag[] || Values.Type.Type == typeof(Tag[]))
SetValue(value);
if (Values[0] is List<Tag>)
else if (Values[0] is List<Tag> || Values.Type.Type == typeof(List<Tag>))
SetValue(new List<Tag>(value));
}
}

View File

@@ -290,7 +290,11 @@ namespace FlaxEditor.GUI.Dialogs
OnCancel();
return true;
case KeyboardKeys.Tab:
Root?.Navigate(NavDirection.Next);
if (Root != null)
{
bool shiftDown = Root.GetKey(KeyboardKeys.Shift);
Root.Navigate(shiftDown ? NavDirection.Previous : NavDirection.Next);
}
return true;
}
return false;

View File

@@ -221,6 +221,23 @@ namespace FlaxEditor.Surface
return;
}
if (_middleMouseDown)
{
// Calculate delta
var delta = location - _middleMouseDownPos;
if (delta.LengthSquared > 0.01f)
{
// Move view
_mouseMoveAmount += delta.Length;
_rootControl.Location += delta;
_middleMouseDownPos = location;
Cursor = CursorType.SizeAll;
}
// Handled
return;
}
// Check if user is selecting or moving node(s)
if (_leftMouseDown)
{
@@ -280,6 +297,11 @@ namespace FlaxEditor.Surface
_rightMouseDown = false;
Cursor = CursorType.Default;
}
if (_middleMouseDown)
{
_middleMouseDown = false;
Cursor = CursorType.Default;
}
_isMovingSelection = false;
ConnectingEnd(null);
@@ -391,6 +413,7 @@ namespace FlaxEditor.Surface
_isMovingSelection = false;
_rightMouseDown = false;
_leftMouseDown = false;
_middleMouseDown = false;
return true;
}
@@ -410,6 +433,11 @@ namespace FlaxEditor.Surface
_rightMouseDown = true;
_rightMouseDownPos = location;
}
if (button == MouseButton.Middle)
{
_middleMouseDown = true;
_middleMouseDownPos = location;
}
// Check if any node is under the mouse
SurfaceControl controlUnderMouse = GetControlUnderMouse();
@@ -455,7 +483,7 @@ namespace FlaxEditor.Surface
Focus();
return true;
}
if (_rightMouseDown)
if (_rightMouseDown || _middleMouseDown)
{
// Start navigating
StartMouseCapture();
@@ -524,6 +552,13 @@ namespace FlaxEditor.Surface
}
_mouseMoveAmount = 0;
}
if (_middleMouseDown && button == MouseButton.Middle)
{
_middleMouseDown = false;
EndMouseCapture();
Cursor = CursorType.Default;
_mouseMoveAmount = 0;
}
// Base
bool handled = base.OnMouseUp(location, button);
@@ -534,6 +569,7 @@ namespace FlaxEditor.Surface
// Clear flags
_rightMouseDown = false;
_leftMouseDown = false;
_middleMouseDown = false;
return true;
}

View File

@@ -60,6 +60,11 @@ namespace FlaxEditor.Surface
/// </summary>
protected bool _rightMouseDown;
/// <summary>
/// The middle mouse down flag.
/// </summary>
protected bool _middleMouseDown;
/// <summary>
/// The left mouse down position.
/// </summary>
@@ -70,6 +75,11 @@ namespace FlaxEditor.Surface
/// </summary>
protected Float2 _rightMouseDownPos = Float2.Minimum;
/// <summary>
/// The middle mouse down position.
/// </summary>
protected Float2 _middleMouseDownPos = Float2.Minimum;
/// <summary>
/// The mouse position.
/// </summary>

View File

@@ -46,7 +46,7 @@ namespace FlaxEditor.Windows
private TextBox _itemsSearchBox;
private ViewDropdown _viewDropdown;
private SortType _sortType;
private bool _showEngineFiles = true, _showPluginsFiles = true, _showAllFiles = true;
private bool _showEngineFiles = true, _showPluginsFiles = true, _showAllFiles = true, _showGeneratedFiles = false;
private RootContentTreeNode _root;
@@ -106,6 +106,19 @@ namespace FlaxEditor.Windows
}
}
internal bool ShowGeneratedFiles
{
get => _showGeneratedFiles;
set
{
if (_showGeneratedFiles != value)
{
_showGeneratedFiles = value;
RefreshView();
}
}
}
internal bool ShowAllFiles
{
get => _showAllFiles;
@@ -314,6 +327,12 @@ namespace FlaxEditor.Windows
b.Checked = ShowPluginsFiles;
b.CloseMenuOnClick = false;
b.AutoCheck = true;
b = show.ContextMenu.AddButton("Generated files", () => ShowGeneratedFiles = !ShowGeneratedFiles);
b.TooltipText = "Shows generated files";
b.Checked = ShowGeneratedFiles;
b.CloseMenuOnClick = false;
b.AutoCheck = true;
b = show.ContextMenu.AddButton("All files", () => ShowAllFiles = !ShowAllFiles);
b.TooltipText = "Shows all files including other than assets and source code";
@@ -973,6 +992,8 @@ namespace FlaxEditor.Windows
var items = target.Folder.Children;
if (!_showAllFiles)
items = items.Where(x => !(x is FileItem)).ToList();
if (!_showGeneratedFiles)
items = items.Where(x => !(x.Path.EndsWith(".Gen.cs", StringComparison.Ordinal) || x.Path.EndsWith(".Gen.h", StringComparison.Ordinal) || x.Path.EndsWith(".Gen.cpp", StringComparison.Ordinal) || x.Path.EndsWith(".csproj", StringComparison.Ordinal) || x.Path.Contains(".CSharp"))).ToList();
_view.ShowItems(items, _sortType, false, true);
}
}
@@ -1149,6 +1170,7 @@ namespace FlaxEditor.Windows
writer.WriteAttributeString("ShowEngineFiles", ShowEngineFiles.ToString());
writer.WriteAttributeString("ShowPluginsFiles", ShowPluginsFiles.ToString());
writer.WriteAttributeString("ShowAllFiles", ShowAllFiles.ToString());
writer.WriteAttributeString("ShowGeneratedFiles", ShowGeneratedFiles.ToString());
writer.WriteAttributeString("ViewType", _view.ViewType.ToString());
}
@@ -1166,6 +1188,8 @@ namespace FlaxEditor.Windows
ShowPluginsFiles = value2;
if (bool.TryParse(node.GetAttribute("ShowAllFiles"), out value2))
ShowAllFiles = value2;
if (bool.TryParse(node.GetAttribute("ShowGeneratedFiles"), out value2))
ShowGeneratedFiles = value2;
if (Enum.TryParse(node.GetAttribute("ViewType"), out ContentViewType viewType))
_view.ViewType = viewType;
}

View File

@@ -192,6 +192,13 @@ namespace FlaxEditor.Windows
/// <inheritdoc />
public override bool OnKeyDown(KeyboardKeys key)
{
// Prevent closing the editor window when using RMB + Ctrl + W to slow down the camera flight
if (Editor.Options.Options.Input.CloseTab.Process(this, key))
{
if (Root.GetMouseButton(MouseButton.Right))
return true;
}
if (base.OnKeyDown(key))
return true;
@@ -207,7 +214,8 @@ namespace FlaxEditor.Windows
case KeyboardKeys.Tab:
if (CanUseNavigation && Root != null)
{
Root.Navigate(NavDirection.Next);
bool shiftDown = Root.GetKey(KeyboardKeys.Shift);
Root.Navigate(shiftDown ? NavDirection.Previous : NavDirection.Next);
return true;
}
break;

View File

@@ -429,21 +429,8 @@ namespace FlaxEditor.Windows.Profiler
private void UpdateTable(ref ViewRange viewRange)
{
_table.IsLayoutLocked = true;
int idx = 0;
while (_table.Children.Count > idx)
{
var child = _table.Children[idx];
if (child is Row row)
{
_tableRowsCache.Add(row);
child.Parent = null;
}
else
{
idx++;
}
}
RecycleTableRows(_table, _tableRowsCache);
UpdateTableInner(ref viewRange);
_table.UnlockChildrenRecursive();

View File

@@ -298,21 +298,7 @@ namespace FlaxEditor.Windows.Profiler
private void UpdateTable()
{
_table.IsLayoutLocked = true;
int idx = 0;
while (_table.Children.Count > idx)
{
var child = _table.Children[idx];
if (child is Row row)
{
_tableRowsCache.Add(row);
child.Parent = null;
}
else
{
idx++;
}
}
_table.LockChildrenRecursive();
RecycleTableRows(_table, _tableRowsCache);
UpdateTableInner();

View File

@@ -1,8 +1,32 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using FlaxEditor.GUI;
using FlaxEngine;
using FlaxEngine.GUI;
namespace FlaxEngine
{
partial class ProfilingTools
{
partial struct NetworkEventStat
{
/// <summary>
/// Gets the event name.
/// </summary>
public unsafe string Name
{
get
{
fixed (byte* name = Name0)
return System.Runtime.InteropServices.Marshal.PtrToStringAnsi(new IntPtr(name));
}
}
}
}
}
namespace FlaxEditor.Windows.Profiler
{
/// <summary>
@@ -13,6 +37,10 @@ namespace FlaxEditor.Windows.Profiler
{
private readonly SingleChart _dataSentChart;
private readonly SingleChart _dataReceivedChart;
private readonly Table _tableRpc;
private readonly Table _tableRep;
private SamplesBuffer<ProfilingTools.NetworkEventStat[]> _events;
private List<Row> _tableRowsCache;
private FlaxEngine.Networking.NetworkDriverStats _prevStats;
public Network()
@@ -48,11 +76,10 @@ namespace FlaxEditor.Windows.Profiler
Parent = layout,
};
_dataReceivedChart.SelectedSampleChanged += OnSelectedSampleChanged;
}
private static string FormatSampleBytes(float v)
{
return Utilities.Utils.FormatBytesCount((ulong)v);
// Tables
_tableRpc = InitTable(layout, "RPC Name");
_tableRep = InitTable(layout, "Replication Name");
}
/// <inheritdoc />
@@ -60,21 +87,30 @@ namespace FlaxEditor.Windows.Profiler
{
_dataSentChart.Clear();
_dataReceivedChart.Clear();
_events?.Clear();
}
/// <inheritdoc />
public override void Update(ref SharedUpdateData sharedData)
{
var peer = FlaxEngine.Networking.NetworkManager.Peer;
if (peer == null)
// Gather peer stats
var peers = FlaxEngine.Networking.NetworkPeer.Peers;
var stats = new FlaxEngine.Networking.NetworkDriverStats();
foreach (var peer in peers)
{
_prevStats = new FlaxEngine.Networking.NetworkDriverStats();
return;
var peerStats = peer.NetworkDriver.GetStats();
stats.TotalDataSent += peerStats.TotalDataSent;
stats.TotalDataReceived += peerStats.TotalDataReceived;
}
var stats = peer.NetworkDriver.GetStats();
_dataSentChart.AddSample(Mathf.Max((long)stats.TotalDataSent - (long)_prevStats.TotalDataSent, 0));
_dataReceivedChart.AddSample(Mathf.Max((long)stats.TotalDataReceived - (long)_prevStats.TotalDataReceived, 0));
_prevStats = stats;
// Gather network events
var events = ProfilingTools.EventsNetwork;
if (_events == null)
_events = new SamplesBuffer<ProfilingTools.NetworkEventStat[]>();
_events.Add(events);
}
/// <inheritdoc />
@@ -82,6 +118,159 @@ namespace FlaxEditor.Windows.Profiler
{
_dataSentChart.SelectedSampleIndex = selectedFrame;
_dataReceivedChart.SelectedSampleIndex = selectedFrame;
// Update events tables
if (_events != null)
{
if (_tableRowsCache == null)
_tableRowsCache = new List<Row>();
_tableRpc.IsLayoutLocked = true;
_tableRep.IsLayoutLocked = true;
RecycleTableRows(_tableRpc, _tableRowsCache);
RecycleTableRows(_tableRep, _tableRowsCache);
var events = _events.Get(selectedFrame);
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];
var name = e.Name;
var isRpc = name.Contains("::", StringComparison.Ordinal);
Row row;
if (_tableRowsCache.Count != 0)
{
var last = _tableRowsCache.Count - 1;
row = _tableRowsCache[last];
_tableRowsCache.RemoveAt(last);
}
else
{
row = new Row
{
Values = new object[5],
};
}
{
// Name
row.Values[0] = name;
// Count
row.Values[1] = (int)e.Count;
// Data Size
row.Values[2] = (int)e.DataSize;
// Message Size
row.Values[3] = (int)e.MessageSize;
// Receivers
row.Values[4] = (float)e.Receivers / (float)e.Count;
}
var table = isRpc ? _tableRpc : _tableRep;
row.Width = table.Width;
row.BackgroundColor = rowCount[isRpc ? 0 : 1] % 2 == 0 ? rowColor2 : Color.Transparent;
row.Parent = table;
if (isRpc)
rowCount.X++;
else
rowCount.Y++;
}
}
_tableRpc.Visible = rowCount.X != 0;
_tableRep.Visible = rowCount.Y != 0;
_tableRpc.Children.Sort(SortRows);
_tableRep.Children.Sort(SortRows);
_tableRpc.UnlockChildrenRecursive();
_tableRpc.PerformLayout();
_tableRep.UnlockChildrenRecursive();
_tableRep.PerformLayout();
}
}
/// <inheritdoc />
public override void OnDestroy()
{
_tableRowsCache?.Clear();
base.OnDestroy();
}
private static Table InitTable(ContainerControl parent, string name)
{
var headerColor = Style.Current.LightBackground;
var table = new Table
{
Columns = new[]
{
new ColumnDefinition
{
UseExpandCollapseMode = true,
CellAlignment = TextAlignment.Near,
Title = name,
TitleBackgroundColor = headerColor,
},
new ColumnDefinition
{
Title = "Count",
TitleBackgroundColor = headerColor,
},
new ColumnDefinition
{
Title = "Data Size",
TitleBackgroundColor = headerColor,
FormatValue = FormatCellBytes,
},
new ColumnDefinition
{
Title = "Message Size",
TitleBackgroundColor = headerColor,
FormatValue = FormatCellBytes,
},
new ColumnDefinition
{
Title = "Receivers",
TitleBackgroundColor = headerColor,
},
},
Splits = new[]
{
0.40f,
0.15f,
0.15f,
0.15f,
0.15f,
},
Parent = parent,
};
return table;
}
private static string FormatSampleBytes(float v)
{
return Utilities.Utils.FormatBytesCount((ulong)v);
}
private static string FormatCellBytes(object x)
{
return Utilities.Utils.FormatBytesCount((int)x);
}
private static int SortRows(Control x, Control y)
{
if (x is Row xRow && y is Row yRow)
{
var xDataSize = (int)xRow.Values[2];
var yDataSize = (int)yRow.Values[2];
return yDataSize - xDataSize;
}
return 0;
}
}
}

View File

@@ -1,6 +1,8 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using FlaxEditor.GUI;
using FlaxEditor.GUI.Tabs;
using FlaxEngine;
@@ -135,5 +137,28 @@ namespace FlaxEditor.Windows.Profiler
{
SelectedSampleChanged?.Invoke(frameIndex);
}
/// <summary>
/// Recycles all table rows to be reused.
/// </summary>
/// <param name="table">The table.</param>
/// <param name="rowsCache">The output cache.</param>
protected static void RecycleTableRows(Table table, List<Row> rowsCache)
{
int idx = 0;
while (table.Children.Count > idx)
{
var child = table.Children[idx];
if (child is Row row)
{
rowsCache.Add(row);
child.Parent = null;
}
else
{
idx++;
}
}
}
}
}

View File

@@ -93,7 +93,7 @@ namespace FlaxEditor.Windows.Profiler
_liveRecordingButton = toolstrip.AddButton(editor.Icons.Play64);
_liveRecordingButton.LinkTooltip("Live profiling events recording");
_liveRecordingButton.AutoCheck = true;
_liveRecordingButton.Clicked += () => _liveRecordingButton.Icon = LiveRecording ? editor.Icons.Stop64 : editor.Icons.Play64;
_liveRecordingButton.Clicked += OnLiveRecordingChanged;
_clearButton = toolstrip.AddButton(editor.Icons.Rotate32, Clear);
_clearButton.LinkTooltip("Clear data");
toolstrip.AddSeparator();
@@ -118,6 +118,12 @@ namespace FlaxEditor.Windows.Profiler
_tabs.SelectedTabChanged += OnSelectedTabChanged;
}
private void OnLiveRecordingChanged()
{
_liveRecordingButton.Icon = LiveRecording ? Editor.Icons.Stop64 : Editor.Icons.Play64;
ProfilingTools.Enabled = LiveRecording;
}
/// <summary>
/// Adds the mode.
/// </summary>

View File

@@ -49,6 +49,8 @@ namespace FlaxEditor.Windows.Profiler
/// <returns>The sample value</returns>
public T Get(int index)
{
if (index >= _data.Length || _data.Length == 0)
return default;
return index == -1 ? _data[_count - 1] : _data[index];
}