[SOLVED] Subclassing ListboxItem (ListboxImageItem)

For help with general CEGUI usage:
- Questions about the usage of CEGUI and its features, if not explained in the documentation.
- Problems with the CMAKE configuration or problems occuring during the build process/compilation.
- Errors or unexpected behaviour.

Moderators: CEGUI MVP, CEGUI Team

Browser12
Not too shy to talk
Not too shy to talk
Posts: 42
Joined: Thu Jan 24, 2008 06:30
Location: UW-Madison
Contact:

[SOLVED] Subclassing ListboxItem (ListboxImageItem)

Postby Browser12 » Mon Apr 25, 2011 22:55

Solved! Thanks dermont. I'm going to fix my code here so people can look at it in the future

[edit] I guess this probably belongs in Advanced Help, since it's defining a custom Window class :oops: [/edit]

Hi, I was looking for some direction on subclassing ListboxItem.
I want to create a ListboxImageItem, that contains a CEGUI::Texture* member and uses that in its draw() function.
So far I've got the class framework down, including:
- the constructor that sets the texture member, the pixelSize, and obviously calls the ListboxItem constructor.
- the overloaded getPixelSize() function to return my size (which is always 64x64)

Now I seem to be having trouble with the draw() function - mostly because it's a bit lower level in CEGUI than the other things i've been doing and haven't really seen it used much.

From my understand(ish)ing, I can just set my texture to be used by the geometrybuffer that's passed in, use the overlap of whatever target+clipping rects to figure out vertices, append those vertices to the geometrybuffer, and return?

