Преглед изворни кода

Added support for users to generate Lua script bindings for their own classes (with integration into gameplay).

Chris Culy пре 13 година
родитељ
комит
20afed09b8

+ 22 - 1
gameplay-luagen/README.md

@@ -32,6 +32,28 @@ There are also prebuilt binaries in the gameplay/bin folder.
 - Note: you can't pass an enum to a function that doesn't explicitly take an enum (i.e. Control::setTextColor, which takes an unsigned char). In these cases, you need to go look up the enum values and pass them directly.
 
 
+## Generating Script Bindings for Your Own Project
+
+Note: This requires doxygen to be installed.
+
+1. Copy the gameplay-luagen.doxyfile file to your project's root directory (and rename it). Then, either manually using a text editor or using the Doxywizard tool, go to the INPUT section and ensure both that the path to gameplay's 'src' folder is valid (relative to where the doxyfile is) and that your own source folder is added.
+
+2. Run doxygen using the above doxyfile from your project's root directory. For example, run 'doxygen my-project.doxyfile' from the command line or run Doxygen using the Doxywizard application.
+
+3. Create a 'lua' folder inside your source folder.
+
+4. Run gameplay-luagen using the following command (make sure you have a trailing '/' for the output directory (second) parameter):
+    "path-to-gameplay/bin/your-platform/gameplay-luagen.exe" ./xml path-to-your-source/lua/ <your-project-name-here>
+    
+    Note: The parameter <your-project-name-here> is used as the namespace that the bindings are generated within. This can be anything you want *except* for "gameplay".
+    
+5. Ensure that your project has "path-to-gameplay/gameplay/src/lua" in its include path.
+
+6. Add the generated Lua script files from path-to-your-source/lua to your project.
+
+7. Compile and run - now you can use your own classes from Lua scripts
+
+
 ## Unsupported Features
 - operators
 - templates
@@ -40,7 +62,6 @@ There are also prebuilt binaries in the gameplay/bin folder.
 
 
 ### To Do List
