Added all the missing serializer support, fixed up serialization notification

Signed-off-by: chcurran <82187351+carlitosan@users.noreply.github.com>
monroegm-disable-blank-issue-2
chcurran 4 years ago
parent c701522adc
commit d7d2e84fee

@ -10,7 +10,6 @@ set(FILES
ArrayView.cpp ArrayView.cpp
ConcurrencyCheckerTests.cpp ConcurrencyCheckerTests.cpp
InstanceDatabase.cpp InstanceDatabase.cpp
JsonSerializationUtilsTests.cpp
lru_cache.cpp lru_cache.cpp
Main.cpp Main.cpp
vector_set.cpp vector_set.cpp

@ -209,39 +209,35 @@ namespace AZ
//! performance sensitive code. //! performance sensitive code.
AZ_INLINE bool CompareAnyValue(const AZStd::any& lhs, const AZStd::any& rhs) AZ_INLINE bool CompareAnyValue(const AZStd::any& lhs, const AZStd::any& rhs)
{ {
bool isEqual = false; if (lhs.type() == rhs.type())
if (lhs.type() != rhs.type())
{ {
return false; AZ::SerializeContext* serializeContext = nullptr;
} AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
AZ::SerializeContext* serializeContext = nullptr; const AZ::SerializeContext::ClassData* classData = serializeContext->FindClassData(lhs.type());
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext); if (classData)
const AZ::SerializeContext::ClassData* classData = serializeContext->FindClassData(lhs.type());
if (classData)
{
if (classData->m_serializer)
{ {
isEqual = classData->m_serializer->CompareValueData(AZStd::any_cast<void>(&lhs), AZStd::any_cast<void>(&rhs)); if (classData->m_serializer)
} {
else return classData->m_serializer->CompareValueData(AZStd::any_cast<void>(&lhs), AZStd::any_cast<void>(&rhs));
{ }
AZStd::vector<AZ::u8> myData; else
AZ::IO::ByteContainerStream<decltype(myData)> myDataStream(&myData); {
AZStd::vector<AZ::u8> myData;
AZ::Utils::SaveObjectToStream(myDataStream, AZ::ObjectStream::ST_BINARY, AZStd::any_cast<void>(&lhs), lhs.type()); AZ::IO::ByteContainerStream<decltype(myData)> myDataStream(&myData);
AZStd::vector<AZ::u8> otherData; AZ::Utils::SaveObjectToStream(myDataStream, AZ::ObjectStream::ST_BINARY, AZStd::any_cast<void>(&lhs), lhs.type());
AZ::IO::ByteContainerStream<decltype(otherData)> otherDataStream(&otherData);
AZStd::vector<AZ::u8> otherData;
AZ::Utils::SaveObjectToStream(otherDataStream, AZ::ObjectStream::ST_BINARY, AZStd::any_cast<void>(&rhs), rhs.type()); AZ::IO::ByteContainerStream<decltype(otherData)> otherDataStream(&otherData);
isEqual = (myData.size() == otherData.size()) && (memcmp(myData.data(), otherData.data(), myData.size()) == 0);
AZ::Utils::SaveObjectToStream(otherDataStream, AZ::ObjectStream::ST_BINARY, AZStd::any_cast<void>(&rhs), rhs.type());
return (myData.size() == otherData.size()) && (memcmp(myData.data(), otherData.data(), myData.size()) == 0);
}
} }
} }
return isEqual; return false;
} }
} }
} }

