2
0
Эх сурвалжийг харах

Fixed UI subsystem to dismiss the FileSelector correctly when its modal window is being closed via ESC key.

Wei Tjong Yao 12 жил өмнө
parent
commit
2f88f7fc81

+ 0 - 11
Bin/Data/Scripts/Editor/EditorInspectorWindow.as

@@ -12,7 +12,6 @@ const String STRIKED_OUT = "——";   // Two unicode EM DASH (U+2014)
 const ShortStringHash NODE_IDS_VAR("NodeIDs");
 const ShortStringHash NODE_IDS_VAR("NodeIDs");
 const ShortStringHash COMPONENT_IDS_VAR("ComponentIDs");
 const ShortStringHash COMPONENT_IDS_VAR("ComponentIDs");
 const ShortStringHash UI_ELEMENT_IDS_VAR("UIElementIDs");
 const ShortStringHash UI_ELEMENT_IDS_VAR("UIElementIDs");
-const ShortStringHash NO_AUTO_REMOVE("NoAutoRemove");
 const int LABEL_WIDTH = 30;
 const int LABEL_WIDTH = 30;
 
 
 // Constants for accessing xmlResources
 // Constants for accessing xmlResources
@@ -378,23 +377,13 @@ void PostEditAttribute(Array<Serializable@>@ serializables, uint index, const Ar
     SaveEditActionGroup(group);
     SaveEditActionGroup(group);
 
 
     // If a UI-element changing its 'Is Modal' attribute, clear the hierarchy list selection
     // If a UI-element changing its 'Is Modal' attribute, clear the hierarchy list selection
-    bool testModalElement = false;
     int itemType = GetType(serializables[0]);
     int itemType = GetType(serializables[0]);
     if (itemType == ITEM_UI_ELEMENT && serializables[0].attributeInfos[index].name == "Is Modal")
     if (itemType == ITEM_UI_ELEMENT && serializables[0].attributeInfos[index].name == "Is Modal")
-    {
         hierarchyList.ClearSelection();
         hierarchyList.ClearSelection();
-        testModalElement = true;
-    }
 
 
     for (uint i = 0; i < serializables.length; ++i)
     for (uint i = 0; i < serializables.length; ++i)
     {
     {
         PostEditAttribute(serializables[i], index);
         PostEditAttribute(serializables[i], index);
-
-        // Set a user-defined var to prevent auto-removal of the modal element being tested in the editor
-        // After losing the modal flag, the modal element should be reparented to its original parent automatically
-        if (testModalElement)
-            cast<UIElement>(serializables[i]).vars[NO_AUTO_REMOVE] = true;
-
         if (itemType == ITEM_UI_ELEMENT)
         if (itemType == ITEM_UI_ELEMENT)
             SetUIElementModified(serializables[i]);
             SetUIElementModified(serializables[i]);
     }
     }

+ 0 - 1
Bin/Data/UI/DefaultStyle.xml

@@ -196,7 +196,6 @@
         <attribute name="Layout Mode" value="vertical" />
         <attribute name="Layout Mode" value="vertical" />
         <attribute name="Layout Spacing" value="4" />
         <attribute name="Layout Spacing" value="4" />
         <attribute name="Layout Border" value="6 6 6 6" />
         <attribute name="Layout Border" value="6 6 6 6" />
-        <attribute name="Is Modal" value="true" />
         <attribute name="Modal Shade Color" value="0.45 0.70 0.45 0.05" />
         <attribute name="Modal Shade Color" value="0.45 0.70 0.45 0.05" />
         <attribute name="Modal Frame Color" value="0.45 0.70 0.45" />
         <attribute name="Modal Frame Color" value="0.45 0.70 0.45" />
         <attribute name="Modal Frame Size" value="2 2" />
         <attribute name="Modal Frame Size" value="2 2" />

+ 1 - 1
Docs/GettingStarted.dox

@@ -78,7 +78,7 @@ To run from Xcode on iPhone/iPad Simulator, edit the Product Scheme to set "Run"
 
 
 \section Building_64bit Desktop 64bit build
 \section Building_64bit Desktop 64bit build
 
 
-Currently CMake build configuration has been set to compile Urho3D as 32bit by default. To enable 64bit build for Visual Studio, run one of the cmake_vs20xx.bat by passing the option "Win64" explicitly. This will overrides CMake to use a 64bit solution generator.
+Currently CMake build configuration has been set to compile Urho3D as 32bit by default. To enable 64bit build for Visual Studio, run one of the cmake_vs20xx.bat by passing the option "Win64" explicitly. This overrides CMake to use a 64bit solution generator.
 
 
 To enable 64bit build for non-MSVC/non-Windows platform, pass the option "-DENABLE_64BIT=1" explicitly when invoking cmake_eclipse.sh/cmake_macosx.sh/cmake_gcc.sh. Alternatively, you can modify the main CMakeLists.txt to enable 64bit by default for non-MSVC/non-Windows platform.
 To enable 64bit build for non-MSVC/non-Windows platform, pass the option "-DENABLE_64BIT=1" explicitly when invoking cmake_eclipse.sh/cmake_macosx.sh/cmake_gcc.sh. Alternatively, you can modify the main CMakeLists.txt to enable 64bit by default for non-MSVC/non-Windows platform.
 
 

+ 5 - 1
Engine/UI/FileSelector.cpp

@@ -123,7 +123,7 @@ FileSelector::FileSelector(Context* context) :
     {
     {
         ui->GetRoot()->AddChild(window_);
         ui->GetRoot()->AddChild(window_);
         ui->SetFocusElement(fileList_);
         ui->SetFocusElement(fileList_);
-        window_->BringToFront();
+        window_->SetModal(true);
     }
     }
 
 
     SubscribeToEvent(filterList_, E_ITEMSELECTED, HANDLER(FileSelector, HandleFilterChanged));
     SubscribeToEvent(filterList_, E_ITEMSELECTED, HANDLER(FileSelector, HandleFilterChanged));
@@ -135,6 +135,7 @@ FileSelector::FileSelector(Context* context) :
     SubscribeToEvent(okButton_, E_RELEASED, HANDLER(FileSelector, HandleOKPressed));
     SubscribeToEvent(okButton_, E_RELEASED, HANDLER(FileSelector, HandleOKPressed));
     SubscribeToEvent(cancelButton_, E_RELEASED, HANDLER(FileSelector, HandleCancelPressed));
     SubscribeToEvent(cancelButton_, E_RELEASED, HANDLER(FileSelector, HandleCancelPressed));
     SubscribeToEvent(closeButton_, E_RELEASED, HANDLER(FileSelector, HandleCancelPressed));
     SubscribeToEvent(closeButton_, E_RELEASED, HANDLER(FileSelector, HandleCancelPressed));
+    SubscribeToEvent(window_, E_MODALCHANGED, HANDLER(FileSelector, HandleCancelPressed));
 }
 }
 
 
 FileSelector::~FileSelector()
 FileSelector::~FileSelector()
