Browse Source

Reordered UIElement's attributes, common attributes got registered first. Enhanced Attribute Inspector to show UIElement's attributes for single selection case. Multiple selection is still WIP.

Wei Tjong Yao 12 years ago
parent
commit
a76a3b1ab7

+ 127 - 85
Bin/Data/Scripts/Editor/EditorNodeWindow.as

@@ -3,7 +3,6 @@
 
 Window@ attributeInspectorWindow;
 UIElement@ parentContainer;
-UIElement@ nodeContainer;
 XMLFile@ nodeXMLResource;
 XMLFile@ componentXMLResource;
 
@@ -14,31 +13,16 @@ const String STRIKED_OUT = "——";   // Two unicode EM DASH (U+2014)
 const ShortStringHash NODE_IDS_VAR("NodeIDs");
 const ShortStringHash COMPONENT_IDS_VAR("ComponentIDs");
 
+uint nodeContainerIndex = M_MAX_UNSIGNED;
 uint componentContainerStartIndex = 0;
-
-void AddNodeContainer()
-{
-    if (nodeContainer !is null)
-        return;
-
-    uint index = parentContainer.numChildren;
-    parentContainer.LoadXML(nodeXMLResource, uiStyle);
-    nodeContainer = GetContainer(index);
-    SubscribeToEvent(nodeContainer.GetChild("NewVarDropDown", true), "ItemSelected", "CreateNewVariable");
-    SubscribeToEvent(nodeContainer.GetChild("DeleteVarButton", true), "Released", "DeleteVariable");
-    ++componentContainerStartIndex;
-}
-
-void AddComponentContainer()
-{
-    parentContainer.LoadXML(componentXMLResource, uiStyle);
-}
+uint elementContainerIndex = M_MAX_UNSIGNED;
 
 void DeleteAllContainers()
 {
     parentContainer.RemoveAllChildren();
-    nodeContainer = null;
+    nodeContainerIndex = M_MAX_UNSIGNED;
     componentContainerStartIndex = 0;
+    elementContainerIndex = M_MAX_UNSIGNED;
 }
 
 UIElement@ GetContainer(uint index)
@@ -46,11 +30,40 @@ UIElement@ GetContainer(uint index)
     return parentContainer.children[index];
 }
 
+UIElement@ GetNodeContainer()
+{
+    if (nodeContainerIndex != M_MAX_UNSIGNED)
+        return GetContainer(nodeContainerIndex);
+
+    nodeContainerIndex = parentContainer.numChildren;
+    parentContainer.LoadXML(nodeXMLResource, uiStyle);
+    UIElement@ container = GetContainer(nodeContainerIndex);
+    SubscribeToEvent(container.GetChild("NewVarDropDown", true), "ItemSelected", "CreateNewVariable");
+    SubscribeToEvent(container.GetChild("DeleteVarButton", true), "Released", "DeleteVariable");
+    ++componentContainerStartIndex;
+    return container;
+}
+
 UIElement@ GetComponentContainer(uint index)
 {
+    for (uint i = parentContainer.numChildren - componentContainerStartIndex; i <= index; ++i)
+        parentContainer.LoadXML(componentXMLResource, uiStyle);
     return parentContainer.children[componentContainerStartIndex + index];
 }
 
+UIElement@ GetElementContainer()
+{
+    if (elementContainerIndex != M_MAX_UNSIGNED)
+        return GetContainer(elementContainerIndex);
+
+    elementContainerIndex = parentContainer.numChildren;
+    parentContainer.LoadXML(nodeXMLResource, uiStyle);
+    UIElement@ container = GetContainer(elementContainerIndex);
+    SubscribeToEvent(container.GetChild("NewVarDropDown", true), "ItemSelected", "CreateNewVariable");
+    SubscribeToEvent(container.GetChild("DeleteVarButton", true), "Released", "DeleteVariable");
+    return container;
+}
+
 void CreateAttributeInspectorWindow()
 {
     if (attributeInspectorWindow !is null)
@@ -69,7 +82,6 @@ void CreateAttributeInspectorWindow()
     attributeInspectorWindow.SetPosition(ui.root.width - 20 - attributeInspectorWindow.width, 40);
     attributeInspectorWindow.opacity = uiMaxOpacity;
     attributeInspectorWindow.BringToFront();
-    UpdateAttributeInspector();
 
     SubscribeToEvent(attributeInspectorWindow.GetChild("CloseButton", true), "Released", "HideAttributeInspectorWindow");
     SubscribeToEvent(attributeInspectorWindow, "LayoutUpdated", "HandleWindowLayoutUpdated");
@@ -92,6 +104,8 @@ void HandleWindowLayoutUpdated()
     for (uint i = 0; i < parentContainer.numChildren; ++i)
     {
         ListView@ list = GetContainer(i).GetChild("AttributeList");
+        if (list is null)
+            continue;
 
         // At the moment, only 'Is Enabled' container (place-holder + check box) is being created as child of the list view instead of as list item
         // When window resize and so the list's width is changed, adjust the 'Is enabled' container width so that check box stays at the right most position
@@ -119,57 +133,46 @@ void UpdateAttributeInspector(bool fullUpdate = true)
 
     // If full update delete all containers and added them back as necessary
     if (fullUpdate)
-    {
         DeleteAllContainers();
-        AddNodeContainer();
-        AddComponentContainer();
-    }
 
-    Text@ nodeTitle = nodeContainer.GetChild("TitleText");
-    String nodeType;
-    if (editNodes.length == 0)
-        nodeTitle.text = "No node";
-    else if (editNode !is null)
-    {
-        String idStr;
-        if (editNode.id >= FIRST_LOCAL_ID)
-            idStr = " Local ID " + String(editNode.id - FIRST_LOCAL_ID);
-        else
-            idStr = " ID " + String(editNode.id);
-        nodeType = editNode.typeName;
-        nodeTitle.text = nodeType + idStr;
-    }
-    else
+    if (!editNodes.empty)
     {
-        nodeType = editNodes[0].typeName;
-        nodeTitle.text = nodeType + " ID " + STRIKED_OUT + " (" + editNodes.length + "x)";
-    }
-    IconizeUIElement(nodeTitle, nodeType);
-
-    ListView@ list = nodeContainer.GetChild("AttributeList");
-    UpdateAttributes(ToSerializableArray(editNodes), list, fullUpdate);
+        UIElement@ container = GetNodeContainer();
 
-    if (fullUpdate)
-    {
-        //\TODO Avoid hardcoding
-        // Resize the node editor according to the number of variables, up to a certain maximum
-        uint maxAttrs = Clamp(list.contentElement.numChildren, MIN_NODE_ATTRIBUTES, MAX_NODE_ATTRIBUTES);
-        list.SetFixedHeight(maxAttrs * ATTR_HEIGHT + 2);
-        nodeContainer.SetFixedHeight(maxAttrs * ATTR_HEIGHT + 60);
-    }
+        Text@ nodeTitle = container.GetChild("TitleText");
+        String nodeType;
 
-    if (editComponents.empty)
-    {
-        Text@ componentTitle = GetComponentContainer(0).GetChild("TitleText");
-        if (selectedComponents.length <= 1)
-            componentTitle.text = "No component";
+        if (editNode !is null)
+        {
+            String idStr;
+            if (editNode.id >= FIRST_LOCAL_ID)
+                idStr = " Local ID " + String(editNode.id - FIRST_LOCAL_ID);
+            else
+                idStr = " ID " + String(editNode.id);
+            nodeType = editNode.typeName;
+            nodeTitle.text = nodeType + idStr;
+        }
         else
-            componentTitle.text = selectedComponents.length + " components";
+        {
+            nodeType = editNodes[0].typeName;
+            nodeTitle.text = nodeType + " ID " + STRIKED_OUT + " (" + editNodes.length + "x)";
+        }
+        IconizeUIElement(nodeTitle, nodeType);
+
+        ListView@ list = container.GetChild("AttributeList");
+        UpdateAttributes(ToSerializableArray(editNodes), list, fullUpdate);
 
-        // Ensure there is no icon
-        IconizeUIElement(componentTitle, "");
+        if (fullUpdate)
+        {
+            //\TODO Avoid hardcoding
+            // Resize the node editor according to the number of variables, up to a certain maximum
+            uint maxAttrs = Clamp(list.contentElement.numChildren, MIN_NODE_ATTRIBUTES, MAX_NODE_ATTRIBUTES);
+            list.SetFixedHeight(maxAttrs * ATTR_HEIGHT + 2);
+            container.SetFixedHeight(maxAttrs * ATTR_HEIGHT + 60);
+        }
     }
-    else
+
+    if (!editComponents.empty)
     {
         uint numEditableComponents = editComponents.length / numEditableComponentsPerNode;
         String multiplierText;
@@ -178,9 +181,6 @@ void UpdateAttributeInspector(bool fullUpdate = true)
 
         for (uint j = 0; j < numEditableComponentsPerNode; ++j)
         {
-            if (j >= parentContainer.numChildren - componentContainerStartIndex)
-                AddComponentContainer();
-
             Text@ componentTitle = GetComponentContainer(j).GetChild("TitleText");
             componentTitle.text = GetComponentTitle(editComponents[j * numEditableComponents]) + multiplierText;
             IconizeUIElement(componentTitle, editComponents[j * numEditableComponents].typeName);
@@ -194,33 +194,65 @@ void UpdateAttributeInspector(bool fullUpdate = true)
         }
     }
 
-    UpdateAttributeInspectorIcons();
+    if (!editUIElements.empty)
+    {
+        UIElement@ container = GetElementContainer();
+
+        Text@ titleText = container.GetChild("TitleText");
+        String elementType;
+
+        if (editUIElement !is null)
+        {
+            elementType = editUIElement.typeName;
+            titleText.text = elementType + " ID " + String(editUIElement.GetVar(UI_ELEMENT_ID_VAR).GetUInt());
+        }
+        else
+        {
+            elementType = editUIElements[0].typeName;
+            titleText.text = elementType + " ID " + STRIKED_OUT + " (" + editUIElements.length + "x)";
+        }
+        IconizeUIElement(titleText, elementType);
+
+        UpdateAttributes(editUIElements, container.GetChild("AttributeList"), fullUpdate);
+    }
+
+    if (parentContainer.numChildren > 0)
+        UpdateAttributeInspectorIcons();
+    else
+    {
+        // No editables, insert a dummy component container to show the information
+        Text@ titleText = GetComponentContainer(0).GetChild("TitleText");
+        titleText.text = "Select editable objects";
+    }
 }
 
 void UpdateNodeAttributes()
 {
-    UpdateAttributes(ToSerializableArray(editNodes), nodeContainer.GetChild("AttributeList"), false);
+    UpdateAttributes(ToSerializableArray(editNodes), GetNodeContainer().GetChild("AttributeList"), false);
 }
 
 void UpdateAttributeInspectorIcons()
 {
-    Text@ nodeTitle = nodeContainer.GetChild("TitleText");
-    if (editNode !is null)
-        SetIconEnabledColor(nodeTitle, editNode.enabled);
-    else if (editNodes.length > 0)
+    if (!editNodes.empty)
     {
-        bool hasSameEnabledState = true;
-
-        for (uint i = 1; i < editNodes.length; ++i)
+        Text@ nodeTitle = GetNodeContainer().GetChild("TitleText");
+        if (editNode !is null)
+            SetIconEnabledColor(nodeTitle, editNode.enabled);
+        else if (editNodes.length > 0)
         {
-            if (editNodes[i].enabled != editNodes[0].enabled)
+            bool hasSameEnabledState = true;
+
+            for (uint i = 1; i < editNodes.length; ++i)
             {
-                hasSameEnabledState = false;
-                break;
+                if (editNodes[i].enabled != editNodes[0].enabled)
+                {
+                    hasSameEnabledState = false;
+                    break;
+                }
             }
-        }
 
-        SetIconEnabledColor(nodeTitle, editNodes[0].enabled, !hasSameEnabledState);
+            SetIconEnabledColor(nodeTitle, editNodes[0].enabled, !hasSameEnabledState);
+        }
     }
 
     if (!editComponents.empty)
@@ -265,7 +297,7 @@ void PostEditAttribute(Array<Serializable@>@ serializables, uint index)
 
 void SetAttributeEditorID(UIElement@ attrEdit, Array<Serializable@>@ serializables)
 {
-    // All target serializables must be either nodes or components, so can check the first for the type
+    // All target serializables must be either nodes, ui-elements, or components
     Node@ node = cast<Node>(serializables[0]);
     Array<Variant> ids;
     if (node !is null)
@@ -276,9 +308,19 @@ void SetAttributeEditorID(UIElement@ attrEdit, Array<Serializable@>@ serializabl
     }
     else
     {
-        for (uint i = 0; i < serializables.length; ++i)
-            ids.Push(Variant(cast<Component>(serializables[i]).id));
-        attrEdit.vars[COMPONENT_IDS_VAR] = ids;
+        Component@ component = cast<Component>(serializables[0]);
+        if (component !is null)
+        {
+            for (uint i = 0; i < serializables.length; ++i)
+                ids.Push(Variant(cast<Component>(serializables[i]).id));
+            attrEdit.vars[COMPONENT_IDS_VAR] = ids;
+        }
+        else
+        {
+            for (uint i = 0; i < serializables.length; ++i)
+                ids.Push(cast<UIElement>(serializables[i]).GetVar(UI_ELEMENT_ID_VAR));
+            attrEdit.vars[COMPONENT_IDS_VAR] = ids;
+        }
     }
 }
 

+ 8 - 10
Bin/Data/Scripts/Editor/EditorScene.as

@@ -77,14 +77,13 @@ bool ResetScene()
 
     UpdateWindowTitle();
     UpdateHierarchyItem(editorScene, true);
-    UpdateAttributeInspector();
     ClearEditActions();
 
     suppressSceneChanges = false;
 
     ResetCamera();
     CreateGizmo();
-    
+
     return true;
 }
 
