Browse Source

Undo actions for component create & remove.
Store undo actions for instantiating builtin or loaded nodes.

Lasse Öörni 12 years ago
parent
commit
9f2c01a1cc

+ 77 - 0
Bin/Data/Scripts/Editor/EditorActions.as

@@ -116,4 +116,81 @@ class ReparentNodeAction : EditAction
         if (parent !is null && node !is null)
             node.parent = parent;
     }
+}
+
+class CreateComponentAction : EditAction
+{
+    uint nodeID;
+    uint componentID;
+    XMLFile@ componentData;
+    
+    void Define(Component@ component)
+    {
+        componentID = component.id;
+        nodeID = component.node.id;
+        componentData = XMLFile();
+        XMLElement rootElem = componentData.CreateRoot("component");
+        component.SaveXML(rootElem);
+    }
+    
+    void Undo()
+    {
+        Node@ node = editorScene.GetNode(nodeID);
+        Component@ component = editorScene.GetComponent(componentID);
+        if (node !is null && component !is null)
+        {
+            ClearSceneSelection();
+            node.RemoveComponent(component);
+        }
+    }
+    
+    void Redo()
+    {
+        Node@ node = editorScene.GetNode(nodeID);
+        if (node !is null)
+        {
+            Component@ component = node.CreateComponent(componentData.root.GetAttribute("type"), componentID < FIRST_LOCAL_ID ? REPLICATED : LOCAL, componentID);
+            component.LoadXML(componentData.root);
+            component.ApplyAttributes();
+        }
+    }
+
+}
+
+class DeleteComponentAction : EditAction
+{
+    uint nodeID;
+    uint componentID;
+    XMLFile@ componentData;
+    
+    void Define(Component@ component)
+    {
+        componentID = component.id;
+        nodeID = component.node.id;
+        componentData = XMLFile();
+        XMLElement rootElem = componentData.CreateRoot("component");
+        component.SaveXML(rootElem);
+    }
+
+    void Undo()
+    {
+        Node@ node = editorScene.GetNode(nodeID);
+        if (node !is null)
+        {
+            Component@ component = node.CreateComponent(componentData.root.GetAttribute("type"), componentID < FIRST_LOCAL_ID ? REPLICATED : LOCAL, componentID);
+            component.LoadXML(componentData.root);
+            component.ApplyAttributes();
+        }
+    }
+    
+    void Redo()
+    {
+        Node@ node = editorScene.GetNode(nodeID);
+        Component@ component = editorScene.GetComponent(componentID);
+        if (node !is null && component !is null)
+        {
+            ClearSceneSelection();
+            node.RemoveComponent(component);
+        }
+    }
 }

+ 13 - 1
Bin/Data/Scripts/Editor/EditorScene.as

@@ -225,6 +225,11 @@ void LoadNode(const String&in fileName)
 
     if (newNode !is null)
     {
+        // Create an undo action for the load
+        CreateNodeAction action;
+        action.Define(newNode);
+        SaveEditAction(action);
+
         FocusNode(newNode);
         instantiateFileName = fileName;
     }
@@ -337,6 +342,11 @@ bool SceneDelete()
             component.typeName == "DebugRenderer"))
             continue;
 
+        // Create undo action
+        DeleteComponentAction action;
+        action.Define(component);
+        group.actions.Push(action);
+
         uint id = node.id;
         node.RemoveComponent(component);
         SetSceneModified();
@@ -599,7 +609,8 @@ bool SceneUndo()
     if (undoStackPos > 0)
     {
         --undoStackPos;
-        for (uint i = 0; i < undoStack[undoStackPos].actions.length; ++i)
+        // Undo commands in reverse order
+        for (int i = int(undoStack[undoStackPos].actions.length - 1); i >= 0; --i)
             undoStack[undoStackPos].actions[i].Undo();
     }
 
@@ -610,6 +621,7 @@ bool SceneRedo()
 {
     if (undoStackPos < undoStack.length)
     {
+        // Redo commands in same order as stored
         for (uint i = 0; i < undoStack[undoStackPos].actions.length; ++i)
             undoStack[undoStackPos].actions[i].Redo();
         ++undoStackPos;

+ 9 - 1
Bin/Data/Scripts/Editor/EditorSceneWindow.as

@@ -741,6 +741,11 @@ void HandleCreateComponent(StringHash eventType, VariantMap& eventData)
         // Some components such as CollisionShape do not create their internal object before the first call to ApplyAttributes()
         // to prevent unnecessary initialization with default values. Call now
         newComponent.ApplyAttributes();
+        
+        CreateComponentAction action;
+        action.Define(newComponent);
+        SaveEditAction(action);
+        
         FocusComponent(newComponent);
     }
 
@@ -756,7 +761,10 @@ void CreateBuiltinObject(const String& name)
     StaticModel@ object = newNode.CreateComponent("StaticModel");
     object.model = cache.GetResource("Model", "Models/" + name + ".mdl");
 
-    SetSceneModified();
+    // Create an undo action for the create
+    CreateNodeAction action;
+    action.Define(newNode);
+    SaveEditAction(action);
 
     FocusNode(newNode);
 }