Ver Fonte

More wiring for Atomic C#

Josh Engebretson há 10 anos atrás
pai
commit
0aa1f73788
34 ficheiros alterados com 1488 adições e 1168 exclusões
  1. 6 2
      Source/ToolCore/Command/BindCmd.cpp
  2. 0 34
      Source/ToolCore/JSBind/CSharp/CSBPackageWriter.cpp
  3. 60 0
      Source/ToolCore/JSBind/CSharp/CSClassWriter.cpp
  4. 8 3
      Source/ToolCore/JSBind/CSharp/CSClassWriter.h
  5. 6 6
      Source/ToolCore/JSBind/CSharp/CSFunctionWriter.cpp
  6. 43 0
      Source/ToolCore/JSBind/CSharp/CSFunctionWriter.h
  7. 27 7
      Source/ToolCore/JSBind/CSharp/CSModuleWriter.cpp
  8. 9 6
      Source/ToolCore/JSBind/CSharp/CSModuleWriter.h
  9. 62 0
      Source/ToolCore/JSBind/CSharp/CSPackageWriter.cpp
  10. 38 0
      Source/ToolCore/JSBind/CSharp/CSPackageWriter.h
  11. 2 2
      Source/ToolCore/JSBind/JSBClass.h
  12. 0 56
      Source/ToolCore/JSBind/JSBClassWriter.cpp
  13. 4 4
      Source/ToolCore/JSBind/JSBClassWriter.h
  14. 2 2
      Source/ToolCore/JSBind/JSBFunction.h
  15. 0 510
      Source/ToolCore/JSBind/JSBFunctionWriter.cpp
  16. 7 6
      Source/ToolCore/JSBind/JSBFunctionWriter.h
  17. 2 27
      Source/ToolCore/JSBind/JSBModule.cpp
  18. 2 9
      Source/ToolCore/JSBind/JSBModule.h
  19. 1 260
      Source/ToolCore/JSBind/JSBModuleWriter.cpp
  20. 3 11
      Source/ToolCore/JSBind/JSBModuleWriter.h
  21. 4 54
      Source/ToolCore/JSBind/JSBPackage.cpp
  22. 5 5
      Source/ToolCore/JSBind/JSBPackage.h
  23. 1 129
      Source/ToolCore/JSBind/JSBPackageWriter.cpp
  24. 4 5
      Source/ToolCore/JSBind/JSBPackageWriter.h
  25. 27 14
      Source/ToolCore/JSBind/JSBind.cpp
  26. 10 2
      Source/ToolCore/JSBind/JSBind.h
  27. 6 6
      Source/ToolCore/JSBind/JavaScript/JSClassWriter.cpp
  28. 4 4
      Source/ToolCore/JSBind/JavaScript/JSClassWriter.h
  29. 558 0
      Source/ToolCore/JSBind/JavaScript/JSFunctionWriter.cpp
  30. 4 4
      Source/ToolCore/JSBind/JavaScript/JSFunctionWriter.h
  31. 302 0
      Source/ToolCore/JSBind/JavaScript/JSModuleWriter.cpp
  32. 42 0
      Source/ToolCore/JSBind/JavaScript/JSModuleWriter.h
  33. 199 0
      Source/ToolCore/JSBind/JavaScript/JSPackageWriter.cpp
  34. 40 0
      Source/ToolCore/JSBind/JavaScript/JSPackageWriter.h

+ 6 - 2
Source/ToolCore/Command/BindCmd.cpp

@@ -76,10 +76,14 @@ void BindCmd::Run()
 
     context_->RegisterSubsystem(jsbind);
 
+    LOGINFOF("Loading Package");
+    jsbind->LoadPackage(sourceRootFolder_, packageFolder_, bindPlatform_);
+
     LOGINFOF("Generating JS Bindings");
+    jsbind->GenerateJavaScriptBindings();
 
-    jsbind->GenerateBindings(sourceRootFolder_, packageFolder_, bindPlatform_);
-    jsbind->GenerateCSharpBindings(sourceRootFolder_, packageFolder_, bindPlatform_);
+    LOGINFOF("Generating C# Bindings");
+    jsbind->GenerateCSharpBindings();
 
     Finished();
 

+ 0 - 34
Source/ToolCore/JSBind/CSharp/CSBPackageWriter.cpp

@@ -1,34 +0,0 @@
-//
-// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
-// LICENSE: Atomic Game Engine Editor and Tools EULA
-// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
-// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
-//
-
-#include <Atomic/IO/FileSystem.h>
-
-#include "../JSBind.h"
-#include "../JSBModule.h"
-#include "../JSBPackage.h"
-#include "../JSBEnum.h"
-#include "../JSBClass.h"
-
-#include "CSBPackageWriter.h"
-
-namespace ToolCore
-{
-
-CSBPackageWriter::CSBPackageWriter(JSBPackage *package) : package_(package)
-{
-
-}
-
-void CSBPackageWriter::GenerateSource(String& sourceOut)
-{
-    String source = "// This file was autogenerated by JSBind, changes will be lost\n\n";
-
-    sourceOut = source;
-
-}
-
-}

+ 60 - 0
Source/ToolCore/JSBind/CSharp/CSClassWriter.cpp

@@ -0,0 +1,60 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// LICENSE: Atomic Game Engine Editor and Tools EULA
+// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
+// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
+//
+
+#include <Atomic/IO/FileSystem.h>
+
+#include "../JSBind.h"
+#include "../JSBModule.h"
+#include "../JSBPackage.h"
+#include "../JSBEnum.h"
+#include "../JSBClass.h"
+#include "../JSBFunction.h"
+
+#include "CSClassWriter.h"
+#include "CSFunctionWriter.h"
+
+namespace ToolCore
+{
+
+CSClassWriter::CSClassWriter(JSBClass *klass) : JSBClassWriter(klass)
+{
+
+}
+
+
+void CSClassWriter::WriteFunctions(String& source)
+{
+    for (unsigned i = 0; i < klass_->functions_.Size(); i++)
+    {
+        JSBFunction* function = klass_->functions_.At(i);
+
+        if (function->Skip())
+            continue;
+
+        if (function->IsDestructor())
+            continue;
+
+        CSFunctionWriter writer(function);
+        writer.GenerateSource(source);
+    }
+
+}
+
+void CSClassWriter::GenerateSource(String& sourceOut)
+{
+    String source = "";
+
+    if (klass_->IsNumberArray())
+        return;
+
+    WriteFunctions(source);
+
+    sourceOut += source;
+
+}
+
+}

+ 8 - 3
Source/ToolCore/JSBind/CSharp/CSBPackageWriter.h → Source/ToolCore/JSBind/CSharp/CSClassWriter.h

@@ -9,6 +9,8 @@
 
 #include <Atomic/Container/Str.h>
 
+#include "../JSBClassWriter.h"
+
 using namespace Atomic;
 
 namespace ToolCore
@@ -17,18 +19,21 @@ namespace ToolCore
 class JSBPackage;
 class JSBClass;
 
-class CSBPackageWriter
+class CSClassWriter : public JSBClassWriter
 {
 
 public:
 
-    CSBPackageWriter(JSBPackage* package);
+    CSClassWriter(JSBClass* klass);
 
     void GenerateSource(String& sourceOut);
 
+    void GenerateNativeSource();
+    void GenerateManagedSource();
+
 private:
 
-    JSBPackage* package_;
+    void WriteFunctions(String& source);
 
 };
 

+ 6 - 6
Source/ToolCore/JSBind/CSharp/CSBFunctionWriter.cpp → Source/ToolCore/JSBind/CSharp/CSFunctionWriter.cpp

@@ -14,33 +14,33 @@
 #include "../JSBClass.h"
 #include "../JSBFunction.h"
 
-#include "CSBFunctionWriter.h"
+#include "CSFunctionWriter.h"
 
 namespace ToolCore
 {
 
-CSBFunctionWriter::CSBFunctionWriter(JSBFunction *function) : function_(function)
+CSFunctionWriter::CSFunctionWriter(JSBFunction *function) : JSBFunctionWriter(function)
 {
 
 }
 
-void CSBFunctionWriter::WriteParameterMarshal(String& source)
+void CSFunctionWriter::WriteParameterMarshal(String& source)
 {
 
 }
 
 
-void CSBFunctionWriter::WriteConstructor(String& source)
+void CSFunctionWriter::WriteConstructor(String& source)
 {
 
 }
 
-void CSBFunctionWriter::WriteFunction(String& source)
+void CSFunctionWriter::WriteFunction(String& source)
 {
 
 }
 
-void CSBFunctionWriter::GenerateSource(String& sourceOut)
+void CSFunctionWriter::GenerateSource(String& sourceOut)
 {
     String source = "";
 

+ 43 - 0
Source/ToolCore/JSBind/CSharp/CSFunctionWriter.h

@@ -0,0 +1,43 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// LICENSE: Atomic Game Engine Editor and Tools EULA
+// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
+// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
+//
+
+#pragma once
+
+#include <Atomic/Container/Str.h>
+
+#include "../JSBFunctionWriter.h"
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+class JSBPackage;
+class JSBFunction;
+
+class CSFunctionWriter : public JSBFunctionWriter
+{
+
+public:
+
+    CSFunctionWriter(JSBFunction* function);
+
+    void GenerateSource(String& sourceOut);
+
+    void GenerateNativeSource();
+    void GenerateManagedSource();
+
+
+private:
+
+    void WriteFunction(String& source);
+    void WriteConstructor(String& source);
+    void WriteParameterMarshal(String& source);
+
+};
+
+}

+ 27 - 7
Source/ToolCore/JSBind/CSharp/CSBModuleWriter.cpp → Source/ToolCore/JSBind/CSharp/CSModuleWriter.cpp

@@ -5,6 +5,7 @@
 // license information: https://github.com/AtomicGameEngine/AtomicGameEngine
 //
 
+#include <Atomic/IO/File.h>
 #include <Atomic/IO/FileSystem.h>
 
 #include "../JSBind.h"
@@ -14,18 +15,18 @@
 #include "../JSBClass.h"
 #include "../JSBFunction.h"
 
-#include "CSBClassWriter.h"
-#include "CSBModuleWriter.h"
+#include "CSClassWriter.h"
+#include "CSModuleWriter.h"
 
 namespace ToolCore
 {
 
-CSBModuleWriter::CSBModuleWriter(JSBModule *module) : module_(module)
+CSModuleWriter::CSModuleWriter(JSBModule *module) : JSBModuleWriter(module)
 {
 
 }
 
-void CSBModuleWriter::WriteIncludes(String& source)
+void CSModuleWriter::WriteIncludes(String& source)
 {
 
     Vector<String>& includes = module_->includes_;
@@ -78,7 +79,7 @@ void CSBModuleWriter::WriteIncludes(String& source)
 }
 
 
-void CSBModuleWriter::GenerateSource(String& sourceOut)
+void CSModuleWriter::GenerateNativeSource()
 {
     source_ = "// This file was autogenerated by JSBind, changes will be lost\n";
 
@@ -118,7 +119,7 @@ void CSBModuleWriter::GenerateSource(String& sourceOut)
 
     for (unsigned i = 0; i < classes.Size(); i++)
     {
-        CSBClassWriter clsWriter(classes[i]);
+        CSClassWriter clsWriter(classes[i]);
         clsWriter.GenerateSource(source_);
     }
 
@@ -132,7 +133,26 @@ void CSBModuleWriter::GenerateSource(String& sourceOut)
         source_ += "#endif //ATOMIC_3D\n";
     }
 
-    sourceOut = source_;
+    JSBind* jsbind = module_->GetSubsystem<JSBind>();
+
+    String filepath = jsbind->GetDestNativeFolder() + "/CSModule" + module_->name_ + ".cpp";
+
+    File file(module_->GetContext());
+    file.Open(filepath, FILE_WRITE);
+    file.Write(source_.CString(), source_.Length());
+    file.Close();
+
+}
+
+void CSModuleWriter::GenerateManagedSource()
+{
+
+}
+
+void CSModuleWriter::GenerateSource()
+{   
+    GenerateNativeSource();
+    GenerateManagedSource();
 }
 
 }

+ 9 - 6
Source/ToolCore/JSBind/CSharp/CSBModuleWriter.h → Source/ToolCore/JSBind/CSharp/CSModuleWriter.h

@@ -9,6 +9,8 @@
 
 #include <Atomic/Container/Str.h>
 
+#include "../JSBModuleWriter.h"
+
 using namespace Atomic;
 
 namespace ToolCore
@@ -16,22 +18,23 @@ namespace ToolCore
 
 class JSBModule;
 
-class CSBModuleWriter
+class CSModuleWriter : public JSBModuleWriter
 {
 
 public:
 
-    CSBModuleWriter(JSBModule* module);
+    CSModuleWriter(JSBModule* module);
+
+    void GenerateSource();
+
+    void GenerateNativeSource();
+    void GenerateManagedSource();
 
-    void GenerateSource(String& sourceOut);
 
 private:
 
     void WriteIncludes(String& source);
 
-    JSBModule* module_;
-    String source_;
-
 };
 
 }

+ 62 - 0
Source/ToolCore/JSBind/CSharp/CSPackageWriter.cpp

