diff --git a/include/osgDB/PropertyInterface b/include/osgDB/PropertyInterface index d34b7407d..ddf4a4459 100644 --- a/include/osgDB/PropertyInterface +++ b/include/osgDB/PropertyInterface @@ -127,7 +127,7 @@ public: /** create an object of specified type for provided compound class name in the form libraryName::className. */ - osg::Object* createObject(const std::string& compounClassdName) const; + osg::Object* createObject(const std::string& compoundClassdName) const; /// template method for getting property data, return true if property available and the type is compatible, otherwise returns false. @@ -152,6 +152,9 @@ public: /// Get the list of of properties supported by object bool getSupportedProperties(const osg::Object* object, PropertyMap& properties, bool searchAssociates=true) const; + /// return true if the object can be cast to the specified class specified by compoundClassName + bool isObjectOfType(const osg::Object* object, const std::string& compoundClassName) const; + /// run method of object bool run(void* objectPtr, const std::string& compoundClassName, const std::string& methodName, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const; diff --git a/src/osgDB/PropertyInterface.cpp b/src/osgDB/PropertyInterface.cpp index ea12e489c..9cd41c940 100644 --- a/src/osgDB/PropertyInterface.cpp +++ b/src/osgDB/PropertyInterface.cpp @@ -520,6 +520,27 @@ bool PropertyInterface::getSupportedProperties(const osg::Object* object, Proper return true; } +bool PropertyInterface::isObjectOfType(const osg::Object* object, const std::string& compoundClassName) const +{ + if (!object) return false; + + if (object->getCompoundClassName()==compoundClassName) return true; + + osgDB::ObjectWrapper* ow = getObjectWrapper(object); + if (!ow) + { + return false; + } + + const osgDB::StringList& associates = ow->getAssociates(); + for(osgDB::StringList::const_iterator aitr = associates.begin(); + aitr != associates.end(); + ++aitr) + { + if ((*aitr)==compoundClassName) return true; + } + return false; +} bool PropertyInterface::run(void* objectPtr, const std::string& compoundClassName, const std::string& methodName, osg::Parameters& inputParameters, osg::Parameters& outputParameters) const { diff --git a/src/osgPlugins/lua/LuaScriptEngine.cpp b/src/osgPlugins/lua/LuaScriptEngine.cpp index ad2ae10e2..9826f4fbc 100644 --- a/src/osgPlugins/lua/LuaScriptEngine.cpp +++ b/src/osgPlugins/lua/LuaScriptEngine.cpp @@ -137,7 +137,8 @@ static int callClassMethod(lua_State* _lua) if (n>=1 && lua_type(_lua, 1)==LUA_TTABLE) { osg::Object* object = lse->getObjectFromTable(1); - OSG_NOTICE<<"callClassMethod() on "<className()<<" method name "<getObjectCompoundClassName(1); // object->getCompoundClassName(); + OSG_NOTICE<<"callClassMethod() on "<className()<<" method name "<popParameterObject()); } -// if (osgDB::MethodsObjectManager::instance()->run(object, object->getCompoundClassName(), methodName, inputParameters, outputParameters)) - if (lse->getPropertyInterface().run(object, object->getCompoundClassName(), methodName, inputParameters, outputParameters)) + if (lse->getPropertyInterface().run(object, compoundClassName, methodName, inputParameters, outputParameters)) { for(osg::Parameters::iterator itr = outputParameters.begin(); itr != outputParameters.end(); @@ -163,106 +163,6 @@ static int callClassMethod(lua_State* _lua) return 0; } -#if 0 -static int getChild(lua_State * _lua) -{ - const LuaScriptEngine* lse = reinterpret_cast(lua_topointer(_lua, lua_upvalueindex(1))); - - int n = lua_gettop(_lua); /* number of arguments */ - if (n==2 && - lua_type(_lua, 1)==LUA_TTABLE && - lua_type(_lua, 2)==LUA_TNUMBER) - { - - osg::Group* group = lse->getObjectFromTable(1); - int index = static_cast(lua_tonumber(_lua, 2)); - if (group) - { - if (index>=0 && index(group->getNumChildren())) - { - lse->pushObject(group->getChild(index)); - return 1; - } - else - { - OSG_NOTICE<<"Warning: child index out of range "<(lua_topointer(_lua, lua_upvalueindex(1))); - - if (lse->matchLuaParameters(LUA_TTABLE, LUA_TNUMBER, LUA_TTABLE)) - { - - osg::Group* group = lse->getObjectFromTable(1); - osg::Node* child = lse->getObjectFromTable(3); - int index = static_cast(lua_tonumber(_lua, 2)); - if (group && child) - { - if (index>=0 && index(group->getNumChildren())) - { - group->setChild(index, child); - return 1; - } - else - { - OSG_NOTICE<<"Warning: child index out of range "<(lua_topointer(_lua, lua_upvalueindex(1))); - - if (lse->matchLuaParameters(LUA_TTABLE, LUA_TTABLE)) - { - osg::Group* group = lse->getObjectFromTable(1); - osg::Node* child = lse->getObjectFromTable(2); - if (group && child) - { - OSG_NOTICE<<"addChild("<className()<<") ptr = "<addChild(child); - return 0; - } - } - - OSG_NOTICE<<"Warning: Lua Group::addChild() parameters not matched"<(lua_topointer(_lua, lua_upvalueindex(1))); - - if (lse->matchLuaParameters(LUA_TTABLE)) - { - osg::Group* group = lse->getObjectFromTable(1); - if (group) - { - lua_pushinteger(_lua, group->getNumChildren()); - return 1; - } - } - - OSG_NOTICE<<"Warning: Lua Group::getNumChildren() not matched"<(lua_topointer(_lua, lua_upvalueindex(1))); + + int n = lua_gettop(_lua); /* number of arguments */ + if (n==2) + { + if (lua_type(_lua, 1)==LUA_TSTRING && lua_type(_lua, 2)==LUA_TTABLE) + { + std::string new_compoundClassName = lua_tostring(_lua, 1); + osg::Object* object = lse->getObjectFromTable(2); + + lse->pushAndCastObject(new_compoundClassName, object); + + return 1; + } + } + return 0; +} + static int readObjectFile(lua_State * _lua) { const LuaScriptEngine* lse = reinterpret_cast(lua_topointer(_lua, lua_upvalueindex(1))); @@ -393,6 +313,13 @@ void LuaScriptEngine::initialize() lua_setglobal(_lua, "new"); } + // provide global new method for casting osg::Object's. + { + lua_pushlightuserdata(_lua, this); + lua_pushcclosure(_lua, castObject, 1); + lua_setglobal(_lua, "cast"); + } + // provide global new method for reading Objects { lua_pushlightuserdata(_lua, this); @@ -1081,6 +1008,7 @@ osgDB::BaseSerializer::Type LuaScriptEngine::getType() const { switch(lua_type(_lua,-1)) { + case(LUA_TNIL): return osgDB::BaseSerializer::RW_UNDEFINED; case(LUA_TNUMBER): return osgDB::BaseSerializer::RW_DOUBLE; case(LUA_TBOOLEAN): return osgDB::BaseSerializer::RW_BOOL; case(LUA_TSTRING): return osgDB::BaseSerializer::RW_STRING; @@ -1603,57 +1531,54 @@ void LuaScriptEngine::pushObject(osg::Object* object) const lua_pushstring(_lua, "libraryName"); lua_pushstring(_lua, object->libraryName()); lua_settable(_lua, -3); lua_pushstring(_lua, "className"); lua_pushstring(_lua, object->className()); lua_settable(_lua, -3); + lua_pushstring(_lua, "compoundClassName"); lua_pushstring(_lua, object->getCompoundClassName().c_str()); lua_settable(_lua, -3); - osg::Group* group = dynamic_cast(object); - osg::Geode* geode = dynamic_cast(object); - if (group) + luaL_getmetatable(_lua, "LuaScriptEngine.Object"); + lua_setmetatable(_lua, -2); + } + else + { + lua_pushnil(_lua); + } +} + +void LuaScriptEngine::pushAndCastObject(const std::string& compoundClassName, osg::Object* object) const +{ + if (object && _pi.isObjectOfType(object, compoundClassName)) + { + lua_newtable(_lua); + + // set up objbect_ptr to handle ref/unref of the object { -#if 0 - assignClosure("getChild", getChild); - assignClosure("setChild", setChild); - assignClosure("addChild", addChild); - assignClosure("getNumChildren", getNumChildren); -#endif -#if 0 - lua_pushstring(_lua, "getChild"); - lua_pushlightuserdata(_lua, const_cast(this)); - lua_pushcclosure(_lua, getChild, 1); + lua_pushstring(_lua, "object_ptr"); + + // create user data for pointer + void* userdata = lua_newuserdata( _lua, sizeof(osg::Object*)); + (*reinterpret_cast(userdata)) = object; + + luaL_getmetatable( _lua, "LuaScriptEngine.UnrefObject"); + lua_setmetatable( _lua, -2 ); + lua_settable(_lua, -3); - lua_pushstring(_lua, "setChild"); - lua_pushlightuserdata(_lua, const_cast(this)); - lua_pushcclosure(_lua, setChild, 1); - lua_settable(_lua, -3); + // increment the reference count as the lua now will unreference it once it's finished with the userdata for the pointer + object->ref(); + } - lua_pushstring(_lua, "addChild"); - lua_pushlightuserdata(_lua, const_cast(this)); - lua_pushcclosure(_lua, addChild, 1); - lua_settable(_lua, -3); + std::string::size_type seperator = compoundClassName.find("::"); + std::string libraryName = (seperator==std::string::npos) ? object->libraryName() : compoundClassName.substr(0, seperator); + std::string className = (seperator==std::string::npos) ? object->className() : compoundClassName.substr(seperator+2,std::string::npos); - lua_pushstring(_lua, "getNumChildren"); - lua_pushlightuserdata(_lua, const_cast(this)); - lua_pushcclosure(_lua, getNumChildren, 1); - lua_settable(_lua, -3); -#endif - luaL_getmetatable(_lua, "LuaScriptEngine.Object"); - lua_setmetatable(_lua, -2); - } - else if (geode) - { -#if 0 - assignClosure("getDrawable",getDrawable,1); - assignClosure("setDrawable",setDrawable,1); - assignClosure("addDrawable",addDrawable,1); - assignClosure("getNumDrawables",getNumDrawables,1); -#endif - luaL_getmetatable(_lua, "LuaScriptEngine.Object"); - lua_setmetatable(_lua, -2); - } - else - { - luaL_getmetatable(_lua, "LuaScriptEngine.Object"); - lua_setmetatable(_lua, -2); - } + + OSG_NOTICE<<"pushAndCastObject("< libraryName="< T* getObjectFromTable(int pos) const @@ -115,6 +116,22 @@ class LuaScriptEngine : public osg::ScriptEngine else return 0; } + std::string getObjectCompoundClassName(int pos) const + { + if (lua_type(_lua, pos)==LUA_TTABLE) + { + lua_pushstring(_lua, "compoundClassName"); + lua_rawget(_lua, pos); + + std::string compoundClassName = lua_tostring(_lua, -1); + + lua_pop(_lua,1); + + return compoundClassName; + } + else return std::string(""); + } + void assignClosure(const char* name, lua_CFunction fn) const; bool matchLuaParameters(int luaType1) const { return ((lua_gettop(_lua)==1) && (lua_type(_lua, 1)==luaType1)); }