@@ -150,7 +149,6 @@ bool LoadScene(const String&in fileName)
 
     UpdateWindowTitle();
     UpdateHierarchyItem(editorScene, true);
-    UpdateAttributeInspector();
     ClearEditActions();
 
     suppressSceneChanges = false;
@@ -182,7 +180,7 @@ bool SaveScene(const String&in fileName)
 
     sceneModified = false;
     UpdateWindowTitle();
-    
+
     return true;
 }
 
@@ -450,7 +448,7 @@ bool ScenePaste()
             Node@ newNode = editorScene.CreateChild("", rootElem.GetBool("local") ? LOCAL : REPLICATED);
             newNode.LoadXML(rootElem);
             newNode.ApplyAttributes();
-            
+
             // Create an undo action for the paste
             CreateNodeAction action;
             action.Define(newNode);
@@ -519,7 +517,7 @@ bool SceneToggleEnable()
         if (selectedComponents[i].numAttributes > 0 && selectedComponents[i].attributeInfos[0].name == "Is Enabled")
             selectedComponents[i].enabled = !selectedComponents[i].enabled;
     }
-    
+
     return true;
 }
 
@@ -592,8 +590,8 @@ bool SceneSelectAll()
         hierarchyList.SetSelections(indices);
         EndSelectionModify();
     }
-    
-    return true; 
+
+    return true;
 }
 
 bool SceneUndo()
@@ -616,7 +614,7 @@ bool SceneRedo()
             undoStack[undoStackPos].actions[i].Redo();
         ++undoStackPos;
     }
-    
+
     return true;
 }
 
@@ -648,7 +646,7 @@ void SaveEditActionGroup(EditActionGroup@ group)
     undoStack.Resize(undoStackPos);
     undoStack.Push(group);
     ++undoStackPos;
-    
+
     SetSceneModified();
 }
 

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

@@ -743,7 +743,7 @@ void HandleCreateComponent(StringHash eventType, VariantMap& eventData)
         newComponent.ApplyAttributes();
         FocusComponent(newComponent);
     }
-    
+
     SetSceneModified();
 }
 

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

@@ -87,7 +87,6 @@ void OpenUIElement(const String&in fileName)
     }
 
     UpdateHierarchyItem(element, true);
-    UpdateAttributeInspector();
 
     suppressSceneChanges = false;
 }
@@ -117,7 +116,6 @@ bool CloseAllUIElements()
 
     editorUIElement.RemoveAllChildren();
     UpdateHierarchyItem(editorUIElement, true);
-    UpdateAttributeInspector();
 
     suppressUIElementChanges = false;
 

+ 1 - 1
Docs/ScriptAPI.dox

@@ -55,7 +55,7 @@ namespace Urho3D
 - void Print(uint, bool arg1 = false)
 - void Print(float, bool arg1 = false)
 - void Print(bool, bool arg1 = false)
-- void Print(Variant, bool arg1 = false)
+- void Print(const Variant&, bool arg1 = false)
 - void PrintCallStack(bool arg0 = false)
 - String GetPath(const String&)
 - String GetFileName(const String&)

+ 3 - 3
Engine/Engine/IOAPI.cpp

@@ -71,7 +71,7 @@ static void Print(bool value, bool error)
     Log::WriteRaw(String(value) + "\n", error);
 }
 
-static void Print(Variant value, bool error)
+static void Print(const Variant& value, bool error)
 {
     Log::WriteRaw(value.ToString() + "\n", error);
 }
@@ -115,7 +115,7 @@ static void Print(int value, bool error) {}
 static void Print(unsigned value, bool error) {}
 static void Print(float value, bool error) {}
 static void Print(bool value, bool error) {}
-static void Print(Variant value, bool error) {}
+static void Print(const Variant& value, bool error) {}
 static void PrintCallStack(bool error) {}
 static void LogWrite(const String& str, bool error, Log* ptr) {}
 static void LogDebug(const String& str, Log* ptr) {}
@@ -154,7 +154,7 @@ static void RegisterLog(asIScriptEngine* engine)
     engine->RegisterGlobalFunction("void Print(uint, bool error = false)", asFUNCTIONPR(Print, (unsigned, bool), void), asCALL_CDECL);
     engine->RegisterGlobalFunction("void Print(float, bool error = false)", asFUNCTIONPR(Print, (float, bool), void), asCALL_CDECL);
     engine->RegisterGlobalFunction("void Print(bool, bool error = false)", asFUNCTIONPR(Print, (bool, bool), void), asCALL_CDECL);
-    engine->RegisterGlobalFunction("void Print(Variant, bool error = false)", asFUNCTIONPR(Print, (Variant, bool), void), asCALL_CDECL);
+    engine->RegisterGlobalFunction("void Print(const Variant&in, bool error = false)", asFUNCTIONPR(Print, (const Variant&, bool), void), asCALL_CDECL);
     engine->RegisterGlobalFunction("void PrintCallStack(bool error = false)", asFUNCTION(PrintCallStack), asCALL_CDECL);
 }
 

+ 4 - 6
Engine/Script/Script.cpp

