Browse Source

Completed the UI element refactoring. Removed hardcoded SetStyle() functions which would read UI element attributes from XML.
Added SaveLayout() function to UI.
Fixed serialization & deserialization of IntRect & IntVector2 variants.
Fixed crash when querying a BorderImage's texture in script.

Lasse Öörni 13 years ago
parent
commit
4cef5395f5

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

@@ -61,6 +61,7 @@ void HandleUpdate(StringHash eventType, VariantMap& eventData)
     UpdateStats(timeStep);
     UpdateStats(timeStep);
     UpdateScene(timeStep);
     UpdateScene(timeStep);
     UpdateGizmo();
     UpdateGizmo();
+    UpdateView();
 }
 }
 
 
 void LoadConfig()
 void LoadConfig()

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

@@ -158,6 +158,16 @@ void UpdateStats(float timeStep)
     cameraPosText.size = cameraPosText.minSize;
     cameraPosText.size = cameraPosText.minSize;
 }
 }
 
 
+void UpdateView()
+{
+    // Update audio listener
+    audio.listenerPosition = cameraNode.position;
+    audio.listenerRotation = cameraNode.rotation;
+    
+    // Update camera fill mode
+    camera.fillMode = fillMode;
+}
+
 void MoveCamera(float timeStep)
 void MoveCamera(float timeStep)
 {
 {
     // Move camera
     // Move camera
@@ -251,13 +261,6 @@ void MoveCamera(float timeStep)
         if (moved)
         if (moved)
             UpdateNodeAttributes();
             UpdateNodeAttributes();
     }
     }
-    
-    // Update audio listener
-    audio.listenerPosition = cameraNode.position;
-    audio.listenerRotation = cameraNode.rotation;
-    
-    // Update camera fill mode
-    camera.fillMode = fillMode;
 }
 }
 
 
 void SteppedObjectManipulation(int key)
 void SteppedObjectManipulation(int key)
@@ -506,5 +509,5 @@ void ToggleOctreeDebug()
 
 
 void ToggleUpdate()
 void ToggleUpdate()
 {
 {
-    runUpdate  = !runUpdate;
+    runUpdate = !runUpdate;
 }
 }

+ 434 - 349
Bin/Data/UI/DefaultStyle.xml

@@ -1,411 +1,496 @@
 <elements>
 <elements>
     <element type="Button">
     <element type="Button">
-        <size value="16 16" />
-        <texture name="Textures/UI.png" />
-        <imagerect value="16 0 32 16" />
-        <border value="4 4 4 4" />
-        <pressedoffset value="16 0" />
-        <hoveroffset value="0 16" />
-        <labeloffset value="-1 1" />
+        <attribute name="Size" value="16 16" />
+        <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+        <attribute name="Image Rect" value="16 0 32 16" />
+        <attribute name="Border" value="4 4 4 4" />
+        <attribute name="Pressed Image Offset" value="16 0" />
+        <attribute name="Hover Image Offset" value="0 16" />
+        <attribute name="Label Offset" value="-1 1" />
     </element>
     </element>
     <element type="CheckBox">
     <element type="CheckBox">
-        <size value="16 16" />
-        <texture name="Textures/UI.png" />
-        <imagerect value="64 0 80 16" />
-        <border value="4 4 4 4" />
-        <checkedoffset value="16 0" />
-        <hoveroffset value="0 16" />
+        <attribute name="Size" value="16 16" />
+        <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+        <attribute name="Image Rect" value="64 0 80 16" />
+        <attribute name="Border" value="4 4 4 4" />
+        <attribute name="Checked Image Offset" value="16 0" />
+        <attribute name="Hover Image Offset" value="0 16" />
     </element>
     </element>
     <element type="CloseButton">
     <element type="CloseButton">
-        <fixedsize value="16 16" />
-        <texture name="Textures/UI.png" />
-        <imagerect value="128 0 144 16" />
-        <border value="4 4 4 4" />
-        <pressedoffset value="16 0" />
-        <hoveroffset value="0 16" />
-        <labeloffset value="-1 1" />
+        <attribute name="Size" value="16 16" />
+        <attribute name="Min Size" value="16 16" />
+        <attribute name="Max Size" value="16 16" />
+        <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+        <attribute name="Image Rect" value="128 0 144 16" />
+        <attribute name="Border" value="4 4 4 4" />
+        <attribute name="Pressed Image Offset" value="16 0" />
+        <attribute name="Hover Image Offset" value="0 16" />
+        <attribute name="Label Offset" value="-1 1" />
     </element>
     </element>
     <element type="Cursor">
     <element type="Cursor">
-        <shape name="normal" texture="Textures/UI.png" imagerect="0 0 12 24" hotspot="0 0" />
-        <shape name="resizevertical" texture="Textures/UI.png" imagerect="0 64 20 84" hotspot="9 9" />
-        <shape name="resizediagonal_topright" texture="Textures/UI.png" imagerect="20 64 40 84" hotspot="9 9" />
-        <shape name="resizehorizontal" texture="Textures/UI.png" imagerect="40 64 60 84" hotspot="9 9" />
-        <shape name="resizediagonal_topleft" texture="Textures/UI.png" imagerect="60 64 80 84" hotspot="9 9" />
-        <shape name="rejectdrop" texture="Textures/UI.png" imagerect="80 64 100 84" hotspot="9 9" />
-        <shape name="acceptdrop" texture="Textures/UI.png" imagerect="100 64 128 90" hotspot="0 0" />
+        <attribute name="Shapes">
+            <variant type="Int" value="7" />
+            <variant type="String" value="Normal" />
+            <variant type="ResourceRef" value="Texture2D;Textures/UI.png" />
+            <variant type="IntRect" value="0 0 12 24" />
+            <variant type="IntVector2" value="0 0" />
+            <variant type="String" value="ResizeVertical" />
+            <variant type="ResourceRef" value="Texture2D;Textures/UI.png" />
+            <variant type="IntRect" value="0 64 20 84" />
+            <variant type="IntVector2" value="9 9" />
+            <variant type="String" value="ResizeDiagonalTopRight" />
+            <variant type="ResourceRef" value="Texture2D;Textures/UI.png" />
+            <variant type="IntRect" value="20 64 40 84" />
+            <variant type="IntVector2" value="9 9" />
+            <variant type="String" value="ResizeHorizontal" />
+            <variant type="ResourceRef" value="Texture2D;Textures/UI.png" />
+            <variant type="IntRect" value="40 64 60 84" />
+            <variant type="IntVector2" value="9 9" />
+            <variant type="String" value="ResizeDiagonalTopLeft" />
+            <variant type="ResourceRef" value="Texture2D;Textures/UI.png" />
+            <variant type="IntRect" value="60 64 80 84" />
+            <variant type="IntVector2" value="9 9" />
+            <variant type="String" value="RejectDrop" />
+            <variant type="ResourceRef" value="Texture2D;Textures/UI.png" />
+            <variant type="IntRect" value="80 64 100 84" />
+            <variant type="IntVector2" value="9 9" />
+            <variant type="String" value="AcceptDrop" />
+            <variant type="ResourceRef" value="Texture2D;Textures/UI.png" />
+            <variant type="IntRect" value="100 64 128 90" />
+            <variant type="IntVector2" value="0 0" />
+        </attribute>
     </element>
     </element>
     <element type="DropDownList">
     <element type="DropDownList">
-        <texture name="Textures/UI.png" />
-        <imagerect value="16 0 32 16" />
-        <border value="4 4 4 4" />
-        <pressedoffset value="16 0" />
-        <hoveroffset value="0 16" />
-        <labeloffset value="-1 1" />
-        <layout mode="horizontal" border="4 2 4 2" />
-        <popup>
-            <texture name="Textures/UI.png" />
-            <imagerect value="48 0 64 16" />
-            <border value="3 3 3 3" />
-            <layout border="4 2 4 2" />
-        </popup>
-        <listview>
-            <horizontalscrollbar>
-                <height value="12" />
-                <backbutton>
-                    <texture name="Textures/UI.png" />
-                    <imagerect horizontal="32 32 48 48" vertical="0 32 16 48" />
-                    <border value="3 3 3 3" />
-                    <pressedoffset value="64 0" />
-                    <hoveroffset value="0 16" />
-                </backbutton>
-                <forwardbutton>
-                    <texture name="Textures/UI.png" />
-                    <imagerect horizontal="48 32 64 48" vertical="16 32 32 48" />
-                    <border value="3 3 3 3" />
-                    <pressedoffset value="64 0" />
-                    <hoveroffset value="0 16" />
-                </forwardbutton>
-                <slider>
-                    <texture name="Textures/UI.png" />
-                    <imagerect value="48 0 64 16" />
-                    <border value="3 3 3 3" />
-                    <knob>
-                        <texture name="Textures/UI.png" />
-                        <imagerect value="16 0 32 16" />
-                        <border value="4 4 4 4" />
-                        <hoveroffset value="0 16" />
-                    </knob>
-                </slider>
-            </horizontalscrollbar>
-            <verticalscrollbar>
-                <width value="12" />
-                <backbutton>
-                    <texture name="Textures/UI.png" />
-                    <imagerect horizontal="32 32 48 48" vertical="0 32 16 48" />
-                    <border value="3 3 3 3" />
-                    <pressedoffset value="64 0" />
-                    <hoveroffset value="0 16" />
-                </backbutton>
-                <forwardbutton>
-                    <texture name="Textures/UI.png" />
-                    <imagerect horizontal="48 32 64 48" vertical="16 32 32 48" />
-                    <border value="3 3 3 3" />
-                    <pressedoffset value="64 0" />
-                    <hoveroffset value="0 16" />
-                </forwardbutton>
-                <slider>
-                    <texture name="Textures/UI.png" />
-                    <imagerect value="48 0 64 16" />
-                    <border value="3 3 3 3" />
-                    <knob>
-                        <texture name="Textures/UI.png" />
-                        <imagerect value="16 0 32 16" />
-                        <border value="4 4 4 4" />
-                        <hoveroffset value="0 16" />
-                    </knob>
-                </slider>
-            </verticalscrollbar>
-            <scrollpanel>
-                <color value="0 0 0 0" />
-            </scrollpanel>
-        </listview>
+        <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+        <attribute name="Image Rect" value="16 0 32 16" />
+        <attribute name="Border" value="4 4 4 4" />
+        <attribute name="Pressed Image Offset" value="16 0" />
+        <attribute name="Hover Image Offset" value="0 16" />
+        <attribute name="Label Offset" value="-1 1" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Border" value="4 1 4 1" />
+        <element type="Window" internal="true">
+            <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+            <attribute name="Image Rect" value="48 0 64 16" />
+            <attribute name="Border" value="3 3 3 3" />
+            <attribute name="Layout Border" value="2 2 2 2" />
+            <element type="ListView" internal="true">
+                <element type="ScrollBar" internal="true">
+                    <attribute name="Size" value="0 12" />
+                    <attribute name="Left Image Rect" value="32 32 48 48" />
+                    <attribute name="Up Image Rect" value="0 32 16 48" />
+                    <attribute name="Right Image Rect" value="48 32 64 48" />
+                    <attribute name="Down Image Rect" value="16 32 32 48" />
+                    <element type="Button" internal="true">
+                        <attribute name="Size" value="12 12" />
+                        <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                        <attribute name="Border" value="3 3 3 3" />
+                        <attribute name="Pressed Image Offset" value="64 0" />
+                        <attribute name="Hover Image Offset" value="0 16" />
+                    </element>
+                    <element type="Slider" internal="true">
+                        <attribute name="Size" value="12 12" />
+                        <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                        <attribute name="Image Rect" value="48 0 64 16" />
+                        <attribute name="Border" value="3 3 3 3" />
+                        <element type="BorderImage" internal="true">
+                            <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                            <attribute name="Image Rect" value="48 0 64 16" />
+                            <attribute name="Border" value="4 4 4 4" />
+                            <attribute name="Hover Image Offset" value="0 16" />
+                        </element>
+                    </element>
+                    <element type="Button" internal="true">
+                        <attribute name="Size" value="12 12" />
+                        <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                        <attribute name="Border" value="3 3 3 3" />
+                        <attribute name="Pressed Image Offset" value="64 0" />
+                        <attribute name="Hover Image Offset" value="0 16" />
+                    </element>
+                </element>
+                <element type="ScrollBar" internal="true">
+                    <attribute name="Size" value="12 0" />
+                    <attribute name="Left Image Rect" value="32 32 48 48" />
+                    <attribute name="Up Image Rect" value="0 32 16 48" />
+                    <attribute name="Right Image Rect" value="48 32 64 48" />
+                    <attribute name="Down Image Rect" value="16 32 32 48" />
+                    <element type="Button" internal="true">
+                        <attribute name="Size" value="12 12" />
+                        <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                        <attribute name="Border" value="3 3 3 3" />
+                        <attribute name="Pressed Image Offset" value="64 0" />
+                        <attribute name="Hover Image Offset" value="0 16" />
+                    </element>
+                    <element type="Slider" internal="true">
+                        <attribute name="Size" value="12 12" />
+                        <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                        <attribute name="Image Rect" value="48 0 64 16" />
+                        <attribute name="Border" value="3 3 3 3" />
+                        <element type="BorderImage" internal="true">
+                            <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                            <attribute name="Image Rect" value="48 0 64 16" />
+                            <attribute name="Border" value="4 4 4 4" />
+                            <attribute name="Hover Image Offset" value="0 16" />
+                        </element>
+                    </element>
+                    <element type="Button" internal="true">
+                        <attribute name="Size" value="12 12" />
+                        <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                        <attribute name="Border" value="3 3 3 3" />
+                        <attribute name="Pressed Image Offset" value="64 0" />
+                        <attribute name="Hover Image Offset" value="0 16" />
+                    </element>
+                </element>
+                <element type="BorderImage" internal="true">
+                    <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                    <attribute name="Image Rect" value="96 0 112 16" />
+                    <attribute name="Border" value="2 2 2 2" />
+                </element>
+            </element>
+        </element>
     </element>
     </element>
     <element type="LineEdit">
     <element type="LineEdit">
-        <texture name="Textures/UI.png" />
-        <imagerect value="112 0 128 16" />
-        <border value="2 2 2 2" />
-        <clipborder value="1 1 1 1" />
-        <hoveroffset value="0 16" />
-        <text>
-            <font name="Fonts/Anonymous Pro.ttf" size="11" />
-            <hovercolor value="0.45 0.70 0.45" />
-            <selectioncolor value="0.70 0.70 0.70" />
-        </text>
-        <cursor>
-            <size value="4 16" />
-            <texture name="Textures/UI.png" />
-            <imagerect value="12 0 16 16" />
-        </cursor>
+        <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+        <attribute name="Image Rect" value="112 0 128 16" />
+        <attribute name="Border" value="2 2 2 2" />
+        <attribute name="Clip Border" value="1 1 1 1" />
+        <attribute name="Hover Image Offset" value="0 16" />
+        <element type="Text" internal="true">
+            <attribute name="Font" value="Font;Fonts/Anonymous Pro.ttf" />
+            <attribute name="Font Size" value="11" />
+            <attribute name="Hover Color" value="0.45 0.70 0.45" />
+            <attribute name="Selection Color" value="0.70 0.70 0.70" />
+        </element>
+        <element type="BorderImage" internal="true">
+            <attribute name="Size" value="4 16" />
+            <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+            <attribute name="Image Rect" value="12 0 16 16" />
+        </element>
     </element>
     </element>
     <element type="ListView">
     <element type="ListView">
-        <horizontalscrollbar>
-            <height value="12" />
-            <backbutton>
-                <texture name="Textures/UI.png" />
-                <imagerect horizontal="32 32 48 48" vertical="0 32 16 48" />
-                <border value="3 3 3 3" />
-                <pressedoffset value="64 0" />
-                <hoveroffset value="0 16" />
-            </backbutton>
-            <forwardbutton>
-                <texture name="Textures/UI.png" />
-                <imagerect horizontal="48 32 64 48" vertical="16 32 32 48" />
-                <border value="3 3 3 3" />
-                <pressedoffset value="64 0" />
-                <hoveroffset value="0 16" />
-            </forwardbutton>
-            <slider>
-                <texture name="Textures/UI.png" />
-                <imagerect value="48 0 64 16" />
-                <border value="3 3 3 3" />
-                <knob>
-                    <texture name="Textures/UI.png" />
-                    <imagerect value="16 0 32 16" />
-                    <border value="4 4 4 4" />
-                    <hoveroffset value="0 16" />
-                </knob>
-            </slider>
-        </horizontalscrollbar>
-        <verticalscrollbar>
-            <width value="12" />
-            <backbutton>
-                <texture name="Textures/UI.png" />
-                <imagerect horizontal="32 32 48 48" vertical="0 32 16 48" />
-                <border value="3 3 3 3" />
-                <pressedoffset value="64 0" />
-                <hoveroffset value="0 16" />
-            </backbutton>
-            <forwardbutton>
-                <texture name="Textures/UI.png" />
-                <imagerect horizontal="48 32 64 48" vertical="16 32 32 48" />
-                <border value="3 3 3 3" />
-                <pressedoffset value="64 0" />
-                <hoveroffset value="0 16" />
-            </forwardbutton>
-            <slider>
-                <texture name="Textures/UI.png" />
-                <imagerect value="48 0 64 16" />
-                <border value="3 3 3 3" />
-                <knob>
-                    <texture name="Textures/UI.png" />
-                    <imagerect value="16 0 32 16" />
-                    <border value="4 4 4 4" />
-                    <hoveroffset value="0 16" />
-                </knob>
-            </slider>
-        </verticalscrollbar>
-        <scrollpanel>
-            <texture name="Textures/UI.png" />
-            <imagerect value="112 0 128 16" />
-            <border value="2 2 2 2" />
-            <clipborder value="1 1 1 1" />
-        </scrollpanel>
+        <element type="ScrollBar" internal="true">
+            <attribute name="Size" value="0 12" />
+            <attribute name="Left Image Rect" value="32 32 48 48" />
+            <attribute name="Up Image Rect" value="0 32 16 48" />
+            <attribute name="Right Image Rect" value="48 32 64 48" />
+            <attribute name="Down Image Rect" value="16 32 32 48" />
+            <element type="Button" internal="true">
+                <attribute name="Size" value="12 12" />
+                <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                <attribute name="Border" value="3 3 3 3" />
+                <attribute name="Pressed Image Offset" value="64 0" />
+                <attribute name="Hover Image Offset" value="0 16" />
+            </element>
+            <element type="Slider" internal="true">
+                <attribute name="Size" value="12 12" />
+                <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                <attribute name="Image Rect" value="48 0 64 16" />
+                <attribute name="Border" value="3 3 3 3" />
+                <element type="BorderImage" internal="true">
+                    <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                    <attribute name="Image Rect" value="48 0 64 16" />
+                    <attribute name="Border" value="4 4 4 4" />
+                    <attribute name="Hover Image Offset" value="0 16" />
+                </element>
+            </element>
+            <element type="Button" internal="true">
+                <attribute name="Size" value="12 12" />
+                <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                <attribute name="Border" value="3 3 3 3" />
+                <attribute name="Pressed Image Offset" value="64 0" />
+                <attribute name="Hover Image Offset" value="0 16" />
+            </element>
+        </element>
+        <element type="ScrollBar" internal="true">
+            <attribute name="Size" value="12 0" />
+            <attribute name="Left Image Rect" value="32 32 48 48" />
+            <attribute name="Up Image Rect" value="0 32 16 48" />
+            <attribute name="Right Image Rect" value="48 32 64 48" />
+            <attribute name="Down Image Rect" value="16 32 32 48" />
+            <element type="Button" internal="true">
+                <attribute name="Size" value="12 12" />
+                <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                <attribute name="Border" value="3 3 3 3" />
+                <attribute name="Pressed Image Offset" value="64 0" />
+                <attribute name="Hover Image Offset" value="0 16" />
+            </element>
+            <element type="Slider" internal="true">
+                <attribute name="Size" value="12 12" />
+                <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                <attribute name="Image Rect" value="48 0 64 16" />
+                <attribute name="Border" value="3 3 3 3" />
+                <element type="BorderImage" internal="true">
+                    <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                    <attribute name="Image Rect" value="48 0 64 16" />
+                    <attribute name="Border" value="4 4 4 4" />
+                    <attribute name="Hover Image Offset" value="0 16" />
+                </element>
+            </element>
+            <element type="Button" internal="true">
+                <attribute name="Size" value="12 12" />
+                <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                <attribute name="Border" value="3 3 3 3" />
+                <attribute name="Pressed Image Offset" value="64 0" />
+                <attribute name="Hover Image Offset" value="0 16" />
+            </element>
+        </element>
+        <element type="BorderImage" internal="true">
+            <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+            <attribute name="Image Rect" value="112 0 128 16" />
+            <attribute name="Border" value="2 2 2 2" />
+            <attribute name="Clip Border" value="1 1 1 1" />
+        </element>
     </element>
     </element>
     <element type="Menu">
     <element type="Menu">
