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 - Nafffen

#26
Hello,
I want to create a custom widget to make navigation easier for big picture.
I first think about a widget that has two scrollbars and draw simply a sprite the user can shrink or expand with mouseScroll.
I have trouble with clipping in draw function. I helped myself with your Label.cpp
bool NavPicture::mouseWheelScrolled(float delta, tgui::Vector2f pos){
    m_sprite.setSize(m_sprite.getSize()+delta*m_sprite.getSize()/20.f);

    m_scrollbar->setSize(16, static_cast<unsigned int>(getSize().y));
    m_scrollbar->setViewportSize(static_cast<unsigned int>(getSize().y));
    m_scrollbar->setMaximum(static_cast<unsigned int>(m_sprite.getSize().y));
    m_scrollbar->setPosition({getSize().x - m_scrollbar->getSize().x, 0});
    m_scrollbar->setScrollAmount(2.f);

    return true;
}

void NavPicture::draw(tgui::BackendRenderTarget& target, tgui::RenderStates states) const
{
    const tgui::RenderStates statesForScrollbar = states;

    // Draw the scrollbar
    if (m_scrollbar->isVisible())
        m_scrollbar->draw(target, statesForScrollbar);

    target.drawBorders(states, {1}, getSize(), tgui::Color::Black);

    target.addClippingLayer(states, {getPosition().x, getPosition().y, getSize().x, getSize().y});

    if (m_scrollbar->isShown())
        states.transform.translate({0, -static_cast<float>(m_scrollbar->getValue())});

    target.drawSprite(states, m_sprite);

    target.removeClippingLayer();
}
With that code, the sprite behavior is very weird, I can't see it in the clipping region but when I zoom in a lot, it appears far from the clipping region, even over the widget size, where I dont want.
When I remove the clipping option "addClippingLayer", the sprite appears well but when I zoom in to much, it is taller than the widget size of course.
Did I miss something with clipping's behavior ?
#27
QuoteWidgets 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).
Oh ok I understand it better now !
Therefor what are the benefits to inherit from SubwidgetContainer instead of Group ?
#28
QuoteDoes VehicleManager inherit from SubwidgetContainer?
Yes, sry I should have included that in the first post

I inherit now from Group and it works as wanted. I needed to call getAbsolutePosition to add a widget in a branch of the widget tree in the same global pos as another widget in another branch of the widget tree

Do you plan to correct this behavior ? Or maybe forbid user to use the function with this class

Thank you !
#29
I'm having trouble with getAbsolutePosition() which returns a value I don't expect
My tree widget is something like:
Gui
|-->group1
       |-->VehicleManager (custom widget)
              |-->Group (= "panels")
I use panels->getAbsolutePosition() but it returns the pos in the VehicleManager reference, not in screen reference.

Capture.PNG

I used gui-builder to load the group (can it be the source of the problem ?):
    auto panels = tgui::Group::create();
    panels->setPosition(0, tgui::bindBottom(btnWarehouse)+m_spaceY);
    panels->setSize("100%", "100%"-tgui::bindHeight(btnWarehouse)-m_spaceY*2);
    panels->loadWidgetsFromFile("data/forms/vehicleManager.fc");

    m_container->add(panels,"panels");

data/forms/vehicleManager.fc only contains two scrollable panels

Did I missunderstand something ?
#30
Ok thank you for the tips

What is the function to override if I want to do stuff when mouse leave widget but with left click pressed ?
I tried mouseNoLongerOnWidget and mouseLeftWidget but no one worked with left click pressed
#31
Thank you very much !
#32
Help requests / Custom button and container
16 March 2023, 18:16:02
I want to make a custom widget that is a clickable widget and contains other widgets.
Is this ok to inherits from ClickableWidget AND SubwidgetContainer ?
Is there a better way ?

