diff --git a/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs b/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs
index 0b975f912..1f5eddc75 100644
--- a/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/UIControlEditor.cs
@@ -655,7 +655,9 @@ namespace FlaxEditor.CustomEditors.Dedicated
if (uiControl.Name.StartsWith(previousName))
{
string newName = controlType.Name + uiControl.Name.Substring(previousName.Length);
- uiControl.Name = Utilities.Utils.IncrementNameNumber(newName, x => uiControl.Parent.GetChild(x) == null);
+ if (uiControl.Parent != null)
+ newName = Utilities.Utils.IncrementNameNumber(newName, x => uiControl.Parent.GetChild(x) == null);
+ uiControl.Name = newName;
}
}
diff --git a/Source/Editor/Editor.cs b/Source/Editor/Editor.cs
index e3c71fba8..6ad621a7a 100644
--- a/Source/Editor/Editor.cs
+++ b/Source/Editor/Editor.cs
@@ -358,11 +358,19 @@ namespace FlaxEditor
{
// Check if prefab root control is this UIControl
var loadingPreview = Viewport.Previews.PrefabPreview.LoadingPreview;
- if (loadingPreview != null)
+ var activePreviews = Viewport.Previews.PrefabPreview.ActivePreviews;
+ if (activePreviews != null)
{
- // Link it to the prefab preview to see it in the editor
- loadingPreview.customControlLinked = control;
- return loadingPreview;
+ foreach (var preview in activePreviews)
+ {
+ if (preview == loadingPreview ||
+ (preview.Instance != null && (preview.Instance == control || preview.Instance.HasActorInHierarchy(control))))
+ {
+ // Link it to the prefab preview to see it in the editor
+ preview.customControlLinked = control;
+ return preview;
+ }
+ }
}
return null;
}
diff --git a/Source/Editor/Viewport/Previews/PrefabPreview.cs b/Source/Editor/Viewport/Previews/PrefabPreview.cs
index b02cd6f4a..514a3e50b 100644
--- a/Source/Editor/Viewport/Previews/PrefabPreview.cs
+++ b/Source/Editor/Viewport/Previews/PrefabPreview.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
+using System.Collections.Generic;
using FlaxEngine;
using Object = FlaxEngine.Object;
@@ -13,10 +14,15 @@ namespace FlaxEditor.Viewport.Previews
public class PrefabPreview : AssetPreview
{
///
- /// The preview that is during prefab instance spawning. Used to link some actors such as UIControl to preview scene and view.
+ /// The currently spawned prefab instance owner. Used to link some actors such as UIControl to preview scene and view.
///
internal static PrefabPreview LoadingPreview;
+ ///
+ /// The list of active prefab previews. Used to link some actors such as UIControl to preview scene and view.
+ ///
+ internal static List ActivePreviews;
+
private Prefab _prefab;
private Actor _instance;
internal UIControl customControlLinked;
@@ -48,13 +54,13 @@ namespace FlaxEditor.Viewport.Previews
_prefab.WaitForLoaded();
// Spawn prefab
- var prevPreview = LoadingPreview;
LoadingPreview = this;
var instance = PrefabManager.SpawnPrefab(_prefab, null);
- LoadingPreview = prevPreview;
+ LoadingPreview = null;
if (instance == null)
{
_prefab = null;
+ ActivePreviews.Remove(this);
throw new Exception("Failed to spawn a prefab for the preview.");
}
@@ -120,6 +126,9 @@ namespace FlaxEditor.Viewport.Previews
public PrefabPreview(bool useWidgets)
: base(useWidgets)
{
+ if (ActivePreviews == null)
+ ActivePreviews = new List();
+ ActivePreviews.Add(this);
}
///
@@ -137,6 +146,7 @@ namespace FlaxEditor.Viewport.Previews
///
public override void OnDestroy()
{
+ ActivePreviews.Remove(this);
Prefab = null;
base.OnDestroy();
diff --git a/Source/Editor/Windows/Profiler/CPU.cs b/Source/Editor/Windows/Profiler/CPU.cs
index d10646da0..36fbf21f4 100644
--- a/Source/Editor/Windows/Profiler/CPU.cs
+++ b/Source/Editor/Windows/Profiler/CPU.cs
@@ -197,7 +197,7 @@ namespace FlaxEditor.Windows.Profiler
if (_tableRowsCache == null)
_tableRowsCache = new List();
- var viewRange = GetEventsViewRange();
+ var viewRange = _showOnlyLastUpdateEvents ? GetMainThreadUpdateRange() : ViewRange.Full;
UpdateTimeline(ref viewRange);
UpdateTable(ref viewRange);
}
@@ -235,36 +235,27 @@ namespace FlaxEditor.Windows.Profiler
}
}
- private ViewRange GetEventsViewRange()
+ private ViewRange GetMainThreadUpdateRange()
{
- if (_showOnlyLastUpdateEvents)
+ if (_events != null && _events.Count != 0)
{
- // Find root event named 'Update' and use it as a view range
- if (_events != null && _events.Count != 0)
+ var threads = _events.Get(_mainChart.SelectedSampleIndex);
+ if (threads != null)
{
- var data = _events.Get(_mainChart.SelectedSampleIndex);
- if (data != null)
+ for (int j = 0; j < threads.Length; j++)
{
- for (int j = 0; j < data.Length; j++)
+ var thread = threads[j];
+ if (thread.Name != "Main" || thread.Events == null)
+ continue;
+ for (int i = 0; i < thread.Events.Length; i++)
{
- var events = data[j].Events;
- if (events == null)
- continue;
-
- for (int i = 0; i < events.Length; i++)
- {
- var e = events[i];
-
- if (e.Depth == 0 && e.Name == "Update")
- {
- return new ViewRange(ref e);
- }
- }
+ ref var e = ref thread.Events[i];
+ if (e.Depth == 0 && e.Name == "Update")
+ return new ViewRange(ref e);
}
}
}
}
-
return ViewRange.Full;
}
@@ -352,13 +343,28 @@ namespace FlaxEditor.Windows.Profiler
// Find the first event start time (for the timeline start time)
double startTime = double.MaxValue;
- for (int i = 0; i < data.Length; i++)
+ if (viewRange.Start > 0)
{
- if (data[i].Events != null && data[i].Events.Length != 0)
- startTime = Math.Min(startTime, data[i].Events[0].Start);
+ startTime = viewRange.Start;
+ }
+ else
+ {
+ var r = GetMainThreadUpdateRange();
+ if (r.Start > 0)
+ {
+ startTime = r.Start;
+ }
+ else
+ {
+ for (int i = 0; i < data.Length; i++)
+ {
+ if (data[i].Events != null && data[i].Events.Length != 0)
+ startTime = Math.Min(startTime, data[i].Events[0].Start);
+ }
+ if (startTime >= double.MaxValue)
+ return 0;
+ }
}
- if (startTime >= double.MaxValue)
- return 0;
var container = _timeline.EventsContainer;
diff --git a/Source/Engine/Content/Asset.h b/Source/Engine/Content/Asset.h
index b48219573..2d2ba4b3f 100644
--- a/Source/Engine/Content/Asset.h
+++ b/Source/Engine/Content/Asset.h
@@ -25,7 +25,7 @@ API_CLASS(Abstract, NoSpawn) class FLAXENGINE_API Asset : public ManagedScriptin
{
DECLARE_SCRIPTING_TYPE_NO_SPAWN(Asset);
friend Content;
- friend class LoadAssetTask;
+ friend LoadAssetTask;
friend class ContentService;
public:
///
diff --git a/Source/Engine/Content/Loading/Tasks/LoadAssetTask.h b/Source/Engine/Content/Loading/Tasks/LoadAssetTask.h
index 911f44226..5ee384769 100644
--- a/Source/Engine/Content/Loading/Tasks/LoadAssetTask.h
+++ b/Source/Engine/Content/Loading/Tasks/LoadAssetTask.h
@@ -69,9 +69,24 @@ protected:
return Result::Ok;
}
+ void OnFail() override
+ {
+ if (Asset)
+ {
+ Asset->_loadingTask = nullptr;
+ Asset = nullptr;
+ }
+
+ // Base
+ ContentLoadTask::OnFail();
+ }
void OnEnd() override
{
- Asset = nullptr;
+ if (Asset)
+ {
+ Asset->_loadingTask = nullptr;
+ Asset = nullptr;
+ }
// Base
ContentLoadTask::OnEnd();
diff --git a/Source/Engine/Content/Types.h b/Source/Engine/Content/Types.h
index a64162501..c62a029e0 100644
--- a/Source/Engine/Content/Types.h
+++ b/Source/Engine/Content/Types.h
@@ -7,5 +7,6 @@ struct AssetInfo;
class Content;
class Asset;
class ContentLoadTask;
+class LoadAssetTask;
template
class AssetReference;
diff --git a/Source/Engine/Platform/Linux/LinuxPlatform.cpp b/Source/Engine/Platform/Linux/LinuxPlatform.cpp
index cdd7800f7..23267b193 100644
--- a/Source/Engine/Platform/Linux/LinuxPlatform.cpp
+++ b/Source/Engine/Platform/Linux/LinuxPlatform.cpp
@@ -2048,12 +2048,12 @@ bool LinuxPlatform::Init()
// Get user locale string
setlocale(LC_ALL, "");
const char* locale = setlocale(LC_CTYPE, NULL);
- if (strcmp(locale, "C") == 0)
- locale = "";
UserLocale = String(locale);
if (UserLocale.FindLast('.') != -1)
UserLocale = UserLocale.Left(UserLocale.Find('.'));
UserLocale.Replace('_', '-');
+ if (UserLocale == TEXT("C"))
+ UserLocale = TEXT("en");
// Get computer name string
gethostname(buffer, UNIX_APP_BUFF_SIZE);
diff --git a/Source/Engine/Profiler/ProfilerCPU.cpp b/Source/Engine/Profiler/ProfilerCPU.cpp
index 0198ed7bc..417178747 100644
--- a/Source/Engine/Profiler/ProfilerCPU.cpp
+++ b/Source/Engine/Profiler/ProfilerCPU.cpp
@@ -24,7 +24,7 @@ ProfilerCPU::EventBuffer::~EventBuffer()
DeleteArray(_data, _capacity);
}
-void ProfilerCPU::EventBuffer::Extract(Array& data, bool withRemove)
+void ProfilerCPU::EventBuffer::Extract(Array& data, bool withRemoval)
{
data.Clear();
@@ -36,6 +36,13 @@ void ProfilerCPU::EventBuffer::Extract(Array& data, bool withRemove)
if (count == 0)
return;
+ // Fix iterators when buffer is full (begin == end)
+ if (count == capacity)
+ {
+ _count--;
+ count--;
+ }
+
// Find the first item (skip non-root events)
Iterator firstEvent = Begin();
for (auto i = firstEvent; i.IsNotEnd(); ++i)
@@ -55,7 +62,7 @@ void ProfilerCPU::EventBuffer::Extract(Array& data, bool withRemove)
Iterator lastEndedRoot = End();
for (auto i = Last(); i != firstEvent; --i)
{
- if (i.Event().Depth == 0 && i.Event().End != 0)
+ if (i.Event().Depth == 0 && i.Event().End > 0)
{
lastEndedRoot = i;
break;
@@ -71,31 +78,27 @@ void ProfilerCPU::EventBuffer::Extract(Array& data, bool withRemove)
const double lastRootEventEndTime = lastEndedRoot.Event().End;
for (auto i = --End(); i != lastEndedRoot; --i)
{
- if (i.Event().End != 0 && i.Event().End <= lastRootEventEndTime)
+ if (i.Event().End > 0 && i.Event().End <= lastRootEventEndTime)
{
lastEvent = i;
break;
}
}
- if (withRemove)
+ if (withRemoval)
{
// Remove all the events between [Begin(), lastEvent]
_count -= (lastEvent.Index() - Begin().Index()) & _capacityMask;
}
// Extract all the events between [firstEvent, lastEvent]
-
const int32 head = (lastEvent.Index() + 1) & _capacityMask;
count = (lastEvent.Index() - firstEvent.Index() + 1) & _capacityMask;
-
data.Resize(count, false);
-
- int32 tail = (head - count) & _capacityMask;
- int32 spaceLeft = capacity - tail;
- int32 spaceLeftCount = Math::Min(spaceLeft, count);
- int32 overflow = count - spaceLeft;
-
+ const int32 tail = (head - count) & _capacityMask;
+ const int32 spaceLeft = capacity - tail;
+ const int32 spaceLeftCount = Math::Min(spaceLeft, count);
+ const int32 overflow = count - spaceLeft;
Platform::MemoryCopy(data.Get(), &_data[tail], spaceLeftCount * sizeof(Event));
if (overflow > 0)
Platform::MemoryCopy(data.Get() + spaceLeftCount, &_data[0], overflow * sizeof(Event));
diff --git a/Source/Engine/Profiler/ProfilerCPU.h b/Source/Engine/Profiler/ProfilerCPU.h
index 000e41ccb..124082c9b 100644
--- a/Source/Engine/Profiler/ProfilerCPU.h
+++ b/Source/Engine/Profiler/ProfilerCPU.h
@@ -106,8 +106,8 @@ public:
/// Extracts the buffer data (only ended events starting from the root level with depth=0).
///
/// The output data.
- /// True if also remove extracted events to prevent double-gather, false if don't modify the buffer data.
- void Extract(Array& data, bool withRemove);
+ /// True if also remove extracted events to prevent double-gather, false if don't modify the buffer data.
+ void Extract(Array& data, bool withRemoval);
public:
///
diff --git a/Source/Engine/Profiler/ProfilingTools.cpp b/Source/Engine/Profiler/ProfilingTools.cpp
index 632915048..6ce8082ba 100644
--- a/Source/Engine/Profiler/ProfilingTools.cpp
+++ b/Source/Engine/Profiler/ProfilingTools.cpp
@@ -57,13 +57,13 @@ void ProfilingToolsService::Update()
ProfilingTools::EventsCPU.EnsureCapacity(threads.Count());
for (int32 i = 0; i < threads.Count(); i++)
{
- auto t = threads[i];
- if (t == nullptr)
+ ProfilerCPU::Thread* thread = threads[i];
+ if (thread == nullptr)
continue;
ProfilingTools::ThreadStats* pt = nullptr;
for (auto& e : ProfilingTools::EventsCPU)
{
- if (e.Name == t->GetName())
+ if (e.Name == thread->GetName())
{
pt = &e;
break;
@@ -72,10 +72,10 @@ void ProfilingToolsService::Update()
if (!pt)
{
pt = &ProfilingTools::EventsCPU.AddOne();
- pt->Name = t->GetName();
+ pt->Name = thread->GetName();
}
- t->Buffer.Extract(pt->Events, true);
+ thread->Buffer.Extract(pt->Events, true);
}
#if 0