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