Below is what I'm using right now.. I don't get errors, and if I print out the rects I see things like {2, 2, 108, 66}, then {2, 66, 108, 130} etc. which looks good (I'm assuming the listbox gives me the extra horizontal space to draw in). I even see my Listbox get a scrollbar after I've added a few of these image items. Yet I don't see anything in my Listbox on the screen. Is there anything else I should be checking, or that I'm obviously doing wrong?

Let me know if you'd like any other info, and thanks for reading-

[edit] I just looked and the GeometryBuffer for OpenGL appears to use triangles, not quads. Changed to pushing 6 vertices, but still have the same problem (obviously I would have expected to see 1 triangle anywho) [/edit]

[editedit] so I was using the Vertex::colour_val member wrong; I now use CEGUI::colours to set these. By doing so, using a non-white colour shows me that my triangles are indeed being drawn where I want them. I verified that the size and ID of the CEGUI::Texture *tex is correct; the ID is the same as this texture that I use / render elsewhere, outside of the GUI, in my program. [/editedit]

When I set my colour up to be blue, I can see the blue box if I don't bind the texture (setActiveTexture(0)). However, if I bind my texture, I see a white box, regardless of my colour's RGB.

Code: Select all

ListboxImageItem::ListboxImageItem(std::string name, int artList, int artIndex) : ListboxItem(String(name.c_str()))
{
   tex = InterfaceManager::Get().GetCustomTexture(artList, artIndex);

   pixelSize = tex->getSize();

   setSelectionBrushImage("WindowsLook", "MultiListSelectionBrush");
}

CEGUI::Size ListboxImageItem::getPixelSize() const
{
   return pixelSize;
}

void ListboxImageItem::draw(GeometryBuffer &buffer, const Rect &targetRect, float alpha, const Rect *clipper) const
{
   if (d_selected && d_selectBrush != 0)
      d_selectBrush->draw(buffer, targetRect, clipper, getModulateAlphaColourRect(d_selectCols, alpha));

   // a simple opaque white
   colour white(1.0f, 1.0f, 1.0f);

   Vertex vbuffer[6];

   // top-left
   vbuffer[0].position = Vector3(targetRect.d_left, targetRect.d_top, 0.0f);
   vbuffer[0].colour_val = white;
   vbuffer[0].tex_coords = Vector2(0.0f, 0.0f);
   // bottom-left
   vbuffer[1].position = Vector3(targetRect.d_left, targetRect.d_bottom, 0.0f);
   vbuffer[1].colour_val = white;
   vbuffer[1].tex_coords = Vector2(0.0f, 1.0f);
   // bottom-right
   vbuffer[2].position = Vector3(targetRect.d_right, targetRect.d_bottom, 0.0f);
   vbuffer[2].colour_val = white;
   vbuffer[2].tex_coords = Vector2(1.0f, 1.0f);
   
   // top-right
   vbuffer[3].position = Vector3(targetRect.d_right, targetRect.d_top, 0.0f);
   vbuffer[3].colour_val = white;
   vbuffer[3].tex_coords = Vector2(1.0f, 0.0f);
   // top-left
   vbuffer[4].position = Vector3(targetRect.d_left, targetRect.d_top, 0.0f);
   vbuffer[4].colour_val = white;
   vbuffer[4].tex_coords = Vector2(0.0f, 0.0f);
   // bottom-right
   vbuffer[5].position = Vector3(targetRect.d_right, targetRect.d_bottom, 0.0f);
   vbuffer[5].colour_val = white;
   vbuffer[5].tex_coords = Vector2(1.0f, 1.0f);

   // give our vertices to the buffer for drawing
   buffer.setActiveTexture(tex);
   buffer.appendGeometry(vbuffer, 6);
}


This is the code where I create my CEGUI::Texture, which is passed to the ListboxImageItem constructor - I've verified that the OpenGL textures themselves are loaded properly (I can render them to the screen just fine)

Code: Select all

CEGUI::Texture *VideoManager::GenCustomTexture(int artList, int artIndex)
{
   Texture *targetTex = GraphicsManager::Get().GetaTextureDB(artList, artIndex);
   CEGUI::Texture *newTex = &CEGUIRenderer->createTexture();
   ((CEGUI::OpenGLTexture *)newTex)->setOpenGLTexture(targetTex->ID, CEGUI::Size(targetTex->data.width,
            targetTex->data.height));
   return newTex;
}
Last edited by Browser12 on Sun May 01, 2011 16:40, edited 4 times in total.

User avatar
dermont
Quite a regular
Quite a regular
Posts: 75
Joined: Mon Aug 29, 2005 16:15

Re: Subclassing ListboxItem (ListboxImageItem)

Postby dermont » Fri Apr 29, 2011 03:46

Sorry don't know the answer to your problem, I ran into similar problems trying to add a video as a ListItem so am also interested in a solution.

As a workaround you could take a look at the CEGUITreeItem and use an Imageset for your texture and draw the image in your custom ListItem ( or BasicImage / render for svn).

I've only tried this with an Ogre RTT on 0.75 but it works OK with svn and an OpenGL Texture so it should work.

Code: Select all

class MyListItem : public CEGUI::ListboxItem
{
protected:
    CEGUI::Texture * mTexture;
    const CEGUI::Image* d_iconImage;

public:
    MyListItem (const String& text, CEGUI::uint item_id , CEGUI::Texture * tex, const CEGUI::Image* image) :
        CEGUI::ListboxItem(text), mTexture(tex), d_iconImage(image)
    {
        setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush");
    }

    CEGUI::Size getPixelSize() const
    {
       //return mTexture->getSize();
       return CEGUI::Size(64.0,64.0);
    }

    void draw(CEGUI::GeometryBuffer &buffer, const CEGUI::Rect &targetRect, float alpha, const CEGUI::Rect *clipper) const
    {
        CEGUI::Rect final_rect(targetRect);
        CEGUI::Rect finalPos(final_rect);

        finalPos.setWidth(targetRect.getHeight());
        finalPos.setHeight(targetRect.getHeight());
        buffer.setActiveTexture(mTexture);
        if (d_iconImage)
            d_iconImage->draw(buffer, finalPos, clipper,
                                  CEGUI::ColourRect(CEGUI::colour(1,1,1,alpha)));
        if (d_selected && d_selectBrush != 0)
            d_selectBrush->draw(buffer, finalPos, clipper,
                            getModulateAlphaColourRect(d_selectCols, 0.5));
    }
};


Code: Select all

....
CEGUI::Imageset &imageSet =
   CEGUI::ImagesetManager::getSingleton().create("RTTImageset", guiTex);
   imageSet.defineImage("RTTImage",
                         CEGUI::Point(0.0f, 0.0f),
                         CEGUI::Size(guiTex.getSize().d_width,
                                     guiTex.getSize().d_height),
                         CEGUI::Point(0.0f, 0.0f));

CEGUI::Imageset &imageSet2 = CEGUI::ImagesetManager::getSingleton().createFromImageFile("BackgroundImage", "GPN-2000-001437.tga");
CEGUI::Imageset& drives = CEGUI::ImagesetManager::getSingleton().create("DriveIcons.imageset");

videoListBox->addItem(new MyListItem("TEST", 0 , drives.getTexture(), &drives.getImage("Lime")) );
videoListBox->addItem(new MyListItem("TEST", 1 , imageSet2.getTexture(), &imageSet2.getImage("full_image")) );
videoListBox->addItem(new MyListItem("TEST",2 , imageSet2.getTexture(), &imageSet2.getImage("full_image")) );
videoListBox->addItem(new MyListItem("TEST", 3 , imageSet.getTexture(), &imageSet.getImage("RTTImage")) );

Browser12
Not too shy to talk
Not too shy to talk
Posts: 42
Joined: Thu Jan 24, 2008 06:30
Location: UW-Madison
Contact:

Re: Subclassing ListboxItem (ListboxImageItem)

Postby Browser12 » Fri Apr 29, 2011 05:25

Thanks der! This will do for now.. at least I don't have to develop the rest of my app with invisible textures ;]
I still can't for the life of me find where my draw() function / texture is going wrong, but this is a nice workaround.

User avatar
dermont
Quite a regular
Quite a regular
Posts: 75
Joined: Mon Aug 29, 2005 16:15

Re: Subclassing ListboxItem (ListboxImageItem)

Postby dermont » Fri Apr 29, 2011 07:18

I tried out your original example and it appears to work OK with OpenGL(mercurial) and Ogre( 0.75 ). The only thing I changed were the texture coordinates (0-1.0). I'm not sure what the problem is, maybe you can upload a simple example.

Code: Select all

void draw(CEGUI::GeometryBuffer &buffer, const CEGUI::Rect &targetRect, float alpha, const CEGUI::Rect *clipper) const
{

   // a simple opaque white

/*
   // figure out our clipped dest rectangle
   CEGUI::Rect finalRect;
   finalRect.d_left = clipper->d_left > targetRect.d_left ? clipper->d_left : targetRect.d_left;
   finalRect.d_top = clipper->d_top > targetRect.d_top ? clipper->d_top : targetRect.d_top;
   finalRect.d_right = clipper->d_right < targetRect.d_right ? clipper->d_right : targetRect.d_right;
   finalRect.d_bottom = clipper->d_bottom < targetRect.d_bottom ? clipper->d_bottom : targetRect.d_bottom;

   if(finalRect.d_right <= finalRect.d_left || finalRect.d_bottom <= finalRect.d_top)
      return;
*/

    CEGUI::colour white(1.0f, 1.0f, 1.0f);
    CEGUI::Size pixelSize = CEGUI::Size(1,1);
    CEGUI::Rect finalRect(targetRect);
    finalRect.setWidth(targetRect.getHeight());
    finalRect.setHeight(targetRect.getHeight());

   CEGUI::Vertex vbuffer[6];

   // top-left
   vbuffer[0].position = CEGUI::Vector3(finalRect.d_left, finalRect.d_top, 0.0f);
   vbuffer[0].colour_val = white;
   vbuffer[0].tex_coords = CEGUI::Vector2(0.0f, 0.0f);
   // bottom-left
   vbuffer[1].position = CEGUI::Vector3(finalRect.d_left, finalRect.d_bottom, 0.0f);
   vbuffer[1].colour_val = white;
   vbuffer[1].tex_coords = CEGUI::Vector2(0.0f, pixelSize.d_height);
   // bottom-right
   vbuffer[2].position = CEGUI::Vector3(finalRect.d_right, finalRect.d_bottom, 0.0f);
   vbuffer[2].colour_val = white;
   vbuffer[2].tex_coords = CEGUI::Vector2(pixelSize.d_width, pixelSize.d_height);
   
   // top-right
   vbuffer[3].position = CEGUI::Vector3(finalRect.d_right, finalRect.d_top, 0.0f);
   vbuffer[3].colour_val = white;
   vbuffer[3].tex_coords = CEGUI::Vector2(pixelSize.d_width, 0.0f);
   // top-left
   vbuffer[4].position = CEGUI::Vector3(finalRect.d_left, finalRect.d_top, 0.0f);
   vbuffer[4].colour_val = white;
   vbuffer[4].tex_coords = CEGUI::Vector2(0.0f, 0.0f);
   // bottom-right
   vbuffer[5].position = CEGUI::Vector3(finalRect.d_right, finalRect.d_bottom, 0.0f);
   vbuffer[5].colour_val = white;
   vbuffer[5].tex_coords = CEGUI::Vector2(pixelSize.d_width, pixelSize.d_height);

   // give our vertices to the buffer for drawing
   buffer.setActiveTexture(mTexture);
   buffer.appendGeometry(vbuffer, 6);

   if (d_selected && d_selectBrush != 0)
      d_selectBrush->draw(buffer, targetRect, clipper, getModulateAlphaColourRect(d_selectCols, 0.5f));
}

Browser12
Not too shy to talk
Not too shy to talk
Posts: 42
Joined: Thu Jan 24, 2008 06:30
Location: UW-Madison
Contact:

Re: Subclassing ListboxItem (ListboxImageItem)

Postby Browser12 » Sun May 01, 2011 03:09

Ah, well you solved my problem. I owe you big time derm.
Set my texcoords to 0.0f / 1.0f instead of the width/height of the image... foolish mistake, but I'm just super happy it's solved.
If nothing else, this should serve as an example of how to fill out the ListboxItem's draw function-


Return to “Help”

Who is online

Users browsing this forum: No registered users and 10 guests