UiDropTargetComponent.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  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 "UiDropTargetComponent.h"
  9. #include <AzCore/Math/Crc.h>
  10. #include <AzCore/Serialization/SerializeContext.h>
  11. #include <AzCore/Serialization/EditContext.h>
  12. #include <AzCore/RTTI/BehaviorContext.h>
  13. #include <LyShine/Bus/UiCanvasBus.h>
  14. #include <LyShine/Bus/UiElementBus.h>
  15. #include <LyShine/Bus/UiDraggableBus.h>
  16. ////////////////////////////////////////////////////////////////////////////////////////////////////
  17. //! UiDropTargetNotificationBus Behavior context handler class
  18. class UiDropTargetNotificationBusBehaviorHandler
  19. : public UiDropTargetNotificationBus::Handler
  20. , public AZ::BehaviorEBusHandler
  21. {
  22. public:
  23. AZ_EBUS_BEHAVIOR_BINDER(UiDropTargetNotificationBusBehaviorHandler, "{B01A3FB5-52E1-4FF4-A627-088DA37A1304}", AZ::SystemAllocator,
  24. OnDropHoverStart, OnDropHoverEnd, OnDrop);
  25. void OnDropHoverStart(AZ::EntityId draggable) override
  26. {
  27. Call(FN_OnDropHoverStart, draggable);
  28. }
  29. void OnDropHoverEnd(AZ::EntityId draggable) override
  30. {
  31. Call(FN_OnDropHoverEnd, draggable);
  32. }
  33. void OnDrop(AZ::EntityId draggable) override
  34. {
  35. Call(FN_OnDrop, draggable);
  36. }
  37. };
  38. ////////////////////////////////////////////////////////////////////////////////////////////////////
  39. // PUBLIC MEMBER FUNCTIONS
  40. ////////////////////////////////////////////////////////////////////////////////////////////////////
  41. ////////////////////////////////////////////////////////////////////////////////////////////////////
  42. UiDropTargetComponent::UiDropTargetComponent()
  43. {
  44. // Must be called in the same order as the states defined in UiDropTargetInterface
  45. m_stateActionManager.AddState(nullptr); // normal state has no state actions
  46. m_stateActionManager.AddState(&m_dropValidStateActions);
  47. m_stateActionManager.AddState(&m_dropInvalidStateActions);
  48. }
  49. ////////////////////////////////////////////////////////////////////////////////////////////////////
  50. UiDropTargetComponent::~UiDropTargetComponent()
  51. {
  52. }
  53. ////////////////////////////////////////////////////////////////////////////////////////////////////
  54. const LyShine::ActionName& UiDropTargetComponent::GetOnDropActionName()
  55. {
  56. return m_onDropActionName;
  57. }
  58. ////////////////////////////////////////////////////////////////////////////////////////////////////
  59. void UiDropTargetComponent::SetOnDropActionName(const LyShine::ActionName& actionName)
  60. {
  61. m_onDropActionName = actionName;
  62. }
  63. ////////////////////////////////////////////////////////////////////////////////////////////////////
  64. void UiDropTargetComponent::HandleDropHoverStart(AZ::EntityId draggable)
  65. {
  66. UiDropTargetNotificationBus::QueueEvent(GetEntityId(), &UiDropTargetNotificationBus::Events::OnDropHoverStart, draggable);
  67. }
  68. ////////////////////////////////////////////////////////////////////////////////////////////////////
  69. void UiDropTargetComponent::HandleDropHoverEnd(AZ::EntityId draggable)
  70. {
  71. UiDropTargetNotificationBus::QueueEvent(GetEntityId(), &UiDropTargetNotificationBus::Events::OnDropHoverEnd, draggable);
  72. }
  73. ////////////////////////////////////////////////////////////////////////////////////////////////////
  74. void UiDropTargetComponent::HandleDrop(AZ::EntityId draggable)
  75. {
  76. UiDropTargetNotificationBus::QueueEvent(GetEntityId(), &UiDropTargetNotificationBus::Events::OnDrop, draggable);
  77. // Check to see if the draggable is a proxy
  78. bool isProxy = false;
  79. UiDraggableBus::EventResult(isProxy, draggable, &UiDraggableBus::Events::IsProxy);
  80. // Tell any action listeners about the event
  81. // Don't do this for proxy draggables though. A proxy draggable always calls HandleDrop on the original
  82. // and we don't want this action triggered twice.
  83. if (!m_onDropActionName.empty() && !isProxy)
  84. {
  85. AZ::EntityId canvasEntityId;
  86. UiElementBus::EventResult(canvasEntityId, GetEntityId(), &UiElementBus::Events::GetCanvasEntityId);
  87. UiCanvasNotificationBus::Event(canvasEntityId, &UiCanvasNotificationBus::Events::OnAction, GetEntityId(), m_onDropActionName);
  88. }
  89. }
  90. ////////////////////////////////////////////////////////////////////////////////////////////////////
  91. UiDropTargetInterface::DropState UiDropTargetComponent::GetDropState()
  92. {
  93. return m_dropState;
  94. }
  95. ////////////////////////////////////////////////////////////////////////////////////////////////////
  96. void UiDropTargetComponent::SetDropState(DropState dropState)
  97. {
  98. if (dropState != m_dropState)
  99. {
  100. m_stateActionManager.ResetAllOverrides();
  101. m_stateActionManager.ApplyStateActions(dropState);
  102. m_dropState = dropState;
  103. }
  104. }
  105. ////////////////////////////////////////////////////////////////////////////////////////////////////
  106. // PROTECTED MEMBER FUNCTIONS
  107. ////////////////////////////////////////////////////////////////////////////////////////////////////
  108. ////////////////////////////////////////////////////////////////////////////////////////////////////
  109. void UiDropTargetComponent::Init()
  110. {
  111. m_stateActionManager.Init(GetEntityId());
  112. }
  113. ////////////////////////////////////////////////////////////////////////////////////////////////////
  114. void UiDropTargetComponent::Activate()
  115. {
  116. m_stateActionManager.Activate();
  117. m_navigationSettings.Activate(m_entity->GetId(), GetNavigableDropTargets);
  118. UiDropTargetBus::Handler::BusConnect(m_entity->GetId());
  119. }
  120. ////////////////////////////////////////////////////////////////////////////////////////////////////
  121. void UiDropTargetComponent::Deactivate()
  122. {
  123. m_stateActionManager.Deactivate();
  124. m_navigationSettings.Deactivate();
  125. UiDropTargetBus::Handler::BusDisconnect();
  126. }
  127. ////////////////////////////////////////////////////////////////////////////////////////////////////
  128. void UiDropTargetComponent::OnDropValidStateActionsChanged()
  129. {
  130. m_stateActionManager.InitInteractableEntityForStateActions(m_dropValidStateActions);
  131. }
  132. ////////////////////////////////////////////////////////////////////////////////////////////////////
  133. void UiDropTargetComponent::OnDropInvalidStateActionsChanged()
  134. {
  135. m_stateActionManager.InitInteractableEntityForStateActions(m_dropInvalidStateActions);
  136. }
  137. ////////////////////////////////////////////////////////////////////////////////////////////////////
  138. // PROTECTED STATIC MEMBER FUNCTIONS
  139. ////////////////////////////////////////////////////////////////////////////////////////////////////
  140. ////////////////////////////////////////////////////////////////////////////////////////////////////
  141. void UiDropTargetComponent::Reflect(AZ::ReflectContext* context)
  142. {
  143. AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
  144. if (serializeContext)
  145. {
  146. serializeContext->Class<UiDropTargetComponent, AZ::Component>()
  147. ->Version(1)
  148. ->Field("DropValidStateActions", &UiDropTargetComponent::m_dropValidStateActions)
  149. ->Field("DropInvalidStateActions", &UiDropTargetComponent::m_dropInvalidStateActions)
  150. ->Field("NavigationSettings", &UiDropTargetComponent::m_navigationSettings)
  151. ->Field("OnDropActionName", &UiDropTargetComponent::m_onDropActionName);
  152. AZ::EditContext* ec = serializeContext->GetEditContext();
  153. if (ec)
  154. {
  155. auto editInfo = ec->Class<UiDropTargetComponent>("DropTarget", "A target component for drag and drop behavior");
  156. editInfo->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  157. ->Attribute(AZ::Edit::Attributes::Category, "UI")
  158. ->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/UiDropTarget.png")
  159. ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Editor/Icons/Components/Viewport/UiDropTarget.png")
  160. ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("UI", 0x27ff46b0))
  161. ->Attribute(AZ::Edit::Attributes::AutoExpand, true);
  162. // Navigation settings
  163. editInfo->DataElement(0, &UiDropTargetComponent::m_navigationSettings, "Navigation",
  164. "How to navigate from this drop target to the next drop target");
  165. // Drop states group
  166. {
  167. editInfo->ClassElement(AZ::Edit::ClassElements::Group, "Drop States")
  168. ->Attribute(AZ::Edit::Attributes::AutoExpand, true);
  169. editInfo->DataElement(0, &UiDropTargetComponent::m_dropValidStateActions, "Valid", "The valid drop state actions")
  170. ->Attribute(AZ::Edit::Attributes::AddNotify, &UiDropTargetComponent::OnDropValidStateActionsChanged);
  171. editInfo->DataElement(0, &UiDropTargetComponent::m_dropInvalidStateActions, "Invalid", "The invalid drop state actions")
  172. ->Attribute(AZ::Edit::Attributes::AddNotify, &UiDropTargetComponent::OnDropInvalidStateActionsChanged);
  173. }
  174. // Actions group
  175. {
  176. editInfo->ClassElement(AZ::Edit::ClassElements::Group, "Actions")
  177. ->Attribute(AZ::Edit::Attributes::AutoExpand, true);
  178. editInfo->DataElement(0, &UiDropTargetComponent::m_onDropActionName, "OnDrop",
  179. "The action name triggered when a draggable is dropped on the drop target");
  180. }
  181. }
  182. }
  183. AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
  184. if (behaviorContext)
  185. {
  186. behaviorContext->Enum<(int)DropStateNormal>("eUiDropState_Normal")
  187. ->Enum<(int)DropStateValid>("eUiDropState_Valid")
  188. ->Enum<(int)DropStateInvalid>("eUiDropState_Invalid");
  189. behaviorContext->EBus<UiDropTargetBus>("UiDropTargetBus")
  190. ->Event("GetOnDropActionName", &UiDropTargetBus::Events::GetOnDropActionName)
  191. ->Event("SetOnDropActionName", &UiDropTargetBus::Events::SetOnDropActionName)
  192. ->Event("GetDropState", &UiDropTargetBus::Events::GetDropState)
  193. ->Event("SetDropState", &UiDropTargetBus::Events::SetDropState);
  194. behaviorContext->EBus<UiDropTargetNotificationBus>("UiDropTargetNotificationBus")
  195. ->Handler<UiDropTargetNotificationBusBehaviorHandler>();
  196. }
  197. }
  198. ////////////////////////////////////////////////////////////////////////////////////////////////////
  199. // PRIVATE STATIC MEMBER FUNCTIONS
  200. ////////////////////////////////////////////////////////////////////////////////////////////////////
  201. ////////////////////////////////////////////////////////////////////////////////////////////////////
  202. LyShine::EntityArray UiDropTargetComponent::GetNavigableDropTargets(AZ::EntityId entityId)
  203. {
  204. // Get a list of all navigable elements
  205. AZ::EntityId canvasEntityId;
  206. UiElementBus::EventResult(canvasEntityId, entityId, &UiElementBus::Events::GetCanvasEntityId);
  207. LyShine::EntityArray navigableElements;
  208. UiCanvasBus::Event(
  209. canvasEntityId,
  210. &UiCanvasBus::Events::FindElements,
  211. [entityId](const AZ::Entity* entity)
  212. {
  213. bool navigable = false;
  214. if (entity->GetId() != entityId)
  215. {
  216. if (UiDropTargetBus::FindFirstHandler(entity->GetId()))
  217. {
  218. UiNavigationInterface::NavigationMode navigationMode = UiNavigationInterface::NavigationMode::None;
  219. UiNavigationBus::EventResult(navigationMode, entity->GetId(), &UiNavigationBus::Events::GetNavigationMode);
  220. navigable = (navigationMode != UiNavigationInterface::NavigationMode::None);
  221. }
  222. }
  223. return navigable;
  224. },
  225. navigableElements);
  226. return navigableElements;
  227. }