-- Add support for users to generate bindings for their own classes.
 - Look into updating bindValue() to support binding to any Lua script function.
 - Add a global function that implements casting for use from Lua scripts (i.e. to downcast from a Control to a Button).
 - Currently ignored: there is one memory leak in gameplay-luagen that is very difficult to fix (it appears to be a locale related leak-something leaks the first time an ofstream is created-doesn't matter the ofstream).

+ 6 - 0
gameplay-luagen/gameplay-luagen.vcxproj

@@ -123,6 +123,12 @@
       <Message>
       </Message>
     </CustomBuildStep>
+    <PostBuildEvent>
+      <Command>copy $(TargetPath) $(ProjectDir)..\bin\win32\$(TargetFileName)</Command>
+    </PostBuildEvent>
+    <PostBuildEvent>
+      <Message>Copying executable to bin/win32 folder ...</Message>
+    </PostBuildEvent>
   </ItemDefinitionGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">

+ 2 - 2
gameplay-luagen/gameplay-luagen.vcxproj.user

@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LocalDebuggerCommandArguments>"$(ProjectDir)xml/" "$(ProjectDir)../gameplay/src/lua/"</LocalDebuggerCommandArguments>
+    <LocalDebuggerCommandArguments>"$(ProjectDir)xml/" "$(ProjectDir)../gameplay/src/lua/" gameplay</LocalDebuggerCommandArguments>
     <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
     <LocalDebuggerCommand>$(TargetPath)</LocalDebuggerCommand>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LocalDebuggerCommandArguments>"$(ProjectDir)xml/" "$(ProjectDir)../gameplay/src/lua/"</LocalDebuggerCommandArguments>
+    <LocalDebuggerCommandArguments>"$(ProjectDir)xml/" "$(ProjectDir)../gameplay/src/lua/" gameplay</LocalDebuggerCommandArguments>
     <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
     <LocalDebuggerCommand>$(TargetPath)</LocalDebuggerCommand>
   </PropertyGroup>

+ 0 - 1
gameplay-luagen/src/Base.h

@@ -16,7 +16,6 @@ using namespace std;
 #define SCOPE_REPLACEMENT ""
 #define SCOPE_REPLACEMENT_SIZE strlen(SCOPE_REPLACEMENT)
 #define REF_CLASS_NAME "Ref"
-#define REMOVE_NAMESPACE true
 
 #ifdef WIN32
 #include <windows.h>

+ 2 - 5
gameplay-luagen/src/ClassBinding.cpp

@@ -14,11 +14,8 @@ static void generateInstanceGetter(ostream& o, const string& classname, const st
 ClassBinding::ClassBinding(string classname, string refId) : classname(classname),
     refId(refId), inaccessibleConstructor(false), inaccessibleDestructor(false)
 {
-    // If specified, remove the namespace from the class name.
-    if (REMOVE_NAMESPACE)
-    {
-        this->classname = Generator::getInstance()->getClassNameWithoutNamespace(classname);
-    }
+    // Get the class's name and namespace.
+    this->classname = Generator::getInstance()->getClassNameAndNamespace(classname, &ns);
 
     // Calculate the unique name for the class.
     uniquename = Generator::getUniqueName(this->classname);

+ 233 - 151
gameplay-luagen/src/Generator.cpp

@@ -71,22 +71,33 @@ string Generator::getIdentifier(string refId)
     return refId;
 }
 
-string Generator::getClassNameWithoutNamespace(string classname)
+string Generator::getClassNameAndNamespace(string classname, string* ns)
 {
     size_t index = classname.find("::");
     if (index != classname.npos)
     {
-        string ns = classname.substr(0, index);
-        if (_namespaces.find(ns) != _namespaces.end())
+        string classNS = classname.substr(0, index);
+        if (_namespaces.find(classNS) != _namespaces.end())
         {
-            string tmp = classname.substr(index + 2);
-            size_t tmpIndex = tmp.find("::");
-            if (tmpIndex != tmp.npos)
-                tmp = tmp.substr(0, tmpIndex);
+            if (ns)
+                *ns = classNS;
 
-            tmp = ns + string("::") + tmp;
-            if (find(_namespaces[ns].begin(), _namespaces[ns].end(), tmp) != _namespaces[ns].end())
+            string tmp = classname.substr(index + 2);
+            if (_namespaces[classNS].find(tmp) != _namespaces[classNS].end())
                 return classname.substr(index + 2);
+            else
+            {
+                size_t tmpIndex = tmp.find("::");
+                if (tmpIndex != tmp.npos)
+                {
+                    tmp = tmp.substr(0, tmpIndex);
+                    if (_namespaces[classNS].find(tmp) != _namespaces[classNS].end())
+                    {
+                        _namespaces[classNS].insert(classname.substr(index + 2));
+                        return classname.substr(index + 2);
+                    }
+                }
+            }
         }
     }
 
@@ -150,7 +161,7 @@ string Generator::getCompoundName(XMLElement* node)
     return string(text);
 }
 
-void Generator::run(string inDir, string outDir)
+void Generator::run(string inDir, string outDir, string* bindingNS)
 {
     // Set the output directory.
     _outDir = outDir;
@@ -248,7 +259,7 @@ void Generator::run(string inDir, string outDir)
     resolveInheritedIncludes();
 
     // Generate the script bindings.
-    generateBindings();
+    generateBindings(bindingNS);
 
     // Print out all warnings (unsupported types, function name-Lua keyword clashes, etc.)
     if (__warnings.size() > 0)
@@ -277,7 +288,7 @@ Generator::~Generator()
 {
 }
 
-void Generator::getFunctions(XMLElement* fileNode)
+void Generator::getFunctions(XMLElement* fileNode, string ns)
 {
     // Process all public, non-static functions and variables that are defined in this file.
     XMLElement* node = NULL;
@@ -313,6 +324,10 @@ void Generator::getFunctions(XMLElement* fileNode)
                             getParams(e, b);
                             getCreateFlag(e, b);
                             _functions[b.getFunctionName()].push_back(b);
+
+                            // Add the function to the set of namespace members if it is part of a namespace.
+                            if (ns.size() > 0)
+                                _namespaces[ns].insert(b.name);
                         }
                         else
                         {
@@ -347,6 +362,10 @@ void Generator::getFunctions(XMLElement* fileNode)
                     {
                         b.returnParam = getParam(e, true);
                         _functions[b.getFunctionName()].push_back(b);
+                        
+                        // Add the variable to the set of namespace members if it is part of a namespace.
+                        if (ns.size() > 0)
+                            _namespaces[ns].insert(b.name);
                     }
                     else
                     {
@@ -365,23 +384,26 @@ void Generator::getNamespace(XMLElement* nsNode, const string& name)
     if (name == "std")
         return;
 
-    // Create a list of all classes that are a part of this namespace.
+    // Create the set of all classes that are a part of this namespace.
     XMLElement* e = nsNode->FirstChildElement("innerclass");
     while (e)
     {
-        _namespaces[name].push_back(e->GetText());
+        string classname = e->GetText();
+        size_t i = classname.find("::");
+        if (i != classname.npos)
+            classname = classname.substr(i + 2);
+        _namespaces[name].insert(classname);
         e = e->NextSiblingElement("innerclass");
     }
 
     // Parse all functions that are directly in this namespace.
-    getFunctions(nsNode);
+    getFunctions(nsNode, name);
 
     // Parse all enums that are directly in this namespace.
     getEnums(nsNode, name);
 
     // Parse all typedefs.
     getTypedefs(nsNode, name);
-    e = nsNode->FirstChildElement("");
 }
 
 void Generator::getClass(XMLElement* classNode, const string& name)
@@ -787,6 +809,10 @@ void Generator::getEnum(XMLElement* e, string classname, string ns, string inclu
     {
         _enums[enumname].values.push_back(getName(e));
     }
+
+    // Add the enum to the set of namespace members if it is part of a namespace.
+    if (ns.size() > 0)
+        _namespaces[ns].insert(enumname);
 }
 
 void Generator::getTypedefs(XMLElement* fileNode, string ns)
@@ -828,9 +854,6 @@ void Generator::getTypedef(XMLElement* e, string classname, string ns)
         tname += string("::");
     tname += getName(e);
 
-    if (!REMOVE_NAMESPACE)
-        tname = ns + string("::") + tname;
-
     // Get the typedef's id and store the mapping from ref id to name.
     string refId = e->Attribute("id");
     setIdentifier(refId, tname);
@@ -840,6 +863,10 @@ void Generator::getTypedef(XMLElement* e, string classname, string ns)
         t.refId = p.info;
 
     _typedefs[tname] = t;
+
+    // Add the typedef to the set of namespace members if it is part of a namespace.
+    if (ns.size() > 0)
+        _namespaces[ns].insert(tname);
 }
 
 static inline bool getScriptFlagHelper(XMLElement* e, string& flag)
@@ -1336,10 +1363,12 @@ void Generator::resolveTypes()
     }
 }
 
-void Generator::generateBindings()
+void Generator::generateBindings(string* bindingNS)
 {
-    string* bindingNS = new string("gameplay");
-    
+    bool generatingGameplay = false;
+    if (bindingNS && (*bindingNS == "gameplay"))
+        generatingGameplay = true;
+
     string luaAllHStr = _outDir + string(LUA_ALL_BINDINGS_FILENAME) + string(".h");
     ofstream luaAllH(luaAllHStr.c_str());
     string includeGuard = string(LUA_ALL_BINDINGS_FILENAME) + string("_H_");
@@ -1365,11 +1394,14 @@ void Generator::generateBindings()
         map<string, ClassBinding>::iterator iter = _classes.begin();
         for (; iter != _classes.end(); iter++)
         {
-            cout << "Generating bindings for '" << iter->first << "'...\n";
-            iter->second.write(_outDir, _includes[iter->second.include], bindingNS);
+            if (generatingGameplay || (!generatingGameplay && _namespaces["gameplay"].find(iter->second.classname) == _namespaces["gameplay"].end()))
+            {
+                cout << "Generating bindings for '" << iter->first << "'...\n";
+                iter->second.write(_outDir, _includes[iter->second.include], bindingNS);
 
-            luaAllH << "#include \"lua_" << iter->second.uniquename << ".h\"\n";
-            luaAllCpp << "    luaRegister_" << iter->second.uniquename << "();\n";
+                luaAllH << "#include \"lua_" << iter->second.uniquename << ".h\"\n";
+                luaAllCpp << "    luaRegister_" << iter->second.uniquename << "();\n";
+            }
         }
     }
 
@@ -1387,118 +1419,123 @@ void Generator::generateBindings()
         // Write out the enum conversion function declarations.
         for (map<string, EnumBinding>::iterator iter = _enums.begin(); iter != _enums.end(); iter++)
         {
-            // Header.
-            string enumHStr = _outDir + string("lua_") + getUniqueName(iter->first) + string(".h");
-            ofstream enumH(enumHStr.c_str());
-            includeGuard = string("lua_") + getUniqueName(iter->first) + string("_H_");
-            transform(includeGuard.begin(), includeGuard.end(), includeGuard.begin(), ::toupper);
-            enumH << "#ifndef " << includeGuard << "\n";
-            enumH << "#define " << includeGuard << "\n\n";
-            enumH << "#include \"" << iter->second.include << "\"\n\n";
-
-            if (bindingNS)
+            if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->first) == _namespaces["gameplay"].end()))
             {
-                enumH << "namespace " << *bindingNS << "\n";
-                enumH << "{\n\n";
-            }
+                cout << "Generating bindings for '" << iter->first << "'...\n";
+
+                // Header.
+                string enumHStr = _outDir + string("lua_") + getUniqueName(iter->first) + string(".h");
+                ofstream enumH(enumHStr.c_str());
+                includeGuard = string("lua_") + getUniqueName(iter->first) + string("_H_");
+                transform(includeGuard.begin(), includeGuard.end(), includeGuard.begin(), ::toupper);
+                enumH << "#ifndef " << includeGuard << "\n";
+                enumH << "#define " << includeGuard << "\n\n";
+                enumH << "#include \"" << iter->second.include << "\"\n\n";
+
+                if (bindingNS)
+                {
+                    enumH << "namespace " << *bindingNS << "\n";
+                    enumH << "{\n\n";
+                }
 
