LevelsGradientComponent.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  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/Components/LevelsGradientComponent.h>
  9. #include <AzCore/Debug/Profiler.h>
  10. #include <AzCore/Math/MathUtils.h>
  11. #include <AzCore/RTTI/BehaviorContext.h>
  12. #include <AzCore/Serialization/EditContext.h>
  13. #include <AzCore/Serialization/SerializeContext.h>
  14. #include <GradientSignal/Util.h>
  15. namespace GradientSignal
  16. {
  17. void LevelsGradientConfig::Reflect(AZ::ReflectContext* context)
  18. {
  19. AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
  20. if (serialize)
  21. {
  22. serialize->Class<LevelsGradientConfig, AZ::ComponentConfig>()
  23. ->Version(0)
  24. ->Field("InputMid", &LevelsGradientConfig::m_inputMid)
  25. ->Field("InputMin", &LevelsGradientConfig::m_inputMin)
  26. ->Field("InputMax", &LevelsGradientConfig::m_inputMax)
  27. ->Field("OutputMin", &LevelsGradientConfig::m_outputMin)
  28. ->Field("OutputMax", &LevelsGradientConfig::m_outputMax)
  29. ->Field("Gradient", &LevelsGradientConfig::m_gradientSampler)
  30. ;
  31. AZ::EditContext* edit = serialize->GetEditContext();
  32. if (edit)
  33. {
  34. edit->Class<LevelsGradientConfig>(
  35. "Levels Gradient", "")
  36. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  37. ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
  38. ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
  39. ->DataElement(AZ::Edit::UIHandlers::Slider, &LevelsGradientConfig::m_inputMid, "Input Mid", "")
  40. ->Attribute(AZ::Edit::Attributes::Min, 0.01f)
  41. ->Attribute(AZ::Edit::Attributes::Max, 10.0f)
  42. ->DataElement(AZ::Edit::UIHandlers::Slider, &LevelsGradientConfig::m_inputMin, "Input Min", "")
  43. ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
  44. ->Attribute(AZ::Edit::Attributes::Max, 1.0f)
  45. ->DataElement(AZ::Edit::UIHandlers::Slider, &LevelsGradientConfig::m_inputMax, "Input Max", "")
  46. ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
  47. ->Attribute(AZ::Edit::Attributes::Max, 1.0f)
  48. ->DataElement(AZ::Edit::UIHandlers::Slider, &LevelsGradientConfig::m_outputMin, "Output Min", "")
  49. ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
  50. ->Attribute(AZ::Edit::Attributes::Max, 1.0f)
  51. ->DataElement(AZ::Edit::UIHandlers::Slider, &LevelsGradientConfig::m_outputMax, "Output Max", "")
  52. ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
  53. ->Attribute(AZ::Edit::Attributes::Max, 1.0f)
  54. ->DataElement(0, &LevelsGradientConfig::m_gradientSampler, "Gradient", "Input gradient whose values will be transformed in relation to threshold.")
  55. ;
  56. }
  57. }
  58. if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  59. {
  60. behaviorContext->Class<LevelsGradientConfig>()
  61. ->Constructor()
  62. ->Attribute(AZ::Script::Attributes::Category, "Vegetation")
  63. ->Property("inputMid", BehaviorValueProperty(&LevelsGradientConfig::m_inputMid))
  64. ->Property("inputMin", BehaviorValueProperty(&LevelsGradientConfig::m_inputMin))
  65. ->Property("inputMax", BehaviorValueProperty(&LevelsGradientConfig::m_inputMax))
  66. ->Property("outputMin", BehaviorValueProperty(&LevelsGradientConfig::m_outputMin))
  67. ->Property("outputMax", BehaviorValueProperty(&LevelsGradientConfig::m_outputMax))
  68. ->Property("gradientSampler", BehaviorValueProperty(&LevelsGradientConfig::m_gradientSampler))
  69. ;
  70. }
  71. }
  72. void LevelsGradientComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services)
  73. {
  74. services.push_back(AZ_CRC_CE("GradientService"));
  75. }
  76. void LevelsGradientComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services)
  77. {
  78. services.push_back(AZ_CRC_CE("GradientService"));
  79. }
  80. void LevelsGradientComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& services)
  81. {
  82. }
  83. void LevelsGradientComponent::Reflect(AZ::ReflectContext* context)
  84. {
  85. LevelsGradientConfig::Reflect(context);
  86. AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
  87. if (serialize)
  88. {
  89. serialize->Class<LevelsGradientComponent, AZ::Component>()
  90. ->Version(0)
  91. ->Field("Configuration", &LevelsGradientComponent::m_configuration)
  92. ;
  93. }
  94. if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  95. {
  96. behaviorContext->Constant("LevelsGradientComponentTypeId", BehaviorConstant(LevelsGradientComponentTypeId));
  97. behaviorContext->Class<LevelsGradientComponent>()->RequestBus("LevelsGradientRequestBus");
  98. behaviorContext->EBus<LevelsGradientRequestBus>("LevelsGradientRequestBus")
  99. ->Attribute(AZ::Script::Attributes::Category, "Vegetation")
  100. ->Event("GetInputMin", &LevelsGradientRequestBus::Events::GetInputMin)
  101. ->Event("SetInputMin", &LevelsGradientRequestBus::Events::SetInputMin)
  102. ->VirtualProperty("InputMin", "GetInputMin", "SetInputMin")
  103. ->Event("GetInputMid", &LevelsGradientRequestBus::Events::GetInputMid)
  104. ->Event("SetInputMid", &LevelsGradientRequestBus::Events::SetInputMid)
  105. ->VirtualProperty("InputMid", "GetInputMid", "SetInputMid")
  106. ->Event("GetInputMax", &LevelsGradientRequestBus::Events::GetInputMax)
  107. ->Event("SetInputMax", &LevelsGradientRequestBus::Events::SetInputMax)
  108. ->VirtualProperty("InputMax", "GetInputMax", "SetInputMax")
  109. ->Event("GetOutputMin", &LevelsGradientRequestBus::Events::GetOutputMin)
  110. ->Event("SetOutputMin", &LevelsGradientRequestBus::Events::SetOutputMin)
  111. ->VirtualProperty("OutputMin", "GetOutputMin", "SetOutputMin")
  112. ->Event("GetOutputMax", &LevelsGradientRequestBus::Events::GetOutputMax)
  113. ->Event("SetOutputMax", &LevelsGradientRequestBus::Events::SetOutputMax)
  114. ->VirtualProperty("PatternType", "GetOutputMax", "SetOutputMax")
  115. ->Event("GetGradientSampler", &LevelsGradientRequestBus::Events::GetGradientSampler)
  116. ;
  117. }
  118. }
  119. LevelsGradientComponent::LevelsGradientComponent(const LevelsGradientConfig& configuration)
  120. : m_configuration(configuration)
  121. {
  122. }
  123. void LevelsGradientComponent::Activate()
  124. {
  125. m_dependencyMonitor.Reset();
  126. m_dependencyMonitor.ConnectOwner(GetEntityId());
  127. m_dependencyMonitor.ConnectDependency(m_configuration.m_gradientSampler.m_gradientId);
  128. LevelsGradientRequestBus::Handler::BusConnect(GetEntityId());
  129. // Connect to GradientRequestBus last so that everything is initialized before listening for gradient queries.
  130. GradientRequestBus::Handler::BusConnect(GetEntityId());
  131. }
  132. void LevelsGradientComponent::Deactivate()
  133. {
  134. // Disconnect from GradientRequestBus first to ensure no queries are in process when deactivating.
  135. GradientRequestBus::Handler::BusDisconnect();
  136. m_dependencyMonitor.Reset();
  137. LevelsGradientRequestBus::Handler::BusDisconnect();
  138. }
  139. bool LevelsGradientComponent::ReadInConfig(const AZ::ComponentConfig* baseConfig)
  140. {
  141. if (auto config = azrtti_cast<const LevelsGradientConfig*>(baseConfig))
  142. {
  143. m_configuration = *config;
  144. return true;
  145. }
  146. return false;
  147. }
  148. bool LevelsGradientComponent::WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const
  149. {
  150. if (auto config = azrtti_cast<LevelsGradientConfig*>(outBaseConfig))
  151. {
  152. *config = m_configuration;
  153. return true;
  154. }
  155. return false;
  156. }
  157. float LevelsGradientComponent::GetValue(const GradientSampleParams& sampleParams) const
  158. {
  159. AZStd::shared_lock lock(m_queryMutex);
  160. float output = 0.0f;
  161. output = GetLevels(
  162. m_configuration.m_gradientSampler.GetValue(sampleParams),
  163. m_configuration.m_inputMid,
  164. m_configuration.m_inputMin,
  165. m_configuration.m_inputMax,
  166. m_configuration.m_outputMin,
  167. m_configuration.m_outputMax);
  168. return output;
  169. }
  170. void LevelsGradientComponent::GetValues(AZStd::span<const AZ::Vector3> positions, AZStd::span<float> outValues) const
  171. {
  172. if (positions.size() != outValues.size())
  173. {
  174. AZ_Assert(false, "input and output lists are different sizes (%zu vs %zu).", positions.size(), outValues.size());
  175. return;
  176. }
  177. AZStd::shared_lock lock(m_queryMutex);
  178. m_configuration.m_gradientSampler.GetValues(positions, outValues);
  179. GetLevels(outValues,
  180. m_configuration.m_inputMid, m_configuration.m_inputMin, m_configuration.m_inputMax,
  181. m_configuration.m_outputMin, m_configuration.m_outputMax);
  182. }
  183. bool LevelsGradientComponent::IsEntityInHierarchy(const AZ::EntityId& entityId) const
  184. {
  185. return m_configuration.m_gradientSampler.IsEntityInHierarchy(entityId);
  186. }
  187. float LevelsGradientComponent::GetInputMin() const
  188. {
  189. return m_configuration.m_inputMin;
  190. }
  191. void LevelsGradientComponent::SetInputMin(float value)
  192. {
  193. bool valueChanged = false;
  194. // Only hold the lock while we're changing the data. Don't hold onto it during the OnCompositionChanged call, because that can
  195. // execute an arbitrary amount of logic, including calls back to this component.
  196. {
  197. AZStd::unique_lock lock(m_queryMutex);
  198. if (m_configuration.m_inputMin != value)
  199. {
  200. m_configuration.m_inputMin = value;
  201. valueChanged = true;
  202. }
  203. }
  204. if (valueChanged)
  205. {
  206. LmbrCentral::DependencyNotificationBus::Event(
  207. GetEntityId(), &LmbrCentral::DependencyNotificationBus::Events::OnCompositionChanged);
  208. }
  209. }
  210. float LevelsGradientComponent::GetInputMid() const
  211. {
  212. return m_configuration.m_inputMid;
  213. }
  214. void LevelsGradientComponent::SetInputMid(float value)
  215. {
  216. bool valueChanged = false;
  217. // Only hold the lock while we're changing the data. Don't hold onto it during the OnCompositionChanged call, because that can
  218. // execute an arbitrary amount of logic, including calls back to this component.
  219. {
  220. AZStd::unique_lock lock(m_queryMutex);
  221. if (m_configuration.m_inputMid != value)
  222. {
  223. m_configuration.m_inputMid = value;
  224. valueChanged = true;
  225. }
  226. }
  227. if (valueChanged)
  228. {
  229. LmbrCentral::DependencyNotificationBus::Event(
  230. GetEntityId(), &LmbrCentral::DependencyNotificationBus::Events::OnCompositionChanged);
  231. }
  232. }
  233. float LevelsGradientComponent::GetInputMax() const
  234. {
  235. return m_configuration.m_inputMax;
  236. }
  237. void LevelsGradientComponent::SetInputMax(float value)
  238. {
  239. bool valueChanged = false;
  240. // Only hold the lock while we're changing the data. Don't hold onto it during the OnCompositionChanged call, because that can
  241. // execute an arbitrary amount of logic, including calls back to this component.
  242. {
  243. AZStd::unique_lock lock(m_queryMutex);
  244. if (m_configuration.m_inputMax != value)
  245. {
  246. m_configuration.m_inputMax = value;
  247. valueChanged = true;
  248. }
  249. }
  250. if (valueChanged)
  251. {
  252. LmbrCentral::DependencyNotificationBus::Event(
  253. GetEntityId(), &LmbrCentral::DependencyNotificationBus::Events::OnCompositionChanged);
  254. }
  255. }
  256. float LevelsGradientComponent::GetOutputMin() const
  257. {
  258. return m_configuration.m_outputMin;
  259. }
  260. void LevelsGradientComponent::SetOutputMin(float value)
  261. {
  262. bool valueChanged = false;
  263. // Only hold the lock while we're changing the data. Don't hold onto it during the OnCompositionChanged call, because that can
  264. // execute an arbitrary amount of logic, including calls back to this component.
  265. {
  266. AZStd::unique_lock lock(m_queryMutex);
  267. if (m_configuration.m_outputMin != value)
  268. {
  269. m_configuration.m_outputMin = value;
  270. valueChanged = true;
  271. }
  272. }
  273. if (valueChanged)
  274. {
  275. LmbrCentral::DependencyNotificationBus::Event(
  276. GetEntityId(), &LmbrCentral::DependencyNotificationBus::Events::OnCompositionChanged);
  277. }
  278. }
  279. float LevelsGradientComponent::GetOutputMax() const
  280. {
  281. return m_configuration.m_outputMin;
  282. }
  283. void LevelsGradientComponent::SetOutputMax(float value)
  284. {
  285. bool valueChanged = false;
  286. // Only hold the lock while we're changing the data. Don't hold onto it during the OnCompositionChanged call, because that can
  287. // execute an arbitrary amount of logic, including calls back to this component.
  288. {
  289. AZStd::unique_lock lock(m_queryMutex);
  290. if (m_configuration.m_outputMax != value)
  291. {
  292. m_configuration.m_outputMax = value;
  293. valueChanged = true;
  294. }
  295. }
  296. if (valueChanged)
  297. {
  298. LmbrCentral::DependencyNotificationBus::Event(
  299. GetEntityId(), &LmbrCentral::DependencyNotificationBus::Events::OnCompositionChanged);
  300. }
  301. }
  302. GradientSampler& LevelsGradientComponent::GetGradientSampler()
  303. {
  304. return m_configuration.m_gradientSampler;
  305. }
  306. }