@ -213,7 +213,7 @@ namespace AZ
void* object, const Uuid& typeId, const rapidjson::Value& value, JsonDeserializerContext& context, ContinuationFlags flags) void* object, const Uuid& typeId, const rapidjson::Value& value, JsonDeserializerContext& context, ContinuationFlags flags)
{ {
bool loadAsNewInstance = (flags & ContinuationFlags::LoadAsNewInstance) == ContinuationFlags::LoadAsNewInstance; bool loadAsNewInstance = (flags & ContinuationFlags::LoadAsNewInstance) == ContinuationFlags::LoadAsNewInstance;
JsonDeserializer::UseTypeDeserializer useCustom = (flags & ContinuationFlags::NoTypeSerializer) == ContinuationFlags::NoTypeSerializer JsonDeserializer::UseTypeDeserializer useCustom = (flags & ContinuationFlags::IgnoreTypeSerializer) == ContinuationFlags::IgnoreTypeSerializer
? JsonDeserializer::UseTypeDeserializer::No ? JsonDeserializer::UseTypeDeserializer::No
: JsonDeserializer::UseTypeDeserializer::Yes; : JsonDeserializer::UseTypeDeserializer::Yes;
@ -228,7 +228,7 @@ namespace AZ
{ {
using namespace JsonSerializationResult; using namespace JsonSerializationResult;
JsonSerializer::UseTypeSerializer useCustom = (flags & ContinuationFlags::NoTypeSerializer) == ContinuationFlags::NoTypeSerializer JsonSerializer::UseTypeSerializer useCustom = (flags & ContinuationFlags::IgnoreTypeSerializer) == ContinuationFlags::IgnoreTypeSerializer
? JsonSerializer::UseTypeSerializer::No ? JsonSerializer::UseTypeSerializer::No
: JsonSerializer::UseTypeSerializer::Yes; : JsonSerializer::UseTypeSerializer::Yes;

@ -159,13 +159,13 @@ namespace AZ
enum class ContinuationFlags enum class ContinuationFlags
{ {
None = 0, //! No extra flags. None = 0, //! No extra flags.
ResolvePointer = 1 << 0, //! The pointer passed in contains a pointer. The (de)serializer will attempt to resolve to an instance. ResolvePointer = 1 << 0, //! The pointer passed in contains a pointer. The (de)serializer will attempt to resolve to an instance.
ReplaceDefault = 1 << 1, //! The default value provided for storing will be replaced with a newly created one. ReplaceDefault = 1 << 1, //! The default value provided for storing will be replaced with a newly created one.
LoadAsNewInstance = 1 << 2, //! Treats the value as if it's a newly created instance. This may trigger serializers marked with LoadAsNewInstance = 1 << 2, //! Treats the value as if it's a newly created instance. This may trigger serializers marked with
//! OperationFlags::InitializeNewInstance. Used for instance by pointers or new instances added to //! OperationFlags::InitializeNewInstance. Used for instance by pointers or new instances added to
//! an array. //! an array.
NoTypeSerializer = 1 << 3, //! Ignore the custom/specific serializer for the TypeId IgnoreTypeSerializer = 1 << 3, //! Ignore the custom/specific serializer for the TypeId
}; };
enum class OperationFlags enum class OperationFlags

@ -73,7 +73,9 @@ namespace AZ
} }
if (BaseJsonSerializer* serializer if (BaseJsonSerializer* serializer
= context.GetRegistrationContext()->GetSerializerForType(classData->m_azRtti->GetGenericTypeId())) = (custom == UseTypeDeserializer::Yes)
? context.GetRegistrationContext()->GetSerializerForType(classData->m_azRtti->GetGenericTypeId())
: nullptr)
{ {
return DeserializerDefaultCheck(serializer, object, typeId, value, isNewInstance, context); return DeserializerDefaultCheck(serializer, object, typeId, value, isNewInstance, context);
} }

@ -22,7 +22,7 @@
#include <AzCore/Serialization/Utils.h> #include <AzCore/Serialization/Utils.h>
#include <AzCore/Utils/Utils.h> #include <AzCore/Utils/Utils.h>
#include "JsonUtils.h" #include <AzCore/Serialization/Json/JsonUtils.h>
namespace AZ namespace AZ
{ {

@ -105,6 +105,7 @@ set(FILES
Serialization/Json/JsonSerializationResultTests.cpp Serialization/Json/JsonSerializationResultTests.cpp
Serialization/Json/JsonSerializationTests.h Serialization/Json/JsonSerializationTests.h
Serialization/Json/JsonSerializationTests.cpp Serialization/Json/JsonSerializationTests.cpp
Serialization/Json/JsonSerializationUtilsTests.cpp
Serialization/Json/JsonSerializerConformityTests.h Serialization/Json/JsonSerializerConformityTests.h
Serialization/Json/JsonSerializerMock.h Serialization/Json/JsonSerializerMock.h
Serialization/Json/MapSerializerTests.cpp Serialization/Json/MapSerializerTests.cpp

@ -19,7 +19,6 @@
#include <Atom/RPI.Public/Material/Material.h> #include <Atom/RPI.Public/Material/Material.h>
#include <Material/MaterialAssetTestUtils.h> #include <Material/MaterialAssetTestUtils.h>
//#include <AzCore/Serialization/Json/JsonUtils.h>
namespace UnitTest namespace UnitTest
{ {
using namespace AZ; using namespace AZ;

@ -11,6 +11,11 @@
#include <ExpressionEvaluation/ExpressionEngine/ExpressionTypes.h> #include <ExpressionEvaluation/ExpressionEngine/ExpressionTypes.h>
namespace AZ
{
class ExpressionTreeVariableDescriptorSerializer;
}
namespace ExpressionEvaluation namespace ExpressionEvaluation
{ {
// Holds all of the tokeniszed information from parsing an expression string. // Holds all of the tokeniszed information from parsing an expression string.
@ -20,8 +25,22 @@ namespace ExpressionEvaluation
{ {
// Friend class for reflection // Friend class for reflection
friend class ExpressionEvaluationSystemComponent; friend class ExpressionEvaluationSystemComponent;
friend class ExpressionTreeVariableDescriptorSerializer;
public: public:
struct VariableDescriptor
{
AZ_TYPE_INFO(VariableDescriptor, "{5E1A0044-E0E7-46D3-8BC6-A22E226ADB83}");
VariableDescriptor()
{
m_supportedTypes.push_back(azrtti_typeid<double>());
}
AZStd::vector< AZ::Uuid > m_supportedTypes;
ExpressionVariable m_value;
};
AZ_RTTI(ExpressionTree, "{4CCF3DFD-2EA8-47CB-AF25-353BC034EF42}"); AZ_RTTI(ExpressionTree, "{4CCF3DFD-2EA8-47CB-AF25-353BC034EF42}");
AZ_CLASS_ALLOCATOR(ExpressionTree, AZ::SystemAllocator, 0); AZ_CLASS_ALLOCATOR(ExpressionTree, AZ::SystemAllocator, 0);
@ -147,18 +166,6 @@ namespace ExpressionEvaluation
private: private:
struct VariableDescriptor
{
AZ_TYPE_INFO(VariableDescriptor, "{5E1A0044-E0E7-46D3-8BC6-A22E226ADB83}");
VariableDescriptor()
{
m_supportedTypes.push_back(azrtti_typeid<double>());
}
AZStd::vector< AZ::Uuid > m_supportedTypes;
ExpressionVariable m_value;
};
AZStd::unordered_map< AZ::Crc32, VariableDescriptor > m_variables; AZStd::unordered_map< AZ::Crc32, VariableDescriptor > m_variables;

@ -0,0 +1,165 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/Memory/Memory.h>
#include <AzCore/Serialization/AZStdAnyDataContainer.inl>
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <ExpressionEvaluation/ExpressionEngine/ExpressionTypes.h>
namespace AZ
{
class ElementInformationSerializer
: public BaseJsonSerializer
{
public:
AZ_RTTI(ElementInformationSerializer, "{B33E6AA9-C700-4E3D-857C-55F362AFE57A}", BaseJsonSerializer);
AZ_CLASS_ALLOCATOR_DECL;
private:
using ElementInformation = ExpressionEvaluation::ElementInformation;
JsonSerializationResult::Result Load
( void* outputValue
, const Uuid& outputValueTypeId
, const rapidjson::Value& inputValue
, JsonDeserializerContext& context) override
{
namespace JSR = JsonSerializationResult;
AZ_Assert(outputValueTypeId == azrtti_typeid<ElementInformation>(), "ElementInformationSerializer Load against "
"output typeID that was not ElementInformation");
AZ_Assert(outputValue, "ElementInformationSerializer Load against null output");
JsonSerializationResult::ResultCode result(JSR::Tasks::ReadField);
auto outputDatum = reinterpret_cast<ElementInformation*>(outputValue);
result.Combine(ContinueLoadingFromJsonObjectField
( &outputDatum->m_id
, azrtti_typeid<decltype(outputDatum->m_id)>()
, inputValue
, "Id"
, context));
// any storage begin
auto isEmptyAny = inputValue.FindMember("isEmptyAny");
if (isEmptyAny == inputValue.MemberEnd())
{
return context.Report
(JSR::Tasks::ReadField
, JSR::Outcomes::Missing
, "ElementInformationSerializer::Load failed to load the 'isEmptyAny'' member");
}
if (!isEmptyAny->value.GetBool())
{
AZ::Uuid typeId = AZ::Uuid::CreateNull();
auto typeIdMember = inputValue.FindMember(JsonSerialization::TypeIdFieldIdentifier);
if (typeIdMember == inputValue.MemberEnd())
{
return context.Report
(JSR::Tasks::ReadField
, JSR::Outcomes::Missing
, AZStd::string::format("ElementInformationSerializer::Load failed to load the %s member"
, JsonSerialization::TypeIdFieldIdentifier));
}
result.Combine(LoadTypeId(typeId, typeIdMember->value, context));
if (typeId.IsNull())
{
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Catastrophic
, "ElementInformationSerializer::Load failed to load the AZ TypeId of the value");
}
AZStd::any storage = context.GetSerializeContext()->CreateAny(typeId);
if (storage.empty() || storage.type() != typeId)
{
return context.Report(result, "ElementInformationSerializer::Load failed to load a value matched the "
"reported AZ TypeId. The C++ declaration may have been deleted or changed.");
}
result.Combine(ContinueLoadingFromJsonObjectField(AZStd::any_cast<void>(&storage), typeId, inputValue, "Value", context));
outputDatum->m_extraStore = storage;
}
// any storage end
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
? "ElementInformationSerializer Load finished loading ElementInformation"
: "ElementInformationSerializer Load failed to load ElementInformation");
}
JsonSerializationResult::Result Store
( rapidjson::Value& outputValue
, const void* inputValue
, const void* defaultValue
, const Uuid& valueTypeId, JsonSerializerContext& context) override
{
namespace JSR = JsonSerializationResult;
AZ_Assert(valueTypeId == azrtti_typeid<ElementInformation>(), "ElementInformation Store against value typeID that "
"was not ElementInformation");
AZ_Assert(inputValue, "ElementInformation Store against null inputValue pointer ");
auto inputScriptDataPtr = reinterpret_cast<const ElementInformation*>(inputValue);
auto defaultScriptDataPtr = reinterpret_cast<const ElementInformation*>(defaultValue);
if (defaultScriptDataPtr)
{
if (inputScriptDataPtr->m_id == defaultScriptDataPtr->m_id
&& AZ::Helpers::CompareAnyValue(inputScriptDataPtr->m_extraStore, defaultScriptDataPtr->m_extraStore))
{
return context.Report
( JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "ElementInformation Store used defaults for "
"ElementInformation");
}
}
JSR::ResultCode result(JSR::Tasks::WriteValue);
outputValue.SetObject();
result.Combine(ContinueStoringToJsonObjectField
( outputValue
, "Id"
, &inputScriptDataPtr->m_id
, defaultScriptDataPtr ? &defaultScriptDataPtr->m_id : nullptr
, azrtti_typeid<decltype(inputScriptDataPtr->m_id)>()
, context));
outputValue.AddMember("isEmptyAny", rapidjson::Value(inputScriptDataPtr->m_extraStore.empty()), context.GetJsonAllocator());
if (!inputScriptDataPtr->m_extraStore.empty())
{
rapidjson::Value typeValue;
result.Combine(StoreTypeId(typeValue, inputScriptDataPtr->m_extraStore.type(), context));
outputValue.AddMember
(rapidjson::StringRef(JsonSerialization::TypeIdFieldIdentifier)
, AZStd::move(typeValue)
, context.GetJsonAllocator());
result.Combine(ContinueStoringToJsonObjectField
( outputValue
, "Value"
, AZStd::any_cast<void>(const_cast<AZStd::any*>(&inputScriptDataPtr->m_extraStore))
, defaultScriptDataPtr ? AZStd::any_cast<void>(const_cast<AZStd::any*>(&defaultScriptDataPtr->m_extraStore)) : nullptr
, inputScriptDataPtr->m_extraStore.type()
, context));
}
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
? "ElementInformation Store finished saving ElementInformation"
: "ElementInformation Store failed to save ElementInformation");
}
};
AZ_CLASS_ALLOCATOR_IMPL(ElementInformationSerializer, SystemAllocator, 0);
}

@ -6,15 +6,16 @@
* *
*/ */
#include <ExpressionEvaluationSystemComponent.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h> #include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/EditContextConstants.inl> #include <AzCore/Serialization/EditContextConstants.inl>
#include <AzCore/Serialization/Json/RegistrationContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <ExpressionEngine/InternalTypes.h> #include <ExpressionEngine/InternalTypes.h>
#include <ExpressionEngine/MathOperators/MathExpressionOperators.h> #include <ExpressionEngine/MathOperators/MathExpressionOperators.h>
#include <ExpressionEngine/Utils.h> #include <ExpressionEngine/Utils.h>
#include <ExpressionEvaluationSystemComponent.h>
#include <ExpressionPrimitivesSerializers.inl>
#include <ElementInformationSerializer.inl>
namespace ExpressionEvaluation namespace ExpressionEvaluation
{ {
@ -145,6 +146,12 @@ namespace ExpressionEvaluation
; ;
} }
} }
if (AZ::JsonRegistrationContext* jsonContext = azrtti_cast<AZ::JsonRegistrationContext*>(context))
{
jsonContext->Serializer<AZ::ExpressionTreeVariableDescriptorSerializer>()->HandlesType<ExpressionTree::VariableDescriptor>();
jsonContext->Serializer<AZ::ElementInformationSerializer>()->HandlesType<ElementInformation>();
}
} }
void ExpressionEvaluationSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) void ExpressionEvaluationSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)

@ -0,0 +1,147 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/Memory/Memory.h>
#include <AzCore/Serialization/AZStdAnyDataContainer.inl>
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <ExpressionEvaluation/ExpressionEngine/ExpressionTree.h>
namespace AZ
{
class ExpressionTreeVariableDescriptorSerializer
: public BaseJsonSerializer
{
public:
AZ_RTTI(ExpressionTreeVariableDescriptorSerializer, "{5EFF37D6-BD54-45C6-9FC6-B1E0D3A8204C}", BaseJsonSerializer);
AZ_CLASS_ALLOCATOR_DECL;
private:
using VariableDescriptor = ExpressionEvaluation::ExpressionTree::VariableDescriptor;
JsonSerializationResult::Result Load
( void* outputValue
, const Uuid& outputValueTypeId
, const rapidjson::Value& inputValue
, JsonDeserializerContext& context) override
{
namespace JSR = JsonSerializationResult;
AZ_Assert(outputValueTypeId == azrtti_typeid<VariableDescriptor>(), "ExpressionTreeVariableDescriptorSerializer Load against "
"output typeID that was not VariableDescriptor");
AZ_Assert(outputValue, "ExpressionTreeVariableDescriptorSerializer Load against null output");
JsonSerializationResult::ResultCode result(JSR::Tasks::ReadField);
auto outputDatum = reinterpret_cast<VariableDescriptor*>(outputValue);
result.Combine(ContinueLoadingFromJsonObjectField
( &outputDatum->m_supportedTypes
, azrtti_typeid<decltype(outputDatum->m_supportedTypes)>()
, inputValue
, "SupportedTypes"
, context));
// any storage begin
AZ::Uuid typeId = AZ::Uuid::CreateNull();
auto typeIdMember = inputValue.FindMember(JsonSerialization::TypeIdFieldIdentifier);
if (typeIdMember == inputValue.MemberEnd())
{
return context.Report
( JSR::Tasks::ReadField
, JSR::Outcomes::Missing
, AZStd::string::format("ExpressionTreeVariableDescriptorSerializer::Load failed to load the %s member"
, JsonSerialization::TypeIdFieldIdentifier));
}
result.Combine(LoadTypeId(typeId, typeIdMember->value, context));
if (typeId.IsNull())
{
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Catastrophic
, "ExpressionTreeVariableDescriptorSerializer::Load failed to load the AZ TypeId of the value");
}
AZStd::any storage = context.GetSerializeContext()->CreateAny(typeId);
if (storage.empty() || storage.type() != typeId)
{
return context.Report(result, "ExpressionTreeVariableDescriptorSerializer::Load failed to load a value matched the "
"reported AZ TypeId. The C++ declaration may have been deleted or changed.");
}
result.Combine(ContinueLoadingFromJsonObjectField(AZStd::any_cast<void>(&storage), typeId, inputValue, "Value", context));
outputDatum->m_value = storage;
// any storage end
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
? "ExpressionTreeVariableDescriptorSerializer Load finished loading VariableDescriptor"
: "ExpressionTreeVariableDescriptorSerializer Load failed to load VariableDescriptor");
}
JsonSerializationResult::Result Store
( rapidjson::Value& outputValue
, const void* inputValue
, const void* defaultValue
, const Uuid& valueTypeId, JsonSerializerContext& context) override
{
namespace JSR = JsonSerializationResult;
AZ_Assert(valueTypeId == azrtti_typeid<VariableDescriptor>(), "VariableDescriptor Store against value typeID that "
"was not VariableDescriptor");
AZ_Assert(inputValue, "VariableDescriptor Store against null inputValue pointer ");
auto inputScriptDataPtr = reinterpret_cast<const VariableDescriptor*>(inputValue);
auto defaultScriptDataPtr = reinterpret_cast<const VariableDescriptor*>(defaultValue);
if (defaultScriptDataPtr)
{
if (inputScriptDataPtr->m_supportedTypes == defaultScriptDataPtr->m_supportedTypes
&& AZ::Helpers::CompareAnyValue(inputScriptDataPtr->m_value, defaultScriptDataPtr->m_value))
{
return context.Report
( JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "VariableDescriptor Store used defaults for "
"VariableDescriptor");
}
}
JSR::ResultCode result(JSR::Tasks::WriteValue);
outputValue.SetObject();
result.Combine(ContinueStoringToJsonObjectField
( outputValue
, "SupportedTypes"
, &inputScriptDataPtr->m_supportedTypes
, defaultScriptDataPtr ? &defaultScriptDataPtr->m_supportedTypes : nullptr
, azrtti_typeid<decltype(inputScriptDataPtr->m_supportedTypes)>()
, context));
rapidjson::Value typeValue;
result.Combine(StoreTypeId(typeValue, inputScriptDataPtr->m_value.type(), context));
outputValue.AddMember
( rapidjson::StringRef(JsonSerialization::TypeIdFieldIdentifier)
, AZStd::move(typeValue)
, context.GetJsonAllocator());
result.Combine(ContinueStoringToJsonObjectField
( outputValue
, "Value"
, AZStd::any_cast<void>(const_cast<AZStd::any*>(&inputScriptDataPtr->m_value))
, defaultScriptDataPtr ? AZStd::any_cast<void>(const_cast<AZStd::any*>(&defaultScriptDataPtr->m_value)) : nullptr
, inputScriptDataPtr->m_value.type()
, context));
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
? "VariableDescriptor Store finished saving VariableDescriptor"
: "VariableDescriptor Store failed to save VariableDescriptor");
}
};
AZ_CLASS_ALLOCATOR_IMPL(ExpressionTreeVariableDescriptorSerializer, SystemAllocator, 0);
}