-        <texture name="Textures/UI.png" />
-        <imagerect value="96 0 112 16" />
-        <border value="2 2 2 2" />
-        <pressedoffset value="16 0" />
-        <hoveroffset value="0 16" />
+        <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+        <attribute name="Image Rect" value="96 0 112 16" />
+        <attribute name="Border" value="2 2 2 2" />
+        <attribute name="Pressed Image Offset" value="16 0" />
+        <attribute name="Hover Image Offset" value="0 16" />
     </element>
     </element>
     <element type="ScrollBar">
     <element type="ScrollBar">
-        <backbutton>
-            <size value="12 12" />
-            <texture name="Textures/UI.png" />
-            <imagerect horizontal="32 32 48 48" vertical="0 32 16 48" />
-            <border value="3 3 3 3" />
-            <pressedoffset value="64 0" />
-            <hoveroffset value="0 16" />
-        </backbutton>
-        <forwardbutton>
-            <size value="12 12" />
-            <texture name="Textures/UI.png" />
-            <imagerect horizontal="48 32 64 48" vertical="16 32 32 48" />
-            <border value="3 3 3 3" />
-            <pressedoffset value="64 0" />
-            <hoveroffset value="0 16" />
-        </forwardbutton>
-        <slider>
-            <size value="12 12" />
-            <texture name="Textures/UI.png" />
-            <imagerect value="48 0 64 16" />
-            <border value="3 3 3 3" />
-            <knob>
-                <texture name="Textures/UI.png" />
-                <imagerect value="16 0 32 16" />
-                <border value="4 4 4 4" />
-                <hoveroffset value="0 16" />
-            </knob>
-        </slider>
+        <attribute name="Left Image Rect" value="32 32 48 48" />
+        <attribute name="Up Image Rect" value="0 32 16 48" />
+        <attribute name="Right Image Rect" value="48 32 64 48" />
+        <attribute name="Down Image Rect" value="16 32 32 48" />
+        <element type="Button" internal="true">
+            <attribute name="Size" value="12 12" />
+            <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+            <attribute name="Border" value="3 3 3 3" />
+            <attribute name="Pressed Image Offset" value="64 0" />
+            <attribute name="Hover Image Offset" value="0 16" />
+        </element>
+        <element type="Slider" internal="true">
+            <attribute name="Size" value="12 12" />
+            <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+            <attribute name="Image Rect" value="48 0 64 16" />
+            <attribute name="Border" value="3 3 3 3" />
+            <element type="BorderImage" internal="true">
+                <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                <attribute name="Image Rect" value="48 0 64 16" />
+                <attribute name="Border" value="4 4 4 4" />
+                <attribute name="Hover Image Offset" value="0 16" />
+            </element>
+        </element>
+        <element type="Button" internal="true">
+            <attribute name="Size" value="12 12" />
+            <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+            <attribute name="Border" value="3 3 3 3" />
+            <attribute name="Pressed Image Offset" value="64 0" />
+            <attribute name="Hover Image Offset" value="0 16" />
+        </element>
     </element>
     </element>
     <element type="ScrollView">
     <element type="ScrollView">
-        <horizontalscrollbar>
-            <height value="12" />
-            <backbutton>
-                <texture name="Textures/UI.png" />
-                <imagerect horizontal="32 32 48 48" vertical="0 32 16 48" />
-                <border value="3 3 3 3" />
-                <pressedoffset value="64 0" />
-                <hoveroffset value="0 16" />
-            </backbutton>
-            <forwardbutton>
-                <texture name="Textures/UI.png" />
-                <imagerect horizontal="48 32 64 48" vertical="16 32 32 48" />
-                <border value="3 3 3 3" />
-                <pressedoffset value="64 0" />
-                <hoveroffset value="0 16" />
-            </forwardbutton>
-            <slider>
-                <texture name="Textures/UI.png" />
-                <imagerect value="48 0 64 16" />
-                <border value="3 3 3 3" />
-                <knob>
-                    <texture name="Textures/UI.png" />
-                    <imagerect value="16 0 32 16" />
-                    <border value="4 4 4 4" />
-                    <hoveroffset value="0 16" />
-                </knob>
-            </slider>
-        </horizontalscrollbar>
-        <verticalscrollbar>
-            <width value="12" />
-            <backbutton>
-                <texture name="Textures/UI.png" />
-                <imagerect horizontal="32 32 48 48" vertical="0 32 16 48" />
-                <border value="3 3 3 3" />
-                <pressedoffset value="64 0" />
-                <hoveroffset value="0 16" />
-            </backbutton>
-            <forwardbutton>
-                <texture name="Textures/UI.png" />
-                <imagerect horizontal="48 32 64 48" vertical="16 32 32 48" />
-                <border value="3 3 3 3" />
-                <pressedoffset value="64 0" />
-                <hoveroffset value="0 16" />
-            </forwardbutton>
-            <slider>
-                <texture name="Textures/UI.png" />
-                <imagerect value="48 0 64 16" />
-                <border value="3 3 3 3" />
-                <knob>
-                    <texture name="Textures/UI.png" />
-                    <imagerect value="16 0 32 16" />
-                    <border value="4 4 4 4" />
-                    <hoveroffset value="0 16" />
-                </knob>
-            </slider>
-        </verticalscrollbar>
-        <scrollpanel>
-            <texture name="Textures/UI.png" />
-            <imagerect value="112 0 128 16" />
-            <border value="2 2 2 2" />
-            <clipborder value="1 1 1 1" />
-        </scrollpanel>
-    </element>
-    <element type="Slider">
-        <size value="12 12" />
-        <texture name="Textures/UI.png" />
-        <imagerect value="48 0 64 16" />
-        <border value="3 3 3 3" />
-        <knob>
-            <texture name="Textures/UI.png" />
-            <imagerect value="16 0 32 16" />
-            <border value="4 4 4 4" />
-            <hoveroffset value="0 16" />
-        </knob>
+        <element type="ScrollBar" internal="true">
+            <attribute name="Size" value="0 12" />
+            <attribute name="Left Image Rect" value="32 32 48 48" />
+            <attribute name="Up Image Rect" value="0 32 16 48" />
+            <attribute name="Right Image Rect" value="48 32 64 48" />
+            <attribute name="Down Image Rect" value="16 32 32 48" />
+            <element type="Button" internal="true">
+                <attribute name="Size" value="12 12" />
+                <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                <attribute name="Border" value="3 3 3 3" />
+                <attribute name="Pressed Image Offset" value="64 0" />
+                <attribute name="Hover Image Offset" value="0 16" />
+            </element>
+            <element type="Slider" internal="true">
+                <attribute name="Size" value="12 12" />
+                <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                <attribute name="Image Rect" value="48 0 64 16" />
+                <attribute name="Border" value="3 3 3 3" />
+                <element type="BorderImage" internal="true">
+                    <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                    <attribute name="Image Rect" value="48 0 64 16" />
+                    <attribute name="Border" value="4 4 4 4" />
+                    <attribute name="Hover Image Offset" value="0 16" />
+                </element>
+            </element>
+            <element type="Button" internal="true">
+                <attribute name="Size" value="12 12" />
+                <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                <attribute name="Border" value="3 3 3 3" />
+                <attribute name="Pressed Image Offset" value="64 0" />
+                <attribute name="Hover Image Offset" value="0 16" />
+            </element>
+        </element>
+        <element type="ScrollBar" internal="true">
+            <attribute name="Size" value="12 0" />
+            <attribute name="Left Image Rect" value="32 32 48 48" />
+            <attribute name="Up Image Rect" value="0 32 16 48" />
+            <attribute name="Right Image Rect" value="48 32 64 48" />
+            <attribute name="Down Image Rect" value="16 32 32 48" />
+            <element type="Button" internal="true">
+                <attribute name="Size" value="12 12" />
+                <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                <attribute name="Border" value="3 3 3 3" />
+                <attribute name="Pressed Image Offset" value="64 0" />
+                <attribute name="Hover Image Offset" value="0 16" />
+            </element>
+            <element type="Slider" internal="true">
+                <attribute name="Size" value="12 12" />
+                <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                <attribute name="Image Rect" value="48 0 64 16" />
+                <attribute name="Border" value="3 3 3 3" />
+                <element type="BorderImage" internal="true">
+                    <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                    <attribute name="Image Rect" value="48 0 64 16" />
+                    <attribute name="Border" value="4 4 4 4" />
+                    <attribute name="Hover Image Offset" value="0 16" />
+                </element>
+            </element>
+            <element type="Button" internal="true">
+                <attribute name="Size" value="12 12" />
+                <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+                <attribute name="Border" value="3 3 3 3" />
+                <attribute name="Pressed Image Offset" value="64 0" />
+                <attribute name="Hover Image Offset" value="0 16" />
+            </element>
+        </element>
+        <element type="BorderImage" internal="true">
+            <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+            <attribute name="Image Rect" value="112 0 128 16" />
+            <attribute name="Border" value="2 2 2 2" />
+            <attribute name="Clip Border" value="1 1 1 1" />
+        </element>
+    </element>
+    <element type="Slider" internal="true">
+        <attribute name="Size" value="12 12" />
+        <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+        <attribute name="Image Rect" value="48 0 64 16" />
+        <attribute name="Border" value="3 3 3 3" />
+        <element type="BorderImage" internal="true">
+            <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+            <attribute name="Image Rect" value="48 0 64 16" />
+            <attribute name="Border" value="4 4 4 4" />
+            <attribute name="Hover Image Offset" value="0 16" />
+        </element>
     </element>
     </element>
     <element type="Window">
     <element type="Window">
-        <texture name="Textures/UI.png" />
-        <imagerect value="48 0 64 16" />
-        <border value="3 3 3 3" />
-        <resizeborder value="8 8 8 8" />
+        <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+        <attribute name="Image Rect" value="48 0 64 16" />
+        <attribute name="Border" value="3 3 3 3" />
+        <attribute name="Resize Border" value="8 8 8 8" />
     </element>
     </element>
     <element type="Text">
     <element type="Text">
-        <font name="Fonts/Anonymous Pro.ttf" size="11" />
+        <attribute name="Font" value="Font;Fonts/Anonymous Pro.ttf" />
+        <attribute name="Font Size" value="11" />
     </element>
     </element>
     <element type="DebugHudText">
     <element type="DebugHudText">
-        <font name="Fonts/Anonymous Pro.ttf" size="11" />
+        <attribute name="Font" value="Font;Fonts/Anonymous Pro.ttf" />
+        <attribute name="Font Size" value="11" />
     </element>
     </element>
     <element type="ConsoleBackground">
     <element type="ConsoleBackground">
-        <color topleft="0 0.25 0 0.75" topright="0 0.25 0 0.75" bottomleft="0.25 0.75 0.25 0.75" bottomright="0.25 0.75 0.25 0.75" />
-        <layout spacing="0" border="4 4 4 4" />
+        <attribute name="Top Left Color" value="0 0.25 0 0.75" />
+        <attribute name="Top Right Color" value="0 0.25 0 0.75" />
+        <attribute name="Bottom Left Color" value="0.25 0.75 0.25 0.75" />
+        <attribute name="Bottom Right Color" value="0.25 0.75 0.25 0.75" />
+        <attribute name="Layout Border" value="4 4 4 4" />
     </element>
     </element>
     <element type="ConsoleText">
     <element type="ConsoleText">
-        <font name="Fonts/Anonymous Pro.ttf" size="11" />
+        <attribute name="Font" value="Font;Fonts/Anonymous Pro.ttf" />
+        <attribute name="Font Size" value="11" />
     </element>
     </element>
     <element type="ConsoleLineEdit">
     <element type="ConsoleLineEdit">
-        <color value="0 0 0 0.5" />
-        <text>
-            <font name="Fonts/Anonymous Pro.ttf" size="11" />
-            <selectioncolor value="0 0.5 0 0.75" />
-        </text>
-        <cursor>
-            <size value="4 16" />
-            <texture name="Textures/UI.png" />
-            <imagerect value="12 0 16 16" />
-        </cursor>
+        <attribute name="Top Left Color" value="0 0 0 0.5" />
+        <attribute name="Top Right Color" value="0 0 0 0.5" />
+        <attribute name="Bottom Left Color" value="0 0 0 0.5" />
+        <attribute name="Bottom Right Color" value="0 0 0 0.5" />
+        <element type="Text" internal="true">
+            <attribute name="Font" value="Font;Fonts/Anonymous Pro.ttf" />
+            <attribute name="Font Size" value="11" />
+            <attribute name="Selection Color" value="0 0.5 0 0.75" />
+        </element>
+        <element type="BorderImage" internal="true">
+            <attribute name="Size" value="4 16" />
+            <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+            <attribute name="Image Rect" value="12 0 16 16" />
+        </element>
     </element>
     </element>
     <element type="FileSelector">
     <element type="FileSelector">
-        <size value="400 300" />
-        <movable enable="true" />
-        <resizable enable="true" />
-        <resizeborder value="6 6 6 6" />
-        <layout mode="vertical" spacing="4" border="6 6 6 6" />
+        <attribute name="Size" value="400 300" />
+        <attribute name="Is Movable" value="true" />
+        <attribute name="Is Resizable" value="true" />
+        <attribute name="Resize Border" value="6 6 6 6" />
+        <attribute name="Layout Mode" value="vertical" />
+        <attribute name="Layout Spacing" value="4" />
+        <attribute name="Layout Border" value="6 6 6 6" />
     </element>
     </element>
     <element type="FileSelectorButton">
     <element type="FileSelectorButton">
-        <fixedsize value="80 22" />
+        <attribute name="Min Size" value="80 22" />
+        <attribute name="Max Size" value="80 22" />
     </element>
     </element>
     <element type="FileSelectorButtonText">
     <element type="FileSelectorButtonText">
-        <font name="Fonts/Anonymous Pro.ttf" size="11" />
+        <attribute name="Font" value="Font;Fonts/Anonymous Pro.ttf" />
+        <attribute name="Font Size" value="11" />
     </element>
     </element>
     <element type="FileSelectorFilterList">
     <element type="FileSelectorFilterList">
-        <fixedwidth value="64" />
-        <resizepopup enable="true" />
+        <attribute name="Min Size" value="64 0" />
+        <attribute name="Max Size" value="64 2147483647" />
+        <attribute name="Resize Popup" value="true" />
     </element>
     </element>
     <element type="FileSelectorFilterText">
     <element type="FileSelectorFilterText">
-        <font name="Fonts/Anonymous Pro.ttf" size="11" />
-        <hovercolor value="0.45 0.70 0.45" />
+        <attribute name="Font" value="Font;Fonts/Anonymous Pro.ttf" />
+        <attribute name="Font Size" value="11" />
+        <attribute name="Hover Color" value="0.45 0.70 0.45" />
     </element>
     </element>
     <element type="FileSelectorTitleLayout">
     <element type="FileSelectorTitleLayout">
-        <fixedheight value="16" />
-        <layout spacing="4" />
+        <attribute name="Min Size" value="0 16" />
+        <attribute name="Max Size" value="2147483647 16" />
+        <attribute name="Layout Spacing" value="4" />
     </element>
     </element>
     <element type="FileSelectorLayout">
     <element type="FileSelectorLayout">
-        <layout spacing="4" />
+        <attribute name="Layout Spacing" value="4" />
     </element>
     </element>
     <element type="FileSelectorListText">
     <element type="FileSelectorListText">
-        <font name="Fonts/Anonymous Pro.ttf" size="11" />
-        <hovercolor value="0.45 0.70 0.45" />
-        <selectioncolor value="0.70 0.70 0.70" />
+        <attribute name="Font" value="Font;Fonts/Anonymous Pro.ttf" />
+        <attribute name="Font Size" value="11" />
+        <attribute name="Hover Color" value="0.45 0.70 0.45" />
+        <attribute name="Selection Color" value="0.70 0.70 0.70" />
     </element>
     </element>
     <element type="FileSelectorTitleText">
     <element type="FileSelectorTitleText">
-        <font name="Fonts/Anonymous Pro.ttf" size="11" />
+        <attribute name="Font" value="Font;Fonts/Anonymous Pro.ttf" />
+        <attribute name="Font Size" value="11" />
     </element>
     </element>
     <element type="EditorDivider">
     <element type="EditorDivider">
-        <texture name="Textures/UI.png" />
-        <imagerect value="112 0 128 16" />
-        <border value="2 2 2 2" />
+        <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+        <attribute name="Image Rect" value="112 0 128 16" />
+        <attribute name="Border" value="2 2 2 2" />
     </element>
     </element>
     <element type="EditorMenuBar">
     <element type="EditorMenuBar">
-        <texture name="Textures/UI.png" />
-        <imagerect value="96 0 112 16" />
-        <border value="2 2 2 2" />
+        <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+        <attribute name="Image Rect" value="96 0 112 16" />
+        <attribute name="Border" value="2 2 2 2" />
     </element>
     </element>
     <element type="EditorMenuText">
     <element type="EditorMenuText">
-        <font name="Fonts/Anonymous Pro.ttf" size="11" />
+        <attribute name="Font" value="Font;Fonts/Anonymous Pro.ttf" />
+        <attribute name="Font Size" value="11" />
     </element>
     </element>
     <element type="EditorAttributeText">
     <element type="EditorAttributeText">
-        <font name="Fonts/BlueHighway.ttf" size="12" />
+        <attribute name="Font" value="Font;Fonts/BlueHighway.ttf" />
+        <attribute name="Font Size" value="12" />
     </element>
     </element>
     <element type="EditorEnumAttributeText">
     <element type="EditorEnumAttributeText">
-        <font name="Fonts/BlueHighway.ttf" size="12" />
-        <hovercolor value="0.45 0.70 0.45" />
+        <attribute name="Font" value="Font;Fonts/BlueHighway.ttf" />
+        <attribute name="Font Size" value="12" />
+        <attribute name="Hover Color" value="0.45 0.70 0.45" />
     </element>
     </element>
     <element type="EditorAttributeEdit">
     <element type="EditorAttributeEdit">
-        <texture name="Textures/UI.png" />
-        <imagerect value="112 0 128 16" />
-        <border value="2 2 2 2" />
-        <clipborder value="1 1 1 1" />
-        <hoveroffset value="0 16" />
-        <text>
-            <font name="Fonts/Anonymous Pro.ttf" size="11" />
-            <hovercolor value="0.45 0.70 0.45" />
-            <selectioncolor value="0.70 0.70 0.70" />
-        </text>
-        <cursor>
-            <size value="4 16" />
-            <texture name="Textures/UI.png" />
-            <imagerect value="12 0 16 16" />
-        </cursor>
-    </element>
-</elements>
+        <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+        <attribute name="Image Rect" value="112 0 128 16" />
+        <attribute name="Border" value="2 2 2 2" />
+        <attribute name="Clip Border" value="1 1 1 1" />
+        <attribute name="Hover Image Offset" value="0 16" />
+        <element type="Text" internal="true">
+            <attribute name="Font" value="Font;Fonts/Anonymous Pro.ttf" />
+            <attribute name="Font Size" value="11" />
+            <attribute name="Hover Color" value="0.45 0.70 0.45" />
+            <attribute name="Selection Color" value="0.70 0.70 0.70" />
+        </element>
+        <element type="BorderImage" internal="true">
+            <attribute name="Size" value="4 16" />
+            <attribute name="Texture" value="Texture2D;Textures/UI.png" />
+            <attribute name="Image Rect" value="12 0 16 16" />
+        </element>
+    </element>
+</elements>

+ 83 - 69
Bin/Data/UI/EditorNodeWindow.xml

@@ -1,90 +1,104 @@
-<element type="Window" name="NodeWindow">
-    <movable enable="true" />
-    <resizable enable="true" />
-    <resizeborder value="6 6 6 6" />
-    <layout mode="vertical" spacing="4" border="6 6 6 6" />
+<element type="Window">
+    <attribute name="Name" value="NodeWindow" />
+    <attribute name="Is Movable" value="true" />
+    <attribute name="Is Resizable" value="true" />
+    <attribute name="Resize Border" value="6 6 6 6" />
+    <attribute name="Layout Mode" value="Vertical" />
+    <attribute name="Layout Spacing" value="4" />
+    <attribute name="Layout Border" value="6 6 6 6" />
     <element>
     <element>
-        <fixedheight value="17" />
-        <layout mode="horizontal" />
-        <element type="Text" name="WindowTitle">
-            <text value="Node / component edit" />
+        <attribute name="Min Size" value="0 16" />
+        <attribute name="Max Size" value="2147483647 16" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <element type="Text">
+            <attribute name="Text" value="Node / component edit" />
+        </element>
+        <element type="Button" style="CloseButton">
+            <attribute name="Name" value="CloseButton" />
         </element>
         </element>
