Linux multi-monitor fullscreen support
[ryzomcore.git] / ryzom / client / src / r2 / dmc / property_accessor.cpp
blob3a8da702a593bf829fb70382864c7a4845e407e4
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "stdpch.h"
19 #include "property_accessor.h"
20 #include "dmc.h"
21 #include "game_share/object.h"
23 #include <assert.h>
25 #ifdef DEBUG_NEW
26 #define new DEBUG_NEW
27 #endif
29 using namespace R2;
33 CPropertyAccessor::~CPropertyAccessor()
35 purgeShadowedValues();
39 CObject* CPropertyAccessor::getPropertyValue(CObject* component, const std::string& attrName)
41 //H_AUTO(R2_CPropertyAccessor_getPropertyValue)
42 return const_cast<CObject*>(getPropertyValue((const CObject *) component, attrName));
46 double CPropertyAccessor::getValueAsNumber(CObject* component, const std::string& attrName) const
48 //H_AUTO(R2_CPropertyAccessor_getValueAsNumber)
49 const CObject* object=getPropertyValue((const CObject *) component, attrName);
50 if (!object || !object->isNumber()) { return 0; }
51 return object->toNumber();
54 sint64 CPropertyAccessor::getValueAsInteger(CObject* component, const std::string& attrName) const
56 //H_AUTO(R2_CPropertyAccessor_getValueAsInteger)
57 const CObject* object=getPropertyValue((const CObject *) component, attrName);
58 if (!object || !object->isInteger()) { return 0; }
59 return object->toInteger();
62 bool CPropertyAccessor::hasValueInBase(CObject *component, const std::string& attrName)
64 //H_AUTO(R2_CPropertyAccessor_hasValueInBase)
65 nlassert(component);
66 if (attrName.empty()) return false;
67 while (component)
69 CObject *base = component->getAttr("Base");
70 if (!(base && base->isString())) break;
71 std::string strBase = base->toString();
72 component = _Client->getPaletteElement(strBase);
73 if (!component)
75 nlwarning("Can't find base palette element : name = %s", strBase.c_str());
76 break;
78 if (component->getAttr(attrName)) return true;
80 return false;
83 const CObject *CPropertyAccessor::getPropertyValue(const CObject* componentParam, const std::string& attrName) const
85 //H_AUTO(R2_CPropertyAccessor_getPropertyValue)
86 const CObject* component = componentParam;
87 nlassert(component);
88 const CObject* toRet = 0;
89 const CObject* base = 0;
90 const CObject* propClass = 0;
91 const CObject* baseElement = 0;
92 toRet = component->getAttr(attrName);
95 // First look in base and in the base of its base and so and so
96 baseElement = component;
97 while (!toRet )
100 base = baseElement->getAttr("Base");
102 if (base && base->isString())
105 std::string strBase = base->toString();
107 baseElement = _Client->getPaletteElement(strBase);
108 if (!baseElement)
110 nlwarning("Can't find base palette element : name = %s", strBase.c_str());
111 return NULL;
113 toRet = baseElement->getAttr(attrName);
115 else
117 break; // no more base
122 // Look in baseClass then in baseClass of its BaseClass
124 baseElement = component;
125 if (!toRet)
127 propClass = baseElement->getAttr("Class");
128 if (propClass && propClass->isString())
130 std::string str = propClass->toString();
133 while (!toRet && !str.empty())
135 CObjectGenerator* generator = _Factory->getGenerator(str);
137 if (!generator)
139 nlwarning("Can't find type : name = %s", str.c_str());
140 return NULL;
142 toRet = generator->getDefaultValue(attrName);
143 if (!toRet)
145 str = generator->getBaseClass();
147 else
149 str.clear();
157 if (toRet)
159 // see if value is currently shadowed
160 for(std::vector<CShadowedValue>::const_iterator it = _ShadowedValues.begin(); it != _ShadowedValues.end(); ++it)
162 if (it->ShadowedValue == toRet)
164 return it->LocalValue;
168 return toRet;
172 void CPropertyAccessor::getPropertyList(CObject* component, std::list<std::string>& propertyList)
174 //H_AUTO(R2_CPropertyAccessor_getPropertyList)
175 std::list<std::string> sublist;
177 while (component)
179 uint32 first = 0;
180 uint32 last = component->getSize();
182 for ( ; first != last ; ++first)
184 std::list<std::string> props;
185 std::string key = component->getKey(first);
186 props.push_back(key);
188 propertyList.insert(sublist.begin(), sublist.end(), propertyList.begin());
190 CObject* base = component->getAttr("base");
192 if (base && base->isString())
194 component = _Client->getPaletteElement(base->toString());
196 else
198 component = 0;
203 void CPropertyAccessor::shadowValue(CObject *shadowedValue, CObject *localValue)
205 //H_AUTO(R2_CPropertyAccessor_shadowValue)
206 if (!shadowedValue) return;
207 purgeShadowedValues();
208 for(uint k = 0; k < _ShadowedValues.size(); ++k)
210 if (_ShadowedValues[k].ShadowedValue == shadowedValue)
212 // just replacing value for an already shadowed value
213 if (localValue != _ShadowedValues[k].LocalValue)
215 delete _ShadowedValues[k].LocalValue;
216 _ShadowedValues[k].LocalValue = localValue;
218 return;
221 // ... this is a new shadowed value
222 CShadowedValue sv;
223 sv.ShadowedValue = shadowedValue;
224 sv.LocalValue = localValue;
225 _ShadowedValues.push_back(sv);
228 CObject *CPropertyAccessor::getShadowingValue(CObject *shadowedValue)
230 //H_AUTO(R2_CPropertyAccessor_getShadowingValue)
231 if (!shadowedValue) return NULL;
232 purgeShadowedValues();
233 for(uint k = 0; k < _ShadowedValues.size(); ++k)
235 if (_ShadowedValues[k].ShadowedValue == shadowedValue)
237 return _ShadowedValues[k].LocalValue;
240 return NULL;
244 void CPropertyAccessor::commitValue(CObject *shadowedValue)
246 //H_AUTO(R2_CPropertyAccessor_commitValue)
247 for(uint k = 0; k < _ShadowedValues.size(); ++k)
249 if (_ShadowedValues[k].ShadowedValue == shadowedValue)
251 // NB Nico : removed the local copy below because of the new 'instant feddback' mechanism
252 // plus, this introduced a bug where the server command was not sent (because new value & local
253 // value were equal)
255 // copy local value to shadowed value
256 //_ShadowedValues[k].ShadowedValue->inPlaceCopy(*_ShadowedValues[k].LocalValue);
257 _ShadowedValues[k].ShadowedValue = NULL; // delete job done by purgeShadowedValues
258 break;
261 purgeShadowedValues();
264 void CPropertyAccessor::rollbackValue(CObject *shadowedValue)
266 //H_AUTO(R2_CPropertyAccessor_rollbackValue)
267 for(uint k = 0; k < _ShadowedValues.size(); ++k)
269 if (_ShadowedValues[k].ShadowedValue == shadowedValue)
271 _ShadowedValues[k].ShadowedValue = NULL; // delete job done by purgeShadowedValues
272 break;
275 purgeShadowedValues();
279 struct CDeadShadowedObjectReferenceTest
281 bool operator()(const CPropertyAccessor::CShadowedValue &sw) const { return sw.ShadowedValue == NULL; }
284 void CPropertyAccessor::purgeShadowedValues()
286 //H_AUTO(R2_CPropertyAccessor_purgeShadowedValues)
287 for(uint k = 0; k < _ShadowedValues.size(); ++k)
289 if (!_ShadowedValues[k].ShadowedValue)
291 delete _ShadowedValues[k].LocalValue;
292 _ShadowedValues[k].LocalValue = NULL;
295 _ShadowedValues.erase(std::remove_if(_ShadowedValues.begin(), _ShadowedValues.end(), CDeadShadowedObjectReferenceTest()), _ShadowedValues.end());