-            enumH << "// Lua bindings for enum conversion functions for " << iter->first << ".\n";
-            enumH << iter->first << " lua_enumFromString_" << getUniqueName(iter->first) << "(const char* s);\n";
-            enumH << "const char* lua_stringFromEnum_" << getUniqueName(iter->first) << "(" << iter->first << " e);\n\n";
+                enumH << "// Lua bindings for enum conversion functions for " << iter->first << ".\n";
+                enumH << iter->first << " lua_enumFromString_" << getUniqueName(iter->first) << "(const char* s);\n";
+                enumH << "const char* lua_stringFromEnum_" << getUniqueName(iter->first) << "(" << iter->first << " e);\n\n";
 
-            if (bindingNS)
-            {
-                enumH << "}\n\n";
-            }
+                if (bindingNS)
+                {
+                    enumH << "}\n\n";
+                }
 
-            enumH << "#endif\n";
-            enumH.close();
+                enumH << "#endif\n";
+                enumH.close();
 
-            // Implementation.
-            string enumCppStr = _outDir + string("lua_") + getUniqueName(iter->first) + string(".cpp"); 
-            ofstream enumCpp(enumCppStr.c_str());
-            enumCpp << "#include \"Base.h\"\n";
-            enumCpp << "#include \"lua_" << getUniqueName(iter->first) << ".h\"\n\n";
+                // Implementation.
+                string enumCppStr = _outDir + string("lua_") + getUniqueName(iter->first) + string(".cpp"); 
+                ofstream enumCpp(enumCppStr.c_str());
+                enumCpp << "#include \"Base.h\"\n";
+                enumCpp << "#include \"lua_" << getUniqueName(iter->first) << ".h\"\n\n";
 
-            if (bindingNS)
-            {
-                enumCpp << "namespace " << *bindingNS << "\n";
-                enumCpp << "{\n\n";
-            }
+                if (bindingNS)
+                {
+                    enumCpp << "namespace " << *bindingNS << "\n";
+                    enumCpp << "{\n\n";
+                }
 
-            enumCpp << "static const char* enumStringEmpty = \"\";\n\n";
+                enumCpp << "static const char* enumStringEmpty = \"\";\n\n";
 
-            // Build the scope string if applicable.
-            string scope;
-            if (iter->second.scopePath.size() > 0)
-            {
-                for (unsigned int i = 0; i < iter->second.scopePath.size(); i++)
+                // Build the scope string if applicable.
+                string scope;
+                if (iter->second.scopePath.size() > 0)
                 {
-                    scope += iter->second.scopePath[i] + string("::");
+                    for (unsigned int i = 0; i < iter->second.scopePath.size(); i++)
+                    {
+                        scope += iter->second.scopePath[i] + string("::");
+                    }
                 }
-            }
 
-            // Write out the string constants that correspond to the enumeration values.
-            for (unsigned int i = 0; i < iter->second.values.size(); i++)
-            {
-                enumCpp << "static const char* luaEnumString_" << getUniqueName(iter->first) << "_";
-                enumCpp << iter->second.values[i] << " = \"" << iter->second.values[i] << "\";\n";
-            }
-            enumCpp << "\n";
+                // Write out the string constants that correspond to the enumeration values.
+                for (unsigned int i = 0; i < iter->second.values.size(); i++)
+                {
+                    enumCpp << "static const char* luaEnumString_" << getUniqueName(iter->first) << "_";
+                    enumCpp << iter->second.values[i] << " = \"" << iter->second.values[i] << "\";\n";
+                }
+                enumCpp << "\n";
 
-            enumCpp << iter->first << " lua_enumFromString_" << getUniqueName(iter->first) << "(const char* s)\n";
-            enumCpp << "{\n";
+                enumCpp << iter->first << " lua_enumFromString_" << getUniqueName(iter->first) << "(const char* s)\n";
+                enumCpp << "{\n";
                 
-            for (unsigned int i = 0; i < iter->second.values.size(); i++)
-            {
-                enumCpp << "    ";
-                        
-                enumCpp << "if (strcmp(s, luaEnumString_" << getUniqueName(iter->first) << "_" << iter->second.values[i] << ") == 0)\n";
-                enumCpp << "        return ";
-                if (scope.size() > 0)
-                    enumCpp << scope;
-                enumCpp << iter->second.values[i] << ";\n";
-
-                if (i == iter->second.values.size() - 1)
+                for (unsigned int i = 0; i < iter->second.values.size(); i++)
                 {
-                    enumCpp << "    GP_ERROR(\"Invalid enumeration value '%s' for enumeration " << iter->first << ".\", s);\n";
-                    enumCpp << "    return ";
+                    enumCpp << "    ";
+                        
+                    enumCpp << "if (strcmp(s, luaEnumString_" << getUniqueName(iter->first) << "_" << iter->second.values[i] << ") == 0)\n";
+                    enumCpp << "        return ";
                     if (scope.size() > 0)
                         enumCpp << scope;
-                    enumCpp << iter->second.values[0] << ";\n";
+                    enumCpp << iter->second.values[i] << ";\n";
+
+                    if (i == iter->second.values.size() - 1)
+                    {
+                        enumCpp << "    GP_ERROR(\"Invalid enumeration value '%s' for enumeration " << iter->first << ".\", s);\n";
+                        enumCpp << "    return ";
+                        if (scope.size() > 0)
+                            enumCpp << scope;
+                        enumCpp << iter->second.values[0] << ";\n";
+                    }
                 }
-            }
 
-            enumCpp << "}\n\n";
+                enumCpp << "}\n\n";
 
-            enumCpp << "const char* lua_stringFromEnum_" << getUniqueName(iter->first) << "(" << iter->first << " e)\n";
-            enumCpp << "{\n";
+                enumCpp << "const char* lua_stringFromEnum_" << getUniqueName(iter->first) << "(" << iter->first << " e)\n";
+                enumCpp << "{\n";
 
-            // Write out the enum-to-string conversion code.
-            for (unsigned int i = 0; i < iter->second.values.size(); i++)
-            {
-                enumCpp << "    ";
+                // Write out the enum-to-string conversion code.
+                for (unsigned int i = 0; i < iter->second.values.size(); i++)
+                {
+                    enumCpp << "    ";
                         
-                enumCpp << "if (e == ";
-                if (scope.size() > 0)
-                    enumCpp << scope;
-                enumCpp << iter->second.values[i] << ")\n";
-                enumCpp << "        return luaEnumString_" << getUniqueName(iter->first) << "_" << iter->second.values[i] << ";\n";
+                    enumCpp << "if (e == ";
+                    if (scope.size() > 0)
+                        enumCpp << scope;
+                    enumCpp << iter->second.values[i] << ")\n";
+                    enumCpp << "        return luaEnumString_" << getUniqueName(iter->first) << "_" << iter->second.values[i] << ";\n";
 
-                if (i == iter->second.values.size() - 1)
-                {
-                    enumCpp << "    GP_ERROR(\"Invalid enumeration value '%d' for enumeration " << iter->first << ".\", e);\n";
-                    enumCpp << "    return enumStringEmpty;\n";
+                    if (i == iter->second.values.size() - 1)
+                    {
+                        enumCpp << "    GP_ERROR(\"Invalid enumeration value '%d' for enumeration " << iter->first << ".\", e);\n";
+                        enumCpp << "    return enumStringEmpty;\n";
+                    }
                 }
-            }
 
-            enumCpp << "}\n\n";
-
-            if (bindingNS)
-            {
                 enumCpp << "}\n\n";
+
+                if (bindingNS)
+                {
+                    enumCpp << "}\n\n";
+                }
+                enumCpp.close();
             }
-            enumCpp.close();
         }
     }
 
