Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Placing animation inside widget #335

Closed
KingDuckZ opened this issue Sep 4, 2018 · 6 comments
Closed

Placing animation inside widget #335

KingDuckZ opened this issue Sep 4, 2018 · 6 comments

Comments

@KingDuckZ
Copy link
Contributor

Sorry if this is a simple question but reading the documentation for 1.6.2 I can't find how to display animations inside widgets.

I want to display small icon-like animations in a grid. The grid itself should be placed on the main window and react to the window being resized, for example I want the grid to behave similarly to how the button behaves in the sample code on nana's home page. In other words the grid itself should be a widget (maybe a custom one I should write), where icons are at fixed position from each other, but the grid widget itself should not be at a fixed position in the main window.

All I could find so far is this. The example there takes fixed coordinates and draws on the window directly, so resizing the window will leave animations at fixed places.

What widget should I use to achieve this?

@cnjinhao
Copy link
Owner

cnjinhao commented Sep 4, 2018

I think the best way to achieve this is to provide a new animation::output() method that accepts the second parameter as a function object which determines the animation position when it renders.

animation ani;
ani.push_back(fset);
ani.output(fm, [&fm]{
    //Keeps the picture in the center of widget.
    return point((fm.size().width - picture_width) / 2, (fm.size().height - picture_height)/ 2);
});
ani.looped(true);
ani.play();

What about it?

@KingDuckZ
Copy link
Contributor Author

Would it be possible to make ani.output() take a nana::picture or nana::panel or something like that, so that I can place the picture/panel as normal within the form?

Also, if I want to write my own widget that aggregates nana::animation, I will be drawing to the widget itself and not to the window. Users (me) will then place that widget without thinking there are animations and whatnot inside. Is that possible at all? Sorry if it's not supposed to work like that, I'm new to nana.

@cnjinhao
Copy link
Owner

cnjinhao commented Sep 5, 2018

The first parameter of output accepts a widget which is not a lite-widget. e.g. panel<true> is acceptable, but panel<false> is not. Because lite-widgets do not have a drawer and graphics buffer.

For the second question, i mentioned a new output overloading that means it will renders the animation at a given position(the coordinate is referenced by the first parameter of output method) in the widget. In above example, it indicates the animation always keeps being rendered in the center of the widget no matter how the widget is resized.

@KingDuckZ
Copy link
Contributor Author

e.g. panel is acceptable, but panel is not.

What do you mean? What's acceptable? I think I tried passing a nana::panel but program errored out. I'll try again.

About the new overload you're proposing, I'm ok with it but I was hoping to do something like this:

fm.div("vert <><<><weight=80% text><>><><weight=24<><button><>><>");
fm["text"]<<lab;

meaning let Nana figure out where to place my grid. In fact there will be other things in the window, not just the icon grid! So I think it's going to be hard to figure out the exact placement relative to other widgets within my own lambda.

To give you some context, this is the grid I have (final size will be bigger):
nana_screenshot

Icon spacing is fixed, but the grid should be placed intelligently within the window. There could be many grids on the screen at the same time, likely 3. So placing is not as simple as "centre", it could be two on top, one at the bottom. Plus file menu, buttons, labels, frames, combo boxes, text boxes. If I understand the fm.div() example above, Nana is capable to manage all that already. If that's the case, I want my grid object to fit in with the rest of the widgets with as little special treatment as possible.

If I understand your proposal, you're thinking something like:

ani.output(fm, [&fm]{
    //Keeps the picture in the center of widget.
    return point((fm.size().width - picture_width - is_grid2_visible * (grid2.size().width + grid_spacing) / 2 + largest_widget_on_the_left.x + largest_widget_on_the_left.width + widget_spacing, /* something similar for y */);
});

That doesn't look very maintainable to me.
If, on the other hand, I could draw animations into a custom widget, then I'm happy to draw it at 0; 0 all the time inside my widget, and then just place that widget within the nana window.

@KingDuckZ
Copy link
Contributor Author

Can I get some help on this please? I've been stuck for days now. I managed to create a custom widget on which I can draw but I'm having several problems. First, this code just segfaults:

#include "nana/gui/animation.hpp"
#include <vector>
#include <iostream>

int main() {
        std::vector<nana::animation> test;
        for (int z = 0; z < 15; ++z) {
                std::cout << "emplace " << z << std::endl;
                test.emplace_back(3);
        }
        return 0;
}

The reason I'm trying to do it like that is because of the problems I first encountered with std::array<nana::animation, 15>. For example calling anims[z].fps(3); causes a deadlock. anims[z].looped(true) and anims[z].play() also cause a deadlock in some cases.

I was first calling those in my trigger::attached() function and pretty much everything deadlocks there. So I moved what I could to the trigger constructor, and only the call to fps() deadlocks there. The std::vector version segfaults.

@cnjinhao
Copy link
Owner

Here is the basic usage of animation.

int main()
{
	using namespace nana;

	//First, frames of animation should be given.
	frameset frmset;

	for (int i = 0; i < the_number_of_frames; ++i)
		//a frame is an image file
		frmset.push_back(paint::image("nth_frame_image.bmp"));

	form fm;

	//Display the animation in a panel
	panel<true> pnl{fm};

	fm.div("panel margin=10");
	fm["panel"] << pnl;
	fm.collocate();

	animation ani;
        //Assign the frames to the ani.
	ani.push_back(frmset);

	ani.output(pnl, nana::point(0,0));
	ani.looped(true);
	ani.play();

	fm.show();

	exec();
}

From your example.

int main() {
        std::vector<nana::animation> test;
        for (int z = 0; z < 15; ++z) {
                std::cout << "emplace " << z << std::endl;
                test.emplace_back(3);
        }
        return 0;
}

It crashes because the animation is non-copyable. But I didn't delete the copy-constructor and assignment operator. it's a bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants