MyGUI
3.2.1
|
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