Merge branch 'FlaxEngine:master' into flax-msdf-font

This commit is contained in:
fibref
2026-02-16 22:48:19 +08:00
committed by GitHub
185 changed files with 3363 additions and 1242 deletions

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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>

View File

@@ -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)

View File

@@ -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();

View File

@@ -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).