Browse Source

Running from new Bindings

Josh Engebretson 10 years ago
parent
commit
523914d1bd
51 changed files with 1883 additions and 57 deletions
  1. 1 0
      CMake/Modules/AtomicAndroid.cmake
  2. 4 2
      CMake/Modules/AtomicIOS.cmake
  3. 2 0
      CMake/Modules/AtomicLinux.cmake
  4. 2 0
      CMake/Modules/AtomicMac.cmake
  5. 2 0
      CMake/Modules/AtomicWeb.cmake
  6. 2 1
      CMake/Modules/AtomicWindows.cmake
  7. 4 21
      Source/AtomicJS/CMakeLists.txt
  8. 4 4
      Source/AtomicJS/JSBind/CMakeLists.txt
  9. 0 1
      Source/AtomicJS/JSBind/JSBFunction.cpp
  10. 2 2
      Source/AtomicJS/Javascript/JSAtomic.cpp
  11. 26 0
      Source/AtomicJS/Packages/Atomic/Atomic2D.json
  12. 22 0
      Source/AtomicJS/Packages/Atomic/Atomic3D.json
  13. 11 0
      Source/AtomicJS/Packages/Atomic/Audio.json
  14. 6 0
      Source/AtomicJS/Packages/Atomic/Container.json
  15. 6 0
      Source/AtomicJS/Packages/Atomic/Environment.json
  16. 11 0
      Source/AtomicJS/Packages/Atomic/Graphics.json
  17. 6 0
      Source/AtomicJS/Packages/Atomic/Input.json
  18. 5 0
      Source/AtomicJS/Packages/Atomic/Javascript.json
  19. 7 0
      Source/AtomicJS/Packages/Atomic/Math.json
  20. 8 0
      Source/AtomicJS/Packages/Atomic/Network.json
  21. 8 3
      Source/AtomicJS/Packages/Atomic/Package.json
  22. 13 0
      Source/AtomicJS/Packages/Atomic/Physics.json
  23. 5 0
      Source/AtomicJS/Packages/Atomic/Resource.json
  24. 12 0
      Source/AtomicJS/Packages/Atomic/Scene.json
  25. 7 1
      Source/AtomicTool/CMakeLists.txt
  26. 1 0
      Source/CMakeLists.txt
  27. 25 3
      Source/ToolCore/Command/BindCmd.cpp
  28. 258 5
      Source/ToolCore/JSBind/JSBClass.cpp
  29. 50 5
      Source/ToolCore/JSBind/JSBClass.h
  30. 90 0
      Source/ToolCore/JSBind/JSBClassWriter.cpp
  31. 30 0
      Source/ToolCore/JSBind/JSBClassWriter.h
  32. 1 1
      Source/ToolCore/JSBind/JSBEnum.cpp
  33. 8 0
      Source/ToolCore/JSBind/JSBEnum.h
  34. 51 0
      Source/ToolCore/JSBind/JSBFunction.cpp
  35. 5 0
      Source/ToolCore/JSBind/JSBFunction.h
  36. 482 0
      Source/ToolCore/JSBind/JSBFunctionWriter.cpp
  37. 32 0
      Source/ToolCore/JSBind/JSBFunctionWriter.h
  38. 3 2
      Source/ToolCore/JSBind/JSBHeader.h
  39. 2 2
      Source/ToolCore/JSBind/JSBHeaderVisitor.h
  40. 66 2
      Source/ToolCore/JSBind/JSBModule.cpp
  41. 17 1
      Source/ToolCore/JSBind/JSBModule.h
  42. 283 0
      Source/ToolCore/JSBind/JSBModuleWriter.cpp
  43. 36 0
      Source/ToolCore/JSBind/JSBModuleWriter.h
  44. 36 0
      Source/ToolCore/JSBind/JSBPackage.cpp
  45. 13 0
      Source/ToolCore/JSBind/JSBPackage.h
  46. 146 0
      Source/ToolCore/JSBind/JSBPackageWriter.cpp
  47. 31 0
      Source/ToolCore/JSBind/JSBPackageWriter.h
  48. 1 0
      Source/ToolCore/JSBind/JSBPreprocessVisitor.h
  49. 1 1
      Source/ToolCore/JSBind/JSBType.h
  50. 17 0
      Source/ToolCore/JSBind/JSBind.cpp
  51. 22 0
      Source/ToolCoreJS/CMakeLists.txt

+ 1 - 0
CMake/Modules/AtomicAndroid.cmake

@@ -1,4 +1,5 @@
 
+set (JAVASCRIPT_BINDINGS_PLATFORM "ANDROID")
 
 add_definitions(-DATOMIC_PLATFORM_ANDROID)
 add_definitions(-DATOMIC_OPENGL -DKNET_UNIX)

+ 4 - 2
CMake/Modules/AtomicIOS.cmake

@@ -1,5 +1,7 @@
 include (BundleUtilities)
 
+set (JAVASCRIPT_BINDINGS_PLATFORM "IOS")
+
 add_definitions (-DIOS -DATOMIC_PLATFORM_IOS -DATOMIC_OPENGL -DKNET_UNIX)
 set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-offsetof -std=gnu++0x")
 
@@ -7,10 +9,10 @@ set (CMAKE_OSX_ARCHITECTURES $(ARCHS_STANDARD_INCLUDING_64_BIT))
 set (CMAKE_XCODE_EFFECTIVE_PLATFORMS -iphoneos -iphonesimulator)
 
 # Set Base SDK to "Latest iOS"
-set (CMAKE_OSX_SYSROOT iphoneos)    
+set (CMAKE_OSX_SYSROOT iphoneos)
 
 # Obtain iOS sysroot path
-execute_process (COMMAND xcodebuild -version -sdk ${CMAKE_OSX_SYSROOT} Path OUTPUT_VARIABLE IOS_SYSROOT OUTPUT_STRIP_TRAILING_WHITESPACE)   
+execute_process (COMMAND xcodebuild -version -sdk ${CMAKE_OSX_SYSROOT} Path OUTPUT_VARIABLE IOS_SYSROOT OUTPUT_STRIP_TRAILING_WHITESPACE)
 
 set (CMAKE_FIND_ROOT_PATH ${IOS_SYSROOT})
 

+ 2 - 0
CMake/Modules/AtomicLinux.cmake

@@ -1,5 +1,7 @@
 include(AtomicDesktop)
 
+set (JAVASCRIPT_BINDINGS_PLATFORM "LINUX")
+
 add_definitions(-DATOMIC_PLATFORM_LINUX -DATOMIC_OPENGL -DKNET_UNIX -DHAVE_INT64_T)
 
 set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-offsetof -std=gnu++0x")

+ 2 - 0
CMake/Modules/AtomicMac.cmake

@@ -2,6 +2,8 @@
 include (BundleUtilities)
 include(AtomicDesktop)
 
+set (JAVASCRIPT_BINDINGS_PLATFORM "MACOSX")
+
 add_definitions(-DATOMIC_PLATFORM_OSX -DATOMIC_OPENGL -DKNET_UNIX)
 
 list (APPEND ATOMIC_LINK_LIBRARIES GLEW)

+ 2 - 0
CMake/Modules/AtomicWeb.cmake

@@ -1,4 +1,6 @@
 
