Browse Source

Moved SetSortChildren() to UIElement public API and exposed it to script.
Added layout skipping optimizations to UI::GetElementAt().

Lasse Öörni 14 years ago
parent
commit
31efab5d65

+ 8 - 0
Engine/Container/VectorBase.h

@@ -65,6 +65,10 @@ public:
     bool operator < (const RandomAccessIterator& rhs) const { return ptr_ < rhs.ptr_; }
     bool operator < (const RandomAccessIterator& rhs) const { return ptr_ < rhs.ptr_; }
     /// Test for greater than with another iterator.
     /// Test for greater than with another iterator.
     bool operator > (const RandomAccessIterator& rhs) const { return ptr_ > rhs.ptr_; }
     bool operator > (const RandomAccessIterator& rhs) const { return ptr_ > rhs.ptr_; }
+    /// Test for less than or equal with another iterator.
+    bool operator <= (const RandomAccessIterator& rhs) const { return ptr_ <= rhs.ptr_; }
+    /// Test for greater than or equal with another iterator.
+    bool operator >= (const RandomAccessIterator& rhs) const { return ptr_ >= rhs.ptr_; }
     
     
     /// Pointer.
     /// Pointer.
     T* ptr_;
     T* ptr_;
@@ -118,6 +122,10 @@ public:
     bool operator < (const RandomAccessConstIterator& rhs) const { return ptr_ < rhs.ptr_; }
     bool operator < (const RandomAccessConstIterator& rhs) const { return ptr_ < rhs.ptr_; }
     /// Test for greater than with another iterator.
     /// Test for greater than with another iterator.
     bool operator > (const RandomAccessConstIterator& rhs) const { return ptr_ > rhs.ptr_; }
     bool operator > (const RandomAccessConstIterator& rhs) const { return ptr_ > rhs.ptr_; }
+    /// Test for less than or equal with another iterator.
+    bool operator <= (const RandomAccessConstIterator& rhs) const { return ptr_ <= rhs.ptr_; }
+    /// Test for greater than or equal with another iterator.
+    bool operator >= (const RandomAccessConstIterator& rhs) const { return ptr_ >= rhs.ptr_; }
     
     
     /// Pointer.
     /// Pointer.
     T* ptr_;
     T* ptr_;

+ 2 - 0
Engine/Engine/APITemplates.h

