Main Menu
Menu

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.

Show posts Menu

Messages - texus

#126
0xEA8 is a rather low number. A read violation that close to 0x0 usually means that a function is being called on a nullptr object.

In e.g. your 'gui.get<tgui::Button>("USR_Button")->setText(User);' line, are you certain that "USR_Button" exists and is a Button type? Otherwise 'gui.get<tgui::Button>("USR_Button")' would be a nullptr.

If you run the code with a debugger it should tell you exactly where it crashes. If the location isn't in your own code, you should be able to show a call stack that will tell you exactly where it happened.
#127
The way draggable widgets work has now been changed. Containers are no longer draggable by default so widgets inheriting from SubwidgetContainer should now correctly receive mouseNoLongerOnWidget and mouseLeftWidget events.
#128
Help requests / Re: EditBox not editable
25 April 2023, 12:52:35
If you are using gui.mainLoop then it should just work (as it calls gui.handleEvent for all SDL events).

For a custom widget you will need to override textEntered (and probably also keyPressed to handle backspace).
#129
Help requests / Re: EditBox not editable
24 April 2023, 18:40:25
Are you passing the SDL_EVENT_TEXT_INPUT events to gui.handleEvent?
#130
General Discussion / Re: Signals Memory
20 April 2023, 14:13:48
In general, the rule is that you don't have to do anything. The signal and lambda function are automatically freed when the widget on which you are connecting is destroyed.

However, it is very easy to accidentally introduce a memory leak when capturing widgets in the lambda. When capturing a shared_ptr in the lambda by value (and Widget::Ptr objects are shared_ptr objects), the captured object won't be destroyed until the lambda itself is destroyed. So if the captured widget is the widget that owns the signal, or the parent of the widget, then there is circular dependency between the widgets and signals, so nothing will be destroyed and the widget leaks.

If you disconnect the signal manually, the circular dependency would be broken. Another method to prevent this issue is to simply never capture a shared_ptr by value, instead capture the raw pointer:
Code (cpp) Select
button->onPress([panel]{ /* panel->... */ }); // Memory leak if button is part of panel
button->onPress([p = panel.get()]{ /* p->... */ }); // No leaks
#131
General Discussion / Re: Localization
09 April 2023, 13:34:32
I'm not certain what you are asking, but I doubt that I can help as I do almost everything in English on my computer.

TGUI itself doesn't handle localization at all, it simply stores the characters in UTF-32.
#132
Help requests / Re: SVG scaling
05 April 2023, 19:39:59
It should be fixed now.
When "tgui::getBackend()->setFontScale(dpiScale)" is called, the SVG images will be internally rasterized to a higher resolution.
#133
Help requests / Re: SVG scaling
05 April 2023, 13:50:57
setScale will always lead to a blurry result, it simply stretches the output when rendering to the screen.

setSize will cause rasterization to be performed. If you don't change the view then it should result in a sharp image.

I'm assuming however that you are still calling setRelativeView on the gui as otherwise everything was rendered too small? The rasterization doesn't take that into account. So I might need to change the code to let rasterization also use the FontScale factor to compensate for the high DPI.
#134
If you run "sudo make install" (assuming you build it with Makefiles) then it will install it to /usr/local and cmake should find it automatically.

Otherwise you have to set the TGUI_DIR variable in your cmake project to the directory containing TGUIConfig.cmake (which is either the directory you built TGUI in or the lib/cmake/TGUI subdirectory at the location where you installed TGUI to).
#135
You can disconnect the signal like this:
Code (cpp) Select
unsigned int callbackId = menu->connectMenuItem(...);
menu->onMenuItemClick.disconnect(callbackId);

This is because the connectMenuItem is a simple wrapper function that connects to the onMenuItemClick and when a menu item is clicked it will check whether it needs to call your callback function or not based on whether the item name matched.

