Browse Source

LUA binding. Some additions

Panagiotis Christopoulos Charitos 11 years ago
parent
commit
4cf9ac00cc

+ 4 - 0
include/anki/script/LuaBinder.h

@@ -78,6 +78,10 @@ public:
 	static void pushLuaCFuncStaticMethod(lua_State* l, const char* className,
 		const char* name, lua_CFunction luafunc);
 
+	/// Add a new function.
+	static void pushLuaCFunc(
+		lua_State* l, const char* name, lua_CFunction luafunc);
+
 	/// Get a number from the stack.
 	template<typename TNumber>
 	static ANKI_USE_RESULT Error checkNumber(

+ 7 - 0
src/script/LuaBinder.cpp

@@ -146,6 +146,13 @@ void LuaBinder::pushLuaCFuncStaticMethod(lua_State* l, const char* className,
 	lua_pop(l, 1); // pop cfunc
 }
 
+//==============================================================================
+void LuaBinder::pushLuaCFunc(
+	lua_State* l, const char* name, lua_CFunction luafunc)
+{
+	lua_register(l, name, luafunc);
+}
+
 //==============================================================================
 Error LuaBinder::checkNumberInternal(
 	lua_State* l, I32 stackIdx, lua_Number& number)

+ 54 - 1
src/script/Scene.cpp

@@ -6,8 +6,8 @@
 // WARNING: The file is auto generated.
 
 #include "anki/script/LuaBinder.h"
+#include "anki/script/ScriptManager.h"
 #include "anki/Scene.h"
-#include <utility>
 
 namespace anki {
 
@@ -29,6 +29,17 @@ static T* newSceneNode(SceneGraph* scene, CString name, TArgs... args)
 	}
 }
 
+//==============================================================================
+static SceneGraph* getSceneGraph(lua_State* l)
+{
+	LuaBinder* binder = reinterpret_cast<LuaBinder*>(lua_getuserdata(l));
+
+	ScriptManager* scriptManager = 
+		reinterpret_cast<ScriptManager*>(binder->getParent());
+
+	return &scriptManager->_getSceneGraph();
+}
+
 //==============================================================================
 // MoveComponent                                                               =
 //==============================================================================
@@ -712,6 +723,47 @@ static inline void wrapSceneGraph(lua_State* l)
 	lua_settop(l, 0);
 }
 
+//==============================================================================
+/// Pre-wrap function getSceneGraph.
+static inline int pwrapgetSceneGraph(lua_State* l)
+{
+	UserData* ud;
+	(void)ud;
+	void* voidp;
+	(void)voidp;
+	
+	LuaBinder::checkArgsCount(l, 0);
+	
+	// Call the function
+	SceneGraph* ret = getSceneGraph(l);
+	
+	// Push return value
+	if(ANKI_UNLIKELY(ret == nullptr))
+	{
+		lua_pushstring(l, "Glue code returned nullptr");
+		return -1;
+	}
+	
+	voidp = lua_newuserdata(l, sizeof(UserData));
+	ud = reinterpret_cast<UserData*>(voidp);
+	luaL_setmetatable(l, "SceneGraph");
+	ud->m_data = reinterpret_cast<void*>(ret);
+	ud->m_gc = false;
+	ud->m_sig = -7754439619132389154;
+	
+	return 1;
+}
+
+//==============================================================================
+/// Wrap function getSceneGraph.
+static int wrapgetSceneGraph(lua_State* l)
+{
+	int res = pwrapgetSceneGraph(l);
+	if(res >= 0) return res;
+	lua_error(l);
+	return 0;
+}
+
 //==============================================================================
 /// Wrap the module.
 void wrapModuleScene(lua_State* l)
@@ -721,6 +773,7 @@ void wrapModuleScene(lua_State* l)
 	wrapModelNode(l);
 	wrapInstanceNode(l);
 	wrapSceneGraph(l);
+	LuaBinder::pushLuaCFunc(l, "getSceneGraph", wrapgetSceneGraph);
 }
 
 } // end namespace anki

+ 19 - 1
src/script/Scene.xml

@@ -7,8 +7,8 @@
 // WARNING: The file is auto generated.
 
 #include "anki/script/LuaBinder.h"
