Browse Source

Added ability to edit attributes of multiple selected nodes, only mutual attribute values are editable. Modify script API for VariantMap's Erase() method to return bool. Fixed one of the Print() function in IOAPI to use the 'error' parameter.

Wei Tjong Yao 12 years ago
parent
commit
14c06b3dc5

+ 1 - 1
Bin/Data/Scripts/Editor/AttributeEditor.as

@@ -34,7 +34,7 @@ UIElement@ SetEditable(UIElement@ element, bool editable)
 
 UIElement@ SetValue(LineEdit@ element, const String&in value, bool sameValue)
 {
-    element.text = sameValue ? value : "---";
+    element.text = sameValue ? value : STRIKED_OUT;
     element.cursorPosition = 0;
     return element;
 }

+ 53 - 30
Bin/Data/Scripts/Editor/EditorNodeWindow.as

@@ -3,12 +3,15 @@
 
 Window@ nodeWindow;
 UIElement@ componentParentContainer;
+XMLFile@ componentXMLResource;
 
 bool applyMaterialList = true;
 
+const String STRIKED_OUT = "---";
+
 void AddComponentContainer()
 {
-    componentParentContainer.LoadXML(cache.GetResource("XMLFile", "UI/EditorComponent.xml"), uiStyle);
+    componentParentContainer.LoadXML(componentXMLResource, uiStyle);
 }
 
 void DeleteAllComponentContainers()
@@ -30,6 +33,7 @@ void CreateNodeWindow()
     InitVectorStructs();
 
     nodeWindow = ui.LoadLayout(cache.GetResource("XMLFile", "UI/EditorNodeWindow.xml"), uiStyle);
+    componentXMLResource = cache.GetResource("XMLFile", "UI/EditorComponent.xml");
     componentParentContainer = nodeWindow.GetChild("ComponentParentContainer", true);
     AddComponentContainer();
     ui.root.AddChild(nodeWindow);
@@ -56,41 +60,50 @@ void ShowNodeWindow()
     nodeWindow.BringToFront();
 }
 
+void AppendID(String&inout localIds, String&inout ids, Node@ node)
+{
+    if (node.id >= FIRST_LOCAL_ID)
+        localIds += " " + String(node.id - FIRST_LOCAL_ID);
+    else
+        ids += " " + String(node.id);
+}
+
 void UpdateNodeWindow()
 {
     // If a resource pick was in progress, it cannot be completed now, as component was changed
     PickResourceCanceled();
 
     Text@ nodeTitle = nodeWindow.GetChild("NodeTitle", true);
-
-    if (editNode is null)
-    {
-        if (selectedNodes.length <= 1)
-            nodeTitle.text = "No node";
-        else
-            nodeTitle.text = selectedNodes.length + " nodes";
-    }
-    else
+    if (editNodes.length == 0)
+        nodeTitle.text = "No node";
+    else if (editNode !is null)
     {
         String idStr;
         if (editNode.id >= FIRST_LOCAL_ID)
-            idStr = "Local ID " + String(editNode.id - FIRST_LOCAL_ID);
+            idStr = " Local ID " + String(editNode.id - FIRST_LOCAL_ID);
         else
-            idStr = "ID " + String(editNode.id);
-        nodeTitle.text = editNode.typeName + " (" + idStr + ")";
+            idStr = " ID " + String(editNode.id);
+        nodeTitle.text = editNode.typeName + idStr;
     }
+    else
+        nodeTitle.text = editNodes[0].typeName + " ID " + STRIKED_OUT + " (" + editNodes.length + "x)";
 
     UpdateAttributes(true);
 }
 
