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#include "GUI/BsGUILabel.h"
4#include "GUI/BsGUIElementStyle.h"
5#include "2D/BsTextSprite.h"
6#include "Image/BsSpriteTexture.h"
7#include "GUI/BsGUIDimensions.h"
8#include "GUI/BsGUIHelper.h"
9
10namespace bs
11{
12 GUILabel::GUILabel(const String& styleName, const GUIContent& content, const GUIDimensions& dimensions)
13 :GUIElement(styleName, dimensions), mContent(content), mImageSprite(nullptr)
14 {
15 mTextSprite = bs_new<TextSprite>();
16 }
17
18 GUILabel::~GUILabel()
19 {
20 bs_delete(mTextSprite);
21
22 if (mImageSprite != nullptr)
23 bs_delete(mImageSprite);
24 }
25
26 UINT32 GUILabel::_getNumRenderElements() const
27 {
28 UINT32 numElements = mTextSprite->getNumRenderElements();
29
30 if(mImageSprite != nullptr)
31 numElements += mImageSprite->getNumRenderElements();
32
33 return numElements;
34 }
35
36 const SpriteMaterialInfo& GUILabel::_getMaterial(UINT32 renderElementIdx, SpriteMaterial** material) const
37 {
38 UINT32 imageSpriteIdx = mTextSprite->getNumRenderElements();
39
40 if(renderElementIdx >= imageSpriteIdx)
41 {
42 *material = mImageSprite->getMaterial(imageSpriteIdx - renderElementIdx);
43 return mImageSprite->getMaterialInfo(imageSpriteIdx - renderElementIdx);
44 }
45 else
46 {
47 *material = mTextSprite->getMaterial(renderElementIdx);
48 return mTextSprite->getMaterialInfo(renderElementIdx);
49 }
50 }
51
52 void GUILabel::_getMeshInfo(UINT32 renderElementIdx, UINT32& numVertices, UINT32& numIndices, GUIMeshType& type) const
53 {
54 UINT32 imageSpriteIdx = mTextSprite->getNumRenderElements();
55
56 UINT32 numQuads;
57 if (renderElementIdx >= imageSpriteIdx)
58 numQuads = mImageSprite->getNumQuads(imageSpriteIdx - renderElementIdx);
59 else
60 numQuads = mTextSprite->getNumQuads(renderElementIdx);
61
62 numVertices = numQuads * 4;
63 numIndices = numQuads * 6;
64 type = GUIMeshType::Triangle;
65 }
66
67 UINT32 GUILabel::_getRenderElementDepth(UINT32 renderElementIdx) const
68 {
69 UINT32 imageSpriteIdx = mTextSprite->getNumRenderElements();
70
71 if (renderElementIdx >= imageSpriteIdx)
72 return _getDepth() + 1;
73 else
74 return _getDepth();
75 }
76
77 UINT32 GUILabel::_getRenderElementDepthRange() const
78 {
79 return 2;
80 }
81
82 void GUILabel::updateRenderElementsInternal()
83 {
84 const HSpriteTexture& activeTex = _getStyle()->normal.texture;
85 if (SpriteTexture::checkIsLoaded(activeTex))
86 {
87 mImageDesc.texture = activeTex;
88
89 if (mImageSprite == nullptr)
90 mImageSprite = bs_new<ImageSprite>();
91 }
92 else
93 {
94 mImageDesc.texture = nullptr;
95
96 if (mImageSprite != nullptr)
97 {
98 bs_delete(mImageSprite);
99 mImageSprite = nullptr;
100 }
101 }
102
103 if (mImageSprite != nullptr)
104 {
105 mImageDesc.width = mLayoutData.area.width;
106 mImageDesc.height = mLayoutData.area.height;
107
108 mImageDesc.borderLeft = _getStyle()->border.left;
109 mImageDesc.borderRight = _getStyle()->border.right;
110 mImageDesc.borderTop = _getStyle()->border.top;
111 mImageDesc.borderBottom = _getStyle()->border.bottom;
112 mImageDesc.color = getTint();
113
114 mImageSprite->update(mImageDesc, (UINT64)_getParentWidget());
115 }
116
117 mDesc.font = _getStyle()->font;
118 mDesc.fontSize = _getStyle()->fontSize;
119 mDesc.wordWrap = _getStyle()->wordWrap;
120 mDesc.horzAlign = _getStyle()->textHorzAlign;
121 mDesc.vertAlign = _getStyle()->textVertAlign;
122 mDesc.width = mLayoutData.area.width;
123 mDesc.height = mLayoutData.area.height;
124 mDesc.text = mContent.text;
125 mDesc.color = getTint() * _getStyle()->normal.textColor;;
126
127 mTextSprite->update(mDesc, (UINT64)_getParentWidget());
128
129 GUIElement::updateRenderElementsInternal();
130 }
131
132 Vector2I GUILabel::_getOptimalSize() const
133 {
134 return GUIHelper::calcOptimalContentsSize(mContent, *_getStyle(), _getDimensions());
135 }
136
137 void GUILabel::_fillBuffer(UINT8* vertices, UINT32* indices, UINT32 vertexOffset, UINT32 indexOffset,
138 UINT32 maxNumVerts, UINT32 maxNumIndices, UINT32 renderElementIdx) const
139 {
140 UINT8* uvs = vertices + sizeof(Vector2);
141 UINT32 vertexStride = sizeof(Vector2) * 2;
142 UINT32 indexStride = sizeof(UINT32);
143 Vector2I offset(mLayoutData.area.x, mLayoutData.area.y);
144
145 UINT32 imageSpriteIdx = mTextSprite->getNumRenderElements();
146
147 if (renderElementIdx < imageSpriteIdx)
148 {
149 mTextSprite->fillBuffer(vertices, uvs, indices, vertexOffset, indexOffset, maxNumVerts, maxNumIndices, vertexStride,
150 indexStride, renderElementIdx, offset, mLayoutData.getLocalClipRect());
151
152 return;
153 }
154
155 mImageSprite->fillBuffer(vertices, uvs, indices, vertexOffset, indexOffset, maxNumVerts, maxNumIndices,
156 vertexStride, indexStride, imageSpriteIdx - renderElementIdx, offset, mLayoutData.getLocalClipRect());
157 }
158
159 void GUILabel::setContent(const GUIContent& content)
160 {
161 Vector2I origSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
162 mContent = content;
163 Vector2I newSize = mDimensions.calculateSizeRange(_getOptimalSize()).optimal;
164
165 if (origSize != newSize)
166 _markLayoutAsDirty();
167 else
168 _markContentAsDirty();
169 }
170
171 GUILabel* GUILabel::create(const HString& text, const String& styleName)
172 {
173 return create(GUIContent(text), styleName);
174 }
175
176 GUILabel* GUILabel::create(const HString& text, const GUIOptions& options, const String& styleName)
177 {
178 return create(GUIContent(text), options, styleName);
179 }
180
181 GUILabel* GUILabel::create(const GUIContent& content, const String& styleName)
182 {
183 return new (bs_alloc<GUILabel>()) GUILabel(getStyleName<GUILabel>(styleName), content, GUIDimensions::create());
184 }
185
186 GUILabel* GUILabel::create(const GUIContent& content, const GUIOptions& options, const String& styleName)
187 {
188 return new (bs_alloc<GUILabel>()) GUILabel(getStyleName<GUILabel>(styleName), content, GUIDimensions::create(options));
189 }
190
191 const String& GUILabel::getGUITypeName()
192 {
193 static String typeName = "Label";
194 return typeName;
195 }
196}