MyGUI  3.2.1
MyGUI_TileRect.cpp
Go to the documentation of this file.
00001 /*
00002  * This source file is part of MyGUI. For the latest info, see http://mygui.info/
00003  * Distributed under the MIT License
00004  * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
00005  */
00006 
00007 #include "MyGUI_Precompiled.h"
00008 #include "MyGUI_TileRect.h"
00009 #include "MyGUI_RenderItem.h"
00010 #include "MyGUI_SkinManager.h"
00011 #include "MyGUI_LanguageManager.h"
00012 #include "MyGUI_LayerNode.h"
00013 #include "MyGUI_CommonStateInfo.h"
00014 #include "MyGUI_RenderManager.h"
00015 #include "MyGUI_TextureUtility.h"
00016 
00017 namespace MyGUI
00018 {
00019 
00020     const size_t TILERECT_COUNT_VERTEX = 16 * VertexQuad::VertexCount;
00021 
00022     TileRect::TileRect() :
00023         mEmptyView(false),
00024         mCurrentColour(0xFFFFFFFF),
00025         mNode(nullptr),
00026         mRenderItem(nullptr),
00027         mCountVertex(TILERECT_COUNT_VERTEX),
00028         mRealTileWidth(0),
00029         mRealTileHeight(0),
00030         mTextureHeightOne(0),
00031         mTextureWidthOne(0),
00032         mTileH(true),
00033         mTileV(true)
00034     {
00035         mVertexFormat = RenderManager::getInstance().getVertexFormat();
00036     }
00037 
00038     TileRect::~TileRect()
00039     {
00040     }
00041 
00042     void TileRect::setVisible(bool _visible)
00043     {
00044         if (mVisible == _visible)
00045             return;
00046         mVisible = _visible;
00047 
00048         if (nullptr != mNode)
00049             mNode->outOfDate(mRenderItem);
00050     }
00051 
00052     void TileRect::setAlpha(float _alpha)
00053     {
00054         uint32 alpha = ((uint8)(_alpha * 255) << 24);
00055         mCurrentColour = (mCurrentColour & 0x00FFFFFF) | (alpha & 0xFF000000);
00056 
00057         if (nullptr != mNode)
00058             mNode->outOfDate(mRenderItem);
00059     }
00060 
00061     void TileRect::_correctView()
00062     {
00063         if (nullptr != mNode)
00064             mNode->outOfDate(mRenderItem);
00065     }
00066 
00067     void TileRect::_setAlign(const IntSize& _oldsize)
00068     {
00069         // необходимо разобраться
00070         bool need_update = true;
00071 
00072         // первоначальное выравнивание
00073         if (mAlign.isHStretch())
00074         {
00075             // растягиваем
00076             mCoord.width = mCoord.width + (mCroppedParent->getWidth() - _oldsize.width);
00077             need_update = true;
00078             mIsMargin = true; // при изменении размеров все пересчитывать
00079         }
00080         else if (mAlign.isRight())
00081         {
00082             // двигаем по правому краю
00083             mCoord.left = mCoord.left + (mCroppedParent->getWidth() - _oldsize.width);
00084             need_update = true;
00085         }
00086         else if (mAlign.isHCenter())
00087         {
00088             // выравнивание по горизонтали без растяжения
00089             mCoord.left = (mCroppedParent->getWidth() - mCoord.width) / 2;
00090             need_update = true;
00091         }
00092 
00093         if (mAlign.isVStretch())
00094         {
00095             // растягиваем
00096             mCoord.height = mCoord.height + (mCroppedParent->getHeight() - _oldsize.height);
00097             need_update = true;
00098             mIsMargin = true; // при изменении размеров все пересчитывать
00099         }
00100         else if (mAlign.isBottom())
00101         {
00102             // двигаем по нижнему краю
00103             mCoord.top = mCoord.top + (mCroppedParent->getHeight() - _oldsize.height);
00104             need_update = true;
00105         }
00106         else if (mAlign.isVCenter())
00107         {
00108             // выравнивание по вертикали без растяжения
00109             mCoord.top = (mCroppedParent->getHeight() - mCoord.height) / 2;
00110             need_update = true;
00111         }
00112 
00113         if (need_update)
00114         {
00115             mCurrentCoord = mCoord;
00116             if (!mTileH) mTileSize.width = mCoord.width;
00117             if (!mTileV) mTileSize.height = mCoord.height;
00118             _updateView();
00119         }
00120     }
00121 
00122     void TileRect::_updateView()
00123     {
00124         bool margin = _checkMargin();
00125 
00126         mEmptyView = ((0 >= _getViewWidth()) || (0 >= _getViewHeight()));
00127 
00128         mCurrentCoord.left = mCoord.left + mMargin.left;
00129         mCurrentCoord.top = mCoord.top + mMargin.top;
00130         mCurrentCoord.width = _getViewWidth();
00131         mCurrentCoord.height = _getViewHeight();
00132 
00133         // подсчитываем необходимое колличество тайлов
00134         if (!mEmptyView)
00135         {
00136             size_t count = 0;
00137             if (!mTileSize.empty())
00138             {
00139                 size_t count_x = mCoord.width / mTileSize.width;
00140                 if ((mCoord.width % mTileSize.width) > 0)
00141                     count_x ++;
00142 
00143                 size_t count_y = mCoord.height / mTileSize.height;
00144                 if ((mCoord.height % mTileSize.height) > 0)
00145                     count_y ++;
00146 
00147                 count = count_y * count_x * VertexQuad::VertexCount;
00148             }
00149 
00150             // нужно больше вершин
00151             if (count > mCountVertex)
00152             {
00153                 mCountVertex = count + TILERECT_COUNT_VERTEX;
00154                 if (nullptr != mRenderItem)
00155                     mRenderItem->reallockDrawItem(this, mCountVertex);
00156             }
00157         }
00158 
00159         // вьюпорт стал битым
00160         if (margin)
00161         {
00162             // проверка на полный выход за границу
00163             if (_checkOutside())
00164             {
00165                 // запоминаем текущее состояние
00166                 mIsMargin = margin;
00167 
00168                 // обновить перед выходом
00169                 if (nullptr != mNode)
00170                     mNode->outOfDate(mRenderItem);
00171                 return;
00172             }
00173         }
00174 
00175         // запоминаем текущее состояние
00176         mIsMargin = margin;
00177 
00178         if (nullptr != mNode)
00179             mNode->outOfDate(mRenderItem);
00180     }
00181 
00182     void TileRect::_setUVSet(const FloatRect& _rect)
00183     {
00184         mCurrentTexture = _rect;
00185         if (nullptr != mNode)
00186             mNode->outOfDate(mRenderItem);
00187     }
00188 
00189     void TileRect::doRender()
00190     {
00191         if (!mVisible || mEmptyView || mTileSize.empty())
00192             return;
00193 
00194         VertexQuad* quad = reinterpret_cast<VertexQuad*>(mRenderItem->getCurrentVertexBuffer());
00195 
00196         const RenderTargetInfo& info = mRenderItem->getRenderTarget()->getInfo();
00197 
00198         // размер одного тайла
00199         mRealTileWidth = info.pixScaleX * (float)(mTileSize.width) * 2;
00200         mRealTileHeight = info.pixScaleY * (float)(mTileSize.height) * 2;
00201 
00202         mTextureHeightOne = (mCurrentTexture.bottom - mCurrentTexture.top) / mRealTileHeight;
00203         mTextureWidthOne = (mCurrentTexture.right - mCurrentTexture.left) / mRealTileWidth;
00204 
00205         float vertex_z = mNode->getNodeDepth();
00206 
00207         // абсолютный размер окна
00208         float window_left = ((info.pixScaleX * (float)(mCoord.left + mCroppedParent->getAbsoluteLeft() - info.leftOffset) + info.hOffset) * 2) - 1;
00209         float window_top = -(((info.pixScaleY * (float)(mCoord.top + mCroppedParent->getAbsoluteTop() - info.topOffset) + info.vOffset) * 2) - 1);
00210 
00211         // размер вьюпорта
00212         float real_left = ((info.pixScaleX * (float)(mCurrentCoord.left + mCroppedParent->getAbsoluteLeft() - info.leftOffset) + info.hOffset) * 2) - 1;
00213         float real_right = real_left + (info.pixScaleX * (float)mCurrentCoord.width * 2);
00214         float real_top = -(((info.pixScaleY * (float)(mCurrentCoord.top + mCroppedParent->getAbsoluteTop() - info.topOffset) + info.vOffset) * 2) - 1);
00215         float real_bottom = real_top - (info.pixScaleY * (float)mCurrentCoord.height * 2);
00216 
00217         size_t count = 0;
00218 
00219         float left = window_left;
00220         float right = window_left;
00221         float top = window_top;
00222         float bottom = window_top;
00223 
00224         for (int y = 0; y < mCoord.height; y += mTileSize.height)
00225         {
00226             top = bottom;
00227             bottom -= mRealTileHeight;
00228             right = window_left;
00229 
00230             float vertex_top = top;
00231             float vertex_bottom = bottom;
00232             bool texture_crop_height  = false;
00233 
00234             if (vertex_top > real_top)
00235             {
00236                 // проверка на полный выход
00237                 if (vertex_bottom > real_top)
00238                 {
00239                     continue;
00240                 }
00241                 // обрезаем
00242                 vertex_top = real_top;
00243                 texture_crop_height = true;
00244             }
00245             if (vertex_bottom < real_bottom)
00246             {
00247                 // вообще вниз ушли
00248                 if (vertex_top < real_bottom)
00249                 {
00250                     continue;
00251                 }
00252                 // обрезаем
00253                 vertex_bottom = real_bottom;
00254                 texture_crop_height = true;
00255             }
00256 
00257             for (int x = 0; x < mCoord.width; x += mTileSize.width)
00258             {
00259                 left = right;
00260                 right += mRealTileWidth;
00261 
00262                 float vertex_left = left;
00263                 float vertex_right = right;
00264                 bool texture_crop_width = false;
00265 
00266 
00267                 if (vertex_left < real_left)
00268                 {
00269                     // проверка на полный выход
00270                     if (vertex_right < real_left)
00271                     {
00272                         continue;
00273                     }
00274                     // обрезаем
00275                     vertex_left = real_left;
00276                     texture_crop_width = true;
00277                 }
00278 
00279                 if (vertex_right > real_right)
00280                 {
00281                     // вообще строку до конца не нуна
00282                     if (vertex_left > real_right)
00283                     {
00284                         continue;
00285                     }
00286                     // обрезаем
00287                     vertex_right = real_right;
00288                     texture_crop_width = true;
00289                 }
00290 
00291                 // текущие текстурные координаты
00292                 float texture_left = mCurrentTexture.left;
00293                 float texture_right = mCurrentTexture.right;
00294                 float texture_top = mCurrentTexture.top;
00295                 float texture_bottom = mCurrentTexture.bottom;
00296 
00297                 // смещение текстуры по вертикили
00298                 if (texture_crop_height)
00299                 {
00300                     // прибавляем размер смещения в текстурных координатах
00301                     texture_top += (top - vertex_top) * mTextureHeightOne;
00302                     // отнимаем размер смещения в текстурных координатах
00303                     texture_bottom -= (vertex_bottom - bottom) * mTextureHeightOne;
00304                 }
00305 
00306                 // смещение текстуры по горизонтали
00307                 if (texture_crop_width)
00308                 {
00309                     // прибавляем размер смещения в текстурных координатах
00310                     texture_left += (vertex_left - left) * mTextureWidthOne;
00311                     // отнимаем размер смещения в текстурных координатах
00312                     texture_right -= (right - vertex_right) * mTextureWidthOne;
00313                 }
00314 
00315                 quad[count].set(
00316                     vertex_left,
00317                     vertex_top,
00318                     vertex_right,
00319                     vertex_bottom,
00320                     vertex_z,
00321                     texture_left,
00322                     texture_top,
00323                     texture_right,
00324                     texture_bottom,
00325                     mCurrentColour);
00326 
00327                 count ++;
00328             }
00329         }
00330 
00331         mRenderItem->setLastVertexCount(VertexQuad::VertexCount * count);
00332     }
00333 
00334     void TileRect::createDrawItem(ITexture* _texture, ILayerNode* _node)
00335     {
00336         MYGUI_ASSERT(!mRenderItem, "mRenderItem must be nullptr");
00337 
00338         mNode = _node;
00339         mRenderItem = mNode->addToRenderItem(_texture, true, false);
00340         mRenderItem->addDrawItem(this, mCountVertex);
00341     }
00342 
00343     void TileRect::destroyDrawItem()
00344     {
00345         MYGUI_ASSERT(mRenderItem, "mRenderItem must be not nullptr");
00346 
00347         mNode = nullptr;
00348         mRenderItem->removeDrawItem(this);
00349         mRenderItem = nullptr;
00350     }
00351 
00352     void TileRect::setStateData(IStateInfo* _data)
00353     {
00354         TileRectStateInfo* data = _data->castType<TileRectStateInfo>();
00355 
00356         mTileSize = data->getTileSize();
00357         mTileH = data->getTileH();
00358         mTileV = data->getTileV();
00359         _setUVSet(data->getRect());
00360     }
00361 
00362     void TileRect::_setColour(const Colour& _value)
00363     {
00364         uint32 colour = texture_utility::toColourARGB(_value);
00365         texture_utility::convertColour(colour, mVertexFormat);
00366         mCurrentColour = (colour & 0x00FFFFFF) | (mCurrentColour & 0xFF000000);
00367 
00368         if (nullptr != mNode)
00369             mNode->outOfDate(mRenderItem);
00370     }
00371 
00372 } // namespace MyGUI