Direct GUI Questions

Hi,

I need some help with getting the hang of the Direct GUI system.
I’m currently having trouble with trying to get some very basic functionality:

My artist created a background image and a button image (let’s assume for the moment he created only one state and only one button) for a main menu. He’s also created an image where the button is placed at a specific position in the background. This last image serves only as a helper for me to see how all parts should be fit together.
The background image is 1024x768, as we want to support the two resolutions 1024x768 and 800x600.

What I want to achieve is to replicate the layout as described by the artist in the last image.

I’m encountering several problems on the road, supposably all caused by not really understanding what’s the supposed workflow for creating GUIs and what are the concepts for positioning and scaling.

  1. I tried to use the on-screen editing-feature by enabling the corresponding variable in the config file. This works also, but when trying to resize the button, there seems to be no way to change only the x or only the y scale, it always keeps the proportions. This is unfortunate because:

  2. I put the two image files into an egg with

egg-texture-cards -o menu.egg background.tif button.tif

For some reason at least the button image is distorted when I actually load it onto the screen. Really it has proportions of about width:height = 7:1 while loaded on screen it has proportions suspiciously looking like 4:3.

  1. The code with which I am loading background and button right now is:
        self.menuTextures= loader.loadModel('gui/menu/menu.egg')
        self.background= DirectFrame(geom= self.menuTextures.find('**/Background'), 
                                    relief= None
                                    )
        self.btnRun= DirectButton(geom= self.menuTextures.find('**/MenuMainRun'), 
                                  relief= None
                                  )

I do not pass any scaling or positioning information because for scaling I was assuming it would just use the original scale of the images and for positioning I wanted to use the on-screen editing feature to position everything, then press a key upon which a saveLayout() function is called which just reads out all positions and writes to a file.

The funny thing, though, is that both button and background appear with the exact same dimensions on screen while in reality the background should fill the screen while the button should be comparatively small. (Currently I am running at 1024x768, so in “real” size; scaling down to 800x600 will be another issue in the future.)

  1. Now I have read some posts here on the forum about using
parent=render2d

in order to get an absolute coordinate system for positioning. There are several quibbles with that approach:

  • if I do that clicking on buttons doesn’t work anymore; if I use after the initial constructor call an additional
wrtReparentTo(aspect2d)

, then it works again, but resizing the window doesn’t resize the images anymore; this is not very dramatic as I probably don’t need to support resizing the window, anyway, but still a shame

  • with absolute coordinates I loose the ability to layout everything once and with that be done for both resolutions, 1024x768 and 800x600.
  1. Checking
aspect2d.getScale()

gives me (0.75, 1, 1). If on the other hand, I pass a scale parameter to the DirectButton and DirectFrame of (4.0/3.0, 1, 1), I get correct dimensions. So obviously the two factors 3/4=0.75 and 4/3=1.3 periodical are cancelling each other out. Now I thought, okay, if this is the way to get the correct proportions, why not just do a

aspect2d.setScaling(1, 1, 1)

before constructing the gui elements? Unfortunately, this has no effectat all. This is probably my inexperience with coordinate transformations, but I don’t understand two things:
a) What’s the point of aspect2d’s scale being setup like that to begin with?
b) Why does changing it have no visible effect on items parented to it?

Generally, I am somewhat at a loss on how to go on. If you could provide me with some insights, I’d be extremely grateful.

Many thanks in advance,

Max
Vienna, Austria

Hmm, I got a little further now with:

        self.background= DirectFrame(geom= self.menuTextures.find('**/Background'), 
                                    relief= None,
                                    scale= Application.__getScaleForFullScreen()
                                    )
        self.buttonTextures= loader.loadModel('gui/menu/buttons.egg')
        self.btnRun= DirectButton(geom= self.menuTextures.find('**/MenuMainRun'), 
                                  relief= None, 
                                  scale= Application.__getScaleAbsoluteProportionsToRelativeProportions(428, 64)
                                  )

with

    @staticmethod
    def __getScaleForFullScreen():
        return (8.0/3.0, 1, 2)
    
    @staticmethod
    def __getScaleAbsoluteProportionsToRelativeProportions(x, y):
        rx= 8.0*x/(3.0*1024.0)
        ry= 1.0
        rz= 2.0*y/768.0
        return (rx, ry, rz)

Now I get the correct proportions of everything, can move the stuff around and then save the positions. So this is at least viable. But I still would prefer not to quote the original dimensions of the button in code at all. Besides, it seeems somewhat unlikely to me that such a style of coding + workflow is what you guys had in mind when designing this. I think I’m still not using your GUI framework as it was planned to be used.
Could you clarify?

Many thanks,

Max
Vienna, Austria

Now, with the work-around from above, I hit another problem: when I want to make the button a child of the frame (which I want in order to be able to hide() the frame and everything inside is hidden, too), with

parent=self.background

, the proportions are again massively distorted.
What is the relationship between the parent’s scale and the child’s scale?

Thanks,
Max
Vienna,Austria

Okay, by adding:

    @staticmethod
    def __getScaleRelativeToFullScreen(x, y):
        rx= float(x)/1024.0
        ry= float(1)
        rz= float(y)/768.0
        return (rx, ry, rz)

and using this like:

        self.btnRun= DirectButton(geom= menuTextures.find('**/MenuMainRun'), 
                                  relief= None, 
                                  parent= self.background,
                                  scale= Application.__getScaleRelativeToFullScreen(428, 64),
                                  )

I’ve got the reparenting problem solved. The general Parent -> child scale relationship is now intuitively clear to me, although I could not write it down in formalized form right now.
But I still have the very uncomfortable feeling that I’m doing things way more complicated than they needed to be done and that the writers of Direct GUI had a completely different route in mind.

Ciao,
Max

Vienna, Austria

Hmm, yes. You are doing far too much work.

One point that you missed is that the default behavior of egg-texture-cards is to always generate the same size and shape card–a 1x1 card centered on the origin–regardless of the size of the texture. This card will be square when parented to aspect2d, and 4x3 when parented to render2d.

(By the way, aspect2d is the correct place to be parented all DirectGui elements. As you’ve discovered, they don’t work properly when you parent them to render2d.)

If you want egg-texture-cards to give you cards that are sized and shaped in proportion to your texture, then you should use the -p parameter. You can find out more about this by running egg-texture-cards -h, but in your case, since your textures are painted to fit a 1024x768 screen, you should use:

egg-texture-cards -p 384,384 -o menu.egg background.tif button.tif

The value 384 is half of the vertical height, 768. The reason that this is the correct value is because the default card is 1 unit high, but the screen is 2 units high (-1 to 1).

David