Browse Source

Better handling of Prefab operations, breaking a prefab is currently an undo-able op

Josh Engebretson 10 years ago
parent
commit
aa31a9a852

+ 0 - 58
Script/AtomicEditor/ui/frames/inspector/SelectionInspector.ts

@@ -288,11 +288,6 @@ class SelectionInspector extends ScriptWidget {
             this.nodeSection = new NodeSection(editType);
             section = this.nodeSection;
 
-            this.subscribeToEvent(this.nodeSection.prefabWidget, "SelectionPrefabSave", (data) => this.handleSelectionPrefabSave());
-            this.subscribeToEvent(this.nodeSection.prefabWidget, "SelectionPrefabUndo", (data) => this.handleSelectionPrefabUndo());
-            this.subscribeToEvent(this.nodeSection.prefabWidget, "SelectionPrefabBreak", (data) => this.handleSelectionPrefabBreak());
-
-
         } else if (editType.typeName == "Scene") {
 
             section = new SceneSection(editType);
@@ -656,59 +651,6 @@ class SelectionInspector extends ScriptWidget {
 
     }
 
-    handleSelectionPrefabSave() {
-
-        if (this.nodes.length != 1)
-            return;
-
-        var c = this.getPrefabComponent(this.nodes[0]);
-        if (!c)
-            return;
-
-        c.savePrefab();
-
-        var node = this.nodes[0];
-        this.removeNode(node);
-        this.addNode(node);
-
-    }
-
-    handleSelectionPrefabBreak() {
-
-        if (this.nodes.length != 1)
-            return;
-
-        var c = this.getPrefabComponent(this.nodes[0]);
-        if (!c)
-            return;
-
-        c.breakPrefab();
-
-        this.sceneEditor.scene.sendEvent("SceneEditEnd");
-
-        var node = this.nodes[0];
-        this.removeNode(node);
-        this.addNode(node);
-
-    }
-
-    handleSelectionPrefabUndo() {
-
-        if (this.nodes.length != 1)
-            return;
-
-        var c = this.getPrefabComponent(this.nodes[0]);
-        if (!c)
-            return;
-
-        c.undoPrefab();
-
-        var node = this.nodes[0];
-        this.removeNode(node);
-        this.addNode(node);
-
-    }
-
     filterComponent(component: Atomic.Component): boolean {
 
         if (component.typeName == "PrefabComponent") {

+ 7 - 4
Script/AtomicEditor/ui/frames/inspector/SelectionPrefabWidget.ts

@@ -10,6 +10,7 @@ class SelectionPrefabWidget extends Atomic.UILayout {
 
     widgetLayout: Atomic.UILayout;
     noticeLayout: Atomic.UILayout;
+    node: Atomic.Node;
 
     constructor() {
 
@@ -38,17 +39,17 @@ class SelectionPrefabWidget extends Atomic.UILayout {
 
         saveButton.onClick = () => {
 
-            this.sendEvent("SelectionPrefabSave");
+            this.node.scene.sendEvent("SceneEditPrefabSave", {node : this.node});
             return true;
         }
 
         var undoButton = new Atomic.UIButton();
-        undoButton.text = "Undo";
+        undoButton.text = "Revert";
         undoButton.fontDescription = fd;
 
         undoButton.onClick = () => {
 
-            this.sendEvent("SelectionPrefabUndo");
+            this.node.scene.sendEvent("SceneEditPrefabRevert", {node : this.node});
             return true;
 
         }
@@ -59,7 +60,7 @@ class SelectionPrefabWidget extends Atomic.UILayout {
 
         breakButton.onClick = () => {
 
-            this.sendEvent("SelectionPrefabBreak");
+            this.node.scene.sendEvent("SceneEditPrefabBreak", {node : this.node});
             return true;
         }
 
@@ -106,6 +107,7 @@ class SelectionPrefabWidget extends Atomic.UILayout {
     updateSelection(nodes: Atomic.Node[]) {
 
         var hasPrefab = false;
+        this.node = null;
 
         for (var i in nodes) {
 
@@ -132,6 +134,7 @@ class SelectionPrefabWidget extends Atomic.UILayout {
 
         this.noticeLayout.visibility = Atomic.UI_WIDGET_VISIBILITY_GONE;
         this.widgetLayout.visibility = Atomic.UI_WIDGET_VISIBILITY_VISIBLE;
+        this.node = nodes[0];
 
     }
 

+ 49 - 0
Source/AtomicEditor/Editors/SceneEditor3D/SceneEditHistory.cpp

@@ -209,6 +209,55 @@ void SceneEditHistory::HandleSceneNodeSelected(StringHash eventType, VariantMap&
         BeginSelectionEdit();
 }
 
+void SceneEditHistory::RemoveNode(Node *node)
+{
+    PODVector<SelectionEditOp*> remove;
+
+    for (unsigned i = 0; i < undoHistory_.Size(); i++)
+    {
+
+        SelectionEditOp* op = undoHistory_[i];
+
+        if (op->EraseNode(node))
+        {
+            assert(!remove.Contains(op));
+            remove.Push(op);
+        }
+
+    }
+
+    for (unsigned i = 0; i < redoHistory_.Size(); i++)
+    {
+
+        SelectionEditOp* op = redoHistory_[i];
+
+        if (op->EraseNode(node))
+        {
+            assert(!remove.Contains(op));
+            remove.Push(op);
+        }
+
+    }
+
+    for (unsigned i = 0; i < remove.Size(); i++)
+    {
+        PODVector<SelectionEditOp*>::Iterator itr = undoHistory_.Find(remove[i]);
+
+        if (itr != undoHistory_.End())
+        {
+            delete *itr;
+            undoHistory_.Erase(itr);
+        }
+        else
+        {
+            itr = redoHistory_.Find(remove[i]);
+            delete *itr;
+            redoHistory_.Erase(itr);
+        }
+    }
+
+
+}
 
 }
 

+ 3 - 0
Source/AtomicEditor/Editors/SceneEditor3D/SceneEditHistory.h

@@ -34,6 +34,9 @@ public:
     void BeginSelectionEdit();
     void EndSelectionEdit(bool begin = true);
 
+    /// Removes a node from the edit history
+    void RemoveNode(Node* node);
+
     void Undo();
     void Redo();
 

+ 24 - 11
Source/AtomicEditor/Editors/SceneEditor3D/SceneEditOp.cpp

@@ -34,6 +34,28 @@ SelectionEditOp::~SelectionEditOp()
 
 }
 
+bool SelectionEditOp::EraseNode(Node *node)
+{
+    PODVector<EditNode*>::Iterator itr = editNodes_.Begin();
+
+    while (itr != editNodes_.End())
+    {
+        if ((*itr)->node_ == node)
+        {
+            for (unsigned j = 0; j < (*itr)->components_.Size(); j++)
+                delete (*itr)->components_[j];
+
+            delete *itr;
+            editNodes_.Erase(itr);
+            break;
+        }
+
+        itr++;
+    }
+
+    return editNodes_.Size() == 0;
+}
+
 void SelectionEditOp::AddNode(Node* node)
 {
 
@@ -59,7 +81,6 @@ void SelectionEditOp::AddNode(Node* node)
         EditComponent* ecomponent = new EditComponent();
         ecomponent->component_ = component;
         ecomponent->nodeBegin_ = ecomponent->nodeEnd_ = node;
-        ecomponent->temporaryBegin_ = ecomponent->temporaryEnd_ = component->IsTemporary();
         component->Serializable::Save(ecomponent->stateBegin_);
         ecomponent->stateBegin_.Seek(0);
         ecomponent->stateEnd_ = ecomponent->stateBegin_;
@@ -131,9 +152,6 @@ bool SelectionEditOp::Commit()
             if (ecomponent->nodeBegin_ != ecomponent->nodeEnd_)
                 return true;
 
-            if (ecomponent->temporaryBegin_ != ecomponent->temporaryEnd_)
-                return true;
-
             if (!CompareStates(ecomponent->stateBegin_, ecomponent->stateEnd_))
                 return true;
 
@@ -162,7 +180,6 @@ void SelectionEditOp::RegisterEdit()
             ecomponent->component_->Serializable::Save(ecomponent->stateEnd_);
             ecomponent->stateEnd_.Seek(0);
             ecomponent->nodeEnd_ = ecomponent->component_->GetNode();
-            ecomponent->temporaryEnd_ = ecomponent->component_->IsTemporary();
         }
 
     }
@@ -255,14 +272,12 @@ bool SelectionEditOp::Undo()
 
             ecomponent->stateBegin_.Seek(0);
 
-            if (component->GetNode() != ecomponent->nodeBegin_ || component->IsTemporary() != ecomponent->temporaryBegin_)
+            if (component->GetNode() != ecomponent->nodeBegin_)
             {
                 component->Remove();
 
                 bool add = ecomponent->nodeBegin_.NotNull();
 
-                component->SetTemporary(ecomponent->temporaryBegin_);
-
                 VariantMap caData;
                 caData[SceneEditComponentAddedRemoved::P_SCENE] = scene_;
                 caData[SceneEditComponentAddedRemoved::P_COMPONENT] = component;
@@ -374,14 +389,12 @@ bool SelectionEditOp::Redo()
                 component->SendEvent(E_SCENEEDITSTATECHANGE, eventData);
             }
 
-            if (component->GetNode() != ecomponent->nodeEnd_ || component->IsTemporary() != ecomponent->temporaryEnd_)
+            if (component->GetNode() != ecomponent->nodeEnd_)
             {
                 component->Remove();
 
                 bool add = ecomponent->nodeEnd_.NotNull();
 
-                component->SetTemporary(ecomponent->temporaryEnd_);
-
                 VariantMap caData;
                 caData[SceneEditComponentAddedRemoved::P_SCENE] = scene_;
                 caData[SceneEditComponentAddedRemoved::P_COMPONENT] = component;

+ 3 - 2
Source/AtomicEditor/Editors/SceneEditor3D/SceneEditOp.h

@@ -75,6 +75,9 @@ public:
     void NodeAdded(Node* node, Node* parent);
     void NodeRemoved(Node* node, Node* parent);
 
+    // Erases a node from the edit op, return true if no other nodes in the operation
+    bool EraseNode(Node *node);
+
     bool Commit();
 
 private:
@@ -86,8 +89,6 @@ private:
         SharedPtr<Node> nodeEnd_;
         VectorBuffer stateBegin_;
         VectorBuffer stateEnd_;
-        bool temporaryBegin_;
-        bool temporaryEnd_;
     };
 
     struct EditNode

+ 1 - 0
Source/AtomicEditor/Editors/SceneEditor3D/SceneEditor3D.h

@@ -53,6 +53,7 @@ public:
     bool OnEvent(const TBWidgetEvent &ev);
 
     SceneSelection* GetSelection() { return selection_; }
+    SceneEditHistory* GetEditHistory() { return editHistory_; }
     SceneView3D* GetSceneView3D() { return sceneView_; }
 
     void RegisterNode(Node* node);

+ 15 - 0
Source/AtomicEditor/Editors/SceneEditor3D/SceneEditor3DEvents.h

@@ -105,6 +105,21 @@ EVENT(E_SCENEEDITCOMPONENTADDEDREMOVED, SceneEditComponentAddedRemoved)
 
 }
 
+EVENT(E_SCENEEDITPREFABSAVE, SceneEditPrefabSave)
+{
+    PARAM(P_NODE, Node);                    // Node pointer
+}
+
+EVENT(E_SCENEEDITPREFABREVERT, SceneEditPrefabRevert)
+{
+    PARAM(P_NODE, Node);                    // Node pointer
+}
+
+
+EVENT(E_SCENEEDITPREFABBREAK, SceneEditPrefabBreak)
+{
+    PARAM(P_NODE, Node);                    // Node pointer
+}
 
 EVENT(E_SCENEEDITADDREMOVENODES, SceneEditAddRemoveNodes)
 {

+ 71 - 0
Source/AtomicEditor/Editors/SceneEditor3D/SceneSelection.cpp

@@ -17,10 +17,12 @@
 #include <Atomic/Scene/SceneEvents.h>
 #include <Atomic/Scene/Node.h>
 #include <Atomic/Scene/Scene.h>
+#include <Atomic/Scene/PrefabComponent.h>
 
 #include "SceneEditor3D.h"
 #include "SceneEditor3DEvents.h"
 #include "SceneSelection.h"
+#include "SceneEditHistory.h"
 
 namespace AtomicEditor
 {
@@ -32,6 +34,10 @@ SceneSelection::SceneSelection(Context* context, SceneEditor3D *sceneEditor) : O
 
     SubscribeToEvent(E_POSTRENDERUPDATE, HANDLER(SceneSelection, HandlePostRenderUpdate));
     SubscribeToEvent(scene_, E_NODEREMOVED, HANDLER(SceneSelection, HandleNodeRemoved));
+
+    SubscribeToEvent(scene_, E_SCENEEDITPREFABSAVE, HANDLER(SceneSelection, HandleSceneEditPrefabSave));
+    SubscribeToEvent(scene_, E_SCENEEDITPREFABREVERT, HANDLER(SceneSelection, HandleSceneEditPrefabRevert));
+    SubscribeToEvent(scene_, E_SCENEEDITPREFABBREAK, HANDLER(SceneSelection, HandleSceneEditPrefabBreak));
 }
 
 SceneSelection::~SceneSelection()
@@ -308,5 +314,70 @@ void SceneSelection::HandlePostRenderUpdate(StringHash eventType, VariantMap& ev
 
 }
 
+void SceneSelection::HandleSceneEditPrefabSave(StringHash eventType, VariantMap& eventData)
+{
+
+    Node* node = static_cast<Node*> ( eventData[SceneEditPrefabSave::P_NODE].GetPtr());
+
+    PrefabComponent* prefab = node->GetComponent<PrefabComponent>();
+    if (!prefab)
+    {
+        LOGERRORF("Prefab Save: Unable to get prefab component for node: %s", node->GetName().CString());
+        return;
+    }
+
+    prefab->SavePrefab();
+
+    AddNode(node, true);
+}
+
+void SceneSelection::HandleSceneEditPrefabRevert(StringHash eventType, VariantMap& eventData)
+{
+    Node* node = static_cast<Node*> ( eventData[SceneEditPrefabRevert::P_NODE].GetPtr());
+
+    PrefabComponent* prefab = node->GetComponent<PrefabComponent>();
+    if (!prefab)
+    {
+        LOGERRORF("Prefab Revert: Unable to get prefab component for node: %s", node->GetName().CString());
+        return;
+    }
+
+    prefab->UndoPrefab();
+
+    AddNode(node, true);
+}
+
+void SceneSelection::HandleSceneEditPrefabBreak(StringHash eventType, VariantMap& eventData)
+{
+    Node* node = static_cast<Node*> ( eventData[SceneEditPrefabBreak::P_NODE].GetPtr());
+
+    PrefabComponent* prefab = node->GetComponent<PrefabComponent>();
+    if (!prefab)
+    {
+        LOGERRORF("Prefab Break: Unable to get prefab component for node: %s", node->GetName().CString());
+        return;
+    }
+
+    Clear();
+
+    prefab->BreakPrefab();
+
+    PODVector<Node*> nodes;
+    node->GetChildren(nodes, true);
+    nodes.Insert(0, node);
+
+    SceneEditHistory* editHistory = sceneEditor3D_->GetEditHistory();
+
+    for (unsigned i = 0; i < nodes.Size(); i++)
+    {
+        editHistory->RemoveNode(nodes[i]);
+    }
+
+    AddNode(node, true);
+
+    scene_->SendEvent(E_SCENEEDITSCENEMODIFIED);
+
+}
+
 
 }

+ 4 - 0
Source/AtomicEditor/Editors/SceneEditor3D/SceneSelection.h

@@ -57,6 +57,10 @@ private:
     void HandlePostRenderUpdate(StringHash eventType, VariantMap& eventData);
     void HandleNodeRemoved(StringHash eventType, VariantMap& eventData);
 
+    void HandleSceneEditPrefabSave(StringHash eventType, VariantMap& eventData);
+    void HandleSceneEditPrefabRevert(StringHash eventType, VariantMap& eventData);
+    void HandleSceneEditPrefabBreak(StringHash eventType, VariantMap& eventData);
+
     WeakPtr<SceneEditor3D> sceneEditor3D_;
     WeakPtr<Scene> scene_;