@@ -1506,6 +1543,34 @@ void Generator::generateBindings()
     cout << "Generating global bindings...\n";
     if (baseClasses.size() > 0 || _functions.size() > 0 || _enums.size() > 0)
     {
+        // Calculate if there are global function bindings to write out.
+        bool generateGlobalFunctionBindings = false;
+        if (_functions.size() > 0)
+        {
+            for (map<string, vector<FunctionBinding> >::iterator iter = _functions.begin(); iter != _functions.end(); iter++)
+            {
+                if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->second[0].name) == _namespaces["gameplay"].end()))
+                {
+                    generateGlobalFunctionBindings = true;
+                    break;
+                }
+            }
+        }
+
+        // Calculate if there are enum bindings to write out.
+        bool generateEnumBindings = false;
+        if (_enums.size() > 0)
+        {
+            for (map<string, EnumBinding>::iterator iter = _enums.begin(); iter != _enums.end(); iter++)
+            {
+                if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->first) == _namespaces["gameplay"].end()))
+                {
+                    generateEnumBindings = true;
+                    break;
+                }
+            }
+        }
+
         // Write out the header file.
         {
             string path = _outDir + string(LUA_GLOBAL_FILENAME) + string(".h");
@@ -1518,7 +1583,8 @@ void Generator::generateBindings()
             // Write out the needed includes for the global enumeration function.
             for (map<string, EnumBinding>::iterator iter = _enums.begin(); iter != _enums.end(); iter++)
             {
-                global << "#include \"lua_" << getUniqueName(iter->first) << ".h\"\n";
+                if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->first) == _namespaces["gameplay"].end()))
+                    global << "#include \"lua_" << getUniqueName(iter->first) << ".h\"\n";
             }
             global << "\n";
             luaAllH << "#include \"" << string(LUA_GLOBAL_FILENAME) << ".h\"\n";
@@ -1530,19 +1596,20 @@ void Generator::generateBindings()
                 global << "{\n\n";
             }
 
-            if (_functions.size() > 0)
+            if (generateGlobalFunctionBindings)
             {
                 global << "// Lua bindings for global functions.\n";
 
                 // Write out the binding function declarations.
                 for (map<string, vector<FunctionBinding> >::iterator iter = _functions.begin(); iter != _functions.end(); iter++)
                 {
-                    global << "int " << iter->second[0].getFunctionName() << "(lua_State* state);\n";
+                    if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->second[0].name) == _namespaces["gameplay"].end()))
+                        global << "int " << iter->second[0].getFunctionName() << "(lua_State* state);\n";
                 }
                 global << "\n";
             }
 
-            if (_enums.size() > 0)
+            if (generateEnumBindings)
             {
                 global << "// Global enum to string conversion function (used to pass enums to Lua from C++).\n";
                 global << "const char* lua_stringFromEnumGlobal(std::string& enumname, unsigned int value);\n\n";
@@ -1584,77 +1651,94 @@ void Generator::generateBindings()
             global << "void luaRegister_" << LUA_GLOBAL_FILENAME << "()\n";
             global << "{\n";
         
-            if (_functions.size() > 0)
+            if (generateGlobalFunctionBindings)
             {
-                global << "\n";
                 // Bind the non-member functions.
                 for (map<string, vector<FunctionBinding> >::iterator iter = _functions.begin(); iter != _functions.end(); iter++)
                 {
-                    global << "    ScriptUtil::registerFunction(\"" << iter->second[0].name << "\", " << iter->second[0].getFunctionName() << ");\n";
+                    if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->second[0].name) == _namespaces["gameplay"].end()))
+                        global << "    ScriptUtil::registerFunction(\"" << iter->second[0].name << "\", " << iter->second[0].getFunctionName() << ");\n";
                 }
             }
 
             // Generate the hierarchy map.
             if (baseClasses.size() > 0)
             {
-                global << "\n    std::map<std::string, std::vector<std::string> > hierarchy;\n";
                 for (unsigned int i = 0, count = baseClasses.size(); i < count; i++)
                 {
                     set<string> derived;
                     getAllDerived(derived, baseClasses[i]);
                     for (set<string>::iterator iter = derived.begin(); iter != derived.end(); iter++)
                     {
-                        global << "    hierarchy[\"" << baseClasses[i] << "\"].push_back(\"" << *iter << "\");\n";
+                        if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(*iter) == _namespaces["gameplay"].end()))
+                            global << "    ScriptUtil::setGlobalHierarchyPair(\"" << baseClasses[i] << "\", \"" << *iter << "\");\n";
                     }
                 }
-                global << "    ScriptUtil::setGlobalHierarchy(hierarchy);\n";
             }
 
             // Register all enums.
-            if (_enums.size() > 0)
+            if (generateEnumBindings)
             {
+                global << "    ScriptUtil::addStringFromEnumConversionFunction(&";
+                if (bindingNS)
+                    global << *bindingNS << "::";
+                global << "lua_stringFromEnumGlobal);\n";
+
                 for (map<string, EnumBinding>::iterator iter = _enums.begin(); iter != _enums.end(); iter++)
                 {
-                    global << "\n    // Register enumeration " << iter->first << ".\n";
-                    global << "    {\n";
-
-                    global << "        std::vector<std::string> scopePath;\n";
-                    for (unsigned int i = 0; i < iter->second.scopePath.size(); i++)
+                    if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->first) == _namespaces["gameplay"].end()))
                     {
-                        global << "        scopePath.push_back(\"" << iter->second.scopePath[i] << "\");\n";
-                    }
+                        global << "\n    // Register enumeration " << iter->first << ".\n";
+                        global << "    {\n";
 
-                    vector<string>::iterator enumIter = iter->second.values.begin();
-                    for (; enumIter != iter->second.values.end(); enumIter++)
-                    {
-                        global << "        ScriptUtil::registerConstantString(\"" << *enumIter << "\", \"" << *enumIter << "\", scopePath);\n";
-                    }
+                        global << "        std::vector<std::string> scopePath;\n";
+                        for (unsigned int i = 0; i < iter->second.scopePath.size(); i++)
+                        {
+                            global << "        scopePath.push_back(\"" << iter->second.scopePath[i] << "\");\n";
+                        }
 
-                    global << "    }\n";
+                        vector<string>::iterator enumIter = iter->second.values.begin();
+                        for (; enumIter != iter->second.values.end(); enumIter++)
+                        {
+                            global << "        ScriptUtil::registerConstantString(\"" << *enumIter << "\", \"" << *enumIter << "\", scopePath);\n";
+                        }
+
+                        global << "    }\n";
+                    }
                 }
             }
             global << "}\n\n";
             
             // Write out the binding functions.
