1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "object_factory_client.h"
24 #include "nel/gui/lua_ihm.h"
25 #include "../interface_v3/lua_ihm_ryzom.h"
36 ///////////////////////////////////////
37 // CObjectRefIdClient implementation //
38 ///////////////////////////////////////
41 // ************************************************************************
42 CObjectRefIdClient::CObjectRefIdClient(const std::string
&value
) : CObjectRefId(""), _ObserverHandle(CEditor::BadInstanceObserverHandle
),
44 _IndexInParentArray(-1),
47 //nlwarning("# Creating CObjectRefIdClient 0x%x", (int) this);
51 // ************************************************************************
52 CObjectRefIdClient::~CObjectRefIdClient()
56 nlassert(getValue().empty() == (_ObserverHandle
== CEditor::BadInstanceObserverHandle
));
57 set("", ""); // force to release the observer
61 // ************************************************************************
62 CObject
* CObjectRefIdClient::clone() const
64 //H_AUTO(R2_CObjectRefIdClient_clone)
65 return new CObjectRefIdClient(getValue());
68 // ************************************************************************
69 void CObjectRefIdClient::enable(bool enabled
)
71 //H_AUTO(R2_CObjectRefIdClient_enable)
72 if (enabled
== _Enabled
) return;
80 removeObserverHandle();
84 // ************************************************************************
85 void CObjectRefIdClient::removeObserverHandle()
87 //H_AUTO(R2_CObjectRefIdClient_removeObserverHandle)
88 if (_ObserverHandle
!= CEditor::BadInstanceObserverHandle
)
90 getEditor().removeInstanceObserver(_ObserverHandle
);
91 _ObserverHandle
= CEditor::BadInstanceObserverHandle
;
95 // ************************************************************************
96 void CObjectRefIdClient::addObserverHandle()
98 //H_AUTO(R2_CObjectRefIdClient_addObserverHandle)
99 if (!getValue().empty())
101 _ObserverHandle
= getEditor().addInstanceObserver(getValue(), this);
105 // ************************************************************************
106 bool CObjectRefIdClient::set(const std::string
&key
, const std::string
& value
)
108 //H_AUTO(R2_CObjectRefIdClient_set)
109 //nlwarning("# Setting CObjectRefIdClient 0x%x value to %s", (int) this, value.c_str());
112 nlassert(getValue().empty() == (_ObserverHandle
== CEditor::BadInstanceObserverHandle
));
114 if (value
== getValue()) return true;
117 removeObserverHandle();
119 bool nodeSet
= CObjectRefId::set(key
, value
);
124 _ObserverHandle
= getEditor().addInstanceObserver(value
, this);
127 nlassert(getValue().empty() == (_ObserverHandle
== CEditor::BadInstanceObserverHandle
));
132 // ************************************************************************
133 void CObjectRefIdClient::onInstanceCreated(CInstance
&/* instance */)
135 //H_AUTO(R2_CObjectRefIdClient_onInstanceCreated)
136 if (!_Enabled
) return;
137 std::string nameInParent
;
139 getNameInParent(nameInParent
, indexInArray
); // parent ptr will be updated
140 if (!_ParentInstance
) return;
141 _ParentInstance
->onTargetInstanceCreated(nameInParent
, indexInArray
);
144 // ************************************************************************
145 void CObjectRefIdClient::onInstanceErased(CInstance
&/* instance */)
147 //H_AUTO(R2_CObjectRefIdClient_onInstanceErased)
148 if (!_Enabled
) return;
149 std::string nameInParent
;
151 getNameInParent(nameInParent
, indexInArray
); // parent ptr will be updated
152 if (!_ParentInstance
) return;
153 _ParentInstance
->onTargetInstanceErased(nameInParent
, indexInArray
);
156 // ************************************************************************
157 void CObjectRefIdClient::onPreHrcMove(CInstance
&/* instance */)
159 //H_AUTO(R2_CObjectRefIdClient_onPreHrcMove)
160 if (!_Enabled
) return;
161 std::string nameInParent
;
163 getNameInParent(nameInParent
, indexInArray
); // parent ptr will be updated
164 if (!_ParentInstance
) return;
165 _ParentInstance
->onTargetInstancePreHrcMove(nameInParent
, indexInArray
);
168 // ************************************************************************
169 void CObjectRefIdClient::onPostHrcMove(CInstance
&/* instance */)
171 //H_AUTO(R2_CObjectRefIdClient_onPostHrcMove)
172 if (!_Enabled
) return;
173 std::string nameInParent
;
175 getNameInParent(nameInParent
, indexInArray
); // parent ptr will be updated
176 if (!_ParentInstance
) return;
177 _ParentInstance
->onTargetInstancePostHrcMove(nameInParent
, indexInArray
);
181 // ************************************************************************
182 void CObjectRefIdClient::onInstanceEraseRequest(CInstance
&/* instance */)
184 //H_AUTO(R2_CObjectRefIdClient_onInstanceEraseRequest)
185 if (!_Enabled
) return;
186 std::string nameInParent
;
188 getNameInParent(nameInParent
, indexInArray
); // parent ptr will be updated
189 if (!_ParentInstance
) return;
190 _ParentInstance
->onTargetInstanceEraseRequested(nameInParent
, indexInArray
);
193 // ************************************************************************
194 void CObjectRefIdClient::onAttrModified(CInstance
&/* instance */, const std::string
&modifiedAttrName
, sint32 modifiedAttrIndexInArray
)
196 //H_AUTO(R2_CObjectRefIdClient_onAttrModified)
197 if (!_Enabled
) return;
198 std::string nameInParent
;
200 getNameInParent(nameInParent
, indexInArray
); // parent ptr will be updated
201 if (!_ParentInstance
) return;
202 _ParentInstance
->onTargetInstanceAttrModified(nameInParent
, indexInArray
, modifiedAttrName
, modifiedAttrIndexInArray
);
205 // ************************************************************************
206 void CObjectRefIdClient::updateParentInstancePtr() const
208 //H_AUTO(R2_CObjectRefIdClient_updateParentInstancePtr)
209 _ParentInstance
= NULL
;
210 CObject
*currParent
= this->getParent();
213 _ParentInstance
= getEditor().getInstanceFromObject(currParent
);
214 if (_ParentInstance
) break;
215 currParent
= currParent
->getParent();
219 // ************************************************************************
220 void CObjectRefIdClient::getNameInParent(std::string
&name
, sint32
&indexInArray
) const
222 //H_AUTO(R2_CObjectRefIdClient_getNameInParent)
223 if (_IndexInParent
!= -1 && _ParentInstance
)
225 CObjectTable
*parentInstanceTable
= _ParentInstance
->getObjectTable();
226 // check that index is still valid (true most of the case unless instance has been moved)
227 if (_IndexInParent
<= (sint32
) parentInstanceTable
->getSize())
229 if (_IndexInParentArray
== -1)
231 if (parentInstanceTable
->getValueAtPos(_IndexInParent
) == static_cast<const CObject
*>(this))
233 name
= parentInstanceTable
->getKey(_IndexInParent
);
240 CObject
*subObject
= parentInstanceTable
->getValueAtPos(_IndexInParent
);
241 if (subObject
->isTable())
243 CObjectTable
*subTable
= (CObjectTable
*) subObject
;
244 if (_IndexInParentArray
< (sint32
) subTable
->getSize())
246 if (subTable
->getValueAtPos(_IndexInParentArray
) == static_cast<const CObject
*>(this))
248 name
= parentInstanceTable
->getKey(_IndexInParent
);
249 indexInArray
= _IndexInParentArray
;
256 // must search name in parent (on init or when object is moved)
257 updateParentInstancePtr();
258 if (!_ParentInstance
)
261 _IndexInParentArray
= -1;
266 CObjectTable
*parentInstanceTable
= _ParentInstance
->getObjectTable();
267 const CObject
*ptrInParent
= (parentInstanceTable
== this->getParent()) ? static_cast<const CObject
*>(this) : this->getParent();
268 // if instance is the direct parent (e.g object is not in an array of the parent)
269 for (uint k
= 0; k
< parentInstanceTable
->getSize(); ++k
)
271 if (parentInstanceTable
->getValueAtPos(k
) == ptrInParent
)
274 if (ptrInParent
== this)
276 _IndexInParentArray
= -1;
278 name
= parentInstanceTable
->getKey(_IndexInParent
);
283 // I'm in an array in my parent, retrieve the index
284 for (uint l
= 0; l
< getParent()->getSize(); ++l
)
286 if (getParent()->getValueAtPos(l
) == static_cast<const CObject
*>(this))
288 name
= parentInstanceTable
->getKey(_IndexInParent
);
289 _IndexInParentArray
= l
;
297 nlwarning("=========================================");
298 CLuaIHMRyzom::dumpCallStack();
299 nlwarning("=========================================");
300 nlwarning("ObservedObject = %s", getValue().c_str());
301 CInstance
*obsInstance
= getEditor().getInstanceFromId(getValue().c_str());
302 nlwarning("ObservedObject instance ptr = %p", obsInstance
);
303 nlwarning("=========================================");
306 obsInstance
->getLuaProjection().dump();
307 CInstance
*parent
= obsInstance
->getParent();
308 nlwarning("ObservedObject parent instance ptr = %p", parent
);
309 parent
->getLuaProjection().dump();
311 nlassert(0); // not found in parent
314 ///////////////////////////////////////
315 // CObjectTableClient implementation //
316 ///////////////////////////////////////
318 // ************************************************************************
319 void CObjectTableClient::pushOnLuaStack(CLuaState
&state
, CLuaObject
&metatable
) const
321 //H_AUTO(R2_CObjectTableClient_pushOnLuaStack)
322 // cache refptr here to avoid costly allocations
323 CLuaStackChecker
lsc(&state
, 1);
326 nlassert(metatable
.isValid());
327 // return a new refptr on the sub table
328 void *block
= state
.newUserData(sizeof(TRefPtrConst
));
334 new (block
) CObjectTable::TRefPtrConst(this); // create in place
337 #define new DEBUG_NEW
341 state
.setMetaTable(-2);
344 nlassert(_Ref
.getLuaState() == &state
);
348 // ************************************************************************
349 CObject
* CObjectTableClient::clone() const
351 //H_AUTO(R2_CObjectTableClient_clone)
352 CObjectTableClient
*ret
= new CObjectTableClient();
353 // NB : don't copy the reference because there can be only one CObjectTableClient per instance (other copy are for undo/redo or network)
354 TContainer::const_iterator
first(_Value
.begin()), last(_Value
.end());
355 for ( ;first
!= last
; ++first
)
357 nlassert(first
->second
);
358 ret
->add(first
->first
, first
->second
->clone());
360 ret
->setGhost(getGhost());
364 // ************************************************************************
365 CObjectTableClient::CObjectTableClient()
369 ///////////////////////////////////////
370 // CClientObjectFactory implementation //
371 ///////////////////////////////////////
373 // ************************************************************************
374 CObject
* CObjectFactoryClient::newBasic(const std::string
& type
)
376 //H_AUTO(R2_CObjectFactoryClient_newBasic)
379 return new CObjectRefIdClient("");
381 else if (type
== "Table")
383 return new CObjectTableClient
;
387 return CObjectFactory::newBasic(type
);
391 // ************************************************************************
392 CObjectFactoryClient::CObjectFactoryClient(const std::string
&prefix
) : CObjectFactory(prefix
)