@@ -363,8 +363,8 @@ void Script::DumpAPI()
 
 void Script::MessageCallback(const asSMessageInfo* msg)
 {
-    String message = String(msg->section) + " (" + String(msg->row) + "," + String(msg->col) + ") " +
-        String(msg->message);
+    String message;
+    message.AppendWithFormat("%s:%d,%d %s", msg->section, msg->row, msg->col, msg->message);
     
     if (logMode_ == LOGMODE_IMMEDIATE)
     {
@@ -393,10 +393,8 @@ void Script::MessageCallback(const asSMessageInfo* msg)
 
 void Script::ExceptionCallback(asIScriptContext* context)
 {
-    asIScriptFunction *function = context->GetExceptionFunction();
-    String message = "Exception '" + String(context->GetExceptionString()) + "' in '" +
-        String(function->GetDeclaration()) + "'\n";
-    message += GetCallStack(context);
+    String message;
+    message.AppendWithFormat("- Exception '%s' in '%s'\n%s", context->GetExceptionString(), context->GetExceptionFunction()->GetDeclaration(), GetCallStack(context).CString());
     
     asSMessageInfo msg;
     msg.row = context->GetExceptionLineNumber(&msg.col, &msg.section);

+ 9 - 9
Engine/UI/BorderImage.cpp

@@ -57,14 +57,14 @@ BorderImage::~BorderImage()
 void BorderImage::RegisterObject(Context* context)
 {
     context->RegisterFactory<BorderImage>();
-    
+
+    COPY_BASE_ATTRIBUTES(BorderImage, UIElement);
     ACCESSOR_ATTRIBUTE(BorderImage, VAR_RESOURCEREF, "Texture", GetTextureAttr, SetTextureAttr, ResourceRef, ResourceRef(Texture2D::GetTypeStatic()), AM_FILE);
     REF_ACCESSOR_ATTRIBUTE(BorderImage, VAR_INTRECT, "Image Rect", GetImageRect, SetImageRect, IntRect, IntRect::ZERO, AM_FILE);
     REF_ACCESSOR_ATTRIBUTE(BorderImage, VAR_INTRECT, "Border", GetBorder, SetBorder, IntRect, IntRect::ZERO, AM_FILE);
     REF_ACCESSOR_ATTRIBUTE(BorderImage, VAR_INTVECTOR2, "Hover Image Offset", GetHoverOffset, SetHoverOffset, IntVector2, IntVector2::ZERO, AM_FILE);
     ACCESSOR_ATTRIBUTE(BorderImage, VAR_BOOL, "Tiled", IsTiled, SetTiled, bool, true, AM_FILE);
     ENUM_ACCESSOR_ATTRIBUTE(BorderImage, "Blend Mode", GetBlendMode, SetBlendMode, BlendMode, blendModeNames, 0, AM_FILE);
-    COPY_BASE_ATTRIBUTES(BorderImage, UIElement);
 }
 
 void BorderImage::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData, const IntRect& currentScissor)
@@ -125,20 +125,20 @@ void BorderImage::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vert
     if (GetDerivedOpacity() < 1.0f || color_[C_TOPLEFT].a_ < 1.0f || color_[C_TOPRIGHT].a_ < 1.0f ||
         color_[C_BOTTOMLEFT].a_ < 1.0f || color_[C_BOTTOMRIGHT].a_ < 1.0f)
         allOpaque = false;
-    
+
     UIBatch batch(this, blendMode_ == BLEND_REPLACE && !allOpaque ? BLEND_ALPHA : blendMode_, currentScissor, texture_, &vertexData);
-    
+
     // Calculate size of the inner rect, and texture dimensions of the inner rect
     int x = GetIndentWidth();
     IntVector2 size = GetSize();
     size.x_ -= x;
     IntVector2 innerSize(
-        Max(size.x_ - border_.left_ - border_.right_, 0), 
+        Max(size.x_ - border_.left_ - border_.right_, 0),
         Max(size.y_ - border_.top_ - border_.bottom_, 0));
     IntVector2 innerTextureSize(
         Max(imageRect_.right_ - imageRect_.left_ - border_.left_ - border_.right_, 0),
         Max(imageRect_.bottom_ - imageRect_.top_ - border_.top_ - border_.bottom_, 0));
-    
+
     IntVector2 topLeft(imageRect_.left_, imageRect_.top_);
     topLeft += offset;
 
@@ -171,7 +171,7 @@ void BorderImage::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vert
     if (border_.bottom_)
     {
         if (border_.left_)
-            batch.AddQuad(x, border_.top_ + innerSize.y_, border_.left_, border_.bottom_, topLeft.x_, topLeft.y_ + border_.top_ + 
+            batch.AddQuad(x, border_.top_ + innerSize.y_, border_.left_, border_.bottom_, topLeft.x_, topLeft.y_ + border_.top_ +
                 innerTextureSize.y_);
         if (innerSize.x_)
             batch.AddQuad(x + border_.left_, border_.top_ + innerSize.y_, innerSize.x_, border_.bottom_, topLeft.x_ +
@@ -180,9 +180,9 @@ void BorderImage::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vert
             batch.AddQuad(x + border_.left_ + innerSize.x_, border_.top_ + innerSize.y_, border_.right_, border_.bottom_,
                 topLeft.x_ + border_.left_ + innerTextureSize.x_, topLeft.y_ + border_.top_ + innerTextureSize.y_);
     }
-    
+
     UIBatch::AddOrMerge(batch, batches);
-    
+
     // Reset hovering for next frame
     hovering_ = false;
 }

+ 10 - 10
Engine/UI/Button.cpp

@@ -52,19 +52,19 @@ Button::~Button()
 void Button::RegisterObject(Context* context)
 {
     context->RegisterFactory<Button>();
-    
+
+    COPY_BASE_ATTRIBUTES(Button, BorderImage);
     REF_ACCESSOR_ATTRIBUTE(Button, VAR_INTVECTOR2, "Pressed Image Offset", GetPressedOffset, SetPressedOffset, IntVector2, IntVector2::ZERO, AM_FILE);
     REF_ACCESSOR_ATTRIBUTE(Button, VAR_INTVECTOR2, "Label Offset", GetLabelOffset, SetLabelOffset, IntVector2, IntVector2::ZERO, AM_FILE);
     ACCESSOR_ATTRIBUTE(Button, VAR_FLOAT, "Repeat Delay", GetRepeatDelay, SetRepeatDelay, float, 1.0f, AM_FILE);
     ACCESSOR_ATTRIBUTE(Button, VAR_FLOAT, "Repeat Rate", GetRepeatRate, SetRepeatRate, float, 0.0f, AM_FILE);
-    COPY_BASE_ATTRIBUTES(Button, BorderImage);
 }
 
 void Button::Update(float timeStep)
 {
     if (!hovering_ && pressed_)
         SetPressed(false);
-    
+
     // Send repeat events if pressed
     if (pressed_ && repeatRate_ > 0.0f)
     {
@@ -72,9 +72,9 @@ void Button::Update(float timeStep)
         if (repeatTimer_ <= 0.0f)
         {
             repeatTimer_ += 1.0f / repeatRate_;
-            
+
             using namespace Pressed;
-            
+
             VariantMap eventData;
             eventData[P_ELEMENT] = (void*)this;
             SendEvent(E_PRESSED, eventData);
@@ -89,7 +89,7 @@ void Button::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexDat
         offset += hoverOffset_;
     if (pressed_ || selected_)
         offset += pressedOffset_;
-    
+
     BorderImage::GetBatches(batches, vertexData, currentScissor, offset);
 }
 
@@ -101,9 +101,9 @@ void Button::OnHover(const IntVector2& position, const IntVector2& screenPositio
         if (!(buttons & MOUSEB_LEFT))
         {
             SetPressed(false);
-            
+
             using namespace Released;
-            
+
             VariantMap eventData;
             eventData[P_ELEMENT] = (void*)this;
             SendEvent(E_RELEASED, eventData);
@@ -118,9 +118,9 @@ void Button::OnClick(const IntVector2& position, const IntVector2& screenPositio
         SetPressed(true);
         repeatTimer_ = repeatDelay_;
         hovering_ = true;
-        
+
         using namespace Pressed;
-        
+
         VariantMap eventData;
         eventData[P_ELEMENT] = (void*)this;
         SendEvent(E_PRESSED, eventData);

+ 5 - 5
Engine/UI/CheckBox.cpp

@@ -48,10 +48,10 @@ CheckBox::~CheckBox()
 void CheckBox::RegisterObject(Context* context)
 {
     context->RegisterFactory<CheckBox>();
-    
+
+    COPY_BASE_ATTRIBUTES(CheckBox, BorderImage);
     ACCESSOR_ATTRIBUTE(CheckBox, VAR_BOOL,"Is Checked", IsChecked, SetChecked, bool, true, AM_FILE);
     REF_ACCESSOR_ATTRIBUTE(CheckBox, VAR_INTVECTOR2,"Checked Image Offset", GetCheckedOffset, SetCheckedOffset, IntVector2, IntVector2::ZERO, AM_FILE);
-    COPY_BASE_ATTRIBUTES(CheckBox, BorderImage);
 }
 
 void CheckBox::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData, const IntRect& currentScissor)
@@ -61,7 +61,7 @@ void CheckBox::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexD
         offset += hoverOffset_;
     if (checked_)
         offset += checkedOffset_;
-    
+
     BorderImage::GetBatches(batches, vertexData, currentScissor, offset);
 }
 
@@ -76,9 +76,9 @@ void CheckBox::SetChecked(bool enable)
     if (enable != checked_)
     {
         checked_ = enable;
-        
+
         using namespace Toggled;
-        
+
         VariantMap eventData;
         eventData[P_ELEMENT] = (void*)this;
         eventData[P_STATE] = checked_;

+ 12 - 12
Engine/UI/Cursor.cpp

@@ -55,7 +55,7 @@ Cursor::Cursor(Context* context) :
 {
     // Show on top of all other UI elements
     priority_ = M_MAX_INT;
-    
+
     for (unsigned i = 0; i < CS_MAX_SHAPES; ++i)
     {
         CursorShapeInfo& info = shapeInfos_[i];
@@ -81,9 +81,9 @@ Cursor::~Cursor()
 void Cursor::RegisterObject(Context* context)
 {
     context->RegisterFactory<Cursor>();
-    
-    ACCESSOR_ATTRIBUTE(Cursor, VAR_VARIANTVECTOR, "Shapes", GetShapesAttr, SetShapesAttr, VariantVector, Variant::emptyVariantVector, AM_FILE);
+
     COPY_BASE_ATTRIBUTES(Cursor, BorderImage);
+    ACCESSOR_ATTRIBUTE(Cursor, VAR_VARIANTVECTOR, "Shapes", GetShapesAttr, SetShapesAttr, VariantVector, Variant::emptyVariantVector, AM_FILE);
 }
 
 void Cursor::DefineShape(CursorShape shape, Image* image, const IntRect& imageRect, const IntVector2& hotSpot, bool osMouseVisible)
@@ -106,13 +106,13 @@ void Cursor::DefineShape(CursorShape shape, Image* image, const IntRect& imageRe
         int imageWidth = image->GetWidth();
         int width = imageRect.Width();
         int height = imageRect.Height();
-        
+
         // Assume little-endian for all the supported platforms
         unsigned rMask = 0x000000ff;
         unsigned gMask = 0x0000ff00;
         unsigned bMask = 0x00ff0000;
         unsigned aMask = 0xff000000;
-        
+
         SDL_Surface* surface = (comp >= 3 ? SDL_CreateRGBSurface(0, width, height, comp * 8, rMask, gMask, bMask, aMask) : 0);
         if (surface)
         {
@@ -143,12 +143,12 @@ void Cursor::SetShape(CursorShape shape)
         return;
 
     shape_ = shape;
-    
+
     CursorShapeInfo& info = shapeInfos_[shape_];
     texture_ = info.texture_;
     imageRect_ = info.imageRect_;
     SetSize(info.imageRect_.Size());
-    
+
     if (info.osCursor_)
         SDL_SetCursor(info.osCursor_);
 }
@@ -158,7 +158,7 @@ void Cursor::SetShapesAttr(VariantVector value)
     unsigned index = 0;
     if (!value.Size())
         return;
-    
+
     Input* input = GetSubsystem<Input>();
     bool osMouseVisible = input->IsMouseVisible();
 
@@ -181,14 +181,14 @@ void Cursor::SetShapesAttr(VariantVector value)
 VariantVector Cursor::GetShapesAttr() const
 {
     VariantVector ret;
-    
+
     unsigned numShapes = 0;
     for (unsigned i = 0; i < CS_MAX_SHAPES; ++i)
     {
         if (shapeInfos_[i].imageRect_ != IntRect::ZERO)
             ++numShapes;
     }
-    
+
     ret.Push(numShapes);
     for (unsigned i = 0; i < CS_MAX_SHAPES; ++i)
     {
@@ -200,7 +200,7 @@ VariantVector Cursor::GetShapesAttr() const
             ret.Push(shapeInfos_[i].hotSpot_);
         }
     }
-    
+
     return ret;
 }
 
@@ -209,7 +209,7 @@ void Cursor::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexDat
     unsigned initialSize = vertexData.Size();
     const IntVector2& offset = shapeInfos_[shape_].hotSpot_;
     Vector2 floatOffset(-(float)offset.x_, -(float)offset.y_);
-    
+
     BorderImage::GetBatches(batches, vertexData, currentScissor);
     for (unsigned i = initialSize; i < vertexData.Size(); i += 6)
     {

+ 41 - 41
Engine/UI/LineEdit.cpp

@@ -53,13 +53,13 @@ LineEdit::LineEdit(Context* context) :
     clipChildren_ = true;
     enabled_ = true;
     focusMode_ = FM_FOCUSABLE_DEFOCUSABLE;
-    
+
     text_ = CreateChild<Text>();
     text_->SetInternal(true);
     cursor_ = CreateChild<BorderImage>();
     cursor_->SetInternal(true);
     cursor_->SetPriority(1); // Show over text
-    
+
     SubscribeToEvent(this, E_FOCUSED, HANDLER(LineEdit, HandleFocused));
     SubscribeToEvent(this, E_DEFOCUSED, HANDLER(LineEdit, HandleDefocused));
 }
@@ -71,7 +71,8 @@ LineEdit::~LineEdit()
 void LineEdit::RegisterObject(Context* context)
 {
     context->RegisterFactory<LineEdit>();
-    
+
+    COPY_BASE_ATTRIBUTES(LineEdit, BorderImage);
     ACCESSOR_ATTRIBUTE(LineEdit, VAR_INT, "Max Length", GetMaxLength, SetMaxLength, unsigned, 0, AM_FILE);
     ACCESSOR_ATTRIBUTE(LineEdit, VAR_BOOL, "Is Cursor Movable", IsCursorMovable, SetCursorMovable, bool, true, AM_FILE);
     ACCESSOR_ATTRIBUTE(LineEdit, VAR_BOOL, "Is Text Selectable", IsTextSelectable, SetTextSelectable, bool, true, AM_FILE);
@@ -79,13 +80,12 @@ void LineEdit::RegisterObject(Context* context)
     ACCESSOR_ATTRIBUTE(LineEdit, VAR_FLOAT, "Cursor Blink Rate", GetCursorBlinkRate, SetCursorBlinkRate, float, 1.0f, AM_FILE);
     ATTRIBUTE(LineEdit, VAR_INT, "Echo Character", echoCharacter_, 0, AM_FILE);
     ACCESSOR_ATTRIBUTE(LineEdit, VAR_FLOAT, "Double Click Interval", GetDoubleClickInterval, SetDoubleClickInterval, float, 0.5f, AM_FILE);
-    COPY_BASE_ATTRIBUTES(LineEdit, BorderImage);
 }
 
 void LineEdit::ApplyAttributes()
 {
     BorderImage::ApplyAttributes();
-    
+
     // Set the text's position to match clipping, so that text left edge is not left partially hidden
     text_->SetPosition(clipBorder_.left_, clipBorder_.top_);
 }
@@ -94,7 +94,7 @@ void LineEdit::Update(float timeStep)
 {
     if (cursorBlinkRate_ > 0.0f)
         cursorBlinkTimer_ = fmodf(cursorBlinkTimer_ + cursorBlinkRate_ * timeStep, 1.0f);
-    
+
     // Update cursor position if font has changed
     if (text_->GetFont() != lastFont_ || text_->GetFontSize() != lastFontSize_)
     {
@@ -102,7 +102,7 @@ void LineEdit::Update(float timeStep)
         lastFontSize_ = text_->GetFontSize();
         UpdateCursor();
     }
-   
+
     bool cursorVisible = HasFocus() ? cursorBlinkTimer_ < 0.5f : false;
     cursor_->SetVisible(cursorVisible);
 }
@@ -154,7 +154,7 @@ bool LineEdit::OnDragDropTest(UIElement* source)
         ShortStringHash sourceType = source->GetType();
         return sourceType == LineEdit::GetTypeStatic() || sourceType == Text::GetTypeStatic();
     }
-    
+
     return false;
 }
 
@@ -176,7 +176,7 @@ bool LineEdit::OnDragDropFinish(UIElement* source)
             return true;
         }
     }
-    
+
     return false;
 }
 
@@ -184,7 +184,7 @@ void LineEdit::OnKey(int key, int buttons, int qualifiers)
 {
     bool changed = false;
     bool cursorMoved = false;
-    
+
     switch (key)
     {
     case 'X':
@@ -193,10 +193,10 @@ void LineEdit::OnKey(int key, int buttons, int qualifiers)
         {
             unsigned start = text_->GetSelectionStart();
             unsigned length = text_->GetSelectionLength();
-            
+
             if (text_->GetSelectionLength())
                 GetSubsystem<UI>()->SetClipBoardText(line_.SubstringUTF8(start, length));
-            
+
             if (key == 'X')
             {
                 if (start + length < line_.LengthUTF8())
@@ -209,7 +209,7 @@ void LineEdit::OnKey(int key, int buttons, int qualifiers)
             }
         }
         break;
-        
+
     case 'V':
         if (textCopyable_ && qualifiers & QUAL_CTRL)
         {
@@ -237,11 +237,11 @@ void LineEdit::OnKey(int key, int buttons, int qualifiers)
             }
         }
         break;
-        
+
     case KEY_HOME:
         qualifiers |= QUAL_CTRL;
         // Fallthru
-            
+
     case KEY_LEFT:
         if (!(qualifiers & QUAL_SHIFT))
             text_->ClearSelection();
@@ -249,13 +249,13 @@ void LineEdit::OnKey(int key, int buttons, int qualifiers)
         {
             if (textSelectable_ && qualifiers & QUAL_SHIFT && !text_->GetSelectionLength())
                 dragBeginCursor_ = cursorPosition_;
-            
+
             if (qualifiers & QUAL_CTRL)
                 cursorPosition_ = 0;
             else
                 --cursorPosition_;
             cursorMoved = true;
-            
+
             if (textSelectable_ && qualifiers & QUAL_SHIFT)
             {
                 unsigned start = dragBeginCursor_;
@@ -267,7 +267,7 @@ void LineEdit::OnKey(int key, int buttons, int qualifiers)
             }
         }
         break;
-        
+
     case KEY_END:
         qualifiers |= QUAL_CTRL;
         // Fallthru
@@ -279,13 +279,13 @@ void LineEdit::OnKey(int key, int buttons, int qualifiers)
         {
             if (textSelectable_ && qualifiers & QUAL_SHIFT && !text_->GetSelectionLength())
                 dragBeginCursor_ = cursorPosition_;
-            
+
             if (qualifiers & QUAL_CTRL)
                 cursorPosition_ = line_.LengthUTF8();
             else
                 ++cursorPosition_;
             cursorMoved = true;
-            
+
             if (textSelectable_ && qualifiers & QUAL_SHIFT)
             {
                 unsigned start = dragBeginCursor_;
@@ -297,7 +297,7 @@ void LineEdit::OnKey(int key, int buttons, int qualifiers)
             }
         }
         break;
-        
+
     case KEY_DELETE:
         if (!text_->GetSelectionLength())
         {
@@ -321,14 +321,14 @@ void LineEdit::OnKey(int key, int buttons, int qualifiers)
             changed = true;
         }
         break;
-        
+
     case KEY_UP:
     case KEY_DOWN:
     case KEY_PAGEUP:
     case KEY_PAGEDOWN:
         {
             using namespace UnhandledKey;
-            
+
             VariantMap eventData;
             eventData[P_ELEMENT] = (void*)this;
             eventData[P_KEY] = key;
@@ -337,7 +337,7 @@ void LineEdit::OnKey(int key, int buttons, int qualifiers)
             SendEvent(E_UNHANDLEDKEY, eventData);
         }
         return;
-        
+
     case KEY_BACKSPACE:
         if (!text_->GetSelectionLength())
         {
@@ -365,13 +365,13 @@ void LineEdit::OnKey(int key, int buttons, int qualifiers)
             changed = true;
         }
         break;
-        
+
     case KEY_RETURN:
     case KEY_RETURN2:
     case KEY_KP_ENTER:
         {
             using namespace TextFinished;
-            
+
             VariantMap eventData;
             eventData[P_ELEMENT] = (void*)this;
             eventData[P_TEXT] = line_;
@@ -380,7 +380,7 @@ void LineEdit::OnKey(int key, int buttons, int qualifiers)
         }
         break;
     }
-    
+
     if (changed)
     {
         UpdateText();
@@ -393,11 +393,11 @@ void LineEdit::OnKey(int key, int buttons, int qualifiers)
 void LineEdit::OnChar(unsigned c, int buttons, int qualifiers)
 {
     bool changed = false;
-    
+
     // If only CTRL is held down, do not edit
     if ((qualifiers & (QUAL_CTRL | QUAL_ALT)) == QUAL_CTRL)
         return;
-    
+
     if (c >= 0x20 && (!maxLength_ || line_.LengthUTF8() < maxLength_))
     {
         String charStr;
@@ -424,7 +424,7 @@ void LineEdit::OnChar(unsigned c, int buttons, int qualifiers)
         }
         changed = true;
     }
-    
+
     if (changed)
     {
         text_->ClearSelection();
@@ -448,7 +448,7 @@ void LineEdit::SetCursorPosition(unsigned position)
 {
     if (position > line_.LengthUTF8() || !cursorMovable_)
         position = line_.LengthUTF8();
-    
+
     if (position != cursorPosition_)
     {
         cursorPosition_ = position;
@@ -459,7 +459,7 @@ void LineEdit::SetCursorPosition(unsigned position)
 void LineEdit::SetCursorBlinkRate(float rate)
 {
     cursorBlinkRate_ = Max(rate, 0.0f);
-    
+
     if (cursorBlinkRate_ == 0.0f)
         cursorBlinkTimer_ = 0.0f;   // Cursor does not blink, i.e. always visible
 }
@@ -503,7 +503,7 @@ float LineEdit::GetDoubleClickInterval() const
 void LineEdit::UpdateText()
 {
     unsigned utf8Length = line_.LengthUTF8();
-    
+
     if (!echoCharacter_)
         text_->SetText(line_);
     else
@@ -518,9 +518,9 @@ void LineEdit::UpdateText()
         cursorPosition_ = utf8Length;
         UpdateCursor();
     }
-    
+
     using namespace TextChanged;
-    
+
     VariantMap eventData;
     eventData[P_ELEMENT] = (void*)this;
     eventData[P_TEXT] = line_;
@@ -533,11 +533,11 @@ void LineEdit::UpdateCursor()
     const PODVector<IntVector2>& charPositions = text_->GetCharPositions();
     if (charPositions.Size())
         x = cursorPosition_ < charPositions.Size() ? charPositions[cursorPosition_].x_ : charPositions.Back().x_;
-    
+
     text_->SetPosition(clipBorder_.left_, clipBorder_.top_);
     cursor_->SetPosition(text_->GetPosition() + IntVector2(x, 0));
     cursor_->SetSize(cursor_->GetWidth(), text_->GetRowHeight());
-    
+
     // Scroll if necessary
     int sx = -GetChildOffset().x_;
     int left = clipBorder_.left_;
@@ -549,7 +549,7 @@ void LineEdit::UpdateCursor()
     if (sx < 0)
         sx = 0;
     SetChildOffset(IntVector2(-sx, 0));
-    
+
     // Restart blinking
     cursorBlinkTimer_ = 0.0f;
 }
@@ -559,16 +559,16 @@ unsigned LineEdit::GetCharIndex(const IntVector2& position)
     IntVector2 screenPosition = ElementToScreen(position);
     IntVector2 textPosition = text_->ScreenToElement(screenPosition);
     const PODVector<IntVector2>& charPositions = text_->GetCharPositions();
-    
+
     if (textPosition.x_ < 0)
         return 0;
-    
+
     for (unsigned i = charPositions.Size() - 1; i < charPositions.Size(); --i)
     {
         if (textPosition.x_ >= charPositions[i].x_)
             return i;
     }
-    
+
     return M_MAX_UNSIGNED;
 }
 

+ 23 - 23
Engine/UI/ListView.cpp

@@ -162,7 +162,7 @@ ListView::ListView(Context* context) :
     ScrollView(context),
     highlightMode_(HM_FOCUS),
     multiselect_(false),
-    hierarchyMode_(true),	// Init to true here so that the setter below takes effect
+    hierarchyMode_(true),    // Init to true here so that the setter below takes effect
     baseIndent_(0),
     clearSelectionOnDefocus_(false),
     doubleClickInterval_(500),
@@ -185,13 +185,13 @@ void ListView::RegisterObject(Context* context)
 {
     context->RegisterFactory<ListView>();
 
+    COPY_BASE_ATTRIBUTES(ListView, ScrollView);
     ENUM_ACCESSOR_ATTRIBUTE(ListView, "Highlight Mode", GetHighlightMode, SetHighlightMode, HighlightMode, highlightModes, HM_FOCUS, AM_FILE);
     ACCESSOR_ATTRIBUTE(ListView, VAR_BOOL, "Multiselect", GetMultiselect, SetMultiselect, bool, false, AM_FILE);
     ACCESSOR_ATTRIBUTE(ListView, VAR_BOOL, "Hierarchy Mode", GetHierarchyMode, SetHierarchyMode, bool, false, AM_FILE);
     ACCESSOR_ATTRIBUTE(ListView, VAR_INT, "Base Indent", GetBaseIndent, SetBaseIndent, int, 0, AM_FILE);
     ACCESSOR_ATTRIBUTE(ListView, VAR_BOOL, "Clear Sel. On Defocus", GetClearSelectionOnDefocus, SetClearSelectionOnDefocus, bool, false, AM_FILE);
     ACCESSOR_ATTRIBUTE(ListView, VAR_FLOAT, "Double Click Interval", GetDoubleClickInterval, SetDoubleClickInterval, float, 0.5f, AM_FILE);
-    COPY_BASE_ATTRIBUTES(ListView, ScrollView);
 }
 
 void ListView::OnKey(int key, int buttons, int qualifiers)
@@ -407,10 +407,10 @@ void ListView::RemoveItem(UIElement* item, unsigned index)
                 if (i > 0)
                 {
                     int baseIndent = item->GetIndent();
-                    UIElement* prevKin = GetItem(i - 1);		// Could be parent or sibling
+                    UIElement* prevKin = GetItem(i - 1);        // Could be parent or sibling
                     if (prevKin->GetIndent() < baseIndent)
                     {
-                        UIElement* nextKin = GetItem(i + 1);	// Could be sibling or parent-sibling or 0 if index out of bound
+                        UIElement* nextKin = GetItem(i + 1);    // Could be sibling or parent-sibling or 0 if index out of bound
                         if (!nextKin || nextKin->GetIndent() < baseIndent)
                         {
                             // If we reach here then the parent has no other children
@@ -471,9 +471,9 @@ void ListView::SetSelections(const PODVector<unsigned>& indices)
 {
     // Make a weak pointer to self to check for destruction as a response to events
     WeakPtr<ListView> self(this);
-    
+
     unsigned numItems = GetNumItems();
-    
+
     // Remove first items that should no longer be selected
     for (PODVector<unsigned>::Iterator i = selections_.Begin(); i != selections_.End();)
     {
@@ -481,23 +481,23 @@ void ListView::SetSelections(const PODVector<unsigned>& indices)
         if (!indices.Contains(index))
         {
             i = selections_.Erase(i);
-            
+
             using namespace ItemSelected;
-            
+
             VariantMap eventData;
             eventData[P_ELEMENT] = (void*)this;
             eventData[P_SELECTION] = index;
             SendEvent(E_ITEMDESELECTED, eventData);
-            
+
             if (self.Expired())
                 return;
         }
         else
             ++i;
     }
-    
+
     bool added = false;
-    
+
     // Then add missing items
     for (PODVector<unsigned>::ConstIterator i = indices.Begin(); i != indices.End(); ++i)
     {
@@ -513,14 +513,14 @@ void ListView::SetSelections(const PODVector<unsigned>& indices)
                     selections_.Push(index);
                     added = true;
                 }
-                
+
                 using namespace ItemSelected;
-                
+
                 VariantMap eventData;
                 eventData[P_ELEMENT] = (void*)this;
                 eventData[P_SELECTION] = *i;
                 SendEvent(E_ITEMSELECTED, eventData);
-                
+
                 if (self.Expired())
                     return;
             }
@@ -529,11 +529,11 @@ void ListView::SetSelections(const PODVector<unsigned>& indices)
         if (!multiselect_)
             break;
     }
-    
+
     // Re-sort selections if necessary
     if (added)
         Sort(selections_.Begin(), selections_.End());
-    
+
     UpdateSelectionEffect();
     SendEvent(E_SELECTIONCHANGED);
 }
@@ -542,31 +542,31 @@ void ListView::AddSelection(unsigned index)
 {
     // Make a weak pointer to self to check for destruction as a response to events
     WeakPtr<ListView> self(this);
-    
+
     if (!multiselect_)
         SetSelection(index);
     else
     {
         if (index >= GetNumItems())
             return;
-        
+
         if (!selections_.Contains(index))
         {
             selections_.Push(index);
-            
+
             using namespace ItemSelected;
-            
+
             VariantMap eventData;
             eventData[P_ELEMENT] = (void*)this;
             eventData[P_SELECTION] = index;
             SendEvent(E_ITEMSELECTED, eventData);
-            
+
             if (self.Expired())
                 return;
-            
+
             Sort(selections_.Begin(), selections_.End());
         }
-        
+
         EnsureItemVisibility(index);
         UpdateSelectionEffect();
         SendEvent(E_SELECTIONCHANGED);

+ 37 - 37
Engine/UI/Menu.cpp

@@ -59,9 +59,9 @@ Menu::~Menu()
 void Menu::RegisterObject(Context* context)
 {
     context->RegisterFactory<Menu>();
-    
-    REF_ACCESSOR_ATTRIBUTE(Menu, VAR_INTVECTOR2, "Popup Offset", GetPopupOffset, SetPopupOffset, IntVector2, IntVector2::ZERO, AM_FILE);
+
     COPY_BASE_ATTRIBUTES(Menu, Button);
+    REF_ACCESSOR_ATTRIBUTE(Menu, VAR_INTVECTOR2, "Popup Offset", GetPopupOffset, SetPopupOffset, IntVector2, IntVector2::ZERO, AM_FILE);
 }
 
 void Menu::OnHover(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
@@ -87,7 +87,7 @@ void Menu::OnHover(const IntVector2& position, const IntVector2& screenPosition,
         }
     }
 }
-    
+
 void Menu::OnShowPopup()
 {
 }
@@ -101,16 +101,16 @@ bool Menu::LoadXML(const XMLElement& source, XMLFile* styleFile)
         String styleName = source.GetAttribute("style");
         if (styleName.Empty())
             styleName = GetTypeName();
-        
+
         SetStyle(styleFile, styleName);
     }
-    
+
     // Then load rest of the attributes from the source
     if (!Serializable::LoadXML(source))
         return false;
-    
+
     unsigned nextInternalChild = 0;
-    
+
     // Load child elements. Internal elements are not to be created as they already exist
     XMLElement childElem = source.GetChild("element");
     while (childElem)
@@ -121,7 +121,7 @@ bool Menu::LoadXML(const XMLElement& source, XMLFile* styleFile)
         if (typeName.Empty())
             typeName = "UIElement";
         UIElement* child = 0;
-        
+
         if (!internalElem)
         {
             if (!popupElem)
@@ -155,23 +155,23 @@ bool Menu::LoadXML(const XMLElement& source, XMLFile* styleFile)
                         break;
                     }
                 }
-                
+
                 if (!child)
                     LOGWARNING("Could not find matching internal child element of type " + typeName + " in " + GetTypeName());
             }
         }
-        
+
         if (child)
         {
             if (!child->LoadXML(childElem, styleFile))
                 return false;
         }
-        
+
         childElem = childElem.GetNext("element");
     }
-    
+
     ApplyAttributes();
-    
+
     return true;
 }
 
@@ -185,11 +185,11 @@ bool Menu::SaveXML(XMLElement& dest)
         if (!dest.SetBool("internal", internal_))
             return false;
     }
-    
+
     // Write attributes
     if (!Serializable::SaveXML(dest))
         return false;
-    
+
     // Write child elements
     for (unsigned i = 0; i < children_.Size(); ++i)
     {
@@ -198,7 +198,7 @@ bool Menu::SaveXML(XMLElement& dest)
         if (!element->SaveXML(childElem))
             return false;
     }
-    
+
     // Save the popup element as a "virtual" child element
     if (popup_)
     {
@@ -207,7 +207,7 @@ bool Menu::SaveXML(XMLElement& dest)
         if (!popup_->SaveXML(childElem))
             return false;
     }
-    
+
     return true;
 }
 