-        <element type="Button" style="CloseButton" name="CloseButton" />
     </element>
     </element>
     <element type="BorderImage" style="EditorDivider">
     <element type="BorderImage" style="EditorDivider">
-        <fixedheight value="4" />
+        <attribute name="Min Size" value="0 4" />
+        <attribute name="Max Size" value="2147483647 4" />
     </element>
     </element>
-    <element type="Text" name="NodeTitle">
-        <fixedheight value="17" />
+    <element type="Text">
+        <attribute name="Name" value="NodeTitle" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
     </element>
     </element>
-    <element type="ListView" name="NodeAttributeList">
-        <highlight value="always" />
-        <fixedheight value="74" />
-        <horizontalscrollbar>
-            <visible enable="false" />
-        </horizontalscrollbar>
+    <element type="ListView">
+        <attribute name="Name" value="NodeAttributeList" />
+        <attribute name="Highlight Mode" value="Always" />
+        <attribute name="Min Size" value="0 74" />
+        <attribute name="Max Size" value="2147483647 74" />
+        <element type="ScrollBar" internal="true">
+            <attribute name="Is Visible" value="false" />
+        </element>
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="17" />
-        <layout mode="horizontal" spacing="4" />
-        <element type="LineEdit" name="VarNameEdit">
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="VarInt">
-            <text value="Int" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="VarBool">
-            <text value="Bool" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="VarFloat">
-            <text value="Float" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="4" />
+        <element type="LineEdit">
+            <attribute name="Name" value="VarNameEdit" />
         </element>
         </element>
-        <element type="Text" style="FileSelectorFilterText" name="VarString">
-            <text value="String" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="VarVector3">
-            <text value="Vector3" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="VarColor">
-            <text value="Color" />
-        </element>
-        <element type="DropDownList" name="NewVarDropDown">
-            <fixedsize value="50 17" />
-            <layout mode="free" />
-            <placeholder>
-                <visible enable="false" />
-            </placeholder>
+        <element type="DropDownList">
+            <attribute name="Name" value="NewVarDropDown" />
+            <attribute name="Min Size" value="50 17" />
+            <attribute name="Max Size" value="50 17" />
+            <element internal="true">
+                <attribute name="Is Visible" value="false" />
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="Int" />
+                </element>
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="Bool" />
+                </element>
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="Float" />
+                </element>
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="String" />
+                </element>
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="Vector3" />
+                </element>
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="Color" />
+                </element>
+            </element>
             <element type="Text">
             <element type="Text">
-                <text value="New" />
-                <alignment horizontal="center" vertical="center" />
+                <attribute name="Text" value="New" />
+                <attribute name="Text Alignment" value="Center" />
             </element>
             </element>
-            <popup>
-                <layout border="4 4 4 4" />   
-            </popup>
-            <popupitem name="VarInt" />
-            <popupitem name="VarBool" />
-            <popupitem name="VarFloat" />
-            <popupitem name="VarString" />
-            <popupitem name="VarVector3" />
-            <popupitem name="VarColor" />
         </element>
         </element>
-        <element type="Button" name="DeleteVarButton">
-            <fixedsize value="50 17" />
+        <element type="Button">
+            <attribute name="Name" value="DeleteVarButton" />
+            <attribute name="Min Size" value="50 17" />
+            <attribute name="Max Size" value="50 17" />
+            <attribute name="Layout Mode" value="Vertical" />
+            <attribute name="Layout Border" value="1 1 1 1" />
             <element type="Text">
             <element type="Text">
-                <text value="Del" />
-                <alignment horizontal="center" vertical="center" />
+                <attribute name="Text" value="Del" />
+                <attribute name="Text Alignment" value="Center" />
             </element>
             </element>
         </element>
         </element>
     </element>
     </element>
     <element type="BorderImage" style="EditorDivider">
     <element type="BorderImage" style="EditorDivider">
-        <fixedheight value="4" />
+        <attribute name="Min Size" value="0 4" />
+        <attribute name="Max Size" value="2147483647 4" />
     </element>
     </element>
-    <element type="Text" name="ComponentTitle">
-        <fixedheight value="17" />
+    <element type="Text">
+        <attribute name="Name" value="ComponentTitle" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
     </element>
     </element>
-    <element type="ListView" name="ComponentAttributeList">
-        <highlight value="always" />
-        <horizontalscrollbar>
-            <visible enable="false" />
-        </horizontalscrollbar>
+    <element type="ListView">
+        <attribute name="Name" value="ComponentAttributeList" />
+        <attribute name="Highlight Mode" value="Always" />
+        <element type="ScrollBar" internal="true">
+            <attribute name="Is Visible" value="false" />
+        </element>
     </element>
     </element>
 </element>
 </element>

+ 66 - 52
Bin/Data/UI/EditorSceneWindow.xml

@@ -1,77 +1,91 @@
-<element type="Window" name="SceneWindow">
-    <movable enable="true" />
-    <resizable enable="true" />
-    <resizeborder value="6 6 6 6" />
-    <layout mode="vertical" spacing="4" border="6 6 6 6" />
+<element type="Window">
+    <attribute name="Name" value="SceneWindow" />
+    <attribute name="Is Movable" value="true" />
+    <attribute name="Is Resizable" value="true" />
+    <attribute name="Resize Border" value="6 6 6 6" />
+    <attribute name="Layout Mode" value="Vertical" />
+    <attribute name="Layout Spacing" value="4" />
+    <attribute name="Layout Border" value="6 6 6 6" />
     <element>
     <element>
-        <fixedheight value="16" />
-        <layout mode="horizontal" />
+        <attribute name="Min Size" value="0 16" />
+        <attribute name="Max Size" value="2147483647 16" />
+        <attribute name="Layout Mode" value="Horizontal" />
         <element type="Text">
         <element type="Text">
-            <text value="Scene hierarchy" />
+            <attribute name="Text" value="Scene hierarchy" />
+        </element>
+        <element type="Button" style="CloseButton">
+            <attribute name="Name" value="CloseButton" />
         </element>
         </element>
-        <element type="Button" style="CloseButton" name="CloseButton" />
     </element>
     </element>
     <element type="BorderImage" style="EditorDivider">
     <element type="BorderImage" style="EditorDivider">
-        <fixedheight value="4" />
+        <attribute name="Min Size" value="0 4" />
+        <attribute name="Max Size" value="2147483647 4" />
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="18" />
-        <layout mode="horizontal" spacing="4" />
-        <element type="Button" name="ExpandAllButton">
-            <fixedwidth value="70" />
-            <element type="Text">
-                <font name="Anonymous Pro.ttf" size="9" />
-                <text value="Expand" />
-                <alignment horizontal="center" vertical="center" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <element type="Button">
+            <attribute name="Name" value="ExpandAllButton" />
+            <attribute name="Min Size" value="70 17" />
+            <attribute name="Max Size" value="70 17" />
+            <attribute name="Layout Mode" value="Vertical" />
+            <attribute name="Layout Border" value="1 1 1 1" />
+            <element type="Text">>
+                <attribute name="Text" value="Expand" />
+                <attribute name="Text Alignment" value="Center" />
             </element>
             </element>
         </element>
         </element>
-        <element type="Button" name="CollapseAllButton">
-            <fixedwidth value="70" />
+        <element type="Button">
+            <attribute name="Name" value="CollapseAllButton" />
+            <attribute name="Min Size" value="70 17" />
+            <attribute name="Max Size" value="70 17" />
+            <attribute name="Layout Mode" value="Vertical" />
+            <attribute name="Layout Border" value="1 1 1 1" />
             <element type="Text">
             <element type="Text">
-                <font name="Anonymous Pro.ttf" size="9" />
-                <text value="Collapse" />
-                <alignment horizontal="center" vertical="center" />
+                <attribute name="Text" value="Collapse" />
+                <attribute name="Text Alignment" value="Center" />
             </element>
             </element>
         </element>
         </element>
-        <element />
     </element>
     </element>
-    <element type="ListView" name="NodeList">
-        <hierarchy enable="true" />
-        <highlight value="always" />
-        <multiselect enable="true" />
+    <element type="ListView">
+        <attribute name="Name" value="NodeList" />
+        <attribute name="Hierarchy Mode" value="true" />
+        <attribute name="Highlight Mode" value="Always" />
+        <attribute name="Multiselect" value="true" />
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="22" />
-        <layout mode="horizontal" spacing="4" />
+        <attribute name="Min Size" value="0 22" />
+        <attribute name="Max Size" value="2147483647 22" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="4" />
         <element />
         <element />
-        <element type="DropDownList" name="NewNodeList">
-            <fixedsize value="90 22" />
-            <layout border="4 4 4 4" />
-            <placeholder>
-                <visible enable="false" />
-            </placeholder>
+        <element type="DropDownList">
+            <attribute name="Name" value="NewNodeList" />
+            <attribute name="Min Size" value="90 22" />
+            <attribute name="Max Size" value="90 22" />
+            <attribute name="Layout Border" value="4 4 4 4" />
+            <element internal="true">
+                <attribute name="Is Visible" value="false" />
+            </element>
             <element type="Text">
             <element type="Text">
-                <text value="New Node" />
-                <textalignment value="center" />
+                <attribute name="Text" value="New Node" />
+                <attribute name="Text Alignment" value="Center" />
             </element>
             </element>
-            <popup>
-                <layout border="4 4 4 4" />   
-            </popup>         
         </element>
         </element>
         <element />
         <element />
-        <element type="DropDownList" name="NewComponentList">
-            <fixedsize value="90 22" />
-            <layout border="4 4 4 4" />
-            <placeholder>
-                <visible enable="false" />
-            </placeholder>
+        <element type="DropDownList">
+            <attribute name="Name" value="NewComponentList" />
+            <attribute name="Min Size" value="90 22" />
+            <attribute name="Max Size" value="90 22" />
+            <attribute name="Layout Border" value="4 4 4 4" />
+            <element internal="true">
+                <attribute name="Is Visible" value="false" />
+            </element>
             <element type="Text">
             <element type="Text">
-                <text value="New Comp" />
-                <textalignment value="center" />
+                <attribute name="Text" value="New Comp" />
+                <attribute name="Text Alignment" value="Center" />
             </element>
             </element>
-            <popup>
-                <layout border="4 4 4 4" />   
-            </popup>
         </element>
         </element>
         <element />
         <element />
     </element>
     </element>

+ 301 - 209
Bin/Data/UI/EditorSettingsDialog.xml

@@ -1,317 +1,409 @@
-<element type="Window" name="EditorSettingsDialog">
-    <fixedwidth value="400" />
-    <movable enable="true" />
-    <layout mode="vertical" spacing="4" border="6 6 6 6" />
+<element type="Window">
+    <attribute name="Name" value="EditorSettingsDialog" />
+    <attribute name="Min Size" value="400 0" />
+    <attribute name="Max Size" value="400 2147483647" />
+    <attribute name="Is Movable" value="true" />
+    <attribute name="Layout Mode" value="Vertical" />
+    <attribute name="Layout Spacing" value="4" />
+    <attribute name="Layout Border" value="6 6 6 6" />
     <element>
     <element>
-        <fixedheight value="16" />
-        <layout mode="horizontal" />
+        <attribute name="Min Size" value="0 16" />
+        <attribute name="Max Size" value="2147483647 16" />
+        <attribute name="Layout Mode" value="Horizontal" />
         <element type="Text">
         <element type="Text">
-            <text value="Editor settings" />
+            <attribute name="Text" value="Editor settings" />
+        </element>
+        <element type="Button" style="CloseButton">
+            <attribute name="Name" value="CloseButton" />
         </element>
         </element>
-        <element type="Button" style="CloseButton" name="CloseButton" />
     </element>
     </element>
     <element type="BorderImage" style="EditorDivider">
     <element type="BorderImage" style="EditorDivider">
-        <fixedheight value="4" />
+        <attribute name="Min Size" value="0 4" />
+        <attribute name="Max Size" value="2147483647 4" />
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="17" />
-        <layout mode="horizontal" spacing="20" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="20" />
         <element type="Text">
         <element type="Text">
-            <text value="Near clip distance" />
+            <attribute name="Text" value="Near clip distance" />
         </element>
         </element>
-        <element type="LineEdit" name="NearClipEdit">
-            <fixedwidth value="100" />
+        <element type="LineEdit">
+            <attribute name="Name" value="NearClipEdit" />
+            <attribute name="Min Size" value="100 0" />
+            <attribute name="Max Size" value="100 2147483647" />
         </element>
         </element>
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="17" />
-        <layout mode="horizontal" spacing="20" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="20" />
         <element type="Text">
         <element type="Text">
-            <text value="Far clip distance" />
+            <attribute name="Text" value="Far clip distance" />
+        </element>
+        <element type="LineEdit">
+            <attribute name="Name" value="FarClipEdit" />
+            <attribute name="Min Size" value="100 0" />
+            <attribute name="Max Size" value="100 2147483647" />
         </element>
         </element>
-        <element type="LineEdit" name="FarClipEdit">
-            <fixedwidth value="100" />
-         </element>
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="17" />
-        <layout mode="horizontal" spacing="20" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="20" />
         <element type="Text">
         <element type="Text">
-            <text value="Field of view" />
+            <attribute name="Text" value="Field of view" />
         </element>
         </element>
-        <element type="LineEdit" name="FOVEdit">
-            <fixedwidth value="100" />
+        <element type="LineEdit">
+            <attribute name="Name" value="FOVEdit" />
+            <attribute name="Min Size" value="100 0" />
+            <attribute name="Max Size" value="100 2147483647" />
         </element>
         </element>
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="17" />
-        <layout mode="horizontal" spacing="20" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="20" />
         <element type="Text">
         <element type="Text">
-            <text value="Movement speed" />
+            <attribute name="Text" value="Movement speed" />
         </element>
         </element>
-        <element type="LineEdit" name="SpeedEdit">
-            <fixedwidth value="100" />
+        <element type="LineEdit">
+            <attribute name="Name" value="SpeedEdit" />
+            <attribute name="Min Size" value="100 0" />
+            <attribute name="Max Size" value="100 2147483647" />
         </element>
         </element>
     </element>
     </element>
     <element type="BorderImage" style="EditorDivider">
     <element type="BorderImage" style="EditorDivider">
-        <fixedheight value="4" />
+        <attribute name="Min Size" value="0 4" />
+        <attribute name="Max Size" value="2147483647 4" />
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="17" />
-        <layout mode="horizontal" spacing="20" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="20" />
         <element type="Text">
         <element type="Text">
-            <text value="New node distance" />
+            <attribute name="Text" value="New node distance" />
         </element>
         </element>
-        <element type="LineEdit" name="DistanceEdit">
-            <fixedwidth value="100" />
+        <element type="LineEdit">
+            <attribute name="Name" value="DistanceEdit" />
+            <attribute name="Min Size" value="100 0" />
+            <attribute name="Max Size" value="100 2147483647" />
         </element>
         </element>
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="17" />
-        <layout mode="horizontal" spacing="8" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="8" />
         <element type="Text">
         <element type="Text">
-            <text value="Node move step" />
+            <attribute name="Text" value="Node move step" />
         </element>
         </element>
-        <element type="CheckBox" name="MoveSnapToggle">
-            <fixedsize value="16 16" />
+        <element type="CheckBox">
+            <attribute name="Name" value="MoveSnapToggle" />
+            <attribute name="Min Size" value="16 16" />
+            <attribute name="Max Size" value="16 16" />
         </element>
         </element>
         <element type="Text">
         <element type="Text">
-            <fixedwidth value="34" />
-            <text value="Snap" />
+            <attribute name="Min Size" value="34 0" />
+            <attribute name="Max Size" value="34 2147483647" />
+            <attribute name="Text" value="Snap" />
         </element>
         </element>
-        <element type="LineEdit" name="MoveStepEdit">
-            <fixedwidth value="100" />
+        <element type="LineEdit">
+            <attribute name="Name" value="MoveStepEdit" />
+            <attribute name="Min Size" value="100 0" />
+            <attribute name="Max Size" value="100 2147483647" />
         </element>
         </element>
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="17" />
-        <layout mode="horizontal" spacing="8" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="8" />
         <element type="Text">
         <element type="Text">
-            <text value="Node rotate step" />
+            <attribute name="Text" value="Node rotate step" />
         </element>
         </element>
-        <element type="CheckBox" name="RotateSnapToggle">
-            <fixedsize value="16 16" />
+        <element type="CheckBox">
+            <attribute name="Name" value="RotateSnapToggle" />
+            <attribute name="Min Size" value="16 16" />
+            <attribute name="Max Size" value="16 16" />
         </element>
         </element>
         <element type="Text">
         <element type="Text">
-            <fixedwidth value="34" />
-            <text value="Snap" />
+            <attribute name="Min Size" value="34 0" />
+            <attribute name="Max Size" value="34 2147483647" />
+            <attribute name="Text" value="Snap" />
         </element>
         </element>
-        <element type="LineEdit" name="RotateStepEdit">
-            <fixedwidth value="100" />
+        <element type="LineEdit">
+            <attribute name="Name" value="RotateStepEdit" />
+            <attribute name="Min Size" value="100 0" />
+            <attribute name="Max Size" value="100 2147483647" />
         </element>
         </element>
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="17" />
-        <layout mode="horizontal" spacing="8" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="8" />
         <element type="Text">
         <element type="Text">
-            <text value="Node scale step" />
+            <attribute name="Text" value="Node scale step" />
         </element>
         </element>
-        <element type="CheckBox" name="ScaleSnapToggle">
-            <fixedsize value="16 16" />
+        <element type="CheckBox">
+            <attribute name="Name" value="ScaleSnapToggle" />
+            <attribute name="Min Size" value="16 16" />
+            <attribute name="Max Size" value="16 16" />
         </element>
         </element>
         <element type="Text">
         <element type="Text">
-            <fixedwidth value="34" />
-            <text value="Snap" />
+            <attribute name="Min Size" value="34 0" />
+            <attribute name="Max Size" value="34 2147483647" />
+            <attribute name="Text" value="Snap" />
         </element>
         </element>
-        <element type="LineEdit" name="ScaleStepEdit">
-            <fixedwidth value="100" />
+        <element type="LineEdit">
+            <attribute name="Name" value="ScaleStepEdit" />
+            <attribute name="Min Size" value="100 0" />
+            <attribute name="Max Size" value="100 2147483647" />
         </element>
         </element>
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="17" />
-        <layout mode="horizontal" spacing="8" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="8" />
         <element type="Text">
         <element type="Text">
-            <text value="Pick components of type" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="PickGeometries">
-            <text value="Geometries" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="PickLights">
-            <text value="Lights" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="PickZones">
-            <text value="Zones" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="PickRigidBodies">
-            <text value="Rigidbodies" />
-        </element>
-        <element type="DropDownList" name="PickModeEdit">
-            <fixedwidth value="100" />
-            <popupitem name="PickGeometries" />
-            <popupitem name="PickLights" />
-            <popupitem name="PickZones" />
-            <popupitem name="PickRigidBodies" />
+            <attribute name="Text" value="Pick components of type" />
+        </element>
+        <element type="DropDownList">
+            <attribute name="Name" value="PickModeEdit" />
+            <attribute name="Min Size" value="100 0" />
+            <attribute name="Max Size" value="100 2147483647" />
+            <attribute name="Resize Popup" value="true" />
+            <element internal="true">
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="Geometries" />
+                </element>
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="Lights" />
+                </element>
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="Zones" />
+                </element>
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="Rigidbodies" />
+                </element>
+            </element>
         </element>
         </element>
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="17" />
-        <layout mode="horizontal" spacing="8" />
-        <element type="CheckBox" name="LocalIDToggle">
-            <fixedsize value="16 16" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="8" />
+        <element type="CheckBox">
+            <attribute name="Name" value="LocalIDToggle" />
+            <attribute name="Min Size" value="16 16" />
+            <attribute name="Max Size" value="16 16" />
         </element>
         </element>
         <element type="Text">
         <element type="Text">
-            <text value="Use local entity IDs on import" />
+            <attribute name="Text" value="Use local entity IDs on import" />
         </element>
         </element>
     </element>
     </element>
     <element type="BorderImage" style="EditorDivider">
     <element type="BorderImage" style="EditorDivider">
-        <fixedheight value="4" />
+        <attribute name="Min Size" value="0 4" />
+        <attribute name="Max Size" value="2147483647 4" />
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="17" />
-        <layout mode="horizontal" spacing="8" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="8" />
         <element type="Text">
         <element type="Text">