@@ -0,0 +1,62 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// LICENSE: Atomic Game Engine Editor and Tools EULA
+// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
+// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
+//
+
+#include <Atomic/IO/File.h>
+#include <Atomic/IO/FileSystem.h>
+
+#include "../JSBind.h"
+#include "../JSBModule.h"
+#include "../JSBPackage.h"
+#include "../JSBEnum.h"
+#include "../JSBClass.h"
+
+#include "CSModuleWriter.h"
+#include "CSPackageWriter.h"
+
+namespace ToolCore
+{
+
+CSPackageWriter::CSPackageWriter(JSBPackage *package) : JSBPackageWriter(package)
+{
+
+}
+
+void CSPackageWriter::GenerateNativeSource()
+{
+    String source = "// This file was autogenerated by JSBind, changes will be lost\n\n";
+
+    JSBind* jsbind = package_->GetSubsystem<JSBind>();
+
+    String filepath = jsbind->GetDestNativeFolder() + "/CSPackage" + package_->name_ + ".cpp";
+
+    File file(package_->GetContext());
+    file.Open(filepath, FILE_WRITE);
+    file.Write(source.CString(), source.Length());
+    file.Close();
+
+    for (unsigned i = 0; i < package_->modules_.Size(); i++)
+    {
+        CSModuleWriter writer(package_->modules_[i]);
+        writer.GenerateSource();
+    }
+
+}
+
+void CSPackageWriter::GenerateManagedSource()
+{
+
+}
+
+void CSPackageWriter::GenerateSource()
+{
+
+    GenerateNativeSource();
+    GenerateManagedSource();
+
+}
+
+}

+ 38 - 0
Source/ToolCore/JSBind/CSharp/CSPackageWriter.h

@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// LICENSE: Atomic Game Engine Editor and Tools EULA
+// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
+// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
+//
+
+#pragma once
+
+#include <Atomic/Container/Str.h>
+
+#include "../JSBPackageWriter.h"
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+class JSBPackage;
+class JSBClass;
+
+class CSPackageWriter : public JSBPackageWriter
+{
+
+public:
+
+    CSPackageWriter(JSBPackage* package);
+
+    void GenerateSource();
+
+    void GenerateNativeSource();
+    void GenerateManagedSource();
+
+private:
+
+};
+
+}

+ 2 - 2
Source/ToolCore/JSBind/JSBClass.h

