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