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

#16
I removed Strawberry but still got the same error.
I tried to build another project that has SFML as dependency and also got the same result. So it's not TGUI issue, but SFML one. I am going to create MCVE and raise issue on SFML forum.
#17
Quote from: texus on 19 September 2020, 20:05:12
Could it be that C:/Strawberry/c/include/freetype2 is giving a conflict with the freetype that comes with SFML?
Maybe, in any case I am going to remove Strawberry and test it again to be sure.
#18
Quote from: texus on 19 September 2020, 20:01:39
I don't see anything wrong with those files, it says that it has freetype at T:/libraries/C++/SFML-2.5.1/extlibs/libs-msvc-universal/x86/freetype.lib

Did you download the SFML version from github?
You are setting TGUI_SHARED_LIBS to FALSE, right?
Could you send the CMakeCache.txt file from your TGUI build?
Could you send your entire SFML folder?
Yes, I download sourse for 2.5.1 release from Github.
Right.
CMakeCache.txt attached

Entire SFML folder is huge (.pdb files for samples are heavy) if it's really useful I'll build SFML without them and send folder.
#19
Yes, attached
#20
No, same issue even when build SFML from source into separate folder.
#21
Maybe it exactly the mess in folder, because I built SFML from source into the same folder. I'll try rebuilt it to different location.
#22
Quote from: texus on 19 September 2020, 13:41:57
Did you manually copy the SFMLConfig.cmake to a different location, because it seems like SFMLConfig.cmake can't find FreeType? The SFMLConfig.cmake hardcodes relative paths, so you are supposed to keep the SFML folder structure.

No, I didn't change(or move, or copied somewhere else) any file inside SFML folder.
#23
Installation help / Error CMake couldn't find SFML
19 September 2020, 13:34:49
While building TGUI got such error:

QuoteSFML found but some of its dependencies are missing ( FreeType)
CMake Warning at src/Backends/SFML/CMakeLists.txt:13 (find_package):
  Found package configuration file:

    */libraries/C++/SFML-2.5.1/SFMLConfig.cmake

  but it set SFML_FOUND to FALSE so package "SFML" is considered to be NOT
  FOUND.
Call Stack (most recent call first):
  src/Backends/CMakeLists.txt:44 (include)
  src/CMakeLists.txt:162 (include)


CMake Error at src/Backends/SFML/CMakeLists.txt:25 (message):
  CMake couldn't find SFML.

  Set SFML_DIR to the directory containing SFMLConfig.cmake (usually
  something like SFML_ROOT/lib/cmake/SFML), or change TGUI_BACKEND to not use
  SFML.
Call Stack (most recent call first):
  src/Backends/CMakeLists.txt:44 (include)
  src/CMakeLists.txt:162 (include)

I suppose that's because this part was removed from CMakeLists.txt:

Quoteif(NOT TGUI_SHARED_LIBS)   
    if(SFML_ROOT)   
        if(TGUI_OS_WINDOWS)   
            set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${SFML_ROOT}/extlibs/headers")   
            if(ARCH_32BITS)   
                if(TGUI_COMPILER_MSVC AND MSVC_VERSION LESS 1900) # older than VC++14   
                    set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${SFML_ROOT}/extlibs/libs-msvc/x86")   
                elseif(TGUI_COMPILER_MSVC) # VC++14 or newer   
                    set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${SFML_ROOT}/extlibs/libs-msvc-universal/x86")   
                else() # gcc   
                    set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${SFML_ROOT}/extlibs/libs-mingw/x86")   
                endif()   
            elseif(ARCH_64BITS)   
                if(TGUI_COMPILER_MSVC AND MSVC_VERSION LESS 1900) # older than VC++14   
                    set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${SFML_ROOT}/extlibs/libs-msvc/x64")   
                elseif(TGUI_COMPILER_MSVC) # VC++14 or newer   
                    set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${SFML_ROOT}/extlibs/libs-msvc-universal/x64")   
                else() # gcc   
                    set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${SFML_ROOT}/extlibs/libs-mingw/x64")   
                endif()   
            endif()   
        elseif(TGUI_OS_MACOSX)   
            set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${SFML_ROOT}/extlibs/headers")   
            set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${SFML_ROOT}/extlibs/libs-osx/lib/")   
        elseif(TGUI_OS_ANDROID)   
            set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${CMAKE_ANDROID_NDK}/sources/third_party/sfml/extlibs/lib/${CMAKE_ANDROID_ARCH_ABI}/")   
        elseif(TGUI_OS_IOS)   
            set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${SFML_ROOT}/extlibs/libs-ios/")   
        endif()   
    endif()   
endif()   

