Welcome, Guest. Please login or register. Did you miss your activation email?

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

Pages: [1] 2
1
SFML development / Re: move semantics for sf::context
« on: November 06, 2023, 07:44:53 pm »
OK, thanks. I will make a pull request.

2
SFML development / move semantics for sf::context
« on: October 29, 2023, 03:25:21 pm »
Hello,
I'm willing to help out on this one, and in principle it's not hard, this object contains just one unique_ptr, so move constructor and move assignment can be defaulted.
Of course there is a complication. In the moved-from object, the m_context pointer will be nullptr. Fixing the destructor is not too hard: just do nothing if m_context is nullptr (the moved-to instance is owner now):

Context::~Context()
{
    if (m_context)
    {
        if (m_context) // if moved from, m_context will be nullptr. In that case, do nothing.
        {
            if (!setActive(false))
            {
                err() << "Failed to set context as inactive during destruction" << std::endl;
            }
        }
    }
}


But the other two member functions, setActive and getSettings also access this pointer, that is nullptr in the case it is moved from.

My questions:
- is it acceptable to you to just have undefined behaviour (a crash) if setActive and/or getSettings are called on a moved-from instance of sf::Context?

if not:
- for setActive, is it acceptable to just return false on a call on a moved-from instance? Of course, in this case the destructor still has to be altered, otherwise it wil cause the diagnostic every time a moved-from sf::Context object runs out of scope.
- for getSettings, is it acceptable to return a default-constructed ContextSettings on a call on a moved-from instance?

