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