Help creating GUI Dialog Box Control

Started by
4 comments, last by TheMightyDude 15 years, 11 months ago
Hello All I have been trying to create a DirectX GUI Library for a couple of projects, and I am wondering, what is the best way to create a dialog box of X by Y size? I have tried a few different ways and all look rubbish, and the one that looks ok seems to be hogging the frame rate :( I have tried to do it how I think they do it in WoW. Engine_20080511_01.png I am using their images to see how they do it, but my code is very slooooow :( For me to create a dialog box with X and Y size I have done the following: Displayed the four corner images, then displayed the top, bottom, left and right sides, then fill in the whole dialog with a background tile of 32x32. This is all done in a double for loop (row, col). All images have alpha-layers. Basically the dialog box consists of multiple of 32x32 images, so a dialog box with X: 352, Y: 192 would be an 11 by 6 grid of images. The problem that I am having is the only way for me to create the dialog is within the Render () loop. I know this is a very bad idea, but I haven’t a clue on any other way of doing it. I would of used a pre-created 352 by 192 image in an art package if that would of worked, but DirectX wants the images in sizes of (2, 4, 8, 16, etc) which is no good :( I guess I could create an image that is 512x256 and have my image that is 352x192 in the middle of it and alpha out the unwanted image; however that would restrict me to have multiple large images for different types of dialog boxes. Has anyone played with this, and found a way around this? I am sure there is a better way to do this? Thanks in advance Paul Kirby
Advertisement
Are you using sprites to create the dialog? If not, that may be faster. Even within the Render-loop, displaying 66 sprites (11x6) shouldn't take much time at all.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Quote:Original post by Buckeye
Are you using sprites to create the dialog? If not, that may be faster. Even within the Render-loop, displaying 66 sprites (11x6) shouldn't take much time at all.


Thanks for the quick reply...
Yeah I am using Sprites:
HRESULT Result = m_Sprite->Draw(Texture->GetTexture(), Texture->GetRect(), NULL, NULL, 0xFFFFFFFF);And m_Sprite is of type LPD3DXSPRITE.


It's most proberbly me doing it...
bool CXDialog::OnRender(){    RECT rect;    int x_tiles            = (int)(this->GetWidth() / 32);    int y_tiles            = (int)(this->GetHeight() / 32);    int left_offset        = 11;    int right_offset       = 12;    int top_offset         = 12;    int botom_offset       = 11;    int new_loffset        = 7;    for (int y=0; y<=y_tiles; y++)    {        for (int x=0; x<=x_tiles; x++)        {            rect.left = 0; rect.right = 32; rect.top = 0; rect.bottom = 32;            if (x ==0)            {                rect.left = left_offset;                rect.right += left_offset;            }            else if(x == x_tiles)            {                rect.right = right_offset;            }            if (y ==0)            {                rect.top = top_offset;                rect.bottom += top_offset;            }            else if(y == y_tiles)            {                rect.bottom = botom_offset;            }            m_BGImage->SetRect(&rect);            m_BGImage->SetOffset(left_offset + (x*32)-new_loffset, top_offset + (y*32));            SetCanvas(m_BGImage);            this->RenderMe();            if(x>0 && x<x_tiles && y ==0)            {                m_TopImage->SetOffset(x*32-new_loffset, 0);                SetCanvas(m_TopImage);                this->RenderMe();            }            if(x>0 && x<x_tiles && y ==y_tiles)            {                m_BotImage->SetOffset(x*32-new_loffset, y_tiles*32);                SetCanvas(m_BotImage);                this->RenderMe();            }        }        if(y>0 && y<y_tiles)        {            m_LeftImage->SetOffset(0-new_loffset, y*32);            SetCanvas(m_LeftImage);            this->RenderMe();            m_RightImage->SetOffset(x_tiles*32-new_loffset, y*32);            SetCanvas(m_RightImage);            this->RenderMe();        }    }    m_TopLeftImage->SetOffset(0*32-new_loffset, 0*32);    SetCanvas(m_TopLeftImage);    this->RenderMe();    m_TopRightImage->SetOffset(x_tiles*32-new_loffset, 0*32);    SetCanvas(m_TopRightImage);    this->RenderMe();    m_BotLeftImage->SetOffset(0*32-new_loffset, y_tiles*32);    SetCanvas(m_BotLeftImage);    this->RenderMe();    m_BotRightImage->SetOffset(x_tiles*32-new_loffset, y_tiles*32);    SetCanvas(m_BotRightImage);    this->RenderMe();    int val = ((x_tiles * 32 / 2) - (256/2))+ (32 /2);    int val2 = 256/2;    int val3 = 256/2;    m_HeaderImage->SetOffset((((x_tiles * 32 / 2)-new_loffset) - (256/2))+ (32 /2), -12);    SetCanvas(m_HeaderImage);    this->RenderMe();    if(m_Caption)    {        D3DXVECTOR2 Abs;        Abs.x = 0;        Abs.y = 0;        GetAbsolutePosition(&Abs);        m_Caption->SetXYPos(0,0);        Abs.x += m_Caption->GetXPos();        Abs.y += m_Caption->GetYPos();        D3DXVECTOR2 k = m_Caption->GetCanvas()->GetOffset();        m_Caption->SetXYPos(Abs.x+val+71-new_loffset, Abs.y);        m_Caption->OnRender();    }    return true;}

Each type of control has its own OnRender() function which then calls the main render RenderMe()

HRESULT CXControl::RenderMe(void){    D3DXVECTOR2 ControlAbsolutePos;    HRESULT Result = E_FAIL;    ControlAbsolutePos.x = 0;    ControlAbsolutePos.y = 0;    this->GetAbsolutePosition(&ControlAbsolutePos);    ControlAbsolutePos.x += this->GetCanvas()->GetOffset().x;    ControlAbsolutePos.y += this->GetCanvas()->GetOffset().y;    this->GetCanvas()->SetTranslation(&ControlAbsolutePos);    Result = this->GetPen()->DrawTexture(this->GetCanvas());    this->GetCanvas()->SetTranslation(NULL);    return Result;}


Drawing the Texture:
HRESULT CXPen::DrawTexture(CXTexture* Texture){    if((Texture != NULL) && (m_Sprite != NULL))    {        D3DXMATRIX Mat;        D3DXMatrixTransformation2D(&Mat, NULL, 0, Texture->GetScaling(),                                    Texture->GetRotationCenter(), Texture->GetRotation(),                                    Texture->GetTranslation());        m_Sprite->Begin(D3DXSPRITE_ALPHABLEND);//      m_Sprite->Begin(0);        m_Sprite->SetTransform(&Mat);        HRESULT Result = m_Sprite->Draw(Texture->GetTexture(), Texture->GetRect(), NULL, NULL, 0xFFFFFFFF);        m_Sprite->End();        return Result;    }    else    {        return E_FAIL;    }}


It could be nothing but I got rather stressed out when I don't have this dialog displayed I get ~200 fps, when the dialog isn't added I get ~2000 ish (could be due to hardly anything to render) but if I display it I get ~100 fps however if I have say 2 dialogs being displayed it goes down to ~50-60 fps which to me is rather bad for just displaying 2 dialogs, I cant imagine what fps I will be getting when I add some 3d to it :(

As you can see by looking at the above code, its most proberbly done a rather crude way, but I have spent the last 12 to 18 so hours trying different ways of doing it and this was the best result.
You should be batching the sprite draw calls. Try to only call ID3DXSprite->Begin and End once per scene, not for every draw call.

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

Quote:Original post by Endurion
You should be batching the sprite draw calls. Try to only call ID3DXSprite->Begin and End once per scene, not for every draw call.


WoW that worked a treat :)

I couldn't do it at the start and end of the scene due to some controls wouldn't display, however...

I did add the Begin() and End() to the start of each controls OnRender Class, which really did the trick for me :)

I have added an extra 2 Dialogs to the Dialog and default plain window, which game me ~30 to 40 fps before the code update.
However with the code change with all these dialog boxes it is now ~170 fps :)

/me is very happy :)

The way I see it now is each Control that has an OnRender() function should have a Sprite Begin() and End() added to each end of it.

I know in normal cases you wouldn't do it like that, but where I am calling it loads of times like 66 times per dialog box that's 198 times when I have 3 dialog boxes, no wonder it slowed down :P

Anyway thanks for the quick and VERY helpful replay :)
Oh wow, just run it outside of M$ DirectX Debugger and i now get ~570 fps with 3 of my Dialogs :)

As I said in my last post, thanks for all the help :)

Now to add some more types of controls and windows, then to add my NetAPI to it :)

This topic is closed to new replies.

Advertisement