1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "BsPrerequisites.h"
6#include "Math/BsRect2I.h"
7#include "Math/BsVector3.h"
8#include "Math/BsQuaternion.h"
9#include "Math/BsMatrix4.h"
10#include "Utility/BsEvent.h"
11
12namespace bs
13{
14 class GUINavGroup;
15
16 /** @addtogroup GUI
17 * @{
18 */
19
20 /**
21 * A top level container for all types of GUI elements. Every GUI element, layout or area must be assigned to a widget
22 * in order to be rendered.
23 *
24 * Widgets are the only GUI objects that may be arbitrarily transformed, allowing you to create 3D interfaces.
25 */
26 class BS_EXPORT GUIWidget
27 {
28 public:
29 virtual ~GUIWidget();
30
31 /** Sets the skin used for all GUI elements in the widget. This will update the look of all current elements. */
32 void setSkin(const HGUISkin& skin);
33
34 /** Returns the currently active GUI skin. */
35 const GUISkin& getSkin() const;
36
37 /** Returns the currently active GUI skin resource. */
38 const HGUISkin& getSkinResource() const { return mSkin; }
39
40 /** Returns the root GUI panel for the widget. */
41 GUIPanel* getPanel() const { return mPanel; }
42
43 /**
44 * Returns the depth to render the widget at. If two widgets overlap the widget with the lower depth will be
45 * rendered in front.
46 */
47 UINT8 getDepth() const { return mDepth; }
48
49 /**
50 * Changes the depth to render the widget at. If two widgets overlap the widget with the lower depth will be
51 * rendered in front.
52 */
53 void setDepth(UINT8 depth);
54
55 /**
56 * Checks are the specified coordinates within widget bounds. Coordinates should be relative to the parent window.
57 */
58 bool inBounds(const Vector2I& position) const;
59
60 /** Returns bounds of the widget, relative to the parent window. */
61 const Rect2I& getBounds() const { return mBounds; }
62
63 /**
64 * Return true if widget or any of its elements are dirty.
65 *
66 * @param[in] cleanIfDirty If true, all dirty elements will be updated and widget will be marked as clean.
67 * @return True if dirty, false if not. If "cleanIfDirty" is true, the returned state is the
68 * one before cleaning.
69 */
70 bool isDirty(bool cleanIfDirty);
71
72 /** Returns the viewport that this widget will be rendered on. */
73 Viewport* getTarget() const;
74
75 /** Returns the camera this widget is being rendered to. */
76 SPtr<Camera> getCamera() const { return mCamera; }
77
78 /** Changes to which camera does the widget output its contents. */
79 void setCamera(const SPtr<Camera>& camera);
80
81 /** Returns a list of all elements parented to this widget. */
82 const Vector<GUIElement*>& getElements() const { return mElements; }
83
84 /** Returns the world transform that all GUI elements beloning to this widget will be transformed by. */
85 const Matrix4 getWorldTfrm() const { return mTransform; }
86
87 /** Checks whether the widget should be rendered or not. */
88 bool getIsActive() const { return mIsActive; }
89
90 /** Sets whether the widget should be rendered or not. */
91 void setIsActive(bool active);
92
93 /** Creates a new GUI widget that will be rendered on the provided camera. */
94 static SPtr<GUIWidget> create(const SPtr<Camera>& camera);
95
96 /** Creates a new GUI widget that will be rendered on the provided camera. */
97 static SPtr<GUIWidget> create(const HCamera& camera);
98
99 /** Triggered when the widget's viewport size changes. */
100 Event<void()> onOwnerTargetResized;
101
102 /** Triggered when the parent window gained or lost focus. */
103 Event<void()> onOwnerWindowFocusChanged;
104
105 public: // ***** INTERNAL ******
106 /** @name Internal
107 * @{
108 */
109
110 /** Registers a new element as a child of the widget. */
111 void _registerElement(GUIElementBase* elem);
112
113 /**
114 * Unregisters an element from the widget. Usually called when the element is destroyed, or reparented to another
115 * widget.
116 */
117 void _unregisterElement(GUIElementBase* elem);
118
119 /**
120 * Returns the default navigation group assigned to all elements of this widget that don't have an explicit nav-
121 * group. See GUIElement::setNavGroup().
122 */
123 SPtr<GUINavGroup> _getDefaultNavGroup() const { return mDefaultNavGroup; }
124
125 /**
126 * Marks the widget mesh dirty requiring a mesh rebuild. Provided element is the one that requested the mesh update.
127 */
128 void _markMeshDirty(GUIElementBase* elem);
129
130 /**
131 * Marks the elements content as dirty, meaning its internal mesh will need to be rebuilt (this implies the entire
132 * widget mesh will be rebuilt as well).
133 */
134 void _markContentDirty(GUIElementBase* elem);
135
136 /** Updates the layout of all child elements, repositioning and resizing them as needed. */
137 void _updateLayout();
138
139 /** Updates the layout of the provided element, and queues content updates. */
140 void _updateLayout(GUIElementBase* elem);
141
142 /**
143 * Updates internal transform values from the specified scene object, in case that scene object's transform changed
144 * since the last call.
145 *
146 * @note Assumes the same scene object will be provided every time.
147 */
148 void _updateTransform(const HSceneObject& parent);
149
150 /**
151 * Checks if the render target of the destination camera changed, and updates the widget with new information if
152 * it has. Should be called every frame.
153 */
154 void _updateRT();
155
156 /** Destroys the GUI widget and all child GUI elements. This is called automatically when GUIWidget is deleted. */
157 void _destroy();
158
159 /** @} */
160
161 protected:
162 friend class SceneObject;
163 friend class GUIElementBase;
164 friend class GUIManager;
165 friend class CGUIWidget;
166
167 /** Constructs a new GUI widget that will be rendered on the provided camera. */
168 GUIWidget(const SPtr<Camera>& camera);
169
170 /** Constructs a new GUI widget that will be rendered on the provided camera. */
171 GUIWidget(const HCamera& camera);
172
173 /** Common code for constructors. */
174 void construct(const SPtr<Camera>& camera);
175
176 /** Called when the parent window gained or lost focus. */
177 virtual void ownerWindowFocusChanged();
178 private:
179 /** Calculates widget bounds using the bounds of all child elements. */
180 void updateBounds() const;
181
182 /** Updates the size of the primary GUI panel based on the viewport. */
183 void updateRootPanel();
184
185 SPtr<Camera> mCamera;
186 Vector<GUIElement*> mElements;
187 GUIPanel* mPanel;
188 UINT8 mDepth;
189 bool mIsActive;
190 SPtr<GUINavGroup> mDefaultNavGroup;
191
192 Vector3 mPosition;
193 Quaternion mRotation;
194 Vector3 mScale;
195 Matrix4 mTransform;
196
197 Set<GUIElement*> mDirtyContents;
198 Set<GUIElement*> mDirtyContentsTemp;
199
200 mutable UINT64 mCachedRTId;
201 mutable bool mWidgetIsDirty;
202 mutable Rect2I mBounds;
203
204 HGUISkin mSkin;
205 };
206
207 /** @} */
208}