Browse Source

Hierarchy frame creation menu, event model improvements

Josh Engebretson 10 years ago
parent
commit
a4ef75b7e0

+ 103 - 46
Script/AtomicEditor/ui/HierarchyFrame.ts

@@ -1,10 +1,20 @@
 
+import HierarchyFrameMenu = require("./HierarchyFrameMenu");
+import MenuItemSources = require("./menus/MenuItemSources");
+
 class HierarchyFrame extends Atomic.UIWidget {
 
+    scene: Atomic.Scene = null;
+    hierList: Atomic.UIListView;
+    menu: HierarchyFrameMenu;
+    nodeIDToItemID = {};
+
     constructor(parent: Atomic.UIWidget) {
 
         super();
 
+        this.menu = new HierarchyFrameMenu();
+
         this.load("AtomicEditor/editor/ui/hierarchyframe.tb.txt");
 
         this.gravity = Atomic.UI_GRAVITY_TOP_BOTTOM;
@@ -20,8 +30,6 @@ class HierarchyFrame extends Atomic.UIWidget {
 
         hierarchycontainer.addChild(hierList);
 
-        this.subscribeToEvent("EditorUpdateHierarchy", (data) => this.handleUpdateHierarchy(data));
-
         this.subscribeToEvent(this, "WidgetEvent", (data) => this.handleWidgetEvent(data));
 
         this.subscribeToEvent("EditorActiveSceneChanged", (data) => this.handleActiveSceneChanged(data));
@@ -29,91 +37,98 @@ class HierarchyFrame extends Atomic.UIWidget {
         this.subscribeToEvent("EditorActiveNodeChange", (data) => {
 
             if (data.node)
-              this.hierList.selectItemByID(data.node.id.toString());
+                this.hierList.selectItemByID(data.node.id.toString());
 
         });
 
     }
 
-    recursiveAddNode(parentID: number, node: Atomic.Node) {
+    handleNodeAdded(ev: Atomic.NodeAddedEvent) {
 
-        //if (node.isTemporary())
-        //  return;
+        var node = ev.node;
 
-        var name = node.name;
+        if (!node.parent || node.scene != this.scene)
+            return;
 
-        if (!name.length)
-            name = "(Anonymous)"
+        var parentID = this.nodeIDToItemID[node.parent.id];
 
-        var childItemID = this.hierList.addChildItem(parentID, name, "Folder.icon", node.id.toString());
+        var childItemID = this.hierList.addChildItem(parentID, node.name, "Folder.icon", node.id.toString());
 
-        for (var i = 0; i < node.getNumChildren(false); i++) {
+        this.nodeIDToItemID[node.id] = childItemID;
 
-            this.recursiveAddNode(childItemID, node.getChildAtIndex(i));
+    }
 
-        }
+    handleNodeRemoved(ev: Atomic.NodeRemovedEvent) {
 
-    }
+        console.log("handle Node Removed");
 
-    refresh() {
+        var node = ev.node;
 
-        this.hierList.deleteAllItems();
+        delete this.nodeIDToItemID[node.id];
 
-        if (!this.scene)
+        if (!node.parent || node.scene != this.scene)
             return;
 
-        var parentID = this.hierList.addRootItem("Scene", "Folder.icon", this.scene.id.toString());
+        this.hierList.deleteItemByID(node.id.toString());
 
-        for (var i = 0; i < this.scene.getNumChildren(false); i++) {
+        this.sendEvent("EditorActiveNodeChange", { node: ev.parent ? ev.parent : this.scene});
 
-            this.recursiveAddNode(parentID, this.scene.getChildAtIndex(i));
+    }
 
-        }
+    handleActiveSceneChanged(data) {
 
-        this.hierList.rootList.value = 0;
-        this.hierList.setExpanded(parentID, true);
+        if (this.scene)
+            this.unsubscribeFromEvents(this.scene);
 
-    }
+        this.scene = <Atomic.Scene> data.scene;
 
-    handleUpdateHierarchy(data) {
+        this.populate();
 
-        this.refresh();
+        if (this.scene) {
 
-    }
+            this.subscribeToEvent(this.scene, "NodeAdded", (ev: Atomic.NodeAddedEvent) => this.handleNodeAdded(ev));
+            this.subscribeToEvent(this.scene, "NodeRemoved", (ev: Atomic.NodeRemovedEvent) => this.handleNodeRemoved(ev));
+            this.subscribeToEvent(this.scene, "NodeNameChanged", (ev: Atomic.NodeNameChangedEvent) => {
 
-    handleActiveSceneChanged(data) {
+                this.hierList.setItemText(ev.node.id.toString(), ev.node.name);
 
-        if (this.scene)
-          this.unsubscribeFromEvents(this.scene);
+            });
 
-        this.scene = <Atomic.Scene> data.scene;
+        }
 
-        if (this.scene) {
+    }
 
-          this.subscribeToEvent("NodeRemoved", (data) => {
+    handleWidgetEvent(data: Atomic.UIWidgetEvent): boolean {
 
-              this.hierList.deleteItemByID(data.node.id.toString());
+        if (data.type == Atomic.UI_EVENT_TYPE_CLICK) {
 
-          });
+            var id = data.target.id;
 
-          this.subscribeToEvent("NodeAdded", (data) => {
+            if (this.menu.handlePopupMenu(data.target, data.refid))
+                return true;
 
-              this.refresh();
+            if (id == "create popup") {
 
-          });
+                if (data.refid == "create_node") {
 
+                    var selectedId = Number(this.hierList.rootList.selectedItemID);
+                    var node = this.scene.getNode(selectedId);
+                    node.createChild("Node");
 
-        }
+                }
 
-        this.refresh();
+            }
 
-    }
+            // create
+            if (id == "menu create") {
 
-    handleWidgetEvent(data: Atomic.UIWidgetEvent): boolean {
+                var src = MenuItemSources.getMenuItemSource("hierarchy create items");
+                var menu = new Atomic.UIMenuWindow(data.target, "create popup");
+                menu.show(src);
+                return true;
 
-        if (data.type == Atomic.UI_EVENT_TYPE_CLICK && data.target) {
+            }
 
-            var id = data.target.id;
 
             if (id == "hierList_") {
 
@@ -131,8 +146,50 @@ class HierarchyFrame extends Atomic.UIWidget {
         return false;
     }
 
-    scene: Atomic.Scene = null;
-    hierList: Atomic.UIListView;
+    recursiveAddNode(parentID: number, node: Atomic.Node) {
+
+        //if (node.isTemporary())
+        //  return;
+
+        var name = node.name;
+
+        if (!name.length)
+            name = "(Anonymous)"
+
+        var childItemID = this.hierList.addChildItem(parentID, name, "Folder.icon", node.id.toString());
+
+        this.nodeIDToItemID[node.id] = childItemID;
+
+        for (var i = 0; i < node.getNumChildren(false); i++) {
+
+            this.recursiveAddNode(childItemID, node.getChildAtIndex(i));
+
+        }
+
+    }
+
+    populate() {
+
+        this.nodeIDToItemID = {};
+        this.hierList.deleteAllItems();
+
+        if (!this.scene)
+            return;
+
+        var parentID = this.hierList.addRootItem("Scene", "Folder.icon", this.scene.id.toString());
+
+        this.nodeIDToItemID[this.scene.id] = parentID;
+
+        for (var i = 0; i < this.scene.getNumChildren(false); i++) {
+
+            this.recursiveAddNode(parentID, this.scene.getChildAtIndex(i));
+
+        }
+
+        this.hierList.rootList.value = 0;
+        this.hierList.setExpanded(parentID, true);
+
+    }
 
 }
 

+ 44 - 0
Script/AtomicEditor/ui/HierarchyFrameMenu.ts

@@ -0,0 +1,44 @@
+
+import strings = require("./EditorStrings");
+import EditorEvents = require("../editor/EditorEvents");
+import EditorUI = require("./EditorUI");
+import MenuItemSources = require("./menus/MenuItemSources");
+
+class HierarchyFrameMenus extends Atomic.ScriptObject {
+
+    constructor() {
+
+        super();
+
+        MenuItemSources.createMenuItemSource("hierarchy create items", createItems);
+
+        this.subscribeToEvent(EditorEvents.ContentFolderChanged, (ev: EditorEvents.ContentFolderChangedEvent) => {
+            this.contentFolder = ev.path;
+        })
+
+    }
+
+    handlePopupMenu(target: Atomic.UIWidget, refid: string): boolean {
+
+        if (!target || !refid) return;
+
+        return false;
+
+    }
+
+    contentFolder: string;
+
+}
+
+export = HierarchyFrameMenus;
+
+// initialization
+var StringID = strings.StringID;
+
+var createItems = {
+    Node: ["create_node", undefined, "Folder.icon"],
+    "-1": null,
+    "3D": {
+        Light: ["create_light", undefined, "JavascriptBitmap"]
+    }
+};

+ 2 - 5
Script/AtomicEditor/ui/ProjectFrame.ts

@@ -107,9 +107,6 @@ class ProjectFrame extends ScriptWidget {
 
             var id = data.target.id;
 
-            var system = ToolCore.getToolSystem();
-            var project = system.project;
-
 
             if (this.menu.handlePopupMenu(data.target, data.refid))
                 return true;
@@ -124,9 +121,9 @@ class ProjectFrame extends ScriptWidget {
 
             }
 
-
+            var system = ToolCore.getToolSystem();
+            var project = system.project;
             var db = ToolCore.getAssetDatabase();
-
             var fs = Atomic.getFileSystem();
 
             if (data.target && data.target.id.length) {

+ 53 - 49
Script/AtomicEditor/ui/inspector/NodeInspector.ts

@@ -11,7 +11,7 @@ class NodeInspector extends ScriptWidget {
         super();
 
         this.subscribeToEvent(this, "WidgetEvent", (data) => this.handleWidgetEvent(data));
-        this.subscribeToEvent("KeyUp", (data) => this.handleKeyUp(data));
+        this.subscribeToEvent("KeyUp", (data) => { this.handleKeyUp(data) });
 
     }
 
@@ -32,14 +32,18 @@ class NodeInspector extends ScriptWidget {
 
             if (this.node) {
 
+                var node = this.node;
+                this.node = null;
+
                 this.nodeLayout.deleteAllChildren();
                 this.nodeLayout = null;
-                this.node.removeComponents(true, true);
-                if (this.node.parent)
-                    this.node.parent.removeChild(this.node);
-                this.node = null;
-                this.sendEvent("EditorActiveNodeChange", { node: null });
-                this.sendEvent("EditorUpdateHierarchy", {});
+
+                if (node.parent) {
+                    node.parent.removeChild(node);
+                }
+
+                node.removeComponents(true, true);
+
 
             }
 
@@ -66,13 +70,13 @@ class NodeInspector extends ScriptWidget {
 
     }
 
-    getPrefabComponent(node: Atomic.Node):Atomic.PrefabComponent {
+    getPrefabComponent(node: Atomic.Node): Atomic.PrefabComponent {
 
-      if (node.parent && node.parent.getComponent("PrefabComponent"))
-        return <Atomic.PrefabComponent> node.parent.getComponent("PrefabComponent");
+        if (node.parent && node.parent.getComponent("PrefabComponent"))
+            return <Atomic.PrefabComponent> node.parent.getComponent("PrefabComponent");
 
-      if (node.parent)
-          return this.getPrefabComponent(node.parent);
+        if (node.parent)
+            return this.getPrefabComponent(node.parent);
 
         return null;
 
@@ -80,11 +84,11 @@ class NodeInspector extends ScriptWidget {
 
     detectPrefab(node: Atomic.Node): boolean {
 
-      if (node.parent && node.parent.getComponent("PrefabComponent"))
-        return true;
+        if (node.parent && node.parent.getComponent("PrefabComponent"))
+            return true;
 
-      if (node.parent)
-          return this.detectPrefab(node.parent);
+        if (node.parent)
+            return this.detectPrefab(node.parent);
 
         return false;
 
@@ -180,60 +184,60 @@ class NodeInspector extends ScriptWidget {
 
         if (this.isPrefab) {
 
-          var name = new Atomic.UITextField();
-          name.textAlign = Atomic.UI_TEXT_ALIGN_LEFT;
-          name.skinBg = "InspectorTextAttrName";
-          name.text = "Prefab"
-          name.fontDescription = fd;
+            var name = new Atomic.UITextField();
+            name.textAlign = Atomic.UI_TEXT_ALIGN_LEFT;
+            name.skinBg = "InspectorTextAttrName";
+            name.text = "Prefab"
+            name.fontDescription = fd;
+
+            var prefabLayout = new Atomic.UILayout();
+            prefabLayout.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_GRAVITY;
 
-          var prefabLayout = new Atomic.UILayout();
-          prefabLayout.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_GRAVITY;
+            var saveButton = new Atomic.UIButton();
+            saveButton.text = "Save";
+            saveButton.fontDescription = fd;
 
-          var saveButton = new Atomic.UIButton();
-          saveButton.text = "Save";
-          saveButton.fontDescription = fd;
+            saveButton.onClick = () => {
 
-          saveButton.onClick = () => {
+                var prefabComponent = this.getPrefabComponent(this.node);
 
-            var prefabComponent = this.getPrefabComponent(this.node);
+                if (prefabComponent) {
 
-            if (prefabComponent) {
+                    prefabComponent.savePrefab();
 
-              prefabComponent.savePrefab();
+                    this.sendEvent("EditorActiveNodeChange", { node: this.node });
 
-              this.sendEvent("EditorActiveNodeChange", {node:this.node});
+                    return true;
 
-              return true;
+                }
 
             }
 
-          }
+            var undoButton = new Atomic.UIButton();
+            undoButton.text = "Undo";
+            undoButton.fontDescription = fd;
 
-          var undoButton = new Atomic.UIButton();
-          undoButton.text = "Undo";
-          undoButton.fontDescription = fd;
+            undoButton.onClick = () => {
 
-          undoButton.onClick = () => {
+                var prefabComponent = this.getPrefabComponent(this.node);
 
-            var prefabComponent = this.getPrefabComponent(this.node);
+                if (prefabComponent) {
 
-            if (prefabComponent) {
+                    prefabComponent.undoPrefab();
 
-              prefabComponent.undoPrefab();
+                    this.sendEvent("EditorActiveNodeChange", { node: this.node });
 
-              this.sendEvent("EditorActiveNodeChange", {node:this.node});
+                    return true;
 
-              return true;
+                }
 
             }
 
-          }
-
-          prefabLayout.addChild(name);
-          prefabLayout.addChild(saveButton);
-          prefabLayout.addChild(undoButton);
+            prefabLayout.addChild(name);
+            prefabLayout.addChild(saveButton);
+            prefabLayout.addChild(undoButton);
 
-          attrsVerticalLayout.addChild(prefabLayout);
+            attrsVerticalLayout.addChild(prefabLayout);
 
         }
 
@@ -264,7 +268,7 @@ class NodeInspector extends ScriptWidget {
 
     }
 
-    isPrefab:boolean;
+    isPrefab: boolean;
     node: Atomic.Node;
     nodeLayout: Atomic.UILayout;
     bindings: Array<DataBinding>;

+ 33 - 15
Script/AtomicEditor/ui/menus/MenuItemSources.ts

@@ -15,9 +15,9 @@ export function getMenuItemSource(id: string): Atomic.UIMenuItemSource {
 
 }
 
-export function createMenuItemSource(id: string, items: any): Atomic.UIMenuItemSource {
+function createMenuItemSourceRecursive(items: any): Atomic.UIMenuItemSource {
 
-    var src = srcLookup[id] = new UIMenuItemSource();
+    var src = new UIMenuItemSource();
 
     for (var key in items) {
 
@@ -31,31 +31,41 @@ export function createMenuItemSource(id: string, items: any): Atomic.UIMenuItemS
 
             } else if (value == null) {
 
+                // add a separator
                 src.addItem(new UIMenuItem(key));
 
-            }
-            else if (typeof value === 'object' && value.length == 1) {
+            } else if (Object.prototype.toString.call(value) === '[object Array]') {
+
+                if (value.length == 1)
+                    src.addItem(new UIMenuItem(key, value[0]));
+                else if (value.length == 2)
+                    src.addItem(new UIMenuItem(key, value[0], strings.EditorString.GetString(value[1])));
+                else if (value.length == 3) {
 
-                src.addItem(new UIMenuItem(key, value[0]));
+                    var str = "";
+                    if (value[1])
+                        str = strings.EditorString.GetString(value[1]);
 
-            } else if (typeof value === 'object' && value.length == 2) {
+                    var skinBg = "";
+                    if (value[2])
+                        skinBg = value[2];
 
-                src.addItem(new UIMenuItem(key, value[0], strings.EditorString.GetString(value[1])));
+                    src.addItem(new UIMenuItem(key, value[0], str, skinBg));
 
-            } else if (typeof value === 'object' && value.length == 3) {
+                }
 
-                var str = "";
-                if (value[1])
-                    str = strings.EditorString.GetString(value[1]);
+            }
+            else if (typeof value === 'object') {
 
-                var skinBg = "";
-                if (value[2])
-                    skinBg = value[2];
+                var subsrc = createMenuItemSourceRecursive(value);
 
-                src.addItem(new UIMenuItem(key, value[0], str, skinBg));
+                var item = new Atomic.UIMenuItem(key);
+                item.subSource = subsrc;
+                src.addItem(item);
 
             }
 
+
         }
 
     }
@@ -63,3 +73,11 @@ export function createMenuItemSource(id: string, items: any): Atomic.UIMenuItemS
     return src;
 
 }
+
+export function createMenuItemSource(id: string, items: any): Atomic.UIMenuItemSource {
+
+    srcLookup[id] = createMenuItemSourceRecursive(items);
+
+    return srcLookup[id];
+
+}

+ 6 - 5
Script/TypeScript/Atomic.d.ts

@@ -1456,10 +1456,6 @@ declare module Atomic {
       getBaseType(): string;
       // Return type name.
       getTypeName(): string;
-      // Unsubscribe from a specific sender's events.
-      unsubscribeFromEvents(sender: AObject): void;
-      // Unsubscribe from all events.
-      unsubscribeFromAllEvents(): void;
       // Return execution context.
       getContext(): Context;
       // Return subsystem by type.
@@ -1475,6 +1471,10 @@ declare module Atomic {
       sendEvent(eventType:string, data?:Object);
       subscribeToEvent(eventType:string, callback:(data:any)=>void);
       subscribeToEvent(sender:AObject, eventType:string, callback:(data:any)=>void);
+      unsubscribeFromAllEvents();
+      unsubscribeFromEvent(event:String);
+      unsubscribeFromEvents(sender:Atomic.AObject);
+      unsubscribeFromSenderEvent(sender:Atomic.AObject, event:String);
 
    }
 
@@ -7123,6 +7123,7 @@ declare module Atomic {
 
       addRootItem(text: string, icon: string, id: string): number;
       addChildItem(parentItemID: number, text: string, icon: string, id: string): number;
+      setItemText(id: string, text: string): void;
       deleteItemByID(id: string): void;
       setExpanded(itemID: number, value: boolean): void;
       deleteAllItems(): void;
@@ -8072,7 +8073,7 @@ declare module Atomic {
    export class JSEventHelper extends AObject {
 
       // Construct.
-      constructor();
+      constructor(object: AObject);
 
 
    }

+ 23 - 21
Script/TypeScript/AtomicWork.d.ts

@@ -18,27 +18,29 @@ declare module Atomic {
 
     }
 
-    /*
-        export enum UIWidgetEventType {
-
-        EVENT_TYPE_CLICK,
-        EVENT_TYPE_LONG_CLICK,
-        EVENT_TYPE_POINTER_DOWN,
-        EVENT_TYPE_POINTER_UP,
-        EVENT_TYPE_POINTER_MOVE,
-        EVENT_TYPE_RIGHT_POINTER_DOWN,
-        EVENT_TYPE_RIGHT_POINTER_UP,
-        EVENT_TYPE_WHEEL,
-        EVENT_TYPE_CHANGED,
-        EVENT_TYPE_KEY_DOWN,
-        EVENT_TYPE_KEY_UP,
-        EVENT_TYPE_SHORTCUT,
-        EVENT_TYPE_CONTEXT_MENU,
-        EVENT_TYPE_FILE_DROP,
-        EVENT_TYPE_TAB_CHANGED,
-        EVENT_TYPE_CUSTOM
-        }
-    */
+    export interface NodeAddedEvent {
+
+        scene: Atomic.Scene;
+        parent: Atomic.Node;
+        node: Atomic.Node;
+
+    }
+
+    export interface NodeRemovedEvent {
+
+        scene: Atomic.Scene;
+        parent: Atomic.Node;
+        node: Atomic.Node;
+
+    }
+
+    export interface NodeNameChangedEvent {
+
+        scene: Atomic.Scene;
+        node: Atomic.Node;
+
+    }
+
     export interface UIWidgetEvent {
 
         handler: UIWidget;

+ 40 - 1
Source/Atomic/UI/UIListView.cpp

@@ -47,6 +47,8 @@ public:
         }
     }
 
+    void UpdateText(const String& text);
+
     ListViewItemSource* source_;
     ListViewItem* parent_;
     int depth_;
@@ -60,7 +62,15 @@ class ListViewItemWidget : public TBLayout
 public:
     ListViewItemWidget(ListViewItem *item, ListViewItemSource *source, TBSelectItemViewer *sourceviewer, int index);
     virtual bool OnEvent(const TBWidgetEvent &ev);
+
+    void UpdateText(const String& text)
+    {
+        if (textField_)
+            textField_->SetText(text.CString());
+    }
+
 private:
+    TBTextField* textField_;
     ListViewItemSource *source_;
     TBSelectItemViewer *sourceviewer_;
     int index_;
@@ -78,6 +88,14 @@ public:
 };
 
 // implementation
+
+void ListViewItem::UpdateText(const String& text)
+{
+    str = text.CString();
+    if (widget_)
+        widget_->UpdateText(text);
+}
+
 ListViewItem* ListViewItem::AddChild(const char *text, const char* icon, const TBID &id)
 {
     ListViewItem* child = new ListViewItem(text, id, icon, source_);
@@ -138,6 +156,7 @@ ListViewItemWidget::ListViewItemWidget(ListViewItem *item, ListViewItemSource *s
     , sourceviewer_(sourceviewer)
     , index_(index)
     , item_(item)
+    , textField_(0)
 {
     SetLayoutDistribution(LAYOUT_DISTRIBUTION_GRAVITY);
     SetLayoutDistributionPosition(LAYOUT_DISTRIBUTION_POSITION_LEFT_TOP);
@@ -166,7 +185,7 @@ ListViewItemWidget::ListViewItemWidget(ListViewItem *item, ListViewItemSource *s
     fd.SetID(TBIDC("Vera"));
     fd.SetSize(11);
 
-    TBTextField* tfield = new TBTextField();
+    TBTextField* tfield = textField_ = new TBTextField();
     tfield->SetIgnoreInput(true);
     tfield->SetSkinBg(TBIDC("Folder"));
     tfield->SetText(item->str);
@@ -279,6 +298,22 @@ unsigned UIListView::AddRootItem(const String& text, const String& icon, const S
     return itemLookupId_ - 1;
 }
 
+void UIListView::SetItemText(const String& id, const String& text)
+{
+    TBID tbid(id.CString());
+
+    for (int i = 0; i <  source_->GetNumItems(); i++)
+    {
+        if (source_->GetItemID(i) == tbid)
+        {
+            ListViewItem* item = source_->GetItem(i);
+            item->UpdateText(text);
+            return;
+        }
+    }
+
+}
+
 void UIListView::DeleteItemByID(const String& id)
 {
     TBID tbid(id.CString());
@@ -287,6 +322,10 @@ void UIListView::DeleteItemByID(const String& id)
     {
         if (source_->GetItemID(i) == tbid)
         {
+            ListViewItem* item = source_->GetItem(i);
+            if (item->parent_)
+                item->parent_->children_.Remove(item);
+
             source_->DeleteItem(i);
             return;
         }

+ 2 - 0
Source/Atomic/UI/UIListView.h

@@ -25,6 +25,8 @@ public:
 
     unsigned AddChildItem(unsigned parentItemID, const String& text, const String& icon, const String& id);
 
+
+    void SetItemText(const String& id, const String& text);
     void DeleteItemByID(const String& id);
 
     void SetExpanded(unsigned itemID, bool value);

+ 2 - 0
Source/Atomic/UI/UIWidget.cpp

@@ -153,6 +153,8 @@ void UIWidget::OnDelete()
 
     widget_ = 0;
 
+    UnsubscribeFromAllEvents();
+
     VariantMap eventData;
     eventData[WidgetDeleted::P_WIDGET] = this;
     SendEvent(E_WIDGETDELETED, eventData);

+ 0 - 2
Source/AtomicEditorWork/Editors/SceneEditor3D/SceneView3D.cpp

@@ -499,8 +499,6 @@ void SceneView3D::HandleDragEnterWidget(StringHash eventType, VariantMap& eventD
             Input* input = GetSubsystem<Input>();
             IntVector2 pos = input->GetMousePosition();
             UpdateDragNode(pos.x_, pos.y_);
-
-            SendEvent("EditorUpdateHierarchy");
         }
 
 

+ 9 - 1
Source/AtomicJS/Javascript/JSCore.cpp

@@ -55,7 +55,7 @@ static int Object_SubscribeToEvent(duk_context* ctx)
         duk_pop(ctx); // pop null or undefined
 
         // construct a new event helper
-        js_push_class_object_instance(ctx, new JSEventHelper(object->GetContext()));
+        js_push_class_object_instance(ctx, new JSEventHelper(object->GetContext(), object));
 
         duk_push_object(ctx);
         duk_put_prop_string(ctx, -2, "__eventHelperFunctions");
@@ -113,6 +113,14 @@ static int Object_SendEvent(duk_context* ctx)
 
 }
 
+/*
+"unsubscribeFromAllEvents();",
+"unsubscribeFromEvent(event:String);",
+"unsubscribeFromEvents(sender:Atomic.AObject);",
+"unsubscribeFromSenderEvent(sender:Atomic.AObject, event:String);"
+*/
+
+
 static int Atomic_GetArguments(duk_context* ctx)
 {
     duk_push_array(ctx);

+ 11 - 6
Source/AtomicJS/Javascript/JSEventHelper.cpp

@@ -45,8 +45,10 @@ void JSEventDispatcher::EndSendEvent(Context* context, Object* sender, StringHas
 
 }
 
-JSEventHelper::JSEventHelper(Context* context) :
-    Object(context)
+JSEventHelper::JSEventHelper(Context* context, Object* object) :
+    Object(context),
+    object_(object)
+
 {
 
 }
@@ -60,18 +62,22 @@ void JSEventHelper::AddEventHandler(StringHash eventType)
 {
     GetSubsystem<JSEventDispatcher>()->RegisterJSEvent(eventType);
 
-    SubscribeToEvent(eventType, HANDLER(JSEventHelper, HandleEvent));
+    // subscribe using object, so unsubscribing from object and not the event helper works
+    object_->SubscribeToEvent(eventType, HANDLER(JSEventHelper, HandleEvent));
 }
 
 void JSEventHelper::AddEventHandler(Object* sender, StringHash eventType)
 {
     GetSubsystem<JSEventDispatcher>()->RegisterJSEvent(eventType);
 
-    SubscribeToEvent(sender, eventType, HANDLER(JSEventHelper, HandleEvent));
+    // subscribe using object, so unsubscribing from object and not the event helper works
+    object_->SubscribeToEvent(sender, eventType, HANDLER(JSEventHelper, HandleEvent));
 }
 
 void JSEventHelper::HandleEvent(StringHash eventType, VariantMap& eventData)
-{    
+{
+    if (object_.Null())
+        return;
 
     JSVM* vm = JSVM::GetJSVM(0);
     duk_context* ctx = vm->GetJSContext();
@@ -112,7 +118,6 @@ void JSEventHelper::HandleEvent(StringHash eventType, VariantMap& eventData)
         duk_remove(ctx, -2); // vmap cache
         duk_remove(ctx, -2); // global stash
 
-
         if (duk_pcall(ctx, 1) != 0)
         {
             vm->SendJSErrorEvent();

+ 3 - 1
Source/AtomicJS/Javascript/JSEventHelper.h

@@ -34,7 +34,7 @@ class ATOMIC_API JSEventHelper : public Object
 
 public:
     /// Construct.
-    JSEventHelper(Context* context);
+    JSEventHelper(Context* context, Object* object);
     /// Destruct.
     virtual ~JSEventHelper();
 
@@ -45,6 +45,8 @@ private:
 
     void HandleEvent(StringHash eventType, VariantMap& eventData);
 
+    WeakPtr<Object> object_;
+
 };
 
 

+ 8 - 2
Source/AtomicJS/Packages/Atomic/Core.json

@@ -7,7 +7,9 @@
 	},
 	"excludes" : {
 		"Object" : {
-			"SendEvent" : ["StringHash"]
+			"SendEvent" : ["StringHash"],
+			"UnsubscribeFromEvents" : ["Object"],
+			"UnsubscribeFromAllEvents" : []
 		}
 	},
 	"typescript_decl" : {
@@ -15,7 +17,11 @@
 		"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);",
+			"unsubscribeFromAllEvents();",
+			"unsubscribeFromEvent(event:String);",
+			"unsubscribeFromEvents(sender:Atomic.AObject);",
+			"unsubscribeFromSenderEvent(sender:Atomic.AObject, event:String);"
 		]
 	}
 }