Browse Source

Added functionality to select UI-elements by using cursor (Only enabled elements at this moment). Changed implementation of creating new component so that it also works for multi-edit nodes.

Wei Tjong Yao 12 years ago
parent
commit
1c38290e77

+ 18 - 11
Bin/Data/Scripts/Editor/EditorScene.as

@@ -7,7 +7,8 @@ const int PICK_GEOMETRIES = 0;
 const int PICK_LIGHTS = 1;
 const int PICK_LIGHTS = 1;
 const int PICK_ZONES = 2;
 const int PICK_ZONES = 2;
 const int PICK_RIGIDBODIES = 3;
 const int PICK_RIGIDBODIES = 3;
-const int MAX_PICK_MODES = 4;
+const int PICK_UI_ELEMENTS = 4;
+const int MAX_PICK_MODES = 5;
 const int MAX_UNDOSTACK_SIZE = 256;
 const int MAX_UNDOSTACK_SIZE = 256;
 
 
 Scene@ editorScene;
 Scene@ editorScene;
@@ -212,22 +213,28 @@ void CreateComponent(const String&in componentType)
     if (editNode is editorScene && CheckForExistingGlobalComponent(editNode, componentType))
     if (editNode is editorScene && CheckForExistingGlobalComponent(editNode, componentType))
         return;
         return;
 
 
+    // Group for storing undo actions
+    EditActionGroup group;
+
     // For now, make a local node's all components local
     // For now, make a local node's all components local
     /// \todo Allow to specify the createmode
     /// \todo Allow to specify the createmode
-    Component@ newComponent = editNode.CreateComponent(componentType, editNode.id < FIRST_LOCAL_ID ? REPLICATED : LOCAL);
-    if (newComponent !is null)
+    for (uint i = 0; i < editNodes.length; ++i)
     {
     {
-        // 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);
+        Component@ newComponent = editNodes[i].CreateComponent(componentType, editNodes[i].id < FIRST_LOCAL_ID ? REPLICATED : LOCAL);
+        if (newComponent !is null)
+        {
+            // 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();
 
 
-        FocusComponent(newComponent);
+            CreateComponentAction action;
+            action.Define(newComponent);
+            group.actions.Push(action);
+        }
     }
     }
 
 
+    SaveEditActionGroup(group);
+
     SetSceneModified();
     SetSceneModified();
 }
 }
 
 

+ 81 - 49
Bin/Data/Scripts/Editor/EditorSceneWindow.as

@@ -448,40 +448,37 @@ void SelectNode(Node@ node, bool multiselect)
         return;
         return;
     }
     }
 
 
-    uint nodeItem = GetListIndex(node);
-
-    // Go in the parent chain up to make sure the chain is expanded
-    for (;;)
-    {
-        Node@ parent = node.parent;
-        if (node is editorScene || parent is null)
-            break;
-        node = parent;
-    }
-
+    uint index = GetListIndex(node);
     uint numItems = hierarchyList.numItems;
     uint numItems = hierarchyList.numItems;
-    uint parentItem = GetListIndex(node);
 
 
-    if (nodeItem < numItems)
+    if (index < numItems)
     {
     {
         // Expand the node chain now
         // Expand the node chain now
-        if (!multiselect || !hierarchyList.IsSelected(nodeItem))
+        if (!multiselect || !hierarchyList.IsSelected(index))
         {
         {
-            if (parentItem < numItems)
-                hierarchyList.Expand(parentItem, true);
-            hierarchyList.Expand(nodeItem, true);
+            // Go in the parent chain up to make sure the chain is expanded
+            for (;;)
+            {
+                Node@ parent = node.parent;
+                if (node is editorScene || parent is null)
+                    break;
+                node = parent;
+            }
+            uint parentIndex = GetListIndex(node);
+            if (parentIndex < numItems)
+                hierarchyList.Expand(parentIndex, true);
+            
+            hierarchyList.Expand(index, true);
         }
         }
+        
         // This causes an event to be sent, in response we set the node/component selections, and refresh editors
         // This causes an event to be sent, in response we set the node/component selections, and refresh editors
         if (!multiselect)
         if (!multiselect)
-            hierarchyList.selection = nodeItem;
+            hierarchyList.selection = index;
         else
         else
-            hierarchyList.ToggleSelection(nodeItem);
-    }
-    else
-    {
-        if (!multiselect)
-            hierarchyList.ClearSelection();
+            hierarchyList.ToggleSelection(index);
     }
     }
