RotationModifierComponent.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  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 "RotationModifierComponent.h"
  9. #include <AzCore/Component/Entity.h>
  10. #include <AzCore/RTTI/BehaviorContext.h>
  11. #include <AzCore/Serialization/EditContext.h>
  12. #include <AzCore/Serialization/SerializeContext.h>
  13. #include <Vegetation/Descriptor.h>
  14. #include <GradientSignal/Ebuses/GradientRequestBus.h>
  15. #include <Vegetation/InstanceData.h>
  16. #include <VegetationProfiler.h>
  17. namespace Vegetation
  18. {
  19. namespace RotationModifierUtil
  20. {
  21. static bool UpdateVersion(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
  22. {
  23. if (classElement.GetVersion() < 1)
  24. {
  25. AZ::Vector3 rangeMin(0.0f, 0.0f, -180.0f);
  26. if (classElement.GetChildData(AZ_CRC_CE("RangeMin"), rangeMin))
  27. {
  28. classElement.RemoveElementByName(AZ_CRC_CE("RangeMin"));
  29. classElement.AddElementWithData(context, "RangeMinX", (float)rangeMin.GetX());
  30. classElement.AddElementWithData(context, "RangeMinY", (float)rangeMin.GetY());
  31. classElement.AddElementWithData(context, "RangeMinZ", (float)rangeMin.GetZ());
  32. }
  33. AZ::Vector3 rangeMax(0.0f, 0.0f, 180.0f);
  34. if (classElement.GetChildData(AZ_CRC_CE("RangeMax"), rangeMax))
  35. {
  36. classElement.RemoveElementByName(AZ_CRC_CE("RangeMax"));
  37. classElement.AddElementWithData(context, "RangeMaxX", (float)rangeMax.GetX());
  38. classElement.AddElementWithData(context, "RangeMaxY", (float)rangeMax.GetY());
  39. classElement.AddElementWithData(context, "RangeMaxZ", (float)rangeMax.GetZ());
  40. }
  41. }
  42. return true;
  43. }
  44. }
  45. void RotationModifierConfig::Reflect(AZ::ReflectContext* context)
  46. {
  47. AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
  48. if (serialize)
  49. {
  50. serialize->Class<RotationModifierConfig, AZ::ComponentConfig>()
  51. ->Version(1, &RotationModifierUtil::UpdateVersion)
  52. ->Field("AllowOverrides", &RotationModifierConfig::m_allowOverrides)
  53. ->Field("RangeMinX", &RotationModifierConfig::m_rangeMinX)
  54. ->Field("RangeMaxX", &RotationModifierConfig::m_rangeMaxX)
  55. ->Field("GradientX", &RotationModifierConfig::m_gradientSamplerX)
  56. ->Field("RangeMinY", &RotationModifierConfig::m_rangeMinY)
  57. ->Field("RangeMaxY", &RotationModifierConfig::m_rangeMaxY)
  58. ->Field("GradientY", &RotationModifierConfig::m_gradientSamplerY)
  59. ->Field("RangeMinZ", &RotationModifierConfig::m_rangeMinZ)
  60. ->Field("RangeMaxZ", &RotationModifierConfig::m_rangeMaxZ)
  61. ->Field("GradientZ", &RotationModifierConfig::m_gradientSamplerZ)
  62. ;
  63. AZ::EditContext* edit = serialize->GetEditContext();
  64. if (edit)
  65. {
  66. edit->Class<RotationModifierConfig>(
  67. "Vegetation Rotation Modifier", "")
  68. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  69. ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
  70. ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
  71. ->DataElement(AZ::Edit::UIHandlers::CheckBox, &RotationModifierConfig::m_allowOverrides, "Allow Per-Item Overrides", "Allow per-descriptor parameters to override component parameters.")
  72. ->ClassElement(AZ::Edit::ClassElements::Group, "Rotation X")
  73. ->Attribute(AZ::Edit::Attributes::AutoExpand, false)
  74. ->DataElement(AZ::Edit::UIHandlers::Slider, &RotationModifierConfig::m_rangeMinX, "Range Min", "Minimum rotation offset on X axis.")
  75. ->Attribute(AZ::Edit::Attributes::Min, std::numeric_limits<float>::lowest())
  76. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<float>::max())
  77. ->Attribute(AZ::Edit::Attributes::SoftMin, -180.0f)
  78. ->Attribute(AZ::Edit::Attributes::SoftMax, 180.0f)
  79. ->DataElement(AZ::Edit::UIHandlers::Slider, &RotationModifierConfig::m_rangeMaxX, "Range Max", "Maximum rotation offset on X axis.")
  80. ->Attribute(AZ::Edit::Attributes::Min, std::numeric_limits<float>::lowest())
  81. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<float>::max())
  82. ->Attribute(AZ::Edit::Attributes::SoftMin, -180.0f)
  83. ->Attribute(AZ::Edit::Attributes::SoftMax, 180.0f)
  84. ->DataElement(0, &RotationModifierConfig::m_gradientSamplerX, "Gradient", "Gradient used as blend factor to lerp between ranges on X axis.")
  85. ->ClassElement(AZ::Edit::ClassElements::Group, "Rotation Y")
  86. ->Attribute(AZ::Edit::Attributes::AutoExpand, false)
  87. ->DataElement(AZ::Edit::UIHandlers::Slider, &RotationModifierConfig::m_rangeMinY, "Range Min", "Minimum rotation offset on Y axis.")
  88. ->Attribute(AZ::Edit::Attributes::Min, std::numeric_limits<float>::lowest())
  89. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<float>::max())
  90. ->Attribute(AZ::Edit::Attributes::SoftMin, -180.0f)
  91. ->Attribute(AZ::Edit::Attributes::SoftMax, 180.0f)
  92. ->DataElement(AZ::Edit::UIHandlers::Slider, &RotationModifierConfig::m_rangeMaxY, "Range Max", "Maximum rotation offset on Y axis.")
  93. ->Attribute(AZ::Edit::Attributes::Min, std::numeric_limits<float>::lowest())
  94. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<float>::max())
  95. ->Attribute(AZ::Edit::Attributes::SoftMin, -180.0f)
  96. ->Attribute(AZ::Edit::Attributes::SoftMax, 180.0f)
  97. ->DataElement(0, &RotationModifierConfig::m_gradientSamplerY, "Gradient", "Gradient used as blend factor to lerp between ranges on Y axis.")
  98. ->ClassElement(AZ::Edit::ClassElements::Group, "Rotation Z")
  99. ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
  100. ->DataElement(AZ::Edit::UIHandlers::Slider, &RotationModifierConfig::m_rangeMinZ, "Range Min", "Minimum rotation offset on Z axis.")
  101. ->Attribute(AZ::Edit::Attributes::Min, std::numeric_limits<float>::lowest())
  102. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<float>::max())
  103. ->Attribute(AZ::Edit::Attributes::SoftMin, -180.0f)
  104. ->Attribute(AZ::Edit::Attributes::SoftMax, 180.0f)
  105. ->DataElement(AZ::Edit::UIHandlers::Slider, &RotationModifierConfig::m_rangeMaxZ, "Range Max", "Maximum rotation offset on Z axis.")
  106. ->Attribute(AZ::Edit::Attributes::Min, std::numeric_limits<float>::lowest())
  107. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<float>::max())
  108. ->Attribute(AZ::Edit::Attributes::SoftMin, -180.0f)
  109. ->Attribute(AZ::Edit::Attributes::SoftMax, 180.0f)
  110. ->DataElement(0, &RotationModifierConfig::m_gradientSamplerZ, "Gradient", "Gradient used as blend factor to lerp between ranges on Z axis.")
  111. ;
  112. }
  113. }
  114. if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  115. {
  116. behaviorContext->Class<RotationModifierConfig>()
  117. ->Attribute(AZ::Script::Attributes::Category, "Vegetation")
  118. ->Constructor()
  119. ->Property("allowOverrides", BehaviorValueProperty(&RotationModifierConfig::m_allowOverrides))
  120. ->Property("rangeMinX", BehaviorValueProperty(&RotationModifierConfig::m_rangeMinX))
  121. ->Property("rangeMaxX", BehaviorValueProperty(&RotationModifierConfig::m_rangeMaxX))
  122. ->Property("gradientSamplerX", BehaviorValueProperty(&RotationModifierConfig::m_gradientSamplerX))
  123. ->Property("rangeMinY", BehaviorValueProperty(&RotationModifierConfig::m_rangeMinY))
  124. ->Property("rangeMaxY", BehaviorValueProperty(&RotationModifierConfig::m_rangeMaxY))
  125. ->Property("gradientSamplerY", BehaviorValueProperty(&RotationModifierConfig::m_gradientSamplerY))
  126. ->Property("rangeMinZ", BehaviorValueProperty(&RotationModifierConfig::m_rangeMinZ))
  127. ->Property("rangeMaxZ", BehaviorValueProperty(&RotationModifierConfig::m_rangeMaxZ))
  128. ->Property("gradientSamplerZ", BehaviorValueProperty(&RotationModifierConfig::m_gradientSamplerZ))
  129. ;
  130. }
  131. }
  132. void RotationModifierComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services)
  133. {
  134. services.push_back(AZ_CRC_CE("VegetationModifierService"));
  135. services.push_back(AZ_CRC_CE("VegetationRotationModifierService"));
  136. }
  137. void RotationModifierComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services)
  138. {
  139. services.push_back(AZ_CRC_CE("VegetationRotationModifierService"));
  140. }
  141. void RotationModifierComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& services)
  142. {
  143. services.push_back(AZ_CRC_CE("VegetationAreaService"));
  144. }
  145. void RotationModifierComponent::Reflect(AZ::ReflectContext* context)
  146. {
  147. RotationModifierConfig::Reflect(context);
  148. AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
  149. if (serialize)
  150. {
  151. serialize->Class<RotationModifierComponent, AZ::Component>()
  152. ->Version(0)
  153. ->Field("Configuration", &RotationModifierComponent::m_configuration)
  154. ;
  155. }
  156. if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  157. {
  158. behaviorContext->Constant("RotationModifierComponentTypeId", BehaviorConstant(RotationModifierComponentTypeId));
  159. behaviorContext->Class<RotationModifierComponent>()->RequestBus("RotationModifierRequestBus");
  160. behaviorContext->EBus<RotationModifierRequestBus>("RotationModifierRequestBus")
  161. ->Attribute(AZ::Script::Attributes::Category, "Vegetation")
  162. ->Event("GetAllowOverrides", &RotationModifierRequestBus::Events::GetAllowOverrides)
  163. ->Event("SetAllowOverrides", &RotationModifierRequestBus::Events::SetAllowOverrides)
  164. ->VirtualProperty("AllowOverrides", "GetAllowOverrides", "SetAllowOverrides")
  165. ->Event("GetRangeMin", &RotationModifierRequestBus::Events::GetRangeMin)
  166. ->Event("SetRangeMin", &RotationModifierRequestBus::Events::SetRangeMin)
  167. ->VirtualProperty("RangeMin", "GetRangeMin", "SetRangeMin")
  168. ->Event("GetRangeMax", &RotationModifierRequestBus::Events::GetRangeMax)
  169. ->Event("SetRangeMax", &RotationModifierRequestBus::Events::SetRangeMax)
  170. ->VirtualProperty("RangeMax", "GetRangeMax", "SetRangeMax")
  171. ->Event("GetGradientSamplerX", &RotationModifierRequestBus::Events::GetGradientSamplerX)
  172. ->Event("GetGradientSamplerY", &RotationModifierRequestBus::Events::GetGradientSamplerY)
  173. ->Event("GetGradientSamplerZ", &RotationModifierRequestBus::Events::GetGradientSamplerZ)
  174. ;
  175. }
  176. }
  177. RotationModifierComponent::RotationModifierComponent(const RotationModifierConfig& configuration)
  178. : m_configuration(configuration)
  179. {
  180. }
  181. void RotationModifierComponent::Activate()
  182. {
  183. m_dependencyMonitor.Reset();
  184. m_dependencyMonitor.ConnectOwner(GetEntityId());
  185. m_dependencyMonitor.ConnectDependencies({
  186. m_configuration.m_gradientSamplerX.m_gradientId,
  187. m_configuration.m_gradientSamplerY.m_gradientId,
  188. m_configuration.m_gradientSamplerZ.m_gradientId });
  189. ModifierRequestBus::Handler::BusConnect(GetEntityId());
  190. RotationModifierRequestBus::Handler::BusConnect(GetEntityId());
  191. }
  192. void RotationModifierComponent::Deactivate()
  193. {
  194. m_dependencyMonitor.Reset();
  195. ModifierRequestBus::Handler::BusDisconnect();
  196. RotationModifierRequestBus::Handler::BusDisconnect();
  197. }
  198. bool RotationModifierComponent::ReadInConfig(const AZ::ComponentConfig* baseConfig)
  199. {
  200. if (auto config = azrtti_cast<const RotationModifierConfig*>(baseConfig))
  201. {
  202. m_configuration = *config;
  203. return true;
  204. }
  205. return false;
  206. }
  207. bool RotationModifierComponent::WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const
  208. {
  209. if (auto config = azrtti_cast<RotationModifierConfig*>(outBaseConfig))
  210. {
  211. *config = m_configuration;
  212. return true;
  213. }
  214. return false;
  215. }
  216. void RotationModifierComponent::Execute(InstanceData& instanceData) const
  217. {
  218. VEGETATION_PROFILE_FUNCTION_VERBOSE
  219. const GradientSignal::GradientSampleParams sampleParams(instanceData.m_position);
  220. float factorX = m_configuration.m_gradientSamplerX.GetValue(sampleParams);
  221. float factorY = m_configuration.m_gradientSamplerY.GetValue(sampleParams);
  222. float factorZ = m_configuration.m_gradientSamplerZ.GetValue(sampleParams);
  223. const bool useOverrides = m_configuration.m_allowOverrides && instanceData.m_descriptorPtr && instanceData.m_descriptorPtr->m_rotationOverrideEnabled;
  224. const AZ::Vector3& min = useOverrides ? instanceData.m_descriptorPtr->GetRotationMin() : GetRangeMin();
  225. const AZ::Vector3& max = useOverrides ? instanceData.m_descriptorPtr->GetRotationMax() : GetRangeMax();
  226. instanceData.m_rotation = AZ::ConvertEulerDegreesToQuaternion(AZ::Vector3(
  227. factorX * (max.GetX() - min.GetX()) + min.GetX(),
  228. factorY * (max.GetY() - min.GetY()) + min.GetY(),
  229. factorZ * (max.GetZ() - min.GetZ()) + min.GetZ()));
  230. }
  231. bool RotationModifierComponent::GetAllowOverrides() const
  232. {
  233. return m_configuration.m_allowOverrides;
  234. }
  235. void RotationModifierComponent::SetAllowOverrides(bool value)
  236. {
  237. m_configuration.m_allowOverrides = value;
  238. LmbrCentral::DependencyNotificationBus::Event(GetEntityId(), &LmbrCentral::DependencyNotificationBus::Events::OnCompositionChanged);
  239. }
  240. AZ::Vector3 RotationModifierComponent::GetRangeMin() const
  241. {
  242. return AZ::Vector3(m_configuration.m_rangeMinX, m_configuration.m_rangeMinY, m_configuration.m_rangeMinZ);
  243. }
  244. void RotationModifierComponent::SetRangeMin(AZ::Vector3 rangeMin)
  245. {
  246. m_configuration.m_rangeMinX = rangeMin.GetX();
  247. m_configuration.m_rangeMinY = rangeMin.GetY();
  248. m_configuration.m_rangeMinZ = rangeMin.GetZ();
  249. LmbrCentral::DependencyNotificationBus::Event(GetEntityId(), &LmbrCentral::DependencyNotificationBus::Events::OnCompositionChanged);
  250. }
  251. AZ::Vector3 RotationModifierComponent::GetRangeMax() const
  252. {
  253. return AZ::Vector3(m_configuration.m_rangeMaxX, m_configuration.m_rangeMaxY, m_configuration.m_rangeMaxZ);
  254. }
  255. void RotationModifierComponent::SetRangeMax(AZ::Vector3 rangeMax)
  256. {
  257. m_configuration.m_rangeMaxX = rangeMax.GetX();
  258. m_configuration.m_rangeMaxY = rangeMax.GetY();
  259. m_configuration.m_rangeMaxZ = rangeMax.GetZ();
  260. LmbrCentral::DependencyNotificationBus::Event(GetEntityId(), &LmbrCentral::DependencyNotificationBus::Events::OnCompositionChanged);
  261. }
  262. GradientSignal::GradientSampler& RotationModifierComponent::GetGradientSamplerX()
  263. {
  264. return m_configuration.m_gradientSamplerX;
  265. }
  266. GradientSignal::GradientSampler& RotationModifierComponent::GetGradientSamplerY()
  267. {
  268. return m_configuration.m_gradientSamplerY;
  269. }
  270. GradientSignal::GradientSampler& RotationModifierComponent::GetGradientSamplerZ()
  271. {
  272. return m_configuration.m_gradientSamplerZ;
  273. }
  274. }