together with SFML_ROOT. When I return it back and define SFML_ROOT all build as expected.
#24
Updated.
Single remaining part is saving/loading the widget to/from file.
Default implementation won't work, because not all panels are holding in inner container so their renderers are not inserted at this point into the renderer map.
#25
Quote from: texus on 24 July 2020, 19:57:18
The code mostly looks fine. A few remarks:
- Why double the height of the tab in the constructor?
For me default height in Tabs is a bit narrow, in PR I changed to default one, but I think it would be good to provide method for changing height of Tabs in some form.
In code above I just use getTabs function, but I removed it in PR because I don't see any sense to provide full access to private member in library. Or am I wrong and such function is OK?

Quote from: texus on 24 July 2020, 19:57:18
- Is "m_tabs->select(m_index);" in "m_tabs->onTabSelect" in tgPanelHolder constructor needed? Wouldn't it already be selected before this callback function is even called (and changed a second time in the Select function)?
Yes, it's needed for case if user forbid selection changing in onSelectionChanging handler, i.e:

            tabContainer->onSelectionChanging([&tabContainerelectedCount](int idx, bool* Vetoed)
            {
                if (someCondition)
                {
                    *Vetoed = true;
                }
            });


Quote from: texus on 24 July 2020, 19:57:18
- Perhaps you should only call "m_tabs->select(index);" in the Select function when the index in the tab is different (i.e. when the user called select himself). Right now you have something that looks like a recursion: Select calls m_tabs->select which triggers onTabSelect in which you call Select again.
It's indeed was reason of one extra call Select function. Index should be changed first, fixed.
#26
Panel holder is a control, which manages multiple windows with associated tabs. This control also known either as Tab container or Notebook widget. It's popular widget so it would be good to have such control in TGUI.

I've made such simple implementation that I current use in own project:

class tgPanelHolder : public tgui::SubwidgetContainer
{
public:

    typedef std::shared_ptr<tgPanelHolder> Ptr; //!< Shared widget pointer
    typedef std::shared_ptr<const tgPanelHolder> ConstPtr; //!< Shared constant widget pointer

    tgPanelHolder(const tgui::Layout2d& size = { "100%", "100%" }) : m_index(-1)
    {
        m_type = "PanelHolder";
        setSize(size);
        m_tabs = tgui::Tabs::create();
        m_tabs->setSize({ size.x, m_tabs->getSize().y * 2 });
        m_tabs->onTabSelect([this]()
            {
                auto cur = m_tabs->getSelectedIndex();
                Select(cur);
                if (m_tabs->getSelectedIndex() != m_index)
                {
                    m_tabs->select(m_index);
                }
            });

        m_container->add(m_tabs, "Tabs");
    }

    static tgPanelHolder::Ptr create(const tgui::Layout2d& size = { "100%", "100%" })
    {
        return std::make_shared<tgPanelHolder>(size);
    }

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

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

    void addPanel(tgui::Panel::Ptr ptr, const tgui::String& name, bool select = true)
    {
        auto size = getSizeLayout();
        ptr->setSize({ size.x , size.y - m_tabs->getSize().y });
        ptr->setPosition({ tgui::bindLeft(m_tabs), tgui::bindBottom(m_tabs) });
        m_panels.push_back(ptr);
        m_tabs->add(name, select);
        if (select)
        {
            Select(m_panels.size() - 1, false);
        }
    }

    bool addPanelAt(tgui::Panel::Ptr ptr, const tgui::String& name, std::size_t index, bool select = true)
    {
        if (index > m_panels.size())
        {
            return false;
        }

        addPanel(ptr, name, select);
        auto size = m_panels.size();
        if (index != size)
        {
            std::swap(m_panels[index], m_panels[size - 1]);
        }
    }

    void RemovePanel(tgui::Panel::Ptr ptr)
    {
        if (ptr != nullptr)
        {
            auto idx = getIndex(ptr);
            if (idx != -1)
            {
                m_tabs->remove(idx);
                m_container->remove(m_panels[idx]);
                m_panels.erase(m_panels.begin() + idx);
                if (idx == 0)
                {
                    Select(m_panels.size() - 1);
                }
                else
                {
                    Select(idx - 1);
                }
            }
        }
    }

    void Select(std::size_t index, bool genEvents = true)
    {
        if (index >= m_panels.size() || index == static_cast<std::size_t>(m_index))
        {
            return;
        }
        if (genEvents)
        {
            bool isVetoed = false;
            onSelectionChanging.emit(this, index, &isVetoed);
            if (isVetoed)
            {
                return;
            }
        }

        if (m_container->getWidgets().size() == 2)
        {
            m_container->remove(m_panels[m_index]);
        }
        m_container->add(m_panels[index]);
        m_tabs->select(index);
        m_index = index;
        if (genEvents)
        {
            onSelectionChanged.emit(this, m_index);
        }
    }

