BlockerComponent.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  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 "BlockerComponent.h"
  9. #include <AzCore/Component/Entity.h>
  10. #include <AzCore/Debug/Profiler.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. #include <LmbrCentral/Dependency/DependencyNotificationBus.h>
  16. #include <LmbrCentral/Shape/ShapeComponentBus.h>
  17. #include <Vegetation/Ebuses/FilterRequestBus.h>
  18. #include <Vegetation/InstanceData.h>
  19. #include <VegetationProfiler.h>
  20. namespace Vegetation
  21. {
  22. namespace BlockerUtil
  23. {
  24. static bool UpdateVersion([[maybe_unused]] AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
  25. {
  26. if (classElement.GetVersion() < 1)
  27. {
  28. classElement.RemoveElementByName(AZ_CRC_CE("UseRelativeUVW"));
  29. }
  30. return true;
  31. }
  32. }
  33. void BlockerConfig::Reflect(AZ::ReflectContext* context)
  34. {
  35. AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
  36. if (serialize)
  37. {
  38. serialize->Class<BlockerConfig, AreaConfig>()
  39. ->Version(1, &BlockerUtil::UpdateVersion)
  40. ->Field("InheritBehavior", &BlockerConfig::m_inheritBehavior)
  41. ;
  42. AZ::EditContext* edit = serialize->GetEditContext();
  43. if (edit)
  44. {
  45. edit->Class<BlockerConfig>(
  46. "Vegetation Layer Blocker", "Vegetation blocker")
  47. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  48. ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
  49. ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
  50. ->DataElement(0, &BlockerConfig::m_inheritBehavior, "Inherit Behavior", "Allow shapes, modifiers, filters of a parent to affect this area.")
  51. ;
  52. }
  53. }
  54. if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  55. {
  56. behaviorContext->Class<BlockerConfig>()
  57. ->Attribute(AZ::Script::Attributes::Category, "Vegetation")
  58. ->Constructor()
  59. ->Property("inheritBehavior", BehaviorValueProperty(&BlockerConfig::m_inheritBehavior))
  60. ;
  61. }
  62. }
  63. void BlockerComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services)
  64. {
  65. AreaComponentBase::GetProvidedServices(services);
  66. }
  67. void BlockerComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services)
  68. {
  69. AreaComponentBase::GetIncompatibleServices(services);
  70. services.push_back(AZ_CRC_CE("VegetationModifierService"));
  71. }
  72. void BlockerComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& services)
  73. {
  74. services.push_back(AZ_CRC_CE("ShapeService"));
  75. }
  76. void BlockerComponent::Reflect(AZ::ReflectContext* context)
  77. {
  78. BlockerConfig::Reflect(context);
  79. AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
  80. if (serialize)
  81. {
  82. serialize->Class<BlockerComponent, AreaComponentBase>()
  83. ->Version(0)
  84. ->Field("Configuration", &BlockerComponent::m_configuration)
  85. ;
  86. }
  87. if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  88. {
  89. behaviorContext->Constant("BlockerComponentTypeId", BehaviorConstant(BlockerComponentTypeId));
  90. behaviorContext->Class<BlockerComponent>()->RequestBus("BlockerRequestBus");
  91. behaviorContext->EBus<BlockerRequestBus>("BlockerRequestBus")
  92. ->Attribute(AZ::Script::Attributes::Category, "Vegetation")
  93. ->Event("GetAreaPriority", &BlockerRequestBus::Events::GetAreaPriority)
  94. ->Event("SetAreaPriority", &BlockerRequestBus::Events::SetAreaPriority)
  95. ->VirtualProperty("AreaPriority", "GetAreaPriority", "SetAreaPriority")
  96. ->Event("GetAreaLayer", &BlockerRequestBus::Events::GetAreaLayer)
  97. ->Event("SetAreaLayer", &BlockerRequestBus::Events::SetAreaLayer)
  98. ->VirtualProperty("AreaLayer", "GetAreaLayer", "SetAreaLayer")
  99. ->Event("GetAreaProductCount", &BlockerRequestBus::Events::GetAreaProductCount)
  100. ->Event("GetInheritBehavior", &BlockerRequestBus::Events::GetInheritBehavior)
  101. ->Event("SetInheritBehavior", &BlockerRequestBus::Events::SetInheritBehavior)
  102. ->VirtualProperty("InheritBehavior", "GetInheritBehavior", "SetInheritBehavior")
  103. ;
  104. }
  105. }
  106. BlockerComponent::BlockerComponent(const BlockerConfig& configuration)
  107. : AreaComponentBase(configuration)
  108. , m_configuration(configuration)
  109. {
  110. }
  111. void BlockerComponent::Activate()
  112. {
  113. BlockerRequestBus::Handler::BusConnect(GetEntityId());
  114. AreaComponentBase::Activate(); //must activate base last to connect AreaRequestBus once everything else is setup
  115. #if VEG_BLOCKER_ENABLE_CACHING
  116. AZStd::lock_guard<decltype(m_cacheMutex)> cacheLock(m_cacheMutex);
  117. m_claimCacheMapping.clear();
  118. #endif
  119. }
  120. void BlockerComponent::Deactivate()
  121. {
  122. AreaComponentBase::Deactivate(); //must deactivate base first to ensure AreaRequestBus disconnect waits for other threads
  123. BlockerRequestBus::Handler::BusDisconnect();
  124. #if VEG_BLOCKER_ENABLE_CACHING
  125. AZStd::lock_guard<decltype(m_cacheMutex)> cacheLock(m_cacheMutex);
  126. m_claimCacheMapping.clear();
  127. #endif
  128. }
  129. void BlockerComponent::OnCompositionChanged()
  130. {
  131. AreaComponentBase::OnCompositionChanged();
  132. #if VEG_BLOCKER_ENABLE_CACHING
  133. AZStd::lock_guard<decltype(m_cacheMutex)> cacheLock(m_cacheMutex);
  134. m_claimCacheMapping.clear();
  135. #endif
  136. }
  137. bool BlockerComponent::ReadInConfig(const AZ::ComponentConfig* baseConfig)
  138. {
  139. AreaComponentBase::ReadInConfig(baseConfig);
  140. if (auto config = azrtti_cast<const BlockerConfig*>(baseConfig))
  141. {
  142. m_configuration = *config;
  143. return true;
  144. }
  145. return false;
  146. }
  147. bool BlockerComponent::WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const
  148. {
  149. AreaComponentBase::WriteOutConfig(outBaseConfig);
  150. if (auto config = azrtti_cast<BlockerConfig*>(outBaseConfig))
  151. {
  152. *config = m_configuration;
  153. return true;
  154. }
  155. return false;
  156. }
  157. bool BlockerComponent::PrepareToClaim([[maybe_unused]] EntityIdStack& stackIds)
  158. {
  159. return true;
  160. }
  161. bool BlockerComponent::ClaimPosition(EntityIdStack& processedIds, const ClaimPoint& point, InstanceData& instanceData)
  162. {
  163. AZ_PROFILE_FUNCTION(Vegetation);
  164. #if VEG_BLOCKER_ENABLE_CACHING
  165. {
  166. AZStd::lock_guard<decltype(m_cacheMutex)> cacheLock(m_cacheMutex);
  167. auto claimItr = m_claimCacheMapping.find(point.m_handle);
  168. if (claimItr != m_claimCacheMapping.end())
  169. {
  170. return claimItr->second;
  171. }
  172. }
  173. #endif
  174. // test shape bus as first pass to claim the point
  175. bool isInsideShape = true;
  176. for (const auto& id : processedIds)
  177. {
  178. LmbrCentral::ShapeComponentRequestsBus::EventResult(isInsideShape, id, &LmbrCentral::ShapeComponentRequestsBus::Events::IsPointInside, point.m_position);
  179. if (!isInsideShape)
  180. {
  181. #if VEG_BLOCKER_ENABLE_CACHING
  182. AZStd::lock_guard<decltype(m_cacheMutex)> cacheLock(m_cacheMutex);
  183. m_claimCacheMapping[point.m_handle] = false;
  184. #endif
  185. return false;
  186. }
  187. }
  188. //generate details for a single vegetation instance
  189. instanceData.m_position = point.m_position;
  190. instanceData.m_normal = point.m_normal;
  191. instanceData.m_masks = point.m_masks;
  192. //determine if an instance can be created using the generated details
  193. for (const auto& id : processedIds)
  194. {
  195. bool accepted = true;
  196. FilterRequestBus::EnumerateHandlersId(id, [&instanceData, &accepted](FilterRequestBus::Events* handler) {
  197. accepted = handler->Evaluate(instanceData);
  198. return accepted;
  199. });
  200. if (!accepted)
  201. {
  202. #if VEG_BLOCKER_ENABLE_CACHING
  203. AZStd::lock_guard<decltype(m_cacheMutex)> cacheLock(m_cacheMutex);
  204. m_claimCacheMapping[point.m_handle] = false;
  205. #endif
  206. return false;
  207. }
  208. }
  209. #if VEG_BLOCKER_ENABLE_CACHING
  210. AZStd::lock_guard<decltype(m_cacheMutex)> cacheLock(m_cacheMutex);
  211. m_claimCacheMapping[point.m_handle] = true;
  212. #endif
  213. return true;
  214. }
  215. void BlockerComponent::ClaimPositions(EntityIdStack& stackIds, ClaimContext& context)
  216. {
  217. AZ_PROFILE_FUNCTION(Vegetation);
  218. //adding entity id to the stack of entity ids affecting vegetation
  219. EntityIdStack emptyIds;
  220. //when the inherit flag is disabled, as opposed to always inheriting, the stack must be cleared but preserved so redirecting to an empty stack to avoid copying
  221. EntityIdStack& processedIds = m_configuration.m_inheritBehavior ? stackIds : emptyIds;
  222. //adding current entity id to be processed uniformly
  223. EntityIdStackPusher stackPusher(processedIds, GetEntityId());
  224. InstanceData instanceData;
  225. instanceData.m_id = GetEntityId();
  226. instanceData.m_changeIndex = GetChangeIndex();
  227. size_t numAvailablePoints = context.m_availablePoints.size();
  228. for (size_t pointIndex = 0; pointIndex < numAvailablePoints; )
  229. {
  230. ClaimPoint& point = context.m_availablePoints[pointIndex];
  231. if (ClaimPosition(processedIds, point, instanceData))
  232. {
  233. context.m_createdCallback(point, instanceData);
  234. //Swap an available point from the end of the list
  235. AZStd::swap(point, context.m_availablePoints.at(numAvailablePoints - 1));
  236. --numAvailablePoints;
  237. continue;
  238. }
  239. ++pointIndex;
  240. }
  241. //resize to remove all used points
  242. context.m_availablePoints.resize(numAvailablePoints);
  243. }
  244. void BlockerComponent::UnclaimPosition([[maybe_unused]] const ClaimHandle handle)
  245. {
  246. }
  247. AZ::Aabb BlockerComponent::GetEncompassingAabb() const
  248. {
  249. AZ_PROFILE_FUNCTION(Vegetation);
  250. AZ::Aabb bounds = AZ::Aabb::CreateNull();
  251. LmbrCentral::ShapeComponentRequestsBus::EventResult(bounds, GetEntityId(), &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb);
  252. return bounds;
  253. }
  254. AZ::u32 BlockerComponent::GetProductCount() const
  255. {
  256. return 0;
  257. }
  258. AZ::u32 BlockerComponent::GetAreaPriority() const
  259. {
  260. return m_configuration.m_priority;
  261. }
  262. void BlockerComponent::SetAreaPriority(AZ::u32 priority)
  263. {
  264. m_configuration.m_priority = priority;
  265. LmbrCentral::DependencyNotificationBus::Event(GetEntityId(), &LmbrCentral::DependencyNotificationBus::Events::OnCompositionChanged);
  266. }
  267. AZ::u32 BlockerComponent::GetAreaLayer() const
  268. {
  269. return m_configuration.m_layer;
  270. }
  271. void BlockerComponent::SetAreaLayer(AZ::u32 layer)
  272. {
  273. m_configuration.m_layer = layer;
  274. LmbrCentral::DependencyNotificationBus::Event(GetEntityId(), &LmbrCentral::DependencyNotificationBus::Events::OnCompositionChanged);
  275. }
  276. AZ::u32 BlockerComponent::GetAreaProductCount() const
  277. {
  278. return GetProductCount();
  279. }
  280. bool BlockerComponent::GetInheritBehavior() const
  281. {
  282. return m_configuration.m_inheritBehavior;
  283. }
  284. void BlockerComponent::SetInheritBehavior(bool value)
  285. {
  286. m_configuration.m_inheritBehavior = value;
  287. LmbrCentral::DependencyNotificationBus::Event(GetEntityId(), &LmbrCentral::DependencyNotificationBus::Events::OnCompositionChanged);
  288. }
  289. }