@@ -215,12 +215,12 @@ void Menu::SetPopup(UIElement* popup)
 {
     if (popup == this)
         return;
-    
+
     if (popup_ && !popup)
         ShowPopup(false);
-    
+
     popup_ = popup;
-    
+
     // Detach from current parent (if any) to only show when it is time
     if (popup_)
         popup_->Remove();
@@ -240,16 +240,16 @@ void Menu::ShowPopup(bool enable)
 {
     if (!popup_)
         return;
-    
+
     if (enable)
     {
         // Find the UI root element for showing the popup
         UIElement* root = GetRoot();
         if (!root)
             return;
-        
+
         OnShowPopup();
-        
+
         if (popup_->GetParent() != root)
             root->AddChild(popup_);
         popup_->SetPosition(GetScreenPosition() + popupOffset_);
@@ -268,12 +268,12 @@ void Menu::ShowPopup(bool enable)
             if (menu)
                 menu->ShowPopup(false);
         }
-        
+
         popup_->SetVar(originHash, Variant::EMPTY);
         popup_->SetVisible(false);
         popup_->Remove();
     }
-    
+
     showPopup_ = enable;
     selected_ = enable;
 }
@@ -282,7 +282,7 @@ void Menu::SetAccelerator(int key, int qualifiers)
 {
     acceleratorKey_ = key;
     acceleratorQualifiers_ = qualifiers;
-    
+
     if (key)
         SubscribeToEvent(E_KEYDOWN, HANDLER(Menu, HandleKeyDown));
     else
@@ -302,15 +302,15 @@ void Menu::HandlePressedReleased(StringHash eventType, VariantMap& eventData)
         if (popup_)
             return;
     }