    std::size_t Count() const
    {
        return m_panels.size();
    }

    int getIndex(tgui::Panel::Ptr ptr)
    {
        for (std::size_t i = 0; i < m_panels.size(); i++)
        {
            if (m_panels[i] == ptr)
            {
                return static_cast<int>(i);
            }
        }
        return -1;
    }

    tgui::Panel::Ptr getSelected()
    {
        return getPanel(m_index);
    }

    int getSelectedIndex() const
    {
        return m_index;
    }

    tgui::Panel::Ptr getPanel(int index)
    {
        if (index < 0 || index >= static_cast<int>(m_panels.size()))
        {
            return nullptr;
        }
        return m_panels[index];
    }

    tgui::Tabs::Ptr getTabs()
    {
        return m_tabs;
    }

    tgui::String getTabText(std::size_t index) const
    {
        return m_tabs->getText(index);
    }

    bool changeTabText(std::size_t index, const tgui::String& text)
    {
        return m_tabs->changeText(index, text);
    }

public:
    tgui::SignalInt onSelectionChanged = { "SelectionChanged" };
    tgui::SignalTyped2<int, bool*> onSelectionChanging = { "SelectionChanging" }; //can be vetoed

private:
    std::vector<tgui::Panel::Ptr> m_panels;
    int m_index;

    tgui::Tabs::Ptr m_tabs;
};


If it's OK - I'm going to open PR with proper changes (code style, tests, ...)
#27
Feature requests / Re: SpinCtrl
17 July 2020, 23:54:56
Wow, mouse cursors will be really cool addition.

Yeah, I'm sure that I missed something (except code style of course). I only now found that widgets based on SubwidgetContainer don't have load/save support out-of-the-box. And I don't see how it should be implemented (I haven't big experience with any DSL-based GUI therefore not use it at all so it's not a problem for me).
#28
Feature requests / Re: SpinCtrl
15 July 2020, 09:54:07
Quote from: texus on 14 July 2020, 19:31:51
Does it really matter that if the user typed "123text", we keep the "123" instead of resetting the value? I don't think anyone is even going to notice the behavior (because you typically do type actual digits in it). And I would kind of consider it a feature that it keeps the value I typed if I accidentally hit another button together with the enter key :).
Maybe the edit box should have Validator::Float set, that way you can't even type text or have multiple commas.
Yeah, I didn't think about that. Updated with validator. 
#29
Feature requests / Re: SpinCtrl
14 July 2020, 15:12:13
Quote from: texus on 10 July 2020, 23:25:12
Maybe instead of choosing Int vs Float, there should be an amount of digits behind the comma? If set to 0, only ints get accepted, if set to 2 then "x", "x.a" or "x.ab" would be accepted but "x.abc" would be rounded. The default could be -1 which allows any float input.
That's indeed better.

Quote from: texus on 10 July 2020, 23:25:12
Instead of using std::stof and exceptions, I think String::toFloat should be used. Whether we should depend on the locale to parse numbers is arguable, but for now it would probably be best to rely on the code always behaving the same on every pc.
Yeah, I though about that, but String::toFloat doesn't have any way to know was full string converted or only some first part. E.g. "123text" give 123  so one need or make extra conversion back to string or something else. For now I copied simplified version of toFloat as a private function, but guess String::toFloat should contains overloading for such cases. Maybe like std::stof with parameter for storing the number of characters processed or something else.
#30
Feature requests / Re: SpinCtrl
10 July 2020, 14:51:40
I've finally finished SpinCtrl, here is code and example:


#include <TGUI/TGUI.hpp>
#include <iostream>

class SpinCtrl : public tgui::SubwidgetContainer
{
public:
    typedef std::shared_ptr<SpinCtrl> Ptr; //!< Shared widget pointer
    typedef std::shared_ptr<const SpinCtrl> ConstPtr; //!< Shared constant widget pointer

