ソースを参照

[TypeScript] Work on strong typed events

Josh Engebretson 9 年 前
コミット
a6b87593f8

+ 1 - 1
Script/AtomicEditor/hostExtensions/languageExtensions/CSharpLanguageExtension.ts

@@ -162,7 +162,7 @@ export default class CSharpLanguageExtension implements Editor.HostExtensions.Re
             this.isNETProject = true;
             this.configureNETProjectMenu();
 
-            this.eventObject.subscribeToEvent("NETBuildResult", (eventData:ToolCore.NETBuildResult) => {
+            this.eventObject.subscribeToEvent("NETBuildResult", (eventData:ToolCore.NETBuildResultEvent) => {
 
                 if (!eventData.success) {
 

+ 1 - 1
Script/AtomicEditor/ui/frames/inspector/InspectorFrame.ts

@@ -90,7 +90,7 @@ class InspectorFrame extends ScriptWidget {
 
             for (var i = 0; i < selection.getSelectedNodeCount(); i++) {
 
-                this.handleSceneNodeSelected( { node: selection.getSelectedNode(i),  scene: this.scene, selected: true, quiet: true} );
+                this.handleSceneNodeSelected( <Editor.SceneNodeSelectedEvent> { node: selection.getSelectedNode(i),  scene: this.scene, selected: true, quiet: true} );
 
             }
 

+ 2 - 2
Script/Packages/Atomic/Core.json

@@ -26,8 +26,8 @@
 			"sendEvent(eventType:string, data?:Object);",
 			"subscribeToEvent(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);"
+			"subscribeToEvent(eventMetaData:Atomic.EventMetaData);",
+			"subscribeToEvent(sender: AObject, eventMetaData:Atomic.EventMetaData);"
 		]
 	},
 	"haxe_decl" : {

+ 17 - 6
Script/TypeScript/AtomicWork.d.ts

@@ -26,8 +26,23 @@ declare module Atomic {
 
     // end subsystems
 
-    // Base interface for events
-    export interface NativeEvent { }
+    // Base interface for events, contains eventType string and callback
+    interface EventMetaData
+    {
+        _eventType: string;
+        _callback: any;
+    }
+
+    interface NativeEvent extends EventMetaData
+    {
+    }
+
+    interface ScriptEvent extends EventMetaData
+    {
+    }
+
+    // typed callback generic
+    type EventCallback<T extends EventMetaData> = (data: T) => void;
 
     export interface PathInfo {
 
@@ -96,10 +111,6 @@ declare module Atomic {
         subObject: number;
     }
 
-    // TODO: delete these when all references have been changed to the auto-generated name
-    export interface UIWidgetEvent extends Atomic.WidgetEvent {}
-    export interface UIWidgetDeletedEvent extends Atomic.WidgetDeletedEvent {}
-
     export interface AttributeInfo {
 
         type: VariantType;

+ 28 - 0
Source/AtomicJS/Javascript/JSAPI.cpp

@@ -197,6 +197,34 @@ void js_setup_prototype(JSVM* vm, const char* package, const char* classname, co
     assert (top == duk_get_top(ctx));
 }
 
+
+static int js_define_native_event_duk(duk_context* ctx) {
+
+    duk_push_current_function(ctx);
+
+    duk_push_object(ctx);
+    duk_get_prop_string(ctx, -2, "_eventType");
+    duk_put_prop_string(ctx, -2, "_eventType");
+    duk_dup(ctx, 0);
+    duk_put_prop_string(ctx, -2, "_callback");
+
+    return 1;
+}
+
+void js_define_native_event(duk_context* ctx, const String& eventType, const String &eventName)
+{
+    // push c function which takes 1 argument, the callback
+    duk_push_c_function(ctx, js_define_native_event_duk, 1);
+
+    // store the event type in the function object
+    duk_push_string(ctx, eventType.CString());
+    duk_put_prop_string(ctx, -2, "_eventType");
+
+    // store to module object
+    duk_put_prop_string(ctx, -2, eventName.CString());
+
+}
+
 void js_object_to_variantmap(duk_context* ctx, int objIdx, VariantMap &v)
 {
     v.Clear();

+ 3 - 0
Source/AtomicJS/Javascript/JSAPI.h

@@ -54,6 +54,9 @@ void js_class_push_propertyobject(JSVM* vm, const char* package, const char* cla
 void js_class_get_prototype(duk_context* ctx, const char* package, const char *classname);
 void js_class_get_constructor(duk_context* ctx, const char* package, const char *classname);
 
+// setups up a native event wrapper on module object at the top of the stack
+void js_define_native_event(duk_context* ctx, const String& eventType, const String& eventName);
+
 /// Pushes variant value or undefined if can't be pushed
 void js_push_variant(duk_context* ctx, const Variant &v);
 void js_push_variantmap(duk_context* ctx, const VariantMap &vmap);

+ 48 - 2
Source/AtomicJS/Javascript/JSCore.cpp

@@ -31,13 +31,56 @@ namespace Atomic
 
 static int Object_SubscribeToEvent(duk_context* ctx)
 {
-
     int top = duk_get_top(ctx);
 
     Object* sender = NULL;
 
     StringHash eventType = StringHash::ZERO;
 
+    // if we have a single argument, it is event meta data
+    if (top == 1)
+    {
+        if (duk_is_object(ctx, 0))
+        {
+            duk_get_prop_string(ctx, 0, "_callback");
+            duk_get_prop_string(ctx, 0, "_eventType");
+
+            if (duk_is_string(ctx, -1) && duk_is_function(ctx, -2))
+            {
+                duk_replace(ctx, 0);
+
+                top = duk_get_top(ctx);
+            }
+        }
+
+        if (top != 2)
+        {
+            duk_push_string(ctx, "Object.subscribeToEvent() - Bad meta data");
+            duk_throw(ctx);
+        }
+    }
+
+
+    // unwrap event data
+    if ( top == 2 && duk_is_object(ctx, 0) && duk_is_object(ctx, 1))
+    {
+        duk_get_prop_string(ctx, 1, "_callback");
+        duk_get_prop_string(ctx, 1, "_eventType");
+
+        if (duk_is_string(ctx, -1) && duk_is_function(ctx, -2))
+        {
+            duk_replace(ctx, 1);
+
+            top = duk_get_top(ctx);
+        }
+
+        if (top != 3)
+        {
+            duk_push_string(ctx, "Object.subscribeToEvent() - Bad sender meta data");
+            duk_throw(ctx);
+        }
+    }
+
     if ( top == 2 ) // General notification: subscribeToEvent("ScreenMode", function() {});
     {
         if (duk_is_string(ctx, 0) && duk_is_function(ctx, 1))
@@ -53,7 +96,8 @@ 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)) {
+        }
+        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));
         }
@@ -95,7 +139,9 @@ static int Object_SubscribeToEvent(duk_context* ctx)
 
     duk_get_prop_string(ctx, -1, "__eventHelperFunctions");
     assert(duk_is_object(ctx, -1));
+
     assert(duk_is_function(ctx, sender ? 2 : 1));
+
     duk_dup(ctx, sender ? 2 : 1);
     duk_put_prop_string(ctx, -2,  eventType.ToString().CString());
     duk_pop(ctx);

+ 15 - 1
Source/ToolCore/JSBind/JSBEvent.cpp

@@ -54,8 +54,22 @@ JSBPackage* JSBEvent::GetPackage()
     return module_->GetPackage();
 }
 
-String JSBEvent::GetScriptEventName() const
+String JSBEvent::GetScriptEventName(BindingLanguage language) const
 {
+
+    if (language == BINDINGLANGUAGE_JAVASCRIPT) {
+
+        if (eventName_ == "WidgetEvent")
+        {
+            return "UIWidgetEvent";
+        }
+
+        if (eventName_ == "WidgetDeleted")
+        {
+            return "UIWidgetDeletedEvent";
+        }
+    }
+
     if (eventName_.EndsWith("Event"))
         return eventName_;
 

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

@@ -24,6 +24,8 @@
 
 #include <Atomic/Core/Object.h>
 
+#include "JSBindTypes.h"
+
 using namespace Atomic;
 
 namespace ToolCore
@@ -56,7 +58,7 @@ namespace ToolCore
         const String& GetEventName() const { return eventName_; }
         unsigned GetEventHash() const;
         /// Generally this is the EventName + "Event"
-        String GetScriptEventName() const;
+        String GetScriptEventName(BindingLanguage language = BINDINGLANGUAGE_ANY) const;
         const Vector<EventParam>& GetParameters() const { return parameters_;  }
 
 

+ 7 - 23
Source/ToolCore/JSBind/JSBTypeScript.cpp

@@ -371,33 +371,12 @@ void JSBTypeScript::ExportModuleEvents(JSBModule* module)
 
     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 = %u", event->GetEventName().CString(), event->GetEventHash());
+        String scriptEventName = event->GetScriptEventName(BINDINGLANGUAGE_JAVASCRIPT);
 
-        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());
+        source += ToString("    export interface %s extends Atomic.NativeEvent {\n", scriptEventName.CString());
 
         // parameters
 
@@ -467,6 +446,11 @@ void JSBTypeScript::ExportModuleEvents(JSBModule* module)
         }
 
         source += "    }\n\n";
+
+        // Write the event function signature
+
+        source += ToString("\nexport function %s (callback : Atomic.EventCallback<%s>) : Atomic.EventMetaData;\n\n", scriptEventName.CString(), scriptEventName.CString());
+
     }
     source_ += source;
 }

+ 11 - 1
Source/ToolCore/JSBind/JavaScript/JSModuleWriter.cpp

@@ -29,7 +29,7 @@
 #include "../JSBEnum.h"
 #include "../JSBClass.h"
 #include "../JSBFunction.h"
-
+#include "../JSBEvent.h"
 
 #include "JSModuleWriter.h"
 #include "JSClassWriter.h"
@@ -238,6 +238,7 @@ void JSModuleWriter::WriteModulePreInit(String& source)
             itr++;
         }
     }
+
     source += "// constants\n";
 
     Vector<String> constants = module_->constants_.Keys();
@@ -252,6 +253,15 @@ void JSModuleWriter::WriteModulePreInit(String& source)
         source.AppendWithFormat("duk_put_prop_string(ctx, -2, \"%s\");\n", constants.At(i).CString());
     }
 