Also, what is the difference between onClick of ClickableWidget and onPress of Button class ?
#33
Help requests / Custom animation
16 March 2023, 18:10:56
Is there a tutorial somewhere to make custom animation ? Is this even possible ?
For example an animation that combines fade in from transparent and pos sliding ?
Or a more complex one ?
#34
Help requests / Wrong clipping with rotation ?
16 March 2023, 09:22:30
I use a custom widget to handle a "brace".
I draw the box and states pos of widget with the following in draw method:
target.drawBorders(states, tgui::Borders(1), getSize(), tgui::Color::Red);
target.drawCircle(states, 5, tgui::Color::Green);
displayed.PNG
The origin of widget is the middle (0.5, 0.5). I need to rotate it some times, and when I rotate it to the right with
m_embrace->setRotation(270.f);, we can see the green dot is downward, but when I move a little bit and the green dot goes below screen size Y, the whole widget isnt drawn anymore.
notDisplayed.PNG
I thought that's sort of clipping to preserve draw computation when a widget is off screen, is that actually true ?
How can I handle my issue ?
#35
Help requests / Re: behavior on phone
06 March 2023, 13:10:12
Ok thank you once again ! Very interesting
QuoteThis method has noticeable downsides though. It breaks dragging in widgets, so you can't e.g. have a slider inside the panel.
Is there a way to have no problem with dragging widgets ?
If a reuse the behavior I wanted to handle dragging widgets it would be:
When first press a finger on the scrollPanel, nothing append (even if finger is on a child widget)
If finger is moved:
   If the child widget under the mouse is not a dragging widget, the panel scrolls
   Else the event is spread through the dragging widget
Else if finger is released, the "click" is spread through child widgets
It is not very clear sorry
#36
Help requests / Re: behavior on phone
05 March 2023, 18:08:52
Ok thank you very much for this information ! Very useful to know.

QuoteUsing only one finger to drag the panel could probably be implemented relatively easily, but it wouldn't work when the finger goes down on top of a widget inside the panel (e.g. press and drag in edit box would start selecting text instead of scrolling the panel).
I want a behavior like this:
When first press a finger on the scrollPanel, nothing append (even if finger is on a child widget)
If finger is moved, the panel scrolls
Else if finger is released, the "click" is spread through child widgets