@@ -88,8 +88,8 @@ public:
 
 class JSBClass : public Object
 {
-    friend class JSBClassWriter;
-    friend class CSBClassWriter;
+    friend class JSClassWriter;
+    friend class CSClassWriter;
 
     OBJECT(JSBClass)
 

+ 0 - 56
Source/ToolCore/JSBind/JSBClassWriter.cpp

@@ -28,67 +28,11 @@ JSBClassWriter::JSBClassWriter(JSBClass *klass) : klass_(klass)
 
 void JSBClassWriter::WriteFunctions(String& source)
 {
-    for (unsigned i = 0; i < klass_->functions_.Size(); i++)
-    {
-        JSBFunction* function = klass_->functions_.At(i);
-
-        if (function->Skip())
-            continue;
-
-        if (function->IsDestructor())
-            continue;
-
-        JSBFunctionWriter writer(function);
-        writer.GenerateSource(source);
-    }
 
 }
 
 void JSBClassWriter::GenerateSource(String& sourceOut)
 {
-    String source = "";
-
-    if (klass_->IsNumberArray())
-        return;
-
-    WriteFunctions(source);
-
-    String packageName = klass_->GetModule()->GetPackage()->GetName();
-
-    source.AppendWithFormat("static void jsb_class_define_%s(JSVM* vm)\n{\n", klass_->GetName().CString());
-    source.Append("duk_context* ctx = vm->GetJSContext();\n");
-    source.AppendWithFormat("js_class_get_prototype(ctx, \"%s\", \"%s\");\n", packageName.CString(), klass_->GetName().CString());
-
-    for (unsigned i = 0; i < klass_->functions_.Size(); i++)
-    {
-        JSBFunction* function = klass_->functions_.At(i);
-
-        if (function->Skip())
-            continue;
-
-        if (function->IsConstructor() || function->IsDestructor())
-            continue;
-
-        if (function->FirstDefaultParameter() != -1)
-        {
-            source.AppendWithFormat("duk_push_c_function(ctx, jsb_class_%s_%s, DUK_VARARGS);\n", klass_->GetName().CString(), function->GetName().CString());
-        }
-        else
-        {
-            source.AppendWithFormat("duk_push_c_function(ctx, jsb_class_%s_%s, %i);\n", klass_->GetName().CString(), function->GetName().CString(), (int) function->GetParameters().Size());
-        }
-
-        String scriptName =  function->GetName();
-        scriptName[0] = tolower(scriptName[0]);
-        source.AppendWithFormat("duk_put_prop_string(ctx, -2, \"%s\");\n", scriptName.CString());
-
-    }
-
-    source.Append("duk_pop(ctx);\n");
-    source.Append("}\n");
-
-
-    sourceOut += source;
 
 }
 

+ 4 - 4
Source/ToolCore/JSBind/JSBClassWriter.h

@@ -22,13 +22,13 @@ class JSBClassWriter
 
 public:
 
-    JSBClassWriter(JSBClass* klass);
+    virtual void GenerateSource(String& sourceOut);
 
-    void GenerateSource(String& sourceOut);
+protected:
 
-private:
+    JSBClassWriter(JSBClass* klass);
 
-    void WriteFunctions(String& source);
+    virtual void WriteFunctions(String& source);
 
     JSBClass* klass_;
 

+ 2 - 2
Source/ToolCore/JSBind/JSBFunction.h

@@ -80,8 +80,8 @@ public:
 
 class JSBFunction : public JSBSymbol
 {
-    friend class JSBFunctionWriter;
-    friend class CSBFunctionWriter;
+    friend class JSFunctionWriter;
+    friend class CSFunctionWriter;
 
 public:
 

+ 0 - 510
Source/ToolCore/JSBind/JSBFunctionWriter.cpp

@@ -26,532 +26,22 @@ JSBFunctionWriter::JSBFunctionWriter(JSBFunction *function) : function_(function
 
 void JSBFunctionWriter::WriteParameterMarshal(String& source)
 {
-    // generate args
-    Vector<JSBFunctionType*>& parameters = function_->GetParameters();
 
-    int cparam = 0;
-    if (parameters.Size())
-    {
-        for (unsigned int i = 0; i < parameters.Size(); i++, cparam++)
-        {
-            JSBFunctionType * ptype = parameters.At(i);
-
-
-            // ignore "Context" parameters
-            if (ptype->type_->asClassType())
-            {
-                JSBClassType* classType = ptype->type_->asClassType();
-                JSBClass* klass = classType->class_;
-                if (klass->GetName() == "Context")
-                {
-                    cparam--;
-                    continue;
-                }
-
-            }
-
-            String pstring = ptype->ToArgString(cparam);
-            const String& init = ptype->initializer_;
-
-            if (ptype->type_->asClassType())
-            {
-                JSBClassType* classType = ptype->type_->asClassType();
-
-                JSBClass* klass = classType->class_;
-
-                if (!klass->IsNumberArray())
-                {
-                    if (init.Length())
-                    {
-                        source.AppendWithFormat("%s = duk_get_top(ctx) >= %i ? js_to_class_instance<%s>(ctx, %i, 0) : %s;\n",
-                                                pstring.CString(), cparam + 1, klass->GetNativeName().CString(), cparam, init.CString());
-                    }
-                    else
-                    {
-                        source.AppendWithFormat("%s = js_to_class_instance<%s>(ctx, %i, 0);\n",
-                                                pstring.CString(), klass->GetNativeName().CString(), cparam);
-                    }
-                }
-                else
-                {
-                    int elements = klass->GetNumberArrayElements();
-                    String elementType = klass->GetArrayElementType();
-                    source.AppendWithFormat("%s arrayData%i[%i];\n", elementType.CString(), cparam, elements);
-
-                    if (init.Length())
-                    {
-                        source.AppendWithFormat("const %s& defaultArg%i = %s;\n", klass->GetNativeName().CString(), cparam,  init.CString());
-                        source.AppendWithFormat("if (duk_get_top(ctx) >= %i) {\n", cparam + 1);
-                    }
-
-                    for (int j = 0; j < elements; j++)
-                    {
-                        source.AppendWithFormat("duk_get_prop_index(ctx, %i, %i);\n", cparam, j);
-                        source.AppendWithFormat("arrayData%i[%i] = (%s) duk_to_number(ctx, -1);\n", cparam, j, elementType.CString());
-                    }
-
-                    source.AppendWithFormat("duk_pop_n(ctx, %i);\n", elements);
-
-                    if (init.Length())
-                    {
-                        source.Append("}\n");
-
-                        source.AppendWithFormat("%s __arg%i(duk_get_top(ctx) >= %i ? arrayData%i : defaultArg%i);\n",
-                                                klass->GetNativeName().CString(), cparam, cparam + 1, cparam, cparam);
-                    }
-                    else
-                    {
-                        source.AppendWithFormat("%s __arg%i(arrayData%i);\n", klass->GetNativeName().CString(), cparam, cparam);
-                    }
-
-
-                }
-
-            }
-            else if (ptype->type_->asStringType() || ptype->type_->asStringHashType())
-            {
-                if (init.Length())
-                {
-                    source.AppendWithFormat("%s = duk_get_top(ctx) >= %i ? duk_to_string(ctx, %i) : %s;\n", pstring.CString(), cparam + 1, cparam, init.CString());
-                }
-                else
-                {
-                    source.AppendWithFormat("%s = duk_to_string(ctx, %i);\n", pstring.CString(),  cparam);
-
-                }
-            }
-            else if (ptype->type_->asHeapPtrType())
-            {
-                if (init.Length())
-                {
-                    source.AppendWithFormat("%s = duk_get_top(ctx) >= %i ? duk_get_heapptr(ctx, %i) : %s;\n", pstring.CString(), cparam + 1, cparam, init.CString());
-                }
-                else
-                {
-                    source.AppendWithFormat("%s = duk_get_heapptr(ctx, %i);\n", pstring.CString(),  cparam);
-
-                }
-            }
-            else if (ptype->type_->asPrimitiveType())
-            {
-                JSBPrimitiveType* prtype = ptype->type_->asPrimitiveType();
-
-                if (prtype->kind_ == JSBPrimitiveType::Bool)
-                {
-                    if (init.Length())
-                    {
-                        source.AppendWithFormat("bool __arg%i = duk_get_top(ctx) >= %i ? (duk_to_boolean(ctx, %i) ? true : false) : %s;\n",
-                                                cparam,  cparam + 1,   cparam, init.CString());
-                    }
-                    else
-                    {
-                        source.AppendWithFormat("bool __arg%i = duk_to_boolean(ctx, %i) ? true : false;\n",  cparam,  cparam);
-                    }
-                }
-                else
-                {
-                    if (init.Length())
-                    {
-                        source.AppendWithFormat("double __arg%i = duk_get_top(ctx) >= %i ? (duk_to_number(ctx, %i)) : %s;\n",
-                                                cparam,  cparam + 1,   cparam, init.CString());
-
-                    }
-                    else
-                    {
-                        source.AppendWithFormat("double __arg%i = duk_to_number(ctx, %i);\n",  cparam,  cparam);
-                    }
-                }
-
-            }
-            else if (ptype->type_->asEnumType())
-            {
-                JSBEnumType* etype = ptype->type_->asEnumType();
-
-                if (init.Length())
-                {
-                    source.AppendWithFormat("%s __arg%i = duk_get_top(ctx) >= %i ? ((%s) ((int) duk_to_number(ctx, %i))) : %s;\n", etype->enum_->GetName().CString(),
-                                            cparam,  cparam + 1, etype->enum_->GetName().CString(),  cparam, init.CString());
-
-                }
-                else
-                {
-                    source.AppendWithFormat("%s __arg%i = (%s) ((int)duk_to_number(ctx, %i));\n", etype->enum_->GetName().CString(),
-                                            cparam, etype->enum_->GetName().CString(),  cparam);
-
-                }
-
-            }
-            else if (ptype->type_->asVectorType())
-            {
-                // read only vector arguments
-                if (ptype->isConst_)
-                {
-                    JSBVectorType* vtype = ptype->type_->asVectorType();
-                    source.AppendWithFormat("%s __arg%i;\n", vtype->ToString().CString(), cparam);
-
-                    source.AppendWithFormat("if (duk_get_top(ctx) >= %i)\n{\n", cparam + 1);
-                    source.AppendWithFormat("duk_require_object_coercible(ctx, %i);\n", cparam);
-                    source.AppendWithFormat("unsigned sz = duk_get_length(ctx, %i);\n", cparam);
-                    source.AppendWithFormat("for (unsigned i = 0; i < sz; i++)\n{\n");
-
-                    source.AppendWithFormat("duk_get_prop_index(ctx, 2, i);\n");
-
-                    if (vtype->vectorType_->asStringType() || vtype->vectorType_->asStringHashType() )
-                    {
-                        source.AppendWithFormat("__arg%i.Push(duk_get_string(ctx, -1));\n", cparam);
-                    }
-
-                    source.AppendWithFormat("duk_pop(ctx);\n");
-
-                    source.AppendWithFormat("\n}\n");
-
-                    source.AppendWithFormat("\n}\n");
-
-                }
-            }
-
-        }
-    }
 }
 
 
 void JSBFunctionWriter::WriteConstructor(String& source)
 {
 
-    // TODO: refactor this
-
-    if (function_->name_ == "RefCounted")
-    {
-        source.Append("// finalizer may be called more than once\n" \
-                      "static int jsb_finalizer_RefCounted(duk_context *ctx)\n" \
-                      "{\n" \
-                      "JSVM* vm =  JSVM::GetJSVM(ctx);\n" \
-                      \
-                      "duk_get_prop_index(ctx, 0, JS_INSTANCE_INDEX_FINALIZED);\n" \
-                      \
-                      "if (!duk_is_boolean(ctx, -1))\n" \
-                      "{\n" \
-                      "RefCounted* ref = vm->GetObjectPtr(duk_get_heapptr(ctx, 0));\n" \
-                      "vm->RemoveObject(ref);\n" \
-                      "ref->ReleaseRef();\n" \
-                      "duk_push_boolean(ctx, 1);\n" \
-                      "duk_put_prop_index(ctx, 0, JS_INSTANCE_INDEX_FINALIZED);\n" \
-                      "}\n" \
-                      \
-                      "return 0;\n" \
-                      "}\n");
-    }
-
-    JSBClass* klass = function_->class_;
-    JSBClass* base = klass->GetBaseClass();
-
-
-    // Constructor
-    source.AppendWithFormat("duk_ret_t jsb_constructor_%s(duk_context* ctx)\n{\n", klass->GetName().CString());
-
-    /*
-
-duk_ret_t jsb_constructor_MyJSClass(duk_context* ctx)
-{
-    JSVM* vm = JSVM::GetJSVM(ctx);
-    duk_push_this(ctx);
-    void *ptr = duk_get_heapptr(ctx, -1);
-    duk_pop(ctx);
-
-    if (!vm->GetObjectPtr(ptr, true))
-    {
-        if (!duk_get_top(ctx) || !duk_is_pointer(ctx, 0))
-        {
-            MyJSClass* native = new MyJSClass(JSVM::GetJSVM(ctx)->GetContext());
-            vm->AddObject(ptr, native);
-        }
-        else if (duk_is_pointer(ctx, 0))
-        {
-            vm->AddObject(ptr, (RefCounted*) duk_get_pointer(ctx, 0));
-        }
-    }
-
-    js_constructor_basecall(ctx, "Atomic", "AObject");
-    return 0;
-}
-
-     */
-
-    source.Append( "\nJSVM* vm = JSVM::GetJSVM(ctx);\n" \
-                   "duk_push_this(ctx);\n" \
-                   "void *ptr = duk_get_heapptr(ctx, -1);\n" \
-                   "duk_pop(ctx);\n\n");
-
-    source.Append("   if (!vm->GetObjectPtr(ptr, true))\n   {\n");
-
-    if (!klass->IsAbstract() && !klass->IsNumberArray())
-    {
-
-        String marshal;
-        WriteParameterMarshal(marshal);
-
-        String sparams;
-        int cparam = 0;
-
-        Vector<JSBFunctionType*>& parameters = function_->GetParameters();
-
-        for (unsigned i = 0; i < parameters.Size(); i++, cparam++)
-        {
-            JSBFunctionType * ptype = parameters.At(i);
-
-            String sarg;
-
-            if (ptype->type_->asClassType())
-            {
-                JSBClassType* classType = ptype->type_->asClassType();
-                JSBClass* klass = classType->class_;
-                if (klass->GetName() == "Context")
-                {
-                    sarg = "vm->GetContext()";
-                    cparam--;
-                }
-
-            }
-
-            if (!sarg.Length())
-            {
-                sarg.AppendWithFormat("__arg%i", cparam);
-            }
-
-            sparams += sarg;
-
-            if (i + 1 < parameters.Size())
-                sparams += ", ";
-
-        }
-
-        source.AppendWithFormat("if (!duk_get_top(ctx) || !duk_is_pointer(ctx, 0))\n"\
-                                "{\n"\
-                                "%s\n"\
-                                "%s* native = new %s(%s);\n" \
-                                "vm->AddObject(ptr, native);\n"\
-                                "}\n" \
-                                "else if (duk_is_pointer(ctx, 0))\n" \
-                                "{\n" \
-                                "vm->AddObject(ptr, (RefCounted*) duk_get_pointer(ctx, 0));\n" \
-                                "}\n", marshal.CString(), klass->GetNativeName().CString(), klass->GetNativeName().CString(), sparams.CString());
-    }
-    else
-    {
-        if (klass->IsAbstract())
-            source.Append("assert(0); // abstract class new'd\n");
-
-        if (klass->IsNumberArray())
-            source.Append("assert(0); // number array class new'd\n");
-
-    }
-    source.Append("   }\n");
-
-    if (base)
-    {
-        String basePackage = base->GetModule()->GetPackage()->GetName();
-        source.AppendWithFormat("   js_constructor_basecall(ctx, \"%s\", \"%s\");\n", basePackage.CString(), base->GetName().CString());
-    }
-
-    if (function_->name_ == "RefCounted")
-    {
-        source.Append("duk_push_this(ctx);\n "\
-                      "duk_push_c_function(ctx, jsb_finalizer_RefCounted, 1);\n "\
-                      "duk_set_finalizer(ctx, -2);\n "\
-                      \
-                      "RefCounted* ref = JSVM::GetJSVM(ctx)->GetObjectPtr(duk_get_heapptr(ctx, -1));\n "\
-                      "ref->AddRef();\n "\
-                      \
-                      "duk_pop(ctx);\n");
-
-    }
-
-    source += "   return 0;";
-    source += "\n}\n";
-
 }
 
 void JSBFunctionWriter::WriteFunction(String& source)
 {
-    JSBClass* klass = function_->class_;
-
-    source.AppendWithFormat("static int jsb_class_%s_%s(duk_context* ctx)\n{\n", klass->GetName().CString(), function_->name_.CString());
-
-    WriteParameterMarshal(source);
-
-    source.Append("duk_push_this(ctx);\n");
-    source.AppendWithFormat("%s* native = js_to_class_instance<%s>(ctx, -1, 0);\n", klass->GetNativeName().CString(), klass->GetNativeName().CString());
 
-    // declare return value;
-    bool returnDeclared = false;
-
-    JSBFunctionType* returnType = function_->returnType_;
-
-    if (returnType)
-    {
-        if (returnType->type_->asStringType())
-        {
-            returnDeclared = true;
-            source.Append("const String& retValue = ");
-        }
-        else if (returnType->type_->asPrimitiveType())
-        {
-            returnDeclared = true;
-
-            JSBPrimitiveType* prtype = returnType->type_->asPrimitiveType();
-
-            if (prtype->kind_ == JSBPrimitiveType::Bool)
-            {
-                source.Append("bool retValue = ");
-            }
-            else
-            {
-                source.Append("double retValue = ");
-            }
-
-        }
-        else if (returnType->type_->asClassType())
-        {
-            JSBClassType* klassType = returnType->type_->asClassType();
-
-            if (returnType->isTemplate_)
-            {
-                returnDeclared = true;
-                source.AppendWithFormat("SharedPtr<%s> object = ", klassType->class_->GetNativeName().CString());
-            }
-            else if (klassType->class_->IsObject())
-            {
-                returnDeclared = true;
-                source.Append("const Object* object = ");
-            }
-            else if (klassType->class_->IsNumberArray())
-            {
-                returnDeclared = true;
-                source.AppendWithFormat("const %s& retValue = ", klassType->class_->GetName().CString());
-            }
-            else
-            {
-                returnDeclared = true;
-                source.Append("const RefCounted* object = ");
-            }
-        }
-        else if (returnType->type_->asEnumType())
-        {
-            JSBEnumType* enumType = returnType->type_->asEnumType();
-            returnDeclared = true;
-            source.AppendWithFormat("%s retValue = ", enumType->enum_->GetName().CString());
-        }
-        else if (returnType->type_->asVectorType())
-        {
-            returnDeclared = true;
-            JSBVectorType* vtype = returnType->type_->asVectorType();
-            source.AppendWithFormat("const %s& retValue = ", vtype->ToString().CString());
-        }
-
-    }
-
-    source.AppendWithFormat("native->%s(", function_->name_.CString());
-
-    Vector<JSBFunctionType*>& parameters = function_->GetParameters();
-
-    for (unsigned int i = 0; i < parameters.Size(); i++)
-    {
-        source.AppendWithFormat("__arg%i",  i);
-
-        if (i != parameters.Size() - 1)
-        {
-            source += ", ";
-        }
-    }
-
-    source += ");\n";
-
-    if (returnDeclared)
-    {
-        if (returnType->type_->asStringType())
-        {
-            source.Append("duk_push_string(ctx, retValue.CString());\n");
-        }
-        else if (returnType->type_->asPrimitiveType())
-        {
-            JSBPrimitiveType* prtype = returnType->type_->asPrimitiveType();
-
-            if (prtype->kind_ == JSBPrimitiveType::Bool)
-            {
-                source.Append("duk_push_boolean(ctx, retValue ? 1 : 0);\n");
-            }
-            else
-            {
-                source.Append("duk_push_number(ctx, retValue);\n");
-            }
-
-        }
-        else if (returnType->type_->asClassType())
-        {
-            JSBClassType* klassType = returnType->type_->asClassType();
-
-            if (klassType->class_->IsObject())
-            {
-                returnDeclared = true;
-                source.Append("js_push_class_object_instance(ctx, object);\n");
-            }
-            else if (klassType->class_->IsNumberArray())
-            {
-                returnDeclared = true;
-                String elementType = klassType->class_->GetArrayElementType();
-                source.AppendWithFormat("const %s* arrayData = retValue.Data();\n", elementType.CString());
-                source.Append("duk_push_array(ctx);\n");
-                for (int i = 0; i < klassType->class_->GetNumberArrayElements(); i++)
-                {
-                    source.AppendWithFormat("duk_push_number(ctx, arrayData[%i]);\n", i);
-                    source.AppendWithFormat("duk_put_prop_index(ctx, -2, %i);\n", i);
-                }
-            }
-            else
-            {
-                returnDeclared = true;
-                source.AppendWithFormat("js_push_class_object_instance(ctx, object, \"%s\");\n", klassType->class_->GetName().CString());
-            }
-        }
-        else if (returnType->type_->asEnumType())
-        {
-            returnDeclared = true;
-            source.Append("duk_push_number(ctx, (double) retValue);\n");
-        }
-        else if (returnType->type_->asVectorType())
-        {
-            source.Append("duk_push_array(ctx);\n");
-            source.Append("for (unsigned i = 0; i < retValue.Size(); i++)\n{\n");
-            source.Append("duk_push_string(ctx, retValue[i].CString());\n");
-            source.Append("duk_put_prop_index(ctx, -2, i);\n}\n");
-        }
-
-
-
-        source += "return 1;\n";
-    }
-    else
-    {
-        source += "return 0;\n";
-    }
-
-    source.Append("}\n");
 }
 
 void JSBFunctionWriter::GenerateSource(String& sourceOut)
 {
-    String source = "";
-
-    if (function_->IsConstructor())
-    {
-        WriteConstructor(source);
-    }
-    else
-    {
-        WriteFunction(source);
-    }
-
-    sourceOut += source;
 
 }
 

+ 7 - 6
Source/ToolCore/JSBind/JSBFunctionWriter.h

@@ -22,15 +22,16 @@ class JSBFunctionWriter
 
 public:
 
-    JSBFunctionWriter(JSBFunction* function);
+    virtual void GenerateSource(String& sourceOut);
 
-    void GenerateSource(String& sourceOut);
+protected:
+    JSBFunctionWriter(JSBFunction* function);
 
-private:
+protected:
 
-    void WriteFunction(String& source);
-    void WriteConstructor(String& source);
-    void WriteParameterMarshal(String& source);
+    virtual void WriteFunction(String& source);
+    virtual void WriteConstructor(String& source);
+    virtual void WriteParameterMarshal(String& source);
 
     JSBFunction* function_;
 

+ 2 - 27
Source/ToolCore/JSBind/JSBModule.cpp

@@ -21,7 +21,8 @@
 #include "JSBModuleWriter.h"
 #include "JSBType.h"
 
-#include "CSharp/CSBModuleWriter.h"
+#include "JavaScript/JSModuleWriter.h"
+#include "CSharp/CSModuleWriter.h"
 
 namespace ToolCore
 {
@@ -486,30 +487,4 @@ bool JSBModule::Load(const String& jsonFilename)
     return true;
 }
 
-void JSBModule::GenerateSource(const String& outPath)
-{
-    JSBModuleWriter writer(this);
-    writer.GenerateSource(source_);
-
-    String filepath = outPath + "/JSModule" + name_ + ".cpp";
-    File file(context_);
-    file.Open(filepath, FILE_WRITE);
-    file.Write(source_.CString(), source_.Length());
-    file.Close();
-}
-
-void JSBModule::GenerateCSharpSource(const String& outPath)
-{
-    CSBModuleWriter writer(this);
-    writer.GenerateSource(source_);
-
-    String filepath = outPath + "/CSModule" + name_ + ".cpp";
-    File file(context_);
-    file.Open(filepath, FILE_WRITE);
-    file.Write(source_.CString(), source_.Length());
-    file.Close();
-
-}
-
-
 }

+ 2 - 9
Source/ToolCore/JSBind/JSBModule.h

@@ -27,8 +27,8 @@ class JSBPrimitiveType;
 
 class JSBModule : public Object
 {
-    friend class JSBModuleWriter;
-    friend class CSBModuleWriter;
+    friend class JSModuleWriter;
+    friend class CSModuleWriter;
 
     OBJECT(JSBModule)
 
@@ -63,11 +63,6 @@ public:
     void ProcessClasses();
     void PostProcessClasses();
 
-    void GenerateSource(const String& outPath);
-    void GenerateCSharpSource(const String& outPath);
-
-    const String& GetSource();
-
 private:
 
     void ProcessOverloads();
@@ -96,8 +91,6 @@ private:
 
     SharedPtr<JSONFile> moduleJSON_;
 
-    String source_;
-
 };
 
 

+ 1 - 260
Source/ToolCore/JSBind/JSBModuleWriter.cpp

@@ -24,268 +24,9 @@ JSBModuleWriter::JSBModuleWriter(JSBModule *module) : module_(module)
 
 }
 
-void JSBModuleWriter::WriteForwardDeclarations(String& source)
+void JSBModuleWriter::GenerateSource()
 {
-    Vector<SharedPtr<JSBClass>> classes = module_->classes_.Values();
 
-    for (unsigned i = 0; i < classes.Size(); i++)
-    {
-        JSBClass* cls = classes.At(i);
-
-        if (cls->IsNumberArray())
-            continue;
-
-        source.AppendWithFormat("static duk_ret_t jsb_constructor_%s(duk_context* ctx);\n", cls->GetName().CString());
-        source.AppendWithFormat("static void jsb_class_define_%s(JSVM* vm);\n", cls->GetName().CString());
-
-    }
-}
-
-void JSBModuleWriter::WriteClassDeclaration(String& source)
-{
-    Vector<SharedPtr<JSBClass>> classes = module_->classes_.Values();
-
-    source += "static void jsb_declare_classes(JSVM* vm)\n{\n";
-
-    source += "duk_context* ctx = vm->GetJSContext();\n";
-
-    String packageName = module_->GetPackage()->GetName();
-
-    for (unsigned i = 0; i < classes.Size(); i++)
-    {
-        JSBClass* klass = classes.At(i);
-
-        if (klass->IsNumberArray())
-            continue;
-
-        source.AppendWithFormat("   js_class_declare<%s>(vm, \"%s\", \"%s\", jsb_constructor_%s);\n", klass->GetNativeName().CString(), packageName.CString(), klass->GetName().CString(), klass->GetName().CString());
-
-        if (klass->HasProperties())
-        {
-            source.AppendWithFormat("js_class_push_propertyobject(vm, \"%s\", \"%s\");\n", packageName.CString(), klass->GetName().CString());
-
-            Vector<String> pnames;
-            klass->GetPropertyNames(pnames);
-
-            for (unsigned j = 0; j < pnames.Size(); j++)
-            {
-                JSBProperty* prop = klass->GetProperty(pnames[j]);
-
-                source.Append("duk_push_object(ctx);\n");
-
-                if (prop->getter_ && !prop->getter_->Skip())
-                {
-                    source.AppendWithFormat("duk_push_c_function(ctx, jsb_class_%s_%s, 0);\n",
-                                            klass->GetName().CString(), prop->getter_->GetName().CString());
-                    source.Append("duk_put_prop_string(ctx, -2, \"get\");\n");
-                }
-                if (prop->setter_ && !prop->setter_->Skip())
-                {
-                    source.AppendWithFormat("duk_push_c_function(ctx, jsb_class_%s_%s, 1);\n",
-                                            klass->GetName().CString(), prop->setter_->GetName().CString());
-                    source.Append("duk_put_prop_string(ctx, -2, \"set\");\n");
-                }
-
-                String propertyName = prop->GetCasePropertyName();
-                source.AppendWithFormat("duk_put_prop_string(ctx, -2, \"%s\");\n", propertyName.CString());
-
-            }
-
-            source.Append("duk_pop(ctx);\n");
-
-        }
-    }
-
-    source += "\n}\n\n";
-
-}
-
-void JSBModuleWriter::WriteIncludes(String& source)
-{
-
-    Vector<String>& includes = module_->includes_;
-    for (unsigned i = 0; i < includes.Size(); i++)
-    {
-      if (includes[i].StartsWith("<"))
-          source.AppendWithFormat("#include %s\n", includes[i].CString());
-      else
-          source.AppendWithFormat("#include \"%s\"\n", includes[i].CString());
-    }
-
-    Vector<JSBHeader*> allheaders;
-
-    HashMap<StringHash, SharedPtr<JSBEnum> >::Iterator eitr = module_->enums_.Begin();
-    while (eitr != module_->enums_.End())
-    {
-        allheaders.Push(eitr->second_->GetHeader());
-        eitr++;
-    }
-
-    HashMap<StringHash, SharedPtr<JSBClass> >::Iterator citr = module_->classes_.Begin();
-    while (citr != module_->classes_.End())
-    {
-        allheaders.Push(citr->second_->GetHeader());
-        citr++;
-    }
-
-    Vector<JSBHeader*> included;
-
-    for (unsigned i = 0; i < allheaders.Size(); i++)
-    {
-        JSBHeader* header = allheaders.At(i);
-
-        if (included.Contains(header))
-            continue;
-
-        String headerPath = GetPath(header->GetFilePath());
-
-        String headerfile = GetFileNameAndExtension(header->GetFilePath());
-
-        JSBind* jsbind = header->GetSubsystem<JSBind>();
-
-        headerPath.Replace(jsbind->GetSourceRootFolder() + "Source/", "");
-
-        source.AppendWithFormat("#include <%s%s>\n", headerPath.CString(), headerfile.CString());
-
-        included.Push(header);
-    }
-
-}
-
-void JSBModuleWriter::WriteClassDefine(String& source)
-{
-    Vector<SharedPtr<JSBClass>> classes = module_->classes_.Values();
-
-    source += "static void jsb_init_classes(JSVM* vm)\n{\n";
-
-    for (unsigned i = 0; i < classes.Size(); i++)
-    {
-        JSBClass* klass = classes.At(i);
-
-        if (klass->IsNumberArray())
-            continue;
-
-        source.AppendWithFormat("   jsb_class_define_%s(vm);\n", klass->GetName().CString());
-    }
-
-    source += "\n}\n\n";
-
-}
-
-
-void JSBModuleWriter::WriteModulePreInit(String& source)
-{
-    source.AppendWithFormat("\nvoid jsb_package_%s_preinit_%s (JSVM* vm)\n{\n\njsb_declare_classes(vm);\n",
-                            module_->package_->GetName().ToLower().CString(), module_->GetName().ToLower().CString());
-
-    // register enums and constants
-    source += "// enums and constants\n";
-    source += "duk_context* ctx = vm->GetJSContext();\n";
-    source.AppendWithFormat("duk_get_global_string(ctx, \"%s\");\n", module_->package_->GetName().CString());
-    source += "// enums\n";
-
-    Vector<SharedPtr<JSBEnum>> enums = module_->enums_.Values();
-
-    for (unsigned i = 0; i < enums.Size(); i++)
-    {
-        JSBEnum* jenum = enums[i];
-
-        Vector<String>& values = jenum->GetValues();
-
-        for (unsigned k = 0; k < values.Size(); k++)
-        {
-            source.AppendWithFormat("duk_push_number(ctx, (double) %s);\n", values[k].CString());
-            source.AppendWithFormat("duk_put_prop_string(ctx, -2, \"%s\");\n",values[k].CString());
-        }
-    }
-    source += "// constants\n";
-
-    Vector<String> constants = module_->constants_.Keys();
-
-    for (unsigned i = 0; i < constants.Size(); i++)
-    {
-        source.AppendWithFormat("duk_push_number(ctx, (double) %s);\n", constants.At(i).CString());
-        source.AppendWithFormat("duk_put_prop_string(ctx, -2, \"%s\");\n", constants.At(i).CString());
-    }
-
-    source += "duk_pop(ctx);\n";
-    source += "// end enums and constants\n";
-
-    source += "\n}\n";
-
-}
-
-void JSBModuleWriter::WriteModuleInit(String& source)
-{
-    source.AppendWithFormat("\nvoid jsb_package_%s_init_%s (JSVM* vm)\n{\n\n    jsb_init_classes(vm);\n\n}\n\n",
-                            module_->package_->GetName().ToLower().CString(), module_->name_.ToLower().CString());
-}
-
-void JSBModuleWriter::GenerateSource(String& sourceOut)
-{
-    source_ = "// This file was autogenerated by JSBind, changes will be lost\n";
-
-    source_ += "#ifdef ATOMIC_PLATFORM_WINDOWS\n";
-
-    source_ += "#pragma warning(disable: 4244) // possible loss of data\n";
-
-    source_ += "#endif\n";
-
-    if (module_->Requires("3D"))
-    {
-        source_ += "#ifdef ATOMIC_3D\n";
-    }
-
-    source_ += "#include <Duktape/duktape.h>\n";
-    source_ += "#include <AtomicJS/Javascript/JSVM.h>\n";
-    source_ += "#include <AtomicJS/Javascript/JSAPI.h>\n";
-
-    WriteIncludes(source_);
-
-    String ns = module_->GetPackage()->GetNamespace();
-
-    if (ns != "Atomic")
-    {
-        source_ += "\n\nusing namespace " + ns + ";\n\n";
-    }
-
-    source_ += "\n\nnamespace Atomic\n{\n \n";
-
-    source_ += "// Begin Class Declarations\n";
-
-    WriteForwardDeclarations(source_);
-
-    source_ += "// End Class Declarations\n\n";
-
-    source_ += "// Begin Classes\n";
-
-    Vector<SharedPtr<JSBClass>> classes = module_->classes_.Values();
-
-    for (unsigned i = 0; i < classes.Size(); i++)
-    {
-        JSBClassWriter clsWriter(classes[i]);
-        clsWriter.GenerateSource(source_);
-    }
-
-    source_ += "// End Classes\n\n";
-
-    WriteClassDeclaration(source_);
-
-    WriteClassDefine(source_);
-
-    WriteModulePreInit(source_);
-
-    WriteModuleInit(source_);
-
-    // end Atomic namespace
-    source_ += "\n}\n";
-
-    if (module_->Requires("3D"))
-    {
-        source_ += "#endif //ATOMIC_3D\n";
-    }
-
-    sourceOut = source_;
 }
 
 }

