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