+    source += "// events\n";
+
+    const Vector<SharedPtr<JSBEvent>>& events = module_->GetEvents();
+
+    for (unsigned i = 0; i < events.Size(); i++)
+    {
+        source.AppendWithFormat("js_define_native_event(ctx, \"%s\", \"%s\");\n", events[i]->GetEventName().CString(), events[i]->GetScriptEventName(BINDINGLANGUAGE_JAVASCRIPT).CString());
+    }
+
     source += "duk_pop(ctx);\n";
     source += "// end enums and constants\n";
 

+ 4 - 4
Source/ToolCore/NETTools/NETBuildSystem.h

@@ -35,14 +35,14 @@ namespace ToolCore
 
     ATOMIC_EVENT(E_NETBUILDRESULT, NETBuildResult)
     {
-        ATOMIC_PARAM(P_BUILD, Build); // NETBuild*
-        ATOMIC_PARAM(P_SUCCESS, Success); // bool = success = true;
-        ATOMIC_PARAM(P_ERRORTEXT, ErrorText); // for failure, the compilation output
+        ATOMIC_PARAM(P_BUILD, Build); // NETBuild
+        ATOMIC_PARAM(P_SUCCESS, Success); // bool success = true;
+        ATOMIC_PARAM(P_ERRORTEXT, ErrorText); // String for failure, the compilation output
     }
 
     ATOMIC_EVENT(E_NETBUILDATOMICPROJECT, NETBuildAtomicProject)
     {
-        ATOMIC_PARAM(P_PROJECT, Project); // Project*
+        ATOMIC_PARAM(P_PROJECT, Project); // Project
     }
 
     enum NETBuildStatus