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