From 7d8609bec44adcab67b0c1a78d560ef76afded8d Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sun, 8 Sep 2019 17:17:02 +0300 Subject: [PATCH] Add a system for animating widgets --- source/container.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++++ source/container.h | 7 +++++++ source/root.cpp | 6 ++++++ source/root.h | 1 + source/widget.cpp | 14 ++++++++++++++ source/widget.h | 9 +++++++++ 6 files changed, 81 insertions(+) diff --git a/source/container.cpp b/source/container.cpp index 91fa487..62e6e12 100644 --- a/source/container.cpp +++ b/source/container.cpp @@ -30,6 +30,8 @@ void Container::add(Widget &wdg) { wdg.set_parent(this); children.push_back(create_child(&wdg)); + if(wdg.get_animation_interval()) + check_animation_interval(); on_child_added(wdg); } @@ -41,6 +43,8 @@ void Container::remove(Widget &wdg) wdg.set_parent(0); delete *i; children.erase(i); + if(wdg.get_animation_interval()) + check_animation_interval(); on_child_removed(wdg); return; } @@ -165,6 +169,20 @@ Widget *Container::get_final_input_focus() const return input_focus; } +void Container::check_animation_interval() +{ + Time::TimeDelta shortest; + for(list::const_iterator i=children.begin(); i!=children.end(); ++i) + { + const Time::TimeDelta &child_iv = (*i)->widget->get_animation_interval(); + if(child_iv && (!shortest || child_iv::iterator i=children.begin(); i!=children.end(); ++i) + { + const Time::TimeDelta &child_iv = (*i)->widget->get_animation_interval(); + if(!child_iv) + continue; + + (*i)->time_since_animate += dt; + if((*i)->time_since_animate>=child_iv) + { + Time::TimeDelta child_dt = (*i)->time_since_animate; + (*i)->time_since_animate = min((*i)->time_since_animate-child_iv, child_iv); + (*i)->widget->animate(child_dt); + } + } +} + void Container::on_reparent() { for(list::iterator i=children.begin(); i!=children.end(); ++i) @@ -329,6 +365,7 @@ Container::Child::Child(Container &c, Widget *w): widget->signal_request_focus.connect(sigc::mem_fun(this, &Child::request_focus)); widget->signal_grab_pointer.connect(sigc::mem_fun(this, &Child::grab_pointer)); widget->signal_ungrab_pointer.connect(sigc::mem_fun(this, &Child::ungrab_pointer)); + widget->signal_request_animation.connect(sigc::mem_fun(this, &Child::request_animation)); } Container::Child::~Child() @@ -377,5 +414,12 @@ void Container::Child::ungrab_pointer() } } +void Container::Child::request_animation(const Time::TimeDelta &interval) +{ + if(!interval) + time_since_animate = Time::zero; + container.check_animation_interval(); +} + } // namespace GLtk } // namespace Msp diff --git a/source/container.h b/source/container.h index b463ff2..f68d81f 100644 --- a/source/container.h +++ b/source/container.h @@ -24,6 +24,7 @@ protected: { Container &container; Widget *widget; + Time::TimeDelta time_since_animate; Child(Container &, Widget *); virtual ~Child(); @@ -32,6 +33,7 @@ protected: void request_focus(); void grab_pointer(); void ungrab_pointer(); + void request_animation(const Time::TimeDelta &); }; std::list children; @@ -66,6 +68,10 @@ public: Widget *get_input_focus() const { return input_focus; } Widget *get_final_input_focus() const; +private: + void check_animation_interval(); + +public: virtual void button_press(int, int, unsigned); virtual void button_release(int, int, unsigned); virtual void pointer_motion(int, int); @@ -81,6 +87,7 @@ public: virtual bool character(wchar_t); virtual void focus_out(); virtual bool navigate(Navigation); + virtual void animate(const Time::TimeDelta &); protected: virtual void on_reparent(); virtual void on_child_added(Widget &) { } diff --git a/source/root.cpp b/source/root.cpp index 4a2d611..ad1ca5b 100644 --- a/source/root.cpp +++ b/source/root.cpp @@ -91,6 +91,12 @@ Root::~Root() void Root::tick() { + Time::TimeStamp t = Time::now(); + Time::TimeDelta dt = (last_tick ? t-last_tick : Time::zero); + last_tick = t; + + animate(dt); + if(tooltip_timeout && Time::now()>tooltip_timeout) { std::string tip; diff --git a/source/root.h b/source/root.h index 7d5a592..5de3626 100644 --- a/source/root.h +++ b/source/root.h @@ -39,6 +39,7 @@ private: int pointer_x; int pointer_y; Time::TimeStamp tooltip_timeout; + Time::TimeStamp last_tick; Widget *tooltip_target; Msp::GL::Camera camera; Msp::GL::Program *shprog; diff --git a/source/widget.cpp b/source/widget.cpp index aa05675..b40aa75 100644 --- a/source/widget.cpp +++ b/source/widget.cpp @@ -188,6 +188,20 @@ void Widget::set_state(State mask, State bits) rebuild(); } +void Widget::set_animation_interval(const Time::TimeDelta &iv) +{ + if(iv signal_request_focus; sigc::signal signal_grab_pointer; sigc::signal signal_ungrab_pointer; + sigc::signal signal_request_animation; protected: Geometry geom; @@ -51,6 +52,7 @@ protected: Container *parent; std::string tooltip; PartCache part_cache; + Time::TimeDelta anim_interval; Widget(); private: @@ -124,6 +126,12 @@ protected: public: State get_state() const { return state; } +protected: + void set_animation_interval(const Time::TimeDelta &); + void stop_animation(); +public: + const Time::TimeDelta &get_animation_interval() const { return anim_interval; } + protected: void rebuild(); virtual void rebuild_special(const Part &); @@ -149,6 +157,7 @@ public: virtual void focus_in(); virtual void focus_out(); virtual bool navigate(Navigation) { return false; } + virtual void animate(const Time::TimeDelta &) { } protected: virtual void on_geometry_change() { } virtual void on_style_change() { } -- 2.45.2