From 9c53794bc76fd9d2a5a6b5ffaae68c7777069abb Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 9 Oct 2013 15:32:56 +0000 Subject: [PATCH] Implemented preliminary readNode/readImage support in the lua plugin allow a lua script to create a scene graph as return it. --- include/osgDB/PropertyInterface | 18 ++ src/osgDB/PropertyInterface.cpp | 47 +++- src/osgPlugins/lua/LuaScriptEngine.cpp | 373 +++++++++++++++++++++---- src/osgPlugins/lua/LuaScriptEngine.h | 9 +- src/osgPlugins/lua/ReaderWriterLua.cpp | 83 ++++++ 5 files changed, 462 insertions(+), 68 deletions(-) diff --git a/include/osgDB/PropertyInterface b/include/osgDB/PropertyInterface index 34ce1b6f2..37a6cd074 100644 --- a/include/osgDB/PropertyInterface +++ b/include/osgDB/PropertyInterface @@ -174,6 +174,10 @@ protected: bool copyPropertyDataToObject(osg::Object* object, const std::string& propertyName, const void* valuePtr, unsigned int valueSize, osgDB::BaseSerializer::Type valueType); + bool copyPropertyObjectFromObject(const osg::Object* object, const std::string& propertyName, void* valuePtr, unsigned int valueSize, osgDB::BaseSerializer::Type valueType); + + bool copyPropertyObjectToObject(osg::Object* object, const std::string& propertyName, const void* valuePtr, unsigned int valueSize, osgDB::BaseSerializer::Type valueType); + osgDB::ObjectWrapper* getObjectWrapper(const osg::Object* object) const; osgDB::BaseSerializer* getSerializer(const osg::Object* object, const std::string& propertyName, osgDB::BaseSerializer::Type& type) const; @@ -214,6 +218,20 @@ bool PropertyInterface::setProperty(osg::Object* object, const std::string& prop } } +typedef osg::Object* ObjectPtr; + +template<> +inline bool PropertyInterface::getProperty(const osg::Object* object, const std::string& propertyName, ObjectPtr& value) +{ + return copyPropertyObjectFromObject(object, propertyName, &value, sizeof(ObjectPtr), getTypeEnum()); +} + +template<> +inline bool PropertyInterface::setProperty(osg::Object* object, const std::string& propertyName, const ObjectPtr& value) +{ + return copyPropertyObjectToObject(object, propertyName, &value, sizeof(ObjectPtr), getTypeEnum()); +} + } #endif diff --git a/src/osgDB/PropertyInterface.cpp b/src/osgDB/PropertyInterface.cpp index 96fd0945c..eae1a8afc 100644 --- a/src/osgDB/PropertyInterface.cpp +++ b/src/osgDB/PropertyInterface.cpp @@ -294,7 +294,15 @@ bool PropertyInterface::copyPropertyDataFromObject(const osg::Object* object, co osgDB::BaseSerializer::Type sourceType; osgDB::BaseSerializer* serializer = getSerializer(object, propertyName, sourceType); - if (serializer && areTypesCompatible(sourceType, valueType) && serializer->write(_outputStream, *object)) + if (!serializer) return false; + + if (!areTypesCompatible(sourceType, valueType)) + { + OSG_NOTICE<<"PropertyInterface::copyPropertyDataFromObject() Types are not compatible, valueType = "<read(_inputStream, *object); + if (areTypesCompatible(valueType, destinationType)) + { + return serializer->read(_inputStream, *object); + } + else + { + OSG_NOTICE<<"PropertyInterface::copyPropertyDataToObject() Types are not compatible, valueType = "< +#include using namespace lua; @@ -115,14 +116,16 @@ static int newObject(lua_State * _lua) LuaScriptEngine::LuaScriptEngine(): osg::ScriptEngine("lua"), - _lua(0) + _lua(0), + _scriptCount(0) { initialize(); } LuaScriptEngine::LuaScriptEngine(const LuaScriptEngine& rhs, const osg::CopyOp&): osg::ScriptEngine("lua"), - _lua(0) + _lua(0), + _scriptCount(0) { initialize(); } @@ -134,34 +137,61 @@ LuaScriptEngine::~LuaScriptEngine() lua_close(_lua); } +std::string LuaScriptEngine::createUniquieScriptName() +{ + std::stringstream sstr; + sstr<<"script_"<<_scriptCount; + ++_scriptCount; + + OSG_NOTICE<<"uniqueScrtiptName "<getScript().c_str()); if (loadResult==0) { - _loadedScripts.insert(script); + std::string scriptID = createUniquieScriptName(); + + lua_pushvalue(_lua, -1); + lua_setglobal(_lua, scriptID.c_str()); + + _loadedScripts[script] = scriptID; + return true; } else @@ -186,59 +222,79 @@ bool LuaScriptEngine::run(osg::Script* script, const std::string& entryPoint, Pa { if (!script || !_lua) return false; + if (_loadedScripts.count(script)==0) { + OSG_NOTICE<<"Stack before load "<second; + + OSG_NOTICE<<"Stack before pcall "<get()); - } - - if (lua_pcall(_lua, inputParameters.size(), outputParameters.size(),0)!=0) - { - OSG_NOTICE<<"Lua error : "<get()); - } - - return true; } - return false; + + OSG_NOTICE<<"After lua_getglobal Type "<get()); + } + + int topBeforeCall = lua_gettop(_lua); + + if (lua_pcall(_lua, inputParameters.size(), LUA_MULTRET,0)!=0) + { + OSG_NOTICE<<"Lua error : "< obj = popParameterObject(); + if (obj.valid()) outputParameters.push_back(obj); + } + + return true; } @@ -459,6 +515,19 @@ int LuaScriptEngine::pushPropertyToStack(osg::Object* object, const std::string& } break; } + case(osgDB::BaseSerializer::RW_IMAGE): + case(osgDB::BaseSerializer::RW_OBJECT): + { + osg::Object* value = 0; + if (_pi.getProperty(object, propertyName, value)) + { + OSG_NOTICE<<"Sucessful getProperty("<(reinterpret_cast(lua_touserdata(_lua,-1))); + lua_pop(_lua, 1); + + if (value) + { + OSG_NOTICE<<"Assigning property object "<className()<<" to to object "<className()<<"::"<className()<<"::"<className()<<"::"<className()<<"::"< object = 0; + + osgDB::BaseSerializer::Type type = getType(); + switch(type) + { + case(osgDB::BaseSerializer::RW_BOOL): + { + if (lua_isboolean(_lua, -1)) object = new osg::BoolValueObject("", lua_toboolean(_lua, -1)!=0); + break; + } + case(osgDB::BaseSerializer::RW_STRING): + { + if (lua_isstring(_lua, -1)) object = new osg::StringValueObject("", lua_tostring(_lua, -1)); + break; + } + case(osgDB::BaseSerializer::RW_ENUM): + case(osgDB::BaseSerializer::RW_INT): + { + if (lua_isnumber(_lua, -1)) object = new osg::IntValueObject("", static_cast(lua_tonumber(_lua, -1))); + break; + } + case(osgDB::BaseSerializer::RW_UINT): + { + if (lua_isnumber(_lua, -1)) object = new osg::UIntValueObject("", static_cast(lua_tonumber(_lua, -1))); + break; + } + case(osgDB::BaseSerializer::RW_FLOAT): + { + if (lua_isnumber(_lua, -1)) object = new osg::FloatValueObject("", static_cast(lua_tonumber(_lua, -1))); + break; + } + case(osgDB::BaseSerializer::RW_DOUBLE): + { + if (lua_isnumber(_lua, -1)) object = new osg::DoubleValueObject("", static_cast(lua_tonumber(_lua, -1))); + break; + } + case(osgDB::BaseSerializer::RW_VEC2F): + { + osg::Vec2f value; + if (getValue(value)) object = new osg::Vec2fValueObject("", value); + break; + } + case(osgDB::BaseSerializer::RW_VEC3F): + { + osg::Vec3f value; + if (getValue(value)) object = new osg::Vec3fValueObject("", value); + break; + } + case(osgDB::BaseSerializer::RW_VEC4F): + { + osg::Vec4f value; + if (getValue(value)) object = new osg::Vec4fValueObject("", value); + break; + } +#ifdef OSG_USE_FLOAT_MATRIX + case(osgDB::BaseSerializer::RW_MATRIX): +#endif + case(osgDB::BaseSerializer::RW_MATRIXF): + { + osg::Matrixf value; + if (getValue(value)) object = new osg::MatrixfValueObject("", value); + break; + } + case(osgDB::BaseSerializer::RW_VEC2D): + { + osg::Vec2d value; + if (getValue(value)) object = new osg::Vec2dValueObject("", value); + break; + } + case(osgDB::BaseSerializer::RW_VEC3D): + { + osg::Vec3d value; + if (getValue(value)) object = new osg::Vec3dValueObject("", value); + break; + } + case(osgDB::BaseSerializer::RW_VEC4D): + { + osg::Vec4d value; + if (getValue(value)) object = new osg::Vec4dValueObject("", value); + break; + } + case(osgDB::BaseSerializer::RW_QUAT): + { + osg::Quat value; + if (getValue(value)) object = new osg::QuatValueObject("", value); + break; + } + case(osgDB::BaseSerializer::RW_PLANE): + { + osg::Plane value; + if (getValue(value)) object = new osg::PlaneValueObject("", value); + break; + } +#ifndef OSG_USE_FLOAT_MATRIX + case(osgDB::BaseSerializer::RW_MATRIX): +#endif + case(osgDB::BaseSerializer::RW_MATRIXD): + { + osg::Matrixd value; + if (getValue(value)) object = new osg::MatrixdValueObject("", value); + break; + } + case(osgDB::BaseSerializer::RW_IMAGE): + case(osgDB::BaseSerializer::RW_OBJECT): + { + lua_pushstring(_lua, "object_ptr"); + lua_rawget(_lua, -2); + if (lua_type(_lua, -1)==LUA_TUSERDATA) + { + object = *const_cast(reinterpret_cast(lua_touserdata(_lua,-1))); + } + lua_pop(_lua, 1); + } + default: + break; + } + + lua_pop(_lua, 1); + + return object.release(); + +#if 0 + osg::ValueObject* vo = dynamic_cast(object); + if (vo) + { + GetStackValueVisitor pvv(this, -1); + vo->set(pvv); + lua_pop(_lua, pvv._numberToPop); + } + else + { + lua_pop(_lua, 1); + } +#endif + return object.release(); +} + void LuaScriptEngine::createAndPushObject(const std::string& compoundName) const { osg::ref_ptr object = _pi.createObject(compoundName); @@ -1034,8 +1289,6 @@ void LuaScriptEngine::pushObject(osg::Object* object) const { if (object) { - OSG_NOTICE<<"Creating lua object representation for "<getCompoundClassName()< > ScriptSet; - ScriptSet _loadedScripts; + unsigned int _scriptCount; + std::string createUniquieScriptName(); + + typedef std::map< osg::ref_ptr, std::string> ScriptMap; + ScriptMap _loadedScripts; mutable osgDB::PropertyInterface _pi; }; diff --git a/src/osgPlugins/lua/ReaderWriterLua.cpp b/src/osgPlugins/lua/ReaderWriterLua.cpp index 3d38aef87..a1af94c1a 100644 --- a/src/osgPlugins/lua/ReaderWriterLua.cpp +++ b/src/osgPlugins/lua/ReaderWriterLua.cpp @@ -63,6 +63,89 @@ class ReaderWriterLua : public osgDB::ReaderWriter return readObject(istream, options); } + + virtual ReadResult readObjectFromScript(std::istream& fin, const osgDB::ReaderWriter::Options* options =NULL) const + { + ReadResult result = readObject(fin, options); + + if (!result.validObject()) return result; + osg::ref_ptr script = dynamic_cast(result.getObject()); + if (!script) return ReadResult::ERROR_IN_READING_FILE; + + std::string entryPoint = ""; + osg::ScriptEngine::Parameters inputParameters; + osg::ScriptEngine::Parameters outputParameters; + + osg::ref_ptr se = new lua::LuaScriptEngine(); + if (!se->run(script.get(), entryPoint, inputParameters, outputParameters)) return 0; + + if (outputParameters.empty()) return 0; + + typedef std::vector< osg::ref_ptr > Objects; + Objects objects; + + for(osg::ScriptEngine::Parameters::iterator itr = outputParameters.begin(); + itr != outputParameters.end(); + ++itr) + { + osg::Object* object = dynamic_cast(itr->get()); + if (object) objects.push_back(object); + } + + if (objects.empty()) return 0; + + if (objects.size()==1) return objects[0].get(); + + osg::ref_ptr group = new osg::Group; + for(Objects::iterator itr = objects.begin(); + itr != objects.end(); + ++itr) + { + osg::Node* node = dynamic_cast(itr->get()); + if (node) group->addChild(node); + } + + if (group->getNumChildren()>0) return group.get(); + else return 0; + } + + virtual ReadResult readImage(std::istream& fin, const osgDB::ReaderWriter::Options* options =NULL) const + { + return readObjectFromScript(fin, options); + } + + virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options =NULL) const + { + std::string ext = osgDB::getLowerCaseFileExtension(file); + if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; + + std::string fileName = osgDB::findDataFile( file, options ); + if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; + + osgDB::ifstream istream(fileName.c_str(), std::ios::in); + if(!istream) return ReadResult::FILE_NOT_HANDLED; + + return readImage(istream, options); + } + + virtual ReadResult readNode(std::istream& fin, const osgDB::ReaderWriter::Options* options =NULL) const + { + return readObjectFromScript(fin, options); + } + + virtual ReadResult readNode(const std::string& file, const osgDB::ReaderWriter::Options* options =NULL) const + { + std::string ext = osgDB::getLowerCaseFileExtension(file); + if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; + + std::string fileName = osgDB::findDataFile( file, options ); + if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; + + osgDB::ifstream istream(fileName.c_str(), std::ios::in); + if(!istream) return ReadResult::FILE_NOT_HANDLED; + + return readNode(istream, options); + } }; // now register with Registry to instantiate the above