EditorImageGradientComponentMode.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  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 <AzToolsFramework/ActionManager/Action/ActionManagerInterface.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 <AzFramework/PaintBrush/PaintBrushNotificationBus.h>
  15. #include <AzToolsFramework/PaintBrush/GlobalPaintBrushSettingsRequestBus.h>
  16. #include <AzToolsFramework/PaintBrush/GlobalPaintBrushSettingsWindow.h>
  17. #include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
  18. #include <Editor/EditorImageGradientComponentMode.h>
  19. #include <GradientSignal/Components/ImageGradientModification.h>
  20. #include <GradientSignal/Ebuses/GradientRequestBus.h>
  21. #include <GradientSignal/Ebuses/ImageGradientModificationBus.h>
  22. #include <GradientSignal/Ebuses/ImageGradientRequestBus.h>
  23. #include <LmbrCentral/Dependency/DependencyNotificationBus.h>
  24. namespace GradientSignal
  25. {
  26. AZ_CLASS_ALLOCATOR_IMPL(EditorImageGradientComponentMode, AZ::SystemAllocator)
  27. //! Class that tracks the data for undoing/redoing a paint stroke.
  28. class PaintBrushUndoBuffer : public AzToolsFramework::UndoSystem::URSequencePoint
  29. {
  30. public:
  31. AZ_CLASS_ALLOCATOR(PaintBrushUndoBuffer, AZ::SystemAllocator);
  32. AZ_RTTI(PaintBrushUndoBuffer, "{E37936AC-22E1-403A-A36B-55390832EDE4}");
  33. PaintBrushUndoBuffer(AZ::EntityId imageEntityId)
  34. : AzToolsFramework::UndoSystem::URSequencePoint("PaintStroke")
  35. , m_entityId(imageEntityId)
  36. {
  37. }
  38. virtual ~PaintBrushUndoBuffer() = default;
  39. void Undo() override
  40. {
  41. if (m_strokeImageBuffer->Empty())
  42. {
  43. return;
  44. }
  45. // Apply the "undo" buffer
  46. const bool undo = true;
  47. m_strokeImageBuffer->ApplyChangeBuffer(undo);
  48. // Notify anything listening to the image gradient that the modified region has changed.
  49. LmbrCentral::DependencyNotificationBus::Event(
  50. m_entityId, &LmbrCentral::DependencyNotificationBus::Events::OnCompositionRegionChanged, m_dirtyArea);
  51. }
  52. void Redo() override
  53. {
  54. if (m_strokeImageBuffer->Empty())
  55. {
  56. return;
  57. }
  58. // Apply the "redo" buffer
  59. const bool undo = false;
  60. m_strokeImageBuffer->ApplyChangeBuffer(undo);
  61. // Notify anything listening to the image gradient that the modified region has changed.
  62. LmbrCentral::DependencyNotificationBus::Event(
  63. m_entityId, &LmbrCentral::DependencyNotificationBus::Events::OnCompositionRegionChanged, m_dirtyArea);
  64. }
  65. bool Changed() const override
  66. {
  67. return !m_strokeImageBuffer->Empty();
  68. }
  69. void SetUndoBufferAndDirtyArea(AZStd::shared_ptr<ImageTileBuffer> buffer, const AZ::Aabb& dirtyArea)
  70. {
  71. m_strokeImageBuffer = buffer;
  72. m_dirtyArea = dirtyArea;
  73. }
  74. private:
  75. //! The entity containing the modified image gradient.
  76. const AZ::EntityId m_entityId;
  77. //! The undo/redo data for the paint strokes.
  78. AZStd::shared_ptr<ImageTileBuffer> m_strokeImageBuffer;
  79. //! Cached dirty area
  80. AZ::Aabb m_dirtyArea;
  81. };
  82. EditorImageGradientComponentMode::EditorImageGradientComponentMode(
  83. const AZ::EntityComponentIdPair& entityComponentIdPair, AZ::Uuid componentType)
  84. : EditorBaseComponentMode(entityComponentIdPair, componentType)
  85. {
  86. ImageGradientModificationNotificationBus::Handler::BusConnect(entityComponentIdPair.GetEntityId());
  87. // Set our paint brush min/max world size range. The minimum size should be large enough to paint at least one pixel, and
  88. // the max size is clamped so that we can't paint more than 256 x 256 pixels per brush stamp.
  89. // 256 is an arbitrary number, but if we start getting much larger, performance can drop precipitously.
  90. // Note: To truly control performance, additional clamping is still needed, because large mouse movements in world space with
  91. // a tiny brush can still cause extremely large numbers of brush points to get calculated and checked.
  92. constexpr float MaxBrushPixelSize = 256.0f;
  93. AZ::Vector2 imagePixelsPerMeter(0.0f);
  94. ImageGradientRequestBus::EventResult(imagePixelsPerMeter, GetEntityId(), &ImageGradientRequestBus::Events::GetImagePixelsPerMeter);
  95. float minBrushSize = AZStd::min(imagePixelsPerMeter.GetX(), imagePixelsPerMeter.GetY());
  96. float maxBrushSize = AZStd::max(imagePixelsPerMeter.GetX(), imagePixelsPerMeter.GetY());
  97. minBrushSize = (minBrushSize <= 0.0f) ? 0.0f : (1.0f / minBrushSize);
  98. maxBrushSize = (maxBrushSize <= 0.0f) ? 0.0f : (MaxBrushPixelSize / maxBrushSize);
  99. AzToolsFramework::GlobalPaintBrushSettingsRequestBus::Broadcast(
  100. &AzToolsFramework::GlobalPaintBrushSettingsRequestBus::Events::SetSizeRange, minBrushSize, maxBrushSize);
  101. AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity();
  102. AZ::TransformBus::EventResult(worldFromLocal, GetEntityId(), &AZ::TransformInterface::GetWorldTM);
  103. // Create the paintbrush manipulator with the appropriate color space.
  104. m_brushManipulator = AzToolsFramework::PaintBrushManipulator::MakeShared(
  105. worldFromLocal, entityComponentIdPair, AzToolsFramework::PaintBrushColorMode::Greyscale);
  106. m_brushManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId);
  107. }
  108. EditorImageGradientComponentMode::~EditorImageGradientComponentMode()
  109. {
  110. EndUndoBatch();
  111. m_brushManipulator->Unregister();
  112. m_brushManipulator.reset();
  113. ImageGradientModificationNotificationBus::Handler::BusDisconnect();
  114. }
  115. void EditorImageGradientComponentMode::Reflect(AZ::ReflectContext* context)
  116. {
  117. AzToolsFramework::ComponentModeFramework::ReflectEditorBaseComponentModeDescendant<EditorImageGradientComponentMode>(context);
  118. }
  119. void EditorImageGradientComponentMode::RegisterActions()
  120. {
  121. // Actions are registered in the PaintBrushMainpulator class
  122. }
  123. void EditorImageGradientComponentMode::BindActionsToModes()
  124. {
  125. AzToolsFramework::PaintBrushManipulator::BindActionsToMode(azrtti_typeid<EditorImageGradientComponentMode>());
  126. }
  127. void EditorImageGradientComponentMode::BindActionsToMenus()
  128. {
  129. // Actions are added to menus in the PaintBrushMainpulator class
  130. }
  131. AZStd::vector<AzToolsFramework::ActionOverride> EditorImageGradientComponentMode::PopulateActionsImpl()
  132. {
  133. return m_brushManipulator->PopulateActionsImpl();
  134. }
  135. AZStd::string EditorImageGradientComponentMode::GetComponentModeName() const
  136. {
  137. return "Image Gradient Paint Mode";
  138. }
  139. AZ::Uuid EditorImageGradientComponentMode::GetComponentModeType() const
  140. {
  141. return azrtti_typeid<EditorImageGradientComponentMode>();
  142. }
  143. bool EditorImageGradientComponentMode::HandleMouseInteraction(
  144. const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction)
  145. {
  146. return m_brushManipulator->HandleMouseInteraction(mouseInteraction);
  147. }
  148. void EditorImageGradientComponentMode::Refresh()
  149. {
  150. }
  151. void EditorImageGradientComponentMode::BeginUndoBatch()
  152. {
  153. AZ_Assert(m_undoBatch == nullptr, "Starting an undo batch while one is already active!");
  154. AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult(
  155. m_undoBatch, &AzToolsFramework::ToolsApplicationRequests::Bus::Events::BeginUndoBatch, "PaintStroke");
  156. m_paintBrushUndoBuffer = aznew PaintBrushUndoBuffer(GetEntityId());
  157. m_paintBrushUndoBuffer->SetParent(m_undoBatch);
  158. }
  159. void EditorImageGradientComponentMode::EndUndoBatch()
  160. {
  161. if (m_undoBatch != nullptr)
  162. {
  163. AzToolsFramework::ToolsApplicationRequests::Bus::Broadcast(
  164. &AzToolsFramework::ToolsApplicationRequests::Bus::Events::EndUndoBatch);
  165. m_undoBatch = nullptr;
  166. m_paintBrushUndoBuffer = nullptr;
  167. }
  168. }
  169. void EditorImageGradientComponentMode::OnImageGradientBrushStrokeBegin()
  170. {
  171. BeginUndoBatch();
  172. }
  173. void EditorImageGradientComponentMode::OnImageGradientBrushStrokeEnd(
  174. AZStd::shared_ptr<ImageTileBuffer> changedDataBuffer, const AZ::Aabb& dirtyRegion)
  175. {
  176. AZ_Assert(m_paintBrushUndoBuffer != nullptr, "Undo batch is expected to exist while painting");
  177. // Hand over ownership of the paint stroke buffer to the undo/redo buffer.
  178. m_paintBrushUndoBuffer->SetUndoBufferAndDirtyArea(changedDataBuffer, dirtyRegion);
  179. EndUndoBatch();
  180. }
  181. } // namespace GradientSignal