-            for (map<string, vector<FunctionBinding> >::iterator iter = _functions.begin(); iter != _functions.end(); iter++)
+            if (generateGlobalFunctionBindings)
             {
-                FunctionBinding::write(global, iter->second);
+                for (map<string, vector<FunctionBinding> >::iterator iter = _functions.begin(); iter != _functions.end(); iter++)
+                {
+                    if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->second[0].name) == _namespaces["gameplay"].end()))
+                        FunctionBinding::write(global, iter->second);
+                }
             }
 
             // Write out the global enum conversion function (used to pass enums from C++ to Lua).
-            global << "static const char* enumStringEmpty = \"\";\n\n";
-            global << "const char* lua_stringFromEnumGlobal(std::string& enumname, unsigned int value)\n";
-            global << "{\n";
-            for (map<string, EnumBinding>::iterator iter = _enums.begin(); iter != _enums.end(); iter++)
+            if (generateEnumBindings)
             {
-                global << "    if (enumname == \"";
-                global << iter->first << "\")\n";
-                global << "        return lua_stringFromEnum_" << getUniqueName(iter->first) << "((" << iter->first << ")value);\n";
+                global << "static const char* enumStringEmpty = \"\";\n\n";
+                global << "const char* lua_stringFromEnumGlobal(std::string& enumname, unsigned int value)\n";
+                global << "{\n";
+                for (map<string, EnumBinding>::iterator iter = _enums.begin(); iter != _enums.end(); iter++)
+                {
+                    if (generatingGameplay || (!generatingGameplay &&  _namespaces["gameplay"].find(iter->first) == _namespaces["gameplay"].end()))
+                    {
+                        global << "    if (enumname == \"";
+                        global << iter->first << "\")\n";
+                        global << "        return lua_stringFromEnum_" << getUniqueName(iter->first) << "((" << iter->first << ")value);\n";
+                    }
+                }
+                global << "\n";
+                global << "    GP_ERROR(\"Unrecognized enumeration type '%s'.\", enumname.c_str());\n";
+                global << "    return enumStringEmpty;\n";
+                global << "}\n\n";
             }
-            global << "\n";
-            global << "    GP_ERROR(\"Unrecognized enumeration type '%s'.\", enumname.c_str());\n";
-            global << "    return enumStringEmpty;\n";
-            global << "}\n\n";
 
             if (bindingNS)
                 global << "}\n";
@@ -1677,8 +1761,6 @@ void Generator::generateBindings()
         luaAllH<< "}\n\n";
     luaAllH << "#endif\n";
     luaAllH.close();
-
-    SAFE_DELETE(bindingNS);
 }
 
 void Generator::getAllDerived(set<string>& derived, string classname)

+ 9 - 7
gameplay-luagen/src/Generator.h

@@ -64,12 +64,13 @@ public:
     string getIdentifier(string refId);
 
     /**
-     * Gets the given class name without the namespace.
+     * Gets the given class name (without the namespace) and stores the class's namespace in the given string pointer (if non-null).
      * 
      * @param classname The fully qualified name of the class.
+     * @param ns Output variable for the namespace of the class.
      * @return The class name without the namespace.
      */
-    string getClassNameWithoutNamespace(string classname);
+    string getClassNameAndNamespace(string classname, string* ns);
 
     /**
      * Sets the given ref id and class/struct/enum name pair.
@@ -87,8 +88,9 @@ public:
      * 
      * @param inDir The input directory (must contain Doxygen XML output files).
      * @param outDir The output directory.
+     * @param bindingNS The namespace to generate the bindings within.
      */
-    void run(string inDir, string outDir);
+    void run(string inDir, string outDir, string* bindingNS = NULL);
 
     /**
      * Retrieves whether the given class is derived from Ref.
@@ -115,8 +117,8 @@ protected:
     // Gets the name of the namespace, file, class, or struct.
     string getCompoundName(XMLElement* node);
 
-    // Parses the non-member functions and adds them to the list.
-    void getFunctions(XMLElement* classNode);
+    // Parses the non-member functions and adds them to the list (optionally within the given namespace).
+    void getFunctions(XMLElement* classNode, string ns = "");
 
     // Parses the namespace (with the given name).
     void getNamespace(XMLElement* nsNode, const string& name);
@@ -178,7 +180,7 @@ protected:
     void resolveTypes();
 
     // Generates the bindings to C++ header and source files.
-    void generateBindings();
+    void generateBindings(string* bindingNS);
     
     // Gets the set off all classes that derives from the given class.
     void getAllDerived(set<string>& derived, string classname);
@@ -197,7 +199,7 @@ private:
     map<string, set<string> > _includes;
     map<string, vector<FunctionBinding> > _functions;
     map<string, EnumBinding> _enums;
-    map<string, vector<string> > _namespaces;
+    map<string, set<string> > _namespaces;
     map<string, TypedefBinding> _typedefs;
     set<string> __warnings;
 };

+ 5 - 3
gameplay-luagen/src/main.cpp

@@ -26,14 +26,16 @@ void printError(const char* format, ...)
 int main(int argc, char** argv)
 {
     // Ensure the user is calling the program correctly.
-    if (argc < 2 || argc > 3)
+    if (argc < 2 || argc > 4)
     {
-        GP_ERROR("Usage: luagen <input-directory> [output-directory]");
+        GP_ERROR("Usage: luagen <input-directory> [output-directory] [binding-namespace]");
     }
 
     // Generate the bindings.
-    Generator::getInstance()->run(argv[1], (argc == 3) ? argv[2] : argv[1]);
+    string* bindingNS = (argc >= 4) ? new string(argv[3]) : NULL;
+    Generator::getInstance()->run(argv[1], (argc >= 3) ? argv[2] : argv[1], bindingNS);
     Generator::releaseInstance();
+    SAFE_DELETE(bindingNS);
 
     system("pause");
     return 0;

+ 4 - 2
gameplay/src/Base.h

@@ -299,7 +299,8 @@ typedef GLuint RenderBufferHandle;
         } \
     } while(0)
 
-// Global variable to hold GL errors
+/** Global variable to hold GL errors
+ * @script{ignore} */
 extern GLenum __gl_error_code;
 
 /**
@@ -325,7 +326,8 @@ extern GLenum __gl_error_code;
         } \
     } while(0)
 
-// Global variable to hold AL errors
+/** Global variable to hold AL errors
+ * @script{ignore} */
 extern ALenum __al_error_code;
 
 /**

+ 2 - 0
gameplay/src/Game.cpp

@@ -6,7 +6,9 @@
 #include "FrameBuffer.h"
 #include "SceneLoader.h"
 
+/** @script{ignore} */
 GLenum __gl_error_code = GL_NO_ERROR;
+/** @script{ignore} */
 ALenum __al_error_code = AL_NO_ERROR;
 
 namespace gameplay

+ 25 - 3
gameplay/src/ScriptController.cpp

@@ -250,9 +250,14 @@ void ScriptUtil::registerFunction(const char* luaFunction, lua_CFunction cppFunc
     lua_setglobal(Game::getInstance()->getScriptController()->_lua, luaFunction);
 }
 