+ 3 - 11
Source/ToolCore/JSBind/JSBModuleWriter.h

@@ -21,19 +21,11 @@ class JSBModuleWriter
 
 public:
 
-    JSBModuleWriter(JSBModule* module);
-
-    void GenerateSource(String& sourceOut);
+    virtual void GenerateSource();
 
-private:
+protected:
 
-    void WriteIncludes(String& source);
-    void WriteForwardDeclarations(String& source);
-    void WriteClassDeclaration(String& source);
-
-    void WriteClassDefine(String& source);
-    void WriteModulePreInit(String& source);
-    void WriteModuleInit(String& source);
+    JSBModuleWriter(JSBModule* module);
 
     JSBModule* module_;
     String source_;

+ 4 - 54
Source/ToolCore/JSBind/JSBPackage.cpp

@@ -13,13 +13,7 @@
 #include "JSBind.h"
 #include "JSBModule.h"
 #include "JSBPackage.h"
-
-#include "JSBDoc.h"
-
-#include "JSBPackageWriter.h" // Atomic JavaScript
-#include "JSBTypeScript.h" // Atomic TypeScript
-#include "JSBHaxe.h" // Atomic Haxe
-#include "CSharp/CSBPackageWriter.h" // Atomic C#
+#include "JSBPackageWriter.h"
 
 namespace ToolCore
 {
@@ -68,54 +62,10 @@ void JSBPackage::ProcessModules()
 
 }
 
-void JSBPackage::GenerateCSharpSource(const String &outPath)
-{
-    CSBPackageWriter writer(this);
-    writer.GenerateSource(source_);
-
-    String filepath = outPath + "/CSPackage" + name_ + ".cpp";
-
-    File file(context_);
-    file.Open(filepath, FILE_WRITE);
-    file.Write(source_.CString(), source_.Length());
-    file.Close();
-
-    for (unsigned i = 0; i < modules_.Size(); i++)
-    {
-        modules_[i]->GenerateCSharpSource(outPath);
-    }
-}
-
-void JSBPackage::GenerateSource(const String &outPath)
+void JSBPackage::GenerateSource(JSBPackageWriter& packageWriter)
 {
-    JSBPackageWriter writer(this);
-    writer.GenerateSource(source_);
-
-    String filepath = outPath + "/JSPackage" + name_ + ".cpp";
-
-    File file(context_);
-    file.Open(filepath, FILE_WRITE);
-    file.Write(source_.CString(), source_.Length());
-    file.Close();
-
-    for (unsigned i = 0; i < modules_.Size(); i++)
-    {
-        modules_[i]->GenerateSource(outPath);
-    }
-
-    JSBind* jsbind = GetSubsystem<JSBind>();
-
-    if (jsbind->GetPlatform() == "MACOSX" || jsbind->GetPlatform() == "WINDOWS" || jsbind->GetPlatform() == "LINUX")
-    {
-        JSBDoc jdoc;
-        jdoc.Emit(this, jsbind->GetSourceRootFolder() + "Artifacts/JSDoc/" + name_ + ".js");
-
-        JSBTypeScript ts;
-        ts.Emit(this, jsbind->GetSourceRootFolder() + "Script/TypeScript/" + name_ + ".d.ts");
-
-        JSBHaxe hx;
-        hx.Emit(this, jsbind->GetSourceRootFolder() + "Script/Haxe/" + name_ + ".hx");
-    }
+    packageWriter.GenerateSource();
+    packageWriter.PostProcess();
 }
 
 JSBClass* JSBPackage::GetClass(const String& name)

+ 5 - 5
Source/ToolCore/JSBind/JSBPackage.h

