Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - texus

Pages: [1] 2 3 ... 95
1
Help requests / Re: how to use builder tool
« on: Yesterday at 23:16:03 »
This question comes up occasionally (which is understandable as it isn't documented). The gui builder itself isn't even in the documentation or tutorials so I wasn't sure where to document it, but I have decided to just add a line on the home page, as this is the only place where the gui builder is currently mentioned on the site.

2
Help requests / Re: Menubar overlap with layout.
« on: 21 August 2019, 23:06:50 »
The Group widget is the most basic container widget (a widget that can contain other widgets). Originally this was the Panel widget but it got split up in Group and Panel where the main difference between the two is that Group has no background color. Despite not calling setSize in my example, the group actually has a size and child widgets that would fall outside the group would be clipped.
The default size of the group is to fill the parent widget 100%, so the code that I gave actually makes the bottom part of the group fall outside of the window (as the group was positioned down a bit to start below the menu bar). This doesn't matter in this case, but if you want to rely on bottom padding then you might want to manually call setSize() on the group as well.

VerticalLayout and HorizontalLayout were contributed by someone who found them useful. They are definitely useful for positioning widgets next to each other or below each other, but I would personally only use them for simple cases like having a couple buttons below each other. The gui mostly relies on manually positioning and sizing widgets (either absolute or relative), but these layout widgets are an exception to this. These widgets try to resize and reposition the widgets that you put inside them automatically. This doesn't always perform ideally and some widgets may not work properly when placed inside a layout widget.

So if you need a container of widgets, which you are going to manually give a position, then use Group. It is useful for e.g. creating multiple screens in your program (with each screen being in a group and only one group shown), position a set of widgets relative to some point (like in your case), etc.
If you have a certain amount of space that you want to divide by a couple of widgets, then you can try to use a layout widget.

Quote
I tried set position only for layout without using group and this works too.
You can choose. You either add menuBar->getSize().y to the position of all widgets added to the gui or you create a new group widget that has this offset and add all widgets to that group. The outcome will be the same (as long as the group is large enough to fill the screen, which it is by default).

3
Help requests / Re: Menubar overlap with layout.
« on: 21 August 2019, 18:17:34 »
Simply add all widgets other than the menu bar to a group.

Create a group and position it below the menu bar:
auto group = tgui::Group::create();
group->setPosition(0, menuBar->getSize().y);
gui.add(group);

Remove the lines that add the widgets to the gui
gui.add(grid);
gui.add(topLayout);

And replace them with adding them to the group:
group->add(grid);
group->add(topLayout);

4
Feature requests / Re: DateTime Selector
« on: 19 August 2019, 17:54:25 »
It is a pretty complex widget. I'll add it to the todo list, but unless someone else implements it, it won't be added anywhere soon.

5
Help requests / Re: Best practice for rendering specific widgets
« on: 18 August 2019, 22:40:58 »
The Group::draw function is not supposed to be called directly. With the current design of the gui, you cannot draw widgets directly, all drawing has to happen via gui.draw().
What you are trying to do isn't supported, the gui always draws everything at once, the only solutions that I can provide are workarounds.

The code that you need looks more like this:
#include "TGUI/TGUI.hpp"

int main()
{
        sf::RenderWindow window(sf::VideoMode(800, 600), "Group Test");
        tgui::Gui gui(window);

        tgui::Button::Ptr button_1 = tgui::Button::create("Button 1");
        button_1->setPosition(5, 5);

        tgui::Button::Ptr button_2 = tgui::Button::create("Button 2");
        button_2->setPosition(5, 30);

        tgui::Group::Ptr group = tgui::Group::create();
        group->setSize(400, 300);
        group->add(button_1);
        gui.add(group);

        tgui::Group::Ptr group2 = tgui::Group::create();
        group2->add(button_2);
        gui.add(group2);

        while (window.isOpen())
        {
                sf::Event event;
                while (window.pollEvent(event))
                {
                        switch (event.type)
                        {
                        case sf::Event::Closed:
                                window.close();
                                break;
                        }

                        gui.handleEvent(event);
                }

                window.clear();
                       
                group->setVisible(true);
                group2->setVisible(false);
                gui.draw();

                // SFML rendering here will be between group and group2

                group->setVisible(false);
                group2->setVisible(true);
                gui.draw();
                       
                window.display();
        }
}

Alternatively, using a canvas:
#include "TGUI/TGUI.hpp"

int main()
{
        sf::RenderWindow window(sf::VideoMode(800, 600), "Group Test");
        tgui::Gui gui(window);

        tgui::Button::Ptr button_1 = tgui::Button::create("Button 1");
        button_1->setPosition(5, 5);

        tgui::Button::Ptr button_2 = tgui::Button::create("Button 2");
        button_2->setPosition(5, 30);

        tgui::Group::Ptr group = tgui::Group::create();
        group->setSize(400, 300);
        group->add(button_1);
        gui.add(group);

        // Warning: the default canvas size is (100%,100%) to fill the screen which can cause performance overhead when changing the gui view.
        // Set a static size (by passing size to create function or calling setSize) if you don't want it to resize itself when resizing the gui.
        tgui::Canvas canvas = tgui::Canvas::create();
        gui.add(canvas);

        tgui::Group::Ptr group2 = tgui::Group::create();
        group2->add(button_2);
        gui.add(group2);

        while (window.isOpen())
        {
                sf::Event event;
                while (window.pollEvent(event))
                {
                        switch (event.type)
                        {
                        case sf::Event::Closed:
                                window.close();
                                break;
                        }

                        gui.handleEvent(event);
                }

                // This clear/draw/display code can be called anywhere, if the contents is static you could even do it before the main loop
                canvas->clear(sf::Color::Transparent);
                // SFML rendering here will be between group and group2
                canvas->display();

                window.clear();
                gui.draw();
                window.display();
        }
}

6
Help requests / Re: Best practice for rendering specific widgets
« on: 18 August 2019, 20:19:35 »
Quote
What I am trying to render is a tgui::Picture
I'm a bit confused now. You said you wanted to render SFML inbetween the widgets (which is what the Canvas is for)? Why would drawing a tgui::Picture be a problem, it can be placed between any widgets already?

If you want to have states and show different widgets in different states (e.g. different screens), then you should just put the widgets of each screen in a tgui::Group and hide all groups except for the one you want the show. Then when changing screen, you hide the currently shown group and show a different one.

If within one screen you need to draw SFML inbetween TGUI then you either render the SFML on a Canvas and have that canvas drawn within the other widgets, or you do something like billarhos suggested: create 2 tgui::Group widgets, show the first and call gui.draw() then show the second one and call gui.draw() again. You must have access to the group in your drawing code because in your simplified example code you also had some parameter to pass to gui.draw.

7
Help requests / Re: Best practice for rendering specific widgets
« on: 18 August 2019, 17:51:45 »
I never though of that option, but that would work too.

8
Help requests / Re: Best practice for rendering specific widgets
« on: 18 August 2019, 09:13:49 »
Two simultaneous gui objects is definitely a bad idea as you could get 2 focused widgets and in case of overlapping widgets both guis may believe that the mouse is on their widget.
Rendering only some of the widgets is also not possible.

The only option you really have to mix tgui and sfml rendering is to use the Canvas widget. The canvas is a wrapper around sf::RenderTarget, so you have to clear() it then draw and then call display() on it. When calling gui.draw(), the sfml rendering you did on the canvas will be displayed inbetween the tgui widgets, depending on which widgets are in front and behind the canvas.

9
My explanation is wrong for this case. I had a better look at the code and it should only have clipped if you have more than 1 menu item. The first menu item still falls within the vertical layout and could thus still be visible. The reason why it isn't visible is because the button is drawn in front of the menu bar. Try adding the following at the end:
menuBar->moveToFront();

In the future I will likely make menus work like the list of a combo box and always bring it to the front when opened, but for now the menus are part of the MenuBar widget itself and they thus have the same z-value.

10
It could be considered a bug, but the layouts simply weren't designed for something like this. Layout widgets such as VerticalLayout are just container widget, so they will clip everything outside their size. The size of a menu bar is only the size of the bar itself, so all of the menus fall outside of the visible area of the container and are thus clipped.

You simply can't have a menu bar in a vertical layout. The only reason that I can think of where it is useful to put it in a VerticalLayout is if you want to have a panel underneath it that fills the rest of the screen so that all widgets inside that panel can have a top position relative to the bottom of the menu bar. In that case you will just have to manually give that panel a position and size (which might actually be easier because you can use an absolute size for the menu bar height instead of a ratio).

11
Actually the Slider2d widget no longer exists. In 0.7 it seems like it was still in an extra folder (together with AnimatedPicture and SpriteSheet), but these 3 "widgets" were removed in 0.8. They didn't fully fit in a gui library and I decided that I wasn't going to keep maintaining them (since every version update required rewriting a lot of code in all widgets).

It wouldn't really solve the issue with detecting where the mouse is. The Slider2d class just acted as one big rectangle and would absorb all mouse events in that area, even if your diagonal slider would only fill a small part of that area. The changes required to Slider2d are so large that you might as well just create a new widget for it

If anyone comes up with the necessary code to make rotation work then I would of course merge it, but I have no intention of writing it myself on short term.

12
The problem isn't going beyond 45°, any angle that can't be divided by 90 is problematic. If an object has to be rotated, around what point should the rotation take place?
Imagine you have a slider of 400 pixels width and 20 pixels height. The slider is places on position (100, 100).
- If you rotate 90° clockwise around the top-left corner then the new top-left position will be at (80, 100).
- If you rotate around the center of the widget, a rotation of 90° will put the top left of the slider on position (290, -100).

What I do in TGUI is correct the offset and move it back to position (100, 100). In the first case (which is what TGUI uses), I simply add 20 pixels to the left position of the slider before the rotation even happens. After the rotation the slider will end up rotated 90° and at position (100,100), which is what the user asked for.

But what happens if you rotate by 45° (or even just 1°), what is the top left position then? I could take a bounding box around the entire widget, but that box would change size for every degree you rotate, so the result will be that the slider position is unpredictable and you have to experiment a bit to find the best position for the slider.

The only way that I see to properly support it, is if I let the user set the position of the center of the widget instead of the top left position. That way you could rotate around any angle and the center would remain on the same spot, hence the result of where the slider will end up would be is predictable.

Another problem is going to be detecting when the mouse is on top of the widget. Right now there are only a handful of widgets that can be rotated and the 90° rotation makes it easy to check the mouse position. If a widget can be freely rotated around any angle, checking when the mouse is on top of the widget (and on which part) gets more difficult.

So although the feature would be nice to have, I currently have no plans to add something like that in TGUI as it involves a lot of work.

13
Help requests / Re: Converting TGUI 0.6 project to TGUI 0.8.5
« on: 11 August 2019, 09:55:18 »
You would basically just have to read the 0.8 tutorials and relearn how widgets are created now and rewrite the code that deals with the gui.
If you don't want to rewrite your code then you will have to stick with 0.6, there have been 4 active years between those two version so a lot has changed (with most of the changes between 0.6 and 0.7).

Looking at the code you basically need the following changes:

Lines like
tgui::Checkbox::Ptr syncbox(gui);
basically have to be changed to
tgui::Checkbox::Ptr syncbox = tgui::Checkbox::create();  // You could use "auto" as type here, to not write "Checkbox" twice
gui.add(syncbox);

In 0.6 I think you still had to have a theme to render something, since 0.7 there actually is a default White theme that gets used if you don't set any theme. I'll just assume you want to keep using the Black theme. You will have to change THEME_CONFIG_FILE to "data/themes/Black.txt" as that is where the new Black theme would be located.

For the Black theme you will have to create a Theme object somewhere. Assuming you only use a single theme you can set it as a default as well. The "theme" object has to remain alive, if the variable is destructed (e.g. when it goes out of scope) then the built-in White theme will automatically be used again.
tgui::Theme theme{THEME_CONFIG_FILE};
tgui::Theme::setDefault(&theme);
If you have a default theme that you want to use then you can just remove lines like
syncbox->load(THEME_CONFIG_FILE);
If you don't have a default theme, then you need to replace the lines with something like
syncbox->setRenderer(theme.getRenderer("CheckBox"));

The biggest difference is probably going to be the callback code. TGUI 0.6 queued callbacks and let you get them later with pollCallback. (This code is so old that I had already forgotten that it used to work like that). Since TGUI 0.7 the callbacks are like interrupts, your callback function will be called immediately. You should definitely read the signal tutorial.
How you need to change the code depends on the structure of your code. If your code is really all in one big main function, then you should actually be able to port it without too much changes.
knob1->bindCallback(tgui::Knob::ValueChanged);
knob1->setCallbackId(Knob_CALLBACK_ID + 1);
and
case Knob_CALLBACK_ID + 1:
{
        [...]
        break;
}
would become
knob1->connect("ValueChanged", [&]{
    [...]
});

Those are just the differences that I saw when scrolling to the code. It is possible that there are other differences, but the biggest changes happened in the way widgets are created and their events. The functions of the widgets themselves (e.g. setPosition, addItem, setSelectedItem, etc.) will mostly be compatible.

14
The MenuBar widget is a bit more complicated than most widgets. I would somehow need to provide an interface to set the menus and their items. I would also need to serialize the menus (including potential submenus) into a single string, preferable without newlines.

The serialization problem could easily be solved if I just use the same format that I currently use for saving a MenuBar to a text file and just replace the newlines with spaces, although maybe there are better alternatives.
The thing that will take more work is providing a form where you can change the properties without having the manually type in the serialized string by hand. The thing I have in mind is something similar to how items of a ListBox are set, but with a TreeView to display the menus. The ability to enable and disable any item complicates this a bit more.

I recently added ChatBox and TreeView widgets to the gui builder, but only because they could be added without a way to set their items at design time. For a menu bar, being able to set the menus at design time is more important so I really do need to provide a way to input the menus. Unfortunately I currently don't have the motivation to actually implement it, I haven't been able to get myself to work on any non-trivial features in TGUI lately.

15
Quote
The option is missing.
You actually just have to set the Height to a larger value than the Width. I'll put on my todo list that I should add a property for it in the gui builder to make it more intuitive, because someone else recently had the same problem with a Slider and I agree that it isn't obvious at all.

Quote
Also; If possible, it would be nice if we could set the angles of scrollbars, sliders, etc.
When rotating over an angle other than 90° there is no more obvious definition about where the top left position actually is. There are multiple ways the scrollbar could be positioned after e.g. a 45° turn. I've never seen diagonal scrollbar, is there a use case that you have in mind where you would need to rotate it over such a non-standard angle?

Pages: [1] 2 3 ... 95