Browse Source

Removed use of the UIQuad intermediate structure. Instead construct vertex data directly.

Lasse Öörni 12 years ago
parent
commit
895819e8d2

+ 21 - 24
Engine/UI/BorderImage.cpp

@@ -67,9 +67,9 @@ void BorderImage::RegisterObject(Context* context)
     COPY_BASE_ATTRIBUTES(BorderImage, UIElement);
     COPY_BASE_ATTRIBUTES(BorderImage, UIElement);
 }
 }
 
 
-void BorderImage::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor)
+void BorderImage::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData, const IntRect& currentScissor)
 {
 {
-    GetBatches(batches, quads, currentScissor, hovering_ || selected_ ? hoverOffset_ : IntVector2::ZERO);
+    GetBatches(batches, vertexData, currentScissor, hovering_ || selected_ ? hoverOffset_ : IntVector2::ZERO);
 }
 }
 
 
 void BorderImage::SetTexture(Texture* texture)
 void BorderImage::SetTexture(Texture* texture)
@@ -119,14 +119,14 @@ void BorderImage::SetTiled(bool enable)
     tiled_ = enable;
     tiled_ = enable;
 }
 }
 
 
-void BorderImage::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor, const IntVector2& offset)
+void BorderImage::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData, const IntRect& currentScissor, const IntVector2& offset)
 {
 {
     bool allOpaque = true;
     bool allOpaque = true;
     if (GetDerivedOpacity() < 1.0f || color_[C_TOPLEFT].a_ < 1.0f || color_[C_TOPRIGHT].a_ < 1.0f ||
     if (GetDerivedOpacity() < 1.0f || color_[C_TOPLEFT].a_ < 1.0f || color_[C_TOPRIGHT].a_ < 1.0f ||
         color_[C_BOTTOMLEFT].a_ < 1.0f || color_[C_BOTTOMRIGHT].a_ < 1.0f)
         color_[C_BOTTOMLEFT].a_ < 1.0f || color_[C_BOTTOMRIGHT].a_ < 1.0f)
         allOpaque = false;
         allOpaque = false;
     
     
-    UIBatch batch(blendMode_ == BLEND_REPLACE && !allOpaque ? BLEND_ALPHA : blendMode_, currentScissor, texture_, &quads);
+    UIBatch batch(this, blendMode_ == BLEND_REPLACE && !allOpaque ? BLEND_ALPHA : blendMode_, currentScissor, texture_, &vertexData);
     
     
     // Calculate size of the inner rect, and texture dimensions of the inner rect
     // Calculate size of the inner rect, and texture dimensions of the inner rect
     int x = GetIndentWidth();
     int x = GetIndentWidth();
@@ -146,42 +146,39 @@ void BorderImage::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& qua
     if (border_.top_)
     if (border_.top_)
     {
     {
         if (border_.left_)
         if (border_.left_)
-            batch.AddQuad(*this, x, 0, border_.left_, border_.top_, topLeft.x_, topLeft.y_);
+            batch.AddQuad(x, 0, border_.left_, border_.top_, topLeft.x_, topLeft.y_);
         if (innerSize.x_)
         if (innerSize.x_)
-            batch.AddQuad(*this, x + border_.left_, 0, innerSize.x_, border_.top_,
-            topLeft.x_ + border_.left_, topLeft.y_, innerTextureSize.x_, border_.top_, tiled_);
+            batch.AddQuad(x + border_.left_, 0, innerSize.x_, border_.top_, topLeft.x_ + border_.left_, topLeft.y_,
+                innerTextureSize.x_, border_.top_, tiled_);
         if (border_.right_)
         if (border_.right_)
-            batch.AddQuad(*this, x + border_.left_ + innerSize.x_, 0, border_.right_, border_.top_,
-            topLeft.x_ + border_.left_ + innerTextureSize.x_, topLeft.y_);
+            batch.AddQuad(x + border_.left_ + innerSize.x_, 0, border_.right_, border_.top_, topLeft.x_ + border_.left_ +
+                innerTextureSize.x_, topLeft.y_);
     }
     }
     // Middle
     // Middle
     if (innerSize.y_)
     if (innerSize.y_)
     {
     {
         if (border_.left_)
         if (border_.left_)
-            batch.AddQuad(*this, x, border_.top_, border_.left_, innerSize.y_,
-            topLeft.x_, topLeft.y_ + border_.top_, border_.left_, innerTextureSize.y_, tiled_);
+            batch.AddQuad(x, border_.top_, border_.left_, innerSize.y_, topLeft.x_, topLeft.y_ + border_.top_, border_.left_,
+                innerTextureSize.y_, tiled_);
         if (innerSize.x_)
         if (innerSize.x_)
-            batch.AddQuad(*this, x + border_.left_, border_.top_, innerSize.x_, innerSize.y_,
-            topLeft.x_ + border_.left_, topLeft.y_ + border_.top_, innerTextureSize.x_, innerTextureSize.y_, tiled_);
+            batch.AddQuad(x + border_.left_, border_.top_, innerSize.x_, innerSize.y_, topLeft.x_ + border_.left_, topLeft.y_ +
+                border_.top_, innerTextureSize.x_, innerTextureSize.y_, tiled_);
         if (border_.right_)
         if (border_.right_)
-            batch.AddQuad(*this, x + border_.left_ + innerSize.x_, border_.top_, border_.right_,
-            innerSize.y_, topLeft.x_ + border_.left_ + innerTextureSize.x_, topLeft.y_ + border_.top_,
-            border_.right_, innerTextureSize.y_, tiled_);
+            batch.AddQuad(x + border_.left_ + innerSize.x_, border_.top_, border_.right_, innerSize.y_, topLeft.x_ +
+                border_.left_ + innerTextureSize.x_, topLeft.y_ + border_.top_, border_.right_, innerTextureSize.y_, tiled_);
     }
     }
     // Bottom
     // Bottom
     if (border_.bottom_)
     if (border_.bottom_)
     {
     {
         if (border_.left_)
         if (border_.left_)
-            batch.AddQuad(*this, x, border_.top_ + innerSize.y_, border_.left_, border_.bottom_,
-            topLeft.x_, topLeft.y_ + border_.top_ + innerTextureSize.y_);
+            batch.AddQuad(x, border_.top_ + innerSize.y_, border_.left_, border_.bottom_, topLeft.x_, topLeft.y_ + border_.top_ + 
+                innerTextureSize.y_);
         if (innerSize.x_)
         if (innerSize.x_)
-            batch.AddQuad(*this, x + border_.left_, border_.top_ + innerSize.y_, innerSize.x_,
-            border_.bottom_, topLeft.x_ + border_.left_, topLeft.y_ + border_.top_ + innerTextureSize.y_,
-            innerTextureSize.x_, border_.bottom_, tiled_);
+            batch.AddQuad(x + border_.left_, border_.top_ + innerSize.y_, innerSize.x_, border_.bottom_, topLeft.x_ +
+                border_.left_, topLeft.y_ + border_.top_ + innerTextureSize.y_, innerTextureSize.x_, border_.bottom_, tiled_);
         if (border_.right_)
         if (border_.right_)
-            batch.AddQuad(*this, x + border_.left_ + innerSize.x_, border_.top_ + innerSize.y_,
-            border_.right_, border_.bottom_, topLeft.x_ + border_.left_ + innerTextureSize.x_, 
-            topLeft.y_ + border_.top_ + innerTextureSize.y_);
+            batch.AddQuad(x + border_.left_ + innerSize.x_, border_.top_ + innerSize.y_, border_.right_, border_.bottom_,
+                topLeft.x_ + border_.left_ + innerTextureSize.x_, topLeft.y_ + border_.top_ + innerTextureSize.y_);
     }
     }
     
     
     UIBatch::AddOrMerge(batch, batches);
     UIBatch::AddOrMerge(batch, batches);

+ 2 - 2
Engine/UI/BorderImage.h

@@ -45,7 +45,7 @@ public:
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
     
     
     /// 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<float>& vertexData, const IntRect& currentScissor);
     
     
     /// Set texture.
     /// Set texture.
     void SetTexture(Texture* texture);
     void SetTexture(Texture* texture);
@@ -84,7 +84,7 @@ public:
     
     
 protected:
 protected:
     /// Return UI rendering batches with offset to image rectangle.
     /// Return UI rendering batches with offset to image rectangle.
-    void GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor, const IntVector2& offset);
+    void GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData, const IntRect& currentScissor, const IntVector2& offset);
     
     
     /// Texture.
     /// Texture.
     SharedPtr<Texture> texture_;
     SharedPtr<Texture> texture_;

