3
0

MaterialPropertyValueSourceDataSerializer.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <Atom/RPI.Edit/Material/MaterialPropertyValueSourceDataSerializer.h>
  9. #include <Atom/RPI.Edit/Material/MaterialPropertyValueSourceData.h>
  10. #include <AzCore/Math/Vector2.h>
  11. #include <AzCore/Math/Vector3.h>
  12. #include <AzCore/Math/Vector4.h>
  13. #include <AzCore/Math/Color.h>
  14. #include <AzCore/Serialization/Json/BaseJsonSerializer.h>
  15. #include <AzCore/Serialization/Json/JsonSerializationResult.h>
  16. #include <AzCore/Serialization/Json/JsonSerialization.h>
  17. #include <AzCore/Serialization/Json/StackedString.h>
  18. namespace AZ
  19. {
  20. namespace RPI
  21. {
  22. AZ_CLASS_ALLOCATOR_IMPL(JsonMaterialPropertyValueSourceDataSerializer, SystemAllocator);
  23. namespace JSR = JsonSerializationResult;
  24. template<typename T>
  25. bool JsonMaterialPropertyValueSourceDataSerializer::LoadAny(
  26. MaterialPropertyValueSourceData& propertyValue, const T& defaultValue,
  27. const rapidjson::Value& inputValue, JsonDeserializerContext& context)
  28. {
  29. T value = defaultValue;
  30. JSR::ResultCode result = ContinueLoading(&value, azrtti_typeid<T>(), inputValue, context);
  31. bool loadSuccess = (result.GetOutcome() == JSR::Outcomes::Success);
  32. if (loadSuccess)
  33. {
  34. propertyValue.m_possibleValues[azrtti_typeid<T>()] = value;
  35. }
  36. return loadSuccess;
  37. }
  38. JsonSerializationResult::Result JsonMaterialPropertyValueSourceDataSerializer::Load(void* outputValue, const Uuid& outputValueTypeId,
  39. const rapidjson::Value& inputValue, JsonDeserializerContext& context)
  40. {
  41. AZ_Assert(azrtti_typeid<MaterialPropertyValueSourceData>() == outputValueTypeId,
  42. "Unable to deserialize material property value to json because the provided type is %s",
  43. outputValueTypeId.ToString<AZStd::string>().c_str());
  44. AZ_UNUSED(outputValueTypeId);
  45. MaterialPropertyValueSourceData* materialPropertyValue = reinterpret_cast<MaterialPropertyValueSourceData*>(outputValue);
  46. AZ_Assert(materialPropertyValue, "Output value for MaterialPropertyValueSourceDataSerializer can't be null.");
  47. JSR::ResultCode result(JSR::Tasks::ReadField);
  48. // We will attempt to read a value with different data types, most of them will fail but this exercise will
  49. // report many warnings that are unnecessary. To avoid spamming the Logs with useless errors/warnings We will push
  50. // a silent reporter and pop it afterwards to report any real errors.
  51. auto silentReporter = []([[maybe_unused]] AZStd::string_view message, AZ::JsonSerializationResult::ResultCode resultCode, [[maybe_unused]] AZStd::string_view path)
  52. {
  53. return resultCode;
  54. };
  55. context.PushReporter(silentReporter);
  56. bool atLeastOneSuccess = false;
  57. // Some types can be serialized into each other, e.g. 42 => true.
  58. // short-circuiting is forbidden here. (Don't write LoadAny() || LoadAny(), or atLeastOneSuccess || LoadAny())
  59. atLeastOneSuccess |= LoadAny<bool>(*materialPropertyValue, true, inputValue, context);
  60. atLeastOneSuccess |= LoadAny<int32_t>(*materialPropertyValue, 0, inputValue, context);
  61. atLeastOneSuccess |= LoadAny<uint32_t>(*materialPropertyValue, 0u, inputValue, context);
  62. atLeastOneSuccess |= LoadAny<float>(*materialPropertyValue, 0.0f, inputValue, context);
  63. atLeastOneSuccess |= LoadAny<AZStd::string>(*materialPropertyValue, AZStd::string(), inputValue, context);
  64. // Vectors/Colors can only be read from arrays or objects. If none of the basic types (+ string) are successfully loaded, the data should be an array.
  65. if (!atLeastOneSuccess)
  66. {
  67. atLeastOneSuccess |= LoadAny<Vector2>(*materialPropertyValue, Vector2(0.0f), inputValue, context);
  68. atLeastOneSuccess |= LoadAny<Vector3>(*materialPropertyValue, Vector3(0.0f), inputValue, context);
  69. atLeastOneSuccess |= LoadAny<Vector4>(*materialPropertyValue, Vector4(0.0f), inputValue, context);
  70. atLeastOneSuccess |= LoadAny<Color>(*materialPropertyValue, Color(0.0f), inputValue, context);
  71. }
  72. context.PopReporter();
  73. if (atLeastOneSuccess)
  74. {
  75. return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Success, "Successfully loaded property value.");
  76. }
  77. else
  78. {
  79. return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unsupported, "No possible supported data type match. See MaterialPropertyDataType");
  80. }
  81. }
  82. JsonSerializationResult::Result JsonMaterialPropertyValueSourceDataSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
  83. [[maybe_unused]] const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context)
  84. {
  85. AZ_Assert(azrtti_typeid<MaterialPropertyValueSourceData>() == valueTypeId,
  86. "Unable to serialize functor property value to json because the provided type is %s",
  87. valueTypeId.ToString<AZStd::string>().c_str());
  88. AZ_UNUSED(valueTypeId);
  89. const MaterialPropertyValueSourceData* materialPropertyValue = reinterpret_cast<const MaterialPropertyValueSourceData*>(inputValue);
  90. AZ_Assert(materialPropertyValue, "Input value for MaterialPropertyValueSourceData can't be null.");
  91. JSR::ResultCode result(JSR::Tasks::WriteValue);
  92. MaterialPropertyValue valueToDeserialize;
  93. // Use the resolved value first. If not applicable, use the first possible source value.
  94. if (materialPropertyValue->IsResolved())
  95. {
  96. valueToDeserialize = materialPropertyValue->m_resolvedValue;
  97. }
  98. else
  99. {
  100. for (const auto& possibleValue : materialPropertyValue->m_possibleValues)
  101. {
  102. if (possibleValue.second.IsValid())
  103. {
  104. valueToDeserialize = possibleValue.second;
  105. }
  106. }
  107. }
  108. if (valueToDeserialize.Is<bool>())
  109. {
  110. result.Combine(ContinueStoring(outputValue, &valueToDeserialize.GetValue<bool>(), nullptr, azrtti_typeid<bool>(), context));
  111. }
  112. else if (valueToDeserialize.Is<int32_t>())
  113. {
  114. result.Combine(ContinueStoring(outputValue, &valueToDeserialize.GetValue<int32_t>(), nullptr, azrtti_typeid<int32_t>(), context));
  115. }
  116. else if (valueToDeserialize.Is<uint32_t>())
  117. {
  118. result.Combine(ContinueStoring(outputValue, &valueToDeserialize.GetValue<uint32_t>(), nullptr, azrtti_typeid<uint32_t>(), context));
  119. }
  120. else if (valueToDeserialize.Is<float>())
  121. {
  122. result.Combine(ContinueStoring(outputValue, &valueToDeserialize.GetValue<float>(), nullptr, azrtti_typeid<float>(), context));
  123. }
  124. else if (valueToDeserialize.Is<Vector2>())
  125. {
  126. result.Combine(ContinueStoring(outputValue, &valueToDeserialize.GetValue<Vector2>(), nullptr, azrtti_typeid<Vector2>(), context));
  127. }
  128. else if (valueToDeserialize.Is<Vector3>())
  129. {
  130. result.Combine(ContinueStoring(outputValue, &valueToDeserialize.GetValue<Vector3>(), nullptr, azrtti_typeid<Vector3>(), context));
  131. }
  132. else if (valueToDeserialize.Is<Vector4>())
  133. {
  134. result.Combine(ContinueStoring(outputValue, &valueToDeserialize.GetValue<Vector4>(), nullptr, azrtti_typeid<Vector4>(), context));
  135. }
  136. else if (valueToDeserialize.Is<Color>())
  137. {
  138. result.Combine(ContinueStoring(outputValue, &valueToDeserialize.GetValue<Color>(), nullptr, azrtti_typeid<Color>(), context));
  139. }
  140. else if (valueToDeserialize.Is<AZStd::string>())
  141. {
  142. result.Combine(ContinueStoring(outputValue, &valueToDeserialize.GetValue<AZStd::string>(), nullptr, azrtti_typeid<AZStd::string>(), context));
  143. }
  144. else
  145. {
  146. ContinueStoring(outputValue, 0, nullptr, azrtti_typeid<int32_t>(), context);
  147. result.Combine(JSR::ResultCode(JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed));
  148. }
  149. if (result.GetProcessing() == JSR::Processing::Completed)
  150. {
  151. return context.Report(result, "Successfully stored property value.");
  152. }
  153. else
  154. {
  155. return context.Report(result, "Partially stored property value.");
  156. }
  157. }
  158. } // namespace RPI
  159. } // namespace AZ