Merge branch 'master' into sdl_platform
# Conflicts: # Source/Editor/GUI/Docking/DockHintWindow.cs # Source/Editor/Options/InterfaceOptions.cs
This commit is contained in:
@@ -641,5 +641,8 @@ namespace FlaxEditor.Windows.Assets
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool LockSelection { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public ISceneEditingContext SceneContext => null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ using FlaxEditor.Content.Create;
|
||||
using FlaxEditor.CustomEditors;
|
||||
using FlaxEditor.CustomEditors.Editors;
|
||||
using FlaxEditor.CustomEditors.Elements;
|
||||
using FlaxEditor.GUI;
|
||||
using FlaxEditor.Viewport.Cameras;
|
||||
using FlaxEditor.Viewport.Previews;
|
||||
using FlaxEngine;
|
||||
@@ -171,13 +172,49 @@ namespace FlaxEditor.Windows.Assets
|
||||
}
|
||||
|
||||
private readonly SplitPanel _split;
|
||||
private readonly ModelBasePreview _preview;
|
||||
private readonly CollisionDataPreview _preview;
|
||||
private readonly CustomEditorPresenter _propertiesPresenter;
|
||||
private readonly PropertiesProxy _properties;
|
||||
private Model _collisionWiresModel;
|
||||
private StaticModel _collisionWiresShowActor;
|
||||
private bool _updateWireMesh;
|
||||
|
||||
private class CollisionDataPreview : ModelBasePreview
|
||||
{
|
||||
public bool ShowCollisionData = false;
|
||||
private int _verticesCount = 0;
|
||||
private int _trianglesCount = 0;
|
||||
|
||||
public void SetVerticesAndTriangleCount(int verticesCount, int triangleCount)
|
||||
{
|
||||
_verticesCount = verticesCount;
|
||||
_trianglesCount = triangleCount;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public CollisionDataPreview(bool useWidgets)
|
||||
: base(useWidgets)
|
||||
{
|
||||
ViewportCamera = new FPSCamera();
|
||||
Task.ViewFlags &= ~ViewFlags.Sky & ~ViewFlags.Bloom & ~ViewFlags.EyeAdaptation;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Draw()
|
||||
{
|
||||
base.Draw();
|
||||
|
||||
if (ShowCollisionData)
|
||||
{
|
||||
var text = string.Format("\nTriangles: {0:N0}\nVertices: {1:N0}\nMemory Size: {2}", _trianglesCount, _verticesCount, Utilities.Utils.FormatBytesCount(Asset.MemoryUsage));
|
||||
var font = Style.Current.FontMedium;
|
||||
var pos = new Float2(10, 50);
|
||||
Render2D.DrawText(font, text, new Rectangle(pos + Float2.One, Size), Color.Black);
|
||||
Render2D.DrawText(font, text, new Rectangle(pos, Size), Color.White);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public CollisionDataWindow(Editor editor, AssetItem item)
|
||||
: base(editor, item)
|
||||
@@ -185,6 +222,12 @@ namespace FlaxEditor.Windows.Assets
|
||||
// Toolstrip
|
||||
_toolstrip.AddSeparator();
|
||||
_toolstrip.AddButton(editor.Icons.CenterView64, () => _preview.ResetCamera()).LinkTooltip("Show whole collision");
|
||||
var infoButton = (ToolStripButton)_toolstrip.AddButton(editor.Icons.Info64).LinkTooltip("Show Collision Data");
|
||||
infoButton.Clicked += () =>
|
||||
{
|
||||
_preview.ShowCollisionData = !_preview.ShowCollisionData;
|
||||
infoButton.Checked = _preview.ShowCollisionData;
|
||||
};
|
||||
_toolstrip.AddButton(editor.Icons.Docs64, () => Platform.OpenUrl(Utilities.Constants.DocsUrl + "manual/physics/colliders/collision-data.html")).LinkTooltip("See documentation to learn more");
|
||||
|
||||
// Split Panel
|
||||
@@ -197,12 +240,10 @@ namespace FlaxEditor.Windows.Assets
|
||||
};
|
||||
|
||||
// Model preview
|
||||
_preview = new ModelBasePreview(true)
|
||||
_preview = new CollisionDataPreview(true)
|
||||
{
|
||||
ViewportCamera = new FPSCamera(),
|
||||
Parent = _split.Panel1
|
||||
};
|
||||
_preview.Task.ViewFlags &= ~ViewFlags.Sky & ~ViewFlags.Bloom & ~ViewFlags.EyeAdaptation;
|
||||
|
||||
// Asset properties
|
||||
_propertiesPresenter = new CustomEditorPresenter(null);
|
||||
@@ -240,7 +281,7 @@ namespace FlaxEditor.Windows.Assets
|
||||
_collisionWiresModel = FlaxEngine.Content.CreateVirtualAsset<Model>();
|
||||
_collisionWiresModel.SetupLODs(new[] { 1 });
|
||||
}
|
||||
Editor.Internal_GetCollisionWires(FlaxEngine.Object.GetUnmanagedPtr(Asset), out var triangles, out var indices, out var _, out var _);
|
||||
Editor.Internal_GetCollisionWires(FlaxEngine.Object.GetUnmanagedPtr(Asset), out var triangles, out var indices, out var triangleCount, out var indicesCount);
|
||||
if (triangles != null && indices != null)
|
||||
_collisionWiresModel.LODs[0].Meshes[0].UpdateMesh(triangles, indices);
|
||||
else
|
||||
@@ -252,6 +293,7 @@ namespace FlaxEditor.Windows.Assets
|
||||
}
|
||||
_collisionWiresShowActor.Model = _collisionWiresModel;
|
||||
_collisionWiresShowActor.SetMaterial(0, FlaxEngine.Content.LoadAsyncInternal<MaterialBase>(EditorAssets.WiresDebugMaterial));
|
||||
_preview.SetVerticesAndTriangleCount(triangleCount, indicesCount / 3);
|
||||
_preview.Asset = FlaxEngine.Content.LoadAsync<ModelBase>(_asset.Options.Model);
|
||||
}
|
||||
|
||||
|
||||
@@ -430,6 +430,12 @@ namespace FlaxEditor.Windows.Assets
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void DeleteSelection()
|
||||
{
|
||||
Delete();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void FocusSelection()
|
||||
{
|
||||
@@ -488,7 +494,8 @@ namespace FlaxEditor.Windows.Assets
|
||||
/// <param name="actor">The actor.</param>
|
||||
/// <param name="parent">The parent.</param>
|
||||
/// <param name="orderInParent">The order of the actor under the parent.</param>
|
||||
public void Spawn(Actor actor, Actor parent, int orderInParent = -1)
|
||||
/// <param name="autoSelect">True if automatically select the spawned actor, otherwise false.</param>
|
||||
public void Spawn(Actor actor, Actor parent, int orderInParent = -1, bool autoSelect = true)
|
||||
{
|
||||
if (actor == null)
|
||||
throw new ArgumentNullException(nameof(actor));
|
||||
@@ -514,8 +521,11 @@ namespace FlaxEditor.Windows.Assets
|
||||
// Create undo action
|
||||
var action = new CustomDeleteActorsAction(new List<SceneGraphNode>(1) { actorNode }, true);
|
||||
Undo.AddAction(action);
|
||||
Focus();
|
||||
Select(actorNode);
|
||||
if (autoSelect)
|
||||
{
|
||||
Focus();
|
||||
Select(actorNode);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTreeRightClick(TreeNode node, Float2 location)
|
||||
|
||||
@@ -91,6 +91,9 @@ namespace FlaxEditor.Windows.Assets
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ISceneEditingContext SceneContext => this;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether use live reloading for the prefab changes (applies prefab changes on modification by auto).
|
||||
/// </summary>
|
||||
|
||||
@@ -194,17 +194,18 @@ namespace FlaxEditor.Windows
|
||||
nodes.Add(node);
|
||||
node = node.ParentNode;
|
||||
}
|
||||
float margin = 1;
|
||||
float x = NavigationBar.DefaultButtonsMargin;
|
||||
float h = _toolStrip.ItemsHeight - 2 * ToolStrip.DefaultMarginV;
|
||||
float h = _toolStrip.ItemsHeight - 2 * margin;
|
||||
for (int i = nodes.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var button = new ContentNavigationButton(nodes[i], x, ToolStrip.DefaultMarginV, h);
|
||||
var button = new ContentNavigationButton(nodes[i], x, margin, h);
|
||||
button.PerformLayout();
|
||||
x += button.Width + NavigationBar.DefaultButtonsMargin;
|
||||
_navigationBar.AddChild(button);
|
||||
if (i > 0)
|
||||
{
|
||||
var separator = new ContentNavigationSeparator(button, x, ToolStrip.DefaultMarginV, h);
|
||||
var separator = new ContentNavigationSeparator(button, x, margin, h);
|
||||
separator.PerformLayout();
|
||||
x += separator.Width + NavigationBar.DefaultButtonsMargin;
|
||||
_navigationBar.AddChild(separator);
|
||||
@@ -215,6 +216,7 @@ namespace FlaxEditor.Windows
|
||||
// Update
|
||||
_navigationBar.IsLayoutLocked = wasLayoutLocked;
|
||||
_navigationBar.PerformLayout();
|
||||
UpdateNavigationBarBounds();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1016,6 +1016,21 @@ namespace FlaxEditor.Windows
|
||||
_navigateUpButton.Enabled = folder != null && _tree.SelectedNode != _root;
|
||||
}
|
||||
|
||||
private void UpdateNavigationBarBounds()
|
||||
{
|
||||
if (_navigationBar != null && _toolStrip != null)
|
||||
{
|
||||
var bottomPrev = _toolStrip.Bottom;
|
||||
_navigationBar.UpdateBounds(_toolStrip);
|
||||
if (bottomPrev != _toolStrip.Bottom)
|
||||
{
|
||||
// Navigation bar changed toolstrip height
|
||||
_split.Offsets = new Margin(0, 0, _toolStrip.Bottom, 0);
|
||||
PerformLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnInit()
|
||||
{
|
||||
@@ -1200,9 +1215,9 @@ namespace FlaxEditor.Windows
|
||||
/// <inheritdoc />
|
||||
protected override void PerformLayoutBeforeChildren()
|
||||
{
|
||||
base.PerformLayoutBeforeChildren();
|
||||
UpdateNavigationBarBounds();
|
||||
|
||||
_navigationBar?.UpdateBounds(_toolStrip);
|
||||
base.PerformLayoutBeforeChildren();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -58,6 +58,9 @@ namespace FlaxEditor.Windows
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ISceneEditingContext SceneContext => Editor.Windows.EditWin;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PropertiesWindow"/> class.
|
||||
/// </summary>
|
||||
|
||||
@@ -26,12 +26,24 @@ namespace FlaxEditor.Windows
|
||||
FlaxEditor.Utilities.Utils.SetupCommonInputActions(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void DeleteSelection()
|
||||
{
|
||||
Editor.SceneEditing.Delete();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void FocusSelection()
|
||||
{
|
||||
Editor.Windows.EditWin.Viewport.FocusSelection();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Spawn(Actor actor, Actor parent = null, int orderInParent = -1, bool autoSelect = true)
|
||||
{
|
||||
Editor.SceneEditing.Spawn(actor, parent, orderInParent, autoSelect);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public EditorViewport Viewport => Editor.Windows.EditWin.Viewport;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "Engine/Render2D/Font.h"
|
||||
#include "Engine/Render2D/TextLayoutOptions.h"
|
||||
#include "Engine/Render2D/Render2D.h"
|
||||
#include "Engine/Platform/FileSystem.h"
|
||||
#include "Engine/Content/Content.h"
|
||||
#include "FlaxEngine.Gen.h"
|
||||
|
||||
@@ -189,8 +190,7 @@ void SplashScreen::Show()
|
||||
|
||||
// Setup
|
||||
_dpiScale = dpiScale;
|
||||
_width = settings.Size.X;
|
||||
_height = settings.Size.Y;
|
||||
_size = settings.Size;
|
||||
_startTime = DateTime::NowUTC();
|
||||
auto str = Globals::ProjectFolder;
|
||||
#if PLATFORM_WIN32
|
||||
@@ -215,6 +215,12 @@ void SplashScreen::Show()
|
||||
font->OnLoaded.Bind<SplashScreen, &SplashScreen::OnFontLoaded>(this);
|
||||
}
|
||||
|
||||
// Load custom image
|
||||
_splashTexture.Loaded.Bind<SplashScreen, &SplashScreen::OnSplashLoaded>(this);
|
||||
String splashImagePath = Globals::ProjectContentFolder / TEXT("SplashImage.flax");
|
||||
if (FileSystem::FileExists(splashImagePath))
|
||||
_splashTexture = Content::LoadAsync<Texture>(splashImagePath);
|
||||
|
||||
_window->Show();
|
||||
}
|
||||
|
||||
@@ -228,6 +234,10 @@ void SplashScreen::Close()
|
||||
// Close window
|
||||
_window->Close(ClosingReason::CloseEvent);
|
||||
_window = nullptr;
|
||||
|
||||
_titleFont = nullptr;
|
||||
_subtitleFont = nullptr;
|
||||
_splashTexture = nullptr;
|
||||
}
|
||||
|
||||
void SplashScreen::OnShown()
|
||||
@@ -240,16 +250,29 @@ void SplashScreen::OnShown()
|
||||
void SplashScreen::OnDraw()
|
||||
{
|
||||
const float s = _dpiScale;
|
||||
const float width = _width;
|
||||
const float height = _height;
|
||||
const float width = _size.X;
|
||||
const float height = _size.Y;
|
||||
|
||||
// Peek time
|
||||
const float time = static_cast<float>((DateTime::NowUTC() - _startTime).GetTotalSeconds());
|
||||
|
||||
// Background
|
||||
const float lightBarHeight = 112 * s;
|
||||
Render2D::FillRectangle(Rectangle(0, 0, width, 150 * s), Color::FromRGB(0x1C1C1C));
|
||||
Render2D::FillRectangle(Rectangle(0, lightBarHeight, width, height), Color::FromRGB(0x0C0C0C));
|
||||
float lightBarHeight = 112 * s;
|
||||
if (_splashTexture != nullptr)
|
||||
{
|
||||
if (_splashTexture->IsLoaded())
|
||||
{
|
||||
lightBarHeight = height - lightBarHeight + 20 * s;
|
||||
Render2D::DrawTexture(_splashTexture, Rectangle(0, 0, width, height));
|
||||
Color rectColor = Color::FromRGB(0x0C0C0C);
|
||||
Render2D::FillRectangle(Rectangle(0, lightBarHeight, width, height - lightBarHeight),rectColor.AlphaMultiplied(0.85f), rectColor.AlphaMultiplied(0.85f), rectColor, rectColor);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Render2D::FillRectangle(Rectangle(0, 0, width, 150 * s), Color::FromRGB(0x1C1C1C));
|
||||
Render2D::FillRectangle(Rectangle(0, lightBarHeight, width, height), Color::FromRGB(0x0C0C0C));
|
||||
}
|
||||
|
||||
// Animated border
|
||||
const float anim = Math::Sin(time * 4.0f) * 0.5f + 0.5f;
|
||||
@@ -277,15 +300,27 @@ void SplashScreen::OnDraw()
|
||||
for (int32 i = 0; i < 4 - static_cast<int32>(time * 2.0f) % 4; i++)
|
||||
subtitle += TEXT(' ');
|
||||
}
|
||||
layout.Bounds = Rectangle(width - 224 * s, lightBarHeight - 39 * s, 220 * s, 35 * s);
|
||||
if (_splashTexture != nullptr)
|
||||
{
|
||||
layout.Bounds = Rectangle(width - 224 * s, lightBarHeight + 4 * s, 220 * s, 35 * s);
|
||||
layout.VerticalAlignment = TextAlignment::Near;
|
||||
}
|
||||
else
|
||||
{
|
||||
layout.Bounds = Rectangle(width - 224 * s, lightBarHeight - 39 * s, 220 * s, 35 * s);
|
||||
layout.VerticalAlignment = TextAlignment::Far;
|
||||
}
|
||||
layout.Scale = 1.0f;
|
||||
layout.HorizontalAlignment = TextAlignment::Far;
|
||||
layout.VerticalAlignment = TextAlignment::Far;
|
||||
Render2D::DrawText(_subtitleFont, subtitle, Color::FromRGB(0x8C8C8C), layout);
|
||||
|
||||
// Additional info
|
||||
const float infoMargin = 6 * s;
|
||||
layout.Bounds = Rectangle(infoMargin, lightBarHeight + infoMargin, width - (2 * infoMargin), height - lightBarHeight - (2 * infoMargin));
|
||||
if (_splashTexture != nullptr)
|
||||
layout.Bounds = Rectangle(infoMargin + 4 * s, lightBarHeight + infoMargin, width - (2 * infoMargin), height - lightBarHeight - (2 * infoMargin));
|
||||
else
|
||||
layout.Bounds = Rectangle(infoMargin, lightBarHeight + infoMargin, width - (2 * infoMargin), height - lightBarHeight - (2 * infoMargin));
|
||||
|
||||
layout.HorizontalAlignment = TextAlignment::Near;
|
||||
layout.VerticalAlignment = TextAlignment::Center;
|
||||
Render2D::DrawText(_subtitleFont, _infoText, Color::FromRGB(0xFFFFFF) * 0.9f, layout);
|
||||
@@ -308,3 +343,14 @@ void SplashScreen::OnFontLoaded(Asset* asset)
|
||||
_titleFont = font->CreateFont(35 * s);
|
||||
_subtitleFont = font->CreateFont(9 * s);
|
||||
}
|
||||
|
||||
void SplashScreen::OnSplashLoaded()
|
||||
{
|
||||
// Resize window to be larger if texture is being used
|
||||
auto desktopSize = Platform::GetDesktopSize();
|
||||
auto xSize = (desktopSize.X / (600.0f * 3.0f)) * 600.0f;
|
||||
auto ySize = (desktopSize.Y / (200.0f * 3.0f)) * 200.0f;
|
||||
_window->SetClientSize(Float2(xSize, ySize));
|
||||
_size = _window->GetSize();
|
||||
_window->SetPosition((desktopSize - _size) * 0.5f);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Content/Assets/Texture.h"
|
||||
#include "Engine/Content/AssetReference.h"
|
||||
#include "Engine/Core/Types/DateTime.h"
|
||||
#include "Engine/Platform/Window.h"
|
||||
|
||||
@@ -18,10 +20,12 @@ private:
|
||||
Window* _window = nullptr;
|
||||
Font* _titleFont = nullptr;
|
||||
Font* _subtitleFont = nullptr;
|
||||
AssetReference<Texture> _splashTexture;
|
||||
String _title;
|
||||
DateTime _startTime;
|
||||
String _infoText;
|
||||
float _dpiScale, _width, _height;
|
||||
float _dpiScale;
|
||||
Float2 _size;
|
||||
StringView _quote;
|
||||
|
||||
public:
|
||||
@@ -78,4 +82,5 @@ private:
|
||||
void OnDraw();
|
||||
bool HasLoadedFonts() const;
|
||||
void OnFontLoaded(Asset* asset);
|
||||
void OnSplashLoaded();
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FlaxEditor.GUI.ContextMenu;
|
||||
using FlaxEditor.GUI.Input;
|
||||
using FlaxEditor.GUI.Tabs;
|
||||
using FlaxEditor.GUI.Tree;
|
||||
@@ -98,10 +99,22 @@ namespace FlaxEditor.Windows
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
private enum SearchFilter
|
||||
{
|
||||
UI = 1,
|
||||
Actors = 2,
|
||||
Primitives = 4,
|
||||
[HideInEditor]
|
||||
Default = UI | Actors | Primitives,
|
||||
}
|
||||
|
||||
private TextBox _searchBox;
|
||||
private ContainerControl _groupSearch;
|
||||
private Tabs _actorGroups;
|
||||
private ContainerControl groupPrimitives;
|
||||
private Button _viewDropdown;
|
||||
private int _searchFilterMask = (int)SearchFilter.Default;
|
||||
|
||||
/// <summary>
|
||||
/// The editor instance.
|
||||
@@ -127,16 +140,25 @@ namespace FlaxEditor.Windows
|
||||
UseScroll = true,
|
||||
AnchorPreset = AnchorPresets.StretchAll,
|
||||
Offsets = Margin.Zero,
|
||||
TabsSize = new Float2(120, 32),
|
||||
TabsSize = new Float2(90, 32),
|
||||
Parent = this,
|
||||
};
|
||||
|
||||
_groupSearch = CreateGroupWithList(_actorGroups, "Search", 26);
|
||||
|
||||
_viewDropdown = new Button(2, 2, 45.0f, TextBoxBase.DefaultHeight)
|
||||
{
|
||||
TooltipText = "Change search filter options.",
|
||||
Text = "Filters",
|
||||
Parent = _groupSearch.Parent.Parent,
|
||||
};
|
||||
_viewDropdown.Clicked += OnViewButtonClicked;
|
||||
|
||||
_searchBox = new SearchBox
|
||||
{
|
||||
AnchorPreset = AnchorPresets.HorizontalStretchTop,
|
||||
Parent = _groupSearch.Parent.Parent,
|
||||
Bounds = new Rectangle(4, 4, _actorGroups.Width - 8, 18),
|
||||
Bounds = new Rectangle(_viewDropdown.Right + 2, 2, _actorGroups.Width - 4, TextBoxBase.DefaultHeight),
|
||||
};
|
||||
_searchBox.TextChanged += OnSearchBoxTextChanged;
|
||||
|
||||
@@ -145,10 +167,38 @@ namespace FlaxEditor.Windows
|
||||
_actorGroups.SelectedTabIndex = 1;
|
||||
}
|
||||
|
||||
private void OnViewButtonClicked()
|
||||
{
|
||||
var menu = new ContextMenu();
|
||||
AddSearchFilterButton(menu, SearchFilter.UI, "UI");
|
||||
AddSearchFilterButton(menu, SearchFilter.Actors, "Actors");
|
||||
AddSearchFilterButton(menu, SearchFilter.Primitives, "Primitives");
|
||||
menu.Show(_viewDropdown.Parent, _viewDropdown.BottomLeft);
|
||||
}
|
||||
|
||||
private void AddSearchFilterButton(ContextMenu menu, SearchFilter value, string name)
|
||||
{
|
||||
var button = menu.AddButton(name);
|
||||
button.AutoCheck = true;
|
||||
button.Checked = (_searchFilterMask & (int)value) != 0;
|
||||
button.Clicked += () =>
|
||||
{
|
||||
_searchFilterMask ^= (int)value;
|
||||
OnSearchBoxTextChanged();
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void PerformLayoutBeforeChildren()
|
||||
{
|
||||
base.PerformLayoutBeforeChildren();
|
||||
|
||||
_searchBox.Width = _groupSearch.Width - _viewDropdown.Right - 4;
|
||||
}
|
||||
|
||||
private void OnScriptsReload()
|
||||
{
|
||||
// Prevent any references to actor types from the game assemblies that will be reloaded
|
||||
_searchBox.Clear();
|
||||
_groupSearch.DisposeChildren();
|
||||
_groupSearch.PerformLayout();
|
||||
|
||||
@@ -172,6 +222,7 @@ namespace FlaxEditor.Windows
|
||||
private void OnScriptsReloadEnd()
|
||||
{
|
||||
RefreshActorTabs();
|
||||
OnSearchBoxTextChanged();
|
||||
}
|
||||
|
||||
private void RefreshActorTabs()
|
||||
@@ -192,14 +243,21 @@ namespace FlaxEditor.Windows
|
||||
group.Dispose();
|
||||
}
|
||||
|
||||
// Setup primitives tabs
|
||||
// Add primitives to primtives and search tab
|
||||
groupPrimitives = CreateGroupWithList(_actorGroups, "Primitives");
|
||||
|
||||
groupPrimitives.AddChild(CreateEditorAssetItem("Cube", "Primitives/Cube.flax"));
|
||||
_groupSearch.AddChild(CreateEditorAssetItem("Cube", "Primitives/Cube.flax"));
|
||||
groupPrimitives.AddChild(CreateEditorAssetItem("Sphere", "Primitives/Sphere.flax"));
|
||||
_groupSearch.AddChild(CreateEditorAssetItem("Sphere", "Primitives/Sphere.flax"));
|
||||
groupPrimitives.AddChild(CreateEditorAssetItem("Plane", "Primitives/Plane.flax"));
|
||||
_groupSearch.AddChild(CreateEditorAssetItem("Plane", "Primitives/Plane.flax"));
|
||||
groupPrimitives.AddChild(CreateEditorAssetItem("Cylinder", "Primitives/Cylinder.flax"));
|
||||
_groupSearch.AddChild(CreateEditorAssetItem("Cylinder", "Primitives/Cylinder.flax"));
|
||||
groupPrimitives.AddChild(CreateEditorAssetItem("Cone", "Primitives/Cone.flax"));
|
||||
_groupSearch.AddChild(CreateEditorAssetItem("Cone", "Primitives/Cone.flax"));
|
||||
groupPrimitives.AddChild(CreateEditorAssetItem("Capsule", "Primitives/Capsule.flax"));
|
||||
_groupSearch.AddChild(CreateEditorAssetItem("Capsule", "Primitives/Capsule.flax"));
|
||||
|
||||
// Created first to order specific tabs
|
||||
CreateGroupWithList(_actorGroups, "Lights");
|
||||
@@ -312,57 +370,115 @@ namespace FlaxEditor.Windows
|
||||
_groupSearch.LockChildrenRecursive();
|
||||
_groupSearch.DisposeChildren();
|
||||
|
||||
foreach (var actorType in Editor.CodeEditing.Actors.Get())
|
||||
if (((int)SearchFilter.Actors & _searchFilterMask) != 0)
|
||||
{
|
||||
ActorToolboxAttribute attribute = null;
|
||||
foreach (var e in actorType.GetAttributes(false))
|
||||
foreach (var actorType in Editor.CodeEditing.Actors.Get())
|
||||
{
|
||||
if (e is ActorToolboxAttribute actorToolboxAttribute)
|
||||
ActorToolboxAttribute attribute = null;
|
||||
foreach (var e in actorType.GetAttributes(false))
|
||||
{
|
||||
attribute = actorToolboxAttribute;
|
||||
break;
|
||||
if (e is ActorToolboxAttribute actorToolboxAttribute)
|
||||
{
|
||||
attribute = actorToolboxAttribute;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var text = (attribute == null) ? actorType.Name : string.IsNullOrEmpty(attribute.Name) ? actorType.Name : attribute.Name;
|
||||
var text = (attribute == null) ? actorType.Name : string.IsNullOrEmpty(attribute.Name) ? actorType.Name : attribute.Name;
|
||||
|
||||
// Display all actors on no search
|
||||
if (string.IsNullOrEmpty(filterText))
|
||||
_groupSearch.AddChild(CreateActorItem(Utilities.Utils.GetPropertyNameUI(text), actorType));
|
||||
|
||||
if (!QueryFilterHelper.Match(filterText, text, out QueryFilterHelper.Range[] ranges))
|
||||
continue;
|
||||
|
||||
var item = CreateActorItem(Utilities.Utils.GetPropertyNameUI(text), actorType);
|
||||
SearchFilterHighlights(item, text, ranges);
|
||||
}
|
||||
|
||||
// Hack primitive models into the search results
|
||||
foreach (var child in groupPrimitives.Children)
|
||||
{
|
||||
if (child is Item primitiveAssetItem)
|
||||
{
|
||||
var text = primitiveAssetItem.Text;
|
||||
// Display all actors on no search
|
||||
if (string.IsNullOrEmpty(filterText))
|
||||
_groupSearch.AddChild(CreateActorItem(Utilities.Utils.GetPropertyNameUI(text), actorType));
|
||||
|
||||
if (!QueryFilterHelper.Match(filterText, text, out QueryFilterHelper.Range[] ranges))
|
||||
continue;
|
||||
|
||||
// Rebuild the path based on item name (it would be better to convert the drag data back to a string somehow)
|
||||
string path = $"Primitives/{text}.flax";
|
||||
|
||||
var item = CreateEditorAssetItem(text, path);
|
||||
var item = CreateActorItem(Utilities.Utils.GetPropertyNameUI(text), actorType);
|
||||
SearchFilterHighlights(item, text, ranges);
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(filterText))
|
||||
_groupSearch.SortChildren();
|
||||
if (((int)SearchFilter.Primitives & _searchFilterMask) != 0)
|
||||
{
|
||||
// Hack primitive models into the search results
|
||||
foreach (var child in groupPrimitives.Children)
|
||||
{
|
||||
if (child is Item primitiveAssetItem)
|
||||
{
|
||||
var text = primitiveAssetItem.Text;
|
||||
|
||||
// Rebuild the path based on item name (it would be better to convert the drag data back to a string somehow)
|
||||
string path = $"Primitives/{text}.flax";
|
||||
|
||||
// Display all primitives on no search
|
||||
if (string.IsNullOrEmpty(filterText))
|
||||
_groupSearch.AddChild(CreateEditorAssetItem(text, path));
|
||||
|
||||
if (!QueryFilterHelper.Match(filterText, text, out QueryFilterHelper.Range[] ranges))
|
||||
continue;
|
||||
|
||||
var item = CreateEditorAssetItem(text, path);
|
||||
SearchFilterHighlights(item, text, ranges);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (((int)SearchFilter.UI & _searchFilterMask) != 0)
|
||||
{
|
||||
foreach (var controlType in Editor.Instance.CodeEditing.Controls.Get())
|
||||
{
|
||||
if (controlType.IsAbstract)
|
||||
continue;
|
||||
|
||||
ActorToolboxAttribute attribute = null;
|
||||
foreach (var e in controlType.GetAttributes(false))
|
||||
{
|
||||
if (e is ActorToolboxAttribute actorToolboxAttribute)
|
||||
{
|
||||
attribute = actorToolboxAttribute;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var text = (attribute == null) ? controlType.Name : string.IsNullOrEmpty(attribute.Name) ? controlType.Name : attribute.Name;
|
||||
|
||||
// Display all controls on no search
|
||||
if (string.IsNullOrEmpty(filterText))
|
||||
_groupSearch.AddChild(CreateControlItem(Utilities.Utils.GetPropertyNameUI(controlType.Name), controlType));
|
||||
|
||||
if (!QueryFilterHelper.Match(filterText, text, out QueryFilterHelper.Range[] ranges))
|
||||
continue;
|
||||
|
||||
var item = CreateControlItem(Utilities.Utils.GetPropertyNameUI(controlType.Name), controlType);
|
||||
SearchFilterHighlights(item, text, ranges);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the search results alphabetically
|
||||
_groupSearch.SortChildren();
|
||||
|
||||
_groupSearch.UnlockChildrenRecursive();
|
||||
PerformLayout();
|
||||
PerformLayout();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Draw()
|
||||
{
|
||||
base.Draw();
|
||||
|
||||
// Show a text to hint the user that either no filter is active or the search does not return any results
|
||||
bool noSearchResults = _groupSearch.Children.Count == 0 && !string.IsNullOrEmpty(_searchBox.Text);
|
||||
bool showHint = _searchFilterMask == 0 || noSearchResults;
|
||||
if (showHint)
|
||||
{
|
||||
string hint = noSearchResults ? "No results" : "No search filter active, please enable at least one filter";
|
||||
var textRect = _groupSearch.Parent.Parent.Bounds;
|
||||
var style = Style.Current;
|
||||
Render2D.DrawText(style.FontMedium, hint, textRect, style.ForegroundGrey, TextAlignment.Center, TextAlignment.Center, TextWrapping.WrapWords);
|
||||
}
|
||||
}
|
||||
|
||||
private void SearchFilterHighlights(Item item, string text, QueryFilterHelper.Range[] ranges)
|
||||
{
|
||||
_groupSearch.AddChild(item);
|
||||
|
||||
Reference in New Issue
Block a user