-            <text value="Rendering mode" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="RenderForward">
-            <text value="Forward" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="RenderPrepass">
-            <text value="Pre-pass" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="RenderDeferred">
-            <text value="Deferred" />
-        </element>
-        <element type="DropDownList" name="RenderModeEdit">
-            <fixedwidth value="100" />
-            <popupitem name="RenderForward" />
-            <popupitem name="RenderPrepass" />
-            <popupitem name="RenderDeferred" />
+            <attribute name="Text" value="Rendering mode" />
+        </element>
+        <element type="DropDownList">
+            <attribute name="Name" value="RenderModeEdit" />
+            <attribute name="Min Size" value="100 0" />
+            <attribute name="Max Size" value="100 2147483647" />
+            <attribute name="Resize Popup" value="true" />
+            <element internal="true">
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="Forward" />
+                </element>
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="Pre-pass" />
+                </element>
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="Deferred" />
+                </element>
+            </element>
         </element>
         </element>
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="17" />
-        <layout mode="horizontal" spacing="8" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="8" />
         <element type="Text">
         <element type="Text">
-            <text value="Texture quality" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="TextureLow">
-            <text value="Low" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="TextureMedium">
-            <text value="Medium" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="TextureHigh">
-            <text value="High" />
-        </element>
-        <element type="DropDownList" name="TextureQualityEdit">
-            <fixedwidth value="100" />
-            <popupitem name="TextureLow" />
-            <popupitem name="TextureMedium" />
-            <popupitem name="TextureHigh" />
+            <attribute name="Text" value="Texture quality" />
+        </element>
+        <element type="DropDownList">
+            <attribute name="Name" value="TextureQualityEdit" />
+            <attribute name="Min Size" value="100 0" />
+            <attribute name="Max Size" value="100 2147483647" />
+            <attribute name="Resize Popup" value="true" />
+            <element internal="true">
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="Low" />
+                </element>
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="Medium" />
+                </element>
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="High" />
+                </element>
+            </element>
         </element>
         </element>
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="17" />
-        <layout mode="horizontal" spacing="8" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="8" />
         <element type="Text">
         <element type="Text">
-            <text value="Material quality" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="MaterialLow">
-            <text value="Low" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="MaterialMedium">
-            <text value="Medium" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="MaterialHigh">
-            <text value="High" />
-        </element>
-        <element type="DropDownList" name="MaterialQualityEdit">
-            <fixedwidth value="100" />
-            <popupitem name="MaterialLow" />
-            <popupitem name="MaterialMedium" />
-            <popupitem name="MaterialHigh" />
+            <attribute name="Text" value="Material quality" />
+        </element>
+        <element type="DropDownList">
+            <attribute name="Name" value="MaterialQualityEdit" />
+            <attribute name="Min Size" value="100 0" />
+            <attribute name="Max Size" value="100 2147483647" />
+            <attribute name="Resize Popup" value="true" />
+            <element internal="true">
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="Low" />
+                </element>
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="Medium" />
+                </element>
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="High" />
+                </element>
+            </element>
         </element>
         </element>
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="17" />
-        <layout mode="horizontal" spacing="8" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="8" />
         <element type="Text">
         <element type="Text">
-            <text value="Shadow resolution" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="ShadowResOff">
-            <text value="Off" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="ShadowResLow">
-            <text value="512x512" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="ShadowResMedium">
-            <text value="1024x1024" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="ShadowResHigh">
-            <text value="2048x2048" />
-        </element>
-        <element type="DropDownList" name="ShadowResolutionEdit">
-            <fixedwidth value="100" />
-            <popupitem name="ShadowResOff" />
-            <popupitem name="ShadowResLow" />
-            <popupitem name="ShadowResMedium" />
-            <popupitem name="ShadowResHigh" />
+            <attribute name="Text" value="Shadow resolution" />
+        </element>
+        <element type="DropDownList">
+            <attribute name="Name" value="ShadowResolutionEdit" />
+            <attribute name="Min Size" value="100 0" />
+            <attribute name="Max Size" value="100 2147483647" />
+            <attribute name="Resize Popup" value="true" />
+            <element internal="true">
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="Off" />
+                </element>
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="512x512" />
+                </element>
+               <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="1024x1024" />
+                </element>
+               <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="2048x2048" />
+                </element>
+            </element>
         </element>
         </element>
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="17" />
-        <layout mode="horizontal" spacing="8" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="8" />
         <element type="Text">
         <element type="Text">
-            <text value="Shadow quality" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="ShadowQuality0">
-            <text value="1-tap 16bit" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="ShadowQuality1">
-            <text value="1-tap 24bit" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="ShadowQuality2">
-            <text value="4-tap 16bit" />
-        </element>
-        <element type="Text" style="FileSelectorFilterText" name="ShadowQuality3">
-            <text value="4-tap 24bit" />
-        </element>
-        <element type="DropDownList" name="ShadowQualityEdit">
-            <fixedwidth value="100" />
-            <popupitem name="ShadowQuality0" />
-            <popupitem name="ShadowQuality1" />
-            <popupitem name="ShadowQuality2" />
-            <popupitem name="ShadowQuality3" />
+            <attribute name="Text" value="Shadow quality" />
+        </element>
+        <element type="DropDownList">
+            <attribute name="Name" value="ShadowQualityEdit" />
+            <attribute name="Min Size" value="100 0" />
+            <attribute name="Max Size" value="100 2147483647" />
+            <attribute name="Resize Popup" value="true" />
+            <element internal="true">
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="1-tap 16bit" />
+                </element>
+                <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="1-tap 24bit" />
+                </element>
+               <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="4-tap 16bit" />
+                </element>
+               <element type="Text" style="FileSelectorFilterText">
+                    <attribute name="Text" value="4-tap 24bit" />
+                </element>
+            </element>
         </element>
         </element>
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="17" />
-        <layout mode="horizontal" spacing="20" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="20" />
         <element type="Text">
         <element type="Text">
-            <text value="Max occluder triangles" />
+            <attribute name="Text" value="Max occluder triangles" />
         </element>
         </element>
-        <element type="LineEdit" name="MaxOccluderTrianglesEdit">
-            <fixedwidth value="100" />
+        <element type="LineEdit">
+            <attribute name="Name" value="MaxOccluderTrianglesEdit" />
+            <attribute name="Min Size" value="100 0" />
+            <attribute name="Max Size" value="100 2147483647" />
          </element>
          </element>
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="17" />
-        <layout mode="horizontal" spacing="8" />
-        <element type="CheckBox" name="SpecularLightingToggle">
-            <fixedsize value="16 16" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="8" />
+        <element type="CheckBox">
+            <attribute name="Name" value="SpecularLightingToggle" />
+            <attribute name="Min Size" value="16 16" />
+            <attribute name="Max Size" value="16 16" />
         </element>
         </element>
         <element type="Text">
         <element type="Text">
-            <text value="Specular lighting" />
+            <attribute name="Text" value="Specular lighting" />
         </element>
         </element>
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="17" />
-        <layout mode="horizontal" spacing="8" />
-        <element type="CheckBox" name="DynamicInstancingToggle">
-            <fixedsize value="16 16" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="8" />
+        <element type="CheckBox">
+            <attribute name="Name" value="DynamicInstancingToggle" />
+            <attribute name="Min Size" value="16 16" />
+            <attribute name="Max Size" value="16 16" />
         </element>
         </element>
         <element type="Text">
         <element type="Text">
-            <text value="Dynamic instancing" />
+            <attribute name="Text" value="Dynamic instancing" />
         </element>
         </element>
     </element>
     </element>
     <element>
     <element>
-        <fixedheight value="17" />
-        <layout mode="horizontal" spacing="8" />
-        <element type="CheckBox" name="FrameLimiterToggle">
-            <fixedsize value="16 16" />
+        <attribute name="Min Size" value="0 17" />
+        <attribute name="Max Size" value="2147483647 17" />
+        <attribute name="Layout Mode" value="Horizontal" />
+        <attribute name="Layout Spacing" value="8" />
+        <element type="CheckBox">
+            <attribute name="Name" value="FrameLimiterToggle" />
+            <attribute name="Min Size" value="16 16" />
+            <attribute name="Max Size" value="16 16" />
         </element>
         </element>
         <element type="Text">
         <element type="Text">
-            <text value="Frame limiter" />
+            <attribute name="Text" value="Frame limiter" />
         </element>
         </element>
     </element>
     </element>
 </element>
 </element>

+ 17 - 197
Docs/Reference.dox

@@ -1006,221 +1006,41 @@ Urho3D implements a simple, hierarchical user interface system based on rectangu
 - UIElement: container for other elements, renders nothing by itself
 - UIElement: container for other elements, renders nothing by itself
 - Window: a movable and resizable window
 - Window: a movable and resizable window
 
 
-The root UI element can be queried from the UI subsystem. It is an empty canvas (UIElement) as large as the application window, into which other elements can be added.
+The root %UI element can be queried from the UI subsystem. It is an empty canvas (UIElement) as large as the application window, into which other elements can be added.
 
 
-Elements are added into each other similarly as scene nodes, using the \ref UIElement::AddChild "AddChild()" and \ref UIElement::RemoveChild "RemoveChild()" functions. Each UI element has also a \ref UIElement::GetVars "user variables" VariantMap for storing custom data.
+Elements are added into each other similarly as scene nodes, using the \ref UIElement::AddChild "AddChild()" and \ref UIElement::RemoveChild "RemoveChild()" functions. Each %UI element has also a \ref UIElement::GetVars "user variables" VariantMap for storing custom data.
 
 
 \section UI_Defining Defining UI elements in XML
 \section UI_Defining Defining UI elements in XML
 
 
-Each UI element knows to load its properties from an XML file. There are two distinct use cases for this: either defining just the UI element style and leaving the actual position and dimensions to be filled in later, or fully defining a set of UI elements. For an example of defining element styles, see the file Data/UI/DefaultStyle.xml.
+User interface elements derive from Serializable, so they can be serialized to/from XML using their attributes. There are two distinct use cases for %UI definition files: either defining just the %UI element style and leaving the actual position and dimensions to be filled in later, or fully defining an %UI element layout. The default element style definitions, used for example by the editor and the debug console, are in the file Data/UI/DefaultStyle.xml.
 
 
-The function \ref UI::LoadLayout "LoadLayout()" in UI will take an XML file and instantiate the elements defined in it. To be valid XML, there should be one root UI element. An optional style XML file can be specified; the idea is to first read the element's style from that file, then fill in the rest from the actual layout XML file. This way the layout file can be relatively simple, as the majority of the data is already defined.
+The function \ref UI::LoadLayout "LoadLayout()" in UI will take an XML file and instantiate the elements defined in it. To be valid XML, there should be one root %UI element. An optional style XML file can be specified; the idea is to first read the element's style from that file, then fill in the rest from the actual layout XML file. This way the layout file can be relatively simple, as the majority of the data is already defined.
 
 
-The XML data for each UI element follows. Everything is optional and defaults will be used if missing. Note the redundant ways in which to define element size. Also note the element class hierarchy; for example a Button derives from BorderImage, and all elements derive from UIElement. See the comments in the elements' header files for descriptions of each property.
+See the elements' C++ code for all supported attributes, and look at the editor's user interface layouts in the Data/UI directory for examples. The serialization format is similar to scene XML serialization, with two important differences:
 
 
-\subsection UI_UIElement UIElement
+1) The element type to instantiate, and the style to use for it can be set separately. For example the following element definition
 
 
 \code
 \code
-<element name="ElementName" type="UIElement" >
-    <position value="x y" />
-    <size value="x y" />
-    <width value="x" />
-    <height value="y" />
-    <minsize value="x y" />
-    <minwidth value="x" />
-    <minheight value="y" />
-    <maxsize value="x y" />
-    <maxwidth value="x" />
-    <maxheight value="y" />
-    <fixedsize value="x y" />
-    <fixedwidth value="x" />
-    <fixedheight value="y" />
-    <alignment horizontal="left|center|right" vertical="top|center|bottom" />
-    <clipborder value="l t r b" />
-    <priority value="p" />
-    <opacity value="o" />
-    <color value="r g b a" | topleft="r g b a" topright="r g b a" bottomleft="r g b a" bottomright="r g b a" />
-    <bringtofront enable="true|false" />
-    <bringtoback enable="true|false" />
-    <clipchildren enable="true|false" />
-    <enabled enable="true|false" />
-    <selected enable="true|false" />
-    <visible enable="true|false" />
-    <focusmode value="notfocusable|resetfocus|focusable|focusabledefocusable" />
-    <layout mode="free|horizontal|vertical" spacing="s" border="l t r b" />
-    <vars>
-        <variant name="n" type="t" value="v" />
-        ...
-    </vars>
-</element>
-\endcode
-
-\subsection UI_BorderImage BorderImage
-
-\code
-<element type="BorderImage">
-    <texture name="TextureName" />
-    <imagerect value="l t r b" />
-    <border value="l t r b" />
-    <hoveroffset value="x y" />
-</element>
-\endcode
-
-\subsection UI_Button Button
-
-\code
-<element type="Button">
-    <pressedoffset value="x y" />
-    <labeloffset value="x y" />
-    <repeat delay="d" rate="r" />
-</element>
-\endcode
-
-\subsection UI_Checkbox Checkbox
-
-\code
-<element type="Checkbox">
-    <checkedoffset value="x y" />
-</element>
+<element type="Button" style="CloseButton" />
 \endcode
 \endcode
 
 
