Main Menu

Recent posts

#41
Help requests / Linking Error only with tgui::...
Last post by LeeDev - 07 January 2024, 07:36:24
I am currently working on a project using TGUI with SFML in Visual Studio and have encountered a linker error that I'm unable to resolve. The error occurs specifically when I try to use the tgui::Texture class. Other components of TGUI seem to work fine in my project, but any attempt to use tgui::Texture results in a linker error.

LNK2001: unresolved external symbol "private: static bool tgui::Texture::m_defaultSmooth" (?m_defaultSmooth@Texture@tgui@@0_NA)


Project Setup:

IDE: Visual Studio 2022
TGUI Version: TGUI 1.1.0
SFML Version: 2.6.1
Build Configuration: Debug
Platform: Win32

I have checked that my project is set up according to the TGUI documentation:

The TGUI library is correctly linked in the project settings.
I am using the correct build configuration (Debug/Release) for both TGUI and SFML.
The include and library directories are properly set in Visual Studio.
I have tried the following steps to troubleshoot the issue:

Rechecked all linker settings in Visual Studio.
Verified that there are no multiple definitions of TGUI symbols.
Rebuilt the TGUI library to ensure it matches my project settings.
Created a minimal test case where I only use tgui::Texture.
Despite these efforts, the linker error persists. It's puzzling that this issue is specific to tgui::Texture and does not affect other TGUI components.

I would greatly appreciate any insights or suggestions on how to resolve this issue. Has anyone else encountered a similar problem, or can anyone spot something I might be missing in my setup?

Thank you in advance for your help!
#42
Themes / Dark Theme
Last post by finjosh - 05 January 2024, 02:37:13
Source Code: https://github.com/finjosh/TGUI-DarkTheme

Supported Widgets:
  • ChatBox
  • ComboBox
  • EditBox
  • EditBox
  • ListBox
  • ListView
  • MenuBar
  • MessageBox
  • RadioButton
  • RangeSlider
  • ScrollBar
  • SeparatorLine
  • Slider
  • TextArea
  • ToggleButton
  • ChildWindow
  • Button
  • Any other widgets that inherit their properties from either global or the listed widget's properties should work

Screenshot 2024-01-05 131937.png
#43
General Discussion / Re: Error in drawRoundedRectHe...
Last post by Nafffen - 21 December 2023, 13:40:48
"4 * (nrCornerPoints - 1)"
Oooh that's where I was wrong, I didn't see this -1 my bad  ;D
Thanks for the reply
#44
General Discussion / Re: Error in drawRoundedRectHe...
Last post by texus - 21 December 2023, 13:13:30
My first instinct was to just render with both versions of the code and see which one looked correct, so that I didn't have to bother with understanding the math again, but I couldn't visually tell the difference between both variants :)

I think my code is correct though.

Let's examine the bottom left corner. The first point needs to be at the leftmost position (as it is connected by a vertical line from the last point of the top-left corner), while the last point needs to be at the bottom-most position (as it needs to be connected with a horizontal line to the first point of the bottom-right corner).
So when you plug in i=0 in the formula, you need to get a cos value of -1 and a sin value of 0. When you set i=nrCornerPoints-1 (the last iteration of the for loop), the cos value should be 0 and the sin value should be -1. I verified with WolframAlpha that this is the case when using my formula.

The thing that makes it weird is probably that when drawing a circle (instead of a rounded rectangle), the top, right, bottom and left points on the circle are duplicated. There is also the fact that the "nrPointsInCircle" might be a bad name. There are "4 * nrCornerPoints" points in total, but "nrPointsInCircle" is set to "4 * (nrCornerPoints - 1)" (the amount of unique points when drawing a circle instead of a rounded rectangle).
#45
General Discussion / Error in drawRoundedRectHelper...
Last post by Nafffen - 21 December 2023, 11:32:40
Hey, I'm not sure about this, but I looked in your drawRoundedRectHelperGetPoints code to help myself with a project, and I think your computation for Bottom left corner and Bottom right corner is slighty offset.
Instead of:
// Bottom left corner
        for (unsigned int i = 0; i < nrCornerPoints; ++i)
        {
            points.emplace_back(offset + radius + (radius * std::cos(twoPi * (2*(nrCornerPoints - 1) + i) / nrPointsInCircle)),
                                offset + size.y - radius - (radius * std::sin(twoPi * (2*(nrCornerPoints - 1) + i) / nrPointsInCircle)));
        }

        // Bottom right corner
        for (unsigned int i = 0; i < nrCornerPoints; ++i)
        {
            points.emplace_back(offset + size.x - radius + (radius * std::cos(twoPi * (3*(nrCornerPoints - 1) + i) / nrPointsInCircle)),
                                offset + size.y - radius - (radius * std::sin(twoPi * (3*(nrCornerPoints - 1) + i) / nrPointsInCircle)));
        }