    SpinCtrl(float min = 0.0F, float max = 10.0F, float step = 1.0F, float value = 0.0F)
    {
        m_type = "SpinCtrl";

        m_spinButton = tgui::SpinButton::create();
        m_spinText = tgui::EditBox::create();
        m_spinText->setText(tgui::String(m_spinButton->getValue()));

        m_spinButton->setPosition(tgui::bindRight(m_spinText), tgui::bindTop(m_spinText));
        m_spinButton->onValueChange([this](const float value)
            {
                m_spinText->setText(tgui::String(value));
                onValueChange.emit(this, value);
            });

        m_spinButton->setMinimum(min);
        m_spinButton->setMaximum(max);
        m_spinButton->setValue(value);
        m_spinButton->setStep(step);

        m_spinText->setSize(m_spinText->getSize().x, m_spinButton->getSize().y);
        m_spinText->onTextChange([this](const tgui::String& text)
            {
                auto curValue = m_spinButton->getValue();
                try
                {
                    std::size_t pos = 0;
                    float value = std::stof(text.toAnsiString(), &pos);
                    if (pos != text.size() || !inRange(value))
                    {
                        m_spinText->setText(tgui::String(curValue));
                    }
                    else if (curValue != value)
                    {
                        m_spinButton->setValue(value);
                    }
                }
                catch (...)
                {
                    m_spinText->setText(tgui::String(curValue));
                }
            });
        m_container->add(m_spinText);
        m_container->add(m_spinButton);
        auto butSize = m_spinButton->getSize();
        auto txtSize = m_spinText->getSize();
        setSize({ butSize.x + txtSize.x, butSize.y });
    }
    static SpinCtrl::Ptr create(float min = 0.0F, float max = 10.0F, float step = 1.0F, float value = 0.0F)
    {
        return std::make_shared<SpinCtrl>(min, max, step, value);
    }
    static SpinCtrl::Ptr copy(SpinCtrl::ConstPtr spinctrl)
    {
        if (spinctrl)
            return std::static_pointer_cast<SpinCtrl>(spinctrl->clone());
        else
            return nullptr;
    }
    Widget::Ptr clone() const override
    {
        return std::make_shared<SpinCtrl>(*this);
    }
    bool SetValue(const float value)
    {
        if (inRange(value) && m_spinButton->getValue() != value)
        {
            m_spinButton->setValue(value);
            m_spinText->setText(tgui::String(value));
            return true;
        }
        return false;
    }
    void setMinimum(const float min)
    {
        m_spinButton->setMinimum(min);
    }
    void setMaximum(const float max)
    {
        m_spinButton->setMaximum(max);
    }
    void setStep(const float inc)
    {
        m_spinButton->setStep(inc);
    }
    float getValue() const
    {
        return m_spinButton->getValue();
    }
    float getMinimum() const
    {
        return m_spinButton->getMinimum();
    }
    float getMaximum() const
    {
        return m_spinButton->getMaximum();
    }
    float getStep() const
    {
        return m_spinButton->getStep();
    }
    tgui::SpinButtonRenderer* getSpinButtonRenderer()
    {
        return m_spinButton->getRenderer();
    }
    tgui::SpinButtonRenderer* getSpinButtonSharedRenderer()
    {
        return m_spinButton->getSharedRenderer();
    }
    tgui::EditBoxRenderer* getSpinTextRenderer()
    {
        return m_spinText->getRenderer();
    }
    tgui::EditBoxRenderer* getSpinTextSharedRenderer()
    {
        return m_spinText->getSharedRenderer();
    }

    tgui::SignalTyped<float> onValueChange = { "ValueChanged" };

private:
    bool inRange(const float value) const
    {
        return m_spinButton->getMinimum() <= value && value <= m_spinButton->getMaximum();
    }

    tgui::SpinButton::Ptr m_spinButton;
    tgui::EditBox::Ptr m_spinText;
};

class MyFrame
{
public:
    MyFrame()
    {
        window.create(sf::VideoMode(800, 600), "SpinCtrl");
        gui.setTarget(window);
        auto spin = SpinCtrl::create(0, 10, 0.2F, 5);
        spin->getSpinTextRenderer()->setBackgroundColor(tgui::Color(205, 14, 98));
        spin->getSpinTextRenderer()->setBackgroundColorHover(tgui::Color(205, 14, 98));
        spin->getSpinButtonRenderer()->setBackgroundColor(tgui::Color(138, 250, 134));
        spin->getSpinButtonRenderer()->setBackgroundColorHover(tgui::Color(138, 250, 134));
        gui.add(spin);

        spin->onValueChange([](float value) { std::cout << "New value is " << value << '\n'; });
    }

    void main()
    {
        while (window.isOpen())
        {
            sf::Event event;
            while (window.pollEvent(event))
            {
                if (event.type == sf::Event::Closed)
                    window.close();
                gui.handleEvent(event);
            }
            gui.draw();
            window.display();
        }
    }
    sf::RenderWindow window;
    tgui::Gui gui;
};

int main()
{
    MyFrame().main();
}


If such implementation is ok, I am going to open PR (will split onto .h/.cpp and add tests).

As an option maybe it make sense to add method createIntegerSpinCtrl and set in that method Integer Validator.