+    else if (!multiselect)
+        hierarchyList.ClearSelection();
 }
 }
 
 
 void SelectComponent(Component@ component, bool multiselect)
 void SelectComponent(Component@ component, bool multiselect)
@@ -499,47 +496,82 @@ void SelectComponent(Component@ component, bool multiselect)
         return;
         return;
     }
     }
 
 
-    uint nodeItem = GetListIndex(node);
-    uint componentItem = GetComponentListIndex(component);
+    uint nodeIndex = GetListIndex(node);
+    uint componentIndex = GetComponentListIndex(component);
+    uint numItems = hierarchyList.numItems;
 
 
-    // Go in the parent chain up to make sure the chain is expanded
-    for (;;)
+    if (nodeIndex < numItems && componentIndex < numItems)
     {
     {
-        Node@ parent = node.parent;
-        if (node is editorScene || parent is null)
-            break;
-        node = parent;
+        // Expand the node chain now
+        if (!multiselect || !hierarchyList.IsSelected(componentIndex))
+        {
+            // Go in the parent chain up to make sure the chain is expanded
+            for (;;)
+            {
+                Node@ parent = node.parent;
+                if (node is editorScene || parent is null)
+                    break;
+                node = parent;
+            }
+            uint parentNodeIndex = GetListIndex(node);
+            if (parentNodeIndex < numItems)
+                hierarchyList.Expand(parentNodeIndex, true);
+            else if (!multiselect)
+            {
+                hierarchyList.ClearSelection();
+                return;
+            }
+            
+            hierarchyList.Expand(nodeIndex, true);
+        }
+        // This causes an event to be sent, in response we set the node/component selections, and refresh editors
+        if (!multiselect)
+            hierarchyList.selection = componentIndex;
+        else
+            hierarchyList.ToggleSelection(componentIndex);
     }
     }
+    else if (!multiselect)
+        hierarchyList.ClearSelection();
+}
 
 
-    uint numItems = hierarchyList.numItems;
-    uint parentItem = GetListIndex(node);
-
-    if (parentItem >= hierarchyList.numItems && !multiselect)
+void SelectUIElement(UIElement@ element, bool multiselect)
+{
+    if (element is null && !multiselect)
     {
     {
         hierarchyList.ClearSelection();
         hierarchyList.ClearSelection();
         return;
         return;
     }
     }
 
 
-    if (nodeItem < numItems && componentItem < numItems)
+    uint index = GetListIndex(element);
+    uint numItems = hierarchyList.numItems;
+
+    if (index < numItems)
     {
     {
         // Expand the node chain now
         // Expand the node chain now
-        if (!multiselect || !hierarchyList.IsSelected(componentItem))
+        if (!multiselect || !hierarchyList.IsSelected(index))
         {
         {
-            if (parentItem < numItems)
-                hierarchyList.Expand(parentItem, true);
-            hierarchyList.Expand(nodeItem, true);
+            // Go in the parent chain up to make sure the chain is expanded
+            for (;;)
+            {
+                UIElement@ parent = element.parent;
+                if (element is editorUIElement || parent is null)
+                    break;
+                element = parent;
+            }
+            uint parentIndex = GetListIndex(element);
+            if (parentIndex < numItems)
+                hierarchyList.Expand(parentIndex, true);
+            
+            hierarchyList.Expand(index, true);
         }
         }
-        // This causes an event to be sent, in response we set the node/component selections, and refresh editors
+        
         if (!multiselect)
         if (!multiselect)
-            hierarchyList.selection = componentItem;
+            hierarchyList.selection = index;
         else
         else
-            hierarchyList.ToggleSelection(componentItem);
-    }
-    else
-    {
-        if (!multiselect)
-            hierarchyList.ClearSelection();
+            hierarchyList.ToggleSelection(index);
     }
     }
+    else if (!multiselect)
+        hierarchyList.ClearSelection();
 }
 }
 
 
 void HandleHierarchyListSelectionChange()
 void HandleHierarchyListSelectionChange()

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