The following will give more accurate result:
// Bottom left corner
        for (unsigned int i = 0; i < nrCornerPoints; ++i)
        {
            points.emplace_back(offset + radius + (radius * std::cos(twoPi * ((2*nrCornerPoints - 1) + i) / nrPointsInCircle)),
                                offset + size.y - radius - (radius * std::sin(twoPi * ((2*nrCornerPoints - 1) + i) / nrPointsInCircle)));
        }

        // Bottom right corner
        for (unsigned int i = 0; i < nrCornerPoints; ++i)
        {
            points.emplace_back(offset + size.x - radius + (radius * std::cos(twoPi * ((3*nrCornerPoints - 1) + i) / nrPointsInCircle)),
                                offset + size.y - radius - (radius * std::sin(twoPi * ((3*nrCornerPoints - 1) + i) / nrPointsInCircle)));
        }

The problem was removing 1 before multiplied by 2 (or 3 for the next corner), we need to remove it after the multiplication.

Tell me if I am wrong.
#46
Help requests / Re: ChildWindow
Last post by Garwin - 18 November 2023, 11:53:23
Thanks Texus.
I would probably used inhereted class. For small example having variables outsides is easy but for anything a little more complex having all variables in one class seems to me better solution.
#47
Help requests / Re: ChildWindow
Last post by texus - 16 November 2023, 18:55:43
Thanks for the detailed description and sample code, I was able to quickly track down the bug in TGUI. There is a branch in setPosition that doesn't actually set any position (when KeepInParent is true and the provided position isn't outside the parent).

A workaround would be to call setKeepInParent(false) right before you call setPosition.

The issue has now been fixed in the latest development version.

QuoteUsing separated lambdas for each button which are not aware of status of the seconds is not ideal. Is there another way to do it?
You can move the state outside the lambda and let the lambda functions take a reference to it. Your lambda already starts with "[&]", so it already has access to all variables outside it by reference. You just have to be careful that the referenced parameter doesn't go out of scope and gets destroyed before the lambda is called.

Code (cpp) Select
bool maximized = false;
bool minimized = false

childWindow->onMaximize([&](){
    // You can use 'minimized' here as well.
    // Make sure to remove the "static bool maximized (false);" line from this lambda
});

childWindow->onMinimize([&](){
    // You can use 'maximized' here as well.
    // Make sure to remove the "static bool minimized (false);" line from this lambda
});

You can do the same for the other static variables.
#48
Help requests / ChildWindow
Last post by Garwin - 16 November 2023, 17:14:40
I first tried to implement both minimalizing and maximizing buttons in ChildWindow Widget with TGUI 1.1, backend SFML on Windows with GCC 13.1 compiler. I got some strange behaviors (code attached at the end)

1. Movement of the widget inside a parent widget
If widget setPositionLocked(false) and setKeepInParent(true) is true then the movement of the widget is only possible on the edges of the parent widget. If setKeepInParent(false), than movement is freely available anywhere.

2. Implementing Maximize button

I have tried implemented it by lambda and it has some limitations (I will discuss later). But Maximize button does not work correctly as childWindow->setPosition(tgui::Vector2f{nonMaxPosition.x, nonMaxPosition.y}); is completely ignored. I stream the position of the widget before that and after that with information about variable nonMaxPosition to std::cout and it shows that variable nonMaxPosition is correct but the row mentioned above do not set new position of the widget so everytime maximize button is pushed when widget is already maximize, the new position is set to left top corner of parent widget ignoring setting new position of stored previous position.

3. Implementing Maximize and Minimize buttons
Using separated lambdas for each button which are not aware of status of the seconds is not ideal. Is there another way to do it?
I have only one idea and to create new widget which inherites from ChildWidget and have private members storing information about status of the widget (maximalized, minimalized), position and size before that.

