1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2013 Robert Osfield 2 * 3 * This library is open source and may be redistributed and/or modified under 4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 5 * (at your option) any later version. The full license is in LICENSE file 6 * included with this distribution, and on the openscenegraph.org website. 7 * 8 * This library is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * OpenSceneGraph Public License for more details. 12 */ 13 14 #ifndef LUASCRIPTENGINE_H 15 #define LUASCRIPTENGINE_H 16 17 #include <osg/ScriptEngine> 18 #include <osgDB/ClassInterface> 19 20 extern "C" { 21 #include <lua.h> 22 #include <lualib.h> 23 #include <lauxlib.h> 24 } 25 26 namespace lua 27 { 28 29 // forward declare 30 class LuaScriptEngine; 31 32 struct SerializerScratchPad : public osg::Referenced 33 { deleteDataSerializerScratchPad34 SerializerScratchPad(unsigned int s=256) : deleteData(true), dataType(osgDB::BaseSerializer::RW_UNDEFINED), dataSize(0) { maxDataSize = s; data = new char[s]; } SerializerScratchPadSerializerScratchPad35 SerializerScratchPad(osgDB::BaseSerializer::Type type, const void* ptr, unsigned int s) : deleteData(false), maxDataSize(s), data(const_cast<char*>(reinterpret_cast<const char*>(ptr))), dataType(type),dataSize(s) {} ~SerializerScratchPadSerializerScratchPad36 virtual ~SerializerScratchPad() { if (deleteData && data) delete [] data; } 37 38 bool deleteData; 39 unsigned int maxDataSize; 40 char* data; 41 42 osgDB::BaseSerializer::Type dataType; 43 unsigned int dataSize; 44 resetSerializerScratchPad45 void reset() 46 { 47 dataType = osgDB::BaseSerializer::RW_UNDEFINED; 48 dataSize = 0; 49 } 50 51 template<typename T> setSerializerScratchPad52 bool set(const T& t) 53 { 54 if (sizeof(T)<=maxDataSize) 55 { 56 *(reinterpret_cast<T*>(data)) = t; 57 dataType = osgDB::getTypeEnum<T>(); 58 dataSize = sizeof(T); 59 return true; 60 } 61 else 62 { 63 dataSize = 0; 64 dataType = osgDB::BaseSerializer::RW_UNDEFINED; 65 return false; 66 } 67 } 68 69 template<typename T> getSerializerScratchPad70 bool get(T& t) const 71 { 72 if (sizeof(T)==dataSize && dataType == osgDB::getTypeEnum<T>()) 73 { 74 t = *(reinterpret_cast<T*>(data)); 75 return true; 76 } 77 else 78 { 79 return false; 80 } 81 } 82 }; 83 84 85 class LuaScriptEngine : public osg::ScriptEngine 86 { 87 public: 88 LuaScriptEngine(); 89 LuaScriptEngine(const LuaScriptEngine& rhs, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); 90 META_Object(lua,LuaScriptEngine)91 META_Object(lua, LuaScriptEngine) 92 93 virtual const std::string& getLanguage() const { return _language; } 94 95 /** run a Script.*/ 96 virtual bool run(osg::Script* script, const std::string& entryPoint, osg::Parameters& inputParameters, osg::Parameters& outputParameters); 97 98 /** get the lua_State object.*/ getLuaState()99 lua_State* getLuaState() const { return _lua; } 100 getClassInterface()101 osgDB::ClassInterface& getClassInterface() const { return _ci; } 102 103 int pushDataToStack(SerializerScratchPad* ssp) const; 104 int getDataFromStack(SerializerScratchPad* ssp, osgDB::BaseSerializer::Type type, int pos) const; 105 106 int pushPropertyToStack(osg::Object* object, const std::string& propertyName) const; 107 int setPropertyFromStack(osg::Object* object, const std::string& propertyName) const; 108 int setPropertyFromStack(osg::Object* object, const std::string& propertyName, osgDB::BaseSerializer::Type type) const; 109 110 bool loadScript(osg::Script* script); 111 getAbsolutePos(int pos)112 int getAbsolutePos(int pos) const { return (pos<0) ? (lua_gettop(_lua)+pos+1) : pos; } 113 114 osgDB::BaseSerializer::Type getType(int pos) const; 115 116 bool getfields(int pos, const char* f1, const char* f2, int type) const; 117 bool getfields(int pos, const char* f1, const char* f2, const char* f3, int type) const; 118 bool getfields(int pos, const char* f1, const char* f2, const char* f3, const char* f4, int type) const; 119 bool getfields(int pos, const char* f1, const char* f2, const char* f3, const char* f4, const char* f5, const char* f6, int type) const; 120 bool getelements(int pos, int numElements, int type) const; 121 122 bool getvec2(int pos) const; 123 bool getvec3(int pos) const; 124 bool getvec4(int pos) const; 125 bool getmatrix(int pos) const; 126 bool getboundingbox(int pos) const; 127 bool getboundingsphere(int pos) const; 128 129 bool getValue(int pos, osg::Vec2f& value) const; 130 bool getValue(int pos, osg::Vec3f& value) const; 131 bool getValue(int pos, osg::Vec4f& value) const; 132 133 bool getValue(int pos, osg::Vec2d& value) const; 134 bool getValue(int pos, osg::Vec3d& value) const; 135 bool getValue(int pos, osg::Vec4d& value) const; 136 bool getValue(int pos, osg::Quat& value) const; 137 bool getValue(int pos, osg::Plane& value) const; 138 139 bool getValue(int pos, osg::Matrixf& value) const; 140 bool getValue(int pos, osg::Matrixd& value) const; 141 142 bool getValue(int pos, osg::BoundingBoxf& value) const; 143 bool getValue(int pos, osg::BoundingBoxd& value) const; 144 145 bool getValue(int pos, osg::BoundingSpheref& value) const; 146 bool getValue(int pos, osg::BoundingSphered& value) const; 147 148 void pushValue(osgDB::BaseSerializer::Type type, const void* ptr) const; 149 150 void pushValue(const osg::Vec2f& value) const; 151 void pushValue(const osg::Vec3f& value) const; 152 void pushValue(const osg::Vec4f& value) const; 153 154 void pushValue(const osg::Vec2d& value) const; 155 void pushValue(const osg::Vec3d& value) const; 156 void pushValue(const osg::Vec4d& value) const; 157 void pushValue(const osg::Quat& value) const; 158 void pushValue(const osg::Plane& value) const; 159 160 void pushValue(const osg::Matrixf& value) const; 161 void pushValue(const osg::Matrixd& value) const; 162 163 void pushValue(const osg::BoundingBoxf& value) const; 164 void pushValue(const osg::BoundingBoxd& value) const; 165 166 void pushValue(const osg::BoundingSpheref& value) const; 167 void pushValue(const osg::BoundingSphered& value) const; 168 169 bool pushParameter(osg::Object* object) const; 170 bool popParameter(osg::Object* object) const; 171 osg::Object* popParameterObject() const; 172 173 void pushContainer(osg::Object* object, const std::string& propertyName) const; 174 175 void createAndPushObject(const std::string& compoundName) const; 176 void pushObject(osg::Object* object) const; 177 void pushAndCastObject(const std::string& compoundClassName, osg::Object* object) const; 178 179 template<class T> getObjectFromTable(int pos)180 T* getObjectFromTable(int pos) const 181 { 182 if (lua_type(_lua, pos)==LUA_TTABLE) 183 { 184 lua_pushstring(_lua, "object_ptr"); 185 lua_rawget(_lua, pos); 186 187 osg::Object* object = (lua_type(_lua, -1)==LUA_TUSERDATA)? 188 *const_cast<osg::Object**>(reinterpret_cast<const osg::Object**>(lua_touserdata(_lua,-1))) : 189 0; 190 191 lua_pop(_lua,1); 192 193 return dynamic_cast<T*>(object); 194 } 195 else return 0; 196 } 197 getStringFromTable(int pos,const std::string & field)198 std::string getStringFromTable(int pos, const std::string& field) const 199 { 200 std::string result; 201 if (lua_type(_lua, pos)==LUA_TTABLE) 202 { 203 lua_pushstring(_lua, field.c_str()); 204 lua_rawget(_lua, pos); 205 206 if (lua_type(_lua, -1)==LUA_TSTRING) 207 { 208 result = lua_tostring(_lua, -1); 209 } 210 211 lua_pop(_lua,1); 212 } 213 return result; 214 } 215 getObjectCompoundClassName(int pos)216 std::string getObjectCompoundClassName(int pos) const 217 { 218 if (lua_type(_lua, pos)==LUA_TTABLE) 219 { 220 lua_pushstring(_lua, "compoundClassName"); 221 lua_rawget(_lua, pos); 222 223 std::string compoundClassName = lua_tostring(_lua, -1); 224 225 lua_pop(_lua,1); 226 227 return compoundClassName; 228 } 229 else return std::string(""); 230 } 231 232 void assignClosure(const char* name, lua_CFunction fn) const; 233 matchLuaParameters(int luaType1)234 bool matchLuaParameters(int luaType1) const { return ((lua_gettop(_lua)==1) && (lua_type(_lua, 1)==luaType1)); } matchLuaParameters(int luaType1,int luaType2)235 bool matchLuaParameters(int luaType1, int luaType2) const { return ((lua_gettop(_lua)==2) && (lua_type(_lua, 1)==luaType1) && (lua_type(_lua, 2)==luaType2)); } matchLuaParameters(int luaType1,int luaType2,int luaType3)236 bool matchLuaParameters(int luaType1, int luaType2, int luaType3) const { return ((lua_gettop(_lua)==3) && (lua_type(_lua, 1)==luaType1) && (lua_type(_lua, 2)==luaType2) && (lua_type(_lua, 3)==luaType3)); } matchLuaParameters(int luaType1,int luaType2,int luaType3,int luaType4)237 bool matchLuaParameters(int luaType1, int luaType2, int luaType3, int luaType4) const { return ((lua_gettop(_lua)==4) && (lua_type(_lua, 1)==luaType1) && (lua_type(_lua, 2)==luaType2) && (lua_type(_lua, 3)==luaType3) && (lua_type(_lua, 4)==luaType4)); } 238 239 std::string lookUpGLenumString(GLenum value) const; 240 GLenum lookUpGLenumValue(const std::string& str) const; 241 242 243 void addPaths(const osgDB::FilePathList& paths); 244 void addPaths(const osgDB::Options* options); 245 246 protected: 247 248 void initialize(); 249 250 virtual ~LuaScriptEngine(); 251 252 lua_State* _lua; 253 254 unsigned int _scriptCount; 255 std::string createUniquieScriptName(); 256 257 typedef std::map< osg::ref_ptr<osg::Script>, std::string> ScriptMap; 258 ScriptMap _loadedScripts; 259 260 mutable osgDB::ClassInterface _ci; 261 }; 262 263 264 } 265 266 #endif 267