@@ -377,7 +377,7 @@ bool PickNode()
 
 
 bool PickComponent()
 bool PickComponent()
 {
 {
-    if (editNode is null)
+    if (editNodes.empty)
         return false;
         return false;
 
 
     Menu@ menu = GetEventSender();
     Menu@ menu = GetEventSender();

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

@@ -55,6 +55,9 @@ bool NewUIElement(const String&in typeName)
         }
         }
         element.style = uiElementDefaultStyle !is null ? uiElementDefaultStyle : uiStyle;
         element.style = uiElementDefaultStyle !is null ? uiElementDefaultStyle : uiStyle;
 
 
+        // Position the newly created element at center
+        CenterDialog(element);
+
         // Create an undo action for the create
         // Create an undo action for the create
         CreateUIElementAction action;
         CreateUIElementAction action;
         action.Define(element);
         action.Define(element);

+ 40 - 11
Bin/Data/Scripts/Editor/EditorView.as

@@ -64,7 +64,8 @@ Array<String> pickModeText = {
     "Geometries",
     "Geometries",
     "Lights",
     "Lights",
     "Zones",
     "Zones",
-    "Rigidbodies"
+    "Rigidbodies",
+    "UI-elements"
 };
 };
 
 
 Array<String> fillModeText = {
 Array<String> fillModeText = {
@@ -382,15 +383,43 @@ void ViewRaycast(bool mouseClick)
     if (ui.modalElement !is null)
     if (ui.modalElement !is null)
         return;
         return;
 
 
-    DebugRenderer@ debug = editorScene.debugRenderer;
+    // Do not raycast / change selection if hovering over the gizmo
+    if (IsGizmoSelected())
+        return;
+
     IntVector2 pos = ui.cursorPosition;
     IntVector2 pos = ui.cursorPosition;
-    Component@ selected;
+    UIElement@ elementAtPos = ui.GetElementAt(pos);
+    if (pickMode == PICK_UI_ELEMENTS)
+    {
+        bool leftClick = mouseClick && input.mouseButtonPress[MOUSEB_LEFT];
+        bool multiselect = input.qualifierDown[QUAL_CTRL];
+
+        if (elementAtPos !is null)
+        {
+            // Only interested in user-created UI elements
+            if (elementAtPos.GetElementEventSender() is editorUIElement)
+            {
+                // \todo Debug draw the UIElement
+                //DebugDrawUIElement();
+
+                if (leftClick)
+                    SelectUIElement(elementAtPos, multiselect);
+            }
+        }
+        else if (leftClick && !multiselect)
+            // If clicked on emptiness in non-multiselect mode, clear the selection
+           SelectUIElement(null, false);
 
 
-    // Do not raycast / change selection if hovering over an UI element or the gizmo
-    if (ui.GetElementAt(pos) !is null || IsGizmoSelected())
+        return;
+    }
+
+    // Do not raycast / change selection if hovering over a UI element when not in PICK_UI_ELEMENTS Mode
+    if (elementAtPos !is null)
         return;
         return;
 
 
+    DebugRenderer@ debug = editorScene.debugRenderer;
     Ray cameraRay = camera.GetScreenRay(float(pos.x) / graphics.width, float(pos.y) / graphics.height);
     Ray cameraRay = camera.GetScreenRay(float(pos.x) / graphics.width, float(pos.y) / graphics.height);
+    Component@ selectedComponent;
 
 
     if (pickMode != PICK_RIGIDBODIES)
     if (pickMode != PICK_RIGIDBODIES)
     {
     {
@@ -405,7 +434,7 @@ void ViewRaycast(bool mouseClick)
             // If selecting a terrain patch, select the parent terrain instead
             // If selecting a terrain patch, select the parent terrain instead
             if (drawable.typeName != "TerrainPatch")
             if (drawable.typeName != "TerrainPatch")
             {
             {
-                selected = drawable;
+                selectedComponent = drawable;
                 if (debug !is null)
                 if (debug !is null)
                 {
                 {
                     debug.AddNode(drawable.node, 1.0, false);
                     debug.AddNode(drawable.node, 1.0, false);
@@ -413,7 +442,7 @@ void ViewRaycast(bool mouseClick)
                 }
                 }
             }
             }
             else if (drawable.node.parent !is null)
             else if (drawable.node.parent !is null)
-                selected = drawable.node.parent.GetComponent("Terrain");
+                selectedComponent = drawable.node.parent.GetComponent("Terrain");
         }
         }
     }
     }
     else
     else
