Add JSON serializer support for the Lua component properties

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

1
.gitignore vendored

@ -25,3 +25,4 @@ TestResults/**
*.swatches
/imgui.ini
/scripts/project_manager/logs/
/AutomatedTesting/Gem/PythonTests/scripting/TestResults

@ -31,7 +31,6 @@ namespace AZ
ScriptPropertyGenericClassArray::Reflect(reflection);
ScriptPropertyAsset::Reflect(reflection);
ScriptPropertyEntityRef::Reflect(reflection);
}
template<class Iterator>
@ -1358,53 +1357,4 @@ namespace AZ
m_value = assetProperty->m_value;
}
}
////////////////////////////
// ScriptPropertyEntityRef
////////////////////////////
void ScriptPropertyEntityRef::Reflect(AZ::ReflectContext* reflection)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection);
if (serializeContext)
{
serializeContext->Class<AZ::ScriptPropertyEntityRef, AZ::ScriptProperty>()->
Version(1)->
Field("value", &AZ::ScriptPropertyEntityRef::m_value);
}
}
const AZ::Uuid& ScriptPropertyEntityRef::GetDataTypeUuid() const
{
return AZ::SerializeTypeInfo<AZ::EntityId>::GetUuid();
}
bool ScriptPropertyEntityRef::DoesTypeMatch(AZ::ScriptDataContext& context, int valueIndex) const
{
return context.IsRegisteredClass(valueIndex);
}
AZ::ScriptPropertyEntityRef* ScriptPropertyEntityRef::Clone(const char* name) const
{
AZ::ScriptPropertyEntityRef* clonedValue = aznew AZ::ScriptPropertyEntityRef(name ? name : m_name.c_str());
clonedValue->m_value = m_value;
return clonedValue;
}
bool ScriptPropertyEntityRef::Write(AZ::ScriptContext& context)
{
AZ::ScriptValue<AZ::EntityId>::StackPush(context.NativeContext(), m_value);
return true;
}
void ScriptPropertyEntityRef::CloneDataFrom(const AZ::ScriptProperty* scriptProperty)
{
const AZ::ScriptPropertyEntityRef* entityProperty = azrtti_cast<const AZ::ScriptPropertyEntityRef*>(scriptProperty);
AZ_Error("ScriptPropertyEntityRef", entityProperty, "Invalid call to CloneData. Types must match before clone attempt is made.\n");
if (entityProperty)
{
m_value = entityProperty->m_value;
}
}
}

@ -488,34 +488,6 @@ namespace AZ
protected:
void CloneDataFrom(const AZ::ScriptProperty* scriptProperty) override;
};
class ScriptPropertyEntityRef
: public ScriptProperty
{
public:
AZ_CLASS_ALLOCATOR(ScriptPropertyEntityRef, AZ::SystemAllocator, 0);
AZ_RTTI(AZ::ScriptPropertyEntityRef, "{68EDE6C3-0A89-4C50-A86E-06C058C9F862}", ScriptProperty);
static void Reflect(AZ::ReflectContext* reflection);
ScriptPropertyEntityRef() {}
ScriptPropertyEntityRef(const char* name)
: ScriptProperty(name) {}
virtual ~ScriptPropertyEntityRef() = default;
const void* GetDataAddress() const override { return &m_value; }
const AZ::Uuid& GetDataTypeUuid() const override;
bool DoesTypeMatch(AZ::ScriptDataContext& context, int valueIndex) const override;
ScriptPropertyEntityRef* Clone(const char* name = nullptr) const override;
bool Write(AZ::ScriptContext& context) override;
AZ::EntityId m_value;
protected:
void CloneDataFrom(const AZ::ScriptProperty* scriptProperty) override;
};
}
#endif

@ -0,0 +1,99 @@
/*
* 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/Script/ScriptPropertySerializer.h>
#include <AzCore/Serialization/DynamicSerializableField.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
namespace AZ
{
AZ_CLASS_ALLOCATOR_IMPL(ScriptPropertySerializer, SystemAllocator, 0);
JsonSerializationResult::Result ScriptPropertySerializer::Load
( void* outputValue
, [[maybe_unused]] const Uuid& outputValueTypeId
, const rapidjson::Value& inputValue
, JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult;
AZ_Assert(outputValueTypeId == azrtti_typeid<DynamicSerializableField>(), "ScriptPropertySerializer Load against output typeID that was not DynamicSerializableField");
AZ_Assert(outputValue, "ScriptPropertySerializer Load against null output");
auto outputVariable = reinterpret_cast<DynamicSerializableField*>(outputValue);
JsonSerializationResult::ResultCode result(JSR::Tasks::ReadField);
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("ScriptPropertySerializer::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, "ScriptPropertySerializer::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, "ScriptPropertySerializer::Load failed to load a value matched the reported AZ TypeId. The C++ declaration may have been deleted or changed.");
}
DynamicSerializableField storageField;
storageField.m_data = AZStd::any_cast<void>(&storage);
storageField.m_typeId = typeId;
outputVariable->CopyDataFrom(storageField, context.GetSerializeContext());
result.Combine(ContinueLoadingFromJsonObjectField(outputVariable->m_data, typeId, inputValue, "value", context));
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
? "ScriptPropertySerializer Load finished loading DynamicSerializableField"
: "ScriptPropertySerializer Load failed to load DynamicSerializableField");
}
JsonSerializationResult::Result ScriptPropertySerializer::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<DynamicSerializableField>(), "DynamicSerializableField Store against value typeID that was not DynamicSerializableField");
AZ_Assert(inputValue, "DynamicSerializableField Store against null inputValue pointer ");
auto inputScriptDataPtr = reinterpret_cast<const DynamicSerializableField*>(inputValue);
auto inputFieldPtr = inputScriptDataPtr->m_data;
auto defaultScriptDataPtr = reinterpret_cast<const DynamicSerializableField*>(defaultValue);
auto defaultFieldPtr = defaultScriptDataPtr ? &defaultScriptDataPtr->m_data : nullptr;
if (defaultScriptDataPtr && inputScriptDataPtr->IsEqualTo(*defaultScriptDataPtr, context.GetSerializeContext()))
{
return context.Report(JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "ScriptPropertySerializer Store used defaults for DynamicSerializableField");
}
JSR::ResultCode result(JSR::Tasks::WriteValue);
outputValue.SetObject();
{
rapidjson::Value typeValue;
result.Combine(StoreTypeId(typeValue, inputScriptDataPtr->m_typeId, context));
outputValue.AddMember(rapidjson::StringRef(JsonSerialization::TypeIdFieldIdentifier), AZStd::move(typeValue), context.GetJsonAllocator());
}
result.Combine(ContinueStoringToJsonObjectField(outputValue, "value", inputFieldPtr, defaultFieldPtr, inputScriptDataPtr->m_typeId, context));
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
? "ScriptPropertySerializer Store finished saving DynamicSerializableField"
: "ScriptPropertySerializer Store failed to save DynamicSerializableField");
}
}

@ -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 ScriptPropertySerializer
: public BaseJsonSerializer
{
public:
AZ_RTTI(ScriptPropertySerializer, "{C7BECA49-84EF-45E6-A89D-052D61766197}", 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;
};
}

@ -8,10 +8,8 @@
#if !defined(AZCORE_EXCLUDE_LUA)
#include <AzCore/Script/ScriptSystemComponent.h>
#include <AzCore/Asset/AssetManagerBus.h>
#include <AzCore/Asset/AssetManager.h>
#include <AzCore/Asset/AssetManagerBus.h>
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/Component/ComponentApplication.h>
#include <AzCore/Component/Entity.h>
@ -21,13 +19,16 @@
#include <AzCore/Math/MathReflection.h>
#include <AzCore/PlatformId/PlatformId.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Script/ScriptAsset.h>
#include <AzCore/Script/ScriptContextDebug.h>
#include <AzCore/Script/ScriptDebug.h>
#include <AzCore/std/string/conversions.h>
#include <AzCore/Script/ScriptPropertySerializer.h>
#include <AzCore/Script/ScriptSystemComponent.h>
#include <AzCore/Script/lua/lua.h>
#include <AzCore/Serialization/DynamicSerializableField.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/Json/RegistrationContext.h>
#include <AzCore/std/string/conversions.h>
using namespace AZ;
@ -921,6 +922,12 @@ void ScriptSystemComponent::Reflect(ReflectContext* reflection)
}
}
if (AZ::JsonRegistrationContext* jsonContext = azrtti_cast<AZ::JsonRegistrationContext*>(reflection))
{
jsonContext->Serializer<AZ::ScriptPropertySerializer>()
->HandlesType<DynamicSerializableField>();
}
if (BehaviorContext* behaviorContext = azrtti_cast<BehaviorContext*>(reflection))
{
// reflect default entity

@ -98,14 +98,14 @@ namespace AZ
return nullptr;
}
//-------------------------------------------------------------------------
void DynamicSerializableField::CopyDataFrom(const DynamicSerializableField& other)
void DynamicSerializableField::CopyDataFrom(const DynamicSerializableField& other, SerializeContext* useContext)
{
DestroyData();
m_typeId = other.m_typeId;
m_data = other.CloneData();
m_data = other.CloneData(useContext);
}
//-------------------------------------------------------------------------
bool DynamicSerializableField::IsEqualTo(const DynamicSerializableField& other, SerializeContext* useContext)
bool DynamicSerializableField::IsEqualTo(const DynamicSerializableField& other, SerializeContext* useContext) const
{
if (other.m_typeId != m_typeId)
{

@ -9,6 +9,8 @@
#define AZCORE_DYNAMIC_SERIALIZABLE_FIELD_H
#include <AzCore/RTTI/TypeInfo.h>
#include <AzCore/Memory/Memory.h>
#include <AzCore/Memory/SystemAllocator.h>
namespace AZ
{
@ -24,6 +26,7 @@ namespace AZ
{
public:
AZ_TYPE_INFO(DynamicSerializableField, "{D761E0C2-A098-497C-B8EB-EA62F5ED896B}")
AZ_CLASS_ALLOCATOR(DynamicSerializableField, AZ::SystemAllocator, 0);
DynamicSerializableField();
DynamicSerializableField(const DynamicSerializableField& serializableField);
@ -33,8 +36,8 @@ namespace AZ
void DestroyData(SerializeContext* useContext = nullptr);
void* CloneData(SerializeContext* useContext = nullptr) const;
void CopyDataFrom(const DynamicSerializableField& other);
bool IsEqualTo(const DynamicSerializableField& other, SerializeContext* useContext = nullptr);
void CopyDataFrom(const DynamicSerializableField& other, SerializeContext* useContext = nullptr);
bool IsEqualTo(const DynamicSerializableField& other, SerializeContext* useContext = nullptr) const;
template<class T>
void Set(T* object)

@ -13,7 +13,6 @@
#include <AzCore/Outcome/Outcome.h>
#include <AzCore/Slice/SliceAsset.h>
#include <AzCore/Serialization/DataPatch.h>
#include <AzCore/Serialization/DynamicSerializableField.h>
#include <AzCore/Serialization/IdUtils.h>
namespace AZ

@ -462,6 +462,8 @@ set(FILES
Script/ScriptTimePoint.h
Script/ScriptProperty.h
Script/ScriptProperty.cpp
Script/ScriptPropertySerializer.h
Script/ScriptPropertySerializer.cpp
Script/ScriptPropertyTable.h
Script/ScriptPropertyTable.cpp
Script/ScriptPropertyWatcherBus.h

@ -1107,17 +1107,7 @@ namespace AzToolsFramework
ElementAttribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)->
Attribute(AZ::Edit::Attributes::NameLabelOverride, &AZ::ScriptProperty::m_name);
ec->Class<AZ::ScriptPropertyAsset>("Script Property Asset(asset)", "A script asset property")->
ClassElement(AZ::Edit::ClassElements::EditorData, "ScriptPropertyEditorAsset's class attributes.")->
Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)->
DataElement("Asset", &AZ::ScriptPropertyAsset::m_value, "m_value", "An object")->
Attribute(AZ::Edit::Attributes::NameLabelOverride, &AZ::ScriptProperty::m_name);
ec->Class<AZ::ScriptPropertyEntityRef>("Script Property Entity(EntityRef)", "A script entity reference property")->
ClassElement(AZ::Edit::ClassElements::EditorData, "ScriptPropertyEditorEntityRef's class attributes.")->
Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)->
DataElement("EntityRef", &AZ::ScriptPropertyEntityRef::m_value, "m_entity", "An entity reference")->
Attribute(AZ::Edit::Attributes::NameLabelOverride, &AZ::ScriptProperty::m_name);
}
}
}

@ -9,7 +9,6 @@
#include "VersionedProperty.h"
#include <AzCore/Script/ScriptContext.h>
#include <AzCore/Serialization/DynamicSerializableField.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Script/ScriptProperty.h>

Loading…
Cancel
Save