@@ -18,10 +18,13 @@ class JSBModule;
 class JSBClass;
 class JSBEnum;
 
+class JSBPackageWriter;
+
 class JSBPackage : public Object
 {
 
-    friend class JSBPackageWriter;
+    friend class JSPackageWriter;
+    friend class CSPackageWriter;
 
     OBJECT(JSBPackage)
 
@@ -59,8 +62,7 @@ public:
 
     static bool ContainsConstantAllPackages(const String& constantName);
 
-    void GenerateSource(const String& outPath);
-    void GenerateCSharpSource(const String &outPath);
+    void GenerateSource(JSBPackageWriter& packageWriter);
 
 private:
 
@@ -79,8 +81,6 @@ private:
 
     static Vector<SharedPtr<JSBPackage> > allPackages_;
 
-    String source_;
-
 };
 
 

+ 1 - 129
Source/ToolCore/JSBind/JSBPackageWriter.cpp

@@ -23,138 +23,10 @@ JSBPackageWriter::JSBPackageWriter(JSBPackage *package) : package_(package)
 
 }
 
-void JSBPackageWriter::WriteProtoTypeRecursive(String &source, JSBClass* klass,  Vector<JSBClass*>& written)
-{
-    if (written.Contains(klass))
-        return;
-
-    PODVector<JSBClass*>& baseClasses = klass->GetBaseClasses();
-
-    Vector<JSBClass*>::Iterator itr = baseClasses.End() - 1 ;
-
-    while (itr != baseClasses.Begin() - 1)
-    {
-        WriteProtoTypeRecursive(source, (*itr), written);
-        itr--;
-    }
-
-    JSBClass* base = baseClasses.Size() ? baseClasses[0] : NULL;
-
-    if (!klass->IsNumberArray() && klass->GetPackage() == package_)
-    {
-        JSBModule* module = klass->GetModule();
-
-        if (module->Requires("3D"))
-            source += "\n#ifdef ATOMIC_3D\n";
-
-        String packageName =  klass->GetModule()->GetPackage()->GetName();
-        String basePackage =  base ? base->GetModule()->GetPackage()->GetName() : "";
-
-        source.AppendWithFormat("   js_setup_prototype(vm, \"%s\", \"%s\", \"%s\", \"%s\", %s);\n",
-                                packageName.CString(), klass->GetName().CString(),
-                                base ? basePackage.CString() : "", base ? base->GetName().CString() : "",
-                                klass->HasProperties() ? "true" : "false");
-
-        if (module->Requires("3D"))
-            source += "#endif\n\n";
-    }
-
-    written.Push(klass);
 
-}
-
-void JSBPackageWriter::WriteProtoTypeSetup(String& source)
-{
-    Vector<JSBClass*> written;
-
-    PODVector<JSBClass*>& allClasses = package_->GetAllClasses();
-
-    for (unsigned i = 0; i < allClasses.Size(); i++)
-    {
-        WriteProtoTypeRecursive(source, allClasses[i], written);
-    }
-}
 
-void JSBPackageWriter::GenerateSource(String& sourceOut)
+void JSBPackageWriter::GenerateSource()
 {
-    String source = "// This file was autogenerated by JSBind, changes will be lost\n\n";
-    source += "#include <Duktape/duktape.h>\n";
-    source += "#include <AtomicJS/Javascript/JSVM.h>\n";
-    source += "#include <AtomicJS/Javascript/JSAPI.h>\n";
-
-    source += "\n\nnamespace Atomic\n{\n";
-
-    String packageLower = package_->GetName().ToLower();
-
-    for (unsigned i = 0; i < package_->modules_.Size(); i++)
-    {
-        JSBModule* module = package_->modules_.At(i);
-
-        String moduleLower = module->GetName().ToLower();
-
-        source.AppendWithFormat("\nextern void jsb_package_%s_preinit_%s (JSVM* vm);", packageLower.CString(), moduleLower.CString());
-        source.AppendWithFormat("\nextern void jsb_package_%s_init_%s (JSVM* vm);", packageLower.CString(), moduleLower.CString());
-    }
-
-    source += "\n\nstatic void jsb_modules_setup_prototypes(JSVM* vm)\n{\n";
-
-    source += "   // It is important that these are in order so the prototypes are created properly\n";
-    source += "   // This isn't trivial as modules can have dependencies, so do it here\n\n";
-
-    WriteProtoTypeSetup(source);
-
-    source += "\n}\n";
-
-    source.AppendWithFormat("\n\nstatic void jsb_package_%s_preinit(JSVM* vm)\n{", packageLower.CString());
-
-
-    source.Append("\n    // Create the global package object\n");
-    source.Append("    duk_context* ctx = vm->GetJSContext();\n");
-    source.Append("    duk_push_object(ctx);\n");
-    source.AppendWithFormat("    duk_put_global_string(ctx, \"%s\");\n", package_->GetName().CString());
-
-    for (unsigned i = 0; i < package_->modules_.Size(); i++)
-    {
-        JSBModule* module = package_->modules_.At(i);
-
-        if (module->Requires("3D"))
-            source += "\n#ifdef ATOMIC_3D";
-
-        String moduleLower = module->GetName().ToLower();
-
-        source.AppendWithFormat("\n   jsb_package_%s_preinit_%s(vm);", packageLower.CString(), moduleLower.CString());
-
-        if (module->Requires("3D"))
-            source += "\n#endif //ATOMIC_3D\n";
-    }
-
-    source += "\n}\n\n";
-
-    source.AppendWithFormat("\n\nvoid jsb_package_%s_init(JSVM* vm)\n{", packageLower.CString());
-
-    source.AppendWithFormat("\n\n   jsb_package_%s_preinit(vm);\n", packageLower.CString());
-
-    source += "\n\n   jsb_modules_setup_prototypes(vm);\n";
-
-    for (unsigned i = 0; i < package_->modules_.Size(); i++)
-    {
-        JSBModule* module = package_->modules_.At(i);
-
-        String moduleLower = module->GetName().ToLower();
-
-        if (module->Requires("3D"))
-            source += "\n#ifdef ATOMIC_3D";
-        source.AppendWithFormat("\n   jsb_package_%s_init_%s(vm);", packageLower.CString(), moduleLower.CString());
-        if (module->Requires("3D"))
-            source += "\n#endif //ATOMIC_3D\n";
-    }
-
-    source += "\n}\n\n";
-
-    // end Atomic namespace
-    source += "\n}\n";
-
-    sourceOut = source;
 
 }
 

+ 4 - 5
Source/ToolCore/JSBind/JSBPackageWriter.h

@@ -22,14 +22,13 @@ class JSBPackageWriter
 
 public:
 
-    JSBPackageWriter(JSBPackage* package);
+    virtual void GenerateSource();
 
-    void GenerateSource(String& sourceOut);
+    virtual void PostProcess() {}
 
-private:
+protected:
 
-    void WriteProtoTypeRecursive(String &source, JSBClass* klass,  Vector<JSBClass*>& written);
-    void WriteProtoTypeSetup(String& source);
+    JSBPackageWriter(JSBPackage* package);
 
     JSBPackage* package_;
 

+ 27 - 14
Source/ToolCore/JSBind/JSBind.cpp

@@ -11,6 +11,9 @@
 #include "JSBPackage.h"
 #include "JSBind.h"
 
+#include "JavaScript/JSPackageWriter.h"
+#include "CSharp/CSPackageWriter.h"
+
 namespace ToolCore
 {
 
@@ -25,7 +28,7 @@ JSBind::~JSBind()
 
 }
 
-bool JSBind::GenerateCSharpBindings(const String& sourceRootFolder, const String& packageFolder, const String& platform)
+bool JSBind::LoadPackage(const String& sourceRootFolder, const String& packageFolder, const String& platform)
 {
     sourceRootFolder_ = sourceRootFolder;
     packageFolder_ = packageFolder;
@@ -33,45 +36,55 @@ bool JSBind::GenerateCSharpBindings(const String& sourceRootFolder, const String
 
     package_->Load(sourceRootFolder_ + packageFolder_);
 
-    String modulesFolder = "Build/Source/Generated/" + platform + "/CSharp/Packages/";
+    return true;
+}
+
+bool JSBind::GenerateCSharpBindings()
+{
+
+    String modulesFolder = "Build/Source/Generated/" + platform_ + "/CSharp/Packages/";
     modulesFolder += package_->GetName() + "/";
 
-    String outputFolder = sourceRootFolder + "/" + modulesFolder;
+    String outputFolder = sourceRootFolder_ + "/" + modulesFolder;
 
     FileSystem* fs = GetSubsystem<FileSystem>();
 
-    if (!fs->CreateDirs(sourceRootFolder, modulesFolder) || !fs->DirExists(outputFolder))
+    if (!fs->CreateDirs(sourceRootFolder_, modulesFolder) || !fs->DirExists(outputFolder))
     {
         String error = "Unable to create bindings output folder: " + outputFolder;
         ErrorExit(error.CString());
     }
 
-    package_->GenerateCSharpSource(outputFolder);
+    destScriptFolder_ = outputFolder;
+    destNativeFolder_ = outputFolder;
+
+    CSPackageWriter writer(package_);
+    package_->GenerateSource(writer);
 
     return true;
 }
 
 
-bool JSBind::GenerateBindings(const String& sourceRootFolder, const String& packageFolder, const String& platform)
+bool JSBind::GenerateJavaScriptBindings()
 {
-    sourceRootFolder_ = sourceRootFolder;
-    packageFolder_ = packageFolder;
-    platform_ = platform;
-
-    String modulesFolder = "Build/Source/Generated/" + platform + "/Javascript/Packages/";
+    String modulesFolder = "Build/Source/Generated/" + platform_ + "/Javascript/Packages/";
     modulesFolder += package_->GetName() + "/";
 
-    String outputFolder = sourceRootFolder + "/" + modulesFolder;
+    String outputFolder = sourceRootFolder_ + "/" + modulesFolder;
 
     FileSystem* fs = GetSubsystem<FileSystem>();
 
-    if (!fs->CreateDirs(sourceRootFolder, modulesFolder) || !fs->DirExists(outputFolder))
+    if (!fs->CreateDirs(sourceRootFolder_, modulesFolder) || !fs->DirExists(outputFolder))
     {
         String error = "Unable to create bindings output folder: " + outputFolder;
         ErrorExit(error.CString());
     }
 
-    package_->GenerateSource(outputFolder);
+    destScriptFolder_ = String::EMPTY;
+    destNativeFolder_ = outputFolder;
+
+    JSPackageWriter writer(package_);
+    package_->GenerateSource(writer);
 
     return true;
 }

+ 10 - 2
Source/ToolCore/JSBind/JSBind.h

@@ -26,13 +26,18 @@ public:
     JSBind(Context* context);
     virtual ~JSBind();
 
-    bool GenerateBindings(const String& sourceRootFolder, const String& packageFolder, const String& platform);
-    bool GenerateCSharpBindings(const String& sourceRootFolder, const String& packageFolder, const String& platform);
+    bool LoadPackage(const String& sourceRootFolder, const String& packageFolder, const String& platform);
+
+    bool GenerateJavaScriptBindings();
+    bool GenerateCSharpBindings();
 
     const String& GetSourceRootFolder() { return sourceRootFolder_; }
     const String& GetPackageFolder() { return packageFolder_; }
     const String& GetPlatform() { return platform_; }
 
+    const String& GetDestScriptFolder() { return destScriptFolder_; }
+    const String& GetDestNativeFolder() { return destNativeFolder_; }
+
 private:
 
     SharedPtr<JSBPackage> package_;
@@ -41,6 +46,9 @@ private:
     String packageFolder_;
     String platform_;
 
+    String destScriptFolder_;
+    String destNativeFolder_;
+
 };
 
 

+ 6 - 6
Source/ToolCore/JSBind/CSharp/CSBClassWriter.cpp → Source/ToolCore/JSBind/JavaScript/JSClassWriter.cpp

@@ -14,19 +14,19 @@
 #include "../JSBClass.h"
 #include "../JSBFunction.h"
 