+set (JAVASCRIPT_BINDINGS_PLATFORM "WEB")
+
 add_definitions(-DATOMIC_PLATFORM_WEB)
 add_definitions(-DATOMIC_OPENGL -Wno-warn-absolute-paths -DATOMIC_TBUI)
 

+ 2 - 1
CMake/Modules/AtomicWindows.cmake

@@ -1,7 +1,8 @@
 
-
 include(AtomicDesktop)
 
+set (JAVASCRIPT_BINDINGS_PLATFORM "WINDOWS")
+
 #set (CMAKE_DEBUG_POSTFIX _d)
 
 set (D3DCOMPILER_47_DLL ${CMAKE_SOURCE_DIR}/Build/Windows/Binaries/x64/D3DCompiler_47.dll)

+ 4 - 21
Source/AtomicJS/CMakeLists.txt

@@ -1,20 +1,4 @@
 
-if (MSVC)
-    set (JAVASCRIPT_BINDINGS_PLATFORM "WINDOWS")
-elseif(APPLE)
-    if (NOT IOS)
-      set (JAVASCRIPT_BINDINGS_PLATFORM "MACOSX")
-    else()
-      set (JAVASCRIPT_BINDINGS_PLATFORM "IOS")
-    endif()
-elseif(LINUX)
-    set (JAVASCRIPT_BINDINGS_PLATFORM "LINUX")
-elseif(ANDROID)
-    set (JAVASCRIPT_BINDINGS_PLATFORM "ANDROID")
-elseif (EMSCRIPTEN)
-  set (JAVASCRIPT_BINDINGS_PLATFORM "WEB")
-endif()
-
 if (NOT IOS AND NOT ANDROID AND NOT EMSCRIPTEN)
     add_subdirectory(JSBind)
 endif()
@@ -39,12 +23,12 @@ endif()
 set (JSFILES JSModuleAtomic2D.cpp;JSModuleAtomic3D.cpp;JSModuleAudio.cpp;JSModuleContainer.cpp;JSModuleCore.cpp;
              JSModuleEngine.cpp;JSModuleEnvironment.cpp;JSModuleGraphics.cpp;JSModuleInput.cpp;
              JSModuleIO.cpp;JSModuleJavascript.cpp;JSModuleMath.cpp;JSModuleNavigation.cpp;
-             JSModuleNetwork.cpp;JSModulePhysics.cpp;JSModuleResource.cpp;JSModules.cpp;
+             JSModuleNetwork.cpp;JSModulePhysics.cpp;JSModuleResource.cpp;JSPackageAtomic.cpp;
              JSModuleScene.cpp;JSModuleUI.cpp)
 
 foreach(JSFILE ${JSFILES})
 
-  set (JSFILEPATH "${CMAKE_SOURCE_DIR}/Build/Source/Generated/${JAVASCRIPT_BINDINGS_PLATFORM}/Javascript/Modules/${JSFILE}")
+  set (JSFILEPATH "${CMAKE_SOURCE_DIR}/Build/Source/Generated/${JAVASCRIPT_BINDINGS_PLATFORM}/Javascript/Packages/Atomic/${JSFILE}")
 
   if (NOT EXISTS ${JSFILEPATH})
     file(WRITE "${JSFILEPATH}" "// will be created by JSBind")
@@ -53,17 +37,16 @@ foreach(JSFILE ${JSFILES})
 endforeach()
 
 