-void ScriptUtil::setGlobalHierarchy(std::map<std::string, std::vector<std::string> > hierarchy)
+void ScriptUtil::setGlobalHierarchyPair(std::string base, std::string derived)
 {
-    Game::getInstance()->getScriptController()->_hierarchy = hierarchy;
+    Game::getInstance()->getScriptController()->_hierarchy[base].push_back(derived);
+}
+
+void ScriptUtil::addStringFromEnumConversionFunction(luaStringEnumConversionFunction stringFromEnum)
+{
+    Game::getInstance()->getScriptController()->_stringFromEnum.push_back(stringFromEnum);
 }
 
 bool* ScriptUtil::getBoolPointer(int index)
@@ -524,6 +529,12 @@ ScriptController::~ScriptController()
     }
 }
 
+static const char* lua_print_function = 
+    "function print(str, ...)\n"
+    "    local arg = {...}\n"
+    "    printError(string.format(str, table.unpack(arg)))\n"
+    "end\n";
+
 void ScriptController::initialize()
 {
     _lua = luaL_newstate();
@@ -531,6 +542,10 @@ void ScriptController::initialize()
         GP_ERROR("Failed to initialize Lua scripting engine.");
     luaL_openlibs(_lua);
     lua_RegisterAllBindings();
+
+    // Create our own print() function that uses gameplay::printError.
+    if (luaL_dostring(_lua, lua_print_function))
+        GP_ERROR("Failed to load custom print() function with error: '%s'.", lua_tostring(_lua, -1));
 }
 
 void ScriptController::initializeGame()
@@ -669,7 +684,14 @@ void ScriptController::executeFunctionHelper(int resultCount, const char* func,
                 // Skip past the closing ']' (the semi-colon here is intentional-do not remove).
                 while (*sig++ != ']');
 
-                lua_pushstring(_lua, lua_stringFromEnumGlobal(type, va_arg(*list, int)));
+                unsigned int value = va_arg(*list, int);
+                std::string enumStr = "";
+                for (unsigned int i = 0; enumStr.size() == 0 && i < _stringFromEnum.size(); i++)
+                {
+                    enumStr = (*_stringFromEnum[i])(type, value);
+                }
+
+                lua_pushstring(_lua, enumStr.c_str());
                 break;
             }
             // Object references/pointers (Lua userdata).

+ 18 - 5
gameplay/src/ScriptController.h

