ViewportSnap.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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 "EditorCommon.h"
  9. #include "ViewportSnap.h"
  10. #include <LyShine/Bus/UiEditorCanvasBus.h>
  11. namespace
  12. {
  13. UiTransform2dInterface::Offsets ResizeAboutPivot(const UiTransform2dInterface::Offsets& offsets,
  14. const ViewportHelpers::GizmoParts& grabbedGizmoParts,
  15. const AZ::Vector2& pivot,
  16. const AZ::Vector2& translation)
  17. {
  18. UiTransform2dInterface::Offsets result(offsets);
  19. if (grabbedGizmoParts.m_right)
  20. {
  21. result.m_left -= translation.GetX() * pivot.GetX();
  22. result.m_right += translation.GetX() * (1.0f - pivot.GetX());
  23. }
  24. if (grabbedGizmoParts.m_top)
  25. {
  26. result.m_top += translation.GetY() * pivot.GetY();
  27. result.m_bottom -= translation.GetY() * (1.0f - pivot.GetY());
  28. }
  29. return result;
  30. }
  31. } // anonymous namespace.
  32. void ViewportSnap::Rotate(HierarchyWidget* hierarchy,
  33. const AZ::EntityId& canvasId,
  34. AZ::Entity* element,
  35. float signedAngle)
  36. {
  37. bool isSnapping = false;
  38. UiEditorCanvasBus::EventResult(isSnapping, canvasId, &UiEditorCanvasBus::Events::GetIsSnapEnabled);
  39. if (isSnapping)
  40. {
  41. HierarchyItem* item = HierarchyItem::RttiCast(HierarchyHelpers::ElementToItem(hierarchy, element, false));
  42. // Update the non-snapped rotation.
  43. item->SetNonSnappedZRotation(item->GetNonSnappedZRotation() + signedAngle);
  44. // Update the currently used rotation.
  45. float realRotation;
  46. UiTransformBus::EventResult(realRotation, element->GetId(), &UiTransformBus::Events::GetZRotation);
  47. float snappedRotation = item->GetNonSnappedZRotation();
  48. {
  49. float snapRotationInDegrees = 1.0f;
  50. UiEditorCanvasBus::EventResult(snapRotationInDegrees, canvasId, &UiEditorCanvasBus::Events::GetSnapRotationDegrees);
  51. snappedRotation = EntityHelpers::Snap(snappedRotation, snapRotationInDegrees);
  52. }
  53. if (snappedRotation != realRotation)
  54. {
  55. UiTransformBus::Event(element->GetId(), &UiTransformBus::Events::SetZRotation, snappedRotation);
  56. UiElementChangeNotificationBus::Event(element->GetId(), &UiElementChangeNotificationBus::Events::UiElementPropertyChanged);
  57. }
  58. }
  59. else // if (!isSnapping)
  60. {
  61. // Add the angle to the current rotation of this element
  62. float rotation;
  63. UiTransformBus::EventResult(rotation, element->GetId(), &UiTransformBus::Events::GetZRotation);
  64. UiTransformBus::Event(element->GetId(), &UiTransformBus::Events::SetZRotation, (rotation + signedAngle));
  65. UiElementChangeNotificationBus::Event(element->GetId(), &UiElementChangeNotificationBus::Events::UiElementPropertyChanged);
  66. }
  67. }
  68. void ViewportSnap::ResizeByGizmo(HierarchyWidget* hierarchy,
  69. const AZ::EntityId& canvasId,
  70. const ViewportHelpers::GizmoParts& grabbedGizmoParts,
  71. AZ::Entity* element,
  72. const AZ::Vector2& pivot,
  73. const AZ::Vector2& translation)
  74. {
  75. bool isSnapping = false;
  76. UiEditorCanvasBus::EventResult(isSnapping, canvasId, &UiEditorCanvasBus::Events::GetIsSnapEnabled);
  77. if (isSnapping)
  78. {
  79. HierarchyItem* item = HierarchyItem::RttiCast(HierarchyHelpers::ElementToItem(hierarchy, element, false));
  80. // Resize the element about the pivot
  81. UiTransform2dInterface::Offsets offsets(ResizeAboutPivot(item->GetNonSnappedOffsets(), grabbedGizmoParts, pivot, translation));
  82. // Update the non-snapped offset.
  83. item->SetNonSnappedOffsets(offsets);
  84. UiTransform2dInterface::Offsets snappedOffsets(item->GetNonSnappedOffsets());
  85. {
  86. float snapDistance = 1.0f;
  87. UiEditorCanvasBus::EventResult(snapDistance, canvasId, &UiEditorCanvasBus::Events::GetSnapDistance);
  88. UiTransform2dInterface::Anchors anchors;
  89. UiTransform2dBus::EventResult(anchors, element->GetId(), &UiTransform2dBus::Events::GetAnchors);
  90. AZ::Entity* parentElement = EntityHelpers::GetParentElement(element);
  91. AZ::Vector2 parentSize;
  92. UiTransformBus::EventResult(parentSize, parentElement->GetId(), &UiTransformBus::Events::GetCanvasSpaceSizeNoScaleRotate);
  93. float newWidth = parentSize.GetX() * (anchors.m_right - anchors.m_left) + offsets.m_right - offsets.m_left;
  94. float newHeight = parentSize.GetY() * (anchors.m_bottom - anchors.m_top) + offsets.m_bottom - offsets.m_top;
  95. if (grabbedGizmoParts.m_right)
  96. {
  97. float snappedWidth = ViewportHelpers::IsHorizontallyFit(element) ? newWidth : EntityHelpers::Snap(newWidth, snapDistance);
  98. float deltaWidth = snappedWidth - newWidth;
  99. snappedOffsets.m_left = offsets.m_left - deltaWidth * pivot.GetX(); // move left when width increases, so decrease offset
  100. snappedOffsets.m_right = offsets.m_right + deltaWidth * (1.0f - pivot.GetX()); // move right when width increases so increase offset
  101. }
  102. if (grabbedGizmoParts.m_top)
  103. {
  104. float snappedHeight = ViewportHelpers::IsVerticallyFit(element) ? newHeight : EntityHelpers::Snap(newHeight, snapDistance);
  105. float deltaHeight = snappedHeight - newHeight;
  106. snappedOffsets.m_top = offsets.m_top - deltaHeight * pivot.GetY(); // move left when width increases, so decrease offset
  107. snappedOffsets.m_bottom = offsets.m_bottom + deltaHeight * (1.0f - pivot.GetY()); // move right when width increases so increase offset
  108. }
  109. }
  110. // Update the currently used offset.
  111. if (snappedOffsets != offsets)
  112. {
  113. UiTransform2dBus::Event(element->GetId(), &UiTransform2dBus::Events::SetOffsets, snappedOffsets);
  114. UiElementChangeNotificationBus::Event(element->GetId(), &UiElementChangeNotificationBus::Events::UiElementPropertyChanged);
  115. }
  116. }
  117. else // if (!isSnapping)
  118. {
  119. // Resize the element about the pivot
  120. UiTransform2dInterface::Offsets offsets;
  121. UiTransform2dBus::EventResult(offsets, element->GetId(), &UiTransform2dBus::Events::GetOffsets);
  122. UiTransform2dInterface::Offsets newOffsets(ResizeAboutPivot(offsets, grabbedGizmoParts, pivot, translation));
  123. // Resize the element
  124. UiTransform2dBus::Event(element->GetId(), &UiTransform2dBus::Events::SetOffsets, newOffsets);
  125. UiElementChangeNotificationBus::Event(element->GetId(), &UiElementChangeNotificationBus::Events::UiElementPropertyChanged);
  126. }
  127. }
  128. void ViewportSnap::ResizeDirectlyWithScaleOrRotation(HierarchyWidget* hierarchy,
  129. const AZ::EntityId& canvasId,
  130. const ViewportHelpers::ElementEdges& grabbedEdges,
  131. AZ::Entity* element,
  132. const UiTransformInterface::RectPoints& translation)
  133. {
  134. bool isSnapping = false;
  135. UiEditorCanvasBus::EventResult(isSnapping, canvasId, &UiEditorCanvasBus::Events::GetIsSnapEnabled);
  136. if (isSnapping)
  137. {
  138. HierarchyItem* item = HierarchyItem::RttiCast(HierarchyHelpers::ElementToItem(hierarchy, element, false));
  139. // Update the non-snapped offset.
  140. item->SetNonSnappedOffsets(item->GetNonSnappedOffsets() + translation);
  141. // Update the currently used offset.
  142. {
  143. UiTransform2dInterface::Offsets currentOffsets;
  144. UiTransform2dBus::EventResult(currentOffsets, element->GetId(), &UiTransform2dBus::Events::GetOffsets);
  145. UiTransform2dInterface::Offsets snappedOffsets(item->GetNonSnappedOffsets());
  146. {
  147. float snapDistance = 1.0f;
  148. UiEditorCanvasBus::EventResult(snapDistance, canvasId, &UiEditorCanvasBus::Events::GetSnapDistance);
  149. snappedOffsets = EntityHelpers::Snap(snappedOffsets, grabbedEdges, snapDistance);
  150. }
  151. if (snappedOffsets != currentOffsets)
  152. {
  153. UiTransform2dBus::Event(element->GetId(), &UiTransform2dBus::Events::SetOffsets, snappedOffsets);
  154. UiElementChangeNotificationBus::Event(element->GetId(), &UiElementChangeNotificationBus::Events::UiElementPropertyChanged);
  155. }
  156. }
  157. }
  158. else // if (!isSnapping)
  159. {
  160. // Resize the element
  161. UiTransform2dInterface::Offsets offsets;
  162. UiTransform2dBus::EventResult(offsets, element->GetId(), &UiTransform2dBus::Events::GetOffsets);
  163. UiTransform2dBus::Event(element->GetId(), &UiTransform2dBus::Events::SetOffsets, (offsets + translation));
  164. UiElementChangeNotificationBus::Event(element->GetId(), &UiElementChangeNotificationBus::Events::UiElementPropertyChanged);
  165. }
  166. }
  167. void ViewportSnap::ResizeDirectlyNoScaleNoRotation(HierarchyWidget* hierarchy,
  168. const AZ::EntityId& canvasId,
  169. const ViewportHelpers::ElementEdges& grabbedEdges,
  170. AZ::Entity* element,
  171. const AZ::Vector2& translation)
  172. {
  173. bool isSnapping = false;
  174. UiEditorCanvasBus::EventResult(isSnapping, canvasId, &UiEditorCanvasBus::Events::GetIsSnapEnabled);
  175. if (isSnapping)
  176. {
  177. HierarchyItem* item = HierarchyItem::RttiCast(HierarchyHelpers::ElementToItem(hierarchy, element, false));
  178. // Update the non-snapped offset.
  179. item->SetNonSnappedOffsets(ViewportHelpers::MoveGrabbedEdges(item->GetNonSnappedOffsets(), grabbedEdges, translation));
  180. // Update the currently used offset.
  181. {
  182. UiTransform2dInterface::Offsets currentOffsets;
  183. UiTransform2dBus::EventResult(currentOffsets, element->GetId(), &UiTransform2dBus::Events::GetOffsets);
  184. UiTransform2dInterface::Offsets snappedOffsets(item->GetNonSnappedOffsets());
  185. {
  186. float snapDistance = 1.0f;
  187. UiEditorCanvasBus::EventResult(snapDistance, canvasId, &UiEditorCanvasBus::Events::GetSnapDistance);
  188. snappedOffsets = EntityHelpers::Snap(snappedOffsets, grabbedEdges, snapDistance);
  189. }
  190. if (snappedOffsets != currentOffsets)
  191. {
  192. UiTransform2dBus::Event(element->GetId(), &UiTransform2dBus::Events::SetOffsets, snappedOffsets);
  193. UiElementChangeNotificationBus::Event(element->GetId(), &UiElementChangeNotificationBus::Events::UiElementPropertyChanged);
  194. }
  195. }
  196. }
  197. else // if (!isSnapping)
  198. {
  199. // Resize the element
  200. UiTransform2dInterface::Offsets offsets;
  201. UiTransform2dBus::EventResult(offsets, element->GetId(), &UiTransform2dBus::Events::GetOffsets);
  202. UiTransform2dBus::Event(element->GetId(), &UiTransform2dBus::Events::SetOffsets, ViewportHelpers::MoveGrabbedEdges(offsets, grabbedEdges, translation));
  203. UiElementChangeNotificationBus::Event(element->GetId(), &UiElementChangeNotificationBus::Events::UiElementPropertyChanged);
  204. }
  205. }