BsDockManager.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  1. #include "BsDockManager.h"
  2. #include "BsEditorWidgetContainer.h"
  3. #include "CmMath.h"
  4. #include "CmException.h"
  5. #include "CmMesh.h"
  6. #include "CmMaterial.h"
  7. #include "CmVector2.h"
  8. #include "CmRenderQueue.h"
  9. #include "CmApplication.h"
  10. #include "CmRendererManager.h"
  11. #include "CmRenderer.h"
  12. #include "CmSceneObject.h"
  13. #include "BsGUIManager.h"
  14. #include "BsBuiltinMaterialManager.h"
  15. #include "BsGUIWidget.h"
  16. #include "BsCamera.h"
  17. #include "BsDragAndDropManager.h"
  18. #include "BsGUIDockSlider.h"
  19. #include "CmVertexDataDesc.h"
  20. #include "BsGUISkin.h"
  21. #include "BsEngineGUI.h"
  22. #include "BsGUISkin.h"
  23. #include "BsEngineGUI.h"
  24. #include "BsGUIButton.h"
  25. using namespace CamelotFramework;
  26. using namespace BansheeEngine;
  27. namespace BansheeEditor
  28. {
  29. const CM::UINT32 DockManager::DockContainer::SLIDER_SIZE = 4;
  30. const CM::UINT32 DockManager::DockContainer::MIN_CHILD_SIZE = 20;
  31. const CM::Color DockManager::TINT_COLOR = Color(0.44f, 0.44f, 0.44f, 0.22f);
  32. const CM::Color DockManager::HIGHLIGHT_COLOR = Color(0.44f, 0.44f, 0.44f, 0.42f);
  33. DockManager::DockContainer::DockContainer()
  34. :mIsLeaf(false), mWidgets(nullptr), mFirstChildSize(0),
  35. mIsHorizontal(false), mParent(nullptr), mSlider(nullptr)
  36. {
  37. mChildren[0] = nullptr;
  38. mChildren[1] = nullptr;
  39. }
  40. DockManager::DockContainer::DockContainer(DockContainer* parent)
  41. :mIsLeaf(false), mWidgets(nullptr), mFirstChildSize(0),
  42. mIsHorizontal(false), mParent(parent), mSlider(nullptr)
  43. {
  44. mChildren[0] = nullptr;
  45. mChildren[1] = nullptr;
  46. }
  47. DockManager::DockContainer::~DockContainer()
  48. {
  49. if(mIsLeaf && mWidgets != nullptr)
  50. cm_delete(mWidgets);
  51. if(!mIsLeaf)
  52. {
  53. if(mChildren[0] != nullptr)
  54. cm_delete(mChildren[0]);
  55. if(mChildren[1] != nullptr)
  56. cm_delete(mChildren[1]);
  57. }
  58. if(mSlider != nullptr)
  59. {
  60. GUIElement::destroy(mSlider);
  61. mSlider = nullptr;
  62. }
  63. }
  64. void DockManager::DockContainer::setArea(CM::INT32 x, CM::INT32 y, UINT32 width, UINT32 height)
  65. {
  66. if(mIsLeaf)
  67. {
  68. if(mWidgets != nullptr)
  69. {
  70. mWidgets->setPosition(x, y);
  71. mWidgets->setSize(width, height);
  72. }
  73. }
  74. else if(mChildren[0] != nullptr && mChildren[1] != nullptr)
  75. {
  76. if(mIsHorizontal)
  77. {
  78. UINT32 currentRemainingSize = (UINT32)std::max(0, (INT32)mArea.height - (INT32)SLIDER_SIZE);
  79. float splitPosition = (float)mFirstChildSize / (float)currentRemainingSize;
  80. UINT32 remainingSize = (UINT32)std::max(0, (INT32)height - (INT32)SLIDER_SIZE);
  81. mFirstChildSize = Math::floorToInt(remainingSize * splitPosition);
  82. }
  83. else
  84. {
  85. UINT32 currentRemainingSize = (UINT32)std::max(0, (INT32)mArea.width - (INT32)SLIDER_SIZE);
  86. float splitPosition = mFirstChildSize / (float)currentRemainingSize;
  87. UINT32 remainingSize = (UINT32)std::max(0, (INT32)width - (INT32)SLIDER_SIZE);
  88. mFirstChildSize = Math::floorToInt(remainingSize * splitPosition);
  89. }
  90. }
  91. mArea.x = x;
  92. mArea.y = y;
  93. mArea.width = width;
  94. mArea.height = height;
  95. updateChildAreas();
  96. }
  97. void DockManager::DockContainer::updateChildAreas()
  98. {
  99. if(!mIsLeaf && mChildren[0] != nullptr && mChildren[1] != nullptr)
  100. {
  101. if(mIsHorizontal)
  102. {
  103. UINT32 remainingSize = (UINT32)std::max(0, (INT32)mArea.height - (INT32)SLIDER_SIZE);
  104. UINT32 sizeBottom = remainingSize - mFirstChildSize;
  105. mChildren[0]->setArea(mArea.x, mArea.y, mArea.width, mFirstChildSize);
  106. mChildren[1]->setArea(mArea.x, mArea.y + mFirstChildSize + SLIDER_SIZE, mArea.width, sizeBottom);
  107. mSlider->_setOffset(Vector2I(mArea.x, mArea.y + mFirstChildSize));
  108. mSlider->_setWidth(mArea.width);
  109. mSlider->_setHeight(SLIDER_SIZE);
  110. }
  111. else
  112. {
  113. UINT32 remainingSize = (UINT32)std::max(0, (INT32)mArea.width - (INT32)SLIDER_SIZE);
  114. UINT32 sizeRight = remainingSize - mFirstChildSize;
  115. mChildren[0]->setArea(mArea.x, mArea.y, mFirstChildSize, mArea.height);
  116. mChildren[1]->setArea(mArea.x + mFirstChildSize + SLIDER_SIZE, mArea.y, sizeRight, mArea.height);
  117. mSlider->_setOffset(Vector2I(mArea.x + mFirstChildSize, mArea.y));
  118. mSlider->_setWidth(SLIDER_SIZE);
  119. mSlider->_setHeight(mArea.height);
  120. }
  121. }
  122. }
  123. void DockManager::DockContainer::makeLeaf(GUIWidget* widgetParent, RenderWindow* parentWindow, EditorWidget* widget)
  124. {
  125. mIsLeaf = true;
  126. mWidgets = cm_new<EditorWidgetContainer>(widgetParent, parentWindow);
  127. mWidgets->onWidgetClosed.connect(boost::bind(&DockManager::DockContainer::widgetRemoved, this));
  128. if(mSlider != nullptr)
  129. {
  130. GUIElement::destroy(mSlider);
  131. mSlider = nullptr;
  132. }
  133. mWidgets->add(*widget);
  134. mWidgets->setPosition(mArea.x, mArea.y);
  135. mWidgets->setSize(mArea.width, mArea.height);
  136. }
  137. void DockManager::DockContainer::makeLeaf(EditorWidgetContainer* existingContainer)
  138. {
  139. mIsLeaf = true;
  140. mWidgets = existingContainer;
  141. mWidgets->onWidgetClosed.connect(boost::bind(&DockManager::DockContainer::widgetRemoved, this));
  142. if(mSlider != nullptr)
  143. {
  144. GUIElement::destroy(mSlider);
  145. mSlider = nullptr;
  146. }
  147. mWidgets->setPosition(mArea.x, mArea.y);
  148. mWidgets->setSize(mArea.width, mArea.height);
  149. }
  150. void DockManager::DockContainer::addLeft(BS::GUIWidget* widgetParent, RenderWindow* parentWindow, EditorWidget* widget)
  151. {
  152. splitContainer(widgetParent, parentWindow, widget, false, true);
  153. }
  154. void DockManager::DockContainer::addRight(BS::GUIWidget* widgetParent, RenderWindow* parentWindow, EditorWidget* widget)
  155. {
  156. splitContainer(widgetParent, parentWindow, widget, false, false);
  157. }
  158. void DockManager::DockContainer::addTop(BS::GUIWidget* widgetParent, RenderWindow* parentWindow, EditorWidget* widget)
  159. {
  160. splitContainer(widgetParent, parentWindow, widget, true, true);
  161. }
  162. void DockManager::DockContainer::addBottom(BS::GUIWidget* widgetParent, RenderWindow* parentWindow, EditorWidget* widget)
  163. {
  164. splitContainer(widgetParent, parentWindow, widget, true, false);
  165. }
  166. void DockManager::DockContainer::splitContainer(BS::GUIWidget* widgetParent, RenderWindow* parentWindow, EditorWidget* widget, bool horizontal, bool newChildIsFirst)
  167. {
  168. UINT32 idxA = newChildIsFirst ? 0 : 1;
  169. UINT32 idxB = (idxA + 1) % 2;
  170. mChildren[idxA] = cm_new<DockContainer>(this);
  171. mChildren[idxB] = cm_new<DockContainer>(this);
  172. mWidgets->onWidgetClosed.disconnect_all_slots();
  173. mChildren[idxA]->makeLeaf(widgetParent, parentWindow, widget);
  174. mChildren[idxB]->makeLeaf(mWidgets);
  175. mIsLeaf = false;
  176. mIsHorizontal = horizontal;
  177. mWidgets = nullptr;
  178. if(horizontal)
  179. {
  180. mSlider = GUIDockSlider::create(*widgetParent, true, EngineGUI::instance().getSkin().getStyle(GUIButton::getGUITypeName()));
  181. mSlider->_setWidgetDepth(widgetParent->getDepth());
  182. UINT32 remainingSize = (UINT32)std::max(0, (INT32)mArea.height - (INT32)SLIDER_SIZE);
  183. mFirstChildSize = Math::floorToInt(remainingSize * 0.5f);
  184. }
  185. else
  186. {
  187. mSlider = GUIDockSlider::create(*widgetParent, false, EngineGUI::instance().getSkin().getStyle(GUIButton::getGUITypeName()));
  188. mSlider->_setWidgetDepth(widgetParent->getDepth());
  189. UINT32 remainingSize = (UINT32)std::max(0, (INT32)mArea.width - (INT32)SLIDER_SIZE);
  190. mFirstChildSize = Math::floorToInt(remainingSize * 0.5f);
  191. }
  192. mSlider->onDragged.connect(boost::bind(&DockManager::DockContainer::sliderDragged, this, _1));
  193. setArea(mArea.x, mArea.y, mArea.width, mArea.height);
  194. }
  195. void DockManager::DockContainer::sliderDragged(const CM::Vector2I& delta)
  196. {
  197. if(mIsHorizontal && delta.y != 0)
  198. {
  199. UINT32 maxSize = (UINT32)std::max(MIN_CHILD_SIZE, (INT32)mArea.height - (INT32)SLIDER_SIZE - MIN_CHILD_SIZE);
  200. mFirstChildSize = Math::clamp(mFirstChildSize + delta.y, MIN_CHILD_SIZE, maxSize);
  201. updateChildAreas();
  202. }
  203. else if(!mIsHorizontal && delta.x != 0)
  204. {
  205. UINT32 maxSize = (UINT32)std::max(MIN_CHILD_SIZE, (INT32)mArea.width - (INT32)SLIDER_SIZE - MIN_CHILD_SIZE);
  206. mFirstChildSize = Math::clamp(mFirstChildSize + delta.x, MIN_CHILD_SIZE, maxSize);
  207. updateChildAreas();
  208. }
  209. }
  210. void DockManager::DockContainer::widgetRemoved()
  211. {
  212. assert(mIsLeaf);
  213. if(mWidgets->getNumWidgets() == 0)
  214. {
  215. if(mParent == nullptr) // We're root so we just reset ourselves, can't delete root
  216. {
  217. cm_delete(mWidgets);
  218. mWidgets = nullptr;
  219. mIsLeaf = false;
  220. mFirstChildSize = 0;
  221. mIsHorizontal = false;
  222. }
  223. else
  224. {
  225. // Replace our parent with our sibling
  226. DockContainer* sibling = nullptr;
  227. if(mParent->mChildren[0] == this)
  228. sibling = mParent->mChildren[1];
  229. else
  230. sibling = mParent->mChildren[0];
  231. sibling->mWidgets->onWidgetClosed.disconnect_all_slots();
  232. mParent->makeLeaf(sibling->mWidgets);
  233. sibling->mWidgets = nullptr;
  234. cm_delete(sibling);
  235. cm_delete(this);
  236. }
  237. }
  238. }
  239. DockManager::DockContainer* DockManager::DockContainer::find(EditorWidgetContainer* widgetContainer)
  240. {
  241. if(mIsLeaf)
  242. {
  243. if(mWidgets == widgetContainer)
  244. return this;
  245. else
  246. return nullptr;
  247. }
  248. else
  249. {
  250. if(mChildren[0] != nullptr && mChildren[0]->find(widgetContainer) != nullptr)
  251. return mChildren[0];
  252. if(mChildren[1] != nullptr && mChildren[1]->find(widgetContainer) != nullptr)
  253. return mChildren[1];
  254. }
  255. return nullptr;
  256. }
  257. DockManager::DockContainer* DockManager::DockContainer::findAtPos(const CM::Vector2I& pos)
  258. {
  259. if(mIsLeaf)
  260. {
  261. if(mArea.contains(pos))
  262. {
  263. return this;
  264. }
  265. }
  266. else
  267. {
  268. if(mChildren[0] != nullptr && mChildren[0]->findAtPos(pos) != nullptr)
  269. return mChildren[0];
  270. if(mChildren[1] != nullptr && mChildren[1]->findAtPos(pos) != nullptr)
  271. return mChildren[1];
  272. }
  273. return nullptr;
  274. }
  275. RectI DockManager::DockContainer::getContentBounds() const
  276. {
  277. if(!mIsLeaf)
  278. return mArea;
  279. return mWidgets->getContentBounds();
  280. }
  281. DockManager::DockManager(BS::GUIWidget& parent, CM::RenderWindow* parentWindow, const GUILayoutOptions& layoutOptions)
  282. :GUIElementContainer(parent, layoutOptions), mParentWindow(parentWindow), mMouseOverContainer(nullptr), mHighlightedDropLoc(DockLocation::None),
  283. mShowOverlay(false)
  284. {
  285. mTopDropPolygon = cm_newN<Vector2>(4);
  286. mBotDropPolygon = cm_newN<Vector2>(4);
  287. mLeftDropPolygon = cm_newN<Vector2>(4);
  288. mRightDropPolygon = cm_newN<Vector2>(4);
  289. mDropOverlayMat = BuiltinMaterialManager::instance().createDockDropOverlayMaterial();
  290. RendererManager::instance().getActive()->addRenderCallback(mParent->getTarget(), boost::bind(&DockManager::render, this, _1, _2));
  291. }
  292. DockManager::~DockManager()
  293. {
  294. cm_deleteN(mTopDropPolygon, 4);
  295. cm_deleteN(mBotDropPolygon, 4);
  296. cm_deleteN(mLeftDropPolygon, 4);
  297. cm_deleteN(mRightDropPolygon, 4);
  298. }
  299. DockManager* DockManager::create(GUIWidget& parent, RenderWindow* parentWindow)
  300. {
  301. return new (cm_alloc<DockManager, PoolAlloc>()) DockManager(parent, parentWindow, GUILayoutOptions::create(&GUISkin::DefaultStyle));
  302. }
  303. void DockManager::update()
  304. {
  305. if(!DragAndDropManager::instance().isDragInProgress())
  306. {
  307. mHighlightedDropLoc = DockLocation::None;
  308. mShowOverlay = false;
  309. }
  310. }
  311. void DockManager::render(const Viewport* viewport, CM::RenderQueue& renderQueue)
  312. {
  313. if(!mShowOverlay)
  314. return;
  315. float invViewportWidth = 1.0f / (viewport->getWidth() * 0.5f);
  316. float invViewportHeight = 1.0f / (viewport->getHeight() * 0.5f);
  317. if(mDropOverlayMesh == nullptr || !mDropOverlayMesh.isLoaded() || !mDropOverlayMesh->isInitialized())
  318. return;
  319. if(mDropOverlayMat == nullptr || !mDropOverlayMat.isLoaded() || !mDropOverlayMat->isInitialized())
  320. return;
  321. mDropOverlayMat->setFloat("invViewportWidth", invViewportWidth);
  322. mDropOverlayMat->setFloat("invViewportHeight", invViewportHeight);
  323. mDropOverlayMat->setColor("tintColor", TINT_COLOR);
  324. mDropOverlayMat->setColor("highlightColor", HIGHLIGHT_COLOR);
  325. Color highlightColor;
  326. switch(mHighlightedDropLoc)
  327. {
  328. case DockLocation::Top:
  329. highlightColor = Color(1.0f, 0.0f, 0.0f, 0.0f);
  330. break;
  331. case DockLocation::Bottom:
  332. highlightColor = Color(0.0f, 1.0f, 0.0f, 0.0f);
  333. break;
  334. case DockLocation::Left:
  335. highlightColor = Color(0.0f, 0.0f, 1.0f, 0.0f);
  336. break;
  337. case DockLocation::Right:
  338. highlightColor = Color(0.0f, 0.0f, 0.0f, 1.0f);
  339. break;
  340. case DockLocation::None:
  341. highlightColor = Color(0.0f, 0.0f, 0.0f, 0.0f);
  342. break;
  343. }
  344. mDropOverlayMat->setColor("highlightActive", highlightColor);
  345. renderQueue.add(mDropOverlayMat.getInternalPtr(), mDropOverlayMesh.getInternalPtr(), 0, Vector3::ZERO);
  346. }
  347. void DockManager::insert(EditorWidgetContainer* relativeTo, EditorWidget* widgetToInsert, DockLocation location)
  348. {
  349. if(relativeTo != nullptr)
  350. {
  351. DockContainer* container = mRootContainer.find(relativeTo);
  352. if(container == nullptr)
  353. CM_EXCEPT(InternalErrorException, "Cannot find the wanted widget container relative to which the widget should be inserted.");
  354. switch(location)
  355. {
  356. case DockLocation::Left:
  357. container->addLeft(mParent, mParentWindow, widgetToInsert);
  358. break;
  359. case DockLocation::Right:
  360. container->addRight(mParent, mParentWindow, widgetToInsert);
  361. break;
  362. case DockLocation::Top:
  363. container->addTop(mParent, mParentWindow, widgetToInsert);
  364. break;
  365. case DockLocation::Bottom:
  366. container->addBottom(mParent, mParentWindow, widgetToInsert);
  367. break;
  368. }
  369. }
  370. else
  371. {
  372. if(mRootContainer.mWidgets != nullptr)
  373. CM_EXCEPT(InternalErrorException, "Trying to insert a widget into dock manager root container but one already exists.");
  374. mRootContainer.makeLeaf(mParent, mParentWindow, widgetToInsert);
  375. }
  376. }
  377. void DockManager::setArea(INT32 x, INT32 y, UINT32 width, UINT32 height)
  378. {
  379. mRootContainer.setArea(x, y, width, height);
  380. updateDropOverlay(x, y, width, height);
  381. }
  382. void DockManager::updateClippedBounds()
  383. {
  384. // TODO - Clipping not actually accounted for
  385. mClippedBounds = mRootContainer.mArea;
  386. }
  387. void DockManager::updateDropOverlay(INT32 x, INT32 y, UINT32 width, UINT32 height)
  388. {
  389. const static int spacing = 10;
  390. const static float innerScale = 0.75f;
  391. UINT32 outWidth = std::max(0, (INT32)width - spacing * 2);
  392. UINT32 outHeight = std::max(0, (INT32)height - spacing * 2);
  393. UINT32 inWidth = (UINT32)Math::floorToInt(innerScale * outWidth);
  394. UINT32 inHeight = (UINT32)Math::floorToInt(innerScale * outHeight);
  395. INT32 inXOffset = Math::floorToInt((outWidth - inWidth) * 0.5f);
  396. INT32 inYOffset = Math::floorToInt((outHeight - inHeight) * 0.5f);
  397. Vector2 outTopLeft((float)x, (float)y);
  398. Vector2 outTopRight((float)(x + outWidth), (float)y);
  399. Vector2 outBotLeft((float)x, (float)(y + outHeight));
  400. Vector2 outBotRight((float)(x + outWidth), (float)(y + outHeight));
  401. Vector2 inTopLeft((float)(x + inXOffset), (float)(y + inYOffset));
  402. Vector2 inTopRight((float)(x + inXOffset + inWidth), (float)(y + inYOffset));
  403. Vector2 inBotLeft((float)(x + inXOffset), (float)(y + inYOffset + inHeight));
  404. Vector2 inBotRight((float)(x + inXOffset + inWidth), (float)(y + inYOffset + inHeight));
  405. VertexDataDescPtr vertexDesc = cm_shared_ptr<VertexDataDesc>();
  406. vertexDesc->addVertElem(VET_FLOAT2, VES_POSITION);
  407. vertexDesc->addVertElem(VET_COLOR, VES_COLOR);
  408. MeshDataPtr meshData = cm_shared_ptr<MeshData, ScratchAlloc>(16, 24, vertexDesc);
  409. auto vertIter = meshData->getVec2DataIter(VES_POSITION);
  410. auto colIter = meshData->getDWORDDataIter(VES_COLOR);
  411. // Top
  412. Vector2 topOffset((float)spacing, 0.0f);
  413. mTopDropPolygon[0] = outTopLeft + topOffset;
  414. mTopDropPolygon[1] = outTopRight + topOffset;
  415. mTopDropPolygon[2] = inTopRight + topOffset;
  416. mTopDropPolygon[3] = inTopLeft + topOffset;
  417. vertIter.addValue(mTopDropPolygon[0]);
  418. vertIter.addValue(mTopDropPolygon[1]);
  419. vertIter.addValue(mTopDropPolygon[2]);
  420. vertIter.addValue(mTopDropPolygon[3]);
  421. Color color(1.0f, 0.0f, 0.0f, 0.0f);
  422. UINT32 color32 = color.getAsRGBA();
  423. colIter.addValue(color32);
  424. colIter.addValue(color32);
  425. colIter.addValue(color32);
  426. colIter.addValue(color32);
  427. // Bottom
  428. Vector2 botOffset((float)spacing, (float)spacing * 2.0f);
  429. mBotDropPolygon[0] = inBotLeft + botOffset;
  430. mBotDropPolygon[1] = inBotRight + botOffset;
  431. mBotDropPolygon[2] = outBotRight + botOffset;
  432. mBotDropPolygon[3] = outBotLeft + botOffset;
  433. vertIter.addValue(mBotDropPolygon[0]);
  434. vertIter.addValue(mBotDropPolygon[1]);
  435. vertIter.addValue(mBotDropPolygon[2]);
  436. vertIter.addValue(mBotDropPolygon[3]);
  437. color = Color(0.0f, 1.0f, 0.0f, 0.0f);
  438. color32 = color.getAsRGBA();
  439. colIter.addValue(color32);
  440. colIter.addValue(color32);
  441. colIter.addValue(color32);
  442. colIter.addValue(color32);
  443. // Left
  444. Vector2 leftOffset(0.0f, (float)spacing);
  445. mLeftDropPolygon[0] = outTopLeft + leftOffset;
  446. mLeftDropPolygon[1] = inTopLeft + leftOffset;
  447. mLeftDropPolygon[2] = inBotLeft + leftOffset;
  448. mLeftDropPolygon[3] = outBotLeft + leftOffset;
  449. vertIter.addValue(mLeftDropPolygon[0]);
  450. vertIter.addValue(mLeftDropPolygon[1]);
  451. vertIter.addValue(mLeftDropPolygon[2]);
  452. vertIter.addValue(mLeftDropPolygon[3]);
  453. color = Color(0.0f, 0.0f, 1.0f, 0.0f);
  454. color32 = color.getAsRGBA();
  455. colIter.addValue(color32);
  456. colIter.addValue(color32);
  457. colIter.addValue(color32);
  458. colIter.addValue(color32);
  459. // Right
  460. Vector2 rightOffset((float)spacing * 2.0f, (float)spacing);
  461. mRightDropPolygon[0] = inTopRight + rightOffset;
  462. mRightDropPolygon[1] = outTopRight + rightOffset;
  463. mRightDropPolygon[2] = outBotRight + rightOffset;
  464. mRightDropPolygon[3] = inBotRight + rightOffset;
  465. vertIter.addValue(mRightDropPolygon[0]);
  466. vertIter.addValue(mRightDropPolygon[1]);
  467. vertIter.addValue(mRightDropPolygon[2]);
  468. vertIter.addValue(mRightDropPolygon[3]);
  469. color = Color(0.0f, 0.0f, 0.0f, 1.0f);
  470. color32 = color.getAsRGBA();
  471. colIter.addValue(color32);
  472. colIter.addValue(color32);
  473. colIter.addValue(color32);
  474. colIter.addValue(color32);
  475. UINT32* indexData = meshData->getIndices32();
  476. // Top
  477. indexData[0] = 0;
  478. indexData[1] = 1;
  479. indexData[2] = 2;
  480. indexData[3] = 0;
  481. indexData[4] = 2;
  482. indexData[5] = 3;
  483. // Bottom
  484. indexData[6] = 4;
  485. indexData[7] = 5;
  486. indexData[8] = 6;
  487. indexData[9] = 4;
  488. indexData[10] = 6;
  489. indexData[11] = 7;
  490. // Left
  491. indexData[12] = 8;
  492. indexData[13] = 9;
  493. indexData[14] = 10;
  494. indexData[15] = 8;
  495. indexData[16] = 10;
  496. indexData[17] = 11;
  497. // Right
  498. indexData[18] = 12;
  499. indexData[19] = 13;
  500. indexData[20] = 14;
  501. indexData[21] = 12;
  502. indexData[22] = 14;
  503. indexData[23] = 15;
  504. mDropOverlayMesh = Mesh::create(meshData);
  505. }
  506. bool DockManager::mouseEvent(const GUIMouseEvent& event)
  507. {
  508. if(event.getType() == GUIMouseEventType::MouseDragAndDropDragged)
  509. {
  510. if(DragAndDropManager::instance().getDragTypeId() != (UINT32)DragAndDropType::EditorWidget)
  511. return false;
  512. const Vector2I& widgetRelPos = event.getPosition();
  513. const Matrix4& worldTfrm = mParent->SO()->getWorldTfrm();
  514. Vector4 tfrmdPos = worldTfrm.multiply3x4(Vector4((float)widgetRelPos.x, (float)widgetRelPos.y, 0.0f, 1.0f));
  515. Vector2 windowPosVec(tfrmdPos.x, tfrmdPos.y);
  516. Vector2I windowPos(Math::roundToInt(windowPosVec.x), Math::roundToInt(windowPosVec.y));
  517. mMouseOverContainer = mRootContainer.findAtPos(windowPos);
  518. if(mMouseOverContainer == nullptr)
  519. mMouseOverContainer = &mRootContainer;
  520. RectI overlayBounds;
  521. if(mMouseOverContainer != nullptr)
  522. overlayBounds = mMouseOverContainer->getContentBounds();
  523. // Update mesh if needed
  524. if(mLastOverlayBounds != overlayBounds)
  525. {
  526. if(overlayBounds.width <= 0 || overlayBounds.height <= 0)
  527. mDropOverlayMesh = HMesh();
  528. else
  529. updateDropOverlay(overlayBounds.x, overlayBounds.y, overlayBounds.width, overlayBounds.height);
  530. mLastOverlayBounds = overlayBounds;
  531. }
  532. // Check if we need to highlight any drop locations
  533. if(mMouseOverContainer != nullptr)
  534. {
  535. if(insidePolygon(mTopDropPolygon, 4, windowPosVec))
  536. mHighlightedDropLoc = DockLocation::Top;
  537. else if(insidePolygon(mBotDropPolygon, 4, windowPosVec))
  538. mHighlightedDropLoc = DockLocation::Bottom;
  539. else if(insidePolygon(mLeftDropPolygon, 4, windowPosVec))
  540. mHighlightedDropLoc = DockLocation::Left;
  541. else if(insidePolygon(mRightDropPolygon, 4, windowPosVec))
  542. mHighlightedDropLoc = DockLocation::Right;
  543. else
  544. mHighlightedDropLoc = DockLocation::None;
  545. if(overlayBounds.contains(windowPos))
  546. mShowOverlay = true;
  547. else
  548. mShowOverlay = false;
  549. }
  550. else
  551. mShowOverlay = false;
  552. return true;
  553. }
  554. else if(event.getType() == GUIMouseEventType::MouseDragAndDropDropped)
  555. {
  556. if(DragAndDropManager::instance().getDragTypeId() != (UINT32)DragAndDropType::EditorWidget)
  557. return false;
  558. EditorWidget* draggedWidget = reinterpret_cast<EditorWidget*>(DragAndDropManager::instance().getDragData());
  559. const Vector2I& widgetRelPos = event.getPosition();
  560. const Matrix4& worldTfrm = mParent->SO()->getWorldTfrm();
  561. Vector4 tfrmdPos = worldTfrm.multiply3x4(Vector4((float)widgetRelPos.x, (float)widgetRelPos.y, 0.0f, 1.0f));
  562. Vector2 windowPosVec(tfrmdPos.x, tfrmdPos.y);
  563. Vector2I windowPos(Math::roundToInt(windowPosVec.x), Math::roundToInt(windowPosVec.y));
  564. DockContainer* mouseOverContainer = mRootContainer.findAtPos(windowPos);
  565. if(mouseOverContainer == nullptr)
  566. {
  567. RectI overlayBounds = mRootContainer.getContentBounds();
  568. if(overlayBounds.contains(windowPos))
  569. {
  570. insert(nullptr, draggedWidget, DockLocation::None);
  571. }
  572. }
  573. else
  574. {
  575. if(insidePolygon(mTopDropPolygon, 4, windowPosVec))
  576. insert(mouseOverContainer->mWidgets, draggedWidget, DockLocation::Top);
  577. else if(insidePolygon(mBotDropPolygon, 4, windowPosVec))
  578. insert(mouseOverContainer->mWidgets, draggedWidget, DockLocation::Bottom);
  579. else if(insidePolygon(mLeftDropPolygon, 4, windowPosVec))
  580. insert(mouseOverContainer->mWidgets, draggedWidget, DockLocation::Left);
  581. else if(insidePolygon(mRightDropPolygon, 4, windowPosVec))
  582. insert(mouseOverContainer->mWidgets, draggedWidget, DockLocation::Right);
  583. }
  584. return true;
  585. }
  586. return false;
  587. }
  588. // TODO - Move to a separate Polygon class?
  589. bool DockManager::insidePolygon(CM::Vector2* polyPoints, CM::UINT32 numPoints, CM::Vector2 point) const
  590. {
  591. bool isInside = false;
  592. for (UINT32 i = 0, j = numPoints - 1; i < numPoints; j = i++)
  593. {
  594. float lineVal = (polyPoints[j].x - polyPoints[i].x) * (point.y - polyPoints[i].y) / (polyPoints[j].y - polyPoints[i].y) + polyPoints[i].x;
  595. if (((polyPoints[i].y > point.y) != (polyPoints[j].y > point.y)) && (point.x < lineVal))
  596. isInside = !isInside;
  597. }
  598. return isInside;
  599. }
  600. }