@ -13,6 +13,8 @@ set(FILES
Include/ExpressionEvaluation/ExpressionEngine/ExpressionTypes.h Include/ExpressionEvaluation/ExpressionEngine/ExpressionTypes.h
Source/ExpressionEvaluationSystemComponent.cpp Source/ExpressionEvaluationSystemComponent.cpp
Source/ExpressionEvaluationSystemComponent.h Source/ExpressionEvaluationSystemComponent.h
Source/ExpressionPrimitivesSerializers.inl
Source/ElementInformationSerializer.inl
Source/ExpressionEngine/ExpressionElementParser.h Source/ExpressionEngine/ExpressionElementParser.h
Source/ExpressionEngine/ExpressionPrimitive.cpp Source/ExpressionEngine/ExpressionPrimitive.cpp
Source/ExpressionEngine/ExpressionPrimitive.h Source/ExpressionEngine/ExpressionPrimitive.h

@ -12,12 +12,12 @@
#include <AzCore/IO/GenericStreams.h> #include <AzCore/IO/GenericStreams.h>
#include <AzCore/Serialization/Json/JsonSerialization.h> #include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/Serialization/Json/JsonSerializationResult.h> #include <AzCore/Serialization/Json/JsonSerializationResult.h>
#include <AzCore/Serialization/Json/JsonUtils.h>
#include <AzCore/Serialization/SerializeContext.h> #include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/Utils.h> #include <AzCore/Serialization/Utils.h>
#include <AzCore/std/string/string_view.h> #include <AzCore/std/string/string_view.h>
#include <AzFramework/StringFunc/StringFunc.h> #include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h> #include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzCore/Serialization/Json/JsonUtils.h>
#include <Core/ScriptCanvasBus.h> #include <Core/ScriptCanvasBus.h>
#include <GraphCanvas/GraphCanvasBus.h> #include <GraphCanvas/GraphCanvasBus.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h> #include <ScriptCanvas/Asset/RuntimeAsset.h>
@ -27,6 +27,26 @@
#include <ScriptCanvas/Components/EditorGraph.h> #include <ScriptCanvas/Components/EditorGraph.h>
#include <ScriptCanvas/Components/EditorGraphVariableManagerComponent.h> #include <ScriptCanvas/Components/EditorGraphVariableManagerComponent.h>
#include <ScriptCanvas/Components/EditorScriptCanvasComponent.h> #include <ScriptCanvas/Components/EditorScriptCanvasComponent.h>
#include <ScriptCanvas/Core/SerializationListener.h>
namespace ScriptCanvasAssetHandlerCpp
{
using namespace ScriptCanvas;
void CollectNodes(const GraphData::NodeContainer& container, SerializationListeners& listeners)
{
for (auto& nodeEntity : container)
{
if (nodeEntity)
{
if (auto listener = azrtti_cast<SerializationListener*>(AZ::EntityUtils::FindFirstDerivedComponent<Node>(nodeEntity)))
{
listeners.push_back(listener);
}
}
}
}
}
namespace ScriptCanvasEditor namespace ScriptCanvasEditor
{ {
@ -84,7 +104,9 @@ namespace ScriptCanvasEditor
auto* scriptCanvasAssetTarget = assetTarget.GetAs<ScriptCanvasAsset>(); auto* scriptCanvasAssetTarget = assetTarget.GetAs<ScriptCanvasAsset>();
AZ_Assert(scriptCanvasAssetTarget, "This should be a ScriptCanvasAsset, as this is the only type we process!"); AZ_Assert(scriptCanvasAssetTarget, "This should be a ScriptCanvasAsset, as this is the only type we process!");
if (scriptCanvasAssetTarget && m_serializeContext && streamSource) if (m_serializeContext
&& streamSource
&& scriptCanvasAssetTarget)
{ {
streamSource->Seek(0U, AZ::IO::GenericStream::ST_SEEK_BEGIN); streamSource->Seek(0U, AZ::IO::GenericStream::ST_SEEK_BEGIN);
auto& scriptCanvasDataTarget = scriptCanvasAssetTarget->GetScriptCanvasData(); auto& scriptCanvasDataTarget = scriptCanvasAssetTarget->GetScriptCanvasData();
@ -99,6 +121,7 @@ namespace ScriptCanvasEditor
byteStreamSource.Seek(0U, AZ::IO::GenericStream::ST_SEEK_BEGIN); byteStreamSource.Seek(0U, AZ::IO::GenericStream::ST_SEEK_BEGIN);
AZ::JsonDeserializerSettings settings; AZ::JsonDeserializerSettings settings;
settings.m_serializeContext = m_serializeContext; settings.m_serializeContext = m_serializeContext;
settings.m_metadata.Create<SerializationListeners>();
// attempt JSON deserialization... // attempt JSON deserialization...
if (JSRU::LoadObjectFromStreamByType if (JSRU::LoadObjectFromStreamByType
( &scriptCanvasDataTarget ( &scriptCanvasDataTarget
@ -106,20 +129,40 @@ namespace ScriptCanvasEditor
, byteStreamSource , byteStreamSource
, &settings).IsSuccess()) , &settings).IsSuccess())
{ {
return AZ::Data::AssetHandler::LoadResult::LoadComplete; if (auto graphData = scriptCanvasAssetTarget->GetScriptCanvasGraph()
} ? scriptCanvasAssetTarget->GetScriptCanvasGraph()->GetGraphData()
: nullptr)
{
auto listeners = settings.m_metadata.Find<SerializationListeners>();
AZ_Assert(listeners, "Failed to create SerializationListeners");
ScriptCanvasAssetHandlerCpp::CollectNodes(graphData->m_nodes, *listeners);
for (auto listener : *listeners)
{
listener->OnDeserialize();
}
return AZ::Data::AssetHandler::LoadResult::LoadComplete;
}
else
{
AZ_Warning("ScriptCanvas", false, "ScriptCanvasAssetHandler::LoadAssetData failed to load graph data from JOSON");
}
}
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)//// #if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
// ...if there is a failure, check if it is saved in the old format else
byteStreamSource.Seek(0U, AZ::IO::GenericStream::ST_SEEK_BEGIN); {// ...if there is a failure, check if it is saved in the old format
// tolerate unknown classes in the editor. Let the asset processor warn about bad nodes... byteStreamSource.Seek(0U, AZ::IO::GenericStream::ST_SEEK_BEGIN);
if (AZ::Utils::LoadObjectFromStreamInPlace // tolerate unknown classes in the editor. Let the asset processor warn about bad nodes...
( byteStreamSource if (AZ::Utils::LoadObjectFromStreamInPlace
(byteStreamSource
, scriptCanvasDataTarget , scriptCanvasDataTarget
, m_serializeContext , m_serializeContext
, AZ::ObjectStream::FilterDescriptor(assetLoadFilterCB, AZ::ObjectStream::FILTERFLAG_IGNORE_UNKNOWN_CLASSES))) , AZ::ObjectStream::FilterDescriptor(assetLoadFilterCB, AZ::ObjectStream::FILTERFLAG_IGNORE_UNKNOWN_CLASSES)))
{ {
return AZ::Data::AssetHandler::LoadResult::LoadComplete; return AZ::Data::AssetHandler::LoadResult::LoadComplete;
}
} }
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED) #endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)
} }
@ -146,11 +189,26 @@ namespace ScriptCanvasEditor
namespace JSRU = AZ::JsonSerializationUtils; namespace JSRU = AZ::JsonSerializationUtils;
using namespace ScriptCanvas; using namespace ScriptCanvas;
if (assetData && stream && m_serializeContext) if (m_serializeContext
&& stream
&& assetData
&& assetData->GetScriptCanvasGraph()
&& assetData->GetScriptCanvasGraph()->GetGraphData())
{ {
auto graphData = assetData->GetScriptCanvasGraph()->GetGraphData();
AZ::JsonSerializerSettings settings; AZ::JsonSerializerSettings settings;
settings.m_metadata.Create<SerializationListeners>();
auto listeners = settings.m_metadata.Find<SerializationListeners>();
AZ_Assert(listeners, "Failed to create SerializationListeners");
ScriptCanvasAssetHandlerCpp::CollectNodes(graphData->m_nodes, *listeners);
settings.m_keepDefaults = false; settings.m_keepDefaults = false;
settings.m_serializeContext = m_serializeContext; settings.m_serializeContext = m_serializeContext;
for (auto listener : *listeners)
{
listener->OnSerialize();
}
return JSRU::SaveObjectToStream<ScriptCanvasData>(&assetData->GetScriptCanvasData(), *stream, nullptr, &settings).IsSuccess(); return JSRU::SaveObjectToStream<ScriptCanvasData>(&assetData->GetScriptCanvasData(), *stream, nullptr, &settings).IsSuccess();
} }
else else

@ -44,18 +44,10 @@ namespace {{attribute_Namespace}}
{ {
{% endif %} {% endif %}
{% set className = Class.attrib['Name'] %} {% set className = Class.attrib['Name'] %}
{% if Class.attrib['Base'] is defined %} {% set baseClassPair = [] %}
{% if Class.attrib['Base'].split(';')|length > 1 %} {% if macros.CreateBaseClassVariables(Class, baseClassPair) %}{% endif %}
{% set baseClass = Class.attrib['Base'].split(';')[0] %} {% set baseClass = baseClassPair[0] %}
{% set baseClasses = ", ".join(Class.attrib['Base'].split(';')) %} {% set baseClasses = baseClassPair[1] %}
{% else %}
{% set baseClass = Class.attrib['Base'] %}
{% set baseClasses = Class.attrib['Base'] %}
{% endif %}
{% else %}
{% set baseClass = "ScriptCanvas::Node" %}
{% set baseClasses = "ScriptCanvas::Node" %}
{% endif %}
///////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////

@ -4,6 +4,8 @@ For complete copyright and license terms please see the LICENSE at the root of t
SPDX-License-Identifier: Apache-2.0 OR MIT SPDX-License-Identifier: Apache-2.0 OR MIT
#} #}
{% import 'ScriptCanvas_Macros.jinja' as macros %}
{% macro add_attribute(attribute, tags) %} {% macro add_attribute(attribute, tags) %}
{% set value = tags[attribute] %} {% set value = tags[attribute] %}
{% if value is defined %} {% if value is defined %}
@ -26,18 +28,11 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
#include "{{ xml.attrib['Include'] }}" #include "{{ xml.attrib['Include'] }}"
{% for Class in xml.iter('Class') %} {% for Class in xml.iter('Class') %}
{% if Class.attrib['Base'] is defined %} {% set baseClassPair = [] %}
{% if Class.attrib['Base'].split(';')|length > 1 %} {% if macros.CreateBaseClassVariables(Class, baseClassPair) %}{% endif %}
{% set baseClass = Class.attrib['Base'].split(';')[0] %} {% set baseClass = baseClassPair[0] %}
{% set baseClasses = ", ".join(Class.attrib['Base'].split(';')) %} {% set baseClasses = baseClassPair[1] %}
{% else %}
{% set baseClass = Class.attrib['Base'] %}
{% set baseClasses = Class.attrib['Base'] %}
{% endif %}
{% else %}
{% set baseClass = "ScriptCanvas::Node" %}
{% set baseClasses = "ScriptCanvas::Node" %}
{% endif %}
void {{ Class.attrib['QualifiedName'] }}::ConfigureSlots() void {{ Class.attrib['QualifiedName'] }}::ConfigureSlots()
{ {
{{ baseClass }}::ConfigureSlots(); {{ baseClass }}::ConfigureSlots();

@ -173,11 +173,29 @@ AZStd::tuple<{{returnTypes|join(", ")}}>
{# ------- #} {# ------- #}
{# CreateBaseClassVariables #}
{# Creates "baseClass" and "baseClasses" variables to use when needed "baseClasses" is a comma separated list that in includes baseClass #}
{%- macro CreateBaseClassVariables(Class, baseClassPair) -%}
{% set baseAttrib = Class.attrib['Base'] %}
{% if baseAttrib is defined %}
{% if baseAttrib.split(';')|length > 1 %}
{% if baseClassPair.append(baseAttrib.split(';')[0]) %}{% endif %}
{% if baseClassPair.append(", ".join(baseAttrib.split(';'))) %}{% endif %}
{% else %}
{% if baseClassPair.append(baseAttrib) %}{% endif %}
{% if baseClassPair.append(baseAttrib) %}{% endif %}
{% endif %}
{% else %}
{% if baseClassPair.append("ScriptCanvas::Node") %}{% endif %}
{% if baseClassPair.append("ScriptCanvas::Node") %}{% endif %}
{% endif %}
{%- endmacro -%}
{# ------- #}
{# ------------------------------------------------------------------------------------- #} {# ------------------------------------------------------------------------------------- #}
{# NODEABLES #} {# NODEABLES #}
{# TODO-LS: This macro lacks parsing the parameters provided to a Contract tag #} {# TODO: This macro lacks parsing the parameters provided to a Contract tag #}
{%- macro AddContract(configurationName, item) -%} {%- macro AddContract(configurationName, item) -%}
{% set contracts = [] %} {% set contracts = [] %}

@ -2041,21 +2041,6 @@ namespace ScriptCanvas
} }
} }
void Datum::OnSerializeBegin()
{
if (m_type.GetType() == Data::eType::BehaviorContextObject)
{
if (BehaviorContextObjectPtr ptr = (*AZStd::any_cast<BehaviorContextObjectPtr>(&m_storage.value)))
{
ptr->OnSerializeBegin();
}
else
{
AZ_Error("ScriptCanvas", false, AZStd::string::format("Datum type (%s) failed to serialized, did not store BehaviorContextObjectPtr properly", m_type.GetAZType().ToString<AZStd::string>().c_str()).c_str());
}
}
}
void Datum::OnDeserialize() void Datum::OnDeserialize()
{ {
if (m_type.GetType() == Data::eType::BehaviorContextObject) if (m_type.GetType() == Data::eType::BehaviorContextObject)
@ -2080,14 +2065,9 @@ namespace ScriptCanvas
} }
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)//// #if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
void Datum::OnReadBegin()
{
OnSerializeBegin();
}
void Datum::OnWriteEnd() void Datum::OnWriteEnd()
{ {
OnSerializeEnd(); OnDeserialize();
} }
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED) #endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)

@ -240,13 +240,6 @@ namespace ScriptCanvas
class SerializeContextEventHandler : public AZ::SerializeContext::IEventHandler class SerializeContextEventHandler : public AZ::SerializeContext::IEventHandler
{ {
public: public:
/// Called after we are done writing to the instance pointed by classPtr.
void OnReadBegin(void* classPtr) override
{
Datum* datum = reinterpret_cast<Datum*>(classPtr);
datum->OnReadBegin();
}
/// Called after we are done writing to the instance pointed by classPtr. /// Called after we are done writing to the instance pointed by classPtr.
void OnWriteEnd(void* classPtr) override void OnWriteEnd(void* classPtr) override
{ {
@ -352,13 +345,9 @@ namespace ScriptCanvas
void OnDatumEdited(); void OnDatumEdited();
void OnSerializeBegin() override;
void OnDeserialize() override; void OnDeserialize() override;
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)//// #if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
void OnReadBegin();
void OnWriteEnd(); void OnWriteEnd();
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED) #endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)

@ -16,8 +16,7 @@ namespace ScriptCanvas
AZ_RTTI(SerializationListener, "{CA4EE281-30B3-4928-BCD8-9305CE75E463}"); AZ_RTTI(SerializationListener, "{CA4EE281-30B3-4928-BCD8-9305CE75E463}");
virtual ~SerializationListener() {} virtual ~SerializationListener() {}
virtual void OnSerializeBegin() {} virtual void OnSerialize() {}
virtual void OnSerializeEnd() {}
virtual void OnDeserialize() {} virtual void OnDeserialize() {}
}; };

@ -17,14 +17,6 @@
namespace ScriptCanvas namespace ScriptCanvas
{ {
void BehaviorContextObject::OnSerializeBegin()
{
if (!IsOwned())
{
Clear();
}
}
void BehaviorContextObject::Reflect(AZ::ReflectContext* reflection) void BehaviorContextObject::Reflect(AZ::ReflectContext* reflection)
{ {
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection)) if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection))
@ -104,6 +96,12 @@ namespace ScriptCanvas
: BehaviorContextObjectPtr(aznew BehaviorContextObject(reference, GetAnyTypeInfoReference(typeID), referenceFlags)); : BehaviorContextObjectPtr(aznew BehaviorContextObject(reference, GetAnyTypeInfoReference(typeID), referenceFlags));
} }
void BehaviorContextObject::Deserialize(BehaviorContextObject& target, const AZ::BehaviorClass& behaviorClass, AZStd::any& source)
{
target.m_object = AZStd::move(AZStd::any(AZStd::any_cast<void>(&source), GetAnyTypeInfoObject(behaviorClass)));
target.m_flags = Owned;
}
void BehaviorContextObject::release() void BehaviorContextObject::release()
{ {
if (--m_referenceCount == 0) if (--m_referenceCount == 0)

@ -22,6 +22,7 @@
namespace AZ namespace AZ
{ {
class ReflectContext; class ReflectContext;
class BehaviorContextObjectSerializer;
} }
namespace ScriptCanvas namespace ScriptCanvas
@ -30,6 +31,7 @@ namespace ScriptCanvas
{ {
friend struct AZStd::IntrusivePtrCountPolicy<BehaviorContextObject>; friend struct AZStd::IntrusivePtrCountPolicy<BehaviorContextObject>;
friend class Datum; friend class Datum;
friend class AZ::BehaviorContextObjectSerializer;
public: public:
AZ_TYPE_INFO(BehaviorContextObject, "{B735214D-5182-4536-B748-61EC83C1F007}"); AZ_TYPE_INFO(BehaviorContextObject, "{B735214D-5182-4536-B748-61EC83C1F007}");
@ -81,6 +83,8 @@ namespace ScriptCanvas
AZ_INLINE static BehaviorContextObject* CreateDefaultHeap(const AZ::BehaviorClass& behaviorClass); AZ_INLINE static BehaviorContextObject* CreateDefaultHeap(const AZ::BehaviorClass& behaviorClass);
static void Deserialize(BehaviorContextObject& target, const AZ::BehaviorClass& behaviorClass, AZStd::any& source);
// use the SSO optimization on behavior class size ALIGNED with a placement new of behavior class create // use the SSO optimization on behavior class size ALIGNED with a placement new of behavior class create
AZ_FORCE_INLINE static AnyTypeInfo GetAnyTypeInfoObject(const AZ::BehaviorClass& behaviorClass); AZ_FORCE_INLINE static AnyTypeInfo GetAnyTypeInfoObject(const AZ::BehaviorClass& behaviorClass);
@ -104,10 +108,10 @@ namespace ScriptCanvas
//...so don't use the ctors, use the Create functions... //...so don't use the ctors, use the Create functions...
//...the friend declarations are here for compatibility with the serialization system only //...the friend declarations are here for compatibility with the serialization system only
AZ_FORCE_INLINE BehaviorContextObject() = default; AZ_FORCE_INLINE BehaviorContextObject() = default;
BehaviorContextObject& operator=(const BehaviorContextObject&) = default;
BehaviorContextObject& operator=(const BehaviorContextObject&) = delete; BehaviorContextObject(const BehaviorContextObject&) = default;
BehaviorContextObject(BehaviorContextObject&&) = default;
BehaviorContextObject(const BehaviorContextObject&) = delete; BehaviorContextObject& operator=(BehaviorContextObject&& source) = default;
// copy ctor // copy ctor
AZ_FORCE_INLINE BehaviorContextObject(const void* source, const AnyTypeInfo& typeInfo, AZ::u32 flags); AZ_FORCE_INLINE BehaviorContextObject(const void* source, const AnyTypeInfo& typeInfo, AZ::u32 flags);
@ -119,8 +123,6 @@ namespace ScriptCanvas
AZ_FORCE_INLINE bool IsOwned() const; AZ_FORCE_INLINE bool IsOwned() const;
void OnSerializeBegin();
AZ_FORCE_INLINE void add_ref(); AZ_FORCE_INLINE void add_ref();
void release(); void release();

@ -188,6 +188,7 @@ namespace ScriptCanvas
RefreshActiveIndexes(); RefreshActiveIndexes();
ConfigureContracts(); ConfigureContracts();
SetWarnOnMissingFunction(true);
} }
SlotId MethodOverloaded::AddMethodInputSlot(const MethodConfiguration& config, size_t argumentIndex) SlotId MethodOverloaded::AddMethodInputSlot(const MethodConfiguration& config, size_t argumentIndex)
@ -400,10 +401,6 @@ namespace ScriptCanvas
} }
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)//// #if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
void MethodOverloaded::OnWriteBegin()
{
}
void MethodOverloaded::OnWriteEnd() void MethodOverloaded::OnWriteEnd()
{ {
OnDeserialize(); OnDeserialize();

@ -97,8 +97,7 @@ namespace ScriptCanvas
// SerializeContextReadWriteHandler // SerializeContextReadWriteHandler
void OnReadBegin() {} void OnReadBegin() {}
void OnReadEnd() {} void OnReadEnd() {}
void OnWriteBegin() {}
void OnWriteBegin();
void OnWriteEnd(); void OnWriteEnd();
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED) #endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)

@ -0,0 +1,149 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/Serialization/AZStdAnyDataContainer.inl>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <ScriptCanvas/Asset/RuntimeAsset.h>
#include <ScriptCanvas/Serialization/BehaviorContextObjectSerializer.h>
using namespace ScriptCanvas;
namespace AZ
{
AZ_CLASS_ALLOCATOR_IMPL(BehaviorContextObjectSerializer, SystemAllocator, 0);
JsonSerializationResult::Result BehaviorContextObjectSerializer::Load
( void* outputValue
, [[maybe_unused]] const Uuid& outputValueTypeId
, const rapidjson::Value& inputValue
, JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult;
AZ_Assert(outputValueTypeId == azrtti_typeid<BehaviorContextObject>(), "BehaviorContextObjectSerializer Load against output typeID"
"that was not BehaviorContextObject");
AZ_Assert(outputValue, "BehaviorContextObjectSerializer Load against null output");
JsonSerializationResult::ResultCode result(JSR::Tasks::ReadField);
auto outputBehaviorContextObject = reinterpret_cast<BehaviorContextObject*>(outputValue);
bool isOwned = false;
result.Combine(ContinueLoadingFromJsonObjectField
( &isOwned
, azrtti_typeid<bool>()
, inputValue
, "isOwned"
, context));
if (isOwned)
{
AZStd::any storage;
{ // any storage begin
auto typeIdMember = inputValue.FindMember(JsonSerialization::TypeIdFieldIdentifier);
if (typeIdMember == inputValue.MemberEnd())
{
return context.Report
(JSR::Tasks::ReadField
, JSR::Outcomes::Missing
, AZStd::string::format("BehaviorContextObjectSerializer::Load failed to load the %s member"
, JsonSerialization::TypeIdFieldIdentifier));
}
AZ::Uuid typeId;
result.Combine(LoadTypeId(typeId, typeIdMember->value, context));
if (typeId.IsNull())
{
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Catastrophic
, "BehaviorContextObjectSerializer::Load failed to load the AZ TypeId of the value");
}
storage = context.GetSerializeContext()->CreateAny(typeId);
if (storage.empty() || storage.type() != typeId)
{
return context.Report(result, "BehaviorContextObjectSerializer::Load failed to load a value matched the reported AZ "
"TypeId. The C++ declaration may have been deleted or changed.");
}
result.Combine(ContinueLoadingFromJsonObjectField(AZStd::any_cast<void>(&storage), typeId, inputValue, "value", context));
} // any storage end
auto bcClass = AZ::BehaviorContextHelper::GetClass(storage.type());
BehaviorContextObject::Deserialize(*outputBehaviorContextObject, *bcClass, storage);
}
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
? "BehaviorContextObjectSerializer Load finished loading BehaviorContextObject"
: "BehaviorContextObjectSerializer Load failed to load BehaviorContextObject");
}
JsonSerializationResult::Result BehaviorContextObjectSerializer::Store
( rapidjson::Value& outputValue
, const void* inputValue
, const void* defaultValue
, [[maybe_unused]] const Uuid& valueTypeId
, JsonSerializerContext& context)
{
namespace JSR = JsonSerializationResult;
AZ_Assert(valueTypeId == azrtti_typeid<BehaviorContextObject>(), "BehaviorContextObjectSerializer Store against value typeID that "
"was not BehaviorContextObject");
AZ_Assert(inputValue, "BehaviorContextObjectSerializer Store against null inputValue pointer ");
auto defaultScriptDataPtr = reinterpret_cast<const BehaviorContextObject*>(defaultValue);
auto inputScriptDataPtr = reinterpret_cast<const BehaviorContextObject*>(inputValue);
if (defaultScriptDataPtr)
{
if (AZ::Helpers::CompareAnyValue(inputScriptDataPtr->ToAny(), defaultScriptDataPtr->ToAny()))
{
return context.Report
( JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "BehaviorContextObjectSerializer Store used defaults "
"for BehaviorContextObject");
}
}
outputValue.SetObject();
JSR::ResultCode result(JSR::Tasks::WriteValue);
const bool isInputOwned = inputScriptDataPtr->IsOwned();
const bool isDefaultOwned = defaultScriptDataPtr ? defaultScriptDataPtr->IsOwned() : false;
result.Combine(ContinueStoringToJsonObjectField
( outputValue
, "isOwned"
, &isInputOwned
, &isDefaultOwned
, azrtti_typeid<bool>()
, context));
if (isInputOwned)
{
// any storage begin
{
rapidjson::Value typeValue;
result.Combine(StoreTypeId(typeValue, inputScriptDataPtr->ToAny().type(), context));
outputValue.AddMember
( rapidjson::StringRef(JsonSerialization::TypeIdFieldIdentifier)
, AZStd::move(typeValue)
, context.GetJsonAllocator());
}
result.Combine(ContinueStoringToJsonObjectField
( outputValue
, "value"
, inputScriptDataPtr->Get()
, defaultScriptDataPtr ? defaultScriptDataPtr->Get() : nullptr
, inputScriptDataPtr->ToAny().type()
, context));
// datum storage end
}
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
? "BehaviorContextObjectSerializer Store finished saving BehaviorContextObject"
: "BehaviorContextObjectSerializer Store failed to save BehaviorContextObject");
}
}

@ -14,11 +14,11 @@
namespace AZ namespace AZ
{ {
class GraphDataSerializer class BehaviorContextObjectSerializer
: public BaseJsonSerializer : public BaseJsonSerializer
{ {
public: public:
AZ_RTTI(GraphDataSerializer, "{2DFF5794-785F-4434-9314-52BB3EF1D00E}", BaseJsonSerializer); AZ_RTTI(BehaviorContextObjectSerializer, "{88469C4C-923F-4508-A45C-33DDBB91074E}", BaseJsonSerializer);
AZ_CLASS_ALLOCATOR_DECL; AZ_CLASS_ALLOCATOR_DECL;
private: private:

@ -50,10 +50,23 @@ namespace AZ
, "scriptCanvasType" , "scriptCanvasType"
, context)); , context));
AZStd::any storage; // datum storage begin
{ // datum storage begin auto isNullPointerMember = inputValue.FindMember("isNullPointer");
AZ::Uuid typeId = AZ::Uuid::CreateNull(); if (isNullPointerMember == inputValue.MemberEnd())
{
return context.Report
( JSR::Tasks::ReadField
, JSR::Outcomes::Missing
, "DatumSerializer::Load failed to load the 'isNullPointer'' member");
}
if (isNullPointerMember->value.GetBool())
{
*outputDatum = Datum(scType, Datum::eOriginality::Original);
}
else
{
AZ::Uuid typeId = AZ::Uuid::CreateNull();
auto typeIdMember = inputValue.FindMember(JsonSerialization::TypeIdFieldIdentifier); auto typeIdMember = inputValue.FindMember(JsonSerialization::TypeIdFieldIdentifier);
if (typeIdMember == inputValue.MemberEnd()) if (typeIdMember == inputValue.MemberEnd())
{ {
@ -71,7 +84,7 @@ namespace AZ
, "DatumSerializer::Load failed to load the AZ TypeId of the value"); , "DatumSerializer::Load failed to load the AZ TypeId of the value");
} }
storage = context.GetSerializeContext()->CreateAny(typeId); AZStd::any storage = context.GetSerializeContext()->CreateAny(typeId);
if (storage.empty() || storage.type() != typeId) if (storage.empty() || storage.type() != typeId)
{ {
return context.Report(result, "DatumSerializer::Load failed to load a value matched the reported AZ TypeId. " return context.Report(result, "DatumSerializer::Load failed to load a value matched the reported AZ TypeId. "
@ -79,24 +92,25 @@ namespace AZ
} }
result.Combine(ContinueLoadingFromJsonObjectField(AZStd::any_cast<void>(&storage), typeId, inputValue, "value", context)); result.Combine(ContinueLoadingFromJsonObjectField(AZStd::any_cast<void>(&storage), typeId, inputValue, "value", context));
*outputDatum = Datum(scType, Datum::eOriginality::Original, AZStd::any_cast<void>(&storage), scType.GetAZType());
} // datum storage end } // datum storage end
AZStd::string label; AZStd::string label;
AZ_Assert(azrtti_typeid<decltype(outputDatum->m_datumLabel)>() == azrtti_typeid<decltype(label)>() AZ_Assert(azrtti_typeid<decltype(outputDatum->m_datumLabel)>() == azrtti_typeid<decltype(label)>()
, "m_datumLabel type changed and won't load properly"); , "m_datumLabel type changed and won't load properly");
result.Combine(ContinueLoadingFromJsonObjectField result.Combine(ContinueLoadingFromJsonObjectField
( &label ( &label
, azrtti_typeid<decltype(outputDatum->m_datumLabel)>() , azrtti_typeid<decltype(outputDatum->m_datumLabel)>()
, inputValue , inputValue
, "label" , "label"
, context)); , context));
outputDatum->SetLabel(label);
Datum copy(scType, Datum::eOriginality::Original, AZStd::any_cast<void>(&storage), scType.GetAZType()); if (auto listeners = context.GetMetadata().Find<SerializationListeners>())
copy.SetLabel(label); {
*outputDatum = copy; listeners->push_back(outputDatum);
outputDatum->OnDeserialize(); }
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
? "DatumSerializer Load finished loading Datum" ? "DatumSerializer Load finished loading Datum"
: "DatumSerializer Load failed to load Datum"); : "DatumSerializer Load failed to load Datum");
@ -126,8 +140,6 @@ namespace AZ
} }
} }
const_cast<Datum*>(inputScriptDataPtr)->OnSerializeBegin();
JSR::ResultCode result(JSR::Tasks::WriteValue); JSR::ResultCode result(JSR::Tasks::WriteValue);
outputValue.SetObject(); outputValue.SetObject();
@ -146,25 +158,31 @@ namespace AZ
, defaultScriptDataPtr ? &defaultScriptDataPtr->GetType() : nullptr , defaultScriptDataPtr ? &defaultScriptDataPtr->GetType() : nullptr
, azrtti_typeid<decltype(inputScriptDataPtr->GetType())>() , azrtti_typeid<decltype(inputScriptDataPtr->GetType())>()
, context)); , context));
{ // datum storage begin // datum storage begin
{ auto inputObjectSource = inputScriptDataPtr->GetAsDanger();
rapidjson::Value typeValue; outputValue.AddMember("isNullPointer", rapidjson::Value(inputObjectSource == nullptr), context.GetJsonAllocator());
result.Combine(StoreTypeId(typeValue, inputScriptDataPtr->GetType().GetAZType(), context));
outputValue.AddMember if (inputObjectSource)
( rapidjson::StringRef(JsonSerialization::TypeIdFieldIdentifier) {
, AZStd::move(typeValue) rapidjson::Value typeValue;
, context.GetJsonAllocator()); result.Combine(StoreTypeId(typeValue, inputScriptDataPtr->GetType().GetAZType(), context));
} outputValue.AddMember
( rapidjson::StringRef(JsonSerialization::TypeIdFieldIdentifier)
, AZStd::move(typeValue)
, context.GetJsonAllocator());
auto defaultObjectSource = defaultScriptDataPtr ? defaultScriptDataPtr->GetAsDanger() : nullptr;
result.Combine(ContinueStoringToJsonObjectField result.Combine(ContinueStoringToJsonObjectField
( outputValue ( outputValue
, "value" , "value"
, inputScriptDataPtr->GetAsDanger() , inputObjectSource
, defaultScriptDataPtr ? defaultScriptDataPtr->GetAsDanger() : nullptr , defaultObjectSource
, inputScriptDataPtr->GetType().GetAZType() , inputScriptDataPtr->GetType().GetAZType()
, context)); , context));
} // datum storage end }
// datum storage end
result.Combine(ContinueStoringToJsonObjectField result.Combine(ContinueStoringToJsonObjectField
( outputValue ( outputValue
@ -174,7 +192,6 @@ namespace AZ
, azrtti_typeid<decltype(inputScriptDataPtr->m_datumLabel)>() , azrtti_typeid<decltype(inputScriptDataPtr->m_datumLabel)>()
, context)); , context));
const_cast<Datum*>(inputScriptDataPtr)->OnSerializeEnd();
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
? "DatumSerializer Store finished saving Datum" ? "DatumSerializer Store finished saving Datum"
: "DatumSerializer Store failed to save Datum"); : "DatumSerializer Store failed to save Datum");

