// Ryzom - MMORPG Framework
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
#include "stdpch.h"
//
#include "instance.h"
//
#include "editor.h"
#include "tool_pick.h"
#include "tool_select_rotate.h"
#include "tool_select_move.h"
//
#include "../entities.h"
#include "../interface_v3/interface_manager.h"
#include "../interface_v3/lua_ihm.h"
//
#include "displayer_visual_entity.h"
using namespace NLMISC;
namespace R2
{
// TMP TMP
#define TEST_LUA_PROJ
//#define TEST_LUA_PROJ nlassert(_ToLua._LuaProjection.isUserData());
// *********************************************************************************************************
/*static*/ void setDisplayedInstance(CDisplayerBase *displayer, CInstance *displayedInstance)
{
displayer->setDisplayedInstance(displayedInstance);
}
// *********************************************************************************************************
CInstance::CInstance(const CObjectTable *objectTable, CLuaState &ls)
{
CLuaStackChecker lsc(&ls);
nlassert(objectTable);
_ObjectTable = objectTable;
// create projection in lua
getEditor().projectInLua(objectTable);
_ToLua._LuaProjection.pop(getEditor().getLua());
TEST_LUA_PROJ;
static volatile bool debugMetatable = false;
if (debugMetatable)
{
_ToLua._LuaProjection.push();
if (!ls.getMetaTable())
{
ls.pop();
nlwarning("No metatable found");
}
else
{
CLuaObject mt(ls);
mt.dump();
}
ls.pop();
}
_Selectable = true;
_LastParentOk = false;
_LastParent = NULL;
_RegisteredInDispNameList = false;
_ClassIndex = getEditor().classToIndex(getClassName());
if (_ClassIndex < 0)
{
nlwarning("Class index not found for '%s'", getClassName().c_str());
}
}
// *********************************************************************************************************
std::string CInstance::getName() const
{
//H_AUTO(R2_CInstance_getName)
TEST_LUA_PROJ;
return getString(_ObjectTable, "Name");
}
// *********************************************************************************************************
std::string CInstance::getPaletteId()
{
//H_AUTO(R2_CInstance_getPaletteId)
TEST_LUA_PROJ;
return getString(_ObjectTable, "Base");
}
// *********************************************************************************************************
ucstring CInstance::getDisplayName()
{
//H_AUTO(R2_CInstance_getDisplayName)
TEST_LUA_PROJ;
CLuaState &ls = getEditor().getLua();
CLuaStackRestorer lsr(&ls, ls.getTop());
if (getLuaProjection()["getDisplayName"].isNil())
{
// object is not displayed -> ignore name
return ucstring("");
}
if (getLuaProjection().callMethodByNameNoThrow("getDisplayName", 0, 1))
{
ucstring result;
if (CLuaIHM::pop(ls, result)) return result;
}
TEST_LUA_PROJ;
return ucstring("Can't find display name");
}
// *********************************************************************************************************
void CInstance::visit(IInstanceVisitor &visitor)
{
//H_AUTO(R2_CInstance_visit)
TEST_LUA_PROJ;
nlassert(_ObjectTable);
// forward object vistor call to 'instance' visitor call
struct CInstanceVisitor : public IObjectVisitor
{
IInstanceVisitor *Visitor;
virtual void visit(CObjectTable &obj)
{
CInstance *inst = getEditor().getInstanceFromObject(&obj);
if (inst)
{
Visitor->visit(*inst);
}
}
};
CInstanceVisitor instanceVisitor;
instanceVisitor.Visitor = &visitor;
const_cast(_ObjectTable)->visit(instanceVisitor); // 'const' is respected here, because CInstanceVisitor gives a reference to CInstance
// which in turn only allow a const reference on CObjectTable
TEST_LUA_PROJ;
}
// *********************************************************************************************************
void CInstance::setDisplayerVisual(CDisplayerVisual *displayer)
{
//H_AUTO(R2_CInstance_setDisplayerVisual)
TEST_LUA_PROJ;
if (_DisplayerVisual)
{
setDisplayedInstance(_DisplayerVisual, NULL);
}
if (displayer)
{
setDisplayedInstance(displayer, this);
}
_DisplayerVisual = displayer;
TEST_LUA_PROJ;
}
// *********************************************************************************************************
CDisplayerVisual *CInstance::getDisplayerVisual() const
{
//H_AUTO(R2_CInstance_getDisplayerVisual)
TEST_LUA_PROJ;
if (!_DisplayerVisual) return NULL;
return NLMISC::safe_cast((CDisplayerBase *)_DisplayerVisual);
}
// *********************************************************************************************************
void CInstance::setDisplayerUI(CDisplayerBase *displayer)
{
//H_AUTO(R2_CInstance_setDisplayerUI)
TEST_LUA_PROJ;
if (_DisplayerUI)
{
setDisplayedInstance(_DisplayerUI, NULL);
}
if (displayer)
{
setDisplayedInstance(displayer, this);
}
_DisplayerUI = displayer;
}
// *********************************************************************************************************
void CInstance::setDisplayerProperties(CDisplayerBase *displayer)
{
//H_AUTO(R2_CInstance_setDisplayerProperties)
TEST_LUA_PROJ;
if (_DisplayerProperties)
{
setDisplayedInstance(_DisplayerProperties, NULL);
}
if (displayer)
{
setDisplayedInstance(displayer, this);
}
_DisplayerProperties = displayer;
}
// *********************************************************************************************************
CInstance::~CInstance()
{
TEST_LUA_PROJ;
setDisplayerVisual(NULL);
setDisplayerUI(NULL);
setDisplayerProperties(NULL);
TEST_LUA_PROJ;
}
// *********************************************************************************************************
void CInstance::onPreActChanged()
{
//H_AUTO(R2_CInstance_onPreActChanged)
TEST_LUA_PROJ;
if (_DisplayerVisual) getDisplayerVisual()->onPreActChanged();
if (_DisplayerUI) _DisplayerUI->onPreActChanged();
if (_DisplayerProperties) _DisplayerProperties->onPreActChanged();
_ToLua.onActChanged();
TEST_LUA_PROJ;
}
// *********************************************************************************************************
void CInstance::onActChanged()
{
//H_AUTO(R2_CInstance_onActChanged)
TEST_LUA_PROJ;
if (_DisplayerVisual) getDisplayerVisual()->onActChanged();
if (_DisplayerUI) _DisplayerUI->onActChanged();
if (_DisplayerProperties) _DisplayerProperties->onActChanged();
_ToLua.onActChanged();
TEST_LUA_PROJ;
refreshDisplayNameHandle();
}
// *********************************************************************************************************
void CInstance::onContinentChanged()
{
//H_AUTO(R2_CInstance_onContinentChanged)
TEST_LUA_PROJ;
if (_DisplayerVisual) getDisplayerVisual()->onContinentChanged();
if (_DisplayerUI) _DisplayerUI->onContinentChanged();
if (_DisplayerProperties) _DisplayerProperties->onContinentChanged();
_ToLua.onContinentChanged();
TEST_LUA_PROJ;
}
// *********************************************************************************************************
void CInstance::onCreate()
{
//H_AUTO(R2_CInstance_onCreate)
TEST_LUA_PROJ;
if (_DisplayerVisual) getDisplayerVisual()->onCreate();
if (_DisplayerUI) _DisplayerUI->onCreate();
if (_DisplayerProperties) _DisplayerProperties->onCreate();
_ToLua.onCreate();
TEST_LUA_PROJ;
}
// *********************************************************************************************************
void CInstance::onPostCreate()
{
//H_AUTO(R2_CInstance_onPostCreate)
TEST_LUA_PROJ;
_LastParentOk = false;
if (_DisplayerVisual) getDisplayerVisual()->onPostCreate();
if (_DisplayerUI) _DisplayerUI->onPostCreate();
if (_DisplayerProperties) _DisplayerProperties->onPostCreate();
_ToLua.onPostCreate();
TEST_LUA_PROJ;
nlassert(!_RegisteredInDispNameList);
getEditor().registerInstanceDispName(getDisplayName(), this);
_RegisteredInDispNameList = true;
}
// *********************************************************************************************************
void CInstance::onErase()
{
//H_AUTO(R2_CInstance_onErase)
TEST_LUA_PROJ;
if (_DisplayerVisual) getDisplayerVisual()->onErase();
if (_DisplayerUI) _DisplayerUI->onErase();
if (_DisplayerProperties) _DisplayerProperties->onErase();
_ToLua.onErase();
TEST_LUA_PROJ;
if (_RegisteredInDispNameList)
{
getEditor().unregisterInstanceDispName(this);
_RegisteredInDispNameList = false;
}
}
// *********************************************************************************************************
void CInstance::refreshDisplayNameHandle()
{
if (_RegisteredInDispNameList)
{
getEditor().unregisterInstanceDispName(this);
getEditor().registerInstanceDispName(getDisplayName(), this);
}
}
// *********************************************************************************************************
void CInstance::onPreHrcMove()
{
//H_AUTO(R2_CInstance_onPreHrcMove)
TEST_LUA_PROJ;
if (_DisplayerVisual) getDisplayerVisual()->onPreHrcMove();
if (_DisplayerUI) _DisplayerUI->onPreHrcMove();
if (_DisplayerProperties) _DisplayerProperties->onPreHrcMove();
_ToLua.onPreHrcMove();
TEST_LUA_PROJ;
}
// *********************************************************************************************************
void CInstance::onPostHrcMove()
{
//H_AUTO(R2_CInstance_onPostHrcMove)
TEST_LUA_PROJ;
_LastParentOk = false;
if (_DisplayerVisual) getDisplayerVisual()->onPostHrcMove();
if (_DisplayerUI) _DisplayerUI->onPostHrcMove();
if (_DisplayerProperties) _DisplayerProperties->onPostHrcMove();
_ToLua.onPostHrcMove();
TEST_LUA_PROJ;
refreshDisplayNameHandle();
}
// *********************************************************************************************************
void CInstance::onFocus(bool highlighted)
{
//H_AUTO(R2_CInstance_onFocus)
TEST_LUA_PROJ;
if (_DisplayerVisual) getDisplayerVisual()->onFocus(highlighted);
if (_DisplayerUI) _DisplayerUI->onFocus(highlighted);
if (_DisplayerProperties) _DisplayerProperties->onFocus(highlighted);
_ToLua.onFocus(highlighted);
TEST_LUA_PROJ;
}
// *********************************************************************************************************
void CInstance::onSelect(bool selected)
{
//H_AUTO(R2_CInstance_onSelect)
TEST_LUA_PROJ;
if (_DisplayerVisual) getDisplayerVisual()->onSelect(selected);
if (_DisplayerUI) _DisplayerUI->onSelect(selected);
if (_DisplayerProperties) _DisplayerProperties->onSelect(selected);
_ToLua.onSelect(selected);
TEST_LUA_PROJ;
}
// *********************************************************************************************************
void CInstance::onAttrModified(const std::string &attrName, sint32 attrIndex)
{
//H_AUTO(R2_CInstance_onAttrModified)
TEST_LUA_PROJ;
if (attrName == "InstanceId")
{
nlwarning("InstanceId modification not allowed !! Please create a new object with a new id");
_Id.clear(); // nevertheless invalidate the cache
}
if (_DisplayerVisual) getDisplayerVisual()->onAttrModified(attrName, attrIndex);
if (_DisplayerUI) _DisplayerUI->onAttrModified(attrName, attrIndex);
if (_DisplayerProperties) _DisplayerProperties->onAttrModified(attrName, attrIndex);
_ToLua.onAttrModified(attrName, attrIndex);
TEST_LUA_PROJ;
if (attrName == "Name" || attrName == "Title")
{
refreshDisplayNameHandle();
}
}
// *********************************************************************************************************
/*void CInstance::onTableModified(const std::string &tableName, const std::string &keyInTable, sint32 indexInTable)
{
if (_DisplayerVisual) getDisplayerVisual()->onTableModified(tableName, keyInTable, indexInTable);
if (_DisplayerUI) _DisplayerUI->onTableModified(tableName, keyInTable, indexInTable);
if (_DisplayerProperties) _DisplayerProperties->onTableModified(tableName, keyInTable, indexInTable);
}*/
// *********************************************************************************************************
void CInstance::onTargetInstanceCreated(const std::string &refMakerAttr, sint32 refMakerAttrIndex)
{
//H_AUTO(R2_CInstance_onTargetInstanceCreated)
TEST_LUA_PROJ;
if (_DisplayerVisual) getDisplayerVisual()->onTargetInstanceCreated(refMakerAttr, refMakerAttrIndex);
if (_DisplayerUI) _DisplayerUI->onTargetInstanceCreated(refMakerAttr, refMakerAttrIndex);
if (_DisplayerProperties) _DisplayerProperties->onTargetInstanceCreated(refMakerAttr, refMakerAttrIndex);
_ToLua.onTargetInstanceCreated(refMakerAttr, refMakerAttrIndex);
TEST_LUA_PROJ;
}
// *********************************************************************************************************
void CInstance::onTargetInstanceErased(const std::string &refMakerAttr, sint32 refMakerAttrIndex)
{
//H_AUTO(R2_CInstance_onTargetInstanceErased)
TEST_LUA_PROJ;
if (_DisplayerVisual) getDisplayerVisual()->onTargetInstanceErased(refMakerAttr, refMakerAttrIndex);
if (_DisplayerUI) _DisplayerUI->onTargetInstanceErased(refMakerAttr, refMakerAttrIndex);
if (_DisplayerProperties) _DisplayerProperties->onTargetInstanceErased(refMakerAttr, refMakerAttrIndex);
_ToLua.onTargetInstanceErased(refMakerAttr, refMakerAttrIndex);
TEST_LUA_PROJ;
}
// *********************************************************************************************************
void CInstance::onTargetInstancePreHrcMove(const std::string &refMakerAttr,sint32 refMakerAttrIndex)
{
//H_AUTO(R2_CInstance_onTargetInstancePreHrcMove)
TEST_LUA_PROJ;
if (_DisplayerVisual) getDisplayerVisual()->onTargetInstancePreHrcMove(refMakerAttr, refMakerAttrIndex);
if (_DisplayerUI) _DisplayerUI->onTargetInstancePreHrcMove(refMakerAttr, refMakerAttrIndex);
if (_DisplayerProperties) _DisplayerProperties->onTargetInstancePreHrcMove(refMakerAttr, refMakerAttrIndex);
_ToLua.onTargetInstancePreHrcMove(refMakerAttr, refMakerAttrIndex);
TEST_LUA_PROJ;
}
// *********************************************************************************************************
void CInstance::onTargetInstancePostHrcMove(const std::string &refMakerAttr,sint32 refMakerAttrIndex)
{
//H_AUTO(R2_CInstance_onTargetInstancePostHrcMove)
TEST_LUA_PROJ;
if (_DisplayerVisual) getDisplayerVisual()->onTargetInstancePostHrcMove(refMakerAttr, refMakerAttrIndex);
if (_DisplayerUI) _DisplayerUI->onTargetInstancePostHrcMove(refMakerAttr, refMakerAttrIndex);
if (_DisplayerProperties) _DisplayerProperties->onTargetInstancePostHrcMove(refMakerAttr, refMakerAttrIndex);
_ToLua.onTargetInstancePostHrcMove(refMakerAttr, refMakerAttrIndex);
TEST_LUA_PROJ;
}
// *********************************************************************************************************
void CInstance::onTargetInstanceEraseRequested(const std::string &refMakerAttr,sint32 refMakerAttrIndex)
{
//H_AUTO(R2_CInstance_onTargetInstanceEraseRequested)
TEST_LUA_PROJ;
// forward to displayer for convenience & legacy code, but should not be handled by displayers ...
if (_DisplayerVisual) getDisplayerVisual()->onTargetInstanceEraseRequested(refMakerAttr, refMakerAttrIndex);
if (_DisplayerUI) _DisplayerUI->onTargetInstanceEraseRequested(refMakerAttr, refMakerAttrIndex);
if (_DisplayerProperties) _DisplayerProperties->onTargetInstanceEraseRequested(refMakerAttr, refMakerAttrIndex);
//
_ToLua.onTargetInstanceEraseRequested(refMakerAttr, refMakerAttrIndex);
TEST_LUA_PROJ;
}
// *********************************************************************************************************
void CInstance::onTargetInstanceAttrModified(const std::string &refMakerAttr, sint32 refMakerAttrIndex, const std::string &targetAttrName, sint32 targetAttrIndex)
{
//H_AUTO(R2_CInstance_onTargetInstanceAttrModified)
TEST_LUA_PROJ;
if (_DisplayerVisual) getDisplayerVisual()->onTargetInstanceAttrModified(refMakerAttr, refMakerAttrIndex, targetAttrName, targetAttrIndex);
if (_DisplayerUI) _DisplayerUI->onTargetInstanceAttrModified(refMakerAttr, refMakerAttrIndex, targetAttrName, targetAttrIndex);
if (_DisplayerProperties) _DisplayerProperties->onTargetInstanceAttrModified(refMakerAttr, refMakerAttrIndex, targetAttrName, targetAttrIndex);
_ToLua.onTargetInstanceAttrModified(refMakerAttr, refMakerAttrIndex, targetAttrName, targetAttrIndex);
TEST_LUA_PROJ;
}
// *********************************************************************************************************
void CInstance::onPreRender()
{
//H_AUTO(R2_CInstance_onPreRender)
TEST_LUA_PROJ;
if (_DisplayerVisual) getDisplayerVisual()->onPreRender();
TEST_LUA_PROJ;
}
// *********************************************************************************************************
void CInstance::onPostRender()
{
//H_AUTO(R2_CInstance_onPostRender)
TEST_LUA_PROJ;
if (_DisplayerVisual) getDisplayerVisual()->onPostRender();
TEST_LUA_PROJ;
}
// *********************************************************************************************************
CLuaObject &CInstance::getLuaProjection()
{
//H_AUTO(R2_CInstance_getLuaProjection)
TEST_LUA_PROJ;
nlassert(_ToLua._LuaProjection.isValid());
TEST_LUA_PROJ;
return _ToLua._LuaProjection;
}
// *********************************************************************************************************
std::string CInstance::getClassName() const
{
//H_AUTO(R2_CInstance_getClassName)
TEST_LUA_PROJ;
return getString(_ObjectTable, "Class");
}
// *********************************************************************************************************
CLuaObject &CInstance::getClass() const
{
//H_AUTO(R2_CInstance_getClass)
TEST_LUA_PROJ;
if (_ToLua._Class.isValid()) return _ToLua._Class;
_ToLua._Class = getEditor().getClasses()[getClassName()];
return _ToLua._Class;
}
// *********************************************************************************************************
TInstanceId CInstance::getId() const
{
//H_AUTO(R2_CInstance_getId)
TEST_LUA_PROJ;
if (!_Id.empty()) return _Id;
nlassert(_ObjectTable);
_Id = getString(_ObjectTable, "InstanceId");
return _Id;
}
// *********************************************************************************************************
CEntityCL *CInstance::getEntity() const
{
//H_AUTO(R2_CInstance_getEntity)
TEST_LUA_PROJ;
CDisplayerVisualEntity *dve = dynamic_cast(getDisplayerVisual());
if (dve)
{
return dve->getEntity();
}
return NULL;
}
// *********************************************************************************************************
std::string CInstance::getSheet() const
{
CDisplayerVisualEntity *dve = dynamic_cast(getDisplayerVisual());
if (dve)
{
return dve->getSheet();
}
return "";
}
// *********************************************************************************************************
CInstance *CInstance::getParent() const
{
//H_AUTO(R2_CInstance_getParent)
TEST_LUA_PROJ;
static volatile bool cacheTest = true;
if (cacheTest)
{
if (_LastParentOk)
{
return _LastParent;
}
}
CInstance *result = NULL;
CObject *currParent = _ObjectTable->getParent();
while (currParent)
{
CInstance *inst = getEditor().getInstanceFromObject(currParent);
if (inst)
{
result = inst;
break;
}
currParent = currParent->getParent();
}
_LastParentOk = true;
_LastParent = result;
return result;
}
// *********************************************************************************************************
bool CInstance::isSonOf(CInstance *other) const
{
//H_AUTO(R2_CInstance_isSonOf)
TEST_LUA_PROJ;
CInstance *curr =this->getParent();
while (curr)
{
if (curr == other) return true;
curr = curr->getParent();
}
return false;
}
// *********************************************************************************************************
bool CInstance::isKindOf(const std::string &className) const
{
//H_AUTO(R2_CInstance_isKindOf)
CEditor &ed = getEditor();
return ed.isKindOf(_ClassIndex, ed.classToIndex(className));
}
// *********************************************************************************************************
CInstance *CInstance::getParentAct() const
{
//H_AUTO(R2_CInstance_getParentAct)
TEST_LUA_PROJ;
CInstance *curr = getParent();
while (curr)
{
if (curr->isKindOf("Act")) return curr;
curr = curr->getParent();
}
return NULL;
}
// *********************************************************************************************************
void CInstance::CToLua::executeHandler(const CLuaString &name, int numArgs)
{
//H_AUTO(R2_CToLua_executeHandler)
CLuaState &ls = getEditor().getLua();
CLuaStackRestorer lsr(&ls, ls.getTop() - numArgs);
//
static volatile bool dumpStackWanted = false;
if (dumpStackWanted) ls.dumpStack();
_Class[name].push();
if (ls.isNil(-1)) return; // not handled
if (dumpStackWanted) ls.dumpStack();
// put method before its args
ls.insert(- numArgs - 1);
if (dumpStackWanted) ls.dumpStack();
// Insert the 'this' as first parameter
_LuaProjection.push();
ls.insert(- numArgs - 1);
//
if (dumpStackWanted) ls.dumpStack();
CLuaIHM::executeFunctionOnStack(ls, numArgs + 1, 0);
if (dumpStackWanted) ls.dumpStack();
}
// *********************************************************************************************************
CLuaState *CInstance::CToLua::getLua()
{
//H_AUTO(R2_CToLua_getLua)
return _LuaProjection.getLuaState();
}
// *********************************************************************************************************
sint CInstance::getSelectedSequence() const
{
//H_AUTO(R2_CInstance_getSelectedSequence)
CLuaObject selected = const_cast(this)->getLuaProjection()["User"]["SelectedSequence"];
sint index = 0;
if (selected.isNumber())
{
index = (sint) selected.toNumber();
}
return index;
}
////////////////
// PROPERTIES //
////////////////
// *********************************************************************************************************
void CInstance::setSelectable(bool selectable)
{
//H_AUTO(R2_CInstance_setSelectable)
TEST_LUA_PROJ;
if (selectable == _Selectable) return;
_Selectable = selectable;
CInstance *selInstance = getEditor().getSelectedInstance();
if (selInstance)
{
if (selInstance && (selInstance == this || selInstance->isSonOf(this)))
{
getEditor().setSelectedInstance(NULL);
}
}
onAttrModified("Selectable");
}
// *********************************************************************************************************
bool CInstance::getSelectableFromRoot() const
{
//H_AUTO(R2_CInstance_getSelectableFromRoot)
TEST_LUA_PROJ;
const CInstance *curr = this;
do
{
if (!curr->getSelectable()) return false;
curr = curr->getParent();
}
while (curr);
return true;
}
// *********************************************************************************************************
void CInstance::dummySetSelectableFromRoot(bool /* selectable */)
{
//H_AUTO(R2_CInstance_dummySetSelectableFromRoot)
nlwarning("SelectableFromRoot is a R/O property");
}
// *********************************************************************************************************
bool CInstance::getGhost() const
{
//H_AUTO(R2_CInstance_getGhost)
TEST_LUA_PROJ;
if (_ObjectTable) return getObjectTable()->getGhost();
return false;
}
// *********************************************************************************************************
void CInstance::setGhost(bool ghost)
{
//H_AUTO(R2_CInstance_setGhost)
TEST_LUA_PROJ;
if (_ObjectTable) getObjectTable()->setGhost(ghost);
}
// *********************************************************************************************************
CInstance *CInstance::getParentGroup()
{
//H_AUTO(R2_CInstance_getParentGroup)
if (isKindOf("NpcGrpFeature")) return this;
if (getParent() && getParent()->isKindOf("NpcGrpFeature"))
{
return getParent();
}
return this;
}
// *********************************************************************************************************
const CInstance *CInstance::getParentGroupLeader() const
{
//H_AUTO(R2_CInstance_getParentGroupLeader)
const CObjectTable *props = NULL;
if (isKindOf("NpcGrpFeature"))
{
props = getObjectTable();
}
else if (getParent() && getParent()->isKindOf("NpcGrpFeature"))
{
props = getParent()->getObjectTable();
}
else
{
return this;
}
if (!props) return NULL;
// this is a group
const CObject *components = props->findAttr("Components");
if (!components || components->getSize() == 0)
{
return NULL;
}
return getEditor().getInstanceFromObject(components->getValue(0));
}
// *********************************************************************************************************
CObject *CInstance::getGroupSelectedSequence() const
{
//H_AUTO(R2_CInstance_getGroupSelectedSequence)
const CInstance *leader = getParentGroupLeader();
if (leader)
{
sint selectedSequence = leader->getSelectedSequence();
const CObject *behav = leader->getObjectTable();
if (behav)
{
behav = behav->findAttr("Behavior");
if (behav)
{
const CObject *activities = behav->findAttr("Activities");
if (activities)
{
if (selectedSequence >= 0 && selectedSequence < (sint) activities->getSize())
{
return activities->getValue((sint32) selectedSequence);
}
}
}
}
}
return NULL;
}
// *********************************************************************************************************
bool CInstance::maxVisibleEntityExceeded() const
{
if (!_DisplayerVisual) return false;
return _DisplayerVisual->maxVisibleEntityExceeded();
}
// *********************************************************************************************************
std::string CInstance::getPosInstanceId() const
{
//H_AUTO(R2_CInstance_getPosInstanceId)
CObject *posObj = getObjectTable()->getAttr("Position");
if (!posObj)
{
nlwarning(" can't retrieve position from object");
return "";
}
return posObj->toString("InstanceId");
}
/////////////////////
// ACTION HANDLERS //
/////////////////////
// *********************************************************************************************************
// Select an instance from its id
class CAHSelectInstance : public IActionHandler
{
virtual void execute(CCtrlBase * /* pCaller */, const std::string &sParams)
{
// retrieve instance from its Id
CInstance *instance = getEditor().getInstanceFromId(sParams);
if(instance != NULL)
{
getEditor().setSelectedInstance(instance);
}
}
};
REGISTER_ACTION_HANDLER(CAHSelectInstance, "r2ed_select_instance");
// *********************************************************************************************************
// Delete selected instance
class CAHDeleteSelectedInstance : public IActionHandler
{
virtual void execute(CCtrlBase * /* pCaller */, const std::string &/* sParams */)
{
CInstance *selectedInstance = getEditor().getSelectedInstance();
if (selectedInstance)
{
getEditor().getDMC().requestEraseNode(selectedInstance->getId(), "", -1);
}
}
};
REGISTER_ACTION_HANDLER(CAHDeleteSelectedInstance, "r2ed_delete_selected_instance");
// *********************************************************************************************************
// handler to pick an instance
class CAHPickerLua : public IActionHandler
{
// TODO nico : replace this action handler by a CTool (in the same way that CToolChoosePosLua derives from CToolChoosePos)
virtual void execute(CCtrlBase * /* pCaller */, const std::string &sParams)
{
// TODO : put this class in a separate file
class CToolPickLua : public CToolPick
{
public:
CToolPickLua() {}
CToolPickLua(const std::string &cursCanPickInstance,
const std::string &cursCannotPickInstance,
const std::string &cursCanPickPos,
const std::string &cursCannotPickPos,
bool wantMouseUp
) : CToolPick(cursCanPickInstance,
cursCannotPickInstance,
cursCanPickPos,
cursCannotPickPos,
wantMouseUp
)
{}
NLMISC_DECLARE_CLASS(CToolPickLua);
void pick(CInstance &instance)
{
CTool::TSmartPtr holdThis(this); // prevent 'setCurrentTool' from deleting 'this'
getEditor().setCurrentTool(NULL);
if (!LuaPickFunc.empty())
{
getEditor().getLua().executeScriptNoThrow(LuaPickFunc + "('" + instance.getId() + "')");
}
}
void pick(const CVector &pos)
{
CTool::TSmartPtr holdThis(this); // prevent 'setCurrentTool' from deleting 'this'
getEditor().setCurrentTool(NULL);
if (!LuaPickPosFunc.empty())
{
getEditor().getLua().executeScriptNoThrow(NLMISC::toString("%s(%f, %f, %f)", LuaPickPosFunc.c_str(), pos.x, pos.y, pos.z));
}
}
bool canPick(const CInstance &instance) const
{
if (LuaPickFunc.empty()) return true;
CLuaState &lua = getEditor().getLua();
int initialSize = lua.getTop();
std::string script = "return " + LuaTestFunc + "('" + instance.getId() + "')";
if (lua.executeScriptNoThrow(script, 1))
{
bool result = lua.toBoolean(initialSize + 1);
lua.setTop(initialSize);
return result;
}
lua.setTop(initialSize);
return false;
}
std::string LuaTestFunc;
std::string LuaPickFunc;
std::string LuaPickPosFunc;
};
std::string cursCanPickInstance = getParam(sParams, "CursCanPickInstance");
std::string cursCannotPickInstance = getParam(sParams, "CursCannotPickInstance");
std::string cursCanPickPos = getParam(sParams, "CursCanPickPos");
std::string cursCannotPickPos = getParam(sParams, "CursCannotPickPos");
std::string wantMouseUp = getParam(sParams, "WantMouseUp");
std::string ignoreInstances = getParam(sParams, "IgnoreInstances");
//
if (cursCanPickInstance.empty()) cursCanPickInstance = "r2ed_tool_can_pick.tga";
if (cursCannotPickInstance.empty()) cursCannotPickInstance = "curs_stop.tga";
if (cursCanPickPos.empty()) cursCanPickPos = "r2ed_tool_pick.tga";
if (cursCannotPickPos.empty()) cursCannotPickPos = "r2ed_tool_pick.tga";
//
CToolPickLua *picker = new CToolPickLua(cursCanPickInstance, cursCannotPickInstance, cursCanPickPos, cursCannotPickPos, wantMouseUp == "true");
picker->LuaTestFunc = getParam(sParams, "TestFunc");
picker->LuaPickFunc = getParam(sParams, "PickFunc");
picker->LuaPickPosFunc = getParam(sParams, "PickPosFunc");
picker->setIgnoreInstances(ignoreInstances);
getEditor().setCurrentTool(picker);
}
};
REGISTER_ACTION_HANDLER(CAHPickerLua, "r2ed_picker_lua");
// *********************************************************************************************************
// rotate
class CAHRotateInstance : public IActionHandler
{
virtual void execute(CCtrlBase * /* pCaller */, const std::string &/* sParams */)
{
getEditor().setCurrentTool(new CToolSelectRotate);
}
};
REGISTER_ACTION_HANDLER(CAHRotateInstance, "r2ed_rotate");
// *********************************************************************************************************
// move
class CAHMoveInstance : public IActionHandler
{
virtual void execute(CCtrlBase * /* pCaller */, const std::string &/* sParams */)
{
getEditor().setCurrentTool(new CToolSelectMove);
}
};
REGISTER_ACTION_HANDLER(CAHMoveInstance, "r2ed_move");
// *********************************************************************************************************
// Debug : dump the lua table for current instance
class CAHDumpLuaTable : public IActionHandler
{
virtual void execute(CCtrlBase * /* pCaller */, const std::string &sParams)
{
if (!getEditor().getSelectedInstance()) return;
std::string maxDepthStr = getParam(sParams, "depth");
uint maxDepth;
if (maxDepthStr.empty())
maxDepth = 20;
else
fromString(maxDepthStr, maxDepth);
// don't want to display the parent
std::set negativeFilter;
if (getEditor().getSelectedInstance()->getParent())
{
negativeFilter.insert(getEditor().getSelectedInstance()->getParent()->getLuaProjection().toPointer());
}
getEditor().getSelectedInstance()->getLuaProjection().dump(30, &negativeFilter);
}
};
REGISTER_ACTION_HANDLER(CAHDumpLuaTable, "r2ed_dump_lua_table");
} // R2