-    
+
     // Toggle popup visibility if exists
     ShowPopup(!showPopup_);
-    
+
     // Send event on each click if no popup, or whenever the popup is opened
     if (!popup_ || showPopup_)
     {
         using namespace MenuSelected;
-        
+
         VariantMap newEventData;
         newEventData[P_ELEMENT] = (void*)this;
         SendEvent(E_MENUSELECTED, newEventData);
@@ -321,23 +321,23 @@ void Menu::HandleFocusChanged(StringHash eventType, VariantMap& eventData)
 {
     if (!showPopup_)
         return;
-    
+
     using namespace FocusChanged;
-    
+
     UIElement* element = static_cast<UIElement*>(eventData[P_ELEMENT].GetPtr());
     UIElement* root = GetRoot();
-    
+
     // If another element was focused due to the menu button being clicked, do not hide the popup
     if (eventType == E_FOCUSCHANGED && static_cast<UIElement*>(eventData[P_CLICKEDELEMENT].GetPtr()))
         return;
-    
+
     // If clicked emptiness or defocused, hide the popup
     if (!element)
     {
         ShowPopup(false);
         return;
     }
-    
+
     // Otherwise see if the clicked element has either the menu item or the popup in its parent chain.
     // In that case, do not hide
     while (element)
@@ -349,7 +349,7 @@ void Menu::HandleFocusChanged(StringHash eventType, VariantMap& eventData)
         else
             element = element->GetParent();
     }
-    
+
     ShowPopup(false);
 }
 
