BsDragAndDropManager.cpp 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. #include "BsDragAndDropManager.h"
  2. #include "BsPlatform.h"
  3. #include "BsCoreApplication.h"
  4. #include <BsTime.h>
  5. using namespace std::placeholders;
  6. namespace BansheeEngine
  7. {
  8. DragAndDropManager::DragAndDropManager()
  9. :mIsDragInProgress(false), mDragTypeId(0), mData(nullptr), mCaptureChanged(false), mCaptureActive(0), mNeedsValidDropTarget(false)
  10. {
  11. mMouseCaptureChangedConn = Platform::onMouseCaptureChanged.connect(std::bind(&DragAndDropManager::mouseCaptureChanged, this));
  12. Input::instance().onPointerReleased.connect(std::bind(&DragAndDropManager::cursorReleased, this, _1));
  13. }
  14. DragAndDropManager::~DragAndDropManager()
  15. {
  16. mMouseCaptureChangedConn.disconnect();
  17. }
  18. void DragAndDropManager::addDropCallback(std::function<void(bool)> dropCallback)
  19. {
  20. mDropCallbacks.push_back(dropCallback);
  21. }
  22. void DragAndDropManager::startDrag(UINT32 typeId, void* data, std::function<void(bool)> dropCallback, bool needsValidDropTarget)
  23. {
  24. if (mIsDragInProgress)
  25. endDrag(false);
  26. mDragTypeId = typeId;
  27. mData = data;
  28. mNeedsValidDropTarget = needsValidDropTarget;
  29. addDropCallback(dropCallback);
  30. mIsDragInProgress = true;
  31. mCaptureActive.store(false);
  32. mCaptureChanged.store(false);
  33. Platform::captureMouse(*gCoreApplication().getPrimaryWindow());
  34. }
  35. void DragAndDropManager::_update()
  36. {
  37. if(!mIsDragInProgress)
  38. return;
  39. // This generally happens when window loses focus and capture is lost (e.g. alt+tab)
  40. int captureActive = mCaptureActive.load();
  41. if (!captureActive && mCaptureChanged.load() &&
  42. (gTime().getFrameIdx() > mCaptureChangeFrame.load())) // Wait one frame to insure input (like mouse up) gets a chance to be processed
  43. {
  44. endDrag(false);
  45. mCaptureChanged.store(false);
  46. }
  47. }
  48. void DragAndDropManager::endDrag(bool processed)
  49. {
  50. for(auto& callback : mDropCallbacks)
  51. callback(processed);
  52. mDragTypeId = 0;
  53. mData = nullptr;
  54. mDropCallbacks.clear();
  55. mIsDragInProgress = false;
  56. }
  57. void DragAndDropManager::mouseCaptureChanged()
  58. {
  59. mCaptureActive.fetch_xor(1); // mCaptureActive = !mCaptureActive;
  60. mCaptureChanged.store(true);
  61. mCaptureChangeFrame.store(gTime().getFrameIdx());
  62. }
  63. void DragAndDropManager::cursorReleased(const PointerEvent& event)
  64. {
  65. if(!mIsDragInProgress)
  66. return;
  67. if(!onDragEnded.empty())
  68. {
  69. DragCallbackInfo info;
  70. onDragEnded(event, info);
  71. endDrag(info.processed);
  72. }
  73. else
  74. endDrag(false);
  75. Platform::releaseMouseCapture();
  76. }
  77. }