Add content deprecation system that auto-saves assets in Editor that use old data format
This commit is contained in:
@@ -226,16 +226,8 @@ void Animation::LoadTimeline(BytesContainer& result) const
|
||||
|
||||
bool Animation::SaveTimeline(BytesContainer& data)
|
||||
{
|
||||
// Wait for asset to be loaded or don't if last load failed (eg. by shader source compilation error)
|
||||
if (LastLoadFailed())
|
||||
{
|
||||
LOG(Warning, "Saving asset that failed to load.");
|
||||
}
|
||||
else if (WaitForLoaded())
|
||||
{
|
||||
LOG(Error, "Asset loading failed. Cannot save it.");
|
||||
if (OnCheckSave())
|
||||
return true;
|
||||
}
|
||||
ScopeLock lock(Locker);
|
||||
MemoryReadStream stream(data.Get(), data.Length());
|
||||
|
||||
@@ -401,17 +393,8 @@ bool Animation::SaveTimeline(BytesContainer& data)
|
||||
|
||||
bool Animation::Save(const StringView& path)
|
||||
{
|
||||
// Wait for asset to be loaded or don't if last load failed (eg. by shader source compilation error)
|
||||
if (LastLoadFailed())
|
||||
{
|
||||
LOG(Warning, "Saving asset that failed to load.");
|
||||
}
|
||||
else if (WaitForLoaded())
|
||||
{
|
||||
LOG(Error, "Asset loading failed. Cannot save it.");
|
||||
if (OnCheckSave(path))
|
||||
return true;
|
||||
}
|
||||
|
||||
ScopeLock lock(Locker);
|
||||
|
||||
// Serialize animation data to the stream
|
||||
|
||||
@@ -138,17 +138,10 @@ public:
|
||||
/// <summary>
|
||||
/// Saves the serialized timeline data to the asset as animation.
|
||||
/// </summary>
|
||||
/// <remarks>The cannot be used by virtual assets.</remarks>
|
||||
/// <remarks>This cannot be used by virtual assets.</remarks>
|
||||
/// <param name="data">The timeline data container.</param>
|
||||
/// <returns><c>true</c> failed to save data; otherwise, <c>false</c>.</returns>
|
||||
API_FUNCTION() bool SaveTimeline(BytesContainer& data);
|
||||
|
||||
/// <summary>
|
||||
/// Saves the animation data to the asset. Supported only in Editor.
|
||||
/// </summary>
|
||||
/// <remarks>The cannot be used by virtual assets.</remarks>
|
||||
/// <returns><c>true</c> failed to save data; otherwise, <c>false</c>.</returns>
|
||||
bool Save(const StringView& path = StringView::Empty);
|
||||
#endif
|
||||
|
||||
private:
|
||||
@@ -161,6 +154,7 @@ public:
|
||||
// [BinaryAsset]
|
||||
#if USE_EDITOR
|
||||
void GetReferences(Array<Guid>& assets, Array<String>& files) const override;
|
||||
bool Save(const StringView& path = StringView::Empty) override;
|
||||
#endif
|
||||
uint64 GetMemoryUsage() const override;
|
||||
void OnScriptingDispose() override;
|
||||
|
||||
@@ -127,7 +127,7 @@ bool AnimationGraph::InitAsAnimation(SkinnedModel* baseModel, Animation* anim, b
|
||||
return Graph.Load(&readStream, USE_EDITOR);
|
||||
}
|
||||
|
||||
BytesContainer AnimationGraph::LoadSurface()
|
||||
BytesContainer AnimationGraph::LoadSurface() const
|
||||
{
|
||||
if (!IsVirtual() && WaitForLoaded())
|
||||
return BytesContainer();
|
||||
@@ -160,19 +160,10 @@ BytesContainer AnimationGraph::LoadSurface()
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
bool AnimationGraph::SaveSurface(BytesContainer& data)
|
||||
bool AnimationGraph::SaveSurface(const BytesContainer& data)
|
||||
{
|
||||
// Wait for asset to be loaded or don't if last load failed
|
||||
if (LastLoadFailed())
|
||||
{
|
||||
LOG(Warning, "Saving asset that failed to load.");
|
||||
}
|
||||
else if (WaitForLoaded())
|
||||
{
|
||||
LOG(Error, "Asset loading failed. Cannot save it.");
|
||||
if (OnCheckSave())
|
||||
return true;
|
||||
}
|
||||
|
||||
ScopeLock lock(Locker);
|
||||
|
||||
if (IsVirtual())
|
||||
@@ -228,4 +219,17 @@ void AnimationGraph::GetReferences(Array<Guid>& assets, Array<String>& files) co
|
||||
Graph.GetReferences(assets);
|
||||
}
|
||||
|
||||
bool AnimationGraph::Save(const StringView& path)
|
||||
{
|
||||
if (OnCheckSave(path))
|
||||
return true;
|
||||
ScopeLock lock(Locker);
|
||||
MemoryWriteStream writeStream;
|
||||
if (Graph.Save(&writeStream, true))
|
||||
return true;
|
||||
BytesContainer data;
|
||||
data.Link(ToSpan(writeStream));
|
||||
return SaveSurface(data);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
/// Tries to load surface graph from the asset.
|
||||
/// </summary>
|
||||
/// <returns>The surface data or empty if failed to load it.</returns>
|
||||
API_FUNCTION() BytesContainer LoadSurface();
|
||||
API_FUNCTION() BytesContainer LoadSurface() const;
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="data">Stream with graph data.</param>
|
||||
/// <returns>True if cannot save it, otherwise false.</returns>
|
||||
API_FUNCTION() bool SaveSurface(BytesContainer& data);
|
||||
API_FUNCTION() bool SaveSurface(const BytesContainer& data);
|
||||
|
||||
private:
|
||||
void FindDependencies(AnimGraphBase* graph);
|
||||
@@ -65,6 +65,7 @@ public:
|
||||
// [BinaryAsset]
|
||||
#if USE_EDITOR
|
||||
void GetReferences(Array<Guid>& assets, Array<String>& files) const override;
|
||||
bool Save(const StringView& path = StringView::Empty) override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Core/Types/DataContainer.h"
|
||||
#include "Engine/Serialization/MemoryReadStream.h"
|
||||
#if USE_EDITOR
|
||||
#include "Engine/Serialization/MemoryWriteStream.h"
|
||||
#endif
|
||||
#include "Engine/Content/Factories/BinaryAssetFactory.h"
|
||||
#include "Engine/Threading/Threading.h"
|
||||
|
||||
@@ -84,19 +87,10 @@ void AnimationGraphFunction::GetSignature(Array<StringView, FixedAllocation<32>>
|
||||
}
|
||||
}
|
||||
|
||||
bool AnimationGraphFunction::SaveSurface(const BytesContainer& data)
|
||||
bool AnimationGraphFunction::SaveSurface(const BytesContainer& data) const
|
||||
{
|
||||
// Wait for asset to be loaded or don't if last load failed
|
||||
if (LastLoadFailed())
|
||||
{
|
||||
LOG(Warning, "Saving asset that failed to load.");
|
||||
}
|
||||
else if (WaitForLoaded())
|
||||
{
|
||||
LOG(Error, "Asset loading failed. Cannot save it.");
|
||||
if (OnCheckSave())
|
||||
return true;
|
||||
}
|
||||
|
||||
ScopeLock lock(Locker);
|
||||
|
||||
// Set Visject Surface data
|
||||
@@ -185,3 +179,24 @@ void AnimationGraphFunction::ProcessGraphForSignature(AnimGraphBase* graph, bool
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
bool AnimationGraphFunction::Save(const StringView& path)
|
||||
{
|
||||
if (OnCheckSave(path))
|
||||
return true;
|
||||
ScopeLock lock(Locker);
|
||||
AnimGraph graph(const_cast<AnimationGraphFunction*>(this), true);
|
||||
MemoryReadStream readStream(GraphData.Get(), GraphData.Length());
|
||||
if (graph.Load(&readStream, true))
|
||||
return true;
|
||||
MemoryWriteStream writeStream;
|
||||
if (graph.Save(&writeStream, true))
|
||||
return true;
|
||||
BytesContainer data;
|
||||
data.Link(ToSpan(writeStream));
|
||||
return SaveSurface(data);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -53,13 +53,19 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="data">The surface graph data.</param>
|
||||
/// <returns>True if cannot save it, otherwise false.</returns>
|
||||
API_FUNCTION() bool SaveSurface(const BytesContainer& data);
|
||||
API_FUNCTION() bool SaveSurface(const BytesContainer& data) const;
|
||||
|
||||
#endif
|
||||
|
||||
private:
|
||||
void ProcessGraphForSignature(AnimGraphBase* graph, bool canUseOutputs);
|
||||
|
||||
public:
|
||||
// [BinaryAsset]
|
||||
#if USE_EDITOR
|
||||
bool Save(const StringView& path = StringView::Empty) override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// [BinaryAsset]
|
||||
LoadResult load() override;
|
||||
|
||||
@@ -191,12 +191,13 @@ Asset::LoadResult Material::load()
|
||||
auto lock = Storage->Lock();
|
||||
|
||||
// Prepare
|
||||
const String name = ToString();
|
||||
MaterialGenerator generator;
|
||||
generator.Error.Bind(&OnGeneratorError);
|
||||
if (_shaderHeader.Material.GraphVersion != MATERIAL_GRAPH_VERSION)
|
||||
LOG(Info, "Converting material \'{0}\', from version {1} to {2}...", ToString(), _shaderHeader.Material.GraphVersion, MATERIAL_GRAPH_VERSION);
|
||||
LOG(Info, "Converting material \'{0}\', from version {1} to {2}...", name, _shaderHeader.Material.GraphVersion, MATERIAL_GRAPH_VERSION);
|
||||
else
|
||||
LOG(Info, "Updating material \'{0}\'...", ToString());
|
||||
LOG(Info, "Updating material \'{0}\'...", name);
|
||||
|
||||
// Load or create material surface
|
||||
MaterialLayer* layer;
|
||||
@@ -205,7 +206,7 @@ Asset::LoadResult Material::load()
|
||||
// Load graph
|
||||
if (LoadChunks(GET_CHUNK_FLAG(SHADER_FILE_CHUNK_VISJECT_SURFACE)))
|
||||
{
|
||||
LOG(Warning, "Cannot load \'{0}\' data from chunk {1}.", ToString(), SHADER_FILE_CHUNK_VISJECT_SURFACE);
|
||||
LOG(Warning, "Cannot load \'{0}\' data from chunk {1}.", name, SHADER_FILE_CHUNK_VISJECT_SURFACE);
|
||||
return LoadResult::Failed;
|
||||
}
|
||||
|
||||
@@ -214,7 +215,19 @@ Asset::LoadResult Material::load()
|
||||
MemoryReadStream stream(surfaceChunk->Get(), surfaceChunk->Size());
|
||||
|
||||
// Load layer
|
||||
layer = MaterialLayer::Load(GetID(), &stream, _shaderHeader.Material.Info, ToString());
|
||||
layer = MaterialLayer::Load(GetID(), &stream, _shaderHeader.Material.Info, name);
|
||||
if (ContentDeprecated::Clear())
|
||||
{
|
||||
// If encountered any deprecated data when loading graph then serialize it
|
||||
MaterialGraph graph;
|
||||
MemoryWriteStream writeStream(1024);
|
||||
stream.SetPosition(0);
|
||||
if (!graph.Load(&stream, true) && !graph.Save(&writeStream, true))
|
||||
{
|
||||
surfaceChunk->Data.Copy(ToSpan(writeStream));
|
||||
ContentDeprecated::Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -245,7 +258,7 @@ Asset::LoadResult Material::load()
|
||||
MaterialInfo info = _shaderHeader.Material.Info;
|
||||
if (generator.Generate(source, info, materialParamsChunk->Data))
|
||||
{
|
||||
LOG(Error, "Cannot generate material source code for \'{0}\'. Please see log for more info.", ToString());
|
||||
LOG(Error, "Cannot generate material source code for \'{0}\'. Please see log for more info.", name);
|
||||
return LoadResult::Failed;
|
||||
}
|
||||
|
||||
@@ -282,9 +295,9 @@ Asset::LoadResult Material::load()
|
||||
|
||||
// Save to file
|
||||
#if USE_EDITOR
|
||||
if (Save())
|
||||
if (SaveShaderAsset())
|
||||
{
|
||||
LOG(Error, "Cannot save \'{0}\'", ToString());
|
||||
LOG(Error, "Cannot save \'{0}\'", name);
|
||||
return LoadResult::Failed;
|
||||
}
|
||||
#endif
|
||||
@@ -505,6 +518,25 @@ void Material::InitCompilationOptions(ShaderCompilationOptions& options)
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Material::Save(const StringView& path)
|
||||
{
|
||||
if (OnCheckSave(path))
|
||||
return true;
|
||||
ScopeLock lock(Locker);
|
||||
BytesContainer existingData = LoadSurface(true);
|
||||
if (existingData.IsInvalid())
|
||||
return true;
|
||||
MaterialGraph graph;
|
||||
MemoryWriteStream writeStream(existingData.Length());
|
||||
MemoryReadStream readStream(existingData);
|
||||
if (graph.Load(&readStream, true) || graph.Save(&writeStream, true))
|
||||
return true;
|
||||
BytesContainer data;
|
||||
data.Link(ToSpan(writeStream));
|
||||
auto materialInfo = _shaderHeader.Material.Info;
|
||||
return SaveSurface(data, materialInfo);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
BytesContainer Material::LoadSurface(bool createDefaultIfMissing)
|
||||
@@ -555,17 +587,8 @@ BytesContainer Material::LoadSurface(bool createDefaultIfMissing)
|
||||
|
||||
bool Material::SaveSurface(const BytesContainer& data, const MaterialInfo& info)
|
||||
{
|
||||
// Wait for asset to be loaded or don't if last load failed (eg. by shader source compilation error)
|
||||
if (LastLoadFailed())
|
||||
{
|
||||
LOG(Warning, "Saving asset that failed to load.");
|
||||
}
|
||||
else if (WaitForLoaded())
|
||||
{
|
||||
LOG(Error, "Asset loading failed. Cannot save it.");
|
||||
if (OnCheckSave())
|
||||
return true;
|
||||
}
|
||||
|
||||
ScopeLock lock(Locker);
|
||||
|
||||
// Release all chunks
|
||||
@@ -582,7 +605,7 @@ bool Material::SaveSurface(const BytesContainer& data, const MaterialInfo& info)
|
||||
ASSERT(visjectSurfaceChunk != nullptr);
|
||||
visjectSurfaceChunk->Data.Copy(data);
|
||||
|
||||
if (Save())
|
||||
if (SaveShaderAsset())
|
||||
{
|
||||
LOG(Error, "Cannot save \'{0}\'", ToString());
|
||||
return true;
|
||||
|
||||
@@ -13,6 +13,7 @@ class MaterialShader;
|
||||
API_CLASS(NoSpawn) class FLAXENGINE_API Material : public ShaderAssetTypeBase<MaterialBase>
|
||||
{
|
||||
DECLARE_BINARY_ASSET_HEADER(Material, ShadersSerializedVersion);
|
||||
|
||||
private:
|
||||
MaterialShader* _materialShader = nullptr;
|
||||
|
||||
@@ -25,7 +26,6 @@ public:
|
||||
API_FUNCTION() BytesContainer LoadSurface(bool createDefaultIfMissing);
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
/// <summary>
|
||||
/// Updates the material surface (save new one, discard cached data, reload asset).
|
||||
/// </summary>
|
||||
@@ -33,7 +33,6 @@ public:
|
||||
/// <param name="info">The material info structure.</param>
|
||||
/// <returns>True if cannot save it, otherwise false.</returns>
|
||||
API_FUNCTION() bool SaveSurface(const BytesContainer& data, const MaterialInfo& info);
|
||||
|
||||
#endif
|
||||
|
||||
public:
|
||||
@@ -52,6 +51,7 @@ public:
|
||||
// [ShaderAssetBase]
|
||||
#if USE_EDITOR
|
||||
void InitCompilationOptions(ShaderCompilationOptions& options) override;
|
||||
bool Save(const StringView& path = StringView::Empty) override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Core/Types/DataContainer.h"
|
||||
#include "Engine/Serialization/MemoryReadStream.h"
|
||||
#include "Engine/Serialization/MemoryWriteStream.h"
|
||||
#endif
|
||||
#include "Engine/Content/Factories/BinaryAssetFactory.h"
|
||||
|
||||
@@ -24,7 +25,7 @@ Asset::LoadResult MaterialFunction::load()
|
||||
if (!surfaceChunk || !surfaceChunk->IsLoaded())
|
||||
return LoadResult::MissingDataChunk;
|
||||
MemoryReadStream stream(surfaceChunk->Get(), surfaceChunk->Size());
|
||||
if (Graph.Load(&stream, false))
|
||||
if (Graph.Load(&stream, USE_EDITOR))
|
||||
return LoadResult::Failed;
|
||||
|
||||
// Cache input and output nodes
|
||||
@@ -89,7 +90,7 @@ BytesContainer MaterialFunction::LoadSurface()
|
||||
return result;
|
||||
}
|
||||
|
||||
bool MaterialFunction::LoadSurface(MaterialGraph& graph)
|
||||
bool MaterialFunction::LoadSurface(MaterialGraph& graph, bool loadMeta)
|
||||
{
|
||||
if (WaitForLoaded())
|
||||
return true;
|
||||
@@ -100,7 +101,7 @@ bool MaterialFunction::LoadSurface(MaterialGraph& graph)
|
||||
{
|
||||
const auto surfaceChunk = GetChunk(0);
|
||||
MemoryReadStream stream(surfaceChunk->Get(), surfaceChunk->Size());
|
||||
return graph.Load(&stream, false);
|
||||
return graph.Load(&stream, loadMeta);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -128,19 +129,10 @@ void MaterialFunction::GetSignature(Array<StringView, FixedAllocation<32>>& type
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
bool MaterialFunction::SaveSurface(BytesContainer& data)
|
||||
bool MaterialFunction::SaveSurface(const BytesContainer& data) const
|
||||
{
|
||||
// Wait for asset to be loaded or don't if last load failed
|
||||
if (LastLoadFailed())
|
||||
{
|
||||
LOG(Warning, "Saving asset that failed to load.");
|
||||
}
|
||||
else if (WaitForLoaded())
|
||||
{
|
||||
LOG(Error, "Asset loading failed. Cannot save it.");
|
||||
if (OnCheckSave())
|
||||
return true;
|
||||
}
|
||||
|
||||
ScopeLock lock(Locker);
|
||||
|
||||
// Set Visject Surface data
|
||||
@@ -160,4 +152,17 @@ bool MaterialFunction::SaveSurface(BytesContainer& data)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MaterialFunction::Save(const StringView& path)
|
||||
{
|
||||
if (OnCheckSave(path))
|
||||
return true;
|
||||
ScopeLock lock(Locker);
|
||||
MemoryWriteStream writeStream;
|
||||
if (Graph.Save(&writeStream, true))
|
||||
return true;
|
||||
BytesContainer data;
|
||||
data.Link(ToSpan(writeStream));
|
||||
return SaveSurface(data);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
API_CLASS(NoSpawn) class FLAXENGINE_API MaterialFunction : public BinaryAsset
|
||||
{
|
||||
DECLARE_BINARY_ASSET_HEADER(MaterialFunction, 1);
|
||||
|
||||
public:
|
||||
#if COMPILE_WITH_MATERIAL_GRAPH
|
||||
|
||||
/// <summary>
|
||||
/// The loaded material function graph.
|
||||
/// </summary>
|
||||
@@ -39,8 +39,9 @@ public:
|
||||
/// Tries to load surface graph from the asset.
|
||||
/// </summary>
|
||||
/// <param name="graph">The graph to load.</param>
|
||||
/// <param name="loadMeta">True if load metadata.</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
bool LoadSurface(MaterialGraph& graph);
|
||||
bool LoadSurface(MaterialGraph& graph, bool loadMeta = false);
|
||||
|
||||
// Gets the function signature for Visject Surface editor.
|
||||
API_FUNCTION() void GetSignature(API_PARAM(Out) Array<StringView, FixedAllocation<32>>& types, API_PARAM(Out) Array<StringView, FixedAllocation<32>>& names);
|
||||
@@ -48,14 +49,18 @@ public:
|
||||
#endif
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
/// <summary>
|
||||
/// Updates the material graph surface (save new one, discards cached data, reloads asset).
|
||||
/// </summary>
|
||||
/// <param name="data">The surface graph data.</param>
|
||||
/// <returns>True if cannot save it, otherwise false.</returns>
|
||||
API_FUNCTION() bool SaveSurface(BytesContainer& data);
|
||||
API_FUNCTION() bool SaveSurface(const BytesContainer& data) const;
|
||||
#endif
|
||||
|
||||
public:
|
||||
// [BinaryAsset]
|
||||
#if USE_EDITOR
|
||||
bool Save(const StringView& path = StringView::Empty) override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
@@ -310,18 +310,8 @@ void MaterialInstance::ResetParameters()
|
||||
|
||||
bool MaterialInstance::Save(const StringView& path)
|
||||
{
|
||||
// Validate state
|
||||
if (WaitForLoaded())
|
||||
{
|
||||
LOG(Error, "Asset loading failed. Cannot save it.");
|
||||
if (OnCheckSave(path))
|
||||
return true;
|
||||
}
|
||||
if (IsVirtual() && path.IsEmpty())
|
||||
{
|
||||
LOG(Error, "To save virtual asset asset you need to specify the target asset path location.");
|
||||
return true;
|
||||
}
|
||||
|
||||
ScopeLock lock(Locker);
|
||||
|
||||
// Save instance data
|
||||
|
||||
@@ -33,18 +33,6 @@ public:
|
||||
/// </summary>
|
||||
API_FUNCTION() void ResetParameters();
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
/// <summary>
|
||||
/// Saves this asset to the file. Supported only in Editor.
|
||||
/// </summary>
|
||||
/// <remarks>If you use saving with the GPU mesh data then the call has to be provided from the thread other than the main game thread.</remarks>
|
||||
/// <param name="path">The custom asset path to use for the saving. Use empty value to save this asset to its own storage location. Can be used to duplicate asset. Must be specified when saving virtual asset.</param>
|
||||
/// <returns>True if cannot save data, otherwise false.</returns>
|
||||
API_FUNCTION() bool Save(const StringView& path = StringView::Empty);
|
||||
|
||||
#endif
|
||||
|
||||
private:
|
||||
void OnBaseSet();
|
||||
void OnBaseUnset();
|
||||
@@ -56,6 +44,7 @@ public:
|
||||
bool IsMaterialInstance() const override;
|
||||
#if USE_EDITOR
|
||||
void GetReferences(Array<Guid>& assets, Array<String>& files) const override;
|
||||
bool Save(const StringView& path = StringView::Empty) override;
|
||||
#endif
|
||||
|
||||
// [IMaterial]
|
||||
|
||||
@@ -400,7 +400,7 @@ bool Model::LoadHeader(ReadStream& stream, byte& headerVersion)
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
bool Model::SaveHeader(WriteStream& stream)
|
||||
bool Model::SaveHeader(WriteStream& stream) const
|
||||
{
|
||||
if (ModelBase::SaveHeader(stream))
|
||||
return true;
|
||||
@@ -457,7 +457,7 @@ bool Model::SaveHeader(WriteStream& stream, const ModelData& modelData)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Model::Save(bool withMeshDataFromGpu, Function<FlaxChunk*(int32)>& getChunk)
|
||||
bool Model::Save(bool withMeshDataFromGpu, Function<FlaxChunk*(int32)>& getChunk) const
|
||||
{
|
||||
if (ModelBase::Save(withMeshDataFromGpu, getChunk))
|
||||
return true;
|
||||
|
||||
@@ -271,9 +271,9 @@ private:
|
||||
bool LoadHeader(ReadStream& stream, byte& headerVersion);
|
||||
#if USE_EDITOR
|
||||
friend class ImportModel;
|
||||
bool SaveHeader(WriteStream& stream) override;
|
||||
bool SaveHeader(WriteStream& stream) const override;
|
||||
static bool SaveHeader(WriteStream& stream, const ModelData& modelData);
|
||||
bool Save(bool withMeshDataFromGpu, Function<FlaxChunk*(int32)>& getChunk) override;
|
||||
bool Save(bool withMeshDataFromGpu, Function<FlaxChunk*(int32)>& getChunk) const override;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
@@ -218,16 +218,8 @@ void ModelBase::GetLODData(int32 lodIndex, BytesContainer& data) const
|
||||
bool ModelBase::Save(bool withMeshDataFromGpu, const StringView& path)
|
||||
{
|
||||
// Validate state
|
||||
if (WaitForLoaded())
|
||||
{
|
||||
LOG(Error, "Asset loading failed. Cannot save it.");
|
||||
if (OnCheckSave(path))
|
||||
return true;
|
||||
}
|
||||
if (IsVirtual() && path.IsEmpty())
|
||||
{
|
||||
LOG(Error, "To save virtual asset asset you need to specify the target asset path location.");
|
||||
return true;
|
||||
}
|
||||
if (withMeshDataFromGpu && IsInMainThread())
|
||||
{
|
||||
LOG(Error, "To save model with GPU mesh buffers it needs to be called from the other thread (not the main thread).");
|
||||
@@ -238,7 +230,6 @@ bool ModelBase::Save(bool withMeshDataFromGpu, const StringView& path)
|
||||
LOG(Error, "To save virtual model asset you need to specify 'withMeshDataFromGpu' (it has no other storage container to get data).");
|
||||
return true;
|
||||
}
|
||||
|
||||
ScopeLock lock(Locker);
|
||||
|
||||
// Use a temporary chunks for data storage for virtual assets
|
||||
@@ -399,7 +390,7 @@ bool ModelBase::LoadMesh(MemoryReadStream& stream, byte meshVersion, MeshBase* m
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
bool ModelBase::SaveHeader(WriteStream& stream)
|
||||
bool ModelBase::SaveHeader(WriteStream& stream) const
|
||||
{
|
||||
// Basic info
|
||||
static_assert(MODEL_HEADER_VERSION == 2, "Update code");
|
||||
@@ -852,7 +843,7 @@ bool ModelBase::SaveMesh(WriteStream& stream, const MeshBase* mesh) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ModelBase::Save(bool withMeshDataFromGpu, Function<FlaxChunk*(int32)>& getChunk)
|
||||
bool ModelBase::Save(bool withMeshDataFromGpu, Function<FlaxChunk*(int32)>& getChunk) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -876,6 +867,11 @@ void ModelBase::GetReferences(Array<Guid>& assets, Array<String>& files) const
|
||||
assets.Add(slot.Material.GetID());
|
||||
}
|
||||
|
||||
bool ModelBase::Save(const StringView& path)
|
||||
{
|
||||
return Save(false, path);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int32 ModelBase::GetCurrentResidency() const
|
||||
|
||||
@@ -331,12 +331,12 @@ protected:
|
||||
virtual bool LoadMesh(class MemoryReadStream& stream, byte meshVersion, MeshBase* mesh, MeshData* dataIfReadOnly = nullptr);
|
||||
bool LoadHeader(ReadStream& stream, byte& headerVersion);
|
||||
#if USE_EDITOR
|
||||
virtual bool SaveHeader(WriteStream& stream);
|
||||
virtual bool SaveHeader(WriteStream& stream) const;
|
||||
static bool SaveHeader(WriteStream& stream, const class ModelData& modelData);
|
||||
bool SaveLOD(WriteStream& stream, int32 lodIndex) const;
|
||||
static bool SaveLOD(WriteStream& stream, const ModelData& modelData, int32 lodIndex, bool(saveMesh)(WriteStream& stream, const ModelData& modelData, int32 lodIndex, int32 meshIndex) = nullptr);
|
||||
virtual bool SaveMesh(WriteStream& stream, const MeshBase* mesh) const;
|
||||
virtual bool Save(bool withMeshDataFromGpu, Function<FlaxChunk*(int32)>& getChunk);
|
||||
virtual bool Save(bool withMeshDataFromGpu, Function<FlaxChunk*(int32)>& getChunk) const;
|
||||
#endif
|
||||
|
||||
public:
|
||||
@@ -344,6 +344,7 @@ public:
|
||||
void CancelStreaming() override;
|
||||
#if USE_EDITOR
|
||||
void GetReferences(Array<Guid>& assets, Array<String>& files) const override;
|
||||
bool Save(const StringView& path = StringView::Empty) override;
|
||||
#endif
|
||||
|
||||
// [StreamableResource]
|
||||
|
||||
@@ -18,18 +18,8 @@ RawDataAsset::RawDataAsset(const SpawnParams& params, const AssetInfo* info)
|
||||
|
||||
bool RawDataAsset::Save(const StringView& path)
|
||||
{
|
||||
// Validate state
|
||||
if (WaitForLoaded())
|
||||
{
|
||||
LOG(Error, "Asset loading failed. Cannot save it.");
|
||||
if (OnCheckSave(path))
|
||||
return true;
|
||||
}
|
||||
if (IsVirtual() && path.IsEmpty())
|
||||
{
|
||||
LOG(Error, "To save virtual asset asset you need to specify the target asset path location.");
|
||||
return true;
|
||||
}
|
||||
|
||||
ScopeLock lock(Locker);
|
||||
|
||||
bool result;
|
||||
|
||||
@@ -16,20 +16,11 @@ public:
|
||||
/// </summary>
|
||||
API_FIELD() Array<byte> Data;
|
||||
|
||||
public:
|
||||
#if USE_EDITOR
|
||||
|
||||
/// <summary>
|
||||
/// Saves this asset to the file. Supported only in Editor.
|
||||
/// </summary>
|
||||
/// <param name="path">The custom asset path to use for the saving. Use empty value to save this asset to its own storage location. Can be used to duplicate asset. Must be specified when saving virtual asset.</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
API_FUNCTION() bool Save(const StringView& path = StringView::Empty);
|
||||
|
||||
#endif
|
||||
|
||||
public:
|
||||
// [BinaryAsset]
|
||||
#if USE_EDITOR
|
||||
bool Save(const StringView& path = StringView::Empty) override;
|
||||
#endif
|
||||
uint64 GetMemoryUsage() const override;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -66,18 +66,8 @@ const BitArray<>& SkeletonMask::GetNodesMask()
|
||||
|
||||
bool SkeletonMask::Save(const StringView& path)
|
||||
{
|
||||
// Validate state
|
||||
if (WaitForLoaded())
|
||||
{
|
||||
LOG(Error, "Asset loading failed. Cannot save it.");
|
||||
if (OnCheckSave(path))
|
||||
return true;
|
||||
}
|
||||
if (IsVirtual() && path.IsEmpty())
|
||||
{
|
||||
LOG(Error, "To save virtual asset asset you need to specify the target asset path location.");
|
||||
return true;
|
||||
}
|
||||
|
||||
ScopeLock lock(Locker);
|
||||
|
||||
// Write data
|
||||
|
||||
@@ -51,17 +51,6 @@ public:
|
||||
/// <returns>The constant reference to the skeleton nodes mask.</returns>
|
||||
API_PROPERTY() const BitArray<>& GetNodesMask();
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
/// <summary>
|
||||
/// Saves this asset to the file. Supported only in Editor.
|
||||
/// </summary>
|
||||
/// <param name="path">The custom asset path to use for the saving. Use empty value to save this asset to its own storage location. Can be used to duplicate asset. Must be specified when saving virtual asset.</param>
|
||||
/// <returns>True if cannot save data, otherwise false.</returns>
|
||||
API_FUNCTION() bool Save(const StringView& path = StringView::Empty);
|
||||
|
||||
#endif
|
||||
|
||||
private:
|
||||
void OnSkeletonUnload();
|
||||
|
||||
@@ -73,6 +62,7 @@ public:
|
||||
BinaryAsset::GetReferences(assets, files);
|
||||
assets.Add(Skeleton.GetID());
|
||||
}
|
||||
bool Save(const StringView& path = StringView::Empty) override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
@@ -661,7 +661,7 @@ bool SkinnedModel::LoadHeader(ReadStream& stream, byte& headerVersion)
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
bool SkinnedModel::SaveHeader(WriteStream& stream)
|
||||
bool SkinnedModel::SaveHeader(WriteStream& stream) const
|
||||
{
|
||||
if (ModelBase::SaveHeader(stream))
|
||||
return true;
|
||||
|
||||
@@ -299,7 +299,7 @@ private:
|
||||
bool LoadHeader(ReadStream& stream, byte& headerVersion);
|
||||
#if USE_EDITOR
|
||||
friend class ImportModel;
|
||||
bool SaveHeader(WriteStream& stream) override;
|
||||
bool SaveHeader(WriteStream& stream) const override;
|
||||
static bool SaveHeader(WriteStream& stream, const ModelData& modelData);
|
||||
bool SaveMesh(WriteStream& stream, const MeshBase* mesh) const override;
|
||||
static bool SaveMesh(WriteStream& stream, const ModelData& modelData, int32 lodIndex, int32 meshIndex);
|
||||
|
||||
@@ -29,24 +29,19 @@ bool Texture::IsNormalMap() const
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
bool Texture::Save(const StringView& path)
|
||||
{
|
||||
return Save(path, nullptr);
|
||||
}
|
||||
|
||||
bool Texture::Save(const StringView& path, const InitData* customData)
|
||||
{
|
||||
// Validate state
|
||||
if (WaitForLoaded())
|
||||
{
|
||||
LOG(Error, "Asset loading failed. Cannot save it.");
|
||||
if (OnCheckSave())
|
||||
return true;
|
||||
}
|
||||
if (IsVirtual() && path.IsEmpty())
|
||||
{
|
||||
LOG(Error, "To save virtual asset asset you need to specify the target asset path location.");
|
||||
return true;
|
||||
}
|
||||
|
||||
ScopeLock lock(Locker);
|
||||
|
||||
AssetInitData data;
|
||||
const auto texture = StreamingTexture();
|
||||
const class StreamingTexture* texture = StreamingTexture();
|
||||
|
||||
// Use a temporary chunks for data storage for virtual assets
|
||||
FlaxChunk* tmpChunks[ASSET_FILE_DATA_CHUNKS];
|
||||
|
||||
@@ -23,17 +23,6 @@ API_CLASS(NoSpawn) class FLAXENGINE_API Texture : public TextureBase
|
||||
|
||||
public:
|
||||
#if USE_EDITOR
|
||||
|
||||
/// <summary>
|
||||
/// Saves this asset to the file. Supported only in Editor.
|
||||
/// </summary>
|
||||
/// <param name="path">The custom asset path to use for the saving. Use empty value to save this asset to its own storage location. Can be used to duplicate asset. Must be specified when saving virtual asset.</param>
|
||||
/// <returns>True if cannot save data, otherwise false.</returns>
|
||||
API_FUNCTION() bool Save(const StringView& path = StringView::Empty)
|
||||
{
|
||||
return Save(path, nullptr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves this asset to the file. Supported only in Editor.
|
||||
/// </summary>
|
||||
@@ -41,7 +30,6 @@ public:
|
||||
/// <param name="customData">The custom texture data container. Can be used to override the data stored in the asset. Use null to ignore this argument.</param>
|
||||
/// <returns>True if cannot save data, otherwise false.</returns>
|
||||
bool Save(const StringView& path, const InitData* customData);
|
||||
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
@@ -60,4 +48,10 @@ public:
|
||||
/// <param name="generateMips">True if generate mipmaps for the imported texture.</param>
|
||||
/// <returns>The loaded texture (virtual asset) or null if fails.</returns>
|
||||
API_FUNCTION() static Texture* FromFile(const StringView& path, bool generateMips = false);
|
||||
|
||||
public:
|
||||
// [TextureBase]
|
||||
#if USE_EDITOR
|
||||
bool Save(const StringView& path = StringView::Empty) override;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "VisualScript.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Core/Types/Span.h"
|
||||
#include "Engine/Core/Types/DataContainer.h"
|
||||
#include "Engine/Content/Content.h"
|
||||
#include "Engine/Content/Factories/BinaryAssetFactory.h"
|
||||
@@ -1303,6 +1304,23 @@ VisualScript::VisualScript(const SpawnParams& params, const AssetInfo* info)
|
||||
{
|
||||
}
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
bool VisualScript::Save(const StringView& path)
|
||||
{
|
||||
if (OnCheckSave(path))
|
||||
return true;
|
||||
ScopeLock lock(Locker);
|
||||
MemoryWriteStream writeStream;
|
||||
if (Graph.Save(&writeStream, true))
|
||||
return true;
|
||||
BytesContainer data;
|
||||
data.Link(ToSpan(writeStream));
|
||||
return SaveSurface(data, Meta);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Asset::LoadResult VisualScript::load()
|
||||
{
|
||||
// Build Visual Script typename that is based on asset id
|
||||
@@ -2184,7 +2202,7 @@ const VisualScript::Field* VisualScript::FindField(const StringAnsiView& name) c
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BytesContainer VisualScript::LoadSurface()
|
||||
BytesContainer VisualScript::LoadSurface() const
|
||||
{
|
||||
if (WaitForLoaded())
|
||||
return BytesContainer();
|
||||
@@ -2202,19 +2220,10 @@ BytesContainer VisualScript::LoadSurface()
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
bool VisualScript::SaveSurface(const BytesContainer& data, const Metadata& meta)
|
||||
bool VisualScript::SaveSurface(const BytesContainer& data, const Metadata& meta) const
|
||||
{
|
||||
// Wait for asset to be loaded or don't if last load failed
|
||||
if (LastLoadFailed())
|
||||
{
|
||||
LOG(Warning, "Saving asset that failed to load.");
|
||||
}
|
||||
else if (WaitForLoaded())
|
||||
{
|
||||
LOG(Error, "Asset loading failed. Cannot save it.");
|
||||
if (OnCheckSave())
|
||||
return true;
|
||||
}
|
||||
|
||||
ScopeLock lock(Locker);
|
||||
|
||||
// Release all chunks
|
||||
|
||||
@@ -246,7 +246,7 @@ public:
|
||||
/// Tries to load surface graph from the asset.
|
||||
/// </summary>
|
||||
/// <returns>The surface data or empty if failed to load it.</returns>
|
||||
API_FUNCTION() BytesContainer LoadSurface();
|
||||
API_FUNCTION() BytesContainer LoadSurface() const;
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
@@ -256,7 +256,7 @@ public:
|
||||
/// <param name="data">Stream with graph data.</param>
|
||||
/// <param name="meta">Script metadata.</param>
|
||||
/// <returns>True if cannot save it, otherwise false.</returns>
|
||||
API_FUNCTION() bool SaveSurface(const BytesContainer& data, API_PARAM(Ref) const Metadata& meta);
|
||||
API_FUNCTION() bool SaveSurface(const BytesContainer& data, API_PARAM(Ref) const Metadata& meta) const;
|
||||
|
||||
// Returns the amount of methods in the script.
|
||||
API_FUNCTION() int32 GetMethodsCount() const
|
||||
@@ -286,6 +286,7 @@ public:
|
||||
BinaryAsset::GetReferences(assets, files);
|
||||
Graph.GetReferences(assets);
|
||||
}
|
||||
bool Save(const StringView& path = StringView::Empty) override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
@@ -406,7 +407,6 @@ public:
|
||||
static Variant Invoke(VisualScript::Method* method, ScriptingObject* instance, Span<Variant> parameters = Span<Variant>());
|
||||
|
||||
#if VISUAL_SCRIPT_DEBUGGING
|
||||
|
||||
// Custom event that is called every time the Visual Script signal flows over the graph (including the data connections). Can be used to read nad visualize the Visual Script execution logic.
|
||||
static Action DebugFlow;
|
||||
|
||||
@@ -420,6 +420,5 @@ public:
|
||||
/// <param name="result">The output value. Valid only if method returned true.</param>
|
||||
/// <returns>True if could fetch the value, otherwise false.</returns>
|
||||
static bool Evaluate(VisualScript* script, ScriptingObject* instance, uint32 nodeId, uint32 boxId, Variant& result);
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user