Alternatively, instead of using connectMenuItem to connect multiple callbacks and deal with disconnection, you could just use onMenuItemClick directy (which is triggered for any menu item click).
Code (cpp) Select
menu->onMenuItemClick([](const std::vector<String>& clickedMenuItem){
    if ((clickedMenuItem[0] == "File) && (clickedMenuItem[1] == "Load")) {
        ...
    }
    else if (...) {
       ...
    }
});
#136
QuoteTherefor what are the benefits to inherit from SubwidgetContainer instead of Group ?
The only benefit would be to not expose the container interface.
For example someone wrote a SpinControl widget which consists of an EditBox and a SpinButton. If SpinControl would inherit from Group, it would have functions such as "add" and "remove" (which you would never use). By inheriting from SubwidgetContainer, it doesn't have these functions.
#137
QuoteDo you plan to correct this behavior ? Or maybe forbid user to use the function with this class
I'm not sure how I can. The getAbsolutePosition call never actually reaches the SubwidgetContainer class (it ends in the m_container member which has no idea it is part of SubwidgetContainer), so I can't add code there to make an exception.

Widgets that are placed into the SubwidgetContainer aren't actually part of the gui, they are just part of your custom widget. While my first reaction was that the getAbsolutePosition might be buggy, the behavior is actually by design: the SubwidgetContainer really is the root of everything inside it. You should think of a SubwidgetContainer as a canvas on which you render: the widgets added to m_container are drawn to the canvas (without knowledge of the gui), and the canvas image is later drawn to the gui (without knowledge of how the image was created).

The only thing that I know I can do is better document this. While the current class description of "consist of subwidgets that act together as if they are a single widget" is accurate, it doesn't really mention any details about the consequences and side-effects of this design. The tutorial about custom widgets might also be improved to explain in which case you should or shouldn't use SubwidgetContainer.
#138
Does VehicleManager inherit from SubwidgetContainer?
If so then this is a bug and I will need to patch SubwidgetContainer.

Edit: this seems harder to fix than expected, I don't immediately see what I could change in SubwidgetContainer to make getAbsolutePosition work. What is the reason you need this function?

Edit 2: I think VehicleManager should inherit from Group instead of SubwidgetContainer (assuming this is what is happening). The SubwidgetContainer class exists so that you can create a widget that internally works like a container, but otherwise pretends to be a normal non-container widget to the rest of the gui. If VehicleManager should work like a container (which you seem to want with your getAbsolutePosition call), then you should probably inherit from a Container-based widget like Group.
#139
Ah ok, you aren't building TGUI yourself but you are using a library that was build with all backends included. In that case it won't be possible, as the TGUIConfig.cmake file will simply load all backends that existed when it was generated. The TGUI_BACKEND variable has no effect in your cmake script because it is only used while building TGUI.

The ubuntu package was build with SFML, SDL and GLFW and it indeed requires that libsfml-dev, libsdl2-dev, libsdl2-ttf-dev, libglfw3-dev and libfreetype-dev are installed on the system. It seems like my package is only listing the dependencies without the "-dev" postfix, which is why those weren't installed automatically. This is something that I will need to look into.

I don't really know what I can do to improve the situation. The ubuntu package was mostly provided for convenience, but I guess it might be even less useful than I though.

The only way right now to have a TGUI library that only contains the components that you need is to build it yourself with CMake.
#140
That should not be happening, it should only search for the selected backend.

If you don't specify TGUI_BACKEND, it will show an error on the first cmake run that no backend was selected, but will set to TGUI_BACKEND to SFML_GRAPHICS for the future. If you run the configure step again, it will thus search for SFML. The cmake script should never be searching for all backends unless you manually ask it to.

Can you clean your build directory, run cmake again and show its output?
#141
Help requests / Re: behavior on phone
25 March 2023, 18:58:46
Two finger scrolling should now work out of the box in the latest TGUI version!
#142
You currently will have to detect this yourself in your mouseMoved function (by checking if the mouse position lies outside the widget).

Draggable widgets (i.e. those that have "m_draggableWidget = true;" in their constructor, e.g. Slider or Scrollbar) will not receive mouseNoLongerOnWidget or mouseLeftWidget events when the mouse leaves with the button pressed. Instead they will continue to receive mouseMoved events until the mouse is released, even when the mouse is no longer on top of the widget.

Currently, containers (like SubwidgetContainer or Panel) are treated as if they are draggable widgets. This is why you don't receive mouseNoLongerOnWidget when you expect it.

Maybe this is something that should be changed. If I remember correctly then the reason for this is that a container could have a draggable widget inside it, so the mouse event is passed to the container just in case. If this really is the only reason, then a better design inside TGUI could be to check whether the leaf widget is draggable or not, and only pass mouse events to the container when that is the case.
#143
QuoteI thought that's sort of clipping to preserve draw computation when a widget is off screen, is that actually true ?
TGUI does indeed clip widgets that are outside the screen.

The clipping code was broken when rotation was applied. I've pushed a fixed version to github, so if you download the latest version again then the brace should stay visible.
#144
You should never inherit from 2 classes which both inherit from the Widget class.

ClickableWidget isn't that complex, you could in theory just copy its code in your custom widget if you really need it. Note that the main purpose of ClickableWidget is to provide a widget with the onClick signal, you don't actually need to inherit from it to support mouse events in your widget.

So you probably don't want to inherit from ClickableWidget and only inherit from SubwidgetContainer. Since SubwidgetContainer already forwards mouse events to the child widgets, the ClickableWidget implementation that consumes all mouse events itself wouldn't even be compatible anyway.

onPress will also be triggered when the button has focus and the user presses the space or return key on the keyboard, onClick will only be triggered as a result of a mouse click.
#145
Help requests / Re: Custom animation
16 March 2023, 19:43:46
Custom animations can't be provided, you will have to just implement the behavior in your own code (by keeping track of the elapsed time yourself and changing the widget properties at each timestep).

Combining existing animations might actually work: if you call showWithEffect (or hideWithEffect) twice (preferably with the same duration) but with a different type then both effects should take place simultaneously.

TGUI doesn't really have proper animation support, the showWithEffect and hideWithEffect functions only intended to provide bare minimum animation functionality.
#146
Help requests / Re: Picture with SVG
13 March 2023, 19:33:44
The nanosvg version has been updated.
#147
Help requests / Re: Picture with SVG
10 March 2023, 19:38:38
Are you calling setSize on the Picture?
Can you attach the svg file that you are trying to use?

Maybe it uses something that isn't supported (TGUI uses nanosvg which only supports simple SVGs and doesn't implement the entire SVG standard).
Can you try with loading the sample drawing.svg in the Picture (which is known to render correctly)?
#148
Help requests / Re: Sprite from SVG
07 March 2023, 22:11:54
The SvgImage class is used internally by the Texture class. You can simply pass a filename ending with ".svg" to the Texture class just like you would load e.g. a png file.
#149
Help requests / Re: behavior on phone
06 March 2023, 18:59:36
Doing it like that is indeed better. If you replace the leftMousePressed function in my previous post with the following then draggable widgets would be supported.
Code (cpp) Select
void leftMousePressed(tgui::Vector2f pos) override
{
    m_mouseDown = true;

    if (m_verticalScrollbar->isMouseOnWidget(pos - getPosition()))
        m_verticalScrollbar->leftMousePressed(pos - getPosition());
    else if (m_horizontalScrollbar->isMouseOnWidget(pos - getPosition()))
        m_horizontalScrollbar->leftMousePressed(pos - getPosition());
    else if (tgui::FloatRect{getPosition().x + getChildWidgetsOffset().x, getPosition().y + getChildWidgetsOffset().y, getInnerSize().x, getInnerSize().y}.contains(pos))
    {
        auto widgetBelowMouse = getWidgetBelowMouse(pos - getPosition() - getChildWidgetsOffset());
        if (widgetBelowMouse && widgetBelowMouse->isDraggableWidget())
            ScrollablePanel::leftMousePressed(pos);
        else
        {
            m_dragging = true;
            m_originalDragPos = pos;
            m_dragPos = pos;
        }
    }
}

