Merge branch '138-toggle-free-look-with-hotkey' into main/gingo-test
[ryzomcore.git] / ryzom / client / src / r2 / instance.cpp
blob1e2d785d1c81edd8204b65506900833c19f0c39a
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 //
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "stdpch.h"
23 #include "instance.h"
25 #include "editor.h"
26 #include "tool_pick.h"
27 #include "tool_select_rotate.h"
28 #include "tool_select_move.h"
30 #include "../entities.h"
31 #include "../interface_v3/interface_manager.h"
32 #include "nel/gui/lua_ihm.h"
33 #include "../interface_v3/lua_ihm_ryzom.h"
35 #include "displayer_visual_entity.h"
37 #ifdef DEBUG_NEW
38 #define new DEBUG_NEW
39 #endif
41 using namespace NLMISC;
43 namespace R2
47 // TMP TMP
48 #define TEST_LUA_PROJ
49 //#define TEST_LUA_PROJ nlassert(_ToLua._LuaProjection.isUserData());
51 // *********************************************************************************************************
52 /*static*/ void setDisplayedInstance(CDisplayerBase *displayer, CInstance *displayedInstance)
54 displayer->setDisplayedInstance(displayedInstance);
57 // *********************************************************************************************************
58 CInstance::CInstance(const CObjectTable *objectTable, CLuaState &ls)
60 CLuaStackChecker lsc(&ls);
61 nlassert(objectTable);
62 _ObjectTable = objectTable;
63 // create projection in lua
64 getEditor().projectInLua(objectTable);
65 _ToLua._LuaProjection.pop(getEditor().getLua());
66 TEST_LUA_PROJ;
67 static volatile bool debugMetatable = false;
68 if (debugMetatable)
70 _ToLua._LuaProjection.push();
71 if (!ls.getMetaTable())
73 ls.pop();
74 nlwarning("No metatable found");
76 else
78 CLuaObject mt(ls);
79 mt.dump();
81 ls.pop();
83 _Selectable = true;
84 _LastParentOk = false;
85 _LastParent = NULL;
86 _RegisteredInDispNameList = false;
87 _ClassIndex = getEditor().classToIndex(getClassName());
88 if (_ClassIndex < 0)
90 nlwarning("Class index not found for '%s'", getClassName().c_str());
94 // *********************************************************************************************************
95 std::string CInstance::getName() const
97 //H_AUTO(R2_CInstance_getName)
98 TEST_LUA_PROJ;
99 return getString(_ObjectTable, "Name");
102 // *********************************************************************************************************
103 std::string CInstance::getPaletteId()
105 //H_AUTO(R2_CInstance_getPaletteId)
106 TEST_LUA_PROJ;
107 return getString(_ObjectTable, "Base");
110 // *********************************************************************************************************
111 ucstring CInstance::getDisplayName()
113 //H_AUTO(R2_CInstance_getDisplayName)
114 TEST_LUA_PROJ;
115 CLuaState &ls = getEditor().getLua();
116 CLuaStackRestorer lsr(&ls, ls.getTop());
117 if (getLuaProjection()["getDisplayName"].isNil())
119 // object is not displayed -> ignore name
120 return ucstring("");
122 if (getLuaProjection().callMethodByNameNoThrow("getDisplayName", 0, 1))
124 #ifdef RYZOM_LUA_UCSTRING
125 ucstring result;
126 if (CLuaIHM::pop(ls, result)) return result;
127 #else
128 std::string res = ls.toString();
129 ls.pop();
130 if (!res.empty()) return res;
131 #endif
133 TEST_LUA_PROJ;
134 return ucstring("Can't find display name");
137 // *********************************************************************************************************
138 void CInstance::visit(IInstanceVisitor &visitor)
140 //H_AUTO(R2_CInstance_visit)
141 TEST_LUA_PROJ;
142 nlassert(_ObjectTable);
143 // forward object vistor call to 'instance' visitor call
144 struct CInstanceVisitor : public IObjectVisitor
146 IInstanceVisitor *Visitor;
147 virtual void visit(CObjectTable &obj)
149 CInstance *inst = getEditor().getInstanceFromObject(&obj);
150 if (inst)
152 Visitor->visit(*inst);
156 CInstanceVisitor instanceVisitor;
157 instanceVisitor.Visitor = &visitor;
158 const_cast<CObjectTable *>(_ObjectTable)->visit(instanceVisitor); // 'const' is respected here, because CInstanceVisitor gives a reference to CInstance
159 // which in turn only allow a const reference on CObjectTable
160 TEST_LUA_PROJ;
163 // *********************************************************************************************************
164 void CInstance::setDisplayerVisual(CDisplayerVisual *displayer)
166 //H_AUTO(R2_CInstance_setDisplayerVisual)
167 TEST_LUA_PROJ;
168 if (_DisplayerVisual)
170 setDisplayedInstance(_DisplayerVisual, NULL);
172 if (displayer)
174 setDisplayedInstance(displayer, this);
176 _DisplayerVisual = displayer;
177 TEST_LUA_PROJ;
180 // *********************************************************************************************************
181 CDisplayerVisual *CInstance::getDisplayerVisual() const
183 //H_AUTO(R2_CInstance_getDisplayerVisual)
184 TEST_LUA_PROJ;
185 if (!_DisplayerVisual) return NULL;
186 return NLMISC::safe_cast<CDisplayerVisual *>((CDisplayerBase *)_DisplayerVisual);
190 // *********************************************************************************************************
191 void CInstance::setDisplayerUI(CDisplayerBase *displayer)
193 //H_AUTO(R2_CInstance_setDisplayerUI)
194 TEST_LUA_PROJ;
195 if (_DisplayerUI)
197 setDisplayedInstance(_DisplayerUI, NULL);
199 if (displayer)
201 setDisplayedInstance(displayer, this);
203 _DisplayerUI = displayer;
206 // *********************************************************************************************************
207 void CInstance::setDisplayerProperties(CDisplayerBase *displayer)
209 //H_AUTO(R2_CInstance_setDisplayerProperties)
210 TEST_LUA_PROJ;
211 if (_DisplayerProperties)
213 setDisplayedInstance(_DisplayerProperties, NULL);
215 if (displayer)
217 setDisplayedInstance(displayer, this);
219 _DisplayerProperties = displayer;
222 // *********************************************************************************************************
223 CInstance::~CInstance()
225 TEST_LUA_PROJ;
226 setDisplayerVisual(NULL);
227 setDisplayerUI(NULL);
228 setDisplayerProperties(NULL);
229 TEST_LUA_PROJ;
233 // *********************************************************************************************************
234 void CInstance::onPreActChanged()
236 //H_AUTO(R2_CInstance_onPreActChanged)
237 TEST_LUA_PROJ;
238 if (_DisplayerVisual) getDisplayerVisual()->onPreActChanged();
239 if (_DisplayerUI) _DisplayerUI->onPreActChanged();
240 if (_DisplayerProperties) _DisplayerProperties->onPreActChanged();
241 _ToLua.onActChanged();
242 TEST_LUA_PROJ;
245 // *********************************************************************************************************
246 void CInstance::onActChanged()
248 //H_AUTO(R2_CInstance_onActChanged)
249 TEST_LUA_PROJ;
250 if (_DisplayerVisual) getDisplayerVisual()->onActChanged();
251 if (_DisplayerUI) _DisplayerUI->onActChanged();
252 if (_DisplayerProperties) _DisplayerProperties->onActChanged();
253 _ToLua.onActChanged();
254 TEST_LUA_PROJ;
255 refreshDisplayNameHandle();
258 // *********************************************************************************************************
259 void CInstance::onContinentChanged()
261 //H_AUTO(R2_CInstance_onContinentChanged)
262 TEST_LUA_PROJ;
263 if (_DisplayerVisual) getDisplayerVisual()->onContinentChanged();
264 if (_DisplayerUI) _DisplayerUI->onContinentChanged();
265 if (_DisplayerProperties) _DisplayerProperties->onContinentChanged();
266 _ToLua.onContinentChanged();
267 TEST_LUA_PROJ;
271 // *********************************************************************************************************
272 void CInstance::onCreate()
274 //H_AUTO(R2_CInstance_onCreate)
275 TEST_LUA_PROJ;
276 if (_DisplayerVisual) getDisplayerVisual()->onCreate();
277 if (_DisplayerUI) _DisplayerUI->onCreate();
278 if (_DisplayerProperties) _DisplayerProperties->onCreate();
279 _ToLua.onCreate();
280 TEST_LUA_PROJ;
283 // *********************************************************************************************************
284 void CInstance::onPostCreate()
286 //H_AUTO(R2_CInstance_onPostCreate)
287 TEST_LUA_PROJ;
288 _LastParentOk = false;
289 if (_DisplayerVisual) getDisplayerVisual()->onPostCreate();
290 if (_DisplayerUI) _DisplayerUI->onPostCreate();
291 if (_DisplayerProperties) _DisplayerProperties->onPostCreate();
292 _ToLua.onPostCreate();
293 TEST_LUA_PROJ;
294 nlassert(!_RegisteredInDispNameList);
295 getEditor().registerInstanceDispName(getDisplayName(), this);
296 _RegisteredInDispNameList = true;
299 // *********************************************************************************************************
300 void CInstance::onErase()
302 //H_AUTO(R2_CInstance_onErase)
303 TEST_LUA_PROJ;
304 if (_DisplayerVisual) getDisplayerVisual()->onErase();
305 if (_DisplayerUI) _DisplayerUI->onErase();
306 if (_DisplayerProperties) _DisplayerProperties->onErase();
307 _ToLua.onErase();
308 TEST_LUA_PROJ;
309 if (_RegisteredInDispNameList)
311 getEditor().unregisterInstanceDispName(this);
312 _RegisteredInDispNameList = false;
316 // *********************************************************************************************************
317 void CInstance::refreshDisplayNameHandle()
319 if (_RegisteredInDispNameList)
321 getEditor().unregisterInstanceDispName(this);
322 getEditor().registerInstanceDispName(getDisplayName(), this);
326 // *********************************************************************************************************
327 void CInstance::onPreHrcMove()
329 //H_AUTO(R2_CInstance_onPreHrcMove)
330 TEST_LUA_PROJ;
331 if (_DisplayerVisual) getDisplayerVisual()->onPreHrcMove();
332 if (_DisplayerUI) _DisplayerUI->onPreHrcMove();
333 if (_DisplayerProperties) _DisplayerProperties->onPreHrcMove();
334 _ToLua.onPreHrcMove();
335 TEST_LUA_PROJ;
338 // *********************************************************************************************************
339 void CInstance::onPostHrcMove()
341 //H_AUTO(R2_CInstance_onPostHrcMove)
342 TEST_LUA_PROJ;
343 _LastParentOk = false;
344 if (_DisplayerVisual) getDisplayerVisual()->onPostHrcMove();
345 if (_DisplayerUI) _DisplayerUI->onPostHrcMove();
346 if (_DisplayerProperties) _DisplayerProperties->onPostHrcMove();
347 _ToLua.onPostHrcMove();
348 TEST_LUA_PROJ;
349 refreshDisplayNameHandle();
353 // *********************************************************************************************************
354 void CInstance::onFocus(bool highlighted)
356 //H_AUTO(R2_CInstance_onFocus)
357 TEST_LUA_PROJ;
358 if (_DisplayerVisual) getDisplayerVisual()->onFocus(highlighted);
359 if (_DisplayerUI) _DisplayerUI->onFocus(highlighted);
360 if (_DisplayerProperties) _DisplayerProperties->onFocus(highlighted);
361 _ToLua.onFocus(highlighted);
362 TEST_LUA_PROJ;
365 // *********************************************************************************************************
366 void CInstance::onSelect(bool selected)
368 //H_AUTO(R2_CInstance_onSelect)
369 TEST_LUA_PROJ;
370 if (_DisplayerVisual) getDisplayerVisual()->onSelect(selected);
371 if (_DisplayerUI) _DisplayerUI->onSelect(selected);
372 if (_DisplayerProperties) _DisplayerProperties->onSelect(selected);
373 _ToLua.onSelect(selected);
374 TEST_LUA_PROJ;
377 // *********************************************************************************************************
378 void CInstance::onAttrModified(const std::string &attrName, sint32 attrIndex)
380 //H_AUTO(R2_CInstance_onAttrModified)
381 TEST_LUA_PROJ;
382 if (attrName == "InstanceId")
384 nlwarning("InstanceId modification not allowed !! Please create a new object with a new id");
385 _Id.clear(); // nevertheless invalidate the cache
387 if (_DisplayerVisual) getDisplayerVisual()->onAttrModified(attrName, attrIndex);
388 if (_DisplayerUI) _DisplayerUI->onAttrModified(attrName, attrIndex);
389 if (_DisplayerProperties) _DisplayerProperties->onAttrModified(attrName, attrIndex);
390 _ToLua.onAttrModified(attrName, attrIndex);
391 TEST_LUA_PROJ;
392 if (attrName == "Name" || attrName == "Title")
394 refreshDisplayNameHandle();
398 // *********************************************************************************************************
399 /*void CInstance::onTableModified(const std::string &tableName, const std::string &keyInTable, sint32 indexInTable)
401 if (_DisplayerVisual) getDisplayerVisual()->onTableModified(tableName, keyInTable, indexInTable);
402 if (_DisplayerUI) _DisplayerUI->onTableModified(tableName, keyInTable, indexInTable);
403 if (_DisplayerProperties) _DisplayerProperties->onTableModified(tableName, keyInTable, indexInTable);
406 // *********************************************************************************************************
407 void CInstance::onTargetInstanceCreated(const std::string &refMakerAttr, sint32 refMakerAttrIndex)
409 //H_AUTO(R2_CInstance_onTargetInstanceCreated)
410 TEST_LUA_PROJ;
411 if (_DisplayerVisual) getDisplayerVisual()->onTargetInstanceCreated(refMakerAttr, refMakerAttrIndex);
412 if (_DisplayerUI) _DisplayerUI->onTargetInstanceCreated(refMakerAttr, refMakerAttrIndex);
413 if (_DisplayerProperties) _DisplayerProperties->onTargetInstanceCreated(refMakerAttr, refMakerAttrIndex);
414 _ToLua.onTargetInstanceCreated(refMakerAttr, refMakerAttrIndex);
415 TEST_LUA_PROJ;
418 // *********************************************************************************************************
419 void CInstance::onTargetInstanceErased(const std::string &refMakerAttr, sint32 refMakerAttrIndex)
421 //H_AUTO(R2_CInstance_onTargetInstanceErased)
422 TEST_LUA_PROJ;
423 if (_DisplayerVisual) getDisplayerVisual()->onTargetInstanceErased(refMakerAttr, refMakerAttrIndex);
424 if (_DisplayerUI) _DisplayerUI->onTargetInstanceErased(refMakerAttr, refMakerAttrIndex);
425 if (_DisplayerProperties) _DisplayerProperties->onTargetInstanceErased(refMakerAttr, refMakerAttrIndex);
426 _ToLua.onTargetInstanceErased(refMakerAttr, refMakerAttrIndex);
427 TEST_LUA_PROJ;
430 // *********************************************************************************************************
431 void CInstance::onTargetInstancePreHrcMove(const std::string &refMakerAttr,sint32 refMakerAttrIndex)
433 //H_AUTO(R2_CInstance_onTargetInstancePreHrcMove)
434 TEST_LUA_PROJ;
435 if (_DisplayerVisual) getDisplayerVisual()->onTargetInstancePreHrcMove(refMakerAttr, refMakerAttrIndex);
436 if (_DisplayerUI) _DisplayerUI->onTargetInstancePreHrcMove(refMakerAttr, refMakerAttrIndex);
437 if (_DisplayerProperties) _DisplayerProperties->onTargetInstancePreHrcMove(refMakerAttr, refMakerAttrIndex);
438 _ToLua.onTargetInstancePreHrcMove(refMakerAttr, refMakerAttrIndex);
439 TEST_LUA_PROJ;
442 // *********************************************************************************************************
443 void CInstance::onTargetInstancePostHrcMove(const std::string &refMakerAttr,sint32 refMakerAttrIndex)
445 //H_AUTO(R2_CInstance_onTargetInstancePostHrcMove)
446 TEST_LUA_PROJ;
447 if (_DisplayerVisual) getDisplayerVisual()->onTargetInstancePostHrcMove(refMakerAttr, refMakerAttrIndex);
448 if (_DisplayerUI) _DisplayerUI->onTargetInstancePostHrcMove(refMakerAttr, refMakerAttrIndex);
449 if (_DisplayerProperties) _DisplayerProperties->onTargetInstancePostHrcMove(refMakerAttr, refMakerAttrIndex);
450 _ToLua.onTargetInstancePostHrcMove(refMakerAttr, refMakerAttrIndex);
451 TEST_LUA_PROJ;
454 // *********************************************************************************************************
455 void CInstance::onTargetInstanceEraseRequested(const std::string &refMakerAttr,sint32 refMakerAttrIndex)
457 //H_AUTO(R2_CInstance_onTargetInstanceEraseRequested)
458 TEST_LUA_PROJ;
459 // forward to displayer for convenience & legacy code, but should not be handled by displayers ...
460 if (_DisplayerVisual) getDisplayerVisual()->onTargetInstanceEraseRequested(refMakerAttr, refMakerAttrIndex);
461 if (_DisplayerUI) _DisplayerUI->onTargetInstanceEraseRequested(refMakerAttr, refMakerAttrIndex);
462 if (_DisplayerProperties) _DisplayerProperties->onTargetInstanceEraseRequested(refMakerAttr, refMakerAttrIndex);
464 _ToLua.onTargetInstanceEraseRequested(refMakerAttr, refMakerAttrIndex);
465 TEST_LUA_PROJ;
468 // *********************************************************************************************************
469 void CInstance::onTargetInstanceAttrModified(const std::string &refMakerAttr, sint32 refMakerAttrIndex, const std::string &targetAttrName, sint32 targetAttrIndex)
471 //H_AUTO(R2_CInstance_onTargetInstanceAttrModified)
472 TEST_LUA_PROJ;
473 if (_DisplayerVisual) getDisplayerVisual()->onTargetInstanceAttrModified(refMakerAttr, refMakerAttrIndex, targetAttrName, targetAttrIndex);
474 if (_DisplayerUI) _DisplayerUI->onTargetInstanceAttrModified(refMakerAttr, refMakerAttrIndex, targetAttrName, targetAttrIndex);
475 if (_DisplayerProperties) _DisplayerProperties->onTargetInstanceAttrModified(refMakerAttr, refMakerAttrIndex, targetAttrName, targetAttrIndex);
476 _ToLua.onTargetInstanceAttrModified(refMakerAttr, refMakerAttrIndex, targetAttrName, targetAttrIndex);
477 TEST_LUA_PROJ;
480 // *********************************************************************************************************
481 void CInstance::onPreRender()
483 //H_AUTO(R2_CInstance_onPreRender)
484 TEST_LUA_PROJ;
485 if (_DisplayerVisual) getDisplayerVisual()->onPreRender();
486 TEST_LUA_PROJ;
489 // *********************************************************************************************************
490 void CInstance::onPostRender()
492 //H_AUTO(R2_CInstance_onPostRender)
493 TEST_LUA_PROJ;
494 if (_DisplayerVisual) getDisplayerVisual()->onPostRender();
495 TEST_LUA_PROJ;
498 // *********************************************************************************************************
499 CLuaObject &CInstance::getLuaProjection()
501 //H_AUTO(R2_CInstance_getLuaProjection)
502 TEST_LUA_PROJ;
503 nlassert(_ToLua._LuaProjection.isValid());
504 TEST_LUA_PROJ;
505 return _ToLua._LuaProjection;
508 // *********************************************************************************************************
509 std::string CInstance::getClassName() const
511 //H_AUTO(R2_CInstance_getClassName)
512 TEST_LUA_PROJ;
513 return getString(_ObjectTable, "Class");
516 // *********************************************************************************************************
517 CLuaObject &CInstance::getClass() const
519 //H_AUTO(R2_CInstance_getClass)
520 TEST_LUA_PROJ;
521 if (_ToLua._Class.isValid()) return _ToLua._Class;
522 _ToLua._Class = getEditor().getClasses()[getClassName()];
523 return _ToLua._Class;
526 // *********************************************************************************************************
527 TInstanceId CInstance::getId() const
529 //H_AUTO(R2_CInstance_getId)
530 TEST_LUA_PROJ;
531 if (!_Id.empty()) return _Id;
532 nlassert(_ObjectTable);
533 _Id = getString(_ObjectTable, "InstanceId");
534 return _Id;
538 // *********************************************************************************************************
539 CEntityCL *CInstance::getEntity() const
541 //H_AUTO(R2_CInstance_getEntity)
542 TEST_LUA_PROJ;
543 CDisplayerVisualEntity *dve = dynamic_cast<CDisplayerVisualEntity *>(getDisplayerVisual());
544 if (dve)
546 return dve->getEntity();
548 return NULL;
551 // *********************************************************************************************************
552 std::string CInstance::getSheet() const
554 CDisplayerVisualEntity *dve = dynamic_cast<CDisplayerVisualEntity *>(getDisplayerVisual());
555 if (dve)
557 return dve->getSheet();
559 return "";
562 // *********************************************************************************************************
563 CInstance *CInstance::getParent() const
565 //H_AUTO(R2_CInstance_getParent)
566 TEST_LUA_PROJ;
567 static volatile bool cacheTest = true;
568 if (cacheTest)
570 if (_LastParentOk)
572 return _LastParent;
575 CInstance *result = NULL;
576 CObject *currParent = _ObjectTable->getParent();
577 while (currParent)
579 CInstance *inst = getEditor().getInstanceFromObject(currParent);
580 if (inst)
582 result = inst;
583 break;
585 currParent = currParent->getParent();
587 _LastParentOk = true;
588 _LastParent = result;
589 return result;
592 // *********************************************************************************************************
593 bool CInstance::isSonOf(CInstance *other) const
595 //H_AUTO(R2_CInstance_isSonOf)
596 TEST_LUA_PROJ;
597 CInstance *curr =this->getParent();
598 while (curr)
600 if (curr == other) return true;
601 curr = curr->getParent();
603 return false;
606 // *********************************************************************************************************
607 bool CInstance::isKindOf(const std::string &className) const
609 //H_AUTO(R2_CInstance_isKindOf)
610 CEditor &ed = getEditor();
611 return ed.isKindOf(_ClassIndex, ed.classToIndex(className));
614 // *********************************************************************************************************
615 CInstance *CInstance::getParentAct() const
617 //H_AUTO(R2_CInstance_getParentAct)
618 TEST_LUA_PROJ;
619 CInstance *curr = getParent();
620 while (curr)
622 if (curr->isKindOf("Act")) return curr;
623 curr = curr->getParent();
625 return NULL;
628 // *********************************************************************************************************
629 void CInstance::CToLua::executeHandler(const CLuaString &name, int numArgs)
631 //H_AUTO(R2_CToLua_executeHandler)
632 CLuaState &ls = getEditor().getLua();
633 CLuaStackRestorer lsr(&ls, ls.getTop() - numArgs);
635 static volatile bool dumpStackWanted = false;
636 if (dumpStackWanted) ls.dumpStack();
637 _Class[ name.getStr().c_str() ].push();
638 if (ls.isNil(-1)) return; // not handled
639 if (dumpStackWanted) ls.dumpStack();
640 // put method before its args
641 ls.insert(- numArgs - 1);
642 if (dumpStackWanted) ls.dumpStack();
643 // Insert the 'this' as first parameter
644 _LuaProjection.push();
645 ls.insert(- numArgs - 1);
647 if (dumpStackWanted) ls.dumpStack();
648 CLuaIHMRyzom::executeFunctionOnStack(ls, numArgs + 1, 0);
649 if (dumpStackWanted) ls.dumpStack();
652 // *********************************************************************************************************
653 CLuaState *CInstance::CToLua::getLua()
655 //H_AUTO(R2_CToLua_getLua)
656 return _LuaProjection.getLuaState();
660 // *********************************************************************************************************
661 sint CInstance::getSelectedSequence() const
663 //H_AUTO(R2_CInstance_getSelectedSequence)
664 CLuaObject selected = const_cast<CInstance *>(this)->getLuaProjection()["User"]["SelectedSequence"];
665 sint index = 0;
666 if (selected.isInteger())
668 index = (sint) selected.toInteger();
670 return index;
674 ////////////////
675 // PROPERTIES //
676 ////////////////
678 // *********************************************************************************************************
679 void CInstance::setSelectable(bool selectable)
681 //H_AUTO(R2_CInstance_setSelectable)
682 TEST_LUA_PROJ;
683 if (selectable == _Selectable) return;
684 _Selectable = selectable;
685 CInstance *selInstance = getEditor().getSelectedInstance();
686 if (selInstance)
688 if (selInstance && (selInstance == this || selInstance->isSonOf(this)))
690 getEditor().setSelectedInstance(NULL);
693 onAttrModified("Selectable");
696 // *********************************************************************************************************
697 bool CInstance::getSelectableFromRoot() const
699 //H_AUTO(R2_CInstance_getSelectableFromRoot)
700 TEST_LUA_PROJ;
701 const CInstance *curr = this;
704 if (!curr->getSelectable()) return false;
705 curr = curr->getParent();
707 while (curr);
708 return true;
711 // *********************************************************************************************************
712 void CInstance::dummySetSelectableFromRoot(bool /* selectable */)
714 //H_AUTO(R2_CInstance_dummySetSelectableFromRoot)
715 nlwarning("SelectableFromRoot is a R/O property");
718 // *********************************************************************************************************
719 bool CInstance::getGhost() const
721 //H_AUTO(R2_CInstance_getGhost)
722 TEST_LUA_PROJ;
723 if (_ObjectTable) return getObjectTable()->getGhost();
724 return false;
726 // *********************************************************************************************************
727 void CInstance::setGhost(bool ghost)
729 //H_AUTO(R2_CInstance_setGhost)
730 TEST_LUA_PROJ;
731 if (_ObjectTable) getObjectTable()->setGhost(ghost);
734 // *********************************************************************************************************
735 CInstance *CInstance::getParentGroup()
737 //H_AUTO(R2_CInstance_getParentGroup)
738 if (isKindOf("NpcGrpFeature")) return this;
739 if (getParent() && getParent()->isKindOf("NpcGrpFeature"))
741 return getParent();
743 return this;
746 // *********************************************************************************************************
747 const CInstance *CInstance::getParentGroupLeader() const
749 //H_AUTO(R2_CInstance_getParentGroupLeader)
750 const CObjectTable *props = NULL;
751 if (isKindOf("NpcGrpFeature"))
753 props = getObjectTable();
755 else if (getParent() && getParent()->isKindOf("NpcGrpFeature"))
757 props = getParent()->getObjectTable();
759 else
761 return this;
763 if (!props) return NULL;
764 // this is a group
765 const CObject *components = props->findAttr("Components");
766 if (!components || components->getSize() == 0)
768 return NULL;
770 return getEditor().getInstanceFromObject(components->getValueAtPos(0));
773 // *********************************************************************************************************
774 CObject *CInstance::getGroupSelectedSequence() const
776 //H_AUTO(R2_CInstance_getGroupSelectedSequence)
777 const CInstance *leader = getParentGroupLeader();
778 if (leader)
780 sint selectedSequence = leader->getSelectedSequence();
781 const CObject *behav = leader->getObjectTable();
782 if (behav)
784 behav = behav->findAttr("Behavior");
785 if (behav)
787 const CObject *activities = behav->findAttr("Activities");
788 if (activities)
790 if (selectedSequence >= 0 && selectedSequence < (sint) activities->getSize())
792 return activities->getValueAtPos((sint32) selectedSequence);
798 return NULL;
802 // *********************************************************************************************************
803 bool CInstance::maxVisibleEntityExceeded() const
805 if (!_DisplayerVisual) return false;
806 return _DisplayerVisual->maxVisibleEntityExceeded();
809 // *********************************************************************************************************
810 std::string CInstance::getPosInstanceId() const
812 //H_AUTO(R2_CInstance_getPosInstanceId)
813 CObject *posObj = getObjectTable()->getAttr("Position");
814 if (!posObj)
816 nlwarning("<CInstance::getPosInstanceId> can't retrieve position from object");
817 return "";
819 return posObj->toString("InstanceId");
823 /////////////////////
824 // ACTION HANDLERS //
825 /////////////////////
827 // *********************************************************************************************************
828 // Select an instance from its id
829 class CAHSelectInstance : public IActionHandler
831 virtual void execute(CCtrlBase * /* pCaller */, const std::string &sParams)
833 // retrieve instance from its Id
834 CInstance *instance = getEditor().getInstanceFromId(sParams);
835 if(instance != NULL)
837 getEditor().setSelectedInstance(instance);
841 REGISTER_ACTION_HANDLER(CAHSelectInstance, "r2ed_select_instance");
844 // *********************************************************************************************************
845 // Delete selected instance
846 class CAHDeleteSelectedInstance : public IActionHandler
848 virtual void execute(CCtrlBase * /* pCaller */, const std::string &/* sParams */)
850 CInstance *selectedInstance = getEditor().getSelectedInstance();
851 if (selectedInstance)
853 getEditor().getDMC().requestEraseNode(selectedInstance->getId(), "", -1);
857 REGISTER_ACTION_HANDLER(CAHDeleteSelectedInstance, "r2ed_delete_selected_instance");
859 // *********************************************************************************************************
860 // handler to pick an instance
861 class CAHPickerLua : public IActionHandler
863 // TODO nico : replace this action handler by a CTool (in the same way that CToolChoosePosLua derives from CToolChoosePos)
864 virtual void execute(CCtrlBase * /* pCaller */, const std::string &sParams)
866 // TODO : put this class in a separate file
867 class CToolPickLua : public CToolPick
869 public:
870 CToolPickLua() {}
871 CToolPickLua(const std::string &cursCanPickInstance,
872 const std::string &cursCannotPickInstance,
873 const std::string &cursCanPickPos,
874 const std::string &cursCannotPickPos,
875 bool wantMouseUp
876 ) : CToolPick(cursCanPickInstance,
877 cursCannotPickInstance,
878 cursCanPickPos,
879 cursCannotPickPos,
880 wantMouseUp
884 NLMISC_DECLARE_CLASS(CToolPickLua);
885 void pick(CInstance &instance)
887 CTool::TSmartPtr holdThis(this); // prevent 'setCurrentTool' from deleting 'this'
888 getEditor().setCurrentTool(NULL);
889 if (!LuaPickFunc.empty())
891 getEditor().getLua().executeScriptNoThrow(LuaPickFunc + "('" + instance.getId() + "')");
894 void pick(const CVector &pos)
896 CTool::TSmartPtr holdThis(this); // prevent 'setCurrentTool' from deleting 'this'
897 getEditor().setCurrentTool(NULL);
898 if (!LuaPickPosFunc.empty())
900 getEditor().getLua().executeScriptNoThrow(NLMISC::toString("%s(%f, %f, %f)", LuaPickPosFunc.c_str(), pos.x, pos.y, pos.z));
903 bool canPick(const CInstance &instance) const
905 if (LuaPickFunc.empty()) return true;
906 CLuaState &lua = getEditor().getLua();
907 int initialSize = lua.getTop();
908 std::string script = "return " + LuaTestFunc + "('" + instance.getId() + "')";
909 if (lua.executeScriptNoThrow(script, 1))
911 bool result = lua.toBoolean(initialSize + 1);
912 lua.setTop(initialSize);
913 return result;
915 lua.setTop(initialSize);
916 return false;
919 std::string LuaTestFunc;
920 std::string LuaPickFunc;
921 std::string LuaPickPosFunc;
923 std::string cursCanPickInstance = getParam(sParams, "CursCanPickInstance");
924 std::string cursCannotPickInstance = getParam(sParams, "CursCannotPickInstance");
925 std::string cursCanPickPos = getParam(sParams, "CursCanPickPos");
926 std::string cursCannotPickPos = getParam(sParams, "CursCannotPickPos");
927 std::string wantMouseUp = getParam(sParams, "WantMouseUp");
928 std::string ignoreInstances = getParam(sParams, "IgnoreInstances");
930 if (cursCanPickInstance.empty()) cursCanPickInstance = "r2ed_tool_can_pick.tga";
931 if (cursCannotPickInstance.empty()) cursCannotPickInstance = "curs_stop.tga";
932 if (cursCanPickPos.empty()) cursCanPickPos = "r2ed_tool_pick.tga";
933 if (cursCannotPickPos.empty()) cursCannotPickPos = "r2ed_tool_pick.tga";
935 CToolPickLua *picker = new CToolPickLua(cursCanPickInstance, cursCannotPickInstance, cursCanPickPos, cursCannotPickPos, wantMouseUp == "true");
936 picker->LuaTestFunc = getParam(sParams, "TestFunc");
937 picker->LuaPickFunc = getParam(sParams, "PickFunc");
938 picker->LuaPickPosFunc = getParam(sParams, "PickPosFunc");
939 picker->setIgnoreInstances(ignoreInstances);
940 getEditor().setCurrentTool(picker);
943 REGISTER_ACTION_HANDLER(CAHPickerLua, "r2ed_picker_lua");
945 // *********************************************************************************************************
946 // rotate
947 class CAHRotateInstance : public IActionHandler
949 virtual void execute(CCtrlBase * /* pCaller */, const std::string &/* sParams */)
951 getEditor().setCurrentTool(new CToolSelectRotate);
954 REGISTER_ACTION_HANDLER(CAHRotateInstance, "r2ed_rotate");
956 // *********************************************************************************************************
957 // move
958 class CAHMoveInstance : public IActionHandler
960 virtual void execute(CCtrlBase * /* pCaller */, const std::string &/* sParams */)
962 getEditor().setCurrentTool(new CToolSelectMove);
965 REGISTER_ACTION_HANDLER(CAHMoveInstance, "r2ed_move");
969 // *********************************************************************************************************
970 // Debug : dump the lua table for current instance
971 class CAHDumpLuaTable : public IActionHandler
973 virtual void execute(CCtrlBase * /* pCaller */, const std::string &sParams)
975 if (!getEditor().getSelectedInstance()) return;
976 std::string maxDepthStr = getParam(sParams, "depth");
977 uint maxDepth;
978 if (maxDepthStr.empty())
979 maxDepth = 20;
980 else
981 fromString(maxDepthStr, maxDepth);
982 // don't want to display the parent
983 std::set<const void *> negativeFilter;
984 if (getEditor().getSelectedInstance()->getParent())
986 negativeFilter.insert(getEditor().getSelectedInstance()->getParent()->getLuaProjection().toPointer());
988 getEditor().getSelectedInstance()->getLuaProjection().dump(30, &negativeFilter);
991 REGISTER_ACTION_HANDLER(CAHDumpLuaTable, "r2ed_dump_lua_table");
996 } // R2