@@ -357,9 +357,9 @@ void Menu::HandleKeyDown(StringHash eventType, VariantMap& eventData)
 {
     if (!enabled_)
         return;
-    
+
     using namespace KeyDown;
-    
+
     // Activate if accelerator key pressed
     if (eventData[P_KEY].GetInt() == acceleratorKey_ && (acceleratorQualifiers_ == QUAL_ANY || eventData[P_QUALIFIERS].GetInt() ==
         acceleratorQualifiers_) && eventData[P_REPEAT].GetBool() == false)

+ 12 - 12
Engine/UI/ScrollBar.cpp

@@ -49,7 +49,7 @@ ScrollBar::ScrollBar(Context* context) :
     downRect_(IntRect::ZERO)
 {
     enabled_ = true;
-    
+
     backButton_ = CreateChild<Button>();
     backButton_->SetInternal(true);
     backButton_->SetRepeat(DEFAULT_REPEAT_DELAY, DEFAULT_REPEAT_RATE);
@@ -59,12 +59,12 @@ ScrollBar::ScrollBar(Context* context) :
     forwardButton_ = CreateChild<Button>();
     forwardButton_->SetInternal(true);
     forwardButton_->SetRepeat(DEFAULT_REPEAT_DELAY, DEFAULT_REPEAT_RATE);
-    
+
     SubscribeToEvent(backButton_, E_PRESSED, HANDLER(ScrollBar, HandleBackButtonPressed));
     SubscribeToEvent(forwardButton_, E_PRESSED, HANDLER(ScrollBar, HandleForwardButtonPressed));
     SubscribeToEvent(slider_, E_SLIDERCHANGED, HANDLER(ScrollBar, HandleSliderChanged));
     SubscribeToEvent(slider_, E_SLIDERPAGED, HANDLER(ScrollBar, HandleSliderPaged));
-    
+
     // Set default orientation/layout
     SetOrientation(O_HORIZONTAL);
 }
@@ -76,7 +76,8 @@ ScrollBar::~ScrollBar()
 void ScrollBar::RegisterObject(Context* context)
 {
     context->RegisterFactory<ScrollBar>();
-    
+
+    COPY_BASE_ATTRIBUTES(ScrollBar, UIElement);
     ENUM_ACCESSOR_ATTRIBUTE(ScrollBar, "Orientation", GetOrientation, SetOrientation, Orientation, orientations, O_HORIZONTAL, AM_FILE);
     ACCESSOR_ATTRIBUTE(ScrollBar, VAR_FLOAT, "Range", GetRange, SetRange, float, 1.0f, AM_FILE);
     ACCESSOR_ATTRIBUTE(ScrollBar, VAR_FLOAT, "Value", GetValue, SetValue, float, 0.0f, AM_FILE);
@@ -86,13 +87,12 @@ void ScrollBar::RegisterObject(Context* context)
     ATTRIBUTE(ScrollBar, VAR_INTRECT, "Right Image Rect", rightRect_, IntRect::ZERO, AM_FILE);
     ATTRIBUTE(ScrollBar, VAR_INTRECT, "Up Image Rect", upRect_, IntRect::ZERO, AM_FILE);
     ATTRIBUTE(ScrollBar, VAR_INTRECT, "Down Image Rect", downRect_, IntRect::ZERO, AM_FILE);
-    COPY_BASE_ATTRIBUTES(ScrollBar, UIElement);
 }
 
 void ScrollBar::ApplyAttributes()
 {
     UIElement::ApplyAttributes();
-    
+
     // Reapply orientation to the button images
     if (slider_->GetOrientation() == O_HORIZONTAL)
     {
@@ -110,7 +110,7 @@ void ScrollBar::OnResize()
 {
     // Disable layout operations while setting the button sizes is incomplete
     DisableLayoutUpdate();
-    
+
     if (slider_->GetOrientation() == O_HORIZONTAL)
     {
         int height = GetHeight();
@@ -123,14 +123,14 @@ void ScrollBar::OnResize()
         backButton_->SetFixedSize(width, width);
         forwardButton_->SetFixedSize(width, width);
     }
-    
+
     EnableLayoutUpdate();
 }
 
 void ScrollBar::SetOrientation(Orientation orientation)
 {
     slider_->SetOrientation(orientation);
-    
+
     if (orientation == O_HORIZONTAL)
     {
         backButton_->SetImageRect(leftRect_);
@@ -141,7 +141,7 @@ void ScrollBar::SetOrientation(Orientation orientation)
         backButton_->SetImageRect(upRect_);
         forwardButton_->SetImageRect(downRect_);
     }
-    
+
     OnResize();
     if (orientation == O_HORIZONTAL)
         SetLayout(LM_HORIZONTAL);
@@ -218,7 +218,7 @@ void ScrollBar::HandleSliderChanged(StringHash eventType, VariantMap& eventData)
 {
     // Send the event forward
     VariantMap newEventData;
-    
+
     newEventData[ScrollBarChanged::P_ELEMENT] = (void*)this;
     newEventData[ScrollBarChanged::P_VALUE] = slider_->GetValue();
     SendEvent(E_SCROLLBARCHANGED, newEventData);
@@ -227,7 +227,7 @@ void ScrollBar::HandleSliderChanged(StringHash eventType, VariantMap& eventData)
 void ScrollBar::HandleSliderPaged(StringHash eventType, VariantMap& eventData)
 {
     using namespace SliderPaged;
- 
+
     if (eventData[P_BUTTONS].GetInt() & MOUSEB_LEFT)
     {
         if (eventData[P_OFFSET].GetInt() < 0)

+ 32 - 32
Engine/UI/ScrollView.cpp

@@ -50,7 +50,7 @@ ScrollView::ScrollView(Context* context) :
     clipChildren_ = true;
     enabled_ = true;
     focusMode_ = FM_FOCUSABLE_DEFOCUSABLE;
-    
+
     horizontalScrollBar_ = CreateChild<ScrollBar>();
     horizontalScrollBar_->SetInternal(true);
     horizontalScrollBar_->SetAlignment(HA_LEFT, VA_BOTTOM);
@@ -63,7 +63,7 @@ ScrollView::ScrollView(Context* context) :
     scrollPanel_->SetInternal(true);
     scrollPanel_->SetEnabled(true);
     scrollPanel_->SetClipChildren(true);
-    
+
     SubscribeToEvent(horizontalScrollBar_, E_SCROLLBARCHANGED, HANDLER(ScrollView, HandleScrollBarChanged));
     SubscribeToEvent(horizontalScrollBar_, E_VISIBLECHANGED, HANDLER(ScrollView, HandleScrollBarVisibleChanged));
     SubscribeToEvent(verticalScrollBar_, E_SCROLLBARCHANGED, HANDLER(ScrollView, HandleScrollBarChanged));
@@ -77,28 +77,28 @@ ScrollView::~ScrollView()
 void ScrollView::RegisterObject(Context* context)
 {
     context->RegisterFactory<ScrollView>();
-    
+
+    COPY_BASE_ATTRIBUTES(ScrollView, UIElement);
     REF_ACCESSOR_ATTRIBUTE(ScrollView, VAR_INTVECTOR2, "View Position", GetViewPosition, SetViewPositionAttr, IntVector2, IntVector2::ZERO, AM_FILE);
     ACCESSOR_ATTRIBUTE(ScrollView, VAR_FLOAT, "Scroll Step", GetScrollStep, SetScrollStep, float, 0.1f, AM_FILE);
     ACCESSOR_ATTRIBUTE(ScrollView, VAR_FLOAT, "Page Step", GetPageStep, SetPageStep, float, 1.0f, AM_FILE);
     ACCESSOR_ATTRIBUTE(ScrollView, VAR_BOOL, "Auto Show/Hide Scrollbars", GetScrollBarsAutoVisible, SetScrollBarsAutoVisible, bool, true, AM_FILE);
-    COPY_BASE_ATTRIBUTES(ScrollView, UIElement);
 }
 
 void ScrollView::ApplyAttributes()
 {
     UIElement::ApplyAttributes();
-    
+
     // Set the scrollbar orientations again and perform size update now that the style is known
     horizontalScrollBar_->SetOrientation(O_HORIZONTAL);
     verticalScrollBar_->SetOrientation(O_VERTICAL);
-    
+
     // If the scroll panel has a child, it should be the content element, which has some special handling
     if (scrollPanel_->GetNumChildren())
         SetContentElement(scrollPanel_->GetChild(0));
-    
+
     OnResize();
-    
+
     // Reapply view position with proper content element and size
     SetViewPosition(viewPositionAttr_);
 }
@@ -124,7 +124,7 @@ void ScrollView::OnKey(int key, int buttons, int qualifiers)
                 horizontalScrollBar_->StepBack();
         }
         break;
-        
+
     case KEY_RIGHT:
         if (horizontalScrollBar_->IsVisible())
         {
@@ -134,11 +134,11 @@ void ScrollView::OnKey(int key, int buttons, int qualifiers)
                 horizontalScrollBar_->StepForward();
         }
         break;
-        
+
     case KEY_HOME:
         qualifiers |= QUAL_CTRL;
         // Fallthru
-        
+
     case KEY_UP:
         if (verticalScrollBar_->IsVisible())
         {
@@ -148,11 +148,11 @@ void ScrollView::OnKey(int key, int buttons, int qualifiers)
                 verticalScrollBar_->StepBack();
         }
         break;
-        
+
     case KEY_END:
         qualifiers |= QUAL_CTRL;
         // Fallthru
-        
+
     case KEY_DOWN:
         if (verticalScrollBar_->IsVisible())
         {
@@ -162,12 +162,12 @@ void ScrollView::OnKey(int key, int buttons, int qualifiers)
                 verticalScrollBar_->StepForward();
         }
         break;
-        
+
     case KEY_PAGEUP:
         if (verticalScrollBar_->IsVisible())
             verticalScrollBar_->ChangeValue(-pageStep_);
         break;
-        
+
     case KEY_PAGEDOWN:
         if (verticalScrollBar_->IsVisible())
             verticalScrollBar_->ChangeValue(pageStep_);
@@ -179,7 +179,7 @@ void ScrollView::OnResize()
 {
     UpdatePanelSize();
     UpdateViewSize();
-    
+
     // If scrollbar autovisibility is enabled, check whether scrollbars should be visible.
     // This may force another update of the panel size
     if (scrollBarsAutoVisible_)
@@ -188,7 +188,7 @@ void ScrollView::OnResize()
         horizontalScrollBar_->SetVisible(horizontalScrollBar_->GetRange() > M_EPSILON);
         verticalScrollBar_->SetVisible(verticalScrollBar_->GetRange() > M_EPSILON);
         ignoreEvents_ = false;
-        
+
         UpdatePanelSize();
     }
 }
@@ -197,7 +197,7 @@ void ScrollView::SetContentElement(UIElement* element)
 {
     if (element == contentElement_)
         return;
-    
+
     if (contentElement_)
     {
         scrollPanel_->RemoveChild(contentElement_);
@@ -209,7 +209,7 @@ void ScrollView::SetContentElement(UIElement* element)
         scrollPanel_->AddChild(contentElement_);
         SubscribeToEvent(contentElement_, E_RESIZED, HANDLER(ScrollView, HandleElementResized));
     }
-    
+
     OnResize();
 }
 
@@ -269,24 +269,24 @@ void ScrollView::UpdatePanelSize()
     // Ignore events in case content element resizes itself along with the panel
     // (content element resize triggers our OnResize(), so it could lead to infinite recursion)
     ignoreEvents_ = true;
-    
+
     IntVector2 panelSize = GetSize();
     if (verticalScrollBar_->IsVisible())
         panelSize.x_ -= verticalScrollBar_->GetWidth();
     if (horizontalScrollBar_->IsVisible())
         panelSize.y_ -= horizontalScrollBar_->GetHeight();
-    
+
     scrollPanel_->SetSize(panelSize);
     horizontalScrollBar_->SetWidth(scrollPanel_->GetWidth());
     verticalScrollBar_->SetHeight(scrollPanel_->GetHeight());
-    
+
     if (resizeContentWidth_ && contentElement_)
     {
         IntRect panelBorder = scrollPanel_->GetClipBorder();
         contentElement_->SetWidth(scrollPanel_->GetWidth() - panelBorder.left_ - panelBorder.right_);
         UpdateViewSize();
     }
-    
+
     ignoreEvents_ = false;
 }
 
@@ -296,10 +296,10 @@ void ScrollView::UpdateViewSize()
     if (contentElement_)
         size = contentElement_->GetSize();
     IntRect panelBorder = scrollPanel_->GetClipBorder();
-    
+
     viewSize_.x_ = Max(size.x_, scrollPanel_->GetWidth() - panelBorder.left_ - panelBorder.right_);
     viewSize_.y_ = Max(size.y_, scrollPanel_->GetHeight() - panelBorder.top_ - panelBorder.bottom_);
-    
+
     UpdateView(viewPosition_);
     UpdateScrollBars();
 }
@@ -307,12 +307,12 @@ void ScrollView::UpdateViewSize()
 void ScrollView::UpdateScrollBars()
 {
     ignoreEvents_ = true;
-    
+
     IntVector2 size = scrollPanel_->GetSize();
     IntRect panelBorder = scrollPanel_->GetClipBorder();
     size.x_ -= panelBorder.left_ + panelBorder.right_;
     size.y_ -= panelBorder.top_ + panelBorder.bottom_;
-    
+
     if (size.x_ > 0 && viewSize_.x_ > 0)
     {
         float range = (float)viewSize_.x_ / (float)size.x_ - 1.0f;
@@ -327,7 +327,7 @@ void ScrollView::UpdateScrollBars()
         verticalScrollBar_->SetValue((float)viewPosition_.y_ / (float)size.y_);
         verticalScrollBar_->SetStepFactor(STEP_FACTOR / (float)size.y_);
     }
-    
+
     ignoreEvents_ = false;
 }
 
@@ -337,15 +337,15 @@ void ScrollView::UpdateView(const IntVector2& position)
     IntRect panelBorder = scrollPanel_->GetClipBorder();
     IntVector2 panelSize(scrollPanel_->GetWidth() - panelBorder.left_ - panelBorder.right_, scrollPanel_->GetHeight() -
         panelBorder.top_ - panelBorder.bottom_);
-    
+
     viewPosition_.x_ = Clamp(position.x_, 0, viewSize_.x_ - panelSize.x_);
     viewPosition_.y_ = Clamp(position.y_, 0, viewSize_.y_ - panelSize.y_);
     scrollPanel_->SetChildOffset(IntVector2(-viewPosition_.x_ + panelBorder.left_, -viewPosition_.y_ + panelBorder.top_));
-    
+
     if (viewPosition_ != oldPosition)
     {
         using namespace ViewChanged;
-        
+
         VariantMap eventData;
         eventData[P_ELEMENT] = (void*)this;
         eventData[P_X] = viewPosition_.x_;
@@ -362,7 +362,7 @@ void ScrollView::HandleScrollBarChanged(StringHash eventType, VariantMap& eventD
         IntRect panelBorder = scrollPanel_->GetClipBorder();
         size.x_ -= panelBorder.left_ + panelBorder.right_;
         size.y_ -= panelBorder.top_ + panelBorder.bottom_;
-        
+
         UpdateView(IntVector2(
             (int)(horizontalScrollBar_->GetValue() * (float)size.x_),
             (int)(verticalScrollBar_->GetValue() * (float)size.y_)

+ 13 - 13
Engine/UI/Slider.cpp

@@ -57,7 +57,7 @@ Slider::Slider(Context* context) :
     enabled_ = true;
     knob_ = CreateChild<BorderImage>();
     knob_->SetInternal(true);
-    
+
     UpdateSlider();
 }
 
@@ -68,19 +68,19 @@ Slider::~Slider()
 void Slider::RegisterObject(Context* context)
 {
     context->RegisterFactory<Slider>();
-    
+
+    COPY_BASE_ATTRIBUTES(Slider, BorderImage);
     ENUM_ACCESSOR_ATTRIBUTE(Slider, "Orientation", GetOrientation, SetOrientation, Orientation, orientations, O_HORIZONTAL, AM_FILE);
     ACCESSOR_ATTRIBUTE(Slider, VAR_FLOAT, "Range", GetRange, SetRange, float, 1.0f, AM_FILE);
     ACCESSOR_ATTRIBUTE(Slider, VAR_FLOAT, "Value", GetValue, SetValue, float, 0.0f, AM_FILE);
     ACCESSOR_ATTRIBUTE(Slider, VAR_FLOAT, "Repeat Rate", GetRepeatRate, SetRepeatRate, float, 0.0f, AM_FILE);
-    COPY_BASE_ATTRIBUTES(Slider, BorderImage);
 }
 
 void Slider::Update(float timeStep)
 {
     if (dragSlider_)
         hovering_ = true;
-    
+
     // Propagate hover effect to the slider knob
     knob_->SetHovering(hovering_);
     knob_->SetSelected(hovering_);
@@ -89,10 +89,10 @@ void Slider::Update(float timeStep)
 void Slider::OnHover(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
 {
     BorderImage::OnHover(position, screenPosition, buttons, qualifiers, cursor);
-    
+
     // Show hover effect if inside the slider knob
     hovering_ = knob_->IsInside(screenPosition, true);
-    
+
     // If not hovering on the knob, send it as page event
     if (!hovering_)
         Page(position, buttons, qualifiers);
@@ -118,10 +118,10 @@ void Slider::OnDragMove(const IntVector2& position, const IntVector2& screenPosi
 {
     if (!dragSlider_ || GetSize() == knob_->GetSize())
         return;
-    
+
     float newValue = value_;
     IntVector2 delta = position - dragBeginCursor_;
-    
+
     if (orientation_ == O_HORIZONTAL)
     {
         int newX = Clamp(dragBeginPosition_.x_ + delta.x_, 0, GetWidth() - knob_->GetWidth());
@@ -134,7 +134,7 @@ void Slider::OnDragMove(const IntVector2& position, const IntVector2& screenPosi
         knob_->SetPosition(0, newY);
         newValue = (float)newY * range_ / (float)(GetHeight() - knob_->GetHeight());
     }
-    
+
     SetValue(newValue);
 }
 
@@ -172,9 +172,9 @@ void Slider::SetValue(float value)
     {
         value_ = value;
         UpdateSlider();
-        
+
         using namespace SliderChanged;
-        
+
         VariantMap eventData;
         eventData[P_ELEMENT] = (void*)this;
         eventData[P_VALUE] = value_;
@@ -195,7 +195,7 @@ void Slider::SetRepeatRate(float rate)
 void Slider::UpdateSlider()
 {
     const IntRect& border = knob_->GetBorder();
-    
+
     if (range_ > 0.0f)
     {
         if (orientation_ == O_HORIZONTAL)
@@ -227,7 +227,7 @@ void Slider::Page(const IntVector2& position, int buttons, int qualifiers)
     float length = (float)(orientation_ == O_HORIZONTAL ? GetWidth() : GetHeight());
 
     using namespace SliderPaged;
-    
+
     VariantMap eventData;
     eventData[P_ELEMENT] = (void*)this;
     eventData[P_OFFSET] = offset;

+ 3 - 2
Engine/UI/Sprite.cpp

@@ -56,14 +56,15 @@ void Sprite::RegisterObject(Context* context)
 {
     context->RegisterFactory<Sprite>();
     
-    ACCESSOR_ATTRIBUTE(Sprite, VAR_RESOURCEREF, "Texture", GetTextureAttr, SetTextureAttr, ResourceRef, ResourceRef(Texture2D::GetTypeStatic()), AM_FILE);
-    ENUM_ACCESSOR_ATTRIBUTE(Sprite, "Blend Mode", GetBlendMode, SetBlendMode, BlendMode, blendModeNames, 0, AM_FILE);
     REF_ACCESSOR_ATTRIBUTE(Sprite, VAR_STRING, "Name", GetName, SetName, String, String::EMPTY, AM_FILE);
     REF_ACCESSOR_ATTRIBUTE(Sprite, VAR_VECTOR2, "Position", GetPosition, SetPosition, Vector2, Vector2::ZERO, AM_FILE);
     REF_ACCESSOR_ATTRIBUTE(Sprite, VAR_INTVECTOR2, "Size", GetSize, SetSize, IntVector2, IntVector2::ZERO, AM_FILE);
     REF_ACCESSOR_ATTRIBUTE(Sprite, VAR_INTVECTOR2, "Hotspot", GetHotSpot, SetHotSpot, IntVector2, IntVector2::ZERO, AM_FILE);
     REF_ACCESSOR_ATTRIBUTE(Sprite, VAR_VECTOR2, "Scale", GetScale, SetScale, Vector2, Vector2::ZERO, AM_FILE);
     ACCESSOR_ATTRIBUTE(Sprite, VAR_FLOAT, "Rotation", GetRotation, SetRotation, float, 0.0f, AM_FILE);
+    ACCESSOR_ATTRIBUTE(Sprite, VAR_RESOURCEREF, "Texture", GetTextureAttr, SetTextureAttr, ResourceRef, ResourceRef(Texture2D::GetTypeStatic()), AM_FILE);
+    REF_ACCESSOR_ATTRIBUTE(Sprite, VAR_INTRECT, "Image Rect", GetImageRect, SetImageRect, IntRect, IntRect::ZERO, AM_FILE);
+    ENUM_ACCESSOR_ATTRIBUTE(Sprite, "Blend Mode", GetBlendMode, SetBlendMode, BlendMode, blendModeNames, 0, AM_FILE);
     ENUM_ACCESSOR_ATTRIBUTE(Sprite, "Horiz Alignment", GetHorizontalAlignment, SetHorizontalAlignment, HorizontalAlignment, horizontalAlignments, HA_LEFT, AM_FILE);
     ENUM_ACCESSOR_ATTRIBUTE(Sprite, "Vert Alignment", GetVerticalAlignment, SetVerticalAlignment, VerticalAlignment, verticalAlignments, VA_TOP, AM_FILE);
     ACCESSOR_ATTRIBUTE(Sprite, VAR_INT, "Priority", GetPriority, SetPriority, int, 0, AM_FILE);

+ 49 - 49
Engine/UI/Text.cpp

@@ -84,7 +84,8 @@ Text::~Text()
 void Text::RegisterObject(Context* context)
 {
     context->RegisterFactory<Text>();
-    
+
+    COPY_BASE_ATTRIBUTES(Text, UIElement);
     ACCESSOR_ATTRIBUTE(Text, VAR_RESOURCEREF, "Font", GetFontAttr, SetFontAttr, ResourceRef, ResourceRef(Font::GetTypeStatic()), AM_FILE);
     ATTRIBUTE(Text, VAR_INT, "Font Size", fontSize_, DEFAULT_FONT_SIZE, AM_FILE);
     ATTRIBUTE(Text, VAR_STRING, "Text", text_, String::EMPTY, AM_FILE);
@@ -93,8 +94,7 @@ void Text::RegisterObject(Context* context)
     ATTRIBUTE(Text, VAR_BOOL, "Word Wrap", wordWrap_, false, AM_FILE);
     REF_ACCESSOR_ATTRIBUTE(Text, VAR_COLOR, "Selection Color", GetSelectionColor, SetSelectionColor, Color, Color::TRANSPARENT, AM_FILE);
     REF_ACCESSOR_ATTRIBUTE(Text, VAR_COLOR, "Hover Color", GetHoverColor, SetHoverColor, Color, Color::TRANSPARENT, AM_FILE);
-    COPY_BASE_ATTRIBUTES(Text, UIElement);
-    
+
     // Change the default value for UseDerivedOpacity
     context->GetAttribute<Text>("Use Derived Opacity")->defaultValue_ = false;
 }
@@ -102,12 +102,12 @@ void Text::RegisterObject(Context* context)
 void Text::ApplyAttributes()
 {
     UIElement::ApplyAttributes();
-    
+
     // Decode to Unicode now
     unicodeText_.Clear();
     for (unsigned i = 0; i < text_.Length();)
         unicodeText_.Push(text_.NextUTF8Char(i));
-    
+
     fontSize_ = Max(fontSize_, 1);
     ValidateSelection();
     UpdateText();
@@ -124,12 +124,12 @@ void Text::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData,
             (selected_ && selectionColor_.a_ > 0.0f ? selectionColor_ : hoverColor_));
         UIBatch::AddOrMerge(batch, batches);
     }
-    
+
     // Partial selection batch
     if (!selected_ && selectionLength_ && charSizes_.Size() >= selectionStart_ + selectionLength_ && selectionColor_.a_ > 0.0f)
     {
         UIBatch batch(this, BLEND_ALPHA, currentScissor, 0, &vertexData);
-        
+
         IntVector2 currentStart = charPositions_[selectionStart_];
         IntVector2 currentEnd = currentStart;
         for (unsigned i = selectionStart_; i < selectionStart_ + selectionLength_; ++i)
@@ -156,10 +156,10 @@ void Text::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData,
             batch.AddQuad(currentStart.x_, currentStart.y_, currentEnd.x_ - currentStart.x_, currentEnd.y_ - currentStart.y_,
                 0, 0, 0, 0, selectionColor_);
         }
-        
+
         UIBatch::AddOrMerge(batch, batches);
     }
-    
+
     // Text batch
     if (font_)
     {
@@ -171,23 +171,23 @@ void Text::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData,
         {
             // Only traversing thru the printText once regardless of number of textures/pages in the font
             Vector<PODVector<GlyphLocation> > pageGlyphLocations(face->textures_.Size());
-            
+
             unsigned rowIndex = 0;
             int x = GetRowStartPosition(rowIndex);
             int y = 0;
-            
+
             for (unsigned i = 0; i < printText_.Size(); ++i)
             {
                 unsigned c = printText_[i];
-                
+
                 if (c != '\n')
                 {
                     const FontGlyph* p = face->GetGlyph(c);
                     if (!p)
                         continue;
-                    
+
                     pageGlyphLocations[p->page_].Push(GlyphLocation(x, y, p));
-                    
+
                     x += p->advanceX_;
                     if (i < printText_.Size() - 1)
                         x += face->GetKerning(c, printText_[i + 1]);
@@ -198,12 +198,12 @@ void Text::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData,
                     y += rowHeight_;
                 }
             }
-            
+
             for (unsigned n = 0; n < face->textures_.Size(); ++n)
             {
                 // One batch per texture/page
                 UIBatch pageBatch(this, BLEND_ALPHA, currentScissor, face->textures_[n], &vertexData);
-                
+
                 const PODVector<GlyphLocation>& pageGlyphLocation = pageGlyphLocations[n];
                 for (unsigned i = 0; i < pageGlyphLocation.Size(); ++i)
                 {
@@ -211,7 +211,7 @@ void Text::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData,
                     const FontGlyph& glyph = *glyphLocation.glyph_;
                     pageBatch.AddQuad(glyphLocation.x_ + glyph.offsetX_, glyphLocation.y_ + glyph.offsetY_, glyph.width_, glyph.height_, glyph.x_, glyph.y_);
                 }
-                
+
                 batches.Push(pageBatch);
             }
         }
@@ -221,21 +221,21 @@ void Text::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData,
             unsigned rowIndex = 0;
             int x = GetRowStartPosition(rowIndex);
             int y = 0;
-            
+
             UIBatch batch(this, BLEND_ALPHA, currentScissor, face->textures_[0], &vertexData);
-            
+
             for (unsigned i = 0; i < printText_.Size(); ++i)
             {
                 unsigned c = printText_[i];
-                
+
                 if (c != '\n')
                 {
                     const FontGlyph* p = face->GetGlyph(c);
                     if (!p)
                         continue;
-                    
+
                     batch.AddQuad(x + p->offsetX_, y + p->offsetY_, p->width_, p->height_, p->x_, p->y_);
-                    
+
                     x += p->advanceX_;
                     if (i < printText_.Size() - 1)
                         x += face->GetKerning(c, printText_[i + 1]);
@@ -246,11 +246,11 @@ void Text::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData,
                     y += rowHeight_;
                 }
             }
-            
+
             UIBatch::AddOrMerge(batch, batches);
         }
     }
-    
+
     // Reset hovering for next frame
     hovering_ = false;
 }
@@ -274,26 +274,26 @@ bool Text::SetFont(Font* font, int size)
         LOGERROR("Null font for Text");
         return false;
     }
-    
+
     if (font != font_ || size != fontSize_)
     {
         font_ = font;
         fontSize_ = Max(size, 1);
         UpdateText();
     }
-    
+
     return true;
 }
 
 void Text::SetText(const String& text)
 {
     text_ = text;
-    
+
     // Decode to Unicode now
     unicodeText_.Clear();
     for (unsigned i = 0; i < text_.Length();)
         unicodeText_.Push(text_.NextUTF8Char(i));
-    
+
     ValidateSelection();
     UpdateText();
 }
@@ -363,22 +363,22 @@ void Text::UpdateText(bool inResize)
 {
     int width = 0;
     int height = 0;
-    
+
     rowWidths_.Clear();
     printText_.Clear();
-    
+
     PODVector<unsigned> printToText;
-    
+
     if (font_)
     {
         const FontFace* face = font_->GetFace(fontSize_);
         if (!face)
             return;
-        
+
         rowHeight_ = face->rowHeight_;
         int rowWidth = 0;
         int rowHeight = (int)(rowSpacing_ * rowHeight_);
-        
+
         // First see if the text must be split up
         if (!wordWrap_)
         {
@@ -396,11 +396,11 @@ void Text::UpdateText(bool inResize)
             {
                 unsigned j;
                 unsigned c = unicodeText_[i];
-                
+
                 if (c != '\n')
                 {
                     bool ok = true;
-                    
+
                     if (nextBreak <= i)
                     {
                         int futureRowWidth = rowWidth;
@@ -431,7 +431,7 @@ void Text::UpdateText(bool inResize)
                             }
                         }
                     }
-                    
+
                     if (!ok)
                     {
                         // If did not find any breaks on the line, copy until j, or at least 1 char, to prevent infinite loop
@@ -449,7 +449,7 @@ void Text::UpdateText(bool inResize)
                         rowWidth = 0;
                         nextBreak = lineStart = i;
                     }
-                    
+
                     if (i < unicodeText_.Size())
                     {
                         // When copying a space, position is allowed to be over row width
@@ -477,13 +477,13 @@ void Text::UpdateText(bool inResize)
                 }
             }
         }
-        
+
         rowWidth = 0;
-        
+
         for (unsigned i = 0; i < printText_.Size(); ++i)
         {
             unsigned c = printText_[i];
-            
+
             if (c != '\n')
             {
                 const FontGlyph* glyph = face->GetGlyph(c);
@@ -502,22 +502,22 @@ void Text::UpdateText(bool inResize)
                 rowWidth = 0;
             }
         }
-        
+
         if (rowWidth)
         {
             width = Max(width, rowWidth);
             height += rowHeight;
             rowWidths_.Push(rowWidth);
         }
-        
+
         // Set row height even if text is empty
         if (!height)
             height = rowHeight;
-        
+
         // Store position & size of each character
         charPositions_.Resize(unicodeText_.Size() + 1);
         charSizes_.Resize(unicodeText_.Size());
-        
+
         unsigned rowIndex = 0;
         int x = GetRowStartPosition(rowIndex);
         int y = 0;
@@ -546,7 +546,7 @@ void Text::UpdateText(bool inResize)
         // Store the ending position
         charPositions_[unicodeText_.Size()] = IntVector2(x, y);
     }
-    
+
     // Set minimum and current size according to the text size, but respect fixed width if set
     if (GetMinWidth() != GetMaxWidth())
     {
@@ -559,7 +559,7 @@ void Text::UpdateText(bool inResize)
 void Text::ValidateSelection()
 {
     unsigned textLength = unicodeText_.Size();
-    
+
     if (textLength)
     {
         if (selectionStart_ >= textLength)
@@ -577,10 +577,10 @@ void Text::ValidateSelection()
 int Text::GetRowStartPosition(unsigned rowIndex) const
 {
     int rowWidth = 0;
-    
+
     if (rowIndex < rowWidths_.Size())
         rowWidth = rowWidths_[rowIndex];
-    
+
     int ret = GetIndentWidth();
 
     switch (textAlignment_)
@@ -594,7 +594,7 @@ int Text::GetRowStartPosition(unsigned rowIndex) const
         ret += GetSize().x_ - rowWidth;
         break;
     }
-    
+
     return ret;
 }
 

+ 1 - 1
Engine/UI/Window.cpp

@@ -61,6 +61,7 @@ void Window::RegisterObject(Context* context)
 {
     context->RegisterFactory<Window>();
 
+    COPY_BASE_ATTRIBUTES(Window, BorderImage);
     REF_ACCESSOR_ATTRIBUTE(Window, VAR_INTRECT, "Resize Border", GetResizeBorder, SetResizeBorder, IntRect, IntRect(DEFAULT_RESIZE_BORDER, \
         DEFAULT_RESIZE_BORDER, DEFAULT_RESIZE_BORDER, DEFAULT_RESIZE_BORDER), AM_FILE);
     ACCESSOR_ATTRIBUTE(Window, VAR_BOOL, "Is Movable", IsMovable, SetMovable, bool, false, AM_FILE);
@@ -69,7 +70,6 @@ void Window::RegisterObject(Context* context)
     REF_ACCESSOR_ATTRIBUTE(Window, VAR_COLOR, "Modal Shade Color", GetModalShadeColor, SetModalShadeColor, Color, Color::TRANSPARENT, AM_FILE);
     REF_ACCESSOR_ATTRIBUTE(Window, VAR_COLOR, "Modal Frame Color", GetModalFrameColor, SetModalFrameColor, Color, Color::TRANSPARENT, AM_FILE);
     REF_ACCESSOR_ATTRIBUTE(Window, VAR_INTVECTOR2, "Modal Frame Size", GetModalFrameSize, SetModalFrameSize, IntVector2, IntVector2::ZERO, AM_FILE);
-    COPY_BASE_ATTRIBUTES(Window, BorderImage);
 }
 
 void Window::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData, const IntRect& currentScissor)