mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-22 23:23:53 +00:00
302 lines
8.4 KiB
C++
302 lines
8.4 KiB
C++
/*!
|
||
@file
|
||
@author Albert Semenov
|
||
@date 02/2008
|
||
@module
|
||
*/
|
||
/*
|
||
This file is part of MyGUI.
|
||
|
||
MyGUI is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU Lesser General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
MyGUI is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU Lesser General Public License for more details.
|
||
|
||
You should have received a copy of the GNU Lesser General Public License
|
||
along with MyGUI. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
#include "MyGUI_Precompiled.h"
|
||
#include "MyGUI_LayerNode.h"
|
||
#include "MyGUI_ILayerItem.h"
|
||
#include "MyGUI_ITexture.h"
|
||
#include "MyGUI_ISubWidget.h"
|
||
#include "MyGUI_ISubWidgetText.h"
|
||
|
||
namespace MyGUI
|
||
{
|
||
|
||
LayerNode::LayerNode(ILayer* _layer, ILayerNode* _parent) :
|
||
mParent(_parent),
|
||
mLayer(_layer),
|
||
mOutOfDate(false)
|
||
{
|
||
}
|
||
|
||
LayerNode::~LayerNode()
|
||
{
|
||
for (VectorRenderItem::iterator iter=mFirstRenderItems.begin(); iter!=mFirstRenderItems.end(); ++iter)
|
||
{
|
||
delete (*iter);
|
||
}
|
||
mFirstRenderItems.clear();
|
||
|
||
for (VectorRenderItem::iterator iter=mSecondRenderItems.begin(); iter!=mSecondRenderItems.end(); ++iter)
|
||
{
|
||
delete (*iter);
|
||
}
|
||
mSecondRenderItems.clear();
|
||
|
||
// удаляем дочерние узлы
|
||
for (VectorILayerNode::iterator iter = mChildItems.begin(); iter!=mChildItems.end(); ++iter)
|
||
{
|
||
delete (*iter);
|
||
}
|
||
mChildItems.clear();
|
||
}
|
||
|
||
ILayerNode* LayerNode::createChildItemNode()
|
||
{
|
||
LayerNode* layer = new LayerNode(mLayer, this);
|
||
mChildItems.push_back(layer);
|
||
return layer;
|
||
}
|
||
|
||
void LayerNode::destroyChildItemNode(ILayerNode* _node)
|
||
{
|
||
for (VectorILayerNode::iterator iter=mChildItems.begin(); iter!=mChildItems.end(); ++iter)
|
||
{
|
||
if ((*iter) == _node)
|
||
{
|
||
delete _node;
|
||
mChildItems.erase(iter);
|
||
return;
|
||
}
|
||
}
|
||
MYGUI_EXCEPT("item node not found");
|
||
}
|
||
|
||
void LayerNode::upChildItemNode(ILayerNode* _item)
|
||
{
|
||
for (VectorILayerNode::iterator iter=mChildItems.begin(); iter!=mChildItems.end(); ++iter)
|
||
{
|
||
if ((*iter) == _item)
|
||
{
|
||
mChildItems.erase(iter);
|
||
mChildItems.push_back(_item);
|
||
return;
|
||
}
|
||
}
|
||
MYGUI_EXCEPT("item node not found");
|
||
}
|
||
|
||
void LayerNode::renderToTarget(IRenderTarget* _target, bool _update)
|
||
{
|
||
// проверяем на сжатие пустот
|
||
bool need_compression = false;
|
||
for (VectorRenderItem::iterator iter=mFirstRenderItems.begin(); iter!=mFirstRenderItems.end(); ++iter)
|
||
{
|
||
if ((*iter)->getCompression())
|
||
{
|
||
need_compression = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (need_compression)
|
||
updateCompression();
|
||
|
||
// сначала отрисовываем свое
|
||
for (VectorRenderItem::iterator iter=mFirstRenderItems.begin(); iter!=mFirstRenderItems.end(); ++iter)
|
||
{
|
||
(*iter)->renderToTarget(_target, _update);
|
||
}
|
||
for (VectorRenderItem::iterator iter=mSecondRenderItems.begin(); iter!=mSecondRenderItems.end(); ++iter)
|
||
{
|
||
(*iter)->renderToTarget(_target, _update);
|
||
}
|
||
|
||
// теперь отрисовываем дочерние узлы
|
||
for (VectorILayerNode::iterator iter = mChildItems.begin(); iter!=mChildItems.end(); ++iter)
|
||
{
|
||
(*iter)->renderToTarget(_target, _update);
|
||
}
|
||
|
||
mOutOfDate = false;
|
||
}
|
||
|
||
ILayerItem* LayerNode::getLayerItemByPoint(int _left, int _top)
|
||
{
|
||
// сначала пикаем детей
|
||
for (VectorILayerNode::iterator iter = mChildItems.begin(); iter!=mChildItems.end(); ++iter)
|
||
{
|
||
ILayerItem * item = (*iter)->getLayerItemByPoint(_left, _top);
|
||
if (nullptr != item) return item;
|
||
}
|
||
|
||
for (VectorLayerItem::iterator iter=mLayerItems.begin(); iter!=mLayerItems.end(); ++iter)
|
||
{
|
||
ILayerItem * item = (*iter)->getLayerItemByPoint(_left, _top);
|
||
if (nullptr != item) return item;
|
||
}
|
||
|
||
return nullptr;
|
||
}
|
||
|
||
RenderItem* LayerNode::addToRenderItem(ITexture* _texture, ISubWidget* _item)
|
||
{
|
||
bool first = _item->castType<ISubWidgetText>(false) == nullptr;
|
||
// для первичной очереди нужен порядок
|
||
if (first)
|
||
{
|
||
if (mFirstRenderItems.empty())
|
||
{
|
||
// создаем новый буфер
|
||
RenderItem * item = new RenderItem();
|
||
item->setTexture(_texture);
|
||
mFirstRenderItems.push_back(item);
|
||
|
||
return item;
|
||
}
|
||
|
||
// если последний буфер пустой, то мона не создавать
|
||
if (mFirstRenderItems.back()->getNeedVertexCount() == 0)
|
||
{
|
||
// пустых может быть сколько угодно, нужен самый первый из пустых
|
||
for (VectorRenderItem::iterator iter=mFirstRenderItems.begin(); iter!=mFirstRenderItems.end(); ++iter)
|
||
{
|
||
if ((*iter)->getNeedVertexCount() == 0)
|
||
{
|
||
// а теперь внимание, если перед пустым наш, то его и юзаем
|
||
if (iter != mFirstRenderItems.begin())
|
||
{
|
||
VectorRenderItem::iterator prev = iter - 1;
|
||
if ((*prev)->getTexture() == _texture)
|
||
{
|
||
return (*prev);
|
||
}
|
||
}
|
||
(*iter)->setTexture(_texture);
|
||
return (*iter);
|
||
}
|
||
}
|
||
}
|
||
|
||
// та же текстура
|
||
if (mFirstRenderItems.back()->getTexture() == _texture)
|
||
{
|
||
return mFirstRenderItems.back();
|
||
}
|
||
|
||
// создаем новый буфер
|
||
RenderItem * item = new RenderItem();
|
||
item->setTexture(_texture);
|
||
mFirstRenderItems.push_back(item);
|
||
|
||
return item;
|
||
}
|
||
|
||
// для второй очереди порядок неважен
|
||
for (VectorRenderItem::iterator iter=mSecondRenderItems.begin(); iter!=mSecondRenderItems.end(); ++iter)
|
||
{
|
||
// либо такая же текстура, либо пустой буфер
|
||
if ((*iter)->getTexture() == _texture)
|
||
{
|
||
return (*iter);
|
||
}
|
||
else if ((*iter)->getNeedVertexCount() == 0)
|
||
{
|
||
(*iter)->setTexture(_texture);
|
||
return (*iter);
|
||
}
|
||
|
||
}
|
||
// не найденно создадим новый
|
||
RenderItem * item = new RenderItem();
|
||
item->setTexture(_texture);
|
||
|
||
mSecondRenderItems.push_back(item);
|
||
return mSecondRenderItems.back();
|
||
}
|
||
|
||
void LayerNode::attachLayerItem(ILayerItem* _item)
|
||
{
|
||
mLayerItems.push_back(_item);
|
||
_item->attachItemToNode(mLayer, this);
|
||
}
|
||
|
||
void LayerNode::detachLayerItem(ILayerItem* _item)
|
||
{
|
||
for (VectorLayerItem::iterator iter=mLayerItems.begin(); iter!=mLayerItems.end(); ++iter)
|
||
{
|
||
if ((*iter) == _item)
|
||
{
|
||
(*iter) = mLayerItems.back();
|
||
mLayerItems.pop_back();
|
||
return;
|
||
}
|
||
}
|
||
MYGUI_EXCEPT("layer item not found");
|
||
}
|
||
|
||
void LayerNode::outOfDate(RenderItem* _item)
|
||
{
|
||
mOutOfDate = true;
|
||
if (_item)
|
||
_item->outOfDate();
|
||
}
|
||
|
||
EnumeratorILayerNode LayerNode::getEnumerator()
|
||
{
|
||
return EnumeratorILayerNode(mChildItems);
|
||
}
|
||
|
||
void LayerNode::updateCompression()
|
||
{
|
||
// буферы освобождаются по одному всегда
|
||
if (mFirstRenderItems.size() > 1)
|
||
{
|
||
// пытаемся поднять пустой буфер выше полных
|
||
VectorRenderItem::iterator iter1 = mFirstRenderItems.begin();
|
||
VectorRenderItem::iterator iter2 = iter1 + 1;
|
||
while (iter2 != mFirstRenderItems.end())
|
||
{
|
||
if ((*iter1)->getNeedVertexCount() == 0)
|
||
{
|
||
RenderItem * tmp = (*iter1);
|
||
(*iter1) = (*iter2);
|
||
(*iter2) = tmp;
|
||
}
|
||
iter1 = iter2;
|
||
++iter2;
|
||
}
|
||
}
|
||
}
|
||
|
||
void LayerNode::dumpStatisticToLog(size_t _level)
|
||
{
|
||
static const char* spacer = " ";
|
||
std::string offset(" ", _level);
|
||
MYGUI_LOG(Info, offset << " - Node batch_count='" << mFirstRenderItems.size() + mSecondRenderItems.size() << spacer);
|
||
|
||
for (VectorRenderItem::iterator iter=mFirstRenderItems.begin(); iter!=mFirstRenderItems.end(); ++iter)
|
||
{
|
||
MYGUI_LOG(Info, offset << " * Batch texture='" << ((*iter)->getTexture() == nullptr ? "nullptr" : (*iter)->getTexture()->getName()) << "' vertex_count='" << (*iter)->getVertexCount() << "'" << spacer);
|
||
}
|
||
for (VectorRenderItem::iterator iter=mSecondRenderItems.begin(); iter!=mSecondRenderItems.end(); ++iter)
|
||
{
|
||
MYGUI_LOG(Info, offset << " * Batch texture='" << ((*iter)->getTexture() == nullptr ? "nullptr" : (*iter)->getTexture()->getName()) << "' vertex_count='" << (*iter)->getVertexCount() << "'" << spacer);
|
||
}
|
||
|
||
for (VectorILayerNode::iterator iter = mChildItems.begin(); iter!=mChildItems.end(); ++iter)
|
||
{
|
||
(*iter)->dumpStatisticToLog(_level + 1);
|
||
}
|
||
}
|
||
|
||
} // namespace MyGUI
|