3
Got it working, though my method is a bit hacky.

  • Downloaded the sources of freetype 2.10.4
  • opened the provided visual studio solution (builds\windows\vc2010 (yes this one works on vs2019 too)
  • built it for the desired configuration
  • now VS builds a dll named freetype.dll. I renamed it to freetyped.dll (debug version). Hovering in windows confirms that it is version 2.10.4.
  • copied it to vcpkg\installed\x64-windows\bin (overwrite existing file)
  • now it works. It seems that 2.10.4 and 2.11.0 are binary compatible.

Stackoverflow says that you have to edit header files. This is not necessary anymore. Just choose dll in the solution properties.

Hopefully they fix that bug soon. I do wonder however how they could miss this with any kind of testing on windows (not an entirely insignificant platform).

4
stupid mistake: in vcpkg.json:

"overrides":[{"name":"sfml", "version":"2.10.0"}] -> "overrides":[{"name":"freetype", "version":"2.10.0"}]

But it doesn't make a difference, it still builds freetype 2.11.0

5
Graphics / Re: problem with sf::Text getGlobalBounds() / getLocalBounds()
« on: September 16, 2021, 10:44:42 am »
I see that this is a duplicate for https://en.sfml-dev.org/forums/index.php?topic=28213.0

6
May I ask how you did this? For me it won't work.
I edited the vcpkg.json in the ports\sfml dir to
(click to show/hide)

I got the value of builtin-baseline by doing
git rev-parse HEAD

This didn't do anything for me: it still grabbed freetype version 2.11.0.

Then I edited vcpkg\versions\baseline.json and changed the baseline of freetype to 2.10.0 and I edited the vcpkg.json of freetype to also take 2.10.0:
"version-semver": "2.10.0",

Now it SAYS that it takes 2.10.0. And vcpkg list says 2.10.0 for freetype. But the dll version is STILL 2.11.0 and drawing an sf::Text STILL crashes in freetype.

Maybe the easier way is to compile sfml with cmake and copy the freetype dll into the vcpkg\bin dir

7
Graphics / Re: problem with sf::Text getGlobalBounds() / getLocalBounds()
« on: September 15, 2021, 03:25:42 pm »
interesting detail: the debugger watch suggests that variable t has no vertices

(click to show/hide)

8
Graphics / Re: problem with sf::Text getGlobalBounds() / getLocalBounds()
« on: September 15, 2021, 02:59:58 pm »
The problem seems to be deeper: sf::Text also doesn't draw properly anymore. Very minimal program:

(click to show/hide)

Compiled with visual studio 16.11.3

Installed libraries (via vcpkg):
(click to show/hide)

9
Graphics / problem with sf::Text getGlobalBounds() / getLocalBounds()
« on: September 15, 2021, 02:35:43 pm »
I take the bounds of an sf::Text object:

sf::Text t{};
t.setFont(m_font);  // yes, m_font is loaded and in scope at this point
t.setString("Hello world");
t.setCharacterSize(20);
auto bounds = t.getGlobalBounds();  // same behaviour with getLocalBounds()

This used to work fine, but now I get the following error:

Exception thrown at 0x00007FFCCAAD2B8D (freetyped.dll) in test.exe: 0xC0000005: Access violation reading location 0x0000000000000008.

The only thing that seems to have changed is an upgrade of freetype to version 2.11.0 (through vcpkg). This might be more a bug in freetype than in SFML, but I can't really tell.

10
SFML projects / Re: SFGUI (0.4.0 released)
« on: September 26, 2020, 04:26:57 pm »
I have a problem with Window widgets in SFGUI. What I try to achieve is that if the user right_clicks on an inventory item, a popup appears with a description of the item. I implement this by holding an sfg::Window::Ptr and adding the text to the label in the window. If the window is "opened" (actually happens only the first time), the window is revealed with Show(true). The onCloseButton is bound to a lambda that just hides the window.

The problem is that the window becomes unresponsive in the following scenarios:
- open popup
- drag it around
- "close" the popup (it is actually just hidden). At this point this works.
- "open" it again. Now the correct text appears, but the window will not respond to events anymore. It will not drag or close.

or
- open popup. The correct text appears
- right click on another inventory item. Now the label changes into the expected text, but the window becomes unresponsive.

The label is found with no problem, the text changes as expected. Only the window can not be dragged or hidden anymore. Here the code, it's small enough.

button->GetSignal (sfg::Widget::OnRightClick).Connect ([this, table, index = i * 10 + j] (){show_description (table, index); }); // the inventory is a sfg::Table of sfg::Togglebutton, the index indicates which button is right-clicked

// ...

void Character_sheet::show_description (sfg::Table::Ptr table, size_t index)
{
        // code to determine the description text left out, goes into desc
        auto desc = item_data->description;
        if (index < inv->bag.contents.size ())  // skip if there is no actual item associated with this inventory slot
        {
                if (m_description_popup)
                {
                        m_description_popup->Show (true);
                }
                else
                {
                        m_description_popup = sfg::Window::Create (sfg::Window::Style::TOPLEVEL | sfg::Window::Style::CLOSE);
                        m_description_popup->GetSignal (sfg::Window::OnCloseButton).Connect ([this] (){m_description_popup->Show (false); });
                        auto text = sfg::Label::Create ();
                        text->SetRequisition({ 200.0f,0.0f });
                        text->SetLineWrap (true);
                        text->SetId ("item_description");
                        m_description_popup->Add (text);
                        m_desktop->Add (m_description_popup);
                }
                auto text = find_widget ("item_description");
                text->SetText (desc);
        }
}

template <typename T = sfg::Label>
std::shared_ptr<T> find_widget (const std::string& id)
{
        return std::dynamic_pointer_cast<T>(sfg::Widget::GetWidgetById (id));
}
 

11
I got to the statemanager chapter. A few constructive remarks:

1- You tend to pass very small data-items bij const ref: e.g. void f (const bool&). I don't see what's the merit in that. A bool or an int is probably even smaller than a pointer. Just pass these things by value and use const refs where a copy is (potentially) expensive.
2- You have a tendency of declaring empty destructors. Probably power of habit, but in C++11 this prevents the generation of move constructor and assignment. This will of course not be a problem with classes like eventmanager and statemanager because they will not be moved around anyway, but this is not a good habit.
3- In the draw and update functions of the statemanager, you traverse back and forth to find the last non-transparent state. In the past I used to be a C programmer, so traversing pointer structures is nothing new for me, but the C++ Committee gave us the algorithms library to be used. This code can be rewritten to be a lot more obvious:


#include <algorithm>

using State_elem = std::pair<StateType, BaseState*>>;  // convenience

void StateManager::Draw()
{
  if (m_states.empty() {return;}
  if (m_states.back().second->IsTransparent() && m_states.size() > 1)
  {
    // find last non-transparent state. find_if normally finds the first element that satisfies its predicate,
    // but if we feed it reverse iterators, it searches backwards.
    // I use find_if_not to avoid confusing negative logic.
    auto r_itr = std::find_if_not (m_states.rbegin(), m_states.rend(), [](State_elem e) {return e.second->isTransparent();});
    // we gave find_if_not reverse iterators, it also gives us a reverse iterator. So we have to trick it:
    for (; r_itr != m_states.rbegin(); --r_itr)
    {
      r_itr -> second -> Draw();
    }
  }
  else
  {
    m_states.back().second->Draw();
  }
}



IMHO this code is self-explanatory, except for the little trick with the reverse iterators.

It might be possible to just say

auto r_itr = std::find_if_not (m_states.rbegin(), m_states.rend(), [](auto e) {return e.second -> isTransparent();});


and let the compiler figure out the type of the argument of the predicate.
The algorithm library works brilliantly with lambdas. Every new C++ programmer should learn about that. This also goes for the HasState function: it can be simplified a lot by using find_if. Use find_if to find the state in m_states and use find to find it in m_toRemove. If the state is found in m_states and not found in m_toRemove, the result is true. Otherwise the result is false.


bool StateManager::HasState(const StateType type)  // type is an int, just pass by value
{
  auto state = std::find_if (m_states.begin(), m_states.end(), [type](State_elem e) {return e.first == type;});
  auto remove = std::find(m_toRemove.begin(), m_toRemove.end(), type);
  if (state != m_states.end() && remove == m_toRemove.end())  // found in m_states, not found in m_toRemove
  {
    return true;
  }
  else
  {
    return false;
  }
}


4- The draw and update functions are almost identical. Duplicate code is Not Very Nice. The only differences are the functions calles (IsTransparent vs IsTranscendent, Draw vs Update). It should be possible to make a private helper function that does the searching and that accepts the functions that are used. I haven't worked this out yet. Probably it isn't worth the trouble in this simple case.

12
First of all: I like the book a lot. Thanks for it.

At the moment I'm going through the event manager chapter. I have one question and one remark.

The question:
You store the Binding objects in an unordered_map keyed on name. The only reason for this seems to be to enforce only one Binding per callback, since you never access the bindings map on name. Why is that important? I would drop that restriction, since there are reasons to want multiple bindings to the same callback. For example, if you want to bind <ctrl>-c to some event, you need two bindings: one for left control and one for right control. Differentiating between left and right shift, alt and control seems artificial to me. The user shouldn't be bothered with the technical fact that left and right key have different keycodes. So I would use a std::vector<Binding*> (or better still: std::vector<std::unique_ptr<Binding>> and even silently include double bindings when the user wants ctrl/alt/shift combinations.

The remark:
You do a great job of abstracting the event side of the event manager, but the callbacks are just wrapped function pointers. Why not put a Command pattern on the callback side? See http://gameprogrammingpatterns.com/command.html for a nice explanation. Of course that adds some code and complexity, but it enables some cool features:
1- if the AI also puts Command objects on the queue, enemies (and a demo mode, if applicable) can use the exact same control mechanism as the user-controlled character.
2- you can control all kinds of actors. So the player character is an actor, but the Window class can also be an actor (to handle focus gained/lost, toggle full screen). You could make anything that receives input an actor, using the same mechanism without messy exceptions to the rule.
3- it makes undo easy. In certain situations (think a strategy game where the player has to plan actions for many units before committing the turn) this could be a really nice touch.
Abstracting the callback side as well as the event side makes the event manager even more versatile.

And a minor point: you have many functions return a bool to indicate succes. It seems cleaner and more natural to me to use exceptions for that kind of behaviour. But that could just be me, I do java for a living.

13
SFML projects / Re: SFGUI (0.3.2 released)
« on: July 27, 2017, 03:41:11 pm »
@Parsley:

I don't think that using more than one desktop in SFGUI will work. See the second reply of eXpl0it3r to me:

Quote
As for desktops, not sure if multiple ones make sense.

I guess there are several basic approaches for traversing from one SFGUI screen to the next:

- keep all screens in memory and make sure only one is visible and sensitive at any given time (my approach)
- keep one window and on a navigation event empty it with RemoveAll and fill it again with the widget hierarchy of the next logical screen: you effectively reuse the sfg::Window object.
- on a navigation event destroy the sfg::Window and construct the sfg::Window of the next screen (Landry's approach)

What works best for your situation depends on your project: if the screens are lightweight (no big background graphics etc) and static, my approach works well. If the layout of the screens is dynamic and can be different every time depending on data, or the screens have a big memory footprint,  Landry's approach will work well.

I don't know how expensive destroying and reconstructing sfg::Window objects is. I don't expect that to be a dealbreaker, but if screen transitions become slow, it's probably worth the effort to try reusing it.

Note: I'm not an SFGUI developer, so take my remarks for what they're worth.

14
SFML projects / Re: SFGUI (0.3.2 released)
« on: July 26, 2017, 05:04:36 pm »
@eXpl0it3r

Thanks a lot for your replies, it has been really helpful. I just needed a lightbulb moment and you have provided that.

15
SFML projects / Re: SFGUI (0.3.2 released)
« on: July 26, 2017, 05:03:11 pm »
Hi Landry,

I have solved the problem by keeping all window objects, and just switching the sensitive/visible states. It works perfectly. Making the window insensitive, makes all widgets in the window insensitive, so there is no weird behaviour at all.

I pushed the responsibility of switching state into the manager. So the manager keeps track of the previous window and the next one. Prev is set equal to next at the top of the loop. Next is made active (sensitive and visible). Now the screen is run, the return value is captured in next. Prev is made inactive and the loop repeats. Easy peasy.

The good thing is, that all windows are present in the manager, so switching is really fast. I guess this will turn into a bad thing if there are many windows, or the windows become big in memory footprint. But for a simple wizard, it's perfect. Also, if the user uses the "back" navigation key, he gets the previous screen exactly as he left it. No need to retype text entries, or to reselect many options.

I also base the window layout on configuration in a SQLite database, but that is not  supposed to be dynamic, so not reloading it is not a problem.

Pages: [1] 2