EditorTerrainMacroMaterialComponentMode.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  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 <AzCore/Component/TransformBus.h>
  9. #include <AzFramework/PaintBrush/PaintBrushNotificationBus.h>
  10. #include <AzToolsFramework/API/ToolsApplicationAPI.h>
  11. #include <AzToolsFramework/Manipulators/PaintBrushManipulator.h>
  12. #include <AzToolsFramework/Manipulators/ManipulatorManager.h>
  13. #include <AzToolsFramework/Manipulators/ManipulatorView.h>
  14. #include <AzToolsFramework/PaintBrush/GlobalPaintBrushSettingsRequestBus.h>
  15. #include <AzToolsFramework/PaintBrush/GlobalPaintBrushSettingsWindow.h>
  16. #include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
  17. #include <LmbrCentral/Dependency/DependencyNotificationBus.h>
  18. #include <TerrainRenderer/EditorComponents/EditorTerrainMacroMaterialComponentMode.h>
  19. #include <TerrainRenderer/TerrainMacroMaterialBus.h>
  20. #include <TerrainRenderer/Components/MacroMaterialImageModification.h>
  21. namespace Terrain
  22. {
  23. //! Class that tracks the data for undoing/redoing a paint stroke.
  24. class PaintBrushUndoBuffer : public AzToolsFramework::UndoSystem::URSequencePoint
  25. {
  26. public:
  27. AZ_CLASS_ALLOCATOR(PaintBrushUndoBuffer, AZ::SystemAllocator);
  28. AZ_RTTI(PaintBrushUndoBuffer, "{6EF041B7-D59F-4CC1-B75E-0C04D6D091FD}");
  29. PaintBrushUndoBuffer(AZ::EntityId imageEntityId)
  30. : AzToolsFramework::UndoSystem::URSequencePoint("PaintStroke")
  31. , m_entityId(imageEntityId)
  32. {
  33. }
  34. virtual ~PaintBrushUndoBuffer() = default;
  35. void Undo() override
  36. {
  37. if (m_strokeImageBuffer->Empty())
  38. {
  39. return;
  40. }
  41. // Apply the "undo" buffer
  42. const bool undo = true;
  43. m_strokeImageBuffer->ApplyChangeBuffer(undo);
  44. // Notify anything listening to the terrain macro material that the modified region has changed.
  45. LmbrCentral::DependencyNotificationBus::Event(
  46. m_entityId, &LmbrCentral::DependencyNotificationBus::Events::OnCompositionRegionChanged, m_dirtyArea);
  47. }
  48. void Redo() override
  49. {
  50. if (m_strokeImageBuffer->Empty())
  51. {
  52. return;
  53. }
  54. // Apply the "redo" buffer
  55. const bool undo = false;
  56. m_strokeImageBuffer->ApplyChangeBuffer(undo);
  57. // Notify anything listening to the terrain macro material that the modified region has changed.
  58. LmbrCentral::DependencyNotificationBus::Event(
  59. m_entityId, &LmbrCentral::DependencyNotificationBus::Events::OnCompositionRegionChanged, m_dirtyArea);
  60. }
  61. bool Changed() const override
  62. {
  63. return !m_strokeImageBuffer->Empty();
  64. }
  65. void SetUndoBufferAndDirtyArea(AZStd::shared_ptr<ImageTileBuffer> buffer, const AZ::Aabb& dirtyArea)
  66. {
  67. m_strokeImageBuffer = buffer;
  68. m_dirtyArea = dirtyArea;
  69. }
  70. private:
  71. //! The entity containing the modified image gradient.
  72. const AZ::EntityId m_entityId;
  73. //! The undo/redo data for the paint strokes.
  74. AZStd::shared_ptr<ImageTileBuffer> m_strokeImageBuffer;
  75. //! Cached dirty area
  76. AZ::Aabb m_dirtyArea;
  77. };
  78. EditorTerrainMacroMaterialComponentMode::EditorTerrainMacroMaterialComponentMode(
  79. const AZ::EntityComponentIdPair& entityComponentIdPair, AZ::Uuid componentType)
  80. : EditorBaseComponentMode(entityComponentIdPair, componentType)
  81. {
  82. TerrainMacroColorModificationNotificationBus::Handler::BusConnect(entityComponentIdPair.GetEntityId());
  83. // Set our paint brush min/max world size range. The minimum size should be large enough to paint at least one pixel, and
  84. // the max size is clamped so that we can't paint more than 256 x 256 pixels per brush stamp.
  85. // 256 is an arbitrary number, but if we start getting much larger, performance can drop precipitously.
  86. // Note: To truly control performance, additional clamping is still needed, because large mouse movements in world space with
  87. // a tiny brush can still cause extremely large numbers of brush points to get calculated and checked.
  88. constexpr float MaxBrushPixelSize = 256.0f;
  89. AZ::Vector2 imagePixelsPerMeter(0.0f);
  90. TerrainMacroMaterialRequestBus::EventResult(
  91. imagePixelsPerMeter, GetEntityId(), &TerrainMacroMaterialRequestBus::Events::GetMacroColorImagePixelsPerMeter);
  92. float minBrushSize = AZStd::min(imagePixelsPerMeter.GetX(), imagePixelsPerMeter.GetY());
  93. float maxBrushSize = AZStd::max(imagePixelsPerMeter.GetX(), imagePixelsPerMeter.GetY());
  94. minBrushSize = (minBrushSize <= 0.0f) ? 0.0f : (1.0f / minBrushSize);
  95. maxBrushSize = (maxBrushSize <= 0.0f) ? 0.0f : (MaxBrushPixelSize / maxBrushSize);
  96. AzToolsFramework::GlobalPaintBrushSettingsRequestBus::Broadcast(
  97. &AzToolsFramework::GlobalPaintBrushSettingsRequestBus::Events::SetSizeRange, minBrushSize, maxBrushSize);
  98. AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity();
  99. AZ::TransformBus::EventResult(worldFromLocal, GetEntityId(), &AZ::TransformInterface::GetWorldTM);
  100. // Create the paintbrush manipulator with the appropriate color space.
  101. m_brushManipulator = AzToolsFramework::PaintBrushManipulator::MakeShared(
  102. worldFromLocal, entityComponentIdPair, AzToolsFramework::PaintBrushColorMode::LinearColor);
  103. m_brushManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId);
  104. }
  105. EditorTerrainMacroMaterialComponentMode::~EditorTerrainMacroMaterialComponentMode()
  106. {
  107. EndUndoBatch();
  108. m_brushManipulator->Unregister();
  109. m_brushManipulator.reset();
  110. TerrainMacroColorModificationNotificationBus::Handler::BusDisconnect();
  111. }
  112. AZStd::vector<AzToolsFramework::ActionOverride> EditorTerrainMacroMaterialComponentMode::PopulateActionsImpl()
  113. {
  114. return m_brushManipulator->PopulateActionsImpl();
  115. }
  116. AZStd::string EditorTerrainMacroMaterialComponentMode::GetComponentModeName() const
  117. {
  118. return "Terrain Macro Material Paint Mode";
  119. }
  120. AZ::Uuid EditorTerrainMacroMaterialComponentMode::GetComponentModeType() const
  121. {
  122. return AZ::AzTypeInfo<EditorTerrainMacroMaterialComponentMode>::Uuid();
  123. }
  124. bool EditorTerrainMacroMaterialComponentMode::HandleMouseInteraction(
  125. const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction)
  126. {
  127. return m_brushManipulator->HandleMouseInteraction(mouseInteraction);
  128. }
  129. void EditorTerrainMacroMaterialComponentMode::Refresh()
  130. {
  131. }
  132. void EditorTerrainMacroMaterialComponentMode::BeginUndoBatch()
  133. {
  134. AZ_Assert(m_undoBatch == nullptr, "Starting an undo batch while one is already active!");
  135. AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult(
  136. m_undoBatch, &AzToolsFramework::ToolsApplicationRequests::Bus::Events::BeginUndoBatch, "PaintStroke");
  137. m_paintBrushUndoBuffer = aznew PaintBrushUndoBuffer(GetEntityId());
  138. m_paintBrushUndoBuffer->SetParent(m_undoBatch);
  139. }
  140. void EditorTerrainMacroMaterialComponentMode::EndUndoBatch()
  141. {
  142. if (m_undoBatch != nullptr)
  143. {
  144. AzToolsFramework::ToolsApplicationRequests::Bus::Broadcast(
  145. &AzToolsFramework::ToolsApplicationRequests::Bus::Events::EndUndoBatch);
  146. m_undoBatch = nullptr;
  147. m_paintBrushUndoBuffer = nullptr;
  148. }
  149. }
  150. void EditorTerrainMacroMaterialComponentMode::OnTerrainMacroColorBrushStrokeBegin()
  151. {
  152. BeginUndoBatch();
  153. }
  154. void EditorTerrainMacroMaterialComponentMode::OnTerrainMacroColorBrushStrokeEnd(
  155. AZStd::shared_ptr<ImageTileBuffer> changedDataBuffer, const AZ::Aabb& dirtyRegion)
  156. {
  157. AZ_Assert(m_paintBrushUndoBuffer != nullptr, "Undo batch is expected to exist while painting");
  158. // Hand over ownership of the paint stroke buffer to the undo/redo buffer.
  159. m_paintBrushUndoBuffer->SetUndoBufferAndDirtyArea(changedDataBuffer, dirtyRegion);
  160. EndUndoBatch();
  161. }
  162. } // namespace Terrain