From: ChunEon Park <chuneon.park@samsung.com>
authorChunEon Park <chuneon.park@samsung.com>
Sun, 4 Jul 2010 23:41:48 +0000 (23:41 +0000)
committerCarsten Haitzler <raster@rasterman.com>
Sun, 4 Jul 2010 23:41:48 +0000 (23:41 +0000)
Subject: elm_animator

an animator wrapper - can be attached to an object (and be deleted if
object is deleted) and otherwise call a callback with a 0.0->1.0 value
where along the path you should be etc. etc. - ie handle higher level
animation runs.

SVN revision: 50039

src/lib/Elementary.h.in
src/lib/Makefile.am
src/lib/elm_animator.c [new file with mode: 0644]

index a906eceb0a786a0499b26a24160eeabd38df16aa..cb869c115ace0162a175b2cb3145d5cfeddf170c 100644 (file)
@@ -1567,6 +1567,26 @@ extern "C" {
    EAPI void         elm_mapbuf_alpha_set(Evas_Object *obj, Eina_Bool alpha);
    EAPI Eina_Bool    elm_mapbuf_alpha_get(const Evas_Object *obj);
 
+   /* animator */
+   typedef struct _Animator Elm_Animator;
+
+   typedef enum {ELM_ANIMATOR_CURVE_LINEAR, ELM_ANIMATOR_CURVE_IN_OUT, ELM_ANIMATOR_CURVE_IN, ELM_ANIMATOR_CURVE_OUT} Elm_Animator_Curve_Style; 
+
+   EAPI Elm_Animator* elm_animator_add(Evas_Object *parent);
+   EAPI void elm_animator_del(Elm_Animator *animator);
+   EAPI void elm_animator_duration_set(Elm_Animator *animator, double duration);
+   EAPI void elm_animator_operation_callback_set(Elm_Animator *animator, void (*func)(void *data, Elm_Animator *animator, double frame), void *data); 
+   EAPI void elm_animator_completion_callback_set(Elm_Animator *animator, void (*func)(void *data), void *data);
+   EAPI void elm_animator_stop(Elm_Animator *animator);
+   EAPI void elm_animator_repeat_set(Elm_Animator *animator, unsigned int repeat_cnt);
+   EAPI void elm_animator_animate(Elm_Animator *animator);
+   EAPI void elm_animator_curve_style_set(Elm_Animator *animator, Elm_Animator_Curve_Style cs);
+   EAPI void elm_animator_auto_reverse_set(Elm_Animator *animator, Eina_Bool reverse);
+   EAPI Eina_Bool elm_animator_auto_reverse_get(Elm_Animator *animator);
+   EAPI Eina_Bool elm_animator_operating_get(Elm_Animator *animator);
+   EAPI unsigned int elm_animator_repeat_get(Elm_Animator *animator);
+
+
 #ifdef __cplusplus
 }
 #endif
index 316dc38d18b94aa4bf34a7d70d64bf6cf4b479cc..e16578a715fba492f88390dc8e24bf1cc4262d6f 100644 (file)
@@ -76,6 +76,7 @@ elm_conform.c \
 elm_mapbuf.c \
 elm_thumb.c \
 elm_config.c \
+elm_animator.c \
 \
 elc_anchorblock.c \
 elc_anchorview.c \