+ 2 - 2
Engine/UI/Button.cpp

@@ -82,7 +82,7 @@ void Button::Update(float timeStep)
     }
     }
 }
 }
 
 
-void Button::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor)
+void Button::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData, const IntRect& currentScissor)
 {
 {
     IntVector2 offset(IntVector2::ZERO);
     IntVector2 offset(IntVector2::ZERO);
     if (hovering_)
     if (hovering_)
@@ -90,7 +90,7 @@ void Button::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, c
     if (pressed_ || selected_)
     if (pressed_ || selected_)
         offset += pressedOffset_;
         offset += pressedOffset_;
     
     
-    BorderImage::GetBatches(batches, quads, currentScissor, offset);
+    BorderImage::GetBatches(batches, vertexData, currentScissor, offset);
 }
 }
 
 
 void Button::OnHover(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
 void Button::OnHover(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)

+ 1 - 1
Engine/UI/Button.h

@@ -43,7 +43,7 @@ public:
     /// 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.
-    virtual void GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor);
+    virtual void GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData, const IntRect& currentScissor);
     /// 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 click.
     /// React to mouse click.

+ 2 - 2
Engine/UI/CheckBox.cpp

@@ -54,7 +54,7 @@ void CheckBox::RegisterObject(Context* context)
     COPY_BASE_ATTRIBUTES(CheckBox, BorderImage);
     COPY_BASE_ATTRIBUTES(CheckBox, BorderImage);
 }
 }
 
 
-void CheckBox::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor)
+void CheckBox::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData, const IntRect& currentScissor)
 {
 {
     IntVector2 offset(IntVector2::ZERO);
     IntVector2 offset(IntVector2::ZERO);
     if (hovering_ || selected_)
     if (hovering_ || selected_)
@@ -62,7 +62,7 @@ void CheckBox::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads,
     if (checked_)
     if (checked_)
         offset += checkedOffset_;
         offset += checkedOffset_;
     
     
-    BorderImage::GetBatches(batches, quads, currentScissor, offset);
+    BorderImage::GetBatches(batches, vertexData, currentScissor, offset);
 }
 }
 
 
 void CheckBox::OnClick(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)
 void CheckBox::OnClick(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor)

+ 1 - 1
Engine/UI/CheckBox.h

@@ -41,7 +41,7 @@ public:
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
     
     
     /// 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<float>& vertexData, const IntRect& currentScissor);
     /// React to mouse click.
     /// React to mouse click.
     virtual void OnClick(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor);
     virtual void OnClick(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers, Cursor* cursor);
     
     

+ 7 - 9
Engine/UI/Cursor.cpp

@@ -204,19 +204,17 @@ VariantVector Cursor::GetShapesAttr() const
     return ret;
     return ret;
 }
 }
 
 
-void Cursor::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor)
+void Cursor::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData, const IntRect& currentScissor)
 {
 {
-    unsigned initialSize = quads.Size();
+    unsigned initialSize = vertexData.Size();
     const IntVector2& offset = shapeInfos_[shape_].hotSpot_;
     const IntVector2& offset = shapeInfos_[shape_].hotSpot_;
-    Vector2 floatOffset((float)offset.x_, (float)offset.y_);
+    Vector2 floatOffset(-(float)offset.x_, -(float)offset.y_);
     
     
-    BorderImage::GetBatches(batches, quads, currentScissor);
-    for (unsigned i = initialSize; i < quads.Size(); ++i)
+    BorderImage::GetBatches(batches, vertexData, currentScissor);
+    for (unsigned i = initialSize; i < vertexData.Size(); i += 6)
     {
     {
-        quads[i].topLeft_ -= floatOffset;
-        quads[i].topRight_ -= floatOffset;
-        quads[i].bottomLeft_ -= floatOffset;
-        quads[i].bottomRight_ -= floatOffset;
+        vertexData[i] += floatOffset.x_;
+        vertexData[i + 1] += floatOffset.y_;
     }
     }
 }
 }
 
 

+ 1 - 1
Engine/UI/Cursor.h

@@ -71,7 +71,7 @@ public:
     static void RegisterObject(Context* context);
     static void RegisterObject(Context* context);
     
     
     /// 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<float>& vertexData, const IntRect& currentScissor);
     
     
     /// Define a shape.
     /// Define a shape.
     void DefineShape(CursorShape shape, Image* image, const IntRect& imageRect, const IntVector2& hotSpot, bool osMouseVisible = false);
     void DefineShape(CursorShape shape, Image* image, const IntRect& imageRect, const IntVector2& hotSpot, bool osMouseVisible = false);

+ 3 - 3
Engine/UI/DropDownList.cpp

@@ -74,9 +74,9 @@ void DropDownList::ApplyAttributes()
     SetSelection(selectionAttr_);
     SetSelection(selectionAttr_);
 }
 }
 
 
-void DropDownList::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor)
+void DropDownList::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData, const IntRect& currentScissor)
 {
 {
-    Menu::GetBatches(batches, quads, currentScissor);
+    Menu::GetBatches(batches, vertexData, currentScissor);
     
     
     if (!placeholder_->IsVisible())
     if (!placeholder_->IsVisible())
         return;
         return;
@@ -92,7 +92,7 @@ void DropDownList::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& qu
         // GetBatches() usually resets the hover flag. Therefore get its value and then reset it for the real rendering
         // GetBatches() usually resets the hover flag. Therefore get its value and then reset it for the real rendering
         bool hover = selectedItem->IsHovering();
         bool hover = selectedItem->IsHovering();
         selectedItem->SetHovering(false);
         selectedItem->SetHovering(false);
-        selectedItem->GetBatchesWithOffset(offset, batches, quads, currentScissor);
+        selectedItem->GetBatchesWithOffset(offset, batches, vertexData, currentScissor);
         selectedItem->SetHovering(hover);
         selectedItem->SetHovering(hover);
     }
     }
 }
 }

+ 1 - 1
Engine/UI/DropDownList.h

@@ -45,7 +45,7 @@ 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();
     /// 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<float>& vertexData, const IntRect& currentScissor);
     /// React to the popup being shown.
     /// React to the popup being shown.
     virtual void OnShowPopup();
     virtual void OnShowPopup();
     
     

+ 4 - 4
Engine/UI/Sprite.cpp

@@ -91,7 +91,7 @@ const IntVector2& Sprite::GetScreenPosition() const
     return screenPosition_;
     return screenPosition_;
 }
 }
 
 
