From 76c6696eadf11c1ce4f92d2a09ed8889d26c1f0e Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 21 Apr 2023 08:36:56 -0500 Subject: [PATCH 01/33] Add saving and re-opening all active scenes between editor sessions. --- Source/Editor/Editor.cs | 53 +++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/Source/Editor/Editor.cs b/Source/Editor/Editor.cs index 4d2cf4346..bf51dd323 100644 --- a/Source/Editor/Editor.cs +++ b/Source/Editor/Editor.cs @@ -323,8 +323,16 @@ namespace FlaxEditor } case GeneralOptions.StartupSceneModes.LastOpened: { - if (ProjectCache.TryGetCustomData(ProjectDataLastScene, out var lastSceneIdName) && Guid.TryParse(lastSceneIdName, out var lastSceneId)) - Internal_LoadAsset(ref lastSceneId); + if (ProjectCache.TryGetCustomData(ProjectDataLastScene, out var lastSceneIdName)) + { + var lastSceneList = JsonSerializer.Deserialize>(lastSceneIdName); + + foreach (var scene in lastSceneList) + { + var lastScene = scene; + Internal_LoadAsset(ref lastScene); + } + } break; } } @@ -438,18 +446,25 @@ namespace FlaxEditor } case GeneralOptions.StartupSceneModes.LastOpened: { - if (ProjectCache.TryGetCustomData(ProjectDataLastScene, out var lastSceneIdName) && Guid.TryParse(lastSceneIdName, out var lastSceneId)) + if (ProjectCache.TryGetCustomData(ProjectDataLastScene, out var lastSceneIdName)) { - var lastScene = ContentDatabase.Find(lastSceneId); - if (lastScene is SceneItem) - { - Editor.Log("Loading last opened scene"); - Scene.OpenScene(lastSceneId); + var lastSceneList = JsonSerializer.Deserialize>(lastSceneIdName); - // Restore view - if (ProjectCache.TryGetCustomData(ProjectDataLastSceneSpawn, out var lastSceneSpawnName)) - Windows.EditWin.Viewport.ViewRay = JsonSerializer.Deserialize(lastSceneSpawnName); + foreach (var sceneId in lastSceneList) + { + var lastScene = ContentDatabase.Find(sceneId); + if (!(lastScene is SceneItem)) + continue; + + Editor.Log($"Loading last opened scene: {lastScene.ShortName}"); + if (sceneId == lastSceneList[0]) + Scene.OpenScene(sceneId); + else + Level.LoadSceneAsync(sceneId); } + // Restore view + if (ProjectCache.TryGetCustomData(ProjectDataLastSceneSpawn, out var lastSceneSpawnName)) + Windows.EditWin.Viewport.ViewRay = JsonSerializer.Deserialize(lastSceneSpawnName); } break; } @@ -664,9 +679,21 @@ namespace FlaxEditor // Cache last opened scene { - var lastSceneId = Level.ScenesCount > 0 ? Level.Scenes[0].ID : Guid.Empty; + List lastSceneIds = new List(); + if (Level.ScenesCount > 0) + { + foreach (var scene in Level.Scenes) + { + lastSceneIds.Add(scene.ID); + } + } + else + { + lastSceneIds.Add(Guid.Empty); + } + //var lastSceneId = Level.ScenesCount > 0 ? Level.Scenes[0].ID : Guid.Empty; var lastSceneSpawn = Windows.EditWin.Viewport.ViewRay; - ProjectCache.SetCustomData(ProjectDataLastScene, lastSceneId.ToString()); + ProjectCache.SetCustomData(ProjectDataLastScene, JsonSerializer.Serialize(lastSceneIds)); ProjectCache.SetCustomData(ProjectDataLastSceneSpawn, JsonSerializer.Serialize(lastSceneSpawn)); } From c93b41a88d839aac31876c791f23dafe281dc983 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 21 Apr 2023 10:34:40 -0500 Subject: [PATCH 02/33] Small Cleanup --- Source/Editor/Editor.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Editor/Editor.cs b/Source/Editor/Editor.cs index bf51dd323..1f4725ef7 100644 --- a/Source/Editor/Editor.cs +++ b/Source/Editor/Editor.cs @@ -691,7 +691,6 @@ namespace FlaxEditor { lastSceneIds.Add(Guid.Empty); } - //var lastSceneId = Level.ScenesCount > 0 ? Level.Scenes[0].ID : Guid.Empty; var lastSceneSpawn = Windows.EditWin.Viewport.ViewRay; ProjectCache.SetCustomData(ProjectDataLastScene, JsonSerializer.Serialize(lastSceneIds)); ProjectCache.SetCustomData(ProjectDataLastSceneSpawn, JsonSerializer.Serialize(lastSceneSpawn)); From 918140bc6dbc19c7b881ea100eb88018339b983f Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Sat, 22 Apr 2023 12:04:57 -0500 Subject: [PATCH 03/33] Change List to Guid[] when deserializing. --- Source/Editor/Editor.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Source/Editor/Editor.cs b/Source/Editor/Editor.cs index 1f4725ef7..11e16f1ef 100644 --- a/Source/Editor/Editor.cs +++ b/Source/Editor/Editor.cs @@ -325,8 +325,7 @@ namespace FlaxEditor { if (ProjectCache.TryGetCustomData(ProjectDataLastScene, out var lastSceneIdName)) { - var lastSceneList = JsonSerializer.Deserialize>(lastSceneIdName); - + var lastSceneList = JsonSerializer.Deserialize(lastSceneIdName); foreach (var scene in lastSceneList) { var lastScene = scene; @@ -448,8 +447,7 @@ namespace FlaxEditor { if (ProjectCache.TryGetCustomData(ProjectDataLastScene, out var lastSceneIdName)) { - var lastSceneList = JsonSerializer.Deserialize>(lastSceneIdName); - + var lastSceneList = JsonSerializer.Deserialize(lastSceneIdName); foreach (var sceneId in lastSceneList) { var lastScene = ContentDatabase.Find(sceneId); @@ -677,7 +675,7 @@ namespace FlaxEditor // Start exit StateMachine.GoToState(); - // Cache last opened scene + // Cache last opened scenes { List lastSceneIds = new List(); if (Level.ScenesCount > 0) From ce1b47979eac7f37218f491cc29b7a350671e4b5 Mon Sep 17 00:00:00 2001 From: Wiktor Kocielski Date: Sun, 23 Apr 2023 14:31:05 +0300 Subject: [PATCH 04/33] Typo fixes --- Source/Engine/Level/Actor.h | 2 +- Source/Engine/Level/Types.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Level/Actor.h b/Source/Engine/Level/Actor.h index c1d038783..53427ab52 100644 --- a/Source/Engine/Level/Actor.h +++ b/Source/Engine/Level/Actor.h @@ -379,7 +379,7 @@ public: } /// - /// Gets the actor static fags. + /// Gets the actor static flags. /// API_PROPERTY(Attributes="NoAnimate, EditorDisplay(\"General\"), EditorOrder(-80), CustomEditorAlias(\"FlaxEditor.CustomEditors.Editors.ActorStaticFlagsEditor\")") FORCE_INLINE StaticFlags GetStaticFlags() const diff --git a/Source/Engine/Level/Types.h b/Source/Engine/Level/Types.h index 9a29fde6e..a9938658b 100644 --- a/Source/Engine/Level/Types.h +++ b/Source/Engine/Level/Types.h @@ -100,7 +100,7 @@ API_ENUM(Attributes="Flags") enum class StaticFlags Navigation = 1 << 3, /// - /// Objects is fully static on the scene. + /// Object is fully static in the scene. /// FullyStatic = Transform | ReflectionProbe | Lightmap | Navigation, From 309302c212a0beba54fbe7a86ad07ffbcba6421d Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Sun, 23 Apr 2023 10:00:26 -0400 Subject: [PATCH 05/33] improv: set new material instance name to parent material name --- Source/Editor/Content/Proxy/MaterialProxy.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Editor/Content/Proxy/MaterialProxy.cs b/Source/Editor/Content/Proxy/MaterialProxy.cs index 9cbd54975..c6a9755fc 100644 --- a/Source/Editor/Content/Proxy/MaterialProxy.cs +++ b/Source/Editor/Content/Proxy/MaterialProxy.cs @@ -75,8 +75,9 @@ namespace FlaxEditor.Content if (materialItem == null) throw new ArgumentNullException(); + var materialInstanceName = materialItem.FileName.Replace(".flax", " Instance"); var materialInstanceProxy = Editor.Instance.ContentDatabase.GetProxy(); - Editor.Instance.Windows.ContentWin.NewItem(materialInstanceProxy, null, item => OnMaterialInstanceCreated(item, materialItem)); + Editor.Instance.Windows.ContentWin.NewItem(materialInstanceProxy, null, item => OnMaterialInstanceCreated(item, materialItem), materialInstanceName); } private static void OnMaterialInstanceCreated(ContentItem item, BinaryAssetItem materialItem) From 0b3259fcc34bd423b1eb9b0c954ed0027761077d Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Mon, 24 Apr 2023 11:02:44 -0500 Subject: [PATCH 06/33] Increase size of add node so that vector3 fits correctly --- Source/Editor/Surface/Archetypes/Math.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/Surface/Archetypes/Math.cs b/Source/Editor/Surface/Archetypes/Math.cs index d2aef9ae5..1b8f62e62 100644 --- a/Source/Editor/Surface/Archetypes/Math.cs +++ b/Source/Editor/Surface/Archetypes/Math.cs @@ -47,7 +47,7 @@ namespace FlaxEditor.Surface.Archetypes Description = desc, Flags = NodeFlags.AllGraphs, AlternativeTitles = altTitles, - Size = new Float2(140, 40), + Size = new Float2(150, 40), DefaultType = new ScriptType(inputType), ConnectionsHints = hints, IndependentBoxes = new[] { 0, 1 }, From 2c9541f6a0c085c0ef2659e2c3df23577e768ab4 Mon Sep 17 00:00:00 2001 From: Wiktor Kocielski Date: Mon, 24 Apr 2023 02:03:11 +0300 Subject: [PATCH 07/33] ViewportIconsRenderer::AddActorWithTexture addition --- .../Utilities/ViewportIconsRenderer.cpp | 72 +++++++++++++++++-- .../Editor/Utilities/ViewportIconsRenderer.h | 7 ++ 2 files changed, 72 insertions(+), 7 deletions(-) diff --git a/Source/Editor/Utilities/ViewportIconsRenderer.cpp b/Source/Editor/Utilities/ViewportIconsRenderer.cpp index 9b7f4979b..a5ed0356f 100644 --- a/Source/Editor/Utilities/ViewportIconsRenderer.cpp +++ b/Source/Editor/Utilities/ViewportIconsRenderer.cpp @@ -47,6 +47,8 @@ AssetReference CustomTextureMaterial; ModelInstanceEntries InstanceBuffers[static_cast(IconTypes::MAX)]; Dictionary ActorTypeToIconType; Dictionary> ActorTypeToTexture; +Dictionary, AssetReference> ActorToTexture; +Dictionary, AssetReference> TextureToMaterial; class ViewportIconsRendererService : public EngineService { @@ -103,10 +105,18 @@ void ViewportIconsRenderer::AddActor(Actor* actor) actor->GetSceneRendering()->AddViewportIcon(actor); } +void ViewportIconsRenderer::AddActorWithTexture(Actor* actor, Texture* iconTexture) +{ + CHECK(actor && actor->GetScene() && iconTexture); + ActorToTexture[actor] = iconTexture; + actor->GetSceneRendering()->AddViewportIcon(actor); +} + void ViewportIconsRenderer::RemoveActor(Actor* actor) { CHECK(actor && actor->GetScene()); actor->GetSceneRendering()->RemoveViewportIcon(actor); + ActorToTexture.Remove(actor); } void ViewportIconsRendererService::DrawIcons(RenderContext& renderContext, Scene* scene, Mesh::DrawInfo& draw) @@ -128,7 +138,7 @@ void ViewportIconsRendererService::DrawIcons(RenderContext& renderContext, Scene ScriptingTypeHandle typeHandle = icon->GetTypeHandle(); draw.Buffer = nullptr; - if (ActorTypeToTexture.TryGet(typeHandle, texture)) + if (ActorToTexture.TryGet(icon, texture) || ActorTypeToTexture.TryGet(typeHandle, texture)) { // Use custom texture draw.Buffer = &InstanceBuffers[static_cast(IconTypes::CustomTexture)]; @@ -137,9 +147,20 @@ void ViewportIconsRendererService::DrawIcons(RenderContext& renderContext, Scene // Lazy-init (use in-built icon material with custom texture) draw.Buffer->Setup(1); draw.Buffer->At(0).ReceiveDecals = false; - draw.Buffer->At(0).Material = InstanceBuffers[0][0].Material->CreateVirtualInstance(); + draw.Buffer->At(0).ShadowsMode = ShadowsCastingMode::None; } - draw.Buffer->At(0).Material->SetParameterValue(TEXT("Image"), Variant(texture)); + + AssetReference material; + + if (!TextureToMaterial.TryGet(texture, material)) + { + // Create custom material per custom texture + TextureToMaterial[texture] = InstanceBuffers[0][0].Material->CreateVirtualInstance(); + TextureToMaterial[texture]->SetParameterValue(TEXT("Image"), Variant(texture)); + material = TextureToMaterial[texture]; + } + + draw.Buffer->At(0).Material = material; } else if (ActorTypeToIconType.TryGet(typeHandle, iconType)) { @@ -170,6 +191,8 @@ void ViewportIconsRendererService::DrawIcons(RenderContext& renderContext, Actor Matrix m1, m2, world; BoundingSphere sphere(actor->GetPosition() - renderContext.View.Origin, ICON_RADIUS); IconTypes iconType; + AssetReference texture; + if (frustum.Intersects(sphere) && ActorTypeToIconType.TryGet(actor->GetTypeHandle(), iconType)) { // Create world matrix @@ -182,7 +205,39 @@ void ViewportIconsRendererService::DrawIcons(RenderContext& renderContext, Actor // Draw icon GeometryDrawStateData drawState; draw.DrawState = &drawState; - draw.Buffer = &InstanceBuffers[static_cast(iconType)]; + + // Support custom icons through types, but not onces that were added through actors, + // since they cant register while in prefab view anyway + if (ActorTypeToTexture.TryGet(actor->GetTypeHandle(), texture)) + { + // Use custom texture + draw.Buffer = &InstanceBuffers[static_cast(IconTypes::CustomTexture)]; + if (draw.Buffer->Count() == 0) + { + // Lazy-init (use in-built icon material with custom texture) + draw.Buffer->Setup(1); + draw.Buffer->At(0).ReceiveDecals = false; + draw.Buffer->At(0).ShadowsMode = ShadowsCastingMode::None; + } + + AssetReference material; + + if (!TextureToMaterial.TryGet(texture, material)) + { + // Create custom material per custom texture + TextureToMaterial[texture] = InstanceBuffers[0][0].Material->CreateVirtualInstance(); + TextureToMaterial[texture]->SetParameterValue(TEXT("Image"), Variant(texture)); + material = TextureToMaterial[texture]; + } + + draw.Buffer->At(0).Material = material; + } + else + { + // Use predefined material + draw.Buffer = &InstanceBuffers[static_cast(iconType)]; + } + draw.World = &world; draw.Bounds = sphere; QuadModel->Draw(renderContext, draw); @@ -196,9 +251,10 @@ bool ViewportIconsRendererService::Init() { QuadModel = Content::LoadAsyncInternal(TEXT("Engine/Models/Quad")); #define INIT(type, path) \ - InstanceBuffers[static_cast(IconTypes::type)].Setup(1); \ - InstanceBuffers[static_cast(IconTypes::type)][0].ReceiveDecals = false; \ - InstanceBuffers[static_cast(IconTypes::type)][0].Material = Content::LoadAsyncInternal(TEXT(path)) + InstanceBuffers[static_cast(IconTypes::type)].Setup(1); \ + InstanceBuffers[static_cast(IconTypes::type)][0].ReceiveDecals = false; \ + InstanceBuffers[static_cast(IconTypes::type)][0].ShadowsMode = ShadowsCastingMode::None; \ + InstanceBuffers[static_cast(IconTypes::type)][0].Material = Content::LoadAsyncInternal(TEXT(path)) INIT(PointLight, "Editor/Icons/PointLight"); INIT(DirectionalLight, "Editor/Icons/DirectionalLight"); INIT(EnvironmentProbe, "Editor/Icons/EnvironmentProbe"); @@ -236,4 +292,6 @@ void ViewportIconsRendererService::Dispose() for (int32 i = 0; i < ARRAY_COUNT(InstanceBuffers); i++) InstanceBuffers[i].Release(); ActorTypeToIconType.Clear(); + ActorToTexture.Clear(); + TextureToMaterial.Clear(); } diff --git a/Source/Editor/Utilities/ViewportIconsRenderer.h b/Source/Editor/Utilities/ViewportIconsRenderer.h index 509252795..4062c2642 100644 --- a/Source/Editor/Utilities/ViewportIconsRenderer.h +++ b/Source/Editor/Utilities/ViewportIconsRenderer.h @@ -37,6 +37,13 @@ public: /// The actor to register for icon drawing. API_FUNCTION() static void AddActor(Actor* actor); + /// + /// Adds actor to the viewport icon rendering. + /// + /// The actor to register for icon drawing. + /// The icon texture to draw. + API_FUNCTION() static void AddActorWithTexture(Actor* actor, Texture* iconTexture); + /// /// Removes actor from the viewport icon rendering. /// From 5178caeda6f418b4b5c99386434f368c8d9892ed Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Mon, 24 Apr 2023 17:27:43 -0500 Subject: [PATCH 08/33] Add inputs to Random Range visject float nodes --- Source/Editor/Surface/Archetypes/Particles.cs | 44 ++++--------------- 1 file changed, 8 insertions(+), 36 deletions(-) diff --git a/Source/Editor/Surface/Archetypes/Particles.cs b/Source/Editor/Surface/Archetypes/Particles.cs index 97be9a20d..dd861d4af 100644 --- a/Source/Editor/Surface/Archetypes/Particles.cs +++ b/Source/Editor/Surface/Archetypes/Particles.cs @@ -730,12 +730,8 @@ namespace FlaxEditor.Surface.Archetypes Elements = new[] { NodeElementArchetype.Factory.Output(0, string.Empty, typeof(float), 0), - - NodeElementArchetype.Factory.Text(0, 0, "Min", 30.0f, 18.0f), - NodeElementArchetype.Factory.Float(30, 0, 0), - - NodeElementArchetype.Factory.Text(0, Surface.Constants.LayoutOffsetY, "Max", 30.0f, 18.0f), - NodeElementArchetype.Factory.Float(30, Surface.Constants.LayoutOffsetY, 1), + NodeElementArchetype.Factory.Input(0, "Min", true, typeof(float), 1, 0), + NodeElementArchetype.Factory.Input(1, "Max", true, typeof(float), 2, 1), } }, new NodeArchetype @@ -753,14 +749,8 @@ namespace FlaxEditor.Surface.Archetypes Elements = new[] { NodeElementArchetype.Factory.Output(0, string.Empty, typeof(Float2), 0), - - NodeElementArchetype.Factory.Text(0, 0, "Min", 30.0f, 18.0f), - NodeElementArchetype.Factory.Vector_X(30, 0, 0), - NodeElementArchetype.Factory.Vector_Y(83, 0, 0), - - NodeElementArchetype.Factory.Text(0, Surface.Constants.LayoutOffsetY, "Max", 30.0f, 18.0f), - NodeElementArchetype.Factory.Vector_X(30, Surface.Constants.LayoutOffsetY, 1), - NodeElementArchetype.Factory.Vector_Y(83, Surface.Constants.LayoutOffsetY, 1), + NodeElementArchetype.Factory.Input(0, "Min", true, typeof(Float2), 1, 0), + NodeElementArchetype.Factory.Input(1, "Max", true, typeof(Float2), 2, 1), } }, new NodeArchetype @@ -778,16 +768,8 @@ namespace FlaxEditor.Surface.Archetypes Elements = new[] { NodeElementArchetype.Factory.Output(0, string.Empty, typeof(Float3), 0), - - NodeElementArchetype.Factory.Text(0, 0, "Min", 30.0f, 18.0f), - NodeElementArchetype.Factory.Vector_X(30, 0, 0), - NodeElementArchetype.Factory.Vector_Y(83, 0, 0), - NodeElementArchetype.Factory.Vector_Z(136, 0, 0), - - NodeElementArchetype.Factory.Text(0, Surface.Constants.LayoutOffsetY, "Max", 30.0f, 18.0f), - NodeElementArchetype.Factory.Vector_X(30, Surface.Constants.LayoutOffsetY, 1), - NodeElementArchetype.Factory.Vector_Y(83, Surface.Constants.LayoutOffsetY, 1), - NodeElementArchetype.Factory.Vector_Z(136, Surface.Constants.LayoutOffsetY, 1), + NodeElementArchetype.Factory.Input(0, "Min", true, typeof(Float3), 1, 0), + NodeElementArchetype.Factory.Input(1, "Max", true, typeof(Float3), 2, 1), } }, new NodeArchetype @@ -805,18 +787,8 @@ namespace FlaxEditor.Surface.Archetypes Elements = new[] { NodeElementArchetype.Factory.Output(0, string.Empty, typeof(Float4), 0), - - NodeElementArchetype.Factory.Text(0, 0, "Min", 30.0f, 18.0f), - NodeElementArchetype.Factory.Vector_X(30, 0, 0), - NodeElementArchetype.Factory.Vector_Y(83, 0, 0), - NodeElementArchetype.Factory.Vector_Z(136, 0, 0), - NodeElementArchetype.Factory.Vector_W(189, 0, 0), - - NodeElementArchetype.Factory.Text(0, Surface.Constants.LayoutOffsetY, "Max", 30.0f, 18.0f), - NodeElementArchetype.Factory.Vector_X(30, Surface.Constants.LayoutOffsetY, 1), - NodeElementArchetype.Factory.Vector_Y(83, Surface.Constants.LayoutOffsetY, 1), - NodeElementArchetype.Factory.Vector_Z(136, Surface.Constants.LayoutOffsetY, 1), - NodeElementArchetype.Factory.Vector_W(189, Surface.Constants.LayoutOffsetY, 1), + NodeElementArchetype.Factory.Input(0, "Min", true, typeof(Float4), 1, 0), + NodeElementArchetype.Factory.Input(1, "Max", true, typeof(Float4), 2, 1), } }, From c920b75142d99a3cccbbec622d0c35de72a76041 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Mon, 24 Apr 2023 17:47:19 -0500 Subject: [PATCH 09/33] Fix collision assets creation in non asset folders. --- Source/Editor/Content/Proxy/CollisionDataProxy.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Source/Editor/Content/Proxy/CollisionDataProxy.cs b/Source/Editor/Content/Proxy/CollisionDataProxy.cs index 55e8c6327..e4a2381f0 100644 --- a/Source/Editor/Content/Proxy/CollisionDataProxy.cs +++ b/Source/Editor/Content/Proxy/CollisionDataProxy.cs @@ -141,7 +141,13 @@ namespace FlaxEditor.Content }); }; var initialName = (modelItem?.ShortName ?? Path.GetFileNameWithoutExtension(model.Path)) + " Collision"; - Editor.Instance.Windows.ContentWin.NewItem(this, null, create, initialName, withRenaming); + + // If folder can not have assets then move to folder with the model and create asset + var contentWin = Editor.Instance.Windows.ContentWin; + if (!contentWin.CurrentViewFolder.CanHaveAssets) + contentWin.Navigate(modelItem?.ParentFolder?.Node); + + contentWin.NewItem(this, null, create, initialName, withRenaming); } } } From 1978cb6df96029da6162c8eba3ee1b0845d6c1e6 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 28 Apr 2023 08:48:13 -0500 Subject: [PATCH 10/33] Fix bug with not deleting all children on folder delete --- Source/Editor/Modules/ContentDatabaseModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/Modules/ContentDatabaseModule.cs b/Source/Editor/Modules/ContentDatabaseModule.cs index e5b2efee3..5e3b722b9 100644 --- a/Source/Editor/Modules/ContentDatabaseModule.cs +++ b/Source/Editor/Modules/ContentDatabaseModule.cs @@ -655,7 +655,7 @@ namespace FlaxEditor.Modules var children = folder.Children.ToArray(); for (int i = 0; i < children.Length; i++) { - Delete(children[0]); + Delete(children[i]); } } From 6fd636b421856c04c7c2a1d025d946aec2e29baa Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 28 Apr 2023 09:33:24 -0500 Subject: [PATCH 11/33] Change to serialize list as array --- Source/Editor/Editor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/Editor.cs b/Source/Editor/Editor.cs index 11e16f1ef..498c8cbd9 100644 --- a/Source/Editor/Editor.cs +++ b/Source/Editor/Editor.cs @@ -690,7 +690,7 @@ namespace FlaxEditor lastSceneIds.Add(Guid.Empty); } var lastSceneSpawn = Windows.EditWin.Viewport.ViewRay; - ProjectCache.SetCustomData(ProjectDataLastScene, JsonSerializer.Serialize(lastSceneIds)); + ProjectCache.SetCustomData(ProjectDataLastScene, JsonSerializer.Serialize(lastSceneIds.ToArray())); ProjectCache.SetCustomData(ProjectDataLastSceneSpawn, JsonSerializer.Serialize(lastSceneSpawn)); } From 299ca398fa0a187972340ec545e56b17405ff220 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Sat, 29 Apr 2023 18:44:54 -0400 Subject: [PATCH 12/33] small change in particle window --- Source/Editor/Windows/Assets/ParticleSystemWindow.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Editor/Windows/Assets/ParticleSystemWindow.cs b/Source/Editor/Windows/Assets/ParticleSystemWindow.cs index 814978858..0b59dc86c 100644 --- a/Source/Editor/Windows/Assets/ParticleSystemWindow.cs +++ b/Source/Editor/Windows/Assets/ParticleSystemWindow.cs @@ -156,14 +156,14 @@ namespace FlaxEditor.Windows.Assets private bool HasEmitter => _track.Asset != null; - [EditorDisplay("Particle Emitter"), VisibleIf("HasEmitter"), EditorOrder(200), Tooltip("The start frame of the media event.")] + [EditorDisplay("Particle Emitter"), VisibleIf(nameof(HasEmitter)), EditorOrder(200), Tooltip("The start frame of the media event.")] public int StartFrame { get => _track.Media.Count > 0 ? _track.TrackMedia.StartFrame : 0; set => _track.TrackMedia.StartFrame = value; } - [EditorDisplay("Particle Emitter"), Limit(1), VisibleIf("HasEmitter"), EditorOrder(300), Tooltip("The total duration of the media event in the timeline sequence frames amount.")] + [EditorDisplay("Particle Emitter"), Limit(1), VisibleIf(nameof(HasEmitter)), EditorOrder(300), Tooltip("The total duration of the media event in the timeline sequence frames amount.")] public int DurationFrames { get => _track.Media.Count > 0 ? _track.TrackMedia.DurationFrames : 0; From cfefe7a24c9326da2e34f6759309319612851c9f Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Sun, 30 Apr 2023 11:06:58 -0400 Subject: [PATCH 13/33] add == operator on Actors --- Source/Engine/Level/Actor.cs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Source/Engine/Level/Actor.cs b/Source/Engine/Level/Actor.cs index bd005d415..7ff6622b3 100644 --- a/Source/Engine/Level/Actor.cs +++ b/Source/Engine/Level/Actor.cs @@ -357,5 +357,27 @@ namespace FlaxEngine { return $"{Name} ({GetType().Name})"; } + + /// + /// Check if Actors are equals + /// + /// + /// + /// + public static bool operator ==(Actor left, Actor right) + { + return Object.Equals(left, right); + } + + /// + /// Check if Actors aren't equals + /// + /// + /// + /// + public static bool operator !=(Actor left, Actor right) + { + return !Object.Equals(left, right); + } } } From 176f95fbbc569fe75133cf1a181c22b5caf3087f Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Sun, 30 Apr 2023 14:25:41 -0400 Subject: [PATCH 14/33] move == operator from Actor class to Object class --- Source/Engine/Level/Actor.cs | 22 ---------------------- Source/Engine/Scripting/Object.cs | 24 ++++++++++++++++++++++++ 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/Source/Engine/Level/Actor.cs b/Source/Engine/Level/Actor.cs index 7ff6622b3..bd005d415 100644 --- a/Source/Engine/Level/Actor.cs +++ b/Source/Engine/Level/Actor.cs @@ -357,27 +357,5 @@ namespace FlaxEngine { return $"{Name} ({GetType().Name})"; } - - /// - /// Check if Actors are equals - /// - /// - /// - /// - public static bool operator ==(Actor left, Actor right) - { - return Object.Equals(left, right); - } - - /// - /// Check if Actors aren't equals - /// - /// - /// - /// - public static bool operator !=(Actor left, Actor right) - { - return !Object.Equals(left, right); - } } } diff --git a/Source/Engine/Scripting/Object.cs b/Source/Engine/Scripting/Object.cs index 227fe99e6..e895b8199 100644 --- a/Source/Engine/Scripting/Object.cs +++ b/Source/Engine/Scripting/Object.cs @@ -205,6 +205,30 @@ namespace FlaxEngine return obj != null && obj.__unmanagedPtr != IntPtr.Zero; } + /// + /// + /// + /// + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator == (Object left, Object right) + { + return Object.Equals(left, right); + } + + /// + /// + /// + /// + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator !=(Object left, Object right) + { + return !Object.Equals(left, right); + } + /// /// Gets the pointer to the native object. Handles null object reference (returns zero). /// From c900b6525db3434bcfbaeb957732f15eac437ec5 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Sun, 30 Apr 2023 14:30:08 -0400 Subject: [PATCH 15/33] forgot to save the XD file --- Source/Engine/Scripting/Object.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Scripting/Object.cs b/Source/Engine/Scripting/Object.cs index e895b8199..ce7846d73 100644 --- a/Source/Engine/Scripting/Object.cs +++ b/Source/Engine/Scripting/Object.cs @@ -206,7 +206,7 @@ namespace FlaxEngine } /// - /// + /// Checks whether the two objects are equal. /// /// /// @@ -218,7 +218,7 @@ namespace FlaxEngine } /// - /// + /// Checks whether the two objects are not equal. /// /// /// From 518ce457dff817d080cdca14fe93e3aa72fa8b86 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Tue, 2 May 2023 08:56:18 -0400 Subject: [PATCH 16/33] fix doc --- Source/Editor/CustomEditors/Elements/ComboBoxElement.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/CustomEditors/Elements/ComboBoxElement.cs b/Source/Editor/CustomEditors/Elements/ComboBoxElement.cs index b9bda5985..3e3f34e07 100644 --- a/Source/Editor/CustomEditors/Elements/ComboBoxElement.cs +++ b/Source/Editor/CustomEditors/Elements/ComboBoxElement.cs @@ -6,7 +6,7 @@ using FlaxEngine.GUI; namespace FlaxEditor.CustomEditors.Elements { /// - /// The combobx element. + /// The combobox element. /// /// public class ComboBoxElement : LayoutElement From f0da221621fc531483a5d37f3bf816cf421c5e00 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Tue, 2 May 2023 21:44:00 -0500 Subject: [PATCH 17/33] Make the drag indicator between tree nodes a little brighter. --- Source/Editor/GUI/Tree/TreeNode.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/Editor/GUI/Tree/TreeNode.cs b/Source/Editor/GUI/Tree/TreeNode.cs index 8691cd14d..ced70a281 100644 --- a/Source/Editor/GUI/Tree/TreeNode.cs +++ b/Source/Editor/GUI/Tree/TreeNode.cs @@ -661,17 +661,20 @@ namespace FlaxEditor.GUI.Tree // Draw drag and drop effect if (IsDragOver && _tree.DraggedOverNode == this) { - Color dragOverColor = style.BackgroundSelected * 0.6f; + Color dragOverColor = style.BackgroundSelected; Rectangle rect; switch (_dragOverMode) { case DragItemPositioning.At: + dragOverColor *= 0.6f; rect = textRect; break; case DragItemPositioning.Above: + dragOverColor *= 1.2f; rect = new Rectangle(textRect.X, textRect.Top - DefaultDragInsertPositionMargin - DefaultNodeOffsetY - _margin.Top, textRect.Width, DefaultDragInsertPositionMargin * 2.0f); break; case DragItemPositioning.Below: + dragOverColor *= 1.2f; rect = new Rectangle(textRect.X, textRect.Bottom + _margin.Bottom - DefaultDragInsertPositionMargin, textRect.Width, DefaultDragInsertPositionMargin * 2.0f); break; default: From 144287ba1c4ea1c222eeae29e9dc2c02191cf943 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Wed, 3 May 2023 20:38:55 -0500 Subject: [PATCH 18/33] Add `Unload all but this scene` option to scene context menu to unload all of the active scenes except for the selected one. --- Source/Editor/Modules/SceneModule.cs | 36 ++++++++++++++++++++ Source/Editor/SceneGraph/Actors/SceneNode.cs | 7 ++++ 2 files changed, 43 insertions(+) diff --git a/Source/Editor/Modules/SceneModule.cs b/Source/Editor/Modules/SceneModule.cs index 4d1aee93e..0a51038ac 100644 --- a/Source/Editor/Modules/SceneModule.cs +++ b/Source/Editor/Modules/SceneModule.cs @@ -315,6 +315,42 @@ namespace FlaxEditor.Modules Editor.StateMachine.ChangingScenesState.UnloadScene(Level.Scenes); } + /// + /// Closes all of the scenes except for the specified scene (async). + /// + /// The scene to not close. + public void CloseAllScenesExcept(Scene scene) + { + // Check if cannot change scene now + if (!Editor.StateMachine.CurrentState.CanChangeScene) + return; + + var scenes = new List(); + foreach (var s in Level.Scenes) + { + if (s == scene) + continue; + scenes.Add(s); + } + + // In play-mode Editor mocks the level streaming script + if (Editor.IsPlayMode) + { + foreach (var s in scenes) + { + Level.UnloadSceneAsync(s); + } + return; + } + + // Ensure to save all pending changes + if (CheckSaveBeforeClose()) + return; + + // Unload scenes + Editor.StateMachine.ChangingScenesState.UnloadScene(scenes); + } + /// /// Show save before scene load/unload action. /// diff --git a/Source/Editor/SceneGraph/Actors/SceneNode.cs b/Source/Editor/SceneGraph/Actors/SceneNode.cs index df7a11b1a..0405e4fdf 100644 --- a/Source/Editor/SceneGraph/Actors/SceneNode.cs +++ b/Source/Editor/SceneGraph/Actors/SceneNode.cs @@ -77,6 +77,8 @@ namespace FlaxEditor.SceneGraph.Actors } contextMenu.AddButton("Save scene", OnSave).LinkTooltip("Saves this scene.").Enabled = IsEdited && !Editor.IsPlayMode; contextMenu.AddButton("Unload scene", OnUnload).LinkTooltip("Unloads this scene.").Enabled = Editor.Instance.StateMachine.CurrentState.CanChangeScene; + if (Level.ScenesCount > 1) + contextMenu.AddButton("Unload all but this scene", OnUnloadAllButSelectedScene).LinkTooltip("Unloads all of the active scenes except for the selected scene.").Enabled = Editor.Instance.StateMachine.CurrentState.CanChangeScene; base.OnContextMenu(contextMenu); } @@ -95,5 +97,10 @@ namespace FlaxEditor.SceneGraph.Actors { Editor.Instance.Scene.CloseScene(Scene); } + + private void OnUnloadAllButSelectedScene() + { + Editor.Instance.Scene.CloseAllScenesExcept(Scene); + } } } From 98a5985ce94764422ca040945e2e4ca33fa5e8f7 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Thu, 4 May 2023 11:03:39 -0500 Subject: [PATCH 19/33] Fix bug of the collection size changing while still editing or sliding the size box. --- Source/Editor/CustomEditors/Editors/CollectionEditor.cs | 2 +- Source/Editor/CustomEditors/Editors/DictionaryEditor.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Editor/CustomEditors/Editors/CollectionEditor.cs b/Source/Editor/CustomEditors/Editors/CollectionEditor.cs index 318dafcc6..8fe5fd5f2 100644 --- a/Source/Editor/CustomEditors/Editors/CollectionEditor.cs +++ b/Source/Editor/CustomEditors/Editors/CollectionEditor.cs @@ -145,7 +145,7 @@ namespace FlaxEditor.CustomEditors.Editors _size.IntValue.MinValue = 0; _size.IntValue.MaxValue = ushort.MaxValue; _size.IntValue.Value = size; - _size.IntValue.ValueChanged += OnSizeChanged; + _size.IntValue.EditEnd += OnSizeChanged; } // Elements diff --git a/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs b/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs index 7dd590576..1b9a7cca1 100644 --- a/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs +++ b/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs @@ -190,7 +190,7 @@ namespace FlaxEditor.CustomEditors.Editors _size.IntValue.MinValue = 0; _size.IntValue.MaxValue = _notNullItems ? size : ushort.MaxValue; _size.IntValue.Value = size; - _size.IntValue.ValueChanged += OnSizeChanged; + _size.IntValue.EditEnd += OnSizeChanged; } // Elements From 5e31a678bd678def61c3c9db527f157c719c7fbb Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 5 May 2023 10:49:07 +0200 Subject: [PATCH 20/33] Improve C# Object comparison by using native pointer compare #1061 #713 #795 --- .../CustomEditors/Values/ValueContainer.cs | 2 +- .../Editor/GUI/Timeline/Tracks/ActorTrack.cs | 2 +- Source/Engine/Scripting/Object.cs | 18 +++++++++++++++--- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Source/Editor/CustomEditors/Values/ValueContainer.cs b/Source/Editor/CustomEditors/Values/ValueContainer.cs index 61c223835..53af4387f 100644 --- a/Source/Editor/CustomEditors/Values/ValueContainer.cs +++ b/Source/Editor/CustomEditors/Values/ValueContainer.cs @@ -187,7 +187,7 @@ namespace FlaxEditor.CustomEditors { for (int i = 0; i < Count; i++) { - if (this[i] == referenceSceneObject) + if ((SceneObject)this[i] == referenceSceneObject) continue; if (this[i] == null || (this[i] is SceneObject valueSceneObject && valueSceneObject && valueSceneObject.PrefabObjectID != referenceSceneObject.PrefabObjectID)) diff --git a/Source/Editor/GUI/Timeline/Tracks/ActorTrack.cs b/Source/Editor/GUI/Timeline/Tracks/ActorTrack.cs index 9e51cc21a..eb3fa39b6 100644 --- a/Source/Editor/GUI/Timeline/Tracks/ActorTrack.cs +++ b/Source/Editor/GUI/Timeline/Tracks/ActorTrack.cs @@ -174,7 +174,7 @@ namespace FlaxEditor.GUI.Timeline.Tracks continue; // Prevent from adding the same track twice - if (SubTracks.Any(x => x is IObjectTrack y && y.Object == script)) + if (SubTracks.Any(x => x is IObjectTrack y && y.Object as SceneObject == script)) continue; var name = Utilities.Utils.GetPropertyNameUI(script.GetType().Name); diff --git a/Source/Engine/Scripting/Object.cs b/Source/Engine/Scripting/Object.cs index ce7846d73..bc1a4b1b5 100644 --- a/Source/Engine/Scripting/Object.cs +++ b/Source/Engine/Scripting/Object.cs @@ -212,9 +212,11 @@ namespace FlaxEngine /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator == (Object left, Object right) + public static bool operator ==(Object left, Object right) { - return Object.Equals(left, right); + IntPtr leftPtr = (object)left != null ? left.__unmanagedPtr : IntPtr.Zero; + IntPtr rightPtr = (object)right != null ? right.__unmanagedPtr : IntPtr.Zero; + return leftPtr == rightPtr; } /// @@ -226,7 +228,17 @@ namespace FlaxEngine [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool operator !=(Object left, Object right) { - return !Object.Equals(left, right); + IntPtr leftPtr = (object)left != null ? left.__unmanagedPtr : IntPtr.Zero; + IntPtr rightPtr = (object)right != null ? right.__unmanagedPtr : IntPtr.Zero; + return leftPtr != rightPtr; + } + + /// + public override bool Equals(object obj) + { + if (obj is FlaxEngine.Object o) + return o.__unmanagedPtr == __unmanagedPtr; + return false; } /// From 65a68131cc405f03750c5232df038fc168ad394e Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 5 May 2023 11:38:28 +0200 Subject: [PATCH 21/33] Improve name construction in #1038 --- Source/Editor/Content/Proxy/MaterialProxy.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Source/Editor/Content/Proxy/MaterialProxy.cs b/Source/Editor/Content/Proxy/MaterialProxy.cs index c6a9755fc..cf7c8b77e 100644 --- a/Source/Editor/Content/Proxy/MaterialProxy.cs +++ b/Source/Editor/Content/Proxy/MaterialProxy.cs @@ -72,10 +72,7 @@ namespace FlaxEditor.Content /// The material item to use as a base material. public static void CreateMaterialInstance(BinaryAssetItem materialItem) { - if (materialItem == null) - throw new ArgumentNullException(); - - var materialInstanceName = materialItem.FileName.Replace(".flax", " Instance"); + var materialInstanceName = materialItem.ShortName + " Instance"; var materialInstanceProxy = Editor.Instance.ContentDatabase.GetProxy(); Editor.Instance.Windows.ContentWin.NewItem(materialInstanceProxy, null, item => OnMaterialInstanceCreated(item, materialItem), materialInstanceName); } From 315df12fbe5b9b7e2908dbe1d3aeff37ad18430b Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 5 May 2023 14:34:32 +0200 Subject: [PATCH 22/33] Favor passing `Tag` as value since it's just `uint32` under the hood --- Source/Engine/Level/Tags.cpp | 4 ++-- Source/Engine/Level/Tags.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Engine/Level/Tags.cpp b/Source/Engine/Level/Tags.cpp index b9b3b1f79..7f287022f 100644 --- a/Source/Engine/Level/Tags.cpp +++ b/Source/Engine/Level/Tags.cpp @@ -55,7 +55,7 @@ Tag Tags::Get(const StringView& tagName) return tag; } -bool Tags::HasTag(const Array& list, const Tag& tag) +bool Tags::HasTag(const Array& list, const Tag tag) { if (tag.Index == 0) return false; @@ -69,7 +69,7 @@ bool Tags::HasTag(const Array& list, const Tag& tag) return false; } -bool Tags::HasTagExact(const Array& list, const Tag& tag) +bool Tags::HasTagExact(const Array& list, const Tag tag) { if (tag.Index == 0) return false; diff --git a/Source/Engine/Level/Tags.h b/Source/Engine/Level/Tags.h index 03b09a1fc..b15b5087f 100644 --- a/Source/Engine/Level/Tags.h +++ b/Source/Engine/Level/Tags.h @@ -99,7 +99,7 @@ public: /// The tags list to use. /// The tag to check. /// True if given tag is contained by the list of tags. Returns false for empty list. - static bool HasTag(const Array& list, const Tag& tag); + static bool HasTag(const Array& list, const Tag tag); /// /// Checks if the list of tags contains a given tag (exact match). For example, HasTag({"A.B"}, "A") returns false, for parents check use HasTag. @@ -107,7 +107,7 @@ public: /// The tags list to use. /// The tag to check. /// True if given tag is contained by the list of tags. Returns false for empty list. - static bool HasTagExact(const Array& list, const Tag& tag); + static bool HasTagExact(const Array& list, const Tag tag); /// /// Checks if the list of tags contains any of the given tags (including parent tags check). For example, HasAny({"A.B", "C"}, {"A"}) returns true, for exact check use HasAnyExact. From 37e8fa7b767916c764567a877c4af2803d4d5cb2 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 5 May 2023 14:54:42 +0200 Subject: [PATCH 23/33] Fix creating localization table on blank project #1060 --- .../CustomEditors/Dedicated/LocalizationSettingsEditor.cs | 5 ++++- Source/Editor/Windows/Assets/JsonAssetWindow.cs | 4 ++++ Source/Engine/Content/Content.cpp | 5 ----- Source/Engine/Content/JsonAsset.cs | 5 +++++ Source/Engine/Localization/LocalizedStringTable.cpp | 1 + 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Source/Editor/CustomEditors/Dedicated/LocalizationSettingsEditor.cs b/Source/Editor/CustomEditors/Dedicated/LocalizationSettingsEditor.cs index e784048af..071810ffa 100644 --- a/Source/Editor/CustomEditors/Dedicated/LocalizationSettingsEditor.cs +++ b/Source/Editor/CustomEditors/Dedicated/LocalizationSettingsEditor.cs @@ -145,7 +145,10 @@ namespace FlaxEditor.CustomEditors.Dedicated else { // No localization so initialize with empty table - var path = Path.Combine(Path.Combine(Path.GetDirectoryName(GameSettings.Load().Localization.Path), "Localization", culture.Name + ".json")); + var folder = Path.Combine(Path.GetDirectoryName(GameSettings.Load().Localization.Path), "Localization"); + if (!Directory.Exists(folder)) + Directory.CreateDirectory(folder); + var path = Path.Combine(Path.Combine(folder, culture.Name + ".json")); var table = FlaxEngine.Content.CreateVirtualAsset(); table.Locale = culture.Name; if (!table.Save(path)) diff --git a/Source/Editor/Windows/Assets/JsonAssetWindow.cs b/Source/Editor/Windows/Assets/JsonAssetWindow.cs index ecc68581c..e6606f35f 100644 --- a/Source/Editor/Windows/Assets/JsonAssetWindow.cs +++ b/Source/Editor/Windows/Assets/JsonAssetWindow.cs @@ -126,6 +126,10 @@ namespace FlaxEditor.Windows.Assets _presenter.NoSelectionText = "Failed to load asset. See log for more. " + ex.Message.Replace('\n', ' '); } } + else if (string.IsNullOrEmpty(dataTypeName)) + { + _presenter.NoSelectionText = "Empty data type."; + } else { _presenter.NoSelectionText = string.Format("Missing type '{0}'.", dataTypeName); diff --git a/Source/Engine/Content/Content.cpp b/Source/Engine/Content/Content.cpp index a30fa7b78..e58aa458d 100644 --- a/Source/Engine/Content/Content.cpp +++ b/Source/Engine/Content/Content.cpp @@ -1002,17 +1002,12 @@ Asset* Content::load(const Guid& id, const ScriptingTypeHandle& type, AssetInfo& } #if ASSETS_LOADING_EXTRA_VERIFICATION - - // Ensure we have valid asset info - ASSERT(assetInfo.TypeName.HasChars() && assetInfo.Path.HasChars()); - // Check if file exists if (!FileSystem::FileExists(assetInfo.Path)) { LOG(Error, "Cannot find file '{0}'", assetInfo.Path); return nullptr; } - #endif // Find asset factory based in its type diff --git a/Source/Engine/Content/JsonAsset.cs b/Source/Engine/Content/JsonAsset.cs index 3278a3377..afd83bafd 100644 --- a/Source/Engine/Content/JsonAsset.cs +++ b/Source/Engine/Content/JsonAsset.cs @@ -35,6 +35,11 @@ namespace FlaxEngine return null; var dataTypeName = DataTypeName; + if (string.IsNullOrEmpty(dataTypeName)) + { + Debug.LogError(string.Format("Missing typename of data in Json asset '{0}'.", Path), this); + return null; + } var assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { diff --git a/Source/Engine/Localization/LocalizedStringTable.cpp b/Source/Engine/Localization/LocalizedStringTable.cpp index 74c9b6774..e14328f89 100644 --- a/Source/Engine/Localization/LocalizedStringTable.cpp +++ b/Source/Engine/Localization/LocalizedStringTable.cpp @@ -15,6 +15,7 @@ REGISTER_JSON_ASSET(LocalizedStringTable, "FlaxEngine.LocalizedStringTable", tru LocalizedStringTable::LocalizedStringTable(const SpawnParams& params, const AssetInfo* info) : JsonAssetBase(params, info) { + DataTypeName = TypeName; } void LocalizedStringTable::AddString(const StringView& id, const StringView& value) From 285a824858670f9d52dc92327819a1b010169183 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 5 May 2023 15:08:53 +0200 Subject: [PATCH 24/33] Fix crash when removing particle emitter from system that has old parameter override #1044 --- Source/Engine/Particles/ParticleSystem.cpp | 31 +++++++--------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/Source/Engine/Particles/ParticleSystem.cpp b/Source/Engine/Particles/ParticleSystem.cpp index b04dfe0c0..6f63101b2 100644 --- a/Source/Engine/Particles/ParticleSystem.cpp +++ b/Source/Engine/Particles/ParticleSystem.cpp @@ -212,6 +212,12 @@ Asset::LoadResult ParticleSystem::load() int32 version; stream.ReadInt32(&version); +#if USE_EDITOR + // Skip unused parameters +#define SKIP_UNUSED_PARAM_OVERRIDE() if (key.First < 0 || key.First >= Emitters.Count() || Emitters[key.First] == nullptr || Emitters[key.First]->Graph.GetParameter(key.Second) == nullptr) continue +#else +#define SKIP_UNUSED_PARAM_OVERRIDE() +#endif switch (version) { case 1: @@ -281,13 +287,7 @@ Asset::LoadResult ParticleSystem::load() stream.ReadInt32(&key.First); stream.Read(key.Second); stream.ReadCommonValue(&value); - -#if USE_EDITOR - // Skip unused parameters - if (key.First < 0 || key.First >= Emitters.Count() || Emitters[key.First]->Graph.GetParameter(key.Second) == nullptr) - continue; -#endif - + SKIP_UNUSED_PARAM_OVERRIDE(); EmittersParametersOverrides.Add(key, Variant(value)); } } @@ -361,13 +361,7 @@ Asset::LoadResult ParticleSystem::load() stream.ReadInt32(&key.First); stream.Read(key.Second); stream.ReadCommonValue(&value); - -#if USE_EDITOR - // Skip unused parameters - if (key.First < 0 || key.First >= Emitters.Count() || Emitters[key.First]->Graph.GetParameter(key.Second) == nullptr) - continue; -#endif - + SKIP_UNUSED_PARAM_OVERRIDE(); EmittersParametersOverrides[key] = Variant(value); } } @@ -440,13 +434,7 @@ Asset::LoadResult ParticleSystem::load() stream.ReadInt32(&key.First); stream.Read(key.Second); stream.ReadVariant(&value); - -#if USE_EDITOR - // Skip unused parameters - if (key.First < 0 || key.First >= Emitters.Count() || Emitters[key.First]->Graph.GetParameter(key.Second) == nullptr) - continue; -#endif - + SKIP_UNUSED_PARAM_OVERRIDE(); EmittersParametersOverrides[key] = value; } } @@ -457,6 +445,7 @@ Asset::LoadResult ParticleSystem::load() LOG(Warning, "Unknown timeline version {0}.", version); return LoadResult::InvalidData; } +#undef SKIP_UNUSED_PARAM_OVERRIDE #if !BUILD_RELEASE _debugName = StringUtils::GetFileNameWithoutExtension(GetPath()); From 86044fcc05afddbfd487e925c2560e1d383e66d6 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 5 May 2023 08:17:07 -0500 Subject: [PATCH 25/33] Change logic for Random Rang particle nodes --- .../ParticleEmitterGraph.GPU.Particles.cpp | 24 +++++++++---------- Source/Engine/Visject/VisjectGraph.cpp | 16 ++++++------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Particles.cpp b/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Particles.cpp index 597c7695c..9b59ba5b9 100644 --- a/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Particles.cpp +++ b/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Particles.cpp @@ -388,33 +388,33 @@ void ParticleEmitterGPUGenerator::ProcessGroupParticles(Box* box, Node* node, Va // Random Float Range case 213: { - auto& a = node->Values[0].AsFloat; - auto& b = node->Values[1].AsFloat; - value = writeLocal(VariantType::Float, String::Format(TEXT("lerp({0}, {1}, RAND)"), a, b), node); + auto a = tryGetValue(node->GetBox(1), node->Values[0]).AsFloat(); + auto b = tryGetValue(node->GetBox(2), node->Values[1]).AsFloat(); + value = writeLocal(VariantType::Float, String::Format(TEXT("lerp({0}, {1}, RAND)"), a.Value, b.Value), node); break; } // Random Vector2 Range case 214: { - auto& a = node->Values[0].AsFloat2(); - auto& b = node->Values[1].AsFloat2(); - value = writeLocal(VariantType::Float2, String::Format(TEXT("float2(lerp({0}, {1}, RAND), lerp({2}, {3}, RAND))"), a.X, b.X, a.Y, b.Y), node); + auto a = tryGetValue(node->GetBox(1), node->Values[0]).AsFloat2(); + auto b = tryGetValue(node->GetBox(2), node->Values[1]).AsFloat2(); + value = writeLocal(VariantType::Float2, String::Format(TEXT("float2(lerp({0}.x, {1}.x, RAND), lerp({0}.y, {1}.y, RAND))"), a.Value, b.Value), node); break; } // Random Vector3 Range case 215: { - auto& a = node->Values[0].AsFloat3(); - auto& b = node->Values[1].AsFloat3(); - value = writeLocal(VariantType::Float3, String::Format(TEXT("float3(lerp({0}, {1}, RAND), lerp({2}, {3}, RAND), lerp({4}, {5}, RAND))"), a.X, b.X, a.Y, b.Y, a.Z, b.Z), node); + auto a = tryGetValue(node->GetBox(1), node->Values[0]).AsFloat3(); + auto b = tryGetValue(node->GetBox(2), node->Values[1]).AsFloat3(); + value = writeLocal(VariantType::Float3, String::Format(TEXT("float3(lerp({0}.x, {1}.x, RAND), lerp({0}.y, {1}.y, RAND), lerp({0}.z, {1}.z, RAND))"), a.Value, b.Value), node); break; } // Random Vector4 Range case 216: { - auto& a = node->Values[0].AsFloat4(); - auto& b = node->Values[1].AsFloat4(); - value = writeLocal(VariantType::Float4, String::Format(TEXT("float4(lerp({0}, {1}, RAND), lerp({2}, {3}, RAND), lerp({4}, {5}, RAND), lerp({6}, {7}, RAND))"), a.X, b.X, a.Y, b.Y, a.Z, b.Z, a.W, b.W), node); + auto a = tryGetValue(node->GetBox(1), node->Values[0]).AsFloat4(); + auto b = tryGetValue(node->GetBox(2), node->Values[1]).AsFloat4(); + value = writeLocal(VariantType::Float4, String::Format(TEXT("float4(lerp({0}.x, {1}.x, RAND), lerp({0}.y, {1}.y, RAND), lerp({0}.z, {1}.z, RAND), lerp({0}.w, {1}.w, RAND))"), a.Value, b.Value), node); break; } // Particle Emitter Function diff --git a/Source/Engine/Visject/VisjectGraph.cpp b/Source/Engine/Visject/VisjectGraph.cpp index 4e067e61c..5559cd713 100644 --- a/Source/Engine/Visject/VisjectGraph.cpp +++ b/Source/Engine/Visject/VisjectGraph.cpp @@ -1273,16 +1273,16 @@ void VisjectExecutor::ProcessGroupParticles(Box* box, Node* node, Value& value) // Random Float Range case 213: { - auto& a = node->Values[0].AsFloat; - auto& b = node->Values[1].AsFloat; + auto a = tryGetValue(node->GetBox(1), node->Values[0]).AsFloat; + auto b = tryGetValue(node->GetBox(2), node->Values[1]).AsFloat; value = Math::Lerp(a, b, RAND); break; } // Random Vector2 Range case 214: { - auto a = (Float2)node->Values[0]; - auto b = (Float2)node->Values[1]; + auto a = tryGetValue(node->GetBox(1), node->Values[0]).AsFloat2(); + auto b = tryGetValue(node->GetBox(2), node->Values[1]).AsFloat2(); value = Float2( Math::Lerp(a.X, b.X, RAND), Math::Lerp(a.Y, b.Y, RAND) @@ -1292,8 +1292,8 @@ void VisjectExecutor::ProcessGroupParticles(Box* box, Node* node, Value& value) // Random Vector3 Range case 215: { - auto a = (Float3)node->Values[0]; - auto b = (Float3)node->Values[1]; + auto a = tryGetValue(node->GetBox(1), node->Values[0]).AsFloat3(); + auto b = tryGetValue(node->GetBox(2), node->Values[1]).AsFloat3(); value = Float3( Math::Lerp(a.X, b.X, RAND), Math::Lerp(a.Y, b.Y, RAND), @@ -1304,8 +1304,8 @@ void VisjectExecutor::ProcessGroupParticles(Box* box, Node* node, Value& value) // Random Vector4 Range case 216: { - auto a = (Float4)node->Values[0]; - auto b = (Float4)node->Values[1]; + auto a = tryGetValue(node->GetBox(1), node->Values[0]).AsFloat4(); + auto b = tryGetValue(node->GetBox(2), node->Values[1]).AsFloat4(); value = Float4( Math::Lerp(a.X, b.X, RAND), Math::Lerp(a.Y, b.Y, RAND), From 95d798f49e8f94eeb3eca257d8e35c9532132531 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 5 May 2023 08:30:17 -0500 Subject: [PATCH 26/33] Standardize to changing the folder for any proxy that can not be created in the current view. --- Source/Editor/Content/Proxy/CollisionDataProxy.cs | 8 +------- Source/Editor/Windows/ContentWindow.cs | 5 +++++ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Source/Editor/Content/Proxy/CollisionDataProxy.cs b/Source/Editor/Content/Proxy/CollisionDataProxy.cs index e4a2381f0..55e8c6327 100644 --- a/Source/Editor/Content/Proxy/CollisionDataProxy.cs +++ b/Source/Editor/Content/Proxy/CollisionDataProxy.cs @@ -141,13 +141,7 @@ namespace FlaxEditor.Content }); }; var initialName = (modelItem?.ShortName ?? Path.GetFileNameWithoutExtension(model.Path)) + " Collision"; - - // If folder can not have assets then move to folder with the model and create asset - var contentWin = Editor.Instance.Windows.ContentWin; - if (!contentWin.CurrentViewFolder.CanHaveAssets) - contentWin.Navigate(modelItem?.ParentFolder?.Node); - - contentWin.NewItem(this, null, create, initialName, withRenaming); + Editor.Instance.Windows.ContentWin.NewItem(this, null, create, initialName, withRenaming); } } } diff --git a/Source/Editor/Windows/ContentWindow.cs b/Source/Editor/Windows/ContentWindow.cs index 43fd6b648..6a59cb218 100644 --- a/Source/Editor/Windows/ContentWindow.cs +++ b/Source/Editor/Windows/ContentWindow.cs @@ -656,6 +656,11 @@ namespace FlaxEditor.Windows throw new ArgumentNullException(nameof(proxy)); string name = initialName ?? proxy.NewItemName; + + // If the proxy can not be created in the current folder, then navigate to the content folder + if (!proxy.CanCreate(CurrentViewFolder)) + Navigate(Editor.Instance.ContentDatabase.Game.Content); + ContentFolder parentFolder = CurrentViewFolder; string parentFolderPath = parentFolder.Path; From 404340b02eaec549441f2d6858a904f1114fe778 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 5 May 2023 15:58:18 +0200 Subject: [PATCH 27/33] Improve #1025 --- Source/Editor/Editor.cs | 136 ++++++++++++++++++++-------------------- 1 file changed, 69 insertions(+), 67 deletions(-) diff --git a/Source/Editor/Editor.cs b/Source/Editor/Editor.cs index 498c8cbd9..2bf2a6922 100644 --- a/Source/Editor/Editor.cs +++ b/Source/Editor/Editor.cs @@ -307,6 +307,7 @@ namespace FlaxEditor _areModulesInited = true; // Preload initial scene asset + try { var startupSceneMode = Options.Options.General.StartupSceneMode; if (startupSceneMode == GeneralOptions.StartupSceneModes.LastOpened && !ProjectCache.HasCustomData(ProjectDataLastScene)) @@ -325,8 +326,8 @@ namespace FlaxEditor { if (ProjectCache.TryGetCustomData(ProjectDataLastScene, out var lastSceneIdName)) { - var lastSceneList = JsonSerializer.Deserialize(lastSceneIdName); - foreach (var scene in lastSceneList) + var lastScenes = JsonSerializer.Deserialize(lastSceneIdName); + foreach (var scene in lastScenes) { var lastScene = scene; Internal_LoadAsset(ref lastScene); @@ -336,6 +337,10 @@ namespace FlaxEditor } } } + catch (Exception ex) + { + // Ignore errors + } InitializationStart?.Invoke(); @@ -408,64 +413,69 @@ namespace FlaxEditor } // Load scene - - // scene cmd line argument - var scene = ContentDatabase.Find(_startupSceneCmdLine); - if (scene is SceneItem) + try { - Editor.Log("Loading scene specified in command line"); - Scene.OpenScene(_startupSceneCmdLine); - return; - } - - // if no scene cmd line argument is provided - var startupSceneMode = Options.Options.General.StartupSceneMode; - if (startupSceneMode == GeneralOptions.StartupSceneModes.LastOpened && !ProjectCache.HasCustomData(ProjectDataLastScene)) - { - // Fallback to default project scene if nothing saved in the cache - startupSceneMode = GeneralOptions.StartupSceneModes.ProjectDefault; - } - switch (startupSceneMode) - { - case GeneralOptions.StartupSceneModes.ProjectDefault: - { - if (string.IsNullOrEmpty(GameProject.DefaultScene)) - break; - JsonSerializer.ParseID(GameProject.DefaultScene, out var defaultSceneId); - var defaultScene = ContentDatabase.Find(defaultSceneId); - if (defaultScene is SceneItem) + // Scene cmd line argument + var scene = ContentDatabase.Find(_startupSceneCmdLine); + if (scene is SceneItem) { - Editor.Log("Loading default project scene"); - Scene.OpenScene(defaultSceneId); - - // Use spawn point - Windows.EditWin.Viewport.ViewRay = GameProject.DefaultSceneSpawn; + Editor.Log("Loading scene specified in command line"); + Scene.OpenScene(_startupSceneCmdLine); + return; } - break; - } - case GeneralOptions.StartupSceneModes.LastOpened: - { - if (ProjectCache.TryGetCustomData(ProjectDataLastScene, out var lastSceneIdName)) + var startupSceneMode = Options.Options.General.StartupSceneMode; + if (startupSceneMode == GeneralOptions.StartupSceneModes.LastOpened && !ProjectCache.HasCustomData(ProjectDataLastScene)) { - var lastSceneList = JsonSerializer.Deserialize(lastSceneIdName); - foreach (var sceneId in lastSceneList) + // Fallback to default project scene if nothing saved in the cache + startupSceneMode = GeneralOptions.StartupSceneModes.ProjectDefault; + } + switch (startupSceneMode) + { + case GeneralOptions.StartupSceneModes.ProjectDefault: + { + if (string.IsNullOrEmpty(GameProject.DefaultScene)) + break; + JsonSerializer.ParseID(GameProject.DefaultScene, out var defaultSceneId); + var defaultScene = ContentDatabase.Find(defaultSceneId); + if (defaultScene is SceneItem) { - var lastScene = ContentDatabase.Find(sceneId); - if (!(lastScene is SceneItem)) - continue; - - Editor.Log($"Loading last opened scene: {lastScene.ShortName}"); - if (sceneId == lastSceneList[0]) - Scene.OpenScene(sceneId); - else - Level.LoadSceneAsync(sceneId); + Editor.Log("Loading default project scene"); + Scene.OpenScene(defaultSceneId); + + // Use spawn point + Windows.EditWin.Viewport.ViewRay = GameProject.DefaultSceneSpawn; } - // Restore view - if (ProjectCache.TryGetCustomData(ProjectDataLastSceneSpawn, out var lastSceneSpawnName)) - Windows.EditWin.Viewport.ViewRay = JsonSerializer.Deserialize(lastSceneSpawnName); + break; + } + case GeneralOptions.StartupSceneModes.LastOpened: + { + if (ProjectCache.TryGetCustomData(ProjectDataLastScene, out var lastSceneIdName)) + { + var lastScenes = JsonSerializer.Deserialize(lastSceneIdName); + foreach (var sceneId in lastScenes) + { + var lastScene = ContentDatabase.Find(sceneId); + if (!(lastScene is SceneItem)) + continue; + + Editor.Log($"Loading last opened scene: {lastScene.ShortName}"); + if (sceneId == lastScenes[0]) + Scene.OpenScene(sceneId); + else + Level.LoadSceneAsync(sceneId); + } + + // Restore view + if (ProjectCache.TryGetCustomData(ProjectDataLastSceneSpawn, out var lastSceneSpawnName)) + Windows.EditWin.Viewport.ViewRay = JsonSerializer.Deserialize(lastSceneSpawnName); + } + break; + } } - break; } + catch (Exception ex) + { + // Ignore errors } } @@ -594,8 +604,8 @@ namespace FlaxEditor UI.UpdateStatusBar(); } - if (UI?.StatusBar?.Text != null && !UI.StatusBar.Text.Contains("Auto") && - _saveNowButton != null && _cancelSaveButton != null && + if (UI?.StatusBar?.Text != null && !UI.StatusBar.Text.Contains("Auto") && + _saveNowButton != null && _cancelSaveButton != null && (_saveNowButton.Visible || _cancelSaveButton.Visible)) { _saveNowButton.Visible = false; @@ -677,20 +687,12 @@ namespace FlaxEditor // Cache last opened scenes { - List lastSceneIds = new List(); - if (Level.ScenesCount > 0) - { - foreach (var scene in Level.Scenes) - { - lastSceneIds.Add(scene.ID); - } - } - else - { - lastSceneIds.Add(Guid.Empty); - } + var lastScenes = Level.Scenes; + var lastSceneIds = new Guid[lastScenes.Length]; + for (int i = 0; i < lastScenes.Length; i++) + lastSceneIds[i] = lastScenes[i].ID; var lastSceneSpawn = Windows.EditWin.Viewport.ViewRay; - ProjectCache.SetCustomData(ProjectDataLastScene, JsonSerializer.Serialize(lastSceneIds.ToArray())); + ProjectCache.SetCustomData(ProjectDataLastScene, JsonSerializer.Serialize(lastSceneIds)); ProjectCache.SetCustomData(ProjectDataLastSceneSpawn, JsonSerializer.Serialize(lastSceneSpawn)); } From 5d2a3482c770abb9ee522d6bd39dce1a62f77cfc Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 5 May 2023 16:10:09 +0200 Subject: [PATCH 28/33] Reduce compilation problems by moving `FindObject` fwd decl to be more commonly included #1040 --- Source/Engine/Scripting/ScriptingObject.h | 2 ++ Source/Engine/Serialization/ReadStream.h | 2 -- Source/Engine/Serialization/Serialization.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Engine/Scripting/ScriptingObject.h b/Source/Engine/Scripting/ScriptingObject.h index 5682f2409..183e23297 100644 --- a/Source/Engine/Scripting/ScriptingObject.h +++ b/Source/Engine/Scripting/ScriptingObject.h @@ -267,3 +267,5 @@ API_CLASS(InBuild) class FLAXENGINE_API PersistentScriptingObject : public Scrip public: PersistentScriptingObject(const SpawnParams& params); }; + +extern FLAXENGINE_API class ScriptingObject* FindObject(const Guid& id, class MClass* type); diff --git a/Source/Engine/Serialization/ReadStream.h b/Source/Engine/Serialization/ReadStream.h index 69e86fa4b..37f8b8433 100644 --- a/Source/Engine/Serialization/ReadStream.h +++ b/Source/Engine/Serialization/ReadStream.h @@ -5,8 +5,6 @@ #include "Stream.h" #include "Engine/Core/Templates.h" -extern FLAXENGINE_API class ScriptingObject* FindObject(const Guid& id, class MClass* type); - /// /// Base class for all data read streams /// diff --git a/Source/Engine/Serialization/Serialization.h b/Source/Engine/Serialization/Serialization.h index 7543f8241..182ac71cf 100644 --- a/Source/Engine/Serialization/Serialization.h +++ b/Source/Engine/Serialization/Serialization.h @@ -456,7 +456,7 @@ namespace Serialization Guid id; Deserialize(stream, id, modifier); modifier->IdsMapping.TryGet(id, id); - v = (T*)FindObject(id, T::GetStaticClass()); + v = (T*)::FindObject(id, T::GetStaticClass()); } // Scripting Object Reference From 68151592a46491143fe0d239f31c0277ba2adf3f Mon Sep 17 00:00:00 2001 From: Wiktor Kocielski Date: Sat, 22 Apr 2023 20:58:26 +0300 Subject: [PATCH 29/33] Make Level class to unload scenes in reversed order --- Source/Engine/Level/Level.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/Engine/Level/Level.cpp b/Source/Engine/Level/Level.cpp index 4d81886a8..f869c058f 100644 --- a/Source/Engine/Level/Level.cpp +++ b/Source/Engine/Level/Level.cpp @@ -903,12 +903,11 @@ bool LevelImpl::unloadScene(Scene* scene) bool LevelImpl::unloadScenes() { auto scenes = Level::Scenes; - for (int32 i = 0; i < scenes.Count(); i++) + for (int32 i = scenes.Count() - 1; i >= 0; i--) { if (unloadScene(scenes[i])) return true; } - return false; } From 12a2a69ad7987711df0e80ef8569244ad559bbe1 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 5 May 2023 09:18:44 -0500 Subject: [PATCH 30/33] Change to `TryGetBox` --- .../GPU/ParticleEmitterGraph.GPU.Particles.cpp | 16 ++++++++-------- Source/Engine/Visject/VisjectGraph.cpp | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Particles.cpp b/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Particles.cpp index 9b59ba5b9..905d1a11c 100644 --- a/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Particles.cpp +++ b/Source/Engine/Particles/Graph/GPU/ParticleEmitterGraph.GPU.Particles.cpp @@ -388,32 +388,32 @@ void ParticleEmitterGPUGenerator::ProcessGroupParticles(Box* box, Node* node, Va // Random Float Range case 213: { - auto a = tryGetValue(node->GetBox(1), node->Values[0]).AsFloat(); - auto b = tryGetValue(node->GetBox(2), node->Values[1]).AsFloat(); + auto a = tryGetValue(node->TryGetBox(1), node->Values[0]).AsFloat(); + auto b = tryGetValue(node->TryGetBox(2), node->Values[1]).AsFloat(); value = writeLocal(VariantType::Float, String::Format(TEXT("lerp({0}, {1}, RAND)"), a.Value, b.Value), node); break; } // Random Vector2 Range case 214: { - auto a = tryGetValue(node->GetBox(1), node->Values[0]).AsFloat2(); - auto b = tryGetValue(node->GetBox(2), node->Values[1]).AsFloat2(); + auto a = tryGetValue(node->TryGetBox(1), node->Values[0]).AsFloat2(); + auto b = tryGetValue(node->TryGetBox(2), node->Values[1]).AsFloat2(); value = writeLocal(VariantType::Float2, String::Format(TEXT("float2(lerp({0}.x, {1}.x, RAND), lerp({0}.y, {1}.y, RAND))"), a.Value, b.Value), node); break; } // Random Vector3 Range case 215: { - auto a = tryGetValue(node->GetBox(1), node->Values[0]).AsFloat3(); - auto b = tryGetValue(node->GetBox(2), node->Values[1]).AsFloat3(); + auto a = tryGetValue(node->TryGetBox(1), node->Values[0]).AsFloat3(); + auto b = tryGetValue(node->TryGetBox(2), node->Values[1]).AsFloat3(); value = writeLocal(VariantType::Float3, String::Format(TEXT("float3(lerp({0}.x, {1}.x, RAND), lerp({0}.y, {1}.y, RAND), lerp({0}.z, {1}.z, RAND))"), a.Value, b.Value), node); break; } // Random Vector4 Range case 216: { - auto a = tryGetValue(node->GetBox(1), node->Values[0]).AsFloat4(); - auto b = tryGetValue(node->GetBox(2), node->Values[1]).AsFloat4(); + auto a = tryGetValue(node->TryGetBox(1), node->Values[0]).AsFloat4(); + auto b = tryGetValue(node->TryGetBox(2), node->Values[1]).AsFloat4(); value = writeLocal(VariantType::Float4, String::Format(TEXT("float4(lerp({0}.x, {1}.x, RAND), lerp({0}.y, {1}.y, RAND), lerp({0}.z, {1}.z, RAND), lerp({0}.w, {1}.w, RAND))"), a.Value, b.Value), node); break; } diff --git a/Source/Engine/Visject/VisjectGraph.cpp b/Source/Engine/Visject/VisjectGraph.cpp index 5559cd713..4aac619af 100644 --- a/Source/Engine/Visject/VisjectGraph.cpp +++ b/Source/Engine/Visject/VisjectGraph.cpp @@ -1273,16 +1273,16 @@ void VisjectExecutor::ProcessGroupParticles(Box* box, Node* node, Value& value) // Random Float Range case 213: { - auto a = tryGetValue(node->GetBox(1), node->Values[0]).AsFloat; - auto b = tryGetValue(node->GetBox(2), node->Values[1]).AsFloat; + auto a = tryGetValue(node->TryGetBox(1), node->Values[0]).AsFloat; + auto b = tryGetValue(node->TryGetBox(2), node->Values[1]).AsFloat; value = Math::Lerp(a, b, RAND); break; } // Random Vector2 Range case 214: { - auto a = tryGetValue(node->GetBox(1), node->Values[0]).AsFloat2(); - auto b = tryGetValue(node->GetBox(2), node->Values[1]).AsFloat2(); + auto a = tryGetValue(node->TryGetBox(1), node->Values[0]).AsFloat2(); + auto b = tryGetValue(node->TryGetBox(2), node->Values[1]).AsFloat2(); value = Float2( Math::Lerp(a.X, b.X, RAND), Math::Lerp(a.Y, b.Y, RAND) @@ -1292,8 +1292,8 @@ void VisjectExecutor::ProcessGroupParticles(Box* box, Node* node, Value& value) // Random Vector3 Range case 215: { - auto a = tryGetValue(node->GetBox(1), node->Values[0]).AsFloat3(); - auto b = tryGetValue(node->GetBox(2), node->Values[1]).AsFloat3(); + auto a = tryGetValue(node->TryGetBox(1), node->Values[0]).AsFloat3(); + auto b = tryGetValue(node->TryGetBox(2), node->Values[1]).AsFloat3(); value = Float3( Math::Lerp(a.X, b.X, RAND), Math::Lerp(a.Y, b.Y, RAND), @@ -1304,8 +1304,8 @@ void VisjectExecutor::ProcessGroupParticles(Box* box, Node* node, Value& value) // Random Vector4 Range case 216: { - auto a = tryGetValue(node->GetBox(1), node->Values[0]).AsFloat4(); - auto b = tryGetValue(node->GetBox(2), node->Values[1]).AsFloat4(); + auto a = tryGetValue(node->TryGetBox(1), node->Values[0]).AsFloat4(); + auto b = tryGetValue(node->TryGetBox(2), node->Values[1]).AsFloat4(); value = Float4( Math::Lerp(a.X, b.X, RAND), Math::Lerp(a.Y, b.Y, RAND), From dee445c32c9c8a203fa3dcca4a1f8c87ece5d102 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 5 May 2023 16:27:57 +0200 Subject: [PATCH 31/33] Fix compilation warnings --- Source/Editor/Editor.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Source/Editor/Editor.cs b/Source/Editor/Editor.cs index 2bf2a6922..67d89786d 100644 --- a/Source/Editor/Editor.cs +++ b/Source/Editor/Editor.cs @@ -9,7 +9,6 @@ using FlaxEditor.Content; using FlaxEditor.Content.Import; using FlaxEditor.Content.Settings; using FlaxEditor.Content.Thumbnails; -using FlaxEditor.GUI; using FlaxEditor.Modules; using FlaxEditor.Modules.SourceCodeEditing; using FlaxEditor.Options; @@ -337,7 +336,7 @@ namespace FlaxEditor } } } - catch (Exception ex) + catch (Exception) { // Ignore errors } @@ -473,7 +472,7 @@ namespace FlaxEditor } } } - catch (Exception ex) + catch (Exception) { // Ignore errors } From 2affebd3753c5d7fa7c68c8d5d6e36ea7e4cbbb8 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 6 May 2023 14:57:44 +0200 Subject: [PATCH 32/33] Fix C# serialization of scene objects when property throws and exception #88 --- Source/Engine/Serialization/JsonConverters.cs | 2 +- Source/Engine/Serialization/JsonSerializer.cs | 127 ++++++++++++------ 2 files changed, 85 insertions(+), 44 deletions(-) diff --git a/Source/Engine/Serialization/JsonConverters.cs b/Source/Engine/Serialization/JsonConverters.cs index 3bb0f8a89..07388a09b 100644 --- a/Source/Engine/Serialization/JsonConverters.cs +++ b/Source/Engine/Serialization/JsonConverters.cs @@ -37,7 +37,7 @@ namespace FlaxEngine.Json { // Skip serialization as reference id for the root object serialization (eg. Script) var cache = JsonSerializer.Current.Value; - if (cache != null && cache.IsDuringSerialization && cache.SerializerWriter.SerializeStackSize == 0) + if (cache != null && cache.IsWriting && cache.SerializerWriter.SerializeStackSize == 0) { return false; } diff --git a/Source/Engine/Serialization/JsonSerializer.cs b/Source/Engine/Serialization/JsonSerializer.cs index 8dad82d64..d988b307c 100644 --- a/Source/Engine/Serialization/JsonSerializer.cs +++ b/Source/Engine/Serialization/JsonSerializer.cs @@ -26,7 +26,8 @@ namespace FlaxEngine.Json public JsonSerializerInternalWriter SerializerWriter; public UnmanagedMemoryStream MemoryStream; public StreamReader Reader; - public bool IsDuringSerialization; + public bool IsWriting; + public bool IsReading; public unsafe SerializerCache(JsonSerializerSettings settings) { @@ -50,6 +51,49 @@ namespace FlaxEngine.Json DateFormatString = JsonSerializer.DateFormatString, }; } + + public void ReadBegin() + { + if (IsReading) + { + // TODO: Reset reading state (eg if previous deserialization got exception) + } + IsWriting = false; + IsReading = true; + } + + public void ReadEnd() + { + IsReading = false; + } + + public void WriteBegin() + { + if (IsWriting) + { + // Reset writing state (eg if previous serialization got exception) + JsonWriter = new JsonTextWriter(StringWriter) + { + IndentChar = '\t', + Indentation = 1, + Formatting = JsonSerializer.Formatting, + DateFormatHandling = JsonSerializer.DateFormatHandling, + DateTimeZoneHandling = JsonSerializer.DateTimeZoneHandling, + FloatFormatHandling = JsonSerializer.FloatFormatHandling, + StringEscapeHandling = JsonSerializer.StringEscapeHandling, + Culture = JsonSerializer.Culture, + DateFormatString = JsonSerializer.DateFormatString, + }; + } + StringBuilder.Clear(); + IsWriting = true; + IsReading = false; + } + + public void WriteEnd() + { + IsWriting = false; + } } internal static JsonSerializerSettings Settings = CreateDefaultSettings(false); @@ -122,9 +166,9 @@ namespace FlaxEngine.Json var cache = isManagedOnly ? CacheManagedOnly.Value : Cache.Value; Current.Value = cache; - cache.StringBuilder.Clear(); - cache.IsDuringSerialization = true; + cache.WriteBegin(); cache.SerializerWriter.Serialize(cache.JsonWriter, obj, type); + cache.WriteEnd(); return cache.StringBuilder.ToString(); } @@ -141,9 +185,9 @@ namespace FlaxEngine.Json var cache = isManagedOnly ? CacheManagedOnly.Value : Cache.Value; Current.Value = cache; - cache.StringBuilder.Clear(); - cache.IsDuringSerialization = true; + cache.WriteBegin(); cache.SerializerWriter.Serialize(cache.JsonWriter, obj, type); + cache.WriteEnd(); return cache.StringBuilder.ToString(); } @@ -161,9 +205,9 @@ namespace FlaxEngine.Json var cache = isManagedOnly ? CacheManagedOnly.Value : Cache.Value; Current.Value = cache; - cache.StringBuilder.Clear(); - cache.IsDuringSerialization = true; + cache.WriteBegin(); cache.SerializerWriter.SerializeDiff(cache.JsonWriter, obj, type, other); + cache.WriteEnd(); return cache.StringBuilder.ToString(); } @@ -176,21 +220,20 @@ namespace FlaxEngine.Json public static void Deserialize(object input, string json) { var cache = Cache.Value; - cache.IsDuringSerialization = false; - Current.Value = cache; - + cache.ReadBegin(); using (JsonReader reader = new JsonTextReader(new StringReader(json))) { cache.JsonSerializer.Populate(reader, input); - - if (!cache.JsonSerializer.CheckAdditionalContent) - return; - while (reader.Read()) + if (cache.JsonSerializer.CheckAdditionalContent) { - if (reader.TokenType != JsonToken.Comment) - throw new Exception("Additional text found in JSON string after finishing deserializing object."); + while (reader.Read()) + { + if (reader.TokenType != JsonToken.Comment) + throw new Exception("Additional text found in JSON string after finishing deserializing object."); + } } } + cache.ReadEnd(); } /// @@ -214,22 +257,20 @@ namespace FlaxEngine.Json { object result; var cache = Cache.Value; - cache.IsDuringSerialization = false; - Current.Value = cache; - + cache.ReadBegin(); using (JsonReader reader = new JsonTextReader(new StringReader(json))) { result = cache.JsonSerializer.Deserialize(reader, objectType); - - if (!cache.JsonSerializer.CheckAdditionalContent) - return result; - while (reader.Read()) + if (cache.JsonSerializer.CheckAdditionalContent) { - if (reader.TokenType != JsonToken.Comment) - throw new Exception("Additional text found in JSON string after finishing deserializing object."); + while (reader.Read()) + { + if (reader.TokenType != JsonToken.Comment) + throw new Exception("Additional text found in JSON string after finishing deserializing object."); + } } } - + cache.ReadEnd(); return result; } @@ -242,22 +283,21 @@ namespace FlaxEngine.Json { object result; var cache = Cache.Value; - cache.IsDuringSerialization = false; - Current.Value = cache; - + cache.ReadBegin(); using (JsonReader reader = new JsonTextReader(new StringReader(json))) { result = cache.JsonSerializer.Deserialize(reader); - if (!cache.JsonSerializer.CheckAdditionalContent) - return result; - while (reader.Read()) + if (cache.JsonSerializer.CheckAdditionalContent) { - if (reader.TokenType != JsonToken.Comment) - throw new Exception("Additional text found in JSON string after finishing deserializing object."); + while (reader.Read()) + { + if (reader.TokenType != JsonToken.Comment) + throw new Exception("Additional text found in JSON string after finishing deserializing object."); + } } } - + cache.ReadEnd(); return result; } @@ -270,8 +310,7 @@ namespace FlaxEngine.Json public static unsafe void Deserialize(object input, byte* jsonBuffer, int jsonLength) { var cache = Cache.Value; - cache.IsDuringSerialization = false; - Current.Value = cache; + cache.ReadBegin(); /*// Debug json string reading cache.MemoryStream.Initialize(jsonBuffer, jsonLength); @@ -291,14 +330,16 @@ namespace FlaxEngine.Json { cache.JsonSerializer.Populate(jsonReader, input); } - - if (!cache.JsonSerializer.CheckAdditionalContent) - return; - while (jsonReader.Read()) + if (cache.JsonSerializer.CheckAdditionalContent) { - if (jsonReader.TokenType != JsonToken.Comment) - throw new Exception("Additional text found in JSON string after finishing deserializing object."); + while (jsonReader.Read()) + { + if (jsonReader.TokenType != JsonToken.Comment) + throw new Exception("Additional text found in JSON string after finishing deserializing object."); + } } + + cache.ReadEnd(); } /// From 10bab59acc9c5850abae116e7ad0904b36cc07f6 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 6 May 2023 14:58:10 +0200 Subject: [PATCH 33/33] Fix scene asset runtime contents when saving scene file in Editor --- Source/Engine/Level/Level.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Source/Engine/Level/Level.cpp b/Source/Engine/Level/Level.cpp index f869c058f..4fa37c80d 100644 --- a/Source/Engine/Level/Level.cpp +++ b/Source/Engine/Level/Level.cpp @@ -1209,6 +1209,15 @@ bool LevelImpl::saveScene(Scene* scene, const String& path) LOG(Info, "Scene saved! Time {0} ms", Math::CeilToInt((float)(DateTime::NowUTC() - startTime).GetTotalMilliseconds())); +#if USE_EDITOR + // Reload asset at the target location if is loaded + Asset* asset = Content::GetAsset(sceneId); + if (!asset) + asset = Content::GetAsset(path); + if (asset) + asset->Reload(); +#endif + // Fire event CallSceneEvent(SceneEventType::OnSceneSaved, scene, sceneId);