1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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.
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/>.
19 #include "property_accessor.h"
21 #include "game_share/object.h"
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)
66 if (attrName
.empty()) return false;
69 CObject
*base
= component
->getAttr("Base");
70 if (!(base
&& base
->isString())) break;
71 std::string strBase
= base
->toString();
72 component
= _Client
->getPaletteElement(strBase
);
75 nlwarning("Can't find base palette element : name = %s", strBase
.c_str());
78 if (component
->getAttr(attrName
)) return true;
83 const CObject
*CPropertyAccessor::getPropertyValue(const CObject
* componentParam
, const std::string
& attrName
) const
85 //H_AUTO(R2_CPropertyAccessor_getPropertyValue)
86 const CObject
* component
= componentParam
;
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
;
100 base
= baseElement
->getAttr("Base");
102 if (base
&& base
->isString())
105 std::string strBase
= base
->toString();
107 baseElement
= _Client
->getPaletteElement(strBase
);
110 nlwarning("Can't find base palette element : name = %s", strBase
.c_str());
113 toRet
= baseElement
->getAttr(attrName
);
117 break; // no more base
122 // Look in baseClass then in baseClass of its BaseClass
124 baseElement
= component
;
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
);
139 nlwarning("Can't find type : name = %s", str
.c_str());
142 toRet
= generator
->getDefaultValue(attrName
);
145 str
= generator
->getBaseClass();
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
;
172 void CPropertyAccessor::getPropertyList(CObject
* component
, std::list
<std::string
>& propertyList
)
174 //H_AUTO(R2_CPropertyAccessor_getPropertyList)
175 std::list
<std::string
> sublist
;
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());
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
;
221 // ... this is a new shadowed value
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
;
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
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
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
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());