@@ -496,6 +497,9 @@ void FileSelector::HandleCancelPressed(StringHash eventType, VariantMap& eventDa
     if (ignoreEvents_)
     if (ignoreEvents_)
         return;
         return;
 
 
+    if (eventType == E_MODALCHANGED && eventData[ModalChanged::P_MODAL].GetBool())
+        return;
+
     using namespace FileSelected;
     using namespace FileSelected;
 
 
     VariantMap newEventData;
     VariantMap newEventData;

+ 10 - 17
Engine/UI/UI.cpp

@@ -61,7 +61,6 @@ ShortStringHash VAR_ORIGIN("Origin");
 const ShortStringHash VAR_ORIGINAL_PARENT("OriginalParent");
 const ShortStringHash VAR_ORIGINAL_PARENT("OriginalParent");
 const ShortStringHash VAR_ORIGINAL_CHILD_INDEX("OriginalChildIndex");
 const ShortStringHash VAR_ORIGINAL_CHILD_INDEX("OriginalChildIndex");
 const ShortStringHash VAR_PARENT_CHANGED("ParentChanged");
 const ShortStringHash VAR_PARENT_CHANGED("ParentChanged");
-const ShortStringHash VAR_NO_AUTO_REMOVE("NoAutoRemove");
 
 
 const char* UI_CATEGORY = "UI";
 const char* UI_CATEGORY = "UI";
 
 
@@ -83,10 +82,10 @@ UI::UI(Context* context) :
 {
 {
     rootElement_->SetTraversalMode(TM_DEPTH_FIRST);
     rootElement_->SetTraversalMode(TM_DEPTH_FIRST);
     rootModalElement_->SetTraversalMode(TM_DEPTH_FIRST);
     rootModalElement_->SetTraversalMode(TM_DEPTH_FIRST);
-    
+
     // Register UI library object factories
     // Register UI library object factories
     RegisterUILibrary(context_);
     RegisterUILibrary(context_);
-    
+
     SubscribeToEvent(E_SCREENMODE, HANDLER(UI, HandleScreenMode));
     SubscribeToEvent(E_SCREENMODE, HANDLER(UI, HandleScreenMode));
     SubscribeToEvent(E_MOUSEBUTTONDOWN, HANDLER(UI, HandleMouseButtonDown));
     SubscribeToEvent(E_MOUSEBUTTONDOWN, HANDLER(UI, HandleMouseButtonDown));
     SubscribeToEvent(E_MOUSEBUTTONUP, HANDLER(UI, HandleMouseButtonUp));
     SubscribeToEvent(E_MOUSEBUTTONUP, HANDLER(UI, HandleMouseButtonUp));
@@ -97,7 +96,7 @@ UI::UI(Context* context) :
     SubscribeToEvent(E_TOUCHMOVE, HANDLER(UI, HandleTouchMove));
     SubscribeToEvent(E_TOUCHMOVE, HANDLER(UI, HandleTouchMove));
     SubscribeToEvent(E_KEYDOWN, HANDLER(UI, HandleKeyDown));
     SubscribeToEvent(E_KEYDOWN, HANDLER(UI, HandleKeyDown));
     SubscribeToEvent(E_CHAR, HANDLER(UI, HandleChar));
     SubscribeToEvent(E_CHAR, HANDLER(UI, HandleChar));
-    
+
     // Try to initialize right now, but skip if screen mode is not yet set
     // Try to initialize right now, but skip if screen mode is not yet set
     Initialize();
     Initialize();
 }
 }
@@ -374,17 +373,17 @@ void UI::RenderUpdate()
 void UI::Render()
 void UI::Render()
 {
 {
     PROFILE(RenderUI);
     PROFILE(RenderUI);
-    
+
     SetVertexData(vertexBuffer_, vertexData_);
     SetVertexData(vertexBuffer_, vertexData_);
     SetVertexData(debugVertexBuffer_, debugVertexData_);
     SetVertexData(debugVertexBuffer_, debugVertexData_);
-    
+
     // Render non-modal batches
     // Render non-modal batches
     Render(vertexBuffer_, batches_, 0, nonModalBatchSize_);
     Render(vertexBuffer_, batches_, 0, nonModalBatchSize_);
     // Render debug draw
     // Render debug draw
     Render(debugVertexBuffer_, debugDrawBatches_, 0, debugDrawBatches_.Size());
     Render(debugVertexBuffer_, debugDrawBatches_, 0, debugDrawBatches_.Size());
     // Render modal batches
     // Render modal batches
     Render(vertexBuffer_, batches_, nonModalBatchSize_, batches_.Size());
     Render(vertexBuffer_, batches_, nonModalBatchSize_, batches_.Size());
-    
+
     // Clear the debug draw batches and data
     // Clear the debug draw batches and data
     debugDrawBatches_.Clear();
     debugDrawBatches_.Clear();
     debugVertexData_.Clear();
     debugVertexData_.Clear();
@@ -559,13 +558,13 @@ void UI::SetVertexData(VertexBuffer* dest, const PODVector<float>& vertexData)
 {
 {
     if (vertexData.Empty())
     if (vertexData.Empty())
         return;
         return;
-    
+
     // Update quad geometry into the vertex buffer
     // Update quad geometry into the vertex buffer
     // Resize the vertex buffer first if too small or much too large
     // Resize the vertex buffer first if too small or much too large
     unsigned numVertices = vertexData.Size() / UI_VERTEX_SIZE;
     unsigned numVertices = vertexData.Size() / UI_VERTEX_SIZE;
     if (dest->GetVertexCount() < numVertices || dest->GetVertexCount() > numVertices * 2)
     if (dest->GetVertexCount() < numVertices || dest->GetVertexCount() > numVertices * 2)
         dest->SetSize(numVertices, MASK_POSITION | MASK_COLOR | MASK_TEXCOORD1, true);
         dest->SetSize(numVertices, MASK_POSITION | MASK_COLOR | MASK_TEXCOORD1, true);
-    
+
     dest->SetData(&vertexData[0]);
     dest->SetData(&vertexData[0]);
 }
 }
 
 
@@ -597,7 +596,7 @@ void UI::Render(VertexBuffer* buffer, const PODVector<UIBatch>& batches, unsigne
     graphics_->SetStencilTest(false);
     graphics_->SetStencilTest(false);
     graphics_->ResetRenderTargets();
     graphics_->ResetRenderTargets();
     graphics_->SetVertexBuffer(buffer);
     graphics_->SetVertexBuffer(buffer);
-    
+
     ShaderVariation* ps = 0;
     ShaderVariation* ps = 0;
     ShaderVariation* vs = 0;
     ShaderVariation* vs = 0;
 
 
@@ -1126,16 +1125,10 @@ void UI::HandleKeyDown(StringHash eventType, VariantMap& eventData)
             SetFocusElement(0);
             SetFocusElement(0);
         else
         else
         {
         {
-            // If it is a modal window, by resetting its modal flag and auto-remove it
+            // If it is a modal window, by resetting its modal flag
             Window* window = dynamic_cast<Window*>(element);
             Window* window = dynamic_cast<Window*>(element);
             if (window)
             if (window)
-            {
                 window->SetModal(false);
                 window->SetModal(false);
-                if (window->GetVars().Contains(VAR_NO_AUTO_REMOVE))
-                    const_cast<VariantMap&>(window->GetVars()).Erase(VAR_NO_AUTO_REMOVE);
-                else
-                    window->Remove();
-            }
         }
         }
 
 
         return;
         return;

+ 7 - 7
Engine/UI/UIElement.cpp

@@ -1192,20 +1192,18 @@ void UIElement::InsertChild(unsigned index, UIElement* element)
 
 
 void UIElement::RemoveChild(UIElement* element, unsigned index)
 void UIElement::RemoveChild(UIElement* element, unsigned index)
 {
 {
-    UIElement* root = GetRoot();
-    UIElement* sender = GetElementEventSender();
-
     for (unsigned i = index; i < children_.Size(); ++i)
     for (unsigned i = index; i < children_.Size(); ++i)
     {
     {
         if (children_[i] == element)
         if (children_[i] == element)
         {
         {
             // Send change event if not already being destroyed
             // Send change event if not already being destroyed
-            if (Refs() > 0 && sender)
+            UIElement* sender = Refs() > 0 ? GetElementEventSender() : 0;
+            if (sender)
             {
             {
                 using namespace ElementRemoved;
                 using namespace ElementRemoved;
 
 
                 VariantMap eventData;
                 VariantMap eventData;
-                eventData[P_ROOT] = (void*)root;
+                eventData[P_ROOT] = (void*)GetRoot();
                 eventData[P_PARENT] = (void*)this;
                 eventData[P_PARENT] = (void*)this;
                 eventData[P_ELEMENT] = (void*)element;
                 eventData[P_ELEMENT] = (void*)element;
 
 
@@ -1233,11 +1231,12 @@ void UIElement::RemoveChildAtIndex(unsigned index)
 void UIElement::RemoveAllChildren()
 void UIElement::RemoveAllChildren()
 {
 {
     UIElement* root = GetRoot();
     UIElement* root = GetRoot();
+    UIElement* sender = Refs() > 0 ? GetElementEventSender() : 0;
 
 
     for (Vector<SharedPtr<UIElement> >::Iterator i = children_.Begin(); i < children_.End(); )
     for (Vector<SharedPtr<UIElement> >::Iterator i = children_.Begin(); i < children_.End(); )
     {
     {
         // Send change event if not already being destroyed
         // Send change event if not already being destroyed
-        if (Refs() > 0 && root)
+        if (sender)
         {
         {
             using namespace ElementRemoved;
             using namespace ElementRemoved;
 
 
@@ -1246,12 +1245,13 @@ void UIElement::RemoveAllChildren()
             eventData[P_PARENT] = (void*)this;
             eventData[P_PARENT] = (void*)this;
             eventData[P_ELEMENT] = (void*)(*i).Get();
             eventData[P_ELEMENT] = (void*)(*i).Get();
 
 
-            root->SendEvent(E_ELEMENTREMOVED, eventData);
+            sender->SendEvent(E_ELEMENTREMOVED, eventData);
         }
         }
 
 
         (*i++)->Detach();
         (*i++)->Detach();
     }
     }
     children_.Clear();
     children_.Clear();
+    UpdateLayout();
 }
 }
 
 
 void UIElement::Remove()
 void UIElement::Remove()

+ 9 - 2
Engine/UI/UIEvents.h

@@ -158,6 +158,13 @@ EVENT(E_VIEWCHANGED, ViewChanged)
     PARAM(P_Y, Y);                          // int
     PARAM(P_Y, Y);                          // int
 }
 }
 
 
+/// UI modal changed (currently only Window has modal flag).
+EVENT(E_MODALCHANGED, ModalChanged)
+{
+    PARAM(P_ELEMENT, Element);              // UIElement pointer
+    PARAM(P_MODAL, Modal);                  // bool
+}
+
 /// Editable text changed
 /// Editable text changed
 EVENT(E_TEXTCHANGED, TextChanged)
 EVENT(E_TEXTCHANGED, TextChanged)
 {
 {
@@ -221,7 +228,7 @@ EVENT(E_FILESELECTED, FileSelected)
     PARAM(P_OK, Ok);                        // bool
     PARAM(P_OK, Ok);                        // bool
 }
 }
 
 
-/// A child element has been added to an element. Sent by the UI root element.
+/// A child element has been added to an element. Sent by the UI root element, or element-event-sender if set.
 EVENT(E_ELEMENTADDED, ElementAdded)
 EVENT(E_ELEMENTADDED, ElementAdded)
 {
 {
     PARAM(P_ROOT, Root);                    // UIElement pointer
     PARAM(P_ROOT, Root);                    // UIElement pointer
@@ -229,7 +236,7 @@ EVENT(E_ELEMENTADDED, ElementAdded)
     PARAM(P_ELEMENT, Element);              // UIElement pointer
     PARAM(P_ELEMENT, Element);              // UIElement pointer
 }
 }
 
 
-/// A child element is about to be removed from an element. Sent by the UI root element.
+/// A child element is about to be removed from an element. Sent by the UI root element, or element-event-sender if set.
 EVENT(E_ELEMENTREMOVED, ElementRemoved)
 EVENT(E_ELEMENTREMOVED, ElementRemoved)
 {
 {
     PARAM(P_ROOT, Root);                    // UIElement pointer
     PARAM(P_ROOT, Root);                    // UIElement pointer

+ 13 - 2
Engine/UI/Window.cpp

@@ -25,6 +25,7 @@
 #include "Cursor.h"
 #include "Cursor.h"
 #include "InputEvents.h"
 #include "InputEvents.h"
 #include "UI.h"
 #include "UI.h"
+#include "UIEvents.h"
 #include "Window.h"
 #include "Window.h"
 
 
 #include "DebugNew.h"
 #include "DebugNew.h"
@@ -221,10 +222,20 @@ void Window::SetResizeBorder(const IntRect& rect)
 
 
 void Window::SetModal(bool modal)
 void Window::SetModal(bool modal)
 {
 {
-    UI* ui = GetSubsystem<UI>();
     // UI may be null at shutdown if for example a script was holding a reference to this window
     // UI may be null at shutdown if for example a script was holding a reference to this window
-    if (ui && ui->SetModalElement(this, modal))
+    UI* ui = GetSubsystem<UI>();
+    if (!ui)
+        return;
+
+    if (ui->SetModalElement(this, modal))
         modal_ = modal;
         modal_ = modal;
+
+    using namespace ModalChanged;
+
+    VariantMap eventData;
+    eventData[P_ELEMENT] = (void*)this;
+    eventData[P_MODAL] = modal;
+    SendEvent(E_MODALCHANGED, eventData);
 }
 }
 
 
 void Window::SetModalShadeColor(const Color& color)
 void Window::SetModalShadeColor(const Color& color)

+ 0 - 4
Engine/UI/Window.h

@@ -129,10 +129,6 @@ protected:
     Color modalFrameColor_;
     Color modalFrameColor_;
     /// Modal frame size, used when modal flag is set.
     /// Modal frame size, used when modal flag is set.
     IntVector2 modalFrameSize_;
     IntVector2 modalFrameSize_;
-
-private:
-    /// Handle modal window being focused.
-    void HandleModalFocused(StringHash eventType, VariantMap& eventData);
 };
 };
 
 
 }
 }

+ 3 - 3
Readme.txt

@@ -239,8 +239,8 @@ Desktop 64bit build
 
 
 Currently CMake build configuration has been set to compile Urho3D as 32bit by
 Currently CMake build configuration has been set to compile Urho3D as 32bit by
 default. To enable 64bit build for Visual Studio, run one of the cmake_vs20xx.bat
 default. To enable 64bit build for Visual Studio, run one of the cmake_vs20xx.bat
-by passing the option "Win64" explicitly. This will overrides CMake to use a
-64bit solution generator.
+by passing the option "Win64" explicitly. This overrides CMake to use a 64bit
+solution generator.
 
 
 To enable 64bit build for non-MSVC/non-Windows platform, pass the
 To enable 64bit build for non-MSVC/non-Windows platform, pass the
 option "-DENABLE_64BIT=1" explicitly when invoking cmake_eclipse.sh/
 option "-DENABLE_64BIT=1" explicitly when invoking cmake_eclipse.sh/
@@ -358,4 +358,4 @@ V1.1    - Object and scene model refactoring.
         - Added OpenGL and cross-platform support.
         - Added OpenGL and cross-platform support.
         - Switched to kNet library for networking.
         - Switched to kNet library for networking.
 
 
-V1.0    - Original release.
+V1.0    - Original release.