@ -1,100 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <ScriptCanvas/Core/SerializationListener.h>
#include <ScriptCanvas/Core/GraphData.h>
#include <ScriptCanvas/Serialization/GraphDataSerializer.h>
using namespace ScriptCanvas;
namespace GraphDataSerializerCpp
{
void CollectNodes(const GraphData::NodeContainer& container, SerializationListeners& listeners)
{
for (auto& nodeEntity : container)
{
if (nodeEntity)
{
if (auto listener = azrtti_cast<SerializationListener*>(AZ::EntityUtils::FindFirstDerivedComponent<Node>(nodeEntity)))
{
listeners.push_back(listener);
}
}
}
}
}
namespace AZ
{
AZ_CLASS_ALLOCATOR_IMPL(GraphDataSerializer, SystemAllocator, 0);
JsonSerializationResult::Result GraphDataSerializer::Load
( void* outputValue
, [[maybe_unused]] const Uuid& outputValueTypeId
, const rapidjson::Value& inputValue
, JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult;
AZ_Assert(outputValueTypeId == azrtti_typeid<GraphData>()
, "RuntimeVariableSerializer Load against output typeID that was not GraphData");
AZ_Assert(outputValue, "RuntimeVariableSerializer Load against null output");
context.GetMetadata().Add(SerializationListeners());
JSR::ResultCode result(JSR::Tasks::ReadField);
result.Combine(ContinueLoading(outputValue, outputValueTypeId, inputValue, context, ContinuationFlags::NoTypeSerializer));
auto listeners = context.GetMetadata().Find<SerializationListeners>();
AZ_Assert(listeners, "Failed to create SerializationListeners");
GraphDataSerializerCpp::CollectNodes(reinterpret_cast<GraphData*>(outputValue)->m_nodes, *listeners);
for (auto listener : *listeners)
{
listener->OnDeserialize();
}
reinterpret_cast<GraphData*>(outputValue)->OnDeserialized();
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
? "GraphDataSerializer Load finished loading GraphData"
: "GraphDataSerializer Load failed to load GraphData");
}
JsonSerializationResult::Result GraphDataSerializer::Store
( rapidjson::Value& outputValue
, const void* inputValue
, const void* defaultValue
, [[maybe_unused]] const Uuid& valueTypeId
, JsonSerializerContext& context)
{
namespace JSR = JsonSerializationResult;
AZ_Assert(valueTypeId == azrtti_typeid<GraphData>()
, "RuntimeVariableSerializer Store against output typeID that was not GraphData");
AZ_Assert(inputValue, "RuntimeVariableSerializer Store against null output");
context.GetMetadata().Add(SerializationListeners());
auto listeners = context.GetMetadata().Find<SerializationListeners>();
GraphDataSerializerCpp::CollectNodes(reinterpret_cast<const GraphData*>(inputValue)->m_nodes, *listeners);
for (auto listener : *listeners)
{
listener->OnSerializeBegin();
}
JSR::ResultCode result(JSR::Tasks::WriteValue);
result.Combine(ContinueStoring(outputValue, inputValue, defaultValue, valueTypeId, context, ContinuationFlags::NoTypeSerializer));
for (auto listener : *listeners)
{
listener->OnSerializeEnd();
}
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
? "GraphDataSerializer::Store finished storing GraphData"
: "GraphDataSerializer::Store failed to store GraphData");
}
}