Can I achieve that more or less easily with a custom widget inherited by tgui::ScrollPanel ?
#37
Help requests / behavior on phone
05 March 2023, 13:58:08
I noticed on home page that TGUI is ok with Android/IOS (I'm with SFML backend so I didnt have a doubt about that). I haven't tested yet, before so, I have some questions to help me organize myself:
- Do TGUI have differents behavior with some events, due the usage of fingers ? For example onHover event
- How scrolling is handled ? Do we need to pinch two fingers or there is something else ?
- With scrollPanel, can we drag finger anywhere on the panel to move it or do we must drag only the bar ? If only the bar, what is the best way to have the first behavior ?
Thank you
#38
Help requests / Re: SpriteSheet in v1.0
04 March 2023, 15:30:26
Thank you I managed to have what I wanted with your advices
#39
Help requests / SpriteSheet in v1.0
04 March 2023, 09:59:42
I wanted to use SpriteSheet class,
I found that there was a class here:
https://tgui.eu/documentation/v0.6/classtgui_1_1SpriteSheet.html
But I can't find a similarity in v1.0.
Therefore, I wanted to implement it myself with a custom widget.
To set the visible part of the sprite I use this function:
m_sprite.setVisibleRect(tgui::FloatRect(m_indexSpriteSheet % m_tileSizeSheet.x * m_sizeOneSprite.x, m_indexSpriteSheet / m_tileSizeSheet.x * m_sizeOneSprite.y, m_sizeOneSprite.x, m_sizeOneSprite.y));However, I can't find in the doc if the value for FloatRect object are in pixel or in range [0,1] ?
In both case, I can't get the sprite to have expected behavior although values seem correct with cout
I don't understand, does it refer to texture size or sprite size ?
For example with a sprite [100,100] and a texture [2000,2000]. If a want to draw the part [0,0,50,50] of texture on sprite, how do I do ?
Thank you
#40
Help requests / Re: ToolTip on click
18 February 2023, 11:52:46
Thank you for theses advices, this is what I did for people who wants:
#pragma once

template <typename T>
concept DerivedFromWidget = std::derived_from<T, tgui::Widget>;

template<DerivedFromWidget T>
class BubblableWidget: public T{
public:
    // Add a Ptr typedef so that "MyCustomWidget::Ptr" has the correct type
    typedef std::shared_ptr<BubblableWidget<T>> Ptr;
    typedef std::shared_ptr<const BubblableWidget<T>> ConstPtr;

    BubblableWidget(): T(){
        T::m_draggableWidget = true;
    }

    // Every widget needs a static create function which creates the widget and returns a smart pointer to it.
    // This function can have any parameters you want.
    static BubblableWidget::Ptr create()
    {
        return std::make_shared<BubblableWidget>();
    }

    // Every widget has a static method to copy it
    static BubblableWidget::Ptr copy(BubblableWidget::ConstPtr widget)
    {
        if (widget)
            return std::static_pointer_cast<BubblableWidget>(widget->clone());
        else
            return nullptr;
    }


    void setBubble(tgui::Container::Ptr parent, tgui::Widget::Ptr widget){
        m_parent = parent;
        m_bubble = widget;
    }

    void bindPosBubbleWith(tgui::Widget::Ptr widgetBindedPos){
        m_widgetBindedPos = widgetBindedPos;
    }

    void leftMousePressed(tgui::Vector2f pos) override{
        T::leftMousePressed(pos);
        // std::cout << "BubblableWidget::leftMousePressed" << std::endl;
        m_bubble->setPosition(m_widgetBindedPos->getAbsolutePosition());
        // std::cout << "pos: " << m_widgetBindedPos->getAbsolutePosition() << std::endl;
        m_parent->add(m_bubble);
    }

    void leftMouseButtonNoLongerDown() override{
        T::leftMouseButtonNoLongerDown();
        T::setToolTip(nullptr);
        // std::cout << "BubblableWidget::leftMouseButtonNoLongerDown " << std::endl;
        m_parent->remove(m_bubble);
    }

    // void mouseMoved(tgui::Vector2f pos) override{
    //     T::mouseMoved(pos);
    //     if(T::m_mouseDown){
    //         std::cout << "BubblableWidget::mouseMoved under" << std::endl;
    //     }
    // }

protected:

    // Every widget needs a method to copy it
    tgui::Widget::Ptr clone() const override
    {
        return std::make_shared<BubblableWidget>(*this);
    }

private:
    tgui::Container::Ptr m_parent;
    tgui::Widget::Ptr m_bubble;
    tgui::Widget::Ptr m_widgetBindedPos;
};

How to use:
auto picture = BubblableWidget<tgui::Picture>::create();
//another widget for the bubble (ItemContainerWidget is mine)
auto itemContainer = ItemContainerWidget::create(ItemContainerWidget::AlignmentSide::ADJUST,
                                                      3,
                                                      ItemContainerWidget::SelectionMode::NONE,
                                                      {ItemStack(ItemTypeEnum::COAL, 2),
                                                       ItemStack(ItemTypeEnum::IRON, 5)});
itemContainer->setOrigin(1.f,0.5f);
itemContainer->setSize("20%","20%");
picture->bindPosBubbleWith(picture);
picture->setBubble(bubbleGroup, itemContainer);

When clicking on the picture, the bubble will appear on the pos of the widget passed to bindPosBubbleWith(), with origin computation.
We need to pass the parent in which we want the bubble to be in setBubble to deal with different pos reference (in my case, I wanted to draw the bubbles in a screen sized group, not the one in which the picture is).
The bubble will not move like a tool tip with mouse pos but it is ok for me.
#41
Help requests / ToolTip on click
14 February 2023, 15:21:54
Hello,
I want to make a custom widget able to show a tool tip only when the mouse click is pressed under it.

What I tried:
template <typename T>
concept DerivedFromWidget = std::derived_from<T, tgui::Widget>;

template<DerivedFromWidget T>
class BubblableWidget: public T{
public:
    BubblableWidget(): T(){}

    void setBubble(tgui::Widget::Ptr widget){
        m_bubble = widget;
    }

    void leftMousePressed(tgui::Vector2f pos) override{
        T::leftMousePressed(pos);
        T::setToolTip(m_bubble);
        std::cout << "BubblableWidget::leftMousePressed" << std::endl;
    }

    void leftMouseButtonNoLongerDown() override{
        T::leftMouseButtonNoLongerDown();
        T::setToolTip(nullptr);
        std::cout << "BubblableWidget::leftMouseButtonNoLongerDown " << std::endl;
        std::cout << m_bubble << std::endl;
    }

private:
    tgui::Widget::Ptr m_bubble;
};

In the above code, I removed Ptr,create,clone to make it easier to read

Then user side:
    auto test = BubblableWidget<tgui::Label>::create();
    test->setAutoSize(true);
    test->setText("Test");

    auto testBubble = tgui::Label::create("Test2");
    testBubble->setAutoSize(true);
    test->setBubble(testBubble);

When I click on the "Test" label, I can see "BubblableWidget::leftMousePressed" as expected, same for "BubblableWidget::leftMouseButtonNoLongerDown". However, the tool tip does not appear.

I was wondering if setToolTip can't be called in those override functions? Why the tool tip isnt drawn ?
How can I manage my wanted behavior ?

Thank you
#42
It works perfectly
Thank you very much !
#43
Quote1) ... If the scrollbar is already at the tip, and the user then moves its mouse on top of the panel and starts scrolling, is it really an issue if it zooms your view?
Yes I don't want this behavior

