3
0

EditorDecalComponent.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  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::Default, &DecalComponentConfig::m_materialAsset, "Material", "The material of the decal.")
  61. ;
  62. }
  63. }
  64. if (auto behaviorContext = azrtti_cast<BehaviorContext*>(context))
  65. {
  66. behaviorContext->Class<EditorDecalComponent>()->RequestBus("DecalRequestBus");
  67. behaviorContext->ConstantProperty("EditorDecalComponentTypeId", BehaviorConstant(Uuid(EditorDecalComponentTypeId)))
  68. ->Attribute(AZ::Script::Attributes::Module, "render")
  69. ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation);
  70. }
  71. }
  72. void EditorDecalComponent::Activate()
  73. {
  74. BaseClass::Activate();
  75. AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(GetEntityId());
  76. AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusConnect(GetEntityId());
  77. AzFramework::BoundsRequestBus::Handler::BusConnect(GetEntityId());
  78. }
  79. void EditorDecalComponent::Deactivate()
  80. {
  81. AzFramework::BoundsRequestBus::Handler::BusDisconnect();
  82. AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusDisconnect();
  83. AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect();
  84. BaseClass::Deactivate();
  85. }
  86. AZ::Transform EditorDecalComponent::GetWorldTransform() const
  87. {
  88. AZ::Transform transform = AZ::Transform::CreateIdentity();
  89. AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
  90. return transform;
  91. }
  92. AZ::Matrix3x4 EditorDecalComponent::GetWorldTransformWithNonUniformScale() const
  93. {
  94. const AZ::Transform worldTransform = GetWorldTransform();
  95. const AZ::Matrix3x3 rotationMat = AZ::Matrix3x3::CreateFromQuaternion(worldTransform.GetRotation());
  96. const AZ::Vector3 nonUniformScale = m_controller.m_cachedNonUniformScale * worldTransform.GetUniformScale();
  97. const AZ::Matrix3x3 nonUniformScaleMat = AZ::Matrix3x3::CreateScale(nonUniformScale);
  98. const AZ::Matrix3x3 rotationAndScale = rotationMat * nonUniformScaleMat;
  99. return AZ::Matrix3x4::CreateFromMatrix3x3AndTranslation(rotationAndScale, worldTransform.GetTranslation());
  100. }
  101. void EditorDecalComponent::DisplayEntityViewport(
  102. [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo,
  103. AzFramework::DebugDisplayRequests& debugDisplay)
  104. {
  105. if (!IsSelected())
  106. {
  107. return;
  108. }
  109. debugDisplay.SetColor(AZ::Colors::Red);
  110. const AZ::Matrix3x4 transform = GetWorldTransformWithNonUniformScale();
  111. debugDisplay.PushPremultipliedMatrix(transform);
  112. debugDisplay.DrawWireBox(-AZ::Vector3::CreateOne(), AZ::Vector3::CreateOne());
  113. AZ::Vector3 x1 = AZ::Vector3(-1, 0, 1);
  114. AZ::Vector3 x2 = AZ::Vector3(1, 0, 1);
  115. AZ::Vector3 y1 = AZ::Vector3(0, -1, 1);
  116. AZ::Vector3 y2 = AZ::Vector3(0, 1, 1);
  117. debugDisplay.DrawLine(x1, x2); // Draw horizontal line
  118. debugDisplay.DrawLine(y1, y2); // Draw vertical line
  119. AZ::Vector3 p0 = AZ::Vector3(-1, -1, 1);
  120. AZ::Vector3 p1 = AZ::Vector3(-1, 1, 1);
  121. AZ::Vector3 p2 = AZ::Vector3(1, 1, 1);
  122. AZ::Vector3 p3 = AZ::Vector3(1, -1, 1);
  123. // Two diagonal edges
  124. debugDisplay.DrawLine(p0, p2);
  125. debugDisplay.DrawLine(p1, p3);
  126. debugDisplay.PopPremultipliedMatrix();
  127. }
  128. AZ::Aabb EditorDecalComponent::GetEditorSelectionBoundsViewport([[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo)
  129. {
  130. return GetWorldBounds();
  131. }
  132. bool EditorDecalComponent::EditorSelectionIntersectRayViewport(
  133. [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, const AZ::Vector3& src, const AZ::Vector3& dir, float& distance)
  134. {
  135. AZ::Transform transform = AZ::Transform::CreateIdentity();
  136. AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
  137. AZ::Vector3 p0 = AZ::Vector3(-1, -1, 0);
  138. AZ::Vector3 p1 = AZ::Vector3(-1, 1, 0);
  139. AZ::Vector3 p2 = AZ::Vector3(1, 1, 0);
  140. AZ::Vector3 p3 = AZ::Vector3(1, -1, 0);
  141. float t{ 0.0f };
  142. bool hitResult = AZ::Intersect::IntersectRayQuad(src, dir, p0, p1, p2, p3, t) != 0;
  143. distance = t;
  144. return hitResult;
  145. }
  146. AZ::Aabb EditorDecalComponent::GetWorldBounds()
  147. {
  148. AZ::Transform transform = AZ::Transform::CreateIdentity();
  149. AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
  150. return GetLocalBounds().GetTransformedAabb(transform);
  151. }
  152. AZ::Aabb EditorDecalComponent::GetLocalBounds()
  153. {
  154. AZ::Aabb bbox = AZ::Aabb::CreateNull();
  155. bbox.AddPoint(AZ::Vector3(-1, -1, 0));
  156. bbox.AddPoint(AZ::Vector3(-1, 1, 0));
  157. bbox.AddPoint(AZ::Vector3(1, 1, 0));
  158. bbox.AddPoint(AZ::Vector3(1, -1, 0));
  159. return bbox;
  160. }
  161. u32 EditorDecalComponent::OnConfigurationChanged()
  162. {
  163. m_controller.ConfigurationChanged();
  164. return Edit::PropertyRefreshLevels::AttributesAndValues;
  165. }
  166. bool EditorDecalComponent::SupportsEditorRayIntersect()
  167. {
  168. return true;
  169. }
  170. } // namespace Render
  171. } // namespace AZ