MyGUI  3.0.1
MyGUI_LayerNode.cpp
Go to the documentation of this file.
1 
7 /*
8  This file is part of MyGUI.
9 
10  MyGUI is free software: you can redistribute it and/or modify
11  it under the terms of the GNU Lesser General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14 
15  MyGUI is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with MyGUI. If not, see <http://www.gnu.org/licenses/>.
22 */
23 
24 #include "MyGUI_Precompiled.h"
25 #include "MyGUI_LayerNode.h"
26 #include "MyGUI_ILayerItem.h"
27 #include "MyGUI_ITexture.h"
28 #include "MyGUI_ISubWidget.h"
29 #include "MyGUI_ISubWidgetText.h"
30 
31 namespace MyGUI
32 {
33 
34  LayerNode::LayerNode(ILayer* _layer, ILayerNode* _parent) :
35  mParent(_parent),
36  mLayer(_layer),
37  mOutOfDate(false)
38  {
39  }
40 
42  {
43  for (VectorRenderItem::iterator iter=mFirstRenderItems.begin(); iter!=mFirstRenderItems.end(); ++iter)
44  {
45  delete (*iter);
46  }
47  mFirstRenderItems.clear();
48 
49  for (VectorRenderItem::iterator iter=mSecondRenderItems.begin(); iter!=mSecondRenderItems.end(); ++iter)
50  {
51  delete (*iter);
52  }
53  mSecondRenderItems.clear();
54 
55  // удаляем дочерние узлы
56  for (VectorILayerNode::iterator iter = mChildItems.begin(); iter!=mChildItems.end(); ++iter)
57  {
58  delete (*iter);
59  }
60  mChildItems.clear();
61  }
62 
64  {
65  LayerNode* layer = new LayerNode(mLayer, this);
66  mChildItems.push_back(layer);
67  return layer;
68  }
69 
71  {
72  for (VectorILayerNode::iterator iter=mChildItems.begin(); iter!=mChildItems.end(); ++iter)
73  {
74  if ((*iter) == _node)
75  {
76  delete _node;
77  mChildItems.erase(iter);
78  return;
79  }
80  }
81  MYGUI_EXCEPT("item node not found");
82  }
83 
85  {
86  for (VectorILayerNode::iterator iter=mChildItems.begin(); iter!=mChildItems.end(); ++iter)
87  {
88  if ((*iter) == _item)
89  {
90  mChildItems.erase(iter);
91  mChildItems.push_back(_item);
92  return;
93  }
94  }
95  MYGUI_EXCEPT("item node not found");
96  }
97 
98  void LayerNode::renderToTarget(IRenderTarget* _target, bool _update)
99  {
100  // проверяем на сжатие пустот
101  bool need_compression = false;
102  for (VectorRenderItem::iterator iter=mFirstRenderItems.begin(); iter!=mFirstRenderItems.end(); ++iter)
103  {
104  if ((*iter)->getCompression())
105  {
106  need_compression = true;
107  break;
108  }
109  }
110 
111  if (need_compression)
113 
114  // сначала отрисовываем свое
115  for (VectorRenderItem::iterator iter=mFirstRenderItems.begin(); iter!=mFirstRenderItems.end(); ++iter)
116  {
117  (*iter)->renderToTarget(_target, _update);
118  }
119  for (VectorRenderItem::iterator iter=mSecondRenderItems.begin(); iter!=mSecondRenderItems.end(); ++iter)
120  {
121  (*iter)->renderToTarget(_target, _update);
122  }
123 
124  // теперь отрисовываем дочерние узлы
125  for (VectorILayerNode::iterator iter = mChildItems.begin(); iter!=mChildItems.end(); ++iter)
126  {
127  (*iter)->renderToTarget(_target, _update);
128  }
129 
130  mOutOfDate = false;
131  }
132 
134  {
135  // сначала пикаем детей
136  for (VectorILayerNode::iterator iter = mChildItems.begin(); iter!=mChildItems.end(); ++iter)
137  {
138  ILayerItem * item = (*iter)->getLayerItemByPoint(_left, _top);
139  if (nullptr != item) return item;
140  }
141 
142  for (VectorLayerItem::iterator iter=mLayerItems.begin(); iter!=mLayerItems.end(); ++iter)
143  {
144  ILayerItem * item = (*iter)->getLayerItemByPoint(_left, _top);
145  if (nullptr != item) return item;
146  }
147 
148  return nullptr;
149  }
150 
152  {
153  bool first = _item->castType<ISubWidgetText>(false) == nullptr;
154  // для первичной очереди нужен порядок
155  if (first)
156  {
157  if (mFirstRenderItems.empty())
158  {
159  // создаем новый буфер
160  RenderItem * item = new RenderItem();
161  item->setTexture(_texture);
162  mFirstRenderItems.push_back(item);
163 
164  return item;
165  }
166 
167  // если последний буфер пустой, то мона не создавать
168  if (mFirstRenderItems.back()->getNeedVertexCount() == 0)
169  {
170  // пустых может быть сколько угодно, нужен самый первый из пустых
171  for (VectorRenderItem::iterator iter=mFirstRenderItems.begin(); iter!=mFirstRenderItems.end(); ++iter)
172  {
173  if ((*iter)->getNeedVertexCount() == 0)
174  {
175  // а теперь внимание, если перед пустым наш, то его и юзаем
176  if (iter != mFirstRenderItems.begin())
177  {
178  VectorRenderItem::iterator prev = iter - 1;
179  if ((*prev)->getTexture() == _texture)
180  {
181  return (*prev);
182  }
183  }
184  (*iter)->setTexture(_texture);
185  return (*iter);
186  }
187  }
188  }
189 
190  // та же текстура
191  if (mFirstRenderItems.back()->getTexture() == _texture)
192  {
193  return mFirstRenderItems.back();
194  }
195 
196  // создаем новый буфер
197  RenderItem * item = new RenderItem();
198  item->setTexture(_texture);
199  mFirstRenderItems.push_back(item);
200 
201  return item;
202  }
203 
204  // для второй очереди порядок неважен
205  for (VectorRenderItem::iterator iter=mSecondRenderItems.begin(); iter!=mSecondRenderItems.end(); ++iter)
206  {
207  // либо такая же текстура, либо пустой буфер
208  if ((*iter)->getTexture() == _texture)
209  {
210  return (*iter);
211  }
212  else if ((*iter)->getNeedVertexCount() == 0)
213  {
214  (*iter)->setTexture(_texture);
215  return (*iter);
216  }
217 
218  }
219  // не найденно создадим новый
220  RenderItem * item = new RenderItem();
221  item->setTexture(_texture);
222 
223  mSecondRenderItems.push_back(item);
224  return mSecondRenderItems.back();
225  }
226 
228  {
229  mLayerItems.push_back(_item);
230  _item->attachItemToNode(mLayer, this);
231  }
232 
234  {
235  for (VectorLayerItem::iterator iter=mLayerItems.begin(); iter!=mLayerItems.end(); ++iter)
236  {
237  if ((*iter) == _item)
238  {
239  (*iter) = mLayerItems.back();
240  mLayerItems.pop_back();
241  return;
242  }
243  }
244  MYGUI_EXCEPT("layer item not found");
245  }
246 
248  {
249  mOutOfDate = true;
250  if (_item)
251  _item->outOfDate();
252  }
253 
255  {
257  }
258 
260  {
261  // буферы освобождаются по одному всегда
262  if (mFirstRenderItems.size() > 1)
263  {
264  // пытаемся поднять пустой буфер выше полных
265  VectorRenderItem::iterator iter1 = mFirstRenderItems.begin();
266  VectorRenderItem::iterator iter2 = iter1 + 1;
267  while (iter2 != mFirstRenderItems.end())
268  {
269  if ((*iter1)->getNeedVertexCount() == 0)
270  {
271  RenderItem * tmp = (*iter1);
272  (*iter1) = (*iter2);
273  (*iter2) = tmp;
274  }
275  iter1 = iter2;
276  ++iter2;
277  }
278  }
279  }
280 
281  void LayerNode::dumpStatisticToLog(size_t _level)
282  {
283  static const char* spacer = " ";
284  std::string offset(" ", _level);
285  MYGUI_LOG(Info, offset << " - Node batch_count='" << mFirstRenderItems.size() + mSecondRenderItems.size() << spacer);
286 
287  for (VectorRenderItem::iterator iter=mFirstRenderItems.begin(); iter!=mFirstRenderItems.end(); ++iter)
288  {
289  MYGUI_LOG(Info, offset << " * Batch texture='" << ((*iter)->getTexture() == nullptr ? "nullptr" : (*iter)->getTexture()->getName()) << "' vertex_count='" << (*iter)->getVertexCount() << "'" << spacer);
290  }
291  for (VectorRenderItem::iterator iter=mSecondRenderItems.begin(); iter!=mSecondRenderItems.end(); ++iter)
292  {
293  MYGUI_LOG(Info, offset << " * Batch texture='" << ((*iter)->getTexture() == nullptr ? "nullptr" : (*iter)->getTexture()->getName()) << "' vertex_count='" << (*iter)->getVertexCount() << "'" << spacer);
294  }
295 
296  for (VectorILayerNode::iterator iter = mChildItems.begin(); iter!=mChildItems.end(); ++iter)
297  {
298  (*iter)->dumpStatisticToLog(_level + 1);
299  }
300  }
301 
302 } // namespace MyGUI