-#include "CSBClassWriter.h"
-#include "CSBFunctionWriter.h"
+#include "JSClassWriter.h"
+#include "JSFunctionWriter.h"
 
 namespace ToolCore
 {
 
-CSBClassWriter::CSBClassWriter(JSBClass *klass) : klass_(klass)
+JSClassWriter::JSClassWriter(JSBClass *klass) : JSBClassWriter(klass)
 {
 
 }
 
 
-void CSBClassWriter::WriteFunctions(String& source)
+void JSClassWriter::WriteFunctions(String& source)
 {
     for (unsigned i = 0; i < klass_->functions_.Size(); i++)
     {
@@ -38,13 +38,13 @@ void CSBClassWriter::WriteFunctions(String& source)
         if (function->IsDestructor())
             continue;
 
-        CSBFunctionWriter writer(function);
+        JSFunctionWriter writer(function);
         writer.GenerateSource(source);
     }
 
 }
 
-void CSBClassWriter::GenerateSource(String& sourceOut)
+void JSClassWriter::GenerateSource(String& sourceOut)
 {
     String source = "";
 

+ 4 - 4
Source/ToolCore/JSBind/CSharp/CSBClassWriter.h → Source/ToolCore/JSBind/JavaScript/JSClassWriter.h

@@ -9,6 +9,8 @@
 
 #include <Atomic/Container/Str.h>
 
+#include "../JSBClassWriter.h"
+
 using namespace Atomic;
 
 namespace ToolCore
@@ -17,12 +19,12 @@ namespace ToolCore
 class JSBPackage;
 class JSBClass;
 
-class CSBClassWriter
+class JSClassWriter : public JSBClassWriter
 {
 
 public:
 
-    CSBClassWriter(JSBClass* klass);
+    JSClassWriter(JSBClass* klass);
 
     void GenerateSource(String& sourceOut);
 
@@ -30,8 +32,6 @@ private:
 
     void WriteFunctions(String& source);
 
-    JSBClass* klass_;
-
 };
 
 }

+ 558 - 0
Source/ToolCore/JSBind/JavaScript/JSFunctionWriter.cpp

@@ -0,0 +1,558 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// LICENSE: Atomic Game Engine Editor and Tools EULA
+// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
+// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
+//
+
+#include <Atomic/IO/FileSystem.h>
+
+#include "../JSBind.h"
+#include "../JSBModule.h"
+#include "../JSBPackage.h"
+#include "../JSBEnum.h"
+#include "../JSBClass.h"
+#include "../JSBFunction.h"
+
+#include "JSFunctionWriter.h"
+
+namespace ToolCore
+{
+
+JSFunctionWriter::JSFunctionWriter(JSBFunction *function) : JSBFunctionWriter(function)
+{
+
+}
+
+void JSFunctionWriter::WriteParameterMarshal(String& source)
+{
+    // generate args
+    Vector<JSBFunctionType*>& parameters = function_->GetParameters();
+
+    int cparam = 0;
+    if (parameters.Size())
+    {
+        for (unsigned int i = 0; i < parameters.Size(); i++, cparam++)
+        {
+            JSBFunctionType * ptype = parameters.At(i);
+
+
+            // ignore "Context" parameters
+            if (ptype->type_->asClassType())
+            {
+                JSBClassType* classType = ptype->type_->asClassType();
+                JSBClass* klass = classType->class_;
+                if (klass->GetName() == "Context")
+                {
+                    cparam--;
+                    continue;
+                }
+
+            }
+
+            String pstring = ptype->ToArgString(cparam);
+            const String& init = ptype->initializer_;
+
+            if (ptype->type_->asClassType())
+            {
+                JSBClassType* classType = ptype->type_->asClassType();
+
+                JSBClass* klass = classType->class_;
+
+                if (!klass->IsNumberArray())
+                {
+                    if (init.Length())
+                    {
+                        source.AppendWithFormat("%s = duk_get_top(ctx) >= %i ? js_to_class_instance<%s>(ctx, %i, 0) : %s;\n",
+                                                pstring.CString(), cparam + 1, klass->GetNativeName().CString(), cparam, init.CString());
+                    }
+                    else
+                    {
+                        source.AppendWithFormat("%s = js_to_class_instance<%s>(ctx, %i, 0);\n",
+                                                pstring.CString(), klass->GetNativeName().CString(), cparam);
+                    }
+                }
+                else
+                {
+                    int elements = klass->GetNumberArrayElements();
+                    String elementType = klass->GetArrayElementType();
+                    source.AppendWithFormat("%s arrayData%i[%i];\n", elementType.CString(), cparam, elements);
+
+                    if (init.Length())
+                    {
+                        source.AppendWithFormat("const %s& defaultArg%i = %s;\n", klass->GetNativeName().CString(), cparam,  init.CString());
+                        source.AppendWithFormat("if (duk_get_top(ctx) >= %i) {\n", cparam + 1);
+                    }
+
+                    for (int j = 0; j < elements; j++)
+                    {
+                        source.AppendWithFormat("duk_get_prop_index(ctx, %i, %i);\n", cparam, j);
+                        source.AppendWithFormat("arrayData%i[%i] = (%s) duk_to_number(ctx, -1);\n", cparam, j, elementType.CString());
+                    }
+
+                    source.AppendWithFormat("duk_pop_n(ctx, %i);\n", elements);
+
+                    if (init.Length())
+                    {
+                        source.Append("}\n");
+
+                        source.AppendWithFormat("%s __arg%i(duk_get_top(ctx) >= %i ? arrayData%i : defaultArg%i);\n",
+                                                klass->GetNativeName().CString(), cparam, cparam + 1, cparam, cparam);
+                    }
+                    else
+                    {
+                        source.AppendWithFormat("%s __arg%i(arrayData%i);\n", klass->GetNativeName().CString(), cparam, cparam);
+                    }
+
+
+                }
+
+            }
+            else if (ptype->type_->asStringType() || ptype->type_->asStringHashType())
+            {
+                if (init.Length())
+                {
+                    source.AppendWithFormat("%s = duk_get_top(ctx) >= %i ? duk_to_string(ctx, %i) : %s;\n", pstring.CString(), cparam + 1, cparam, init.CString());
+                }
+                else
+                {
+                    source.AppendWithFormat("%s = duk_to_string(ctx, %i);\n", pstring.CString(),  cparam);
+
+                }
+            }
+            else if (ptype->type_->asHeapPtrType())
+            {
+                if (init.Length())
+                {
+                    source.AppendWithFormat("%s = duk_get_top(ctx) >= %i ? duk_get_heapptr(ctx, %i) : %s;\n", pstring.CString(), cparam + 1, cparam, init.CString());
+                }
+                else
+                {
+                    source.AppendWithFormat("%s = duk_get_heapptr(ctx, %i);\n", pstring.CString(),  cparam);
+
+                }
+            }
+            else if (ptype->type_->asPrimitiveType())
+            {
+                JSBPrimitiveType* prtype = ptype->type_->asPrimitiveType();
+
+                if (prtype->kind_ == JSBPrimitiveType::Bool)
+                {
+                    if (init.Length())
+                    {
+                        source.AppendWithFormat("bool __arg%i = duk_get_top(ctx) >= %i ? (duk_to_boolean(ctx, %i) ? true : false) : %s;\n",
+                                                cparam,  cparam + 1,   cparam, init.CString());
+                    }
+                    else
+                    {
+                        source.AppendWithFormat("bool __arg%i = duk_to_boolean(ctx, %i) ? true : false;\n",  cparam,  cparam);
+                    }
+                }
+                else
+                {
+                    if (init.Length())
+                    {
+                        source.AppendWithFormat("double __arg%i = duk_get_top(ctx) >= %i ? (duk_to_number(ctx, %i)) : %s;\n",
+                                                cparam,  cparam + 1,   cparam, init.CString());
+
+                    }
+                    else
+                    {
+                        source.AppendWithFormat("double __arg%i = duk_to_number(ctx, %i);\n",  cparam,  cparam);
+                    }
+                }
+
+            }
+            else if (ptype->type_->asEnumType())
+            {
+                JSBEnumType* etype = ptype->type_->asEnumType();
+
+                if (init.Length())
+                {
+                    source.AppendWithFormat("%s __arg%i = duk_get_top(ctx) >= %i ? ((%s) ((int) duk_to_number(ctx, %i))) : %s;\n", etype->enum_->GetName().CString(),
+                                            cparam,  cparam + 1, etype->enum_->GetName().CString(),  cparam, init.CString());
+
+                }
+                else
+                {
+                    source.AppendWithFormat("%s __arg%i = (%s) ((int)duk_to_number(ctx, %i));\n", etype->enum_->GetName().CString(),
+                                            cparam, etype->enum_->GetName().CString(),  cparam);
+
+                }
+
+            }
+            else if (ptype->type_->asVectorType())
+            {
+                // read only vector arguments
+                if (ptype->isConst_)
+                {
+                    JSBVectorType* vtype = ptype->type_->asVectorType();
+                    source.AppendWithFormat("%s __arg%i;\n", vtype->ToString().CString(), cparam);
+
+                    source.AppendWithFormat("if (duk_get_top(ctx) >= %i)\n{\n", cparam + 1);
+                    source.AppendWithFormat("duk_require_object_coercible(ctx, %i);\n", cparam);
+                    source.AppendWithFormat("unsigned sz = duk_get_length(ctx, %i);\n", cparam);
+                    source.AppendWithFormat("for (unsigned i = 0; i < sz; i++)\n{\n");
+
+                    source.AppendWithFormat("duk_get_prop_index(ctx, 2, i);\n");
+
+                    if (vtype->vectorType_->asStringType() || vtype->vectorType_->asStringHashType() )
+                    {
+                        source.AppendWithFormat("__arg%i.Push(duk_get_string(ctx, -1));\n", cparam);
+                    }
+
+                    source.AppendWithFormat("duk_pop(ctx);\n");
+
+                    source.AppendWithFormat("\n}\n");
+
+                    source.AppendWithFormat("\n}\n");
+
+                }
+            }
+
+        }
+    }
+}
+
+
+void JSFunctionWriter::WriteConstructor(String& source)
+{
+
+    // TODO: refactor this
+
+    if (function_->name_ == "RefCounted")
+    {
+        source.Append("// finalizer may be called more than once\n" \
+                      "static int jsb_finalizer_RefCounted(duk_context *ctx)\n" \
+                      "{\n" \
+                      "JSVM* vm =  JSVM::GetJSVM(ctx);\n" \
+                      \
+                      "duk_get_prop_index(ctx, 0, JS_INSTANCE_INDEX_FINALIZED);\n" \
+                      \
+                      "if (!duk_is_boolean(ctx, -1))\n" \
+                      "{\n" \
+                      "RefCounted* ref = vm->GetObjectPtr(duk_get_heapptr(ctx, 0));\n" \
+                      "vm->RemoveObject(ref);\n" \
+                      "ref->ReleaseRef();\n" \
+                      "duk_push_boolean(ctx, 1);\n" \
+                      "duk_put_prop_index(ctx, 0, JS_INSTANCE_INDEX_FINALIZED);\n" \
+                      "}\n" \
+                      \
+                      "return 0;\n" \
+                      "}\n");
+    }
+
+    JSBClass* klass = function_->class_;
+    JSBClass* base = klass->GetBaseClass();
+
+
+    // Constructor
+    source.AppendWithFormat("duk_ret_t jsb_constructor_%s(duk_context* ctx)\n{\n", klass->GetName().CString());
+
+    /*
+
+duk_ret_t jsb_constructor_MyJSClass(duk_context* ctx)
+{
+    JSVM* vm = JSVM::GetJSVM(ctx);
+    duk_push_this(ctx);
+    void *ptr = duk_get_heapptr(ctx, -1);
+    duk_pop(ctx);
+
+    if (!vm->GetObjectPtr(ptr, true))
+    {
+        if (!duk_get_top(ctx) || !duk_is_pointer(ctx, 0))
+        {
+            MyJSClass* native = new MyJSClass(JSVM::GetJSVM(ctx)->GetContext());
+            vm->AddObject(ptr, native);
+        }
+        else if (duk_is_pointer(ctx, 0))
+        {
+            vm->AddObject(ptr, (RefCounted*) duk_get_pointer(ctx, 0));
+        }
+    }
+
+    js_constructor_basecall(ctx, "Atomic", "AObject");
+    return 0;
+}
+
+     */
+
+    source.Append( "\nJSVM* vm = JSVM::GetJSVM(ctx);\n" \
+                   "duk_push_this(ctx);\n" \
+                   "void *ptr = duk_get_heapptr(ctx, -1);\n" \
+                   "duk_pop(ctx);\n\n");
+
+    source.Append("   if (!vm->GetObjectPtr(ptr, true))\n   {\n");
+
+    if (!klass->IsAbstract() && !klass->IsNumberArray())
+    {
+
+        String marshal;
+        WriteParameterMarshal(marshal);
+
+        String sparams;
+        int cparam = 0;
+
+        Vector<JSBFunctionType*>& parameters = function_->GetParameters();
+
+        for (unsigned i = 0; i < parameters.Size(); i++, cparam++)
+        {
+            JSBFunctionType * ptype = parameters.At(i);
+
+            String sarg;
+
+            if (ptype->type_->asClassType())
+            {
+                JSBClassType* classType = ptype->type_->asClassType();
+                JSBClass* klass = classType->class_;
+                if (klass->GetName() == "Context")
+                {
+                    sarg = "vm->GetContext()";
+                    cparam--;
+                }
+
+            }
+
+            if (!sarg.Length())
+            {
+                sarg.AppendWithFormat("__arg%i", cparam);
+            }
+
+            sparams += sarg;
+
+            if (i + 1 < parameters.Size())
+                sparams += ", ";
+
+        }
+
+        source.AppendWithFormat("if (!duk_get_top(ctx) || !duk_is_pointer(ctx, 0))\n"\
+                                "{\n"\
+                                "%s\n"\
+                                "%s* native = new %s(%s);\n" \
+                                "vm->AddObject(ptr, native);\n"\
+                                "}\n" \
+                                "else if (duk_is_pointer(ctx, 0))\n" \
+                                "{\n" \
+                                "vm->AddObject(ptr, (RefCounted*) duk_get_pointer(ctx, 0));\n" \
+                                "}\n", marshal.CString(), klass->GetNativeName().CString(), klass->GetNativeName().CString(), sparams.CString());
+    }
+    else
+    {
+        if (klass->IsAbstract())
+            source.Append("assert(0); // abstract class new'd\n");
+
+        if (klass->IsNumberArray())
+            source.Append("assert(0); // number array class new'd\n");
+
+    }
+    source.Append("   }\n");
+
+    if (base)
+    {
+        String basePackage = base->GetModule()->GetPackage()->GetName();
+        source.AppendWithFormat("   js_constructor_basecall(ctx, \"%s\", \"%s\");\n", basePackage.CString(), base->GetName().CString());
+    }
+
+    if (function_->name_ == "RefCounted")
+    {
+        source.Append("duk_push_this(ctx);\n "\
+                      "duk_push_c_function(ctx, jsb_finalizer_RefCounted, 1);\n "\
+                      "duk_set_finalizer(ctx, -2);\n "\
+                      \
+                      "RefCounted* ref = JSVM::GetJSVM(ctx)->GetObjectPtr(duk_get_heapptr(ctx, -1));\n "\
+                      "ref->AddRef();\n "\
+                      \
+                      "duk_pop(ctx);\n");
+
+    }
+
+    source += "   return 0;";
+    source += "\n}\n";
+
+}
+
+void JSFunctionWriter::WriteFunction(String& source)
+{
+    JSBClass* klass = function_->class_;
+
+    source.AppendWithFormat("static int jsb_class_%s_%s(duk_context* ctx)\n{\n", klass->GetName().CString(), function_->name_.CString());
+
+    WriteParameterMarshal(source);
+
+    source.Append("duk_push_this(ctx);\n");
+    source.AppendWithFormat("%s* native = js_to_class_instance<%s>(ctx, -1, 0);\n", klass->GetNativeName().CString(), klass->GetNativeName().CString());
+
+    // declare return value;
+    bool returnDeclared = false;
+
+    JSBFunctionType* returnType = function_->returnType_;
+
+    if (returnType)
+    {
+        if (returnType->type_->asStringType())
+        {
+            returnDeclared = true;
+            source.Append("const String& retValue = ");
+        }
+        else if (returnType->type_->asPrimitiveType())
+        {
+            returnDeclared = true;
+
+            JSBPrimitiveType* prtype = returnType->type_->asPrimitiveType();
+
+            if (prtype->kind_ == JSBPrimitiveType::Bool)
+            {
+                source.Append("bool retValue = ");
+            }
+            else
+            {
+                source.Append("double retValue = ");
+            }
+
+        }
+        else if (returnType->type_->asClassType())
+        {
+            JSBClassType* klassType = returnType->type_->asClassType();
+
+            if (returnType->isTemplate_)
+            {
+                returnDeclared = true;
+                source.AppendWithFormat("SharedPtr<%s> object = ", klassType->class_->GetNativeName().CString());
+            }
+            else if (klassType->class_->IsObject())
+            {
+                returnDeclared = true;
+                source.Append("const Object* object = ");
+            }
+            else if (klassType->class_->IsNumberArray())
+            {
+                returnDeclared = true;
+                source.AppendWithFormat("const %s& retValue = ", klassType->class_->GetName().CString());
+            }
+            else
+            {
+                returnDeclared = true;
+                source.Append("const RefCounted* object = ");
+            }
+        }
+        else if (returnType->type_->asEnumType())
+        {
+            JSBEnumType* enumType = returnType->type_->asEnumType();
+            returnDeclared = true;
+            source.AppendWithFormat("%s retValue = ", enumType->enum_->GetName().CString());
+        }
+        else if (returnType->type_->asVectorType())
+        {
+            returnDeclared = true;
+            JSBVectorType* vtype = returnType->type_->asVectorType();
+            source.AppendWithFormat("const %s& retValue = ", vtype->ToString().CString());
+        }
+
+    }
+
+    source.AppendWithFormat("native->%s(", function_->name_.CString());
+
+    Vector<JSBFunctionType*>& parameters = function_->GetParameters();
+
+    for (unsigned int i = 0; i < parameters.Size(); i++)
+    {
+        source.AppendWithFormat("__arg%i",  i);
+
+        if (i != parameters.Size() - 1)
+        {
+            source += ", ";
+        }
+    }
+
+    source += ");\n";
+
+    if (returnDeclared)
+    {
+        if (returnType->type_->asStringType())
+        {
+            source.Append("duk_push_string(ctx, retValue.CString());\n");
+        }
+        else if (returnType->type_->asPrimitiveType())
+        {
+            JSBPrimitiveType* prtype = returnType->type_->asPrimitiveType();
+
+            if (prtype->kind_ == JSBPrimitiveType::Bool)
+            {
+                source.Append("duk_push_boolean(ctx, retValue ? 1 : 0);\n");
+            }
+            else
+            {
+                source.Append("duk_push_number(ctx, retValue);\n");
+            }
+
+        }
+        else if (returnType->type_->asClassType())
+        {
+            JSBClassType* klassType = returnType->type_->asClassType();
+
+            if (klassType->class_->IsObject())
+            {
+                returnDeclared = true;
+                source.Append("js_push_class_object_instance(ctx, object);\n");
+            }
+            else if (klassType->class_->IsNumberArray())
+            {
+                returnDeclared = true;
+                String elementType = klassType->class_->GetArrayElementType();
+                source.AppendWithFormat("const %s* arrayData = retValue.Data();\n", elementType.CString());
+                source.Append("duk_push_array(ctx);\n");
+                for (int i = 0; i < klassType->class_->GetNumberArrayElements(); i++)
+                {
+                    source.AppendWithFormat("duk_push_number(ctx, arrayData[%i]);\n", i);
+                    source.AppendWithFormat("duk_put_prop_index(ctx, -2, %i);\n", i);
+                }
+            }
+            else
+            {
+                returnDeclared = true;
+                source.AppendWithFormat("js_push_class_object_instance(ctx, object, \"%s\");\n", klassType->class_->GetName().CString());
+            }
+        }
+        else if (returnType->type_->asEnumType())
+        {
+            returnDeclared = true;
+            source.Append("duk_push_number(ctx, (double) retValue);\n");
+        }
+        else if (returnType->type_->asVectorType())
+        {
+            source.Append("duk_push_array(ctx);\n");
+            source.Append("for (unsigned i = 0; i < retValue.Size(); i++)\n{\n");
+            source.Append("duk_push_string(ctx, retValue[i].CString());\n");
+            source.Append("duk_put_prop_index(ctx, -2, i);\n}\n");
+        }
+
+
+
+        source += "return 1;\n";
+    }
+    else
+    {
+        source += "return 0;\n";
+    }
+
+    source.Append("}\n");
+}
+
+void JSFunctionWriter::GenerateSource(String& sourceOut)
+{
+    String source = "";
+
+    if (function_->IsConstructor())
+    {
+        WriteConstructor(source);
+    }
+    else
+    {
+        WriteFunction(source);
+    }
+
+    sourceOut += source;
+
+}
+
+}

+ 4 - 4
Source/ToolCore/JSBind/CSharp/CSBFunctionWriter.h → Source/ToolCore/JSBind/JavaScript/JSFunctionWriter.h

@@ -9,6 +9,8 @@
 
 #include <Atomic/Container/Str.h>
 
+#include "../JSBFunctionWriter.h"
+
 using namespace Atomic;
 
 namespace ToolCore
@@ -17,12 +19,12 @@ namespace ToolCore
 class JSBPackage;
 class JSBFunction;
 
-class CSBFunctionWriter
+class JSFunctionWriter : public JSBFunctionWriter
 {
 
 public:
 
-    CSBFunctionWriter(JSBFunction* function);
+    JSFunctionWriter(JSBFunction* function);
 
     void GenerateSource(String& sourceOut);
 
@@ -32,8 +34,6 @@ private:
     void WriteConstructor(String& source);
     void WriteParameterMarshal(String& source);
 
-    JSBFunction* function_;
-
 };
 
 }

