• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

MyGUI_TileRect.cpp

Go to the documentation of this file.
00001 
00007 /*
00008     This file is part of MyGUI.
00009 
00010     MyGUI is free software: you can redistribute it and/or modify
00011     it under the terms of the GNU Lesser General Public License as published by
00012     the Free Software Foundation, either version 3 of the License, or
00013     (at your option) any later version.
00014 
00015     MyGUI is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018     GNU Lesser General Public License for more details.
00019 
00020     You should have received a copy of the GNU Lesser General Public License
00021     along with MyGUI.  If not, see <http://www.gnu.org/licenses/>.
00022 */
00023 #include "MyGUI_Precompiled.h"
00024 #include "MyGUI_TileRect.h"
00025 #include "MyGUI_RenderItem.h"
00026 #include "MyGUI_SkinManager.h"
00027 #include "MyGUI_LanguageManager.h"
00028 #include "MyGUI_LayerNode.h"
00029 #include "MyGUI_CommonStateInfo.h"
00030 
00031 namespace MyGUI
00032 {
00033 
00034     const size_t TILERECT_COUNT_VERTEX = 16 * VertexQuad::VertexCount;
00035 
00036     TileRect::TileRect() :
00037         mEmptyView(false),
00038         mCurrentAlpha(0xFFFFFFFF),
00039         mNode(nullptr),
00040         mRenderItem(nullptr),
00041         mCountVertex(TILERECT_COUNT_VERTEX),
00042         mTileH(true),
00043         mTileV(true)
00044     {
00045     }
00046 
00047     TileRect::~TileRect()
00048     {
00049     }
00050 
00051     void TileRect::setVisible(bool _visible)
00052     {
00053         if (mVisible == _visible) return;
00054         mVisible = _visible;
00055 
00056         if (nullptr != mNode) mNode->outOfDate(mRenderItem);
00057     }
00058 
00059     void TileRect::setAlpha(float _alpha)
00060     {
00061         mCurrentAlpha = 0x00FFFFFF | ((uint8)(_alpha*255) << 24);
00062         if (nullptr != mNode) mNode->outOfDate(mRenderItem);
00063     }
00064 
00065     void TileRect::_correctView()
00066     {
00067         if (nullptr != mNode) mNode->outOfDate(mRenderItem);
00068     }
00069 
00070     void TileRect::_setAlign(const IntCoord& _oldcoord, bool _update)
00071     {
00072         _setAlign(_oldcoord.size(), _update);
00073     }
00074 
00075     void TileRect::_setAlign(const IntSize& _oldsize, bool _update)
00076     {
00077         // необходимо разобраться
00078         bool need_update = true;//_update;
00079 
00080         // первоначальное выравнивание
00081         if (mAlign.isHStretch())
00082         {
00083             // растягиваем
00084             mCoord.width = mCoord.width + (mCroppedParent->getWidth() - _oldsize.width);
00085             need_update = true;
00086             mIsMargin = true; // при изменении размеров все пересчитывать
00087         }
00088         else if (mAlign.isRight())
00089         {
00090             // двигаем по правому краю
00091             mCoord.left = mCoord.left + (mCroppedParent->getWidth() - _oldsize.width);
00092             need_update = true;
00093         }
00094         else if (mAlign.isHCenter())
00095         {
00096             // выравнивание по горизонтали без растяжения
00097             mCoord.left = (mCroppedParent->getWidth() - mCoord.width) / 2;
00098             need_update = true;
00099         }
00100 
00101         if (mAlign.isVStretch())
00102         {
00103             // растягиваем
00104             mCoord.height = mCoord.height + (mCroppedParent->getHeight() - _oldsize.height);
00105             need_update = true;
00106             mIsMargin = true; // при изменении размеров все пересчитывать
00107         }
00108         else if (mAlign.isBottom())
00109         {
00110             // двигаем по нижнему краю
00111             mCoord.top = mCoord.top + (mCroppedParent->getHeight() - _oldsize.height);
00112             need_update = true;
00113         }
00114         else if (mAlign.isVCenter())
00115         {
00116             // выравнивание по вертикали без растяжения
00117             mCoord.top = (mCroppedParent->getHeight() - mCoord.height) / 2;
00118             need_update = true;
00119         }
00120 
00121         if (need_update)
00122         {
00123             mCurrentCoord = mCoord;
00124             if (!mTileH) mTileSize.width = mCoord.width;
00125             if (!mTileV) mTileSize.height = mCoord.height;
00126             _updateView();
00127         }
00128 
00129     }
00130 
00131     void TileRect::_updateView()
00132     {
00133         bool margin = _checkMargin();
00134 
00135         mEmptyView = ((0 >= _getViewWidth()) || (0 >= _getViewHeight()));
00136 
00137         mCurrentCoord.left = mCoord.left + mMargin.left;
00138         mCurrentCoord.top = mCoord.top + mMargin.top;
00139         mCurrentCoord.width = _getViewWidth();
00140         mCurrentCoord.height = _getViewHeight();
00141 
00142         // подсчитываем необходимое колличество тайлов
00143         if (false == mEmptyView)
00144         {
00145             size_t count = 0;
00146             if (!mTileSize.empty())
00147             {
00148                 size_t count_x = mCoord.width / mTileSize.width;
00149                 if ((mCoord.width % mTileSize.width) > 0) count_x ++;
00150                 size_t count_y = mCoord.height / mTileSize.height;
00151                 if ((mCoord.height % mTileSize.height) > 0) count_y ++;
00152                 count = count_y * count_x * VertexQuad::VertexCount;
00153             }
00154 
00155             // нужно больше вершин
00156             if (count > mCountVertex)
00157             {
00158                 mCountVertex = count + TILERECT_COUNT_VERTEX;
00159                 if (nullptr != mRenderItem) mRenderItem->reallockDrawItem(this, mCountVertex);
00160             }
00161         }
00162 
00163         // вьюпорт стал битым
00164         if (margin)
00165         {
00166             // проверка на полный выход за границу
00167             if (_checkOutside())
00168             {
00169                 // запоминаем текущее состояние
00170                 mIsMargin = margin;
00171 
00172                 // обновить перед выходом
00173                 if (nullptr != mNode) mNode->outOfDate(mRenderItem);
00174                 return;
00175             }
00176         }
00177 
00178         // запоминаем текущее состояние
00179         mIsMargin = margin;
00180 
00181         if (nullptr != mNode) mNode->outOfDate(mRenderItem);
00182     }
00183 
00184     void TileRect::_setUVSet(const FloatRect& _rect)
00185     {
00186         mCurrentTexture = _rect;
00187         if (nullptr != mNode) mNode->outOfDate(mRenderItem);
00188     }
00189 
00190     void TileRect::doRender()
00191     {
00192         if (!mVisible || mEmptyView || mTileSize.empty()) return;
00193 
00194         VertexQuad* quad = (VertexQuad*)mRenderItem->getCurrentVertextBuffer();
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 = info.maximumDepth;
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                     mCurrentAlpha
00326                     );
00327 
00328                 count ++;
00329             }
00330         }
00331 
00332         mRenderItem->setLastVertexCount(VertexQuad::VertexCount * count);
00333     }
00334 
00335     void TileRect::createDrawItem(const std::string& _texture, ILayerNode * _node)
00336     {
00337         MYGUI_ASSERT(!mRenderItem, "mRenderItem must be nullptr");
00338 
00339         mNode = _node;
00340         mRenderItem = mNode->addToRenderItem(_texture, this);
00341         mRenderItem->addDrawItem(this, mCountVertex);
00342     }
00343 
00344     void TileRect::destroyDrawItem()
00345     {
00346         MYGUI_ASSERT(mRenderItem, "mRenderItem must be not nullptr");
00347 
00348         mNode = nullptr;
00349         mRenderItem->removeDrawItem(this);
00350         mRenderItem = nullptr;
00351     }
00352 
00353     void TileRect::setStateData(IStateInfo* _data)
00354     {
00355         TileRectStateInfo* data = _data->castType<TileRectStateInfo>();
00356 
00357         mTileSize = data->getTileSize();
00358         mTileH = data->getTileH();
00359         mTileV = data->getTileV();
00360         _setUVSet(data->getRect());
00361     }
00362 
00363 } // namespace MyGUI

Generated on Sun Jan 30 2011 for MyGUI by  doxygen 1.7.1