BsDockManager.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsEditorPrerequisites.h"
  5. #include "Renderer/BsRendererExtension.h"
  6. #include "GUI/BsGUIElementContainer.h"
  7. #include "Math/BsRect2I.h"
  8. namespace bs
  9. {
  10. /** @addtogroup EditorWindow-Internal
  11. * @{
  12. */
  13. namespace ct { class DockOverlayRenderer; }
  14. /**
  15. * GUI element that allows editor widgets to be docked in it using arbitrary layouts. Docked widgets can be resized,
  16. * undocked, maximizes or closed as needed.
  17. */
  18. class DockManager : public GUIElementContainer
  19. {
  20. public:
  21. /**
  22. * Contains information about a single dock area. Each container can be a parent to two other containers or may
  23. * contain a widget, which results in a container hierarchy. Two children can be split vertically or horizontally
  24. * at an user-defined point.
  25. */
  26. class DockContainer
  27. {
  28. public:
  29. DockContainer(DockManager* manager);
  30. DockContainer(DockManager* manager, DockContainer* parent);
  31. ~DockContainer();
  32. /** Determines the position and size of the container, relative to the parent dock manager. */
  33. void setArea(INT32 x, INT32 y, UINT32 width, UINT32 height);
  34. /**
  35. * Transforms the container from non-leaf (parent to other containers) to leaf (parent to widgets). This
  36. * involves creating a widget container to which you can dock widgets to.
  37. *
  38. * @param[in] parentWindow Editor window of the parent dock manager.
  39. */
  40. void makeLeaf(EditorWindowBase* parentWindow);
  41. /**
  42. * Transforms the container from non-leaf (parent to other containers) to leaf (parent to widgets). Unlike the
  43. * other overload this one accepts a previously created widget container.
  44. *
  45. * @param[in] guiWidgetSO Parent SceneObject of the GUIWidget used by the provided widget container.
  46. * @param[in] existingContainer An existing widget container that may be used for docking widgets.
  47. */
  48. void makeLeaf(const HSceneObject& guiWidgetSO, EditorWidgetContainer* existingContainer);
  49. /**
  50. * Splits a leaf container containing a widget container (or may be empty in the case of root with no elements)
  51. * into a container parent to two other containers.
  52. *
  53. * @param[in] horizontal Whether the split is horizontal (true) or vertical (false.
  54. * @param[in] newChildIsFirst Determines to which child should the widget container from this object be
  55. * moved to. If the new child is first, then bottom or right (for horizontal
  56. * and vertical respectively) will receive the current widget container, and
  57. * opposite if it's not first.
  58. * @param[in] splitPosition Determines at what position(in percent) should this container be split. User
  59. * can modify this later via a dock slider.
  60. */
  61. void splitContainer(bool horizontal, bool newChildIsFirst, float splitPosition = 0.5f);
  62. /**
  63. * Splits a leaf container containing a widget container (or may be empty in the case of root with no elements)
  64. * into a container parent to two other containers. Unlike "splitContainer" new containers aren't created
  65. * automatically but you must provide existing ones. If this container is non-leaf its widget container will be
  66. * destroyed.
  67. *
  68. * @param[in] first Container to insert into the first child slot (left if vertical split, top if
  69. * horizontal split).
  70. * @param[in] second Container to insert into the second child slot (right if vertical split, bottom
  71. * if horizontal split).
  72. * @param[in] horizontal Whether the split is horizontal (true) or vertical (false.
  73. * @param[in] splitPosition Determines at what position(in percent) should this container be split. User can
  74. * modify this later via a dock slider.
  75. */
  76. void makeSplit(DockContainer* first, DockContainer* second, bool horizontal, float splitPosition);
  77. /**
  78. * Adds a new widget to the left side of the container. If the container is leaf it will be split into two
  79. * containers vertically.
  80. */
  81. void addLeft(EditorWidgetBase* widget);
  82. /**
  83. * Adds a new widget to the right side of the container. If the container is leaf it will be split into two
  84. * containers vertically.
  85. */
  86. void addRight(EditorWidgetBase* widget);
  87. /**
  88. * Adds a new widget to the top side of the container. If the container is leaf it will be split into two
  89. * containers horizontally.
  90. */
  91. void addTop(EditorWidgetBase* widget);
  92. /**
  93. * Adds a new widget to the bottom side of the container. If the container is leaf it will be split into two
  94. * containers horizontally.
  95. */
  96. void addBottom(EditorWidgetBase* widget);
  97. /** Adds an existing widget to this leaf container. */
  98. void addWidget(EditorWidgetBase* widget);
  99. /** Attempts to find a widget with the specified name, opens it and adds it to this leaf container. */
  100. void addWidget(const String& name);
  101. /** Update to be called once per frame. Calls updates on all child widgets. */
  102. void update();
  103. /**
  104. * Attempts to find an existing leaf dock container with the specified widget container. Returns null if one
  105. * cannot be found.
  106. */
  107. DockContainer* find(EditorWidgetContainer* widgetContainer);
  108. /**
  109. * Searches for a container at the specified position. Call this at this top-most container in order to search
  110. * them all.
  111. *
  112. * @param[in] pos Position is relative to the container area.
  113. * @return null if it fails, else the found DockContainer at position.
  114. */
  115. DockContainer* findAtPos(const Vector2I& pos);
  116. /** Returns the bounds of the container that are to be considered dockable and interactable. */
  117. Rect2I getContentBounds() const;
  118. bool mIsLeaf;
  119. DockContainer* mChildren[2];
  120. DockContainer* mParent;
  121. DockManager* mManager;
  122. EditorWidgetContainer* mWidgets;
  123. HSceneObject mGUIWidgetSO;
  124. GUIDockSlider* mSlider;
  125. Rect2I mArea;
  126. float mSplitPosition;
  127. bool mIsHorizontal;
  128. static const UINT32 SLIDER_SIZE;
  129. static const UINT32 MIN_CHILD_SIZE;
  130. private:
  131. /** Updates sizes and positions of all child containers. Normally called when parent area changes. */
  132. void updateChildAreas();
  133. /** Triggered whenever the user drags the GUI slider belonging to this container. */
  134. void sliderDragged(const Vector2I& delta);
  135. /** Triggered whenever the user closes or undocks a widget belonging to this container. */
  136. void widgetRemoved();
  137. /** Triggered when the maximize button in the container's title bar is clicked. */
  138. void maximizeClicked();
  139. };
  140. /** Available dock locations for the dock manager. */
  141. enum class DockLocation
  142. {
  143. Top,
  144. Bottom,
  145. Left,
  146. Right,
  147. None
  148. };
  149. public:
  150. /** Creates a new dock manager for the specified window. */
  151. static DockManager* create(EditorWindowBase* parentWindow);
  152. /** Internal method. Called once every frame. */
  153. void update();
  154. /**
  155. * Inserts a new widget at the specified location.
  156. *
  157. * @param[in] relativeTo Container relative to which to insert the widget. Can be null in which case the
  158. * widget is inserted at the root.
  159. * @param[in] widgetToInsert Widget we want to insert into the dock layout.
  160. * @param[in] location Location to insert the widget at, relative to @p relativeTo container.
  161. * If @p relativeTo is null this is ignored.
  162. */
  163. void insert(EditorWidgetContainer* relativeTo, EditorWidgetBase* widgetToInsert, DockLocation location);
  164. /** Returns a saved layout of all the currently docked widgets and their positions and areas. */
  165. SPtr<DockManagerLayout> getLayout() const;
  166. /**
  167. * Sets a previously saved layout of docked widgets. This will close all currently active widgets and open and
  168. * position new ones according to the layout.
  169. */
  170. void setLayout(const SPtr<DockManagerLayout>& layout);
  171. /** Changes the position and size of the dock manager. */
  172. void setArea(INT32 x, INT32 y, UINT32 width, UINT32 height);
  173. /** Closes all docked widgets. */
  174. void closeAll();
  175. private:
  176. DockManager(EditorWindowBase* parentWindow, const GUIDimensions& dimensions);
  177. ~DockManager();
  178. /** Updates the dock overlay mesh that is displayed when user is dragging a widget over a certain area. */
  179. void updateDropOverlay(INT32 x, INT32 y, UINT32 width, UINT32 height);
  180. /**
  181. * Checks is the provided point inside the provided polygon.
  182. *
  183. * @param[i] polyPoints Points of the polygon to test against.
  184. * @param[i] numPoints Number of points in "polyPoints".
  185. * @param[i] point Point to check if it's in the polygon.
  186. * @return True if the point is in the polygon.
  187. */
  188. bool insidePolygon(Vector2* polyPoints, UINT32 numPoints, Vector2 point) const;
  189. /** @copydoc GUIElementBase::updateClippedBounds */
  190. void updateClippedBounds() override;
  191. /**
  192. * Maximizes or restored the specified container. If any container is previously maximized it needs to be toggled
  193. * back to restored state before maximizing another.
  194. */
  195. void toggleMaximize(DockContainer* container);
  196. /** @copydoc GUIElementBase::_mouseEvent */
  197. bool _mouseEvent(const GUIMouseEvent& event) override;
  198. SPtr<ct::DockOverlayRenderer> mRenderer;
  199. EditorWindowBase* mParentWindow;
  200. DockContainer mRootContainer;
  201. Rect2I mArea;
  202. HMesh mDropOverlayMesh;
  203. Rect2I mLastOverlayBounds;
  204. bool mIsMaximized;
  205. DockContainer* mMaximizedContainer;
  206. SPtr<DockManagerLayout> mRestoredLayout;
  207. DockContainer* mMouseOverContainer;
  208. DockLocation mHighlightedDropLoc;
  209. bool mShowOverlay;
  210. Vector2* mTopDropPolygon;
  211. Vector2* mBotDropPolygon;
  212. Vector2* mLeftDropPolygon;
  213. Vector2* mRightDropPolygon;
  214. };
  215. namespace ct
  216. {
  217. /** Handles rendering of the dock overlay on the core thread. */
  218. class DockOverlayRenderer : public RendererExtension
  219. {
  220. public:
  221. DockOverlayRenderer();
  222. private:
  223. friend class bs::DockManager;
  224. /** @copydoc RendererExtension::initialize */
  225. void initialize(const Any& data) override;
  226. /** @copydoc RendererExtension::check */
  227. RendererExtensionRequest check(const Camera& camera) override;
  228. /** @copydoc RendererExtension::render */
  229. void render(const Camera& camera, const RendererViewContext& viewContext) override;
  230. /**
  231. * Updates the grid mesh to render.
  232. *
  233. * @param[in] camera Camera to render the dock overlay to.
  234. * @param[in] mesh Overlay mesh to render.
  235. * @param[in] active Should the overlay be shown or not.
  236. * @param[in] location Highlighted location of the overlay.
  237. */
  238. void updateData(const SPtr<Camera>& camera, const SPtr<Mesh>& mesh, bool active,
  239. DockManager::DockLocation location);
  240. SPtr<Camera> mCamera;
  241. SPtr<Material> mMaterial;
  242. SPtr<GpuParamsSet> mParams;
  243. SPtr<Mesh> mMesh;
  244. DockManager::DockLocation mHighlightedDropLoc;
  245. bool mShowOverlay;
  246. static const Color TINT_COLOR;
  247. static const Color HIGHLIGHT_COLOR;
  248. };
  249. }
  250. /** @} */
  251. }