Quote2) ... But it would also absorb scroll events when the mouse is e.g. on top of a button or a non-scrollable panel.
In my case it will not be a problem but I understand it can be for other users
#44
Thank you for the clarification, I understand why this is not the first behavior anymore.

In my case, the scroll event passed to the parent is actually not consumed by any widget, it is my game event handler which comsumes it, so when the scroll bar comes to the tip, my game is zooming or dezooming the view, and I absolutely don't want this behavior. Then I think I would be happy with the old first behavior, as I would not deal with the main drawback you mentioned (because I don't have two nested scroll bars).

I understand this is not the best behavior for all of us, the flag to allow us to choose is a good idea in my opinion

Thank you again for your work on TGUI
#45
Hello,

What is the best way to have a scrollPanel not dispatch the scroll event to parent when the scrollbar is at the tip ? Did I even understand well the behavior ?
Is making a custom widget subclass of scrollPanel a good idea ? with mouseWheelScrolled override

Thank you
#46
QuoteI will investigate this further and try to figure out where the crash is coming from tomorrow. Thanks for providing the simple code example that allowed me to quickly reproduce the issue.
I am happy to be useful, thank you to be so much active in TGUI !

QuoteIf you make your window too small, the size becomes negative (because the scrollable window height is less than the scrollbar height). In this case you call text.setCharacterSize with a negative number, which becomes a very large number because the character size is unsigned. This causes TGUI to crash while loading the font glyph to figure out the size of the text.
Nice point, I think my window will have a minimum size but it's important to be aware of that.
#47
there it is, the reproductible crash in one file
#include <TGUI/TGUI.hpp>
#include <TGUI/Backend/SFML-Graphics.hpp>

#include <iostream>
#include <cmath>

using namespace std;

struct ItemStack{
    tgui::Texture texture = tgui::Texture("iron.png");
    int nb = 1;
};


class ItemContainerWidget : public tgui::Widget
{
public:
    enum AlignmentSide{
        HORIZONTAL,
        VERTICAL
    };

    // Add a Ptr typedef so that "MyCustomWidget::Ptr" has the correct type
    typedef std::shared_ptr<ItemContainerWidget> Ptr;
    typedef std::shared_ptr<const ItemContainerWidget> ConstPtr;

    // Add functions that are explained in "Basic functionality" section

    // The constructor should create the subwidgets and add them to the internal container
    ItemContainerWidget(AlignmentSide alignmentSide, unsigned nbItemPerAlignmentSide, const std::vector<ItemStack> &listIS, const char* typeName = "ItemContainerWidget", bool initRenderer = true):
    tgui::Widget(typeName, true),
    m_alignmentSide(alignmentSide),
    m_nbItemPerAlignmentSide(nbItemPerAlignmentSide)
    {
        for(const auto &is : listIS){
            addItem(is);
        }
        updateSize();
    }

    void addItem(const ItemStack &is){
        itemStruct item;

        item.is = is;

        item.sprite.setTexture(is.texture);
        item.text.setString(std::to_string(is.nb));
        //TODO override setOpacity to handle change of color
        item.text.setFont(m_fontCached);
        item.text.setColor(tgui::Color::applyOpacity(tgui::Color::White, m_opacityCached));
        item.text.setOutlineColor(tgui::Color::applyOpacity(tgui::Color::Black, m_opacityCached));

        item.selected = false;

        m_listItem.push_back(item);
    }

    // Every widget needs a static create function which creates the widget and returns a smart pointer to it.
    // This function can have any parameters you want.
    static ItemContainerWidget::Ptr create(AlignmentSide alignmentSide, unsigned nbItemPerAlignmentSide, const std::vector<ItemStack> &listIS)
    {
        return std::make_shared<ItemContainerWidget>(alignmentSide, nbItemPerAlignmentSide, listIS);
    }

