From 6a65ccd5efd3b807d0138308d33cc6574ec480ea Mon Sep 17 00:00:00 2001
From: NoriteSC <53096989+NoriteSC@users.noreply.github.com>
Date: Mon, 24 Jul 2023 22:10:12 +0200
Subject: [PATCH 01/40] rev1
---
Source/Editor/Content/ContentFilter.cs | 262 ++++++++++++++++++
.../Content/GUI/ContentNavigationBar.cs | 27 ++
.../Content/GUI/ContentNavigationButton.cs | 2 +-
.../GUI/ContentNavigationButtonSeparator.cs | 85 ++++++
.../Content/GUI/ContentSettingsDropdown.cs | 95 +++++++
Source/Editor/Content/GUI/ContentView.cs | 9 +-
Source/Editor/Content/Items/ContentItem.cs | 8 +-
Source/Editor/GUI/ComboBox.cs | 72 +++--
.../Windows/ContentWindow.Navigation.cs | 10 +-
Source/Editor/Windows/ContentWindow.cs | 59 ++--
10 files changed, 588 insertions(+), 41 deletions(-)
create mode 100644 Source/Editor/Content/ContentFilter.cs
create mode 100644 Source/Editor/Content/GUI/ContentNavigationBar.cs
create mode 100644 Source/Editor/Content/GUI/ContentNavigationButtonSeparator.cs
create mode 100644 Source/Editor/Content/GUI/ContentSettingsDropdown.cs
diff --git a/Source/Editor/Content/ContentFilter.cs b/Source/Editor/Content/ContentFilter.cs
new file mode 100644
index 000000000..2cbd78e65
--- /dev/null
+++ b/Source/Editor/Content/ContentFilter.cs
@@ -0,0 +1,262 @@
+using FlaxEditor.Content;
+using FlaxEditor.Content.GUI;
+using FlaxEngine;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+namespace FlaxEditor.Content
+{
+ ///
+ /// class with is controling visability of items in content window
+ ///
+ internal class ContentFilter
+ {
+ #region Filters Config
+ ///
+ /// all suported files by engine Content Folder
+ ///
+ public static readonly List SuportedFileExtencionsInContentFolder = new List()
+ {
+ ".flax",
+ ".json",
+ ".scene",
+ ".prefab",
+ };
+ ///
+ /// all suported files by engine Source Folder
+ ///
+ public static readonly List SuportedFileExtencionsInSourceFolder = new List()
+ {
+ ".shader",
+ ".cs",
+ ".h",
+ ".cpp",
+ };
+ ///
+ /// ignores folders in source folder (top layer),
+ /// for example obj folder is default c# project folder
+ ///
+ internal static readonly List HideFoldersInSourceFolder = new List()
+ {
+ "obj", // default c# project folder
+ "Properties", // c# project stuff ?
+ };
+ ///
+ /// ignores files in source folder (top layer),
+ ///
+ internal static readonly List HideFilesInSourceFolder = new List() //dont edit
+ {
+ "Game.csproj", //solucion file
+ "Game.Gen.cs", //auto-generated not be edited
+ "GameEditorTarget.Build.cs",
+ "GameTarget.Build.cs",
+ };
+ #endregion
+ internal static ContentItem gameSettings;
+ internal static List buildFiles;
+
+ internal static ContentTreeNode settings;
+ internal static ContentTreeNode shaders;
+ internal static ProjectTreeNode engine;
+ internal static List plugins = new();
+ internal static List FilterFolder(ContentFolder folder)
+ {
+ return FilterFolder(folder, SuportedFileExtencionsInContentFolder.ToArray(), SuportedFileExtencionsInSourceFolder.ToArray());
+ }
+ internal static List FilterFolder(ContentFolder folder, string[] FileExtencionsInContentFolder, string[] ExtencionsInSourceFolder)
+ {
+ if (folder.CanHaveAssets)
+ {
+ for (int i = 0; i < folder.Children.Count; i++)
+ {
+ bool Visible = false;
+ for (int j = 0; j < FileExtencionsInContentFolder.Length; j++)
+ {
+ if ((folder.Children[i].Path.EndsWith(FileExtencionsInContentFolder[j]) || folder.Children[i].IsFolder))
+ {
+ if (folder.Children[i].Visible)
+ {
+ Visible = true;
+ }
+ break;
+ }
+ }
+ folder.Children[i].Visible = Visible;
+ }
+ }
+ else if (folder.CanHaveScripts)
+ {
+ for (int i = 0; i < folder.Children.Count; i++)
+ {
+ bool Visible = false;
+ for (int j = 0; j < ExtencionsInSourceFolder.Length; j++)
+ {
+ if ((folder.Children[i].Path.EndsWith(ExtencionsInSourceFolder[j]) || folder.Children[i].IsFolder))
+ {
+ if (folder.Children[i].Visible)
+ {
+ Visible = true;
+ }
+ break;
+ }
+ }
+ folder.Children[i].Visible = Visible;
+ }
+ }
+ return folder.Children;
+ }
+ internal static ProjectTreeNode Filter(ProjectTreeNode tree)
+ {
+ var content = tree.Children[0] as ContentTreeNode;
+ var source = tree.Children[1] as ContentTreeNode;
+ //filter content folder (top layer)
+ buildFiles = new();
+ for (int i = 0; i < content.Folder.Children.Count; i++)
+ {
+ if (content.Folder.Children[i].FileName == "GameSettings.json")
+ {
+ gameSettings = content.Folder.Children[i];
+ content.Folder.Children[i].Visible = false;
+ break;
+ }
+ }
+
+ int hindenCount = 0;
+
+ for (int i = content.Children.Count - 1; i >= 0; i--)//we are starting from back it faster
+ {
+ var node = content.Children[i] as ContentTreeNode;
+ if (node.Folder.FileName == "Settings")
+ {
+ settings = node;
+ hindenCount++;
+ node.Visible = false;
+ node.Folder.Visible = false;
+ }
+ if (node.Folder.FileName == "Shaders")
+ {
+ shaders = node;
+ hindenCount++;
+ node.Visible = false;
+ node.Folder.Visible = false;
+
+ }
+ if (hindenCount == 2)
+ break;
+ }
+
+
+ //-----------------------------------------------------------------------------------------------------
+
+ //filter source folder (top layer)
+ hindenCount = 0;
+ for (int i = 0; i < source.Folder.Children.Count; i++)
+ {
+ for (int j = 0; j < HideFilesInSourceFolder.Count; j++)
+ {
+ if (source.Folder.Children[i].FileName == HideFilesInSourceFolder[j])
+ {
+ source.Folder.Children[i].Visible = false;
+ hindenCount++;
+ if(i > 1)
+ {
+ buildFiles.Add(source.Folder.Children[i]);
+ }
+ if (HideFilesInSourceFolder.Count == hindenCount) goto HideFilesInSourceFolderComplited;
+ break;
+ }
+ }
+ }
+ HideFilesInSourceFolderComplited:
+ hindenCount = 0;
+ for (int i = source.Children.Count - 1; i >= 0; i--)
+ {
+ var node = source.Children[i] as ContentTreeNode;
+ for (int j = 0; j < HideFoldersInSourceFolder.Count; j++)
+ {
+ if (node.Folder.FileName == HideFoldersInSourceFolder[j])
+ {
+ node.Visible = false;
+ node.Folder.Visible = false;
+ hindenCount++;
+ if (HideFoldersInSourceFolder.Count == hindenCount) goto HideFoldersInSourceFolderComplited;
+ break;
+ }
+ }
+ }
+ HideFoldersInSourceFolderComplited:
+ //content
+ return tree;
+ }
+ internal static void UpdateFilterVisability(ContentSettingsDropdown dropdown)
+ {
+ engine.Visible = false;
+ engine.Folder.Visible = false;
+
+ foreach (var item in plugins)
+ {
+ item.Visible = false;
+ item.Folder.Visible = false;
+ }
+ foreach (var item in buildFiles)
+ {
+ item.Visible = false;
+ }
+ gameSettings.Visible = false;
+ settings.Visible = false;
+ settings.Folder.Visible = false;
+
+ shaders.Visible = false;
+ shaders.Folder.Visible = false;
+
+ for (int i = 0; i < dropdown.Selection.Count; i++)
+ {
+ if (dropdown.Selection[i] == 0) //Show Engine Content
+ {
+ engine.Visible = true;
+ engine.Folder.Visible = true;
+ Editor.Instance.Windows.ContentWin.RefreshView(engine);
+ }
+
+ if (dropdown.Selection[i] == 1)//Show Plugin Content
+ {
+ foreach (var item in plugins)
+ {
+ item.Visible = true;
+ item.Folder.Visible = true;
+ Editor.Instance.Windows.ContentWin.RefreshView(item);
+ }
+ }
+
+ if (dropdown.Selection[i] == 2)//Show Build Files
+ {
+ foreach (var item in buildFiles)
+ {
+ item.Visible = true;
+ }
+ }
+
+ if (dropdown.Selection[i] == 3)//Show Game Settings
+ {
+ gameSettings.Visible = true;
+ settings.Visible = true;
+ settings.Folder.Visible = true;
+ Editor.Instance.Windows.ContentWin.RefreshView((ContentTreeNode)settings.Parent);
+ }
+
+ if (dropdown.Selection[i] == 4)//"Show Shader Source"
+ {
+ shaders.Visible = true;
+ shaders.Folder.Visible = true;
+ Editor.Instance.Windows.ContentWin.RefreshView(shaders);
+ }
+ }
+
+
+
+ }
+ }
+}
diff --git a/Source/Editor/Content/GUI/ContentNavigationBar.cs b/Source/Editor/Content/GUI/ContentNavigationBar.cs
new file mode 100644
index 000000000..673ac806e
--- /dev/null
+++ b/Source/Editor/Content/GUI/ContentNavigationBar.cs
@@ -0,0 +1,27 @@
+using FlaxEditor.GUI;
+using FlaxEngine;
+
+namespace FlaxEditor.Content.GUI
+{
+ internal class ContentNavigationBar : NavigationBar
+ {
+ ToolStrip _toolstrip;
+ internal float ofssetFromRightEdge = 80;
+ internal ContentNavigationBar(ToolStrip toolstrip) : base()
+ {
+ _toolstrip = toolstrip;
+ }
+ ///
+ protected override void Arrange()
+ {
+ base.Arrange();
+ var lastToolstripButton = _toolstrip.LastButton;
+ var parentSize = Parent.Size;
+ Bounds = new Rectangle
+ (
+ new Float2(lastToolstripButton.Right, 0),
+ new Float2(parentSize.X - X - ofssetFromRightEdge, _toolstrip.Height)
+ );
+ }
+ }
+}
diff --git a/Source/Editor/Content/GUI/ContentNavigationButton.cs b/Source/Editor/Content/GUI/ContentNavigationButton.cs
index d37e1629b..beec247da 100644
--- a/Source/Editor/Content/GUI/ContentNavigationButton.cs
+++ b/Source/Editor/Content/GUI/ContentNavigationButton.cs
@@ -31,7 +31,7 @@ namespace FlaxEditor.Content.GUI
: base(x, y, height)
{
TargetNode = targetNode;
- Text = targetNode.NavButtonLabel + "/";
+ Text = targetNode.NavButtonLabel;
}
///
diff --git a/Source/Editor/Content/GUI/ContentNavigationButtonSeparator.cs b/Source/Editor/Content/GUI/ContentNavigationButtonSeparator.cs
new file mode 100644
index 000000000..cad63066d
--- /dev/null
+++ b/Source/Editor/Content/GUI/ContentNavigationButtonSeparator.cs
@@ -0,0 +1,85 @@
+using FlaxEditor;
+using FlaxEditor.GUI;
+using FlaxEditor.GUI.ContextMenu;
+using FlaxEngine;
+using FlaxEngine.GUI;
+using System.Collections.Generic;
+
+namespace FlaxEditor.Content.GUI
+{
+ internal class ContentNavigationButtonSeparator : ComboBox
+ {
+ public ContentNavigationButton Target { get; }
+ public ContentNavigationButtonSeparator(ContentNavigationButton target, float x, float y,float height)
+ {
+ Target = target;
+ Bounds = new Rectangle(x, y, 16, height);
+ Offsets = new Margin(Bounds.X, Bounds.Width, Bounds.Y, Bounds.Height);
+ UpdateTransform();
+
+ MaximumItemsInViewCount = 20;
+ var style = Style.Current;
+ BackgroundColor = style.BackgroundNormal;
+ BackgroundColorHighlighted = BackgroundColor;
+ BackgroundColorSelected = BackgroundColor;
+ }
+ protected override ContextMenu OnCreatePopup()
+ {
+ UpdateDropDownItems();
+ return base.OnCreatePopup();
+ }
+ internal void UpdateDropDownItems()
+ {
+ ClearItems();
+ _items = new();
+ for (int i = 0; i < Target.TargetNode.Children.Count; i++)
+ {
+ if (Target.TargetNode.Children[i] is ContentTreeNode node)
+ {
+ if (node.Folder.VisibleInHierarchy) // respect the filter set by ContentFilterConfig.Filter(...)
+ AddItem(node.Folder.ShortName);
+ }
+ }
+ }
+ ///
+ public override void Draw()
+ {
+ // Cache data
+ var style = Style.Current;
+ var clientRect = new Rectangle(Float2.Zero, Size);
+ // Draw background
+ if (IsDragOver)
+ {
+ Render2D.FillRectangle(clientRect, Style.Current.BackgroundSelected * 0.6f);
+ }
+ else if (_mouseDown)
+ {
+ Render2D.FillRectangle(clientRect, style.BackgroundSelected);
+ }
+ else if (IsMouseOver)
+ {
+ Render2D.FillRectangle(clientRect, style.BackgroundHighlighted);
+ }
+
+ Render2D.DrawSprite(Editor.Instance.Icons.ArrowRight12, new Rectangle(clientRect.Location.X, clientRect.Y + ((Size.Y / 2f)/2f), Size.X, Size.X), EnabledInHierarchy ? Style.Current.Foreground : Style.Current.ForegroundDisabled);
+ }
+ protected override void OnLayoutMenuButton(ref ContextMenuButton button, int index, bool construct = false)
+ {
+ var style = Style.Current;
+ button.Icon = Editor.Instance.Icons.FolderClosed32;
+ if (_tooltips != null && _tooltips.Length > index)
+ {
+ button.TooltipText = _tooltips[index];
+ }
+ }
+ protected override void OnItemClicked(int index)
+ {
+ base.OnItemClicked(index);
+ if (Target.TargetNode.Children[index] is ContentTreeNode node)
+ {
+ Editor.Instance.Windows.ContentWin.Navigate(node);
+ }
+ // Navigate calls the OnDestroy at some point dont place code below or editor will crash
+ }
+ }
+}
diff --git a/Source/Editor/Content/GUI/ContentSettingsDropdown.cs b/Source/Editor/Content/GUI/ContentSettingsDropdown.cs
new file mode 100644
index 000000000..04722a674
--- /dev/null
+++ b/Source/Editor/Content/GUI/ContentSettingsDropdown.cs
@@ -0,0 +1,95 @@
+using FlaxEditor.Content;
+using FlaxEditor.CustomEditors.Editors;
+using FlaxEditor.GUI;
+using FlaxEditor.GUI.ContextMenu;
+using FlaxEditor.States;
+using FlaxEditor.Utilities;
+using FlaxEngine;
+using FlaxEngine.GUI;
+using FlaxEngine.Json;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace FlaxEditor.Content.GUI
+{
+ class ContentSettingsDropdown : ComboBox
+ {
+ internal readonly List Settings = new()
+ {
+ "Show Engine Content",
+ "Show Plugin Content",
+ "Show Build Files",
+ "Show Game Settings",
+ "Show Shader Source"
+ };
+ public ContentSettingsDropdown()
+ {
+ SupportMultiSelect = true;
+ MaximumItemsInViewCount = 20;
+ var style = Style.Current;
+ BackgroundColor = style.BackgroundNormal;
+ BackgroundColorHighlighted = BackgroundColor;
+ BackgroundColorSelected = BackgroundColor;
+
+ }
+ protected override ContextMenu OnCreatePopup()
+ {
+ UpdateDropDownItems();
+ return base.OnCreatePopup();
+ }
+ internal void UpdateDropDownItems()
+ {
+ ClearItems();
+
+ for (int i = 0; i < Settings.Count; i++)
+ {
+ AddItem(Settings[i]);
+ }
+ }
+ ///
+ public override void Draw()
+ {
+ // Cache data
+ var style = Style.Current;
+ var clientRect = new Rectangle(Float2.Zero, Size);
+ // Draw background
+ if (IsDragOver)
+ {
+ Render2D.FillRectangle(clientRect, Style.Current.BackgroundSelected * 0.6f);
+ }
+ else if (_mouseDown)
+ {
+ Render2D.FillRectangle(clientRect, style.BackgroundSelected);
+ }
+ else if (IsMouseOver)
+ {
+ Render2D.FillRectangle(clientRect, style.BackgroundHighlighted);
+ }
+ float size = (Size.Y / 1.5f); //Icon size
+ // Draw text
+ Render2D.DrawText(Font.GetFont(), "Settings", new Rectangle(size, 0, Size.X - Size.Y, Size.Y), TextColor, TextAlignment.Center, TextAlignment.Center);
+ Render2D.DrawSprite(Editor.Instance.Icons.Settings12, new Rectangle((Size.Y - size) / 2.0f, (Size.Y - size) / 2.0f, size, size));
+ }
+ protected override void OnLayoutMenuButton(ref ContextMenuButton button, int index, bool construct = false)
+ {
+ var style = Style.Current;
+ if (_selectedIndices.Contains(index))
+ {
+ button.Icon = style.CheckBoxTick;
+ }
+ else
+ {
+ button.Icon = SpriteHandle.Default;
+ }
+ if (_tooltips != null && _tooltips.Length > index)
+ {
+ button.TooltipText = _tooltips[index];
+ }
+ }
+ protected override void OnSelectedIndexChanged()
+ {
+ ContentFilter.UpdateFilterVisability(this);
+ base.OnSelectedIndexChanged();
+ }
+ }
+}
diff --git a/Source/Editor/Content/GUI/ContentView.cs b/Source/Editor/Content/GUI/ContentView.cs
index 6065ca9f8..9dca03953 100644
--- a/Source/Editor/Content/GUI/ContentView.cs
+++ b/Source/Editor/Content/GUI/ContentView.cs
@@ -261,11 +261,14 @@ namespace FlaxEditor.Content.GUI
ClearItems();
// Add references and link items
- _items.AddRange(items);
for (int i = 0; i < items.Count; i++)
{
- items[i].Parent = this;
- items[i].AddReference(this);
+ if (items[i].Visible)
+ {
+ items[i].Parent = this;
+ items[i].AddReference(this);
+ _items.Add(items[i]);
+ }
}
if (selection != null)
{
diff --git a/Source/Editor/Content/Items/ContentItem.cs b/Source/Editor/Content/Items/ContentItem.cs
index 66825fb42..377c6dac0 100644
--- a/Source/Editor/Content/Items/ContentItem.cs
+++ b/Source/Editor/Content/Items/ContentItem.cs
@@ -441,6 +441,11 @@ namespace FlaxEditor.Content
{
get
{
+ if (!Visible)
+ {
+ return Rectangle.Empty;
+ }
+
var view = Parent as ContentView;
var size = Size;
switch (view?.ViewType ?? ContentViewType.Tiles)
@@ -448,7 +453,7 @@ namespace FlaxEditor.Content
case ContentViewType.Tiles:
{
var textHeight = DefaultTextHeight * size.X / DefaultWidth;
- return new Rectangle(0, size.Y - textHeight, size.X, textHeight);
+ return new Rectangle(0, size.Y - textHeight, size.X - 2, textHeight);
}
case ContentViewType.List:
{
@@ -642,6 +647,7 @@ namespace FlaxEditor.Content
///
public override void Draw()
{
+
// Cache data
var size = Size;
var style = Style.Current;
diff --git a/Source/Editor/GUI/ComboBox.cs b/Source/Editor/GUI/ComboBox.cs
index 2481316d0..da38268b2 100644
--- a/Source/Editor/GUI/ComboBox.cs
+++ b/Source/Editor/GUI/ComboBox.cs
@@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Linq;
using FlaxEngine;
using FlaxEngine.GUI;
+using FlaxEditor.GUI.ContextMenu;
namespace FlaxEditor.GUI
{
@@ -396,14 +397,23 @@ namespace FlaxEditor.GUI
_popupMenu.ButtonClicked += btn =>
{
OnItemClicked((int)btn.Tag);
- _popupMenu?.Hide();
+ if (SupportMultiSelect)
+ {
+ UpdateButtons();
+ _popupMenu?.PerformLayout();
+ }
+ else
+ {
+ _popupMenu?.Hide();
+ }//[nori_sc] don't hide it Support MultiSelect is on actions per min is important for UX, if some one wont to set more then 5 elements in multi select menu let them do it
};
}
// Check if menu hs been already shown
if (_popupMenu.Visible)
{
- _popupMenu.Hide();
+ if (!SupportMultiSelect)
+ _popupMenu.Hide();
return;
}
@@ -412,31 +422,59 @@ namespace FlaxEditor.GUI
// Check if has any items
if (_items.Count > 0)
{
- // Setup items list
+ UpdateButtons();
+ // Show dropdown list
+ _popupMenu.MinimumWidth = Width;
+ _popupMenu.Show(this, new Float2(1, Height));
+ }
+ }
+ ///
+ /// update buttons layout and repains
+ ///
+ private void UpdateButtons()
+ {
+ if (_popupMenu.Items.Count() != _items.Count)
+ {
var itemControls = _popupMenu.Items.ToArray();
foreach (var e in itemControls)
e.Dispose();
if (Sorted)
_items.Sort();
- var style = Style.Current;
for (int i = 0; i < _items.Count; i++)
{
var btn = _popupMenu.AddButton(_items[i]);
- if (_selectedIndices.Contains(i))
- {
- btn.Icon = style.CheckBoxTick;
- }
- if (_tooltips != null && _tooltips.Length > i)
- {
- btn.TooltipText = _tooltips[i];
- }
-
+ OnLayoutMenuButton(ref btn, i, true);
btn.Tag = i;
}
-
- // Show dropdown list
- _popupMenu.MinimumWidth = Width;
- _popupMenu.Show(this, new Float2(1, Height));
+ }
+ else
+ {
+ var itemControls = _popupMenu.Items.ToArray();
+ if (Sorted)
+ _items.Sort();
+ for (int i = 0; i < _items.Count; i++)
+ {
+ if (itemControls[i] is ContextMenuButton btn)
+ {
+ btn.Text = _items[i];
+ OnLayoutMenuButton(ref btn, i, true);
+ }
+ }
+ }
+ }
+ ///
+ /// caled when button is created or repainted u can overite it to give the button custom look
+ ///
+ /// button refrance
+ /// curent item index
+ /// true if button is created else it is repainting the button
+ protected virtual void OnLayoutMenuButton(ref FlaxEditor.GUI.ContextMenu.ContextMenuButton button,int index, bool construct = false)
+ {
+ var style = Style.Current;
+ button.Checked = _selectedIndices.Contains(index);
+ if (_tooltips != null && _tooltips.Length > index)
+ {
+ button.TooltipText = _tooltips[index];
}
}
diff --git a/Source/Editor/Windows/ContentWindow.Navigation.cs b/Source/Editor/Windows/ContentWindow.Navigation.cs
index ad690c2d0..ca3de992d 100644
--- a/Source/Editor/Windows/ContentWindow.Navigation.cs
+++ b/Source/Editor/Windows/ContentWindow.Navigation.cs
@@ -196,12 +196,18 @@ namespace FlaxEditor.Windows
}
float x = NavigationBar.DefaultButtonsMargin;
float h = _toolStrip.ItemsHeight - 2 * ToolStrip.DefaultMarginV;
- for (int i = nodes.Count - 1; i >= 0; i--)
+ for (int i = nodes.Count - 2; i >= 0; i--)
{
- var button = new ContentNavigationButton(nodes[i], x, ToolStrip.DefaultMarginV, h);
+ var button = new ContentNavigationButton(nodes[i], x - 100, ToolStrip.DefaultMarginV, h);
button.PerformLayout();
x += button.Width + NavigationBar.DefaultButtonsMargin;
_navigationBar.AddChild(button);
+ if (i == 0)
+ continue;
+ var buttonSeparator = new ContentNavigationButtonSeparator(button, x, ToolStrip.DefaultMarginV, h);
+ buttonSeparator.PerformLayout();
+ x += buttonSeparator.Width + NavigationBar.DefaultButtonsMargin;
+ _navigationBar.AddChild(buttonSeparator);
}
nodes.Clear();
diff --git a/Source/Editor/Windows/ContentWindow.cs b/Source/Editor/Windows/ContentWindow.cs
index f993b79f9..58aaf3e4c 100644
--- a/Source/Editor/Windows/ContentWindow.cs
+++ b/Source/Editor/Windows/ContentWindow.cs
@@ -39,11 +39,13 @@ namespace FlaxEditor.Windows
private readonly ToolStripButton _navigateForwardButton;
private readonly ToolStripButton _navigateUpButton;
- private NavigationBar _navigationBar;
+ private ContentNavigationBar _navigationBar;
private Tree _tree;
private TextBox _foldersSearchBox;
private TextBox _itemsSearchBox;
private ViewDropdown _viewDropdown;
+ private ContentSettingsDropdown _ContentSettingDropdown;
+ private const float _ContentDropdownSizeX = 100;
private SortType _sortType;
private RootContentTreeNode _root;
@@ -73,7 +75,7 @@ namespace FlaxEditor.Windows
{
Title = "Content";
Icon = editor.Icons.Folder32;
-
+
// Content database events
editor.ContentDatabase.WorkspaceModified += () => _isWorkspaceDirty = true;
editor.ContentDatabase.ItemRemoved += OnContentDatabaseItemRemoved;
@@ -107,11 +109,25 @@ namespace FlaxEditor.Windows
_navigateBackwardButton = (ToolStripButton)_toolStrip.AddButton(Editor.Icons.Left64, NavigateBackward).LinkTooltip("Navigate backward");
_navigateForwardButton = (ToolStripButton)_toolStrip.AddButton(Editor.Icons.Right64, NavigateForward).LinkTooltip("Navigate forward");
_navigateUpButton = (ToolStripButton)_toolStrip.AddButton(Editor.Icons.Up64, NavigateUp).LinkTooltip("Navigate up");
-
+ _toolStrip.AddSeparator();
// Navigation bar
- _navigationBar = new NavigationBar
+
+ _navigationBar = new ContentNavigationBar(_toolStrip)
{
- Parent = this,
+ Parent = _toolStrip,
+ ofssetFromRightEdge = _ContentDropdownSizeX
+ };
+ var DropdownSettingsPanel = new Panel(ScrollBars.None)
+ {
+ Parent = _toolStrip,
+ Size = new Float2(_ContentDropdownSizeX, _toolStrip.Height)
+ };
+ //setings Dropdown
+ _ContentSettingDropdown = new ContentSettingsDropdown
+ {
+ AnchorPreset = AnchorPresets.StretchAll,
+ Parent = DropdownSettingsPanel,
+ Offsets = new Margin(2, 4, 4, 4)
};
// Split panel
@@ -215,7 +231,7 @@ namespace FlaxEditor.Windows
private ContextMenu OnViewDropdownPopupCreate(ComboBox comboBox)
{
var menu = new ContextMenu();
-
+
var showFileExtensionsButton = menu.AddButton("Show file extensions", () => View.ShowFileExtensions = !View.ShowFileExtensions);
showFileExtensionsButton.Checked = View.ShowFileExtensions;
showFileExtensionsButton.AutoCheck = true;
@@ -877,8 +893,9 @@ namespace FlaxEditor.Windows
}
else
{
+
// Show folder contents
- _view.ShowItems(target.Folder.Children, _sortType, false, true);
+ _view.ShowItems(ContentFilter.FilterFolder(target.Folder), _sortType, false, true);
}
}
@@ -918,15 +935,17 @@ namespace FlaxEditor.Windows
_root.Expand(true);
// Add game project on top, plugins in the middle and engine at bottom
- _root.AddChild(Editor.ContentDatabase.Game);
+ _root.AddChild(ContentFilter.Filter(Editor.ContentDatabase.Game));
foreach (var project in Editor.ContentDatabase.Projects)
{
project.SortChildrenRecursive();
if (project == Editor.ContentDatabase.Game || project == Editor.ContentDatabase.Engine)
continue;
_root.AddChild(project);
+ ContentFilter.plugins.Add(project);
}
_root.AddChild(Editor.ContentDatabase.Engine);
+ ContentFilter.engine = Editor.ContentDatabase.Engine;
Editor.ContentDatabase.Game?.Expand(true);
_tree.Margin = new Margin(0.0f, 0.0f, -16.0f, 2.0f); // Hide root node
@@ -1035,15 +1054,6 @@ namespace FlaxEditor.Windows
return base.OnMouseUp(location, button);
}
-
- ///
- protected override void PerformLayoutBeforeChildren()
- {
- base.PerformLayoutBeforeChildren();
-
- _navigationBar?.UpdateBounds(_toolStrip);
- }
-
///
public override bool UseLayoutData => true;
@@ -1054,6 +1064,12 @@ namespace FlaxEditor.Windows
writer.WriteAttributeString("Scale", _view.ViewScale.ToString(CultureInfo.InvariantCulture));
writer.WriteAttributeString("ShowFileExtensions", _view.ShowFileExtensions.ToString());
writer.WriteAttributeString("ViewType", _view.ViewType.ToString());
+ for (int i = 0; i < _ContentSettingDropdown.Selection.Count; i++)
+ {
+ if(_ContentSettingDropdown.Selection.Count != 0)
+ writer.WriteAttributeString(_ContentSettingDropdown.Settings[_ContentSettingDropdown.Selection[i]].Replace(' ', '_'), _ContentSettingDropdown.Selection[i].ToString());
+ }
+
}
///
@@ -1066,6 +1082,15 @@ namespace FlaxEditor.Windows
_view.ShowFileExtensions = value2;
if (Enum.TryParse(node.GetAttribute("ViewType"), out ContentViewType viewType))
_view.ViewType = viewType;
+
+ for (int i = 0; i < _ContentSettingDropdown.Settings.Count; i++)
+ {
+ int flag;
+ if (int.TryParse(node.GetAttribute(_ContentSettingDropdown.Settings[i].Replace(' ', '_')), out flag))
+ _ContentSettingDropdown.Selection.Add(flag);
+
+ }
+ ContentFilter.UpdateFilterVisability(_ContentSettingDropdown);
}
///
From 131060efa7c1030ae2010acfcd7b4eedb5fc3a90 Mon Sep 17 00:00:00 2001
From: NoriteSC <53096989+NoriteSC@users.noreply.github.com>
Date: Fri, 28 Jul 2023 12:48:43 +0200
Subject: [PATCH 02/40] bug fix
---
Source/Editor/Content/ContentFilter.cs | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/Source/Editor/Content/ContentFilter.cs b/Source/Editor/Content/ContentFilter.cs
index 2cbd78e65..12cca5c41 100644
--- a/Source/Editor/Content/ContentFilter.cs
+++ b/Source/Editor/Content/ContentFilter.cs
@@ -195,7 +195,7 @@ namespace FlaxEditor.Content
{
engine.Visible = false;
engine.Folder.Visible = false;
-
+
foreach (var item in plugins)
{
item.Visible = false;
@@ -218,7 +218,6 @@ namespace FlaxEditor.Content
{
engine.Visible = true;
engine.Folder.Visible = true;
- Editor.Instance.Windows.ContentWin.RefreshView(engine);
}
if (dropdown.Selection[i] == 1)//Show Plugin Content
@@ -227,7 +226,6 @@ namespace FlaxEditor.Content
{
item.Visible = true;
item.Folder.Visible = true;
- Editor.Instance.Windows.ContentWin.RefreshView(item);
}
}
@@ -244,19 +242,16 @@ namespace FlaxEditor.Content
gameSettings.Visible = true;
settings.Visible = true;
settings.Folder.Visible = true;
- Editor.Instance.Windows.ContentWin.RefreshView((ContentTreeNode)settings.Parent);
}
if (dropdown.Selection[i] == 4)//"Show Shader Source"
{
shaders.Visible = true;
shaders.Folder.Visible = true;
- Editor.Instance.Windows.ContentWin.RefreshView(shaders);
}
}
-
-
-
+ engine.ParentTree.PerformLayout();
+ Editor.Instance.Windows.ContentWin.RefreshView();
}
}
}
From fb69bc64f8dc0c85c244f1742e87558b579bb2ac Mon Sep 17 00:00:00 2001
From: Chandler Cox
Date: Thu, 24 Aug 2023 11:38:14 -0500
Subject: [PATCH 03/40] Add automated plugin project creation and Git cloning.
---
Source/Editor/Windows/PluginsWindow.cs | 556 ++++++++++++++++++++++++-
1 file changed, 554 insertions(+), 2 deletions(-)
diff --git a/Source/Editor/Windows/PluginsWindow.cs b/Source/Editor/Windows/PluginsWindow.cs
index 694551345..451e58afa 100644
--- a/Source/Editor/Windows/PluginsWindow.cs
+++ b/Source/Editor/Windows/PluginsWindow.cs
@@ -2,11 +2,19 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.IO.Compression;
using System.Linq;
+using System.Net.Http;
+using System.Threading.Tasks;
using FlaxEditor.GUI;
+using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.GUI.Tabs;
using FlaxEngine;
using FlaxEngine.GUI;
+using FlaxEngine.Json;
+using Debug = FlaxEngine.Debug;
namespace FlaxEditor.Windows
{
@@ -17,6 +25,8 @@ namespace FlaxEditor.Windows
public sealed class PluginsWindow : EditorWindow
{
private Tabs _tabs;
+ private Button _addPluginProjectButton;
+ private Button _cloneProjectButton;
private readonly List _categories = new List();
private readonly Dictionary _entries = new Dictionary();
@@ -174,19 +184,557 @@ namespace FlaxEditor.Windows
{
Title = "Plugins";
+ var vp = new Panel
+ {
+ AnchorPreset = AnchorPresets.StretchAll,
+ Parent = this,
+ };
+ _addPluginProjectButton = new Button
+ {
+ Text = "Create Plugin Project",
+ TooltipText = "Add new plugin project.",
+ AnchorPreset = AnchorPresets.TopLeft,
+ LocalLocation = new Float2(70,18),
+ Size = new Float2(150, 25),
+ Parent = vp,
+ };
+ _addPluginProjectButton.Clicked += OnAddButtonClicked;
+
+ _cloneProjectButton = new Button
+ {
+ Text = "Clone Plugin Project",
+ TooltipText = "Git Clone a plugin project.",
+ AnchorPreset = AnchorPresets.TopLeft,
+ LocalLocation = new Float2(70 + _addPluginProjectButton.Size.X + 8, 18),
+ Size = new Float2(150, 25),
+ Parent = vp,
+ };
+ _cloneProjectButton.Clicked += OnCloneProjectButtonClicked;
+
_tabs = new Tabs
{
Orientation = Orientation.Vertical,
AnchorPreset = AnchorPresets.StretchAll,
- Offsets = Margin.Zero,
+ Offsets = new Margin(0, 0, _addPluginProjectButton.Bottom + 8, 0),
TabsSize = new Float2(120, 32),
- Parent = this
+ Parent = vp
};
OnPluginsChanged();
PluginManager.PluginsChanged += OnPluginsChanged;
}
+ private void OnCloneProjectButtonClicked()
+ {
+ var popup = new ContextMenuBase
+ {
+ Size = new Float2(300, 125),
+ ClipChildren = false,
+ CullChildren = false,
+ };
+ popup.Show(_cloneProjectButton, new Float2(_cloneProjectButton.Width, 0));
+
+ var nameLabel = new Label
+ {
+ Parent = popup,
+ AnchorPreset = AnchorPresets.TopLeft,
+ AutoWidth = true,
+ Text = "Name",
+ HorizontalAlignment = TextAlignment.Near,
+ };
+ nameLabel.LocalY += 10;
+
+ var nameTextBox = new TextBox
+ {
+ Parent = popup,
+ WatermarkText = "Plugin Name",
+ TooltipText = "If left blank, this will take the git name.",
+ AnchorPreset = AnchorPresets.TopLeft,
+ IsMultiline = false,
+ };
+ nameTextBox.LocalX += (300 - (10)) * 0.5f;
+ nameTextBox.LocalY += 10;
+ nameLabel.LocalX += (300 - (nameLabel.Width + nameTextBox.Width)) * 0.5f + 10;
+
+ var defaultTextBoxBorderColor = nameTextBox.BorderColor;
+ var defaultTextBoxBorderSelectedColor = nameTextBox.BorderSelectedColor;
+ nameTextBox.TextChanged += () =>
+ {
+ if (string.IsNullOrEmpty(nameTextBox.Text))
+ {
+ nameTextBox.BorderColor = defaultTextBoxBorderColor;
+ nameTextBox.BorderSelectedColor = defaultTextBoxBorderSelectedColor;
+ return;
+ }
+
+ var pluginPath = Path.Combine(Globals.ProjectFolder, "Plugins", nameTextBox.Text);
+ if (Directory.Exists(pluginPath))
+ {
+ nameTextBox.BorderColor = Color.Red;
+ nameTextBox.BorderSelectedColor = Color.Red;
+ }
+ else
+ {
+ nameTextBox.BorderColor = defaultTextBoxBorderColor;
+ nameTextBox.BorderSelectedColor = defaultTextBoxBorderSelectedColor;
+ }
+ };
+
+ var gitPathLabel = new Label
+ {
+ Parent = popup,
+ AnchorPreset = AnchorPresets.TopLeft,
+ AutoWidth = true,
+ Text = "Git Path",
+ HorizontalAlignment = TextAlignment.Near,
+ };
+ gitPathLabel.LocalX += (300 - gitPathLabel.Width) * 0.5f;
+ gitPathLabel.LocalY += 35;
+
+ var gitPathTextBox = new TextBox
+ {
+ Parent = popup,
+ WatermarkText = "https://github.com/FlaxEngine/ExamplePlugin.git",
+ AnchorPreset = AnchorPresets.TopLeft,
+ Size = new Float2(280, TextBox.DefaultHeight),
+ IsMultiline = false,
+ };
+ gitPathTextBox.LocalY += 60;
+ gitPathTextBox.LocalX += 10;
+
+ var submitButton = new Button
+ {
+ Parent = popup,
+ AnchorPreset = AnchorPresets.TopLeft,
+ Text = "Clone",
+ Width = 70,
+ };
+ submitButton.LocalX += 300 * 0.5f - submitButton.Width - 10;
+ submitButton.LocalY += 90;
+
+ submitButton.Clicked += () =>
+ {
+ if (Directory.Exists(Path.Combine(Globals.ProjectFolder, "Plugins", nameTextBox.Text)) && !string.IsNullOrEmpty(nameTextBox.Text))
+ {
+ Debug.Logger.LogHandler.LogWrite(LogType.Warning, "Cannot create plugin due to name conflict.");
+ return;
+ }
+ OnCloneButtonClicked(nameTextBox.Text, gitPathTextBox.Text);
+ nameTextBox.Clear();
+ gitPathTextBox.Clear();
+ popup.Hide();
+ };
+
+ var cancelButton = new Button
+ {
+ Parent = popup,
+ AnchorPreset = AnchorPresets.TopLeft,
+ Text = "Cancel",
+ Width = 70,
+ };
+ cancelButton.LocalX += 300 * 0.5f + 10;
+ cancelButton.LocalY += 90;
+
+ cancelButton.Clicked += () =>
+ {
+ nameTextBox.Clear();
+ gitPathTextBox.Clear();
+ popup.Hide();
+ };
+ }
+
+ private async void OnCloneButtonClicked(string pluginName, string gitPath)
+ {
+ if (string.IsNullOrEmpty(gitPath))
+ {
+ Debug.Logger.LogHandler.LogWrite(LogType.Error, $"Failed to create plugin project due to no GIT path.");
+ return;
+ }
+ if (string.IsNullOrEmpty(pluginName))
+ {
+ var split = gitPath.Split('/');
+ if (string.IsNullOrEmpty(split[^1]))
+ {
+ var name = split[^2].Replace(".git", "");
+ pluginName = name;
+ }
+ else
+ {
+ var name = split[^1].Replace(".git", "");
+ pluginName = name;
+ }
+ }
+
+ var clonePath = Path.Combine(Globals.ProjectFolder, "Plugins", pluginName);
+ if (!Directory.Exists(clonePath))
+ Directory.CreateDirectory(clonePath);
+ else
+ {
+ Debug.Logger.LogHandler.LogWrite(LogType.Error, $"Plugin Name is already used. Pick a different Name.");
+ return;
+ }
+ try
+ {
+ // Start git clone
+ var gitProcess = new Process();
+ gitProcess.StartInfo.FileName = "git";
+ gitProcess.StartInfo.Arguments = $"clone {gitPath} \"{clonePath}\"";
+ gitProcess.StartInfo.UseShellExecute = false;
+ gitProcess.StartInfo.RedirectStandardOutput = true;
+ gitProcess.StartInfo.RedirectStandardError = true;
+
+ gitProcess.Start();
+ await gitProcess.WaitForExitAsync();
+
+ string output = await gitProcess.StandardOutput.ReadToEndAsync();
+ string error = await gitProcess.StandardError.ReadToEndAsync();
+ Debug.Logger.LogHandler.LogWrite(LogType.Info, $"{output}");
+ Debug.Logger.LogHandler.LogWrite(LogType.Info, $"{error}");
+ }
+ catch (Exception e)
+ {
+ Debug.Logger.LogHandler.LogWrite(LogType.Error, $"Failed Gir process. {e}");
+ return;
+ }
+
+ Debug.Logger.LogHandler.LogWrite(LogType.Info, $"Plugin project has been cloned.");
+
+ // Find project config file. Could be different then what the user named the folder.
+ var files = Directory.GetFiles(clonePath);
+ string pluginProjectName = "";
+ foreach (var file in files)
+ {
+ if (file.Contains(".flaxproj", StringComparison.OrdinalIgnoreCase))
+ {
+ pluginProjectName = Path.GetFileNameWithoutExtension(file);
+ Debug.Log(pluginProjectName);
+ }
+ }
+
+ if (string.IsNullOrEmpty(pluginProjectName))
+ Debug.Logger.LogHandler.LogWrite(LogType.Error, $"Failed to find plugin project file to add to Project config. Please add manually.");
+ else
+ {
+ await AddReferenceToProject(pluginName, pluginProjectName);
+ MessageBox.Show($"{pluginName} has been successfully cloned. Restart editor for changes to take effect.", "Plugin Project Created", MessageBoxButtons.OK);
+ }
+ }
+
+ private void OnAddButtonClicked()
+ {
+ var popup = new ContextMenuBase
+ {
+ Size = new Float2(230, 125),
+ ClipChildren = false,
+ CullChildren = false,
+ };
+ popup.Show(_addPluginProjectButton, new Float2(_addPluginProjectButton.Width, 0));
+
+ var nameLabel = new Label
+ {
+ Parent = popup,
+ AnchorPreset = AnchorPresets.TopLeft,
+ Text = "Name",
+ HorizontalAlignment = TextAlignment.Near,
+ };
+ nameLabel.LocalX += 10;
+ nameLabel.LocalY += 10;
+
+ var nameTextBox = new TextBox
+ {
+ Parent = popup,
+ WatermarkText = "Plugin Name",
+ AnchorPreset = AnchorPresets.TopLeft,
+ IsMultiline = false,
+ };
+ nameTextBox.LocalX += 100;
+ nameTextBox.LocalY += 10;
+ var defaultTextBoxBorderColor = nameTextBox.BorderColor;
+ var defaultTextBoxBorderSelectedColor = nameTextBox.BorderSelectedColor;
+ nameTextBox.TextChanged += () =>
+ {
+ if (string.IsNullOrEmpty(nameTextBox.Text))
+ {
+ nameTextBox.BorderColor = defaultTextBoxBorderColor;
+ nameTextBox.BorderSelectedColor = defaultTextBoxBorderSelectedColor;
+ return;
+ }
+
+ var pluginPath = Path.Combine(Globals.ProjectFolder, "Plugins", nameTextBox.Text);
+ if (Directory.Exists(pluginPath))
+ {
+ nameTextBox.BorderColor = Color.Red;
+ nameTextBox.BorderSelectedColor = Color.Red;
+ }
+ else
+ {
+ nameTextBox.BorderColor = defaultTextBoxBorderColor;
+ nameTextBox.BorderSelectedColor = defaultTextBoxBorderSelectedColor;
+ }
+ };
+
+ var versionLabel = new Label
+ {
+ Parent = popup,
+ AnchorPreset = AnchorPresets.TopLeft,
+ Text = "Version",
+ HorizontalAlignment = TextAlignment.Near,
+ };
+ versionLabel.LocalX += 10;
+ versionLabel.LocalY += 35;
+
+ var versionTextBox = new TextBox
+ {
+ Parent = popup,
+ WatermarkText = "1.0.0",
+ AnchorPreset = AnchorPresets.TopLeft,
+ IsMultiline = false,
+ };
+ versionTextBox.LocalY += 35;
+ versionTextBox.LocalX += 100;
+
+ var companyLabel = new Label
+ {
+ Parent = popup,
+ AnchorPreset = AnchorPresets.TopLeft,
+ Text = "Company",
+ HorizontalAlignment = TextAlignment.Near,
+ };
+ companyLabel.LocalX += 10;
+ companyLabel.LocalY += 60;
+
+ var companyTextBox = new TextBox
+ {
+ Parent = popup,
+ WatermarkText = "Company Name",
+ AnchorPreset = AnchorPresets.TopLeft,
+ IsMultiline = false,
+ };
+ companyTextBox.LocalY += 60;
+ companyTextBox.LocalX += 100;
+
+ var submitButton = new Button
+ {
+ Parent = popup,
+ AnchorPreset = AnchorPresets.TopLeft,
+ Text = "Create",
+ Width = 70,
+ };
+ submitButton.LocalX += 40;
+ submitButton.LocalY += 90;
+
+ submitButton.Clicked += () =>
+ {
+ if (Directory.Exists(Path.Combine(Globals.ProjectFolder, "Plugins", nameTextBox.Text)))
+ {
+ Debug.Logger.LogHandler.LogWrite(LogType.Warning, "Cannot create plugin due to name conflict.");
+ return;
+ }
+ OnCreateButtonClicked(nameTextBox.Text, versionTextBox.Text, companyTextBox.Text);
+ nameTextBox.Clear();
+ versionTextBox.Clear();
+ companyTextBox.Clear();
+ popup.Hide();
+ };
+
+ var cancelButton = new Button
+ {
+ Parent = popup,
+ AnchorPreset = AnchorPresets.TopLeft,
+ Text = "Cancel",
+ Width = 70,
+ };
+ cancelButton.LocalX += 120;
+ cancelButton.LocalY += 90;
+
+ cancelButton.Clicked += () =>
+ {
+ nameTextBox.Clear();
+ versionTextBox.Clear();
+ companyTextBox.Clear();
+ popup.Hide();
+ };
+ }
+
+ private async void OnCreateButtonClicked(string pluginName, string pluginVersion, string companyName)
+ {
+ if (string.IsNullOrEmpty(pluginName))
+ {
+ Debug.Logger.LogHandler.LogWrite(LogType.Error, $"Failed to create plugin project due to no plugin name.");
+ return;
+ }
+
+ var templateUrl = "https://github.com/FlaxEngine/ExamplePlugin/archive/refs/heads/master.zip";
+ var localTemplateFolderLocation = Path.Combine(Editor.LocalCachePath, "TemplatePluginCache");
+ if (!Directory.Exists(localTemplateFolderLocation))
+ Directory.CreateDirectory(localTemplateFolderLocation);
+ var localTemplatePath = localTemplateFolderLocation + @"\TemplatePlugin.zip";
+
+ try
+ {
+ // Download example plugin
+ using (HttpClient client = new HttpClient())
+ {
+ byte[] zipBytes = await client.GetByteArrayAsync(templateUrl);
+ await File.WriteAllBytesAsync(!File.Exists(localTemplatePath) ? Path.Combine(localTemplatePath) : Path.Combine(Editor.LocalCachePath, "TemplatePluginCache") + @"\TemplatePlugin1.zip", zipBytes);
+
+ Debug.Logger.LogHandler.LogWrite(LogType.Info, "Template for plugin project has downloaded");
+ }
+ }
+ catch (Exception e)
+ {
+ Debug.Logger.LogHandler.LogWrite(LogType.Error, $"Failed to download template project. Trying to use local file. {e}");
+ if (!File.Exists(localTemplatePath))
+ {
+ Debug.Logger.LogHandler.LogWrite(LogType.Error, $"Failed to use local file. Does not exist.");
+ return;
+ }
+ }
+
+ // Check if any changes in new downloaded file
+ if (File.Exists(Path.Combine(Editor.LocalCachePath, "TemplatePluginCache") + @"\TemplatePlugin1.zip"))
+ {
+ var localTemplatePath2 = Path.Combine(Editor.LocalCachePath, "TemplatePluginCache") + @"\TemplatePlugin1.zip";
+ bool areDifferent = false;
+ using (var zip1 = ZipFile.OpenRead(localTemplatePath))
+ {
+ using (var zip2 = ZipFile.OpenRead(localTemplatePath2))
+ {
+ if (zip1.Entries.Count != zip2.Entries.Count)
+ {
+ areDifferent = true;
+ }
+
+ foreach (ZipArchiveEntry entry1 in zip1.Entries)
+ {
+ ZipArchiveEntry entry2 = zip2.GetEntry(entry1.FullName);
+ if (entry2 == null)
+ {
+ areDifferent = true;
+ break;
+ }
+ if (entry1.Length != entry2.Length || entry1.CompressedLength != entry2.CompressedLength || entry1.Crc32 != entry2.Crc32)
+ {
+ areDifferent = true;
+ break;
+ }
+ }
+ }
+ }
+ if (areDifferent)
+ {
+ File.Delete(localTemplatePath);
+ File.Move(localTemplatePath2, localTemplatePath);
+ }
+ else
+ {
+ File.Delete(localTemplatePath2);
+ }
+ }
+
+ var extractPath = Path.Combine(Globals.ProjectFolder, "Plugins");
+ if (!Directory.Exists(extractPath))
+ Directory.CreateDirectory(extractPath);
+
+ try
+ {
+ await Task.Run(() => ZipFile.ExtractToDirectory(localTemplatePath, extractPath));
+ Debug.Logger.LogHandler.LogWrite(LogType.Info, "Template for plugin project successfully moved to project.");
+ }
+ catch (IOException e)
+ {
+ Debug.Logger.LogHandler.LogWrite(LogType.Error, $"Failed to add plugin to project. {e}");
+ }
+
+ var oldpluginPath = Path.Combine(extractPath, "ExamplePlugin-master");
+ var newPluginPath = Path.Combine(extractPath , pluginName);
+ Directory.Move(oldpluginPath, newPluginPath);
+
+ var oldFlaxProjFile = Path.Combine(newPluginPath, "ExamplePlugin.flaxproj");
+ var newFlaxProjFile = Path.Combine(newPluginPath, $"{pluginName}.flaxproj");
+ File.Move(oldFlaxProjFile, newFlaxProjFile);
+
+ var readme = Path.Combine(newPluginPath, "README.md");
+ if (File.Exists(readme))
+ File.Delete(readme);
+ var license = Path.Combine(newPluginPath, "LICENSE");
+ if (File.Exists(license))
+ File.Delete(license);
+
+ // Flax plugin project file
+ var flaxPluginProjContents = JsonSerializer.Deserialize(await File.ReadAllTextAsync(newFlaxProjFile));
+ flaxPluginProjContents.Name = pluginName;
+ if (!string.IsNullOrEmpty(pluginVersion))
+ flaxPluginProjContents.Version = new Version(pluginVersion);
+ if (!string.IsNullOrEmpty(companyName))
+ flaxPluginProjContents.Company = companyName;
+ flaxPluginProjContents.GameTarget = $"{pluginName}Target";
+ flaxPluginProjContents.EditorTarget = $"{pluginName}EditorTarget";
+ await File.WriteAllTextAsync(newFlaxProjFile, JsonSerializer.Serialize(flaxPluginProjContents, typeof(ProjectInfo)));
+
+ // Rename source directories
+ var sourcePath = Path.Combine(newPluginPath, "Source");
+ var sourceDirectories = Directory.GetDirectories(sourcePath);
+ foreach (var directory in sourceDirectories)
+ {
+ var files = Directory.GetFiles(directory);
+ foreach (var file in files)
+ {
+ if (file.Contains("MyPlugin.cs") || file.Contains("MyPluginEditor.cs"))
+ {
+ File.Delete(file);
+ continue;
+ }
+
+ var fileText = await File.ReadAllTextAsync(file);
+ await File.WriteAllTextAsync(file, fileText.Replace("ExamplePlugin", pluginName));
+ var fileName = Path.GetFileName(file).Replace("ExamplePlugin", pluginName);
+ File.Move(file, Path.Combine(directory, fileName));
+ }
+
+ var newName = directory.Replace("ExamplePlugin", pluginName);
+ Directory.Move(directory, newName);
+ }
+
+ // Rename targets
+ var targetFiles = Directory.GetFiles(sourcePath);
+ foreach (var file in targetFiles)
+ {
+ var fileText = await File.ReadAllTextAsync(file);
+ await File.WriteAllTextAsync(file, fileText.Replace("ExamplePlugin", pluginName));
+ var newName = file.Replace("ExamplePlugin", pluginName);
+ File.Move(file, newName);
+ }
+ Debug.Logger.LogHandler.LogWrite(LogType.Info, $"Plugin project {pluginName} has successfully been created.");
+
+ await AddReferenceToProject(pluginName, pluginName);
+ MessageBox.Show($"{pluginName} has been successfully created. Restart editor for changes to take effect.", "Plugin Project Created", MessageBoxButtons.OK);
+ }
+
+ private async Task AddReferenceToProject(string pluginFolderName, string pluginName)
+ {
+ // Project flax config file
+ var flaxProjPath = Editor.GameProject.ProjectPath;
+ if (File.Exists(flaxProjPath))
+ {
+ var flaxProjContents = JsonSerializer.Deserialize(await File.ReadAllTextAsync(flaxProjPath));
+ var oldReferences = flaxProjContents.References;
+ var references = new List(oldReferences);
+ var newPath = $"$(ProjectPath)/Plugins/{pluginFolderName}/{pluginName}.flaxproj";
+ if (!references.Exists(x => string.Equals(x.Name, newPath)))
+ {
+ var newReference = new ProjectInfo.Reference
+ {
+ Name = newPath,
+ };
+ references.Add(newReference);
+ }
+ flaxProjContents.References = references.ToArray();
+ await File.WriteAllTextAsync(flaxProjPath, JsonSerializer.Serialize(flaxProjContents, typeof(ProjectInfo)));
+ }
+ }
+
+
private void OnPluginsChanged()
{
List toRemove = null;
@@ -312,6 +860,10 @@ namespace FlaxEditor.Windows
///
public override void OnDestroy()
{
+ if (_addPluginProjectButton != null)
+ _addPluginProjectButton.Clicked -= OnAddButtonClicked;
+ if (_cloneProjectButton != null)
+ _cloneProjectButton.Clicked -= OnCloneProjectButtonClicked;
PluginManager.PluginsChanged -= OnPluginsChanged;
base.OnDestroy();
From 51664fc236dfc748185dab7ab0ac6323defb1ede Mon Sep 17 00:00:00 2001
From: Chandler Cox
Date: Thu, 24 Aug 2023 13:51:08 -0500
Subject: [PATCH 04/40] Use pltform process.
---
Source/Editor/Windows/PluginsWindow.cs | 21 ++++++---------------
1 file changed, 6 insertions(+), 15 deletions(-)
diff --git a/Source/Editor/Windows/PluginsWindow.cs b/Source/Editor/Windows/PluginsWindow.cs
index 451e58afa..deac0d9ce 100644
--- a/Source/Editor/Windows/PluginsWindow.cs
+++ b/Source/Editor/Windows/PluginsWindow.cs
@@ -2,7 +2,6 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
@@ -376,20 +375,12 @@ namespace FlaxEditor.Windows
try
{
// Start git clone
- var gitProcess = new Process();
- gitProcess.StartInfo.FileName = "git";
- gitProcess.StartInfo.Arguments = $"clone {gitPath} \"{clonePath}\"";
- gitProcess.StartInfo.UseShellExecute = false;
- gitProcess.StartInfo.RedirectStandardOutput = true;
- gitProcess.StartInfo.RedirectStandardError = true;
-
- gitProcess.Start();
- await gitProcess.WaitForExitAsync();
-
- string output = await gitProcess.StandardOutput.ReadToEndAsync();
- string error = await gitProcess.StandardError.ReadToEndAsync();
- Debug.Logger.LogHandler.LogWrite(LogType.Info, $"{output}");
- Debug.Logger.LogHandler.LogWrite(LogType.Info, $"{error}");
+ var settings = new CreateProcessSettings();
+ settings.FileName = "git";
+ settings.Arguments = $"clone {gitPath} \"{clonePath}\"";
+ settings.ShellExecute = false;
+ settings.LogOutput = true;
+ Platform.CreateProcess(ref settings);
}
catch (Exception e)
{
From 0bbd619e329a355fff606afa4fff6c1bb1f06832 Mon Sep 17 00:00:00 2001
From: Chandler Cox
Date: Thu, 24 Aug 2023 13:54:55 -0500
Subject: [PATCH 05/40] Code cleanup
---
Source/Editor/Windows/PluginsWindow.cs | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/Source/Editor/Windows/PluginsWindow.cs b/Source/Editor/Windows/PluginsWindow.cs
index deac0d9ce..cf68c6ad8 100644
--- a/Source/Editor/Windows/PluginsWindow.cs
+++ b/Source/Editor/Windows/PluginsWindow.cs
@@ -384,7 +384,7 @@ namespace FlaxEditor.Windows
}
catch (Exception e)
{
- Debug.Logger.LogHandler.LogWrite(LogType.Error, $"Failed Gir process. {e}");
+ Debug.Logger.LogHandler.LogWrite(LogType.Error, $"Failed Git process. {e}");
return;
}
@@ -559,7 +559,7 @@ namespace FlaxEditor.Windows
var localTemplateFolderLocation = Path.Combine(Editor.LocalCachePath, "TemplatePluginCache");
if (!Directory.Exists(localTemplateFolderLocation))
Directory.CreateDirectory(localTemplateFolderLocation);
- var localTemplatePath = localTemplateFolderLocation + @"\TemplatePlugin.zip";
+ var localTemplatePath = Path.Combine(localTemplateFolderLocation, "TemplatePlugin.zip");
try
{
@@ -567,7 +567,7 @@ namespace FlaxEditor.Windows
using (HttpClient client = new HttpClient())
{
byte[] zipBytes = await client.GetByteArrayAsync(templateUrl);
- await File.WriteAllBytesAsync(!File.Exists(localTemplatePath) ? Path.Combine(localTemplatePath) : Path.Combine(Editor.LocalCachePath, "TemplatePluginCache") + @"\TemplatePlugin1.zip", zipBytes);
+ await File.WriteAllBytesAsync(!File.Exists(localTemplatePath) ? Path.Combine(localTemplatePath) : Path.Combine(Editor.LocalCachePath, "TemplatePluginCache" , "TemplatePlugin1.zip"), zipBytes);
Debug.Logger.LogHandler.LogWrite(LogType.Info, "Template for plugin project has downloaded");
}
@@ -583,9 +583,9 @@ namespace FlaxEditor.Windows
}
// Check if any changes in new downloaded file
- if (File.Exists(Path.Combine(Editor.LocalCachePath, "TemplatePluginCache") + @"\TemplatePlugin1.zip"))
+ if (File.Exists(Path.Combine(Editor.LocalCachePath, "TemplatePluginCache", "TemplatePlugin1.zip")))
{
- var localTemplatePath2 = Path.Combine(Editor.LocalCachePath, "TemplatePluginCache") + @"\TemplatePlugin1.zip";
+ var localTemplatePath2 = Path.Combine(Editor.LocalCachePath, "TemplatePluginCache", "TemplatePlugin1.zip");
bool areDifferent = false;
using (var zip1 = ZipFile.OpenRead(localTemplatePath))
{
From ff2f239858a6bc1690d670d9985e44c3ec655890 Mon Sep 17 00:00:00 2001
From: Chandler Cox
Date: Fri, 25 Aug 2023 08:17:09 -0500
Subject: [PATCH 06/40] Add system reference.
---
Source/Editor/Editor.Build.cs | 1 +
1 file changed, 1 insertion(+)
diff --git a/Source/Editor/Editor.Build.cs b/Source/Editor/Editor.Build.cs
index a971dbefa..f497225bb 100644
--- a/Source/Editor/Editor.Build.cs
+++ b/Source/Editor/Editor.Build.cs
@@ -41,6 +41,7 @@ public class Editor : EditorModule
options.ScriptingAPI.SystemReferences.Add("System.Xml.ReaderWriter");
options.ScriptingAPI.SystemReferences.Add("System.Text.RegularExpressions");
options.ScriptingAPI.SystemReferences.Add("System.ComponentModel.TypeConverter");
+ options.ScriptingAPI.SystemReferences.Add("System.IO.Compression.ZipFile");
// Enable optimizations for Editor, disable this for debugging the editor
if (options.Configuration == TargetConfiguration.Development)
From 5b5c298a960a7d096af06ef512ec56d406dfa4ce Mon Sep 17 00:00:00 2001
From: Chandler Cox
Date: Fri, 1 Sep 2023 06:35:52 -0500
Subject: [PATCH 07/40] Add remove tag method to actor.
---
Source/Engine/Level/Actor.cpp | 5 +++++
Source/Engine/Level/Actor.h | 6 ++++++
2 files changed, 11 insertions(+)
diff --git a/Source/Engine/Level/Actor.cpp b/Source/Engine/Level/Actor.cpp
index 8185f3b9d..a9d136b30 100644
--- a/Source/Engine/Level/Actor.cpp
+++ b/Source/Engine/Level/Actor.cpp
@@ -476,6 +476,11 @@ void Actor::AddTag(const Tag& tag)
Tags.AddUnique(tag);
}
+void Actor::RemoveTag(const Tag& tag)
+{
+ Tags.Remove(tag);
+}
+
PRAGMA_DISABLE_DEPRECATION_WARNINGS
const String& Actor::GetTag() const
diff --git a/Source/Engine/Level/Actor.h b/Source/Engine/Level/Actor.h
index 510bc9eb8..8643dba05 100644
--- a/Source/Engine/Level/Actor.h
+++ b/Source/Engine/Level/Actor.h
@@ -136,6 +136,12 @@ public:
/// The tag to add.
API_FUNCTION() void AddTag(const Tag& tag);
+ ///
+ /// Removes a tag to the actor
+ ///
+ /// The tag to remove.
+ API_FUNCTION() void RemoveTag(const Tag& tag);
+
///
/// Gets the name of the tag.
/// [Deprecated in v1.5]
From 53861c479580ba36aa956fb282578be3b5acd924 Mon Sep 17 00:00:00 2001
From: Chandler Cox
Date: Fri, 1 Sep 2023 14:28:26 -0500
Subject: [PATCH 08/40] Improve content item in tile view. Decrease margin
between list view items.
---
Source/Editor/Content/GUI/ContentView.cs | 15 ++---
Source/Editor/Content/Items/ContentItem.cs | 71 ++++++++++++++++++----
2 files changed, 66 insertions(+), 20 deletions(-)
diff --git a/Source/Editor/Content/GUI/ContentView.cs b/Source/Editor/Content/GUI/ContentView.cs
index 6065ca9f8..40a06c1b6 100644
--- a/Source/Editor/Content/GUI/ContentView.cs
+++ b/Source/Editor/Content/GUI/ContentView.cs
@@ -711,7 +711,7 @@ namespace FlaxEditor.Content.GUI
protected override void PerformLayoutBeforeChildren()
{
float width = GetClientArea().Width;
- float x = 0, y = 0;
+ float x = 0, y = 1;
float viewScale = _viewScale * 0.97f;
switch (ViewType)
@@ -722,21 +722,22 @@ namespace FlaxEditor.Content.GUI
int itemsToFit = Mathf.FloorToInt(width / defaultItemsWidth) - 1;
if (itemsToFit < 1)
itemsToFit = 1;
- float itemsWidth = width / Mathf.Max(itemsToFit, 1);
+ int xSpace = 4;
+ float itemsWidth = width / Mathf.Max(itemsToFit, 1) - xSpace;
float itemsHeight = itemsWidth / defaultItemsWidth * (ContentItem.DefaultHeight * viewScale);
var flooredItemsWidth = Mathf.Floor(itemsWidth);
var flooredItemsHeight = Mathf.Floor(itemsHeight);
- x = itemsToFit == 1 ? 0 : itemsWidth / itemsToFit;
+ x = itemsToFit == 1 ? 1 : itemsWidth / itemsToFit + xSpace;
for (int i = 0; i < _children.Count; i++)
{
var c = _children[i];
c.Bounds = new Rectangle(Mathf.Floor(x), Mathf.Floor(y), flooredItemsWidth, flooredItemsHeight);
- x += itemsWidth + itemsWidth / itemsToFit;
+ x += (itemsWidth + xSpace) + (itemsWidth + xSpace) / itemsToFit;
if (x + itemsWidth > width)
{
- x = itemsToFit == 1 ? 0 : itemsWidth / itemsToFit;
- y += itemsHeight + 5;
+ x = itemsToFit == 1 ? 1 : itemsWidth / itemsToFit + xSpace;
+ y += itemsHeight + 7;
}
}
if (x > 0)
@@ -751,7 +752,7 @@ namespace FlaxEditor.Content.GUI
{
var c = _children[i];
c.Bounds = new Rectangle(x, y, width, itemsHeight);
- y += itemsHeight + 5;
+ y += itemsHeight + 1;
}
y += 40.0f;
diff --git a/Source/Editor/Content/Items/ContentItem.cs b/Source/Editor/Content/Items/ContentItem.cs
index 66825fb42..41f35b4c7 100644
--- a/Source/Editor/Content/Items/ContentItem.cs
+++ b/Source/Editor/Content/Items/ContentItem.cs
@@ -483,6 +483,30 @@ namespace FlaxEditor.Content
else
Render2D.FillRectangle(rectangle, Color.Black);
}
+
+ ///
+ /// Draws the item thumbnail.
+ ///
+ /// The thumbnail rectangle.
+ /// /// Whether or not to draw the shadow. Overrides DrawShadow.
+ public void DrawThumbnail(ref Rectangle rectangle, bool shadow)
+ {
+ // Draw shadow
+ if (shadow)
+ {
+ const float thumbnailInShadowSize = 50.0f;
+ var shadowRect = rectangle.MakeExpanded((DefaultThumbnailSize - thumbnailInShadowSize) * rectangle.Width / DefaultThumbnailSize * 1.3f);
+ if (!_shadowIcon.IsValid)
+ _shadowIcon = Editor.Instance.Icons.AssetShadow128;
+ Render2D.DrawSprite(_shadowIcon, shadowRect);
+ }
+
+ // Draw thumbnail
+ if (_thumbnail.IsValid)
+ Render2D.DrawSprite(_thumbnail, rectangle);
+ else
+ Render2D.FillRectangle(rectangle, Color.Black);
+ }
///
/// Gets the amount of references to that item.
@@ -655,9 +679,32 @@ namespace FlaxEditor.Content
{
case ContentViewType.Tiles:
{
- var thumbnailSize = size.X - 2 * DefaultMarginSize;
- thumbnailRect = new Rectangle(DefaultMarginSize, DefaultMarginSize, thumbnailSize, thumbnailSize);
+ var thumbnailSize = size.X;
+ thumbnailRect = new Rectangle(0, 0, thumbnailSize, thumbnailSize);
nameAlignment = TextAlignment.Center;
+
+ // Small shadow
+ var shadowRect = new Rectangle(2, 2, clientRect.Width + 1, clientRect.Height + 1);
+ var color = Color.Black.AlphaMultiplied(0.2f);
+ Render2D.FillRectangle(shadowRect, color);
+
+ Render2D.FillRectangle(clientRect, style.LightBackground);
+ Render2D.FillRectangle(TextRectangle, style.TextBoxBackground);
+ var accentHeight = 2 * view.ViewScale;
+ var barRect = new Rectangle(0, thumbnailRect.Height - accentHeight, clientRect.Width, accentHeight);
+ Render2D.FillRectangle(barRect, Color.DimGray);
+
+ DrawThumbnail(ref thumbnailRect, false);
+ if (isSelected)
+ {
+ Render2D.FillRectangle(textRect, Parent.ContainsFocus ? style.BackgroundSelected : style.LightBackground);
+ Render2D.DrawRectangle(clientRect, Parent.ContainsFocus ? style.BackgroundSelected : style.LightBackground);
+ }
+ else if (IsMouseOver)
+ {
+ Render2D.FillRectangle(textRect, style.BackgroundHighlighted);
+ Render2D.DrawRectangle(clientRect, style.BackgroundHighlighted);
+ }
break;
}
case ContentViewType.List:
@@ -665,23 +712,21 @@ namespace FlaxEditor.Content
var thumbnailSize = size.Y - 2 * DefaultMarginSize;
thumbnailRect = new Rectangle(DefaultMarginSize, DefaultMarginSize, thumbnailSize, thumbnailSize);
nameAlignment = TextAlignment.Near;
+
+ if (isSelected)
+ Render2D.FillRectangle(clientRect, Parent.ContainsFocus ? style.BackgroundSelected : style.LightBackground);
+ else if (IsMouseOver)
+ Render2D.FillRectangle(clientRect, style.BackgroundHighlighted);
+
+ DrawThumbnail(ref thumbnailRect);
break;
}
default: throw new ArgumentOutOfRangeException();
}
-
- // Draw background
- if (isSelected)
- Render2D.FillRectangle(clientRect, Parent.ContainsFocus ? style.BackgroundSelected : style.LightBackground);
- else if (IsMouseOver)
- Render2D.FillRectangle(clientRect, style.BackgroundHighlighted);
-
- // Draw preview
- DrawThumbnail(ref thumbnailRect);
-
+
// Draw short name
Render2D.PushClip(ref textRect);
- Render2D.DrawText(style.FontMedium, ShowFileExtension || view.ShowFileExtensions ? FileName : ShortName, textRect, style.Foreground, nameAlignment, TextAlignment.Center, TextWrapping.WrapWords, 0.75f, 0.95f);
+ Render2D.DrawText(style.FontMedium, ShowFileExtension || view.ShowFileExtensions ? FileName : ShortName, textRect, style.Foreground, nameAlignment, TextAlignment.Center, TextWrapping.WrapWords, 1f, 0.95f);
Render2D.PopClip();
}
From 67909e33c824068df4f4dd3a19aecb908dfefff2 Mon Sep 17 00:00:00 2001
From: Chandler Cox
Date: Fri, 1 Sep 2023 16:37:14 -0500
Subject: [PATCH 09/40] Add difference for folders.
---
Source/Editor/Content/Items/ContentItem.cs | 55 +++++++++++++++-------
1 file changed, 37 insertions(+), 18 deletions(-)
diff --git a/Source/Editor/Content/Items/ContentItem.cs b/Source/Editor/Content/Items/ContentItem.cs
index 41f35b4c7..b27159aa0 100644
--- a/Source/Editor/Content/Items/ContentItem.cs
+++ b/Source/Editor/Content/Items/ContentItem.cs
@@ -683,27 +683,46 @@ namespace FlaxEditor.Content
thumbnailRect = new Rectangle(0, 0, thumbnailSize, thumbnailSize);
nameAlignment = TextAlignment.Center;
- // Small shadow
- var shadowRect = new Rectangle(2, 2, clientRect.Width + 1, clientRect.Height + 1);
- var color = Color.Black.AlphaMultiplied(0.2f);
- Render2D.FillRectangle(shadowRect, color);
-
- Render2D.FillRectangle(clientRect, style.LightBackground);
- Render2D.FillRectangle(TextRectangle, style.TextBoxBackground);
- var accentHeight = 2 * view.ViewScale;
- var barRect = new Rectangle(0, thumbnailRect.Height - accentHeight, clientRect.Width, accentHeight);
- Render2D.FillRectangle(barRect, Color.DimGray);
-
- DrawThumbnail(ref thumbnailRect, false);
- if (isSelected)
+ if (this is ContentFolder)
{
- Render2D.FillRectangle(textRect, Parent.ContainsFocus ? style.BackgroundSelected : style.LightBackground);
- Render2D.DrawRectangle(clientRect, Parent.ContainsFocus ? style.BackgroundSelected : style.LightBackground);
+ // Small shadow
+ var shadowRect = new Rectangle(2, 2, clientRect.Width + 1, clientRect.Height + 1);
+ var color = Color.Black.AlphaMultiplied(0.2f);
+ Render2D.FillRectangle(shadowRect, color);
+ Render2D.FillRectangle(clientRect, style.Background.RGBMultiplied(1.25f));
+
+ if (isSelected)
+ Render2D.FillRectangle(clientRect, Parent.ContainsFocus ? style.BackgroundSelected : style.LightBackground);
+ else if (IsMouseOver)
+ Render2D.FillRectangle(clientRect, style.BackgroundHighlighted);
+
+ DrawThumbnail(ref thumbnailRect, false);
}
- else if (IsMouseOver)
+ else
{
- Render2D.FillRectangle(textRect, style.BackgroundHighlighted);
- Render2D.DrawRectangle(clientRect, style.BackgroundHighlighted);
+ // Small shadow
+ var shadowRect = new Rectangle(2, 2, clientRect.Width + 1, clientRect.Height + 1);
+ var color = Color.Black.AlphaMultiplied(0.2f);
+ Render2D.FillRectangle(shadowRect, color);
+
+ Render2D.FillRectangle(clientRect, style.Background.RGBMultiplied(1.25f));
+ Render2D.FillRectangle(TextRectangle, style.LightBackground);
+
+ var accentHeight = 2 * view.ViewScale;
+ var barRect = new Rectangle(0, thumbnailRect.Height - accentHeight, clientRect.Width, accentHeight);
+ Render2D.FillRectangle(barRect, Color.DimGray);
+
+ DrawThumbnail(ref thumbnailRect, false);
+ if (isSelected)
+ {
+ Render2D.FillRectangle(textRect, Parent.ContainsFocus ? style.BackgroundSelected : style.LightBackground);
+ Render2D.DrawRectangle(clientRect, Parent.ContainsFocus ? style.BackgroundSelected : style.LightBackground);
+ }
+ else if (IsMouseOver)
+ {
+ Render2D.FillRectangle(textRect, style.BackgroundHighlighted);
+ Render2D.DrawRectangle(clientRect, style.BackgroundHighlighted);
+ }
}
break;
}
From 92a5432d224f105e5f526a47656dbddd82fc3e60 Mon Sep 17 00:00:00 2001
From: Chandler Cox
Date: Sat, 2 Sep 2023 13:13:34 -0500
Subject: [PATCH 10/40] Sort plugin projects in content tree.
---
Source/Editor/Windows/ContentWindow.cs | 1 +
1 file changed, 1 insertion(+)
diff --git a/Source/Editor/Windows/ContentWindow.cs b/Source/Editor/Windows/ContentWindow.cs
index b1f04c8f5..9d782b13b 100644
--- a/Source/Editor/Windows/ContentWindow.cs
+++ b/Source/Editor/Windows/ContentWindow.cs
@@ -931,6 +931,7 @@ namespace FlaxEditor.Windows
// Add game project on top, plugins in the middle and engine at bottom
_root.AddChild(Editor.ContentDatabase.Game);
+ Editor.ContentDatabase.Projects.Sort();
foreach (var project in Editor.ContentDatabase.Projects)
{
project.SortChildrenRecursive();
From afec6afe4c9e9d57c903fd1e363db5258f6bc06d Mon Sep 17 00:00:00 2001
From: Ari Vuollet
Date: Sun, 3 Sep 2023 14:04:46 +0300
Subject: [PATCH 11/40] Fix managed UTF-8 string allocation not using correct
encoding
---
Source/Engine/Engine/NativeInterop.Unmanaged.cs | 4 ++--
Source/Engine/Scripting/Runtime/DotNet.cpp | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Source/Engine/Engine/NativeInterop.Unmanaged.cs b/Source/Engine/Engine/NativeInterop.Unmanaged.cs
index 879f804d2..2c1bab744 100644
--- a/Source/Engine/Engine/NativeInterop.Unmanaged.cs
+++ b/Source/Engine/Engine/NativeInterop.Unmanaged.cs
@@ -581,9 +581,9 @@ namespace FlaxEngine.Interop
}
[UnmanagedCallersOnly]
- internal static IntPtr NewStringLength(sbyte* text, int length)
+ internal static IntPtr NewStringUTF8(sbyte* text, int length)
{
- return ManagedString.ToNativeWeak(new string(text, 0, length));
+ return ManagedString.ToNativeWeak(new string(text, 0, length, System.Text.Encoding.UTF8));
}
[UnmanagedCallersOnly]
diff --git a/Source/Engine/Scripting/Runtime/DotNet.cpp b/Source/Engine/Scripting/Runtime/DotNet.cpp
index f4ae5b1ec..1bcef50b8 100644
--- a/Source/Engine/Scripting/Runtime/DotNet.cpp
+++ b/Source/Engine/Scripting/Runtime/DotNet.cpp
@@ -365,8 +365,8 @@ MString* MCore::String::GetEmpty(MDomain* domain)
MString* MCore::String::New(const char* str, int32 length, MDomain* domain)
{
- static void* NewStringLengthPtr = GetStaticMethodPointer(TEXT("NewStringLength"));
- return (MString*)CallStaticMethod(NewStringLengthPtr, str, length);
+ static void* NewStringUTF8Ptr = GetStaticMethodPointer(TEXT("NewStringUTF8"));
+ return (MString*)CallStaticMethod(NewStringUTF8Ptr, str, length);
}
MString* MCore::String::New(const Char* str, int32 length, MDomain* domain)
From 924e1c6d81efca81b3aaf3af2b1f863e349c4ec8 Mon Sep 17 00:00:00 2001
From: Chandler Cox
Date: Sun, 3 Sep 2023 06:36:29 -0500
Subject: [PATCH 12/40] Fix right click deselecting scene tree nodes.
---
Source/Editor/GUI/Tree/TreeNode.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Source/Editor/GUI/Tree/TreeNode.cs b/Source/Editor/GUI/Tree/TreeNode.cs
index ced70a281..1a1ebe5a1 100644
--- a/Source/Editor/GUI/Tree/TreeNode.cs
+++ b/Source/Editor/GUI/Tree/TreeNode.cs
@@ -762,7 +762,7 @@ namespace FlaxEditor.GUI.Tree
// Add/Remove
tree.AddOrRemoveSelection(this);
}
- else
+ else if (button != MouseButton.Right)
{
// Select
tree.Select(this);
From 39ecfe8c242940126c394ac8bd2c2e042beff4a2 Mon Sep 17 00:00:00 2001
From: Chandler Cox
Date: Sun, 3 Sep 2023 12:11:33 -0500
Subject: [PATCH 13/40] Small bug fix
---
Source/Editor/GUI/Tree/TreeNode.cs | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/Source/Editor/GUI/Tree/TreeNode.cs b/Source/Editor/GUI/Tree/TreeNode.cs
index 1a1ebe5a1..7e3af05bf 100644
--- a/Source/Editor/GUI/Tree/TreeNode.cs
+++ b/Source/Editor/GUI/Tree/TreeNode.cs
@@ -762,7 +762,11 @@ namespace FlaxEditor.GUI.Tree
// Add/Remove
tree.AddOrRemoveSelection(this);
}
- else if (button != MouseButton.Right)
+ else if (button == MouseButton.Right && tree.Selection.Contains(this))
+ {
+ // Do nothing
+ }
+ else
{
// Select
tree.Select(this);
From 20f35e332f309a13512b2982627fd7736da9ab02 Mon Sep 17 00:00:00 2001
From: Chandler Cox
Date: Mon, 4 Sep 2023 20:15:59 -0500
Subject: [PATCH 14/40] Add slider control
---
Source/Engine/UI/GUI/Common/Slider.cs | 347 ++++++++++++++++++++++++++
1 file changed, 347 insertions(+)
create mode 100644 Source/Engine/UI/GUI/Common/Slider.cs
diff --git a/Source/Engine/UI/GUI/Common/Slider.cs b/Source/Engine/UI/GUI/Common/Slider.cs
new file mode 100644
index 000000000..06c73f15e
--- /dev/null
+++ b/Source/Engine/UI/GUI/Common/Slider.cs
@@ -0,0 +1,347 @@
+using System;
+
+namespace FlaxEngine.GUI;
+
+///
+/// The slider control.
+///
+public class Slider : ContainerControl
+{
+ ///
+ /// The minimum value.
+ ///
+ protected float _minimum;
+
+ ///
+ /// The maximum value.
+ ///
+ protected float _maximum = 100f;
+
+ ///
+ /// Gets or sets the minimum value.
+ ///
+ [EditorOrder(20), Tooltip("The minimum value.")]
+ public float Minimum
+ {
+ get => _minimum;
+ set
+ {
+ if (value > _maximum)
+ throw new ArgumentOutOfRangeException();
+ if (WholeNumbers)
+ value = Mathf.RoundToInt(value);
+ _minimum = value;
+ if (Value < _minimum)
+ Value = _minimum;
+ }
+ }
+
+ ///
+ /// Gets or sets the maximum value.
+ ///
+ [EditorOrder(30), Tooltip("The maximum value.")]
+ public float Maximum
+ {
+ get => _maximum;
+ set
+ {
+ if (value < _minimum || Mathf.IsZero(value))
+ throw new ArgumentOutOfRangeException();
+ if (WholeNumbers)
+ value = Mathf.RoundToInt(value);
+ _maximum = value;
+ if (Value > _maximum)
+ Value = _maximum;
+ }
+ }
+
+ private float _value = 100f;
+ private Rectangle _thumbRect;
+ private float _thumbCenter;
+ private Float2 _thumbSize = new Float2(16, 16);
+ private bool _isSliding;
+
+ ///
+ /// Gets or sets the value (normalized to range 0-100).
+ ///
+ [EditorOrder(10), Tooltip("The current value.")]
+ public float Value
+ {
+ get => _value;
+ set
+ {
+ value = Mathf.Clamp(value, Minimum, Maximum);
+ if (WholeNumbers)
+ value = Mathf.RoundToInt(value);
+ if (!Mathf.NearEqual(value, _value))
+ {
+ _value = value;
+
+ // Update
+ UpdateThumb();
+ ValueChanged?.Invoke();
+ }
+ }
+ }
+
+ ///
+ /// The height of the track.
+ ///
+ [EditorOrder(40), Tooltip("The track height.")]
+ public int TrackHeight { get; set; } = 2;
+
+ ///
+ /// The thumb size.
+ ///
+ [EditorOrder(41), Tooltip("The size of the thumb.")]
+ public Float2 ThumbSize {
+ get => _thumbSize;
+ set
+ {
+ _thumbSize = value;
+ UpdateThumb();
+ }
+ }
+
+ ///
+ /// Whether to fill the track.
+ ///
+ [EditorOrder(42), Tooltip("Fill the track.")]
+ public bool FillTrack = true;
+
+ ///
+ /// Whether to use whole numbers.
+ ///
+ [EditorOrder(43), Tooltip("Use whole numbers.")]
+ public bool WholeNumbers = false;
+
+ ///
+ /// The color of the slider track line
+ ///
+ [EditorDisplay("Track Style"), EditorOrder(2010), Tooltip("The color of the slider track line."), ExpandGroups]
+ public Color TrackLineColor { get; set; }
+
+ ///
+ /// The color of the slider fill track line
+ ///
+ [EditorDisplay("Track Style"), EditorOrder(2011), VisibleIf(nameof(FillTrack)), Tooltip("The color of the slider fill track line.")]
+ public Color TrackFillLineColor { get; set; }
+
+ ///
+ /// Gets the size of the track.
+ ///
+ private float TrackWidth => Width;
+
+ ///
+ /// Gets or sets the brush used for slider track drawing.
+ ///
+ [EditorDisplay("Track Style"), EditorOrder(2012), Tooltip("The brush used for slider track drawing.")]
+ public IBrush TrackBrush { get; set; }
+
+ ///
+ /// Gets or sets the brush used for slider fill track drawing.
+ ///
+ [EditorDisplay("Track Style"), EditorOrder(2013), VisibleIf(nameof(FillTrack)), Tooltip("The brush used for slider fill track drawing.")]
+ public IBrush FillTrackBrush { get; set; }
+
+ ///
+ /// The color of the slider thumb when it's not selected
+ ///
+ [EditorDisplay("Thumb Style"), EditorOrder(2030), Tooltip("The color of the slider thumb when it's not selected."), ExpandGroups]
+ public Color ThumbColor { get; set; }
+
+ ///
+ /// The color of the slider thumb when it's selected
+ ///
+ [EditorDisplay("Thumb Style"), EditorOrder(2031), Tooltip("The color of the slider thumb when it's selected.")]
+ public Color ThumbColorSelected { get; set; }
+
+ ///
+ /// Gets or sets the brush used for slider thumb drawing.
+ ///
+ [EditorDisplay("Thumb Style"), EditorOrder(2032), Tooltip("The brush of the slider thumb.")]
+ public IBrush ThumbBrush { get; set; }
+
+ ///
+ /// Gets a value indicating whether user is using a slider.
+ ///
+ [HideInEditor]
+ public bool IsSliding => _isSliding;
+
+ ///
+ /// Occurs when sliding starts.
+ ///
+ public event Action SlidingStart;
+
+ ///
+ /// Occurs when sliding ends.
+ ///
+ public event Action SlidingEnd;
+
+ ///
+ /// Occurs when value gets changed.
+ ///
+ public event Action ValueChanged;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public Slider()
+ : this(120, 30)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The width.
+ /// The height.
+ public Slider(float width, float height)
+ : base(0, 0, width, height)
+ {
+ var style = Style.Current;
+ TrackLineColor = style.BackgroundHighlighted;
+ TrackFillLineColor = style.LightBackground;
+ ThumbColor = style.BackgroundNormal;
+ ThumbColorSelected = style.BackgroundSelected;
+ UpdateThumb();
+ }
+
+ private void UpdateThumb()
+ {
+ // Cache data
+ float trackSize = TrackWidth;
+ float range = Maximum - Minimum;
+ float pixelRange = trackSize - _thumbSize.X;
+ float perc = (_value - Minimum) / range;
+ float thumbPosition = (int)(perc * pixelRange);
+ _thumbCenter = thumbPosition + _thumbSize.X / 2;
+ _thumbRect = new Rectangle(thumbPosition, (Height - _thumbSize.Y) / 2, _thumbSize.X, _thumbSize.Y);
+ }
+
+ private void EndSliding()
+ {
+ _isSliding = false;
+ EndMouseCapture();
+ SlidingEnd?.Invoke();
+ }
+
+ ///
+ public override void Draw()
+ {
+ base.Draw();
+
+ // Draw track line
+ //var lineRect = new Rectangle(4, (Height - TrackHeight) / 2, Width - 8, TrackHeight);
+ var lineRect = new Rectangle(_thumbSize.X / 2, (Height - TrackHeight) / 2, Width - _thumbSize.X, TrackHeight);
+ if (TrackBrush != null)
+ TrackBrush.Draw(lineRect, TrackLineColor);
+ else
+ Render2D.FillRectangle(lineRect, TrackLineColor);
+
+ // Draw track fill
+ if (FillTrack)
+ {
+ var fillLineRect = new Rectangle(_thumbSize.X / 2, (Height - TrackHeight - 2) / 2, Width - (Width - _thumbCenter) - _thumbSize.X / 2, TrackHeight + 2);
+ Render2D.PushClip(ref fillLineRect);
+ if (FillTrackBrush != null)
+ FillTrackBrush.Draw(lineRect, TrackFillLineColor);
+ else
+ Render2D.FillRectangle(lineRect, TrackFillLineColor);
+ Render2D.PopClip();
+ }
+
+ // Draw thumb
+ var thumbColor = _isSliding ? ThumbColorSelected : ThumbColor;
+ if (ThumbBrush != null)
+ ThumbBrush.Draw(_thumbRect, thumbColor);
+ else
+ Render2D.FillRectangle(_thumbRect, thumbColor);
+ }
+
+ ///
+ public override void OnLostFocus()
+ {
+ if (_isSliding)
+ {
+ EndSliding();
+ }
+
+ base.OnLostFocus();
+ }
+
+ ///
+ public override bool OnMouseDown(Float2 location, MouseButton button)
+ {
+ if (button == MouseButton.Left)
+ {
+ Focus();
+ float mousePosition = location.X;
+
+ if (_thumbRect.Contains(ref location))
+ {
+ // Start sliding
+ _isSliding = true;
+ StartMouseCapture();
+ SlidingStart?.Invoke();
+ return true;
+ }
+ else
+ {
+ // Click change
+ Value += (mousePosition < _thumbCenter ? -1 : 1) * 10;
+ }
+ }
+
+ return base.OnMouseDown(location, button);
+ }
+
+ ///
+ public override void OnMouseMove(Float2 location)
+ {
+ if (_isSliding)
+ {
+ // Update sliding
+ var slidePosition = location + Root.TrackingMouseOffset;
+ Value = Mathf.Remap(slidePosition.X, 4, TrackWidth - 4, Minimum, Maximum);
+ }
+ else
+ {
+ base.OnMouseMove(location);
+ }
+ }
+
+ ///
+ public override bool OnMouseUp(Float2 location, MouseButton button)
+ {
+ if (button == MouseButton.Left && _isSliding)
+ {
+ EndSliding();
+ return true;
+ }
+
+ return base.OnMouseUp(location, button);
+ }
+
+ ///
+ public override void OnEndMouseCapture()
+ {
+ // Check if was sliding
+ if (_isSliding)
+ {
+ EndSliding();
+ }
+ else
+ {
+ base.OnEndMouseCapture();
+ }
+ }
+
+ ///
+ protected override void OnSizeChanged()
+ {
+ base.OnSizeChanged();
+
+ UpdateThumb();
+ }
+}
From 65a02f032fd686bbeebeddc32752a25c95ed5b37 Mon Sep 17 00:00:00 2001
From: Chandler Cox
Date: Tue, 5 Sep 2023 08:25:25 -0500
Subject: [PATCH 15/40] Expose helpful slider data.
---
Source/Engine/UI/GUI/Common/Slider.cs | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/Source/Engine/UI/GUI/Common/Slider.cs b/Source/Engine/UI/GUI/Common/Slider.cs
index 06c73f15e..b0344f055 100644
--- a/Source/Engine/UI/GUI/Common/Slider.cs
+++ b/Source/Engine/UI/GUI/Common/Slider.cs
@@ -83,6 +83,24 @@ public class Slider : ContainerControl
}
}
}
+
+ ///
+ /// The local position of the thumb center
+ ///
+ [HideInEditor]
+ public float ThumbCenter => _thumbCenter;
+
+ ///
+ /// The local position of the beginning of the track.
+ ///
+ [HideInEditor]
+ public float TrackBeginning => _thumbSize.X / 2;
+
+ ///
+ /// The local position of the end of the track.
+ ///
+ [HideInEditor]
+ public float TrackEnd => Width - _thumbSize.X / 2;
///
/// The height of the track.
From d96f19e5c66bc8f54bb806c515ce564d6b75260a Mon Sep 17 00:00:00 2001
From: Chandler Cox
Date: Tue, 5 Sep 2023 08:44:59 -0500
Subject: [PATCH 16/40] Change exposed positionns to float 2
---
Source/Engine/UI/GUI/Common/Slider.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Source/Engine/UI/GUI/Common/Slider.cs b/Source/Engine/UI/GUI/Common/Slider.cs
index b0344f055..d7324ae0e 100644
--- a/Source/Engine/UI/GUI/Common/Slider.cs
+++ b/Source/Engine/UI/GUI/Common/Slider.cs
@@ -88,19 +88,19 @@ public class Slider : ContainerControl
/// The local position of the thumb center
///
[HideInEditor]
- public float ThumbCenter => _thumbCenter;
+ public Float2 ThumbCenter => new(_thumbCenter, Height / 2);
///
/// The local position of the beginning of the track.
///
[HideInEditor]
- public float TrackBeginning => _thumbSize.X / 2;
+ public Float2 TrackBeginning => new(_thumbSize.X / 2, Height / 2);
///
/// The local position of the end of the track.
///
[HideInEditor]
- public float TrackEnd => Width - _thumbSize.X / 2;
+ public Float2 TrackEnd => new(Width - _thumbSize.X / 2, Height / 2);
///
/// The height of the track.
From 5ceafaad77cb70d3ac3ffd3975d2d7a483c46f34 Mon Sep 17 00:00:00 2001
From: Wiktor Kocielski
Date: Wed, 6 Sep 2023 05:23:06 +0300
Subject: [PATCH 17/40] WindowBase::Resized delegate
---
Source/Engine/Platform/Base/WindowBase.cpp | 1 +
Source/Engine/Platform/Base/WindowBase.h | 5 +++++
2 files changed, 6 insertions(+)
diff --git a/Source/Engine/Platform/Base/WindowBase.cpp b/Source/Engine/Platform/Base/WindowBase.cpp
index 5cff76361..49b4cc631 100644
--- a/Source/Engine/Platform/Base/WindowBase.cpp
+++ b/Source/Engine/Platform/Base/WindowBase.cpp
@@ -405,6 +405,7 @@ void WindowBase::OnResize(int32 width, int32 height)
_swapChain->Resize(width, height);
if (RenderTask)
RenderTask->Resize(width, height);
+ Resized({ static_cast(width), static_cast(height) });
INVOKE_EVENT_PARAMS_2(OnResize, &width, &height);
}
diff --git a/Source/Engine/Platform/Base/WindowBase.h b/Source/Engine/Platform/Base/WindowBase.h
index e4e7d2080..812359fb4 100644
--- a/Source/Engine/Platform/Base/WindowBase.h
+++ b/Source/Engine/Platform/Base/WindowBase.h
@@ -315,6 +315,11 @@ public:
///
Action Closed;
+ ///
+ /// Event fired when window gets resized.
+ ///
+ Delegate Resized;
+
///
/// Event fired when window gets focused.
///
From fc7c24f7714bca2781119b3cfdb2bc645f62c5e8 Mon Sep 17 00:00:00 2001
From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com>
Date: Thu, 7 Sep 2023 11:33:16 -0400
Subject: [PATCH 18/40] Fix for #1365
---
.../Engine/Physics/Colliders/CharacterController.cpp | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/Source/Engine/Physics/Colliders/CharacterController.cpp b/Source/Engine/Physics/Colliders/CharacterController.cpp
index 488acd6e4..0d5819422 100644
--- a/Source/Engine/Physics/Colliders/CharacterController.cpp
+++ b/Source/Engine/Physics/Colliders/CharacterController.cpp
@@ -245,12 +245,10 @@ void CharacterController::CreateShape()
void CharacterController::UpdateBounds()
{
- void* actor = _shape ? PhysicsBackend::GetShapeActor(_shape) : nullptr;
- if (actor)
- PhysicsBackend::GetActorBounds(actor, _box);
- else
- _box = BoundingBox(_transform.Translation);
- BoundingSphere::FromBox(_box, _sphere);
+ const float radius = Math::Max(_height, _radius);
+ const Vector3 position = _transform.LocalToWorld(_center);
+ _sphere = BoundingSphere(position, radius);
+ _box = BoundingBox::FromSphere(_sphere);
}
void CharacterController::AddMovement(const Vector3& translation, const Quaternion& rotation)
From 317384ed28287473b16b95e6dfb3c35f937992a9 Mon Sep 17 00:00:00 2001
From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com>
Date: Fri, 8 Sep 2023 22:19:09 -0400
Subject: [PATCH 19/40] add debugdraw::drawray
---
Source/Engine/Debug/DebugDraw.cpp | 5 +++++
Source/Engine/Debug/DebugDraw.h | 11 +++++++++++
2 files changed, 16 insertions(+)
diff --git a/Source/Engine/Debug/DebugDraw.cpp b/Source/Engine/Debug/DebugDraw.cpp
index 97422b9e2..e8489f5b5 100644
--- a/Source/Engine/Debug/DebugDraw.cpp
+++ b/Source/Engine/Debug/DebugDraw.cpp
@@ -920,6 +920,11 @@ void DebugDraw::DrawActors(Actor** selectedActors, int32 selectedActorsCount, bo
}
}
+void DebugDraw::DrawRay(const Vector3& origin, const Vector3& direction, const Color& color, float duration, bool depthTest)
+{
+ DrawLine(origin, origin + direction, color, duration, depthTest);
+}
+
void DebugDraw::DrawLine(const Vector3& start, const Vector3& end, const Color& color, float duration, bool depthTest)
{
const Float3 startF = start - Context->Origin, endF = end - Context->Origin;
diff --git a/Source/Engine/Debug/DebugDraw.h b/Source/Engine/Debug/DebugDraw.h
index 8cc5452ed..a4f69678a 100644
--- a/Source/Engine/Debug/DebugDraw.h
+++ b/Source/Engine/Debug/DebugDraw.h
@@ -69,6 +69,16 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// True if draw all debug shapes from scenes too or false if draw just from specified actor list.
API_FUNCTION() static void DrawActors(Actor** selectedActors, int32 selectedActorsCount, bool drawScenes);
+ ///
+ /// Draws the line in a direction.
+ ///
+ /// The origin of the line.
+ /// The direction of the line.
+ /// The color.
+ /// The duration (in seconds). Use 0 to draw it only once.
+ /// If set to true depth test will be performed, otherwise depth will be ignored.
+ API_FUNCTION() static void DrawRay(const Vector3& origin, const Vector3& direction, const Color& color, float duration = 0.0f, bool depthTest = true);
+
///
/// Draws the line.
///
@@ -604,6 +614,7 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
API_FUNCTION() static void DrawText(const StringView& text, const Transform& transform, const Color& color, int32 size = 32, float duration = 0.0f);
};
+#define DEBUG_DRAW_RAY(origin, direction, color, duration, depthTest) DebugDraw::DrawRay(origin, direction, color, duration, depthTest)
#define DEBUG_DRAW_LINE(start, end, color, duration, depthTest) DebugDraw::DrawLine(start, end, color, duration, depthTest)
#define DEBUG_DRAW_LINES(lines, transform, color, duration, depthTest) DebugDraw::DrawLines(lines, transform, color, duration, depthTest)
#define DEBUG_DRAW_BEZIER(p1, p2, p3, p4, color, duration, depthTest) DebugDraw::DrawBezier(p1, p2, p3, p4, color, duration, depthTest)
From 420e02e3c19f4d109c2a6dbb4e89f333c2c79e99 Mon Sep 17 00:00:00 2001
From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com>
Date: Sat, 9 Sep 2023 09:28:06 -0400
Subject: [PATCH 20/40] add empty drawRay
---
Source/Engine/Debug/DebugDraw.cs | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/Source/Engine/Debug/DebugDraw.cs b/Source/Engine/Debug/DebugDraw.cs
index af39ebeea..0fe0d51d2 100644
--- a/Source/Engine/Debug/DebugDraw.cs
+++ b/Source/Engine/Debug/DebugDraw.cs
@@ -31,6 +31,18 @@ namespace FlaxEngine
{
}
+ ///
+ /// Draws the line in a direction.
+ ///
+ /// The start point.
+ /// The direction of the line.
+ /// The color.
+ /// The duration (in seconds). Use 0 to draw it only once.
+ /// If set to true depth test will be performed, otherwise depth will be ignored.
+ public static void DrawRay(Vector3 origin, Vector3 direction, Color color, float duration = 0.0f, bool depthTest = true)
+ {
+ }
+
///
/// Draws the line.
///
From c6ad4d0e19836995a31716563601e954b2717982 Mon Sep 17 00:00:00 2001
From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com>
Date: Sat, 9 Sep 2023 13:07:39 -0400
Subject: [PATCH 21/40] small doc fix
---
Source/Engine/Debug/DebugDraw.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Source/Engine/Debug/DebugDraw.cs b/Source/Engine/Debug/DebugDraw.cs
index 0fe0d51d2..bc000e03d 100644
--- a/Source/Engine/Debug/DebugDraw.cs
+++ b/Source/Engine/Debug/DebugDraw.cs
@@ -34,7 +34,7 @@ namespace FlaxEngine
///
/// Draws the line in a direction.
///
- /// The start point.
+ /// The origin of the line.
/// The direction of the line.
/// The color.
/// The duration (in seconds). Use 0 to draw it only once.
From 9291295a4d9997e3257037db7135d3a5e52d3962 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Sun, 10 Sep 2023 11:25:36 +0200
Subject: [PATCH 22/40] Fix `Dictionary` and `HashSet` iterators to prevent
unwanted data copies
#1361
---
Source/Engine/Content/Assets/VisualScript.cpp | 6 +--
Source/Engine/Core/Collections/Array.h | 8 ++--
Source/Engine/Core/Collections/ChunkedArray.h | 1 -
Source/Engine/Core/Collections/Dictionary.h | 48 +++++++++++--------
Source/Engine/Core/Collections/HashSet.h | 46 +++++++++---------
5 files changed, 57 insertions(+), 52 deletions(-)
diff --git a/Source/Engine/Content/Assets/VisualScript.cpp b/Source/Engine/Content/Assets/VisualScript.cpp
index e292a0133..698f1ca8c 100644
--- a/Source/Engine/Content/Assets/VisualScript.cpp
+++ b/Source/Engine/Content/Assets/VisualScript.cpp
@@ -1251,7 +1251,7 @@ void VisualScriptExecutor::ProcessGroupFlow(Box* boxBase, Node* node, Value& val
boxBase = node->GetBox(3);
if (boxBase->HasConnection())
eatBox(node, boxBase->FirstConnection());
- Dictionary::Iterator it(dictionary, iteratorValue.Value.AsInt);
+ Dictionary::Iterator it(&dictionary, iteratorValue.Value.AsInt);
++it;
iteratorValue.Value.AsInt = it.Index();
}
@@ -1269,12 +1269,12 @@ void VisualScriptExecutor::ProcessGroupFlow(Box* boxBase, Node* node, Value& val
// Key
case 1:
if (iteratorIndex != scope->ReturnedValues.Count() && dictionaryIndex != scope->ReturnedValues.Count())
- value = Dictionary::Iterator(*scope->ReturnedValues[dictionaryIndex].Value.AsDictionary, scope->ReturnedValues[iteratorIndex].Value.AsInt)->Key;
+ value = Dictionary::Iterator(scope->ReturnedValues[dictionaryIndex].Value.AsDictionary, scope->ReturnedValues[iteratorIndex].Value.AsInt)->Key;
break;
// Value
case 2:
if (iteratorIndex != scope->ReturnedValues.Count() && dictionaryIndex != scope->ReturnedValues.Count())
- value = Dictionary::Iterator(*scope->ReturnedValues[dictionaryIndex].Value.AsDictionary, scope->ReturnedValues[iteratorIndex].Value.AsInt)->Value;
+ value = Dictionary::Iterator(scope->ReturnedValues[dictionaryIndex].Value.AsDictionary, scope->ReturnedValues[iteratorIndex].Value.AsInt)->Value;
break;
// Break
case 5:
diff --git a/Source/Engine/Core/Collections/Array.h b/Source/Engine/Core/Collections/Array.h
index 3feae4e73..58117cf0a 100644
--- a/Source/Engine/Core/Collections/Array.h
+++ b/Source/Engine/Core/Collections/Array.h
@@ -938,12 +938,12 @@ public:
FORCE_INLINE bool IsEnd() const
{
- return _index == _array->Count();
+ return _index == _array->_count;
}
FORCE_INLINE bool IsNotEnd() const
{
- return _index != _array->Count();
+ return _index != _array->_count;
}
FORCE_INLINE T& operator*() const
@@ -975,7 +975,7 @@ public:
Iterator& operator++()
{
- if (_index != _array->Count())
+ if (_index != _array->_count)
_index++;
return *this;
}
@@ -983,7 +983,7 @@ public:
Iterator operator++(int)
{
Iterator temp = *this;
- if (_index != _array->Count())
+ if (_index != _array->_count)
_index++;
return temp;
}
diff --git a/Source/Engine/Core/Collections/ChunkedArray.h b/Source/Engine/Core/Collections/ChunkedArray.h
index 86473763b..d01711e38 100644
--- a/Source/Engine/Core/Collections/ChunkedArray.h
+++ b/Source/Engine/Core/Collections/ChunkedArray.h
@@ -95,7 +95,6 @@ public:
struct Iterator
{
friend ChunkedArray;
-
private:
ChunkedArray* _collection;
int32 _chunkIndex;
diff --git a/Source/Engine/Core/Collections/Dictionary.h b/Source/Engine/Core/Collections/Dictionary.h
index 2327f3c24..01c25a842 100644
--- a/Source/Engine/Core/Collections/Dictionary.h
+++ b/Source/Engine/Core/Collections/Dictionary.h
@@ -237,22 +237,28 @@ public:
{
friend Dictionary;
private:
- Dictionary& _collection;
+ Dictionary* _collection;
int32 _index;
public:
- Iterator(Dictionary& collection, const int32 index)
+ Iterator(Dictionary* collection, const int32 index)
: _collection(collection)
, _index(index)
{
}
- Iterator(Dictionary const& collection, const int32 index)
- : _collection((Dictionary&)collection)
+ Iterator(Dictionary const* collection, const int32 index)
+ : _collection(const_cast(collection))
, _index(index)
{
}
+ Iterator()
+ : _collection(nullptr)
+ , _index(-1)
+ {
+ }
+
Iterator(const Iterator& i)
: _collection(i._collection)
, _index(i._index)
@@ -273,27 +279,27 @@ public:
FORCE_INLINE bool IsEnd() const
{
- return _index == _collection._size;
+ return _index == _collection->_size;
}
FORCE_INLINE bool IsNotEnd() const
{
- return _index != _collection._size;
+ return _index != _collection->_size;
}
FORCE_INLINE Bucket& operator*() const
{
- return _collection._allocation.Get()[_index];
+ return _collection->_allocation.Get()[_index];
}
FORCE_INLINE Bucket* operator->() const
{
- return &_collection._allocation.Get()[_index];
+ return &_collection->_allocation.Get()[_index];
}
FORCE_INLINE explicit operator bool() const
{
- return _index >= 0 && _index < _collection._size;
+ return _index >= 0 && _index < _collection->_size;
}
FORCE_INLINE bool operator!() const
@@ -320,10 +326,10 @@ public:
Iterator& operator++()
{
- const int32 capacity = _collection.Capacity();
+ const int32 capacity = _collection->_size;
if (_index != capacity)
{
- const Bucket* data = _collection._allocation.Get();
+ const Bucket* data = _collection->_allocation.Get();
do
{
_index++;
@@ -343,7 +349,7 @@ public:
{
if (_index > 0)
{
- const Bucket* data = _collection._allocation.Get();
+ const Bucket* data = _collection->_allocation.Get();
do
{
_index--;
@@ -633,7 +639,7 @@ public:
/// Iterator with key and value.
void Add(const Iterator& i)
{
- ASSERT(&i._collection != this && i);
+ ASSERT(i._collection != this && i);
const Bucket& bucket = *i;
Add(bucket.Key, bucket.Value);
}
@@ -667,7 +673,7 @@ public:
/// True if cannot remove item from the collection because cannot find it, otherwise false.
bool Remove(const Iterator& i)
{
- ASSERT(&i._collection == this);
+ ASSERT(i._collection == this);
if (i)
{
ASSERT(_allocation.Get()[i._index].IsOccupied());
@@ -711,7 +717,7 @@ public:
return End();
FindPositionResult pos;
FindPosition(key, pos);
- return pos.ObjectIndex != -1 ? Iterator(*this, pos.ObjectIndex) : End();
+ return pos.ObjectIndex != -1 ? Iterator(this, pos.ObjectIndex) : End();
}
///
@@ -812,38 +818,38 @@ public:
public:
Iterator Begin() const
{
- Iterator i(*this, -1);
+ Iterator i(this, -1);
++i;
return i;
}
Iterator End() const
{
- return Iterator(*this, _size);
+ return Iterator(this, _size);
}
Iterator begin()
{
- Iterator i(*this, -1);
+ Iterator i(this, -1);
++i;
return i;
}
FORCE_INLINE Iterator end()
{
- return Iterator(*this, _size);
+ return Iterator(this, _size);
}
const Iterator begin() const
{
- Iterator i(*this, -1);
+ Iterator i(this, -1);
++i;
return i;
}
FORCE_INLINE const Iterator end() const
{
- return Iterator(*this, _size);
+ return Iterator(this, _size);
}
protected:
diff --git a/Source/Engine/Core/Collections/HashSet.h b/Source/Engine/Core/Collections/HashSet.h
index ad6f8ffc6..107e42e65 100644
--- a/Source/Engine/Core/Collections/HashSet.h
+++ b/Source/Engine/Core/Collections/HashSet.h
@@ -213,17 +213,17 @@ public:
{
friend HashSet;
private:
- HashSet& _collection;
+ HashSet* _collection;
int32 _index;
- Iterator(HashSet& collection, const int32 index)
+ Iterator(HashSet* collection, const int32 index)
: _collection(collection)
, _index(index)
{
}
- Iterator(HashSet const& collection, const int32 index)
- : _collection((HashSet&)collection)
+ Iterator(HashSet const* collection, const int32 index)
+ : _collection(const_cast(collection))
, _index(index)
{
}
@@ -244,27 +244,27 @@ public:
public:
FORCE_INLINE bool IsEnd() const
{
- return _index == _collection.Capacity();
+ return _index == _collection->_size;
}
FORCE_INLINE bool IsNotEnd() const
{
- return _index != _collection.Capacity();
+ return _index != _collection->_size;
}
FORCE_INLINE Bucket& operator*() const
{
- return _collection._allocation.Get()[_index];
+ return _collection->_allocation.Get()[_index];
}
FORCE_INLINE Bucket* operator->() const
{
- return &_collection._allocation.Get()[_index];
+ return &_collection->_allocation.Get()[_index];
}
FORCE_INLINE explicit operator bool() const
{
- return _index >= 0 && _index < _collection._size;
+ return _index >= 0 && _index < _collection->_size;
}
FORCE_INLINE bool operator !() const
@@ -274,12 +274,12 @@ public:
FORCE_INLINE bool operator==(const Iterator& v) const
{
- return _index == v._index && &_collection == &v._collection;
+ return _index == v._index && _collection == v._collection;
}
FORCE_INLINE bool operator!=(const Iterator& v) const
{
- return _index != v._index || &_collection != &v._collection;
+ return _index != v._index || _collection != v._collection;
}
Iterator& operator=(const Iterator& v)
@@ -291,10 +291,10 @@ public:
Iterator& operator++()
{
- const int32 capacity = _collection.Capacity();
+ const int32 capacity = _collection->_size;
if (_index != capacity)
{
- const Bucket* data = _collection._allocation.Get();
+ const Bucket* data = _collection->_allocation.Get();
do
{
_index++;
@@ -314,7 +314,7 @@ public:
{
if (_index > 0)
{
- const Bucket* data = _collection._allocation.Get();
+ const Bucket* data = _collection->_allocation.Get();
do
{
_index--;
@@ -464,7 +464,7 @@ public:
/// Iterator with item to add
void Add(const Iterator& i)
{
- ASSERT(&i._collection != this && i);
+ ASSERT(i._collection != this && i);
const Bucket& bucket = *i;
Add(bucket.Item);
}
@@ -498,7 +498,7 @@ public:
/// True if cannot remove item from the collection because cannot find it, otherwise false.
bool Remove(const Iterator& i)
{
- ASSERT(&i._collection == this);
+ ASSERT(i._collection == this);
if (i)
{
ASSERT(_allocation.Get()[i._index].IsOccupied());
@@ -523,7 +523,7 @@ public:
return End();
FindPositionResult pos;
FindPosition(item, pos);
- return pos.ObjectIndex != -1 ? Iterator(*this, pos.ObjectIndex) : End();
+ return pos.ObjectIndex != -1 ? Iterator(this, pos.ObjectIndex) : End();
}
///
@@ -559,38 +559,38 @@ public:
public:
Iterator Begin() const
{
- Iterator i(*this, -1);
+ Iterator i(this, -1);
++i;
return i;
}
Iterator End() const
{
- return Iterator(*this, _size);
+ return Iterator(this, _size);
}
Iterator begin()
{
- Iterator i(*this, -1);
+ Iterator i(this, -1);
++i;
return i;
}
FORCE_INLINE Iterator end()
{
- return Iterator(*this, _size);
+ return Iterator(this, _size);
}
const Iterator begin() const
{
- Iterator i(*this, -1);
+ Iterator i(this, -1);
++i;
return i;
}
FORCE_INLINE const Iterator end() const
{
- return Iterator(*this, _size);
+ return Iterator(this, _size);
}
protected:
From 53deeff11601b326b4506a5d6747f98ef1426023 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Sun, 10 Sep 2023 11:33:08 +0200
Subject: [PATCH 23/40] Missing change from
9291295a4d9997e3257037db7135d3a5e52d3962
---
Source/Engine/Core/Collections/Dictionary.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Source/Engine/Core/Collections/Dictionary.h b/Source/Engine/Core/Collections/Dictionary.h
index 01c25a842..f5ffb1bfa 100644
--- a/Source/Engine/Core/Collections/Dictionary.h
+++ b/Source/Engine/Core/Collections/Dictionary.h
@@ -314,7 +314,7 @@ public:
FORCE_INLINE bool operator!=(const Iterator& v) const
{
- return _index != v._index || &_collection != &v._collection;
+ return _index != v._index || _collection != v._collection;
}
Iterator& operator=(const Iterator& v)
From 9da686cd525c3ff76fc5b8722b697d26c64688a1 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Sun, 10 Sep 2023 11:58:54 +0200
Subject: [PATCH 24/40] Improve #1369 for #1365
---
.../Physics/Colliders/CharacterController.cpp | 34 ++++++++++---------
1 file changed, 18 insertions(+), 16 deletions(-)
diff --git a/Source/Engine/Physics/Colliders/CharacterController.cpp b/Source/Engine/Physics/Colliders/CharacterController.cpp
index 0d5819422..42455daa4 100644
--- a/Source/Engine/Physics/Colliders/CharacterController.cpp
+++ b/Source/Engine/Physics/Colliders/CharacterController.cpp
@@ -8,6 +8,8 @@
#include "Engine/Serialization/Serialization.h"
#include "Engine/Engine/Time.h"
+#define CC_MIN_SIZE 0.001f
+
CharacterController::CharacterController(const SpawnParams& params)
: Collider(params)
, _controller(nullptr)
@@ -100,10 +102,9 @@ void CharacterController::SetStepOffset(float value)
{
const float scaling = _cachedScale.GetAbsolute().MaxValue();
const float contactOffset = Math::Max(_contactOffset, ZeroTolerance);
- const float minSize = 0.001f;
- const float height = Math::Max(Math::Abs(_height) * scaling, minSize);
- const float radius = Math::Max(Math::Abs(_radius) * scaling - contactOffset, minSize);
- PhysicsBackend::SetControllerStepOffset(_controller, Math::Min(value, height + radius * 2.0f - minSize));
+ const float height = Math::Max(Math::Abs(_height) * scaling, CC_MIN_SIZE);
+ const float radius = Math::Max(Math::Abs(_radius) * scaling - contactOffset, CC_MIN_SIZE);
+ PhysicsBackend::SetControllerStepOffset(_controller, Math::Min(value, height + radius * 2.0f - CC_MIN_SIZE));
}
}
@@ -175,9 +176,8 @@ CharacterController::CollisionFlags CharacterController::Move(const Vector3& dis
void CharacterController::DrawPhysicsDebug(RenderView& view)
{
const float scaling = _cachedScale.GetAbsolute().MaxValue();
- const float minSize = 0.001f;
- const float radius = Math::Max(Math::Abs(_radius) * scaling, minSize);
- const float height = Math::Max(Math::Abs(_height) * scaling, minSize);
+ const float radius = Math::Max(Math::Abs(_radius) * scaling, CC_MIN_SIZE);
+ const float height = Math::Max(Math::Abs(_height) * scaling, CC_MIN_SIZE);
const Vector3 position = _transform.LocalToWorld(_center);
if (view.Mode == ViewMode::PhysicsColliders)
DEBUG_DRAW_TUBE(position, Quaternion::Euler(90, 0, 0), radius, height, Color::LightYellow, 0, true);
@@ -188,9 +188,8 @@ void CharacterController::DrawPhysicsDebug(RenderView& view)
void CharacterController::OnDebugDrawSelected()
{
const float scaling = _cachedScale.GetAbsolute().MaxValue();
- const float minSize = 0.001f;
- const float radius = Math::Max(Math::Abs(_radius) * scaling, minSize);
- const float height = Math::Max(Math::Abs(_height) * scaling, minSize);
+ const float radius = Math::Max(Math::Abs(_radius) * scaling, CC_MIN_SIZE);
+ const float height = Math::Max(Math::Abs(_height) * scaling, CC_MIN_SIZE);
const Vector3 position = _transform.LocalToWorld(_center);
DEBUG_DRAW_WIRE_TUBE(position, Quaternion::Euler(90, 0, 0), radius, height, Color::GreenYellow, 0, false);
@@ -231,9 +230,8 @@ void CharacterController::UpdateSize() const
if (_controller)
{
const float scaling = _cachedScale.GetAbsolute().MaxValue();
- const float minSize = 0.001f;
- const float radius = Math::Max(Math::Abs(_radius) * scaling - Math::Max(_contactOffset, ZeroTolerance), minSize);
- const float height = Math::Max(Math::Abs(_height) * scaling, minSize);
+ const float radius = Math::Max(Math::Abs(_radius) * scaling - Math::Max(_contactOffset, ZeroTolerance), CC_MIN_SIZE);
+ const float height = Math::Max(Math::Abs(_height) * scaling, CC_MIN_SIZE);
PhysicsBackend::SetControllerSize(_controller, radius, height);
}
}
@@ -245,10 +243,14 @@ void CharacterController::CreateShape()
void CharacterController::UpdateBounds()
{
- const float radius = Math::Max(_height, _radius);
+ const float scaling = GetScale().GetAbsolute().MaxValue();
+ const float radius = Math::Max(Math::Abs(_radius) * scaling, CC_MIN_SIZE);
+ const float height = Math::Max(Math::Abs(_height) * scaling, CC_MIN_SIZE);
const Vector3 position = _transform.LocalToWorld(_center);
- _sphere = BoundingSphere(position, radius);
- _box = BoundingBox::FromSphere(_sphere);
+ const Vector3 extent(radius, height * 0.5f + radius, radius);
+ _box = BoundingBox(position - extent, position + extent);
+ BoundingSphere::FromBox(_box, _sphere);
+ DEBUG_DRAW_BOX(_box, Color::Red.AlphaMultiplied(0.4f), 2.0f, true);
}
void CharacterController::AddMovement(const Vector3& translation, const Quaternion& rotation)
From a4312590e794b7d1566620ced859dc75cdc90cd0 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Sun, 10 Sep 2023 13:34:46 +0200
Subject: [PATCH 25/40] Fix debug draw leftover from
9da686cd525c3ff76fc5b8722b697d26c64688a1
#1369 #1365
---
Source/Engine/Physics/Colliders/CharacterController.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/Source/Engine/Physics/Colliders/CharacterController.cpp b/Source/Engine/Physics/Colliders/CharacterController.cpp
index 42455daa4..59521e51c 100644
--- a/Source/Engine/Physics/Colliders/CharacterController.cpp
+++ b/Source/Engine/Physics/Colliders/CharacterController.cpp
@@ -250,7 +250,6 @@ void CharacterController::UpdateBounds()
const Vector3 extent(radius, height * 0.5f + radius, radius);
_box = BoundingBox(position - extent, position + extent);
BoundingSphere::FromBox(_box, _sphere);
- DEBUG_DRAW_BOX(_box, Color::Red.AlphaMultiplied(0.4f), 2.0f, true);
}
void CharacterController::AddMovement(const Vector3& translation, const Quaternion& rotation)
From ae27d51dc68381eac5162f58990813d68f38c350 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Sun, 10 Sep 2023 14:53:58 +0200
Subject: [PATCH 26/40] Fix building for Android with the latest Java version
(update to Gradle `8.3`)
---
Source/Platforms/Android/Binaries/Project/app/build.gradle | 1 +
Source/Platforms/Android/Binaries/Project/build.gradle | 2 +-
Source/Platforms/Android/Binaries/Project/gradle.properties | 3 +--
.../Binaries/Project/gradle/wrapper/gradle-wrapper.properties | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Source/Platforms/Android/Binaries/Project/app/build.gradle b/Source/Platforms/Android/Binaries/Project/app/build.gradle
index 0ad5776b5..2f5da0a56 100644
--- a/Source/Platforms/Android/Binaries/Project/app/build.gradle
+++ b/Source/Platforms/Android/Binaries/Project/app/build.gradle
@@ -1,6 +1,7 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 24
+ namespace "${PackageName}"
defaultConfig {
applicationId "${PackageName}"
minSdkVersion 24
diff --git a/Source/Platforms/Android/Binaries/Project/build.gradle b/Source/Platforms/Android/Binaries/Project/build.gradle
index 31d9237bc..ff4610757 100644
--- a/Source/Platforms/Android/Binaries/Project/build.gradle
+++ b/Source/Platforms/Android/Binaries/Project/build.gradle
@@ -6,7 +6,7 @@ buildscript {
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:4.1.0'
+ classpath 'com.android.tools.build:gradle:8.1.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/Source/Platforms/Android/Binaries/Project/gradle.properties b/Source/Platforms/Android/Binaries/Project/gradle.properties
index 7be81848a..f38a936bd 100644
--- a/Source/Platforms/Android/Binaries/Project/gradle.properties
+++ b/Source/Platforms/Android/Binaries/Project/gradle.properties
@@ -9,5 +9,4 @@
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
-# Default value: -Xmx10248m -XX:MaxPermSize=256m
-org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+org.gradle.jvmargs=-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
diff --git a/Source/Platforms/Android/Binaries/Project/gradle/wrapper/gradle-wrapper.properties b/Source/Platforms/Android/Binaries/Project/gradle/wrapper/gradle-wrapper.properties
index 483089527..ee1048a44 100644
--- a/Source/Platforms/Android/Binaries/Project/gradle/wrapper/gradle-wrapper.properties
+++ b/Source/Platforms/Android/Binaries/Project/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
From 716e643f2a609cbc829dc8c117bd3ed4d2cf14e0 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Sun, 10 Sep 2023 21:07:41 +0200
Subject: [PATCH 27/40] Fix applying prefab changes to nesting prefab instances
#1256
---
Source/Editor/Modules/SceneModule.cs | 2 +-
Source/Editor/SceneGraph/GUI/ActorTreeNode.cs | 5 -----
Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs | 2 +-
Source/Engine/Level/Prefabs/Prefab.Apply.cpp | 7 +++----
4 files changed, 5 insertions(+), 11 deletions(-)
diff --git a/Source/Editor/Modules/SceneModule.cs b/Source/Editor/Modules/SceneModule.cs
index 0a51038ac..257262585 100644
--- a/Source/Editor/Modules/SceneModule.cs
+++ b/Source/Editor/Modules/SceneModule.cs
@@ -591,7 +591,7 @@ namespace FlaxEditor.Modules
private void OnActorNameChanged(Actor actor)
{
ActorNode node = GetActorNode(actor);
- node?.TreeNode.OnNameChanged();
+ node?.TreeNode.UpdateText();
}
private void OnActorActiveChanged(Actor actor)
diff --git a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
index 83ea666d9..c4edda65e 100644
--- a/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
+++ b/Source/Editor/SceneGraph/GUI/ActorTreeNode.cs
@@ -97,11 +97,6 @@ namespace FlaxEditor.SceneGraph.GUI
}
}
- internal void OnNameChanged()
- {
- UpdateText();
- }
-
///
/// Updates the tree node text.
///
diff --git a/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs b/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs
index 1b1cfb4ff..5a532e362 100644
--- a/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs
+++ b/Source/Editor/Windows/Assets/PrefabWindow.Hierarchy.cs
@@ -430,7 +430,7 @@ namespace FlaxEditor.Windows.Assets
{
if (actorNode.Actor)
{
- actorNode.TreeNode.OnNameChanged();
+ actorNode.TreeNode.UpdateText();
actorNode.TreeNode.OnOrderInParentChanged();
}
diff --git a/Source/Engine/Level/Prefabs/Prefab.Apply.cpp b/Source/Engine/Level/Prefabs/Prefab.Apply.cpp
index 5ea8ad0a4..e0df48fae 100644
--- a/Source/Engine/Level/Prefabs/Prefab.Apply.cpp
+++ b/Source/Engine/Level/Prefabs/Prefab.Apply.cpp
@@ -1255,20 +1255,19 @@ void Prefab::SyncNestedPrefabs(const NestedPrefabsList& allPrefabs, ArrayWaitForLoaded())
{
LOG(Warning, "Waiting for prefab asset load failed.");
continue;
}
+ // Sync only if prefab is used by this prefab (directly) and it has been captured before
const int32 nestedPrefabIndex = nestedPrefab->NestedPrefabs.Find(GetID());
if (nestedPrefabIndex != -1)
{
- if (nestedPrefab->SyncChangesInternal(allPrefabsInstancesData[nestedPrefabIndex]))
+ if (nestedPrefab->SyncChangesInternal(allPrefabsInstancesData[i]))
continue;
-
nestedPrefab->SyncNestedPrefabs(allPrefabs, allPrefabsInstancesData);
-
ObjectsRemovalService::Flush();
}
}
From fb27606541f05333d6fb186458cd2946e120a52d Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Mon, 11 Sep 2023 13:54:44 +0200
Subject: [PATCH 28/40] Add missing `Particle Scale` getter node to Particle
Emitter graph
#1343
---
Source/Editor/Surface/Archetypes/Particles.cs | 12 ++++++++++++
.../Graph/CPU/ParticleEmitterGraph.CPU.Particles.cpp | 6 ++++++
.../Graph/GPU/ParticleEmitterGraph.GPU.Particles.cpp | 4 ++++
Source/Engine/Particles/Graph/ParticleEmitterGraph.h | 9 ++++++++-
4 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/Source/Editor/Surface/Archetypes/Particles.cs b/Source/Editor/Surface/Archetypes/Particles.cs
index dd861d4af..1389a6904 100644
--- a/Source/Editor/Surface/Archetypes/Particles.cs
+++ b/Source/Editor/Surface/Archetypes/Particles.cs
@@ -553,6 +553,18 @@ namespace FlaxEditor.Surface.Archetypes
NodeElementArchetype.Factory.Output(0, string.Empty, typeof(float), 0),
}
},
+ new NodeArchetype
+ {
+ TypeID = 112,
+ Title = "Particle Scale",
+ Description = "Particle scale.",
+ Flags = NodeFlags.ParticleEmitterGraph,
+ Size = new Float2(200, 30),
+ Elements = new[]
+ {
+ NodeElementArchetype.Factory.Output(0, string.Empty, typeof(Float3), 0),
+ }
+ },
// Simulation data access nodes
new NodeArchetype
diff --git a/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.Particles.cpp b/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.Particles.cpp
index 9ef996869..9d91d0013 100644
--- a/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.Particles.cpp
+++ b/Source/Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.Particles.cpp
@@ -331,6 +331,12 @@ void ParticleEmitterGraphCPUExecutor::ProcessGroupParticles(Box* box, Node* node
value = GET_PARTICLE_ATTRIBUTE(0, float);
break;
}
+ // Particle Scale
+ case 112:
+ {
+ value = GET_PARTICLE_ATTRIBUTE(0, Float3);
+ break;
+ }
// Effect Position
case 200:
{
diff --git a/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Particles.cpp b/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Particles.cpp
index 905d1a11c..de142827c 100644
--- a/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Particles.cpp
+++ b/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Particles.cpp
@@ -331,6 +331,10 @@ void ParticleEmitterGPUGenerator::ProcessGroupParticles(Box* box, Node* node, Va
case 111:
value = AccessParticleAttribute(node, TEXT("Radius"), ParticleAttribute::ValueTypes::Float, AccessMode::Read);
break;
+ // Particle Scale
+ case 112:
+ value = AccessParticleAttribute(node, TEXT("Scale"), ParticleAttribute::ValueTypes::Float3, AccessMode::Read);
+ break;
// Effect Position
case 200:
value = Value(VariantType::Float3, TEXT("EffectPosition"));
diff --git a/Source/Engine/Particles/Graph/ParticleEmitterGraph.h b/Source/Engine/Particles/Graph/ParticleEmitterGraph.h
index cfe259a72..f5946c226 100644
--- a/Source/Engine/Particles/Graph/ParticleEmitterGraph.h
+++ b/Source/Engine/Particles/Graph/ParticleEmitterGraph.h
@@ -269,13 +269,20 @@ public:
USE_ATTRIBUTE(Lifetime, Float, 1);
break;
}
- // Particle Mass
+ // Particle Radius
case GRAPH_NODE_MAKE_TYPE(14, 111):
{
node->UsesParticleData = true;
USE_ATTRIBUTE(Radius, Float, 0);
break;
}
+ // Particle Scale
+ case GRAPH_NODE_MAKE_TYPE(14, 112):
+ {
+ node->UsesParticleData = true;
+ USE_ATTRIBUTE(Scale, Float3, 0);
+ break;
+ }
// Random
case GRAPH_NODE_MAKE_TYPE(14, 208):
case GRAPH_NODE_MAKE_TYPE(14, 209):
From 9afa98e9059dd54525c00b93ee231e57c512e0c3 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Mon, 11 Sep 2023 13:59:10 +0200
Subject: [PATCH 29/40] Fix `Random Range` nodes in CPU particles/script graphs
when using `int`
#1341
---
Source/Engine/Visject/VisjectGraph.cpp | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/Source/Engine/Visject/VisjectGraph.cpp b/Source/Engine/Visject/VisjectGraph.cpp
index ca4495f67..1cee5d46e 100644
--- a/Source/Engine/Visject/VisjectGraph.cpp
+++ b/Source/Engine/Visject/VisjectGraph.cpp
@@ -1279,16 +1279,16 @@ void VisjectExecutor::ProcessGroupParticles(Box* box, Node* node, Value& value)
// Random Float Range
case 213:
{
- auto a = tryGetValue(node->TryGetBox(1), node->Values[0]).AsFloat;
- auto b = tryGetValue(node->TryGetBox(2), node->Values[1]).AsFloat;
+ auto a = (float)tryGetValue(node->TryGetBox(1), node->Values[0]);
+ auto b = (float)tryGetValue(node->TryGetBox(2), node->Values[1]);
value = Math::Lerp(a, b, RAND);
break;
}
// Random Vector2 Range
case 214:
{
- auto a = tryGetValue(node->TryGetBox(1), node->Values[0]).AsFloat2();
- auto b = tryGetValue(node->TryGetBox(2), node->Values[1]).AsFloat2();
+ auto a = (Float2)tryGetValue(node->TryGetBox(1), node->Values[0]);
+ auto b = (Float2)tryGetValue(node->TryGetBox(2), node->Values[1]);
value = Float2(
Math::Lerp(a.X, b.X, RAND),
Math::Lerp(a.Y, b.Y, RAND)
@@ -1298,8 +1298,8 @@ void VisjectExecutor::ProcessGroupParticles(Box* box, Node* node, Value& value)
// Random Vector3 Range
case 215:
{
- auto a = tryGetValue(node->TryGetBox(1), node->Values[0]).AsFloat3();
- auto b = tryGetValue(node->TryGetBox(2), node->Values[1]).AsFloat3();
+ auto a = (Float3)tryGetValue(node->TryGetBox(1), node->Values[0]);
+ auto b = (Float3)tryGetValue(node->TryGetBox(2), node->Values[1]);
value = Float3(
Math::Lerp(a.X, b.X, RAND),
Math::Lerp(a.Y, b.Y, RAND),
@@ -1310,8 +1310,8 @@ void VisjectExecutor::ProcessGroupParticles(Box* box, Node* node, Value& value)
// Random Vector4 Range
case 216:
{
- auto a = tryGetValue(node->TryGetBox(1), node->Values[0]).AsFloat4();
- auto b = tryGetValue(node->TryGetBox(2), node->Values[1]).AsFloat4();
+ auto a = (Float4)tryGetValue(node->TryGetBox(1), node->Values[0]);
+ auto b = (Float4)tryGetValue(node->TryGetBox(2), node->Values[1]);
value = Float4(
Math::Lerp(a.X, b.X, RAND),
Math::Lerp(a.Y, b.Y, RAND),
From 1134cfa6a6964837d6391247a899a95573ce6f91 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Mon, 11 Sep 2023 15:05:46 +0200
Subject: [PATCH 30/40] Fix using `ManagedDictionary` when item value type is
array
#1305
---
Source/Engine/Scripting/Scripting.cs | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/Source/Engine/Scripting/Scripting.cs b/Source/Engine/Scripting/Scripting.cs
index 2b49d97d4..68da64bf7 100644
--- a/Source/Engine/Scripting/Scripting.cs
+++ b/Source/Engine/Scripting/Scripting.cs
@@ -205,6 +205,13 @@ namespace FlaxEngine
internal static void AddDictionaryItem(IDictionary dictionary, object key, object value)
{
+ // TODO: more generic approach to properly add value that is of custom boxed type? (eg. via NativeInterop.MarshalToManaged)
+ if (value is ManagedArray managedArray)
+ {
+ var managedArrayHandle = ManagedHandle.Alloc(managedArray, GCHandleType.Normal);
+ value = NativeInterop.MarshalToManaged((IntPtr)managedArrayHandle, managedArray.ArrayType);
+ managedArrayHandle.Free();
+ }
dictionary.Add(key, value);
}
From 48d4a51c1b589ec2b7560812cecc3af5154422fd Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Mon, 11 Sep 2023 15:06:26 +0200
Subject: [PATCH 31/40] Fix crash when boxing native array to managed value
---
Source/Engine/Scripting/ManagedCLR/MUtils.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Source/Engine/Scripting/ManagedCLR/MUtils.h b/Source/Engine/Scripting/ManagedCLR/MUtils.h
index 90feecab3..7b340e5c6 100644
--- a/Source/Engine/Scripting/ManagedCLR/MUtils.h
+++ b/Source/Engine/Scripting/ManagedCLR/MUtils.h
@@ -3,6 +3,7 @@
#pragma once
#include "MTypes.h"
+#include "MClass.h"
#include "MCore.h"
#include "Engine/Core/Types/StringView.h"
#include "Engine/Core/Types/DataContainer.h"
@@ -354,7 +355,7 @@ struct MConverter>
{
if (!klass)
return nullptr;
- MArray* result = MCore::Array::New(klass, data.Count());
+ MArray* result = MCore::Array::New(klass->GetElementClass(), data.Count());
MConverter converter;
converter.ToManagedArray(result, Span(data.Get(), data.Count()));
return (MObject*)result;
From 829d3b3642c1ade36c2e74ff37178a5a29df6702 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Mon, 11 Sep 2023 15:07:06 +0200
Subject: [PATCH 32/40] Add editor shortcuts usability when toolstrip or main
menu controls are focused
---
Source/Editor/GUI/MainMenu.cs | 11 ++++++++++
Source/Editor/GUI/ToolStrip.cs | 21 +++++++++++++++++++
Source/Editor/Modules/ContentFindingModule.cs | 2 ++
3 files changed, 34 insertions(+)
diff --git a/Source/Editor/GUI/MainMenu.cs b/Source/Editor/GUI/MainMenu.cs
index 66b10f0aa..370ad056b 100644
--- a/Source/Editor/GUI/MainMenu.cs
+++ b/Source/Editor/GUI/MainMenu.cs
@@ -304,6 +304,17 @@ namespace FlaxEditor.GUI
return true;
}
+ ///
+ public override bool OnKeyDown(KeyboardKeys key)
+ {
+ if (base.OnKeyDown(key))
+ return true;
+
+ // Fallback to the edit window for shortcuts
+ var editor = Editor.Instance;
+ return editor.Windows.EditWin.InputActions.Process(editor, this, key);
+ }
+
///
protected override void PerformLayoutAfterChildren()
{
diff --git a/Source/Editor/GUI/ToolStrip.cs b/Source/Editor/GUI/ToolStrip.cs
index 0dac241ed..360d63ffe 100644
--- a/Source/Editor/GUI/ToolStrip.cs
+++ b/Source/Editor/GUI/ToolStrip.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
+using FlaxEditor.Windows;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -181,5 +182,25 @@ namespace FlaxEditor.GUI
PerformLayout();
}
+
+ ///
+ public override bool OnKeyDown(KeyboardKeys key)
+ {
+ if (base.OnKeyDown(key))
+ return true;
+
+ // Fallback to the owning window for shortcuts
+ EditorWindow editorWindow = null;
+ ContainerControl c = Parent;
+ while (c != null && editorWindow == null)
+ {
+ editorWindow = c as EditorWindow;
+ c = c.Parent;
+ }
+ var editor = Editor.Instance;
+ if (editorWindow == null)
+ editorWindow = editor.Windows.EditWin; // Fallback to main editor window
+ return editorWindow.InputActions.Process(editor, this, key);
+ }
}
}
diff --git a/Source/Editor/Modules/ContentFindingModule.cs b/Source/Editor/Modules/ContentFindingModule.cs
index ccf1cb3e4..9e8002c8a 100644
--- a/Source/Editor/Modules/ContentFindingModule.cs
+++ b/Source/Editor/Modules/ContentFindingModule.cs
@@ -166,6 +166,8 @@ namespace FlaxEditor.Modules
public void ShowFinder(Control control)
{
var finder = _finder ?? (_finder = new ContentFinder());
+ if (control == null)
+ control = Editor.Instance.Windows.MainWindow.GUI;
var position = (control.Size - new Float2(finder.Width, 300.0f)) * 0.5f;
finder.Show(control, position);
}
From 748ff3b8a5a09aa89d2912d33f9a7a108b2121b0 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Mon, 11 Sep 2023 15:07:37 +0200
Subject: [PATCH 33/40] Optimize `CultureInfoEditor` and `TagEditor`
performance when searching entries by text
---
Source/Editor/CustomEditors/Editors/CultureInfoEditor.cs | 4 ++--
Source/Editor/CustomEditors/Editors/TagEditor.cs | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Source/Editor/CustomEditors/Editors/CultureInfoEditor.cs b/Source/Editor/CustomEditors/Editors/CultureInfoEditor.cs
index d04b5b6da..e1a2b0195 100644
--- a/Source/Editor/CustomEditors/Editors/CultureInfoEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/CultureInfoEditor.cs
@@ -123,9 +123,9 @@ namespace FlaxEditor.CustomEditors.Editors
{
if (tree.IsLayoutLocked)
return;
- root.LockChildrenRecursive();
+ tree.LockChildrenRecursive();
Utilities.Utils.UpdateSearchPopupFilter(root, searchBox.Text);
- root.UnlockChildrenRecursive();
+ tree.UnlockChildrenRecursive();
menu.PerformLayout();
};
root.ExpandAll(true);
diff --git a/Source/Editor/CustomEditors/Editors/TagEditor.cs b/Source/Editor/CustomEditors/Editors/TagEditor.cs
index ab5fd5d1a..3d2dd86aa 100644
--- a/Source/Editor/CustomEditors/Editors/TagEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/TagEditor.cs
@@ -593,9 +593,9 @@ namespace FlaxEditor.CustomEditors.Editors
{
if (tree.IsLayoutLocked)
return;
- root.LockChildrenRecursive();
+ tree.LockChildrenRecursive();
Utilities.Utils.UpdateSearchPopupFilter(root, searchBox.Text);
- root.UnlockChildrenRecursive();
+ tree.UnlockChildrenRecursive();
menu.PerformLayout();
};
From 59c460ccbccc4944462b8f978d7fc5393e02efa9 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Mon, 11 Sep 2023 15:08:13 +0200
Subject: [PATCH 34/40] Format code
---
Source/Editor/Managed/ManagedEditor.Internal.cpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Source/Editor/Managed/ManagedEditor.Internal.cpp b/Source/Editor/Managed/ManagedEditor.Internal.cpp
index bed9cfb5c..afcbb740a 100644
--- a/Source/Editor/Managed/ManagedEditor.Internal.cpp
+++ b/Source/Editor/Managed/ManagedEditor.Internal.cpp
@@ -321,7 +321,7 @@ DEFINE_INTERNAL_CALL(bool) EditorInternal_SaveJsonAsset(MString* outputPathObj,
const StringView dataObjChars = MCore::String::GetChars(dataObj);
const StringAsANSI<> data(dataObjChars.Get(), dataObjChars.Length());
const StringAnsiView dataAnsi(data.Get(), data.Length());
-
+
const StringView dataTypeNameObjChars = MCore::String::GetChars(dataTypeNameObj);
const StringAsANSI<> dataTypeName(dataTypeNameObjChars.Get(), dataTypeNameObjChars.Length());
const StringAnsiView dataTypeNameAnsi(dataTypeName.Get(), dataTypeName.Length());
@@ -427,7 +427,7 @@ DEFINE_INTERNAL_CALL(void) EditorInternal_GetCollisionWires(CollisionData* colli
const int32 linesCount = debugLines.Count() / 2;
MCore::GC::WriteRef(triangles, (MObject*)MCore::Array::New(Float3::TypeInitializer.GetClass(), debugLines.Count()));
- MCore::GC::WriteRef(indices, (MObject*)MCore::Array::New( MCore::TypeCache::Int32, linesCount * 3));
+ MCore::GC::WriteRef(indices, (MObject*)MCore::Array::New(MCore::TypeCache::Int32, linesCount * 3));
// Use one triangle per debug line
Platform::MemoryCopy(MCore::Array::GetAddress(*triangles), debugLines.Get(), debugLines.Count() * sizeof(Float3));
@@ -585,7 +585,7 @@ DEFINE_INTERNAL_CALL(MArray*) EditorInternal_GetVisualScriptLocals(int* localsCo
const int32 count = stack->Scope->Parameters.Length() + stack->Scope->ReturnedValues.Count();
const MClass* mclass = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly->GetClass("FlaxEditor.Editor+VisualScriptLocal");
ASSERT(mclass);
- result = MCore::Array::New( mclass, count);
+ result = MCore::Array::New(mclass, count);
VisualScriptLocalManaged local;
local.NodeId = MAX_uint32;
if (stack->Scope->Parameters.Length() != 0)
@@ -642,7 +642,7 @@ DEFINE_INTERNAL_CALL(MArray*) EditorInternal_GetVisualScriptStackFrames(int* sta
}
const MClass* mclass = ((NativeBinaryModule*)GetBinaryModuleFlaxEngine())->Assembly->GetClass("FlaxEditor.Editor+VisualScriptStackFrame");
ASSERT(mclass);
- result = MCore::Array::New( mclass, count);
+ result = MCore::Array::New(mclass, count);
VisualScriptStackFrameManaged* resultPtr = MCore::Array::GetAddress(result);
s = stack;
count = 0;
From 16fed8927c9657bea85d990a75551ba77ef4a4be Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Mon, 11 Sep 2023 20:02:53 +0200
Subject: [PATCH 35/40] Refactor #1266 (code quality and simplicity)
---
Source/Editor/Content/ContentFilter.cs | 257 ------------------
...vigationButton.cs => ContentNavigation.cs} | 68 ++++-
.../Content/GUI/ContentNavigationBar.cs | 27 --
.../GUI/ContentNavigationButtonSeparator.cs | 85 ------
.../Content/GUI/ContentSettingsDropdown.cs | 95 -------
Source/Editor/Content/Items/ContentItem.cs | 8 +-
.../Content/Tree/RootContentTreeNode.cs | 2 +-
Source/Editor/GUI/ComboBox.cs | 27 +-
.../GUI/ContextMenu/ContextMenuButton.cs | 2 +-
Source/Editor/GUI/NavigationBar.cs | 7 +-
.../Editor/Modules/ContentDatabaseModule.cs | 17 ++
.../Windows/ContentWindow.Navigation.cs | 27 +-
Source/Editor/Windows/ContentWindow.Search.cs | 33 +--
Source/Editor/Windows/ContentWindow.cs | 170 ++++++++----
14 files changed, 241 insertions(+), 584 deletions(-)
delete mode 100644 Source/Editor/Content/ContentFilter.cs
rename Source/Editor/Content/GUI/{ContentNavigationButton.cs => ContentNavigation.cs} (59%)
delete mode 100644 Source/Editor/Content/GUI/ContentNavigationBar.cs
delete mode 100644 Source/Editor/Content/GUI/ContentNavigationButtonSeparator.cs
delete mode 100644 Source/Editor/Content/GUI/ContentSettingsDropdown.cs
diff --git a/Source/Editor/Content/ContentFilter.cs b/Source/Editor/Content/ContentFilter.cs
deleted file mode 100644
index 12cca5c41..000000000
--- a/Source/Editor/Content/ContentFilter.cs
+++ /dev/null
@@ -1,257 +0,0 @@
-using FlaxEditor.Content;
-using FlaxEditor.Content.GUI;
-using FlaxEngine;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-namespace FlaxEditor.Content
-{
- ///
- /// class with is controling visability of items in content window
- ///
- internal class ContentFilter
- {
- #region Filters Config
- ///
- /// all suported files by engine Content Folder
- ///
- public static readonly List SuportedFileExtencionsInContentFolder = new List()
- {
- ".flax",
- ".json",
- ".scene",
- ".prefab",
- };
- ///
- /// all suported files by engine Source Folder
- ///
- public static readonly List SuportedFileExtencionsInSourceFolder = new List()
- {
- ".shader",
- ".cs",
- ".h",
- ".cpp",
- };
- ///
- /// ignores folders in source folder (top layer),
- /// for example obj folder is default c# project folder
- ///
- internal static readonly List HideFoldersInSourceFolder = new List()
- {
- "obj", // default c# project folder
- "Properties", // c# project stuff ?
- };
- ///
- /// ignores files in source folder (top layer),
- ///
- internal static readonly List HideFilesInSourceFolder = new List() //dont edit
- {
- "Game.csproj", //solucion file
- "Game.Gen.cs", //auto-generated not be edited
- "GameEditorTarget.Build.cs",
- "GameTarget.Build.cs",
- };
- #endregion
- internal static ContentItem gameSettings;
- internal static List buildFiles;
-
- internal static ContentTreeNode settings;
- internal static ContentTreeNode shaders;
- internal static ProjectTreeNode engine;
- internal static List plugins = new();
- internal static List FilterFolder(ContentFolder folder)
- {
- return FilterFolder(folder, SuportedFileExtencionsInContentFolder.ToArray(), SuportedFileExtencionsInSourceFolder.ToArray());
- }
- internal static List FilterFolder(ContentFolder folder, string[] FileExtencionsInContentFolder, string[] ExtencionsInSourceFolder)
- {
- if (folder.CanHaveAssets)
- {
- for (int i = 0; i < folder.Children.Count; i++)
- {
- bool Visible = false;
- for (int j = 0; j < FileExtencionsInContentFolder.Length; j++)
- {
- if ((folder.Children[i].Path.EndsWith(FileExtencionsInContentFolder[j]) || folder.Children[i].IsFolder))
- {
- if (folder.Children[i].Visible)
- {
- Visible = true;
- }
- break;
- }
- }
- folder.Children[i].Visible = Visible;
- }
- }
- else if (folder.CanHaveScripts)
- {
- for (int i = 0; i < folder.Children.Count; i++)
- {
- bool Visible = false;
- for (int j = 0; j < ExtencionsInSourceFolder.Length; j++)
- {
- if ((folder.Children[i].Path.EndsWith(ExtencionsInSourceFolder[j]) || folder.Children[i].IsFolder))
- {
- if (folder.Children[i].Visible)
- {
- Visible = true;
- }
- break;
- }
- }
- folder.Children[i].Visible = Visible;
- }
- }
- return folder.Children;
- }
- internal static ProjectTreeNode Filter(ProjectTreeNode tree)
- {
- var content = tree.Children[0] as ContentTreeNode;
- var source = tree.Children[1] as ContentTreeNode;
- //filter content folder (top layer)
- buildFiles = new();
- for (int i = 0; i < content.Folder.Children.Count; i++)
- {
- if (content.Folder.Children[i].FileName == "GameSettings.json")
- {
- gameSettings = content.Folder.Children[i];
- content.Folder.Children[i].Visible = false;
- break;
- }
- }
-
- int hindenCount = 0;
-
- for (int i = content.Children.Count - 1; i >= 0; i--)//we are starting from back it faster
- {
- var node = content.Children[i] as ContentTreeNode;
- if (node.Folder.FileName == "Settings")
- {
- settings = node;
- hindenCount++;
- node.Visible = false;
- node.Folder.Visible = false;
- }
- if (node.Folder.FileName == "Shaders")
- {
- shaders = node;
- hindenCount++;
- node.Visible = false;
- node.Folder.Visible = false;
-
- }
- if (hindenCount == 2)
- break;
- }
-
-
- //-----------------------------------------------------------------------------------------------------
-
- //filter source folder (top layer)
- hindenCount = 0;
- for (int i = 0; i < source.Folder.Children.Count; i++)
- {
- for (int j = 0; j < HideFilesInSourceFolder.Count; j++)
- {
- if (source.Folder.Children[i].FileName == HideFilesInSourceFolder[j])
- {
- source.Folder.Children[i].Visible = false;
- hindenCount++;
- if(i > 1)
- {
- buildFiles.Add(source.Folder.Children[i]);
- }
- if (HideFilesInSourceFolder.Count == hindenCount) goto HideFilesInSourceFolderComplited;
- break;
- }
- }
- }
- HideFilesInSourceFolderComplited:
- hindenCount = 0;
- for (int i = source.Children.Count - 1; i >= 0; i--)
- {
- var node = source.Children[i] as ContentTreeNode;
- for (int j = 0; j < HideFoldersInSourceFolder.Count; j++)
- {
- if (node.Folder.FileName == HideFoldersInSourceFolder[j])
- {
- node.Visible = false;
- node.Folder.Visible = false;
- hindenCount++;
- if (HideFoldersInSourceFolder.Count == hindenCount) goto HideFoldersInSourceFolderComplited;
- break;
- }
- }
- }
- HideFoldersInSourceFolderComplited:
- //content
- return tree;
- }
- internal static void UpdateFilterVisability(ContentSettingsDropdown dropdown)
- {
- engine.Visible = false;
- engine.Folder.Visible = false;
-
- foreach (var item in plugins)
- {
- item.Visible = false;
- item.Folder.Visible = false;
- }
- foreach (var item in buildFiles)
- {
- item.Visible = false;
- }
- gameSettings.Visible = false;
- settings.Visible = false;
- settings.Folder.Visible = false;
-
- shaders.Visible = false;
- shaders.Folder.Visible = false;
-
- for (int i = 0; i < dropdown.Selection.Count; i++)
- {
- if (dropdown.Selection[i] == 0) //Show Engine Content
- {
- engine.Visible = true;
- engine.Folder.Visible = true;
- }
-
- if (dropdown.Selection[i] == 1)//Show Plugin Content
- {
- foreach (var item in plugins)
- {
- item.Visible = true;
- item.Folder.Visible = true;
- }
- }
-
- if (dropdown.Selection[i] == 2)//Show Build Files
- {
- foreach (var item in buildFiles)
- {
- item.Visible = true;
- }
- }
-
- if (dropdown.Selection[i] == 3)//Show Game Settings
- {
- gameSettings.Visible = true;
- settings.Visible = true;
- settings.Folder.Visible = true;
- }
-
- if (dropdown.Selection[i] == 4)//"Show Shader Source"
- {
- shaders.Visible = true;
- shaders.Folder.Visible = true;
- }
- }
- engine.ParentTree.PerformLayout();
- Editor.Instance.Windows.ContentWin.RefreshView();
- }
- }
-}
diff --git a/Source/Editor/Content/GUI/ContentNavigationButton.cs b/Source/Editor/Content/GUI/ContentNavigation.cs
similarity index 59%
rename from Source/Editor/Content/GUI/ContentNavigationButton.cs
rename to Source/Editor/Content/GUI/ContentNavigation.cs
index beec247da..7adf6aa62 100644
--- a/Source/Editor/Content/GUI/ContentNavigationButton.cs
+++ b/Source/Editor/Content/GUI/ContentNavigation.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using FlaxEditor.GUI;
+using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.GUI.Drag;
using FlaxEngine;
using FlaxEngine.GUI;
@@ -72,7 +73,6 @@ namespace FlaxEditor.Content.GUI
if (_dragOverItems == null)
_dragOverItems = new DragItems(ValidateDragItem);
-
_dragOverItems.OnDragEnter(data);
var result = GetDragEffect(data);
_validDragOver = result != DragDropEffect.None;
@@ -122,4 +122,70 @@ namespace FlaxEditor.Content.GUI
return result;
}
}
+
+ sealed class ContentNavigationSeparator : ComboBox
+ {
+ public ContentNavigationButton Target;
+
+ public ContentNavigationSeparator(ContentNavigationButton target, float x, float y, float height)
+ {
+ Target = target;
+ Bounds = new Rectangle(x, y, 16, height);
+ Offsets = new Margin(Bounds.X, Bounds.Width, Bounds.Y, Bounds.Height);
+ UpdateTransform();
+
+ MaximumItemsInViewCount = 20;
+ var style = Style.Current;
+ BackgroundColor = style.BackgroundNormal;
+ BackgroundColorHighlighted = BackgroundColor;
+ BackgroundColorSelected = BackgroundColor;
+ }
+
+ protected override ContextMenu OnCreatePopup()
+ {
+ // Update items
+ ClearItems();
+ foreach (var child in Target.TargetNode.Children)
+ {
+ if (child is ContentTreeNode node)
+ {
+ if (node.Folder.VisibleInHierarchy) // Respect the filter set by ContentFilterConfig.Filter(...)
+ AddItem(node.Folder.ShortName);
+ }
+ }
+
+ return base.OnCreatePopup();
+ }
+
+ public override void Draw()
+ {
+ var style = Style.Current;
+ var rect = new Rectangle(Float2.Zero, Size);
+ var color = IsDragOver ? style.BackgroundSelected * 0.6f : (_mouseDown ? style.BackgroundSelected : (IsMouseOver ? style.BackgroundHighlighted : Color.Transparent));
+ Render2D.FillRectangle(rect, color);
+ Render2D.DrawSprite(Editor.Instance.Icons.ArrowRight12, new Rectangle(rect.Location.X, rect.Y + rect.Size.Y * 0.25f, rect.Size.X, rect.Size.X), EnabledInHierarchy ? style.Foreground : style.ForegroundDisabled);
+ }
+
+ protected override void OnLayoutMenuButton(ContextMenuButton button, int index, bool construct = false)
+ {
+ button.Icon = Editor.Instance.Icons.FolderClosed32;
+ if (_tooltips != null && _tooltips.Length > index)
+ button.TooltipText = _tooltips[index];
+ }
+
+ protected override void OnItemClicked(int index)
+ {
+ base.OnItemClicked(index);
+
+ var item = _items[index];
+ foreach (var child in Target.TargetNode.Children)
+ {
+ if (child is ContentTreeNode node && node.Folder.ShortName == item)
+ {
+ Editor.Instance.Windows.ContentWin.Navigate(node);
+ return;
+ }
+ }
+ }
+ }
}
diff --git a/Source/Editor/Content/GUI/ContentNavigationBar.cs b/Source/Editor/Content/GUI/ContentNavigationBar.cs
deleted file mode 100644
index 673ac806e..000000000
--- a/Source/Editor/Content/GUI/ContentNavigationBar.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using FlaxEditor.GUI;
-using FlaxEngine;
-
-namespace FlaxEditor.Content.GUI
-{
- internal class ContentNavigationBar : NavigationBar
- {
- ToolStrip _toolstrip;
- internal float ofssetFromRightEdge = 80;
- internal ContentNavigationBar(ToolStrip toolstrip) : base()
- {
- _toolstrip = toolstrip;
- }
- ///
- protected override void Arrange()
- {
- base.Arrange();
- var lastToolstripButton = _toolstrip.LastButton;
- var parentSize = Parent.Size;
- Bounds = new Rectangle
- (
- new Float2(lastToolstripButton.Right, 0),
- new Float2(parentSize.X - X - ofssetFromRightEdge, _toolstrip.Height)
- );
- }
- }
-}
diff --git a/Source/Editor/Content/GUI/ContentNavigationButtonSeparator.cs b/Source/Editor/Content/GUI/ContentNavigationButtonSeparator.cs
deleted file mode 100644
index cad63066d..000000000
--- a/Source/Editor/Content/GUI/ContentNavigationButtonSeparator.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-using FlaxEditor;
-using FlaxEditor.GUI;
-using FlaxEditor.GUI.ContextMenu;
-using FlaxEngine;
-using FlaxEngine.GUI;
-using System.Collections.Generic;
-
-namespace FlaxEditor.Content.GUI
-{
- internal class ContentNavigationButtonSeparator : ComboBox
- {
- public ContentNavigationButton Target { get; }
- public ContentNavigationButtonSeparator(ContentNavigationButton target, float x, float y,float height)
- {
- Target = target;
- Bounds = new Rectangle(x, y, 16, height);
- Offsets = new Margin(Bounds.X, Bounds.Width, Bounds.Y, Bounds.Height);
- UpdateTransform();
-
- MaximumItemsInViewCount = 20;
- var style = Style.Current;
- BackgroundColor = style.BackgroundNormal;
- BackgroundColorHighlighted = BackgroundColor;
- BackgroundColorSelected = BackgroundColor;
- }
- protected override ContextMenu OnCreatePopup()
- {
- UpdateDropDownItems();
- return base.OnCreatePopup();
- }
- internal void UpdateDropDownItems()
- {
- ClearItems();
- _items = new();
- for (int i = 0; i < Target.TargetNode.Children.Count; i++)
- {
- if (Target.TargetNode.Children[i] is ContentTreeNode node)
- {
- if (node.Folder.VisibleInHierarchy) // respect the filter set by ContentFilterConfig.Filter(...)
- AddItem(node.Folder.ShortName);
- }
- }
- }
- ///
- public override void Draw()
- {
- // Cache data
- var style = Style.Current;
- var clientRect = new Rectangle(Float2.Zero, Size);
- // Draw background
- if (IsDragOver)
- {
- Render2D.FillRectangle(clientRect, Style.Current.BackgroundSelected * 0.6f);
- }
- else if (_mouseDown)
- {
- Render2D.FillRectangle(clientRect, style.BackgroundSelected);
- }
- else if (IsMouseOver)
- {
- Render2D.FillRectangle(clientRect, style.BackgroundHighlighted);
- }
-
- Render2D.DrawSprite(Editor.Instance.Icons.ArrowRight12, new Rectangle(clientRect.Location.X, clientRect.Y + ((Size.Y / 2f)/2f), Size.X, Size.X), EnabledInHierarchy ? Style.Current.Foreground : Style.Current.ForegroundDisabled);
- }
- protected override void OnLayoutMenuButton(ref ContextMenuButton button, int index, bool construct = false)
- {
- var style = Style.Current;
- button.Icon = Editor.Instance.Icons.FolderClosed32;
- if (_tooltips != null && _tooltips.Length > index)
- {
- button.TooltipText = _tooltips[index];
- }
- }
- protected override void OnItemClicked(int index)
- {
- base.OnItemClicked(index);
- if (Target.TargetNode.Children[index] is ContentTreeNode node)
- {
- Editor.Instance.Windows.ContentWin.Navigate(node);
- }
- // Navigate calls the OnDestroy at some point dont place code below or editor will crash
- }
- }
-}
diff --git a/Source/Editor/Content/GUI/ContentSettingsDropdown.cs b/Source/Editor/Content/GUI/ContentSettingsDropdown.cs
deleted file mode 100644
index 04722a674..000000000
--- a/Source/Editor/Content/GUI/ContentSettingsDropdown.cs
+++ /dev/null
@@ -1,95 +0,0 @@
-using FlaxEditor.Content;
-using FlaxEditor.CustomEditors.Editors;
-using FlaxEditor.GUI;
-using FlaxEditor.GUI.ContextMenu;
-using FlaxEditor.States;
-using FlaxEditor.Utilities;
-using FlaxEngine;
-using FlaxEngine.GUI;
-using FlaxEngine.Json;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace FlaxEditor.Content.GUI
-{
- class ContentSettingsDropdown : ComboBox
- {
- internal readonly List Settings = new()
- {
- "Show Engine Content",
- "Show Plugin Content",
- "Show Build Files",
- "Show Game Settings",
- "Show Shader Source"
- };
- public ContentSettingsDropdown()
- {
- SupportMultiSelect = true;
- MaximumItemsInViewCount = 20;
- var style = Style.Current;
- BackgroundColor = style.BackgroundNormal;
- BackgroundColorHighlighted = BackgroundColor;
- BackgroundColorSelected = BackgroundColor;
-
- }
- protected override ContextMenu OnCreatePopup()
- {
- UpdateDropDownItems();
- return base.OnCreatePopup();
- }
- internal void UpdateDropDownItems()
- {
- ClearItems();
-
- for (int i = 0; i < Settings.Count; i++)
- {
- AddItem(Settings[i]);
- }
- }
- ///
- public override void Draw()
- {
- // Cache data
- var style = Style.Current;
- var clientRect = new Rectangle(Float2.Zero, Size);
- // Draw background
- if (IsDragOver)
- {
- Render2D.FillRectangle(clientRect, Style.Current.BackgroundSelected * 0.6f);
- }
- else if (_mouseDown)
- {
- Render2D.FillRectangle(clientRect, style.BackgroundSelected);
- }
- else if (IsMouseOver)
- {
- Render2D.FillRectangle(clientRect, style.BackgroundHighlighted);
- }
- float size = (Size.Y / 1.5f); //Icon size
- // Draw text
- Render2D.DrawText(Font.GetFont(), "Settings", new Rectangle(size, 0, Size.X - Size.Y, Size.Y), TextColor, TextAlignment.Center, TextAlignment.Center);
- Render2D.DrawSprite(Editor.Instance.Icons.Settings12, new Rectangle((Size.Y - size) / 2.0f, (Size.Y - size) / 2.0f, size, size));
- }
- protected override void OnLayoutMenuButton(ref ContextMenuButton button, int index, bool construct = false)
- {
- var style = Style.Current;
- if (_selectedIndices.Contains(index))
- {
- button.Icon = style.CheckBoxTick;
- }
- else
- {
- button.Icon = SpriteHandle.Default;
- }
- if (_tooltips != null && _tooltips.Length > index)
- {
- button.TooltipText = _tooltips[index];
- }
- }
- protected override void OnSelectedIndexChanged()
- {
- ContentFilter.UpdateFilterVisability(this);
- base.OnSelectedIndexChanged();
- }
- }
-}
diff --git a/Source/Editor/Content/Items/ContentItem.cs b/Source/Editor/Content/Items/ContentItem.cs
index e6a8c309c..94db3a5b9 100644
--- a/Source/Editor/Content/Items/ContentItem.cs
+++ b/Source/Editor/Content/Items/ContentItem.cs
@@ -441,11 +441,9 @@ namespace FlaxEditor.Content
{
get
{
+ // Skip when hidden
if (!Visible)
- {
return Rectangle.Empty;
- }
-
var view = Parent as ContentView;
var size = Size;
switch (view?.ViewType ?? ContentViewType.Tiles)
@@ -453,7 +451,7 @@ namespace FlaxEditor.Content
case ContentViewType.Tiles:
{
var textHeight = DefaultTextHeight * size.X / DefaultWidth;
- return new Rectangle(0, size.Y - textHeight, size.X - 2, textHeight);
+ return new Rectangle(0, size.Y - textHeight, size.X, textHeight);
}
case ContentViewType.List:
{
@@ -671,8 +669,6 @@ namespace FlaxEditor.Content
///
public override void Draw()
{
-
- // Cache data
var size = Size;
var style = Style.Current;
var view = Parent as ContentView;
diff --git a/Source/Editor/Content/Tree/RootContentTreeNode.cs b/Source/Editor/Content/Tree/RootContentTreeNode.cs
index 6dde4cbb2..328c51874 100644
--- a/Source/Editor/Content/Tree/RootContentTreeNode.cs
+++ b/Source/Editor/Content/Tree/RootContentTreeNode.cs
@@ -17,6 +17,6 @@ namespace FlaxEditor.Content
}
///
- public override string NavButtonLabel => string.Empty;
+ public override string NavButtonLabel => " /";
}
}
diff --git a/Source/Editor/GUI/ComboBox.cs b/Source/Editor/GUI/ComboBox.cs
index da38268b2..da2106450 100644
--- a/Source/Editor/GUI/ComboBox.cs
+++ b/Source/Editor/GUI/ComboBox.cs
@@ -3,9 +3,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using FlaxEditor.GUI.ContextMenu;
using FlaxEngine;
using FlaxEngine.GUI;
-using FlaxEditor.GUI.ContextMenu;
namespace FlaxEditor.GUI
{
@@ -399,13 +399,14 @@ namespace FlaxEditor.GUI
OnItemClicked((int)btn.Tag);
if (SupportMultiSelect)
{
+ // Don't hide in multi-select, so user can edit multiple elements instead of just one
UpdateButtons();
_popupMenu?.PerformLayout();
}
else
{
_popupMenu?.Hide();
- }//[nori_sc] don't hide it Support MultiSelect is on actions per min is important for UX, if some one wont to set more then 5 elements in multi select menu let them do it
+ }
};
}
@@ -423,13 +424,15 @@ namespace FlaxEditor.GUI
if (_items.Count > 0)
{
UpdateButtons();
+
// Show dropdown list
_popupMenu.MinimumWidth = Width;
_popupMenu.Show(this, new Float2(1, Height));
}
}
+
///
- /// update buttons layout and repains
+ /// Updates buttons layout.
///
private void UpdateButtons()
{
@@ -443,7 +446,7 @@ namespace FlaxEditor.GUI
for (int i = 0; i < _items.Count; i++)
{
var btn = _popupMenu.AddButton(_items[i]);
- OnLayoutMenuButton(ref btn, i, true);
+ OnLayoutMenuButton(btn, i, true);
btn.Tag = i;
}
}
@@ -457,25 +460,23 @@ namespace FlaxEditor.GUI
if (itemControls[i] is ContextMenuButton btn)
{
btn.Text = _items[i];
- OnLayoutMenuButton(ref btn, i, true);
+ OnLayoutMenuButton(btn, i, true);
}
}
}
}
+
///
- /// caled when button is created or repainted u can overite it to give the button custom look
+ /// Called when button is created or updated. Can be used to customize the visuals.
///
- /// button refrance
- /// curent item index
+ /// The button.
+ /// The item index.
/// true if button is created else it is repainting the button
- protected virtual void OnLayoutMenuButton(ref FlaxEditor.GUI.ContextMenu.ContextMenuButton button,int index, bool construct = false)
+ protected virtual void OnLayoutMenuButton(ContextMenuButton button, int index, bool construct = false)
{
- var style = Style.Current;
button.Checked = _selectedIndices.Contains(index);
if (_tooltips != null && _tooltips.Length > index)
- {
button.TooltipText = _tooltips[index];
- }
}
///
@@ -498,6 +499,8 @@ namespace FlaxEditor.GUI
_popupMenu = null;
}
+ if (IsDisposing)
+ return;
_selectedIndices.Clear();
_selectedIndices = null;
_items.Clear();
diff --git a/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs b/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs
index c2b130e4e..e371f7c4b 100644
--- a/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs
+++ b/Source/Editor/GUI/ContextMenu/ContextMenuButton.cs
@@ -138,7 +138,7 @@ namespace FlaxEditor.GUI.ContextMenu
// Draw icon
const float iconSize = 14;
- var icon = Checked ? Style.Current.CheckBoxTick : Icon;
+ var icon = Checked ? style.CheckBoxTick : Icon;
if (icon.IsValid)
Render2D.DrawSprite(icon, new Rectangle(-iconSize - 1, (Height - iconSize) / 2, iconSize, iconSize), textColor);
}
diff --git a/Source/Editor/GUI/NavigationBar.cs b/Source/Editor/GUI/NavigationBar.cs
index 3c717423b..b3811b4a9 100644
--- a/Source/Editor/GUI/NavigationBar.cs
+++ b/Source/Editor/GUI/NavigationBar.cs
@@ -50,14 +50,9 @@ namespace FlaxEditor.GUI
{
if (toolstrip == null)
return;
-
var lastToolstripButton = toolstrip.LastButton;
var parentSize = Parent.Size;
- Bounds = new Rectangle
- (
- new Float2(lastToolstripButton.Right + 8.0f, 0),
- new Float2(parentSize.X - X - 8.0f, toolstrip.Height)
- );
+ Bounds = new Rectangle(lastToolstripButton.Right + 8.0f, 0, parentSize.X - X - 8.0f, toolstrip.Height);
}
}
}
diff --git a/Source/Editor/Modules/ContentDatabaseModule.cs b/Source/Editor/Modules/ContentDatabaseModule.cs
index ecafbf5d4..29d6b2c00 100644
--- a/Source/Editor/Modules/ContentDatabaseModule.cs
+++ b/Source/Editor/Modules/ContentDatabaseModule.cs
@@ -902,6 +902,23 @@ namespace FlaxEditor.Modules
}
if (sortChildren)
node.SortChildren();
+
+ // Ignore some special folders
+ if (node is MainContentTreeNode mainNode && mainNode.Folder.ShortName == "Source")
+ {
+ var mainNodeChild = mainNode.Folder.Find(StringUtils.CombinePaths(mainNode.Path, "obj")) as ContentFolder;
+ if (mainNodeChild != null)
+ {
+ mainNodeChild.Visible = false;
+ mainNodeChild.Node.Visible = false;
+ }
+ mainNodeChild = mainNode.Folder.Find(StringUtils.CombinePaths(mainNode.Path, "Properties")) as ContentFolder;
+ if (mainNodeChild != null)
+ {
+ mainNodeChild.Visible = false;
+ mainNodeChild.Node.Visible = false;
+ }
+ }
}
private void LoadScripts(ContentTreeNode parent, string[] files)
diff --git a/Source/Editor/Windows/ContentWindow.Navigation.cs b/Source/Editor/Windows/ContentWindow.Navigation.cs
index ca3de992d..b1def7ae8 100644
--- a/Source/Editor/Windows/ContentWindow.Navigation.cs
+++ b/Source/Editor/Windows/ContentWindow.Navigation.cs
@@ -196,18 +196,19 @@ namespace FlaxEditor.Windows
}
float x = NavigationBar.DefaultButtonsMargin;
float h = _toolStrip.ItemsHeight - 2 * ToolStrip.DefaultMarginV;
- for (int i = nodes.Count - 2; i >= 0; i--)
+ for (int i = nodes.Count - 1; i >= 0; i--)
{
- var button = new ContentNavigationButton(nodes[i], x - 100, ToolStrip.DefaultMarginV, h);
+ var button = new ContentNavigationButton(nodes[i], x, ToolStrip.DefaultMarginV, h);
button.PerformLayout();
x += button.Width + NavigationBar.DefaultButtonsMargin;
_navigationBar.AddChild(button);
- if (i == 0)
- continue;
- var buttonSeparator = new ContentNavigationButtonSeparator(button, x, ToolStrip.DefaultMarginV, h);
- buttonSeparator.PerformLayout();
- x += buttonSeparator.Width + NavigationBar.DefaultButtonsMargin;
- _navigationBar.AddChild(buttonSeparator);
+ if (i > 0)
+ {
+ var separator = new ContentNavigationSeparator(button, x, ToolStrip.DefaultMarginV, h);
+ separator.PerformLayout();
+ x += separator.Width + NavigationBar.DefaultButtonsMargin;
+ _navigationBar.AddChild(separator);
+ }
}
nodes.Clear();
@@ -224,21 +225,13 @@ namespace FlaxEditor.Windows
///
/// Gets the current view folder.
///
- public ContentFolder CurrentViewFolder
- {
- get
- {
- var node = SelectedNode;
- return node?.Folder;
- }
- }
+ public ContentFolder CurrentViewFolder => SelectedNode?.Folder;
///
/// Shows the root folder.
///
public void ShowRoot()
{
- // Show root folder
_tree.Select(_root);
}
}
diff --git a/Source/Editor/Windows/ContentWindow.Search.cs b/Source/Editor/Windows/ContentWindow.Search.cs
index a6fd2c81e..a1072d158 100644
--- a/Source/Editor/Windows/ContentWindow.Search.cs
+++ b/Source/Editor/Windows/ContentWindow.Search.cs
@@ -191,6 +191,7 @@ namespace FlaxEditor.Windows
}
// Search by filter only
+ bool showAllFiles = _showAllFiles;
if (string.IsNullOrWhiteSpace(query))
{
if (SelectedNode == _root)
@@ -199,12 +200,12 @@ namespace FlaxEditor.Windows
for (int i = 0; i < _root.ChildrenCount; i++)
{
if (_root.GetChild(i) is ContentTreeNode node)
- UpdateItemsSearchFilter(node.Folder, items, filters);
+ UpdateItemsSearchFilter(node.Folder, items, filters, showAllFiles);
}
}
else
{
- UpdateItemsSearchFilter(CurrentViewFolder, items, filters);
+ UpdateItemsSearchFilter(CurrentViewFolder, items, filters, showAllFiles);
}
}
// Search by asset ID
@@ -221,12 +222,12 @@ namespace FlaxEditor.Windows
for (int i = 0; i < _root.ChildrenCount; i++)
{
if (_root.GetChild(i) is ContentTreeNode node)
- UpdateItemsSearchFilter(node.Folder, items, filters, query);
+ UpdateItemsSearchFilter(node.Folder, items, filters, showAllFiles, query);
}
}
else
{
- UpdateItemsSearchFilter(CurrentViewFolder, items, filters, query);
+ UpdateItemsSearchFilter(CurrentViewFolder, items, filters, showAllFiles, query);
}
}
@@ -234,42 +235,34 @@ namespace FlaxEditor.Windows
_view.ShowItems(items, _sortType);
}
- private void UpdateItemsSearchFilter(ContentFolder folder, List items, bool[] filters)
+ private void UpdateItemsSearchFilter(ContentFolder folder, List items, bool[] filters, bool showAllFiles)
{
for (int i = 0; i < folder.Children.Count; i++)
{
var child = folder.Children[i];
-
if (child is ContentFolder childFolder)
{
- UpdateItemsSearchFilter(childFolder, items, filters);
+ UpdateItemsSearchFilter(childFolder, items, filters, showAllFiles);
}
- else
+ else if (filters[(int)child.SearchFilter] && (showAllFiles || !(child is FileItem)))
{
- if (filters[(int)child.SearchFilter])
- {
- items.Add(child);
- }
+ items.Add(child);
}
}
}
- private void UpdateItemsSearchFilter(ContentFolder folder, List items, bool[] filters, string filterText)
+ private void UpdateItemsSearchFilter(ContentFolder folder, List items, bool[] filters, bool showAllFiles, string filterText)
{
for (int i = 0; i < folder.Children.Count; i++)
{
var child = folder.Children[i];
-
if (child is ContentFolder childFolder)
{
- UpdateItemsSearchFilter(childFolder, items, filters, filterText);
+ UpdateItemsSearchFilter(childFolder, items, filters, showAllFiles, filterText);
}
- else if (filters[(int)child.SearchFilter])
+ else if (filters[(int)child.SearchFilter] && (showAllFiles || !(child is FileItem)) && QueryFilterHelper.Match(filterText, child.ShortName))
{
- if (filters[(int)child.SearchFilter] && QueryFilterHelper.Match(filterText, child.ShortName))
- {
- items.Add(child);
- }
+ items.Add(child);
}
}
}
diff --git a/Source/Editor/Windows/ContentWindow.cs b/Source/Editor/Windows/ContentWindow.cs
index 2a779ec01..f4fb4afdc 100644
--- a/Source/Editor/Windows/ContentWindow.cs
+++ b/Source/Editor/Windows/ContentWindow.cs
@@ -4,6 +4,7 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
+using System.Linq;
using System.Xml;
using FlaxEditor.Content;
using FlaxEditor.Content.GUI;
@@ -39,14 +40,13 @@ namespace FlaxEditor.Windows
private readonly ToolStripButton _navigateForwardButton;
private readonly ToolStripButton _navigateUpButton;
- private ContentNavigationBar _navigationBar;
+ private NavigationBar _navigationBar;
private Tree _tree;
private TextBox _foldersSearchBox;
private TextBox _itemsSearchBox;
private ViewDropdown _viewDropdown;
- private ContentSettingsDropdown _ContentSettingDropdown;
- private const float _ContentDropdownSizeX = 100;
private SortType _sortType;
+ private bool _showEngineFiles = true, _showPluginsFiles = true, _showAllFiles = true;
private RootContentTreeNode _root;
@@ -66,6 +66,57 @@ namespace FlaxEditor.Windows
///
public ContentView View => _view;
+ internal bool ShowEngineFiles
+ {
+ get => _showEngineFiles;
+ set
+ {
+ if (_showEngineFiles != value)
+ {
+ _showEngineFiles = value;
+ if (Editor.ContentDatabase.Engine != null)
+ {
+ Editor.ContentDatabase.Engine.Visible = value;
+ Editor.ContentDatabase.Engine.Folder.Visible = value;
+ RefreshView();
+ }
+ }
+ }
+ }
+
+ internal bool ShowPluginsFiles
+ {
+ get => _showPluginsFiles;
+ set
+ {
+ if (_showPluginsFiles != value)
+ {
+ _showPluginsFiles = value;
+ foreach (var project in Editor.ContentDatabase.Projects)
+ {
+ if (project == Editor.ContentDatabase.Game || project == Editor.ContentDatabase.Engine)
+ continue;
+ project.Visible = value;
+ project.Folder.Visible = value;
+ RefreshView();
+ }
+ }
+ }
+ }
+
+ internal bool ShowAllFiles
+ {
+ get => _showAllFiles;
+ set
+ {
+ if (_showAllFiles != value)
+ {
+ _showAllFiles = value;
+ RefreshView();
+ }
+ }
+ }
+
///
/// Initializes a new instance of the class.
///
@@ -75,7 +126,7 @@ namespace FlaxEditor.Windows
{
Title = "Content";
Icon = editor.Icons.Folder32;
-
+
// Content database events
editor.ContentDatabase.WorkspaceModified += () => _isWorkspaceDirty = true;
editor.ContentDatabase.ItemRemoved += OnContentDatabaseItemRemoved;
@@ -110,24 +161,11 @@ namespace FlaxEditor.Windows
_navigateForwardButton = (ToolStripButton)_toolStrip.AddButton(Editor.Icons.Right64, NavigateForward).LinkTooltip("Navigate forward");
_navigateUpButton = (ToolStripButton)_toolStrip.AddButton(Editor.Icons.Up64, NavigateUp).LinkTooltip("Navigate up");
_toolStrip.AddSeparator();
+
// Navigation bar
-
- _navigationBar = new ContentNavigationBar(_toolStrip)
+ _navigationBar = new NavigationBar
{
Parent = _toolStrip,
- ofssetFromRightEdge = _ContentDropdownSizeX
- };
- var DropdownSettingsPanel = new Panel(ScrollBars.None)
- {
- Parent = _toolStrip,
- Size = new Float2(_ContentDropdownSizeX, _toolStrip.Height)
- };
- //setings Dropdown
- _ContentSettingDropdown = new ContentSettingsDropdown
- {
- AnchorPreset = AnchorPresets.StretchAll,
- Parent = DropdownSettingsPanel,
- Offsets = new Margin(2, 4, 4, 4)
};
// Split panel
@@ -231,10 +269,6 @@ namespace FlaxEditor.Windows
private ContextMenu OnViewDropdownPopupCreate(ComboBox comboBox)
{
var menu = new ContextMenu();
-
- var showFileExtensionsButton = menu.AddButton("Show file extensions", () => View.ShowFileExtensions = !View.ShowFileExtensions);
- showFileExtensionsButton.Checked = View.ShowFileExtensions;
- showFileExtensionsButton.AutoCheck = true;
var viewScale = menu.AddButton("View Scale");
viewScale.CloseMenuOnClick = false;
@@ -259,6 +293,33 @@ namespace FlaxEditor.Windows
}
};
+ var show = menu.AddChildMenu("Show");
+ {
+ var b = show.ContextMenu.AddButton("File extensions", () => View.ShowFileExtensions = !View.ShowFileExtensions);
+ b.TooltipText = "Shows all files with extensions";
+ b.Checked = View.ShowFileExtensions;
+ b.CloseMenuOnClick = false;
+ b.AutoCheck = true;
+
+ b = show.ContextMenu.AddButton("Engine files", () => ShowEngineFiles = !ShowEngineFiles);
+ b.TooltipText = "Shows in-built engine content";
+ b.Checked = ShowEngineFiles;
+ b.CloseMenuOnClick = false;
+ b.AutoCheck = true;
+
+ b = show.ContextMenu.AddButton("Plugins files", () => ShowPluginsFiles = !ShowPluginsFiles);
+ b.TooltipText = "Shows plugin projects content";
+ b.Checked = ShowPluginsFiles;
+ 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";
+ b.Checked = ShowAllFiles;
+ b.CloseMenuOnClick = false;
+ b.AutoCheck = true;
+ }
+
var filters = menu.AddChildMenu("Filters");
for (int i = 0; i < _viewDropdown.Items.Count; i++)
{
@@ -367,7 +428,7 @@ namespace FlaxEditor.Windows
{
if (!item.CanRename)
return;
-
+
// Show element in the view
Select(item, true);
@@ -444,10 +505,7 @@ namespace FlaxEditor.Windows
if (!Editor.ContentEditing.IsValidAssetName(item, newShortName, out string hint))
{
// Invalid name
- MessageBox.Show("Given asset name is invalid. " + hint,
- "Invalid name",
- MessageBoxButtons.OK,
- MessageBoxIcon.Error);
+ MessageBox.Show("Given asset name is invalid. " + hint, "Invalid name", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
@@ -893,7 +951,7 @@ namespace FlaxEditor.Windows
if (target == _root)
{
// Special case for root folder
- List items = new List(8);
+ var items = new List(8);
for (int i = 0; i < _root.ChildrenCount; i++)
{
if (_root.GetChild(i) is ContentTreeNode node)
@@ -905,9 +963,11 @@ namespace FlaxEditor.Windows
}
else
{
-
// Show folder contents
- _view.ShowItems(ContentFilter.FilterFolder(target.Folder), _sortType, false, true);
+ var items = target.Folder.Children;
+ if (!_showAllFiles)
+ items = items.Where(x => !(x is FileItem)).ToList();
+ _view.ShowItems(items, _sortType, false, true);
}
}
@@ -930,12 +990,6 @@ namespace FlaxEditor.Windows
_navigateUpButton.Enabled = folder != null && _tree.SelectedNode != _root;
}
- private void RemoveFolder2Root(ContentTreeNode node)
- {
- // Remove from the root
- _root.RemoveChild(node);
- }
-
///
public override void OnInit()
{
@@ -947,18 +1001,20 @@ namespace FlaxEditor.Windows
_root.Expand(true);
// Add game project on top, plugins in the middle and engine at bottom
- _root.AddChild(ContentFilter.Filter(Editor.ContentDatabase.Game));
+ _root.AddChild(Editor.ContentDatabase.Game);
Editor.ContentDatabase.Projects.Sort();
foreach (var project in Editor.ContentDatabase.Projects)
{
project.SortChildrenRecursive();
if (project == Editor.ContentDatabase.Game || project == Editor.ContentDatabase.Engine)
continue;
+ project.Visible = _showPluginsFiles;
+ project.Folder.Visible = _showPluginsFiles;
_root.AddChild(project);
- ContentFilter.plugins.Add(project);
}
+ Editor.ContentDatabase.Engine.Visible = _showEngineFiles;
+ Editor.ContentDatabase.Engine.Folder.Visible = _showEngineFiles;
_root.AddChild(Editor.ContentDatabase.Engine);
- ContentFilter.engine = Editor.ContentDatabase.Engine;
Editor.ContentDatabase.Game?.Expand(true);
_tree.Margin = new Margin(0.0f, 0.0f, -16.0f, 2.0f); // Hide root node
@@ -1029,7 +1085,6 @@ namespace FlaxEditor.Windows
///
public override bool OnMouseUp(Float2 location, MouseButton button)
{
- // Check if it's a right mouse button
if (button == MouseButton.Right)
{
// Find control that is under the mouse
@@ -1067,6 +1122,15 @@ namespace FlaxEditor.Windows
return base.OnMouseUp(location, button);
}
+
+ ///
+ protected override void PerformLayoutBeforeChildren()
+ {
+ base.PerformLayoutBeforeChildren();
+
+ _navigationBar?.UpdateBounds(_toolStrip);
+ }
+
///
public override bool UseLayoutData => true;
@@ -1076,13 +1140,10 @@ namespace FlaxEditor.Windows
LayoutSerializeSplitter(writer, "Split", _split);
writer.WriteAttributeString("Scale", _view.ViewScale.ToString(CultureInfo.InvariantCulture));
writer.WriteAttributeString("ShowFileExtensions", _view.ShowFileExtensions.ToString());
+ writer.WriteAttributeString("ShowEngineFiles", ShowEngineFiles.ToString());
+ writer.WriteAttributeString("ShowPluginsFiles", ShowPluginsFiles.ToString());
+ writer.WriteAttributeString("ShowAllFiles", ShowAllFiles.ToString());
writer.WriteAttributeString("ViewType", _view.ViewType.ToString());
- for (int i = 0; i < _ContentSettingDropdown.Selection.Count; i++)
- {
- if(_ContentSettingDropdown.Selection.Count != 0)
- writer.WriteAttributeString(_ContentSettingDropdown.Settings[_ContentSettingDropdown.Selection[i]].Replace(' ', '_'), _ContentSettingDropdown.Selection[i].ToString());
- }
-
}
///
@@ -1093,17 +1154,14 @@ namespace FlaxEditor.Windows
_view.ViewScale = value1;
if (bool.TryParse(node.GetAttribute("ShowFileExtensions"), out bool value2))
_view.ShowFileExtensions = value2;
+ if (bool.TryParse(node.GetAttribute("ShowEngineFiles"), out value2))
+ ShowEngineFiles = value2;
+ if (bool.TryParse(node.GetAttribute("ShowPluginsFiles"), out value2))
+ ShowPluginsFiles = value2;
+ if (bool.TryParse(node.GetAttribute("ShowAllFiles"), out value2))
+ ShowAllFiles = value2;
if (Enum.TryParse(node.GetAttribute("ViewType"), out ContentViewType viewType))
_view.ViewType = viewType;
-
- for (int i = 0; i < _ContentSettingDropdown.Settings.Count; i++)
- {
- int flag;
- if (int.TryParse(node.GetAttribute(_ContentSettingDropdown.Settings[i].Replace(' ', '_')), out flag))
- _ContentSettingDropdown.Selection.Add(flag);
-
- }
- ContentFilter.UpdateFilterVisability(_ContentSettingDropdown);
}
///
From 0a5f983ff4eff7fc2b9bf23ad3f75423e77761ac Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Mon, 11 Sep 2023 21:36:36 +0200
Subject: [PATCH 36/40] Fix error when model is missing in Editor for prefab
editor
#1354
---
Source/Editor/CustomEditors/Editors/ModelInstanceEntryEditor.cs | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Source/Editor/CustomEditors/Editors/ModelInstanceEntryEditor.cs b/Source/Editor/CustomEditors/Editors/ModelInstanceEntryEditor.cs
index 277f9ecb0..9607680f2 100644
--- a/Source/Editor/CustomEditors/Editors/ModelInstanceEntryEditor.cs
+++ b/Source/Editor/CustomEditors/Editors/ModelInstanceEntryEditor.cs
@@ -39,6 +39,8 @@ namespace FlaxEditor.CustomEditors.Editors
_entryIndex = entryIndex;
_modelInstance = modelInstance;
var slots = modelInstance.MaterialSlots;
+ if (slots == null || entryIndex >= slots.Length)
+ return;
if (entry.Material == slots[entryIndex].Material)
{
// Ensure that entry with default material set is set back to null
From 776fbe2a7b8a44b7c008c7337827c17031d226a6 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Mon, 11 Sep 2023 22:30:51 +0200
Subject: [PATCH 37/40] Fix creating plugin with whitespace or non-ASCII
character in the name
#1335
---
Source/Editor/Windows/PluginsWindow.cs | 26 ++++++++++++++++----------
1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/Source/Editor/Windows/PluginsWindow.cs b/Source/Editor/Windows/PluginsWindow.cs
index cf68c6ad8..f4acfffc8 100644
--- a/Source/Editor/Windows/PluginsWindow.cs
+++ b/Source/Editor/Windows/PluginsWindow.cs
@@ -636,11 +636,17 @@ namespace FlaxEditor.Windows
{
Debug.Logger.LogHandler.LogWrite(LogType.Error, $"Failed to add plugin to project. {e}");
}
-
var oldpluginPath = Path.Combine(extractPath, "ExamplePlugin-master");
var newPluginPath = Path.Combine(extractPath , pluginName);
Directory.Move(oldpluginPath, newPluginPath);
+ // Format plugin name into a valid name for code (C#/C++ typename)
+ var pluginCodeName = Content.ScriptItem.FilterScriptName(pluginName);
+ if (string.IsNullOrEmpty(pluginCodeName))
+ pluginCodeName = "MyPlugin";
+ Editor.Log($"Using plugin code type name: {pluginCodeName}");
+
+
var oldFlaxProjFile = Path.Combine(newPluginPath, "ExamplePlugin.flaxproj");
var newFlaxProjFile = Path.Combine(newPluginPath, $"{pluginName}.flaxproj");
File.Move(oldFlaxProjFile, newFlaxProjFile);
@@ -659,8 +665,8 @@ namespace FlaxEditor.Windows
flaxPluginProjContents.Version = new Version(pluginVersion);
if (!string.IsNullOrEmpty(companyName))
flaxPluginProjContents.Company = companyName;
- flaxPluginProjContents.GameTarget = $"{pluginName}Target";
- flaxPluginProjContents.EditorTarget = $"{pluginName}EditorTarget";
+ flaxPluginProjContents.GameTarget = $"{pluginCodeName}Target";
+ flaxPluginProjContents.EditorTarget = $"{pluginCodeName}EditorTarget";
await File.WriteAllTextAsync(newFlaxProjFile, JsonSerializer.Serialize(flaxPluginProjContents, typeof(ProjectInfo)));
// Rename source directories
@@ -676,14 +682,14 @@ namespace FlaxEditor.Windows
File.Delete(file);
continue;
}
-
+
var fileText = await File.ReadAllTextAsync(file);
- await File.WriteAllTextAsync(file, fileText.Replace("ExamplePlugin", pluginName));
- var fileName = Path.GetFileName(file).Replace("ExamplePlugin", pluginName);
+ await File.WriteAllTextAsync(file, fileText.Replace("ExamplePlugin", pluginCodeName));
+ var fileName = Path.GetFileName(file).Replace("ExamplePlugin", pluginCodeName);
File.Move(file, Path.Combine(directory, fileName));
}
-
- var newName = directory.Replace("ExamplePlugin", pluginName);
+
+ var newName = directory.Replace("ExamplePlugin", pluginCodeName);
Directory.Move(directory, newName);
}
@@ -692,8 +698,8 @@ namespace FlaxEditor.Windows
foreach (var file in targetFiles)
{
var fileText = await File.ReadAllTextAsync(file);
- await File.WriteAllTextAsync(file, fileText.Replace("ExamplePlugin", pluginName));
- var newName = file.Replace("ExamplePlugin", pluginName);
+ await File.WriteAllTextAsync(file, fileText.Replace("ExamplePlugin", pluginCodeName));
+ var newName = file.Replace("ExamplePlugin", pluginCodeName);
File.Move(file, newName);
}
Debug.Logger.LogHandler.LogWrite(LogType.Info, $"Plugin project {pluginName} has successfully been created.");
From 99c2adc1f3f91ee9f6240b35b38858fb57747393 Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Mon, 11 Sep 2023 22:32:17 +0200
Subject: [PATCH 38/40] Add game settings formatting for created plugin
ProjectInfo
#1335
---
Source/Editor/Windows/PluginsWindow.cs | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/Source/Editor/Windows/PluginsWindow.cs b/Source/Editor/Windows/PluginsWindow.cs
index f4acfffc8..fa2547797 100644
--- a/Source/Editor/Windows/PluginsWindow.cs
+++ b/Source/Editor/Windows/PluginsWindow.cs
@@ -669,6 +669,17 @@ namespace FlaxEditor.Windows
flaxPluginProjContents.EditorTarget = $"{pluginCodeName}EditorTarget";
await File.WriteAllTextAsync(newFlaxProjFile, JsonSerializer.Serialize(flaxPluginProjContents, typeof(ProjectInfo)));
+ // Format game settings
+ var gameSettingsPath = Path.Combine(newPluginPath, "Content", "GameSettings.json");
+ if (File.Exists(gameSettingsPath))
+ {
+ var contents = await File.ReadAllTextAsync(gameSettingsPath);
+ contents = contents.Replace("Example Plugin", pluginName);
+ contents = contents.Replace("\"CompanyName\": \"Flax\"", $"\"CompanyName\": \"{companyName}\"");
+ contents = contents.Replace("1.0", pluginVersion);
+ await File.WriteAllTextAsync(gameSettingsPath, contents, Encoding.UTF8);
+ }
+
// Rename source directories
var sourcePath = Path.Combine(newPluginPath, "Source");
var sourceDirectories = Directory.GetDirectories(sourcePath);
From 985d6cc811134f5321b71fd81d16680efb941bef Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Mon, 11 Sep 2023 22:32:37 +0200
Subject: [PATCH 39/40] Add UTF8 format for created plugin files and format
code
#1335
---
Source/Editor/Content/Items/ScriptItem.cs | 2 +-
Source/Editor/Windows/PluginsWindow.cs | 87 ++++++++++++-----------
2 files changed, 45 insertions(+), 44 deletions(-)
diff --git a/Source/Editor/Content/Items/ScriptItem.cs b/Source/Editor/Content/Items/ScriptItem.cs
index 811afc179..95b879b79 100644
--- a/Source/Editor/Content/Items/ScriptItem.cs
+++ b/Source/Editor/Content/Items/ScriptItem.cs
@@ -30,7 +30,7 @@ namespace FlaxEditor.Content
ShowFileExtension = true;
}
- private static string FilterScriptName(string input)
+ internal static string FilterScriptName(string input)
{
var length = input.Length;
var sb = new StringBuilder(length);
diff --git a/Source/Editor/Windows/PluginsWindow.cs b/Source/Editor/Windows/PluginsWindow.cs
index fa2547797..d53b64e22 100644
--- a/Source/Editor/Windows/PluginsWindow.cs
+++ b/Source/Editor/Windows/PluginsWindow.cs
@@ -6,6 +6,7 @@ using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net.Http;
+using System.Text;
using System.Threading.Tasks;
using FlaxEditor.GUI;
using FlaxEditor.GUI.ContextMenu;
@@ -13,7 +14,6 @@ using FlaxEditor.GUI.Tabs;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Json;
-using Debug = FlaxEngine.Debug;
namespace FlaxEditor.Windows
{
@@ -193,7 +193,7 @@ namespace FlaxEditor.Windows
Text = "Create Plugin Project",
TooltipText = "Add new plugin project.",
AnchorPreset = AnchorPresets.TopLeft,
- LocalLocation = new Float2(70,18),
+ LocalLocation = new Float2(70, 18),
Size = new Float2(150, 25),
Parent = vp,
};
@@ -209,7 +209,7 @@ namespace FlaxEditor.Windows
Parent = vp,
};
_cloneProjectButton.Clicked += OnCloneProjectButtonClicked;
-
+
_tabs = new Tabs
{
Orientation = Orientation.Vertical,
@@ -254,7 +254,7 @@ namespace FlaxEditor.Windows
nameTextBox.LocalX += (300 - (10)) * 0.5f;
nameTextBox.LocalY += 10;
nameLabel.LocalX += (300 - (nameLabel.Width + nameTextBox.Width)) * 0.5f + 10;
-
+
var defaultTextBoxBorderColor = nameTextBox.BorderColor;
var defaultTextBoxBorderSelectedColor = nameTextBox.BorderSelectedColor;
nameTextBox.TextChanged += () =>
@@ -265,7 +265,7 @@ namespace FlaxEditor.Windows
nameTextBox.BorderSelectedColor = defaultTextBoxBorderSelectedColor;
return;
}
-
+
var pluginPath = Path.Combine(Globals.ProjectFolder, "Plugins", nameTextBox.Text);
if (Directory.Exists(pluginPath))
{
@@ -315,7 +315,7 @@ namespace FlaxEditor.Windows
{
if (Directory.Exists(Path.Combine(Globals.ProjectFolder, "Plugins", nameTextBox.Text)) && !string.IsNullOrEmpty(nameTextBox.Text))
{
- Debug.Logger.LogHandler.LogWrite(LogType.Warning, "Cannot create plugin due to name conflict.");
+ Editor.LogWarning("Cannot create plugin due to name conflict.");
return;
}
OnCloneButtonClicked(nameTextBox.Text, gitPathTextBox.Text);
@@ -346,7 +346,7 @@ namespace FlaxEditor.Windows
{
if (string.IsNullOrEmpty(gitPath))
{
- Debug.Logger.LogHandler.LogWrite(LogType.Error, $"Failed to create plugin project due to no GIT path.");
+ Editor.LogError($"Failed to create plugin project due to no GIT path.");
return;
}
if (string.IsNullOrEmpty(pluginName))
@@ -363,32 +363,34 @@ namespace FlaxEditor.Windows
pluginName = name;
}
}
-
+
var clonePath = Path.Combine(Globals.ProjectFolder, "Plugins", pluginName);
if (!Directory.Exists(clonePath))
Directory.CreateDirectory(clonePath);
else
{
- Debug.Logger.LogHandler.LogWrite(LogType.Error, $"Plugin Name is already used. Pick a different Name.");
+ Editor.LogError($"Plugin Name is already used. Pick a different Name.");
return;
}
try
{
// Start git clone
- var settings = new CreateProcessSettings();
- settings.FileName = "git";
- settings.Arguments = $"clone {gitPath} \"{clonePath}\"";
- settings.ShellExecute = false;
- settings.LogOutput = true;
+ var settings = new CreateProcessSettings
+ {
+ FileName = "git",
+ Arguments = $"clone {gitPath} \"{clonePath}\"",
+ ShellExecute = false,
+ LogOutput = true,
+ };
Platform.CreateProcess(ref settings);
}
catch (Exception e)
{
- Debug.Logger.LogHandler.LogWrite(LogType.Error, $"Failed Git process. {e}");
+ Editor.LogError($"Failed Git process. {e}");
return;
}
-
- Debug.Logger.LogHandler.LogWrite(LogType.Info, $"Plugin project has been cloned.");
+
+ Editor.Log($"Plugin project has been cloned.");
// Find project config file. Could be different then what the user named the folder.
var files = Directory.GetFiles(clonePath);
@@ -401,9 +403,9 @@ namespace FlaxEditor.Windows
Debug.Log(pluginProjectName);
}
}
-
+
if (string.IsNullOrEmpty(pluginProjectName))
- Debug.Logger.LogHandler.LogWrite(LogType.Error, $"Failed to find plugin project file to add to Project config. Please add manually.");
+ Editor.LogError($"Failed to find plugin project file to add to Project config. Please add manually.");
else
{
await AddReferenceToProject(pluginName, pluginProjectName);
@@ -450,7 +452,7 @@ namespace FlaxEditor.Windows
nameTextBox.BorderSelectedColor = defaultTextBoxBorderSelectedColor;
return;
}
-
+
var pluginPath = Path.Combine(Globals.ProjectFolder, "Plugins", nameTextBox.Text);
if (Directory.Exists(pluginPath))
{
@@ -518,7 +520,7 @@ namespace FlaxEditor.Windows
{
if (Directory.Exists(Path.Combine(Globals.ProjectFolder, "Plugins", nameTextBox.Text)))
{
- Debug.Logger.LogHandler.LogWrite(LogType.Warning, "Cannot create plugin due to name conflict.");
+ Editor.LogWarning("Cannot create plugin due to name conflict.");
return;
}
OnCreateButtonClicked(nameTextBox.Text, versionTextBox.Text, companyTextBox.Text);
@@ -551,10 +553,10 @@ namespace FlaxEditor.Windows
{
if (string.IsNullOrEmpty(pluginName))
{
- Debug.Logger.LogHandler.LogWrite(LogType.Error, $"Failed to create plugin project due to no plugin name.");
+ Editor.LogError($"Failed to create plugin project due to no plugin name.");
return;
}
-
+
var templateUrl = "https://github.com/FlaxEngine/ExamplePlugin/archive/refs/heads/master.zip";
var localTemplateFolderLocation = Path.Combine(Editor.LocalCachePath, "TemplatePluginCache");
if (!Directory.Exists(localTemplateFolderLocation))
@@ -564,24 +566,24 @@ namespace FlaxEditor.Windows
try
{
// Download example plugin
- using (HttpClient client = new HttpClient())
+ using (var client = new HttpClient())
{
byte[] zipBytes = await client.GetByteArrayAsync(templateUrl);
- await File.WriteAllBytesAsync(!File.Exists(localTemplatePath) ? Path.Combine(localTemplatePath) : Path.Combine(Editor.LocalCachePath, "TemplatePluginCache" , "TemplatePlugin1.zip"), zipBytes);
-
- Debug.Logger.LogHandler.LogWrite(LogType.Info, "Template for plugin project has downloaded");
+ await File.WriteAllBytesAsync(!File.Exists(localTemplatePath) ? Path.Combine(localTemplatePath) : Path.Combine(Editor.LocalCachePath, "TemplatePluginCache", "TemplatePlugin1.zip"), zipBytes);
+
+ Editor.Log("Template for plugin project has downloaded");
}
}
catch (Exception e)
{
- Debug.Logger.LogHandler.LogWrite(LogType.Error, $"Failed to download template project. Trying to use local file. {e}");
+ Editor.LogError($"Failed to download template project. Trying to use local file. {e}");
if (!File.Exists(localTemplatePath))
{
- Debug.Logger.LogHandler.LogWrite(LogType.Error, $"Failed to use local file. Does not exist.");
+ Editor.LogError($"Failed to use local file. Does not exist.");
return;
}
}
-
+
// Check if any changes in new downloaded file
if (File.Exists(Path.Combine(Editor.LocalCachePath, "TemplatePluginCache", "TemplatePlugin1.zip")))
{
@@ -622,7 +624,7 @@ namespace FlaxEditor.Windows
File.Delete(localTemplatePath2);
}
}
-
+
var extractPath = Path.Combine(Globals.ProjectFolder, "Plugins");
if (!Directory.Exists(extractPath))
Directory.CreateDirectory(extractPath);
@@ -630,15 +632,12 @@ namespace FlaxEditor.Windows
try
{
await Task.Run(() => ZipFile.ExtractToDirectory(localTemplatePath, extractPath));
- Debug.Logger.LogHandler.LogWrite(LogType.Info, "Template for plugin project successfully moved to project.");
+ Editor.Log("Template for plugin project successfully moved to project.");
}
catch (IOException e)
{
- Debug.Logger.LogHandler.LogWrite(LogType.Error, $"Failed to add plugin to project. {e}");
+ Editor.LogError($"Failed to add plugin to project. {e}");
}
- var oldpluginPath = Path.Combine(extractPath, "ExamplePlugin-master");
- var newPluginPath = Path.Combine(extractPath , pluginName);
- Directory.Move(oldpluginPath, newPluginPath);
// Format plugin name into a valid name for code (C#/C++ typename)
var pluginCodeName = Content.ScriptItem.FilterScriptName(pluginName);
@@ -646,11 +645,14 @@ namespace FlaxEditor.Windows
pluginCodeName = "MyPlugin";
Editor.Log($"Using plugin code type name: {pluginCodeName}");
+ var oldPluginPath = Path.Combine(extractPath, "ExamplePlugin-master");
+ var newPluginPath = Path.Combine(extractPath, pluginName);
+ Directory.Move(oldPluginPath, newPluginPath);
var oldFlaxProjFile = Path.Combine(newPluginPath, "ExamplePlugin.flaxproj");
var newFlaxProjFile = Path.Combine(newPluginPath, $"{pluginName}.flaxproj");
File.Move(oldFlaxProjFile, newFlaxProjFile);
-
+
var readme = Path.Combine(newPluginPath, "README.md");
if (File.Exists(readme))
File.Delete(readme);
@@ -667,7 +669,7 @@ namespace FlaxEditor.Windows
flaxPluginProjContents.Company = companyName;
flaxPluginProjContents.GameTarget = $"{pluginCodeName}Target";
flaxPluginProjContents.EditorTarget = $"{pluginCodeName}EditorTarget";
- await File.WriteAllTextAsync(newFlaxProjFile, JsonSerializer.Serialize(flaxPluginProjContents, typeof(ProjectInfo)));
+ await File.WriteAllTextAsync(newFlaxProjFile, JsonSerializer.Serialize(flaxPluginProjContents, typeof(ProjectInfo)), Encoding.UTF8);
// Format game settings
var gameSettingsPath = Path.Combine(newPluginPath, "Content", "GameSettings.json");
@@ -703,17 +705,17 @@ namespace FlaxEditor.Windows
var newName = directory.Replace("ExamplePlugin", pluginCodeName);
Directory.Move(directory, newName);
}
-
+
// Rename targets
var targetFiles = Directory.GetFiles(sourcePath);
foreach (var file in targetFiles)
{
var fileText = await File.ReadAllTextAsync(file);
- await File.WriteAllTextAsync(file, fileText.Replace("ExamplePlugin", pluginCodeName));
+ await File.WriteAllTextAsync(file, fileText.Replace("ExamplePlugin", pluginCodeName), Encoding.UTF8);
var newName = file.Replace("ExamplePlugin", pluginCodeName);
File.Move(file, newName);
}
- Debug.Logger.LogHandler.LogWrite(LogType.Info, $"Plugin project {pluginName} has successfully been created.");
+ Editor.Log($"Plugin project {pluginName} has successfully been created.");
await AddReferenceToProject(pluginName, pluginName);
MessageBox.Show($"{pluginName} has been successfully created. Restart editor for changes to take effect.", "Plugin Project Created", MessageBoxButtons.OK);
@@ -738,11 +740,10 @@ namespace FlaxEditor.Windows
references.Add(newReference);
}
flaxProjContents.References = references.ToArray();
- await File.WriteAllTextAsync(flaxProjPath, JsonSerializer.Serialize(flaxProjContents, typeof(ProjectInfo)));
+ await File.WriteAllTextAsync(flaxProjPath, JsonSerializer.Serialize(flaxProjContents, typeof(ProjectInfo)), Encoding.UTF8);
}
}
-
private void OnPluginsChanged()
{
List toRemove = null;
From 9d494679ac3cb06baf5f414bb643abe620f29e9f Mon Sep 17 00:00:00 2001
From: Wojtek Figat
Date: Mon, 11 Sep 2023 22:42:48 +0200
Subject: [PATCH 40/40] Add formatting `MyPlugin.cs` for new plugin setup
#1335
---
Source/Editor/Windows/PluginsWindow.cs | 29 ++++++++++++++++----------
1 file changed, 18 insertions(+), 11 deletions(-)
diff --git a/Source/Editor/Windows/PluginsWindow.cs b/Source/Editor/Windows/PluginsWindow.cs
index d53b64e22..c5ec02b31 100644
--- a/Source/Editor/Windows/PluginsWindow.cs
+++ b/Source/Editor/Windows/PluginsWindow.cs
@@ -346,7 +346,7 @@ namespace FlaxEditor.Windows
{
if (string.IsNullOrEmpty(gitPath))
{
- Editor.LogError($"Failed to create plugin project due to no GIT path.");
+ Editor.LogError("Failed to create plugin project due to no GIT path.");
return;
}
if (string.IsNullOrEmpty(pluginName))
@@ -369,7 +369,7 @@ namespace FlaxEditor.Windows
Directory.CreateDirectory(clonePath);
else
{
- Editor.LogError($"Plugin Name is already used. Pick a different Name.");
+ Editor.LogError("Plugin Name is already used. Pick a different Name.");
return;
}
try
@@ -390,7 +390,7 @@ namespace FlaxEditor.Windows
return;
}
- Editor.Log($"Plugin project has been cloned.");
+ Editor.Log("Plugin project has been cloned.");
// Find project config file. Could be different then what the user named the folder.
var files = Directory.GetFiles(clonePath);
@@ -405,7 +405,7 @@ namespace FlaxEditor.Windows
}
if (string.IsNullOrEmpty(pluginProjectName))
- Editor.LogError($"Failed to find plugin project file to add to Project config. Please add manually.");
+ Editor.LogError("Failed to find plugin project file to add to Project config. Please add manually.");
else
{
await AddReferenceToProject(pluginName, pluginProjectName);
@@ -553,7 +553,7 @@ namespace FlaxEditor.Windows
{
if (string.IsNullOrEmpty(pluginName))
{
- Editor.LogError($"Failed to create plugin project due to no plugin name.");
+ Editor.LogError("Failed to create plugin project due to no plugin name.");
return;
}
@@ -579,7 +579,7 @@ namespace FlaxEditor.Windows
Editor.LogError($"Failed to download template project. Trying to use local file. {e}");
if (!File.Exists(localTemplatePath))
{
- Editor.LogError($"Failed to use local file. Does not exist.");
+ Editor.LogError("Failed to use local file. Does not exist.");
return;
}
}
@@ -690,15 +690,24 @@ namespace FlaxEditor.Windows
var files = Directory.GetFiles(directory);
foreach (var file in files)
{
- if (file.Contains("MyPlugin.cs") || file.Contains("MyPluginEditor.cs"))
+ if (file.Contains("MyPluginEditor.cs"))
{
File.Delete(file);
continue;
}
- var fileText = await File.ReadAllTextAsync(file);
- await File.WriteAllTextAsync(file, fileText.Replace("ExamplePlugin", pluginCodeName));
var fileName = Path.GetFileName(file).Replace("ExamplePlugin", pluginCodeName);
+ var fileText = await File.ReadAllTextAsync(file);
+ fileText = fileText.Replace("ExamplePlugin", pluginCodeName);
+ if (file.Contains("MyPlugin.cs"))
+ {
+ fileName = "ExamplePlugin.cs";
+ fileText = fileText.Replace("MyPlugin", pluginCodeName);
+ fileText = fileText.Replace("My Plugin", pluginName);
+ fileText = fileText.Replace("Flax Engine", companyName);
+ fileText = fileText.Replace("new Version(1, 0)", $"new Version({pluginVersion.Trim().Replace(".", ", ")})");
+ }
+ await File.WriteAllTextAsync(file, fileText);
File.Move(file, Path.Combine(directory, fileName));
}
@@ -856,13 +865,11 @@ namespace FlaxEditor.Windows
{
if (pluginType == null)
return null;
-
foreach (var e in _entries.Keys)
{
if (e.GetType() == pluginType && _entries.ContainsKey(e))
return _entries[e];
}
-
return null;
}