Sfoglia il codice sorgente

UIElement: unsigned to signed

Related: https://github.com/urho3d/Urho3D/issues/2940
1vanK 3 anni fa
parent
commit
4885f4631e

+ 23 - 23
Source/Urho3D/AngelScript/Generated_Members.h

@@ -16375,8 +16375,8 @@ template <class T> void RegisterMembers_UIElement(asIScriptEngine* engine, const
     // void UIElement::BringToFront()
     engine->RegisterObjectMethod(className, "void BringToFront()", AS_METHODPR(T, BringToFront, (), void), AS_CALL_THISCALL);
 
-    // UIElement* UIElement::CreateChild(StringHash type, const String& name = String::EMPTY, unsigned index = M_MAX_UNSIGNED)
-    engine->RegisterObjectMethod(className, "UIElement@+ CreateChild(StringHash, const String&in = String::EMPTY, uint = M_MAX_UNSIGNED)", AS_METHODPR(T, CreateChild, (StringHash, const String&, unsigned), UIElement*), AS_CALL_THISCALL);
+    // UIElement* UIElement::CreateChild(StringHash type, const String& name = String::EMPTY, i32 index = ENDPOS)
+    engine->RegisterObjectMethod(className, "UIElement@+ CreateChild(StringHash, const String&in = String::EMPTY, int = ENDPOS)", AS_METHODPR(T, CreateChild, (StringHash, const String&, i32), UIElement*), AS_CALL_THISCALL);
 
     // void UIElement::DisableLayoutUpdate()
     engine->RegisterObjectMethod(className, "void DisableLayoutUpdate()", AS_METHODPR(T, DisableLayoutUpdate, (), void), AS_CALL_THISCALL);
@@ -16390,8 +16390,8 @@ template <class T> void RegisterMembers_UIElement(asIScriptEngine* engine, const
     // bool UIElement::FilterAttributes(XMLElement& dest) const
     engine->RegisterObjectMethod(className, "bool FilterAttributes(XMLElement&) const", AS_METHODPR(T, FilterAttributes, (XMLElement&) const, bool), AS_CALL_THISCALL);
 
-    // unsigned UIElement::FindChild(UIElement* element) const
-    engine->RegisterObjectMethod(className, "uint FindChild(UIElement@+) const", AS_METHODPR(T, FindChild, (UIElement*) const, unsigned), AS_CALL_THISCALL);
+    // i32 UIElement::FindChild(UIElement* element) const
+    engine->RegisterObjectMethod(className, "int FindChild(UIElement@+) const", AS_METHODPR(T, FindChild, (UIElement*) const, i32), AS_CALL_THISCALL);
 
     // const String& UIElement::GetAppliedStyle() const
     engine->RegisterObjectMethod(className, "const String& GetAppliedStyle() const", AS_METHODPR(T, GetAppliedStyle, () const, const String&), AS_CALL_THISCALL);
@@ -16405,9 +16405,9 @@ template <class T> void RegisterMembers_UIElement(asIScriptEngine* engine, const
     engine->RegisterObjectMethod(className, "bool GetBringToFront() const", AS_METHODPR(T, GetBringToFront, () const, bool), AS_CALL_THISCALL);
     engine->RegisterObjectMethod(className, "bool get_bringToFront() const", AS_METHODPR(T, GetBringToFront, () const, bool), AS_CALL_THISCALL);
 
-    // UIElement* UIElement::GetChild(unsigned index) const
-    engine->RegisterObjectMethod(className, "UIElement@+ GetChild(uint) const", AS_METHODPR(T, GetChild, (unsigned) const, UIElement*), AS_CALL_THISCALL);
-    engine->RegisterObjectMethod(className, "UIElement@+ get_children(uint) const", AS_METHODPR(T, GetChild, (unsigned) const, UIElement*), AS_CALL_THISCALL);
+    // UIElement* UIElement::GetChild(i32 index) const
+    engine->RegisterObjectMethod(className, "UIElement@+ GetChild(int) const", AS_METHODPR(T, GetChild, (i32) const, UIElement*), AS_CALL_THISCALL);
+    engine->RegisterObjectMethod(className, "UIElement@+ get_children(int) const", AS_METHODPR(T, GetChild, (i32) const, UIElement*), AS_CALL_THISCALL);
 
     // UIElement* UIElement::GetChild(const String& name, bool recursive = false) const
     engine->RegisterObjectMethod(className, "UIElement@+ GetChild(const String&in, bool = false) const", AS_METHODPR(T, GetChild, (const String&, bool) const, UIElement*), AS_CALL_THISCALL);
@@ -16461,9 +16461,9 @@ template <class T> void RegisterMembers_UIElement(asIScriptEngine* engine, const
     engine->RegisterObjectMethod(className, "MouseButtonFlags GetDragButtonCombo() const", AS_METHODPR(T, GetDragButtonCombo, () const, MouseButtonFlags), AS_CALL_THISCALL);
     engine->RegisterObjectMethod(className, "MouseButtonFlags get_dragButtonCombo() const", AS_METHODPR(T, GetDragButtonCombo, () const, MouseButtonFlags), AS_CALL_THISCALL);
 
-    // unsigned UIElement::GetDragButtonCount() const
-    engine->RegisterObjectMethod(className, "uint GetDragButtonCount() const", AS_METHODPR(T, GetDragButtonCount, () const, unsigned), AS_CALL_THISCALL);
-    engine->RegisterObjectMethod(className, "uint get_dragButtonCount() const", AS_METHODPR(T, GetDragButtonCount, () const, unsigned), AS_CALL_THISCALL);
+    // i32 UIElement::GetDragButtonCount() const
+    engine->RegisterObjectMethod(className, "int GetDragButtonCount() const", AS_METHODPR(T, GetDragButtonCount, () const, i32), AS_CALL_THISCALL);
+    engine->RegisterObjectMethod(className, "int get_dragButtonCount() const", AS_METHODPR(T, GetDragButtonCount, () const, i32), AS_CALL_THISCALL);
 
     // DragAndDropModeFlags UIElement::GetDragDropMode() const
     engine->RegisterObjectMethod(className, "DragAndDropModeFlags GetDragDropMode() const", AS_METHODPR(T, GetDragDropMode, () const, DragAndDropModeFlags), AS_CALL_THISCALL);
@@ -16566,8 +16566,8 @@ template <class T> void RegisterMembers_UIElement(asIScriptEngine* engine, const
     engine->RegisterObjectMethod(className, "const String& GetName() const", AS_METHODPR(T, GetName, () const, const String&), AS_CALL_THISCALL);
     engine->RegisterObjectMethod(className, "const String& get_name() const", AS_METHODPR(T, GetName, () const, const String&), AS_CALL_THISCALL);
 
-    // unsigned UIElement::GetNumChildren(bool recursive = false) const
-    engine->RegisterObjectMethod(className, "uint GetNumChildren(bool = false) const", AS_METHODPR(T, GetNumChildren, (bool) const, unsigned), AS_CALL_THISCALL);
+    // i32 UIElement::GetNumChildren(bool recursive = false) const
+    engine->RegisterObjectMethod(className, "int GetNumChildren(bool = false) const", AS_METHODPR(T, GetNumChildren, (bool) const, i32), AS_CALL_THISCALL);
 
     // float UIElement::GetOpacity() const
     engine->RegisterObjectMethod(className, "float GetOpacity() const", AS_METHODPR(T, GetOpacity, () const, float), AS_CALL_THISCALL);
@@ -16638,8 +16638,8 @@ template <class T> void RegisterMembers_UIElement(asIScriptEngine* engine, const
     // bool UIElement::HasTag(const String& tag) const
     engine->RegisterObjectMethod(className, "bool HasTag(const String&in) const", AS_METHODPR(T, HasTag, (const String&) const, bool), AS_CALL_THISCALL);
 
-    // void UIElement::InsertChild(unsigned index, UIElement* element)
-    engine->RegisterObjectMethod(className, "void InsertChild(uint, UIElement@+)", AS_METHODPR(T, InsertChild, (unsigned, UIElement*), void), AS_CALL_THISCALL);
+    // void UIElement::InsertChild(i32 index, UIElement* element)
+    engine->RegisterObjectMethod(className, "void InsertChild(int, UIElement@+)", AS_METHODPR(T, InsertChild, (i32, UIElement*), void), AS_CALL_THISCALL);
 
     // bool UIElement::IsChildOf(UIElement* element) const
     engine->RegisterObjectMethod(className, "bool IsChildOf(UIElement@+) const", AS_METHODPR(T, IsChildOf, (UIElement*) const, bool), AS_CALL_THISCALL);
@@ -16769,11 +16769,11 @@ template <class T> void RegisterMembers_UIElement(asIScriptEngine* engine, const
     // void UIElement::RemoveAllTags()
     engine->RegisterObjectMethod(className, "void RemoveAllTags()", AS_METHODPR(T, RemoveAllTags, (), void), AS_CALL_THISCALL);
 
-    // void UIElement::RemoveChild(UIElement* element, unsigned index = 0)
-    engine->RegisterObjectMethod(className, "void RemoveChild(UIElement@+, uint = 0)", AS_METHODPR(T, RemoveChild, (UIElement*, unsigned), void), AS_CALL_THISCALL);
+    // void UIElement::RemoveChild(UIElement* element, i32 index = 0)
+    engine->RegisterObjectMethod(className, "void RemoveChild(UIElement@+, int = 0)", AS_METHODPR(T, RemoveChild, (UIElement*, i32), void), AS_CALL_THISCALL);
 
-    // void UIElement::RemoveChildAtIndex(unsigned index)
-    engine->RegisterObjectMethod(className, "void RemoveChildAtIndex(uint)", AS_METHODPR(T, RemoveChildAtIndex, (unsigned), void), AS_CALL_THISCALL);
+    // void UIElement::RemoveChildAtIndex(i32 index)
+    engine->RegisterObjectMethod(className, "void RemoveChildAtIndex(int)", AS_METHODPR(T, RemoveChildAtIndex, (i32), void), AS_CALL_THISCALL);
 
     // bool UIElement::RemoveTag(const String& tag)
     engine->RegisterObjectMethod(className, "bool RemoveTag(const String&in)", AS_METHODPR(T, RemoveTag, (const String&), bool), AS_CALL_THISCALL);
@@ -16969,8 +16969,8 @@ template <class T> void RegisterMembers_UIElement(asIScriptEngine* engine, const
     engine->RegisterObjectMethod(className, "void SetOpacity(float)", AS_METHODPR(T, SetOpacity, (float), void), AS_CALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_opacity(float)", AS_METHODPR(T, SetOpacity, (float), void), AS_CALL_THISCALL);
 
-    // void UIElement::SetParent(UIElement* parent, unsigned index = M_MAX_UNSIGNED)
-    engine->RegisterObjectMethod(className, "void SetParent(UIElement@+, uint = M_MAX_UNSIGNED)", AS_METHODPR(T, SetParent, (UIElement*, unsigned), void), AS_CALL_THISCALL);
+    // void UIElement::SetParent(UIElement* parent, i32 index = ENDPOS)
+    engine->RegisterObjectMethod(className, "void SetParent(UIElement@+, int = ENDPOS)", AS_METHODPR(T, SetParent, (UIElement*, i32), void), AS_CALL_THISCALL);
 
     // void UIElement::SetPivot(const Vector2& pivot)
     engine->RegisterObjectMethod(className, "void SetPivot(const Vector2&in)", AS_METHODPR(T, SetPivot, (const Vector2&), void), AS_CALL_THISCALL);
@@ -17045,15 +17045,15 @@ template <class T> void RegisterMembers_UIElement(asIScriptEngine* engine, const
     // void UIElement::UpdateLayout()
     engine->RegisterObjectMethod(className, "void UpdateLayout()", AS_METHODPR(T, UpdateLayout, (), void), AS_CALL_THISCALL);
 
-    // template <class T> T* UIElement::CreateChild(const String& name = String::EMPTY, unsigned index = M_MAX_UNSIGNED)
+    // template <class T> T* UIElement::CreateChild(const String& name = String::EMPTY, i32 index = ENDPOS)
     // Not registered because template
-    // template <class T> T* UIElement::GetChildDynamicCast(unsigned index) const
+    // template <class T> T* UIElement::GetChildDynamicCast(i32 index) const
     // Not registered because template
     // template <class T> T* UIElement::GetChildDynamicCast(const String& name, bool recursive = false) const
     // Not registered because template
     // template <class T> T* UIElement::GetChildDynamicCast(const StringHash& key, const Variant& value = Variant::EMPTY, bool recursive = false) const
     // Not registered because template
-    // template <class T> T* UIElement::GetChildStaticCast(unsigned index) const
+    // template <class T> T* UIElement::GetChildStaticCast(i32 index) const
     // Not registered because template
     // template <class T> T* UIElement::GetChildStaticCast(const String& name, bool recursive = false) const
     // Not registered because template

+ 39 - 19
Source/Urho3D/UI/UIElement.cpp

@@ -200,11 +200,13 @@ bool UIElement::LoadXML(const XMLElement& source, XMLFile* styleFile)
         String typeName = childElem.GetAttribute("type");
         if (typeName.Empty())
             typeName = "UIElement";
-        unsigned index = childElem.HasAttribute("index") ? childElem.GetUInt("index") : M_MAX_UNSIGNED;
+        i32 index = childElem.HasAttribute("index") ? childElem.GetInt("index") : ENDPOS;
         UIElement* child = nullptr;
 
         if (!internalElem)
+        {
             child = CreateChild(typeName, String::EMPTY, index);
+        }
         else
         {
             for (unsigned i = nextInternalChild; i < children_.Size(); ++i)
@@ -252,7 +254,7 @@ UIElement* UIElement::LoadChildXML(const XMLElement& childElem, XMLFile* styleFi
     String typeName = childElem.GetAttribute("type");
     if (typeName.Empty())
         typeName = "UIElement";
-    unsigned index = childElem.HasAttribute("index") ? childElem.GetUInt("index") : M_MAX_UNSIGNED;
+    i32 index = childElem.HasAttribute("index") ? childElem.GetUInt("index") : ENDPOS;
     UIElement* child = CreateChild(typeName, String::EMPTY, index);
 
     if (child)
@@ -1249,10 +1251,13 @@ void UIElement::BringToFront()
     }
 }
 
-UIElement* UIElement::CreateChild(StringHash type, const String& name, unsigned index)
+UIElement* UIElement::CreateChild(StringHash type, const String& name, i32 index/* = ENDPOS*/)
 {
+    assert(index == ENDPOS || (index >= 0 && index <= children_.Size()));
+
     // Check that creation succeeds and that the object in fact is a UI element
     SharedPtr<UIElement> newElement = DynamicCast<UIElement>(context_->CreateObject(type));
+    
     if (!newElement)
     {
         URHO3D_LOGERROR("Could not create unknown UI element type " + type.ToString());
@@ -1268,25 +1273,30 @@ UIElement* UIElement::CreateChild(StringHash type, const String& name, unsigned
 
 void UIElement::AddChild(UIElement* element)
 {
-    InsertChild(M_MAX_UNSIGNED, element);
+    InsertChild(ENDPOS, element);
 }
 
-void UIElement::InsertChild(unsigned index, UIElement* element)
+void UIElement::InsertChild(i32 index, UIElement* element)
 {
+    assert(index == ENDPOS || (index >= 0 && index <= children_.Size()));
+
     // Check for illegal or redundant parent assignment
     if (!element || element == this || element->parent_ == this)
         return;
+
     // Check for possible cyclic parent assignment
     UIElement* parent = parent_;
+
     while (parent)
     {
         if (parent == element)
             return;
+
         parent = parent->parent_;
     }
 
     // Add first, then remove from old parent, to ensure the element does not get deleted
-    if (index >= children_.Size())
+    if (index >= children_.Size() || index == ENDPOS)
         children_.Push(SharedPtr<UIElement>(element));
     else
         children_.Insert(children_.Begin() + index, SharedPtr<UIElement>(element));
@@ -1308,6 +1318,7 @@ void UIElement::InsertChild(unsigned index, UIElement* element)
     // Send change event
     UIElement* root = GetRoot();
     UIElement* sender = GetElementEventSender();
+    
     if (sender)
     {
         using namespace ElementAdded;
@@ -1321,14 +1332,17 @@ void UIElement::InsertChild(unsigned index, UIElement* element)
     }
 }
 
-void UIElement::RemoveChild(UIElement* element, unsigned index)
+void UIElement::RemoveChild(UIElement* element, i32 index/* = 0*/)
 {
-    for (unsigned i = index; i < children_.Size(); ++i)
+    assert(index >= 0);
+
+    for (i32 i = index; i < children_.Size(); ++i)
     {
         if (children_[i] == element)
         {
             // Send change event if not already being destroyed
             UIElement* sender = Refs() > 0 ? GetElementEventSender() : nullptr;
+            
             if (sender)
             {
                 using namespace ElementRemoved;
@@ -1349,8 +1363,10 @@ void UIElement::RemoveChild(UIElement* element, unsigned index)
     }
 }
 
-void UIElement::RemoveChildAtIndex(unsigned index)
+void UIElement::RemoveChildAtIndex(i32 index)
 {
+    assert(index >= 0);
+
     if (index >= children_.Size())
         return;
 
@@ -1405,13 +1421,13 @@ void UIElement::Remove()
         parent_->RemoveChild(this);
 }
 
-unsigned UIElement::FindChild(UIElement* element) const
+i32 UIElement::FindChild(UIElement* element) const
 {
-    Vector<SharedPtr<UIElement>>::ConstIterator i = children_.Find(SharedPtr<UIElement>(element));
-    return i != children_.End() ? (unsigned)(i - children_.Begin()) : M_MAX_UNSIGNED;
+    Vector<SharedPtr<UIElement>>::ConstIterator it = children_.Find(SharedPtr<UIElement>(element));
+    return it != children_.End() ? (i32)(it - children_.Begin()) : NINDEX;
 }
 
-void UIElement::SetParent(UIElement* parent, unsigned index)
+void UIElement::SetParent(UIElement* parent, i32 index/* = ENDPOS*/)
 {
     if (parent)
         parent->InsertChild(index, this);
@@ -1595,23 +1611,27 @@ Vector<UIElement*> UIElement::GetChildren(bool recursive) const
     return dest;
 }
 
-unsigned UIElement::GetNumChildren(bool recursive) const
+i32 UIElement::GetNumChildren(bool recursive/* = false*/) const
 {
     if (!recursive)
+    {
         return children_.Size();
+    }
     else
     {
-        unsigned allChildren = children_.Size();
-        for (Vector<SharedPtr<UIElement>>::ConstIterator i = children_.Begin(); i != children_.End(); ++i)
-            allChildren += (*i)->GetNumChildren(true);
+        i32 allChildren = children_.Size();
+        
+        for (const SharedPtr<UIElement>& child : children_)
+            allChildren += child->GetNumChildren(true);
 
         return allChildren;
     }
 }
 
-UIElement* UIElement::GetChild(unsigned index) const
+UIElement* UIElement::GetChild(i32 index) const
 {
-    return index < children_.Size() ? children_[index] : nullptr;
+    assert(index >= 0 || index == NINDEX);
+    return (index >= 0 && index < children_.Size()) ? children_[index] : nullptr;
 }
 
 UIElement* UIElement::GetChild(const String& name, bool recursive) const

+ 39 - 17
Source/Urho3D/UI/UIElement.h

@@ -373,24 +373,34 @@ public:
     void EnableLayoutUpdate();
     /// Bring UI element to front.
     void BringToFront();
+    
     /// Create and add a child element and return it.
-    UIElement* CreateChild(StringHash type, const String& name = String::EMPTY, unsigned index = M_MAX_UNSIGNED);
+    UIElement* CreateChild(StringHash type, const String& name = String::EMPTY, i32 index = ENDPOS);
+    
     /// Add a child element.
     void AddChild(UIElement* element);
-    /// Insert a child element into a specific position in the child list.
-    void InsertChild(unsigned index, UIElement* element);
+    
+    /// Insert a child element into a specific position in the child list. index can be ENDPOS.
+    void InsertChild(i32 index, UIElement* element);
+    
     /// Remove a child element. Starting search at specified index if provided.
-    void RemoveChild(UIElement* element, unsigned index = 0);
+    void RemoveChild(UIElement* element, i32 index = 0);
+    
     /// Remove a child element at index.
-    void RemoveChildAtIndex(unsigned index);
+    void RemoveChildAtIndex(i32 index);
+    
     /// Remove all child elements.
     void RemoveAllChildren();
+    
     /// Remove from the parent element. If no other shared pointer references exist, causes immediate deletion.
     void Remove();
-    /// Find child index. Return M_MAX_UNSIGNED if not found.
-    unsigned FindChild(UIElement* element) const;
+    
+    /// Find child index. Return NINDEX if not found.
+    i32 FindChild(UIElement* element) const;
+    
     /// Set parent element. Same as parent->InsertChild(index, this).
-    void SetParent(UIElement* parent, unsigned index = M_MAX_UNSIGNED);
+    void SetParent(UIElement* parent, i32 index = ENDPOS);
+    
     /// Set a user variable.
     void SetVar(StringHash key, const Variant& value);
     /// Mark as internally (programmatically) created. Used when an element composes itself out of child elements.
@@ -417,17 +427,23 @@ public:
     void RemoveAllTags();
 
     /// Template version of creating a child element.
-    template <class T> T* CreateChild(const String& name = String::EMPTY, unsigned index = M_MAX_UNSIGNED);
+    template <class T> T* CreateChild(const String& name = String::EMPTY, i32 index = ENDPOS);
+    
     /// Template version of returning child element by index using static cast.
-    template <class T> T* GetChildStaticCast(unsigned index) const;
+    template <class T> T* GetChildStaticCast(i32 index) const;
+    
     /// Template version of returning child element by name using static cast.
     template <class T> T* GetChildStaticCast(const String& name, bool recursive = false) const;
+    
     /// Template version of returning child element by variable using static cast. If only key is provided, return the first child having the matching variable key. If value is also provided then the actual variable value would also be checked against.
     template <class T> T* GetChildStaticCast(const StringHash& key, const Variant& value = Variant::EMPTY, bool recursive = false) const;
+    
     /// Template version of returning child element by index using dynamic cast. May return 0 when casting failed.
-    template <class T> T* GetChildDynamicCast(unsigned index) const;
+    template <class T> T* GetChildDynamicCast(i32 index) const;
+    
     /// Template version of returning child element by name using dynamic cast. May return 0 when casting failed.
     template <class T> T* GetChildDynamicCast(const String& name, bool recursive = false) const;
+    
     /// Template version of returning child element by variable. If only key is provided, return the first child having the matching variable key. If value is also provided then the actual variable value would also be checked against using dynamic cast. May return 0 when casting failed.
     template <class T> T* GetChildDynamicCast(const StringHash& key, const Variant& value = Variant::EMPTY, bool recursive = false) const;
 
@@ -637,12 +653,15 @@ public:
     const Vector2& GetLayoutFlexScale() const { return layoutFlexScale_; }
 
     /// Return number of child elements.
-    unsigned GetNumChildren(bool recursive = false) const;
+    i32 GetNumChildren(bool recursive = false) const;
+    
     /// Return child element by index.
     /// @property{get_children}
-    UIElement* GetChild(unsigned index) const;
+    UIElement* GetChild(i32 index) const;
+    
     /// Return child element by name.
     UIElement* GetChild(const String& name, bool recursive = false) const;
+    
     /// Return child element by variable. If only key is provided, return the first child having the matching variable key. If value is also provided then the actual variable value would also be checked against.
     UIElement* GetChild(const StringHash& key, const Variant& value = Variant::EMPTY, bool recursive = false) const;
 
@@ -689,7 +708,7 @@ public:
 
     /// Return the number of buttons dragging this element.
     /// @property
-    unsigned GetDragButtonCount() const { return dragButtonCount_; }
+    i32 GetDragButtonCount() const { return dragButtonCount_; }
 
     /// Return whether a point (either in element or screen coordinates) is inside the element.
     bool IsInside(IntVector2 position, bool isScreen);
@@ -912,13 +931,15 @@ private:
     StringVector tags_;
 };
 
-template <class T> T* UIElement::CreateChild(const String& name, unsigned index)
+template <class T> T* UIElement::CreateChild(const String& name, i32 index/* = ENDPOS*/)
 {
+    assert(index >= 0 || index == ENDPOS);
     return static_cast<T*>(CreateChild(T::GetTypeStatic(), name, index));
 }
 
-template <class T> T* UIElement::GetChildStaticCast(unsigned index) const
+template <class T> T* UIElement::GetChildStaticCast(i32 index) const
 {
+    assert(index >= 0);
     return static_cast<T*>(GetChild(index));
 }
 
@@ -932,8 +953,9 @@ template <class T> T* UIElement::GetChildStaticCast(const StringHash& key, const
     return static_cast<T*>(GetChild(key, value, recursive));
 }
 
-template <class T> T* UIElement::GetChildDynamicCast(unsigned index) const
+template <class T> T* UIElement::GetChildDynamicCast(i32 index) const
 {
+    assert(index >= 0);
     return dynamic_cast<T*>(GetChild(index));
 }