+Array<Serializable@> ToSerializableArray(Array<Node@> nodes)
+{
+    Array<Serializable@> serializables;
+    for (uint i = 0; i < nodes.length; ++i)
+        serializables.Push(nodes[i]);
+    return serializables;
+}
+
 void UpdateAttributes(bool fullUpdate)
 {
     if (nodeWindow !is null)
     {
-        Array<Serializable@> nodes;
-        if (editNode !is null)
-            nodes.Push(editNode);
-        UpdateAttributes(nodes, nodeWindow.GetChild("NodeAttributeList", true), fullUpdate);
+        UpdateAttributes(ToSerializableArray(editNodes), nodeWindow.GetChild("NodeAttributeList", true), fullUpdate);
 
         if (fullUpdate)
             DeleteAllComponentContainers();
@@ -135,18 +148,18 @@ void UpdateNodeAttributes()
 {
     if (nodeWindow !is null)
     {
-        Array<Serializable@> nodes;
-        if (editNode !is null)
-            nodes.Push(editNode);
-        UpdateAttributes(nodes, nodeWindow.GetChild("NodeAttributeList", true), false);
+        UpdateAttributes(ToSerializableArray(editNodes), nodeWindow.GetChild("NodeAttributeList", true), false);
     }
 }
 
 void PostEditAttribute(Array<Serializable@>@ serializables, uint index)
 {
     // If node name changed, update it in the scene window also
-    if (serializables[0] is editNode && serializables[0].attributeInfos[index].name == "Name")
-        UpdateSceneWindowNodeOnly(editNode);
+    if (serializables[0].attributeInfos[index].name == "Name")
+    {
+        for (uint i = 0; i < serializables.length; ++i)
+            UpdateSceneWindowNodeOnly(serializables[i]);
+    }
 
     // If a StaticModel/AnimatedModel/Skybox model was changed, apply a possibly different material list
     if (applyMaterialList && serializables[0].attributeInfos[index].name == "Model")
@@ -209,7 +222,7 @@ Array<Serializable@>@ GetAttributeEditorTargets(UIElement@ attrEdit)
 
 void CreateNewVariable(StringHash eventType, VariantMap& eventData)
 {
-    if (editNode is null)
+    if (editNodes.length == 0)
         return;
 
     DropDownList@ dropDown = eventData["Element"].GetUIElement();
@@ -244,14 +257,18 @@ void CreateNewVariable(StringHash eventType, VariantMap& eventData)
     }
 
     // If we overwrite an existing variable, must recreate the editor(s) for the correct type
-    bool overwrite = editNode.vars.Contains(sanitatedVarName);
-    editNode.vars[sanitatedVarName] = newValue;
+    bool overwrite = false;
+    for (uint i = 0; i < editNodes.length; ++i)
+    {
+        overwrite = overwrite || editNodes[i].vars.Contains(sanitatedVarName);
+        editNodes[i].vars[sanitatedVarName] = newValue;
+    }
     UpdateAttributes(overwrite);
 }
 
 void DeleteVariable(StringHash eventType, VariantMap& eventData)
 {
-    if (editNode is null)
+    if (editNodes.length == 0)
         return;
 
     LineEdit@ nameEdit = nodeWindow.GetChild("VarNameEdit", true);
@@ -259,6 +276,12 @@ void DeleteVariable(StringHash eventType, VariantMap& eventData)
     if (sanitatedVarName.empty)
         return;
 
-    editNode.vars.Erase(sanitatedVarName);
-    UpdateAttributes(false);
-}
+    bool erased = false;
+    for (uint i = 0; i < editNodes.length; ++i)
+    {
+        // \todo Should first check whether var in question is editable
+        erased = editNodes[i].vars.Erase(sanitatedVarName) || erased;
+    }
+    if (erased)
+        UpdateAttributes(false);
+}

+ 3 - 0
Bin/Data/Scripts/Editor/EditorScene.as

@@ -344,6 +344,9 @@ bool SceneDelete()
 
     BeginSelectionModify();
     ListView@ list = sceneWindow.GetChild("NodeList", true);
+    
+    // Clear the selection now to prevent repopulation of selectedNodes and selectedComponents combo
+    list.ClearSelection();
 
     // Remove nodes
     for (uint i = 0; i < selectedNodes.length; ++i)

+ 16 - 8
Bin/Data/Scripts/Editor/EditorSceneWindow.as

@@ -529,21 +529,29 @@ void HandleSceneWindowSelectionChange()
         editNode = commonNode;
     }
     