+ 302 - 0
Source/ToolCore/JSBind/JavaScript/JSModuleWriter.cpp

@@ -0,0 +1,302 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// LICENSE: Atomic Game Engine Editor and Tools EULA
+// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
+// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
+//
+
+#include <Atomic/IO/File.h>
+#include <Atomic/IO/FileSystem.h>
+
+#include "../JSBind.h"
+#include "../JSBPackage.h"
+#include "../JSBModule.h"
+#include "../JSBEnum.h"
+#include "../JSBClass.h"
+#include "../JSBFunction.h"
+
+
+#include "JSModuleWriter.h"
+#include "JSClassWriter.h"
+
+namespace ToolCore
+{
+
+JSModuleWriter::JSModuleWriter(JSBModule *module) : JSBModuleWriter(module)
+{
+
+}
+
+void JSModuleWriter::WriteForwardDeclarations(String& source)
+{
+    Vector<SharedPtr<JSBClass>> classes = module_->classes_.Values();
+
+    for (unsigned i = 0; i < classes.Size(); i++)
+    {
+        JSBClass* cls = classes.At(i);
+
+        if (cls->IsNumberArray())
+            continue;
+
+        source.AppendWithFormat("static duk_ret_t jsb_constructor_%s(duk_context* ctx);\n", cls->GetName().CString());
+        source.AppendWithFormat("static void jsb_class_define_%s(JSVM* vm);\n", cls->GetName().CString());
+
+    }
+}
+
+void JSModuleWriter::WriteClassDeclaration(String& source)
+{
+    Vector<SharedPtr<JSBClass>> classes = module_->classes_.Values();
+
+    source += "static void jsb_declare_classes(JSVM* vm)\n{\n";
+
+    source += "duk_context* ctx = vm->GetJSContext();\n";
+
+    String packageName = module_->GetPackage()->GetName();
+
+    for (unsigned i = 0; i < classes.Size(); i++)
+    {
+        JSBClass* klass = classes.At(i);
+
+        if (klass->IsNumberArray())
+            continue;
+
+        source.AppendWithFormat("   js_class_declare<%s>(vm, \"%s\", \"%s\", jsb_constructor_%s);\n", klass->GetNativeName().CString(), packageName.CString(), klass->GetName().CString(), klass->GetName().CString());
+
+        if (klass->HasProperties())
+        {
+            source.AppendWithFormat("js_class_push_propertyobject(vm, \"%s\", \"%s\");\n", packageName.CString(), klass->GetName().CString());
+
+            Vector<String> pnames;
+            klass->GetPropertyNames(pnames);
+
+            for (unsigned j = 0; j < pnames.Size(); j++)
+            {
+                JSBProperty* prop = klass->GetProperty(pnames[j]);
+
+                source.Append("duk_push_object(ctx);\n");
+
+                if (prop->getter_ && !prop->getter_->Skip())
+                {
+                    source.AppendWithFormat("duk_push_c_function(ctx, jsb_class_%s_%s, 0);\n",
+                                            klass->GetName().CString(), prop->getter_->GetName().CString());
+                    source.Append("duk_put_prop_string(ctx, -2, \"get\");\n");
+                }
+                if (prop->setter_ && !prop->setter_->Skip())
+                {
+                    source.AppendWithFormat("duk_push_c_function(ctx, jsb_class_%s_%s, 1);\n",
+                                            klass->GetName().CString(), prop->setter_->GetName().CString());
+                    source.Append("duk_put_prop_string(ctx, -2, \"set\");\n");
+                }
+
+                String propertyName = prop->GetCasePropertyName();
+                source.AppendWithFormat("duk_put_prop_string(ctx, -2, \"%s\");\n", propertyName.CString());
+
+            }
+
+            source.Append("duk_pop(ctx);\n");
+
+        }
+    }
+
+    source += "\n}\n\n";
+
+}
+
+void JSModuleWriter::WriteIncludes(String& source)
+{
+
+    Vector<String>& includes = module_->includes_;
+    for (unsigned i = 0; i < includes.Size(); i++)
+    {
+      if (includes[i].StartsWith("<"))
+          source.AppendWithFormat("#include %s\n", includes[i].CString());
+      else
+          source.AppendWithFormat("#include \"%s\"\n", includes[i].CString());
+    }
+
+    Vector<JSBHeader*> allheaders;
+
+    HashMap<StringHash, SharedPtr<JSBEnum> >::Iterator eitr = module_->enums_.Begin();
+    while (eitr != module_->enums_.End())
+    {
+        allheaders.Push(eitr->second_->GetHeader());
+        eitr++;
+    }
+
+    HashMap<StringHash, SharedPtr<JSBClass> >::Iterator citr = module_->classes_.Begin();
+    while (citr != module_->classes_.End())
+    {
+        allheaders.Push(citr->second_->GetHeader());
+        citr++;
+    }
+
+    Vector<JSBHeader*> included;
+
+    for (unsigned i = 0; i < allheaders.Size(); i++)
+    {
+        JSBHeader* header = allheaders.At(i);
+
+        if (included.Contains(header))
+            continue;
+
+        String headerPath = GetPath(header->GetFilePath());
+
+        String headerfile = GetFileNameAndExtension(header->GetFilePath());
+
+        JSBind* jsbind = header->GetSubsystem<JSBind>();
+
+        headerPath.Replace(jsbind->GetSourceRootFolder() + "Source/", "");
+
+        source.AppendWithFormat("#include <%s%s>\n", headerPath.CString(), headerfile.CString());
+
+        included.Push(header);
+    }
+
+}
+
+void JSModuleWriter::WriteClassDefine(String& source)
+{
+    Vector<SharedPtr<JSBClass>> classes = module_->classes_.Values();
+
+    source += "static void jsb_init_classes(JSVM* vm)\n{\n";
+
+    for (unsigned i = 0; i < classes.Size(); i++)
+    {
+        JSBClass* klass = classes.At(i);
+
+        if (klass->IsNumberArray())
+            continue;
+
+        source.AppendWithFormat("   jsb_class_define_%s(vm);\n", klass->GetName().CString());
+    }
+
+    source += "\n}\n\n";
+
+}
+
+
+void JSModuleWriter::WriteModulePreInit(String& source)
+{
+    source.AppendWithFormat("\nvoid jsb_package_%s_preinit_%s (JSVM* vm)\n{\n\njsb_declare_classes(vm);\n",
+                            module_->package_->GetName().ToLower().CString(), module_->GetName().ToLower().CString());
+
+    // register enums and constants
+    source += "// enums and constants\n";
+    source += "duk_context* ctx = vm->GetJSContext();\n";
+    source.AppendWithFormat("duk_get_global_string(ctx, \"%s\");\n", module_->package_->GetName().CString());
+    source += "// enums\n";
+
+    Vector<SharedPtr<JSBEnum>> enums = module_->enums_.Values();
+
+    for (unsigned i = 0; i < enums.Size(); i++)
+    {
+        JSBEnum* jenum = enums[i];
+
+        Vector<String>& values = jenum->GetValues();
+
+        for (unsigned k = 0; k < values.Size(); k++)
+        {
+            source.AppendWithFormat("duk_push_number(ctx, (double) %s);\n", values[k].CString());
+            source.AppendWithFormat("duk_put_prop_string(ctx, -2, \"%s\");\n",values[k].CString());
+        }
+    }
+    source += "// constants\n";
+
+    Vector<String> constants = module_->constants_.Keys();
+
+    for (unsigned i = 0; i < constants.Size(); i++)
+    {
+        source.AppendWithFormat("duk_push_number(ctx, (double) %s);\n", constants.At(i).CString());
+        source.AppendWithFormat("duk_put_prop_string(ctx, -2, \"%s\");\n", constants.At(i).CString());
+    }
+
+    source += "duk_pop(ctx);\n";
+    source += "// end enums and constants\n";
+
+    source += "\n}\n";
+
+}
+
+void JSModuleWriter::WriteModuleInit(String& source)
+{
+    source.AppendWithFormat("\nvoid jsb_package_%s_init_%s (JSVM* vm)\n{\n\n    jsb_init_classes(vm);\n\n}\n\n",
+                            module_->package_->GetName().ToLower().CString(), module_->name_.ToLower().CString());
+}
+
+void JSModuleWriter::GenerateSource()
+{
+    source_ = "// This file was autogenerated by JSBind, changes will be lost\n";
+
+    source_ += "#ifdef ATOMIC_PLATFORM_WINDOWS\n";
+
+    source_ += "#pragma warning(disable: 4244) // possible loss of data\n";
+
+    source_ += "#endif\n";
+
+    if (module_->Requires("3D"))
+    {
+        source_ += "#ifdef ATOMIC_3D\n";
+    }
+
+    source_ += "#include <Duktape/duktape.h>\n";
+    source_ += "#include <AtomicJS/Javascript/JSVM.h>\n";
+    source_ += "#include <AtomicJS/Javascript/JSAPI.h>\n";
+
+    WriteIncludes(source_);
+
+    String ns = module_->GetPackage()->GetNamespace();
+
+    if (ns != "Atomic")
+    {
+        source_ += "\n\nusing namespace " + ns + ";\n\n";
+    }
+
+    source_ += "\n\nnamespace Atomic\n{\n \n";
+
+    source_ += "// Begin Class Declarations\n";
+
+    WriteForwardDeclarations(source_);
+
+    source_ += "// End Class Declarations\n\n";
+
+    source_ += "// Begin Classes\n";
+
+    Vector<SharedPtr<JSBClass>> classes = module_->classes_.Values();
+
+    for (unsigned i = 0; i < classes.Size(); i++)
+    {
+        JSClassWriter clsWriter(classes[i]);
+        clsWriter.GenerateSource(source_);
+    }
+
+    source_ += "// End Classes\n\n";
+
+    WriteClassDeclaration(source_);
+
+    WriteClassDefine(source_);
+
+    WriteModulePreInit(source_);
+
+    WriteModuleInit(source_);
+
+    // end Atomic namespace
+    source_ += "\n}\n";
+
+    if (module_->Requires("3D"))
+    {
+        source_ += "#endif //ATOMIC_3D\n";
+    }
+
+    JSBind* jsbind = module_->GetSubsystem<JSBind>();
+
+    String filepath = jsbind->GetDestNativeFolder() + "/JSModule" + module_->name_ + ".cpp";
+
+    File file(module_->GetContext());
+    file.Open(filepath, FILE_WRITE);
+    file.Write(source_.CString(), source_.Length());
+    file.Close();
+
+}
+
+}

