Ver Fonte

Multi-copy & paste in the editor.

Lasse Öörni há 14 anos atrás
pai
commit
061e68d0d1
1 ficheiros alterados com 80 adições e 60 exclusões
  1. 80 60
      Bin/Data/Scripts/Editor/EditorSceneWindow.as

+ 80 - 60
Bin/Data/Scripts/Editor/EditorSceneWindow.as

@@ -6,7 +6,7 @@ const int ITEM_COMPONENT = 2;
 const uint NO_ITEM = 0xffffffff;
 
 Window@ sceneWindow;
-XMLFile copyBuffer;
+Array<XMLFile@> copyBuffer;
 bool copyBufferLocal = false;
 bool copyBufferExpanded = false;
 
@@ -113,7 +113,7 @@ void UpdateSceneWindow()
     UpdateSceneWindowNode(0, editorScene);
 
     // Clear copybuffer when whole window refreshed
-    copyBuffer.CreateRoot("none");
+    copyBuffer.Clear();
 }
 
 uint UpdateSceneWindowNode(uint itemIndex, Node@ node)
@@ -841,90 +841,110 @@ bool SceneCut()
 
 bool SceneCopy()
 {
-    /// \todo allow multi-copy
-    if (editNode is null || !CheckSceneWindowFocus())
+    if ((selectedNodes.empty && selectedComponents.empty) || !CheckSceneWindowFocus())
+        return false;
+
+    // Must have either only components, or only nodes
+    if (!selectedNodes.empty && !selectedComponents.empty)
         return false;
-    Component@ editComponent = editComponents.length == 1 ? editComponents[0] : null;
 
     ListView@ list = sceneWindow.GetChild("NodeList", true);
+    copyBuffer.Clear();
 
-    // Copy component
-    if (editNode !is null && editComponent !is null)
+    // Copy components
+    if (!selectedComponents.empty)
     {
-        XMLElement rootElem = copyBuffer.CreateRoot("component");
-        editComponent.SaveXML(rootElem);
-        // Note: component type has to be saved manually
-        rootElem.SetString("type", editComponent.typeName);
-        copyBufferLocal = editComponent.id >= FIRST_LOCAL_ID;
+        for (uint i = 0; i < selectedComponents.length; ++i)
+        {
+            XMLFile@ xml = XMLFile();
+            XMLElement rootElem = xml.CreateRoot("component");
+            selectedComponents[i].SaveXML(rootElem);
+            // Note: component type has to be saved manually
+            rootElem.SetString("type", selectedComponents[i].typeName);
+            rootElem.SetBool("local", selectedComponents[i].id >= FIRST_LOCAL_ID);
+            copyBuffer.Push(xml);
+        }
         return true;
     }
     // Copy node. The root node can not be copied
-    else if (editNode !is null && editComponent is null && editNode !is editorScene)
+    else
     {
-        XMLElement rootElem = copyBuffer.CreateRoot("node");
-        editNode.SaveXML(rootElem);
-        copyBufferLocal = editNode.id >= FIRST_LOCAL_ID;
-        copyBufferExpanded = SaveExpandedStatus(GetNodeListIndex(editNode));
+        for (uint i = 0; i < selectedNodes.length; ++i)
+        {
+            if (selectedNodes[i] is editorScene)
+                return false;
+        }
+
+        for (uint i = 0; i < selectedNodes.length; ++i)
+        {
+            XMLFile@ xml = XMLFile();
+            XMLElement rootElem = xml.CreateRoot("node");
+            selectedNodes[i].SaveXML(rootElem);
+            rootElem.SetBool("local", selectedNodes[i].id >= FIRST_LOCAL_ID);
+            copyBuffer.Push(xml);
+        }
+
+        copyBufferExpanded = SaveExpandedStatus(GetNodeListIndex(selectedNodes[0]));
         return true;
     }
-    
-    return false;
 }
 
 bool ScenePaste()
 {
-    /// \todo allow multi-paste
-    if (editNode is null || !CheckSceneWindowFocus())
+    if (editNode is null || !CheckSceneWindowFocus() || copyBuffer.empty)
         return false;
 
     ListView@ list = sceneWindow.GetChild("NodeList", true);
-    XMLElement rootElem = copyBuffer.root;
-    String mode = rootElem.name;
+    bool pasteComponents = false;
 
-    if (mode == "component")
+    for (uint i = 0; i < copyBuffer.length; ++i)
     {
-        BeginModify(editNode.id);
+        XMLElement rootElem = copyBuffer[i].root;
+        String mode = rootElem.name;
+        if (mode == "component")
+        {
+            pasteComponents = true;
 
-        // If this is the root node, do not allow to create duplicate scene-global components
-        if (editNode is editorScene && CheckForExistingGlobalComponent(editNode, rootElem.GetAttribute("type")))
-            return false;
+            // If this is the root node, do not allow to create duplicate scene-global components
+            if (editNode is editorScene && CheckForExistingGlobalComponent(editNode, rootElem.GetAttribute("type")))
+                return false;
 
-        // If copied component was local, make the new local too
-        Component@ newComponent = editNode.CreateComponent(rootElem.GetAttribute("type"), copyBufferLocal ? LOCAL :
-            REPLICATED);
-        if (newComponent is null)
-        {
+            BeginModify(editNode.id);
+
+            // If copied component was local, make the new local too
+            Component@ newComponent = editNode.CreateComponent(rootElem.GetAttribute("type"), rootElem.GetBool("local") ? LOCAL :
+                REPLICATED);
+            if (newComponent is null)
+            {
+                EndModify(editNode.id);
+                return false;
+            }
+            newComponent.LoadXML(rootElem);
+            newComponent.ApplyAttributes();
             EndModify(editNode.id);
-            return false;
         }
-        newComponent.LoadXML(rootElem);
-        newComponent.ApplyAttributes();
-        EndModify(editNode.id);
+        else if (mode == "node")
+        {
+            // Make the paste go always to the root node, no matter of the selected node
+            BeginModify(editorScene.id);
+            // If copied node was local, make the new local too
+            Node@ newNode = editorScene.CreateChild("", rootElem.GetBool("local") ? LOCAL : REPLICATED);
+            BeginModify(newNode.id);
+            newNode.LoadXML(rootElem);
+            newNode.ApplyAttributes();
+            EndModify(newNode.id);
+            EndModify(editorScene.id);
+
+            uint addIndex = GetParentAddIndex(newNode);
+            UpdateSceneWindowNode(addIndex, newNode);
+            RestoreExpandedStatus(addIndex, copyBufferExpanded);
+        }
+    }
 
+    if (pasteComponents)
         UpdateSceneWindowNode(editNode);
-        list.selection = GetComponentListIndex(newComponent);
-        return true;
-    }
-    else if (mode == "node")
-    {
-        // Make the paste go always to the root node, no matter of the selected node
-        BeginModify(editorScene.id);
-        // If copied node was local, make the new local too
-        Node@ newNode = editorScene.CreateChild("", copyBufferLocal ? LOCAL : REPLICATED);
-        BeginModify(newNode.id);
-        newNode.LoadXML(rootElem);
-        newNode.ApplyAttributes();
-        EndModify(newNode.id);
-        EndModify(editorScene.id);
-
-        uint addIndex = GetParentAddIndex(newNode);
-        UpdateSceneWindowNode(addIndex, newNode);
-        RestoreExpandedStatus(addIndex, copyBufferExpanded);
-        list.selection = addIndex;
-        return true;
-    }
-    
-    return false;
+
+    return true;
 }
 
 bool SaveExpandedStatus(uint itemIndex)