-    // Now check if the component(s) can be edited. If many selected, must have same type
+    // Now check if the component(s) can be edited. If many selected, must have same type or have same edit node
     if (!selectedComponents.empty)
     {
-        ShortStringHash compType = selectedComponents[0].type;
-        bool sameType = true;
-        for (uint i = 1; i < selectedComponents.length; ++i)
+        if (editNode is null)
         {
-            if (selectedComponents[i].type != compType)
+            ShortStringHash compType = selectedComponents[0].type;
+            bool sameType = true;
+            for (uint i = 1; i < selectedComponents.length; ++i)
             {
-                sameType = false;
-                break;
+                if (selectedComponents[i].type != compType)
+                {
+                    sameType = false;
+                    break;
+                }
             }
+            if (sameType)
+                editComponents = selectedComponents;
         }
-        if (sameType)
+        else
+        {
             editComponents = selectedComponents;
+            numEditableComponentsPerNode = selectedComponents.length;
+        }
     }
     
     // If just nodes selected, and no components, show as many matching components for editing as possible

+ 2 - 2
Docs/ScriptAPI.dox

@@ -751,9 +751,9 @@ VariantMap
 
 Methods:<br>
 - bool Contains(const String&) const
-- void Erase(const String&)
+- bool Erase(const String&)
 - bool Contains(ShortStringHash) const
-- void Erase(ShortStringHash)
+- bool Erase(ShortStringHash)
 - void Clear()
 
 Properties:<br>

+ 6 - 6
Engine/Engine/CoreAPI.cpp

@@ -364,9 +364,9 @@ static bool VariantMapContains(const String& key, VariantMap& map)
     return map.Contains(ShortStringHash(key));
 }
 
-static void VariantMapErase(const String& key, VariantMap& map)
+static bool VariantMapErase(const String& key, VariantMap& map)
 {
-    map.Erase(ShortStringHash(key));
+    return map.Erase(ShortStringHash(key));
 }
 
 static bool VariantMapContainsHash(ShortStringHash key, VariantMap& map)
@@ -374,9 +374,9 @@ static bool VariantMapContainsHash(ShortStringHash key, VariantMap& map)
     return map.Contains(key);
 }
 
-static void VariantMapEraseHash(ShortStringHash key, VariantMap& map)
+static bool VariantMapEraseHash(ShortStringHash key, VariantMap& map)
 {
-    map.Erase(key);
+    return map.Erase(key);
 }
 
 static CScriptArray* VariantMapGetKeys(const VariantMap& map)
@@ -530,9 +530,9 @@ static void RegisterVariant(asIScriptEngine* engine)
     engine->RegisterObjectMethod("VariantMap", "Variant& opIndex(ShortStringHash)", asFUNCTION(VariantMapAtHash), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("VariantMap", "const Variant& opIndex(ShortStringHash) const", asFUNCTION(VariantMapAtHash), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("VariantMap", "bool Contains(const String&in) const", asFUNCTION(VariantMapContains), asCALL_CDECL_OBJLAST);
-    engine->RegisterObjectMethod("VariantMap", "void Erase(const String&in)", asFUNCTION(VariantMapErase), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("VariantMap", "bool Erase(const String&in)", asFUNCTION(VariantMapErase), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("VariantMap", "bool Contains(ShortStringHash) const", asFUNCTION(VariantMapContainsHash), asCALL_CDECL_OBJLAST);
-    engine->RegisterObjectMethod("VariantMap", "void Erase(ShortStringHash)", asFUNCTION(VariantMapEraseHash), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("VariantMap", "bool Erase(ShortStringHash)", asFUNCTION(VariantMapEraseHash), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("VariantMap", "void Clear()", asMETHOD(VariantMap, Clear), asCALL_THISCALL);
     engine->RegisterObjectMethod("VariantMap", "uint get_length() const", asMETHOD(VariantMap, Size), asCALL_THISCALL);
     engine->RegisterObjectMethod("VariantMap", "Array<ShortStringHash>@ get_keys() const", asFUNCTION(VariantMapGetKeys), asCALL_CDECL_OBJLAST);

+ 1 - 1
Engine/Engine/IOAPI.cpp

@@ -68,7 +68,7 @@ static void Print(float value, bool error)
 
 static void Print(bool value, bool error)
 {
-    Log::WriteRaw(String(value) + "\n");
+    Log::WriteRaw(String(value) + "\n", error);
 }
 
 static void LogWrite(const String& str, bool error, Log* ptr)