MyGUI  3.2.1
MyGUI_SubSkin.cpp
Go to the documentation of this file.
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_SubSkin.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     SubSkin::SubSkin() :
00021         ISubWidgetRect(),
00022         mEmptyView(false),
00023         mCurrentColour(0xFFFFFFFF),
00024         mNode(nullptr),
00025         mRenderItem(nullptr),
00026         mSeparate(false)
00027     {
00028         mVertexFormat = RenderManager::getInstance().getVertexFormat();
00029     }
00030 
00031     SubSkin::~SubSkin()
00032     {
00033     }
00034 
00035     void SubSkin::setVisible(bool _visible)
00036     {
00037         if (mVisible == _visible)
00038             return;
00039         mVisible = _visible;
00040 
00041         if (nullptr != mNode)
00042             mNode->outOfDate(mRenderItem);
00043     }
00044 
00045     void SubSkin::setAlpha(float _alpha)
00046     {
00047         uint32 alpha = ((uint8)(_alpha * 255) << 24);
00048         mCurrentColour = (mCurrentColour & 0x00FFFFFF) | (alpha & 0xFF000000);
00049 
00050         if (nullptr != mNode)
00051             mNode->outOfDate(mRenderItem);
00052     }
00053 
00054     void SubSkin::_correctView()
00055     {
00056         if (nullptr != mNode)
00057             mNode->outOfDate(mRenderItem);
00058     }
00059 
00060     void SubSkin::_setAlign(const IntSize& _oldsize)
00061     {
00062         // необходимо разобраться
00063         bool need_update = true;//_update;
00064 
00065         // первоначальное выравнивание
00066         if (mAlign.isHStretch())
00067         {
00068             // растягиваем
00069             mCoord.width = mCoord.width + (mCroppedParent->getWidth() - _oldsize.width);
00070             need_update = true;
00071             mIsMargin = true; // при изменении размеров все пересчитывать
00072         }
00073         else if (mAlign.isRight())
00074         {
00075             // двигаем по правому краю
00076             mCoord.left = mCoord.left + (mCroppedParent->getWidth() - _oldsize.width);
00077             need_update = true;
00078         }
00079         else if (mAlign.isHCenter())
00080         {
00081             // выравнивание по горизонтали без растяжения
00082             mCoord.left = (mCroppedParent->getWidth() - mCoord.width) / 2;
00083             need_update = true;
00084         }
00085 
00086         if (mAlign.isVStretch())
00087         {
00088             // растягиваем
00089             mCoord.height = mCoord.height + (mCroppedParent->getHeight() - _oldsize.height);
00090             need_update = true;
00091             mIsMargin = true; // при изменении размеров все пересчитывать
00092         }
00093         else if (mAlign.isBottom())
00094         {
00095             // двигаем по нижнему краю
00096             mCoord.top = mCoord.top + (mCroppedParent->getHeight() - _oldsize.height);
00097             need_update = true;
00098         }
00099         else if (mAlign.isVCenter())
00100         {
00101             // выравнивание по вертикали без растяжения
00102             mCoord.top = (mCroppedParent->getHeight() - mCoord.height) / 2;
00103             need_update = true;
00104         }
00105 
00106         if (need_update)
00107         {
00108             mCurrentCoord = mCoord;
00109             _updateView();
00110         }
00111     }
00112 
00113     void SubSkin::_updateView()
00114     {
00115         //mAbsolutePosition = mCroppedParent->getAbsolutePosition() + mCoord.point();
00116         bool margin = _checkMargin();
00117 
00118         mEmptyView = ((0 >= _getViewWidth()) || (0 >= _getViewHeight()));
00119 
00120         mCurrentCoord.left = mCoord.left + mMargin.left;
00121         mCurrentCoord.top = mCoord.top + mMargin.top;
00122 
00123         // вьюпорт стал битым
00124         if (margin)
00125         {
00126             // проверка на полный выход за границу
00127             if (_checkOutside())
00128             {
00129                 // запоминаем текущее состояние
00130                 mIsMargin = margin;
00131 
00132                 // обновить перед выходом
00133                 if (nullptr != mNode)
00134                     mNode->outOfDate(mRenderItem);
00135                 return;
00136             }
00137         }
00138 
00139         // мы обрезаны или были обрезаны
00140         if (mIsMargin || margin)
00141         {
00142             mCurrentCoord.width = _getViewWidth();
00143             mCurrentCoord.height = _getViewHeight();
00144 
00145             if ((mCurrentCoord.width > 0) && (mCurrentCoord.height > 0))
00146             {
00147                 // теперь смещаем текстуру
00148                 float UV_lft = mMargin.left / (float)mCoord.width;
00149                 float UV_top = mMargin.top / (float)mCoord.height;
00150                 float UV_rgt = (mCoord.width - mMargin.right) / (float)mCoord.width;
00151                 float UV_btm = (mCoord.height - mMargin.bottom) / (float)mCoord.height;
00152 
00153                 float UV_sizeX = mRectTexture.right - mRectTexture.left;
00154                 float UV_sizeY = mRectTexture.bottom - mRectTexture.top;
00155 
00156                 float UV_lft_total = mRectTexture.left + UV_lft * UV_sizeX;
00157                 float UV_top_total = mRectTexture.top + UV_top * UV_sizeY;
00158                 float UV_rgt_total = mRectTexture.right - (1 - UV_rgt) * UV_sizeX;
00159                 float UV_btm_total = mRectTexture.bottom - (1 - UV_btm) * UV_sizeY;
00160 
00161                 mCurrentTexture.set(UV_lft_total, UV_top_total, UV_rgt_total, UV_btm_total);
00162             }
00163         }
00164 
00165         if (mIsMargin && !margin)
00166         {
00167             // мы не обрезаны, но были, ставим базовые координаты
00168             mCurrentTexture = mRectTexture;
00169         }
00170 
00171         // запоминаем текущее состояние
00172         mIsMargin = margin;
00173 
00174         if (nullptr != mNode)
00175             mNode->outOfDate(mRenderItem);
00176     }
00177 
00178     void SubSkin::createDrawItem(ITexture* _texture, ILayerNode* _node)
00179     {
00180         MYGUI_ASSERT(!mRenderItem, "mRenderItem must be nullptr");
00181 
00182         mNode = _node;
00183         mRenderItem = mNode->addToRenderItem(_texture, true, mSeparate);
00184         mRenderItem->addDrawItem(this, VertexQuad::VertexCount);
00185     }
00186 
00187     void SubSkin::destroyDrawItem()
00188     {
00189         MYGUI_ASSERT(mRenderItem, "mRenderItem must be not nullptr");
00190 
00191         mNode = nullptr;
00192         mRenderItem->removeDrawItem(this);
00193         mRenderItem = nullptr;
00194     }
00195 
00196     void SubSkin::_setUVSet(const FloatRect& _rect)
00197     {
00198         if (mRectTexture == _rect)
00199             return;
00200         mRectTexture = _rect;
00201 
00202         // если обрезаны, то просчитываем с учето обрезки
00203         if (mIsMargin)
00204         {
00205             float UV_lft = mMargin.left / (float)mCoord.width;
00206             float UV_top = mMargin.top / (float)mCoord.height;
00207             float UV_rgt = (mCoord.width - mMargin.right) / (float)mCoord.width;
00208             float UV_btm = (mCoord.height - mMargin.bottom) / (float)mCoord.height;
00209 
00210             float UV_sizeX = mRectTexture.right - mRectTexture.left;
00211             float UV_sizeY = mRectTexture.bottom - mRectTexture.top;
00212 
00213             float UV_lft_total = mRectTexture.left + UV_lft * UV_sizeX;
00214             float UV_top_total = mRectTexture.top + UV_top * UV_sizeY;
00215             float UV_rgt_total = mRectTexture.right - (1 - UV_rgt) * UV_sizeX;
00216             float UV_btm_total = mRectTexture.bottom - (1 - UV_btm) * UV_sizeY;
00217 
00218             mCurrentTexture.set(UV_lft_total, UV_top_total, UV_rgt_total, UV_btm_total);
00219         }
00220         // мы не обрезаны, базовые координаты
00221         else
00222         {
00223             mCurrentTexture = mRectTexture;
00224         }
00225 
00226         if (nullptr != mNode)
00227             mNode->outOfDate(mRenderItem);
00228     }
00229 
00230     void SubSkin::doRender()
00231     {
00232         if (!mVisible || mEmptyView)
00233             return;
00234 
00235         VertexQuad* quad = reinterpret_cast<VertexQuad*>(mRenderItem->getCurrentVertexBuffer());
00236 
00237         const RenderTargetInfo& info = mRenderItem->getRenderTarget()->getInfo();
00238 
00239         float vertex_z = mNode->getNodeDepth();
00240 
00241         float vertex_left = ((info.pixScaleX * (float)(mCurrentCoord.left + mCroppedParent->getAbsoluteLeft() - info.leftOffset) + info.hOffset) * 2) - 1;
00242         float vertex_right = vertex_left + (info.pixScaleX * (float)mCurrentCoord.width * 2);
00243         float vertex_top = -(((info.pixScaleY * (float)(mCurrentCoord.top + mCroppedParent->getAbsoluteTop() - info.topOffset) + info.vOffset) * 2) - 1);
00244         float vertex_bottom = vertex_top - (info.pixScaleY * (float)mCurrentCoord.height * 2);
00245 
00246         quad->set(
00247             vertex_left,
00248             vertex_top,
00249             vertex_right,
00250             vertex_bottom,
00251             vertex_z,
00252             mCurrentTexture.left,
00253             mCurrentTexture.top,
00254             mCurrentTexture.right,
00255             mCurrentTexture.bottom,
00256             mCurrentColour);
00257 
00258         mRenderItem->setLastVertexCount(VertexQuad::VertexCount);
00259     }
00260 
00261     void SubSkin::_setColour(const Colour& _value)
00262     {
00263         uint32 colour = texture_utility::toColourARGB(_value);
00264         texture_utility::convertColour(colour, mVertexFormat);
00265         mCurrentColour = (colour & 0x00FFFFFF) | (mCurrentColour & 0xFF000000);
00266 
00267         if (nullptr != mNode)
00268             mNode->outOfDate(mRenderItem);
00269     }
00270 
00271     void SubSkin::setStateData(IStateInfo* _data)
00272     {
00273         _setUVSet(_data->castType<SubSkinStateInfo>()->getRect());
00274     }
00275 
00276 } // namespace MyGUI