@ -23,7 +23,7 @@
#include <ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.h> #include <ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.h>
#include <ScriptCanvas/Execution/RuntimeComponent.h> #include <ScriptCanvas/Execution/RuntimeComponent.h>
#include <ScriptCanvas/Serialization/DatumSerializer.h> #include <ScriptCanvas/Serialization/DatumSerializer.h>
#include <ScriptCanvas/Serialization/GraphDataSerializer.h> #include <ScriptCanvas/Serialization/BehaviorContextObjectSerializer.h>
#include <ScriptCanvas/Serialization/RuntimeVariableSerializer.h> #include <ScriptCanvas/Serialization/RuntimeVariableSerializer.h>
#include <ScriptCanvas/SystemComponent.h> #include <ScriptCanvas/SystemComponent.h>
#include <ScriptCanvas/Variable/GraphVariableManagerComponent.h> #include <ScriptCanvas/Variable/GraphVariableManagerComponent.h>
@ -90,7 +90,7 @@ namespace ScriptCanvas
if (AZ::JsonRegistrationContext* jsonContext = azrtti_cast<AZ::JsonRegistrationContext*>(context)) if (AZ::JsonRegistrationContext* jsonContext = azrtti_cast<AZ::JsonRegistrationContext*>(context))
{ {
jsonContext->Serializer<AZ::DatumSerializer>()->HandlesType<Datum>(); jsonContext->Serializer<AZ::DatumSerializer>()->HandlesType<Datum>();
jsonContext->Serializer<AZ::GraphDataSerializer>()->HandlesType<GraphData>(); jsonContext->Serializer<AZ::BehaviorContextObjectSerializer>()->HandlesType<BehaviorContextObject>();
jsonContext->Serializer<AZ::RuntimeVariableSerializer>()->HandlesType<RuntimeVariable>(); jsonContext->Serializer<AZ::RuntimeVariableSerializer>()->HandlesType<RuntimeVariable>();
} }

@ -540,10 +540,10 @@ set(FILES
Include/ScriptCanvas/Profiler/Aggregator.cpp Include/ScriptCanvas/Profiler/Aggregator.cpp
Include/ScriptCanvas/Profiler/DrillerEvents.h Include/ScriptCanvas/Profiler/DrillerEvents.h
Include/ScriptCanvas/Profiler/DrillerEvents.cpp Include/ScriptCanvas/Profiler/DrillerEvents.cpp
Include/ScriptCanvas/Serialization/BehaviorContextObjectSerializer.h
Include/ScriptCanvas/Serialization/BehaviorContextObjectSerializer.cpp
Include/ScriptCanvas/Serialization/DatumSerializer.h Include/ScriptCanvas/Serialization/DatumSerializer.h
Include/ScriptCanvas/Serialization/DatumSerializer.cpp Include/ScriptCanvas/Serialization/DatumSerializer.cpp
Include/ScriptCanvas/Serialization/GraphDataSerializer.cpp
Include/ScriptCanvas/Serialization/GraphDataSerializer.h
Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.h Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.h
Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.cpp Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.cpp
Include/ScriptCanvas/Data/DataTrait.cpp Include/ScriptCanvas/Data/DataTrait.cpp

Loading…
Cancel
Save