1 /* 2 * This source file is part of MyGUI. For the latest info, see http://mygui.info/ 3 * Distributed under the MIT License 4 * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT) 5 */ 6 7 #include "MyGUI_Precompiled.h" 8 #include "MyGUI_SubSkin.h" 9 #include "MyGUI_RenderItem.h" 10 #include "MyGUI_SkinManager.h" 11 #include "MyGUI_LanguageManager.h" 12 #include "MyGUI_LayerNode.h" 13 #include "MyGUI_CommonStateInfo.h" 14 #include "MyGUI_RenderManager.h" 15 #include "MyGUI_TextureUtility.h" 16 17 namespace MyGUI 18 { 19 SubSkin()20 SubSkin::SubSkin() : 21 ISubWidgetRect(), 22 mEmptyView(false), 23 mCurrentColour(0xFFFFFFFF), 24 mNode(nullptr), 25 mRenderItem(nullptr), 26 mSeparate(false) 27 { 28 mVertexFormat = RenderManager::getInstance().getVertexFormat(); 29 } 30 setVisible(bool _visible)31 void SubSkin::setVisible(bool _visible) 32 { 33 if (mVisible == _visible) 34 return; 35 mVisible = _visible; 36 37 if (nullptr != mNode) 38 mNode->outOfDate(mRenderItem); 39 } 40 setAlpha(float _alpha)41 void SubSkin::setAlpha(float _alpha) 42 { 43 uint32 alpha = ((uint8)(_alpha * 255) << 24); 44 mCurrentColour = (mCurrentColour & 0x00FFFFFF) | (alpha & 0xFF000000); 45 46 if (nullptr != mNode) 47 mNode->outOfDate(mRenderItem); 48 } 49 _correctView()50 void SubSkin::_correctView() 51 { 52 if (nullptr != mNode) 53 mNode->outOfDate(mRenderItem); 54 } 55 _setAlign(const IntSize & _oldsize)56 void SubSkin::_setAlign(const IntSize& _oldsize) 57 { 58 // необходимо разобраться 59 bool need_update = true;//_update; 60 61 // первоначальное выравнивание 62 if (mAlign.isHStretch()) 63 { 64 // растягиваем 65 mCoord.width = mCoord.width + (mCroppedParent->getWidth() - _oldsize.width); 66 need_update = true; 67 mIsMargin = true; // при изменении размеров все пересчитывать 68 } 69 else if (mAlign.isRight()) 70 { 71 // двигаем по правому краю 72 mCoord.left = mCoord.left + (mCroppedParent->getWidth() - _oldsize.width); 73 need_update = true; 74 } 75 else if (mAlign.isHCenter()) 76 { 77 // выравнивание по горизонтали без растяжения 78 mCoord.left = (mCroppedParent->getWidth() - mCoord.width) / 2; 79 need_update = true; 80 } 81 82 if (mAlign.isVStretch()) 83 { 84 // растягиваем 85 mCoord.height = mCoord.height + (mCroppedParent->getHeight() - _oldsize.height); 86 need_update = true; 87 mIsMargin = true; // при изменении размеров все пересчитывать 88 } 89 else if (mAlign.isBottom()) 90 { 91 // двигаем по нижнему краю 92 mCoord.top = mCoord.top + (mCroppedParent->getHeight() - _oldsize.height); 93 need_update = true; 94 } 95 else if (mAlign.isVCenter()) 96 { 97 // выравнивание по вертикали без растяжения 98 mCoord.top = (mCroppedParent->getHeight() - mCoord.height) / 2; 99 need_update = true; 100 } 101 102 if (need_update) 103 { 104 mCurrentCoord = mCoord; 105 _updateView(); 106 } 107 } 108 _updateView()109 void SubSkin::_updateView() 110 { 111 //mAbsolutePosition = mCroppedParent->getAbsolutePosition() + mCoord.point(); 112 bool margin = _checkMargin(); 113 114 mEmptyView = ((0 >= _getViewWidth()) || (0 >= _getViewHeight())); 115 116 mCurrentCoord.left = mCoord.left + mMargin.left; 117 mCurrentCoord.top = mCoord.top + mMargin.top; 118 119 // вьюпорт стал битым 120 if (margin) 121 { 122 // проверка на полный выход за границу 123 if (_checkOutside()) 124 { 125 // запоминаем текущее состояние 126 mIsMargin = margin; 127 128 // обновить перед выходом 129 if (nullptr != mNode) 130 mNode->outOfDate(mRenderItem); 131 return; 132 } 133 } 134 135 // мы обрезаны или были обрезаны 136 if (mIsMargin || margin) 137 { 138 mCurrentCoord.width = _getViewWidth(); 139 mCurrentCoord.height = _getViewHeight(); 140 141 if ((mCurrentCoord.width > 0) && (mCurrentCoord.height > 0)) 142 { 143 // теперь смещаем текстуру 144 float UV_lft = mMargin.left / (float)mCoord.width; 145 float UV_top = mMargin.top / (float)mCoord.height; 146 float UV_rgt = (mCoord.width - mMargin.right) / (float)mCoord.width; 147 float UV_btm = (mCoord.height - mMargin.bottom) / (float)mCoord.height; 148 149 float UV_sizeX = mRectTexture.right - mRectTexture.left; 150 float UV_sizeY = mRectTexture.bottom - mRectTexture.top; 151 152 float UV_lft_total = mRectTexture.left + UV_lft * UV_sizeX; 153 float UV_top_total = mRectTexture.top + UV_top * UV_sizeY; 154 float UV_rgt_total = mRectTexture.right - (1 - UV_rgt) * UV_sizeX; 155 float UV_btm_total = mRectTexture.bottom - (1 - UV_btm) * UV_sizeY; 156 157 mCurrentTexture.set(UV_lft_total, UV_top_total, UV_rgt_total, UV_btm_total); 158 } 159 } 160 161 if (mIsMargin && !margin) 162 { 163 // мы не обрезаны, но были, ставим базовые координаты 164 mCurrentTexture = mRectTexture; 165 } 166 167 // запоминаем текущее состояние 168 mIsMargin = margin; 169 170 if (nullptr != mNode) 171 mNode->outOfDate(mRenderItem); 172 } 173 createDrawItem(ITexture * _texture,ILayerNode * _node)174 void SubSkin::createDrawItem(ITexture* _texture, ILayerNode* _node) 175 { 176 MYGUI_ASSERT(!mRenderItem, "mRenderItem must be nullptr"); 177 178 mNode = _node; 179 mRenderItem = mNode->addToRenderItem(_texture, true, mSeparate); 180 mRenderItem->addDrawItem(this, VertexQuad::VertexCount); 181 } 182 destroyDrawItem()183 void SubSkin::destroyDrawItem() 184 { 185 MYGUI_ASSERT(mRenderItem, "mRenderItem must be not nullptr"); 186 187 mNode = nullptr; 188 mRenderItem->removeDrawItem(this); 189 mRenderItem = nullptr; 190 } 191 _setUVSet(const FloatRect & _rect)192 void SubSkin::_setUVSet(const FloatRect& _rect) 193 { 194 if (mRectTexture == _rect) 195 return; 196 mRectTexture = _rect; 197 198 // если обрезаны, то просчитываем с учето обрезки 199 if (mIsMargin) 200 { 201 float UV_lft = mMargin.left / (float)mCoord.width; 202 float UV_top = mMargin.top / (float)mCoord.height; 203 float UV_rgt = (mCoord.width - mMargin.right) / (float)mCoord.width; 204 float UV_btm = (mCoord.height - mMargin.bottom) / (float)mCoord.height; 205 206 float UV_sizeX = mRectTexture.right - mRectTexture.left; 207 float UV_sizeY = mRectTexture.bottom - mRectTexture.top; 208 209 float UV_lft_total = mRectTexture.left + UV_lft * UV_sizeX; 210 float UV_top_total = mRectTexture.top + UV_top * UV_sizeY; 211 float UV_rgt_total = mRectTexture.right - (1 - UV_rgt) * UV_sizeX; 212 float UV_btm_total = mRectTexture.bottom - (1 - UV_btm) * UV_sizeY; 213 214 mCurrentTexture.set(UV_lft_total, UV_top_total, UV_rgt_total, UV_btm_total); 215 } 216 // мы не обрезаны, базовые координаты 217 else 218 { 219 mCurrentTexture = mRectTexture; 220 } 221 222 if (nullptr != mNode) 223 mNode->outOfDate(mRenderItem); 224 } 225 doRender()226 void SubSkin::doRender() 227 { 228 if (!mVisible || mEmptyView) 229 return; 230 231 VertexQuad* quad = reinterpret_cast<VertexQuad*>(mRenderItem->getCurrentVertexBuffer()); 232 233 const RenderTargetInfo& info = mRenderItem->getRenderTarget()->getInfo(); 234 235 float vertex_z = mNode->getNodeDepth(); 236 237 float vertex_left = ((info.pixScaleX * (float)(mCurrentCoord.left + mCroppedParent->getAbsoluteLeft() - info.leftOffset) + info.hOffset) * 2) - 1; 238 float vertex_right = vertex_left + (info.pixScaleX * (float)mCurrentCoord.width * 2); 239 float vertex_top = -(((info.pixScaleY * (float)(mCurrentCoord.top + mCroppedParent->getAbsoluteTop() - info.topOffset) + info.vOffset) * 2) - 1); 240 float vertex_bottom = vertex_top - (info.pixScaleY * (float)mCurrentCoord.height * 2); 241 242 quad->set( 243 vertex_left, 244 vertex_top, 245 vertex_right, 246 vertex_bottom, 247 vertex_z, 248 mCurrentTexture.left, 249 mCurrentTexture.top, 250 mCurrentTexture.right, 251 mCurrentTexture.bottom, 252 mCurrentColour); 253 254 mRenderItem->setLastVertexCount(VertexQuad::VertexCount); 255 } 256 _setColour(const Colour & _value)257 void SubSkin::_setColour(const Colour& _value) 258 { 259 uint32 colour = texture_utility::toColourARGB(_value); 260 texture_utility::convertColour(colour, mVertexFormat); 261 mCurrentColour = (colour & 0x00FFFFFF) | (mCurrentColour & 0xFF000000); 262 263 if (nullptr != mNode) 264 mNode->outOfDate(mRenderItem); 265 } 266 setStateData(IStateInfo * _data)267 void SubSkin::setStateData(IStateInfo* _data) 268 { 269 _setUVSet(_data->castType<SubSkinStateInfo>()->getRect()); 270 } 271 272 } // namespace MyGUI 273