@@ -764,6 +764,8 @@ template <class T> void RegisterUIElement(asIScriptEngine* engine, const char* c
     engine->RegisterObjectMethod(className, "bool get_bringToBack() const", asMETHOD(T, GetBringToBack), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "bool get_bringToBack() const", asMETHOD(T, GetBringToBack), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_clipChildren(bool)", asMETHOD(T, SetClipChildren), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_clipChildren(bool)", asMETHOD(T, SetClipChildren), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "bool get_clipChildren() const", asMETHOD(T, GetClipChildren), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "bool get_clipChildren() const", asMETHOD(T, GetClipChildren), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "void set_sortChildren(bool)", asMETHOD(T, SetSortChildren), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "bool get_sortChildren() const", asMETHOD(T, GetSortChildren), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_active(bool)", asMETHOD(T, SetActive), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_active(bool)", asMETHOD(T, SetActive), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "bool get_active() const", asMETHOD(T, IsActive), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "bool get_active() const", asMETHOD(T, IsActive), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_focus(bool)", asMETHOD(T, SetFocus), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_focus(bool)", asMETHOD(T, SetFocus), asCALL_THISCALL);

+ 1 - 1
Engine/UI/ListView.cpp

@@ -64,7 +64,7 @@ ListView::ListView(Context* context) :
     UIElement* container = new UIElement(context_);
     UIElement* container = new UIElement(context_);
     container->SetActive(true);
     container->SetActive(true);
     container->SetLayout(LM_VERTICAL);
     container->SetLayout(LM_VERTICAL);
-    container->SetSortingEnabled(false);
+    container->SetSortChildren(false);
     SetContentElement(container);
     SetContentElement(container);
     
     
     SubscribeToEvent(E_UIMOUSECLICK, HANDLER(ListView, HandleUIMouseClick));
     SubscribeToEvent(E_UIMOUSECLICK, HANDLER(ListView, HandleUIMouseClick));

+ 41 - 2
Engine/UI/UI.cpp

@@ -550,6 +550,7 @@ void UI::GetElementAt(UIElement*& result, UIElement* current, const IntVector2&
     
     
     current->SortChildren();
     current->SortChildren();
     const Vector<SharedPtr<UIElement> >& children = current->GetChildren();
     const Vector<SharedPtr<UIElement> >& children = current->GetChildren();
+    LayoutMode parentLayoutMode = current->GetLayoutMode();
     
     
     for (Vector<SharedPtr<UIElement> >::ConstIterator i = children.Begin(); i != children.End(); ++i)
     for (Vector<SharedPtr<UIElement> >::ConstIterator i = children.Begin(); i != children.End(); ++i)
     {
     {
@@ -567,11 +568,49 @@ void UI::GetElementAt(UIElement*& result, UIElement* current, const IntVector2&
                 
                 
                 if (hasChildren)
                 if (hasChildren)
                     GetElementAt(result, element, position, activeOnly);
                     GetElementAt(result, element, position, activeOnly);
+                // Layout optimization: if the element has no children, can break out after the first match
+                else if (parentLayoutMode != LM_FREE)
+                    break;
             }
             }
             else
             else
             {
             {
-                if (hasChildren && element->IsInsideCombined(position, true))
-                    GetElementAt(result, element, position, activeOnly);
+                if (hasChildren)
+                {
+                    if (element->IsInsideCombined(position, true))
+                        GetElementAt(result, element, position, activeOnly);
+                }
+                // Layout optimization: if position is much beyond the visible screen, check how many elements we can skip,
+                // or if we already passed all visible elements
+                else if (parentLayoutMode != LM_FREE)
+                {
+                    if (i == children.Begin())
+                    {
+                        int screenPos = (parentLayoutMode == LM_HORIZONTAL) ? element->GetScreenPosition().x_ :
+                            element->GetScreenPosition().y_;
+                        int layoutMinSize = current->GetLayoutMinSize();
+                        
+                        if (screenPos < 0 && layoutMinSize > 0)
+                        {
+                            unsigned toSkip = -screenPos / layoutMinSize;
+                            if (toSkip > 0)
+                            {
+                                i += (toSkip - 1);
+                                if (i >= children.End())
+                                    break;
+                            }
+                        }
+                    }
+                    else if (parentLayoutMode == LM_HORIZONTAL)
+                    {
+                        if (element->GetScreenPosition().x_ >= rootElement_->GetSize().x_)
+                            break;
+                    }
+                    else if (parentLayoutMode == LM_VERTICAL)
+                    {
+                        if (element->GetScreenPosition().y_ >= rootElement_->GetSize().y_)
+                            break;
+                    }
+                }
             }
             }
         }
         }
     }
     }

+ 30 - 20
Engine/UI/UIElement.cpp

@@ -93,6 +93,7 @@ UIElement::UIElement(Context* context) :
     layoutBorder_(IntRect::ZERO),
     layoutBorder_(IntRect::ZERO),
     resizeNestingLevel_(0),
     resizeNestingLevel_(0),
     layoutNestingLevel_(0),
     layoutNestingLevel_(0),
+    layoutMinSize_(0),
     position_(IntVector2::ZERO),
     position_(IntVector2::ZERO),
     size_(IntVector2::ZERO),
     size_(IntVector2::ZERO),
     minSize_(IntVector2::ZERO),
     minSize_(IntVector2::ZERO),
@@ -104,7 +105,7 @@ UIElement::UIElement(Context* context) :
     opacityDirty_(true),
     opacityDirty_(true),
     derivedColorDirty_(true),
     derivedColorDirty_(true),
     sortOrderDirty_(false),
     sortOrderDirty_(false),
-    sortingEnabled_(true),
+    sortChildren_(true),
     colorGradient_(false)
     colorGradient_(false)
 {
 {
 }
 }
@@ -521,6 +522,14 @@ void UIElement::SetClipChildren(bool enable)
     clipChildren_ = enable;
     clipChildren_ = enable;
 }
 }
 
 