    // Every widget has a static method to copy it
    static ItemContainerWidget::Ptr copy(ItemContainerWidget::ConstPtr widget)
    {
        if (widget)
            return std::static_pointer_cast<ItemContainerWidget>(widget->clone());
        else
            return nullptr;
    }

    void setSize(const tgui::Layout2d& size){
        // cout << "before" << endl;
        // cout << "size.getValue(): " << size.getValue() << endl;

        if(m_alignmentSide == AlignmentSide::HORIZONTAL){
            m_sizeItemRect = size.getValue().x/m_nbItemPerAlignmentSide;
        }else if(m_alignmentSide == AlignmentSide::VERTICAL){
            m_sizeItemRect = size.getValue().y/m_nbItemPerAlignmentSide;
        }
        // cout << "m_sizeItemRect: " << m_sizeItemRect << endl;

        unsigned nbItemPerNonAlignmentSide = std::ceil(m_listItem.size()/(float)m_nbItemPerAlignmentSide);
        // cout << "nbItemPerNonAlignmentSide: " << nbItemPerNonAlignmentSide << endl;

        //update size accordingly to m_nbItemPerAlignmentSide
        tgui::Layout2d newSize = size;
        if(m_alignmentSide == AlignmentSide::HORIZONTAL){
            newSize.y = nbItemPerNonAlignmentSide*m_sizeItemRect;
        }else if(m_alignmentSide == AlignmentSide::VERTICAL){
            newSize.x = nbItemPerNonAlignmentSide*m_sizeItemRect;
        }
        // cout << "newSize: " << newSize.toString() << endl;
        Widget::setSize(newSize);
       
        updateSize();
    }

    void updateSize(){
        // cout << "m_size: " << m_size.toString() << endl;
        // cout << "m_size.getValue(): " << m_size.getValue() << endl;
       
        m_borders = tgui::Borders{m_sizeItemRect/20};
        auto sizeInsideBorder = tgui::Vector2f{m_sizeItemRect - m_borders.getLeft() - m_borders.getRight(), m_sizeItemRect - m_borders.getTop() - m_borders.getBottom()};

        for(unsigned i=0;i<m_listItem.size();i++){
            m_listItem[i].sprite.setSize(sizeInsideBorder);
            m_listItem[i].text.setCharacterSize(m_sizeItemRect/4);
            m_listItem[i].text.setOutlineThickness(1+m_listItem[i].text.getCharacterSize()/25);
           
            if(m_alignmentSide == AlignmentSide::HORIZONTAL){
                m_listItem[i].sprite.setPosition(tgui::Vector2f{(i%m_nbItemPerAlignmentSide)*m_sizeItemRect, (i/m_nbItemPerAlignmentSide)*m_sizeItemRect}+m_borders.getOffset());
                m_listItem[i].text.setPosition(tgui::Vector2f{(i%m_nbItemPerAlignmentSide)*m_sizeItemRect, (i/m_nbItemPerAlignmentSide)*m_sizeItemRect}+m_borders.getOffset()+sizeInsideBorder-m_listItem[i].text.getSize());
            }else if(m_alignmentSide == AlignmentSide::VERTICAL){
                m_listItem[i].sprite.setPosition(tgui::Vector2f{(i/m_nbItemPerAlignmentSide)*m_sizeItemRect, (i%m_nbItemPerAlignmentSide)*m_sizeItemRect}+m_borders.getOffset());
                m_listItem[i].text.setPosition(tgui::Vector2f{(i/m_nbItemPerAlignmentSide)*m_sizeItemRect, (i%m_nbItemPerAlignmentSide)*m_sizeItemRect}+m_borders.getOffset()+sizeInsideBorder-m_listItem[i].text.getSize());
            }
        }

        // cout << "after" << endl;
    }

    // The isMouseOnWidget function should return true if the mouse is on top of the widget
    bool isMouseOnWidget(tgui::Vector2f pos) const
    {
        // The following assumes that the widget is rectangular and fills the entire size.
        // Note that "pos" is relative the the parent of the widget.
        return tgui::FloatRect{getPosition().x, getPosition().y, getSize().x, getSize().y}.contains(pos);
    }


