Merge branch 'FlaxEngine:master' into flax-msdf-font
This commit is contained in:
@@ -487,6 +487,8 @@ bool Asset::WaitForLoaded(double timeoutInMilliseconds) const
|
||||
const auto loadingTask = (ContentLoadTask*)Platform::AtomicRead(&_loadingTask);
|
||||
if (loadingTask == nullptr)
|
||||
{
|
||||
if (IsLoaded())
|
||||
return false;
|
||||
LOG(Warning, "WaitForLoaded asset \'{0}\' failed. No loading task attached and asset is not loaded.", ToString());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -61,16 +61,24 @@ Array<String> SkinnedModel::GetBlendShapes()
|
||||
|
||||
SkinnedModel::SkeletonMapping SkinnedModel::GetSkeletonMapping(Asset* source, bool autoRetarget)
|
||||
{
|
||||
// Fast-path to use cached mapping
|
||||
SkeletonMapping mapping;
|
||||
mapping.TargetSkeleton = this;
|
||||
SkeletonMappingData mappingData;
|
||||
if (_skeletonMappingCache.TryGet(source, mappingData))
|
||||
{
|
||||
mapping.SourceSkeleton = mappingData.SourceSkeleton;
|
||||
mapping.NodesMapping = mappingData.NodesMapping;
|
||||
return mapping;
|
||||
}
|
||||
mapping.SourceSkeleton = nullptr;
|
||||
|
||||
if (WaitForLoaded() || !source || source->WaitForLoaded())
|
||||
return mapping;
|
||||
PROFILE_CPU();
|
||||
ScopeLock lock(Locker);
|
||||
SkeletonMappingData mappingData;
|
||||
if (!_skeletonMappingCache.TryGet(source, mappingData))
|
||||
{
|
||||
PROFILE_CPU();
|
||||
|
||||
// Initialize the mapping
|
||||
SkeletonRetarget* retarget = nullptr;
|
||||
const Guid sourceId = source->GetID();
|
||||
@@ -370,6 +378,7 @@ bool SkinnedModel::SetupSkeleton(const Array<SkeletonNode>& nodes)
|
||||
model->Skeleton.Bones[i].LocalTransform = node.LocalTransform;
|
||||
model->Skeleton.Bones[i].NodeIndex = i;
|
||||
}
|
||||
model->Skeleton.Dirty();
|
||||
ClearSkeletonMapping();
|
||||
|
||||
// Calculate offset matrix (inverse bind pose transform) for every bone manually
|
||||
@@ -427,6 +436,7 @@ bool SkinnedModel::SetupSkeleton(const Array<SkeletonNode>& nodes, const Array<S
|
||||
// Setup
|
||||
model->Skeleton.Nodes = nodes;
|
||||
model->Skeleton.Bones = bones;
|
||||
model->Skeleton.Dirty();
|
||||
ClearSkeletonMapping();
|
||||
|
||||
// Calculate offset matrix (inverse bind pose transform) for every bone manually
|
||||
@@ -823,13 +833,13 @@ bool SkinnedModel::SaveMesh(WriteStream& stream, const ModelData& modelData, int
|
||||
|
||||
void SkinnedModel::ClearSkeletonMapping()
|
||||
{
|
||||
for (auto& e : _skeletonMappingCache)
|
||||
for (const auto& e : _skeletonMappingCache)
|
||||
{
|
||||
e.Key->OnUnloaded.Unbind<SkinnedModel, &SkinnedModel::OnSkeletonMappingSourceAssetUnloaded>(this);
|
||||
#if USE_EDITOR
|
||||
e.Key->OnReloading.Unbind<SkinnedModel, &SkinnedModel::OnSkeletonMappingSourceAssetUnloaded>(this);
|
||||
#endif
|
||||
Allocator::Free(e.Value.NodesMapping.Get());
|
||||
Allocator::Free((void*)e.Value.NodesMapping.Get());
|
||||
}
|
||||
_skeletonMappingCache.Clear();
|
||||
}
|
||||
@@ -837,8 +847,9 @@ void SkinnedModel::ClearSkeletonMapping()
|
||||
void SkinnedModel::OnSkeletonMappingSourceAssetUnloaded(Asset* obj)
|
||||
{
|
||||
ScopeLock lock(Locker);
|
||||
auto i = _skeletonMappingCache.Find(obj);
|
||||
ASSERT(i != _skeletonMappingCache.End());
|
||||
SkeletonMappingData mappingData;
|
||||
bool found = _skeletonMappingCache.TryGet(obj, mappingData);
|
||||
ASSERT(found);
|
||||
|
||||
// Unlink event
|
||||
obj->OnUnloaded.Unbind<SkinnedModel, &SkinnedModel::OnSkeletonMappingSourceAssetUnloaded>(this);
|
||||
@@ -847,8 +858,8 @@ void SkinnedModel::OnSkeletonMappingSourceAssetUnloaded(Asset* obj)
|
||||
#endif
|
||||
|
||||
// Clear cache
|
||||
Allocator::Free(i->Value.NodesMapping.Get());
|
||||
_skeletonMappingCache.Remove(i);
|
||||
Allocator::Free(mappingData.NodesMapping.Get());
|
||||
_skeletonMappingCache.Remove(obj);
|
||||
}
|
||||
|
||||
uint64 SkinnedModel::GetMemoryUsage() const
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "ModelBase.h"
|
||||
#include "Engine/Core/Collections/Dictionary.h"
|
||||
#include "Engine/Threading/ConcurrentDictionary.h"
|
||||
#include "Engine/Graphics/Models/SkinnedMesh.h"
|
||||
#include "Engine/Graphics/Models/SkeletonData.h"
|
||||
|
||||
@@ -101,9 +101,9 @@ public:
|
||||
struct FLAXENGINE_API SkeletonMapping
|
||||
{
|
||||
// Target skeleton.
|
||||
AssetReference<SkinnedModel> TargetSkeleton;
|
||||
SkinnedModel* TargetSkeleton;
|
||||
// Source skeleton.
|
||||
AssetReference<SkinnedModel> SourceSkeleton;
|
||||
SkinnedModel* SourceSkeleton;
|
||||
// The node-to-node mapping for the fast animation sampling for the skinned model skeleton nodes. Each item is index of the source skeleton node into target skeleton node.
|
||||
Span<int32> NodesMapping;
|
||||
};
|
||||
@@ -115,7 +115,7 @@ private:
|
||||
Span<int32> NodesMapping;
|
||||
};
|
||||
|
||||
Dictionary<Asset*, SkeletonMappingData> _skeletonMappingCache;
|
||||
ConcurrentDictionary<Asset*, SkeletonMappingData> _skeletonMappingCache;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
|
||||
@@ -1700,6 +1700,8 @@ void VisualScript::CacheScriptingType()
|
||||
VisualScriptingBinaryModule::VisualScriptingBinaryModule()
|
||||
: _name("Visual Scripting")
|
||||
{
|
||||
// Visual Scripts can be unloaded and loaded again even in game
|
||||
CanReload = true;
|
||||
}
|
||||
|
||||
ScriptingObject* VisualScriptingBinaryModule::VisualScriptObjectSpawn(const ScriptingObjectSpawnParams& params)
|
||||
|
||||
@@ -684,6 +684,19 @@ Array<Asset*> Content::GetAssets()
|
||||
return assets;
|
||||
}
|
||||
|
||||
Array<Asset*> Content::GetAssets(const MClass* type)
|
||||
{
|
||||
Array<Asset*> assets;
|
||||
AssetsLocker.Lock();
|
||||
for (auto& e : Assets)
|
||||
{
|
||||
if (e.Value->Is(type))
|
||||
assets.Add(e.Value);
|
||||
}
|
||||
AssetsLocker.Unlock();
|
||||
return assets;
|
||||
}
|
||||
|
||||
const Dictionary<Guid, Asset*>& Content::GetAssetsRaw()
|
||||
{
|
||||
AssetsLocker.Lock();
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Scripting/ScriptingType.h"
|
||||
#ifndef _MSC_VER
|
||||
#include "Engine/Core/Collections/Array.h"
|
||||
#endif
|
||||
#include "AssetInfo.h"
|
||||
#include "Asset.h"
|
||||
#include "Config.h"
|
||||
@@ -122,7 +125,26 @@ public:
|
||||
/// Gets the assets (loaded or during load).
|
||||
/// </summary>
|
||||
/// <returns>The collection of assets.</returns>
|
||||
static Array<Asset*, HeapAllocation> GetAssets();
|
||||
API_FUNCTION() static Array<Asset*, HeapAllocation> GetAssets();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assets (loaded or during load).
|
||||
/// </summary>
|
||||
/// <param name="type">Type of the assets to search for. Includes any assets derived from the type.</param>
|
||||
/// <returns>Found actors list.</returns>
|
||||
API_FUNCTION() static Array<Asset*, HeapAllocation> GetAssets(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assets (loaded or during load).
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the object.</typeparam>
|
||||
/// <returns>Found actors list.</returns>
|
||||
template<typename T>
|
||||
static Array<T*, HeapAllocation> GetAssets()
|
||||
{
|
||||
Array<Asset*, HeapAllocation> assets = GetAssets(T::GetStaticClass());
|
||||
return *(Array<T*, HeapAllocation>*) & assets;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the raw dictionary of assets (loaded or during load).
|
||||
|
||||
Reference in New Issue
Block a user