+void UIElement::SetSortChildren(bool enable)
+{
+    if (!sortChildren_ && enable)
+        sortOrderDirty_ = true;
+    
+    sortChildren_ = enable;
+}
+
 void UIElement::SetActive(bool enable)
 void UIElement::SetActive(bool enable)
 {
 {
     active_ = enable;
     active_ = enable;
@@ -800,7 +809,7 @@ void UIElement::InsertChild(unsigned index, UIElement* element)
     if (element->parent_)
     if (element->parent_)
         element->parent_->RemoveChild(element);
         element->parent_->RemoveChild(element);
     
     
-    if (sortingEnabled_)
+    if (sortChildren_)
         sortOrderDirty_ = true;
         sortOrderDirty_ = true;
     
     
     element->parent_ = this;
     element->parent_ = this;
@@ -1036,18 +1045,21 @@ IntRect UIElement::GetCombinedScreenRect()
     IntVector2 screenPosition(GetScreenPosition());
     IntVector2 screenPosition(GetScreenPosition());
     IntRect combined(screenPosition.x_, screenPosition.y_, screenPosition.x_ + size_.x_, screenPosition.y_ + size_.y_);
     IntRect combined(screenPosition.x_, screenPosition.y_, screenPosition.x_ + size_.x_, screenPosition.y_ + size_.y_);
     
     
-    for (Vector<SharedPtr<UIElement> >::Iterator i = children_.Begin(); i != children_.End(); ++i)
+    if (!clipChildren_)
     {
     {
-        IntVector2 childPos = (*i)->GetScreenPosition();
-        const IntVector2& childSize = (*i)->GetSize();
-        if (childPos.x_ < combined.left_)
-            combined.left_ = childPos.x_;
-        if (childPos.y_ < combined.top_)
-            combined.top_ = childPos.y_;
-        if (childPos.x_ + childSize.x_ > combined.right_)
-            combined.right_ = childPos.x_ + childSize.x_;
-        if (childPos.y_ + childSize.y_ > combined.bottom_)
-            combined.bottom_ = childPos.y_ + childSize.y_;
+        for (Vector<SharedPtr<UIElement> >::Iterator i = children_.Begin(); i != children_.End(); ++i)
+        {
+            IntVector2 childPos = (*i)->GetScreenPosition();
+            const IntVector2& childSize = (*i)->GetSize();
+            if (childPos.x_ < combined.left_)
+                combined.left_ = childPos.x_;
+            if (childPos.y_ < combined.top_)
+                combined.top_ = childPos.y_;
+            if (childPos.x_ + childSize.x_ > combined.right_)
+                combined.right_ = childPos.x_ + childSize.x_;
+            if (childPos.y_ + childSize.y_ > combined.bottom_)
+                combined.bottom_ = childPos.y_ + childSize.y_;
+        }
     }
     }
     
     
     return combined;
     return combined;
@@ -1055,7 +1067,7 @@ IntRect UIElement::GetCombinedScreenRect()
 
 
 void UIElement::SortChildren()
 void UIElement::SortChildren()
 {
 {
-    if (sortingEnabled_ && sortOrderDirty_)
+    if (sortChildren_ && sortOrderDirty_)
     {
     {
         Sort(children_.Begin(), children_.End(), CompareUIElements);
         Sort(children_.Begin(), children_.End(), CompareUIElements);
         sortOrderDirty_ = false;
         sortOrderDirty_ = false;
@@ -1072,11 +1084,6 @@ void UIElement::SetChildOffset(const IntVector2& offset)
     }
     }
 }
 }
 
 
-void UIElement::SetSortingEnabled(bool enable)
-{
-    sortingEnabled_ = enable;
-}
-
 void UIElement::SetHovering(bool enable)
 void UIElement::SetHovering(bool enable)
 {
 {
     hovering_ = enable;
     hovering_ = enable;
@@ -1235,13 +1242,16 @@ void UIElement::CalculateLayout(PODVector<int>& positions, PODVector<int>& sizes
         }
         }
     }
     }
     
     
-    // Calculate final positions
+    // Calculate final positions and store the minimum child element size
+    layoutMinSize_ = M_MAX_INT;
     int position = begin;
     int position = begin;
     for (int i = 0; i < numChildren; ++i)
     for (int i = 0; i < numChildren; ++i)
     {
     {
         positions[i] = position;
         positions[i] = position;
         position += sizes[i];
         position += sizes[i];
         position += spacing;
         position += spacing;
+        if (sizes[i] < layoutMinSize_)
+            layoutMinSize_ = sizes[i];
     }
     }
 }
 }
 
 

+ 13 - 9
Engine/UI/UIElement.h

@@ -203,8 +203,10 @@ public:
     void SetBringToFront(bool enable);
     void SetBringToFront(bool enable);
     /// %Set whether should be put to background when another element is focused.
     /// %Set whether should be put to background when another element is focused.
     void SetBringToBack(bool enable);
     void SetBringToBack(bool enable);
-    /// %Set whether should clip child elements.
+    /// %Set whether should clip child elements. Default false.
     void SetClipChildren(bool enable);
     void SetClipChildren(bool enable);