diff --git a/src/lib/elm_animator.c b/src/lib/elm_animator.c
new file mode 100644 (file)
index 0000000..c682f9e
--- /dev/null
@@ -0,0 +1,409 @@
+#include <Elementary.h>
+
+/**
+ * @addtogroup Animator Animator
+ * @ingroup Elementary
+ *
+ * Support normalized frame value for animation.  
+*/
+
+struct _Animator
+{
+   Evas_Object *parent;
+   Ecore_Animator *animator;
+   double begin_time;
+   double cur_time;
+   double duration;
+   unsigned int repeat_cnt;
+   unsigned int cur_repeat_cnt;
+   double (*curve_op) (double frame);
+   void (*animator_op) (void *data, Elm_Animator *animator, double frame);
+   void *animator_arg;
+   void (*completion_op) (void *data);
+   void *completion_arg;
+   Eina_Bool auto_reverse:1;
+   Eina_Bool on_animating:1;
+};
+
+static double _animator_curve_linear(double frame);
+static double _animator_curve_in_out(double frame);
+static double _animator_curve_in(double frame);
+static double _animator_curve_out(double frame);
+static unsigned int _animator_compute_reverse_repeat_count(unsigned int cnt);
+static unsigned int _animator_compute_no_reverse_repeat_count(unsigned int cnt);
+static int _animator_animate_cb(void *data);
+static void _delete_animator(Elm_Animator *animator);
+static void _animator_parent_del(void *data);
+
+static unsigned int
+_animator_compute_reverse_repeat_count(unsigned int cnt)
+{
+   return ((cnt + 1) * 2) - 1;
+}
+
+static unsigned int
+_animator_compute_no_reverse_repeat_count(unsigned int cnt)
+{
+   return cnt / 2;
+}
+
+static double
+_animator_curve_linear(double frame)
+{
+   return frame;
+}
+
+static double
+_animator_curve_in_out(double frame)
+{
+   if (frame < 0.5)
+      return _animator_curve_out(frame * 2) * 0.5;
+   else
+      return (_animator_curve_in(frame * 2 - 1) * 0.5) + 0.5;
+}
+
+static double
+_animator_curve_in(double frame)
+{
+   return sqrt(1 - pow(frame - 1, 2));
+}
+
+static double
+_animator_curve_out(double frame)
+{
+   return 1 - sqrt(1 - pow(frame, 2));
+}
+
+static void
+_delete_animator(Elm_Animator *animator)
+{
+   if (animator->animator)
+     {
+       ecore_animator_del(animator->animator);
+       animator->animator = NULL;
+     }
+}
+
+static int
+_animator_animate_cb(void *data)
+{
+   Elm_Animator *animator = (Elm_Animator *) data;
+
+   animator->cur_time = ecore_loop_time_get();
+   double elapsed_time = animator->cur_time - animator->begin_time;
+
+   if (elapsed_time > animator->duration)
+      elapsed_time = animator->duration;
+
+   double frame = animator->curve_op(elapsed_time / animator->duration);
+
+   //Reverse?
+   if (animator->auto_reverse)
+     {
+       if ((animator->cur_repeat_cnt % 2) == 0)
+          frame = 1 - frame;
+     }
+
+   if (animator->duration > 0)
+      animator->animator_op(animator->animator_arg, animator, frame);
+
+   //Not end. Keep going.
+   if (elapsed_time < animator->duration)
+      return ECORE_CALLBACK_RENEW;
+
+   //Repeat and reverse and time done! 
+   if (animator->cur_repeat_cnt == 0)
+     {
+       animator->on_animating = EINA_FALSE;
+       _delete_animator(animator);
+       if (animator->completion_op)
+          animator->completion_op(animator->completion_arg);
+       return ECORE_CALLBACK_CANCEL;
+     }
+
+   //Repeat Case
+   --animator->cur_repeat_cnt;
+   animator->begin_time = ecore_loop_time_get();
+
+   return ECORE_CALLBACK_RENEW;
+}
+
+static void
+_animator_parent_del(void *data)
+{
+   elm_animator_del(data);
+}
+
+/**
+ * Get the value of reverse mode. 
+ *
+ * @param animator Animator object
+ * @return EINA_TRUE is reverse mode 
+ *
+ * @ingroup Animator 
+ */
+EAPI Eina_Bool
+elm_animator_auto_reverse_get(Elm_Animator *animator)
+{
+   if (!animator)
+      return EINA_FALSE;
+   return animator->auto_reverse;
+}
+
+/**
+ * Get the value of repeat count.
+ *
+ * @param animator Animator object
+ * @return Repeat count
+ *
+ * @ingroup Animator 
+ */
+EAPI unsigned int
+elm_animator_repeat_get(Elm_Animator *animator)
+{
+   if (!animator)
+      return EINA_FALSE;
+   return animator->repeat_cnt;
+}
+
+/**
+ * Set auto reverse function.  
+ *
+ * @param animator Animator object
+ * @param reverse Reverse or not
+ * 
+ * @ingroup Animator 
+ */
+EAPI void
+elm_animator_auto_reverse_set(Elm_Animator *animator, Eina_Bool reverse)
+{
+   if (!animator)
+      return;
+   if (animator->auto_reverse == reverse)
+      return;
+   animator->auto_reverse = reverse;
+   if (reverse)
+      animator->repeat_cnt =
+        _animator_compute_reverse_repeat_count(animator->repeat_cnt);
+   else
+      animator->repeat_cnt =
+        _animator_compute_no_reverse_repeat_count(animator->repeat_cnt);
+}
+
+/**
+ * Set the animation acceleration style. 
+ *
+ * @param animator Animator object
+ * @param cs Curve style. Default is ELM_ANIMATOR_CURVE_LINEAR 
+ *
+ * @ingroup Animator
+ */
+EAPI void
+elm_animator_curve_style_set(Elm_Animator *animator,
+                            Elm_Animator_Curve_Style cs)
+{
+   if (!animator)
+      return;
+
+   switch (cs)
+     {
+     case ELM_ANIMATOR_CURVE_LINEAR:
+       animator->curve_op = _animator_curve_linear;
+       break;
+     case ELM_ANIMATOR_CURVE_IN_OUT:
+       animator->curve_op = _animator_curve_in_out;
+       break;
+     case ELM_ANIMATOR_CURVE_IN:
+       animator->curve_op = _animator_curve_in;
+       break;
+     case ELM_ANIMATOR_CURVE_OUT:
+       animator->curve_op = _animator_curve_out;
+       break;
+     default:
+       animator->curve_op = _animator_curve_linear;
+       break;
+     }
+}
+
+/**
+ * Set the operation duration.  
+ *
+ * @param animator Animator object
+ * @param duration Duration in second 
+ *
+ * @ingroup Animator
+ */
+EAPI void
+elm_animator_duration_set(Elm_Animator *animator, double duration)
+{
+   if (!animator)
+      return;
+   if (animator->on_animating)
+      return;
+   animator->duration = duration;
+}
+
+/**
+ * Set the callback function for animator operation.  
+ * The range of callback function frame data is to 0 ~ 1
+ * User can refer this frame value for one's animation frame data. 
+ * @param animator Animator object
+ * @param op Callback function pointer 
+ * @param data Callback function user argument 
+ *
+ * @ingroup Animator
+ */
+EAPI void
+elm_animator_operation_callback_set(Elm_Animator *animator,
+                                   void (*func) (void *data,
+                                                 Elm_Animator *animator,
+                                                 double frame), void *data)
+{
+   if (!animator)
+      return;
+   if (animator->on_animating)
+      return;
+   animator->animator_op = func;
+   animator->animator_arg = data;
+}
+
+/**
+ * Add new animator. 
+ *
+ * @param parent Parent object
+ * @return animator object 
+ *
+ * @ingroup Animator
+ */
+EAPI Elm_Animator *
+elm_animator_add(Evas_Object *parent)
+{
+   Elm_Animator *animator = calloc(1, sizeof(Elm_Animator));
+
+   if (!animator)
+      return NULL;
+   elm_animator_auto_reverse_set(animator, EINA_FALSE);
+   elm_animator_curve_style_set(animator, ELM_ANIMATOR_CURVE_LINEAR);
+
+   if (parent)
+      evas_object_event_callback_add(parent, EVAS_CALLBACK_DEL,
+                                    _animator_parent_del, animator);
+
+   animator->parent = parent;
+
+   return animator;
+}
+
+/**
+ * Get the status for the animator operation.
+ *
+ * @param animator Animator object 
+ * @return EINA_TRUE is animator is operating. 
+ *
+ * @ingroup Animator
+ */
+EAPI Eina_Bool
+elm_animator_operating_get(Elm_Animator *animator)
+{
+   if (!animator)
+      return EINA_FALSE;
+   return animator->on_animating;
+}
+
+/**
+ * Delete animator. 
+ *
+ * @param animator Animator object 
+ *
+ * @ingroup Animator
+ */
+EAPI void
+elm_animator_del(Elm_Animator *animator)
+{
+   if (!animator)
+      return;
+   _delete_animator(animator);
+   
+   if(animator->parent) 
+       evas_object_event_callback_del(animator->parent, EVAS_CALLBACK_DEL, _animator_parent_del);
+   free(animator);
+}
+
+/**
+ * Set the callback function for the animator end.  
+ *
+ * @param  animator Animator object 
+ * @param  op Callback function pointer
+ * @param  data Callback function user argument 
+ *
+ * @ingroup Animator
+ */
+EAPI void
+elm_animator_completion_callback_set(Elm_Animator *animator,
+                                    void (*func) (void *data), void *data)
+{
+   if (!animator)
+      return;
+   if (animator->on_animating)
+      return;
+   animator->completion_op = func;
+   animator->completion_arg = data;
+}
+
+/**
+ * Stop animator.
+ *
+ * @param animator Animator object 
+ *
+ * @ingroup Animator
+ */
+EAPI void
+elm_animator_stop(Elm_Animator *animator)
+{
+   if (!animator)
+      return;
+   animator->on_animating = EINA_FALSE;
+   _delete_animator(animator);
+}
+
+/**
+ * Set the animator repeat count.
+ *
+ * @param  animator Animator object
+ * @param  repeat_cnt Repeat count
+ *
+ * @ingroup Animator
+ */
+EAPI void
+elm_animator_repeat_set(Elm_Animator *animator, unsigned int repeat_cnt)
+{
+   if (!animator)
+      return;
+   if (!animator->auto_reverse)
+      animator->repeat_cnt = repeat_cnt;
+   else
+      animator->repeat_cnt = _animator_compute_reverse_repeat_count(repeat_cnt);
+}
+
+/**
+ * Animate now.
+ *
+ * @param animator Animator object
+ *
+ * @ingroup Animator
+ */
+EAPI void
+elm_animator_animate(Elm_Animator *animator)
+{
+   if (!animator)
+      return;
+   if (!animator->animator_op)
+      return;
+   animator->begin_time = ecore_loop_time_get();
+   animator->on_animating = EINA_TRUE;
+   animator->cur_repeat_cnt = animator->repeat_cnt;
+   if (!animator->animator) 
+      animator->animator = ecore_animator_add(_animator_animate_cb, animator);
+   if (!animator->animator)
+      animator->on_animating = EINA_FALSE;
+}