Descriptor.cpp 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832
  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 <Vegetation/Descriptor.h>
  9. #include <SurfaceData/SurfaceTag.h>
  10. #include <AzCore/Asset/AssetManager.h>
  11. #include <AzCore/Serialization/SerializeContext.h>
  12. #include <AzCore/Serialization/EditContext.h>
  13. #include <AzCore/std/smart_ptr/make_shared.h>
  14. #include <AzCore/std/sort.h>
  15. #include <Vegetation/EmptyInstanceSpawner.h>
  16. #include <Vegetation/PrefabInstanceSpawner.h>
  17. //////////////////////////////////////////////////////////////////////
  18. // #pragma inline_depth(0)
  19. namespace Vegetation
  20. {
  21. namespace DescriptorUtil
  22. {
  23. static bool UpdateVersion(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
  24. {
  25. if (classElement.GetVersion() < 4)
  26. {
  27. AZ::Vector3 positionMin(-0.3f, -0.3f, 0.0f);
  28. if (classElement.GetChildData(AZ_CRC_CE("PositionMin"), positionMin))
  29. {
  30. classElement.RemoveElementByName(AZ_CRC_CE("PositionMin"));
  31. classElement.AddElementWithData(context, "PositionMinX", (float)positionMin.GetX());
  32. classElement.AddElementWithData(context, "PositionMinY", (float)positionMin.GetY());
  33. classElement.AddElementWithData(context, "PositionMinZ", (float)positionMin.GetZ());
  34. }
  35. AZ::Vector3 positionMax(0.3f, 0.3f, 0.0f);
  36. if (classElement.GetChildData(AZ_CRC_CE("PositionMax"), positionMax))
  37. {
  38. classElement.RemoveElementByName(AZ_CRC_CE("PositionMax"));
  39. classElement.AddElementWithData(context, "PositionMaxX", (float)positionMax.GetX());
  40. classElement.AddElementWithData(context, "PositionMaxY", (float)positionMax.GetY());
  41. classElement.AddElementWithData(context, "PositionMaxZ", (float)positionMax.GetZ());
  42. }
  43. AZ::Vector3 rotationMin(0.0f, 0.0f, -180.0f);
  44. if (classElement.GetChildData(AZ_CRC_CE("RotationMin"), rotationMin))
  45. {
  46. classElement.RemoveElementByName(AZ_CRC_CE("RotationMin"));
  47. classElement.AddElementWithData(context, "RotationMinX", (float)rotationMin.GetX());
  48. classElement.AddElementWithData(context, "RotationMinY", (float)rotationMin.GetY());
  49. classElement.AddElementWithData(context, "RotationMinZ", (float)rotationMin.GetZ());
  50. }
  51. AZ::Vector3 rotationMax(0.0f, 0.0f, 180.0f);
  52. if (classElement.GetChildData(AZ_CRC_CE("RotationMax"), rotationMax))
  53. {
  54. classElement.RemoveElementByName(AZ_CRC_CE("RotationMax"));
  55. classElement.AddElementWithData(context, "RotationMaxX", (float)rotationMax.GetX());
  56. classElement.AddElementWithData(context, "RotationMaxY", (float)rotationMax.GetY());
  57. classElement.AddElementWithData(context, "RotationMaxZ", (float)rotationMax.GetZ());
  58. }
  59. }
  60. if (classElement.GetVersion() < 5)
  61. {
  62. classElement.RemoveElementByName(AZ_CRC_CE("RadiusMax"));
  63. }
  64. if (classElement.GetVersion() < 7)
  65. {
  66. // The only type of spawners supported prior to this version were legacy vegetation spawners so replace with an empty spawner.
  67. auto baseInstanceSpawner = AZStd::make_shared<EmptyInstanceSpawner>();
  68. classElement.AddElementWithData(context, "InstanceSpawner", baseInstanceSpawner);
  69. AZ_Error("Dynamic Vegetation", false, "Replacing legacy vegetation spawner with an empty instance spawner");
  70. }
  71. if (classElement.GetVersion() < 8)
  72. {
  73. // Spawner type was briefly stored as a display string instead of a TypeId.
  74. AZStd::string spawnerType;
  75. if (classElement.GetChildData(AZ_CRC_CE("SpawnerType"), spawnerType))
  76. {
  77. AZ::TypeId newSpawnerType = azrtti_typeid<EmptyInstanceSpawner>();
  78. if (spawnerType == "Legacy Vegetation")
  79. {
  80. AZ_Error("Dynamic Vegetation", false, "Replacing legacy vegetation spawner with an empty instance spawner");
  81. }
  82. classElement.RemoveElementByName(AZ_CRC_CE("SpawnerType"));
  83. classElement.AddElementWithData(context, "SpawnerType", newSpawnerType);
  84. }
  85. }
  86. return true;
  87. }
  88. }
  89. AZStd::fixed_vector<AZStd::pair<AZ::TypeId, AZStd::string_view>, Descriptor::m_maxSpawnerTypesExpected> Descriptor::m_spawnerTypes;
  90. void Descriptor::Reflect(AZ::ReflectContext* context)
  91. {
  92. // Don't reflect again if we're already reflected to the passed in context
  93. if (context->IsTypeReflected(VegetationDescriptorTypeId))
  94. {
  95. return;
  96. }
  97. SurfaceTagDistance::Reflect(context);
  98. AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
  99. if (serialize)
  100. {
  101. serialize->RegisterGenericType<AZStd::vector<Descriptor>>();
  102. serialize->RegisterGenericType<AZStd::shared_ptr<Descriptor>>();
  103. serialize->Class<Descriptor>()
  104. ->Version(8, &DescriptorUtil::UpdateVersion)
  105. ->Field("SpawnerType", &Descriptor::m_spawnerType)
  106. ->Field("InstanceSpawner", &Descriptor::m_instanceSpawner)
  107. ->Field("Weight", &Descriptor::m_weight)
  108. ->Field("Advanced", &Descriptor::m_advanced)
  109. ->Field("PositionOverrideEnabled", &Descriptor::m_positionOverrideEnabled)
  110. ->Field("PositionMinX", &Descriptor::m_positionMinX)
  111. ->Field("PositionMaxX", &Descriptor::m_positionMaxX)
  112. ->Field("PositionMinY", &Descriptor::m_positionMinY)
  113. ->Field("PositionMaxY", &Descriptor::m_positionMaxY)
  114. ->Field("PositionMinZ", &Descriptor::m_positionMinZ)
  115. ->Field("PositionMaxZ", &Descriptor::m_positionMaxZ)
  116. ->Field("RotationOverrideEnabled", &Descriptor::m_rotationOverrideEnabled)
  117. ->Field("RotationMinX", &Descriptor::m_rotationMinX)
  118. ->Field("RotationMaxX", &Descriptor::m_rotationMaxX)
  119. ->Field("RotationMinY", &Descriptor::m_rotationMinY)
  120. ->Field("RotationMaxY", &Descriptor::m_rotationMaxY)
  121. ->Field("RotationMinZ", &Descriptor::m_rotationMinZ)
  122. ->Field("RotationMaxZ", &Descriptor::m_rotationMaxZ)
  123. ->Field("ScaleOverrideEnabled", &Descriptor::m_scaleOverrideEnabled)
  124. ->Field("ScaleMin", &Descriptor::m_scaleMin)
  125. ->Field("ScaleMax", &Descriptor::m_scaleMax)
  126. ->Field("AltitudeFilterOverrideEnabled", &Descriptor::m_altitudeFilterOverrideEnabled)
  127. ->Field("AltitudeFilterMin", &Descriptor::m_altitudeFilterMin)
  128. ->Field("AltitudeFilterMax", &Descriptor::m_altitudeFilterMax)
  129. ->Field("RadiusOverrideEnabled", &Descriptor::m_radiusOverrideEnabled)
  130. ->Field("BoundMode", &Descriptor::m_boundMode)
  131. ->Field("RadiusMin", &Descriptor::m_radiusMin)
  132. ->Field("SurfaceAlignmentOverrideEnabled", &Descriptor::m_surfaceAlignmentOverrideEnabled)
  133. ->Field("SurfaceAlignmentMin", &Descriptor::m_surfaceAlignmentMin)
  134. ->Field("SurfaceAlignmentMax", &Descriptor::m_surfaceAlignmentMax)
  135. ->Field("SlopeFilterOverrideEnabled", &Descriptor::m_slopeFilterOverrideEnabled)
  136. ->Field("SlopeFilterMin", &Descriptor::m_slopeFilterMin)
  137. ->Field("SlopeFilterMax", &Descriptor::m_slopeFilterMax)
  138. ->Field("SurfaceFilterOverrideMode", &Descriptor::m_surfaceFilterOverrideMode)
  139. ->Field("InclusiveSurfaceFilterTags", &Descriptor::m_inclusiveSurfaceFilterTags)
  140. ->Field("ExclusiveSurfaceFilterTags", &Descriptor::m_exclusiveSurfaceFilterTags)
  141. ->Field("SurfaceTagDistance", &Descriptor::m_surfaceTagDistance)
  142. ;
  143. AZ::EditContext* edit = serialize->GetEditContext();
  144. if (edit)
  145. {
  146. edit->Class<Descriptor>(
  147. "Vegetation Descriptor", "Details used to create vegetation instances")
  148. // For this ComboBox to actually work, there is a PropertyHandler registration in EditorVegetationSystemComponent.cpp
  149. ->DataElement(AZ::Edit::UIHandlers::ComboBox, &Descriptor::m_spawnerType, "Instance Spawner", "The type of instances to spawn")
  150. ->Attribute(AZ::Edit::Attributes::GenericValueList, &Descriptor::GetSpawnerTypeList)
  151. ->Attribute(AZ::Edit::Attributes::ChangeNotify, &Descriptor::SpawnerTypeChanged)
  152. ->DataElement(AZ::Edit::UIHandlers::Default, &Descriptor::m_instanceSpawner, "Instance", "Instance data")
  153. ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
  154. ->DataElement(0, &Descriptor::m_weight, "Weight", "Weight counted against the total density of the placed vegetation sector")
  155. ->DataElement(0, &Descriptor::m_advanced, "Display Per-Item Overrides", "Display the per-item override settings that can be used with filter and modifier components when those components have 'Allow Per-Item Overrides' enabled.")
  156. ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree)
  157. ->ClassElement(AZ::Edit::ClassElements::Group, "Position Modifier")
  158. ->Attribute(AZ::Edit::Attributes::AutoExpand, false)
  159. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  160. ->DataElement(0, &Descriptor::m_positionOverrideEnabled, "Override Enabled", "Enable per-item override settings for this item when the Position Modifier has 'Allow Per-Item Overrides' enabled.")
  161. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  162. ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues)
  163. ->DataElement(AZ::Edit::UIHandlers::Slider, &Descriptor::m_positionMinX, "Min X", "Minimum position offset on X axis.")
  164. ->Attribute(AZ::Edit::Attributes::Min, std::numeric_limits<float>::lowest())
  165. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<float>::max())
  166. ->Attribute(AZ::Edit::Attributes::SoftMin, -2.0f)
  167. ->Attribute(AZ::Edit::Attributes::SoftMax, 2.0f)
  168. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  169. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsPositionFilterReadOnly)
  170. ->DataElement(AZ::Edit::UIHandlers::Slider, &Descriptor::m_positionMaxX, "Max X", "Maximum position offset on X axis.")
  171. ->Attribute(AZ::Edit::Attributes::Min, std::numeric_limits<float>::lowest())
  172. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<float>::max())
  173. ->Attribute(AZ::Edit::Attributes::SoftMin, -2.0f)
  174. ->Attribute(AZ::Edit::Attributes::SoftMax, 2.0f)
  175. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  176. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsPositionFilterReadOnly)
  177. ->DataElement(AZ::Edit::UIHandlers::Slider, &Descriptor::m_positionMinY, "Min Y", "Minimum position offset on Y axis.")
  178. ->Attribute(AZ::Edit::Attributes::Min, std::numeric_limits<float>::lowest())
  179. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<float>::max())
  180. ->Attribute(AZ::Edit::Attributes::SoftMin, -2.0f)
  181. ->Attribute(AZ::Edit::Attributes::SoftMax, 2.0f)
  182. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  183. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsPositionFilterReadOnly)
  184. ->DataElement(AZ::Edit::UIHandlers::Slider, &Descriptor::m_positionMaxY, "Max Y", "Maximum position offset on Y axis.")
  185. ->Attribute(AZ::Edit::Attributes::Min, std::numeric_limits<float>::lowest())
  186. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<float>::max())
  187. ->Attribute(AZ::Edit::Attributes::SoftMin, -2.0f)
  188. ->Attribute(AZ::Edit::Attributes::SoftMax, 2.0f)
  189. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  190. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsPositionFilterReadOnly)
  191. ->DataElement(AZ::Edit::UIHandlers::Slider, &Descriptor::m_positionMinZ, "Min Z", "Minimum position offset on Z axis.")
  192. ->Attribute(AZ::Edit::Attributes::Min, std::numeric_limits<float>::lowest())
  193. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<float>::max())
  194. ->Attribute(AZ::Edit::Attributes::SoftMin, -2.0f)
  195. ->Attribute(AZ::Edit::Attributes::SoftMax, 2.0f)
  196. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  197. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsPositionFilterReadOnly)
  198. ->DataElement(AZ::Edit::UIHandlers::Slider, &Descriptor::m_positionMaxZ, "Max Z", "Maximum position offset on Z axis.")
  199. ->Attribute(AZ::Edit::Attributes::Min, std::numeric_limits<float>::lowest())
  200. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<float>::max())
  201. ->Attribute(AZ::Edit::Attributes::SoftMin, -2.0f)
  202. ->Attribute(AZ::Edit::Attributes::SoftMax, 2.0f)
  203. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  204. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsPositionFilterReadOnly)
  205. ->ClassElement(AZ::Edit::ClassElements::Group, "Rotation Modifier")
  206. ->Attribute(AZ::Edit::Attributes::AutoExpand, false)
  207. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  208. ->DataElement(0, &Descriptor::m_rotationOverrideEnabled, "Override Enabled", "Enable per-item override settings for this item when the Rotation Modifier has 'Allow Per-Item Overrides' enabled.")
  209. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  210. ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues)
  211. ->DataElement(AZ::Edit::UIHandlers::Slider, &Descriptor::m_rotationMinX, "Min X", "Minimum rotation offset on X axis.")
  212. ->Attribute(AZ::Edit::Attributes::Min, std::numeric_limits<float>::lowest())
  213. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<float>::max())
  214. ->Attribute(AZ::Edit::Attributes::SoftMin, -180.0f)
  215. ->Attribute(AZ::Edit::Attributes::SoftMax, 180.0f)
  216. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  217. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsRotationFilterReadOnly)
  218. ->DataElement(AZ::Edit::UIHandlers::Slider, &Descriptor::m_rotationMaxX, "Max X", "Maximum rotation offset on X axis.")
  219. ->Attribute(AZ::Edit::Attributes::Min, std::numeric_limits<float>::lowest())
  220. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<float>::max())
  221. ->Attribute(AZ::Edit::Attributes::SoftMin, -180.0f)
  222. ->Attribute(AZ::Edit::Attributes::SoftMax, 180.0f)
  223. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  224. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsRotationFilterReadOnly)
  225. ->DataElement(AZ::Edit::UIHandlers::Slider, &Descriptor::m_rotationMinY, "Min Y", "Minimum rotation offset on Y axis.")
  226. ->Attribute(AZ::Edit::Attributes::Min, std::numeric_limits<float>::lowest())
  227. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<float>::max())
  228. ->Attribute(AZ::Edit::Attributes::SoftMin, -180.0f)
  229. ->Attribute(AZ::Edit::Attributes::SoftMax, 180.0f)
  230. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  231. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsRotationFilterReadOnly)
  232. ->DataElement(AZ::Edit::UIHandlers::Slider, &Descriptor::m_rotationMaxY, "Max Y", "Maximum rotation offset on Y axis.")
  233. ->Attribute(AZ::Edit::Attributes::Min, std::numeric_limits<float>::lowest())
  234. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<float>::max())
  235. ->Attribute(AZ::Edit::Attributes::SoftMin, -180.0f)
  236. ->Attribute(AZ::Edit::Attributes::SoftMax, 180.0f)
  237. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  238. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsRotationFilterReadOnly)
  239. ->DataElement(AZ::Edit::UIHandlers::Slider, &Descriptor::m_rotationMinZ, "Min Z", "Minimum rotation offset on Z axis.")
  240. ->Attribute(AZ::Edit::Attributes::Min, std::numeric_limits<float>::lowest())
  241. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<float>::max())
  242. ->Attribute(AZ::Edit::Attributes::SoftMin, -180.0f)
  243. ->Attribute(AZ::Edit::Attributes::SoftMax, 180.0f)
  244. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  245. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsRotationFilterReadOnly)
  246. ->DataElement(AZ::Edit::UIHandlers::Slider, &Descriptor::m_rotationMaxZ, "Max Z", "Maximum rotation offset on Z axis.")
  247. ->Attribute(AZ::Edit::Attributes::Min, std::numeric_limits<float>::lowest())
  248. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<float>::max())
  249. ->Attribute(AZ::Edit::Attributes::SoftMin, -180.0f)
  250. ->Attribute(AZ::Edit::Attributes::SoftMax, 180.0f)
  251. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  252. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsRotationFilterReadOnly)
  253. ->ClassElement(AZ::Edit::ClassElements::Group, "Scale Modifier")
  254. ->Attribute(AZ::Edit::Attributes::AutoExpand, false)
  255. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  256. ->DataElement(0, &Descriptor::m_scaleOverrideEnabled, "Override Enabled", "Enable per-item override settings for this item when the Scale Modifier has 'Allow Per-Item Overrides' enabled.")
  257. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  258. ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues)
  259. ->DataElement(AZ::Edit::UIHandlers::Slider, &Descriptor::m_scaleMin, "Min", "")
  260. ->Attribute(AZ::Edit::Attributes::Min, 0.01f)
  261. ->Attribute(AZ::Edit::Attributes::SoftMax, 10.0f)
  262. ->Attribute(AZ::Edit::Attributes::Step, 0.125f)
  263. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<float>::max())
  264. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  265. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsScaleFilterReadOnly)
  266. ->DataElement(AZ::Edit::UIHandlers::Slider, &Descriptor::m_scaleMax, "Max", "")
  267. ->Attribute(AZ::Edit::Attributes::Min, 0.01f)
  268. ->Attribute(AZ::Edit::Attributes::SoftMax, 10.0f)
  269. ->Attribute(AZ::Edit::Attributes::Step, 0.125f)
  270. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<float>::max())
  271. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  272. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsScaleFilterReadOnly)
  273. ->ClassElement(AZ::Edit::ClassElements::Group, "Altitude Filter")
  274. ->Attribute(AZ::Edit::Attributes::AutoExpand, false)
  275. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  276. ->DataElement(0, &Descriptor::m_altitudeFilterOverrideEnabled, "Override Enabled", "Enable per-item override settings for this item when the Altitude Filter has 'Allow Per-Item Overrides' enabled.")
  277. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  278. ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues)
  279. ->DataElement(0, &Descriptor::m_altitudeFilterMin, "Min", "")
  280. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  281. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsAltitudeFilterReadOnly)
  282. ->DataElement(0, &Descriptor::m_altitudeFilterMax, "Max", "")
  283. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  284. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsAltitudeFilterReadOnly)
  285. ->ClassElement(AZ::Edit::ClassElements::Group, "Distance Between Filter (Radius)")
  286. ->Attribute(AZ::Edit::Attributes::AutoExpand, false)
  287. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  288. ->DataElement(0, &Descriptor::m_radiusOverrideEnabled, "Override Enabled", "Enable per-item override settings for this item when the Distance Between Filter has 'Allow Per-Item Overrides' enabled.")
  289. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  290. ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues)
  291. ->DataElement(AZ::Edit::UIHandlers::ComboBox, &Descriptor::m_boundMode, "Bound Mode", "")
  292. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetBoundModeVisibility)
  293. ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues)
  294. ->EnumAttribute(BoundMode::Radius, "Radius")
  295. ->EnumAttribute(BoundMode::MeshRadius, "MeshRadius")
  296. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsDistanceBetweenFilterReadOnly)
  297. ->DataElement(AZ::Edit::UIHandlers::Slider, &Descriptor::m_radiusMin, "Radius Min", "")
  298. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  299. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsRadiusReadOnly)
  300. ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
  301. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<float>::max())
  302. ->Attribute(AZ::Edit::Attributes::SoftMax, 16.0f) // match current default sector size in meters.
  303. ->ClassElement(AZ::Edit::ClassElements::Group, "Surface Slope Alignment")
  304. ->Attribute(AZ::Edit::Attributes::AutoExpand, false)
  305. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  306. ->DataElement(0, &Descriptor::m_surfaceAlignmentOverrideEnabled, "Override Enabled", "Enable per-item override settings for this item when the Surface Slope Alignment Modifier has 'Allow Per-Item Overrides' enabled.")
  307. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  308. ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues)
  309. ->DataElement(AZ::Edit::UIHandlers::Slider, &Descriptor::m_surfaceAlignmentMin, "Min", "")
  310. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  311. ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
  312. ->Attribute(AZ::Edit::Attributes::Max, 1.0f)
  313. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsSurfaceAlignmentFilterReadOnly)
  314. ->DataElement(AZ::Edit::UIHandlers::Slider, &Descriptor::m_surfaceAlignmentMax, "Max", "")
  315. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  316. ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
  317. ->Attribute(AZ::Edit::Attributes::Max, 1.0f)
  318. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsSurfaceAlignmentFilterReadOnly)
  319. ->ClassElement(AZ::Edit::ClassElements::Group, "Slope Filter")
  320. ->Attribute(AZ::Edit::Attributes::AutoExpand, false)
  321. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  322. ->DataElement(0, &Descriptor::m_slopeFilterOverrideEnabled, "Override Enabled", "Enable per-item override settings for this item when the Slope Filter has 'Allow Per-Item Overrides' enabled.")
  323. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  324. ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues)
  325. ->DataElement(AZ::Edit::UIHandlers::Slider, &Descriptor::m_slopeFilterMin, "Min", "")
  326. ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
  327. ->Attribute(AZ::Edit::Attributes::Max, 180.0f)
  328. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  329. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsSlopeFilterReadOnly)
  330. ->DataElement(AZ::Edit::UIHandlers::Slider, &Descriptor::m_slopeFilterMax, "Max", "")
  331. ->Attribute(AZ::Edit::Attributes::Min, 0.0f)
  332. ->Attribute(AZ::Edit::Attributes::Max, 180.0f)
  333. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  334. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsSlopeFilterReadOnly)
  335. ->ClassElement(AZ::Edit::ClassElements::Group, "Surface Mask Filter")
  336. ->Attribute(AZ::Edit::Attributes::AutoExpand, false)
  337. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  338. ->DataElement(AZ::Edit::UIHandlers::ComboBox, &Descriptor::m_surfaceFilterOverrideMode, "Override Mode", "Enable per-item override settings for this item when the Surface Mask Filter has 'Allow Per-Item Overrides' enabled.")
  339. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  340. ->EnumAttribute(OverrideMode::Disable, "Disable")
  341. ->EnumAttribute(OverrideMode::Replace, "Replace")
  342. ->EnumAttribute(OverrideMode::Extend, "Extend")
  343. ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues)
  344. ->DataElement(0, &Descriptor::m_inclusiveSurfaceFilterTags, "Inclusion Tags", "")
  345. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  346. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsSurfaceTagFilterReadOnly)
  347. ->DataElement(0, &Descriptor::m_exclusiveSurfaceFilterTags, "Exclusion Tags", "")
  348. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  349. ->Attribute(AZ::Edit::Attributes::ReadOnly, &Descriptor::IsSurfaceTagFilterReadOnly)
  350. ->EndGroup()
  351. ->DataElement(0, &Descriptor::m_surfaceTagDistance, "Surface Mask Depth Filter", "")
  352. ->Attribute(AZ::Edit::Attributes::Visibility, &Descriptor::GetAdvancedGroupVisibility)
  353. ;
  354. }
  355. }
  356. if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  357. {
  358. behaviorContext->Class<Descriptor>()
  359. ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
  360. ->Attribute(AZ::Script::Attributes::Category, "Vegetation")
  361. ->Attribute(AZ::Script::Attributes::Module, "vegetation")
  362. ->Constructor()
  363. ->Property("spawnerType", &Descriptor::GetSpawnerType, &Descriptor::SetSpawnerType)
  364. ->Property("spawner", &Descriptor::GetSpawner, &Descriptor::SetSpawner)
  365. ->Property("weight", BehaviorValueProperty(&Descriptor::m_weight))
  366. ->Property("surfaceTagDistance", BehaviorValueProperty(&Descriptor::m_surfaceTagDistance))
  367. ->Property("surfaceFilterOverrideMode",
  368. [](Descriptor* descriptor) { return (AZ::u8)(descriptor->m_surfaceFilterOverrideMode); },
  369. [](Descriptor* descriptor, const AZ::u8& i) { descriptor->m_surfaceFilterOverrideMode = (OverrideMode)i; })
  370. ->Property("radiusOverrideEnabled", BehaviorValueProperty(&Descriptor::m_radiusOverrideEnabled))
  371. ->Property("radiusMin", BehaviorValueProperty(&Descriptor::m_radiusMin))
  372. ->Property("boundMode",
  373. [](Descriptor* descriptor) { return (AZ::u8)(descriptor->m_boundMode); },
  374. [](Descriptor* descriptor, const AZ::u8& i) { descriptor->m_boundMode = (BoundMode)i; })
  375. ->Property("surfaceAlignmentOverrideEnabled", BehaviorValueProperty(&Descriptor::m_surfaceAlignmentOverrideEnabled))
  376. ->Property("surfaceAlignmentMin", BehaviorValueProperty(&Descriptor::m_surfaceAlignmentMin))
  377. ->Property("surfaceAlignmentMax", BehaviorValueProperty(&Descriptor::m_surfaceAlignmentMax))
  378. ->Property("rotationOverrideEnabled", BehaviorValueProperty(&Descriptor::m_rotationOverrideEnabled))
  379. ->Property("rotationMinX", BehaviorValueProperty(&Descriptor::m_rotationMinX))
  380. ->Property("rotationMaxX", BehaviorValueProperty(&Descriptor::m_rotationMaxX))
  381. ->Property("rotationMinY", BehaviorValueProperty(&Descriptor::m_rotationMinY))
  382. ->Property("rotationMaxY", BehaviorValueProperty(&Descriptor::m_rotationMaxY))
  383. ->Property("rotationMinZ", BehaviorValueProperty(&Descriptor::m_rotationMinZ))
  384. ->Property("rotationMaxZ", BehaviorValueProperty(&Descriptor::m_rotationMaxZ))
  385. ->Property("positionOverrideEnabled", BehaviorValueProperty(&Descriptor::m_positionOverrideEnabled))
  386. ->Property("positionMinX", BehaviorValueProperty(&Descriptor::m_positionMinX))
  387. ->Property("positionMaxX", BehaviorValueProperty(&Descriptor::m_positionMaxX))
  388. ->Property("positionMinY", BehaviorValueProperty(&Descriptor::m_positionMinY))
  389. ->Property("positionMaxY", BehaviorValueProperty(&Descriptor::m_positionMaxY))
  390. ->Property("positionMinZ", BehaviorValueProperty(&Descriptor::m_positionMinZ))
  391. ->Property("positionMaxZ", BehaviorValueProperty(&Descriptor::m_positionMaxZ))
  392. ->Property("scaleOverrideEnabled", BehaviorValueProperty(&Descriptor::m_scaleOverrideEnabled))
  393. ->Property("scaleMin", BehaviorValueProperty(&Descriptor::m_scaleMin))
  394. ->Property("scaleMax", BehaviorValueProperty(&Descriptor::m_scaleMax))
  395. ->Property("altitudeFilterOverrideEnabled", BehaviorValueProperty(&Descriptor::m_altitudeFilterOverrideEnabled))
  396. ->Property("altitudeFilterMin", BehaviorValueProperty(&Descriptor::m_altitudeFilterMin))
  397. ->Property("altitudeFilterMax", BehaviorValueProperty(&Descriptor::m_altitudeFilterMax))
  398. ->Property("slopeFilterOverrideEnabled", BehaviorValueProperty(&Descriptor::m_slopeFilterOverrideEnabled))
  399. ->Property("slopeFilterMin", BehaviorValueProperty(&Descriptor::m_slopeFilterMin))
  400. ->Property("slopeFilterMax", BehaviorValueProperty(&Descriptor::m_slopeFilterMax))
  401. ->Method("GetNumInclusiveSurfaceFilterTags", &Descriptor::GetNumInclusiveSurfaceFilterTags)
  402. ->Method("GetInclusiveSurfaceFilterTag", &Descriptor::GetInclusiveSurfaceFilterTag)
  403. ->Method("RemoveInclusiveSurfaceFilterTag", &Descriptor::RemoveInclusiveSurfaceFilterTag)
  404. ->Method("AddInclusiveSurfaceFilterTag", &Descriptor::AddInclusiveSurfaceFilterTag)
  405. ->Method("GetNumExclusiveSurfaceFilterTags", &Descriptor::GetNumExclusiveSurfaceFilterTags)
  406. ->Method("GetExclusiveSurfaceFilterTag", &Descriptor::GetExclusiveSurfaceFilterTag)
  407. ->Method("RemoveExclusiveSurfaceFilterTag", &Descriptor::RemoveExclusiveSurfaceFilterTag)
  408. ->Method("AddExclusiveSurfaceFilterTag", &Descriptor::AddExclusiveSurfaceFilterTag)
  409. ;
  410. }
  411. }
  412. void SurfaceTagDistance::Reflect(AZ::ReflectContext * context)
  413. {
  414. AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
  415. if (serialize)
  416. {
  417. serialize->Class<SurfaceTagDistance>()
  418. ->Version(0)
  419. ->Field("SurfaceTag", &SurfaceTagDistance::m_tags)
  420. ->Field("UpperDistanceInMeters", &SurfaceTagDistance::m_upperDistanceInMeters)
  421. ->Field("LowerDistanceInMeters", &SurfaceTagDistance::m_lowerDistanceInMeters)
  422. ;
  423. AZ::EditContext* edit = serialize->GetEditContext();
  424. if (edit)
  425. {
  426. edit->Class<SurfaceTagDistance>(
  427. "VegetationSurfaceTagDepth", "Describes depth information for a vegetation object based on a tag to match with a surface mask")
  428. ->DataElement(0, &SurfaceTagDistance::m_tags, "Surface Tags", "The surface tags to compare the distance from the planting tag to.")
  429. ->DataElement(0, &SurfaceTagDistance::m_upperDistanceInMeters, "Upper Distance Range (m)", "Upper Distance in meters from comparison surface, negative for below")
  430. ->DataElement(0, &SurfaceTagDistance::m_lowerDistanceInMeters, "Lower Distance Range (m)", "Lower Distance in meters from comparison surface, negative for below")
  431. ;
  432. }
  433. }
  434. if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  435. {
  436. behaviorContext->Class<SurfaceTagDistance>()
  437. ->Attribute(AZ::Script::Attributes::Category, "Vegetation")
  438. ->Constructor()
  439. ->Property("upperDistanceInMeters", BehaviorValueProperty(&SurfaceTagDistance::m_upperDistanceInMeters))
  440. ->Property("lowerDistanceInMeters", BehaviorValueProperty(&SurfaceTagDistance::m_lowerDistanceInMeters))
  441. ->Method("GetNumTags", &SurfaceTagDistance::GetNumTags)
  442. ->Method("GetTag", &SurfaceTagDistance::GetTag)
  443. ->Method("RemoveTag", &SurfaceTagDistance::RemoveTag)
  444. ->Method("AddTag", &SurfaceTagDistance::AddTag)
  445. ;
  446. }
  447. }
  448. size_t SurfaceTagDistance::GetNumTags() const
  449. {
  450. return m_tags.size();
  451. }
  452. AZ::Crc32 SurfaceTagDistance::GetTag(int tagIndex) const
  453. {
  454. if (tagIndex < m_tags.size() && tagIndex >= 0)
  455. {
  456. return m_tags[tagIndex];
  457. }
  458. return AZ::Crc32();
  459. }
  460. void SurfaceTagDistance::RemoveTag(int tagIndex)
  461. {
  462. if (tagIndex < m_tags.size() && tagIndex >= 0)
  463. {
  464. m_tags.erase(m_tags.begin() + tagIndex);
  465. }
  466. }
  467. void SurfaceTagDistance::AddTag(const AZStd::string& tag)
  468. {
  469. m_tags.push_back(SurfaceData::SurfaceTag(tag));
  470. }
  471. bool SurfaceTagDistance::operator==(const SurfaceTagDistance& rhs) const
  472. {
  473. return m_tags == rhs.m_tags && m_lowerDistanceInMeters == rhs.m_lowerDistanceInMeters && m_upperDistanceInMeters == rhs.m_upperDistanceInMeters;
  474. }
  475. Descriptor::Descriptor()
  476. {
  477. m_instanceSpawner = AZStd::make_shared<PrefabInstanceSpawner>();
  478. m_spawnerType = azrtti_typeid(*m_instanceSpawner);
  479. }
  480. Descriptor::~Descriptor()
  481. {
  482. }
  483. bool Descriptor::HasEquivalentInstanceSpawners(const Descriptor& rhs) const
  484. {
  485. bool instanceSpawnersMatch = false;
  486. if (m_spawnerType == rhs.m_spawnerType)
  487. {
  488. if (m_instanceSpawner == rhs.m_instanceSpawner)
  489. {
  490. // This will match if they're both null, or both the same pointer.
  491. instanceSpawnersMatch = true;
  492. }
  493. else
  494. {
  495. // Only match if they're both not null and have equivalent data.
  496. if (m_instanceSpawner && rhs.m_instanceSpawner)
  497. {
  498. instanceSpawnersMatch = (*m_instanceSpawner) == (*rhs.m_instanceSpawner);
  499. }
  500. }
  501. }
  502. return instanceSpawnersMatch;
  503. }
  504. bool Descriptor::operator==(const Descriptor& rhs) const
  505. {
  506. return
  507. HasEquivalentInstanceSpawners(rhs) &&
  508. m_weight == rhs.m_weight &&
  509. m_surfaceTagDistance == rhs.m_surfaceTagDistance &&
  510. m_surfaceFilterOverrideMode == rhs.m_surfaceFilterOverrideMode &&
  511. m_inclusiveSurfaceFilterTags == rhs.m_inclusiveSurfaceFilterTags &&
  512. m_exclusiveSurfaceFilterTags == rhs.m_exclusiveSurfaceFilterTags &&
  513. m_radiusOverrideEnabled == rhs.m_radiusOverrideEnabled &&
  514. m_radiusMin == rhs.m_radiusMin &&
  515. m_boundMode == rhs.m_boundMode &&
  516. m_surfaceAlignmentOverrideEnabled == rhs.m_surfaceAlignmentOverrideEnabled &&
  517. m_surfaceAlignmentMin == rhs.m_surfaceAlignmentMin &&
  518. m_surfaceAlignmentMax == rhs.m_surfaceAlignmentMax &&
  519. m_rotationOverrideEnabled == rhs.m_rotationOverrideEnabled &&
  520. m_rotationMinX == rhs.m_rotationMinX &&
  521. m_rotationMaxX == rhs.m_rotationMaxX &&
  522. m_rotationMinY == rhs.m_rotationMinY &&
  523. m_rotationMaxY == rhs.m_rotationMaxY &&
  524. m_rotationMinZ == rhs.m_rotationMinZ &&
  525. m_rotationMaxZ == rhs.m_rotationMaxZ &&
  526. m_positionOverrideEnabled == rhs.m_positionOverrideEnabled &&
  527. m_positionMinX == rhs.m_positionMinX &&
  528. m_positionMaxX == rhs.m_positionMaxX &&
  529. m_positionMinY == rhs.m_positionMinY &&
  530. m_positionMaxY == rhs.m_positionMaxY &&
  531. m_positionMinZ == rhs.m_positionMinZ &&
  532. m_positionMaxZ == rhs.m_positionMaxZ &&
  533. m_scaleOverrideEnabled == rhs.m_scaleOverrideEnabled &&
  534. m_scaleMin == rhs.m_scaleMin &&
  535. m_scaleMax == rhs.m_scaleMax &&
  536. m_altitudeFilterOverrideEnabled == rhs.m_altitudeFilterOverrideEnabled &&
  537. m_altitudeFilterMin == rhs.m_altitudeFilterMin &&
  538. m_altitudeFilterMax == rhs.m_altitudeFilterMax &&
  539. m_slopeFilterOverrideEnabled == rhs.m_slopeFilterOverrideEnabled &&
  540. m_slopeFilterMin == rhs.m_slopeFilterMin &&
  541. m_slopeFilterMax == rhs.m_slopeFilterMax
  542. ;
  543. }
  544. size_t Descriptor::GetNumInclusiveSurfaceFilterTags() const
  545. {
  546. return m_inclusiveSurfaceFilterTags.size();
  547. }
  548. AZ::Crc32 Descriptor::GetInclusiveSurfaceFilterTag(int tagIndex) const
  549. {
  550. if (tagIndex < m_inclusiveSurfaceFilterTags.size() && tagIndex >= 0)
  551. {
  552. return m_inclusiveSurfaceFilterTags[tagIndex];
  553. }
  554. return AZ::Crc32();
  555. }
  556. void Descriptor::RemoveInclusiveSurfaceFilterTag(int tagIndex)
  557. {
  558. if (tagIndex < m_inclusiveSurfaceFilterTags.size() && tagIndex >= 0)
  559. {
  560. m_inclusiveSurfaceFilterTags.erase(m_inclusiveSurfaceFilterTags.begin() + tagIndex);
  561. }
  562. }
  563. void Descriptor::AddInclusiveSurfaceFilterTag(const AZStd::string& tag)
  564. {
  565. m_inclusiveSurfaceFilterTags.push_back(SurfaceData::SurfaceTag(tag));
  566. }
  567. size_t Descriptor::GetNumExclusiveSurfaceFilterTags() const
  568. {
  569. return m_exclusiveSurfaceFilterTags.size();
  570. }
  571. AZ::Crc32 Descriptor::GetExclusiveSurfaceFilterTag(int tagIndex) const
  572. {
  573. if (tagIndex < m_exclusiveSurfaceFilterTags.size() && tagIndex >= 0)
  574. {
  575. return m_exclusiveSurfaceFilterTags[tagIndex];
  576. }
  577. return AZ::Crc32();
  578. }
  579. void Descriptor::RemoveExclusiveSurfaceFilterTag(int tagIndex)
  580. {
  581. if (tagIndex < m_exclusiveSurfaceFilterTags.size() && tagIndex >= 0)
  582. {
  583. m_exclusiveSurfaceFilterTags.erase(m_exclusiveSurfaceFilterTags.begin() + tagIndex);
  584. }
  585. }
  586. void Descriptor::AddExclusiveSurfaceFilterTag(const AZStd::string& tag)
  587. {
  588. m_exclusiveSurfaceFilterTags.push_back(SurfaceData::SurfaceTag(tag));
  589. }
  590. AZ::u32 Descriptor::GetAdvancedGroupVisibility() const
  591. {
  592. return m_advanced ? AZ::Edit::PropertyVisibility::Show : AZ::Edit::PropertyVisibility::Hide;
  593. }
  594. AZ::u32 Descriptor::GetBoundModeVisibility() const
  595. {
  596. // Only show Bound Mode if we're showing advanced settings *and* this type of instance spawner
  597. // can provide radius data. If not, the "MeshRadius" setting is meaningless, so don't allow it
  598. // to be set.
  599. return (m_advanced && m_instanceSpawner && m_instanceSpawner->HasRadiusData())
  600. ? AZ::Edit::PropertyVisibility::Show
  601. : AZ::Edit::PropertyVisibility::Hide;
  602. }
  603. void Descriptor::RefreshSpawnerTypeList() const
  604. {
  605. m_spawnerTypes.clear();
  606. // Find all registered types that are derived from InstanceSpawner, and get their display names.
  607. // (To change the display name for a class, go to its EditContext and change the name passed in
  608. // to the EditContext Class constructor)
  609. AZ::SerializeContext* serializeContext{};
  610. AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
  611. AZ_Assert(serializeContext, "No SerializeContext found.");
  612. if (serializeContext)
  613. {
  614. serializeContext->EnumerateDerived<InstanceSpawner>(
  615. [&](const AZ::SerializeContext::ClassData* classData, [[maybe_unused]] const AZ::Uuid& classUuid) -> bool
  616. {
  617. auto spawnerDisplayName = classData->m_editData ? classData->m_editData->m_name : classData->m_name;
  618. m_spawnerTypes.push_back(AZStd::make_pair(classData->m_typeId, spawnerDisplayName));
  619. return true;
  620. });
  621. }
  622. // Alphabetically sort the list so that it has a well-defined order, regardless of what order we find the entries.
  623. AZStd::sort(m_spawnerTypes.begin(), m_spawnerTypes.end(), [](const auto& lhs, const auto& rhs) {return lhs.second < rhs.second; });
  624. AZ_Assert(!m_spawnerTypes.empty(), "No serialized InstanceSpawner types were found.");
  625. }
  626. AZStd::vector<AZStd::pair<AZ::TypeId, AZStd::string>> Descriptor::GetSpawnerTypeList() const
  627. {
  628. if (m_spawnerTypes.empty())
  629. {
  630. RefreshSpawnerTypeList();
  631. }
  632. AZ_Assert(!m_spawnerTypes.empty(), "No serialized InstanceSpawner types were found.");
  633. // Copy our static list into a new list with the proper types.
  634. // This is necessary because the PropertyEditor doesn't always recognize alternate forms of string types,
  635. // such as string_view or const char*.
  636. AZStd::vector<AZStd::pair<AZ::TypeId, AZStd::string>> returnList;
  637. returnList.reserve(m_spawnerTypes.size());
  638. returnList.assign(m_spawnerTypes.begin(), m_spawnerTypes.end());
  639. return returnList;
  640. }
  641. bool Descriptor::CreateInstanceSpawner(AZ::TypeId spawnerType, InstanceSpawner* spawnerToClone)
  642. {
  643. // Locate the registered Behavior class for the requested type.
  644. const AZ::BehaviorClass* sourceClass = AZ::BehaviorContextHelper::GetClass(spawnerType);
  645. if (!sourceClass)
  646. {
  647. // Can't find the new spawner type, so set back to the previous one.
  648. AZ_Error("Vegetation", false, "Unrecognized spawner type: %s", spawnerType.ToString<AZStd::string>().c_str());
  649. return false;
  650. }
  651. // Create (or clone) a new instance of the type, and verify that it's the type we expected.
  652. AZ::BehaviorObject newInstance;
  653. if (spawnerToClone)
  654. {
  655. AZ_Assert(spawnerType == azrtti_typeid(spawnerToClone), "Mismatched InstanceSpawner types");
  656. AZ::BehaviorObject source(spawnerToClone, spawnerType);
  657. newInstance = sourceClass->Clone(source);
  658. }
  659. else
  660. {
  661. newInstance = sourceClass->Create();
  662. }
  663. AZ_Assert(newInstance.m_address, "Failed to create requested spawner type: %s", spawnerType.ToString<AZStd::string>().c_str());
  664. AZ_Assert(newInstance.m_typeId == spawnerType, "Unrecognized spawner type: %s", newInstance.m_typeId.ToString<AZStd::string>().c_str());
  665. m_instanceSpawner = AZStd::shared_ptr<InstanceSpawner>(reinterpret_cast<InstanceSpawner*>(newInstance.m_address));
  666. AZ_Assert(spawnerType == azrtti_typeid(*m_instanceSpawner), "Unrecognized spawner type: %s", m_instanceSpawner->RTTI_GetTypeName());
  667. // Force the bound mode to use Radius if this type of spawner can't provide MeshRadius information.
  668. if (!m_instanceSpawner->HasRadiusData())
  669. {
  670. m_boundMode = BoundMode::Radius;
  671. }
  672. // Make sure the spawner type stays in sync with the actual spawner type
  673. m_spawnerType = spawnerType;
  674. return true;
  675. }
  676. AZ::TypeId Descriptor::GetSpawnerType() const
  677. {
  678. return m_spawnerType;
  679. }
  680. void Descriptor::SetSpawnerType(const AZ::TypeId& spawnerType)
  681. {
  682. m_spawnerType = spawnerType;
  683. SpawnerTypeChanged();
  684. }
  685. AZStd::any Descriptor::GetSpawner() const
  686. {
  687. // Note that this is bypassing our shared pointer, which has the potential to cause pointer lifetime
  688. // issues, since scripts won't affect the shared pointer lifetime.
  689. AZStd::any::type_info valueInfo;
  690. valueInfo.m_id = azrtti_typeid(*m_instanceSpawner);
  691. valueInfo.m_isPointer = false;
  692. valueInfo.m_useHeap = true;
  693. valueInfo.m_handler = [](AZStd::any::Action action, AZStd::any* dest, const AZStd::any* source)
  694. {
  695. switch (action)
  696. {
  697. case AZStd::any::Action::Reserve:
  698. {
  699. // No-op
  700. break;
  701. }
  702. case AZStd::any::Action::Copy:
  703. case AZStd::any::Action::Move:
  704. {
  705. *reinterpret_cast<void**>(dest) = AZStd::any_cast<void>(const_cast<AZStd::any*>(source));
  706. break;
  707. }
  708. case AZStd::any::Action::Destroy:
  709. {
  710. *reinterpret_cast<void**>(dest) = nullptr;
  711. break;
  712. }
  713. }
  714. };
  715. return AZStd::any(&(*m_instanceSpawner), valueInfo);
  716. }
  717. void Descriptor::SetSpawner(const AZStd::any& spawnerContainer)
  718. {
  719. bool success = false;
  720. // Convert our AZStd::any container back to an InstanceSpawner pointer.
  721. void* anyToVoidPtr = AZStd::any_cast<void>(&const_cast<AZStd::any&>(spawnerContainer));
  722. InstanceSpawner* spawner = reinterpret_cast<InstanceSpawner*>(anyToVoidPtr);
  723. if (spawner)
  724. {
  725. success = CreateInstanceSpawner(spawnerContainer.type(), spawner);
  726. }
  727. if (!success)
  728. {
  729. AZ_Error("Vegetation", false, "Error setting spawner to type: %s", spawnerContainer.type().ToString<AZStd::string>().c_str());
  730. }
  731. }
  732. AZ::u32 Descriptor::SpawnerTypeChanged()
  733. {
  734. // Create a new InstanceSpawner if we changed the spawner type.
  735. if (m_spawnerType != azrtti_typeid(*m_instanceSpawner))
  736. {
  737. bool success = CreateInstanceSpawner(m_spawnerType);
  738. // If something went wrong creating the new one, still make sure our spawner type
  739. // stays in sync with whatever existing spawner type we have.
  740. if (!success)
  741. {
  742. m_spawnerType = azrtti_typeid(*m_instanceSpawner);
  743. }
  744. // If we change our instance spawner, refresh the entire tree. The set of editable properties
  745. // will change based on the new spawner type.
  746. return AZ::Edit::PropertyRefreshLevels::EntireTree;
  747. }
  748. // Nothing changed, so nothing to refresh.
  749. return AZ::Edit::PropertyRefreshLevels::None;
  750. }
  751. }