@@ -8,6 +8,9 @@
 namespace gameplay
 {
 
+/** Function pointer typedef for string-from-enum conversion functions. */
+typedef const char* (*luaStringEnumConversionFunction)(std::string&, unsigned int);
+
 /**
  * Functions and structures used by the generated Lua script bindings.
  */
@@ -89,13 +92,21 @@ void registerClass(const char* name, const luaL_Reg* members, lua_CFunction newF
 void registerFunction(const char* luaFunction, lua_CFunction cppFunction);
 
 /**
- * Sets the global inheritance hierarchy.
+ * Sets an inheritance pair within the global inheritance hierarchy (base, derived).
+ * 
+ * @param base The base class of the inheritance pair.
+ * @param derived The derived class of the inheritance pair.
+ * @script{ignore}
+ */
+void setGlobalHierarchyPair(std::string base, std::string derived);
+
+/**
+ * Adds the given function as a string-from-enumerated value conversion function.
  * 
- * @param hierarchy The inheritance hierarchy stored as a map of class names
- *      to a list of all derived class names.
+ * @param stringFromEnum The pointer to the string-from-enum conversion function.
  * @script{ignore}
  */
-void setGlobalHierarchy(std::map<std::string, std::vector<std::string> > hierarchy);
+void addStringFromEnumConversionFunction(luaStringEnumConversionFunction stringFromEnum);
 
 /**
  * Gets a pointer to a bool (as an array-use SAFE_DELETE_ARRAY to clean up) for the given stack index.
@@ -703,7 +714,8 @@ private:
     friend void ScriptUtil::registerClass(const char* name, const luaL_Reg* members, lua_CFunction newFunction,
         lua_CFunction deleteFunction, const luaL_Reg* statics, std::vector<std::string> scopePath);
     friend void ScriptUtil::registerFunction(const char* luaFunction, lua_CFunction cppFunction);
-    friend void ScriptUtil::setGlobalHierarchy(std::map<std::string, std::vector<std::string> > hierarchy);
+    friend void ScriptUtil::setGlobalHierarchyPair(std::string base, std::string derived);
+    friend void ScriptUtil::addStringFromEnumConversionFunction(luaStringEnumConversionFunction stringFromEnum);
     friend bool* ScriptUtil::getBoolPointer(int index);
     friend short* ScriptUtil::getShortPointer(int index);
     friend int* ScriptUtil::getIntPointer(int index);
@@ -722,6 +734,7 @@ private:
     std::map<std::string, std::vector<std::string> > _hierarchy;
     std::string* _callbacks[CALLBACK_COUNT];
     std::set<std::string> _loadedScripts;
+    std::vector<luaStringEnumConversionFunction> _stringFromEnum;
 };
 
 /** Template specialization. */

+ 123 - 188
gameplay/src/lua/lua_Global.cpp

@@ -6,135 +6,130 @@ namespace gameplay
 
 void luaRegister_lua_Global()
 {
-
-    ScriptUtil::registerFunction("__al_error_code", lua____al_error_code);
-    ScriptUtil::registerFunction("__gl_error_code", lua____gl_error_code);
     ScriptUtil::registerFunction("printError", lua__printError);
-
-    std::map<std::string, std::vector<std::string> > hierarchy;
-    hierarchy["AnimationTarget"].push_back("Button");
-    hierarchy["AnimationTarget"].push_back("CheckBox");
-    hierarchy["AnimationTarget"].push_back("Container");
-    hierarchy["AnimationTarget"].push_back("Control");
-    hierarchy["AnimationTarget"].push_back("Form");
-    hierarchy["AnimationTarget"].push_back("Joint");
-    hierarchy["AnimationTarget"].push_back("Joystick");
-    hierarchy["AnimationTarget"].push_back("Label");
-    hierarchy["AnimationTarget"].push_back("MaterialParameter");
-    hierarchy["AnimationTarget"].push_back("Node");
-    hierarchy["AnimationTarget"].push_back("RadioButton");
-    hierarchy["AnimationTarget"].push_back("Slider");
-    hierarchy["AnimationTarget"].push_back("TextBox");
-    hierarchy["AnimationTarget"].push_back("Transform");
-    hierarchy["Button"].push_back("CheckBox");
-    hierarchy["Button"].push_back("RadioButton");
-    hierarchy["Container"].push_back("Form");
-    hierarchy["Control"].push_back("Button");
-    hierarchy["Control"].push_back("CheckBox");
-    hierarchy["Control"].push_back("Container");
-    hierarchy["Control"].push_back("Form");
-    hierarchy["Control"].push_back("Joystick");
-    hierarchy["Control"].push_back("Label");
-    hierarchy["Control"].push_back("RadioButton");
-    hierarchy["Control"].push_back("Slider");
-    hierarchy["Control"].push_back("TextBox");
-    hierarchy["Label"].push_back("Button");
-    hierarchy["Label"].push_back("CheckBox");
-    hierarchy["Label"].push_back("RadioButton");
-    hierarchy["Label"].push_back("Slider");
-    hierarchy["Label"].push_back("TextBox");
-    hierarchy["Layout"].push_back("AbsoluteLayout");
-    hierarchy["Layout"].push_back("FlowLayout");
-    hierarchy["Layout"].push_back("VerticalLayout");
-    hierarchy["Node"].push_back("Joint");
-    hierarchy["PhysicsCollisionObject"].push_back("PhysicsCharacter");
-    hierarchy["PhysicsCollisionObject"].push_back("PhysicsGhostObject");
-    hierarchy["PhysicsCollisionObject"].push_back("PhysicsRigidBody");
-    hierarchy["PhysicsConstraint"].push_back("PhysicsFixedConstraint");
-    hierarchy["PhysicsConstraint"].push_back("PhysicsGenericConstraint");
-    hierarchy["PhysicsConstraint"].push_back("PhysicsHingeConstraint");
-    hierarchy["PhysicsConstraint"].push_back("PhysicsSocketConstraint");
-    hierarchy["PhysicsConstraint"].push_back("PhysicsSpringConstraint");
-    hierarchy["PhysicsGenericConstraint"].push_back("PhysicsFixedConstraint");
-    hierarchy["PhysicsGenericConstraint"].push_back("PhysicsSpringConstraint");
-    hierarchy["PhysicsGhostObject"].push_back("PhysicsCharacter");
-    hierarchy["Ref"].push_back("AIAgent");
-    hierarchy["Ref"].push_back("AIState");
-    hierarchy["Ref"].push_back("AbsoluteLayout");
-    hierarchy["Ref"].push_back("Animation");
-    hierarchy["Ref"].push_back("AnimationClip");
-    hierarchy["Ref"].push_back("AudioBuffer");
-    hierarchy["Ref"].push_back("AudioSource");
-    hierarchy["Ref"].push_back("Bundle");
-    hierarchy["Ref"].push_back("Button");
-    hierarchy["Ref"].push_back("Camera");
-    hierarchy["Ref"].push_back("CheckBox");
-    hierarchy["Ref"].push_back("Container");
-    hierarchy["Ref"].push_back("Control");
-    hierarchy["Ref"].push_back("Curve");
-    hierarchy["Ref"].push_back("DepthStencilTarget");
-    hierarchy["Ref"].push_back("Effect");
-    hierarchy["Ref"].push_back("FlowLayout");
-    hierarchy["Ref"].push_back("Font");
-    hierarchy["Ref"].push_back("Form");
-    hierarchy["Ref"].push_back("FrameBuffer");
-    hierarchy["Ref"].push_back("Image");
-    hierarchy["Ref"].push_back("Joint");
-    hierarchy["Ref"].push_back("Joystick");
-    hierarchy["Ref"].push_back("Label");
-    hierarchy["Ref"].push_back("Layout");
-    hierarchy["Ref"].push_back("Light");
-    hierarchy["Ref"].push_back("Material");
-    hierarchy["Ref"].push_back("MaterialParameter");
-    hierarchy["Ref"].push_back("Mesh");
-    hierarchy["Ref"].push_back("Model");
-    hierarchy["Ref"].push_back("Node");
-    hierarchy["Ref"].push_back("ParticleEmitter");
-    hierarchy["Ref"].push_back("Pass");
-    hierarchy["Ref"].push_back("PhysicsCollisionShape");
-    hierarchy["Ref"].push_back("RadioButton");
-    hierarchy["Ref"].push_back("RenderState");
-    hierarchy["Ref"].push_back("RenderState::StateBlock");
-    hierarchy["Ref"].push_back("RenderTarget");
-    hierarchy["Ref"].push_back("Scene");
-    hierarchy["Ref"].push_back("Slider");
-    hierarchy["Ref"].push_back("Technique");
-    hierarchy["Ref"].push_back("TextBox");
-    hierarchy["Ref"].push_back("Texture");
-    hierarchy["Ref"].push_back("Texture::Sampler");
-    hierarchy["Ref"].push_back("Theme");
-    hierarchy["Ref"].push_back("Theme::ThemeImage");
-    hierarchy["Ref"].push_back("VertexAttributeBinding");
-    hierarchy["Ref"].push_back("VerticalLayout");
-    hierarchy["RenderState"].push_back("Material");
-    hierarchy["RenderState"].push_back("Pass");
-    hierarchy["RenderState"].push_back("Technique");
-    hierarchy["ScriptTarget"].push_back("AIAgent");
-    hierarchy["ScriptTarget"].push_back("AIState");
-    hierarchy["ScriptTarget"].push_back("Button");
-    hierarchy["ScriptTarget"].push_back("CheckBox");
-    hierarchy["ScriptTarget"].push_back("Container");
-    hierarchy["ScriptTarget"].push_back("Control");
-    hierarchy["ScriptTarget"].push_back("Form");
-    hierarchy["ScriptTarget"].push_back("Joint");
-    hierarchy["ScriptTarget"].push_back("Joystick");
-    hierarchy["ScriptTarget"].push_back("Label");
-    hierarchy["ScriptTarget"].push_back("Node");
-    hierarchy["ScriptTarget"].push_back("PhysicsController");
-    hierarchy["ScriptTarget"].push_back("RadioButton");
-    hierarchy["ScriptTarget"].push_back("Slider");
-    hierarchy["ScriptTarget"].push_back("TextBox");
-    hierarchy["ScriptTarget"].push_back("Transform");
-    hierarchy["Transform"].push_back("Joint");
-    hierarchy["Transform"].push_back("Node");
-    hierarchy["Transform::Listener"].push_back("AudioListener");
-    hierarchy["Transform::Listener"].push_back("AudioSource");
-    hierarchy["Transform::Listener"].push_back("Camera");
-    hierarchy["Transform::Listener"].push_back("MeshSkin");
-    hierarchy["Transform::Listener"].push_back("PhysicsCharacter");
-    hierarchy["Transform::Listener"].push_back("PhysicsGhostObject");
-    hierarchy["Transform::Listener"].push_back("PhysicsRigidBody");
-    ScriptUtil::setGlobalHierarchy(hierarchy);
+    ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "Button");
+    ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "CheckBox");
+    ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "Container");
+    ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "Control");
+    ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "Form");
+    ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "Joint");
+    ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "Joystick");
+    ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "Label");
+    ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "MaterialParameter");
+    ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "Node");
+    ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "RadioButton");
+    ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "Slider");
+    ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "TextBox");
+    ScriptUtil::setGlobalHierarchyPair("AnimationTarget", "Transform");
+    ScriptUtil::setGlobalHierarchyPair("Button", "CheckBox");
+    ScriptUtil::setGlobalHierarchyPair("Button", "RadioButton");
+    ScriptUtil::setGlobalHierarchyPair("Container", "Form");
+    ScriptUtil::setGlobalHierarchyPair("Control", "Button");
+    ScriptUtil::setGlobalHierarchyPair("Control", "CheckBox");
+    ScriptUtil::setGlobalHierarchyPair("Control", "Container");
+    ScriptUtil::setGlobalHierarchyPair("Control", "Form");
+    ScriptUtil::setGlobalHierarchyPair("Control", "Joystick");
+    ScriptUtil::setGlobalHierarchyPair("Control", "Label");
+    ScriptUtil::setGlobalHierarchyPair("Control", "RadioButton");
+    ScriptUtil::setGlobalHierarchyPair("Control", "Slider");
+    ScriptUtil::setGlobalHierarchyPair("Control", "TextBox");
+    ScriptUtil::setGlobalHierarchyPair("Label", "Button");
+    ScriptUtil::setGlobalHierarchyPair("Label", "CheckBox");
+    ScriptUtil::setGlobalHierarchyPair("Label", "RadioButton");
+    ScriptUtil::setGlobalHierarchyPair("Label", "Slider");
+    ScriptUtil::setGlobalHierarchyPair("Label", "TextBox");
+    ScriptUtil::setGlobalHierarchyPair("Layout", "AbsoluteLayout");
+    ScriptUtil::setGlobalHierarchyPair("Layout", "FlowLayout");
+    ScriptUtil::setGlobalHierarchyPair("Layout", "VerticalLayout");
+    ScriptUtil::setGlobalHierarchyPair("Node", "Joint");
+    ScriptUtil::setGlobalHierarchyPair("PhysicsCollisionObject", "PhysicsCharacter");
+    ScriptUtil::setGlobalHierarchyPair("PhysicsCollisionObject", "PhysicsGhostObject");
+    ScriptUtil::setGlobalHierarchyPair("PhysicsCollisionObject", "PhysicsRigidBody");
+    ScriptUtil::setGlobalHierarchyPair("PhysicsConstraint", "PhysicsFixedConstraint");
+    ScriptUtil::setGlobalHierarchyPair("PhysicsConstraint", "PhysicsGenericConstraint");
+    ScriptUtil::setGlobalHierarchyPair("PhysicsConstraint", "PhysicsHingeConstraint");
+    ScriptUtil::setGlobalHierarchyPair("PhysicsConstraint", "PhysicsSocketConstraint");
+    ScriptUtil::setGlobalHierarchyPair("PhysicsConstraint", "PhysicsSpringConstraint");
+    ScriptUtil::setGlobalHierarchyPair("PhysicsGenericConstraint", "PhysicsFixedConstraint");
+    ScriptUtil::setGlobalHierarchyPair("PhysicsGenericConstraint", "PhysicsSpringConstraint");
+    ScriptUtil::setGlobalHierarchyPair("PhysicsGhostObject", "PhysicsCharacter");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "AIAgent");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "AIState");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "AbsoluteLayout");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Animation");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "AnimationClip");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "AudioBuffer");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "AudioSource");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Bundle");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Button");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Camera");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "CheckBox");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Container");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Control");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Curve");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "DepthStencilTarget");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Effect");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "FlowLayout");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Font");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Form");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "FrameBuffer");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Image");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Joint");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Joystick");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Label");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Layout");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Light");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Material");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "MaterialParameter");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Mesh");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Model");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Node");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "ParticleEmitter");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Pass");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "PhysicsCollisionShape");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "RadioButton");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "RenderState");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "RenderState::StateBlock");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "RenderTarget");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Scene");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Slider");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Technique");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "TextBox");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Texture");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Texture::Sampler");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Theme");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "Theme::ThemeImage");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "VertexAttributeBinding");
+    ScriptUtil::setGlobalHierarchyPair("Ref", "VerticalLayout");
+    ScriptUtil::setGlobalHierarchyPair("RenderState", "Material");
+    ScriptUtil::setGlobalHierarchyPair("RenderState", "Pass");
+    ScriptUtil::setGlobalHierarchyPair("RenderState", "Technique");
+    ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "AIAgent");
+    ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "AIState");
+    ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "Button");
+    ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "CheckBox");
+    ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "Container");
+    ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "Control");
+    ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "Form");
+    ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "Joint");
+    ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "Joystick");
+    ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "Label");
+    ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "Node");
+    ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "PhysicsController");
+    ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "RadioButton");
+    ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "Slider");
+    ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "TextBox");
+    ScriptUtil::setGlobalHierarchyPair("ScriptTarget", "Transform");
+    ScriptUtil::setGlobalHierarchyPair("Transform", "Joint");
+    ScriptUtil::setGlobalHierarchyPair("Transform", "Node");
+    ScriptUtil::setGlobalHierarchyPair("Transform::Listener", "AudioListener");
+    ScriptUtil::setGlobalHierarchyPair("Transform::Listener", "AudioSource");
+    ScriptUtil::setGlobalHierarchyPair("Transform::Listener", "Camera");
+    ScriptUtil::setGlobalHierarchyPair("Transform::Listener", "MeshSkin");
+    ScriptUtil::setGlobalHierarchyPair("Transform::Listener", "PhysicsCharacter");
+    ScriptUtil::setGlobalHierarchyPair("Transform::Listener", "PhysicsGhostObject");
+    ScriptUtil::setGlobalHierarchyPair("Transform::Listener", "PhysicsRigidBody");
+    ScriptUtil::addStringFromEnumConversionFunction(&gameplay::lua_stringFromEnumGlobal);
 
     // Register enumeration AIMessage::ParameterType.
     {
@@ -769,66 +764,6 @@ void luaRegister_lua_Global()
     }
 }
 