-\subsection UI_Cursor Cursor
+tells to instantiate a Button element, and that it should use the style "CloseButton" defined in the style XML file.
 
 
-\code
-<element type="Cursor">
-    <shape name="normal|resizevertical|resizediagonal_topright|resizehorizontal|resizediagonal_topleft|acceptdrop|rejectdrop"
-        texture="TextureName" imagerect="l t r b" hotspot="x y" />
-    ...
-</element>
-\endcode
-
-\subsection UI_Menu Menu
-
-If a popup element is specified, it will be searched for by name from the UI element hierarchy.
-
-\code
-<element type="Menu">
-    <popup name="ElementName" />
-    <popupoffset value="x y" />
-</element>
-\endcode
-
-\subsection UI_Text Text
-
-\code
-<element type="Text">
-    <font name="FontName" size="s" />
-    <text value="..." />
-    <textalignment value="left|center|right" />
-    <rowspacing value="s" />
-    <selection start="s" length="l" />
-    <selectioncolor value="r g b a" />
-    <hovercolor value="r g b a" />
-</element>
-\endcode
-
-\subsection UI_Window Window
+2) Internal sub-elements, for example the scroll bars of a ScrollView, need to be marked as such to avoid instantiating them as duplicates. This is done by adding the attribute internal="true" to the XML element, and is required in  both layout and style XML files. Furthermore, the elements must be listed in the order they have been added as children of the parent element (if in doubt, see the element's C++ constructor code. Omitting elements in the middle is OK.) For example:
 
 
 \code
 \code
-<element type="Window">
-    <resizeborder value="l t r b" />
-    <movable enable="true|false" />
-    <resizable enable="true|false" />
+<element type="ScrollView" />
+    <element type="ScrollBar" internal="true" />
+        ...customize the horizontal scroll bar attributes here...
+    </element>
+    <element type="ScrollBar" internal="true" />
+        ...customize the vertical scroll bar attributes here...
+    </element>
 </element>
 </element>
 \endcode
 \endcode
 
 
-\subsection UI_DropDownList DropDownList
-
-The styles of the listview, popup and placeholder sub-elements can be specified within the respective XML elements. The listview can be pre-filled by specifying popup items; they will be searched for by name from the UI element hierarchy.
+Note that when %UI elements are serialized back to XML using \ref UI::SaveLayout "SaveLayout()" it is no longer possible to separate what was defined in the style XML file, and what in the actual layout file. Instead all attributes will be serialized.
 
 
-\code
-<element type="DropDownList">
-    <selection value="s" />
-    <resizepopup enable="true|false" />
-    <listview />
-    <popup />
-    <placeholder />
-    <popupitem name="ElementName" />
-    ...
-</element>
-\endcode
-
-\subsection UI_LineEdit LineEdit
-
-The style of the cursor sub-element can specified with the "cursor" XML element.
-\code
-<element type="LineEdit">
-    <maxlength value="l" />
-    <cursormovable enable="true|false" />
-    <textselectable enable="true|false" />
-    <textcopyable enable="true|false" />
-    <text value="..." />
-    <cursorposition value="p" />
-    <cursorblinkrate value="r" />
-    <echocharacter value="c" />
-    <cursor />
-</element>
-\endcode
-
-\subsection UI_Slider Slider
-
-The style of the knob sub-element can specified with the "knob" XML element.
-
-\code
-<element type="Slider">
-    <orientation value="horizontal|vertical" />
-    <range max="m" value="v" />
-    <knob />
-</element>
-\endcode
-
-\subsection UI_ScrollBar ScrollBar
-
-The styles of the back button, forward button and the slider can be specified with the respective XML elements. Note the buttons' nonstandard imagerect element, which specifies the image to use for both a horizontal and a vertical button.
-
-\code
-<element type="ScrollBar">
-    <orientation value="horizontal|vertical" />
-    <range max="m" value="v" />
-    <scrollstep value="s" />
-    <stepfactor value="f" />
-    <backbutton>
-        <imagerect horizontal="l t r b" vertical="l t r b" />
-    </backbutton>
-    <forwardbutton>
-        <imagerect horizontal="l t r b" vertical="l t r b" />
-    </forwardbutton>
-    <slider />
-</element>
-\endcode
-
-\subsection UI_ScrollView ScrollView
-
-The styles of the horizontal and vertical scrollbars can be specified with the respective XML elements. If a content element is specified, it will be searched for by name from the UI element hierarchy.
-
-\code
-<element type="ScrollView">
-    <viewposition value="x y" />
-    <scrollstep value="s" />
-    <pagestep value="p" />
-    <horizontalscrollbar />
-    <verticalscrollbar />
-    <contentelement name="ElementName" />
-</element>
-\endcode
-
-\subsection UI_ListView ListView
-
-\code
-<element type="ListView">
-    <selection value="s" />
-    <highlight value="never|focus|always" />
-    <multiselect enable="true|false" />
-    <hierarchy enable="true|false" />
-    <clearselection enable="true|false" />
-    <doubleclickinterval value="i" />
-</element>
-\endcode
 
 
 \section UI_Layouts UI element layout
 \section UI_Layouts UI element layout
 
 

+ 15 - 0
Docs/ScriptAPI.dox

@@ -2746,6 +2746,7 @@ Methods:<br>
 - void ApplyAttributes()
 - void ApplyAttributes()
 - bool SetAttribute(const String&, const Variant&)
 - bool SetAttribute(const String&, const Variant&)
 - Variant GetAttribute(const String&)
 - Variant GetAttribute(const String&)
+- bool LoadXML(const XMLElement&, XMLFile@)
 - bool LoadXML(File@)
 - bool LoadXML(File@)
 - bool SaveXML(File@)
 - bool SaveXML(File@)
 - void SetStyle(const XMLElement&)
 - void SetStyle(const XMLElement&)
@@ -2839,6 +2840,7 @@ Methods:<br>
 - void ApplyAttributes()
 - void ApplyAttributes()
 - bool SetAttribute(const String&, const Variant&)
 - bool SetAttribute(const String&, const Variant&)
 - Variant GetAttribute(const String&)
 - Variant GetAttribute(const String&)
+- bool LoadXML(const XMLElement&, XMLFile@)
 - bool LoadXML(File@)
 - bool LoadXML(File@)
 - bool SaveXML(File@)
 - bool SaveXML(File@)
 - void SetStyle(const XMLElement&)
 - void SetStyle(const XMLElement&)
@@ -2938,6 +2940,7 @@ Methods:<br>
 - void ApplyAttributes()
 - void ApplyAttributes()
 - bool SetAttribute(const String&, const Variant&)
 - bool SetAttribute(const String&, const Variant&)
 - Variant GetAttribute(const String&)
 - Variant GetAttribute(const String&)
+- bool LoadXML(const XMLElement&, XMLFile@)
 - bool LoadXML(File@)
 - bool LoadXML(File@)
 - bool SaveXML(File@)
 - bool SaveXML(File@)
 - void SetStyle(const XMLElement&)
 - void SetStyle(const XMLElement&)
@@ -3044,6 +3047,7 @@ Methods:<br>
 - void ApplyAttributes()
 - void ApplyAttributes()
 - bool SetAttribute(const String&, const Variant&)
 - bool SetAttribute(const String&, const Variant&)
 - Variant GetAttribute(const String&)
 - Variant GetAttribute(const String&)
+- bool LoadXML(const XMLElement&, XMLFile@)
 - bool LoadXML(File@)
 - bool LoadXML(File@)
 - bool SaveXML(File@)
 - bool SaveXML(File@)
 - void SetStyle(const XMLElement&)
 - void SetStyle(const XMLElement&)
@@ -3146,6 +3150,7 @@ Methods:<br>
 - void ApplyAttributes()
 - void ApplyAttributes()
 - bool SetAttribute(const String&, const Variant&)
 - bool SetAttribute(const String&, const Variant&)
 - Variant GetAttribute(const String&)
 - Variant GetAttribute(const String&)
+- bool LoadXML(const XMLElement&, XMLFile@)
 - bool LoadXML(File@)
 - bool LoadXML(File@)
 - bool SaveXML(File@)
 - bool SaveXML(File@)
 - void SetStyle(const XMLElement&)
 - void SetStyle(const XMLElement&)
@@ -3247,6 +3252,7 @@ Methods:<br>
 - void ApplyAttributes()
 - void ApplyAttributes()
 - bool SetAttribute(const String&, const Variant&)
 - bool SetAttribute(const String&, const Variant&)
 - Variant GetAttribute(const String&)
 - Variant GetAttribute(const String&)
+- bool LoadXML(const XMLElement&, XMLFile@)
 - bool LoadXML(File@)
 - bool LoadXML(File@)
 - bool SaveXML(File@)
 - bool SaveXML(File@)
 - void SetStyle(const XMLElement&)
 - void SetStyle(const XMLElement&)
@@ -3351,6 +3357,7 @@ Methods:<br>
 - void ApplyAttributes()
 - void ApplyAttributes()
 - bool SetAttribute(const String&, const Variant&)
 - bool SetAttribute(const String&, const Variant&)
 - Variant GetAttribute(const String&)
 - Variant GetAttribute(const String&)
+- bool LoadXML(const XMLElement&, XMLFile@)
 - bool LoadXML(File@)
 - bool LoadXML(File@)
 - bool SaveXML(File@)
 - bool SaveXML(File@)
 - void SetStyle(const XMLElement&)
 - void SetStyle(const XMLElement&)
@@ -3456,6 +3463,7 @@ Methods:<br>
 - void ApplyAttributes()
 - void ApplyAttributes()
 - bool SetAttribute(const String&, const Variant&)
 - bool SetAttribute(const String&, const Variant&)
 - Variant GetAttribute(const String&)
 - Variant GetAttribute(const String&)
+- bool LoadXML(const XMLElement&, XMLFile@)
 - bool LoadXML(File@)
 - bool LoadXML(File@)
 - bool SaveXML(File@)
 - bool SaveXML(File@)
 - void SetStyle(const XMLElement&)
 - void SetStyle(const XMLElement&)
@@ -3558,6 +3566,7 @@ Methods:<br>
 - void ApplyAttributes()
 - void ApplyAttributes()
 - bool SetAttribute(const String&, const Variant&)
 - bool SetAttribute(const String&, const Variant&)
 - Variant GetAttribute(const String&)
 - Variant GetAttribute(const String&)
+- bool LoadXML(const XMLElement&, XMLFile@)
 - bool LoadXML(File@)
 - bool LoadXML(File@)
 - bool SaveXML(File@)
 - bool SaveXML(File@)
 - void SetStyle(const XMLElement&)
 - void SetStyle(const XMLElement&)
@@ -3687,6 +3696,7 @@ Methods:<br>
 - void ApplyAttributes()
 - void ApplyAttributes()
 - bool SetAttribute(const String&, const Variant&)
 - bool SetAttribute(const String&, const Variant&)
 - Variant GetAttribute(const String&)
 - Variant GetAttribute(const String&)
+- bool LoadXML(const XMLElement&, XMLFile@)
 - bool LoadXML(File@)
 - bool LoadXML(File@)
 - bool SaveXML(File@)
 - bool SaveXML(File@)
 - void SetStyle(const XMLElement&)
 - void SetStyle(const XMLElement&)
@@ -3796,6 +3806,7 @@ Methods:<br>
 - void ApplyAttributes()
 - void ApplyAttributes()
 - bool SetAttribute(const String&, const Variant&)
 - bool SetAttribute(const String&, const Variant&)
 - Variant GetAttribute(const String&)
 - Variant GetAttribute(const String&)
+- bool LoadXML(const XMLElement&, XMLFile@)
 - bool LoadXML(File@)
 - bool LoadXML(File@)
 - bool SaveXML(File@)
 - bool SaveXML(File@)
 - void SetStyle(const XMLElement&)
 - void SetStyle(const XMLElement&)
@@ -3905,6 +3916,7 @@ Methods:<br>
 - void ApplyAttributes()
 - void ApplyAttributes()
 - bool SetAttribute(const String&, const Variant&)
 - bool SetAttribute(const String&, const Variant&)
 - Variant GetAttribute(const String&)
 - Variant GetAttribute(const String&)
+- bool LoadXML(const XMLElement&, XMLFile@)
 - bool LoadXML(File@)
 - bool LoadXML(File@)
 - bool SaveXML(File@)
 - bool SaveXML(File@)
 - void SetStyle(const XMLElement&)
 - void SetStyle(const XMLElement&)
@@ -4018,6 +4030,7 @@ Methods:<br>
 - void ApplyAttributes()
 - void ApplyAttributes()
 - bool SetAttribute(const String&, const Variant&)
 - bool SetAttribute(const String&, const Variant&)
 - Variant GetAttribute(const String&)
 - Variant GetAttribute(const String&)
+- bool LoadXML(const XMLElement&, XMLFile@)
 - bool LoadXML(File@)
 - bool LoadXML(File@)
 - bool SaveXML(File@)
 - bool SaveXML(File@)
 - void SetStyle(const XMLElement&)
 - void SetStyle(const XMLElement&)
@@ -4142,6 +4155,7 @@ Methods:<br>
 - void ApplyAttributes()
 - void ApplyAttributes()
 - bool SetAttribute(const String&, const Variant&)
 - bool SetAttribute(const String&, const Variant&)
 - Variant GetAttribute(const String&)
 - Variant GetAttribute(const String&)
+- bool LoadXML(const XMLElement&, XMLFile@)
 - bool LoadXML(File@)
 - bool LoadXML(File@)
 - bool SaveXML(File@)
 - bool SaveXML(File@)
 - void SetStyle(const XMLElement&)
 - void SetStyle(const XMLElement&)
@@ -4267,6 +4281,7 @@ Methods:<br>
 - void Clear()
 - void Clear()
 - UIElement@ LoadLayout(XMLFile@)
 - UIElement@ LoadLayout(XMLFile@)
 - UIElement@ LoadLayout(XMLFile@, XMLFile@)
 - UIElement@ LoadLayout(XMLFile@, XMLFile@)
+- bool SaveLayout(File@, UIElement@)
 - UIElement@ GetElementAt(const IntVector2&, bool arg1 = true)
 - UIElement@ GetElementAt(const IntVector2&, bool arg1 = true)
 - UIElement@ GetElementAt(int, int, bool arg2 = true)
 - UIElement@ GetElementAt(int, int, bool arg2 = true)
 
 

+ 2 - 1
Engine/Engine/APITemplates.h

@@ -740,6 +740,7 @@ template <class T> void RegisterUIElement(asIScriptEngine* engine, const char* c
     RegisterObjectConstructor<T>(engine, className);
     RegisterObjectConstructor<T>(engine, className);
     RegisterNamedObjectConstructor<T>(engine, className);
     RegisterNamedObjectConstructor<T>(engine, className);
     RegisterSubclass<UIElement, T>(engine, "UIElement", className);
     RegisterSubclass<UIElement, T>(engine, "UIElement", className);
+    engine->RegisterObjectMethod(className, "bool LoadXML(const XMLElement&in, XMLFile@+)", asMETHODPR(T, LoadXML, (const XMLElement&, XMLFile*), bool), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "bool LoadXML(File@+)", asFUNCTION(UIElementLoadXML), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod(className, "bool LoadXML(File@+)", asFUNCTION(UIElementLoadXML), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod(className, "bool SaveXML(File@+)", asFUNCTION(UIElementSaveXML), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod(className, "bool SaveXML(File@+)", asFUNCTION(UIElementSaveXML), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod(className, "void SetStyle(const XMLElement&in)", asMETHODPR(T, SetStyle, (const XMLElement&), void), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void SetStyle(const XMLElement&in)", asMETHODPR(T, SetStyle, (const XMLElement&), void), asCALL_THISCALL);
@@ -854,7 +855,7 @@ template <class T> void RegisterBorderImage(asIScriptEngine* engine, const char*
     engine->RegisterObjectMethod(className, "void SetFullImageRect()", asMETHOD(T, SetFullImageRect), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void SetFullImageRect()", asMETHOD(T, SetFullImageRect), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void SetHoverOffset(int, int)", asMETHODPR(T, SetHoverOffset, (int, int), void), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void SetHoverOffset(int, int)", asMETHODPR(T, SetHoverOffset, (int, int), void), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_texture(Texture@+)", asMETHOD(T, SetTexture), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_texture(Texture@+)", asMETHOD(T, SetTexture), asCALL_THISCALL);
-    engine->RegisterObjectMethod(className, "Texture@+ get_texture() const", asMETHOD(T, SetTexture), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "Texture@+ get_texture() const", asMETHOD(T, GetTexture), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_imageRect(const IntRect&in)", asMETHODPR(T, SetImageRect, (const IntRect&), void), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_imageRect(const IntRect&in)", asMETHODPR(T, SetImageRect, (const IntRect&), void), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "const IntRect& get_imageRect() const", asMETHOD(T, GetImageRect), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "const IntRect& get_imageRect() const", asMETHOD(T, GetImageRect), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_border(const IntRect&in)", asMETHODPR(T, SetBorder, (const IntRect&), void), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "void set_border(const IntRect&in)", asMETHODPR(T, SetBorder, (const IntRect&), void), asCALL_THISCALL);

+ 9 - 0
Engine/Engine/UIAPI.cpp

@@ -434,12 +434,21 @@ static UIElement* UILoadLayoutWithStyle(XMLFile* file, XMLFile* styleFile, UI* p
     return root.Get();
     return root.Get();
 }
 }
 
 
+static bool UISaveLayout(File* file, UIElement* element, UI* ptr)
+{
+    if (file)
+        return ptr->SaveLayout(*file, element);
+    else
+        return false;
+}
+
 static void RegisterUI(asIScriptEngine* engine)
 static void RegisterUI(asIScriptEngine* engine)
 {
 {
     RegisterObject<UI>(engine, "UI");
     RegisterObject<UI>(engine, "UI");
     engine->RegisterObjectMethod("UI", "void Clear()", asMETHOD(UI, Clear), asCALL_THISCALL);
     engine->RegisterObjectMethod("UI", "void Clear()", asMETHOD(UI, Clear), asCALL_THISCALL);
     engine->RegisterObjectMethod("UI", "UIElement@ LoadLayout(XMLFile@+)", asFUNCTION(UILoadLayout), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("UI", "UIElement@ LoadLayout(XMLFile@+)", asFUNCTION(UILoadLayout), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("UI", "UIElement@ LoadLayout(XMLFile@+, XMLFile@+)", asFUNCTION(UILoadLayoutWithStyle), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("UI", "UIElement@ LoadLayout(XMLFile@+, XMLFile@+)", asFUNCTION(UILoadLayoutWithStyle), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("UI", "bool SaveLayout(File@+, UIElement@+)", asFUNCTION(UISaveLayout), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("UI", "UIElement@+ GetElementAt(const IntVector2&in, bool activeOnly = true)", asMETHODPR(UI, GetElementAt, (const IntVector2&, bool), UIElement*), asCALL_THISCALL);
     engine->RegisterObjectMethod("UI", "UIElement@+ GetElementAt(const IntVector2&in, bool activeOnly = true)", asMETHODPR(UI, GetElementAt, (const IntVector2&, bool), UIElement*), asCALL_THISCALL);
     engine->RegisterObjectMethod("UI", "UIElement@+ GetElementAt(int, int, bool activeOnly = true)", asMETHODPR(UI, GetElementAt, (int, int, bool), UIElement*), asCALL_THISCALL);
     engine->RegisterObjectMethod("UI", "UIElement@+ GetElementAt(int, int, bool activeOnly = true)", asMETHODPR(UI, GetElementAt, (int, int, bool), UIElement*), asCALL_THISCALL);
     engine->RegisterObjectMethod("UI", "void set_cursor(Cursor@+)", asMETHOD(UI, SetCursor), asCALL_THISCALL);
     engine->RegisterObjectMethod("UI", "void set_cursor(Cursor@+)", asMETHOD(UI, SetCursor), asCALL_THISCALL);

+ 16 - 0
Engine/Scene/Serializable.cpp

@@ -122,6 +122,14 @@ void Serializable::OnSetAttribute(const AttributeInfo& attr, const Variant& src)
     case VAR_VARIANTMAP:
     case VAR_VARIANTMAP:
         *(reinterpret_cast<VariantMap*>(dest)) = src.GetVariantMap();
         *(reinterpret_cast<VariantMap*>(dest)) = src.GetVariantMap();
         break;
         break;
+        
+    case VAR_INTRECT:
+        *(reinterpret_cast<IntRect*>(dest)) = src.GetIntRect();
+        break;
+        
+    case VAR_INTVECTOR2:
+        *(reinterpret_cast<IntVector2*>(dest)) = src.GetIntVector2();
+        break;
     }
     }
 }
 }
 
 
@@ -198,6 +206,14 @@ void Serializable::OnGetAttribute(const AttributeInfo& attr, Variant& dest)
     case VAR_VARIANTMAP:
     case VAR_VARIANTMAP:
         dest = *(reinterpret_cast<const VariantMap*>(src));
         dest = *(reinterpret_cast<const VariantMap*>(src));
         break;
         break;
+        
+    case VAR_INTRECT:
+        dest = *(reinterpret_cast<const IntRect*>(src));
+        break;
+        
+    case VAR_INTVECTOR2:
+        dest = *(reinterpret_cast<const IntVector2*>(src));
+        break;
     }
     }
 }
 }
 
 

+ 2 - 20
Engine/UI/BorderImage.cpp

@@ -50,29 +50,11 @@ void BorderImage::RegisterObject(Context* context)
 {
 {
     context->RegisterFactory<BorderImage>();
     context->RegisterFactory<BorderImage>();
     
     
-    COPY_BASE_ATTRIBUTES(BorderImage, UIElement);
     ACCESSOR_ATTRIBUTE(BorderImage, VAR_RESOURCEREF, "Texture", GetTextureAttr, SetTextureAttr, ResourceRef, ResourceRef(Texture2D::GetTypeStatic()), AM_FILE);
     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, "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_INTRECT, "Border", GetBorder, SetBorder, IntRect, IntRect::ZERO, AM_FILE);
-    REF_ACCESSOR_ATTRIBUTE(BorderImage, VAR_INTVECTOR2, "Hover Offset", GetHoverOffset, SetHoverOffset, IntVector2, IntVector2::ZERO, AM_FILE);
-}
-
-void BorderImage::SetStyle(const XMLElement& element)
-{
-    UIElement::SetStyle(element);
-    
-    if (element.HasChild("texture"))
-        SetTexture(GetSubsystem<ResourceCache>()->GetResource<Texture2D>(element.GetChild("texture").GetAttribute("name")));
-    if (element.HasChild("imagerect"))
-    {
-        XMLElement imageElem = element.GetChild("imagerect");
-        if (imageElem.HasAttribute("value"))
-            SetImageRect(imageElem.GetIntRect("value"));
-    }
-    if (element.HasChild("border"))
-        SetBorder(element.GetChild("border").GetIntRect("value"));
-    if (element.HasChild("hoveroffset"))
-        SetHoverOffset(element.GetChild("hoveroffset").GetIntVector2("value"));
+    REF_ACCESSOR_ATTRIBUTE(BorderImage, VAR_INTVECTOR2, "Hover Image Offset", GetHoverOffset, SetHoverOffset, IntVector2, IntVector2::ZERO, AM_FILE);
+    COPY_BASE_ATTRIBUTES(BorderImage, UIElement);
 }
 }
 
 
 void BorderImage::SetTextureAttr(ResourceRef value)
 void BorderImage::SetTextureAttr(ResourceRef value)

+ 0 - 4
Engine/UI/BorderImage.h

@@ -36,8 +36,6 @@ class BorderImage : public UIElement
 {
 {
     OBJECT(BorderImage);
     OBJECT(BorderImage);
     
     
-    using UIElement::SetStyle;
-    
 public:
 public:
     /// Construct.
     /// Construct.
     BorderImage(Context* context);
     BorderImage(Context* context);
@@ -46,8 +44,6 @@ public:
     /// Register object factory.
     /// Register object factory.
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
     
     
-    /// Set UI element style from XML data.
-    virtual void SetStyle(const XMLElement& element);
     /// Return UI rendering batches.
     /// Return UI rendering batches.
     virtual void GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor);
     virtual void GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor);
     
     

+ 2 - 17
Engine/UI/Button.cpp

@@ -54,26 +54,11 @@ void Button::RegisterObject(Context* context)
 {
 {
     context->RegisterFactory<Button>();
     context->RegisterFactory<Button>();
     
     
-    COPY_BASE_ATTRIBUTES(Button, BorderImage);
-    REF_ACCESSOR_ATTRIBUTE(Button, VAR_INTVECTOR2, "Pressed Offset", GetPressedOffset, SetPressedOffset, IntVector2, IntVector2::ZERO, AM_FILE);
+    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);
     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 Delay", GetRepeatDelay, SetRepeatDelay, float, 1.0f, AM_FILE);
     ACCESSOR_ATTRIBUTE(Button, VAR_FLOAT, "Repeat Rate", GetRepeatRate, SetRepeatRate, float, 0.0f, AM_FILE);
     ACCESSOR_ATTRIBUTE(Button, VAR_FLOAT, "Repeat Rate", GetRepeatRate, SetRepeatRate, float, 0.0f, AM_FILE);
-}
-
-void Button::SetStyle(const XMLElement& element)
-{
-    BorderImage::SetStyle(element);
-    
-    if (element.HasChild("pressedoffset"))
-        SetPressedOffset(element.GetChild("pressedoffset").GetIntVector2("value"));
-    if (element.HasChild("labeloffset"))
-        SetLabelOffset(element.GetChild("labeloffset").GetIntVector2("value"));
-    if (element.HasChild("repeat"))
-    {
-        XMLElement repeatElem = element.GetChild("repeat");
-        SetRepeat(repeatElem.GetFloat("delay"), repeatElem.GetFloat("rate"));
-    }
+    COPY_BASE_ATTRIBUTES(Button, BorderImage);
 }
 }
 
 
 void Button::Update(float timeStep)
 void Button::Update(float timeStep)

+ 0 - 4
Engine/UI/Button.h

@@ -33,8 +33,6 @@ class Button : public BorderImage
 {
 {
     OBJECT(Button);
     OBJECT(Button);
     
     
-    using UIElement::SetStyle;
-    
 public:
 public:
     /// Construct.
     /// Construct.
     Button(Context* context);
     Button(Context* context);
@@ -43,8 +41,6 @@ public:
     /// Register object factory.
     /// Register object factory.
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
     
     
-    /// Set UI element style from XML data.
-    virtual void SetStyle(const XMLElement& element);
     /// Perform UI element update.
     /// Perform UI element update.
     virtual void Update(float timeStep);
     virtual void Update(float timeStep);
     /// Return UI rendering batches.
     /// Return UI rendering batches.

+ 1 - 9
Engine/UI/CheckBox.cpp

@@ -50,16 +50,8 @@ void CheckBox::RegisterObject(Context* context)
 {
 {
     context->RegisterFactory<CheckBox>();
     context->RegisterFactory<CheckBox>();
     
     
+    REF_ACCESSOR_ATTRIBUTE(CheckBox, VAR_INTVECTOR2,"Checked Image Offset", GetCheckedOffset, SetCheckedOffset, IntVector2, IntVector2::ZERO, AM_FILE);
     COPY_BASE_ATTRIBUTES(CheckBox, BorderImage);
     COPY_BASE_ATTRIBUTES(CheckBox, BorderImage);
-    REF_ACCESSOR_ATTRIBUTE(CheckBox, VAR_INTVECTOR2,"Checked Offset", GetCheckedOffset, SetCheckedOffset, IntVector2, IntVector2::ZERO, AM_FILE);
-}
-
-void CheckBox::SetStyle(const XMLElement& element)
-{
-    BorderImage::SetStyle(element);
-    
-    if (element.HasChild("checkedoffset"))
-        SetCheckedOffset(element.GetChild("checkedoffset").GetIntVector2("value"));
 }
 }
 
 
 void CheckBox::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor)
 void CheckBox::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor)

+ 0 - 4
Engine/UI/CheckBox.h

@@ -33,8 +33,6 @@ class CheckBox : public BorderImage
 {
 {
     OBJECT(CheckBox);
     OBJECT(CheckBox);
     
     
-    using UIElement::SetStyle;
-    
 public:
 public:
     /// Construct.
     /// Construct.
     CheckBox(Context* context);
     CheckBox(Context* context);
@@ -43,8 +41,6 @@ public:
     /// Register object factory.
     /// Register object factory.
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
     
     
-    /// Set UI element style from XML data.
-    virtual void SetStyle(const XMLElement& element);
     /// Return UI rendering batches.
     /// Return UI rendering batches.
     virtual void GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor);
     virtual void GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor);
     /// React to mouse click.
     /// React to mouse click.

+ 59 - 22
Engine/UI/Cursor.cpp

@@ -33,16 +33,16 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
-static const String shapeNames[] =
+static const char* shapeNames[] =
 {
 {
-    "normal",
-    "resizevertical",
-    "resizediagonal_topright",
-    "resizehorizontal",
-    "resizediagonal_topleft",
-    "acceptdrop",
-    "rejectdrop",
-    ""
+    "Normal",
+    "ResizeVertical",
+    "ResizeDiagonalTopRight",
+    "ResizeHorizontal",
+    "ResizeDiagonalTopLeft",
+    "AcceptDrop",
+    "RejectDrop",
+    0
 };
 };
 
 
 OBJECTTYPESTATIC(Cursor);
 OBJECTTYPESTATIC(Cursor);
@@ -69,20 +69,9 @@ Cursor::~Cursor()
 void Cursor::RegisterObject(Context* context)
 void Cursor::RegisterObject(Context* context)
 {
 {
     context->RegisterFactory<Cursor>();
     context->RegisterFactory<Cursor>();
-}
-
-void Cursor::SetStyle(const XMLElement& element)
-{
-    UIElement::SetStyle(element);
     
     
-    XMLElement shapeElem = element.GetChild("shape");
-    while (shapeElem)
-    {
-        CursorShape shape = (CursorShape)GetStringListIndex(shapeElem.GetAttributeLower("name"), shapeNames, CS_NORMAL);
-        DefineShape(shape, GetSubsystem<ResourceCache>()->GetResource<Texture2D>(shapeElem.GetAttribute("texture")),
-            shapeElem.GetIntRect("imagerect"), shapeElem.GetIntVector2("hotspot"));
-        shapeElem = shapeElem.GetNext("shape");
-    }
+    ACCESSOR_ATTRIBUTE(Cursor, VAR_VARIANTVECTOR, "Shapes", GetShapesAttr, SetShapesAttr, VariantVector, VariantVector(), AM_FILE);
+    COPY_BASE_ATTRIBUTES(Cursor, BorderImage);
 }
 }
 
 
 void Cursor::DefineShape(CursorShape shape, Texture* texture, const IntRect& imageRect, const IntVector2& hotSpot)
 void Cursor::DefineShape(CursorShape shape, Texture* texture, const IntRect& imageRect, const IntVector2& hotSpot)
@@ -107,6 +96,54 @@ void Cursor::SetShape(CursorShape shape)
     SetSize(info.imageRect_.Size());
     SetSize(info.imageRect_.Size());
 }
 }
 
 
+void Cursor::SetShapesAttr(VariantVector value)
+{
+    unsigned index = 0;
+    if (!value.Size())
+        return;
+    
+    unsigned numShapes = value[index++].GetUInt();
+    while (numShapes-- && (index + 4) <= value.Size())
+    {
+        CursorShape shape = (CursorShape)GetStringListIndex(value[index++].GetString().CString(), shapeNames, CS_MAX_SHAPES);
+        if (shape != CS_MAX_SHAPES)
+        {
+            ResourceRef ref = value[index++].GetResourceRef();
+            IntRect imageRect = value[index++].GetIntRect();
+            IntVector2 hotSpot = value[index++].GetIntVector2();
+            DefineShape(shape, GetSubsystem<ResourceCache>()->GetResource<Texture2D>(ref.id_), imageRect, hotSpot);
+        }
+        else
+            index += 3;
+    }
+}
+
+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)
+    {
+        if (shapeInfos_[i].imageRect_ != IntRect::ZERO)
+        {
+            ret.Push(String(shapeNames[i]));
+            ret.Push(GetResourceRef(shapeInfos_[i].texture_, Texture2D::GetTypeStatic()));
+            ret.Push(shapeInfos_[i].imageRect_);
+            ret.Push(shapeInfos_[i].hotSpot_);
+        }
+    }
+    
+    return ret;
+}
+
 void Cursor::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor)
 void Cursor::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor)
 {
 {
     unsigned initialSize = quads.Size();
     unsigned initialSize = quads.Size();

+ 5 - 4
Engine/UI/Cursor.h

@@ -57,8 +57,6 @@ class Cursor : public BorderImage
 {
 {
     OBJECT(Cursor);
     OBJECT(Cursor);
     
     
-    using UIElement::SetStyle;
-    
 public:
 public:
     /// Construct.
     /// Construct.
     Cursor(Context* context);
     Cursor(Context* context);
@@ -67,8 +65,6 @@ public:
     /// Register object factory.
     /// Register object factory.
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
     
     
-    /// Set UI element style from XML data.
-    virtual void SetStyle(const XMLElement& element);
     /// Return UI rendering batches.
     /// Return UI rendering batches.
     virtual void GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor);
     virtual void GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor);
     
     
@@ -80,6 +76,11 @@ public:
     /// Get current shape.
     /// Get current shape.
     CursorShape GetShape() const { return shape_; }
     CursorShape GetShape() const { return shape_; }
     
     
+    /// Set shapes attribute.
+    void SetShapesAttr(VariantVector value);
+    /// Return shapes attribute.
+    VariantVector GetShapesAttr() const;
+    
 protected:
 protected:
     /// Current shape index.
     /// Current shape index.
     CursorShape shape_;
     CursorShape shape_;

+ 13 - 31
Engine/UI/DropDownList.cpp

@@ -43,6 +43,10 @@ DropDownList::DropDownList(Context* context) :
     window->SetInternal(true);
     window->SetInternal(true);
     SetPopup(window);
     SetPopup(window);
     
     
+    // Hack: parent the popup to the dropdownlist until first shown to allow loading style from XML
+    AddChild(window);
+    window->SetVisible(false);
+    
     listView_ = new ListView(context_);
     listView_ = new ListView(context_);
     listView_->SetInternal(true);
     listView_->SetInternal(true);
     listView_->SetScrollBarsVisible(false, false);
     listView_->SetScrollBarsVisible(false, false);
@@ -62,40 +66,17 @@ DropDownList::~DropDownList()
 void DropDownList::RegisterObject(Context* context)
 void DropDownList::RegisterObject(Context* context)
 {
 {
     context->RegisterFactory<DropDownList>();
     context->RegisterFactory<DropDownList>();
+    
+    COPY_BASE_ATTRIBUTES(DropDownList, Menu);
+    ACCESSOR_ATTRIBUTE(DropDownList, VAR_BOOL, "Resize Popup", GetResizePopup, SetResizePopup, bool, false, AM_FILE);
 }
 }
 
 
-void DropDownList::SetStyle(const XMLElement& element)
+void DropDownList::ApplyAttributes()
 {
 {
-    Menu::SetStyle(element);
-    
-    XMLElement listElem = element.GetChild("listview");
-    if (listElem)
-        listView_->SetStyle(listElem);
-    
-    XMLElement popupElem = element.GetChild("popup");
-    if (popupElem)
-        popup_->SetStyle(popupElem);
-    
-    XMLElement placeholderElem = element.GetChild("placeholder");
-    if (placeholderElem)
-        placeholder_->SetStyle(placeholderElem);
-    
-    UIElement* root = GetRoot();
-    XMLElement itemElem = element.GetChild("popupitem");
-    if (root)
-    {
-        while (itemElem)
-        {
-            if (itemElem.HasAttribute("name"))
-                AddItem(root->GetChild(itemElem.GetAttribute("name"), true));
-            itemElem = itemElem.GetNext("popupitem");
-        }
-    }
-    
-    if (element.HasChild("selection"))
-        SetSelection(element.GetChild("selection").GetInt("value"));
-    if (element.HasChild("resizepopup"))
-        SetResizePopup(element.GetChild("resizepopup").GetBool("enable"));
+    // Hack: if the placeholder has any child elements defined, move them to the list
+    /// \todo This will not be serialized back to XML as expected
+    while (placeholder_->GetNumChildren())
+        AddItem(placeholder_->GetChild(0));
 }
 }
 
 
 void DropDownList::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor)
 void DropDownList::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor)
@@ -130,6 +111,7 @@ void DropDownList::OnShowPopup()
     const IntRect& border = popup_->GetLayoutBorder();
     const IntRect& border = popup_->GetLayoutBorder();
     popup_->SetSize(resizePopup_ ? GetWidth() : contentSize.x_ + border.left_ + border.right_, contentSize.y_ + border.top_ + 
     popup_->SetSize(resizePopup_ ? GetWidth() : contentSize.x_ + border.left_ + border.right_, contentSize.y_ + border.top_ + 
         border.bottom_);
         border.bottom_);
+    listView_->SetViewPosition(IntVector2::ZERO);
     
     
     // Check if popup fits below the button. If not, show above instead
     // Check if popup fits below the button. If not, show above instead
     bool showAbove = false;
     bool showAbove = false;

+ 2 - 4
Engine/UI/DropDownList.h

@@ -35,8 +35,6 @@ class DropDownList : public Menu
 {
 {
     OBJECT(DropDownList)
     OBJECT(DropDownList)
     
     
-    using UIElement::SetStyle;
-    
 public:
 public:
     /// Construct.
     /// Construct.
     DropDownList(Context* context);
     DropDownList(Context* context);
@@ -45,8 +43,8 @@ public:
     /// Register object factory.
     /// Register object factory.
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
     
     
-    /// Set UI element style from XML data.
-    virtual void SetStyle(const XMLElement& element);
+    /// Apply attribute changes that can not be applied immediately.
+    virtual void ApplyAttributes();
     /// Return UI rendering batches.
     /// Return UI rendering batches.
     virtual void GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor);
     virtual void GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor);
     /// React to the popup being shown.
     /// React to the popup being shown.

+ 3 - 36
Engine/UI/LineEdit.cpp

@@ -72,51 +72,18 @@ void LineEdit::RegisterObject(Context* context)
 {
 {
     context->RegisterFactory<LineEdit>();
     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_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 Cursor Movable", IsCursorMovable, SetCursorMovable, bool, true, AM_FILE);
     ACCESSOR_ATTRIBUTE(LineEdit, VAR_BOOL, "Is Text Selectable", IsTextSelectable, SetTextSelectable, bool, true, AM_FILE);
     ACCESSOR_ATTRIBUTE(LineEdit, VAR_BOOL, "Is Text Selectable", IsTextSelectable, SetTextSelectable, bool, true, AM_FILE);
     ACCESSOR_ATTRIBUTE(LineEdit, VAR_BOOL, "Is Text Copyable", IsTextCopyable, SetTextCopyable, bool, true, AM_FILE);
     ACCESSOR_ATTRIBUTE(LineEdit, VAR_BOOL, "Is Text Copyable", IsTextCopyable, SetTextCopyable, bool, true, AM_FILE);
-    ACCESSOR_ATTRIBUTE(LineEdit, VAR_INT, "Cursor Position", GetCursorPosition, SetCursorPosition, unsigned, 0, AM_FILE);
     ACCESSOR_ATTRIBUTE(LineEdit, VAR_FLOAT, "Cursor Blink Rate", GetCursorBlinkRate, SetCursorBlinkRate, float, 1.0f, AM_FILE);
     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);
     ATTRIBUTE(LineEdit, VAR_INT, "Echo Character", echoCharacter_, 0, AM_FILE);
+    COPY_BASE_ATTRIBUTES(LineEdit, BorderImage);
 }
 }
 
 
