MyGUI  3.0.1
MyGUI_SubSkin.cpp
Go to the documentation of this file.
00001 
00007 /*
00008     This file is part of MyGUI.
00009 
00010     MyGUI is free software: you can redistribute it and/or modify
00011     it under the terms of the GNU Lesser General Public License as published by
00012     the Free Software Foundation, either version 3 of the License, or
00013     (at your option) any later version.
00014 
00015     MyGUI is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018     GNU Lesser General Public License for more details.
00019 
00020     You should have received a copy of the GNU Lesser General Public License
00021     along with MyGUI.  If not, see <http://www.gnu.org/licenses/>.
00022 */
00023 #include "MyGUI_Precompiled.h"
00024 #include "MyGUI_SubSkin.h"
00025 #include "MyGUI_RenderItem.h"
00026 #include "MyGUI_SkinManager.h"
00027 #include "MyGUI_LanguageManager.h"
00028 #include "MyGUI_LayerNode.h"
00029 #include "MyGUI_CommonStateInfo.h"
00030 #include "MyGUI_RenderManager.h"
00031 #include "MyGUI_TextureUtility.h"
00032 
00033 namespace MyGUI
00034 {
00035 
00036     SubSkin::SubSkin() :
00037         ISubWidgetRect(),
00038         mEmptyView(false),
00039         mCurrentColour(0xFFFFFFFF),
00040         mNode(nullptr),
00041         mRenderItem(nullptr)
00042     {
00043     }
00044 
00045     SubSkin::~SubSkin()
00046     {
00047     }
00048 
00049     void SubSkin::setVisible(bool _visible)
00050     {
00051         if (mVisible == _visible) return;
00052         mVisible = _visible;
00053 
00054         if (nullptr != mNode) mNode->outOfDate(mRenderItem);
00055     }
00056 
00057     void SubSkin::setAlpha(float _alpha)
00058     {
00059         uint32 alpha = ((uint8)(_alpha*255) << 24);
00060         mCurrentColour = (mCurrentColour & 0x00FFFFFF) | (alpha & 0xFF000000);
00061 
00062         if (nullptr != mNode)
00063             mNode->outOfDate(mRenderItem);
00064     }
00065 
00066     void SubSkin::_correctView()
00067     {
00068         if (nullptr != mNode) mNode->outOfDate(mRenderItem);
00069     }
00070 
00071     void SubSkin::_setAlign(const IntCoord& _oldcoord, bool _update)
00072     {
00073         _setAlign(_oldcoord.size(), _update);
00074     }
00075 
00076     void SubSkin::_setAlign(const IntSize& _oldsize, bool _update)
00077     {
00078         // необходимо разобраться
00079         bool need_update = true;//_update;
00080 
00081         // первоначальное выравнивание
00082         if (mAlign.isHStretch())
00083         {
00084             // растягиваем
00085             mCoord.width = mCoord.width + (mCroppedParent->getWidth() - _oldsize.width);
00086             need_update = true;
00087             mIsMargin = true; // при изменении размеров все пересчитывать
00088         }
00089         else if (mAlign.isRight())
00090         {
00091             // двигаем по правому краю
00092             mCoord.left = mCoord.left + (mCroppedParent->getWidth() - _oldsize.width);
00093             need_update = true;
00094         }
00095         else if (mAlign.isHCenter())
00096         {
00097             // выравнивание по горизонтали без растяжения
00098             mCoord.left = (mCroppedParent->getWidth() - mCoord.width) / 2;
00099             need_update = true;
00100         }
00101 
00102         if (mAlign.isVStretch())
00103         {
00104             // растягиваем
00105             mCoord.height = mCoord.height + (mCroppedParent->getHeight() - _oldsize.height);
00106             need_update = true;
00107             mIsMargin = true; // при изменении размеров все пересчитывать
00108         }
00109         else if (mAlign.isBottom())
00110         {
00111             // двигаем по нижнему краю
00112             mCoord.top = mCoord.top + (mCroppedParent->getHeight() - _oldsize.height);
00113             need_update = true;
00114         }
00115         else if (mAlign.isVCenter())
00116         {
00117             // выравнивание по вертикали без растяжения
00118             mCoord.top = (mCroppedParent->getHeight() - mCoord.height) / 2;
00119             need_update = true;
00120         }
00121 
00122         if (need_update)
00123         {
00124             mCurrentCoord = mCoord;
00125             _updateView();
00126         }
00127 
00128     }
00129 
00130     void SubSkin::_updateView()
00131     {
00132         //mAbsolutePosition = mCroppedParent->getAbsolutePosition() + mCoord.point();
00133         bool margin = _checkMargin();
00134 
00135         mEmptyView = ((0 >= _getViewWidth()) || (0 >= _getViewHeight()));
00136 
00137         mCurrentCoord.left = mCoord.left + mMargin.left;
00138         mCurrentCoord.top = mCoord.top + mMargin.top;
00139 
00140         // вьюпорт стал битым
00141         if (margin)
00142         {
00143             // проверка на полный выход за границу
00144             if (_checkOutside())
00145             {
00146 
00147                 // запоминаем текущее состояние
00148                 mIsMargin = margin;
00149 
00150                 // обновить перед выходом
00151                 if (nullptr != mNode) mNode->outOfDate(mRenderItem);
00152                 return;
00153             }
00154         }
00155 
00156         // мы обрезаны или были обрезаны
00157         if ( mIsMargin || margin )
00158         {
00159             mCurrentCoord.width = _getViewWidth();
00160             mCurrentCoord.height = _getViewHeight();
00161 
00162             if ( (mCurrentCoord.width > 0) && (mCurrentCoord.height > 0) )
00163             {
00164                 // теперь смещаем текстуру
00165                 float UV_lft = mMargin.left / (float)mCoord.width;
00166                 float UV_top = mMargin.top / (float)mCoord.height;
00167                 float UV_rgt = (mCoord.width - mMargin.right) / (float)mCoord.width;
00168                 float UV_btm = (mCoord.height - mMargin.bottom) / (float)mCoord.height;
00169 
00170                 float UV_sizeX = mRectTexture.right - mRectTexture.left;
00171                 float UV_sizeY = mRectTexture.bottom - mRectTexture.top;
00172 
00173                 float UV_lft_total = mRectTexture.left + UV_lft * UV_sizeX;
00174                 float UV_top_total = mRectTexture.top + UV_top * UV_sizeY;
00175                 float UV_rgt_total = mRectTexture.right - (1-UV_rgt) * UV_sizeX;
00176                 float UV_btm_total = mRectTexture.bottom - (1-UV_btm) * UV_sizeY;
00177 
00178                 mCurrentTexture.set(UV_lft_total, UV_top_total, UV_rgt_total, UV_btm_total);
00179             }
00180         }
00181 
00182         if (mIsMargin && !margin)
00183         {
00184             // мы не обрезаны, но были, ставим базовые координаты
00185             mCurrentTexture = mRectTexture;
00186         }
00187 
00188         // запоминаем текущее состояние
00189         mIsMargin = margin;
00190 
00191         if (nullptr != mNode) mNode->outOfDate(mRenderItem);
00192     }
00193 
00194     void SubSkin::createDrawItem(ITexture* _texture, ILayerNode * _node)
00195     {
00196         MYGUI_ASSERT(!mRenderItem, "mRenderItem must be nullptr");
00197 
00198         mNode = _node;
00199         mRenderItem = mNode->addToRenderItem(_texture, this);
00200         mRenderItem->addDrawItem(this, VertexQuad::VertexCount);
00201     }
00202 
00203     void SubSkin::destroyDrawItem()
00204     {
00205         MYGUI_ASSERT(mRenderItem, "mRenderItem must be not nullptr");
00206 
00207         mNode = nullptr;
00208         mRenderItem->removeDrawItem(this);
00209         mRenderItem = nullptr;
00210     }
00211 
00212     void SubSkin::_setUVSet(const FloatRect& _rect)
00213     {
00214         if (mRectTexture == _rect) return;
00215         mRectTexture = _rect;
00216 
00217         // если обрезаны, то просчитываем с учето обрезки
00218         if (mIsMargin)
00219         {
00220             float UV_lft = mMargin.left / (float)mCoord.width;
00221             float UV_top = mMargin.top / (float)mCoord.height;
00222             float UV_rgt = (mCoord.width - mMargin.right) / (float)mCoord.width;
00223             float UV_btm = (mCoord.height - mMargin.bottom) / (float)mCoord.height;
00224 
00225             float UV_sizeX = mRectTexture.right - mRectTexture.left;
00226             float UV_sizeY = mRectTexture.bottom - mRectTexture.top;
00227 
00228             float UV_lft_total = mRectTexture.left + UV_lft * UV_sizeX;
00229             float UV_top_total = mRectTexture.top + UV_top * UV_sizeY;
00230             float UV_rgt_total = mRectTexture.right - (1-UV_rgt) * UV_sizeX;
00231             float UV_btm_total = mRectTexture.bottom - (1-UV_btm) * UV_sizeY;
00232 
00233             mCurrentTexture.set(UV_lft_total, UV_top_total, UV_rgt_total, UV_btm_total);
00234         }
00235 
00236         // мы не обрезаны, базовые координаты
00237         else
00238         {
00239             mCurrentTexture = mRectTexture;
00240         }
00241 
00242         if (nullptr != mNode) mNode->outOfDate(mRenderItem);
00243     }
00244 
00245     void SubSkin::doRender()
00246     {
00247         if (!mVisible || mEmptyView) return;
00248 
00249         VertexQuad* quad = (VertexQuad*)mRenderItem->getCurrentVertextBuffer();
00250 
00251         const RenderTargetInfo& info = mRenderItem->getRenderTarget()->getInfo();
00252 
00253         float vertex_z = info.maximumDepth;
00254 
00255         float vertex_left = ((info.pixScaleX * (float)(mCurrentCoord.left + mCroppedParent->getAbsoluteLeft() - info.leftOffset) + info.hOffset) * 2) - 1;
00256         float vertex_right = vertex_left + (info.pixScaleX * (float)mCurrentCoord.width * 2);
00257         float vertex_top = -(((info.pixScaleY * (float)(mCurrentCoord.top + mCroppedParent->getAbsoluteTop() - info.topOffset) + info.vOffset) * 2) - 1);
00258         float vertex_bottom = vertex_top - (info.pixScaleY * (float)mCurrentCoord.height * 2);
00259 
00260         quad->set(
00261             vertex_left,
00262             vertex_top,
00263             vertex_right,
00264             vertex_bottom,
00265             vertex_z,
00266             mCurrentTexture.left,
00267             mCurrentTexture.top,
00268             mCurrentTexture.right,
00269             mCurrentTexture.bottom,
00270             mCurrentColour
00271             );
00272 
00273         mRenderItem->setLastVertexCount(VertexQuad::VertexCount);
00274     }
00275 
00276     void SubSkin::_setColour(const Colour& _value)
00277     {
00278         uint32 colour = texture_utility::toColourARGB(_value);
00279         texture_utility::convertColour(colour, RenderManager::getInstance().getVertexFormat());
00280         mCurrentColour = (colour & 0x00FFFFFF) | (mCurrentColour & 0xFF000000);
00281 
00282         if (nullptr != mNode)
00283             mNode->outOfDate(mRenderItem);
00284     }
00285 
00286     void SubSkin::setStateData(IStateInfo* _data)
00287     {
00288         _setUVSet(_data->castType<SubSkinStateInfo>()->getRect());
00289     }
00290 
00291 } // namespace MyGUI