MyGUI  3.0.3
MyGUI_LayerNode.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 
00024 #include "MyGUI_Precompiled.h"
00025 #include "MyGUI_LayerNode.h"
00026 #include "MyGUI_ILayerItem.h"
00027 #include "MyGUI_ITexture.h"
00028 #include "MyGUI_ISubWidget.h"
00029 #include "MyGUI_ISubWidgetText.h"
00030 
00031 namespace MyGUI
00032 {
00033 
00034     LayerNode::LayerNode(ILayer* _layer, ILayerNode* _parent) :
00035         mParent(_parent),
00036         mLayer(_layer),
00037         mOutOfDate(false)
00038     {
00039     }
00040 
00041     LayerNode::~LayerNode()
00042     {
00043         for (VectorRenderItem::iterator iter=mFirstRenderItems.begin(); iter!=mFirstRenderItems.end(); ++iter)
00044         {
00045             delete (*iter);
00046         }
00047         mFirstRenderItems.clear();
00048 
00049         for (VectorRenderItem::iterator iter=mSecondRenderItems.begin(); iter!=mSecondRenderItems.end(); ++iter)
00050         {
00051             delete (*iter);
00052         }
00053         mSecondRenderItems.clear();
00054 
00055         // удаляем дочерние узлы
00056         for (VectorILayerNode::iterator iter = mChildItems.begin(); iter!=mChildItems.end(); ++iter)
00057         {
00058             delete (*iter);
00059         }
00060         mChildItems.clear();
00061     }
00062 
00063     ILayerNode* LayerNode::createChildItemNode()
00064     {
00065         LayerNode* layer = new LayerNode(mLayer, this);
00066         mChildItems.push_back(layer);
00067         return layer;
00068     }
00069 
00070     void LayerNode::destroyChildItemNode(ILayerNode* _node)
00071     {
00072         for (VectorILayerNode::iterator iter=mChildItems.begin(); iter!=mChildItems.end(); ++iter)
00073         {
00074             if ((*iter) == _node)
00075             {
00076                 delete _node;
00077                 mChildItems.erase(iter);
00078                 return;
00079             }
00080         }
00081         MYGUI_EXCEPT("item node not found");
00082     }
00083 
00084     void LayerNode::upChildItemNode(ILayerNode* _item)
00085     {
00086         for (VectorILayerNode::iterator iter=mChildItems.begin(); iter!=mChildItems.end(); ++iter)
00087         {
00088             if ((*iter) == _item)
00089             {
00090                 mChildItems.erase(iter);
00091                 mChildItems.push_back(_item);
00092                 return;
00093             }
00094         }
00095         MYGUI_EXCEPT("item node not found");
00096     }
00097 
00098     void LayerNode::renderToTarget(IRenderTarget* _target, bool _update)
00099     {
00100         // проверяем на сжатие пустот
00101         bool need_compression = false;
00102         for (VectorRenderItem::iterator iter=mFirstRenderItems.begin(); iter!=mFirstRenderItems.end(); ++iter)
00103         {
00104             if ((*iter)->getCompression())
00105             {
00106                 need_compression = true;
00107                 break;
00108             }
00109         }
00110 
00111         if (need_compression)
00112             updateCompression();
00113 
00114         // сначала отрисовываем свое
00115         for (VectorRenderItem::iterator iter=mFirstRenderItems.begin(); iter!=mFirstRenderItems.end(); ++iter)
00116         {
00117             (*iter)->renderToTarget(_target, _update);
00118         }
00119         for (VectorRenderItem::iterator iter=mSecondRenderItems.begin(); iter!=mSecondRenderItems.end(); ++iter)
00120         {
00121             (*iter)->renderToTarget(_target, _update);
00122         }
00123 
00124         // теперь отрисовываем дочерние узлы
00125         for (VectorILayerNode::iterator iter = mChildItems.begin(); iter!=mChildItems.end(); ++iter)
00126         {
00127             (*iter)->renderToTarget(_target, _update);
00128         }
00129 
00130         mOutOfDate = false;
00131     }
00132 
00133     ILayerItem* LayerNode::getLayerItemByPoint(int _left, int _top)
00134     {
00135         // сначала пикаем детей
00136         for (VectorILayerNode::iterator iter = mChildItems.begin(); iter!=mChildItems.end(); ++iter)
00137         {
00138             ILayerItem * item = (*iter)->getLayerItemByPoint(_left, _top);
00139             if (nullptr != item) return item;
00140         }
00141 
00142         for (VectorLayerItem::iterator iter=mLayerItems.begin(); iter!=mLayerItems.end(); ++iter)
00143         {
00144             ILayerItem * item = (*iter)->getLayerItemByPoint(_left, _top);
00145             if (nullptr != item) return item;
00146         }
00147 
00148         return nullptr;
00149     }
00150 
00151     RenderItem* LayerNode::addToRenderItem(ITexture* _texture, ISubWidget* _item)
00152     {
00153         bool _firstQueue = _item->castType<ISubWidgetText>(false) == nullptr;
00154         // для первичной очереди нужен порядок
00155         if (_firstQueue)
00156         {
00157             if (mFirstRenderItems.empty())
00158             {
00159                 // создаем новый буфер
00160                 RenderItem* item = new RenderItem();
00161                 item->setTexture(_texture);
00162                 mFirstRenderItems.push_back(item);
00163 
00164                 return item;
00165             }
00166 
00167             // если в конце пустой буфер, то нуна найти последний пустой с краю
00168             // либо с нужной текстурой за пустым
00169             VectorRenderItem::reverse_iterator iter = mFirstRenderItems.rbegin();
00170             if ((*iter)->getNeedVertexCount() == 0)
00171             {
00172                 while (true)
00173                 {
00174                     VectorRenderItem::reverse_iterator next = iter + 1;
00175                     if (next != mFirstRenderItems.rend())
00176                     {
00177                         if ((*next)->getNeedVertexCount() == 0)
00178                         {
00179                             iter = next;
00180                             continue;
00181                         }
00182                         else if ((*next)->getTexture() == _texture)
00183                             iter = next;
00184                     }
00185 
00186                     break;
00187                 }
00188 
00189                 (*iter)->setTexture(_texture);
00190                 return (*iter);
00191             }
00192             // последний буфер с нужной текстурой
00193             else if ((*iter)->getTexture() == _texture)
00194             {
00195                 return *iter;
00196             }
00197 
00198             // создаем новый буфер
00199             RenderItem* item = new RenderItem();
00200             item->setTexture(_texture);
00201             mFirstRenderItems.push_back(item);
00202 
00203             return item;
00204         }
00205 
00206         // для второй очереди порядок неважен
00207         for (VectorRenderItem::iterator iter = mSecondRenderItems.begin(); iter != mSecondRenderItems.end(); ++iter)
00208         {
00209             // либо такая же текстура, либо пустой буфер
00210             if ((*iter)->getTexture() == _texture)
00211             {
00212                 return (*iter);
00213             }
00214             else if ((*iter)->getNeedVertexCount() == 0)
00215             {
00216                 (*iter)->setTexture(_texture);
00217                 return (*iter);
00218             }
00219 
00220         }
00221         // не найденно создадим новый
00222         RenderItem* item = new RenderItem();
00223         item->setTexture(_texture);
00224 
00225         mSecondRenderItems.push_back(item);
00226         return mSecondRenderItems.back();
00227     }
00228 
00229     void LayerNode::attachLayerItem(ILayerItem* _item)
00230     {
00231         mLayerItems.push_back(_item);
00232         _item->attachItemToNode(mLayer, this);
00233     }
00234 
00235     void LayerNode::detachLayerItem(ILayerItem* _item)
00236     {
00237         for (VectorLayerItem::iterator iter=mLayerItems.begin(); iter!=mLayerItems.end(); ++iter)
00238         {
00239             if ((*iter) == _item)
00240             {
00241                 (*iter) = mLayerItems.back();
00242                 mLayerItems.pop_back();
00243                 return;
00244             }
00245         }
00246         MYGUI_EXCEPT("layer item not found");
00247     }
00248 
00249     void LayerNode::outOfDate(RenderItem* _item)
00250     {
00251         mOutOfDate = true;
00252         if (_item)
00253             _item->outOfDate();
00254     }
00255 
00256     EnumeratorILayerNode LayerNode::getEnumerator()
00257     {
00258         return EnumeratorILayerNode(mChildItems);
00259     }
00260 
00261     void LayerNode::updateCompression()
00262     {
00263         // буферы освобождаются по одному всегда
00264         if (mFirstRenderItems.size() > 1)
00265         {
00266             // пытаемся поднять пустой буфер выше полных
00267             VectorRenderItem::iterator iter1 = mFirstRenderItems.begin();
00268             VectorRenderItem::iterator iter2 = iter1 + 1;
00269             while (iter2 != mFirstRenderItems.end())
00270             {
00271                 if ((*iter1)->getNeedVertexCount() == 0)
00272                 {
00273                     RenderItem * tmp = (*iter1);
00274                     (*iter1) = (*iter2);
00275                     (*iter2) = tmp;
00276                 }
00277                 iter1 = iter2;
00278                 ++iter2;
00279             }
00280         }
00281     }
00282 
00283     void LayerNode::dumpStatisticToLog(size_t _level)
00284     {
00285         static const char* spacer = "                                                                                                                        ";
00286         std::string offset(" ", _level);
00287         MYGUI_LOG(Info, offset << " - Node batch_count='" << mFirstRenderItems.size() + mSecondRenderItems.size() << spacer);
00288 
00289         for (VectorRenderItem::iterator iter=mFirstRenderItems.begin(); iter!=mFirstRenderItems.end(); ++iter)
00290         {
00291             MYGUI_LOG(Info, offset << "  * Batch texture='" << ((*iter)->getTexture() == nullptr ? "nullptr" : (*iter)->getTexture()->getName()) << "' vertex_count='" << (*iter)->getVertexCount() << "'" << spacer);
00292         }
00293         for (VectorRenderItem::iterator iter=mSecondRenderItems.begin(); iter!=mSecondRenderItems.end(); ++iter)
00294         {
00295             MYGUI_LOG(Info, offset << "  * Batch texture='" << ((*iter)->getTexture() == nullptr ? "nullptr" : (*iter)->getTexture()->getName()) << "' vertex_count='" << (*iter)->getVertexCount() << "'" << spacer);
00296         }
00297 
00298         for (VectorILayerNode::iterator iter = mChildItems.begin(); iter!=mChildItems.end(); ++iter)
00299         {
00300             (*iter)->dumpStatisticToLog(_level + 1);
00301         }
00302     }
00303 
00304 } // namespace MyGUI