-void Sprite::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor)
+void Sprite::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData, const IntRect& currentScissor)
 {
 {
     bool allOpaque = true;
     bool allOpaque = true;
     if (GetDerivedOpacity() < 1.0f || color_[C_TOPLEFT].a_ < 1.0f || color_[C_TOPRIGHT].a_ < 1.0f ||
     if (GetDerivedOpacity() < 1.0f || color_[C_TOPLEFT].a_ < 1.0f || color_[C_TOPRIGHT].a_ < 1.0f ||
@@ -99,10 +99,10 @@ void Sprite::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, c
         allOpaque = false;
         allOpaque = false;
     
     
     const IntVector2& size = GetSize();
     const IntVector2& size = GetSize();
-    UIBatch batch(blendMode_ == BLEND_REPLACE && !allOpaque ? BLEND_ALPHA : blendMode_, currentScissor, texture_, &quads);
+    UIBatch batch(this, blendMode_ == BLEND_REPLACE && !allOpaque ? BLEND_ALPHA : blendMode_, currentScissor, texture_, &vertexData);
     
     
-    batch.AddQuad(UIQuad(*this, GetTransform(), 0, 0, size.x_, size.y_, imageRect_.left_, imageRect_.top_, imageRect_.right_ -
-        imageRect_.left_, imageRect_.bottom_ - imageRect_.top_));
+    batch.AddQuad(GetTransform(), 0, 0, size.x_, size.y_, imageRect_.left_, imageRect_.top_, imageRect_.right_ -
+        imageRect_.left_, imageRect_.bottom_ - imageRect_.top_);
     
     
     UIBatch::AddOrMerge(batch, batches);
     UIBatch::AddOrMerge(batch, batches);
     
     

+ 1 - 1
Engine/UI/Sprite.h

@@ -46,7 +46,7 @@ public:
     /// Update and return screen position.
     /// Update and return screen position.
     virtual const IntVector2& GetScreenPosition() const;
     virtual const IntVector2& GetScreenPosition() const;
     /// 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<float>& vertexData, const IntRect& currentScissor);
     /// React to position change.
     /// React to position change.
     virtual void OnPositionSet();
     virtual void OnPositionSet();
     
     

+ 35 - 37
Engine/UI/Text.cpp

@@ -99,13 +99,13 @@ void Text::ApplyAttributes()
     UpdateText();
     UpdateText();
 }
 }
 
 
-void Text::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor)
+void Text::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData, const IntRect& currentScissor)
 {
 {
     // Hovering or whole selection batch
     // Hovering or whole selection batch
     if ((hovering_ && hoverColor_.a_ > 0.0) || (selected_ && selectionColor_.a_ > 0.0f))
     if ((hovering_ && hoverColor_.a_ > 0.0) || (selected_ && selectionColor_.a_ > 0.0f))
     {
     {
-        UIBatch batch(BLEND_ALPHA, currentScissor, 0, &quads);
-        batch.AddQuad(*this, 0, 0, GetWidth(), GetHeight(), 0, 0, 0, 0, selected_ && selectionColor_.a_ > 0.0f ? selectionColor_ :
+        UIBatch batch(this, BLEND_ALPHA, currentScissor, 0, &vertexData);
+        batch.AddQuad(0, 0, GetWidth(), GetHeight(), 0, 0, 0, 0, selected_ && selectionColor_.a_ > 0.0f ? selectionColor_ :
             hoverColor_);
             hoverColor_);
         UIBatch::AddOrMerge(batch, batches);
         UIBatch::AddOrMerge(batch, batches);
     }
     }
@@ -113,7 +113,7 @@ void Text::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, con
     // Partial selection batch
     // Partial selection batch
     if (!selected_ && selectionLength_ && charSizes_.Size() >= selectionStart_ + selectionLength_ && selectionColor_.a_ > 0.0f)
     if (!selected_ && selectionLength_ && charSizes_.Size() >= selectionStart_ + selectionLength_ && selectionColor_.a_ > 0.0f)
     {
     {
-        UIBatch batch(BLEND_ALPHA, currentScissor, 0, &quads);
+        UIBatch batch(this, BLEND_ALPHA, currentScissor, 0, &vertexData);
         
         
         IntVector2 currentStart = charPositions_[selectionStart_];
         IntVector2 currentStart = charPositions_[selectionStart_];
         IntVector2 currentEnd = currentStart;
         IntVector2 currentEnd = currentStart;
@@ -124,7 +124,7 @@ void Text::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, con
             {
             {
                 if (charPositions_[i].y_ != currentStart.y_)
                 if (charPositions_[i].y_ != currentStart.y_)
                 {
                 {
-                    batch.AddQuad(*this, currentStart.x_, currentStart.y_, currentEnd.x_ - currentStart.x_, currentEnd.y_ - currentStart.y_,
+                    batch.AddQuad(currentStart.x_, currentStart.y_, currentEnd.x_ - currentStart.x_, currentEnd.y_ - currentStart.y_,
                         0, 0, 0, 0, selectionColor_);
                         0, 0, 0, 0, selectionColor_);
                     currentStart = charPositions_[i];
                     currentStart = charPositions_[i];
                     currentEnd = currentStart + charSizes_[i];
                     currentEnd = currentStart + charSizes_[i];
@@ -138,7 +138,7 @@ void Text::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, con
         }
         }
         if (currentEnd != currentStart)
         if (currentEnd != currentStart)
         {
         {
-            batch.AddQuad(*this, currentStart.x_, currentStart.y_, currentEnd.x_ - currentStart.x_, currentEnd.y_ - currentStart.y_,
+            batch.AddQuad(currentStart.x_, currentStart.y_, currentEnd.x_ - currentStart.x_, currentEnd.y_ - currentStart.y_,
                 0, 0, 0, 0, selectionColor_);
                 0, 0, 0, 0, selectionColor_);
         }
         }
         
         
@@ -152,41 +152,39 @@ void Text::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, con
         if (!face)
         if (!face)
             return;
             return;
         
         
-        Vector<PODVector<UIQuad> > pageQuads(face->textures_.Size());
-        
-        unsigned rowIndex = 0;
-        int x = GetRowStartPosition(rowIndex);
-        int y = 0;
-        
-        for (unsigned i = 0; i < printText_.Size(); ++i)
+        for (unsigned n = 0; n < face->textures_.Size(); ++n)
         {
         {
-            unsigned c = printText_[i];
-            
-            if (c != '\n')
+            UIBatch pageBatch(this, BLEND_ALPHA, currentScissor, face->textures_[n], &vertexData);
+
+            unsigned rowIndex = 0;
+            int x = GetRowStartPosition(rowIndex);
+            int y = 0;
+        
+            for (unsigned i = 0; i < printText_.Size(); ++i)
             {
             {
-                const FontGlyph* p = face->GetGlyph(c);
-                if (!p)
-                    continue;
-                
-                const FontGlyph& glyph = *p;
-                pageQuads[glyph.page_].Push(UIQuad(*this, x + glyph.offsetX_, y + glyph.offsetY_, glyph.width_, glyph.height_, glyph.x_, glyph.y_));
+                unsigned c = printText_[i];
+            
+                if (c != '\n')
+                {
+                    const FontGlyph* p = face->GetGlyph(c);
+                    if (!p || p->page_ != n)
+                        continue;
+                                 
+                    const FontGlyph& glyph = *p;
+                    pageBatch.AddQuad(x + glyph.offsetX_, y + glyph.offsetY_, glyph.width_, glyph.height_, glyph.x_, glyph.y_);
                 
                 
-                x += glyph.advanceX_;
-                if (i < printText_.Size() - 1)
-                    x += face->GetKerning(c, printText_[i + 1]);
-            }
-            else
-            {
-                x = GetRowStartPosition(++rowIndex);
-                y += rowHeight_;
+                    x += glyph.advanceX_;
+                    if (i < printText_.Size() - 1)
+                        x += face->GetKerning(c, printText_[i + 1]);
+                }
+                else
+                {
+                    x = GetRowStartPosition(++rowIndex);
+                    y += rowHeight_;
+                }
             }
             }
-        }
-            
-        for (unsigned page = 0; page < face->textures_.Size(); ++page)
-        {
-            UIBatch batch(BLEND_ALPHA, currentScissor, face->textures_[page], &quads);
-            batch.AddQuad(pageQuads[page]);
-            UIBatch::AddOrMerge(batch, batches);
+
+            UIBatch::AddOrMerge(pageBatch, batches);
         }
         }
     }
     }
     
     

+ 1 - 1
Engine/UI/Text.h

@@ -47,7 +47,7 @@ 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();
     /// 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<float>& vertexData, const IntRect& currentScissor);
     /// React to resize.
     /// React to resize.
     virtual void OnResize();
     virtual void OnResize();
     
     

+ 12 - 11
Engine/UI/UI.cpp

@@ -52,6 +52,8 @@
 
 
 #include "Sort.h"
 #include "Sort.h"
 
 
+#include <cstring>
+
 #include "DebugNew.h"
 #include "DebugNew.h"
 
 
 namespace Urho3D
 namespace Urho3D
@@ -244,9 +246,9 @@ void UI::RenderUpdate()
         cursor_->SetTempVisible(false);
         cursor_->SetTempVisible(false);
     }
     }
     
     
-    // Get batches & quads from the UI elements
+    // Get rendering batches from the UI elements
     batches_.Clear();
     batches_.Clear();
-    quads_.Clear();
+    vertexData_.Clear();
     const IntVector2& rootSize = rootElement_->GetSize();
     const IntVector2& rootSize = rootElement_->GetSize();
     GetBatches(rootElement_, IntRect(0, 0, rootSize.x_, rootSize.y_));
     GetBatches(rootElement_, IntRect(0, 0, rootSize.x_, rootSize.y_));
 
 
@@ -262,11 +264,11 @@ void UI::Render()
     
     
     PROFILE(RenderUI);
     PROFILE(RenderUI);
     
     
-    if (quads_.Empty())
+    if (vertexData_.Empty())
         return;
         return;
     
     
     // Update quad geometry into the vertex buffer
     // Update quad geometry into the vertex buffer
-    unsigned numVertices = quads_.Size() * 6;
+    unsigned numVertices = vertexData_.Size() / 6;
     // Resize the vertex buffer if too small or much too large
     // Resize the vertex buffer if too small or much too large
     if (vertexBuffer_->GetVertexCount() < numVertices || vertexBuffer_->GetVertexCount() > numVertices * 2)
     if (vertexBuffer_->GetVertexCount() < numVertices || vertexBuffer_->GetVertexCount() > numVertices * 2)
         vertexBuffer_->SetSize(numVertices, MASK_POSITION | MASK_COLOR | MASK_TEXCOORD1, true);
         vertexBuffer_->SetSize(numVertices, MASK_POSITION | MASK_COLOR | MASK_TEXCOORD1, true);
@@ -276,9 +278,8 @@ void UI::Render()
     if (!dest)
     if (!dest)
         return;
         return;
     
     
-    for (unsigned i = 0; i < batches_.Size(); ++i)
-        batches_[i].UpdateGeometry(graphics_, ((unsigned char*)dest) + batches_[i].quadStart_ * vertexSize * 6);
-    
+    memcpy(dest, &vertexData_[0], vertexData_.Size() * sizeof(float));
+
     vertexBuffer_->Unlock();
     vertexBuffer_->Unlock();
     
     
     Vector2 invScreenSize(1.0f / (float)graphics_->GetWidth(), 1.0f / (float)graphics_->GetHeight());
     Vector2 invScreenSize(1.0f / (float)graphics_->GetWidth(), 1.0f / (float)graphics_->GetHeight());
@@ -309,7 +310,7 @@ void UI::Render()
     for (unsigned i = 0; i < batches_.Size(); ++i)
     for (unsigned i = 0; i < batches_.Size(); ++i)
     {
     {
         const UIBatch& batch = batches_[i];
         const UIBatch& batch = batches_[i];
-        if (!batch.quadCount_)
+        if (batch.vertexStart_ == batch.vertexEnd_)
             continue;
             continue;
         
         
         if (!batch.texture_)
         if (!batch.texture_)
@@ -342,7 +343,7 @@ void UI::Render()
         graphics_->SetScissorTest(true, batch.scissor_);
         graphics_->SetScissorTest(true, batch.scissor_);
         graphics_->SetTexture(0, batch.texture_);
         graphics_->SetTexture(0, batch.texture_);
         graphics_->SetVertexBuffer(vertexBuffer_);
         graphics_->SetVertexBuffer(vertexBuffer_);
-        graphics_->Draw(TRIANGLE_LIST, batch.quadStart_ * 6, batch.quadCount_ * 6);
+        graphics_->Draw(TRIANGLE_LIST, batch.vertexStart_ / 6, (batch.vertexEnd_ - batch.vertexStart_) / 6);
     }
     }
 }
 }
 
 
