Add content deprecation upgrades support to prefabs and scenes when loading levels
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
#include "SceneObjectsFactory.h"
|
||||
#include "Scene/Scene.h"
|
||||
#include "Engine/Content/Content.h"
|
||||
#include "Engine/Content/Deprecated.h"
|
||||
#include "Engine/Core/Cache.h"
|
||||
#include "Engine/Core/Collections/CollectionPoolCache.h"
|
||||
#include "Engine/Core/ObjectsRemovalService.h"
|
||||
@@ -827,7 +828,7 @@ bool Level::loadScene(JsonAsset* sceneAsset)
|
||||
return true;
|
||||
}
|
||||
|
||||
return loadScene(*sceneAsset->Data, sceneAsset->DataEngineBuild);
|
||||
return loadScene(*sceneAsset->Data, sceneAsset->DataEngineBuild, nullptr, &sceneAsset->GetPath());
|
||||
}
|
||||
|
||||
bool Level::loadScene(const BytesContainer& sceneData, Scene** outScene)
|
||||
@@ -866,11 +867,14 @@ bool Level::loadScene(rapidjson_flax::Document& document, Scene** outScene)
|
||||
return loadScene(data->value, saveEngineBuild, outScene);
|
||||
}
|
||||
|
||||
bool Level::loadScene(rapidjson_flax::Value& data, int32 engineBuild, Scene** outScene)
|
||||
bool Level::loadScene(rapidjson_flax::Value& data, int32 engineBuild, Scene** outScene, const String* assetPath)
|
||||
{
|
||||
PROFILE_CPU_NAMED("Level.LoadScene");
|
||||
if (outScene)
|
||||
*outScene = nullptr;
|
||||
#if USE_EDITOR
|
||||
ContentDeprecated::Clear();
|
||||
#endif
|
||||
LOG(Info, "Loading scene...");
|
||||
Stopwatch stopwatch;
|
||||
_lastSceneLoadTime = DateTime::Now();
|
||||
@@ -1002,6 +1006,9 @@ bool Level::loadScene(rapidjson_flax::Value& data, int32 engineBuild, Scene** ou
|
||||
if (context.Async)
|
||||
{
|
||||
ScenesLock.Unlock(); // Unlock scenes from Main Thread so Job Threads can use it to safely setup actors hierarchy (see Actor::Deserialize)
|
||||
#if USE_EDITOR
|
||||
volatile int64 deprecated = 0;
|
||||
#endif
|
||||
JobSystem::Execute([&](int32 i)
|
||||
{
|
||||
i++; // Start from 1. at index [0] was scene
|
||||
@@ -1011,9 +1018,17 @@ bool Level::loadScene(rapidjson_flax::Value& data, int32 engineBuild, Scene** ou
|
||||
auto& idMapping = Scripting::ObjectsLookupIdMapping.Get();
|
||||
idMapping = &context.GetModifier()->IdsMapping;
|
||||
SceneObjectsFactory::Deserialize(context, obj, data[i]);
|
||||
#if USE_EDITOR
|
||||
if (ContentDeprecated::Clear())
|
||||
Platform::InterlockedIncrement(&deprecated);
|
||||
#endif
|
||||
idMapping = nullptr;
|
||||
}
|
||||
}, dataCount - 1);
|
||||
#if USE_EDITOR
|
||||
if (deprecated != 0)
|
||||
ContentDeprecated::Mark();
|
||||
#endif
|
||||
ScenesLock.Lock();
|
||||
}
|
||||
else
|
||||
@@ -1103,6 +1118,28 @@ bool Level::loadScene(rapidjson_flax::Value& data, int32 engineBuild, Scene** ou
|
||||
LOG(Info, "Scene loaded in {0}ms", stopwatch.GetMilliseconds());
|
||||
if (outScene)
|
||||
*outScene = scene;
|
||||
|
||||
#if USE_EDITOR
|
||||
// Resave assets that use deprecated data format
|
||||
for (auto& e : context.DeprecatedPrefabs)
|
||||
{
|
||||
AssetReference<Prefab> prefab = e.Item;
|
||||
LOG(Info, "Resaving asset '{}' that uses deprecated data format", prefab->GetPath());
|
||||
if (prefab->Resave())
|
||||
{
|
||||
LOG(Error, "Failed to resave asset '{}'", prefab->GetPath());
|
||||
}
|
||||
}
|
||||
if (ContentDeprecated::Clear() && assetPath)
|
||||
{
|
||||
LOG(Info, "Resaving asset '{}' that uses deprecated data format", *assetPath);
|
||||
if (saveScene(scene, *assetPath))
|
||||
{
|
||||
LOG(Error, "Failed to resave asset '{}'", *assetPath);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1125,6 +1162,7 @@ bool LevelImpl::saveScene(Scene* scene)
|
||||
|
||||
bool LevelImpl::saveScene(Scene* scene, const String& path)
|
||||
{
|
||||
PROFILE_CPU_NAMED("Level.SaveScene");
|
||||
ASSERT(scene && EnumHasNoneFlags(scene->Flags, ObjectFlags::WasMarkedToDelete));
|
||||
auto sceneId = scene->GetID();
|
||||
|
||||
|
||||
@@ -551,5 +551,5 @@ private:
|
||||
static bool loadScene(JsonAsset* sceneAsset);
|
||||
static bool loadScene(const BytesContainer& sceneData, Scene** outScene = nullptr);
|
||||
static bool loadScene(rapidjson_flax::Document& document, Scene** outScene = nullptr);
|
||||
static bool loadScene(rapidjson_flax::Value& data, int32 engineBuild, Scene** outScene = nullptr);
|
||||
static bool loadScene(rapidjson_flax::Value& data, int32 engineBuild, Scene** outScene = nullptr, const String* assetPath = nullptr);
|
||||
};
|
||||
|
||||
@@ -732,6 +732,50 @@ bool Prefab::ApplyAll(Actor* targetActor)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Prefab::Resave()
|
||||
{
|
||||
if (OnCheckSave())
|
||||
return true;
|
||||
PROFILE_CPU_NAMED("Prefab.Resave");
|
||||
ScopeLock lock(Locker);
|
||||
|
||||
Dictionary<Guid, Guid> objectIds;
|
||||
objectIds.EnsureCapacity(ObjectsIds.Count());
|
||||
for (int32 i = 0; i < ObjectsIds.Count(); i++)
|
||||
{
|
||||
Guid id = ObjectsIds[i];
|
||||
objectIds.Add(id, id);
|
||||
}
|
||||
PrefabManager::SpawnOptions options;
|
||||
options.WithLink = false;
|
||||
options.IDs = &objectIds;
|
||||
auto instance = PrefabManager::SpawnPrefab(this, options);
|
||||
if (instance == nullptr)
|
||||
return true;
|
||||
|
||||
// Serialize to json data
|
||||
CollectionPoolCache<ActorsCache::SceneObjectsListType>::ScopeCache sceneObjects = ActorsCache::SceneObjectsListCache.Get();
|
||||
SceneQuery::GetAllSerializableSceneObjects(instance, *sceneObjects.Value);
|
||||
rapidjson_flax::StringBuffer dataBuffer;
|
||||
{
|
||||
PrettyJsonWriter writerObj(dataBuffer);
|
||||
PrefabInstanceData::SerializeObjects(*sceneObjects.Value, writerObj);
|
||||
}
|
||||
|
||||
// Remove temporary objects
|
||||
instance->DeleteObject();
|
||||
instance = nullptr;
|
||||
|
||||
// Save to file
|
||||
if (CreateJson::Create(GetPath(), dataBuffer, TypeName))
|
||||
{
|
||||
LOG(Warning, "Failed to serialize prefab data to the asset.");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Prefab::ApplyAllInternal(Actor* targetActor, bool linkTargetActorObjectToPrefab, PrefabInstancesData& prefabInstancesData)
|
||||
{
|
||||
PROFILE_CPU_NAMED("Prefab.Apply");
|
||||
|
||||
@@ -10,7 +10,7 @@ class Actor;
|
||||
class SceneObject;
|
||||
|
||||
/// <summary>
|
||||
/// Json asset that stores the collection of scene objects including actors and scripts. In general it can serve as any grouping of scene objects (for example a level) or be used as a form of a template instantiated and reused throughout the scene.
|
||||
/// Json asset that stores the collection of scene objects including actors and scripts. In general, it can serve as any grouping of scene objects (for example a level) or be used as a form of a template instantiated and reused throughout the scene.
|
||||
/// </summary>
|
||||
/// <seealso cref="JsonAssetBase" />
|
||||
API_CLASS(NoSpawn) class FLAXENGINE_API Prefab : public JsonAssetBase
|
||||
@@ -74,11 +74,16 @@ public:
|
||||
/// <summary>
|
||||
/// Applies the difference from the prefab object instance, saves the changes and synchronizes them with the active instances of the prefab asset.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Applies all the changes from not only the given actor instance but all actors created within that prefab instance.
|
||||
/// </remarks>
|
||||
/// <remarks>Applies all the changes from not only the given actor instance but all actors created within that prefab instance.</remarks>
|
||||
/// <param name="targetActor">The root actor of spawned prefab instance to use as modified changes sources.</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
bool ApplyAll(Actor* targetActor);
|
||||
|
||||
/// <summary>
|
||||
/// Resaves the prefab asset to the file by serializing default instance in the latest format and defaults.
|
||||
/// </summary>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
API_FUNCTION() bool Resave();
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "Engine/Level/Level.h"
|
||||
#include "Engine/Content/AssetInfo.h"
|
||||
#include "Engine/Content/Content.h"
|
||||
#include "Engine/Content/Deprecated.h"
|
||||
#include "Engine/Content/Factories/JsonAssetFactory.h"
|
||||
#include "Engine/Physics/Colliders/MeshCollider.h"
|
||||
#include "Engine/Level/Actors/StaticModel.h"
|
||||
@@ -306,6 +307,7 @@ void Scene::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
|
||||
if (e != stream.MemberEnd())
|
||||
{
|
||||
// Upgrade from old single hidden navmesh data into NavMesh actors on a scene
|
||||
MARK_CONTENT_DEPRECATED();
|
||||
AssetReference<RawDataAsset> dataAsset;
|
||||
Serialization::Deserialize(e->value, dataAsset, modifier);
|
||||
const auto settings = NavigationSettings::Get();
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "Engine/Threading/Threading.h"
|
||||
#include "Engine/Level/Scripts/MissingScript.h"
|
||||
#endif
|
||||
#include "Engine/Content/Deprecated.h"
|
||||
#include "Engine/Level/Scripts/ModelPrefab.h"
|
||||
|
||||
#if USE_EDITOR
|
||||
@@ -199,6 +200,7 @@ SceneObject* SceneObjectsFactory::Spawn(Context& context, const ISerializable::D
|
||||
else
|
||||
{
|
||||
// [Deprecated: 18.07.2019 expires 18.07.2020]
|
||||
MARK_CONTENT_DEPRECATED();
|
||||
const auto typeIdMember = stream.FindMember("TypeID");
|
||||
if (typeIdMember == stream.MemberEnd())
|
||||
{
|
||||
@@ -286,7 +288,19 @@ void SceneObjectsFactory::Deserialize(Context& context, SceneObject* obj, ISeria
|
||||
// Deserialize prefab data (recursive prefab loading to support nested prefabs)
|
||||
const auto prevVersion = modifier->EngineBuild;
|
||||
modifier->EngineBuild = prefab->DataEngineBuild;
|
||||
#if USE_EDITOR
|
||||
bool prevDeprecated = ContentDeprecated::Clear();
|
||||
#endif
|
||||
Deserialize(context, obj, *(ISerializable::DeserializeStream*)prefabData);
|
||||
#if USE_EDITOR
|
||||
if (ContentDeprecated::Clear(prevDeprecated))
|
||||
{
|
||||
// Prefab contains deprecated data format
|
||||
context.Locker.Lock();
|
||||
context.DeprecatedPrefabs.Add(prefab);
|
||||
context.Locker.Unlock();
|
||||
}
|
||||
#endif
|
||||
modifier->EngineBuild = prevVersion;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,9 @@ public:
|
||||
Dictionary<Guid, int32> ObjectToInstance;
|
||||
CriticalSection Locker;
|
||||
ThreadLocal<ISerializeModifier*> Modifiers;
|
||||
#if USE_EDITOR
|
||||
HashSet<Prefab*> DeprecatedPrefabs;
|
||||
#endif
|
||||
|
||||
Context(ISerializeModifier* modifier);
|
||||
~Context();
|
||||
|
||||
Reference in New Issue
Block a user