1 /*
2  * This source file is part of MyGUI. For the latest info, see http://mygui.info/
3  * Distributed under the MIT License
4  * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
5  */
6 
7 #include "MyGUI_Precompiled.h"
8 #include "MyGUI_SubSkin.h"
9 #include "MyGUI_RenderItem.h"
10 #include "MyGUI_SkinManager.h"
11 #include "MyGUI_LanguageManager.h"
12 #include "MyGUI_LayerNode.h"
13 #include "MyGUI_CommonStateInfo.h"
14 #include "MyGUI_RenderManager.h"
15 #include "MyGUI_TextureUtility.h"
16 
17 namespace MyGUI
18 {
19 
SubSkin()20 	SubSkin::SubSkin() :
21 		ISubWidgetRect(),
22 		mEmptyView(false),
23 		mCurrentColour(0xFFFFFFFF),
24 		mNode(nullptr),
25 		mRenderItem(nullptr),
26 		mSeparate(false)
27 	{
28 		mVertexFormat = RenderManager::getInstance().getVertexFormat();
29 	}
30 
setVisible(bool _visible)31 	void SubSkin::setVisible(bool _visible)
32 	{
33 		if (mVisible == _visible)
34 			return;
35 		mVisible = _visible;
36 
37 		if (nullptr != mNode)
38 			mNode->outOfDate(mRenderItem);
39 	}
40 
setAlpha(float _alpha)41 	void SubSkin::setAlpha(float _alpha)
42 	{
43 		uint32 alpha = ((uint8)(_alpha * 255) << 24);
44 		mCurrentColour = (mCurrentColour & 0x00FFFFFF) | (alpha & 0xFF000000);
45 
46 		if (nullptr != mNode)
47 			mNode->outOfDate(mRenderItem);
48 	}
49 
_correctView()50 	void SubSkin::_correctView()
51 	{
52 		if (nullptr != mNode)
53 			mNode->outOfDate(mRenderItem);
54 	}
55 
_setAlign(const IntSize & _oldsize)56 	void SubSkin::_setAlign(const IntSize& _oldsize)
57 	{
58 		// необходимо разобраться
59 		bool need_update = true;//_update;
60 
61 		// первоначальное выравнивание
62 		if (mAlign.isHStretch())
63 		{
64 			// растягиваем
65 			mCoord.width = mCoord.width + (mCroppedParent->getWidth() - _oldsize.width);
66 			need_update = true;
67 			mIsMargin = true; // при изменении размеров все пересчитывать
68 		}
69 		else if (mAlign.isRight())
70 		{
71 			// двигаем по правому краю
72 			mCoord.left = mCoord.left + (mCroppedParent->getWidth() - _oldsize.width);
73 			need_update = true;
74 		}
75 		else if (mAlign.isHCenter())
76 		{
77 			// выравнивание по горизонтали без растяжения
78 			mCoord.left = (mCroppedParent->getWidth() - mCoord.width) / 2;
79 			need_update = true;
80 		}
81 
82 		if (mAlign.isVStretch())
83 		{
84 			// растягиваем
85 			mCoord.height = mCoord.height + (mCroppedParent->getHeight() - _oldsize.height);
86 			need_update = true;
87 			mIsMargin = true; // при изменении размеров все пересчитывать
88 		}
89 		else if (mAlign.isBottom())
90 		{
91 			// двигаем по нижнему краю
92 			mCoord.top = mCoord.top + (mCroppedParent->getHeight() - _oldsize.height);
93 			need_update = true;
94 		}
95 		else if (mAlign.isVCenter())
96 		{
97 			// выравнивание по вертикали без растяжения
98 			mCoord.top = (mCroppedParent->getHeight() - mCoord.height) / 2;
99 			need_update = true;
100 		}
101 
102 		if (need_update)
103 		{
104 			mCurrentCoord = mCoord;
105 			_updateView();
106 		}
107 	}
108 
_updateView()109 	void SubSkin::_updateView()
110 	{
111 		//mAbsolutePosition = mCroppedParent->getAbsolutePosition() + mCoord.point();
112 		bool margin = _checkMargin();
113 
114 		mEmptyView = ((0 >= _getViewWidth()) || (0 >= _getViewHeight()));
115 
116 		mCurrentCoord.left = mCoord.left + mMargin.left;
117 		mCurrentCoord.top = mCoord.top + mMargin.top;
118 
119 		// вьюпорт стал битым
120 		if (margin)
121 		{
122 			// проверка на полный выход за границу
123 			if (_checkOutside())
124 			{
125 				// запоминаем текущее состояние
126 				mIsMargin = margin;
127 
128 				// обновить перед выходом
129 				if (nullptr != mNode)
130 					mNode->outOfDate(mRenderItem);
131 				return;
132 			}
133 		}
134 
135 		// мы обрезаны или были обрезаны
136 		if (mIsMargin || margin)
137 		{
138 			mCurrentCoord.width = _getViewWidth();
139 			mCurrentCoord.height = _getViewHeight();
140 
141 			if ((mCurrentCoord.width > 0) && (mCurrentCoord.height > 0))
142 			{
143 				// теперь смещаем текстуру
144 				float UV_lft = mMargin.left / (float)mCoord.width;
145 				float UV_top = mMargin.top / (float)mCoord.height;
146 				float UV_rgt = (mCoord.width - mMargin.right) / (float)mCoord.width;
147 				float UV_btm = (mCoord.height - mMargin.bottom) / (float)mCoord.height;
148 
149 				float UV_sizeX = mRectTexture.right - mRectTexture.left;
150 				float UV_sizeY = mRectTexture.bottom - mRectTexture.top;
151 
152 				float UV_lft_total = mRectTexture.left + UV_lft * UV_sizeX;
153 				float UV_top_total = mRectTexture.top + UV_top * UV_sizeY;
154 				float UV_rgt_total = mRectTexture.right - (1 - UV_rgt) * UV_sizeX;
155 				float UV_btm_total = mRectTexture.bottom - (1 - UV_btm) * UV_sizeY;
156 
157 				mCurrentTexture.set(UV_lft_total, UV_top_total, UV_rgt_total, UV_btm_total);
158 			}
159 		}
160 
161 		if (mIsMargin && !margin)
162 		{
163 			// мы не обрезаны, но были, ставим базовые координаты
164 			mCurrentTexture = mRectTexture;
165 		}
166 
167 		// запоминаем текущее состояние
168 		mIsMargin = margin;
169 
170 		if (nullptr != mNode)
171 			mNode->outOfDate(mRenderItem);
172 	}
173 
createDrawItem(ITexture * _texture,ILayerNode * _node)174 	void SubSkin::createDrawItem(ITexture* _texture, ILayerNode* _node)
175 	{
176 		MYGUI_ASSERT(!mRenderItem, "mRenderItem must be nullptr");
177 
178 		mNode = _node;
179 		mRenderItem = mNode->addToRenderItem(_texture, true, mSeparate);
180 		mRenderItem->addDrawItem(this, VertexQuad::VertexCount);
181 	}
182 
destroyDrawItem()183 	void SubSkin::destroyDrawItem()
184 	{
185 		MYGUI_ASSERT(mRenderItem, "mRenderItem must be not nullptr");
186 
187 		mNode = nullptr;
188 		mRenderItem->removeDrawItem(this);
189 		mRenderItem = nullptr;
190 	}
191 
_setUVSet(const FloatRect & _rect)192 	void SubSkin::_setUVSet(const FloatRect& _rect)
193 	{
194 		if (mRectTexture == _rect)
195 			return;
196 		mRectTexture = _rect;
197 
198 		// если обрезаны, то просчитываем с учето обрезки
199 		if (mIsMargin)
200 		{
201 			float UV_lft = mMargin.left / (float)mCoord.width;
202 			float UV_top = mMargin.top / (float)mCoord.height;
203 			float UV_rgt = (mCoord.width - mMargin.right) / (float)mCoord.width;
204 			float UV_btm = (mCoord.height - mMargin.bottom) / (float)mCoord.height;
205 
206 			float UV_sizeX = mRectTexture.right - mRectTexture.left;
207 			float UV_sizeY = mRectTexture.bottom - mRectTexture.top;
208 
209 			float UV_lft_total = mRectTexture.left + UV_lft * UV_sizeX;
210 			float UV_top_total = mRectTexture.top + UV_top * UV_sizeY;
211 			float UV_rgt_total = mRectTexture.right - (1 - UV_rgt) * UV_sizeX;
212 			float UV_btm_total = mRectTexture.bottom - (1 - UV_btm) * UV_sizeY;
213 
214 			mCurrentTexture.set(UV_lft_total, UV_top_total, UV_rgt_total, UV_btm_total);
215 		}
216 		// мы не обрезаны, базовые координаты
217 		else
218 		{
219 			mCurrentTexture = mRectTexture;
220 		}
221 
222 		if (nullptr != mNode)
223 			mNode->outOfDate(mRenderItem);
224 	}
225 
doRender()226 	void SubSkin::doRender()
227 	{
228 		if (!mVisible || mEmptyView)
229 			return;
230 
231 		VertexQuad* quad = reinterpret_cast<VertexQuad*>(mRenderItem->getCurrentVertexBuffer());
232 
233 		const RenderTargetInfo& info = mRenderItem->getRenderTarget()->getInfo();
234 
235 		float vertex_z = mNode->getNodeDepth();
236 
237 		float vertex_left = ((info.pixScaleX * (float)(mCurrentCoord.left + mCroppedParent->getAbsoluteLeft() - info.leftOffset) + info.hOffset) * 2) - 1;
238 		float vertex_right = vertex_left + (info.pixScaleX * (float)mCurrentCoord.width * 2);
239 		float vertex_top = -(((info.pixScaleY * (float)(mCurrentCoord.top + mCroppedParent->getAbsoluteTop() - info.topOffset) + info.vOffset) * 2) - 1);
240 		float vertex_bottom = vertex_top - (info.pixScaleY * (float)mCurrentCoord.height * 2);
241 
242 		quad->set(
243 			vertex_left,
244 			vertex_top,
245 			vertex_right,
246 			vertex_bottom,
247 			vertex_z,
248 			mCurrentTexture.left,
249 			mCurrentTexture.top,
250 			mCurrentTexture.right,
251 			mCurrentTexture.bottom,
252 			mCurrentColour);
253 
254 		mRenderItem->setLastVertexCount(VertexQuad::VertexCount);
255 	}
256 
_setColour(const Colour & _value)257 	void SubSkin::_setColour(const Colour& _value)
258 	{
259 		uint32 colour = texture_utility::toColourARGB(_value);
260 		texture_utility::convertColour(colour, mVertexFormat);
261 		mCurrentColour = (colour & 0x00FFFFFF) | (mCurrentColour & 0xFF000000);
262 
263 		if (nullptr != mNode)
264 			mNode->outOfDate(mRenderItem);
265 	}
266 
setStateData(IStateInfo * _data)267 	void SubSkin::setStateData(IStateInfo* _data)
268 	{
269 		_setUVSet(_data->castType<SubSkinStateInfo>()->getRect());
270 	}
271 
272 } // namespace MyGUI
273