@@ -530,7 +531,7 @@ void UI::GetBatches(UIElement* element, IntRect currentScissor)
             while (j != children.End() && (*j)->GetPriority() == currentPriority)
             while (j != children.End() && (*j)->GetPriority() == currentPriority)
             {
             {
                 if ((*j)->IsWithinScissor(currentScissor))
                 if ((*j)->IsWithinScissor(currentScissor))
-                    (*j)->GetBatches(batches_, quads_, currentScissor);
+                    (*j)->GetBatches(batches_, vertexData_, currentScissor);
                 ++j;
                 ++j;
             }
             }
             // Now recurse into the children
             // Now recurse into the children
@@ -548,7 +549,7 @@ void UI::GetBatches(UIElement* element, IntRect currentScissor)
         while (i != children.End())
         while (i != children.End())
         {
         {
             if ((*i)->IsWithinScissor(currentScissor))
             if ((*i)->IsWithinScissor(currentScissor))
-                (*i)->GetBatches(batches_, quads_, currentScissor);
+                (*i)->GetBatches(batches_, vertexData_, currentScissor);
             if ((*i)->IsVisible())
             if ((*i)->IsVisible())
                 GetBatches(*i, currentScissor);
                 GetBatches(*i, currentScissor);
             ++i;
             ++i;

+ 2 - 2
Engine/UI/UI.h

@@ -150,8 +150,8 @@ private:
     WeakPtr<UIElement> focusElement_;
     WeakPtr<UIElement> focusElement_;
     /// UI rendering batches.
     /// UI rendering batches.
     PODVector<UIBatch> batches_;
     PODVector<UIBatch> batches_;
-    /// UI rendering quads.
-    PODVector<UIQuad> quads_;
+    /// UI rendering vertex data.
+    PODVector<float> vertexData_;
     /// UI vertex buffer.
     /// UI vertex buffer.
     SharedPtr<VertexBuffer> vertexBuffer_;
     SharedPtr<VertexBuffer> vertexBuffer_;
     /// UI element query vector.
     /// UI element query vector.

+ 155 - 210
Engine/UI/UIBatch.cpp

@@ -33,191 +33,189 @@ namespace Urho3D
 {
 {
 
 
 #ifdef USE_OPENGL
 #ifdef USE_OPENGL
-static const Vector2 posAdjust(Vector2::ZERO);
+static const float posAdjust = 0.0f;
 #else
 #else
-static const Vector2 posAdjust(0.5f, 0.5f);
+static const float posAdjust = 0.5f;
 #endif
 #endif
 
 
-UIQuad::UIQuad() :
-    defined_(false)
+UIBatch::UIBatch() :
+    element_(0),
+    blendMode_(BLEND_REPLACE),
+    texture_(0),
+    vertexData_(0),
+    vertexStart_(0),
+    vertexEnd_(0)
+{
+}
+
+UIBatch::UIBatch(UIElement* element, BlendMode blendMode, const IntRect& scissor, Texture* texture, PODVector<float>* vertexData) :
+    element_(element),
+    blendMode_(blendMode),
+    scissor_(scissor),
+    texture_(texture),
+    vertexData_(vertexData),
+    vertexStart_(vertexData->Size()),
+    vertexEnd_(vertexData->Size())
 {
 {
 }
 }
 
 
-UIQuad::UIQuad(const UIElement& element, int x, int y, int width, int height, int texOffsetX, int texOffsetY,
-    int texWidth, int texHeight, Color* color) :
-    defined_(false)
+
+void UIBatch::AddQuad(int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth, int texHeight,
+    Color* color)
 {
 {
-    if (color || !element.HasColorGradient())
+    unsigned topLeftColor, topRightColor, bottomLeftColor, bottomRightColor;
+
+    if (color || !element_->HasColorGradient())
     {
     {
-        unsigned uintColor = (color ? *color : element.GetDerivedColor()).ToUInt();
+        unsigned uintColor = (color ? *color : element_->GetDerivedColor()).ToUInt();
         
         
         // If alpha is 0, nothing will be rendered, so do not add the quad
         // If alpha is 0, nothing will be rendered, so do not add the quad
         if (!(uintColor & 0xff000000))
         if (!(uintColor & 0xff000000))
             return;
             return;
         
         
-        topLeftColor_ = uintColor;
-        topRightColor_ = uintColor;
-        bottomLeftColor_ = uintColor;
-        bottomRightColor_ = uintColor;
+        topLeftColor = uintColor;
+        topRightColor = uintColor;
+        bottomLeftColor = uintColor;
+        bottomRightColor = uintColor;
     }
     }
     else
     else
     {
     {
-        topLeftColor_ = GetInterpolatedColor(element, x, y);
-        topRightColor_ = GetInterpolatedColor(element, x + width, y);
-        bottomLeftColor_ = GetInterpolatedColor(element, x, y + height);
-        bottomRightColor_ = GetInterpolatedColor(element, x + width, y + height);
+        topLeftColor = GetInterpolatedColor(x, y);
+        topRightColor = GetInterpolatedColor(x + width, y);
+        bottomLeftColor = GetInterpolatedColor(x, y + height);
+        bottomRightColor = GetInterpolatedColor(x + width, y + height);
     }
     }
     
     
-    const IntVector2& screenPos = element.GetScreenPosition();
+    const IntVector2& screenPos = element_->GetScreenPosition();
+    
+    Vector2 invTextureSize;
+    if (texture_)
+        invTextureSize = Vector2(1.0f / (float)texture_->GetWidth(), 1.0f / (float)texture_->GetHeight());
+    else
+        invTextureSize = Vector2::ONE;
     
     
-    float left = (float)(x + screenPos.x_);
+    float left = (float)(x + screenPos.x_) - posAdjust;
     float right = left + (float)width;
     float right = left + (float)width;
-    float top = (float)(y + screenPos.y_);
+    float top = (float)(y + screenPos.y_) - posAdjust;
     float bottom = top + (float)height;
     float bottom = top + (float)height;
-    topLeft_ = Vector2(left, top) - posAdjust;
-    topRight_ = Vector2(right, top) - posAdjust;
-    bottomLeft_ = Vector2(left, bottom) - posAdjust;
-    bottomRight_ = Vector2(right, bottom) - posAdjust;
     
     
-    leftUV_ = texOffsetX;
-    topUV_ = texOffsetY;
-    rightUV_ = texOffsetX + (texWidth ? texWidth : width);
-    bottomUV_ = texOffsetY + (texHeight ? texHeight : height);
+    float leftUV = texOffsetX * invTextureSize.x_;
+    float topUV = texOffsetY * invTextureSize.y_;
+    float rightUV = (texOffsetX + (texWidth ? texWidth : width)) * invTextureSize.x_;
+    float bottomUV = (texOffsetY + (texHeight ? texHeight : height)) * invTextureSize.y_;
+    
+    unsigned begin = vertexData_->Size();
+    vertexData_->Resize(begin + 6 * 6);
+    float* dest = &(vertexData_->At(begin));
+    vertexEnd_ = vertexData_->Size();
+    
+    *dest++ = left; *dest++ = top; *dest++ = 0.0f;
+    *((unsigned*)dest) = topLeftColor; dest++;
+    *dest++ = leftUV; *dest++ = topUV;
+    
+    *dest++ = right; *dest++ = top; *dest++ = 0.0f;
+    *((unsigned*)dest) = topRightColor; dest++;
+    *dest++ = rightUV; *dest++ = topUV;
+    
+    *dest++ = left; *dest++ = bottom; *dest++ = 0.0f;
+    *((unsigned*)dest) = bottomLeftColor; dest++;
+    *dest++ = leftUV; *dest++ = bottomUV;
     
     
-    defined_ = true;
+    *dest++ = right; *dest++ = top; *dest++ = 0.0f;
+    *((unsigned*)dest) = topRightColor; dest++;
+    *dest++ = rightUV; *dest++ = topUV;
+    
+    *dest++ = right; *dest++ = bottom; *dest++ = 0.0f;
+    *((unsigned*)dest) = bottomRightColor; dest++;
+    *dest++ = rightUV; *dest++ = bottomUV;
+
+    *dest++ = left; *dest++ = bottom; *dest++ = 0.0f;
+    *((unsigned*)dest) = bottomLeftColor; dest++;
+    *dest++ = leftUV; *dest++ = bottomUV;
 }
 }
 
 
-UIQuad::UIQuad(const UIElement& element, const Matrix3x4& transform, int x, int y, int width, int height, int texOffsetX, int texOffsetY,
-    int texWidth, int texHeight, Color* color) :
-    defined_(false)
+void UIBatch::AddQuad(const Matrix3x4& transform, int x, int y, int width, int height, int texOffsetX, int texOffsetY,
+    int texWidth, int texHeight, Color* color) 
 {
 {
-    if (color || !element.HasColorGradient())
+    unsigned topLeftColor, topRightColor, bottomLeftColor, bottomRightColor;
+    
+    if (color || !element_->HasColorGradient())
     {
     {
-        unsigned uintColor = (color ? *color : element.GetDerivedColor()).ToUInt();
+        unsigned uintColor = (color ? *color : element_->GetDerivedColor()).ToUInt();
         
         
         // If alpha is 0, nothing will be rendered, so do not add the quad
         // If alpha is 0, nothing will be rendered, so do not add the quad
         if (!(uintColor & 0xff000000))
         if (!(uintColor & 0xff000000))
             return;
             return;
         
         
-        topLeftColor_ = uintColor;
-        topRightColor_ = uintColor;
-        bottomLeftColor_ = uintColor;
-        bottomRightColor_ = uintColor;
+        topLeftColor = uintColor;
+        topRightColor = uintColor;
+        bottomLeftColor = uintColor;
+        bottomRightColor = uintColor;
     }
     }
     else
     else
     {
     {
-        topLeftColor_ = GetInterpolatedColor(element, x, y);
-        topRightColor_ = GetInterpolatedColor(element, x + width, y);
-        bottomLeftColor_ = GetInterpolatedColor(element, x, y + height);
-        bottomRightColor_ = GetInterpolatedColor(element, x + width, y + height);
+        topLeftColor = GetInterpolatedColor(x, y);
+        topRightColor = GetInterpolatedColor(x + width, y);
+        bottomLeftColor = GetInterpolatedColor(x, y + height);
+        bottomRightColor = GetInterpolatedColor(x + width, y + height);
     }
     }
     
     
-    Vector3 v1 = transform * Vector3((float)x, (float)y, 0.0f);
-    Vector3 v2 = transform * Vector3((float)x + (float)width, (float)y, 0.0f);
-    Vector3 v3 = transform * Vector3((float)x, (float)y + (float)height, 0.0f);
-    Vector3 v4 = transform * Vector3((float)x + (float)width, (float)y + (float)height, 0.0f);
+    Vector2 invTextureSize;
+    if (texture_)
+        invTextureSize = Vector2(1.0f / (float)texture_->GetWidth(), 1.0f / (float)texture_->GetHeight());
+    else
+        invTextureSize = Vector2::ONE;
     
     
-    topLeft_.x_ = v1.x_; topLeft_.y_ = v1.y_;
-    topRight_.x_ = v2.x_; topRight_.y_ = v2.y_;
-    bottomLeft_.x_ = v3.x_; bottomLeft_.y_ = v3.y_;
-    bottomRight_.x_ = v4.x_; bottomRight_.y_ = v4.y_;
+    Vector3 posAdjustVec(posAdjust, posAdjust, 0.0f);
     
     
-    leftUV_ = texOffsetX;
-    topUV_ = texOffsetY;
-    rightUV_ = texOffsetX + (texWidth ? texWidth : (int)width);
-    bottomUV_ = texOffsetY + (texHeight ? texHeight : (int)height);
+    Vector3 v1 = (transform * Vector3((float)x, (float)y, 0.0f)) - posAdjustVec;
+    Vector3 v2 = (transform * Vector3((float)x + (float)width, (float)y, 0.0f)) - posAdjustVec;
+    Vector3 v3 = (transform * Vector3((float)x, (float)y + (float)height, 0.0f)) - posAdjustVec;
+    Vector3 v4 = (transform * Vector3((float)x + (float)width, (float)y + (float)height, 0.0f)) - posAdjustVec;
     
     
-    defined_ = true;
-}
-
-unsigned UIQuad::GetInterpolatedColor(const UIElement& element, int x, int y)
-{
-    const IntVector2& size = element.GetSize();
+    float leftUV = ((float)texOffsetX) * invTextureSize.x_;
+    float topUV = ((float)texOffsetY) * invTextureSize.y_;
+    float rightUV = ((float)(texOffsetX + (texWidth ? texWidth : width))) * invTextureSize.x_;
+    float bottomUV = ((float)(texOffsetY + (texHeight ? texHeight : height))) * invTextureSize.y_;
     
     
-    if (size.x_ && size.y_)
-    {
-        float cLerpX = Clamp((float)x / (float)size.x_, 0.0f, 1.0f);
-        float cLerpY = Clamp((float)y / (float)size.y_, 0.0f, 1.0f);
-        
-        Color topColor = element.GetColor(C_TOPLEFT).Lerp(element.GetColor(C_TOPRIGHT), cLerpX);
-        Color bottomColor = element.GetColor(C_BOTTOMLEFT).Lerp(element.GetColor(C_BOTTOMRIGHT), cLerpX);
-        Color color = topColor.Lerp(bottomColor, cLerpY);
-        color.a_ *= element.GetDerivedOpacity();
-        return color.ToUInt();
-    }
-    else
-    {
-        Color color = element.GetColor(C_TOPLEFT);
-        color.a_ *= element.GetDerivedOpacity();
-        return color.ToUInt();
-    }
-}
-
-UIBatch::UIBatch() :
-    blendMode_(BLEND_REPLACE),
-    texture_(0),
-    quads_(0),
-    quadStart_(0),
-    quadCount_(0)
-{
-}
+    unsigned begin = vertexData_->Size();
+    vertexData_->Resize(begin + 6 * 6);
+    float* dest = &(vertexData_->At(begin));
+    vertexEnd_ = vertexData_->Size();
 
 
-UIBatch::UIBatch(BlendMode blendMode, const IntRect& scissor, Texture* texture, PODVector<UIQuad>* quads) :
-    blendMode_(blendMode),
-    scissor_(scissor),
-    texture_(texture),
-    quads_(0),
-    quadStart_(0),
-    quadCount_(0)
-{
-    Begin(quads);
-}
-
-void UIBatch::Begin(PODVector<UIQuad>* quads)
-{
-    quads_ = quads;
-    quadStart_ = quads_->Size();
-    quadCount_ = 0;
-}
-
-void UIBatch::AddQuad(const PODVector<UIQuad>& quads)
-{
-    if (quads.Empty())
-        return;
+    *dest++ = v1.x_; *dest++ = v1.y_; *dest++ = 0.0f;
+    *((unsigned*)dest) = topLeftColor; dest++;
+    *dest++ = leftUV; *dest++ = topUV;
     
     
-    *quads_ += quads;
-    quadCount_ += quads.Size();
-}
-
-void UIBatch::AddQuad(UIQuad quad)
-{
-    if (quad.defined_)
-    {
-        quads_->Push(quad);
-        ++quadCount_;
-    }
-}
-
-void UIBatch::AddQuad(const UIElement& element, int x, int y, int width, int height, int texOffsetX, int texOffsetY)
-{
-    AddQuad(UIQuad(element, x, y, width, height, texOffsetX, texOffsetY));
-}
+    *dest++ = v2.x_; *dest++ = v2.y_; *dest++ = 0.0f;
+    *((unsigned*)dest) = topRightColor; dest++;
+    *dest++ = rightUV; *dest++ = topUV;
+    
+    *dest++ = v3.x_; *dest++ = v3.y_; *dest++ = 0.0f;
+    *((unsigned*)dest) = bottomLeftColor; dest++;
+    *dest++ = leftUV; *dest++ = bottomUV;
+    
+    *dest++ = v2.x_; *dest++ = v2.y_; *dest++ = 0.0f;
+    *((unsigned*)dest) = topRightColor; dest++;
+    *dest++ = rightUV; *dest++ = topUV;
+    
+    *dest++ = v4.x_; *dest++ = v4.y_; *dest++ = 0.0f;
+    *((unsigned*)dest) = bottomRightColor; dest++;
+    *dest++ = rightUV; *dest++ = bottomUV;
 
 
-void UIBatch::AddQuad(const UIElement& element, int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth,
-    int texHeight)
-{
-    AddQuad(UIQuad(element, x, y, width, height, texOffsetX, texOffsetY, texWidth, texHeight));
+    *dest++ = v3.x_; *dest++ = v3.y_; *dest++ = 0.0f;
+    *((unsigned*)dest) = bottomLeftColor; dest++;
+    *dest++ = leftUV; *dest++ = bottomUV;
 }
 }
 
 
-void UIBatch::AddQuad(const UIElement& element, int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth,
-    int texHeight, bool tiled)
+void UIBatch::AddQuad(int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth, int texHeight, bool tiled)
 {
 {
-    if (!(element.HasColorGradient() || element.GetDerivedColor().ToUInt() & 0xff000000))
-        return; // No gradient and alpha is 0, so do not add the quads
+    if (!(element_->HasColorGradient() || element_->GetDerivedColor().ToUInt() & 0xff000000))
+        return; // No gradient and alpha is 0, so do not add the quad
     
     
     if (!tiled)
     if (!tiled)
     {
     {
-        AddQuad(element, x, y, width, height, texOffsetX, texOffsetY, texWidth, texHeight);
+        AddQuad(x, y, width, height, texOffsetX, texOffsetY, texWidth, texHeight);
         return;
         return;
     }
     }
     
     
@@ -235,7 +233,7 @@ void UIBatch::AddQuad(const UIElement& element, int x, int y, int width, int hei
         {
         {
             tileW = Min(width - tileX, texWidth);
             tileW = Min(width - tileX, texWidth);
             
             
-            AddQuad(element, x + tileX, y + tileY, tileW, tileH, texOffsetX, texOffsetY, tileW, tileH);
+            AddQuad(x + tileX, y + tileY, tileW, tileH, texOffsetX, texOffsetY, tileW, tileH);
             
             
             tileX += tileW;
             tileX += tileW;
         }
         }
@@ -244,11 +242,11 @@ void UIBatch::AddQuad(const UIElement& element, int x, int y, int width, int hei
     }
     }
 }
 }
 
 
-void UIBatch::AddQuad(const UIElement& element, int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth,
-    int texHeight, const Color& color)
+void UIBatch::AddQuad(int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth, int texHeight,
+    const Color& color)
 {
 {
-    Color derivedColor(color.r_, color.g_, color.b_, color.a_ * element.GetDerivedOpacity());
-    AddQuad(UIQuad(element, x, y, width, height, texOffsetX, texOffsetY, texWidth, texHeight, &derivedColor));
+    Color derivedColor(color.r_, color.g_, color.b_, color.a_ * element_->GetDerivedOpacity());
+    AddQuad(x, y, width, height, texOffsetX, texOffsetY, texWidth, texHeight, &derivedColor);
 }
 }
 
 
 bool UIBatch::Merge(const UIBatch& batch)
 bool UIBatch::Merge(const UIBatch& batch)
@@ -256,93 +254,40 @@ bool UIBatch::Merge(const UIBatch& batch)
     if (batch.blendMode_ != blendMode_ ||
     if (batch.blendMode_ != blendMode_ ||
         batch.scissor_ != scissor_ ||
         batch.scissor_ != scissor_ ||
         batch.texture_ != texture_ ||
         batch.texture_ != texture_ ||
-        batch.quads_ != quads_ ||
-        batch.quadStart_ != quadStart_ + quadCount_)
+        batch.vertexData_ != vertexData_ ||
+        batch.vertexStart_ != vertexEnd_)
         return false;
         return false;
     
     
-    quadCount_ += batch.quadCount_;
+    vertexEnd_ = batch.vertexEnd_;
     return true;
     return true;
 }
 }
 
 
-void UIBatch::UpdateGeometry(Graphics* graphics, void* lockedData)
+unsigned UIBatch::GetInterpolatedColor(int x, int y)
 {
 {
-    if (!quadCount_)
-        return;
-    
-    float* dest = (float*)lockedData;
+    const IntVector2& size = element_->GetSize();
     
     
-    if (texture_)
+    if (size.x_ && size.y_)
     {
     {
-        Vector2 invTextureSize(1.0f / (float)texture_->GetWidth(), 1.0f / (float)texture_->GetHeight());
+        float cLerpX = Clamp((float)x / (float)size.x_, 0.0f, 1.0f);
+        float cLerpY = Clamp((float)y / (float)size.y_, 0.0f, 1.0f);
         
         
-        for (unsigned i = 0; i < quadCount_; ++i)
-        {
-            const UIQuad& quad = quads_->At(quadStart_ + i);
-            
-            Vector2 topLeftUV = Vector2((float)quad.leftUV_, (float)quad.topUV_) * invTextureSize;
-            Vector2 bottomRightUV = Vector2((float)quad.rightUV_, (float)quad.bottomUV_) * invTextureSize;
-            
-            *dest++ = quad.topLeft_.x_; *dest++ = quad.topLeft_.y_; *dest++ = 0.0f;
-            *((unsigned*)dest) = quad.topLeftColor_; dest++;
-            *dest++ = topLeftUV.x_; *dest++ = topLeftUV.y_;
-            
-            *dest++ = quad.topRight_.x_; *dest++ = quad.topRight_.y_; *dest++ = 0.0f;
-            *((unsigned*)dest) = quad.topRightColor_; dest++;
-            *dest++ = bottomRightUV.x_; *dest++ = topLeftUV.y_;
-            
-            *dest++ = quad.bottomLeft_.x_; *dest++ = quad.bottomLeft_.y_; *dest++ = 0.0f;
-            *((unsigned*)dest) = quad.bottomLeftColor_; dest++;
-            *dest++ = topLeftUV.x_; *dest++ = bottomRightUV.y_;
-            
-            *dest++ = quad.topRight_.x_; *dest++ = quad.topRight_.y_; *dest++ = 0.0f;
-            *((unsigned*)dest) = quad.topRightColor_; dest++;
-            *dest++ = bottomRightUV.x_; *dest++ = topLeftUV.y_;
-            
-            *dest++ = quad.bottomRight_.x_; *dest++ = quad.bottomRight_.y_; *dest++ = 0.0f;
-            *((unsigned*)dest) = quad.bottomRightColor_; dest++;
-            *dest++ = bottomRightUV.x_; *dest++ = bottomRightUV.y_;
-            
-            *dest++ = quad.bottomLeft_.x_; *dest++ = quad.bottomLeft_.y_; *dest++ = 0.0f;
-            *((unsigned*)dest) = quad.bottomLeftColor_; dest++;
-            *dest++ = topLeftUV.x_; *dest++ = bottomRightUV.y_;
-        }
+        Color topColor = element_->GetColor(C_TOPLEFT).Lerp(element_->GetColor(C_TOPRIGHT), cLerpX);
+        Color bottomColor = element_->GetColor(C_BOTTOMLEFT).Lerp(element_->GetColor(C_BOTTOMRIGHT), cLerpX);
+        Color color = topColor.Lerp(bottomColor, cLerpY);
+        color.a_ *= element_->GetDerivedOpacity();
+        return color.ToUInt();
     }
     }
     else
     else
     {
     {
-        for (unsigned i = 0; i < quadCount_; ++i)
-        {
-            const UIQuad& quad = quads_->At(quadStart_ + i);
-            
-            *dest++ = quad.topLeft_.x_; *dest++ = quad.topLeft_.y_; *dest++ = 0.0f;
-            *((unsigned*)dest) = quad.topLeftColor_; dest++;
-            dest += 2; // Jump over unused UV coordinates
-            
-            *dest++ = quad.topRight_.x_; *dest++ = quad.topRight_.y_; *dest++ = 0.0f;
-            *((unsigned*)dest) = quad.topRightColor_; dest++;
-            dest += 2;
-            
-            *dest++ = quad.bottomLeft_.x_; *dest++ = quad.bottomLeft_.y_; *dest++ = 0.0f;
-            *((unsigned*)dest) = quad.bottomLeftColor_; dest++;
-            dest += 2;
-            
-            *dest++ = quad.topRight_.x_; *dest++ = quad.topRight_.y_; *dest++ = 0.0f;
-            *((unsigned*)dest) = quad.topRightColor_; dest++;
-            dest += 2;
-            
-            *dest++ = quad.bottomRight_.x_; *dest++ = quad.bottomRight_.y_; *dest++ = 0.0f;
-            *((unsigned*)dest) = quad.bottomRightColor_; dest++;
-            dest += 2;
-            
-            *dest++ = quad.bottomLeft_.x_; *dest++ = quad.bottomLeft_.y_; *dest++ = 0.0f;
-            *((unsigned*)dest) = quad.bottomLeftColor_; dest++;
-            dest += 2;
-        }
+        Color color = element_->GetColor(C_TOPLEFT);
+        color.a_ *= element_->GetDerivedOpacity();
+        return color.ToUInt();
     }
     }
 }
 }
 
 
 void UIBatch::AddOrMerge(const UIBatch& batch, PODVector<UIBatch>& batches)
 void UIBatch::AddOrMerge(const UIBatch& batch, PODVector<UIBatch>& batches)
 {
 {
-    if (!batch.quadCount_)
+    if (batch.vertexEnd_ == batch.vertexStart_)
         return;
         return;
     
     
     if (!batches.Empty() && batches.Back().Merge(batch))
     if (!batches.Empty() && batches.Back().Merge(batch))

+ 16 - 63
Engine/UI/UIBatch.h

@@ -36,49 +36,6 @@ class ShaderVariation;
 class Texture;
 class Texture;
 class UIElement;
 class UIElement;
 
 
-/// %UI rendering quad.
-struct UIQuad
-{
-    /// Construct with defaults.
-    UIQuad();
-    /// Construct.
-    UIQuad(const UIElement& element, int x, int y, int width, int height, int texOffsetX, int texOffsetY,
-        int texWidth = 0, int texHeight = 0, Color* color = 0);
-    /// Construct using a transform matrix.
-    UIQuad(const UIElement& element, const Matrix3x4& transform, int x, int y, int width, int height, int texOffsetX, int texOffsetY,
-        int texWidth = 0, int texHeight = 0, Color* color = 0);
-    
-    /// Return an interpolated color for an UI element.
-    static unsigned GetInterpolatedColor(const UIElement& element, int x, int y);
-    
-    /// Top left position.
-    Vector2 topLeft_;
-    /// Top right position.
-    Vector2 topRight_;
-    /// Bottom left position.
-    Vector2 bottomLeft_;
-    /// Bottom right position.
-    Vector2 bottomRight_;
-    /// Left texture coordinate.
-    short leftUV_;
-    /// Top texture coordinate.
-    short topUV_;
-    /// Right texture coordinate.
-    short rightUV_;
-    /// Bottom texture coordinate.
-    short bottomUV_;
-    /// Top left color.
-    unsigned topLeftColor_;
-    /// Top right color.
-    unsigned topRightColor_;
-    /// Bottom left color.
-    unsigned bottomLeftColor_;
-    /// Bottom right color.
-    unsigned bottomRightColor_;
-    /// Defined flag.
-    bool defined_;
-};
-
 /// %UI rendering draw call.
 /// %UI rendering draw call.
 class UIBatch
 class UIBatch
 {
 {
@@ -86,42 +43,38 @@ public:
     /// Construct with defaults.
     /// Construct with defaults.
     UIBatch();
     UIBatch();
     /// Construct.
     /// Construct.
-    UIBatch(BlendMode blendMode, const IntRect& scissor, Texture* texture, PODVector<UIQuad>* quads);
+    UIBatch(UIElement* element, BlendMode blendMode, const IntRect& scissor, Texture* texture, PODVector<float>* vertexData);
     
     
-    /// Begin adding quads.
-    void Begin(PODVector<UIQuad>* quads);
-    /// Add a collection of quads. Each quad is added without first checking whether it is properly defined.
-    void AddQuad(const PODVector<UIQuad>& quads);
-    /// Add a quad.
-    void AddQuad(UIQuad quad);
     /// Add a quad.
     /// Add a quad.
-    void AddQuad(const UIElement& element, int x, int y, int width, int height, int texOffsetX, int texOffsetY);
-    /// Add a quad with scaled texture.
-    void AddQuad(const UIElement& element, int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth, int texHeight);
+    void AddQuad(int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth = 0, int texHeight = 0, Color* color = 0);
+    /// Add a quad using a transform matrix.
+    void AddQuad(const Matrix3x4& transform, int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth = 0, int texHeight = 0, Color* color = 0);
     /// Add a quad with tiled texture.
     /// Add a quad with tiled texture.
-    void AddQuad(const UIElement& element, int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth, int texHeight, bool tiled);
+    void AddQuad(int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth, int texHeight, bool tiled);
     /// Add a quad with custom color.
     /// Add a quad with custom color.
-    void AddQuad(const UIElement& element, int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth, int texHeight, const Color& color);
+    void AddQuad(int x, int y, int width, int height, int texOffsetX, int texOffsetY, int texWidth, int texHeight, const Color& color);
     /// Merge with another batch.
     /// Merge with another batch.
     bool Merge(const UIBatch& batch);
     bool Merge(const UIBatch& batch);
-    /// Update the vertex data.
-    void UpdateGeometry(Graphics* graphics, void* lockedData);
+    /// Return an interpolated color for the UI element.
+    unsigned GetInterpolatedColor(int x, int y);
     
     
     /// Add or merge a batch.
     /// Add or merge a batch.
     static void AddOrMerge(const UIBatch& batch, PODVector<UIBatch>& batches);
     static void AddOrMerge(const UIBatch& batch, PODVector<UIBatch>& batches);
     
     
+    /// Element this batch represents.
+    UIElement* element_;
     /// Blending mode.
     /// Blending mode.
     BlendMode blendMode_;
     BlendMode blendMode_;
     /// Scissor rectangle.
     /// Scissor rectangle.
     IntRect scissor_;
     IntRect scissor_;
     /// Texture.
     /// Texture.
     Texture* texture_;
     Texture* texture_;
-    /// Quads.
-    PODVector<UIQuad>* quads_;
-    /// Quad start index.
-    unsigned quadStart_;
-    /// Number of quads.
-    unsigned quadCount_;
+    /// Vertex data
+    PODVector<float>* vertexData_;
+    /// Vertex data start index.
+    unsigned vertexStart_;
+    /// Vertex data end index.
+    unsigned vertexEnd_;
 };
 };
 
 
 }
 }

+ 8 - 10
Engine/UI/UIElement.cpp

@@ -302,7 +302,7 @@ void UIElement::Update(float timeStep)
 {
 {
 }
 }
 
 
-void UIElement::GetBatches(PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, const IntRect& currentScissor)
+void UIElement::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData, const IntRect& currentScissor)
 {
 {
     // Reset hovering for next frame
     // Reset hovering for next frame
     hovering_ = false;
     hovering_ = false;
@@ -1347,26 +1347,24 @@ void UIElement::AdjustScissor(IntRect& currentScissor)
     }
     }
 }
 }
 
 