-file (GLOB JAVASCRIPT_BINDINGS_SOURCE ${CMAKE_SOURCE_DIR}/Build/Source/Generated/${JAVASCRIPT_BINDINGS_PLATFORM}/Javascript/Modules/*.cpp)
+file (GLOB JAVASCRIPT_BINDINGS_SOURCE ${CMAKE_SOURCE_DIR}/Build/Source/Generated/${JAVASCRIPT_BINDINGS_PLATFORM}/Javascript/Packages/Atomic/*.cpp)
 
 set (SOURCE_FILES ${JAVASCRIPT_SOURCE} ${JAVASCRIPT_BINDINGS_SOURCE} )
 
 add_library(AtomicJS ${SOURCE_FILES})
 
 if (NOT IOS AND NOT ANDROID AND NOT EMSCRIPTEN)
-    add_dependencies(AtomicJS JSBind)
+    add_dependencies(AtomicJS AtomicTool)
 endif()
 
 add_custom_command (TARGET AtomicJS POST_BUILD
 COMMAND ${CMAKE_COMMAND}
 ARGS -E copy_if_different \"${CMAKE_CURRENT_SOURCE_DIR}/JSPlugin/AtomicPlugin.h\" \"${CMAKE_SOURCE_DIR}/Bin/NativePluginSDK/AtomicPlugin.h\")
-

+ 4 - 4
Source/AtomicJS/JSBind/CMakeLists.txt

@@ -22,10 +22,10 @@ if (MSVC)
 endif()
 
 #TODO: finer grained dependencies
-add_custom_command(TARGET JSBind POST_BUILD
-                   COMMAND $<TARGET_FILE:JSBind> "\"${CMAKE_SOURCE_DIR}\"" "${JAVASCRIPT_BINDINGS_PLATFORM}"
-                   COMMENT "Generating Javascript Bindings")
+#add_custom_command(TARGET JSBind POST_BUILD
+#                   COMMAND $<TARGET_FILE:JSBind> "\"${CMAKE_SOURCE_DIR}\"" "${JAVASCRIPT_BINDINGS_PLATFORM}"
+#                   COMMENT "Generating Javascript Bindings")
                    
                    
         
-                   
+                   

+ 0 - 1
Source/AtomicJS/JSBind/JSBFunction.cpp

@@ -173,7 +173,6 @@ void JSBFunction::Process()
         return;
     }
 
-
     // if not already marked as a getter
     if (!isGetter_)
     {

+ 2 - 2
Source/AtomicJS/Javascript/JSAtomic.cpp

@@ -29,7 +29,7 @@
 namespace Atomic
 {
 
-extern void jsb_modules_init(JSVM* vm);
+extern void jsb_package_atomic_init(JSVM* vm);
 
 static int js_module_read_file(duk_context* ctx)
 {
@@ -252,7 +252,7 @@ static int js_atomic_destroy(duk_context* ctx)
 void jsapi_init_atomic(JSVM* vm)
 {
     // core modules
-    jsb_modules_init(vm);
+    jsb_package_atomic_init(vm);
 
     // extensions
     jsapi_init_core(vm);

+ 26 - 0
Source/AtomicJS/Packages/Atomic/Atomic2D.json

@@ -0,0 +1,26 @@
+{
+	"name" : "Atomic2D",
+	"sources" : ["Source/Atomic/Atomic2D"],
+	"includes" : ["<Atomic/Graphics/Texture2D.h>", "<Atomic/Scene/Node.h>", "<Atomic/Graphics/Material.h>"],
+	"classes" : [ "SpriteSheet2D", "Sprite2D", "Drawable2D", "StaticSprite2D", "AnimationSet2D", "AnimatedSprite2D",
+				 "CollisionShape2D", "CollisionBox2D", "RigidBody2D", "Animation2D", "CollisionChain2D",
+				 "CollisionCircle2D", "CollisionEdge2D", "CollisionPolygon2D",
+				 "Constraint2D", "ConstraintDistance2D", "ConstraintFriction2D", "ConstraintGear2D",
+				 "ConstraintMotor2D", "ConstraintMouse2D", "ConstraintPrismatic2D", "ConstraintPulley2D",
+				 "ConstraintRevolute2D", "ConstraintRope2D", "ConstraintWeld2D", "ConstraintWheel2D",
+				 "ParticleEffect2D", "ParticleEmitter2D", "PhysicsWorld2D",
+				 "TileMap2D", "PropertySet2D", "Tile2D", "TileMapObject2D", "TileMapLayer2D",
+				 "TmxLayer2D", "TmxTileLayer2D", "TmxObjectGroup2D", "TmxImageLayer2D", "TmxFile2D",
+				 "Light2DGroup", "Light2D", "DirectionalLight2D", "PositionalLight2D", "PointLight2D"],
+	"overloads" : {
+		"AnimatedSprite2D" : {
+			"SetAnimation" : ["AnimationSet2D", "String", "LoopMode2D"]
+		},
+		"CollisionBox2D" : {
+			"SetSize" : ["Vector2"]
+		},
+		"PhysicsWorld2D" : {
+			"DrawDebugGeometry" : []
+		}
+	}
+}

+ 22 - 0
Source/AtomicJS/Packages/Atomic/Atomic3D.json

@@ -0,0 +1,22 @@
+{
+	"name" : "Atomic3D",
+	"sources" : ["Source/Atomic/Atomic3D"],
+	"requires" : ["3D"],
+	"includes" : ["<Atomic/Container/ArrayPtr.h>","<Atomic/Scene/Scene.h>", "<Atomic/Atomic3D/Animation.h>", "<Atomic/Graphics/OcclusionBuffer.h>",
+			      "<Atomic/Scene/ValueAnimation.h>", "<Atomic/Graphics/Material.h>", "<Atomic/Resource/Image.h>"],
+	"classes" : ["Model",
+				 "StaticModel",
+				 "Animation", "AnimatedModel", "AnimationController", "AnimationState", "BillboardSet", "CustomGeometry",
+				 "DecalSet", "ParticleEffect", "ParticleEmitter",
+				 "Skybox", "StaticModelGroup", "Terrain", "TerrainPatch"],
+	"overloads" : {
+		"StaticModel" : {
+			"SetMaterial" : ["Material"]
+		},
+		"AnimationState" : {
+			"AnimationState" : ["AnimatedModel", "Animation"]
+		}
+
+	}
+
+}

+ 11 - 0
Source/AtomicJS/Packages/Atomic/Audio.json

@@ -0,0 +1,11 @@
+{
+	"name" : "Audio",
+	"sources" : ["Source/Atomic/Audio"],
+	"classes" : ["Sound", "SoundSource"],
+	"overloads" : {
+		"SoundSource" : {
+			"Play" : ["Sound"]
+		}
+	}
+
+ }

+ 6 - 0
Source/AtomicJS/Packages/Atomic/Container.json

@@ -0,0 +1,6 @@
+{
+	"name" : "Engine",
+	"sources" : ["Source/Atomic/Engine"],
+	"includes" : [],
+	"classes" : ["Engine"]
+}

+ 6 - 0
Source/AtomicJS/Packages/Atomic/Environment.json

@@ -0,0 +1,6 @@
+{
+	"name" : "Environment",
+	"requires" : ["3D"],
+	"sources" : ["Source/Atomic/Environment"],
+	"classes" : ["ProcSky"]
+}

+ 11 - 0
Source/AtomicJS/Packages/Atomic/Graphics.json

@@ -0,0 +1,11 @@
+{
+	"name" : "IO",
+	"sources" : ["Source/Atomic/IO"],
+	"classes" : ["Log", "File", "FileSystem", "FileWatcher"],
+	"overloads" : {
+		"File" : {
+			"File" : ["Context", "String", "FileMode"]
+		}
+	}
+
+}

+ 6 - 0
Source/AtomicJS/Packages/Atomic/Input.json

@@ -0,0 +1,6 @@
+{
+	"name" : "Input",
+	"sources" : ["Source/Atomic/Input"],
+	"classes" : ["Input"]
+
+}

+ 5 - 0
Source/AtomicJS/Packages/Atomic/Javascript.json

@@ -0,0 +1,5 @@
+{
+	"name" : "Javascript",
+	"sources" : ["Source/AtomicJS/Javascript"],
+	"classes" : ["JSVM", "JSComponent", "JSMetrics", "JSEventHelper"]
+}

+ 7 - 0
Source/AtomicJS/Packages/Atomic/Math.json

@@ -0,0 +1,7 @@
+{
+	"name" : "Navigation",
+	"requires" : ["3D"],
+	"sources" : ["Source/Atomic/Navigation"],
+	"includes" : ["<Atomic/Scene/Node.h>"],
+	"classes" : ["Navigable", "NavigationMesh", "OffMeshConnection"]
+}

+ 8 - 0
Source/AtomicJS/Packages/Atomic/Network.json

@@ -0,0 +1,8 @@
+{
+	"name" : "Network",
+	"sources" : ["Source/Atomic/Network"],
+	"includes" : ["<Atomic/Network/Protocol.h>", "<Atomic/Scene/Scene.h>"],
+	"classes" : ["Network", "NetworkPriority"]
+
+
+}

+ 8 - 3
Source/AtomicJS/Packages/Atomic/Package.json

@@ -1,8 +1,13 @@
 
 {
+	"name" : "Atomic",
+	"namespace" : "Atomic",
 
-  "name" : "Atomic",
-  "namespace" : "Atomic",
-  "modules" : ["Container", "Math", "Core", "Graphics", "Scene"]
+	"modules" : ["Container", "Math", "Core", "Scene", "Graphics", "Atomic3D", "Atomic2D", "Audio",
+	"Physics", "Navigation", "Input", "UI", "Resource", "Network", "IO",
+	"Engine", "Javascript", "Environment"],
 
+	"moduleExclude" : {
+		"WEB" : ["Network", "Navigation"]
+	}
 }

+ 13 - 0
Source/AtomicJS/Packages/Atomic/Physics.json

@@ -0,0 +1,13 @@
+{
+	"name" : "Physics",
+	"requires" : ["3D"],
+	"sources" : ["Source/Atomic/Physics"],
+	"includes" : ["<Atomic/Atomic3D/Model.h>"],
+	"classes" : ["CollisionShape", "Constraint", "PhysicsWorld", "RigidBody"],
+ 	"overloads" : {
+		"RigidBody" : {
+			"ApplyImpulse" : ["Vector3"]
+		}
+
+	}
+}

+ 5 - 0
Source/AtomicJS/Packages/Atomic/Resource.json

@@ -0,0 +1,5 @@
+{
+	"name" : "Resource",
+	"sources" : ["Source/Atomic/Resource"],
+	"classes" : ["Resource", "ResourceCache", "XMLFile", "PListFile", "JSONFile", "Image"]
+}

+ 12 - 0
Source/AtomicJS/Packages/Atomic/Scene.json

@@ -0,0 +1,12 @@
+{
+	"name" : "UI",
+	"sources" : ["Source/Atomic/UI"],
+	"includes" : ["<Atomic/Graphics/Material.h>", "<Atomic/Scene/Node.h>", "<Atomic/Scene/Scene.h>", "<Atomic/Graphics/Texture2D.h>",
+								"<Atomic/UI/UIBatch.h>"],
+	"classes" : ["UIWidget", "UILayout", "UIView", "UIWindow", "UIButton", "UITextField",
+								"UISelectItem", "UISelectItemSource", "UIMenuWindow", "UIEditField",
+								"UIImageWidget", "UIClickLabel", "UICheckBox", "UIMenuItem", "UIMenuItemSource",
+								"UISelectList", "UIListView"],
+	"overloads" : {
+	}
+}

+ 7 - 1
Source/AtomicTool/CMakeLists.txt

@@ -8,7 +8,7 @@ add_executable(AtomicTool ${ATOMIC_TOOL_SOURCES})
 
 target_link_libraries(AtomicTool ToolCore Poco ${ATOMIC_LINK_LIBRARIES})
 
-add_dependencies(AtomicTool AtomicEditor)
+# add_dependencies(AtomicTool AtomicEditor)
 
 if (MSVC)
     target_link_libraries(AtomicTool libcurl Iphlpapi Wldap32)
@@ -22,3 +22,9 @@ if (MSVC)
 else()
     target_link_libraries(AtomicTool curl)
 endif()
+
+
+add_custom_command(TARGET AtomicTool POST_BUILD
+                   COMMAND $<TARGET_FILE:AtomicTool> bind "\"${CMAKE_SOURCE_DIR}\"" "Source/AtomicJS/Packages/Atomic/" "${JAVASCRIPT_BINDINGS_PLATFORM}"
+                   COMMAND $<TARGET_FILE:AtomicTool> bind "\"${CMAKE_SOURCE_DIR}\"" "Source/AtomicJS/Packages/ToolCore/" "${JAVASCRIPT_BINDINGS_PLATFORM}"
+                   COMMENT "Generating Javascript Bindings")

+ 1 - 0
Source/CMakeLists.txt

@@ -6,6 +6,7 @@ add_subdirectory(AtomicPlayer)
 
 if (NOT IOS AND NOT ANDROID AND NOT EMSCRIPTEN)
     add_subdirectory(ToolCore)
+    add_subdirectory(ToolCoreJS)
     add_subdirectory(AtomicEditor)
     add_subdirectory(AtomicEditorWork)
     add_subdirectory(AtomicTool)

+ 25 - 3
Source/ToolCore/Command/BindCmd.cpp

@@ -27,7 +27,9 @@ BindCmd::~BindCmd()
 bool BindCmd::Parse(const Vector<String>& arguments, unsigned startIndex, String& errorMsg)
 {
     String argument = arguments[startIndex].ToLower();
-    String value = startIndex + 1 < arguments.Size() ? arguments[startIndex + 1] : String::EMPTY;
+    sourceRootFolder_ = startIndex + 1 < arguments.Size() ? arguments[startIndex + 1] : String::EMPTY;
+    packageFolder_ = startIndex + 2 < arguments.Size() ? arguments[startIndex + 2] : String::EMPTY;
+    bindPlatform_ = startIndex + 3 < arguments.Size() ? arguments[startIndex + 3] : String::EMPTY;
 
     if (argument != "bind")
     {
@@ -35,6 +37,26 @@ bool BindCmd::Parse(const Vector<String>& arguments, unsigned startIndex, String
         return false;
     }
 
+    if (!sourceRootFolder_.Length())
+    {
+        errorMsg = "Unable to parse bind command";
+        return false;
+    }
+
+
+    if (!packageFolder_.Length())
+    {
+        errorMsg = "Unable to parse bind command";
+        return false;
+    }
+
+    if (!bindPlatform_.Length())
+    {
+        errorMsg = "Unable to parse bind command";
+        return false;
+    }
+
+
     return true;
 }
 
@@ -42,9 +64,9 @@ void BindCmd::Run()
 {
     ToolEnvironment* env = GetSubsystem<ToolEnvironment>();
 
-    bindPlatform_ = "MACOSX";
+    //bindPlatform_ = "MACOSX";
     sourceRootFolder_ = env->GetRootSourceDir();
-    packageFolder_ = "Source/AtomicJS/Packages/ToolCore/";
+    //packageFolder_ = "Source/AtomicJS/Packages/Atomic/";
 
     SharedPtr<JSBind> jsbind(new JSBind(context_));
 

+ 258 - 5
Source/ToolCore/JSBind/JSBClass.cpp

@@ -28,7 +28,7 @@ void JSBFunctionOverride::Parse()
         JSBType* type = JSBType::Parse(sig_.At(i));
         if (!type)
         {
-            ErrorExit("Unable to parse override type");
+            ErrorExit(ToString("Unable to parse override type: %s", sig_.At(i).CString()));
         }
         types_.Push(type);
     }
@@ -38,7 +38,8 @@ void JSBFunctionOverride::Parse()
 JSBClass::JSBClass(Context* context, JSBModule *module, const String& name, const String& nativeName) : Object(context),
     module_(module), name_(name), nativeName_(nativeName),
     isAbstract_(false), isObject_(false),
-    numberArrayElements_(0), arrayElementType_("float")
+    numberArrayElements_(0), arrayElementType_("float"),
+    hasProperties_(false)
 {
 
     if (nativeName == "Object")
@@ -83,12 +84,264 @@ void JSBClass::AddFunction(JSBFunction* function)
     functions_.Push(function);
 }
 
-void JSBClass::AddBaseClass(JSBClass *baseClass)
+JSBClass* JSBClass::GetBaseClass()
 {
+    if (!baseClasses_.Size())
+        return 0;
+
+    return baseClasses_[0];
+
+}
+
+JSBFunction* JSBClass::GetConstructor()
+{
+    {
+        for (unsigned i = 0; i < functions_.Size(); i++)
+            if (functions_[i]->IsConstructor() && !functions_[i]->Skip())
+                return functions_[i];
+    }
+
+    return NULL;
+
+}
+
+void JSBClass::SetSkipFunction(const String& name, bool skip)
+{
+    for (unsigned i = 0; i < functions_.Size(); i++)
+    {
+        if (functions_[i]->IsConstructor())
+            continue;
+
+        if (functions_[i]->GetName() == name)
+            functions_[i]->SetSkip(skip);
+    }
+
+}
+void JSBClass::SetBaseClass(JSBClass *baseClass)
+{
+    // we can't hook up chain here, as base class may not have been visited yet
+
+    assert(!baseClasses_.Size());
     baseClasses_.Push(baseClass);
+}
+
+void JSBClass::RecursiveAddBaseClass(PODVector<JSBClass*>& baseClasses)
+{
+    for (unsigned i = 0; i < baseClasses.Size(); i++)
+    {
+        JSBClass* base = baseClasses.At(i);
+
+        if (base->IsObject())
+            SetObject(true);
+
+        if (!baseClasses_.Contains(base))
+            baseClasses_.Push(base);
+
+        RecursiveAddBaseClass(base->baseClasses_);
+    }
+}
+
+void JSBClass::Preprocess()
+{
+    RecursiveAddBaseClass(baseClasses_);
+}
+
+void JSBClass::Process()
+{
+    for (unsigned j = 0; j < overrides_.Size(); j++)
+    {
+        overrides_.At(j)->Parse();
+    }
+
+    // detect overridden functions, only works for in class atm (not baseclasses)
+    for (unsigned j = 0; j < functions_.Size(); j++)
+    {
+        JSBFunction* function = functions_[j];
+
+        if (IsNumberArray())
+        {
+            function->SetSkip(true);
+            continue;
+        }
+
+        // skip function if only one parameter of type Context, if not Constuctor
+        if (!function->IsConstructor())
+        {
+            Vector<JSBFunctionType*>& parameters = function->GetParameters();
+
+            if (parameters.Size() == 1 && parameters.At(0)->type_->asClassType())
+            {
+                if (parameters.At(0)->type_->asClassType()->class_->GetName() == "Context")
+                {
+                    function->SetSkip(true);
+                    continue;
+                }
+            }
+        }
+
+
+        if (function->IsOverride())
+            continue;
+
+        for (unsigned k = 0; k < functions_.Size(); k++)
+        {
+            if (j == k)
+                continue;
+
+            JSBFunction* function2 = functions_[k];
+
+            if (function->GetName() == function2->GetName())
+            {
+                function->SetOverride();
+                function2->SetOverride();
+                // initially set all overridden functions to skip
+                function->SetSkip(true);
+                function2->SetSkip(true);
+                break;
+            }
+        }
+
+    }
+
+    // mark overrides
+    for (unsigned j = 0; j < functions_.Size(); j++)
+    {
+        JSBFunction* function = functions_[j];
+
+        if (function->IsOverride())
+        {
+            for (unsigned k = 0; k < overrides_.Size(); k++)
+            {
+                JSBFunctionOverride* override =  overrides_[k];
+
+                if (override->name_ != function->GetName())
+                    continue;
+
+                Vector<JSBFunctionType*>& parameters = function->GetParameters();
+
+                if (override->types_.Size() != parameters.Size())
+                    continue;
+
+                bool match = true;
+                for (unsigned x = 0; x < parameters.Size(); x++)
+                {
+                    JSBType* ot = override->types_[x];
+                    JSBType* pt = parameters[x]->type_;
+
+                    // should add an == operator
+                    if ((ot->asPrimitiveType() == NULL) != (pt->asPrimitiveType() == NULL) ||
+                            (ot->asClassType() == NULL) != (pt->asClassType() == NULL) )
+                    {
+                        match = false;
+                        break;
+                    }
+
+                    if (ot->asPrimitiveType())
+                    {
+                        JSBPrimitiveType* pot = ot->asPrimitiveType();
+                        JSBPrimitiveType* ppt = pt->asPrimitiveType();
+
+                        if (pot->kind_ != ppt->kind_)
+                        {
+                            match = false;
+                            break;
+                        }
+                    }
+                    if (ot->asClassType())
+                    {
+                        JSBClassType* cot = ot->asClassType();
+                        JSBClassType* cpt = pt->asClassType();
+
+                        if (cot->class_ != cpt->class_)
+                        {
+                            match = false;
+                            break;
+                        }
+                    }
+                    if (ot->asStringType())
+                    {
+                        if (!pt->asStringType())
+                        {
+                            match = false;
+                            break;
+                        }
+                    }
+                    if (ot->asStringHashType())
+                    {
+                        if (!pt->asStringHashType())
+                        {
+                            match = false;
+                            break;
+                        }
+                    }
+
+
+                }
+                if (match)
+                {
+                    function->SetSkip(false);
+                    break;
+                }
+
+            }
+
+        }
+
+    }
+
+}
+
+void JSBClass::PostProcess()
+{
+    for (unsigned j = 0; j < functions_.Size(); j++)
+    {
+        JSBFunction* function = functions_[j];
+        function->Process();
+    }
+}
+
+void JSBClass::AddPropertyFunction(JSBFunction* function)
+{
+    hasProperties_ = true;
+
+    if (!function->GetPropertyName().Length())
+    {
+        ErrorExit("Function has no property name");
+    }
+
+    if (!function->IsGetter() && !function->IsSetter())
+    {
+        ErrorExit("Function is not a getter or setter");
+    }
+
+    JSBProperty* prop = NULL;
+
+    if (properties_.Contains(function->GetPropertyName()))
+    {
+        prop = properties_[function->GetPropertyName()];
+    }
+
+    if (!prop)
+    {
+        prop = new JSBProperty();
+        properties_[function->GetPropertyName()] = prop;
+    }
+
+    if (prop->getter_ && function->IsGetter())
+    {
+        ErrorExit("getter already registered");
+    }
+
+    if (prop->setter_ && function->IsSetter())
+    {
+        ErrorExit("setter already registered");
+    }
+
+    if (function->IsSetter())
+        prop->setter_ = function;
+    else
+        prop->getter_ = function;
 
-    if (baseClass->GetNativeName() == "Object")
-        SetObject(true);
 }
 
 void JSBClass::Dump()

+ 50 - 5
Source/ToolCore/JSBind/JSBClass.h

@@ -4,13 +4,14 @@
 #include <Atomic/Core/Object.h>
 
 #include "JSBHeader.h"
+#include "JSBModule.h"
 
 using namespace Atomic;
 
 namespace ToolCore
 {
 
-class JSBModule;
+class JSBPackage;
 class JSBFunction;
 class JSBType;
 
@@ -32,8 +33,24 @@ public:
 
 };
 
+class JSBProperty
+{
+public:
+    String name_;
+    JSBFunction* getter_;
+    JSBFunction* setter_;
+
+    JSBProperty() : getter_(0), setter_(0)
+    {
+
+    }
+
+};
+
+
 class JSBClass : public Object
 {
+    friend class JSBClassWriter;
 
     OBJECT(JSBClass)
 
@@ -44,6 +61,8 @@ public:
 
     const String& GetName() { return name_; }
     const String& GetNativeName() { return nativeName_; }
+    JSBClass* GetBaseClass();
+    PODVector<JSBClass*>& GetBaseClasses() {return baseClasses_; }
 
     bool IsAbstract() { return isAbstract_; }
 
@@ -52,24 +71,47 @@ public:
     /// itself an object
     bool IsObject() { return isObject_; }
 
-    void SetAbstract(bool value = true) { isAbstract_ = value; }
-    void SetObject(bool value = true) { isObject_ = value; }
+    bool HasProperties() { return hasProperties_; }
+    void GetPropertyNames(Vector<String>& names) { names = properties_.Keys(); }
+    JSBProperty* GetProperty(const String& name)
+    {
+        if (!properties_.Contains(name))
+            return 0;
+
+        return properties_[name];
+    }
+
+
+    JSBHeader* GetHeader() { return header_; }
+    JSBModule* GetModule() { return module_; }
+    JSBPackage* GetPackage() { return module_->GetPackage(); }
 
     bool IsNumberArray() { return numberArrayElements_ != 0; }
     int  GetNumberArrayElements() { return numberArrayElements_;}
     const String& GetArrayElementType() const { return arrayElementType_; }
 
-    void SetHeader(JSBHeader* header) { header_ = header; }
+    JSBFunction* GetConstructor();
 
-    void AddBaseClass(JSBClass* baseClass);
+    void SetAbstract(bool value = true) { isAbstract_ = value; }
+    void SetObject(bool value = true) { isObject_ = value; }
+    void SetHeader(JSBHeader* header) { header_ = header; }
+    void SetBaseClass(JSBClass* baseClass);
 
+    void SetSkipFunction(const String& name, bool skip = true);
     void AddFunction(JSBFunction* function);
     void AddFunctionOverride(JSBFunctionOverride* override) { overrides_.Push(override); }
+    void AddPropertyFunction(JSBFunction* function);
+
+    void Preprocess();
+    void Process();
+    void PostProcess();
 
     void Dump();
 
 private:
 
+    void RecursiveAddBaseClass(PODVector<JSBClass *> &baseClasses);
+
     String name_;
     String nativeName_;
 
@@ -88,6 +130,9 @@ private:
     int numberArrayElements_;
     String arrayElementType_;
 
+    bool hasProperties_;
+    HashMap<String, JSBProperty*> properties_;
+
 };
 
 

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

@@ -0,0 +1,90 @@
+
+
+
+#include <Atomic/IO/FileSystem.h>
+
+#include "JSBind.h"
+#include "JSBModule.h"
+#include "JSBPackage.h"
+#include "JSBEnum.h"
+#include "JSBClass.h"
+#include "JSBFunction.h"
+
+#include "JSBClassWriter.h"
+#include "JSBFunctionWriter.h"
+
+namespace ToolCore
+{
+
+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);
+
+    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\");\n", 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;
+
+}
+
+}
+

+ 30 - 0
Source/ToolCore/JSBind/JSBClassWriter.h

@@ -0,0 +1,30 @@
+#pragma once
+
+#include <Atomic/Container/Str.h>
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+class JSBPackage;
+class JSBClass;
+
+class JSBClassWriter
+{
+
+public:
+
+    JSBClassWriter(JSBClass* klass);
+
+    void GenerateSource(String& sourceOut);
+
+private:
+
+    void WriteFunctions(String& source);
+
+    JSBClass* klass_;
+
+};
+
+}

+ 1 - 1
Source/ToolCore/JSBind/JSBEnum.cpp

@@ -10,7 +10,7 @@ namespace ToolCore
 {
 
 JSBEnum::JSBEnum(Context* context, JSBModule *module, const String& name) : Object(context),
-    module_(module), name_(name)
+    module_(module), name_(name), header_(0)
 {
 
 }

+ 8 - 0
Source/ToolCore/JSBind/JSBEnum.h

@@ -9,6 +9,7 @@ namespace ToolCore
 {
 
 class JSBModule;
+class JSBHeader;
 
 class JSBEnum : public Object
 {
@@ -21,6 +22,11 @@ public:
     virtual ~JSBEnum();
 
     const String& GetName() { return name_; }
+    JSBHeader* GetHeader() { return header_; }
+
+    Vector<String>& GetValues() { return values_; }
+
+    void SetHeader(JSBHeader* header) { header_ = header; }
 
     void Preprocess();
 
@@ -34,6 +40,8 @@ private:
 
     Vector<String> values_;
 
+    JSBHeader* header_;
+
 };
 
 

+ 51 - 0
Source/ToolCore/JSBind/JSBFunction.cpp

@@ -0,0 +1,51 @@
+
+#include "JSBFunction.h"
+
+namespace ToolCore
+{
+void JSBFunction::Process()
+{
+    if (skip_)
+    {
+        return;
+    }
+
+    // if not already marked as a getter
+    if (!isGetter_)
+    {
+        if (!parameters_.Size() && returnType_)
+        {
+            if (name_.Length() > 3 && name_.StartsWith("Get") && isupper(name_[3]))
+            {
+                String pname = name_.Substring(3);
+                class_->SetSkipFunction(pname);
+                isGetter_ = true;
+                propertyName_ = pname;
+
+            }
+        }
+    }
+
+    if (!isSetter_)
+    {
+        if (parameters_.Size() == 1 && !returnType_)
+        {
+            if (name_.Length() > 3 && name_.StartsWith("Set") && isupper(name_[3]))
+            {
+
+                String pname = name_.Substring(3);
+                class_->SetSkipFunction(pname);
+                isSetter_ = true;
+                propertyName_ = pname;
+            }
+        }
+    }
+
+    if (isGetter_)
+        class_->AddPropertyFunction(this);
+
+    if (isSetter_)
+        class_->AddPropertyFunction(this);
+
+}
+}

+ 5 - 0
Source/ToolCore/JSBind/JSBFunction.h

@@ -75,6 +75,8 @@ public:
 
 class JSBFunction : public JSBSymbol
 {
+    friend class JSBFunctionWriter;
+
 public:
 
     JSBFunction(JSBClass* klass) : class_(klass), returnType_(0),
@@ -94,7 +96,10 @@ public:
     bool IsOverride() { return isOverride_; }
     bool Skip() { return skip_; }
 
+    const String& GetPropertyName() { return propertyName_; }
+
     JSBFunctionType* GetReturnType() { return returnType_; }
+    Vector<JSBFunctionType*>& GetParameters() { return parameters_; }
 
     const String& GetDocString() { return docString_; }
 

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

@@ -0,0 +1,482 @@
+
+
+
+#include <Atomic/IO/FileSystem.h>
+
+#include "JSBind.h"
+#include "JSBModule.h"
+#include "JSBPackage.h"
+#include "JSBEnum.h"
+#include "JSBClass.h"
+#include "JSBFunction.h"
+
+#include "JSBFunctionWriter.h"
+
+namespace ToolCore
+{
+
+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);
+
+                }
+
+            }
+
+        }
+    }
+}
+
+
+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());
+
+    source.Append("   if (duk_is_constructor_call(ctx))\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 = "JSVM::GetJSVM(ctx)->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" \
+                                "duk_push_this(ctx);\n" \
+                                "JSVM::GetJSVM(ctx)->AddObject(duk_get_heapptr(ctx, -1), native);\n"\
+                                "duk_pop(ctx);\n"\
+                                "}\n" \
+                                "else if (duk_is_pointer(ctx, 0))\n" \
+                                "{\n" \
+                                "duk_push_this(ctx);\n" \
+                                "JSVM::GetJSVM(ctx)->AddObject(duk_get_heapptr(ctx, -1), (RefCounted*) duk_get_pointer(ctx, 0));\n" \
+                                "duk_pop(ctx);\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)
+    {
+        source.AppendWithFormat("   js_constructor_basecall(ctx, \"%s\");\n", 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());
+        }
+    }
+
+    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");
+        }
+
+
+        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;
+
+}
+
+}
+

+ 32 - 0
Source/ToolCore/JSBind/JSBFunctionWriter.h

@@ -0,0 +1,32 @@
+#pragma once
+
+#include <Atomic/Container/Str.h>
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+class JSBPackage;
+class JSBFunction;
+
+class JSBFunctionWriter
+{
+
+public:
+
+    JSBFunctionWriter(JSBFunction* function);
+
+    void GenerateSource(String& sourceOut);
+
+private:
+
+    void WriteFunction(String& source);
+    void WriteConstructor(String& source);
+    void WriteParameterMarshal(String& source);
+
+    JSBFunction* function_;
+
+};
+
+}

+ 3 - 2
Source/ToolCore/JSBind/JSBHeader.h

@@ -33,13 +33,14 @@ public:
     JSBHeader(Context* context, JSBModule* module, const String& filepath);
     virtual ~JSBHeader();
 
+    const String& GetFilePath() { return filepath_; }
+    JSBModule* GetModule() { return module_; }
+
     void Parse();
 
     void VisitPreprocess();
     void VisitHeader();
 
-    JSBModule* GetModule() { return module_; }
-
 private:
 
     CPlusPlus::TranslationUnit* translationUnit_;

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

@@ -244,7 +244,7 @@ public:
         if (name.StartsWith("operator "))
             return NULL;
 
-        if (name == klass->GetName())
+        if (name == klass->GetNativeName())
             jfunction->SetConstructor();
 
         if (name.StartsWith("~"))
@@ -413,7 +413,7 @@ public:
             }
             else
             {
-                jclass->AddBaseClass(base);
+                jclass->SetBaseClass(base);
             }
         }
 

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

@@ -11,6 +11,7 @@
 #include "JSBHeader.h"
 #include "JSBClass.h"
 #include "JSBEnum.h"
+#include "JSBModuleWriter.h"
 
 namespace ToolCore
 {
@@ -56,6 +57,36 @@ void JSBModule::VisitHeaders()
 
 }
 
+void JSBModule::PreprocessClasses()
+{
+    HashMap<StringHash, SharedPtr<JSBClass> >::Iterator itr;
+
+    for (itr = classes_.Begin(); itr != classes_.End(); itr++)
+    {
+        itr->second_->Preprocess();
+    }
+}
+
+void JSBModule::ProcessClasses()
+{
+    HashMap<StringHash, SharedPtr<JSBClass> >::Iterator itr;
+
+    for (itr = classes_.Begin(); itr != classes_.End(); itr++)
+    {
+        itr->second_->Process();
+    }
+}
+
+void JSBModule::PostProcessClasses()
+{
+    HashMap<StringHash, SharedPtr<JSBClass> >::Iterator itr;
+
+    for (itr = classes_.Begin(); itr != classes_.End(); itr++)
+    {
+        itr->second_->PostProcess();
+    }
+}
+
 void JSBModule::ProcessOverloads()
 {
     // overloads
@@ -164,7 +195,7 @@ void JSBModule::RegisterClass(String name)
 
         classes_[nativeName] = cls;
 
-        LOGINFOF("Registered Class: %s", cls->GetName().CString());
+        package_->RegisterClass(cls);
     }
 }
 
@@ -177,7 +208,6 @@ void JSBModule::RegisterEnum(JSBEnum* jenum)
 
     enums_[jenum->GetName()] = jenum;
 
-    LOGINFOF("Registered Enum: %s", jenum->GetName().CString());
 }
 
 JSBEnum* JSBModule::GetEnum(const String& name)
@@ -237,6 +267,17 @@ bool JSBModule::Load(const String& jsonFilename)
 
     name_ = root.GetString("name");
 
+    JSONValue requires = root.GetChild("requires");
+
+    if (requires.IsArray())
+    {
+        for (unsigned j = 0; j < requires.GetSize(); j++)
+        {
+            requirements_.Push(requires.GetString(j));
+        }
+
+    }
+
     JSONValue classes = root.GetChild("classes");
 
     for (unsigned i = 0; i < classes.GetSize(); i++)
@@ -260,6 +301,17 @@ bool JSBModule::Load(const String& jsonFilename)
 
     }
 
+    JSONValue includes = root.GetChild("includes");
+
+    if (includes.IsArray())
+    {
+        for (unsigned j = 0; j < includes.GetSize(); j++)
+        {
+            includes_.Push(includes.GetString(j));
+
+        }
+    }
+
     JSONValue sources = root.GetChild("sources");
 
     for (unsigned i = 0; i < sources.GetSize(); i++)
@@ -293,4 +345,16 @@ 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();
+}
+
 }

+ 17 - 1
Source/ToolCore/JSBind/JSBModule.h

@@ -20,6 +20,7 @@ class JSBEnum;
 
 class JSBModule : public Object
 {
+    friend class JSBModuleWriter;
 
     OBJECT(JSBModule)
 
@@ -28,21 +29,32 @@ public:
     JSBModule(Context* context, JSBPackage* package);
     virtual ~JSBModule();
 
+    const String& GetName() { return name_; }
     JSBPackage* GetPackage() { return package_; }
 
     JSBClass* GetClass(const String& name);
+
     void RegisterClass(String name);
 
     JSBEnum* GetEnum(const String& name);
-    void RegisterEnum(JSBEnum* jenum);
+    void RegisterEnum(JSBEnum* jenum);       
 
     bool ContainsConstant(const String& constantName);
     void RegisterConstant(const String& constantName);
 
+    bool Requires(const String& requirement) { return requirements_.Contains(requirement); }
+
     bool Load(const String& jsonFilename);
     void PreprocessHeaders();
     void VisitHeaders();
 
+    void PreprocessClasses();
+    void ProcessClasses();
+    void PostProcessClasses();
+
+    void GenerateSource(const String& outPath);
+    const String& GetSource();
+
 private:
 
     void ProcessOverloads();
@@ -53,6 +65,7 @@ private:
 
     SharedPtr<JSBPackage> package_;
     Vector<SharedPtr<JSBHeader>> headers_;
+    Vector<String> includes_;
 
     Vector<String> sourceDirs_;
     Vector<String> classnames_;
@@ -63,9 +76,12 @@ private:
     HashMap<StringHash, SharedPtr<JSBClass> > classes_;
     HashMap<StringHash, SharedPtr<JSBEnum> > enums_;
     Vector<String> constants_;
+    Vector<String> requirements_;
 
     SharedPtr<JSONFile> moduleJSON_;
 
+    String source_;
+
 };
 
 

+ 283 - 0
Source/ToolCore/JSBind/JSBModuleWriter.cpp

@@ -0,0 +1,283 @@
+
+#include <Atomic/IO/FileSystem.h>
+
+#include "JSBind.h"
+#include "JSBPackage.h"
+#include "JSBModule.h"
+#include "JSBEnum.h"
+#include "JSBClass.h"
+#include "JSBFunction.h"
+#include "JSBModuleWriter.h"
+#include "JSBClassWriter.h"
+
+namespace ToolCore
+{
+
+JSBModuleWriter::JSBModuleWriter(JSBModule *module) : module_(module)
+{
+
+}
+
+void JSBModuleWriter::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 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";
+
+    for (unsigned i = 0; i < classes.Size(); i++)
+    {
+        JSBClass* klass = classes.At(i);
+
+        if (klass->IsNumberArray())
+            continue;
+
+        source.AppendWithFormat("   js_class_declare(vm, \"%s\", jsb_constructor_%s);\n", klass->GetName().CString(), klass->GetName().CString());
+
+        if (klass->HasProperties())
+        {
+            source.AppendWithFormat("js_class_push_propertyobject(vm, \"%s\");\n", 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");
+                }
+
+                pnames[j][0] = tolower(pnames[j][0]);
+                source.AppendWithFormat("duk_put_prop_string(ctx, -2, \"%s\");\n", pnames[j].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 += "duk_get_global_string(ctx, \"Atomic\");\n";
+
+    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";
+
+    for (unsigned i = 0; i < module_->constants_.Size(); i++)
+    {
+        source.AppendWithFormat("duk_push_number(ctx, (double) %s);\n",  module_->constants_.At(i).CString());
+        source.AppendWithFormat("duk_put_prop_string(ctx, -2, \"%s\");\n",  module_->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_;
+}
+
+}

+ 36 - 0
Source/ToolCore/JSBind/JSBModuleWriter.h

@@ -0,0 +1,36 @@
+#pragma once
+
+#include <Atomic/Container/Str.h>
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+class JSBModule;
+
+class JSBModuleWriter
+{
+
+public:
+
+    JSBModuleWriter(JSBModule* module);
+
+    void GenerateSource(String& sourceOut);
+
+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);
+
+    JSBModule* module_;
+    String source_;
+
+};
+
+}

+ 36 - 0
Source/ToolCore/JSBind/JSBPackage.cpp

@@ -7,6 +7,8 @@
 #include "JSBModule.h"
 #include "JSBPackage.h"
 
+#include "JSBPackageWriter.h"
+
 namespace ToolCore
 {
 
@@ -36,6 +38,40 @@ void JSBPackage::ProcessModules()
     {
         modules_[i]->VisitHeaders();
     }
+
+    for (unsigned i = 0; i < modules_.Size(); i++)
+    {
+        modules_[i]->PreprocessClasses();
+    }
+
+    for (unsigned i = 0; i < modules_.Size(); i++)
+    {
+        modules_[i]->ProcessClasses();
+    }
+
+    for (unsigned i = 0; i < modules_.Size(); i++)
+    {
+        modules_[i]->PostProcessClasses();
+    }
+
+}
+
+void JSBPackage::GenerateSource(const String &outPath)
+{
+    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);
+    }
 }
 
 JSBClass* JSBPackage::GetClass(const String& name)

+ 13 - 0
Source/ToolCore/JSBind/JSBPackage.h

@@ -15,6 +15,8 @@ class JSBEnum;
 class JSBPackage : public Object
 {
 
+    friend class JSBPackageWriter;
+
     OBJECT(JSBPackage)
 
 public:
@@ -28,8 +30,15 @@ public:
 
     void ProcessModules();
 
+    const String& GetName() { return name_; }
+    const String& GetNamespace() { return namespace_; }
+
+
     JSBClass* GetClass(const String& name);
 
+    PODVector<JSBClass*>& GetAllClasses() { return allClasses_; }
+    void RegisterClass(JSBClass* cls) {allClasses_.Push(cls); }
+
     // get a class by name across all loaded packages
     static JSBClass* GetClassAllPackages(const String& name);
 
@@ -42,6 +51,7 @@ public:
 
     static bool ContainsConstantAllPackages(const String& constantName);
 
+    void GenerateSource(const String& outPath);
 
 private:
 
@@ -54,9 +64,12 @@ private:
     Vector<SharedPtr<JSBPackage> > dependencies_;
 
     Vector<SharedPtr<JSBModule> > modules_;
+    PODVector<JSBClass*> allClasses_;
 
     static Vector<SharedPtr<JSBPackage> > allPackages_;
 
+    String source_;
+
 };
 
 

+ 146 - 0
Source/ToolCore/JSBind/JSBPackageWriter.cpp

@@ -0,0 +1,146 @@
+
+
+
+#include <Atomic/IO/FileSystem.h>
+
+#include "JSBind.h"
+#include "JSBModule.h"
+#include "JSBPackage.h"
+#include "JSBEnum.h"
+#include "JSBClass.h"
+
+#include "JSBPackageWriter.h"
+
+namespace ToolCore
+{
+
+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";
+        source.AppendWithFormat("   js_setup_prototype(vm, \"%s\", \"%s\", %s);\n",
+                                klass->GetName().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)
+{
+    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());
+
+    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_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;
+
+}
+
+}
+

+ 31 - 0
Source/ToolCore/JSBind/JSBPackageWriter.h

@@ -0,0 +1,31 @@
+#pragma once
+
+#include <Atomic/Container/Str.h>
+
+using namespace Atomic;
+
+namespace ToolCore
+{
+
+class JSBPackage;
+class JSBClass;
+
+class JSBPackageWriter
+{
+
+public:
+
+    JSBPackageWriter(JSBPackage* package);
+
+    void GenerateSource(String& sourceOut);
+
+private:
+
+    void WriteProtoTypeRecursive(String &source, JSBClass* klass,  Vector<JSBClass*>& written);
+    void WriteProtoTypeSetup(String& source);
+
+    JSBPackage* package_;
+
+};
+
+}

+ 1 - 0
Source/ToolCore/JSBind/JSBPreprocessVisitor.h

@@ -46,6 +46,7 @@ public:
         JSBModule* module = header_->GetModule();
 
         JSBEnum* jenum = new JSBEnum(header_->GetContext(), module_, getNameString(penum->name()));
+        jenum->SetHeader(header_);
 
         for (unsigned i = 0; i < penum->memberCount(); i++)
         {

+ 1 - 1
Source/ToolCore/JSBind/JSBType.h

@@ -158,7 +158,7 @@ public:
 
     String ToString()
     {
-        return class_->GetName();
+        return class_->GetNativeName();
     }
 
 };

+ 17 - 0
Source/ToolCore/JSBind/JSBind.cpp

@@ -1,3 +1,5 @@
+#include <Atomic/Core/ProcessUtils.h>
+#include <Atomic/IO/FileSystem.h>
 
 #include "JSBPackage.h"
 #include "JSBind.h"
@@ -25,6 +27,21 @@ bool JSBind::GenerateBindings(const String& sourceRootFolder, const String& pack
 
     package->Load(sourceRootFolder_ + packageFolder_);
 
+    String modulesFolder = "Build/Source/Generated/" + platform + "/Javascript/Packages/";
+    modulesFolder += package->GetName() + "/";
+
+    String outputFolder = sourceRootFolder + "/" + modulesFolder;
+
+    FileSystem* fs = GetSubsystem<FileSystem>();
+
+    if (!fs->CreateDirs(sourceRootFolder, modulesFolder) || !fs->DirExists(outputFolder))
+    {
+        String error = "Unable to create bindings output folder: " + outputFolder;
+        ErrorExit(error.CString());
+    }
+
+    package->GenerateSource(outputFolder);
+
     return true;
 }
 

+ 22 - 0
Source/ToolCoreJS/CMakeLists.txt

@@ -0,0 +1,22 @@
+include_directories (${CMAKE_SOURCE_DIR}/Source/ThirdParty)
+
+file (GLOB_RECURSE SOURCE_FILES *.cpp *.h)
+
+# Create the JSBind files ahead of time, so they are picked up with glob
+set (JSFILES JSPackageToolCore.cpp;JSModuleToolCore.cpp)
+
+foreach(JSFILE ${JSFILES})
+
+  set (JSFILEPATH "${CMAKE_SOURCE_DIR}/Build/Source/Generated/${JAVASCRIPT_BINDINGS_PLATFORM}/Javascript/Packages/ToolCore/${JSFILE}")
+
+  if (NOT EXISTS ${JSFILEPATH})
+    file(WRITE "${JSFILEPATH}" "// will be created by JSBind")
+  endif()
+
+endforeach()
+
+file (GLOB JAVASCRIPT_BINDINGS_SOURCE ${CMAKE_SOURCE_DIR}/Build/Source/Generated/${JAVASCRIPT_BINDINGS_PLATFORM}/Javascript/Packages/ToolCore/*.cpp)
+
+add_library(ToolCoreJS ${SOURCE_FILES} ${JAVASCRIPT_BINDINGS_SOURCE})
+
+target_link_libraries(ToolCoreJS ToolCore)