-int lua____al_error_code(lua_State* state)
-{
-    // Validate the number of parameters.
-    if (lua_gettop(state) > 1)
-    {
-        lua_pushstring(state, "Invalid number of parameters (expected 0 or 1).");
-        lua_error(state);
-    }
-
-    if (lua_gettop(state) == 1)
-    {
-        // Get parameter 1 off the stack.
-        GP_WARN("Attempting to get parameter 1 with unrecognized type ALenum as an unsigned integer.");
-        ALenum param1 = (ALenum)luaL_checkunsigned(state, 1);
-
-        __al_error_code = param1;
-        return 0;
-    }
-    else
-    {
-        ALenum result = __al_error_code;
-
-        // Push the return value onto the stack.
-        GP_WARN("Attempting to return value with unrecognized type ALenum as an unsigned integer.");
-        lua_pushunsigned(state, result);
-
-        return 1;
-    }
-}
-
-int lua____gl_error_code(lua_State* state)
-{
-    // Validate the number of parameters.
-    if (lua_gettop(state) > 1)
-    {
-        lua_pushstring(state, "Invalid number of parameters (expected 0 or 1).");
-        lua_error(state);
-    }
-
-    if (lua_gettop(state) == 1)
-    {
-        // Get parameter 1 off the stack.
-        GP_WARN("Attempting to get parameter 1 with unrecognized type GLenum as an unsigned integer.");
-        GLenum param1 = (GLenum)luaL_checkunsigned(state, 1);
-
-        __gl_error_code = param1;
-        return 0;
-    }
-    else
-    {
-        GLenum result = __gl_error_code;
-
-        // Push the return value onto the stack.
-        GP_WARN("Attempting to return value with unrecognized type GLenum as an unsigned integer.");
-        lua_pushunsigned(state, result);
-
-        return 1;
-    }
-}
-
 int lua__printError(lua_State* state)
 {
     // Get the number of parameters.

+ 0 - 2
gameplay/src/lua/lua_Global.h

@@ -45,8 +45,6 @@ namespace gameplay
 {
 
 // Lua bindings for global functions.
-int lua____al_error_code(lua_State* state);
-int lua____gl_error_code(lua_State* state);
 int lua__printError(lua_State* state);
 
 // Global enum to string conversion function (used to pass enums to Lua from C++).