When I find some time in the next few weeks I will investigate how much work it would be to get two-finger scrolling working. It would be a much better option if I can get it to work.
#150
Help requests / Re: behavior on phone
05 March 2023, 21:43:19
It can definitely be done.
I quickly implemented it myself to demonstrate it, but you will need to get the latest TGUI version as I had to make the scrollbars in ScrollablePanel protected instead of private in order to compile this code.
Code (cpp) Select
class CustomScrollablePanel : public tgui::ScrollablePanel
{
public:
    typedef std::shared_ptr<CustomScrollablePanel> Ptr;
    typedef std::shared_ptr<const CustomScrollablePanel> ConstPtr;

    CustomScrollablePanel(const char* typeName = "CustomScrollablePanel", bool initRenderer = true) :
        tgui::ScrollablePanel(typeName, initRenderer)
    {
    }

    void leftMousePressed(tgui::Vector2f pos) override
    {
        m_mouseDown = true;

        if (m_verticalScrollbar->isMouseOnWidget(pos - getPosition()))
            m_verticalScrollbar->leftMousePressed(pos - getPosition());
        else if (m_horizontalScrollbar->isMouseOnWidget(pos - getPosition()))
            m_horizontalScrollbar->leftMousePressed(pos - getPosition());
        else if (tgui::FloatRect{getPosition().x + getChildWidgetsOffset().x, getPosition().y + getChildWidgetsOffset().y, getInnerSize().x, getInnerSize().y}.contains(pos))
        {
            m_dragging = true;
            m_originalDragPos = pos;
            m_dragPos = pos;
        }
    }

