Add support for virtual Prefab assets created from code
This commit is contained in:
@@ -230,7 +230,8 @@ void Asset::OnDeleteObject()
|
||||
Content::GetRegistry()->DeleteAsset(id, nullptr);
|
||||
|
||||
// Delete file
|
||||
Content::deleteFileSafety(path, id);
|
||||
if (!IsVirtual())
|
||||
Content::deleteFileSafety(path, id);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -288,8 +289,13 @@ void Asset::OnScriptingDispose()
|
||||
|
||||
void Asset::ChangeID(const Guid& newId)
|
||||
{
|
||||
// Don't allow to change asset ids
|
||||
CRASH;
|
||||
// Only virtual asset can change ID
|
||||
if (!IsVirtual())
|
||||
CRASH;
|
||||
|
||||
const Guid oldId = _id;
|
||||
ManagedScriptingObject::ChangeID(newId);
|
||||
Content::onAssetChangeId(this, oldId, newId);
|
||||
}
|
||||
|
||||
bool Asset::LastLoadFailed() const
|
||||
|
||||
@@ -460,12 +460,16 @@ Asset* Content::LoadAsync(const StringView& path, const ScriptingTypeHandle& typ
|
||||
Array<Asset*> Content::GetAssets()
|
||||
{
|
||||
Array<Asset*> assets;
|
||||
AssetsLocker.Lock();
|
||||
Assets.GetValues(assets);
|
||||
AssetsLocker.Unlock();
|
||||
return assets;
|
||||
}
|
||||
|
||||
const Dictionary<Guid, Asset*>& Content::GetAssetsRaw()
|
||||
{
|
||||
AssetsLocker.Lock();
|
||||
AssetsLocker.Unlock();
|
||||
return Assets;
|
||||
}
|
||||
|
||||
@@ -862,6 +866,13 @@ void Content::onAssetUnload(Asset* asset)
|
||||
LoadedAssetsToInvoke.Remove(asset);
|
||||
}
|
||||
|
||||
void Content::onAssetChangeId(Asset* asset, const Guid& oldId, const Guid& newId)
|
||||
{
|
||||
ScopeLock locker(AssetsLocker);
|
||||
Assets.Remove(oldId);
|
||||
Assets.Add(newId, asset);
|
||||
}
|
||||
|
||||
bool Content::IsAssetTypeIdInvalid(const ScriptingTypeHandle& type, const ScriptingTypeHandle& assetType)
|
||||
{
|
||||
// Skip if no restrictions for the type
|
||||
|
||||
@@ -358,6 +358,7 @@ private:
|
||||
static void tryCallOnLoaded(Asset* asset);
|
||||
static void onAssetLoaded(Asset* asset);
|
||||
static void onAssetUnload(Asset* asset);
|
||||
static void onAssetChangeId(Asset* asset, const Guid& oldId, const Guid& newId);
|
||||
static Asset* load(const Guid& id, const ScriptingTypeHandle& type, AssetInfo& assetInfo);
|
||||
|
||||
private:
|
||||
|
||||
@@ -45,6 +45,29 @@ String JsonAssetBase::GetData() const
|
||||
return String((const char*)buffer.GetString(), (int32)buffer.GetSize());
|
||||
}
|
||||
|
||||
bool JsonAssetBase::Init(const StringView& dataTypeName, const StringAnsiView& dataJson)
|
||||
{
|
||||
CHECK_RETURN(IsVirtual(), true);
|
||||
unload(true);
|
||||
DataTypeName = dataTypeName;
|
||||
DataEngineBuild = FLAXENGINE_VERSION_BUILD;
|
||||
|
||||
// Parse json document
|
||||
{
|
||||
PROFILE_CPU_NAMED("Json.Parse");
|
||||
Document.Parse(dataJson.Get(), dataJson.Length());
|
||||
}
|
||||
if (Document.HasParseError())
|
||||
{
|
||||
Log::JsonParseException(Document.GetParseError(), Document.GetErrorOffset());
|
||||
return true;
|
||||
}
|
||||
Data = &Document;
|
||||
|
||||
// Load asset-specific data
|
||||
return loadAsset() != LoadResult::Ok;
|
||||
}
|
||||
|
||||
const String& JsonAssetBase::GetPath() const
|
||||
{
|
||||
#if USE_EDITOR
|
||||
@@ -114,6 +137,9 @@ void JsonAssetBase::GetReferences(Array<Guid>& output) const
|
||||
|
||||
Asset::LoadResult JsonAssetBase::loadAsset()
|
||||
{
|
||||
if (IsVirtual())
|
||||
return LoadResult::Ok;
|
||||
|
||||
// Load data (raw json file in editor, cooked asset in build game)
|
||||
#if USE_EDITOR
|
||||
BytesContainer data;
|
||||
|
||||
@@ -50,6 +50,15 @@ public:
|
||||
/// </summary>
|
||||
API_PROPERTY() String GetData() const;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the virtual Json asset with custom data.
|
||||
/// </summary>
|
||||
/// <remarks>Can be used only for virtual assets created at runtime.</remarks>
|
||||
/// <param name="dataTypeName">The data type name from the header. Allows to recognize the data type.</param>
|
||||
/// <param name="dataJson">The Json with serialized data.</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
API_FUNCTION() bool Init(const StringView& dataTypeName, const StringAnsiView& dataJson);
|
||||
|
||||
#if USE_EDITOR
|
||||
/// <summary>
|
||||
/// Parses Json string to find any object references inside it. It can produce list of references to assets and/or scene objects. Supported only in Editor.
|
||||
|
||||
@@ -661,10 +661,16 @@ bool Prefab::ApplyAll(Actor* targetActor)
|
||||
|
||||
// Assign references to the prefabs
|
||||
allPrefabs.EnsureCapacity(Math::RoundUpToPowerOf2(Math::Max(30, nestedPrefabIds.Count())));
|
||||
const Dictionary<Guid, Asset*, HeapAllocation>& assetsRaw = Content::GetAssetsRaw();
|
||||
for (auto& e : assetsRaw)
|
||||
{
|
||||
if (e.Value->GetTypeHandle() == Prefab::TypeInitializer)
|
||||
nestedPrefabIds.AddUnique(e.Key);
|
||||
}
|
||||
for (int32 i = 0; i < nestedPrefabIds.Count(); i++)
|
||||
{
|
||||
const auto nestedPrefab = Content::LoadAsync<Prefab>(nestedPrefabIds[i]);
|
||||
if (nestedPrefab && nestedPrefab != this)
|
||||
if (nestedPrefab && nestedPrefab != this && (nestedPrefab->Flags & ObjectFlags::WasMarkedToDelete) == 0)
|
||||
{
|
||||
allPrefabs.Add(nestedPrefab);
|
||||
}
|
||||
@@ -1079,6 +1085,10 @@ bool Prefab::UpdateInternal(const Array<SceneObject*>& defaultInstanceObjects, r
|
||||
LOG(Info, "Updating prefab data");
|
||||
|
||||
// Reload prefab data
|
||||
if (IsVirtual())
|
||||
{
|
||||
return Init(TypeName, StringAnsiView(tmpBuffer.GetString(), (int32)tmpBuffer.GetSize()));
|
||||
}
|
||||
#if 1 // Set to 0 to use memory-only reload that does not modifies the source file - useful for testing and debugging prefabs apply
|
||||
#if COMPILE_WITH_ASSETS_IMPORTER
|
||||
Locker.Unlock();
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "Engine/Scripting/Scripting.h"
|
||||
#endif
|
||||
|
||||
REGISTER_JSON_ASSET(Prefab, "FlaxEngine.Prefab", false);
|
||||
REGISTER_JSON_ASSET(Prefab, "FlaxEngine.Prefab", true);
|
||||
|
||||
Prefab::Prefab(const SpawnParams& params, const AssetInfo* info)
|
||||
: JsonAssetBase(params, info)
|
||||
|
||||
Reference in New Issue
Block a user