@@ -434,28 +463,28 @@ void ViewRaycast(bool mouseClick)
                 debug.AddNode(body.node, 1.0, false);
                 debug.AddNode(body.node, 1.0, false);
                 body.DrawDebugGeometry(debug, false);
                 body.DrawDebugGeometry(debug, false);
             }
             }
-            selected = body;
+            selectedComponent = body;
         }
         }
     }
     }
 
 
     if (mouseClick && input.mouseButtonPress[MOUSEB_LEFT])
     if (mouseClick && input.mouseButtonPress[MOUSEB_LEFT])
     {
     {
         bool multiselect = input.qualifierDown[QUAL_CTRL];
         bool multiselect = input.qualifierDown[QUAL_CTRL];
-        if (selected !is null)
+        if (selectedComponent !is null)
         {
         {
             if (input.qualifierDown[QUAL_SHIFT])
             if (input.qualifierDown[QUAL_SHIFT])
             {
             {
                 // If we are selecting components, but have nodes in existing selection, do not multiselect to prevent confusion
                 // If we are selecting components, but have nodes in existing selection, do not multiselect to prevent confusion
                 if (!selectedNodes.empty)
                 if (!selectedNodes.empty)
                     multiselect = false;
                     multiselect = false;
-                SelectComponent(selected, multiselect);
+                SelectComponent(selectedComponent, multiselect);
             }
             }
             else
             else
             {
             {
                 // If we are selecting nodes, but have components in existing selection, do not multiselect to prevent confusion
                 // If we are selecting nodes, but have components in existing selection, do not multiselect to prevent confusion
                 if (!selectedComponents.empty)
                 if (!selectedComponents.empty)
                     multiselect = false;
                     multiselect = false;
-                SelectNode(selected.node, multiselect);
+                SelectNode(selectedComponent.node, multiselect);
             }
             }
         }
         }
         else
         else

+ 1 - 1
Docs/GettingStarted.dox

@@ -675,7 +675,7 @@ Ctrl+1,2,3      - Object manipulation mode: move/rotate/scale
 Ctrl+4          - Object selection mode, no manipulation
 Ctrl+4          - Object selection mode, no manipulation
 Ctrl+5          - Toggle between world and local axes manipulation
 Ctrl+5          - Toggle between world and local axes manipulation
 Ctrl+6,7        - Cycle through components to pick: geometries, lights, zones,
 Ctrl+6,7        - Cycle through components to pick: geometries, lights, zones,
-                  collision shapes
+                  collision shapes; and ui-elements
 Ctrl+arrows     - Manipulate node in X & Z directions
 Ctrl+arrows     - Manipulate node in X & Z directions
 Ctrl+pgup/pgdn  - Manipulate node in Y direction
 Ctrl+pgup/pgdn  - Manipulate node in Y direction
 Ctrl+plus/minus - Scale node uniformly (scale mode only)
 Ctrl+plus/minus - Scale node uniformly (scale mode only)

+ 1 - 0
Docs/ScriptAPI.dox

@@ -5376,6 +5376,7 @@ Properties:<br>
 - bool enabledEffective (readonly)
 - bool enabledEffective (readonly)
 - uint id (readonly)
 - uint id (readonly)
 - Node@ node (readonly)
 - Node@ node (readonly)
+- uint flags
 
 
 
 
 NavigationMesh
 NavigationMesh