Merge pull request #3309 from aws-lumberyard-dev/carlitosan/development

JSON serialization of SC Editor Assets
This commit is contained in:
carlitosan
2021-08-24 11:45:18 -07:00
committed by GitHub
86 changed files with 8079 additions and 11644 deletions
@@ -43,10 +43,8 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
namespace {{attribute_Namespace}}
{
{% endif %}
{% set className = Class.attrib['Name'] %}
{% set baseClass = Class.attrib['Base'] %}
{% set baseClasses = ", ".join(Class.attrib['Base'].split(';')) if Class.attrib['Base'] is string else "ScriptCanvas::Node" %}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
////
@@ -66,7 +64,7 @@ namespace {{attribute_Namespace}}
// You must #include the generated header into the source header
#define SCRIPTCANVAS_NODE_{{ className }} \
public: \
AZ_COMPONENT({{ className }}, "{{ classUuid }}"{% if baseClass is defined %}, {{ baseClass }}{% endif %}); \
AZ_COMPONENT({{ className }}, "{{ classUuid }}", {{ baseClasses }} ); \
static void Reflect(AZ::ReflectContext* reflection); \
void ConfigureSlots() override; \
bool RequiresDynamicSlotOrdering() const override; \
@@ -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
#}
{% import 'ScriptCanvas_Macros.jinja' as macros %}
{% macro add_attribute(attribute, tags) %}
{% set value = tags[attribute] %}
{% if value is defined %}
@@ -26,7 +28,7 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
#include "{{ xml.attrib['Include'] }}"
{% for Class in xml.iter('Class') %}
{% set baseClass = Class.attrib['Base'].split(';')[0] if Class.attrib['Base'] is string else "ScriptCanvas::Node" %}
{% set attribute_Namespace = undefined %}
{%- if Class.attrib['Namespace'] is defined %}
{% if Class.attrib['Namespace'] != "None" %}
@@ -42,10 +44,8 @@ namespace {{attribute_Namespace}}
void {{ Class.attrib['QualifiedName'] }}::ConfigureSlots()
{
{% if Class.attrib['Base'] is defined %}
{{ Class.attrib['Base'] }}::ConfigureSlots();
{{ baseClass }}::ConfigureSlots();
{% endif %}
{% for Property in Class.iter('Property') %}
{% if Property.attrib['IsInput'] | booleanTrue %}
// {{ Property.attrib['Name'] }}
@@ -208,15 +208,15 @@ void {{ Class.attrib['QualifiedName'] }}::Reflect(AZ::ReflectContext* context)
{% endfor %}
{% endif %}
{% if Class.attrib['Base'] is defined %}
static_assert((std::is_base_of<ScriptCanvas::Node, {{ Class.attrib['Base'] }}>::value), "Script Canvas nodes require the first base class to be derived from ScriptCanvas::Node");
static_assert((std::is_base_of<ScriptCanvas::Node, {{ baseClass }}>::value), "Script Canvas nodes require the first base class to be derived from ScriptCanvas::Node");
{% endif %}
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<{{ Class.attrib['QualifiedName'] }}{% if Class.attrib['Base'] is defined %}, {{ Class.attrib['Base'] }}{% endif %}>()
serializeContext->Class<{{ Class.attrib['QualifiedName'] }}, {{ baseClass }}>()
{% if Class.attrib['EventHandler'] is defined %}
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
->EventHandler<{{ Class.attrib['EventHandler'] }}>()
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)
{% endif %}
{% if Class.attrib['Version'] is defined %}
->Version({{ Class.attrib['Version'] }}{% if Class.attrib['VersionConverter'] is defined %}, &{{ Class.attrib['VersionConverter'] }}{% endif %})
@@ -160,7 +160,9 @@ void {{attribute_QualifiedName}}::Reflect(AZ::ReflectContext* context)
{
{% if ExtendReflectionSerialize is defined %} auto {{preSerialize}} = {% else %} {% endif %}serializeContext->Class<{{ attribute_Name }}{% if attribute_Base is defined %}, {{ attribute_Base }}{% endif %}>(){{postSerialize}}
{% if attribute_EventHandler is defined %}
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
{{preSerialize}}->EventHandler<{{ attribute_EventHandler }}>(){{postSerialize}}
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)
{% endif %}
{# Serialized Properties #}
@@ -173,11 +173,10 @@ AZStd::tuple<{{returnTypes|join(", ")}}>
{# ------- #}
{# ------------------------------------------------------------------------------------- #}
{# 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) -%}
{% set contracts = [] %}
@@ -24,6 +24,8 @@
#include <Core/NamedId.h>
#include <ScriptCanvas/Grammar/PrimitivesDeclarations.h>
#define OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED
namespace AZ
{
class Entity;
@@ -94,7 +96,7 @@ namespace ScriptCanvas
struct VersionData
{
AZ_TYPE_INFO(VersionData, "{14C629F6-467B-46FE-8B63-48FDFCA42175}");
AZ_TYPE_INFO(VersionData, "{52036892-DA63-4199-AC6A-9BAFE6B74EFC}");
static void Reflect(AZ::ReflectContext* context);
@@ -2041,7 +2041,7 @@ namespace ScriptCanvas
}
}
void Datum::OnWriteEnd()
void Datum::OnDeserialize()
{
if (m_type.GetType() == Data::eType::BehaviorContextObject)
{
@@ -2059,18 +2059,27 @@ namespace ScriptCanvas
}
else
{
AZ_Error("Script Canvas", false, AZStd::string::format("Datum type (%s) de-serialized, but no such class found in the behavior context", m_type.GetAZType().ToString<AZStd::string>().c_str()).c_str());
AZ_Error("ScriptCanvas", false, AZStd::string::format("Datum type (%s) de-serialized, but no such class found in the behavior context", m_type.GetAZType().ToString<AZStd::string>().c_str()).c_str());
}
}
}
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
void Datum::OnWriteEnd()
{
OnDeserialize();
}
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)
void Datum::Reflect(AZ::ReflectContext* reflection)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection))
{
serializeContext->Class<Datum>()
->Version(DatumHelpers::Version::Current, &DatumHelpers::VersionConverter)
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
->EventHandler<SerializeContextEventHandler>()
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)
->Field("m_isUntypedStorage", &Datum::m_isOverloadedStorage)
->Field("m_type", &Datum::m_type)
->Field("m_originality", &Datum::m_originality)
@@ -8,14 +8,15 @@
#pragma once
#include <AzCore/Outcome/Outcome.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/std/string/string_view.h>
#include <ScriptCanvas/Core/Core.h>
#include <ScriptCanvas/Core/SerializationListener.h>
#include <ScriptCanvas/Data/BehaviorContextObject.h>
#include <ScriptCanvas/Data/Data.h>
#include <ScriptCanvas/Data/DataTrait.h>
#include <ScriptCanvas/Data/BehaviorContextObject.h>
#include <AzCore/Outcome/Outcome.h>
namespace AZ
{
@@ -33,11 +34,12 @@ namespace ScriptCanvas
/// A Datum is used to provide generic storage for all data types in ScriptCanvas, and provide a common interface to accessing, modifying, and displaying them
/// in the editor, regardless of their actual ScriptCanvas or BehaviorContext type.
class Datum final
: public SerializationListener
{
friend class AZ::DatumSerializer;
public:
AZ_TYPE_INFO(Datum, "{8B836FC0-98A8-4A81-8651-35C7CA125451}");
AZ_RTTI(Datum, "{8B836FC0-98A8-4A81-8651-35C7CA125451}", SerializationListener);
AZ_CLASS_ALLOCATOR(Datum, AZ::SystemAllocator, 0);
enum class eOriginality : int
@@ -234,6 +236,7 @@ namespace ScriptCanvas
}
};
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
class SerializeContextEventHandler : public AZ::SerializeContext::IEventHandler
{
public:
@@ -244,6 +247,7 @@ namespace ScriptCanvas
datum->OnWriteEnd();
}
};
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)
friend class SerializeContextEventHandler;
@@ -341,9 +345,11 @@ namespace ScriptCanvas
void OnDatumEdited();
void OnReadBegin();
void OnDeserialize() override;
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
void OnWriteEnd();
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)
AZ_INLINE bool SatisfiesTraits(AZ::u8 behaviorValueTraits) const;
@@ -19,17 +19,17 @@ namespace AZ
namespace ScriptCanvas
{
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
class GraphDataEventHandler : public AZ::SerializeContext::IEventHandler
{
public:
/// Called to rebuild the Endpoint map
void OnWriteEnd(void* classPtr) override
{
auto* graphData = reinterpret_cast<GraphData*>(classPtr);
graphData->BuildEndpointMap();
graphData->LoadDependentAssets();
reinterpret_cast<GraphData*>(classPtr)->OnDeserialized();
}
};
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)
void GraphData::Reflect(AZ::ReflectContext* context)
{
@@ -42,7 +42,9 @@ namespace ScriptCanvas
serializeContext->Class<GraphData>()
->Version(4, &GraphData::VersionConverter)
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
->EventHandler<GraphDataEventHandler>()
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)
->Field("m_nodes", &GraphData::m_nodes)
->Field("m_connections", &GraphData::m_connections)
->Field("m_dependentAssets", &GraphData::m_dependentAssets)
@@ -215,4 +217,10 @@ namespace ScriptCanvas
m_dependentAssets.clear();
}
void GraphData::OnDeserialized()
{
BuildEndpointMap();
LoadDependentAssets();
}
}
@@ -37,6 +37,7 @@ namespace ScriptCanvas
void BuildEndpointMap();
void Clear(bool deleteData = false);
void LoadDependentAssets();
void OnDeserialized();
using NodeContainer = AZStd::unordered_set<AZ::Entity*>;
using ConnectionContainer = AZStd::vector<AZ::Entity*>;
@@ -60,6 +60,7 @@ namespace ScriptCanvas
// Node
/////////
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
class NodeEventHandler
: public AZ::SerializeContext::IEventHandler
{
@@ -67,9 +68,10 @@ namespace ScriptCanvas
void OnWriteEnd(void* objectPtr) override
{
auto node = reinterpret_cast<Node*>(objectPtr);
node->RebuildInternalState();
node->OnDeserialize();
}
};
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)
bool NodeVersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& nodeElementNode)
{
@@ -420,7 +422,9 @@ namespace ScriptCanvas
serializeContext->RegisterGenericType<AZStd::unordered_map<SlotId, Deprecated::VariableInfo>>();
serializeContext->Class<Node, AZ::Component>()
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
->EventHandler<NodeEventHandler>()
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)
->Version(NodeCpp::Version::Current, &NodeVersionConverter)
->Field("Slots", &Node::m_slots)
->Field("Datums", &Node::m_slotDatums)
@@ -2616,6 +2620,11 @@ namespace ScriptCanvas
}
}
void Node::OnDeserialize()
{
RebuildInternalState();
}
void Node::OnEndpointConnected(const Endpoint& endpoint)
{
const SlotId& currentSlotId = EndpointNotificationBus::GetCurrentBusId()->GetSlotId();
@@ -14,25 +14,23 @@
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/std/tuple.h>
#include <ScriptCanvas/CodeGen/NodeableCodegen.h>
#include <ScriptCanvas/Core/Contracts/TypeContract.h>
#include <ScriptCanvas/Core/Core.h>
#include <ScriptCanvas/Core/DatumBus.h>
#include <ScriptCanvas/Core/Endpoint.h>
#include <ScriptCanvas/Core/SubgraphInterface.h>
#include <ScriptCanvas/Core/ExecutionNotificationsBus.h>
#include <ScriptCanvas/Core/GraphBus.h>
#include <ScriptCanvas/Core/NodeBus.h>
#include <ScriptCanvas/Core/SerializationListener.h>
#include <ScriptCanvas/Core/Slot.h>
#include <ScriptCanvas/Core/SubgraphInterface.h>
#include <ScriptCanvas/Debugger/StatusBus.h>
#include <ScriptCanvas/Debugger/ValidationEvents/ValidationEvent.h>
#include <ScriptCanvas/Execution/ErrorBus.h>
#include <ScriptCanvas/Execution/ExecutionBus.h>
#include <ScriptCanvas/Variable/GraphVariable.h>
#include <ScriptCanvas/Grammar/Primitives.h>
#include <ScriptCanvas/Debugger/ValidationEvents/ValidationEvent.h>
#include <ScriptCanvas/CodeGen/NodeableCodegen.h>
#include <ScriptCanvas/Variable/GraphVariable.h>
#define SCRIPT_CANVAS_CALL_ON_INDEX_SEQUENCE(lambdaInterior)\
int dummy[]{ 0, ( lambdaInterior , 0)... };\
@@ -65,6 +63,7 @@ namespace ScriptCanvas
struct BehaviorContextMethodHelper;
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
template<typename t_Class>
class SerializeContextReadWriteHandler : public AZ::SerializeContext::IEventHandler
{
@@ -128,6 +127,7 @@ namespace ScriptCanvas
deserializedObject->OnWriteEnd();
}
};
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)
// List of slots that will be create visual only slots on the nodes.
// Useful for special configurations or editor only concepts.
@@ -401,6 +401,7 @@ namespace ScriptCanvas
, public DatumNotificationBus::Handler
, public NodeRequestBus::Handler
, public EndpointNotificationBus::MultiHandler
, public SerializationListener
{
friend class Graph;
friend class RuntimeComponent;
@@ -472,7 +473,7 @@ namespace ScriptCanvas
public:
AZ_COMPONENT(Node, "{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}");
AZ_COMPONENT(Node, "{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}", SerializationListener);
static void Reflect(AZ::ReflectContext* reflection);
Node();
@@ -821,6 +822,7 @@ namespace ScriptCanvas
//////////////////////////////////////////////////////////////////////////
protected:
void OnDeserialize() override;
virtual void OnReconfigurationBegin() {}
virtual void OnReconfigurationEnd() {}
@@ -0,0 +1,25 @@
/*
* 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
namespace ScriptCanvas
{
class SerializationListener
{
public:
AZ_RTTI(SerializationListener, "{CA4EE281-30B3-4928-BCD8-9305CE75E463}");
virtual ~SerializationListener() {}
virtual void OnSerialize() {}
virtual void OnDeserialize() {}
};
using SerializationListeners = AZStd::vector<SerializationListener*>;
}
@@ -17,26 +17,12 @@
namespace ScriptCanvas
{
void BehaviorContextObject::OnReadBegin()
{
if (!IsOwned())
{
Clear();
}
}
void BehaviorContextObject::OnWriteEnd()
{
// Id Remapping invokes this method as well, not just serializing from an ObjectStream
}
void BehaviorContextObject::Reflect(AZ::ReflectContext* reflection)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection))
{
serializeContext->Class<BehaviorContextObject>()
->Version(0)
->EventHandler<SerializeContextEventHandler>()
->Field("m_flags", &BehaviorContextObject::m_flags)
->Field("m_object", &BehaviorContextObject::m_object)
;
@@ -55,24 +41,11 @@ namespace ScriptCanvas
}
}
void BehaviorContextObject::SerializeContextEventHandler::OnReadBegin(void* classPtr)
{
BehaviorContextObject* object = reinterpret_cast<BehaviorContextObject*>(classPtr);
object->OnReadBegin();
}
void BehaviorContextObject::SerializeContextEventHandler::OnWriteEnd(void* classPtr)
{
BehaviorContextObject* object = reinterpret_cast<BehaviorContextObject*>(classPtr);
object->OnWriteEnd();
}
BehaviorContextObjectPtr BehaviorContextObject::CloneObject(const AZ::BehaviorClass& behaviorClass)
{
if (SystemRequestBus::HasHandlers())
{
AZStd::vector<char> buffer;
{
bool wasOwned = IsOwned();
m_flags |= Flags::Owned;
@@ -87,7 +60,6 @@ namespace ScriptCanvas
}
AZ::IO::ByteContainerStream<AZStd::vector<char>> readStream(&buffer);
BehaviorContextObject* newObject = CreateDefault(behaviorClass);
AZ::Utils::LoadObjectFromStreamInPlace(readStream, (*newObject));
@@ -124,6 +96,12 @@ namespace ScriptCanvas
: 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()
{
if (--m_referenceCount == 0)
@@ -22,6 +22,7 @@
namespace AZ
{
class ReflectContext;
class BehaviorContextObjectSerializer;
}
namespace ScriptCanvas
@@ -29,6 +30,8 @@ namespace ScriptCanvas
class BehaviorContextObject final
{
friend struct AZStd::IntrusivePtrCountPolicy<BehaviorContextObject>;
friend class Datum;
friend class AZ::BehaviorContextObjectSerializer;
public:
AZ_TYPE_INFO(BehaviorContextObject, "{B735214D-5182-4536-B748-61EC83C1F007}");
@@ -69,16 +72,6 @@ namespace ScriptCanvas
Reference = 1 << 3,
};
class SerializeContextEventHandler : public AZ::SerializeContext::IEventHandler
{
public:
/// Called right before we start reading from the instance pointed by classPtr.
void OnReadBegin(void* classPtr) override;
/// Called after we are done writing to the instance pointed by classPtr.
void OnWriteEnd(void* classPtr) override;
};
template<typename... Args>
static AZ::BehaviorObject InvokeConstructor(const AZ::BehaviorClass& behaviorClass, void* resultPtr, Args&&... args);
@@ -90,6 +83,8 @@ namespace ScriptCanvas
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
AZ_FORCE_INLINE static AnyTypeInfo GetAnyTypeInfoObject(const AZ::BehaviorClass& behaviorClass);
@@ -110,6 +105,7 @@ namespace ScriptCanvas
// it is very important to track these from the moment they are created...
friend struct AZ::Serialize::InstanceFactory<BehaviorContextObject, true, false>;
friend struct AZ::AnyTypeInfoConcept<BehaviorContextObject, void>;
//...so don't use the ctors, use the Create functions...
//...the friend declarations are here for compatibility with the serialization system only
AZ_FORCE_INLINE BehaviorContextObject() = default;
@@ -128,10 +124,6 @@ namespace ScriptCanvas
AZ_FORCE_INLINE bool IsOwned() const;
void OnReadBegin();
void OnWriteEnd();
AZ_FORCE_INLINE void add_ref();
void release();
@@ -602,15 +602,24 @@ namespace ScriptCanvas
}
}
void EBusEventHandler::OnWriteEnd()
void EBusEventHandler::OnDeserialize()
{
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
if (!m_ebus)
{
CreateHandler(m_ebusName);
}
Node::OnDeserialize();
}
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
void EBusEventHandler::OnWriteEnd()
{
OnDeserialize();
}
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)
NodeTypeIdentifier EBusEventHandler::GetOutputNodeType(const SlotId& slotId) const
{
for (auto mapPair : m_eventMap)
@@ -138,7 +138,11 @@ namespace ScriptCanvas
void SetAutoConnectToGraphOwner(bool enabled);
void OnDeserialize();
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
void OnWriteEnd();
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)
AZStd::string GetNodeName() const override
{
@@ -313,6 +313,7 @@ namespace ScriptCanvas
}
PopulateNodeType();
m_warnOnMissingFunction = true;
}
bool Method::InitializeOverloaded([[maybe_unused]] const NamespacePath& namespaces, AZStd::string_view className, AZStd::string_view methodName)
@@ -739,10 +740,11 @@ namespace ScriptCanvas
return TupleType{ nullptr, MethodType::Count, EventType::Count, nullptr };
}
void Method::OnWriteEnd()
void Method::OnDeserialize()
{
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex);
m_warnOnMissingFunction = true;
const AZ::BehaviorClass* bcClass{};
const AZ::BehaviorMethod* method{};
EventType eventType;
@@ -758,15 +760,23 @@ namespace ScriptCanvas
{
AZ_Warning("ScriptCanvas", !m_warnOnMissingFunction, "method node failed to deserialize properly");
}
}
if (m_resultSlotIDs.empty())
{
m_resultSlotIDs.emplace_back(SlotId{});
}
Node::OnDeserialize();
}
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
void Method::OnWriteEnd()
{
OnDeserialize();
}
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)
bool Method::BranchesOnResult() const
{
return m_method && m_method->HasResult() &&
@@ -829,7 +839,9 @@ namespace ScriptCanvas
{
serializeContext->Class<Method, Node>()
->Version(MethodCPP::eVersion::Current, &MethodCPP::MethodVersionConverter)
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
->EventHandler<SerializeContextOnWriteEndHandler<Method>>()
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)
->Field("methodType", &Method::m_methodType)
->Field("methodName", &Method::m_lookupName)
->Field("className", &Method::m_className)
@@ -22,7 +22,6 @@ namespace AZ
namespace ScriptCanvas
{
AZ::Outcome<void, AZStd::string> IsExposable(const AZ::BehaviorMethod& method);
Grammar::FunctionPrototype ToSignature(const AZ::BehaviorMethod& method);
@@ -31,7 +30,8 @@ namespace ScriptCanvas
{
namespace Core
{
class Method : public Node
class Method
: public Node
{
public:
AZ_COMPONENT(Method, "{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF}", Node);
@@ -107,7 +107,11 @@ namespace ScriptCanvas
SlotId GetBusSlotId() const;
void OnDeserialize();
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
void OnWriteEnd();
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)
virtual bool IsMethodOverloaded() const { return false; }
@@ -180,7 +184,7 @@ namespace ScriptCanvas
AZStd::vector<SlotId> m_inputSlots;
AZStd::vector<SlotId> m_resultSlotIDs;
AZStd::recursive_mutex m_mutex; // post-serialization
bool m_warnOnMissingFunction = true;
bool m_warnOnMissingFunction = false;
Method(const Method&) = delete;
};
@@ -60,7 +60,9 @@ namespace ScriptCanvas
{
serializeContext->Class<MethodOverloaded, Method>()
->Version(MethodOverloadedCpp::Version::Current, &MethodOverloadedVersionConverter)
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
->EventHandler<SerializeContextReadWriteHandler<MethodOverloaded>>()
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)
->Field("orderedInputSlotIds", &MethodOverloaded::m_orderedInputSlotIds)
->Field("outputSlotIds", &MethodOverloaded::m_outputSlotIds)
;
@@ -186,6 +188,7 @@ namespace ScriptCanvas
RefreshActiveIndexes();
ConfigureContracts();
SetWarnOnMissingFunction(true);
}
SlotId MethodOverloaded::AddMethodInputSlot(const MethodConfiguration& config, size_t argumentIndex)
@@ -397,20 +400,14 @@ namespace ScriptCanvas
return signature;
}
void MethodOverloaded::OnReadBegin()
{
}
void MethodOverloaded::OnReadEnd()
{
}
void MethodOverloaded::OnWriteBegin()
{
SetWarnOnMissingFunction(false);
}
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
void MethodOverloaded::OnWriteEnd()
{
OnDeserialize();
}
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)
void MethodOverloaded::OnDeserialize()
{
AZStd::lock_guard<AZStd::recursive_mutex> lock(GetMutex());
@@ -462,6 +459,7 @@ namespace ScriptCanvas
}
SetWarnOnMissingFunction(true);
Node::OnDeserialize();
}
void MethodOverloaded::SetupMethodData(const AZ::BehaviorMethod* behaviorMethod, const AZ::BehaviorClass* behaviorClass)
@@ -33,7 +33,9 @@ namespace ScriptCanvas
, public OverloadContractInterface
{
private:
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
friend class SerializeContextReadWriteHandler<MethodOverloaded>;
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)
public:
static void Reflect(AZ::ReflectContext* reflectContext);
@@ -91,13 +93,15 @@ namespace ScriptCanvas
// \todo make execution thread sensitive, which can then support generic programming
Grammar::FunctionPrototype GetInputSignature() const;
#if defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)////
// SerializeContextReadWriteHandler
void OnReadBegin();
void OnReadEnd();
void OnWriteBegin();
void OnReadBegin() {}
void OnReadEnd() {}
void OnWriteBegin() {}
void OnWriteEnd();
////
#endif//defined(OBJECT_STREAM_EDITOR_ASSET_LOADING_SUPPORT_ENABLED)
void OnDeserialize() override;
void SetupMethodData(const AZ::BehaviorMethod* lookupMethod, const AZ::BehaviorClass* lookupClass);
void ConfigureContracts();
@@ -5,7 +5,6 @@
QualifiedName="ScriptCanvas::Nodes::Logic::Gate"
PreferredClassName="If"
Uuid="{F19CC10A-02FD-4E75-ADAA-9CFBD8A4E2F8}"
Base="ScriptCanvas::Node"
Icon="Icons/ScriptCanvas/Print.png"
Version="0"
GeneratePropertyFriend="True"
@@ -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");
}
}
@@ -0,0 +1,37 @@
/*
* 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/Json/BaseJsonSerializer.h>
#include <AzCore/Serialization/SerializeContext.h>
namespace AZ
{
class BehaviorContextObjectSerializer
: public BaseJsonSerializer
{
public:
AZ_RTTI(BehaviorContextObjectSerializer, "{88469C4C-923F-4508-A45C-33DDBB91074E}", BaseJsonSerializer);
AZ_CLASS_ALLOCATOR_DECL;
private:
JsonSerializationResult::Result Load
( void* outputValue
, const Uuid& outputValueTypeId
, const rapidjson::Value& inputValue
, JsonDeserializerContext& context) override;
JsonSerializationResult::Result Store
( rapidjson::Value& outputValue
, const void* inputValue
, const void* defaultValue
, const Uuid& valueTypeId, JsonSerializerContext& context) override;
};
}
@@ -50,10 +50,23 @@ namespace AZ
, "scriptCanvasType"
, context));
AZStd::any storage;
{ // datum storage begin
AZ::Uuid typeId = AZ::Uuid::CreateNull();
// datum storage begin
auto isNullPointerMember = inputValue.FindMember("isNullPointer");
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);
if (typeIdMember == inputValue.MemberEnd())
{
@@ -71,7 +84,7 @@ namespace AZ
, "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)
{
return context.Report(result, "DatumSerializer::Load failed to load a value matched the reported AZ TypeId. "
@@ -79,22 +92,25 @@ namespace AZ
}
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
AZStd::string label;
AZ_Assert(azrtti_typeid<decltype(outputDatum->m_datumLabel)>() == azrtti_typeid<decltype(label)>()
, "m_datumLabel type changed and won't load properly");
result.Combine(ContinueLoadingFromJsonObjectField
result.Combine(ContinueLoadingFromJsonObjectField
( &label
, azrtti_typeid<decltype(outputDatum->m_datumLabel)>()
, inputValue
, "label"
, context));
outputDatum->SetLabel(label);
Datum copy(scType, Datum::eOriginality::Original, AZStd::any_cast<void>(&storage), scType.GetAZType());
copy.SetLabel(label);
*outputDatum = copy;
if (auto listeners = context.GetMetadata().Find<SerializationListeners>())
{
listeners->push_back(outputDatum);
}
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
? "DatumSerializer Load finished loading Datum"
: "DatumSerializer Load failed to load Datum");
@@ -123,7 +139,7 @@ namespace AZ
( JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "DatumSerializer Store used defaults for Datum");
}
}
JSR::ResultCode result(JSR::Tasks::WriteValue);
outputValue.SetObject();
@@ -142,26 +158,32 @@ namespace AZ
, defaultScriptDataPtr ? &defaultScriptDataPtr->GetType() : nullptr
, azrtti_typeid<decltype(inputScriptDataPtr->GetType())>()
, context));
{ // datum storage begin
{
rapidjson::Value typeValue;
result.Combine(StoreTypeId(typeValue, inputScriptDataPtr->GetType().GetAZType(), context));
outputValue.AddMember
( rapidjson::StringRef(JsonSerialization::TypeIdFieldIdentifier)
, AZStd::move(typeValue)
, context.GetJsonAllocator());
}
// datum storage begin
auto inputObjectSource = inputScriptDataPtr->GetAsDanger();
outputValue.AddMember("isNullPointer", rapidjson::Value(inputObjectSource == nullptr), context.GetJsonAllocator());
if (inputObjectSource)
{
rapidjson::Value typeValue;
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
( outputValue
, "value"
, inputScriptDataPtr->GetAsDanger()
, defaultScriptDataPtr ? defaultScriptDataPtr->GetAsDanger() : nullptr
, inputObjectSource
, defaultObjectSource
, inputScriptDataPtr->GetType().GetAZType()
, context));
} // datum storage end
}
// datum storage end
result.Combine(ContinueStoringToJsonObjectField
( outputValue
, "label"
@@ -174,5 +196,4 @@ namespace AZ
? "DatumSerializer Store finished saving Datum"
: "DatumSerializer Store failed to save Datum");
}
}
@@ -50,6 +50,7 @@ namespace AZ
}
result.Combine(ContinueLoadingFromJsonObjectField(AZStd::any_cast<void>(&outputVariable->value), typeId, inputValue, "value", context));
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
? "RuntimeVariableSerializer Load finished loading RuntimeVariable"
: "RuntimeVariableSerializer Load failed to load RuntimeVariable");