+    /// %Set whether should sort child elements according to priority. Default true.
+    void SetSortChildren(bool enable);
     /// %Set whether reacts to input.
     /// %Set whether reacts to input.
     void SetActive(bool enable);
     void SetActive(bool enable);
     /// %Set whether is focused. Only one element can be focused at a time.
     /// %Set whether is focused. Only one element can be focused at a time.
@@ -296,6 +298,8 @@ public:
     bool GetBringToBack() const { return bringToBack_; }
     bool GetBringToBack() const { return bringToBack_; }
     /// Return whether should clip child elements.
     /// Return whether should clip child elements.
     bool GetClipChildren() const { return clipChildren_; }
     bool GetClipChildren() const { return clipChildren_; }
+    /// Return whether should sort child elements according to priority.
+    bool GetSortChildren() const { return sortChildren_; }
     /// Return whether has focus.
     /// Return whether has focus.
     bool HasFocus() const;
     bool HasFocus() const;
     /// Return whether reacts to input.
     /// Return whether reacts to input.
@@ -343,19 +347,17 @@ public:
     IntVector2 ElementToScreen(const IntVector2& position);
     IntVector2 ElementToScreen(const IntVector2& position);
     /// Return whether a point (either in element or screen coordinates) is inside the element.
     /// Return whether a point (either in element or screen coordinates) is inside the element.
     bool IsInside(IntVector2 position, bool isScreen);
     bool IsInside(IntVector2 position, bool isScreen);
-    /// Return whether a point (either in element or screen coordinates) is inside the combined rect of element and its children.
+    /// Return whether a point (either in element or screen coordinates) is inside the combined rect of the element and its children.
     bool IsInsideCombined(IntVector2 position, bool isScreen);
     bool IsInsideCombined(IntVector2 position, bool isScreen);
     /// Return combined screen coordinate rect of element and its children.
     /// Return combined screen coordinate rect of element and its children.
     IntRect GetCombinedScreenRect();
     IntRect GetCombinedScreenRect();
-    /// Sort child elements if sort order dirty. Called by UI.
+    /// Sort child elements if sorting enabled and order dirty. Called by UI.
     void SortChildren();
     void SortChildren();
+    /// Return minimum layout element size in the layout direction. Only valid after layout has been calculated.
+    int GetLayoutMinSize() const { return layoutMinSize_; }
     
     
     /// %Set child offset.
     /// %Set child offset.
     void SetChildOffset(const IntVector2& offset);
     void SetChildOffset(const IntVector2& offset);
-    /// %Set whether child elements should be sorted according to priority.
-    void SetSortingEnabled(bool enable);
-    /// Return whether child elements are sorted according to priority.
-    bool GetSortingEnabled() const { return sortingEnabled_; }
     /// %Set hovering state.
     /// %Set hovering state.
     void SetHovering(bool enable);
     void SetHovering(bool enable);
     /// Adjust scissor for rendering.
     /// Adjust scissor for rendering.
@@ -389,6 +391,8 @@ protected:
     bool bringToBack_;
     bool bringToBack_;
     /// Clip children flag.
     /// Clip children flag.
     bool clipChildren_;
     bool clipChildren_;
+    /// Sort childrenaccording to priority flag.
+    bool sortChildren_;
     /// Input enabled flag.
     /// Input enabled flag.
     bool active_;
     bool active_;
     /// Selected flag.
     /// Selected flag.
@@ -411,6 +415,8 @@ protected:
     unsigned resizeNestingLevel_;
     unsigned resizeNestingLevel_;
     /// Layout update nesting level to prevent endless loop.
     /// Layout update nesting level to prevent endless loop.
     unsigned layoutNestingLevel_;
     unsigned layoutNestingLevel_;
+    /// Layout element minimum size in layout direction.
+    int layoutMinSize_;
     
     
 private:
 private:
     /// Return child elements recursively.
     /// Return child elements recursively.
@@ -452,8 +458,6 @@ private:
     bool derivedColorDirty_;
     bool derivedColorDirty_;
     /// Child priority sorting dirty flag.
     /// Child priority sorting dirty flag.
     bool sortOrderDirty_;
     bool sortOrderDirty_;
-    /// Child priority sorting enabled flag.
-    bool sortingEnabled_;
     /// Has color gradient flag.
     /// Has color gradient flag.
     bool colorGradient_;
     bool colorGradient_;
 };
 };