Animations

Started by Xdesign, 22 December 2021, 21:38:07

Xdesign

I've got couple of questions.
First:
      Is it possible to add animations on setSize() and setPosition()?
      I think it'll make a great addition!

Second:
      BoxShadows? is it possible? I tried adding it to my project with sf::Vertex,
      but i figured its gonna take me a lot of time because its to complex for me.

Third (least important):
      Can you add sf::Vector2f support for setSize() setPosition() as well?
      I have to add x and y separately every time.

I do understand this gui is supposed to be simple, but can you atleast help me on how to implement my own animations?
I am enjoying tgui very much tho :D
Thank you in advance!

texus

QuoteIs it possible to add animations on setSize() and setPosition()?
You could look at MoveAnimation::update in TGUI/src/Animation.cpp to see the few lines that are needed to implement it. Now that I looked at the code myself, I realize that it looks like it already does exactly what you need though. I though that it would be more limited, but it accepts any start position or size, the only limitation is the functions in the Widget class itself. So maybe I'll have a look soon if I can add some additional functions to Widget to create a move and resize animation.

QuoteBoxShadows?
That looks difficult to do properly, I'm not even sure where to start with that (even if I had the time for it). Maybe you can emulate it by placing a Picture (which would contain an image of the shadow) behind the widget? If a "middle" rectangle is provided when loading the texture then 9-slice scaling is used so that you can give the picture any size without stretching the shadow. So as long as all shadows have the same width (e.g. 10px at each side of the widget) then you can do this with a single image.
Something like the following (code was not tested).
Code (cpp) Select
// shadow.png is 25x25 image with center 5x5 pixels as fully transparent and the pixels around it are the semi-transparent borders of width 10px
auto shadow = tgui::Picture::create(Texture{"shadow.png", {0, 0, 0, 0}, {10, 10, 5, 5});
shadow->setPosition({otherWidgetPos.x - 10, otherWidgetPos.y - 10});
shadow->setSize({otherWidgetSize.x + 20, otherWidgetSize.y + 20});
gui.add(shadow);


QuoteCan you add sf::Vector2f support for setSize() setPosition() as well?
They have an overload that takes a tgui::Vector2f type. Although I suggest you change your sf::Vector2f into a tgui::Vector2f in cases where you are only dealing with TGUI, there is actually an implicit conversion between the sf and tgui classes. The conversion doesn't happen automatically here because a Layout object is required, but all you have to do is put braces around your sf::Vector2f:
Code (cpp) Select
sf::Vector2f pos;
widget->setPosition({pos});  // equivalent to widget->setPosition(tgui::Vector2f(pos));

Xdesign

Im excited to try animations!
I thought using texture for boxshadows, but now that you added rounded panels this cant be used (i think).
Im gonna try adding it with vertex soon because i did some rounded rectangles last year in sfml and maybe i can do it.
I'll post if i make it!
This is the first time i see braces for implicit conversation tbh.
Thank you for quick response!

texus

#3
QuoteI thought using texture for boxshadows, but now that you added rounded panels this cant be used (i think).
The method would still work if you can create an image with such rounded borders. I wonder if this can be done easily in GIMP by using a few careful selections and radial gradient fills (I don't have time to check right now).
Edit: I've attached a file that I think could work (you would have to create it yourself depending on how much rounding the corners have). You can show it with the following code:
Code (cpp) Select
auto pic = tgui::Picture::create({"RoundBorders.png", {}, {9, 9, 2, 2}});
gui.add(pic);
pic->setSize(100, 100); // Any size you want


The file was created in GIMP by creating a 20x20 image with transparent background, adding a radial gradient fill of a circle with a diameter of 20px and then selecting a circle of diameter 10px in the center of the image and deleting those pixels (i.e. making them transparent again). This results in an image that can be used around widgets with 5px rounded corners, and the shadow is 5px thick. You can change the image size (same as outer circle diameter) and the inner circle diameter to adapt for different rounded corners and shadow thickness.
The middle rect when loading the image is always {imageWidth/2 - 1, imageHeight/2 - 1, 2, 2} for this situation.

This is of course only one way of doing it, you can do it yourself with vertices and sfml (which have the advantage of not needing a different image for different shadow thicknesses and rounded corners) or with some other tool.

QuoteThis is the first time i see braces for implicit conversation tbh.
My explanation about what the line does is technically wrong, the brackets aren't doing an implicit conversion.
The function expects a Layout2d object which can be implicitly converted from tgui::Vector2f. The tgui::Vector2f class can be implicitly converted from an sf::Vector2f. Since c++ doesn't do 2 implicit conversions in a row, it won't accept the function call if you pass an sf::Vector2f. The line I gave is in reality equivalent to "widget->setPosition(Layout2d(pos))" which would then use an implicit conversion from sf::Vector2f to tgui::Vector2f to pass to the Layout2d constructor.
The "widget->setPosition(tgui::Vector2f(pos))" call on the other hand would do an explicit conversion of the Vector2f types, but then do an implicit conversion to Layout2d. The end result is the same, but this is technically not what happens when writing "setPosition({pos})".

Xdesign

Okey, im gonna try with shadows with textures now because it seems simple.
I've looked up animations and got confused i bit.
I got MoveAnimation from priv namespace.
The animation works! Widgets are moving, but i cant figure out how to make gui handle updates for it.
Thx for explaining the rest :)

texus

#5
Quotei cant figure out how to make gui handle updates for it.
You can't yet, the gui only handles the show and hide animations. That's why I need to add some new functions to the Widget class.
If you just update the animation yourself then you however don't need the new functions and can already use the animations without waiting until I add proper support for them.

I've been looking at the code that has to be changed and noticed that this is annoying to handle in a backwards compatible way, so the new functions may only be added to TGUI 0.10-dev and not to 0.9

Edit: I have added the moveWithAnimation and resizeWithAnimation functions to Widget in the 0.10 branch on github.
The following example code would move the widget from its current position to x=100, y=50 over a duration of 0.5 seconds:
Code (cpp) Select
widget->moveWithAnimation({100, 50}, 500);

Xdesign

You are awesome!
Thank you.