#include <TGUI/Widgets/ChildWindow.hpp>
#include <TGUI/Widgets/Group.hpp>
#include <TGUI/Backend/SFML-Graphics.hpp>

#include <iostream>

int main ()
{
    sf::RenderWindow window({800, 600}, "TGUI example (SFML-Graphics)");
    tgui::Gui gui(window);

    auto group = tgui::Group::create();
    group->setSize({700,500});
    group->setPosition({50,50});
    gui.add(group);

    auto childWindow = tgui::ChildWindow::create("Settings");
    group->add(childWindow);
    childWindow->setSize({150,100});
    childWindow->setPosition(50,50);
    childWindow->setPositionLocked(false);
    childWindow->setTitleButtons(tgui::ChildWindow::TitleButton::Maximize
                                 | tgui::ChildWindow::TitleButton::Minimize
                                 | tgui::ChildWindow::TitleButton::Close);
    childWindow->setResizable(true);
    childWindow->setKeepInParent(true); // Prevents any part of the window to go outside the screen

    childWindow->onMaximize([&](){
        static bool maximized (false);
        static bool keepInParent {childWindow->isKeptInParent()};
        static tgui::Vector2f nonMaxSize {childWindow->getSize()};
        static tgui::Vector2f nonMaxPosition (childWindow->getPosition());

        if (maximized)
        {
            childWindow->setSize(nonMaxSize);
            childWindow->setPosition(tgui::Vector2f{nonMaxPosition.x, nonMaxPosition.y}); // DO NOT WORK
            childWindow->setKeepInParent(keepInParent);
            childWindow->setPositionLocked(false);
        }
        else
        {
            keepInParent = childWindow->isKeptInParent();
            nonMaxSize = childWindow->getSize();
            nonMaxPosition = childWindow->getPosition();
            childWindow->setPosition({0,0});
            childWindow->setSize(childWindow->getParent()->getSize());
            childWindow->setKeepInParent(true);
            childWindow->setPositionLocked(true);
        }
        maximized = !maximized;
    });

    childWindow->onMinimize([&](){
        static bool minimized {false};
        static tgui::Vector2f nonMinimizedSize {childWindow->getSize()};
        if (minimized)
            childWindow->setSize(nonMinimizedSize);
        else
        {
            if (childWindow->getInnerSize().y !=0 && childWindow->getMaximumSize() != childWindow->getSize())
                nonMinimizedSize = childWindow->getSize();
            childWindow->setClientSize({childWindow->getSize().x,0});
        }
        minimized = !minimized;
    });

    gui.mainLoop();

    return 0;
}

#49
Help requests / Re: Texture class
Last post by texus - 15 November 2023, 21:37:19
Correct.

The reason why this change was made is because a copy was always being made before as well, the constructor overload that accepted an sf::Texture object is calling the slow copyToImage function internally. The deprecation makes it a lot more clear that this method shouldn't be used.

TGUI requires ownership of the sf::Texture, so you can't load one in your own code and then share it with TGUI.

If you load a tgui::Texture with a filename, TGUI's internal texture manager will already handle sharing the image between all tgui::Texture objects that were loaded with the same filename (and the image will be released once there are no more tgui::Texture objects with that image).
#50
Help requests / Texture class
Last post by Garwin - 15 November 2023, 20:13:43
I have just recently updated my old project from TGUI 0.9 to TGUI 1.1

I get some warning:
src\game_state_game.cpp|62|warning: 'tgui::Texture::Texture(const sf::Texture&, const tgui::UIntRect&, const tgui::UIntRect&)' is deprecated: Use Texture() and loadFromPixelData(texture.getSize(), texture.copyToImage().getPixelsPtr()) instead [-Wdeprecated-declarations]|

Do I get it correctly, that the change to TGUI 1.1 is depreciation of direct construction of tgui::Texture from sf::Texture and shows more clearly the intention that TGUI copy that texture internally (slow) so using function loadFromPixelData is more appropriate? And having correct non-depreciated code is than:
tgui::Texture tguiPicture;
tguiPicture.loadFromPixelData(sfPicture.getSize(), sfPicture.copyToImage().getPixelsPtr());
auto picture = tgui::Picture::create(std::move(tguiPicture));
Do I have it correct that if my texture manager using sf::Texture to store all textures, than there is no way to avoid copies from sf::Texture to tgui::Texture?