1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-23 02:53:55 +00:00
openmw/extern/mygui_3.0.1/MyGUIEngine/src/MyGUI_LayerNode.cpp

303 lines
8.4 KiB
C++
Raw Normal View History

/*!
@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