MyGUI  3.0.1
MyGUI_ResourceSkin.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 #include "MyGUI_Precompiled.h"
24 #include "MyGUI_ResourceSkin.h"
25 #include "MyGUI_FactoryManager.h"
26 #include "MyGUI_LanguageManager.h"
27 
28 namespace MyGUI
29 {
30 
32  {
33  }
34 
36  {
37  Base::deserialization(_node, _version);
38 
39  // парсим атрибуты скина
40  std::string name, texture, tmp;
41  IntSize size;
42  _node->findAttribute("name", name);
43  _node->findAttribute("texture", texture);
44  if (_node->findAttribute("size", tmp)) size = IntSize::parse(tmp);
45 
47 
48  // вспомогательный класс для биндинга сабскинов
49  SubWidgetBinding bind;
50 
51  // поддержка замены тегов в скинах
52  if (_version >= Version(1, 1))
53  {
54  texture = localizator.replaceTags(texture);
55  }
56 
57  setInfo(size, texture);
58 
59  // проверяем маску
60  if (_node->findAttribute("mask", tmp))
61  {
62  if (!loadMask(tmp))
63  {
64  MYGUI_LOG(Error, "Skin: mask not load '" << tmp << "'");
65  }
66  }
67 
68  // берем детей и крутимся, цикл с саб скинами
70  while (basis.next())
71  {
72  if (basis->getName() == "Property")
73  {
74  // загружаем свойства
75  std::string key, value;
76  if (!basis->findAttribute("key", key)) continue;
77  if (!basis->findAttribute("value", value)) continue;
78 
79  // поддержка замены тегов в скинах
80  if (_version >= Version(1, 1))
81  {
82  value = localizator.replaceTags(value);
83  }
84 
85  // добавляем свойство
86  addProperty(key, value);
87  }
88  else if (basis->getName() == "Child")
89  {
90  ChildSkinInfo child(
91  basis->findAttribute("type"),
92  WidgetStyle::parse(basis->findAttribute("style")),
93  basis->findAttribute("skin"),
94  IntCoord::parse(basis->findAttribute("offset")),
95  Align::parse(basis->findAttribute("align")),
96  basis->findAttribute("layer"),
97  basis->findAttribute("name")
98  );
99 
100  xml::ElementEnumerator child_params = basis->getElementEnumerator();
101  while (child_params.next("Property"))
102  child.addParam(child_params->findAttribute("key"), child_params->findAttribute("value"));
103 
104  addChild(child);
105  //continue;
106  }
107  else if (basis->getName() == "BasisSkin")
108  {
109  // парсим атрибуты
110  std::string basisSkinType, tmp_str;
111  IntCoord offset;
112  Align align = Align::Default;
113  basis->findAttribute("type", basisSkinType);
114  if (basis->findAttribute("offset", tmp_str)) offset = IntCoord::parse(tmp_str);
115  if (basis->findAttribute("align", tmp_str)) align = Align::parse(tmp_str);
116 
117  bind.create(offset, align, basisSkinType);
118 
119  // берем детей и крутимся, цикл со стейтами
121 
122  // проверяем на новый формат стейтов
123  bool new_format = false;
124  // если версия меньше 1.0 то переименовываем стейты
125  if (_version < Version(1, 0))
126  {
127  while (state.next())
128  {
129  if (state->getName() == "State")
130  {
131  const std::string& name_state = state->findAttribute("name");
132  if ((name_state == "normal_checked") || (state->findAttribute("name") == "normal_check"))
133  {
134  new_format = true;
135  break;
136  }
137  }
138  }
139  // обновляем
140  state = basis->getElementEnumerator();
141  }
142 
143  while (state.next())
144  {
145  if (state->getName() == "State")
146  {
147  // парсим атрибуты стейта
148  std::string basisStateName;
149  state->findAttribute("name", basisStateName);
150 
151  // если версия меньше 1.0 то переименовываем стейты
152  if (_version < Version(1, 0))
153  {
154  // это обсолет новых типов
155  if (basisStateName == "disable_check") basisStateName = "disabled_checked";
156  else if (basisStateName == "normal_check") basisStateName = "normal_checked";
157  else if (basisStateName == "active_check") basisStateName = "highlighted_checked";
158  else if (basisStateName == "pressed_check") basisStateName = "pushed_checked";
159  else if (basisStateName == "disable") basisStateName = "disabled";
160  else if (basisStateName == "active") basisStateName = "highlighted";
161  else if (basisStateName == "select") basisStateName = "pushed";
162  else if (basisStateName == "pressed")
163  {
164  if (new_format) basisStateName = "pushed";
165  else basisStateName = "normal_checked";
166  }
167  }
168 
169  // конвертируем инфу о стейте
170  IStateInfo* data = nullptr;
171  IObject* object = FactoryManager::getInstance().createObject("BasisSkin/State", basisSkinType);
172  if (object != nullptr)
173  {
174  data = object->castType<IStateInfo>();
175  data->deserialization(state.current(), _version);
176  }
177 
178  // добавляем инфо о стайте
179  bind.add(basisStateName, data, name);
180  }
181  }
182 
183  // теперь всё вместе добавляем в скин
184  addInfo(bind);
185  }
186 
187  }
188  }
189 
190  void ResourceSkin::setInfo(const IntSize& _size, const std::string &_texture)
191  {
192  mSize = _size;
193  mTexture = _texture;
194  }
195 
196  void ResourceSkin::addInfo(const SubWidgetBinding& _bind)
197  {
198  checkState(_bind.mStates);
199  mBasis.push_back(SubWidgetInfo(_bind.mType, _bind.mOffset, _bind.mAlign));
200  checkBasis();
201  fillState(_bind.mStates, mBasis.size()-1);
202  }
203 
204  void ResourceSkin::addProperty(const std::string &_key, const std::string &_value)
205  {
206  mProperties[_key] = _value;
207  }
208 
209  void ResourceSkin::addChild(const ChildSkinInfo& _child)
210  {
211  mChilds.push_back(_child);
212  }
213 
214  bool ResourceSkin::loadMask(const std::string& _file)
215  {
216  return mMaskPeek.load(_file);
217  }
218 
219  void ResourceSkin::clear()
220  {
221  for (MapWidgetStateInfo::iterator iter = mStates.begin(); iter!=mStates.end(); ++iter)
222  {
223  for (VectorStateInfo::iterator iter2=iter->second.begin(); iter2!=iter->second.end(); ++iter2)
224  {
225  delete *iter2;
226  }
227  }
228  }
229 
230  void ResourceSkin::checkState(const MapStateInfo& _states)
231  {
232  for (MapStateInfo::const_iterator iter = _states.begin(); iter != _states.end(); ++iter)
233  {
234  checkState(iter->first);
235  }
236  }
237 
238  void ResourceSkin::checkState(const std::string& _name)
239  {
240  // ищем такой же ключ
241  MapWidgetStateInfo::const_iterator iter = mStates.find(_name);
242  if (iter == mStates.end())
243  {
244  // добавляем новый стейт
245  mStates[_name] = VectorStateInfo();
246  }
247  }
248 
249  void ResourceSkin::checkBasis()
250  {
251  // и увеличиваем размер смещений по колличеству сабвиджетов
252  for (MapWidgetStateInfo::iterator iter = mStates.begin(); iter!=mStates.end(); ++iter)
253  {
254  iter->second.resize(mBasis.size());
255  }
256  }
257 
258  void ResourceSkin::fillState(const MapStateInfo& _states, size_t _index)
259  {
260  for (MapStateInfo::const_iterator iter = _states.begin(); iter != _states.end(); ++iter)
261  {
262  mStates[iter->first][_index] = iter->second;
263  }
264  }
265 
266 } // namespace MyGUI