    // The draw function will be called when it is time to render the widget to the screen
    void draw(tgui::BackendRenderTarget& target, tgui::RenderStates states) const
    {
        // To render something you can call functions on the "target" object.
        // Note that the position in "states" is already relative to this widget,
        // so you no longer have to add getPosition() anywhere.

        // This example code will draw a red rectangle with blue borders of 2px around it.
        // The m_opacityCached variable is defined in the Widget base class and contains
        // the value of the Opacity property of the widget renderer.

        tgui::RenderStates saveStates = states;

        target.drawFilledRect(states,
                            getSize(),
                            tgui::Color::applyOpacity(m_bgColor, m_opacityCached));


        unsigned nbDraw = 0;
        //draw fist all border
        for(const auto &it:m_listItem){
            target.drawBorders(states, m_borders, {m_sizeItemRect,m_sizeItemRect}, tgui::Color::applyOpacity(m_borderColorItem, m_opacityCached));
           
            if(m_alignmentSide == AlignmentSide::HORIZONTAL)
                states.transform.translate({m_sizeItemRect,0});
            else if(m_alignmentSide == AlignmentSide::VERTICAL)
                states.transform.translate({0,m_sizeItemRect});

            nbDraw++;

            if(nbDraw%m_nbItemPerAlignmentSide == 0)
            {   
                if(m_alignmentSide == AlignmentSide::HORIZONTAL)
                    states.transform.translate({-(m_sizeItemRect*m_nbItemPerAlignmentSide),m_sizeItemRect});
                else if(m_alignmentSide == AlignmentSide::VERTICAL)
                    states.transform.translate({m_sizeItemRect,-(m_sizeItemRect*m_nbItemPerAlignmentSide)});
            }
        }

        //draw then all rect
        states = saveStates;
        nbDraw = 0;
        states.transform.translate(m_borders.getOffset());
        for(const auto &it:m_listItem){
            target.drawFilledRect(states,
                {m_sizeItemRect - m_borders.getLeft() - m_borders.getRight(), m_sizeItemRect - m_borders.getTop() - m_borders.getBottom()},
                tgui::Color::applyOpacity(m_bgColorItem, m_opacityCached));
           
            if(m_alignmentSide == AlignmentSide::HORIZONTAL)
                states.transform.translate({m_sizeItemRect,0});
            else if(m_alignmentSide == AlignmentSide::VERTICAL)
                states.transform.translate({0,m_sizeItemRect});

            nbDraw++;

            if(nbDraw%m_nbItemPerAlignmentSide == 0)
            {   
                if(m_alignmentSide == AlignmentSide::HORIZONTAL)
                    states.transform.translate({-(m_sizeItemRect*m_nbItemPerAlignmentSide),m_sizeItemRect});
                else if(m_alignmentSide == AlignmentSide::VERTICAL)
                    states.transform.translate({m_sizeItemRect,-(m_sizeItemRect*m_nbItemPerAlignmentSide)});
            }
        }

        //draw all sprite
        states = saveStates;
        for(const auto &it:m_listItem){
            target.drawSprite(states,it.sprite);
        }

        //draw all text
        for(const auto &it:m_listItem){
            target.drawText(states,it.text);
        }
    }

    // Add the following line to allow the compiler to find the setSize(w, h) function,
    // which will simply call the setSize(size) function that was overridden above.
    using tgui::Widget::setSize;


protected:

    struct itemStruct{
        ItemStack is;
        tgui::Sprite sprite;
        tgui::Text text;
        bool selected;
    };

    // Every widget needs a method to copy it
    Widget::Ptr clone() const override
    {
        std::vector<ItemStack> list = {};
        auto ret = std::make_shared<ItemContainerWidget>(m_alignmentSide, m_nbItemPerAlignmentSide, list);
        ret->m_listItem = this->m_listItem;
        return ret;
    }

    unsigned m_nbItemPerAlignmentSide;

    AlignmentSide m_alignmentSide;
    tgui::Borders m_borders;
    float m_sizeItemRect;

    tgui::Color m_bgColor;
    tgui::Color m_bgColorItem;
    tgui::Color m_borderColorItem;
    tgui::Color m_borderColorItemSelected;

    std::vector<itemStruct> m_listItem;
};

