Browse Source

Initial work on auto-exposing the events to TypeScript and making subscribeToEvent more type safe. Fixes #1203

Shaddock Heath 9 years ago
parent
commit
c279358f83

+ 3 - 1
Script/Packages/Atomic/Core.json

@@ -25,7 +25,9 @@
 		"Object" : [
 			"sendEvent(eventType:string, data?:Object);",
 			"subscribeToEvent(eventType:string, callback:(data:any) => void);",
-			"subscribeToEvent(sender:AObject, eventType:string, callback:(data: any) => void);"
+			"subscribeToEvent(sender:AObject, eventType:string, callback:(data: any) => void);",
+			"subscribeToEvent<T extends Atomic.NativeEvent>(sender: AObject, eventType: Atomic.NativeEventType, callback:(data: T) => void);",
+			"subscribeToEvent<T extends Atomic.NativeEvent>(eventType: Atomic.NativeEventType, callback:(data: T) => void);"
 		]
 	},
 	"haxe_decl" : {

+ 41 - 39
Script/TypeScript/AtomicWork.d.ts

@@ -26,6 +26,8 @@ declare module Atomic {
 
     // end subsystems
 
+    // Base interface for events
+    export interface NativeEvent { }
 
     export interface PathInfo {
 
@@ -35,7 +37,7 @@ declare module Atomic {
 
     }
 
-    export interface ScreenModeEvent {
+    export interface ScreenModeEvent extends Atomic.NativeEvent {
 
         width: number;
         height: number;
@@ -104,7 +106,7 @@ declare module Atomic {
         subObject: number;
     }
 
-    export interface KeyDownEvent {
+    export interface KeyDownEvent extends NativeEvent {
 
         // keycode
         key: number;
@@ -116,7 +118,7 @@ declare module Atomic {
 
     }
 
-    export interface KeyUpEvent {
+    export interface KeyUpEvent extends NativeEvent {
 
         // keycode
         key: number;
@@ -127,7 +129,7 @@ declare module Atomic {
 
     }
 
-    export interface UIShortcutEvent {
+    export interface UIShortcutEvent extends NativeEvent {
 
         // keycode
         key: number;
@@ -136,14 +138,14 @@ declare module Atomic {
 
     }
 
-    export interface UIListViewSelectionChangedEvent {
+    export interface UIListViewSelectionChangedEvent extends NativeEvent {
 
         refid: string;
         selected: boolean;
 
     }
 
-    export interface NodeAddedEvent {
+    export interface NodeAddedEvent extends NativeEvent {
 
         scene: Atomic.Scene;
         parent: Atomic.Node;
@@ -151,7 +153,7 @@ declare module Atomic {
 
     }
 
-    export interface NodeRemovedEvent {
+    export interface NodeRemovedEvent extends NativeEvent {
 
         scene: Atomic.Scene;
         parent: Atomic.Node;
@@ -159,14 +161,14 @@ declare module Atomic {
 
     }
 
-    export interface NodeNameChangedEvent {
+    export interface NodeNameChangedEvent extends NativeEvent {
 
         scene: Atomic.Scene;
         node: Atomic.Node;
 
     }
 
-    export interface UIWidgetEvent {
+    export interface UIWidgetEvent extends NativeEvent {
 
         handler: UIWidget;
         target: UIWidget;
@@ -183,51 +185,51 @@ declare module Atomic {
         touch: boolean;
     }
 
-    export interface UIWidgetFocusChangedEvent {
+    export interface UIWidgetFocusChangedEvent extends NativeEvent {
         widget: UIWidget;
         focused: boolean;
     }
 
-    export interface UIWidgetEditCompleteEvent {
+    export interface UIWidgetEditCompleteEvent extends NativeEvent {
         widget: UIWidget;
     }
 
-    export interface UIWidgetDeletedEvent {
+    export interface UIWidgetDeletedEvent extends NativeEvent {
 
         widget: UIWidget;
     }
 
-    export interface DragBeginEvent {
+    export interface DragBeginEvent extends NativeEvent {
 
         source: UIWidget;
         dragObject: UIDragObject;
     }
 
-    export interface DragEnterWidgetEvent {
+    export interface DragEnterWidgetEvent extends NativeEvent {
 
         widget: UIWidget;
         dragObject: UIDragObject;
     }
 
-    export interface DragExitWidgetEvent {
+    export interface DragExitWidgetEvent extends NativeEvent {
 
         widget: UIWidget;
         dragObject: UIDragObject;
     }
 
-    export interface DragEndedEvent {
+    export interface DragEndedEvent extends NativeEvent {
 
         target: UIWidget;
         dragObject: UIDragObject;
     }
 
-    export interface TemporaryChangedEvent {
+    export interface TemporaryChangedEvent extends NativeEvent {
 
         serializable: Atomic.Serializable;
 
     }
 
-    export interface ComponentAddedEvent {
+    export interface ComponentAddedEvent extends NativeEvent {
 
         scene: Atomic.Scene;
         node: Atomic.Node;
@@ -235,7 +237,7 @@ declare module Atomic {
 
     }
 
-    export interface ComponentRemovedEvent {
+    export interface ComponentRemovedEvent extends NativeEvent {
 
         scene: Atomic.Scene;
         node: Atomic.Node;
@@ -243,7 +245,7 @@ declare module Atomic {
 
     }
 
-    export interface IPCJSErrorEvent {
+    export interface IPCJSErrorEvent extends NativeEvent {
 
         errorName: string;
         errorMessage: string;
@@ -254,7 +256,7 @@ declare module Atomic {
     }
 
 
-    export interface IPCMessageEvent {
+    export interface IPCMessageEvent extends NativeEvent {
 
         message: string;
         value: number;
@@ -312,21 +314,21 @@ declare module Atomic {
 
 declare module Editor {
 
-    export interface SceneNodeSelectedEvent {
+    export interface SceneNodeSelectedEvent extends Atomic.NativeEvent {
         scene: Atomic.Scene;
         node: Atomic.Node;
         selected: boolean;
         quiet: boolean;
     }
 
-    export interface SceneEditAddRemoveNodesEvent {
+    export interface SceneEditAddRemoveNodesEvent extends Atomic.NativeEvent {
 
         end: boolean;
 
     }
 
 
-    export interface SceneEditNodeAddedEvent {
+    export interface SceneEditNodeAddedEvent extends Atomic.NativeEvent {
 
         scene: Atomic.Scene;
         parent: Atomic.Node;
@@ -334,7 +336,7 @@ declare module Editor {
 
     }
 
-    export interface SceneEditNodeRemovedEvent {
+    export interface SceneEditNodeRemovedEvent extends Atomic.NativeEvent {
 
         scene: Atomic.Scene;
         parent: Atomic.Node;
@@ -342,7 +344,7 @@ declare module Editor {
 
     }
 
-    export interface SceneEditComponentAddedRemovedEvent {
+    export interface SceneEditComponentAddedRemovedEvent extends Atomic.NativeEvent {
 
         scene: Atomic.Scene;
         node: Atomic.Node;
@@ -350,21 +352,21 @@ declare module Editor {
         removed: boolean;
     }
 
-    export interface SceneEditStateChangeEvent {
+    export interface SceneEditStateChangeEvent extends Atomic.NativeEvent {
 
         serializable: Atomic.Serializable;
 
     }
 
-    export interface SceneEditNodeCreatedEvent {
+    export interface SceneEditNodeCreatedEvent extends Atomic.NativeEvent {
         node: Atomic.Node;
     }
 
-    export interface GizmoEditModeChangedEvent {
+    export interface GizmoEditModeChangedEvent extends Atomic.NativeEvent {
         mode: EditMode;
     }
 
-    export interface GizmoAxisModeChangedEvent {
+    export interface GizmoAxisModeChangedEvent extends Atomic.NativeEvent {
         mode: AxisMode;
     }
 
@@ -372,38 +374,38 @@ declare module Editor {
 
 declare module ToolCore {
 
-    export interface ResourceAddedEvent {
+    export interface ResourceAddedEvent extends Atomic.NativeEvent {
 
         guid: string;
 
     }
 
-    export interface ResourceRemovedEvent {
+    export interface ResourceRemovedEvent extends Atomic.NativeEvent {
 
         guid: string;
 
     }
 
-    export interface LicenseDeactivationErrorEvent {
+    export interface LicenseDeactivationErrorEvent extends Atomic.NativeEvent {
 
         message: string;
 
     }
 
-    export interface AssetImportErrorEvent {
+    export interface AssetImportErrorEvent extends Atomic.NativeEvent {
 
         path: string;
         guid: string;
         error: string;
     }
 
-    export interface AssetRenamedEvent {
+    export interface AssetRenamedEvent extends Atomic.NativeEvent {
 
         asset: Asset;
 
     }
 
-    export interface AssetMovedEvent {
+    export interface AssetMovedEvent extends Atomic.NativeEvent {
 
         asset: Asset;
         oldPath: string;
@@ -411,19 +413,19 @@ declare module ToolCore {
     }
 
 
-    export interface PlatformChangedEvent {
+    export interface PlatformChangedEvent extends Atomic.NativeEvent {
 
         platform: ToolCore.Platform;
 
     }
 
-    export interface BuildOutputEvent {
+    export interface BuildOutputEvent extends Atomic.NativeEvent {
 
         text: string;
 
     }
 
-    export interface BuildCompleteEvent {
+    export interface BuildCompleteEvent extends Atomic.NativeEvent {
 
         platformID: number;
         message: string;

+ 5 - 0
Source/AtomicJS/Javascript/JSCore.cpp

@@ -43,6 +43,8 @@ static int Object_SubscribeToEvent(duk_context* ctx)
         if (duk_is_string(ctx, 0) && duk_is_function(ctx, 1))
         {
             eventType = duk_to_string(ctx, 0);
+        } else if(duk_is_number(ctx, 0) && duk_is_function(ctx, 1)) {
+            eventType = StringHash(duk_to_number(ctx, 0));
         }
     }
     else if (top == 3) // Listen to specific object sender subscribeToEvent(graphics, "ScreenMode", function() {});
@@ -51,6 +53,9 @@ static int Object_SubscribeToEvent(duk_context* ctx)
         {
             sender = js_to_class_instance<Object>(ctx, 0, 0);
             eventType = duk_to_string(ctx, 1);
+        } else if (duk_is_object(ctx, 0) && duk_is_number(ctx, 1) && duk_is_function(ctx, 2)) {
+            sender = js_to_class_instance<Object>(ctx, 0, 0);
+            eventType = StringHash(duk_to_number(ctx, 1));
         }
     }
 

+ 5 - 0
Source/ToolCore/JSBind/JSBEvent.cpp

@@ -63,6 +63,11 @@ String JSBEvent::GetScriptEventName() const
 
 }
 
+unsigned JSBEvent::GetEventHash() const
+{
+    return StringHash(eventName_).Value();
+}
+
 bool JSBEvent::ScanModuleEvents(JSBModule* module)
 {
     const Vector<SharedPtr<JSBHeader>>& headers = module->GetHeaders();

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

@@ -54,6 +54,7 @@ namespace ToolCore
 
         const String& GetEventID() const { return eventID_; }
         const String& GetEventName() const { return eventName_; }
+        unsigned GetEventHash() const;
         /// Generally this is the EventName + "Event"
         String GetScriptEventName() const;
         const Vector<EventParam>& GetParameters() const { return parameters_;  }

+ 100 - 0
Source/ToolCore/JSBind/JSBTypeScript.cpp

@@ -30,6 +30,7 @@
 #include "JSBModule.h"
 #include "JSBFunction.h"
 #include "JSBTypeScript.h"
+#include "JSBEvent.h"
 
 namespace ToolCore
 {
@@ -362,6 +363,104 @@ void JSBTypeScript::ExportModuleEnums(JSBModule* module)
 
 }
 
+
+void JSBTypeScript::ExportModuleEvents(JSBModule* module)
+{
+
+    String source;
+
+    const Vector<SharedPtr<JSBEvent>>& events = module->GetEvents();
+
+    // First build up the Event Types
+    for (unsigned i = 0; i < events.Size(); i++)
+    {
+        JSBEvent* event = events[i];
+        const String& eventID = event->GetEventID();
+        if (i == 0) {
+            source += "    // this is a partial enum that combines with other definitions of 'NativeEventType'\n";
+            source += "    export const enum NativeEventType {\n";
+        }
+
+        source += ToString("        %s = %d", event->GetEventName().CString(), event->GetEventHash());
+
+        if (i == events.Size() -1) {
+            source += "\n";
+            source += "    }\n\n";
+        } else {
+            source += ",\n";
+        }
+    }
+
+    for (unsigned i = 0; i < events.Size(); i++)
+    {
+        JSBEvent* event = events[i];
+
+        const String& eventID = event->GetEventID();
+
+        source += ToString("    export interface %s extends Atomic.NativeEvent {\n", event->GetScriptEventName().CString());
+
+        // parameters
+
+        const Vector<JSBEvent::EventParam>& params = event->GetParameters();
+
+        for (unsigned j = 0; j < params.Size(); j++)
+        {
+            const JSBEvent::EventParam& p = params[j];
+
+            JSBClass* cls = JSBPackage::GetClassAllPackages(p.typeInfo_);
+
+            String typeName = p.typeInfo_;
+            String enumTypeName = p.enumTypeName_;
+
+            if (!cls)
+                typeName = typeName.ToLower();
+            else
+                typeName = cls->GetName();
+
+            if (typeName == "int" || typeName == "float" || typeName == "unsigned" ||
+                typeName == "bool" || typeName == "string" || typeName == "enum" || cls)
+            {
+
+                bool isEnum = false;
+                if (typeName == "enum")
+                {
+                    isEnum = true;
+                    // Once proper TypeScript enums are in place, uncomment the following.  See: #1268
+                    //if (enumTypeName.Length())
+                    //    typeName = enumTypeName;
+                    //else
+                    typeName = "number";
+                }
+
+                if (typeName == "int" || typeName == "float" || typeName == "unsigned")
+                {
+                    typeName = "number";
+                } else if (typeName == "bool") {
+                    typeName = "boolean";
+                } else if (cls) {
+                    typeName = ToString("%s.%s", cls->GetPackage()->GetName().CString(), typeName.CString());
+                }
+
+                if (isEnum && enumTypeName.Length())
+                {
+                    source += ToString("        /** Enum: %s */\n", enumTypeName.CString());
+                    source += ToString("        %s : %s;\n", p.paramName_.ToLower().CString(), typeName.CString());
+                } else {
+                    source += ToString("        %s : %s;\n", p.paramName_.ToLower().CString(), typeName.CString());
+                }
+            }
+            else
+            {
+                source += ToString("        // Unmapped Native Type:%s \n", typeName.CString());
+                source += ToString("        // %s : any;\n", p.paramName_.ToLower().CString());
+            }
+        }
+
+        source += "    }\n\n";
+    }
+    source_ += source;
+}
+
 void JSBTypeScript::WriteToFile(const String &path)
 {
     File file(package_->GetContext());
@@ -405,6 +504,7 @@ void JSBTypeScript::Emit(JSBPackage* package, const String& path)
         source_ += "// MODULE: " + modules[i]->GetName() + "\n";
         source_ += "//----------------------------------------------------\n\n";
         ExportModuleClasses(modules[i]);
+        ExportModuleEvents(modules[i]);
     }
 
 

+ 2 - 0
Source/ToolCore/JSBind/JSBTypeScript.h

@@ -58,6 +58,8 @@ private:
     void ExportModuleConstants(JSBModule*  moduleName);
     void ExportModuleClasses(JSBModule*  moduleName);
 
+    void ExportModuleEvents(JSBModule* module);
+
     void WriteToFile(const String& path);
 
     JSBPackage* package_;