-void UIElement::GetBatchesWithOffset(IntVector2& offset, PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, IntRect
+void UIElement::GetBatchesWithOffset(IntVector2& offset, PODVector<UIBatch>& batches, PODVector<float>& vertexData, IntRect
     currentScissor)
     currentScissor)
 {
 {
     Vector2 floatOffset((float)offset.x_, (float)offset.y_);
     Vector2 floatOffset((float)offset.x_, (float)offset.y_);
-    unsigned initialSize = quads.Size();
+    unsigned initialSize = vertexData.Size();
     
     
-    GetBatches(batches, quads, currentScissor);
-    for (unsigned i = initialSize; i < quads.Size(); ++i)
+    GetBatches(batches, vertexData, currentScissor);
+    for (unsigned i = initialSize; i < vertexData.Size(); i += 6)
     {
     {
-        quads[i].topLeft_ += floatOffset;
-        quads[i].topRight_ += floatOffset;
-        quads[i].bottomLeft_ += floatOffset;
-        quads[i].bottomRight_ += floatOffset;
+        vertexData[i] += floatOffset.x_;
+        vertexData[i + 1] += floatOffset.y_;
     }
     }
     
     
     AdjustScissor(currentScissor);
     AdjustScissor(currentScissor);
     for (Vector<SharedPtr<UIElement> >::ConstIterator i = children_.Begin(); i != children_.End(); ++i)
     for (Vector<SharedPtr<UIElement> >::ConstIterator i = children_.Begin(); i != children_.End(); ++i)
     {
     {
         if ((*i)->IsVisible())
         if ((*i)->IsVisible())
-            (*i)->GetBatchesWithOffset(offset, batches, quads, currentScissor);
+            (*i)->GetBatchesWithOffset(offset, batches, vertexData, currentScissor);
     }
     }
 }
 }
 
 

