Merge pull request #671 from aws-lumberyard-dev/Prefabs/AssetPreload

Asset Preload fix for json serialization and prefab game mode
This commit is contained in:
sconel
2021-05-11 09:35:06 -07:00
committed by GitHub
15 changed files with 236 additions and 23 deletions
@@ -18,6 +18,7 @@
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/Math/Uuid.h>
#include <AzCore/Preprocessor/Enum.h>
#include <AzCore/std/containers/bitset.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/string/string_view.h>
@@ -216,16 +217,14 @@ namespace AZ
/**
* Setting for each reference (Asset<T>) to control loading of referenced assets during serialization.
*/
enum class AssetLoadBehavior : u8
{
PreLoad = 0, ///< Serializer will "Pre load" dependencies, asset containers may load in parallel but will not signal AssetReady
QueueLoad = 1, ///< Serializer will queue an asynchronous load of the referenced asset and return the object to the user. User code should use the \ref AZ::Data::AssetBus to monitor for when it's ready.
NoLoad = 2, ///< Serializer will load reference information, but asset loading will be left to the user. User code should call Asset<T>::QueueLoad and use the \ref AZ::Data::AssetBus to monitor for when it's ready.
///< AssetContainers will skip NoLoad dependencies
AZ_ENUM_WITH_UNDERLYING_TYPE(AssetLoadBehavior, u8,
(PreLoad, 0), ///< Serializer will "Pre load" dependencies, asset containers may load in parallel but will not signal AssetReady
(QueueLoad, 1), ///< Serializer will queue an asynchronous load of the referenced asset and return the object to the user. User code should use the \ref AZ::Data::AssetBus to monitor for when it's ready.
(NoLoad, 2), ///< Serializer will load reference information, but asset loading will be left to the user. User code should call Asset<T>::QueueLoad and use the \ref AZ::Data::AssetBus to monitor for when it's ready.
///< AssetContainers will skip NoLoad dependencies
Count,
Default = QueueLoad,
};
(Default, QueueLoad)
);
struct AssetFilterInfo
{
@@ -1222,6 +1221,7 @@ namespace AZ
} // namespace ProductDependencyInfo
} // namespace Data
AZ_TYPE_INFO_SPECIALIZE(Data::AssetLoadBehavior, "{DAF9ECED-FEF3-4D7A-A220-8CFD6A5E6DA1}");
AZ_TYPE_INFO_TEMPLATE_WITH_NAME(AZ::Data::Asset, "Asset", "{C891BF19-B60C-45E2-BFD0-027D15DDC939}", AZ_TYPE_INFO_CLASS);
} // namespace AZ
@@ -70,6 +70,17 @@ namespace AZ
}
}
{
const AZ::Data::AssetLoadBehavior autoLoadBehavior = instance->GetAutoLoadBehavior();
const AZ::Data::AssetLoadBehavior defaultAutoLoadBehavior = defaultInstance ?
defaultInstance->GetAutoLoadBehavior() : AZ::Data::AssetLoadBehavior::Default;
result.Combine(
ContinueStoringToJsonObjectField(outputValue, "loadBehavior",
&autoLoadBehavior, &defaultAutoLoadBehavior,
azrtti_typeid<Data::AssetLoadBehavior>(), context));
}
{
ScopedContextPath subPathHint(context, "m_assetHint");
const AZStd::string* hint = &instance->GetHint();
@@ -100,14 +111,28 @@ namespace AZ
AssetId id;
JSR::ResultCode result(JSR::Tasks::ReadField);
SerializedAssetTracker* assetTracker =
context.GetMetadata().Find<SerializedAssetTracker>();
{
Data::AssetLoadBehavior loadBehavior = instance->GetAutoLoadBehavior();
result =
ContinueLoadingFromJsonObjectField(&loadBehavior,
azrtti_typeid<Data::AssetLoadBehavior>(),
inputValue, "loadBehavior", context);
instance->SetAutoLoadBehavior(loadBehavior);
}
auto it = inputValue.FindMember("assetId");
if (it != inputValue.MemberEnd())
{
ScopedContextPath subPath(context, "assetId");
result = ContinueLoading(&id, azrtti_typeid<AssetId>(), it->value, context);
result.Combine(ContinueLoading(&id, azrtti_typeid<AssetId>(), it->value, context));
if (!id.m_guid.IsNull())
{
*instance = AssetManager::Instance().FindOrCreateAsset(id, instance->GetType(), AssetLoadBehavior::NoLoad);
*instance = AssetManager::Instance().FindOrCreateAsset(id, instance->GetType(), instance->GetAutoLoadBehavior());
result.Combine(context.Report(result, "Successfully created Asset<T> with id."));
@@ -142,6 +167,11 @@ namespace AZ
"The asset hint is missing for Asset<T>, so it will be left empty."));
}
if (assetTracker)
{
assetTracker->AddAsset(*instance);
}
bool success = result.GetOutcome() <= JSR::Outcomes::PartialSkip;
bool defaulted = result.GetOutcome() == JSR::Outcomes::DefaultsUsed || result.GetOutcome() == JSR::Outcomes::PartialDefaults;
AZStd::string_view message =
@@ -150,5 +180,20 @@ namespace AZ
"Not enough information was available to create an instance of Asset<T> or data was corrupted.";
return context.Report(result, message);
}
void SerializedAssetTracker::AddAsset(Asset<AssetData>& asset)
{
m_serializedAssets.emplace_back(asset);
}
const AZStd::vector<Asset<AssetData>>& SerializedAssetTracker::GetTrackedAssets() const
{
return m_serializedAssets;
}
AZStd::vector<Asset<AssetData>>& SerializedAssetTracker::GetTrackedAssets()
{
return m_serializedAssets;
}
} // namespace Data
} // namespace AZ
@@ -13,6 +13,7 @@
#pragma once
#include <AzCore/Memory/Memory.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
namespace AZ
@@ -37,5 +38,18 @@ namespace AZ
private:
JsonSerializationResult::Result LoadAsset(void* outputValue, const rapidjson::Value& inputValue, JsonDeserializerContext& context);
};
class SerializedAssetTracker final
{
public:
AZ_RTTI(SerializedAssetTracker, "{1E067091-8C0A-44B1-A455-6E97663F6963}");
void AddAsset(Asset<AssetData>& asset);
AZStd::vector<Asset<AssetData>>& GetTrackedAssets();
const AZStd::vector<Asset<AssetData>>& GetTrackedAssets() const;
private:
AZStd::vector<Asset<AssetData>> m_serializedAssets;
};
} // namespace Data
} // namespace AZ
@@ -13,7 +13,7 @@
#include <AzCore/Asset/AssetJsonSerializer.h>
#include <AzCore/Asset/AssetManagerComponent.h>
#include <AzCore/Asset/AssetManagerBus.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Preprocessor/EnumReflectUtils.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Asset/AssetManager.h>
@@ -24,6 +24,11 @@
namespace AZ
{
namespace Data
{
AZ_ENUM_DEFINE_REFLECT_UTILITIES(AssetLoadBehavior);
}
//=========================================================================
// AssetDatabaseComponent
// [6/25/2012]
@@ -99,6 +104,8 @@ namespace AZ
if (SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context))
{
AZ::Data::AssetLoadBehaviorReflect(*serializeContext);
serializeContext->RegisterGenericType<Data::Asset<Data::AssetData>>();
serializeContext->Class<AssetManagerComponent, AZ::Component>()
@@ -14,8 +14,6 @@
#include <limits>
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Memory/OSAllocator.h>
#include <AzCore/Memory/SystemAllocator.h>
@@ -135,6 +135,7 @@ namespace JsonSerializationTests
auto instance = AZStd::make_shared<Asset>();
instance->Create(id, false);
instance->SetHint("TestFile");
instance->SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::PreLoad);
return instance;
}
@@ -158,6 +159,7 @@ namespace JsonSerializationTests
"guid": "{BBEAC89F-8BAD-4A9D-BF6E-D0DF84A8DFD6}",
"subId": 1
},
"loadBehavior": "PreLoad",
"assetHint": "TestFile"
})";
}