GradientSampler.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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 <GradientSignal/GradientSampler.h>
  9. #include <AzCore/Debug/Profiler.h>
  10. #include <AzCore/Math/Vector3.h>
  11. #include <AzCore/RTTI/BehaviorContext.h>
  12. #include <AzCore/Serialization/EditContext.h>
  13. #include <AzCore/Serialization/SerializeContext.h>
  14. #include <GradientSignal/Ebuses/GradientRequestBus.h>
  15. #include <GradientSignal/Ebuses/GradientTransformRequestBus.h>
  16. #include <GradientSignal/Util.h>
  17. namespace GradientSignal
  18. {
  19. void GradientSampler::Reflect(AZ::ReflectContext* context)
  20. {
  21. AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
  22. if (serialize)
  23. {
  24. serialize->Class<GradientSampler>()
  25. ->Version(1)
  26. ->Field("GradientId", &GradientSampler::m_gradientId)
  27. ->Field("Opacity", &GradientSampler::m_opacity)
  28. ->Field("InvertInput", &GradientSampler::m_invertInput)
  29. ->Field("EnableTransform", &GradientSampler::m_enableTransform)
  30. ->Field("Translate", &GradientSampler::m_translate)
  31. ->Field("Scale", &GradientSampler::m_scale)
  32. ->Field("Rotate", &GradientSampler::m_rotate)
  33. ->Field("EnableLevels", &GradientSampler::m_enableLevels)
  34. ->Field("InputMid", &GradientSampler::m_inputMid)
  35. ->Field("InputMin", &GradientSampler::m_inputMin)
  36. ->Field("InputMax", &GradientSampler::m_inputMax)
  37. ->Field("OutputMin", &GradientSampler::m_outputMin)
  38. ->Field("OutputMax", &GradientSampler::m_outputMax)
  39. ;
  40. AZ::EditContext* edit = serialize->GetEditContext();
  41. if (edit)
  42. {
  43. edit->Class<GradientSampler>("Gradient Sampler", "")
  44. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  45. ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
  46. ->DataElement(0, &GradientSampler::m_gradientId, "Gradient Entity Id", "Entity with attached gradient component")
  47. ->Attribute(AZ::Edit::Attributes::RequiredService, AZ_CRC_CE("GradientService"))
  48. ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify)
  49. ->Attribute(AZ::Edit::Attributes::ChangeValidate, &GradientSampler::ValidatePotentialEntityId)
  50. ->DataElement(AZ::Edit::UIHandlers::Slider, &GradientSampler::m_opacity, "Opacity", "Factor multiplied by the current gradient before mixing.")
  51. ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
  52. ->Attribute(AZ::Edit::Attributes::Max, 1.0f)
  53. ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify)
  54. ->ClassElement(AZ::Edit::ClassElements::Group, "Advanced")
  55. ->Attribute(AZ::Edit::Attributes::AutoExpand, false)
  56. ->DataElement(0, &GradientSampler::m_invertInput, "Invert Input", "")
  57. ->Attribute(AZ::Edit::Attributes::ChangeNotify, &GradientSampler::ChangeNotify)
  58. ->GroupElementToggle("Enable Transform", &GradientSampler::m_enableTransform)
  59. ->Attribute(AZ::Edit::Attributes::AutoExpand, false)
  60. ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues)
  61. ->DataElement(0, &GradientSampler::m_translate, "Translate", "")
  62. ->Attribute(AZ::Edit::Attributes::ReadOnly, &GradientSampler::AreTransformSettingsDisabled)
  63. ->DataElement(0, &GradientSampler::m_scale, "Scale", "")
  64. ->Attribute(AZ::Edit::Attributes::ReadOnly, &GradientSampler::AreTransformSettingsDisabled)
  65. ->DataElement(0, &GradientSampler::m_rotate, "Rotate", "Rotation in degrees.")
  66. ->Attribute(AZ::Edit::Attributes::ReadOnly, &GradientSampler::AreTransformSettingsDisabled)
  67. ->GroupElementToggle("Enable Levels", &GradientSampler::m_enableLevels)
  68. ->Attribute(AZ::Edit::Attributes::AutoExpand, false)
  69. ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues)
  70. ->DataElement(AZ::Edit::UIHandlers::Slider, &GradientSampler::m_inputMid, "Input Mid", "")
  71. ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
  72. ->Attribute(AZ::Edit::Attributes::Max, 10.0f)
  73. ->Attribute(AZ::Edit::Attributes::ReadOnly, &GradientSampler::AreLevelSettingsDisabled)
  74. ->DataElement(AZ::Edit::UIHandlers::Slider, &GradientSampler::m_inputMin, "Input Min", "")
  75. ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
  76. ->Attribute(AZ::Edit::Attributes::Max, 1.0f)
  77. ->Attribute(AZ::Edit::Attributes::ReadOnly, &GradientSampler::AreLevelSettingsDisabled)
  78. ->DataElement(AZ::Edit::UIHandlers::Slider, &GradientSampler::m_inputMax, "Input Max", "")
  79. ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
  80. ->Attribute(AZ::Edit::Attributes::Max, 1.0f)
  81. ->Attribute(AZ::Edit::Attributes::ReadOnly, &GradientSampler::AreLevelSettingsDisabled)
  82. ->DataElement(AZ::Edit::UIHandlers::Slider, &GradientSampler::m_outputMin, "Output Min", "")
  83. ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
  84. ->Attribute(AZ::Edit::Attributes::Max, 1.0f)
  85. ->Attribute(AZ::Edit::Attributes::ReadOnly, &GradientSampler::AreLevelSettingsDisabled)
  86. ->DataElement(AZ::Edit::UIHandlers::Slider, &GradientSampler::m_outputMax, "Output Max", "")
  87. ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
  88. ->Attribute(AZ::Edit::Attributes::Max, 1.0f)
  89. ->Attribute(AZ::Edit::Attributes::ReadOnly, &GradientSampler::AreLevelSettingsDisabled)
  90. ->ClassElement(AZ::Edit::ClassElements::Group, "Preview (Inbound)")
  91. ->Attribute(AZ::Edit::Attributes::AutoExpand, false)
  92. ->UIElement("GradientPreviewer", "Previewer")
  93. ->Attribute(AZ::Edit::Attributes::NameLabelOverride, "")
  94. ->Attribute(AZ_CRC_CE("GradientSampler"), &GradientSampler::GetSampler)
  95. ;
  96. }
  97. }
  98. if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  99. {
  100. behaviorContext->Class<GradientSampler>()
  101. ->Constructor()
  102. ->Property("gradientId", BehaviorValueProperty(&GradientSampler::m_gradientId))
  103. ->Property("opacity", BehaviorValueProperty(&GradientSampler::m_opacity))
  104. ->Property("invertInput", BehaviorValueProperty(&GradientSampler::m_invertInput))
  105. ->Property("enableLevels", BehaviorValueProperty(&GradientSampler::m_enableLevels))
  106. ->Property("inputMid", BehaviorValueProperty(&GradientSampler::m_inputMid))
  107. ->Property("inputMin", BehaviorValueProperty(&GradientSampler::m_inputMin))
  108. ->Property("inputMax", BehaviorValueProperty(&GradientSampler::m_inputMax))
  109. ->Property("outputMin", BehaviorValueProperty(&GradientSampler::m_outputMin))
  110. ->Property("outputMax", BehaviorValueProperty(&GradientSampler::m_outputMax))
  111. ->Property("enableTransforms", BehaviorValueProperty(&GradientSampler::m_enableTransform))
  112. ->Property("translation", BehaviorValueProperty(&GradientSampler::m_translate))
  113. ->Property("scale", BehaviorValueProperty(&GradientSampler::m_scale))
  114. ->Property("rotation", BehaviorValueProperty(&GradientSampler::m_rotate))
  115. ;
  116. }
  117. }
  118. GradientSampler* GradientSampler::GetSampler()
  119. {
  120. return this;
  121. }
  122. AZ::u32 GradientSampler::ChangeNotify() const
  123. {
  124. return AZ::Edit::PropertyRefreshLevels::AttributesAndValues;
  125. }
  126. AZ::Outcome<void, AZStd::string> GradientSampler::ValidatePotentialEntityId(void* newValue, const AZ::Uuid& valueType) const
  127. {
  128. if (azrtti_typeid<AZ::EntityId>() != valueType)
  129. {
  130. AZ_Assert(false, "Unexpected value type");
  131. return AZ::Failure(AZStd::string("Trying to set an entity ID to something that isn't an entity ID!"));
  132. }
  133. AZ::EntityId potentialEntityId = static_cast<AZ::EntityId>(*((AZ::EntityId*)newValue));
  134. // Always allow a clear, no need to check
  135. if (!potentialEntityId.IsValid())
  136. {
  137. return AZ::Success();
  138. }
  139. // Prevent setting the parent to the entity itself.
  140. if (potentialEntityId == m_ownerEntityId)
  141. {
  142. return AZ::Failure(AZStd::string("You cannot set a gradient or modifier to point to itself!"));
  143. }
  144. else
  145. {
  146. bool loopCreated = false;
  147. // See if we are in the new connections network already
  148. GradientRequestBus::EventResult(loopCreated, potentialEntityId, &GradientRequestBus::Events::IsEntityInHierarchy, m_ownerEntityId);
  149. if (loopCreated)
  150. {
  151. return AZ::Failure(AZStd::string("Setting this entity reference will cause a cyclical loop, which is not allowed!"));
  152. }
  153. }
  154. return AZ::Success();
  155. }
  156. bool GradientSampler::ValidateGradientEntityId()
  157. {
  158. AZ::ComponentValidationResult result = ValidatePotentialEntityId(&m_gradientId, azrtti_typeid<AZ::EntityId>());
  159. if (!result.IsSuccess())
  160. {
  161. AZ_Warning("GradientSignal", false, "Gradient Sampler refers to an entity that will cause a cyclical loop, which is not allowed! Clearing gradient entity id!");
  162. m_gradientId = AZ::EntityId();
  163. return false;
  164. }
  165. return true;
  166. }
  167. bool GradientSampler::IsEntityInHierarchy(const AZ::EntityId& entityId) const
  168. {
  169. if (entityId == m_gradientId)
  170. {
  171. return true;
  172. }
  173. bool inHierarchy = false;
  174. GradientRequestBus::EventResult(inHierarchy, m_gradientId, &GradientRequestBus::Events::IsEntityInHierarchy, entityId);
  175. return inHierarchy;
  176. }
  177. AZ::Aabb GradientSampler::TransformDirtyRegion(const AZ::Aabb& dirtyRegion) const
  178. {
  179. if ((!m_enableTransform) || (!dirtyRegion.IsValid()))
  180. {
  181. return dirtyRegion;
  182. }
  183. // We do *not* use the inverse transform here because we're transforming from world space to world space.
  184. AZ::Matrix3x4 transformMatrix = GetTransformMatrix();
  185. return dirtyRegion.GetTransformedAabb(transformMatrix);
  186. }
  187. bool GradientSampler::AreLevelSettingsDisabled() const
  188. {
  189. return !m_enableLevels;
  190. }
  191. bool GradientSampler::AreTransformSettingsDisabled() const
  192. {
  193. return !m_enableTransform;
  194. }
  195. }