+ 2 - 2
Engine/UI/UIElement.h

@@ -128,7 +128,7 @@ public:
     /// Update and return screen position.
     /// Update and return screen position.
     virtual const IntVector2& GetScreenPosition() const;
     virtual const IntVector2& GetScreenPosition() const;
     /// 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<float>& vertexData, const IntRect& currentScissor);
     /// 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 click.
     /// React to mouse click.
@@ -411,7 +411,7 @@ public:
     /// Adjust scissor for rendering.
     /// Adjust scissor for rendering.
     void AdjustScissor(IntRect& currentScissor);
     void AdjustScissor(IntRect& currentScissor);
     /// Get UI rendering batches with a specified offset. Also recurses to child elements.
     /// Get UI rendering batches with a specified offset. Also recurses to child elements.
-    void GetBatchesWithOffset(IntVector2& offset, PODVector<UIBatch>& batches, PODVector<UIQuad>& quads, IntRect
+    void GetBatchesWithOffset(IntVector2& offset, PODVector<UIBatch>& batches, PODVector<float>& vertexData, IntRect
         currentScissor);
         currentScissor);
     /// Get color attribute. Uses just the top-left color.
     /// Get color attribute. Uses just the top-left color.
     const Color& GetColorAttr() const { return color_[0]; }
     const Color& GetColorAttr() const { return color_[0]; }