diff --git a/Source/Editor/GUI/Popups/RenamePopup.cs b/Source/Editor/GUI/Popups/RenamePopup.cs
index 891ced9c7..01fbdc03f 100644
--- a/Source/Editor/GUI/Popups/RenamePopup.cs
+++ b/Source/Editor/GUI/Popups/RenamePopup.cs
@@ -81,6 +81,20 @@ namespace FlaxEditor.GUI
private bool IsInputValid => !string.IsNullOrWhiteSpace(_inputField.Text) && (_inputField.Text == _startValue || Validate == null || Validate(this, _inputField.Text));
+ ///
+ public override void Update(float deltaTime)
+ {
+ var mouseLocation = Root.MousePosition;
+ if (!ContainsPoint(ref mouseLocation) && RootWindow.ContainsFocus && Text != _startValue)
+ {
+ // rename item before closing if left mouse button in clicked
+ if (FlaxEngine.Input.GetMouseButtonDown(MouseButton.Left))
+ OnEnd();
+ }
+
+ base.Update(deltaTime);
+ }
+
private void OnTextChanged()
{
if (Validate == null)
diff --git a/Source/Editor/Windows/ToolboxWindow.cs b/Source/Editor/Windows/ToolboxWindow.cs
index 2ef8b7db2..ff03d8e0d 100644
--- a/Source/Editor/Windows/ToolboxWindow.cs
+++ b/Source/Editor/Windows/ToolboxWindow.cs
@@ -2,7 +2,6 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using FlaxEditor.GUI.Tabs;
using FlaxEditor.GUI.Tree;
using FlaxEditor.Scripting;
@@ -100,6 +99,7 @@ namespace FlaxEditor.Windows
private TextBox _searchBox;
private ContainerControl _groupSearch;
+ private Tabs _actorGroups;
///
/// The editor instance.
@@ -117,8 +117,9 @@ namespace FlaxEditor.Windows
Editor = editor;
Selected += tab => Editor.Windows.EditWin.Viewport.SetActiveMode();
ScriptsBuilder.ScriptsReload += OnScriptsReload;
+ ScriptsBuilder.ScriptsReloadEnd += OnScriptsReloadEnd;
- var actorGroups = new Tabs
+ _actorGroups = new Tabs
{
Orientation = Orientation.Vertical,
UseScroll = true,
@@ -128,74 +129,19 @@ namespace FlaxEditor.Windows
Parent = this,
};
- _groupSearch = CreateGroupWithList(actorGroups, "Search", 26);
+ _groupSearch = CreateGroupWithList(_actorGroups, "Search", 26);
_searchBox = new TextBox
{
AnchorPreset = AnchorPresets.HorizontalStretchTop,
WatermarkText = "Search...",
Parent = _groupSearch.Parent.Parent,
- Bounds = new Rectangle(4, 4, actorGroups.Width - 8, 18),
+ Bounds = new Rectangle(4, 4, _actorGroups.Width - 8, 18),
};
_searchBox.TextChanged += OnSearchBoxTextChanged;
- var groupBasicModels = CreateGroupWithList(actorGroups, "Basic Models");
- groupBasicModels.AddChild(CreateEditorAssetItem("Cube", "Primitives/Cube.flax"));
- groupBasicModels.AddChild(CreateEditorAssetItem("Sphere", "Primitives/Sphere.flax"));
- groupBasicModels.AddChild(CreateEditorAssetItem("Plane", "Primitives/Plane.flax"));
- groupBasicModels.AddChild(CreateEditorAssetItem("Cylinder", "Primitives/Cylinder.flax"));
- groupBasicModels.AddChild(CreateEditorAssetItem("Cone", "Primitives/Cone.flax"));
- groupBasicModels.AddChild(CreateEditorAssetItem("Capsule", "Primitives/Capsule.flax"));
+ RefreshActorTabs();
- var groupLights = CreateGroupWithList(actorGroups, "Lights");
- groupLights.AddChild(CreateActorItem("Directional Light", typeof(DirectionalLight)));
- groupLights.AddChild(CreateActorItem("Point Light", typeof(PointLight)));
- groupLights.AddChild(CreateActorItem("Spot Light", typeof(SpotLight)));
- groupLights.AddChild(CreateActorItem("Sky Light", typeof(SkyLight)));
-
- var groupVisuals = CreateGroupWithList(actorGroups, "Visuals");
- groupVisuals.AddChild(CreateActorItem("Camera", typeof(Camera)));
- groupVisuals.AddChild(CreateActorItem("Environment Probe", typeof(EnvironmentProbe)));
- groupVisuals.AddChild(CreateActorItem("Skybox", typeof(Skybox)));
- groupVisuals.AddChild(CreateActorItem("Sky", typeof(Sky)));
- groupVisuals.AddChild(CreateActorItem("Exponential Height Fog", typeof(ExponentialHeightFog)));
- groupVisuals.AddChild(CreateActorItem("PostFx Volume", typeof(PostFxVolume)));
- groupVisuals.AddChild(CreateActorItem("Decal", typeof(Decal)));
- groupVisuals.AddChild(CreateActorItem("Particle Effect", typeof(ParticleEffect)));
-
- var groupPhysics = CreateGroupWithList(actorGroups, "Physics");
- groupPhysics.AddChild(CreateActorItem("Rigid Body", typeof(RigidBody)));
- groupPhysics.AddChild(CreateActorItem("Character Controller", typeof(CharacterController)));
- groupPhysics.AddChild(CreateActorItem("Box Collider", typeof(BoxCollider)));
- groupPhysics.AddChild(CreateActorItem("Sphere Collider", typeof(SphereCollider)));
- groupPhysics.AddChild(CreateActorItem("Capsule Collider", typeof(CapsuleCollider)));
- groupPhysics.AddChild(CreateActorItem("Mesh Collider", typeof(MeshCollider)));
- groupPhysics.AddChild(CreateActorItem("Fixed Joint", typeof(FixedJoint)));
- groupPhysics.AddChild(CreateActorItem("Distance Joint", typeof(DistanceJoint)));
- groupPhysics.AddChild(CreateActorItem("Slider Joint", typeof(SliderJoint)));
- groupPhysics.AddChild(CreateActorItem("Spherical Joint", typeof(SphericalJoint)));
- groupPhysics.AddChild(CreateActorItem("Hinge Joint", typeof(HingeJoint)));
- groupPhysics.AddChild(CreateActorItem("D6 Joint", typeof(D6Joint)));
-
- var groupOther = CreateGroupWithList(actorGroups, "Other");
- groupOther.AddChild(CreateActorItem("Animated Model", typeof(AnimatedModel)));
- groupOther.AddChild(CreateActorItem("Bone Socket", typeof(BoneSocket)));
- groupOther.AddChild(CreateActorItem("CSG Box Brush", typeof(BoxBrush)));
- groupOther.AddChild(CreateActorItem("Audio Source", typeof(AudioSource)));
- groupOther.AddChild(CreateActorItem("Audio Listener", typeof(AudioListener)));
- groupOther.AddChild(CreateActorItem("Empty Actor", typeof(EmptyActor)));
- groupOther.AddChild(CreateActorItem("Scene Animation", typeof(SceneAnimationPlayer)));
- groupOther.AddChild(CreateActorItem("Nav Mesh Bounds Volume", typeof(NavMeshBoundsVolume)));
- groupOther.AddChild(CreateActorItem("Nav Link", typeof(NavLink)));
- groupOther.AddChild(CreateActorItem("Nav Modifier Volume", typeof(NavModifierVolume)));
- groupOther.AddChild(CreateActorItem("Spline", typeof(Spline)));
-
- var groupGui = CreateGroupWithList(actorGroups, "GUI");
- groupGui.AddChild(CreateActorItem("UI Control", typeof(UIControl)));
- groupGui.AddChild(CreateActorItem("UI Canvas", typeof(UICanvas)));
- groupGui.AddChild(CreateActorItem("Text Render", typeof(TextRender)));
- groupGui.AddChild(CreateActorItem("Sprite Render", typeof(SpriteRender)));
-
- actorGroups.SelectedTabIndex = 1;
+ _actorGroups.SelectedTabIndex = 1;
}
private void OnScriptsReload()
@@ -206,6 +152,91 @@ namespace FlaxEditor.Windows
_groupSearch.PerformLayout();
}
+ private void OnScriptsReloadEnd()
+ {
+ RefreshActorTabs();
+ }
+
+ private void RefreshActorTabs()
+ {
+ // Remove tabs
+ var tabs = new List();
+ foreach (var child in _actorGroups.Children)
+ {
+ if (child is Tab tab)
+ {
+ if (tab.Text != "Search")
+ tabs.Add(tab);
+ }
+ }
+ foreach (var tab in tabs)
+ {
+ var group = _actorGroups.Children.Find(T => T == tab);
+ group.Dispose();
+ }
+
+ // Setup primitives tabs
+ var groupBasicModels = CreateGroupWithList(_actorGroups, "Basic Models");
+ groupBasicModels.AddChild(CreateEditorAssetItem("Cube", "Primitives/Cube.flax"));
+ groupBasicModels.AddChild(CreateEditorAssetItem("Sphere", "Primitives/Sphere.flax"));
+ groupBasicModels.AddChild(CreateEditorAssetItem("Plane", "Primitives/Plane.flax"));
+ groupBasicModels.AddChild(CreateEditorAssetItem("Cylinder", "Primitives/Cylinder.flax"));
+ groupBasicModels.AddChild(CreateEditorAssetItem("Cone", "Primitives/Cone.flax"));
+ groupBasicModels.AddChild(CreateEditorAssetItem("Capsule", "Primitives/Capsule.flax"));
+
+ // Created first to order specific tabs
+ CreateGroupWithList(_actorGroups, "Lights");
+ CreateGroupWithList(_actorGroups, "Visuals");
+ CreateGroupWithList(_actorGroups, "Physics");
+ CreateGroupWithList(_actorGroups, "GUI");
+ CreateGroupWithList(_actorGroups, "Other");
+
+ // Add other actor types to respective tab based on attribute
+ foreach (var actorType in Editor.CodeEditing.Actors.Get())
+ {
+ if (actorType.IsAbstract)
+ continue;
+ ActorToolboxAttribute attribute = null;
+ foreach (var e in actorType.GetAttributes(false))
+ {
+ if (e is ActorToolboxAttribute actorToolboxAttribute)
+ {
+ attribute = actorToolboxAttribute;
+ break;
+ }
+ }
+ if (attribute == null)
+ continue;
+ var groupName = attribute.Group.Trim();
+
+ // Check if tab already exists and add it to the tab
+ var actorTabExists = false;
+ foreach (var child in _actorGroups.Children)
+ {
+ if (child is Tab tab)
+ {
+ if (string.Equals(tab.Text, groupName, StringComparison.OrdinalIgnoreCase))
+ {
+ var tree = tab.GetChild().GetChild();
+ if (tree != null)
+ {
+ tree.AddChild(string.IsNullOrEmpty(attribute.Name) ? CreateActorItem(Utilities.Utils.GetPropertyNameUI(actorType.Name), actorType) : CreateActorItem(attribute.Name, actorType));
+ tree.SortChildren();
+ }
+ actorTabExists = true;
+ break;
+ }
+ }
+ }
+ if (actorTabExists)
+ continue;
+
+ var group = CreateGroupWithList(_actorGroups, groupName);
+ group.AddChild(string.IsNullOrEmpty(attribute.Name) ? CreateActorItem(Utilities.Utils.GetPropertyNameUI(actorType.Name), actorType) : CreateActorItem(attribute.Name, actorType));
+ group.SortChildren();
+ }
+ }
+
private void OnSearchBoxTextChanged()
{
// Skip events during setup or init stuff
@@ -218,7 +249,17 @@ namespace FlaxEditor.Windows
foreach (var actorType in Editor.CodeEditing.Actors.Get())
{
- var text = actorType.Name;
+ ActorToolboxAttribute attribute = null;
+ foreach (var e in actorType.GetAttributes(true))
+ {
+ if (e is ActorToolboxAttribute actorToolboxAttribute)
+ {
+ attribute = actorToolboxAttribute;
+ break;
+ }
+ }
+
+ var text = (attribute == null) ? actorType.Name : string.IsNullOrEmpty(attribute.Name) ? actorType.Name : attribute.Name;
if (!QueryFilterHelper.Match(filterText, text, out QueryFilterHelper.Range[] ranges))
continue;
diff --git a/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.h b/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.h
index cdeb29fa5..d7243a09b 100644
--- a/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.h
+++ b/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.h
@@ -11,7 +11,8 @@
///
/// The scene animation playback actor.
///
-API_CLASS(Attributes = "ActorContextMenu(\"New/Other/Scene Animation\")") class FLAXENGINE_API SceneAnimationPlayer : public Actor, public IPostFxSettingsProvider
+API_CLASS(Attributes="ActorContextMenu(\"New/Other/Scene Animation\"), ActorToolbox(\"Other\", \"Scene Animation\")")
+class FLAXENGINE_API SceneAnimationPlayer : public Actor, public IPostFxSettingsProvider
{
DECLARE_SCENE_OBJECT(SceneAnimationPlayer);
diff --git a/Source/Engine/Audio/AudioListener.h b/Source/Engine/Audio/AudioListener.h
index 9edcb4ff7..28bca3b81 100644
--- a/Source/Engine/Audio/AudioListener.h
+++ b/Source/Engine/Audio/AudioListener.h
@@ -7,7 +7,8 @@
///
/// Represents a listener that hears audio sources. For spatial audio the volume and pitch of played audio is determined by the distance, orientation and velocity differences between the source and the listener.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Audio/Audio Listener\")") class FLAXENGINE_API AudioListener : public Actor
+API_CLASS(Attributes="ActorContextMenu(\"New/Audio/Audio Listener\"), ActorToolbox(\"Other\")")
+class FLAXENGINE_API AudioListener : public Actor
{
DECLARE_SCENE_OBJECT(AudioListener);
private:
diff --git a/Source/Engine/Audio/AudioSource.h b/Source/Engine/Audio/AudioSource.h
index 4335795e9..791e9465e 100644
--- a/Source/Engine/Audio/AudioSource.h
+++ b/Source/Engine/Audio/AudioSource.h
@@ -13,7 +13,8 @@
///
/// Whether or not an audio source is spatial is controlled by the assigned AudioClip.The volume and the pitch of a spatial audio source is controlled by its position and the AudioListener's position/direction/velocity.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Audio/Audio Source\")") class FLAXENGINE_API AudioSource : public Actor
+API_CLASS(Attributes="ActorContextMenu(\"New/Audio/Audio Source\"), ActorToolbox(\"Other\")")
+class FLAXENGINE_API AudioSource : public Actor
{
DECLARE_SCENE_OBJECT(AudioSource);
friend class AudioStreamingHandler;
diff --git a/Source/Engine/Core/Collections/Dictionary.h b/Source/Engine/Core/Collections/Dictionary.h
index 7211d0ecd..d7d3a34ff 100644
--- a/Source/Engine/Core/Collections/Dictionary.h
+++ b/Source/Engine/Core/Collections/Dictionary.h
@@ -509,14 +509,14 @@ public:
_deletedCount = _elementsCount = 0;
if (capacity != 0 && (capacity & (capacity - 1)) != 0)
{
- // Align capacity value to the next power of two (if it's not)
- capacity++;
+ // Align capacity value to the next power of two (http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2)
+ capacity--;
capacity |= capacity >> 1;
capacity |= capacity >> 2;
capacity |= capacity >> 4;
capacity |= capacity >> 8;
capacity |= capacity >> 16;
- capacity = capacity + 1;
+ capacity++;
}
if (capacity)
{
diff --git a/Source/Engine/Core/Collections/HashSet.h b/Source/Engine/Core/Collections/HashSet.h
index a2cb21be7..fc1f53bde 100644
--- a/Source/Engine/Core/Collections/HashSet.h
+++ b/Source/Engine/Core/Collections/HashSet.h
@@ -380,14 +380,14 @@ public:
_deletedCount = _elementsCount = 0;
if (capacity != 0 && (capacity & (capacity - 1)) != 0)
{
- // Align capacity value to the next power of two (if it's not)
- capacity++;
+ // Align capacity value to the next power of two (http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2)
+ capacity--;
capacity |= capacity >> 1;
capacity |= capacity >> 2;
capacity |= capacity >> 4;
capacity |= capacity >> 8;
capacity |= capacity >> 16;
- capacity = capacity + 1;
+ capacity++;
}
if (capacity)
{
diff --git a/Source/Engine/Core/Memory/Allocation.h b/Source/Engine/Core/Memory/Allocation.h
index 14aa41f7a..9ae127805 100644
--- a/Source/Engine/Core/Memory/Allocation.h
+++ b/Source/Engine/Core/Memory/Allocation.h
@@ -111,8 +111,8 @@ public:
}
else
{
- // Round up to the next power of 2 and multiply by 2
- capacity++;
+ // Round up to the next power of 2 and multiply by 2 (http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2)
+ capacity--;
capacity |= capacity >> 1;
capacity |= capacity >> 2;
capacity |= capacity >> 4;
diff --git a/Source/Engine/Level/Actors/AnimatedModel.h b/Source/Engine/Level/Actors/AnimatedModel.h
index d07c93752..7f247267f 100644
--- a/Source/Engine/Level/Actors/AnimatedModel.h
+++ b/Source/Engine/Level/Actors/AnimatedModel.h
@@ -12,7 +12,8 @@
///
/// Performs an animation and renders a skinned model.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Other/Animated Model\")") class FLAXENGINE_API AnimatedModel : public ModelInstanceActor
+API_CLASS(Attributes="ActorContextMenu(\"New/Other/Animated Model\"), ActorToolbox(\"Other\")")
+class FLAXENGINE_API AnimatedModel : public ModelInstanceActor
{
DECLARE_SCENE_OBJECT(AnimatedModel);
friend class AnimationsSystem;
diff --git a/Source/Engine/Level/Actors/BoneSocket.h b/Source/Engine/Level/Actors/BoneSocket.h
index 4e107aac0..e73ec38eb 100644
--- a/Source/Engine/Level/Actors/BoneSocket.h
+++ b/Source/Engine/Level/Actors/BoneSocket.h
@@ -7,10 +7,10 @@
///
/// Actor that links to the animated model skeleton node transformation.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Other/Bone Socket\")") class FLAXENGINE_API BoneSocket : public Actor
+API_CLASS(Attributes="ActorContextMenu(\"New/Other/Bone Socket\"), ActorToolbox(\"Other\")")
+class FLAXENGINE_API BoneSocket : public Actor
{
DECLARE_SCENE_OBJECT(BoneSocket);
-
private:
String _node;
int32 _index;
@@ -20,7 +20,6 @@ public:
///
/// Gets the target node name to link to it.
///
- /// The target node name.
API_PROPERTY(Attributes="EditorOrder(10), EditorDisplay(\"Bone Socket\"), CustomEditorAlias(\"FlaxEditor.CustomEditors.Editors.SkeletonNodeEditor\")")
FORCE_INLINE const String& GetNode() const
{
@@ -30,14 +29,12 @@ public:
///
/// Sets the target node to link to it.
///
- /// The target node name.
API_PROPERTY()
void SetNode(const StringView& name);
///
/// Gets the value indicating whenever use the target node scale. Otherwise won't override the actor scale.
///
- /// If set to true the node socket will use target node scale, otherwise it will be ignored.
API_PROPERTY(Attributes="EditorOrder(20), EditorDisplay(\"Bone Socket\"), DefaultValue(false)")
FORCE_INLINE bool GetUseScale() const
{
@@ -47,7 +44,6 @@ public:
///
/// Sets the value indicating whenever use the target node scale. Otherwise won't override the actor scale.
///
- /// If set to true the node socket will use target node scale, otherwise it will be ignored.
API_PROPERTY()
void SetUseScale(bool value);
diff --git a/Source/Engine/Level/Actors/BoxBrush.h b/Source/Engine/Level/Actors/BoxBrush.h
index 5e8fe2cb9..aed66e420 100644
--- a/Source/Engine/Level/Actors/BoxBrush.h
+++ b/Source/Engine/Level/Actors/BoxBrush.h
@@ -65,7 +65,8 @@ public:
///
/// Performs CSG box brush operation that adds or removes geometry.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Other/Box Brush\")") class FLAXENGINE_API BoxBrush : public Actor, public CSG::Brush
+API_CLASS(Attributes="ActorContextMenu(\"New/Other/Box Brush\"), ActorToolbox(\"Other\", \"CSG Box Brush\")")
+class FLAXENGINE_API BoxBrush : public Actor, public CSG::Brush
{
DECLARE_SCENE_OBJECT(BoxBrush);
private:
diff --git a/Source/Engine/Level/Actors/Camera.cpp b/Source/Engine/Level/Actors/Camera.cpp
index 142baa745..28c8bbbe5 100644
--- a/Source/Engine/Level/Actors/Camera.cpp
+++ b/Source/Engine/Level/Actors/Camera.cpp
@@ -2,6 +2,7 @@
#include "Camera.h"
#include "Engine/Level/SceneObjectsFactory.h"
+#include "Engine/Core/Math/Matrix.h"
#include "Engine/Core/Math/Viewport.h"
#include "Engine/Content/Assets/Model.h"
#include "Engine/Content/Content.h"
diff --git a/Source/Engine/Level/Actors/Camera.h b/Source/Engine/Level/Actors/Camera.h
index e01cf11c4..601bb4d91 100644
--- a/Source/Engine/Level/Actors/Camera.h
+++ b/Source/Engine/Level/Actors/Camera.h
@@ -3,7 +3,6 @@
#pragma once
#include "../Actor.h"
-#include "Engine/Core/Math/Matrix.h"
#include "Engine/Core/Math/BoundingFrustum.h"
#include "Engine/Core/Math/Viewport.h"
#include "Engine/Core/Math/Ray.h"
@@ -18,7 +17,8 @@
///
/// Describes the camera projection and view. Provides information about how to render scene (viewport location and direction, etc.).
///
-API_CLASS(Sealed, Attributes="ActorContextMenu(\"New/Camera\")") class FLAXENGINE_API Camera : public Actor
+API_CLASS(Sealed, Attributes="ActorContextMenu(\"New/Camera\"), ActorToolbox(\"Visuals\")")
+class FLAXENGINE_API Camera : public Actor
{
DECLARE_SCENE_OBJECT(Camera);
diff --git a/Source/Engine/Level/Actors/Decal.h b/Source/Engine/Level/Actors/Decal.h
index 497186cc5..6dceb223a 100644
--- a/Source/Engine/Level/Actors/Decal.h
+++ b/Source/Engine/Level/Actors/Decal.h
@@ -11,7 +11,8 @@
///
/// Actor that draws the can be used to draw a custom decals on top of the other objects.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Decal\")") class FLAXENGINE_API Decal : public Actor
+API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Decal\"), ActorToolbox(\"Visuals\")")
+class FLAXENGINE_API Decal : public Actor
{
DECLARE_SCENE_OBJECT(Decal);
private:
@@ -50,7 +51,6 @@ public:
///
/// Sets the decal bounds size (in local space).
///
- /// The value.
API_PROPERTY() void SetSize(const Vector3& value);
public:
diff --git a/Source/Engine/Level/Actors/DirectionalLight.h b/Source/Engine/Level/Actors/DirectionalLight.h
index f9347be36..78e9112c9 100644
--- a/Source/Engine/Level/Actors/DirectionalLight.h
+++ b/Source/Engine/Level/Actors/DirectionalLight.h
@@ -7,7 +7,8 @@
///
/// Directional light emits light from direction in space.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Directional Light\")") class FLAXENGINE_API DirectionalLight : public LightWithShadow
+API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Directional Light\"), ActorToolbox(\"Lights\")")
+class FLAXENGINE_API DirectionalLight : public LightWithShadow
{
DECLARE_SCENE_OBJECT(DirectionalLight);
public:
diff --git a/Source/Engine/Level/Actors/EmptyActor.h b/Source/Engine/Level/Actors/EmptyActor.h
index 17742d137..063f96f59 100644
--- a/Source/Engine/Level/Actors/EmptyActor.h
+++ b/Source/Engine/Level/Actors/EmptyActor.h
@@ -7,7 +7,8 @@
///
/// The empty actor that is useful to create hierarchy and/or hold scripts. See .
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Actor\")") class FLAXENGINE_API EmptyActor : public Actor
+API_CLASS(Attributes="ActorContextMenu(\"New/Actor\"), ActorToolbox(\"Other\")")
+class FLAXENGINE_API EmptyActor : public Actor
{
DECLARE_SCENE_OBJECT(EmptyActor);
public:
diff --git a/Source/Engine/Level/Actors/EnvironmentProbe.h b/Source/Engine/Level/Actors/EnvironmentProbe.h
index e5a5faa84..9267c206c 100644
--- a/Source/Engine/Level/Actors/EnvironmentProbe.h
+++ b/Source/Engine/Level/Actors/EnvironmentProbe.h
@@ -10,7 +10,8 @@
///
/// Environment Probe can capture space around the objects to provide reflections.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Environment Probe\")") class FLAXENGINE_API EnvironmentProbe : public Actor
+API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Environment Probe\"), ActorToolbox(\"Visuals\")")
+class FLAXENGINE_API EnvironmentProbe : public Actor
{
DECLARE_SCENE_OBJECT(EnvironmentProbe);
public:
diff --git a/Source/Engine/Level/Actors/ExponentialHeightFog.h b/Source/Engine/Level/Actors/ExponentialHeightFog.h
index ac2d24d91..7c6da6a5a 100644
--- a/Source/Engine/Level/Actors/ExponentialHeightFog.h
+++ b/Source/Engine/Level/Actors/ExponentialHeightFog.h
@@ -12,7 +12,8 @@
///
/// Used to create fogging effects such as clouds but with a density that is related to the height of the fog.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Exponential Height Fog\")") class FLAXENGINE_API ExponentialHeightFog : public Actor, public IFogRenderer
+API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Exponential Height Fog\"), ActorToolbox(\"Visuals\")")
+class FLAXENGINE_API ExponentialHeightFog : public Actor, public IFogRenderer
{
DECLARE_SCENE_OBJECT(ExponentialHeightFog);
private:
diff --git a/Source/Engine/Level/Actors/PointLight.h b/Source/Engine/Level/Actors/PointLight.h
index 066bfb81b..87af4f970 100644
--- a/Source/Engine/Level/Actors/PointLight.h
+++ b/Source/Engine/Level/Actors/PointLight.h
@@ -9,7 +9,8 @@
///
/// Point light emits light from point in all directions.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Point Light\")") class FLAXENGINE_API PointLight : public LightWithShadow
+API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Point Light\"), ActorToolbox(\"Lights\")")
+class FLAXENGINE_API PointLight : public LightWithShadow
{
DECLARE_SCENE_OBJECT(PointLight);
private:
diff --git a/Source/Engine/Level/Actors/PostFxVolume.h b/Source/Engine/Level/Actors/PostFxVolume.h
index 97d61f1f3..6171523f1 100644
--- a/Source/Engine/Level/Actors/PostFxVolume.h
+++ b/Source/Engine/Level/Actors/PostFxVolume.h
@@ -9,7 +9,8 @@
///
/// A special type of volume that blends custom set of post process settings into the rendering.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Post Fx Volume\")") class FLAXENGINE_API PostFxVolume : public BoxVolume, public IPostFxSettingsProvider
+API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Post Fx Volume\"), ActorToolbox(\"Visuals\")")
+class FLAXENGINE_API PostFxVolume : public BoxVolume, public IPostFxSettingsProvider
{
DECLARE_SCENE_OBJECT(PostFxVolume);
private:
diff --git a/Source/Engine/Level/Actors/Sky.h b/Source/Engine/Level/Actors/Sky.h
index 85c09eefd..e1fad03a3 100644
--- a/Source/Engine/Level/Actors/Sky.h
+++ b/Source/Engine/Level/Actors/Sky.h
@@ -14,7 +14,8 @@ class GPUPipelineState;
///
/// Sky actor renders atmosphere around the scene with fog and sky.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Sky\")") class FLAXENGINE_API Sky : public Actor, public IAtmosphericFogRenderer, public ISkyRenderer
+API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Sky\"), ActorToolbox(\"Visuals\")")
+class FLAXENGINE_API Sky : public Actor, public IAtmosphericFogRenderer, public ISkyRenderer
{
DECLARE_SCENE_OBJECT(Sky);
private:
diff --git a/Source/Engine/Level/Actors/SkyLight.h b/Source/Engine/Level/Actors/SkyLight.h
index 4663709b5..d5077a21c 100644
--- a/Source/Engine/Level/Actors/SkyLight.h
+++ b/Source/Engine/Level/Actors/SkyLight.h
@@ -9,7 +9,8 @@
///
/// Sky light captures the distant parts of the scene and applies it as a light. Allows to add ambient light.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Sky Light\")") class FLAXENGINE_API SkyLight : public Light
+API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Sky Light\"), ActorToolbox(\"Lights\")")
+class FLAXENGINE_API SkyLight : public Light
{
DECLARE_SCENE_OBJECT(SkyLight);
public:
diff --git a/Source/Engine/Level/Actors/Skybox.h b/Source/Engine/Level/Actors/Skybox.h
index 0684976bd..088dc1ac1 100644
--- a/Source/Engine/Level/Actors/Skybox.h
+++ b/Source/Engine/Level/Actors/Skybox.h
@@ -11,7 +11,8 @@
///
/// Skybox actor renders sky using custom cube texture or material.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Sky Box\")") class FLAXENGINE_API Skybox : public Actor, public ISkyRenderer
+API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Sky Box\"), ActorToolbox(\"Visuals\")")
+class FLAXENGINE_API Skybox : public Actor, public ISkyRenderer
{
DECLARE_SCENE_OBJECT(Skybox);
private:
diff --git a/Source/Engine/Level/Actors/Spline.h b/Source/Engine/Level/Actors/Spline.h
index a2d2fa7d2..a1b447a26 100644
--- a/Source/Engine/Level/Actors/Spline.h
+++ b/Source/Engine/Level/Actors/Spline.h
@@ -8,7 +8,8 @@
///
/// Spline shape actor that defines spatial curve with utility functions for general purpose usage.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Other/Spline\")") class FLAXENGINE_API Spline : public Actor
+API_CLASS(Attributes="ActorContextMenu(\"New/Other/Spline\"), ActorToolbox(\"Other\")")
+class FLAXENGINE_API Spline : public Actor
{
DECLARE_SCENE_OBJECT(Spline);
typedef BezierCurveKeyframe Keyframe;
diff --git a/Source/Engine/Level/Actors/SpotLight.h b/Source/Engine/Level/Actors/SpotLight.h
index 059e4d28d..d28ff9fcd 100644
--- a/Source/Engine/Level/Actors/SpotLight.h
+++ b/Source/Engine/Level/Actors/SpotLight.h
@@ -9,7 +9,8 @@
///
/// Spot light emits light from the point in a given direction.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Spot Light\")") class FLAXENGINE_API SpotLight : public LightWithShadow
+API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Spot Light\"), ActorToolbox(\"Lights\")")
+class FLAXENGINE_API SpotLight : public LightWithShadow
{
DECLARE_SCENE_OBJECT(SpotLight);
private:
diff --git a/Source/Engine/Navigation/NavLink.h b/Source/Engine/Navigation/NavLink.h
index 7a788a2a5..bd2aa7792 100644
--- a/Source/Engine/Navigation/NavLink.h
+++ b/Source/Engine/Navigation/NavLink.h
@@ -5,10 +5,10 @@
#include "Engine/Level/Actor.h"
///
-/// The off-mesh link objects used to define a custom point-to-point edge within the navigation graph.
-/// An off-mesh connection is a user defined traversable connection made up to two vertices, at least one of which resides within a navigation mesh polygon allowing movement outside the navigation mesh.
+/// The off-mesh link objects used to define a custom point-to-point edge within the navigation graph. An off-mesh connection is a user defined traversable connection made up to two vertices, at least one of which resides within a navigation mesh polygon allowing movement outside the navigation mesh.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Other/Nav Link\")") class FLAXENGINE_API NavLink : public Actor
+API_CLASS(Attributes="ActorContextMenu(\"New/Other/Nav Link\"), ActorToolbox(\"Other\")")
+class FLAXENGINE_API NavLink : public Actor
{
DECLARE_SCENE_OBJECT(NavLink);
public:
diff --git a/Source/Engine/Navigation/NavMeshBoundsVolume.h b/Source/Engine/Navigation/NavMeshBoundsVolume.h
index 595105048..4c079c695 100644
--- a/Source/Engine/Navigation/NavMeshBoundsVolume.h
+++ b/Source/Engine/Navigation/NavMeshBoundsVolume.h
@@ -8,7 +8,8 @@
///
/// A special type of volume that defines the area of the scene in which navigation meshes are generated.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Other/Nav Mesh Bounds Volume\")") class FLAXENGINE_API NavMeshBoundsVolume : public BoxVolume
+API_CLASS(Attributes="ActorContextMenu(\"New/Other/Nav Mesh Bounds Volume\"), ActorToolbox(\"Other\")")
+class FLAXENGINE_API NavMeshBoundsVolume : public BoxVolume
{
DECLARE_SCENE_OBJECT(NavMeshBoundsVolume);
public:
diff --git a/Source/Engine/Navigation/NavModifierVolume.h b/Source/Engine/Navigation/NavModifierVolume.h
index c2992ccdc..0f1e9f9c6 100644
--- a/Source/Engine/Navigation/NavModifierVolume.h
+++ b/Source/Engine/Navigation/NavModifierVolume.h
@@ -8,7 +8,7 @@
///
/// A special type of volume that defines the area of the scene in which navigation is restricted (eg. higher traversal cost or dynamic obstacle block).
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Other/Nav Modifier Volume\")") class FLAXENGINE_API NavModifierVolume : public BoxVolume
+API_CLASS(Attributes="ActorContextMenu(\"New/Other/Nav Modifier Volume\"), ActorToolbox(\"Other\")") class FLAXENGINE_API NavModifierVolume : public BoxVolume
{
DECLARE_SCENE_OBJECT(NavModifierVolume);
public:
diff --git a/Source/Engine/Particles/ParticleEffect.h b/Source/Engine/Particles/ParticleEffect.h
index 5f3b898ea..9d735b364 100644
--- a/Source/Engine/Particles/ParticleEffect.h
+++ b/Source/Engine/Particles/ParticleEffect.h
@@ -133,7 +133,8 @@ public:
///
/// The particle system instance that plays the particles simulation in the game.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Particle Effects\")") class FLAXENGINE_API ParticleEffect : public Actor
+API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Particle Effects\"), ActorToolbox(\"Visuals\")")
+class FLAXENGINE_API ParticleEffect : public Actor
{
DECLARE_SCENE_OBJECT(ParticleEffect);
public:
diff --git a/Source/Engine/Physics/Actors/RigidBody.h b/Source/Engine/Physics/Actors/RigidBody.h
index f93abe915..399e40596 100644
--- a/Source/Engine/Physics/Actors/RigidBody.h
+++ b/Source/Engine/Physics/Actors/RigidBody.h
@@ -14,7 +14,8 @@ class Collider;
/// Physics simulation driven object.
///
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Rigid Body\")") class FLAXENGINE_API RigidBody : public Actor, public IPhysicsActor
+API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Rigid Body\"), ActorToolbox(\"Physics\")")
+class FLAXENGINE_API RigidBody : public Actor, public IPhysicsActor
{
DECLARE_SCENE_OBJECT(RigidBody);
protected:
diff --git a/Source/Engine/Physics/Colliders/BoxCollider.h b/Source/Engine/Physics/Colliders/BoxCollider.h
index a91872acd..c15d1c8b4 100644
--- a/Source/Engine/Physics/Colliders/BoxCollider.h
+++ b/Source/Engine/Physics/Colliders/BoxCollider.h
@@ -9,7 +9,8 @@
/// A box-shaped primitive collider.
///
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Box Collider\")") class FLAXENGINE_API BoxCollider : public Collider
+API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Box Collider\"), ActorToolbox(\"Physics\")")
+class FLAXENGINE_API BoxCollider : public Collider
{
DECLARE_SCENE_OBJECT(BoxCollider);
private:
diff --git a/Source/Engine/Physics/Colliders/CapsuleCollider.h b/Source/Engine/Physics/Colliders/CapsuleCollider.h
index c4837b814..fa4e487ec 100644
--- a/Source/Engine/Physics/Colliders/CapsuleCollider.h
+++ b/Source/Engine/Physics/Colliders/CapsuleCollider.h
@@ -10,7 +10,8 @@
///
/// Capsules are cylinders with a half-sphere at each end centered at the origin and extending along the X axis, and two hemispherical ends.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Capsule Collider\")") class FLAXENGINE_API CapsuleCollider : public Collider
+API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Capsule Collider\"), ActorToolbox(\"Physics\")")
+class FLAXENGINE_API CapsuleCollider : public Collider
{
DECLARE_SCENE_OBJECT(CapsuleCollider);
private:
diff --git a/Source/Engine/Physics/Colliders/CharacterController.h b/Source/Engine/Physics/Colliders/CharacterController.h
index 79a88d601..95d9e3293 100644
--- a/Source/Engine/Physics/Colliders/CharacterController.h
+++ b/Source/Engine/Physics/Colliders/CharacterController.h
@@ -9,7 +9,8 @@
/// Physical objects that allows to easily do player movement constrained by collisions without having to deal with a rigidbody.
///
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Character Controller\")") class FLAXENGINE_API CharacterController : public Collider, public IPhysicsActor
+API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Character Controller\"), ActorToolbox(\"Physics\")")
+class FLAXENGINE_API CharacterController : public Collider, public IPhysicsActor
{
DECLARE_SCENE_OBJECT(CharacterController);
public:
diff --git a/Source/Engine/Physics/Colliders/MeshCollider.h b/Source/Engine/Physics/Colliders/MeshCollider.h
index 9aea57e72..44c3662ab 100644
--- a/Source/Engine/Physics/Colliders/MeshCollider.h
+++ b/Source/Engine/Physics/Colliders/MeshCollider.h
@@ -10,7 +10,8 @@
/// A collider represented by an arbitrary mesh.
///
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Mesh Collider\")") class FLAXENGINE_API MeshCollider : public Collider
+API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Mesh Collider\"), ActorToolbox(\"Physics\")")
+class FLAXENGINE_API MeshCollider : public Collider
{
DECLARE_SCENE_OBJECT(MeshCollider);
public:
diff --git a/Source/Engine/Physics/Colliders/SphereCollider.h b/Source/Engine/Physics/Colliders/SphereCollider.h
index 263ff84f2..6a816b5e5 100644
--- a/Source/Engine/Physics/Colliders/SphereCollider.h
+++ b/Source/Engine/Physics/Colliders/SphereCollider.h
@@ -8,7 +8,8 @@
/// A sphere-shaped primitive collider.
///
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Sphere Collider\")") class FLAXENGINE_API SphereCollider : public Collider
+API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Sphere Collider\"), ActorToolbox(\"Physics\")")
+class FLAXENGINE_API SphereCollider : public Collider
{
DECLARE_SCENE_OBJECT(SphereCollider);
private:
diff --git a/Source/Engine/Physics/Joints/D6Joint.h b/Source/Engine/Physics/Joints/D6Joint.h
index 2182f810f..a0aafd48e 100644
--- a/Source/Engine/Physics/Joints/D6Joint.h
+++ b/Source/Engine/Physics/Joints/D6Joint.h
@@ -160,7 +160,8 @@ public:
/// It also allows you to constrain limits to only specific axes or completely lock specific axes.
///
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Physics/D6 Joint\")") class FLAXENGINE_API D6Joint : public Joint
+API_CLASS(Attributes="ActorContextMenu(\"New/Physics/D6 Joint\"), ActorToolbox(\"Physics\")")
+class FLAXENGINE_API D6Joint : public Joint
{
DECLARE_SCENE_OBJECT(D6Joint);
private:
diff --git a/Source/Engine/Physics/Joints/DistanceJoint.h b/Source/Engine/Physics/Joints/DistanceJoint.h
index 1d60f8473..44940b5ea 100644
--- a/Source/Engine/Physics/Joints/DistanceJoint.h
+++ b/Source/Engine/Physics/Joints/DistanceJoint.h
@@ -37,7 +37,8 @@ DECLARE_ENUM_OPERATORS(DistanceJointFlag);
/// Physics joint that maintains an upper or lower (or both) bound on the distance between two bodies.
///
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Distance Joint\")") class FLAXENGINE_API DistanceJoint : public Joint
+API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Distance Joint\"), ActorToolbox(\"Physics\")")
+class FLAXENGINE_API DistanceJoint : public Joint
{
DECLARE_SCENE_OBJECT(DistanceJoint);
private:
diff --git a/Source/Engine/Physics/Joints/FixedJoint.h b/Source/Engine/Physics/Joints/FixedJoint.h
index cb6c9e133..0e2eee8e4 100644
--- a/Source/Engine/Physics/Joints/FixedJoint.h
+++ b/Source/Engine/Physics/Joints/FixedJoint.h
@@ -8,7 +8,8 @@
/// Physics joint that maintains a fixed distance and orientation between its two attached bodies.
///
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Fixed Joint\")") class FLAXENGINE_API FixedJoint : public Joint
+API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Fixed Joint\"), ActorToolbox(\"Physics\")")
+class FLAXENGINE_API FixedJoint : public Joint
{
DECLARE_SCENE_OBJECT(FixedJoint);
public:
diff --git a/Source/Engine/Physics/Joints/HingeJoint.h b/Source/Engine/Physics/Joints/HingeJoint.h
index 27f012c85..9a3769c3c 100644
--- a/Source/Engine/Physics/Joints/HingeJoint.h
+++ b/Source/Engine/Physics/Joints/HingeJoint.h
@@ -67,7 +67,8 @@ public:
/// Physics joint that removes all but a single rotation degree of freedom from its two attached bodies (for example a door hinge).
///
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Hinge Joint\")") class FLAXENGINE_API HingeJoint : public Joint
+API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Hinge Joint\"), ActorToolbox(\"Physics\")")
+class FLAXENGINE_API HingeJoint : public Joint
{
DECLARE_SCENE_OBJECT(HingeJoint);
private:
diff --git a/Source/Engine/Physics/Joints/SliderJoint.h b/Source/Engine/Physics/Joints/SliderJoint.h
index 3bee7d242..46fb2a3de 100644
--- a/Source/Engine/Physics/Joints/SliderJoint.h
+++ b/Source/Engine/Physics/Joints/SliderJoint.h
@@ -27,7 +27,8 @@ DECLARE_ENUM_OPERATORS(SliderJointFlag);
/// Physics joint that removes all but a single translational degree of freedom. Bodies are allowed to move along a single axis.
///
///
-API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Slider Joint\")") class FLAXENGINE_API SliderJoint : public Joint
+API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Slider Joint\"), ActorToolbox(\"Physics\")")
+class FLAXENGINE_API SliderJoint : public Joint
{
DECLARE_SCENE_OBJECT(SliderJoint);
private:
diff --git a/Source/Engine/Physics/Joints/SphericalJoint.h b/Source/Engine/Physics/Joints/SphericalJoint.h
index dbee8d7cc..5b29a0a25 100644
--- a/Source/Engine/Physics/Joints/SphericalJoint.h
+++ b/Source/Engine/Physics/Joints/SphericalJoint.h
@@ -29,7 +29,8 @@ DECLARE_ENUM_OPERATORS(SphericalJointFlag);
/// rotate around the anchor points, and their rotation can be limited by an elliptical cone.
///
///
-API_CLASS(Attributes = "ActorContextMenu(\"New/Physics/Spherical Joint\")") class FLAXENGINE_API SphericalJoint : public Joint
+API_CLASS(Attributes = "ActorContextMenu(\"New/Physics/Spherical Joint\"), ActorToolbox(\"Physics\")")
+class FLAXENGINE_API SphericalJoint : public Joint
{
DECLARE_SCENE_OBJECT(SphericalJoint);
private:
diff --git a/Source/Engine/Scripting/Attributes/Editor/ActorContextMenu.cs b/Source/Engine/Scripting/Attributes/Editor/ActorContextMenuAttribute.cs
similarity index 94%
rename from Source/Engine/Scripting/Attributes/Editor/ActorContextMenu.cs
rename to Source/Engine/Scripting/Attributes/Editor/ActorContextMenuAttribute.cs
index aab4ed92d..618b88439 100644
--- a/Source/Engine/Scripting/Attributes/Editor/ActorContextMenu.cs
+++ b/Source/Engine/Scripting/Attributes/Editor/ActorContextMenuAttribute.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
namespace FlaxEngine
{
@@ -13,11 +13,11 @@ namespace FlaxEngine
/// The path to be used in the context menu
///
public string Path;
-
+
///
/// Initializes a new instance of the class.
///
- /// The path to use to create the context menu
+ /// The path to use to create the context menu.
public ActorContextMenuAttribute(string path)
{
Path = path;
diff --git a/Source/Engine/Scripting/Attributes/Editor/ActorToolboxAttribute.cs b/Source/Engine/Scripting/Attributes/Editor/ActorToolboxAttribute.cs
new file mode 100644
index 000000000..5d4aeb2fd
--- /dev/null
+++ b/Source/Engine/Scripting/Attributes/Editor/ActorToolboxAttribute.cs
@@ -0,0 +1,42 @@
+using System;
+
+namespace FlaxEngine
+{
+ ///
+ /// This attribute is used to show actors that can be created in the actor tab of the toolbox.
+ ///
+ [Serializable]
+ [AttributeUsage(AttributeTargets.Class)]
+ public class ActorToolboxAttribute : Attribute
+ {
+ ///
+ /// The path to be used in the tool box
+ ///
+ public string Group;
+
+ ///
+ /// The name to be used for the actor in the tool box. Will default to actor name if now used.
+ ///
+ public string Name;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The group to use to create the tab.
+ public ActorToolboxAttribute(string group)
+ {
+ Group = group;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The group used to create the tab.
+ /// The name to use rather than default.
+ public ActorToolboxAttribute(string group, string name)
+ {
+ Group = group;
+ Name = name;
+ }
+ }
+}
diff --git a/Source/Engine/Scripting/Attributes/Editor/ContentContextMenu.cs b/Source/Engine/Scripting/Attributes/Editor/ContentContextMenuAttribute.cs
similarity index 95%
rename from Source/Engine/Scripting/Attributes/Editor/ContentContextMenu.cs
rename to Source/Engine/Scripting/Attributes/Editor/ContentContextMenuAttribute.cs
index ee9956ede..24e080ed7 100644
--- a/Source/Engine/Scripting/Attributes/Editor/ContentContextMenu.cs
+++ b/Source/Engine/Scripting/Attributes/Editor/ContentContextMenuAttribute.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
namespace FlaxEngine
{
@@ -17,7 +17,7 @@ namespace FlaxEngine
///
/// Initializes a new instance of the class.
///
- /// The path to use to create the context menu
+ /// The path to use to create the context menu.
public ContentContextMenuAttribute(string path)
{
Path = path;
diff --git a/Source/Engine/UI/GUI/Common/TextBoxBase.cs b/Source/Engine/UI/GUI/Common/TextBoxBase.cs
index 340459c8f..69b4fa123 100644
--- a/Source/Engine/UI/GUI/Common/TextBoxBase.cs
+++ b/Source/Engine/UI/GUI/Common/TextBoxBase.cs
@@ -370,7 +370,7 @@ namespace FlaxEngine.GUI
{
Focus();
SetText(value);
- Defocus();
+ RemoveFocus();
}
///
@@ -907,6 +907,14 @@ namespace FlaxEngine.GUI
return HitTestText(location);
}
+ private void RemoveFocus()
+ {
+ if (Parent != null)
+ Parent.Focus();
+ else
+ Defocus();
+ }
+
///
/// Calculates total text size. Called by to cache the text size.
///
@@ -1297,7 +1305,7 @@ namespace FlaxEngine.GUI
_text = _onStartEditValue;
if (!IsNavFocused)
- Defocus();
+ RemoveFocus();
OnTextChanged();
return true;
@@ -1311,7 +1319,7 @@ namespace FlaxEngine.GUI
else if (!IsNavFocused)
{
// End editing
- Defocus();
+ RemoveFocus();
}
return true;
case KeyboardKeys.Home:
diff --git a/Source/Engine/UI/SpriteRender.h b/Source/Engine/UI/SpriteRender.h
index 839b274f2..c5efc018a 100644
--- a/Source/Engine/UI/SpriteRender.h
+++ b/Source/Engine/UI/SpriteRender.h
@@ -10,7 +10,8 @@
///
/// Sprite rendering object.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/UI/Sprite Render\")") class FLAXENGINE_API SpriteRender : public Actor
+API_CLASS(Attributes="ActorContextMenu(\"New/UI/Sprite Render\"), ActorToolbox(\"GUI\")")
+class FLAXENGINE_API SpriteRender : public Actor
{
DECLARE_SCENE_OBJECT(SpriteRender);
private:
diff --git a/Source/Engine/UI/TextRender.h b/Source/Engine/UI/TextRender.h
index 3c8be565a..da3c73ae0 100644
--- a/Source/Engine/UI/TextRender.h
+++ b/Source/Engine/UI/TextRender.h
@@ -3,7 +3,6 @@
#pragma once
#include "Engine/Level/Actor.h"
-#include "Engine/Core/Math/Matrix.h"
#include "Engine/Render2D/TextLayoutOptions.h"
#include "Engine/Render2D/FontAsset.h"
#include "Engine/Renderer/DrawCall.h"
@@ -19,7 +18,8 @@
///
/// Text rendering object.
///
-API_CLASS(Attributes="ActorContextMenu(\"New/UI/Text Render\")") class FLAXENGINE_API TextRender : public Actor
+API_CLASS(Attributes="ActorContextMenu(\"New/UI/Text Render\"), ActorToolbox(\"GUI\")")
+class FLAXENGINE_API TextRender : public Actor
{
DECLARE_SCENE_OBJECT(TextRender);
private:
@@ -138,16 +138,13 @@ public:
API_FUNCTION() void UpdateLayout();
#if USE_PRECISE_MESH_INTERSECTS
-
///
/// Gets the collision proxy used by the text geometry.
///
- /// The collisions proxy container object reference.
FORCE_INLINE const CollisionProxy& GetCollisionProxy() const
{
return _collisionProxy;
}
-
#endif
private:
diff --git a/Source/Engine/UI/UICanvas.h b/Source/Engine/UI/UICanvas.h
index d207739eb..9a8b76794 100644
--- a/Source/Engine/UI/UICanvas.h
+++ b/Source/Engine/UI/UICanvas.h
@@ -7,7 +7,8 @@
///
/// Root of the UI structure. Renders GUI and handles input events forwarding.
///
-API_CLASS(Sealed, NoConstructor, Attributes="ActorContextMenu(\"New/UI/UI Canvas\")") class FLAXENGINE_API UICanvas : public Actor
+API_CLASS(Sealed, NoConstructor, Attributes="ActorContextMenu(\"New/UI/UI Canvas\"), ActorToolbox(\"GUI\")")
+class FLAXENGINE_API UICanvas : public Actor
{
DECLARE_SCENE_OBJECT(UICanvas);
public:
diff --git a/Source/Engine/UI/UIControl.h b/Source/Engine/UI/UIControl.h
index 381cbf98a..490abcbb1 100644
--- a/Source/Engine/UI/UIControl.h
+++ b/Source/Engine/UI/UIControl.h
@@ -8,7 +8,8 @@
///
/// Contains a single GUI control (on C# side).
///
-API_CLASS(Sealed, Attributes="ActorContextMenu(\"New/UI/UI Control\")") class FLAXENGINE_API UIControl : public Actor
+API_CLASS(Sealed, Attributes="ActorContextMenu(\"New/UI/UI Control\"), ActorToolbox(\"GUI\")")
+class FLAXENGINE_API UIControl : public Actor
{
DECLARE_SCENE_OBJECT(UIControl);
private: