EditorDecalComponent.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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 <Decals/EditorDecalComponent.h>
  9. #include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
  10. #include <AzCore/Math/IntersectSegment.h>
  11. namespace AZ
  12. {
  13. namespace Render
  14. {
  15. EditorDecalComponent::EditorDecalComponent(const DecalComponentConfig& config)
  16. : BaseClass(config)
  17. {
  18. }
  19. void EditorDecalComponent::Reflect(AZ::ReflectContext* context)
  20. {
  21. BaseClass::Reflect(context);
  22. if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  23. {
  24. serializeContext->Class<EditorDecalComponent, BaseClass>()
  25. ->Version(2, ConvertToEditorRenderComponentAdapter<1>);
  26. if (AZ::EditContext* editContext = serializeContext->GetEditContext())
  27. {
  28. editContext->Class<EditorDecalComponent>(
  29. "Decal", "The Decal component allows an entity to project a texture or material onto a mesh")
  30. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  31. ->Attribute(AZ::Edit::Attributes::Category, "Graphics/Mesh")
  32. ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Decal.svg")
  33. ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Decal.svg")
  34. ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game"))
  35. ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
  36. ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/decal/")
  37. ;
  38. editContext->Class<DecalComponentController>(
  39. "DecalComponentController", "")
  40. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  41. ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
  42. ->DataElement(AZ::Edit::UIHandlers::Default, &DecalComponentController::m_configuration, "Configuration", "")
  43. ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
  44. ;
  45. editContext->Class<DecalComponentConfig>(
  46. "DecalComponentConfig", "")
  47. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  48. ->DataElement(AZ::Edit::UIHandlers::Slider, &DecalComponentConfig::m_attenuationAngle, "Attenuation Angle", "Controls how much the angle between geometry and the decal affects decal opacity.")
  49. ->Attribute(AZ::Edit::Attributes::Min, 0.f)
  50. ->Attribute(AZ::Edit::Attributes::Max, 1.f)
  51. ->DataElement(AZ::Edit::UIHandlers::Slider, &DecalComponentConfig::m_opacity, "Opacity", "The opacity of the decal.")
  52. ->Attribute(AZ::Edit::Attributes::Min, 0.f)
  53. ->Attribute(AZ::Edit::Attributes::Max, 1.f)
  54. ->DataElement(AZ::Edit::UIHandlers::Slider, &DecalComponentConfig::m_normalMapOpacity, "Normal Map Opacity", "The opacity of the decal's normal map.")
  55. ->Attribute(AZ::Edit::Attributes::Min, 0.f)
  56. ->Attribute(AZ::Edit::Attributes::Max, 1.f)
  57. ->DataElement(AZ::Edit::UIHandlers::Slider, &DecalComponentConfig::m_sortKey, "Sort Key", "Decals with a larger sort key appear over top of smaller sort keys.")
  58. ->Attribute(AZ::Edit::Attributes::Min, std::numeric_limits<uint8_t>::min())
  59. ->Attribute(AZ::Edit::Attributes::Max, std::numeric_limits<uint8_t>::max())
  60. ->DataElement(AZ::Edit::UIHandlers::Color, &DecalComponentConfig::m_decalColor, "Decal Color", "Decal Color can be applied as a multiplier")
  61. ->DataElement(AZ::Edit::UIHandlers::Slider, &DecalComponentConfig::m_decalColorFactor, "Decal Color Factor", "The factor associated with decal color which also acts as a multiplier. ")
  62. ->Attribute(AZ::Edit::Attributes::Min, 0.f)
  63. ->Attribute(AZ::Edit::Attributes::Max, 5.f)
  64. ->DataElement(AZ::Edit::UIHandlers::Default, &DecalComponentConfig::m_materialAsset, "Material", "The material of the decal.")
  65. ;
  66. }
  67. }
  68. if (auto behaviorContext = azrtti_cast<BehaviorContext*>(context))
  69. {
  70. behaviorContext->Class<EditorDecalComponent>()->RequestBus("DecalRequestBus");
  71. behaviorContext->ConstantProperty("EditorDecalComponentTypeId", BehaviorConstant(Uuid(EditorDecalComponentTypeId)))
  72. ->Attribute(AZ::Script::Attributes::Module, "render")
  73. ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation);
  74. }
  75. }
  76. void EditorDecalComponent::Activate()
  77. {
  78. BaseClass::Activate();
  79. AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(GetEntityId());
  80. AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusConnect(GetEntityId());
  81. AzFramework::BoundsRequestBus::Handler::BusConnect(GetEntityId());
  82. }
  83. void EditorDecalComponent::Deactivate()
  84. {
  85. AzFramework::BoundsRequestBus::Handler::BusDisconnect();
  86. AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusDisconnect();
  87. AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect();
  88. BaseClass::Deactivate();
  89. }
  90. AZ::Transform EditorDecalComponent::GetWorldTransform() const
  91. {
  92. AZ::Transform transform = AZ::Transform::CreateIdentity();
  93. AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
  94. return transform;
  95. }
  96. AZ::Matrix3x4 EditorDecalComponent::GetWorldTransformWithNonUniformScale() const
  97. {
  98. const AZ::Transform worldTransform = GetWorldTransform();
  99. const AZ::Matrix3x3 rotationMat = AZ::Matrix3x3::CreateFromQuaternion(worldTransform.GetRotation());
  100. const AZ::Vector3 nonUniformScale = m_controller.m_cachedNonUniformScale * worldTransform.GetUniformScale();
  101. const AZ::Matrix3x3 nonUniformScaleMat = AZ::Matrix3x3::CreateScale(nonUniformScale);
  102. const AZ::Matrix3x3 rotationAndScale = rotationMat * nonUniformScaleMat;
  103. return AZ::Matrix3x4::CreateFromMatrix3x3AndTranslation(rotationAndScale, worldTransform.GetTranslation());
  104. }
  105. void EditorDecalComponent::DisplayEntityViewport(
  106. [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo,
  107. AzFramework::DebugDisplayRequests& debugDisplay)
  108. {
  109. if (!IsSelected())
  110. {
  111. return;
  112. }
  113. debugDisplay.SetColor(AZ::Colors::Red);
  114. const AZ::Matrix3x4 transform = GetWorldTransformWithNonUniformScale();
  115. debugDisplay.PushPremultipliedMatrix(transform);
  116. debugDisplay.DrawWireBox(-AZ::Vector3::CreateOne(), AZ::Vector3::CreateOne());
  117. AZ::Vector3 x1 = AZ::Vector3(-1, 0, 1);
  118. AZ::Vector3 x2 = AZ::Vector3(1, 0, 1);
  119. AZ::Vector3 y1 = AZ::Vector3(0, -1, 1);
  120. AZ::Vector3 y2 = AZ::Vector3(0, 1, 1);
  121. debugDisplay.DrawLine(x1, x2); // Draw horizontal line
  122. debugDisplay.DrawLine(y1, y2); // Draw vertical line
  123. AZ::Vector3 p0 = AZ::Vector3(-1, -1, 1);
  124. AZ::Vector3 p1 = AZ::Vector3(-1, 1, 1);
  125. AZ::Vector3 p2 = AZ::Vector3(1, 1, 1);
  126. AZ::Vector3 p3 = AZ::Vector3(1, -1, 1);
  127. // Two diagonal edges
  128. debugDisplay.DrawLine(p0, p2);
  129. debugDisplay.DrawLine(p1, p3);
  130. debugDisplay.PopPremultipliedMatrix();
  131. }
  132. AZ::Aabb EditorDecalComponent::GetEditorSelectionBoundsViewport([[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo)
  133. {
  134. return GetWorldBounds();
  135. }
  136. bool EditorDecalComponent::EditorSelectionIntersectRayViewport(
  137. [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, const AZ::Vector3& src, const AZ::Vector3& dir, float& distance)
  138. {
  139. AZ::Transform transform = AZ::Transform::CreateIdentity();
  140. AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
  141. AZ::Vector3 p0 = AZ::Vector3(-1, -1, 0);
  142. AZ::Vector3 p1 = AZ::Vector3(-1, 1, 0);
  143. AZ::Vector3 p2 = AZ::Vector3(1, 1, 0);
  144. AZ::Vector3 p3 = AZ::Vector3(1, -1, 0);
  145. float t{ 0.0f };
  146. bool hitResult = AZ::Intersect::IntersectRayQuad(src, dir, p0, p1, p2, p3, t) != 0;
  147. distance = t;
  148. return hitResult;
  149. }
  150. AZ::Aabb EditorDecalComponent::GetWorldBounds() const
  151. {
  152. AZ::Transform transform = AZ::Transform::CreateIdentity();
  153. AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
  154. return GetLocalBounds().GetTransformedAabb(transform);
  155. }
  156. AZ::Aabb EditorDecalComponent::GetLocalBounds() const
  157. {
  158. AZ::Aabb bbox = AZ::Aabb::CreateNull();
  159. bbox.AddPoint(AZ::Vector3(-1, -1, 0));
  160. bbox.AddPoint(AZ::Vector3(-1, 1, 0));
  161. bbox.AddPoint(AZ::Vector3(1, 1, 0));
  162. bbox.AddPoint(AZ::Vector3(1, -1, 0));
  163. return bbox;
  164. }
  165. u32 EditorDecalComponent::OnConfigurationChanged()
  166. {
  167. m_controller.ConfigurationChanged();
  168. return Edit::PropertyRefreshLevels::AttributesAndValues;
  169. }
  170. bool EditorDecalComponent::SupportsEditorRayIntersect()
  171. {
  172. return true;
  173. }
  174. } // namespace Render
  175. } // namespace AZ