+#include "anki/script/ScriptManager.h"
 #include "anki/Scene.h"
-#include <utility>
 
 namespace anki {
 
@@ -28,6 +28,17 @@ static T* newSceneNode(SceneGraph* scene, CString name, TArgs... args)
 	{
 		return nullptr;
 	}
+}
+
+//==============================================================================
+static SceneGraph* getSceneGraph(lua_State* l)
+{
+	LuaBinder* binder = reinterpret_cast<LuaBinder*>(lua_getuserdata(l));
+
+	ScriptManager* scriptManager = 
+		reinterpret_cast<ScriptManager*>(binder->getParent());
+
+	return &scriptManager->_getSceneGraph();
 }]]></head>
 
 	<classes>
@@ -112,6 +123,13 @@ static T* newSceneNode(SceneGraph* scene, CString name, TArgs... args)
 		</class>
 	</classes>
 
+	<functions>
+		<function name="getSceneGraph">
+			<overrideCall>SceneGraph* ret = getSceneGraph(l);</overrideCall>
+			<return>SceneGraph*</return>
+		</function>
+	</functions>
+
 	<tail><![CDATA[} // end namespace anki]]></tail>
 </glue>
 

+ 2 - 61
src/script/ScriptManager.cpp

@@ -6,68 +6,12 @@
 #include "anki/script/ScriptManager.h"
 #include "anki/util/Logger.h"
 
-namespace anki {
-
-//==============================================================================
-
-#if 0
-/// Dummy class
-class Anki
-{};
-
-/// A lua function to check if the user data are not null.
-static int userDataValid(lua_State* l)
-{
-	detail::checkArgsCount(l, 1);
-	detail::UserData* data = (detail::UserData*)lua_touserdata(l, 1);
-
-	if(data == nullptr)
-	{
-		luaL_error(l, "Argument is not user data");
-	}
-	ANKI_ASSERT(data); // This will never happen
-	Bool hasValue = data->m_ptr != nullptr;
-	lua_pushunsigned(l, hasValue);
-	return 1;
-}
-
-/// XXX
-static int getSceneGraph(lua_State* l)
-{
-	LuaBinder* binder = reinterpret_cast<LuaBinder*>(lua_getuserdata(l));
-	ANKI_ASSERT(binder != nullptr);
-
-	ScriptManager* scriptManager = 
-		reinterpret_cast<ScriptManager*>(binder->_getParent());
-
-	ANKI_ASSERT(scriptManager != nullptr);
-
-	detail::UserData* d = reinterpret_cast<detail::UserData*>(
-		lua_newuserdata(l, sizeof(detail::UserData)));
-	luaL_setmetatable(l, "SceneGraph");
-
-	d->m_ptr = &scriptManager->_getSceneGraph();
-	d->m_gc = false;
-
-	return 1;
-}
-
-// Common anki functions
-ANKI_SCRIPT_WRAP(Anki)
-{
-	ANKI_LUA_CLASS_BEGIN_NO_DESTRUCTOR(lb, Anki)
-		detail::pushCFunctionStatic(lb._getLuaState(), "Anki",
-			"userDataValid", &userDataValid);
-		detail::pushCFunctionStatic(lb._getLuaState(), "Anki",
-			"getSceneGraph", &getSceneGraph);
-	ANKI_LUA_CLASS_END()
-}
-#endif
-
 #define ANKI_SCRIPT_CALL_WRAP(type_) \
 	extern void wrap##x(lua_State*); \
 	wrap##x(l);
 
+namespace anki {
+
 //==============================================================================
 ScriptManager::ScriptManager()
 {}
@@ -93,9 +37,6 @@ Error ScriptManager::create(
 
 	// Wrap stuff
 	lua_State* l = m_lua.getLuaState();
-#if 0
-	ANKI_SCRIPT_CALL_WRAP(Anki);
-#endif
 
 	ANKI_SCRIPT_CALL_WRAP(Math);
 	ANKI_SCRIPT_CALL_WRAP(Renderer);

+ 77 - 4
src/script/lua_glue_gen.py

@@ -194,7 +194,7 @@ def arg(arg_txt, stack_index, index):
 			wglue("%s arg%d(*iarg%d);" % (arg_txt, index, index))
 
 
-def args(args_el, stack_index, class_name):
+def args(args_el, stack_index):
 	""" Write the pop code for argument parsing and return the arg list """
 
 	if args_el is None:
@@ -300,7 +300,7 @@ def method(class_name, meth_el):
 	wglue("ANKI_ASSERT(self != nullptr);")
 	wglue("")
 
-	args_str = args(meth_el.find("args"), 2, class_name)
+	args_str = args(meth_el.find("args"), 2)
 
 	# Return value
 	ret_txt = None
@@ -362,7 +362,7 @@ def static_method(class_name, meth_el):
 	check_args(meth_el.find("args"), 0)
 
 	# Args
-	args_str = args(meth_el.find("args"), 1, class_name)
+	args_str = args(meth_el.find("args"), 1)
 	
 	# Return value
 	ret_txt = None
@@ -414,7 +414,7 @@ def constructor(constr_el, class_name):
 	check_args(constr_el.find("args"), 0)
 
 	# Args
-	args_str = args(constr_el.find("args"), 1, class_name)
+	args_str = args(constr_el.find("args"), 1)
 
 	# Create new userdata
 	wglue("// Create user data")
@@ -593,6 +593,67 @@ def class_(class_el):
 	wglue("}")
 	wglue("")
 
+def function(func_el):
+	""" Handle a plain function """
+
+	func_name = func_el.get("name")
+	func_alias = get_meth_alias(func_el)
+
+	global separator
+
+	wglue(separator)
+	wglue("/// Pre-wrap function %s." % func_name)
+	wglue("static inline int pwrap%s(lua_State* l)" % func_alias)
+	wglue("{")
+	ident(1)
+	write_local_vars()
+
+	check_args(func_el.find("args"), 0)
+
+	# Args
+	args_str = args(func_el.find("args"), 1)
+	
+	# Return value
+	ret_txt = None
+	ret_el = func_el.find("return")
+	if ret_el is not None:
+		ret_txt = ret_el.text
+
+	# Call
+	wglue("// Call the function")
+	call = func_el.find("overrideCall")
+	if call is not None:
+		call = call.text
+
+	if call is not None:
+		wglue("%s" % call)
+	else:
+		if ret_txt is None:
+			wglue("%s(%s);" % (func_name, args_str))
+		else:
+			wglue("%s ret = %s(%s);" % (ret_txt, func_name, args_str))
+
+	wglue("")
+	ret(ret_el)
+
+	ident(-1)
+	wglue("}")
+	wglue("")
+
+	# Write the actual function
+	wglue(separator)
+	wglue("/// Wrap function %s." % func_name)
+	wglue("static int wrap%s(lua_State* l)" % func_alias)
+	wglue("{")
+	ident(1)
+	wglue("int res = pwrap%s(l);" % func_alias)
+	wglue("if(res >= 0) return res;")
+	wglue("lua_error(l);")
+	wglue("return 0;")
+	ident(-1)
+	wglue("}")
+	wglue("")
+
 def main():
 	""" Main function """
 
@@ -613,12 +674,21 @@ def main():
 			wglue("%s" % head.text)
 			wglue("")
 
+		# Classes
 		class_names = []
 		for cls in root.iter("classes"):
 			for cl in cls.iter("class"):
 				class_(cl)
 				class_names.append(cl.get("name"))
 
+		# Functions
+		func_names = []
+		for fs in root.iter("functions"):
+			for f in fs.iter("function"):
+				function(f)
+				func_names.append(f.get("name"))
+
+		# Wrap function
 		wglue(separator)
 		wglue("/// Wrap the module.")
 		wglue("void wrapModule%s(lua_State* l)" % get_base_fname(filename))
@@ -626,6 +696,9 @@ def main():
 		ident(1)
 		for class_name in class_names:
 			wglue("wrap%s(l);" % class_name)
+		for func_name in func_names:
+			wglue("LuaBinder::pushLuaCFunc(l, \"%s\", wrap%s);" \
+				% (func_name, func_name))
 		ident(-1)
 		wglue("}")
 		wglue("")