    void leftMouseReleased(tgui::Vector2f pos) override
    {
        if (m_dragging)
        {
            m_dragging = false;

            if (std::abs(m_originalDragPos.x - pos.x) <= 2 && std::abs(m_originalDragPos.y - pos.y) <= 2)
            {
                if ((!m_verticalScrollbar->isMouseOnWidget(pos - getPosition()) && !m_horizontalScrollbar->isMouseOnWidget(pos - getPosition()))
                 && tgui::FloatRect{getPosition().x + getChildWidgetsOffset().x, getPosition().y + getChildWidgetsOffset().y, getInnerSize().x, getInnerSize().y}.contains(pos))
                {
                    ScrollablePanel::leftMousePressed({pos.x + static_cast<float>(m_horizontalScrollbar->getValue()),
                                                       pos.y + static_cast<float>(m_verticalScrollbar->getValue())});
                    ScrollablePanel::leftMouseReleased({pos.x + static_cast<float>(m_horizontalScrollbar->getValue()),
                                                        pos.y + static_cast<float>(m_verticalScrollbar->getValue())});
                }
            }

            return;
        }

        ScrollablePanel::leftMouseReleased(pos);
    }

    void mouseMoved(tgui::Vector2f pos) override
    {
        if (m_dragging)
        {
            const float delta = (pos.y - m_dragPos.y) / static_cast<float>(m_verticalScrollbar->getScrollAmount());
            m_verticalScrollbar->mouseWheelScrolled(delta, pos);
            m_dragPos = pos;
            return;
        }

        ScrollablePanel::mouseMoved(pos);
    }

    void leftMouseButtonNoLongerDown() override
    {
        m_dragging = false;
        ScrollablePanel::leftMouseButtonNoLongerDown();
    }

    static CustomScrollablePanel::Ptr create()
    {
        return std::make_shared<CustomScrollablePanel>();
    }

    static CustomScrollablePanel::Ptr copy(CustomScrollablePanel::ConstPtr widget)
    {
        if (widget)
            return std::static_pointer_cast<CustomScrollablePanel>(widget->clone());
        else
            return nullptr;
    }

protected:

    Widget::Ptr clone() const override
    {
        return std::make_shared<CustomScrollablePanel>(*this);
    }

private:
    bool m_dragging = false;
    tgui::Vector2f m_originalDragPos;
    tgui::Vector2f m_dragPos;
};

This method has noticeable downsides though. It breaks dragging in widgets, so you can't e.g. have a slider inside the panel. You also e.g. don't get a visual feedback on button presses: because the click happens instantly, you won't see the button go to down state. This actually caused me to believe the code wasn't working for a moment until I realized it and connected an onPress callback to properly test the button press.