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 "GUI/BsGUIElement.h"
7#include "2D/BsImageSprite.h"
8#include "2D/BsTextSprite.h"
9
10namespace bs
11{
12 /** @addtogroup GUI
13 * @{
14 */
15
16 /**
17 * A GUI element that allows the user to draw custom graphics. All drawn elements relative to the canvas, to its origin
18 * in the top left corner.
19 */
20 class BS_EXPORT GUICanvas : public GUIElement
21 {
22 public:
23 /** Returns type name of the GUI element used for finding GUI element styles. */
24 static const String& getGUITypeName();
25
26 /**
27 * Creates a new GUI canvas element.
28 *
29 * @param[in] options Options that allow you to control how is the element positioned and sized. This will
30 * override any similar options set by style.
31 * @param[in] styleName Optional style to use for the element. Style will be retrieved from GUISkin of the
32 * GUIWidget the element is used on. If not specified default style is used.
33 */
34 static GUICanvas* create(const GUIOptions& options, const String& styleName = StringUtil::BLANK);
35
36 /**
37 * Creates a new GUI canvas element.
38 *
39 * @param[in] styleName Optional style to use for the element. Style will be retrieved from GUISkin of the
40 * GUIWidget the element is used on. If not specified default style is used.
41 */
42 static GUICanvas* create(const String& styleName = StringUtil::BLANK);
43
44 /**
45 * Draws a line going from @p a to @p b.
46 *
47 * @param[in] a Starting point of the line, relative to the canvas origin (top-left).
48 * @param[in] b Ending point of the line, relative to the canvas origin (top-left).
49 * @param[in] color Color of the line.
50 * @param[in] depth Depth at which to draw the element. Elements with higher depth will be drawn before others.
51 * Additionally elements of the same type (triangle or line) will be drawn in order they are
52 * submitted if they share the same depth.
53 */
54 void drawLine(const Vector2I& a, const Vector2I& b, const Color& color = Color::White, UINT8 depth = 128);
55
56 /**
57 * Draws multiple lines following the path by the provided vertices. First vertex connects to the second vertex,
58 * and every following vertex connects to the previous vertex.
59 *
60 * @param[in] vertices Points to use for drawing the line. Must have at least two elements. All points are
61 * relative to the canvas origin (top-left).
62 * @param[in] color Color of the line.
63 * @param[in] depth Depth at which to draw the element. Elements with higher depth will be drawn before
64 * others. Additionally elements of the same type (triangle or line) will be drawn in order
65 * they are submitted if they share the same depth.
66 */
67 void drawPolyLine(const Vector<Vector2I>& vertices, const Color& color = Color::White, UINT8 depth = 128);
68
69 /**
70 * Draws a quad with a the provided texture displayed.
71 *
72 * @param[in] texture Texture to draw.
73 * @param[in] area Position and size of the texture to draw. Position is relative to the canvas origin
74 * (top-left). If size is zero, the default texture size will be used.
75 * @param[in] scaleMode Scale mode to use when sizing the texture. Only relevant if the provided quad size
76 * doesn't match the texture size.
77 * @param[in] color Color to tint the drawn texture with.
78 * @param[in] depth Depth at which to draw the element. Elements with higher depth will be drawn before
79 * others. Additionally elements of the same type (triangle or line) will be drawn in order
80 * they are submitted if they share the same depth.
81 */
82 void drawTexture(const HSpriteTexture& texture, const Rect2I& area,
83 TextureScaleMode scaleMode = TextureScaleMode::StretchToFit, const Color& color = Color::White, UINT8 depth = 128);
84
85 /**
86 * Draws a triangle strip. First three vertices are used to form the initial triangle, and every next vertex will
87 * form a triangle with the previous two.
88 *
89 * @param[in] vertices A set of points defining the triangles. Must have at least three elements. All points
90 * are relative to the canvas origin (top-left).
91 * @param[in] color Color of the triangles.
92 * @param[in] depth Depth at which to draw the element. Elements with higher depth will be drawn before
93 * others. Additionally elements of the same type (triangle or line) will be drawn in order
94 * they are submitted if they share the same depth.
95 */
96 void drawTriangleStrip(const Vector<Vector2I>& vertices, const Color& color = Color::White, UINT8 depth = 128);
97
98 /**
99 * Draws a triangle list. Every three vertices in the list represent a unique triangle.
100 *
101 * @param[in] vertices A set of points defining the triangles. Must have at least three elements, and its size
102 * must be a multiple of three.
103 * @param[in] color Color of the triangles.
104 * @param[in] depth Depth at which to draw the element. Elements with higher depth will be drawn before
105 * others. Additionally elements of the same type (triangle or line) will be drawn in order
106 * they are submitted if they share the same depth.
107 */
108 void drawTriangleList(const Vector<Vector2I>& vertices, const Color& color = Color::White, UINT8 depth = 128);
109
110 /**
111 * Draws a piece of text with the wanted font. The text will be aligned to the top-left corner of the provided
112 * position, and will not be word wrapped.
113 *
114 * @param[in] text Text to draw.
115 * @param[in] position Position of the text to draw. This represents the top-left corner of the text. It is
116 * relative to the canvas origin (top-left).
117 * @param[in] font Font to draw the text with.
118 * @param[in] size Size of the font.
119 * @param[in] color Color of the text.
120 * @param[in] depth Depth at which to draw the element. Elements with higher depth will be drawn before
121 * others. Additionally elements of the same type (triangle or line) will be drawn in order
122 * they are submitted if they share the same depth.
123 */
124 void drawText(const String& text, const Vector2I& position, const HFont& font, UINT32 size = 10,
125 const Color& color = Color::White, UINT8 depth = 128);
126
127 /** Clears the canvas, removing any previously drawn elements. */
128 void clear();
129
130 public: // ***** INTERNAL ******
131 /** @name Internal
132 * @{
133 */
134
135 /** @copydoc GUIElement::_getOptimalSize */
136 Vector2I _getOptimalSize() const override;
137
138 /** @copydoc GUIElement::_getRenderElementDepthRange */
139 UINT32 _getRenderElementDepthRange() const override { return mDepthRange; }
140
141 /** @} */
142 protected:
143 /** Type of elements that may be drawn on the canvas. */
144 enum class CanvasElementType
145 {
146 Line,
147 Triangle,
148 Image,
149 Text
150 };
151
152 /** Represents a single element drawn by the canvas. */
153 struct CanvasElement
154 {
155 CanvasElementType type;
156 Color color;
157 UINT32 renderElemStart;
158 UINT32 renderElemEnd;
159 UINT32 dataId;
160 UINT8 depth;
161
162 union
163 {
164 struct
165 {
166 UINT32 vertexStart;
167 UINT32 numVertices;
168 mutable UINT32 clippedVertexStart;
169 mutable UINT32 clippedNumVertices;
170 };
171
172 struct
173 {
174 ImageSprite* imageSprite;
175 TextureScaleMode scaleMode;
176 };
177
178 struct
179 {
180 TextSprite* textSprite;
181 UINT32 size;
182 };
183 };
184 };
185
186 /** Information required for drawing a text canvas element. */
187 struct TextElementData
188 {
189 String string;
190 HFont font;
191 Vector2I position;
192 };
193
194 /** Information required for drawing an image canvas element. */
195 struct ImageElementData
196 {
197 HSpriteTexture texture;
198 Rect2I area;
199 };
200
201 /** Information required for drawing an arbitrary triangle canvas element. */
202 struct TriangleElementData
203 {
204 SpriteMaterialInfo matInfo;
205 };
206
207 GUICanvas(const String& styleName, const GUIDimensions& dimensions);
208 virtual ~GUICanvas();
209
210 /** @copydoc GUIElement::_getNumRenderElements */
211 UINT32 _getNumRenderElements() const override;
212
213 /** @copydoc GUIElement::_getMaterial */
214 const SpriteMaterialInfo& _getMaterial(UINT32 renderElementIdx, SpriteMaterial** material) const override;
215
216 /** @copydoc GUIElement::_getMeshInfo() */
217 void _getMeshInfo(UINT32 renderElementIdx, UINT32& numVertices, UINT32& numIndices, GUIMeshType& type) const override;
218
219 /** @copydoc GUIElement::_fillBuffer */
220 void _fillBuffer(UINT8* vertices, UINT32* indices, UINT32 vertexOffset, UINT32 indexOffset,
221 UINT32 maxNumVerts, UINT32 maxNumIndices, UINT32 renderElementIdx) const override;
222
223 /** @copydoc GUIElement::_getRenderElementDepth */
224 UINT32 _getRenderElementDepth(UINT32 renderElementIdx) const override;
225
226 /** @copydoc GUIElement::updateRenderElementsInternal */
227 void updateRenderElementsInternal() override;
228
229 /** Build an image sprite from the provided canvas element. */
230 void buildImageElement(const CanvasElement& element);
231
232 /** Build a text sprite from the provided canvas element. */
233 void buildTextElement(const CanvasElement& element);
234
235 /** Build a set of clipped triangles from the source triangles provided by the canvas element. */
236 void buildTriangleElement(const CanvasElement& element, const Vector2& offset, const Rect2I& clipRect) const;
237
238 /**
239 * Rebuilds all triangle elements on the canvas, by constructing a set of clipped and offset triangles from the
240 * triangles provided by the canvas elements.
241 */
242 void buildAllTriangleElementsIfDirty(const Vector2& offset, const Rect2I& clipRect) const;
243
244 /** Finds the canvas element that contains the render element with the specified index. */
245 const CanvasElement& findElement(UINT32 renderElementIdx) const;
246
247 Vector<CanvasElement> mElements;
248 UINT32 mNumRenderElements;
249 UINT8 mDepthRange;
250
251 Vector<ImageElementData> mImageData;
252 Vector<TextElementData> mTextData;
253 mutable Vector<TriangleElementData> mTriangleElementData;
254 Vector<Vector2> mVertexData;
255
256 mutable Vector<Vector2> mClippedVertices;
257 mutable Vector<Vector2> mClippedLineVertices;
258 mutable Vector2 mLastOffset;
259 mutable Rect2I mLastClipRect;
260 mutable bool mForceTriangleBuild;
261
262 static const float LINE_SMOOTH_BORDER_WIDTH;
263 };
264
265 /** @} */
266}