BsDragAndDropManager.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #pragma once
  2. #include "BsPrerequisites.h"
  3. #include "BsModule.h"
  4. #include "BsInput.h"
  5. #include "BsEvent.h"
  6. #include <atomic>
  7. namespace BansheeEngine
  8. {
  9. /**
  10. * @brief Holds data returned by DragAndDropManager callbacks.
  11. */
  12. struct BS_EXPORT DragCallbackInfo
  13. {
  14. DragCallbackInfo()
  15. :processed(false)
  16. { }
  17. bool processed;
  18. };
  19. /**
  20. * @brief Handles GUI drag and drop operations. When active GUI elements
  21. * will be notified of any drag events and will be able to retrieve
  22. * dragged data.
  23. *
  24. * @note Sim thread only.
  25. */
  26. class BS_EXPORT DragAndDropManager : public Module<DragAndDropManager>
  27. {
  28. public:
  29. DragAndDropManager();
  30. ~DragAndDropManager();
  31. /**
  32. * @brief Starts a drag operation of the specified type. This means GUI elements will start receiving
  33. * drag and drop related events and they may choose to handle them.
  34. *
  35. * @param typeId Type of the drag and drop operation that other objects may query and decide if they want
  36. * to handle it. User defined.
  37. * @param data Some operation specific data that is just passed through to however needs it.
  38. * @param dropCallback The drop callback that gets triggered whenever mouse button is released and drag operation ends.
  39. * You should perform any cleanup here.
  40. * @param needsValidDropTarget (optional) Determines whether the drop operation may happen anywhere or does the GUI element need to specifically
  41. * accept the drag of this type. If false all GUI elements we mouse over will receive drag/drop events, otherwise only
  42. * those that specifically subscribe to the specified drag operation of this typeId will.
  43. *
  44. * Additionally this will determine the cursor displayed (whether or not it can have a "denied" state).
  45. */
  46. void startDrag(UINT32 typeId, void* data, std::function<void(bool)> dropCallback, bool needsValidDropTarget = false);
  47. /**
  48. * @brief Returns true if drag is currently in progress.
  49. */
  50. bool isDragInProgress() const { return mIsDragInProgress; }
  51. /**
  52. * @brief Get type ID of drag currently in progress. Only valid if drag is in progress.
  53. */
  54. UINT32 getDragTypeId() const { return mDragTypeId; }
  55. /**
  56. * @brief Gets drag specific data specified when the drag started. Only valid if drag is in progress.
  57. */
  58. void* getDragData() const { return mData; }
  59. /**
  60. * @brief Determines whether the drop operation may happen anywhere or does the GUI element need to specifically
  61. * accept the drag of this type. If false all GUI elements we mouse over will receive drag/drop events, otherwise only
  62. * those that specifically subscribe to the specified drag operation of this typeId will.
  63. *
  64. * Additionally this will determine the cursor displayed (whether or not it can have a "denied" state).
  65. */
  66. bool needsValidDropTarget() const { return mNeedsValidDropTarget; }
  67. /**
  68. * @brief Registers a new callback that will be triggered when dragged item is dropped.
  69. * Provided parameter specifies if the drop operation was handled by anyone or not.
  70. */
  71. void addDropCallback(std::function<void(bool)> dropCallback);
  72. /**
  73. * @brief Called once per frame.
  74. *
  75. * @note Internal method.
  76. */
  77. void _update();
  78. /**
  79. * @brief Triggers a callback when user releases the pointer and the drag operation ends.
  80. * Provided parameters inform the subscriber where the pointer was released, and allows
  81. * the subscriber to note whether the drag operation was processed or not.
  82. *
  83. * @note Internal event. You should use addDropCallback for normal use.
  84. */
  85. Event<void(const PointerEvent&, DragCallbackInfo&)> onDragEnded;
  86. private:
  87. /**
  88. * @brief Triggers any drop callbacks and clears callback data.
  89. */
  90. void endDrag(bool processed);
  91. /**
  92. * @brief Called by the core thread whenever mouse capture state changes.
  93. * This can happen when window loses focus (e.g. alt+tab). In that
  94. * case we want to end the drag even if the user is still holding
  95. * the dragged item.
  96. *
  97. * @note Core thread.
  98. */
  99. void mouseCaptureChanged();
  100. /**
  101. * @brief Called by the input system when pointer is released.
  102. */
  103. void cursorReleased(const PointerEvent& event);
  104. private:
  105. UINT32 mDragTypeId;
  106. void* mData;
  107. Vector<std::function<void(bool)>> mDropCallbacks;
  108. bool mIsDragInProgress;
  109. bool mNeedsValidDropTarget;
  110. HEvent mMouseCaptureChangedConn;
  111. std::atomic<bool> mCaptureChanged;
  112. std::atomic<int> mCaptureActive;
  113. std::atomic<unsigned long> mCaptureChangeFrame;
  114. };
  115. }