bool runExample(tgui::BackendGui& gui)
{
    try
    {
        auto m_scrollPanel = tgui::ScrollablePanel::create();
        m_scrollPanel->setPosition("0%", "80%");
        m_scrollPanel->setSize("100%", "20%");
        m_scrollPanel->setVerticalScrollbarPolicy(tgui::Scrollbar::Policy::Never);
        m_scrollPanel->setHorizontalScrollbarPolicy(tgui::Scrollbar::Policy::Always);
        gui.add(m_scrollPanel);

        std::vector<ItemStack> listItemStack;
        listItemStack.push_back(ItemStack());
        listItemStack.push_back(ItemStack());
        listItemStack.push_back(ItemStack());
        listItemStack.push_back(ItemStack());
        listItemStack.push_back(ItemStack());
        listItemStack.push_back(ItemStack());

        auto m_itemContainer = ItemContainerWidget::create(ItemContainerWidget::AlignmentSide::VERTICAL, 2, listItemStack);
        m_itemContainer->setSize(800, tgui::bindHeight(m_scrollPanel)-m_scrollPanel->getScrollbarWidth());
        m_scrollPanel->add(m_itemContainer);
    }
    catch (const tgui::Exception& e)
    {
        std::cerr << "TGUI Exception: " << e.what() << std::endl;
        return false;
    }

    return true;
}

int main()
{
    sf::RenderWindow window{ {800, 600}, "TGUI example - SFML_GRAPHICS backend" };

    tgui::Gui gui{window};
    if (runExample(gui))
        gui.mainLoop(sf::Color(0,0,0));
}

#48
Ok I understand thank you
QuoteYour ItemContainerWidget::setSize function should call Widget::setSize like you do in the code you showed
Yes, the fact that I change the size before passing it to Widget::setSize could be the problem ?
Program works fine if I don't change size before passing it to Widget::setSize but that is not what I want. How it is managed with Label and its auto size feature ? I looked into it and if we use Label::setSize, autoSize is disabled, the size of Widget seems to be modified directly with setText function if I understand well, that's not really what I want.
The modification is as follows:
tgui::Layout2d newSize = size;
    if(m_alignmentSide == AlignmentSide::HORIZONTAL){
        newSize.y = nbItemPerNonAlignmentSide*m_sizeItemRect;
    }else if(m_alignmentSide == AlignmentSide::VERTICAL){
        newSize.x = nbItemPerNonAlignmentSide*m_sizeItemRect;
    }
    cout << "newSize: " << newSize.toString() << endl;
    Widget::setSize(newSize);
So it changes one of the edge with a direct value computed, the other one is still a bounded value.

QuoteIf you replace "itemContainerW->setSize(800, tgui::bindHeight(m_scrollPanel)-m_scrollPanel->getScrollbarWidth());" with just "itemContainerW->setSize(800,600)", does the program work fine?
Yes it worked, as I remember, I tried this and I passed the size unmodified to Widget::setSize, I will try this evening with modification before passing.

QuoteSo one thing you could still test is to check that m_boundSizeLayouts is really empty in ItemContainerWidget::setSize.
I will this evening
QuoteCould you perhaps share your code so that I can try to reproduce it here?
I will this evening if I don't find a solution
#49
Thank you for your precision,

QuoteRecursions usually do end up with a call stack, as you get a crash at a maximum recurse depth
Yes it crashes, it is definitely a recursion issue. In debugger mode, it seems to be stuck in Widget.cpp:567 in setSize function. m_boundSizeLayouts seems to be endless
for (auto& layout : m_boundSizeLayouts)
    layout->recalculateValue();
however, it is not in the call of Widget::setSize by my custom widget, it's after.

Basically, my layout can be simplified as:
gui
->  ScrollablePanel with
    m_scrollPanel->setPosition("0%", "80%");
    m_scrollPanel->setSize("100%", "20%");

    --> ItemContainerWidget (my custom widget) with
        itemContainerW->setSize(800, tgui::bindHeight(m_scrollPanel)-m_scrollPanel->getScrollbarWidth());


m_scrollPanel is not modified in ItemContainerWidget's setSize, the code is the same as my first post.

Well I obviously don't get something in here... When we resize the window, wich setSize is called first, the child widgets, or parent ones ?
#50
Crash occurs after ItemContainerWidget::setSize, no recursion in this method but probably maybe somewhere else, but I can't find it. I think it's recursion issue as there is no call stack, no error output just crash. In debug mode of vsc, the app stays without any response, it's another hint that's recursion issue.

I tried to look into Widget::setSize(size) but I don't understand very well what is happenning, does this function recall setSize of my custom widget ItemContainerWidget ?

the scrollPanel is juste linked to the size of gui, m_scrollPanel->setSize("100%", "20%");
If this is a circular dependency issue, why is the crash not happenning every time ?