+ 42 - 0
Source/ToolCore/JSBind/JavaScript/JSModuleWriter.h

@@ -0,0 +1,42 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// LICENSE: Atomic Game Engine Editor and Tools EULA
+// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
+// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
+//
+
+#pragma once
+
+#include <Atomic/Container/Str.h>
+
+#include "../JSBModuleWriter.h"
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+class JSBModule;
+
+class JSModuleWriter : public JSBModuleWriter
+{
+
+public:
+
+    JSModuleWriter(JSBModule* module);
+
+    void GenerateSource();
+
+private:
+
+    void WriteIncludes(String& source);
+    void WriteForwardDeclarations(String& source);
+    void WriteClassDeclaration(String& source);
+
+    void WriteClassDefine(String& source);
+    void WriteModulePreInit(String& source);
+    void WriteModuleInit(String& source);
+
+};
+
+}

+ 199 - 0
Source/ToolCore/JSBind/JavaScript/JSPackageWriter.cpp

@@ -0,0 +1,199 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// LICENSE: Atomic Game Engine Editor and Tools EULA
+// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
+// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
+//
+
+#include <Atomic/IO/File.h>
+#include <Atomic/IO/FileSystem.h>
+
+#include "../JSBind.h"
+#include "../JSBModule.h"
+#include "../JSBPackage.h"
+#include "../JSBEnum.h"
+#include "../JSBClass.h"
+
+#include "../JSBDoc.h"
+#include "../JSBTypeScript.h"
+#include "../JSBHaxe.h"
+
+#include "JSPackageWriter.h"
+#include "JSModuleWriter.h"
+
+namespace ToolCore
+{
+
+JSPackageWriter::JSPackageWriter(JSBPackage *package) : JSBPackageWriter(package)
+{
+
+}
+
+void JSPackageWriter::WriteProtoTypeRecursive(String &source, JSBClass* klass,  Vector<JSBClass*>& written)
+{
+    if (written.Contains(klass))
+        return;
+
+    PODVector<JSBClass*>& baseClasses = klass->GetBaseClasses();
+
+    Vector<JSBClass*>::Iterator itr = baseClasses.End() - 1 ;
+
+    while (itr != baseClasses.Begin() - 1)
+    {
+        WriteProtoTypeRecursive(source, (*itr), written);
+        itr--;
+    }
+
+    JSBClass* base = baseClasses.Size() ? baseClasses[0] : NULL;
+
+    if (!klass->IsNumberArray() && klass->GetPackage() == package_)
+    {
+        JSBModule* module = klass->GetModule();
+
+        if (module->Requires("3D"))
+            source += "\n#ifdef ATOMIC_3D\n";
+
+        String packageName =  klass->GetModule()->GetPackage()->GetName();
+        String basePackage =  base ? base->GetModule()->GetPackage()->GetName() : "";
+
+        source.AppendWithFormat("   js_setup_prototype(vm, \"%s\", \"%s\", \"%s\", \"%s\", %s);\n",
+                                packageName.CString(), klass->GetName().CString(),
+                                base ? basePackage.CString() : "", base ? base->GetName().CString() : "",
+                                klass->HasProperties() ? "true" : "false");
+
+        if (module->Requires("3D"))
+            source += "#endif\n\n";
+    }
+
+    written.Push(klass);
+
+}
+
+void JSPackageWriter::WriteProtoTypeSetup(String& source)
+{
+    Vector<JSBClass*> written;
+
+    PODVector<JSBClass*>& allClasses = package_->GetAllClasses();
+
+    for (unsigned i = 0; i < allClasses.Size(); i++)
+    {
+        WriteProtoTypeRecursive(source, allClasses[i], written);
+    }
+}
+
+void JSPackageWriter::GenerateSource()
+{
+    String source = "// This file was autogenerated by JSBind, changes will be lost\n\n";
+    source += "#include <Duktape/duktape.h>\n";
+    source += "#include <AtomicJS/Javascript/JSVM.h>\n";
+    source += "#include <AtomicJS/Javascript/JSAPI.h>\n";
+
+    source += "\n\nnamespace Atomic\n{\n";
+
+    String packageLower = package_->GetName().ToLower();
+
+    for (unsigned i = 0; i < package_->modules_.Size(); i++)
+    {
+        JSBModule* module = package_->modules_.At(i);
+
+        String moduleLower = module->GetName().ToLower();
+
+        source.AppendWithFormat("\nextern void jsb_package_%s_preinit_%s (JSVM* vm);", packageLower.CString(), moduleLower.CString());
+        source.AppendWithFormat("\nextern void jsb_package_%s_init_%s (JSVM* vm);", packageLower.CString(), moduleLower.CString());
+    }
+
+    source += "\n\nstatic void jsb_modules_setup_prototypes(JSVM* vm)\n{\n";
+
+    source += "   // It is important that these are in order so the prototypes are created properly\n";
+    source += "   // This isn't trivial as modules can have dependencies, so do it here\n\n";
+
+    WriteProtoTypeSetup(source);
+
+    source += "\n}\n";
+
+    source.AppendWithFormat("\n\nstatic void jsb_package_%s_preinit(JSVM* vm)\n{", packageLower.CString());
+
+
+    source.Append("\n    // Create the global package object\n");
+    source.Append("    duk_context* ctx = vm->GetJSContext();\n");
+    source.Append("    duk_push_object(ctx);\n");
+    source.AppendWithFormat("    duk_put_global_string(ctx, \"%s\");\n", package_->GetName().CString());
+
+    for (unsigned i = 0; i < package_->modules_.Size(); i++)
+    {
+        JSBModule* module = package_->modules_.At(i);
+
+        if (module->Requires("3D"))
+            source += "\n#ifdef ATOMIC_3D";
+
+        String moduleLower = module->GetName().ToLower();
+
+        source.AppendWithFormat("\n   jsb_package_%s_preinit_%s(vm);", packageLower.CString(), moduleLower.CString());
+
+        if (module->Requires("3D"))
+            source += "\n#endif //ATOMIC_3D\n";
+    }
+
+    source += "\n}\n\n";
+
+    source.AppendWithFormat("\n\nvoid jsb_package_%s_init(JSVM* vm)\n{", packageLower.CString());
+
+    source.AppendWithFormat("\n\n   jsb_package_%s_preinit(vm);\n", packageLower.CString());
+
+    source += "\n\n   jsb_modules_setup_prototypes(vm);\n";
+
+    for (unsigned i = 0; i < package_->modules_.Size(); i++)
+    {
+        JSBModule* module = package_->modules_.At(i);
+
+        String moduleLower = module->GetName().ToLower();
+
+        if (module->Requires("3D"))
+            source += "\n#ifdef ATOMIC_3D";
+        source.AppendWithFormat("\n   jsb_package_%s_init_%s(vm);", packageLower.CString(), moduleLower.CString());
+        if (module->Requires("3D"))
+            source += "\n#endif //ATOMIC_3D\n";
+    }
+
+    source += "\n}\n\n";
+
+    // end Atomic namespace
+    source += "\n}\n";
+
+    JSBind* jsbind = package_->GetSubsystem<JSBind>();
+
+    String filepath = jsbind->GetDestNativeFolder() + "/JSPackage" + package_->name_ + ".cpp";
+
+    File file(package_->GetContext());
+    file.Open(filepath, FILE_WRITE);
+    file.Write(source.CString(), source.Length());
+    file.Close();
+
+    for (unsigned i = 0; i < package_->modules_.Size(); i++)
+    {
+        JSModuleWriter writer(package_->modules_[i]);
+        writer.GenerateSource();
+    }
+
+}
+
+void JSPackageWriter::PostProcess()
+{
+
+    JSBind* jsbind = package_->GetSubsystem<JSBind>();
+
+    if (jsbind->GetPlatform() == "MACOSX" || jsbind->GetPlatform() == "WINDOWS" || jsbind->GetPlatform() == "LINUX")
+    {
+        JSBDoc jdoc;
+        jdoc.Emit(package_, jsbind->GetSourceRootFolder() + "Artifacts/JSDoc/" + package_->GetName() + ".js");
+
+        JSBTypeScript ts;
+        ts.Emit(package_, jsbind->GetSourceRootFolder() + "Script/TypeScript/" + package_->GetName() + ".d.ts");
+
+        JSBHaxe hx;
+        hx.Emit(package_, jsbind->GetSourceRootFolder() + "Script/Haxe/" + package_->GetName() + ".hx");
+    }
+
+}
+
+}

+ 40 - 0
Source/ToolCore/JSBind/JavaScript/JSPackageWriter.h

@@ -0,0 +1,40 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// LICENSE: Atomic Game Engine Editor and Tools EULA
+// Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
+// license information: https://github.com/AtomicGameEngine/AtomicGameEngine
+//
+
+#pragma once
+
+#include <Atomic/Container/Str.h>
+
+#include "../JSBPackageWriter.h"
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+class JSBPackage;
+class JSBClass;
+
+class JSPackageWriter : public JSBPackageWriter
+{
+
+public:
+
+    JSPackageWriter(JSBPackage* package);
+
+    void GenerateSource();
+
+    virtual void PostProcess();
+
+private:
+
+    void WriteProtoTypeRecursive(String &source, JSBClass* klass,  Vector<JSBClass*>& written);
+    void WriteProtoTypeSetup(String& source);
+
+};
+
+}