-void LineEdit::SetStyle(const XMLElement& element)
+void LineEdit::ApplyAttributes()
 {
 {
-    BorderImage::SetStyle(element);
-    
-    if (element.HasChild("maxlength"))
-        SetMaxLength(element.GetChild("maxlength").GetInt("value"));
-    if (element.HasChild("cursormovable"))
-        SetCursorMovable(element.GetChild("cursormovable").GetBool("enable"));
-    if (element.HasChild("textselectable"))
-        SetTextSelectable(element.GetChild("textselectable").GetBool("enable"));
-    if (element.HasChild("textcopyable"))
-        SetTextCopyable(element.GetChild("textcopyable").GetBool("enable"));
-    
-    XMLElement textElem = element.GetChild("text");
-    if (textElem)
-    {
-        if (textElem.HasAttribute("value"))
-            SetText(textElem.GetAttribute("value"));
-        text_->SetStyle(textElem);
-    }
-    
-    XMLElement cursorElem = element.GetChild("cursor");
-    if (cursorElem)
-        cursor_->SetStyle(cursorElem);
-    
-    if (element.HasChild("cursorposition"))
-        SetCursorPosition(element.GetChild("cursorposition").GetInt("value"));
-    if (element.HasChild("cursorblinkrate"))
-        SetCursorBlinkRate(element.GetChild("cursorblinkrate").GetFloat("value"));
-    if (element.HasChild("echocharacter"))
-    {
-        String text = element.GetChild("echocharacter").GetAttribute("value");
-        if (text.Length())
-            SetEchoCharacter(text[0]);
-    }
+    UIElement::ApplyAttributes();
     
     
     // Set the text's position to match clipping, so that text left edge is not left partially hidden
     // Set the text's position to match clipping, so that text left edge is not left partially hidden
     text_->SetPosition(clipBorder_.left_, clipBorder_.top_);
     text_->SetPosition(clipBorder_.left_, clipBorder_.top_);

+ 2 - 4
Engine/UI/LineEdit.h

@@ -36,8 +36,6 @@ class LineEdit : public BorderImage
 {
 {
     OBJECT(LineEdit);
     OBJECT(LineEdit);
     
     
-    using UIElement::SetStyle;
-    
 public:
 public:
     /// Construct.
     /// Construct.
     LineEdit(Context* context);
     LineEdit(Context* context);
@@ -46,8 +44,8 @@ public:
     /// Register object factory.
     /// Register object factory.
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
     
     
-    /// Set UI element style from XML data.
-    virtual void SetStyle(const XMLElement& element);
+    /// Apply attribute changes that can not be applied immediately.
+    virtual void ApplyAttributes();
     /// Perform UI element update.
     /// Perform UI element update.
     virtual void Update(float timeStep);
     virtual void Update(float timeStep);
     
     

+ 19 - 52
Engine/UI/ListView.cpp

@@ -38,14 +38,19 @@ namespace Urho3D
 
 
 static const ShortStringHash indentHash("Indent");
 static const ShortStringHash indentHash("Indent");
 
 
-static const String highlightModes[] =
+static const char* highlightModes[] =
 {
 {
-    "never",
-    "focus",
-    "always",
+    "Never",
+    "Focus",
+    "Always",
     ""
     ""
 };
 };
 
 
+template<> HighlightMode Variant::Get<HighlightMode>() const
+{
+    return (HighlightMode)GetInt();
+}
+
 int GetItemIndent(UIElement* item)
 int GetItemIndent(UIElement* item)
 {
 {
     if (!item)
     if (!item)
@@ -84,52 +89,13 @@ ListView::~ListView()
 void ListView::RegisterObject(Context* context)
 void ListView::RegisterObject(Context* context)
 {
 {
     context->RegisterFactory<ListView>();
     context->RegisterFactory<ListView>();
-}
-
-void ListView::SetStyle(const XMLElement& element)
-{
-    ScrollView::SetStyle(element);
-    
-    UIElement* root = GetRoot();
-    XMLElement itemElem = element.GetChild("listitem");
-    if (root)
-    {
-        while (itemElem)
-        {
-            if (itemElem.HasAttribute("name"))
-            {
-                UIElement* item = root->GetChild(itemElem.GetAttribute("name"), true);
-                AddItem(item);
-                if (itemElem.HasAttribute("indent"))
-                    item->SetVar(indentHash, itemElem.GetInt("indent"));
-                itemElem = itemElem.GetNext("listitem");
-            }
-        }
-    }
-    
-    if (element.HasChild("highlight"))
-    {
-        String highlight = element.GetChild("highlight").GetAttributeLower("value");
-        SetHighlightMode((HighlightMode)GetStringListIndex(highlight, highlightModes, HM_FOCUS));
-    }
-    if (element.HasChild("multiselect"))
-        SetMultiselect(element.GetChild("multiselect").GetBool("enable"));
-    if (element.HasChild("hierarchy"))
-        SetHierarchyMode(element.GetChild("hierarchy").GetBool("enable"));
-    if (element.HasChild("clearselection"))
-        SetClearSelectionOnDefocus(element.GetChild("clearselection").GetBool("enable"));
-    if (element.HasChild("doubleclickinterval"))
-        SetDoubleClickInterval(element.GetChild("doubleclickinterval").GetFloat("value"));
-    
-    XMLElement selectionElem = element.GetChild("selection");
-    while (selectionElem)
-    {
-        AddSelection(selectionElem.GetInt("value"));
-        selectionElem = selectionElem.GetNext("selection");
-    }
     
     
-    // Set the container's layout border to match scroll panel clipping, so that elements are not left partially hidden
-    contentElement_->SetLayoutBorder(scrollPanel_->GetClipBorder());
+    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_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::Update(float timeStep)
 void ListView::Update(float timeStep)
@@ -260,8 +226,9 @@ void ListView::OnResize()
 {
 {
     ScrollView::OnResize();
     ScrollView::OnResize();
     
     
-    // Set the content element width to match the scrollpanel
-    contentElement_->SetWidth(scrollPanel_->GetWidth());
+    // Set the content element width to match the scrollpanel minus clipping
+    IntRect panelBorder = scrollPanel_->GetClipBorder();
+    contentElement_->SetWidth(scrollPanel_->GetWidth() - panelBorder.left_ - panelBorder.right_);
 }
 }
 
 
 void ListView::AddItem(UIElement* item)
 void ListView::AddItem(UIElement* item)
@@ -719,8 +686,8 @@ void ListView::EnsureItemVisibility(UIElement* item)
     if (!item || !item->IsVisible())
     if (!item || !item->IsVisible())
         return;
         return;
     
     
-    IntVector2 currentOffset = item->GetScreenPosition() - scrollPanel_->GetScreenPosition() - contentElement_->GetPosition();
     IntVector2 newView = GetViewPosition();
     IntVector2 newView = GetViewPosition();
+    IntVector2 currentOffset = item->GetPosition() - newView;
     const IntRect& clipBorder = scrollPanel_->GetClipBorder();
     const IntRect& clipBorder = scrollPanel_->GetClipBorder();
     IntVector2 windowSize(scrollPanel_->GetWidth() - clipBorder.left_ - clipBorder.right_, scrollPanel_->GetHeight() -
     IntVector2 windowSize(scrollPanel_->GetWidth() - clipBorder.left_ - clipBorder.right_, scrollPanel_->GetHeight() -
         clipBorder.top_ - clipBorder.bottom_);
         clipBorder.top_ - clipBorder.bottom_);

+ 0 - 4
Engine/UI/ListView.h

@@ -45,8 +45,6 @@ class ListView : public ScrollView
 {
 {
     OBJECT(ListView);
     OBJECT(ListView);
     
     
-    using UIElement::SetStyle;
-    
 public:
 public:
     /// Construct.
     /// Construct.
     ListView(Context* context);
     ListView(Context* context);
@@ -55,8 +53,6 @@ public:
     /// Register object factory.
     /// Register object factory.
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
     
     
-    /// Set UI element style from XML data.
-    virtual void SetStyle(const XMLElement& element);
     /// Perform UI element update.
     /// Perform UI element update.
     virtual void Update(float timeStep);
     virtual void Update(float timeStep);
     /// React to a key press.
     /// React to a key press.

+ 2 - 15
Engine/UI/Menu.cpp

@@ -59,22 +59,9 @@ Menu::~Menu()
 void Menu::RegisterObject(Context* context)
 void Menu::RegisterObject(Context* context)
 {
 {
     context->RegisterFactory<Menu>();
     context->RegisterFactory<Menu>();
-}
-
-void Menu::SetStyle(const XMLElement& element)
-{
-    Button::SetStyle(element);
-    
-    XMLElement popupElem = element.GetChild("popup");
-    if (popupElem && popupElem.HasAttribute("name"))
-    {
-        UIElement* root = GetRoot();
-        if (root)
-            SetPopup(root->GetChild(popupElem.GetAttribute("name"), true));
-    }
     
     
-    if (element.HasChild("popupoffset"))
-        SetPopupOffset(element.GetChild("popupoffset").GetIntVector2("value"));
+    REF_ACCESSOR_ATTRIBUTE(Menu, VAR_INTVECTOR2, "Popup Offset", GetPopupOffset, SetPopupOffset, IntVector2, IntVector2::ZERO, AM_FILE);
+    COPY_BASE_ATTRIBUTES(Menu, Button);
 }
 }
 
 
 void Menu::OnShowPopup()
 void Menu::OnShowPopup()

+ 0 - 4
Engine/UI/Menu.h

@@ -33,8 +33,6 @@ class Menu : public Button
 {
 {
     OBJECT(Menu);
     OBJECT(Menu);
     
     
-    using UIElement::SetStyle;
-    
 public:
 public:
     /// Construct.
     /// Construct.
     Menu(Context* context);
     Menu(Context* context);
@@ -43,8 +41,6 @@ public:
     /// Register object factory.
     /// Register object factory.
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
     
     
-    /// Set UI element style from XML data.
-    virtual void SetStyle(const XMLElement& element);
     /// React to the popup being shown.
     /// React to the popup being shown.
     virtual void OnShowPopup();
     virtual void OnShowPopup();
     
     

+ 22 - 51
Engine/UI/ScrollBar.cpp

@@ -35,6 +35,8 @@ static const float DEFAULT_SCROLL_STEP = 0.1f;
 static const float DEFAULT_REPEAT_DELAY = 0.4f;
 static const float DEFAULT_REPEAT_DELAY = 0.4f;
 static const float DEFAULT_REPEAT_RATE = 20.0f;
 static const float DEFAULT_REPEAT_RATE = 20.0f;
 
 
+extern const char* orientations[];
+
 OBJECTTYPESTATIC(ScrollBar);
 OBJECTTYPESTATIC(ScrollBar);
 
 
 ScrollBar::ScrollBar(Context* context) :
 ScrollBar::ScrollBar(Context* context) :
@@ -72,64 +74,33 @@ ScrollBar::~ScrollBar()
 void ScrollBar::RegisterObject(Context* context)
 void ScrollBar::RegisterObject(Context* context)
 {
 {
     context->RegisterFactory<ScrollBar>();
     context->RegisterFactory<ScrollBar>();
+    
+    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);
+    ACCESSOR_ATTRIBUTE(ScrollBar, VAR_FLOAT, "Scroll Step", GetScrollStep, SetScrollStep, float, DEFAULT_SCROLL_STEP, AM_FILE);
+    ACCESSOR_ATTRIBUTE(ScrollBar, VAR_FLOAT, "Step Factor", GetStepFactor, SetStepFactor, float, 1.0f, AM_FILE);
+    ATTRIBUTE(ScrollBar, VAR_INTRECT, "Left Image Rect", leftRect_, IntRect::ZERO, AM_FILE);
+    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::SetStyle(const XMLElement& element)
+void ScrollBar::ApplyAttributes()
 {
 {
-    UIElement::SetStyle(element);
-    
-    if (element.HasChild("range"))
-    {
-        XMLElement rangeElem = element.GetChild("range");
-        SetRange(rangeElem.GetFloat("max"));
-        SetValue(rangeElem.GetFloat("value"));
-    }
-    if (element.HasChild("scrollstep"))
-        SetScrollStep(element.GetChild("scrollstep").GetFloat("value"));
-    if (element.HasChild("stepfactor"))
-        SetStepFactor(element.GetChild("stepfactor").GetFloat("value"));
-    
-    XMLElement backButtonElem = element.GetChild("backbutton");
-    if (backButtonElem)
-    {
-        XMLElement imageElem = backButtonElem.GetChild("imagerect");
-        if (imageElem.HasAttribute("horizontal"))
-            leftRect_ = imageElem.GetIntRect("horizontal");
-        if (imageElem.HasAttribute("vertical"))
-            upRect_ = imageElem.GetIntRect("vertical");
-        if (imageElem.HasAttribute("h"))
-            leftRect_ = imageElem.GetIntRect("h");
-        if (imageElem.HasAttribute("v"))
-            upRect_ = imageElem.GetIntRect("v");
-        backButton_->SetStyle(backButtonElem);
-    }
+    UIElement::ApplyAttributes();
     
     
-    XMLElement forwardButtonElem = element.GetChild("forwardbutton");
-    if (forwardButtonElem)
+    // Reapply orientation to the button images
+    if (slider_->GetOrientation() == O_HORIZONTAL)
     {
     {
-        XMLElement imageElem = forwardButtonElem.GetChild("imagerect");
-        if (imageElem.HasAttribute("horizontal"))
-            rightRect_ = imageElem.GetIntRect("horizontal");
-        if (imageElem.HasAttribute("vertical"))
-            downRect_ = imageElem.GetIntRect("vertical");
-        if (imageElem.HasAttribute("h"))
-            rightRect_ = imageElem.GetIntRect("h");
-        if (imageElem.HasAttribute("v"))
-            downRect_ = imageElem.GetIntRect("v");
-        forwardButton_->SetStyle(forwardButtonElem);
+        backButton_->SetImageRect(leftRect_);
+        forwardButton_->SetImageRect(rightRect_);
     }
     }
-    
-    XMLElement sliderElem = element.GetChild("slider");
-    if (sliderElem)
-        slider_->SetStyle(sliderElem);
-    
-    if (element.HasChild("orientation"))
+    else
     {
     {
-        String orientation = element.GetChild("orientation").GetAttributeLower("value");
-        if (orientation == "horizontal" || orientation == "h")
-            SetOrientation(O_HORIZONTAL);
-        if (orientation == "vertical" || orientation == "v")
-            SetOrientation(O_VERTICAL);
+        backButton_->SetImageRect(upRect_);
+        forwardButton_->SetImageRect(downRect_);
     }
     }
 }
 }
 
 

+ 2 - 4
Engine/UI/ScrollBar.h

@@ -36,8 +36,6 @@ class ScrollBar : public UIElement
 {
 {
     OBJECT(ScrollBar);
     OBJECT(ScrollBar);
     
     
-    using UIElement::SetStyle;
-    
 public:
 public:
     /// Construct.
     /// Construct.
     ScrollBar(Context* context);
     ScrollBar(Context* context);
@@ -46,8 +44,8 @@ public:
     /// Register object factory.
     /// Register object factory.
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
     
     
-    /// Set UI element style from XML data.
-    virtual void SetStyle(const XMLElement& element);
+    /// Apply attribute changes that can not be applied immediately.
+    virtual void ApplyAttributes();
     /// React to resize.
     /// React to resize.
     virtual void OnResize();
     virtual void OnResize();
     
     

+ 27 - 31
Engine/UI/ScrollView.cpp

@@ -60,6 +60,7 @@ ScrollView::ScrollView(Context* context) :
     scrollPanel_->SetInternal(true);
     scrollPanel_->SetInternal(true);
     scrollPanel_->SetActive(true);
     scrollPanel_->SetActive(true);
     scrollPanel_->SetClipChildren(true);
     scrollPanel_->SetClipChildren(true);
+    scrollPanel_->SetPriority(-1);
     
     
     SubscribeToEvent(horizontalScrollBar_, E_SCROLLBARCHANGED, HANDLER(ScrollView, HandleScrollBarChanged));
     SubscribeToEvent(horizontalScrollBar_, E_SCROLLBARCHANGED, HANDLER(ScrollView, HandleScrollBarChanged));
     SubscribeToEvent(horizontalScrollBar_, E_VISIBLECHANGED, HANDLER(ScrollView, HandleScrollBarVisibleChanged));
     SubscribeToEvent(horizontalScrollBar_, E_VISIBLECHANGED, HANDLER(ScrollView, HandleScrollBarVisibleChanged));
@@ -74,36 +75,21 @@ ScrollView::~ScrollView()
 void ScrollView::RegisterObject(Context* context)
 void ScrollView::RegisterObject(Context* context)
 {
 {
     context->RegisterFactory<ScrollView>();
     context->RegisterFactory<ScrollView>();
+    
+    REF_ACCESSOR_ATTRIBUTE(ScrollView, VAR_INTVECTOR2, "View Position", GetViewPosition, SetViewPosition, 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);
+    COPY_BASE_ATTRIBUTES(ScrollView, UIElement);
 }
 }
 
 
-void ScrollView::SetStyle(const XMLElement& element)
+void ScrollView::ApplyAttributes()
 {
 {
-    UIElement::SetStyle(element);
-    
-    if (element.HasChild("viewposition"))
-        SetViewPosition(element.GetChild("viewposition").GetIntVector2("value"));
-    if (element.HasChild("scrollstep"))
-        SetScrollStep(element.GetChild("scrollstep").GetFloat("value"));
-    if (element.HasChild("pagestep"))
-        SetScrollStep(element.GetChild("pagestep").GetFloat("value"));
-    
-    XMLElement horizElem = element.GetChild("horizontalscrollbar");
-    if (horizElem)
-        horizontalScrollBar_->SetStyle(horizElem);
-    XMLElement vertElem = element.GetChild("verticalscrollbar");
-    if (vertElem)
-        verticalScrollBar_->SetStyle(vertElem);
-    XMLElement panelElem = element.GetChild("scrollpanel");
-    if (panelElem)
-        scrollPanel_->SetStyle(panelElem);
-    
-    UIElement* root = GetRoot();
-    if (root && element.HasChild("contentelement"))
-        SetContentElement(root->GetChild(element.GetChild("contentelement").GetAttribute("name"), true));
+    UIElement::ApplyAttributes();
     
     
     // Set the scrollbar orientations again and perform size update now that the style is known
     // Set the scrollbar orientations again and perform size update now that the style is known
     horizontalScrollBar_->SetOrientation(O_HORIZONTAL);
     horizontalScrollBar_->SetOrientation(O_HORIZONTAL);
     verticalScrollBar_->SetOrientation(O_VERTICAL);
     verticalScrollBar_->SetOrientation(O_VERTICAL);
+    
     OnResize();
     OnResize();
 }
 }
 
 
@@ -254,9 +240,10 @@ void ScrollView::UpdateViewSize()
     IntVector2 size(IntVector2::ZERO);
     IntVector2 size(IntVector2::ZERO);
     if (contentElement_)
     if (contentElement_)
         size = contentElement_->GetSize();
         size = contentElement_->GetSize();
+    IntRect panelBorder = scrollPanel_->GetClipBorder();
     
     
-    viewSize_.x_ = Max(size.x_, scrollPanel_->GetWidth());
-    viewSize_.y_ = Max(size.y_, scrollPanel_->GetHeight());
+    viewSize_.x_ = Max(size.x_, scrollPanel_->GetWidth() - panelBorder.left_ - panelBorder.right_);
+    viewSize_.y_ = Max(size.y_, scrollPanel_->GetHeight() - panelBorder.top_ - panelBorder.bottom_);
     UpdateView(viewPosition_);
     UpdateView(viewPosition_);
     UpdateScrollBars();
     UpdateScrollBars();
 }
 }
@@ -265,7 +252,10 @@ void ScrollView::UpdateScrollBars()
 {
 {
     ignoreEvents_ = true;
     ignoreEvents_ = true;
     
     
-    const IntVector2& size = scrollPanel_->GetSize();
+    IntVector2 size = scrollPanel_->GetSize();
+    IntRect panelBorder = scrollPanel_->GetClipBorder();
+    size.x_ -= panelBorder.left_ + panelBorder.right_;
+    size.y_ -= panelBorder.top_ + panelBorder.bottom_;
     
     
     if (horizontalScrollBar_ && size.x_ > 0 && viewSize_.x_ > 0)
     if (horizontalScrollBar_ && size.x_ > 0 && viewSize_.x_ > 0)
     {
     {
@@ -286,10 +276,11 @@ void ScrollView::UpdateScrollBars()
 void ScrollView::UpdateView(const IntVector2& position)
 void ScrollView::UpdateView(const IntVector2& position)
 {
 {
     IntVector2 oldPosition = viewPosition_;
     IntVector2 oldPosition = viewPosition_;
+    IntRect panelBorder = scrollPanel_->GetClipBorder();
     
     
-    viewPosition_.x_ = Clamp(position.x_, 0, viewSize_.x_ - scrollPanel_->GetWidth());
-    viewPosition_.y_ = Clamp(position.y_, 0, viewSize_.y_ - scrollPanel_->GetHeight());
-    scrollPanel_->SetChildOffset(-viewPosition_);
+    viewPosition_.x_ = Clamp(position.x_, 0, viewSize_.x_);
+    viewPosition_.y_ = Clamp(position.y_, 0, viewSize_.y_);
+    scrollPanel_->SetChildOffset(IntVector2(-viewPosition_.x_ + panelBorder.left_, -viewPosition_.y_ + panelBorder.top_));
     
     
     if (viewPosition_ != oldPosition)
     if (viewPosition_ != oldPosition)
     {
     {
@@ -305,11 +296,16 @@ void ScrollView::UpdateView(const IntVector2& position)
 
 
 void ScrollView::HandleScrollBarChanged(StringHash eventType, VariantMap& eventData)
 void ScrollView::HandleScrollBarChanged(StringHash eventType, VariantMap& eventData)
 {
 {
+    IntVector2 size = scrollPanel_->GetSize();
+    IntRect panelBorder = scrollPanel_->GetClipBorder();
+    size.x_ -= panelBorder.left_ + panelBorder.right_;
+    size.y_ -= panelBorder.top_ + panelBorder.bottom_;
+    
     if (!ignoreEvents_)
     if (!ignoreEvents_)
     {
     {
         UpdateView(IntVector2(
         UpdateView(IntVector2(
-            (int)(horizontalScrollBar_->GetValue() * (float)scrollPanel_->GetWidth()),
-            (int)(verticalScrollBar_->GetValue() * (float)scrollPanel_->GetHeight())
+            (int)(horizontalScrollBar_->GetValue() * (float)size.x_),
+            (int)(verticalScrollBar_->GetValue() * (float)size.y_)
         ));
         ));
     }
     }
 }
 }

+ 2 - 4
Engine/UI/ScrollView.h

@@ -36,8 +36,6 @@ class ScrollView : public UIElement
 {
 {
     OBJECT(ScrollView);
     OBJECT(ScrollView);
     
     
-    using UIElement::SetStyle;
-    
 public:
 public:
     /// Construct.
     /// Construct.
     ScrollView(Context* context);
     ScrollView(Context* context);
@@ -46,8 +44,8 @@ public:
     /// Register object factory.
     /// Register object factory.
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
     
     
-    /// Set UI element style from XML data.
-    virtual void SetStyle(const XMLElement& element);
+    /// Apply attribute changes that can not be applied immediately.
+    virtual void ApplyAttributes();
     /// React to mouse wheel.
     /// React to mouse wheel.
     virtual void OnWheel(int delta, int buttons, int qualifiers);
     virtual void OnWheel(int delta, int buttons, int qualifiers);
     /// React to a key press.
     /// React to a key press.

+ 16 - 23
Engine/UI/Slider.cpp

@@ -33,6 +33,18 @@
 namespace Urho3D
 namespace Urho3D
 {
 {
 
 
+const char* orientations[] =
+{
+    "Horizontal",
+    "Vertical",
+    0
+};
+
+template<> Orientation Variant::Get<Orientation>() const
+{
+    return (Orientation)GetInt();
+}
+
 OBJECTTYPESTATIC(Slider);
 OBJECTTYPESTATIC(Slider);
 
 
 Slider::Slider(Context* context) :
 Slider::Slider(Context* context) :
@@ -56,30 +68,11 @@ Slider::~Slider()
 void Slider::RegisterObject(Context* context)
 void Slider::RegisterObject(Context* context)
 {
 {
     context->RegisterFactory<Slider>();
     context->RegisterFactory<Slider>();
-}
-
-void Slider::SetStyle(const XMLElement& element)
-{
-    BorderImage::SetStyle(element);
-    
-    if (element.HasChild("orientation"))
-    {
-        String orientation = element.GetChild("orientation").GetAttributeLower("value");
-        if (orientation == "horizontal" || orientation == "h")
-            SetOrientation(O_HORIZONTAL);
-        if (orientation == "vertical" || orientation == "v")
-            SetOrientation(O_VERTICAL);
-    }
-    if (element.HasChild("range"))
-    {
-        XMLElement rangeElem = element.GetChild("range");
-        SetRange(rangeElem.GetFloat("max"));
-        SetValue(rangeElem.GetFloat("value"));
-    }
     
     
-    XMLElement knobElem = element.GetChild("knob");
-    if (knobElem)
-        knob_->SetStyle(knobElem);
+    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);
+    COPY_BASE_ATTRIBUTES(Slider, BorderImage);
 }
 }
 
 
 void Slider::Update(float timeStep)
 void Slider::Update(float timeStep)

+ 0 - 4
Engine/UI/Slider.h

@@ -33,8 +33,6 @@ class Slider : public BorderImage
 {
 {
     OBJECT(Slider);
     OBJECT(Slider);
     
     
-    using UIElement::SetStyle;
-    
 public:
 public:
     /// Construct.
     /// Construct.
     Slider(Context* context);
     Slider(Context* context);
@@ -43,8 +41,6 @@ public:
     /// Register object factory.
     /// Register object factory.
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
     
     
-    /// Set UI element style from XML data.
-    virtual void SetStyle(const XMLElement& element);
     /// Perform UI element update.
     /// Perform UI element update.
     virtual void Update(float timeStep);
     virtual void Update(float timeStep);
     /// React to mouse hover.
     /// React to mouse hover.

+ 6 - 88
Engine/UI/Text.cpp

@@ -70,113 +70,31 @@ void Text::RegisterObject(Context* context)
 {
 {
     context->RegisterFactory<Text>();
     context->RegisterFactory<Text>();
     
     
-    COPY_BASE_ATTRIBUTES(Text, UIElement);
     ACCESSOR_ATTRIBUTE(Text, VAR_RESOURCEREF, "Font", GetFontAttr, SetFontAttr, ResourceRef, ResourceRef(Font::GetTypeStatic()), AM_FILE);
     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_INT, "Font Size", fontSize_, DEFAULT_FONT_SIZE, AM_FILE);
     ATTRIBUTE(Text, VAR_STRING, "Text", text_, String(), AM_FILE);
     ATTRIBUTE(Text, VAR_STRING, "Text", text_, String(), AM_FILE);
     ENUM_ATTRIBUTE(Text, "Text Alignment", textAlignment_, horizontalAlignments, HA_LEFT, AM_FILE);
     ENUM_ATTRIBUTE(Text, "Text Alignment", textAlignment_, horizontalAlignments, HA_LEFT, AM_FILE);
     ATTRIBUTE(Text, VAR_FLOAT, "Row Spacing", rowSpacing_, 1.0f, AM_FILE);
     ATTRIBUTE(Text, VAR_FLOAT, "Row Spacing", rowSpacing_, 1.0f, AM_FILE);
     ATTRIBUTE(Text, VAR_BOOL, "Word Wrap", wordWrap_, false, AM_FILE);
     ATTRIBUTE(Text, VAR_BOOL, "Word Wrap", wordWrap_, false, AM_FILE);
-    ATTRIBUTE(Text, VAR_INT, "Selection Start", selectionStart_, 0, AM_FILE);
-    ATTRIBUTE(Text, VAR_INT, "Selection Length", selectionLength_, 0, AM_FILE);
     REF_ACCESSOR_ATTRIBUTE(Text, VAR_COLOR, "Selection Color", GetSelectionColor, SetSelectionColor, Color, Color::BLACK, AM_FILE);
     REF_ACCESSOR_ATTRIBUTE(Text, VAR_COLOR, "Selection Color", GetSelectionColor, SetSelectionColor, Color, Color::BLACK, AM_FILE);
     REF_ACCESSOR_ATTRIBUTE(Text, VAR_COLOR, "Hover Color", GetHoverColor, SetHoverColor, Color, Color::BLACK, AM_FILE);
     REF_ACCESSOR_ATTRIBUTE(Text, VAR_COLOR, "Hover Color", GetHoverColor, SetHoverColor, Color, Color::BLACK, AM_FILE);
+    COPY_BASE_ATTRIBUTES(Text, UIElement);
 }
 }
 
 
 void Text::ApplyAttributes()
 void Text::ApplyAttributes()
 {
 {
     UIElement::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);
     fontSize_ = Max(fontSize_, 1);
     ValidateSelection();
     ValidateSelection();
     UpdateText();
     UpdateText();
 }
 }
 
 
-void Text::SetStyle(const XMLElement& element)
-{
-    UIElement::SetStyle(element);
-    
-    // Recalculating the text is expensive, so do it only once at the end if something changed
-    bool changed = false;
-    
-    if (element.HasChild("font"))
-    {
-        XMLElement fontElem = element.GetChild("font");
-        String fontName = fontElem.GetAttribute("name");
-        
-        ResourceCache* cache = GetSubsystem<ResourceCache>();
-        if (cache->Exists(fontName))
-        {
-            Font* font = cache->GetResource<Font>(fontName);
-            if (font)
-            {
-                font_ = font;
-                fontSize_ = Max(fontElem.GetInt("size"), 1);
-                changed = true;
-            }
-        }
-        else if (element.HasChild("fallbackfont"))
-        {
-            fontElem = element.GetChild("fallbackfont");
-            String fontName = fontElem.GetAttribute("name");
-            Font* font = cache->GetResource<Font>(fontName);
-            if (font)
-            {
-                font_ = font;
-                fontSize_ = Max(fontElem.GetInt("size"), 1);
-                changed = true;
-            }
-        }
-    }
-    if (element.HasChild("text"))
-    {
-        // Do not call SetText() as that would possibly resize the element
-        text_ = String(element.GetChild("text").GetAttribute("value")).Replaced("\\n", "\n");
-        
-        unicodeText_.Clear();
-        for (unsigned i = 0; i < text_.Length();)
-            unicodeText_.Push(text_.NextUTF8Char(i));
-        
-        changed = true;
-    }
-    if (element.HasChild("textalignment"))
-    {
-        String horiz = element.GetChild("textalignment").GetAttributeLower("value");
-        if (!horiz.Empty())
-        {
-            textAlignment_ = (HorizontalAlignment)GetStringListIndex(horiz.CString(), horizontalAlignments, HA_LEFT);
-            changed = true;
-        }
-    }
-    if (element.HasChild("rowspacing"))
-    {
-        rowSpacing_ = Max(element.GetChild("rowspacing").GetFloat("value"), MIN_ROW_SPACING);
-        changed = true;
-    }
-    if (element.HasChild("wordwrap"))
-    {
-        wordWrap_ = element.GetChild("wordwrap").GetBool("enable");
-        changed = true;
-    }
-    if (element.HasChild("selection"))
-    {
-        XMLElement selectionElem = element.GetChild("selection");
-        selectionStart_ = selectionElem.GetInt("start");
-        selectionLength_ = selectionElem.GetInt("length");
-        changed = true;
-    }
-    if (element.HasChild("selectioncolor"))
-        SetSelectionColor(element.GetChild("selectioncolor").GetColor("value"));
-    if (element.HasChild("hovercolor"))
-        SetHoverColor(element.GetChild("hovercolor").GetColor("value"));
-    
-    if (changed)
-    {
-        ValidateSelection();
-        UpdateText();
-    }
-}
-
 void Text::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor)
 void Text::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor)
 {
 {
     // Hovering or whole selection batch
     // Hovering or whole selection batch

+ 0 - 4
Engine/UI/Text.h

@@ -37,8 +37,6 @@ class Text : public UIElement
 {
 {
     OBJECT(Text);
     OBJECT(Text);
     
     
-    using UIElement::SetStyle;
-    
 public:
 public:
     /// Construct.
     /// Construct.
     Text(Context* context);
     Text(Context* context);
@@ -49,8 +47,6 @@ public:
     
     
     /// Apply attribute changes that can not be applied immediately.
     /// Apply attribute changes that can not be applied immediately.
     virtual void ApplyAttributes();
     virtual void ApplyAttributes();
-    /// Set UI element style from XML data.
-    virtual void SetStyle(const XMLElement& element);
     /// Return UI rendering batches.
     /// Return UI rendering batches.
     virtual void GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor);
     virtual void GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor);
     /// React to resize.
     /// React to resize.

+ 16 - 50
Engine/UI/UI.cpp

@@ -369,30 +369,31 @@ SharedPtr<UIElement> UI::LoadLayout(XMLFile* file, XMLFile* styleFile)
         return root;
         return root;
     }
     }
     
     
-    String type = rootElem.GetAttribute("type");
-    if (type.Empty())
-        type = "UIElement";
+    String typeName = rootElem.GetAttribute("type");
+    if (typeName.Empty())
+        typeName = "UIElement";
     
     
-    root = DynamicCast<UIElement>(context_->CreateObject(ShortStringHash(type)));
+    root = DynamicCast<UIElement>(context_->CreateObject(ShortStringHash(typeName)));
     if (!root)
     if (!root)
     {
     {
-        LOGERROR("Could not create unknown UI element " + type);
+        LOGERROR("Could not create unknown UI element " + typeName);
         return root;
         return root;
     }
     }
-    root->SetName(rootElem.GetAttribute("name"));
-    
-    String styleName = rootElem.HasAttribute("style") ? rootElem.GetAttribute("style") : rootElem.GetAttribute("type");
-    // First set the base style from the style file if exists, then apply UI layout overrides
-    if (styleFile)
-        root->SetStyle(styleFile, styleName);
-    root->SetStyle(rootElem);
-    
-    // Load rest of the elements recursively
-    LoadLayout(root, rootElem, styleFile);
     
     
+    root->LoadXML(rootElem, styleFile);
     return root;
     return root;
 }
 }
 
 
+bool UI::SaveLayout(Serializer& dest, UIElement* element)
+{
+    PROFILE(SaveUILayout);
+    
+    if (element)
+        return element->SaveXML(dest);
+    else
+        return false;
+}
+
 void UI::SetClipBoardText(const String& text)
 void UI::SetClipBoardText(const String& text)
 {
 {
     clipBoard_ = text;
     clipBoard_ = text;
@@ -642,41 +643,6 @@ UIElement* UI::GetFocusableElement(UIElement* element)
     return element;
     return element;
 }
 }
 
 
-void UI::LoadLayout(UIElement* current, const XMLElement& elem, XMLFile* styleFile)
-{
-    XMLElement childElem = elem.GetChild("element");
-    while (childElem)
-    {
-        // Create element
-        String type = childElem.GetAttribute("type");
-        if (type.Empty())
-            type = "UIElement";
-        
-        SharedPtr<UIElement> child = DynamicCast<UIElement>(context_->CreateObject(ShortStringHash(type)));
-        if (!child)
-        {
-            LOGERROR("Could not create unknown UI element " + type);
-            childElem = childElem.GetNext("element");
-            continue;
-        }
-        child->SetName(childElem.GetAttribute("name"));
-        
-        // Add to the hierarchy
-        current->AddChild(child);
-        
-        // First set the base style from the style file if exists, then apply UI layout overrides
-        String styleName = childElem.HasAttribute("style") ? childElem.GetAttribute("style") : childElem.GetAttribute("type");
-        if (styleFile)
-            child->SetStyle(styleFile, styleName);
-        child->SetStyle(childElem);
-        
-        // Load the children recursively
-        LoadLayout(child, childElem, styleFile);
-        
-        childElem = childElem.GetNext("element");
-    }
-}
-
 void UI::HandleScreenMode(StringHash eventType, VariantMap& eventData)
 void UI::HandleScreenMode(StringHash eventType, VariantMap& eventData)
 {
 {
     using namespace ScreenMode;
     using namespace ScreenMode;

+ 2 - 2
Engine/UI/UI.h

@@ -63,6 +63,8 @@ public:
     void Render();
     void Render();
     /// Load a UI layout from an XML file. Optionally specify another XML file for element style. Return the root element.
     /// Load a UI layout from an XML file. Optionally specify another XML file for element style. Return the root element.
     SharedPtr<UIElement> LoadLayout(XMLFile* file, XMLFile* styleFile = 0);
     SharedPtr<UIElement> LoadLayout(XMLFile* file, XMLFile* styleFile = 0);
+    /// Save a UI layout to an XML file. Return true if successful.
+    bool SaveLayout(Serializer& dest, UIElement* element);
     /// Set clipboard text.
     /// Set clipboard text.
     void SetClipBoardText(const String& text);
     void SetClipBoardText(const String& text);
     
     
@@ -96,8 +98,6 @@ private:
     void GetElementAt(UIElement*& result, UIElement* current, const IntVector2& position, bool activeOnly);
     void GetElementAt(UIElement*& result, UIElement* current, const IntVector2& position, bool activeOnly);
     /// Return the first element in hierarchy that can alter focus.
     /// Return the first element in hierarchy that can alter focus.
     UIElement* GetFocusableElement(UIElement* element);
     UIElement* GetFocusableElement(UIElement* element);
-    /// Load a UI layout from an XML file recursively.
-    void LoadLayout(UIElement* current, const XMLElement& elem, XMLFile* styleFile);
     /// Handle screen mode event.
     /// Handle screen mode event.
     void HandleScreenMode(StringHash eventType, VariantMap& eventData);
     void HandleScreenMode(StringHash eventType, VariantMap& eventData);
     /// Handle mouse button down event.
     /// Handle mouse button down event.

+ 73 - 117
Engine/UI/UIElement.cpp

@@ -213,11 +213,13 @@ bool UIElement::LoadXML(const XMLElement& source)
     unsigned nextInternalChild = 0;
     unsigned nextInternalChild = 0;
     
     
     // Load child elements. Internal elements are not to be created as they already exist
     // Load child elements. Internal elements are not to be created as they already exist
-    XMLElement childElem = source.GetChild("node");
+    XMLElement childElem = source.GetChild("element");
     while (childElem)
     while (childElem)
     {
     {
         bool internalElem = childElem.GetBool("internal");
         bool internalElem = childElem.GetBool("internal");
         String typeName = childElem.GetAttribute("type");
         String typeName = childElem.GetAttribute("type");
+        if (typeName.Empty())
+            typeName = "UIElement";
         UIElement* child = 0;
         UIElement* child = 0;
         
         
         if (!internalElem)
         if (!internalElem)
@@ -247,7 +249,7 @@ bool UIElement::LoadXML(const XMLElement& source)
         else
         else
             LOGWARNING("Could not find matching internal child element of type " + typeName);
             LOGWARNING("Could not find matching internal child element of type " + typeName);
         
         
-        childElem = childElem.GetNext();
+        childElem = childElem.GetNext("element");
     }
     }
     
     
     return true;
     return true;
@@ -280,121 +282,6 @@ bool UIElement::SaveXML(XMLElement& dest)
     return true;
     return true;
 }
 }
 
 
-void UIElement::SetStyle(const XMLElement& element)
-{
-    if (element.HasAttribute("name"))
-        name_ = element.GetAttribute("name");
-    if (element.HasChild("position"))
-        SetPosition(element.GetChild("position").GetIntVector2("value"));
-    if (element.HasChild("size"))
-        SetSize(element.GetChild("size").GetIntVector2("value"));
-    if (element.HasChild("width"))
-        SetWidth(element.GetChild("width").GetInt("value"));
-    if (element.HasChild("height"))
-        SetHeight(element.GetChild("height").GetInt("value"));
-    if (element.HasChild("minsize"))
-        SetMinSize(element.GetChild("minsize").GetIntVector2("value"));
-    if (element.HasChild("minwidth"))
-        SetMinWidth(element.GetChild("minwidth").GetInt("value"));
-    if (element.HasChild("minheight"))
-        SetMinHeight(element.GetChild("minheight").GetInt("value"));
-    if (element.HasChild("maxsize"))
-        SetMaxSize(element.GetChild("maxsize").GetIntVector2("value"));
-    if (element.HasChild("maxwidth"))
-        SetMinWidth(element.GetChild("maxwidth").GetInt("value"));
-    if (element.HasChild("maxheight"))
-        SetMinHeight(element.GetChild("maxheight").GetInt("value"));
-    if (element.HasChild("fixedsize"))
-        SetFixedSize(element.GetChild("fixedsize").GetIntVector2("value"));
-    if (element.HasChild("fixedwidth"))
-        SetFixedWidth(element.GetChild("fixedwidth").GetInt("value"));
-    if (element.HasChild("fixedheight"))
-        SetFixedHeight(element.GetChild("fixedheight").GetInt("value"));
-    if (element.HasChild("alignment"))
-    {
-        XMLElement alignElem = element.GetChild("alignment");
-        
-        String horiz;
-        String vert;
-        if (alignElem.HasAttribute("horizontal"))
-            horiz = alignElem.GetAttributeLower("horizontal");
-        if (alignElem.HasAttribute("vertical"))
-            vert = alignElem.GetAttributeLower("vertical");
-        if (alignElem.HasAttribute("h"))
-            horiz = alignElem.GetAttributeLower("h");
-        if (alignElem.HasAttribute("v"))
-            vert = alignElem.GetAttributeLower("v");
-        if (!horiz.Empty())
-            SetHorizontalAlignment((HorizontalAlignment)GetStringListIndex(horiz.CString(), horizontalAlignments, HA_LEFT));
-        if (!vert.Empty())
-            SetVerticalAlignment((VerticalAlignment)GetStringListIndex(vert.CString(), verticalAlignments, VA_TOP));
-    }
-    if (element.HasChild("clipborder"))
-        SetClipBorder(element.GetChild("clipborder").GetIntRect("value"));
-    if (element.HasChild("priority"))
-        SetPriority(element.GetChild("priority").GetInt("value"));
-    if (element.HasChild("opacity"))
-        SetOpacity(element.GetChild("opacity").GetFloat("value"));
-    if (element.HasChild("color"))
-    {
-        XMLElement colorElem = element.GetChild("color");
-        if (colorElem.HasAttribute("value"))
-            SetColor(colorElem.GetColor("value"));
-        if (colorElem.HasAttribute("topleft"))
-            SetColor(C_TOPLEFT, colorElem.GetColor("topleft"));
-        if (colorElem.HasAttribute("topright"))
-            SetColor(C_TOPRIGHT, colorElem.GetColor("topright"));
-        if (colorElem.HasAttribute("bottomleft"))
-            SetColor(C_BOTTOMLEFT, colorElem.GetColor("bottomleft"));
-        if (colorElem.HasAttribute("bottomright"))
-            SetColor(C_BOTTOMRIGHT, colorElem.GetColor("bottomright"));
-    }
-    if (element.HasChild("bringtofront"))
-        SetBringToFront(element.GetChild("bringtofront").GetBool("enable"));
-    if (element.HasChild("bringtoback"))
-        SetBringToBack(element.GetChild("bringtoback").GetBool("enable"));
-    if (element.HasChild("clipchildren"))
-        SetClipChildren(element.GetChild("clipchildren").GetBool("enable"));
-    if (element.HasChild("enabled"))
-        SetActive(element.GetChild("enabled").GetBool("enable"));
-    if (element.HasChild("selected"))
-        SetSelected(element.GetChild("selected").GetBool("enable"));
-    if (element.HasChild("visible"))
-        SetVisible(element.GetChild("visible").GetBool("enable"));
-    if (element.HasChild("focusmode"))
-    {
-        String focusMode = element.GetChild("focusmode").GetAttributeLower("value");
-        SetFocusMode((FocusMode)GetStringListIndex(focusMode.CString(), focusModes, FM_NOTFOCUSABLE));
-        if (focusMode == "defocusable")
-            SetFocusMode(FM_FOCUSABLE_DEFOCUSABLE);
-    }
-    if (element.HasChild("dragdropmode"))
-    {
-        String dragDropMode = element.GetChild("dragdropmode").GetAttributeLower("value");
-        SetDragDropMode(GetStringListIndex(dragDropMode.CString(), dragDropModes, DD_DISABLED));
-    }
-    if (element.HasChild("layout"))
-    {
-        XMLElement layoutElem = element.GetChild("layout");
-        String mode = layoutElem.GetAttributeLower("mode");
-        if (mode == "free")
-            layoutMode_ = LM_FREE;
-        if (mode == "horizontal" || mode == "h")
-            layoutMode_ = LM_HORIZONTAL;
-        if (mode == "vertical" || mode == "v")
-            layoutMode_ = LM_VERTICAL;
-        
-        if (layoutElem.HasAttribute("spacing"))
-            layoutSpacing_ = Max(layoutElem.GetInt("spacing"), 0);
-        if (layoutElem.HasAttribute("border"))
-            SetLayoutBorder(layoutElem.GetIntRect("border"));
-        else
-            UpdateLayout();
-    }
-    if (element.HasChild("vars"))
-        vars_ = element.GetChild("vars").GetVariantMap();
-}
-
 void UIElement::Update(float timeStep)
 void UIElement::Update(float timeStep)
 {
 {
 }
 }
@@ -452,6 +339,69 @@ void UIElement::OnResize()
 {
 {
 }
 }
 
 
+bool UIElement::LoadXML(const XMLElement& source, XMLFile* styleFile)
+{
+    // Apply the style first, but only for non-internal elements
+    if (!internal_ && styleFile)
+    {
+        // Use style override if defined, otherwise type name
+        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)
+    {
+        bool internalElem = childElem.GetBool("internal");
+        String typeName = childElem.GetAttribute("type");
+        if (typeName.Empty())
+            typeName = "UIElement";
+        UIElement* child = 0;
+        
+        if (!internalElem)
+        {
+            child = CreateChild(ShortStringHash(typeName));
+            if (!child)
+                return false;
+        }
+        else
+        {
+            for (unsigned i = nextInternalChild; i < children_.Size(); ++i)
+            {
+                if (children_[i]->IsInternal() && children_[i]->GetTypeName() == typeName)
+                {
+                    child = children_[i];
+                    nextInternalChild = i + 1;
+                    break;
+                }
+            }
+        }
+        
+        if (child)
+        {
+            if (!child->LoadXML(childElem, styleFile))
+                return false;
+        }
+        else
+            LOGWARNING("Could not find matching internal child element of type " + typeName);
+        
+        childElem = childElem.GetNext("element");
+    }
+    
+    ApplyAttributes();
+    
+    return true;
+}
 
 
 bool UIElement::LoadXML(Deserializer& source)
 bool UIElement::LoadXML(Deserializer& source)
 {
 {
@@ -770,6 +720,12 @@ void UIElement::SetStyle(XMLFile* file, const String& typeName)
     }
     }
 }
 }
 
 
+
+void UIElement::SetStyle(const XMLElement& element)
+{
+    LoadXML(element);
+}
+
 void UIElement::SetStyleAuto(XMLFile* file)
 void UIElement::SetStyleAuto(XMLFile* file)
 {
 {
     SetStyle(file, GetTypeName());
     SetStyle(file, GetTypeName());

+ 4 - 2
Engine/UI/UIElement.h

@@ -119,8 +119,6 @@ public:
     virtual bool LoadXML(const XMLElement& source);
     virtual bool LoadXML(const XMLElement& source);
     /// Save as XML data. Return true if successful.
     /// Save as XML data. Return true if successful.
     virtual bool SaveXML(XMLElement& dest);
     virtual bool SaveXML(XMLElement& dest);
-    /// Set UI element style from XML data.
-    virtual void SetStyle(const XMLElement& element);
     /// Perform UI element update.
     /// Perform UI element update.
     virtual void Update(float timeStep);
     virtual void Update(float timeStep);
     /// Return UI rendering batches.
     /// Return UI rendering batches.
@@ -149,6 +147,8 @@ public:
     /// React to resize.
     /// React to resize.
     virtual void OnResize();
     virtual void OnResize();
     
     
+    /// Load from XML data with style. Return true if successful.
+    bool LoadXML(const XMLElement& source, XMLFile* styleFile);
     /// Load from an XML file. Return true if successful.
     /// Load from an XML file. Return true if successful.
     bool LoadXML(Deserializer& source);
     bool LoadXML(Deserializer& source);
     /// Save to an XML file. Return true if successful.
     /// Save to an XML file. Return true if successful.
@@ -230,6 +230,8 @@ public:
     void SetDragDropMode(unsigned mode);
     void SetDragDropMode(unsigned mode);
     /// Set style from an XML file. Find the style element by name.
     /// Set style from an XML file. Find the style element by name.
     void SetStyle(XMLFile* file, const String& typeName);
     void SetStyle(XMLFile* file, const String& typeName);
+    /// Set style from an XML element.
+    void SetStyle(const XMLElement& element);
     /// Set style from an XML file. Find the style element automatically.
     /// Set style from an XML file. Find the style element automatically.
     void SetStyleAuto(XMLFile* file);
     void SetStyleAuto(XMLFile* file);
     /// Set layout.
     /// Set layout.

+ 5 - 11
Engine/UI/Window.cpp

@@ -55,18 +55,12 @@ Window::~Window()
 void Window::RegisterObject(Context* context)
 void Window::RegisterObject(Context* context)
 {
 {
     context->RegisterFactory<Window>();
     context->RegisterFactory<Window>();
-}
-
-void Window::SetStyle(const XMLElement& element)
-{
-    BorderImage::SetStyle(element);
     
     
-    if (element.HasChild("resizeborder"))
-        SetResizeBorder(element.GetChild("resizeborder").GetIntRect("value"));
-    if (element.HasChild("movable"))
-        SetMovable(element.GetChild("movable").GetBool("enable"));
-    if (element.HasChild("resizable"))
-        SetResizable(element.GetChild("resizable").GetBool("enable"));
+    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);
+    ACCESSOR_ATTRIBUTE(Window, VAR_BOOL, "Is Resizable", IsResizable, SetResizable, bool, false, AM_FILE);
+    COPY_BASE_ATTRIBUTES(Window, BorderImage);
 }
 }
 
 
 void Window::OnHover(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
 void Window::OnHover(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)

+ 0 - 4
Engine/UI/Window.h

@@ -48,8 +48,6 @@ class Window : public BorderImage
 {
 {
     OBJECT(Window);
     OBJECT(Window);
     
     
-    using UIElement::SetStyle;
-    
 public:
 public:
     /// Construct.
     /// Construct.
     Window(Context* context);
     Window(Context* context);
@@ -58,8 +56,6 @@ public:
     /// Register object factory.
     /// Register object factory.
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
     
     
-    /// Set UI element style from XML data.
-    virtual void SetStyle(const XMLElement& element);
     /// React to mouse hover.
     /// React to mouse hover.
     virtual void OnHover(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor);
     virtual void OnHover(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor);
     /// React to mouse drag begin.
     /// React to mouse drag begin.