Przeglądaj źródła

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 lat temu
rodzic
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)
 UIElement@ SetValue(LineEdit@ element, const String&in value, bool sameValue)
 {
 {
-    element.text = sameValue ? value : "---";
+    element.text = sameValue ? value : STRIKED_OUT;
     element.cursorPosition = 0;
     element.cursorPosition = 0;
     return element;
     return element;
 }
 }

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

@@ -3,12 +3,15 @@
 
 
 Window@ nodeWindow;
 Window@ nodeWindow;
 UIElement@ componentParentContainer;
 UIElement@ componentParentContainer;
+XMLFile@ componentXMLResource;
 
 
 bool applyMaterialList = true;
 bool applyMaterialList = true;
 
 
+const String STRIKED_OUT = "---";
+
 void AddComponentContainer()
 void AddComponentContainer()
 {
 {
-    componentParentContainer.LoadXML(cache.GetResource("XMLFile", "UI/EditorComponent.xml"), uiStyle);
+    componentParentContainer.LoadXML(componentXMLResource, uiStyle);
 }
 }
 
 
 void DeleteAllComponentContainers()
 void DeleteAllComponentContainers()
@@ -30,6 +33,7 @@ void CreateNodeWindow()
     InitVectorStructs();
     InitVectorStructs();
 
 
     nodeWindow = ui.LoadLayout(cache.GetResource("XMLFile", "UI/EditorNodeWindow.xml"), uiStyle);
     nodeWindow = ui.LoadLayout(cache.GetResource("XMLFile", "UI/EditorNodeWindow.xml"), uiStyle);
+    componentXMLResource = cache.GetResource("XMLFile", "UI/EditorComponent.xml");
     componentParentContainer = nodeWindow.GetChild("ComponentParentContainer", true);
     componentParentContainer = nodeWindow.GetChild("ComponentParentContainer", true);
     AddComponentContainer();
     AddComponentContainer();
     ui.root.AddChild(nodeWindow);
     ui.root.AddChild(nodeWindow);
@@ -56,41 +60,50 @@ void ShowNodeWindow()
     nodeWindow.BringToFront();
     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()
 void UpdateNodeWindow()
 {
 {
     // If a resource pick was in progress, it cannot be completed now, as component was changed
     // If a resource pick was in progress, it cannot be completed now, as component was changed
     PickResourceCanceled();
     PickResourceCanceled();
 
 
     Text@ nodeTitle = nodeWindow.GetChild("NodeTitle", true);
     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;
         String idStr;
         if (editNode.id >= FIRST_LOCAL_ID)
         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
         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);
     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)
 void UpdateAttributes(bool fullUpdate)
 {
 {
     if (nodeWindow !is null)
     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)
         if (fullUpdate)
             DeleteAllComponentContainers();
             DeleteAllComponentContainers();
@@ -135,18 +148,18 @@ void UpdateNodeAttributes()
 {
 {
     if (nodeWindow !is null)
     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)
 void PostEditAttribute(Array<Serializable@>@ serializables, uint index)
 {
 {
     // If node name changed, update it in the scene window also
     // 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 a StaticModel/AnimatedModel/Skybox model was changed, apply a possibly different material list
     if (applyMaterialList && serializables[0].attributeInfos[index].name == "Model")
     if (applyMaterialList && serializables[0].attributeInfos[index].name == "Model")
@@ -209,7 +222,7 @@ Array<Serializable@>@ GetAttributeEditorTargets(UIElement@ attrEdit)
 
 
 void CreateNewVariable(StringHash eventType, VariantMap& eventData)
 void CreateNewVariable(StringHash eventType, VariantMap& eventData)
 {
 {
-    if (editNode is null)
+    if (editNodes.length == 0)
         return;
         return;
 
 
     DropDownList@ dropDown = eventData["Element"].GetUIElement();
     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
     // 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);
     UpdateAttributes(overwrite);
 }
 }
 
 
 void DeleteVariable(StringHash eventType, VariantMap& eventData)
 void DeleteVariable(StringHash eventType, VariantMap& eventData)
 {
 {
-    if (editNode is null)
+    if (editNodes.length == 0)
         return;
         return;
 
 
     LineEdit@ nameEdit = nodeWindow.GetChild("VarNameEdit", true);
     LineEdit@ nameEdit = nodeWindow.GetChild("VarNameEdit", true);
@@ -259,6 +276,12 @@ void DeleteVariable(StringHash eventType, VariantMap& eventData)
     if (sanitatedVarName.empty)
     if (sanitatedVarName.empty)
         return;
         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();
     BeginSelectionModify();
     ListView@ list = sceneWindow.GetChild("NodeList", true);
     ListView@ list = sceneWindow.GetChild("NodeList", true);
+    
+    // Clear the selection now to prevent repopulation of selectedNodes and selectedComponents combo
+    list.ClearSelection();
 
 
     // Remove nodes
     // Remove nodes
     for (uint i = 0; i < selectedNodes.length; ++i)
     for (uint i = 0; i < selectedNodes.length; ++i)

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

@@ -529,21 +529,29 @@ void HandleSceneWindowSelectionChange()
         editNode = commonNode;
         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)
     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;
             editComponents = selectedComponents;
+            numEditableComponentsPerNode = selectedComponents.length;
+        }
     }
     }
     
     
     // If just nodes selected, and no components, show as many matching components for editing as possible
     // 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>
 Methods:<br>
 - bool Contains(const String&) const
 - bool Contains(const String&) const
-- void Erase(const String&)
+- bool Erase(const String&)
 - bool Contains(ShortStringHash) const
 - bool Contains(ShortStringHash) const
-- void Erase(ShortStringHash)
+- bool Erase(ShortStringHash)
 - void Clear()
 - void Clear()
 
 
 Properties:<br>
 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));
     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)
 static bool VariantMapContainsHash(ShortStringHash key, VariantMap& map)
@@ -374,9 +374,9 @@ static bool VariantMapContainsHash(ShortStringHash key, VariantMap& map)
     return map.Contains(key);
     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)
 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", "Variant& opIndex(ShortStringHash)", asFUNCTION(VariantMapAtHash), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("VariantMap", "const Variant& opIndex(ShortStringHash) const", 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", "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", "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", "void Clear()", asMETHOD(VariantMap, Clear), asCALL_THISCALL);
     engine->RegisterObjectMethod("VariantMap", "uint get_length() const", asMETHOD(VariantMap, Size), 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);
     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)
 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)
 static void LogWrite(const String& str, bool error, Log* ptr)