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 | |
12 | namespace 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 | } |