MyGUI  3.2.1
MyGUI_RotatingSkin.cpp
Go to the documentation of this file.
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_RotatingSkin.h"
9 #include "MyGUI_RenderItem.h"
10 #include "MyGUI_CommonStateInfo.h"
11 #include "MyGUI_RenderManager.h"
12 #include "MyGUI_GeometryUtility.h"
13 
14 namespace MyGUI
15 {
16 
18  mGeometryOutdated(false),
19  mAngle(0.0f),
20  mEmptyView(false),
21  mCurrentColour(0xFFFFFFFF),
22  mNode(nullptr),
23  mRenderItem(nullptr)
24  {
25  mVertexFormat = RenderManager::getInstance().getVertexFormat();
26  }
27 
29  {
30  }
31 
32  void RotatingSkin::setAngle(float _angle)
33  {
34  mAngle = _angle;
35  mGeometryOutdated = true;
36 
37  if (nullptr != mNode)
38  mNode->outOfDate(mRenderItem);
39  }
40 
41  void RotatingSkin::setCenter(const IntPoint& _center)
42  {
43  mCenterPos = _center;
44  mGeometryOutdated = true;
45 
46  if (nullptr != mNode)
47  mNode->outOfDate(mRenderItem);
48  }
49 
50  IntPoint RotatingSkin::getCenter(bool _local) const
51  {
52  return mCenterPos + (_local ? IntPoint() : mCroppedParent->getAbsolutePosition());
53  }
54 
55  void RotatingSkin::setVisible(bool _visible)
56  {
57  if (mVisible == _visible)
58  return;
59 
60  mVisible = _visible;
61  mGeometryOutdated = true;
62 
63  if (nullptr != mNode)
64  mNode->outOfDate(mRenderItem);
65  }
66 
67  void RotatingSkin::setAlpha(float _alpha)
68  {
69  uint32 alpha = ((uint8)(_alpha * 255) << 24);
70  mCurrentColour = (mCurrentColour & 0x00FFFFFF) | (alpha & 0xFF000000);
71 
72  if (nullptr != mNode)
73  mNode->outOfDate(mRenderItem);
74  }
75 
77  {
78  mGeometryOutdated = true;
79 
80  if (nullptr != mNode)
81  mNode->outOfDate(mRenderItem);
82  }
83 
84  void RotatingSkin::_setAlign(const IntSize& _oldsize)
85  {
86  // необходимо разобраться
87  bool need_update = true;
88 
89  // первоначальное выравнивание
90  if (mAlign.isHStretch())
91  {
92  // растягиваем
93  mCoord.width = mCoord.width + (mCroppedParent->getWidth() - _oldsize.width);
94  need_update = true;
95  mIsMargin = true; // при изменении размеров все пересчитывать
96  }
97  else if (mAlign.isRight())
98  {
99  // двигаем по правому краю
100  mCoord.left = mCoord.left + (mCroppedParent->getWidth() - _oldsize.width);
101  need_update = true;
102  }
103  else if (mAlign.isHCenter())
104  {
105  // выравнивание по горизонтали без растяжения
107  need_update = true;
108  }
109 
110  if (mAlign.isVStretch())
111  {
112  // растягиваем
114  need_update = true;
115  mIsMargin = true; // при изменении размеров все пересчитывать
116  }
117  else if (mAlign.isBottom())
118  {
119  // двигаем по нижнему краю
120  mCoord.top = mCoord.top + (mCroppedParent->getHeight() - _oldsize.height);
121  need_update = true;
122  }
123  else if (mAlign.isVCenter())
124  {
125  // выравнивание по вертикали без растяжения
127  need_update = true;
128  }
129 
130  if (need_update)
131  {
132  mCurrentCoord = mCoord;
133  _updateView();
134  }
135  }
136 
138  {
139  mEmptyView = ((0 >= _getViewWidth()) || (0 >= _getViewHeight()));
140 
141  mGeometryOutdated = true;
142 
143  if (nullptr != mNode)
144  mNode->outOfDate(mRenderItem);
145  }
146 
148  {
149  MYGUI_ASSERT(!mRenderItem, "mRenderItem must be nullptr");
150 
151  mNode = _node;
152  mRenderItem = mNode->addToRenderItem(_texture, true, false);
153  mRenderItem->addDrawItem(this, (GEOMETRY_VERTICIES_TOTAL_COUNT - 2) * 3);
154  }
155 
157  {
158  MYGUI_ASSERT(mRenderItem, "mRenderItem must be not nullptr");
159 
160  mNode = nullptr;
161  mRenderItem->removeDrawItem(this);
162  mRenderItem = nullptr;
163  }
164 
166  {
167  if (!mVisible || mEmptyView)
168  return;
169 
170  Vertex* verticies = mRenderItem->getCurrentVertexBuffer();
171 
172  float vertex_z = mNode->getNodeDepth();
173 
174  if (mGeometryOutdated)
175  {
177  mGeometryOutdated = false;
178  }
179 
180  for (int i = 1; i < GEOMETRY_VERTICIES_TOTAL_COUNT - 1; ++i)
181  {
182  verticies[3 * i - 3].set(mResultVerticiesPos[0].left, mResultVerticiesPos[0].top, vertex_z, mResultVerticiesUV[0].left, mResultVerticiesUV[0].top, mCurrentColour);
183  verticies[3 * i - 2].set(mResultVerticiesPos[i].left, mResultVerticiesPos[i].top, vertex_z, mResultVerticiesUV[i].left, mResultVerticiesUV[i].top, mCurrentColour);
184  verticies[3 * i - 1].set(mResultVerticiesPos[i + 1].left, mResultVerticiesPos[i + 1].top, vertex_z, mResultVerticiesUV[i + 1].left, mResultVerticiesUV[i + 1].top, mCurrentColour);
185  }
186 
187  mRenderItem->setLastVertexCount((GEOMETRY_VERTICIES_TOTAL_COUNT - 2) * 3);
188  }
189 
190  void RotatingSkin::_setColour(const Colour& _value)
191  {
192  uint32 colour = texture_utility::toColourARGB(_value);
193  texture_utility::convertColour(colour, mVertexFormat);
194  mCurrentColour = (colour & 0x00FFFFFF) | (mCurrentColour & 0xFF000000);
195 
196  if (nullptr != mNode)
197  mNode->outOfDate(mRenderItem);
198  }
199 
201  {
203 
204  setAngle(data->getAngle());
205  setCenter(data->getCenter());
206 
207  _setUVSet(data->getRect());
208  }
209 
211  {
212  mCurrentTexture = _rect;
213 
214  mGeometryOutdated = true;
215 
216  if (nullptr != mNode)
217  mNode->outOfDate(mRenderItem);
218  }
219 
220  inline float len(float x, float y)
221  {
222  return sqrt(x * x + y * y);
223  }
224 
226  {
227  /*
228  0 1
229  3 2
230  */
231 #ifndef M_PI
232  const float M_PI = 3.141593f;
233 #endif
234 
235  float width_base = (float)mCurrentCoord.width;
236  float height_base = (float)mCurrentCoord.height;
237 
238  // calculate original unrotated angles of uncropped rectangle verticies: between axis and line from center of rotation to vertex)
239  float baseAngles[RECT_VERTICIES_COUNT];
240  baseAngles[0] = atan2((float)mCenterPos.left, (float)mCenterPos.top) + M_PI / 2;
241  baseAngles[1] = atan2(- width_base + (float)mCenterPos.left, (float)mCenterPos.top) + M_PI / 2;
242  baseAngles[2] = atan2(- width_base + (float)mCenterPos.left, - height_base + (float)mCenterPos.top) + M_PI / 2;
243  baseAngles[3] = atan2((float)mCenterPos.left, - height_base + (float)mCenterPos.top) + M_PI / 2;
244 
245  // calculate original unrotated distances of uncropped rectangle verticies: between center of rotation and vertex)
246  float baseDistances[RECT_VERTICIES_COUNT];
247  baseDistances[0] = len((float)mCenterPos.left, (float)mCenterPos.top);
248  baseDistances[1] = len(- width_base + (float)mCenterPos.left, (float)mCenterPos.top);
249  baseDistances[2] = len(- width_base + (float)mCenterPos.left, - height_base + (float)mCenterPos.top);
250  baseDistances[3] = len((float)mCenterPos.left, - height_base + (float)mCenterPos.top);
251 
252 
253  // calculate rotated positions of uncropped rectangle verticies (relative to parent)
254  FloatPoint baseVerticiesPos[RECT_VERTICIES_COUNT];
255 
256  int offsetX = /*mCurrentCoord.left +*/ mCenterPos.left;
257  int offsetY = /*mCurrentCoord.top +*/ mCenterPos.top;
258 
259  for (int i = 0; i < RECT_VERTICIES_COUNT; ++i)
260  {
261  baseVerticiesPos[i].left = offsetX + cos(-mAngle + baseAngles[i]) * baseDistances[i];
262  baseVerticiesPos[i].top = offsetY - sin(-mAngle + baseAngles[i]) * baseDistances[i];
263  }
264 
265  // base texture coordinates
266  FloatPoint baseVerticiesUV[RECT_VERTICIES_COUNT] =
267  {
268  FloatPoint(mCurrentTexture.left, mCurrentTexture.top),
269  FloatPoint(mCurrentTexture.right, mCurrentTexture.top),
270  FloatPoint(mCurrentTexture.right, mCurrentTexture.bottom),
271  FloatPoint(mCurrentTexture.left, mCurrentTexture.bottom)
272  };
273 
274  // now we have rotated uncropped rectangle verticies coordinates
275 
276  // --------- here the cropping starts ---------
277 
278  // now we are going to calculate verticies of resulting figure
279 
280  // no parent - no cropping
281  size_t size = RECT_VERTICIES_COUNT;
282  if (nullptr == mCroppedParent->getCroppedParent())
283  {
284  for (int i = 0; i < RECT_VERTICIES_COUNT; ++i)
285  {
286  mResultVerticiesPos[i] = baseVerticiesPos[i];
287  mResultVerticiesUV[i] = baseVerticiesUV[i];
288  }
289  }
290  else
291  {
293 
294  VectorFloatPoint resultVerticiesPos = geometry_utility::cropPolygon(
295  baseVerticiesPos,
296  RECT_VERTICIES_COUNT,
297  IntCoord(
298  parent->_getMarginLeft() - mCroppedParent->getLeft(),
299  parent->_getMarginTop() - mCroppedParent->getTop(),
300  parent->_getViewWidth(),
301  parent->_getViewHeight()));
302 
303  for (size_t i = 0; i < resultVerticiesPos.size(); ++i)
304  {
305  mResultVerticiesPos[i] = resultVerticiesPos[i];
306  }
307 
308  size = resultVerticiesPos.size();
309 
310  // calculate texture coordinates
311  FloatPoint v0 = baseVerticiesUV[3] - baseVerticiesUV[0];
312  FloatPoint v1 = baseVerticiesUV[1] - baseVerticiesUV[0];
313  for (size_t i = 0; i < GEOMETRY_VERTICIES_TOTAL_COUNT; ++i)
314  {
315  if (i < size)
316  {
317  FloatPoint point = geometry_utility::getPositionInsideRect(mResultVerticiesPos[i], baseVerticiesPos[0], baseVerticiesPos[1], baseVerticiesPos[3]);
318  mResultVerticiesUV[i] = geometry_utility::getUVFromPositionInsideRect(point, v0, v1, baseVerticiesUV[0]);
319  }
320  else
321  {
322  // all unused verticies is equal to last used
323  mResultVerticiesUV[i] = mResultVerticiesUV[size - 1];
324  }
325  }
326  }
327 
328 
329  // now calculate widget base offset and then resulting position in screen coordinates
330  const RenderTargetInfo& info = mRenderItem->getRenderTarget()->getInfo();
331  float vertex_left_base = ((info.pixScaleX * (float)(mCroppedParent->getAbsoluteLeft()) + info.hOffset) * 2) - 1;
332  float vertex_top_base = -(((info.pixScaleY * (float)(mCroppedParent->getAbsoluteTop()) + info.vOffset) * 2) - 1);
333 
334  for (size_t i = 0; i < GEOMETRY_VERTICIES_TOTAL_COUNT; ++i)
335  {
336  if (i < size)
337  {
338  mResultVerticiesPos[i].left = vertex_left_base + mResultVerticiesPos[i].left * info.pixScaleX * 2;
339  mResultVerticiesPos[i].top = vertex_top_base + mResultVerticiesPos[i].top * info.pixScaleY * -2;
340  }
341  else
342  {
343  // all unused verticies is equal to last used
344  mResultVerticiesPos[i] = mResultVerticiesPos[size - 1];
345  }
346  }
347  }
348 
350  {
351  return mAngle;
352  }
353 
354 } // namespace MyGUI