diff --git a/.gitmodules b/.gitmodules
index e69de29..018c244 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "animation/third_party/glm"]
+ path = animation/third_party/glm
+ url = git://github.com/g-truc/glm
diff --git a/animation-glib/bounce/bounce.cpp b/animation-glib/bounce/bounce.cpp
new file mode 100644
index 0000000..72e06d1
--- /dev/null
+++ b/animation-glib/bounce/bounce.cpp
@@ -0,0 +1,349 @@
+/*
+ * animation-glib/bounce/bounce.cpp
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject implementation for a "bounce" animation.
+ */
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace agd = animation::geometry::dimension;
+namespace ab = animation::bounce;
+namespace as = animation::stepper;
+namespace at = animation::transform;
+
+struct _AnimationBounceAnimation
+{
+ AnimationTransformAnimation parent_instance;
+};
+
+typedef struct _AnimationBounceAnimationPrivate
+{
+} AnimationBounceAnimationPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (AnimationBounceAnimation,
+ animation_bounce_animation,
+ ANIMATION_TYPE_TRANSFORM_ANIMATION)
+
+enum {
+ PROP_0,
+ PROP_INITIAL_SCALE,
+ PROP_MAXIMUM_SCALE,
+ PROP_N_BOUNCE,
+ PROP_TARGET,
+ PROP_STEPPER,
+ NPROPS
+};
+
+static GParamSpec *animation_bounce_animation_props [NPROPS] = { NULL, };
+
+float
+animation_bounce_animation_get_initial_scale (AnimationBounceAnimation *animation)
+{
+ return LookupTypedInterfaceProp (G_OBJECT (animation))->InitialScale ();
+}
+
+void
+animation_bounce_animation_set_initial_scale (AnimationBounceAnimation *animation,
+ float initial_scale)
+{
+ LookupTypedInterfaceProp (G_OBJECT (animation))->InitialScale (initial_scale);
+}
+
+float
+animation_bounce_animation_get_maximum_scale (AnimationBounceAnimation *animation)
+{
+ return LookupTypedInterfaceProp (G_OBJECT (animation))->MaximumScale ();
+}
+
+void
+animation_bounce_animation_set_maximum_scale (AnimationBounceAnimation *animation,
+ float maximum_scale)
+{
+ LookupTypedInterfaceProp (G_OBJECT (animation))->MaximumScale (maximum_scale);
+}
+
+unsigned int
+animation_bounce_animation_get_n_bounce (AnimationBounceAnimation *animation)
+{
+ return LookupTypedInterfaceProp (G_OBJECT (animation))->NBounce ();
+}
+
+void
+animation_bounce_animation_set_n_bounce (AnimationBounceAnimation *animation,
+ unsigned int n_bounce)
+{
+ LookupTypedInterfaceProp (G_OBJECT (animation))->NBounce (n_bounce);
+}
+
+/**
+ * animation_bounce_animation_get_target:
+ * @animation: An #AnimationBounceAnimation
+ * @out_box: (out caller-allocates): Return location for an #AnimationBox
+ *
+ * Get the box representing the animation target.
+ */
+void
+animation_bounce_animation_get_target (AnimationBounceAnimation *animation,
+ AnimationBox *out_box)
+{
+ g_return_if_fail (out_box != nullptr);
+
+ animation::Box const &box =
+ LookupTypedInterfaceProp (G_OBJECT (animation))->Target ();
+
+ out_box->top_left.x = agd::get <0> (box.topLeft ());
+ out_box->top_left.y = agd::get <1> (box.topLeft ());
+ out_box->bottom_right.x = agd::get <0> (box.bottomRight ());
+ out_box->bottom_right.y = agd::get <1> (box.bottomRight ());
+}
+
+void
+animation_bounce_animation_set_stepper (AnimationBounceAnimation *animation,
+ AnimationStepper *stepper)
+{
+ animation::stepper::Stepper *stepper_ptr = nullptr;
+ g_object_get (stepper, "stepper", (gpointer) &stepper_ptr, NULL);
+
+ LookupTypedInterfaceProp (G_OBJECT (animation))->Stepper (*stepper_ptr);
+}
+
+/**
+ * animation_bounce_animation_get_stepper:
+ * @animation: An #AnimationBounceAnimation
+ *
+ * Returns: (transfer full): Get the stepper for this #AnimationBounceAnimation
+ */
+AnimationStepper *
+animation_bounce_animation_get_stepper (AnimationBounceAnimation *animation)
+{
+ auto const &stepper (LookupTypedInterfaceProp (G_OBJECT (animation))->Stepper ());
+
+ return animation_stepper_wrapper_new ((gpointer) &stepper);
+}
+
+static void
+animation_bounce_animation_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ case PROP_INITIAL_SCALE:
+ animation_bounce_animation_set_initial_scale (ANIMATION_BOUNCE_ANIMATION (object),
+ g_value_get_float (value));
+ break;
+ case PROP_MAXIMUM_SCALE:
+ animation_bounce_animation_set_maximum_scale (ANIMATION_BOUNCE_ANIMATION (object),
+ g_value_get_float (value));
+ break;
+ case PROP_N_BOUNCE:
+ animation_bounce_animation_set_n_bounce (ANIMATION_BOUNCE_ANIMATION (object),
+ g_value_get_uint (value));
+ break;
+ case PROP_TARGET:
+ /* No-op here to handle the constructor */
+ break;
+ case PROP_STEPPER:
+ animation_bounce_animation_set_stepper (ANIMATION_BOUNCE_ANIMATION (object),
+ ANIMATION_STEPPER (g_value_get_object (value)));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+animation_bounce_animation_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ AnimationBounceAnimation *bounce_animation = ANIMATION_BOUNCE_ANIMATION (object);
+
+ switch (prop_id)
+ {
+ case PROP_INITIAL_SCALE:
+ g_value_set_float (value, animation_bounce_animation_get_initial_scale (bounce_animation));
+ break;
+ case PROP_MAXIMUM_SCALE:
+ g_value_set_float (value, animation_bounce_animation_get_maximum_scale (bounce_animation));
+ break;
+ case PROP_N_BOUNCE:
+ g_value_set_uint (value, animation_bounce_animation_get_n_bounce (bounce_animation));
+ break;
+ case PROP_TARGET:
+ {
+ AnimationBox target;
+ animation_bounce_animation_get_target (bounce_animation, &target);
+
+ g_value_set_boxed (value, &target);
+ break;
+ }
+ case PROP_STEPPER:
+ g_value_take_object (value, animation_bounce_animation_get_stepper (bounce_animation));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static GObject *
+animation_bounce_animation_constructor (GType type,
+ unsigned int n_construct_params,
+ GObjectConstructParam *construct_params)
+{
+ replace_named_pointer_prop_in_construct_params_if_null (construct_params,
+ n_construct_params,
+ "stepper",
+ g_value_get_object,
+ g_value_set_object,
+ []() -> gpointer {
+ return animation_linear_stepper_new (300);
+ });
+
+ const char * const wanted_properties[] = {
+ "initial-scale",
+ "maximum-scale",
+ "n-bounce",
+ "target",
+ "stepper",
+ NULL
+ };
+ g_autoptr(GHashTable) properties_table =
+ static_hash_table_of_values_for_specs (wanted_properties,
+ construct_params,
+ n_construct_params);
+
+ auto *interface =
+ static_cast (InterfaceConstructor ::construct (
+ ForwardFromValueHT (properties_table, g_value_get_float, "initial-scale"),
+ ForwardFromValueHT (properties_table, g_value_get_float, "maximum-scale"),
+ ForwardFromValueHT (properties_table, g_value_get_uint, "n-bounce"),
+ ForwardFromValueHT (properties_table, animation_box_from_gvalue, "target"),
+ ForwardFromValueHT (properties_table, animation_stepper_from_gvalue, "stepper")
+ ));
+
+ replace_interface_prop_in_construct_params (construct_params,
+ n_construct_params,
+ g_steal_pointer (&interface));
+
+ return G_OBJECT_CLASS (animation_bounce_animation_parent_class)->constructor (type,
+ n_construct_params,
+ construct_params);
+}
+
+static void
+animation_bounce_animation_init (AnimationBounceAnimation *model)
+{
+}
+
+
+static void
+animation_bounce_animation_class_init (AnimationBounceAnimationClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructor = animation_bounce_animation_constructor;
+ object_class->get_property = animation_bounce_animation_get_property;
+ object_class->set_property = animation_bounce_animation_set_property;
+
+ animation_bounce_animation_props[PROP_INITIAL_SCALE] =
+ g_param_spec_float ("initial-scale",
+ "Initial Scale",
+ "The initial scale of the animation",
+ 0.1f,
+ 1.0f,
+ 0.7f,
+ static_cast (G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ animation_bounce_animation_props[PROP_MAXIMUM_SCALE] =
+ g_param_spec_float ("maximum-scale",
+ "Maximum Scale",
+ "The maximum scale of the animation",
+ 1.0f,
+ 3.0f,
+ 1.2f,
+ static_cast (G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ animation_bounce_animation_props[PROP_N_BOUNCE] =
+ g_param_spec_uint ("n-bounce",
+ "Number of Bounces",
+ "The number of bounces in the animation",
+ 1,
+ 10,
+ 1,
+ static_cast (G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ animation_bounce_animation_props[PROP_TARGET] =
+ g_param_spec_boxed ("target",
+ "Target Box",
+ "Box that we are animating to",
+ ANIMATION_TYPE_BOX,
+ static_cast (G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+
+ animation_bounce_animation_props[PROP_STEPPER] =
+ g_param_spec_object ("stepper",
+ "Stepper",
+ "Stepper to use to progress the animation",
+ ANIMATION_TYPE_STEPPER,
+ static_cast (G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_properties (object_class,
+ NPROPS,
+ animation_bounce_animation_props);
+}
+
+/**
+ * animation_bounce_new:
+ * @initial_scale: Scale factor that the surface will initially have.
+ * @maximum_scale: Scale factor that the surface will have at maximum.
+ * @n_bounce: Number of bounces.
+ * @target: The #AnimationBox that we are animating to.
+ * @stepper: The #AnimationStepper of the animation.
+ *
+ * Returns: (transfer full): A new #AnimationBounceAnimation.
+ */
+AnimationBounceAnimation *
+animation_bounce_new (float initial_scale,
+ float maximum_scale,
+ unsigned int n_bounce,
+ const AnimationBox *target,
+ AnimationStepper *stepper)
+{
+ return ANIMATION_BOUNCE_ANIMATION (g_object_new (ANIMATION_TYPE_BOUNCE_ANIMATION,
+ "initial-scale", initial_scale,
+ "maximum-scale", maximum_scale,
+ "n-bounce", n_bounce,
+ "target", target,
+ "stepper", stepper,
+ NULL));
+}
diff --git a/animation-glib/bounce/bounce.h b/animation-glib/bounce/bounce.h
new file mode 100644
index 0000000..684f44f
--- /dev/null
+++ b/animation-glib/bounce/bounce.h
@@ -0,0 +1,61 @@
+/*
+ * animation-glib/bounce/bounce.h
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject Interface for "bounce" animation.
+ */
+#pragma once
+
+#include
+
+#include
+#include
+#include
+#include
+
+G_BEGIN_DECLS
+
+#define ANIMATION_TYPE_BOUNCE_ANIMATION animation_bounce_animation_get_type ()
+G_DECLARE_FINAL_TYPE (AnimationBounceAnimation, animation_bounce_animation, ANIMATION, BOUNCE_ANIMATION, AnimationTransformAnimation)
+
+float animation_bounce_animation_get_initial_scale (AnimationBounceAnimation *animation);
+void animation_bounce_animation_set_initial_scale (AnimationBounceAnimation *animation,
+ float initial_scale);
+
+float animation_bounce_animation_get_maximum_scale (AnimationBounceAnimation *animation);
+void animation_bounce_animation_set_maximum_scale (AnimationBounceAnimation *animation,
+ float maximum_scale);
+
+unsigned int animation_bounce_animation_get_n_bounce (AnimationBounceAnimation *animation);
+void animation_bounce_animation_set_n_bounce (AnimationBounceAnimation *animation,
+ unsigned int n_bounce);
+
+void animation_bounce_animation_get_target (AnimationBounceAnimation *animation,
+ AnimationBox *out_box);
+
+void animation_bounce_animation_set_stepper (AnimationBounceAnimation *animation,
+ AnimationStepper *stepper);
+AnimationStepper * animation_bounce_animation_get_stepper (AnimationBounceAnimation *animation);
+
+AnimationBounceAnimation * animation_bounce_new (float initial_scale,
+ float maximum_scale,
+ unsigned int n_bounce,
+ const AnimationBox *target,
+ AnimationStepper *stepper);
+
+G_END_DECLS
+
+#pragma once
diff --git a/animation-glib/bounce/meson.build b/animation-glib/bounce/meson.build
new file mode 100644
index 0000000..0c47361
--- /dev/null
+++ b/animation-glib/bounce/meson.build
@@ -0,0 +1,18 @@
+# /animation/bounce/meson.build
+#
+# Build the libanimation library (bounce animation component).
+#
+# See /LICENCE.md for Copyright information.
+
+bounce_introspectable_sources = files([
+ 'bounce.cpp'
+])
+
+bounce_headers = files([
+ 'bounce.h'
+])
+
+animation_glib_introspectable_sources += bounce_introspectable_sources
+animation_glib_headers += bounce_headers
+
+install_headers(bounce_headers, subdir: join_paths(animation_headers_subdir, 'bounce'))
diff --git a/animation-glib/box.cpp b/animation-glib/box.cpp
new file mode 100644
index 0000000..ca21198
--- /dev/null
+++ b/animation-glib/box.cpp
@@ -0,0 +1,40 @@
+/*
+ * animation-glib/box.cpp
+ *
+ * Copyright 2018 Endless Mobile, Inc.
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject Interface for "wobbly" textures, box
+ * type implementation.
+ */
+
+#include
+
+static gpointer
+animation_box_copy (gpointer ptr)
+{
+ AnimationBox *src = reinterpret_cast (ptr);
+ AnimationBox *dst = g_new0 (AnimationBox, 1);
+
+ *dst = *src;
+
+ return reinterpret_cast (dst);
+}
+
+G_DEFINE_BOXED_TYPE (AnimationBox,
+ animation_box,
+ animation_box_copy,
+ g_free)
diff --git a/animation-glib/box.h b/animation-glib/box.h
new file mode 100644
index 0000000..30b635c
--- /dev/null
+++ b/animation-glib/box.h
@@ -0,0 +1,39 @@
+/*
+ * animation-glib/box.h
+ *
+ * Copyright 2018 Endless Mobile, Inc.
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject Interface for "wobbly" textures, 2D box type.
+ */
+#pragma once
+
+#include
+
+#include
+
+G_BEGIN_DECLS
+
+typedef struct {
+ AnimationVector top_left;
+ AnimationVector bottom_right;
+} AnimationBox;
+
+#define ANIMATION_TYPE_BOX animation_box_get_type ()
+
+GType animation_box_get_type (void);
+
+G_END_DECLS
diff --git a/animation-glib/constructor-helpers.cpp b/animation-glib/constructor-helpers.cpp
new file mode 100644
index 0000000..41af673
--- /dev/null
+++ b/animation-glib/constructor-helpers.cpp
@@ -0,0 +1,156 @@
+/*
+ * animation-glib/constructor-helpers.cpp
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * Helpers for constructing C++ objects directly from GObject properties
+ * in a GObject constructor.
+ */
+
+#include
+
+#include "constructor-helpers.h"
+
+GHashTable *
+static_hash_table_of_values_for_specs (const char * const *wanted_properties,
+ GObjectConstructParam *construct_params,
+ unsigned int n_construct_params)
+{
+ g_autoptr(GHashTable) ht = g_hash_table_new (g_str_hash, g_str_equal);
+
+ /* Insert all the properties we intend to
+ * have in the hash table, with NULL as
+ * their value. */
+ for (const char * const *iter = wanted_properties; *iter != NULL; ++iter)
+ g_hash_table_insert (ht,
+ (gpointer) (*iter),
+ NULL);
+
+ /* Now go through all the construct params and insert
+ * their value pointer into the hash table. */
+ for (unsigned int i = 0; i < n_construct_params; ++i)
+ {
+ GParamSpec *pspec = construct_params[i].pspec;
+ GValue *value = construct_params[i].value;
+
+ if (g_hash_table_contains (ht, pspec->name))
+ g_hash_table_insert (ht,
+ (gpointer) pspec->name,
+ value);
+ }
+
+ return reinterpret_cast (g_steal_pointer (&ht));
+}
+
+/**
+ * replace_construct_param:
+ * @construct_params: (array length=n_construct_params) An array of #GObjectConstructParam
+ * @n_construct_params: Number of elements in @construct_params.
+ * @prop_name: The name of the construct prop to replace the value of.
+ * @initialize_func: A function which sets the GValue to something sensible.
+ *
+ * Replace a construction parameter @prop_name in the
+ * passed @construct_params by using the passed @initialize_func.
+ *
+ * This function must always replace one construct parameter, it is
+ * an error to pass a @prop_name that is not in the @construct_params.
+ */
+void
+replace_construct_param (GObjectConstructParam *construct_params,
+ unsigned int n_construct_params,
+ const char *prop_name,
+ AnimationConstructorHelpersInitializeValueFunc initialize_func,
+ gpointer initialize_func_data)
+{
+ /* The prop should always be found in the array so that we can replace
+ * it, this function doesn't support appending the prop. That means
+ * that the relevant prop must always G_PARAM_CONSTRUCT or
+ * G_PARAM_CONSTRUCT_ONLY. */
+ for (unsigned int i = 0; i < n_construct_params; ++i)
+ {
+ if (g_strcmp0 (construct_params[i].pspec->name, prop_name) == 0)
+ {
+ g_value_unset (construct_params[i].value);
+ initialize_func (construct_params[i].value, initialize_func_data);
+ return;
+ }
+ }
+
+ g_assert_not_reached ();
+}
+
+template
+static typename std::result_of ::type
+invoke_function_thunk (Args... args, gpointer lambda)
+{
+ FunctionType *f = reinterpret_cast (lambda);
+
+ return (*f)(args...);
+}
+
+
+void
+replace_named_pointer_prop_in_construct_params (GObjectConstructParam *construct_params,
+ unsigned int n_construct_params,
+ const char *prop_name,
+ gpointer ptr)
+{
+ auto set_value = [ptr](GValue *value) {
+ g_value_init (value, G_TYPE_POINTER);
+ g_value_set_pointer (value, ptr);
+ };
+ replace_construct_param (construct_params,
+ n_construct_params,
+ prop_name,
+ (AnimationConstructorHelpersInitializeValueFunc) invoke_function_thunk ,
+ &set_value);
+}
+
+void
+replace_interface_prop_in_construct_params (GObjectConstructParam *construct_params,
+ unsigned int n_construct_params,
+ gpointer interface)
+{
+ replace_named_pointer_prop_in_construct_params (construct_params,
+ n_construct_params,
+ "interface",
+ interface);
+}
+
+void
+replace_named_pointer_prop_in_construct_params_if_null (GObjectConstructParam *construct_params,
+ unsigned int n_construct_params,
+ const char *prop_name,
+ AnimationConstructorHelpersGValueGetPointerFunc get_func,
+ AnimationConstructorHelpersGValueSetPointerFunc set_func,
+ AnimationConstructorHelpersConstructDefaultValueFunc construct_func)
+{
+ /* The prop should always be found in the array so that we can replace
+ * it, this function doesn't support appending the prop. That means
+ * that the relevant prop must always G_PARAM_CONSTRUCT or
+ * G_PARAM_CONSTRUCT_ONLY. */
+ for (unsigned int i = 0; i < n_construct_params; ++i)
+ {
+ if (g_strcmp0 (construct_params[i].pspec->name, prop_name) == 0)
+ {
+ if (get_func (construct_params[i].value) == nullptr)
+ set_func (construct_params[i].value, construct_func ());
+
+ return;
+ }
+ }
+
+ g_assert_not_reached ();
+}
diff --git a/animation-glib/constructor-helpers.h b/animation-glib/constructor-helpers.h
new file mode 100644
index 0000000..1c3c72b
--- /dev/null
+++ b/animation-glib/constructor-helpers.h
@@ -0,0 +1,163 @@
+/*
+ * animation-glib/constructor-helpers.h
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * Helpers for constructing C++ objects directly from GObject properties
+ * in a GObject constructor.
+ */
+
+#pragma once
+
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+G_BEGIN_DECLS
+
+inline GValue *
+lookup_gvalue (GHashTable *ht, const char *key)
+{
+ return reinterpret_cast (g_hash_table_lookup (ht, key));
+}
+
+GHashTable *
+static_hash_table_of_values_for_specs (const char * const *wanted_properties,
+ GObjectConstructParam *construct_params,
+ unsigned int n_construct_params);
+
+typedef void (*AnimationConstructorHelpersInitializeValueFunc) (GValue *value,
+ gpointer user_data);
+
+void replace_construct_param (GObjectConstructParam *construct_params,
+ unsigned int n_construct_params,
+ const char *prop_name,
+ AnimationConstructorHelpersInitializeValueFunc initialize_func,
+ gpointer initialize_func_data);
+
+void replace_named_pointer_prop_in_construct_params (GObjectConstructParam *construct_params,
+ unsigned int n_construct_params,
+ const char *prop_name,
+ gpointer ptr);
+
+void replace_interface_prop_in_construct_params (GObjectConstructParam *construct_params,
+ unsigned int n_construct_params,
+ gpointer interface);
+
+typedef gpointer (*AnimationConstructorHelpersGValueGetPointerFunc) (const GValue *value);
+typedef void (*AnimationConstructorHelpersGValueSetPointerFunc) (GValue *value, gpointer);
+typedef gpointer (*AnimationConstructorHelpersConstructDefaultValueFunc) (void);
+
+void replace_named_pointer_prop_in_construct_params_if_null (GObjectConstructParam *construct_params,
+ unsigned int n_construct_params,
+ const char *prop_name,
+ AnimationConstructorHelpersGValueGetPointerFunc get_func,
+ AnimationConstructorHelpersGValueSetPointerFunc set_func,
+ AnimationConstructorHelpersConstructDefaultValueFunc construct_func);
+
+G_END_DECLS
+
+#ifdef __cplusplus
+inline animation::Box
+animation_box_from_gvalue (GValue *value)
+{
+ AnimationBox *boxed_box = reinterpret_cast (g_value_get_boxed (value));
+
+ if (boxed_box == nullptr)
+ return animation::Box (animation::Point (0, 0),
+ animation::Point (1, 1));
+
+ return animation::Box (animation::Point (boxed_box->top_left.x,
+ boxed_box->top_left.y),
+ animation::Point (boxed_box->bottom_right.x,
+ boxed_box->bottom_right.y));
+}
+
+inline animation::Point
+animation_point_from_gvalue (GValue *value)
+{
+ AnimationVector *boxed_point = reinterpret_cast (g_value_get_boxed (value));
+
+ if (boxed_point == nullptr)
+ return animation::geometry::PointModel (0, 0);
+
+ return animation::Point (boxed_point->x, boxed_point->y);
+}
+
+inline animation::geometry::PointModel
+animation_point_size_t_from_gvalue (GValue *value)
+{
+ AnimationVector *boxed_point = reinterpret_cast (g_value_get_boxed (value));
+
+ if (boxed_point == nullptr)
+ return animation::geometry::PointModel (0, 0);
+
+ return animation::geometry::PointModel (boxed_point->x, boxed_point->y);
+}
+
+inline animation::stepper::Stepper
+animation_stepper_from_gvalue (GValue *value)
+{
+ static const unsigned int DefaultAnimationLength = 300;
+
+ AnimationStepper *stepper =
+ reinterpret_cast (g_value_get_object (value));
+ animation::stepper::Stepper *stepper_ptr = NULL;
+
+ if (stepper != nullptr)
+ {
+ g_object_get (G_OBJECT (stepper), "stepper", &stepper_ptr, NULL);
+ return *stepper_ptr;
+ }
+
+ return animation::stepper::Linear (DefaultAnimationLength);
+}
+
+template
+typename std::result_of ::type ForwardFromValueHT (GHashTable *ht,
+ Marshaller &&m,
+ const char *name)
+{
+ return m (lookup_gvalue (ht, name));
+}
+
+template
+struct InterfaceConstructor
+{
+ template
+ static Interface * construct (ArgTypes&&... args)
+ {
+ return new Interface (args...);
+ }
+};
+
+template
+DerivedType * LookupTypedInterfaceProp (GObject *object)
+{
+ InterfaceType *iface = nullptr;
+ g_object_get (object, "interface", (gpointer) &iface, NULL);
+
+ return static_cast (iface);
+}
+#endif
diff --git a/animation-glib/glide/glide.cpp b/animation-glib/glide/glide.cpp
new file mode 100644
index 0000000..525f959
--- /dev/null
+++ b/animation-glib/glide/glide.cpp
@@ -0,0 +1,404 @@
+/*
+ * animation-glib/glide/glide.cpp
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject implementation for a "glide" animation.
+ */
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace agd = animation::geometry::dimension;
+namespace ag = animation::glide;
+namespace at = animation::transform;
+
+struct _AnimationGlideAnimation
+{
+ AnimationTransformAnimation parent_instance;
+};
+
+typedef struct _AnimationGlideAnimationPrivate
+{
+} AnimationGlideAnimationPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (AnimationGlideAnimation,
+ animation_glide_animation,
+ ANIMATION_TYPE_TRANSFORM_ANIMATION)
+
+enum {
+ PROP_0,
+ PROP_INITIAL_DISTANCE,
+ PROP_X_ROTATION_ANGLE_DEGREES,
+ PROP_Y_ROTATION_ANGLE_DEGREES,
+ PROP_X_AXIS_LOCATION_UNIT,
+ PROP_Y_AXIS_LOCATION_UNIT,
+ PROP_SCREEN_WIDTH,
+ PROP_TARGET,
+ PROP_STEPPER,
+ NPROPS
+};
+
+static GParamSpec *animation_glide_animation_props [NPROPS] = { NULL, };
+
+void
+animation_glide_animation_set_initial_distance (AnimationGlideAnimation *animation,
+ float initial_distance)
+{
+ LookupTypedInterfaceProp (G_OBJECT (animation))->InitialDistance (initial_distance);
+}
+
+float
+animation_glide_animation_get_initial_distance (AnimationGlideAnimation *animation)
+{
+ return LookupTypedInterfaceProp (G_OBJECT (animation))->InitialDistance ();
+}
+
+void
+animation_glide_animation_set_x_rotation_angle_degrees (AnimationGlideAnimation *animation,
+ float x_rotation_angle_degrees)
+{
+ LookupTypedInterfaceProp (G_OBJECT (animation))->XRotationAngleDegrees (x_rotation_angle_degrees);
+}
+
+float
+animation_glide_animation_get_x_rotation_angle_degrees (AnimationGlideAnimation *animation)
+{
+ return LookupTypedInterfaceProp (G_OBJECT (animation))->XRotationAngleDegrees ();
+}
+
+void
+animation_glide_animation_set_y_rotation_angle_degrees (AnimationGlideAnimation *animation,
+ float y_rotation_angle_degrees)
+{
+ LookupTypedInterfaceProp (G_OBJECT (animation))->YRotationAngleDegrees (y_rotation_angle_degrees);
+}
+
+float
+animation_glide_animation_get_y_rotation_angle_degrees (AnimationGlideAnimation *animation)
+{
+ return LookupTypedInterfaceProp (G_OBJECT (animation))->YRotationAngleDegrees ();
+}
+
+void
+animation_glide_animation_set_x_axis_location_unit (AnimationGlideAnimation *animation,
+ float x_axis_location_unit)
+{
+ LookupTypedInterfaceProp (G_OBJECT (animation))->XAxisLocationUnit (x_axis_location_unit);
+}
+
+float
+animation_glide_animation_get_x_axis_location_unit (AnimationGlideAnimation *animation)
+{
+ return LookupTypedInterfaceProp (G_OBJECT (animation))->XAxisLocationUnit ();
+}
+
+void
+animation_glide_animation_set_y_axis_location_unit (AnimationGlideAnimation *animation,
+ float y_axis_location_unit)
+{
+ LookupTypedInterfaceProp (G_OBJECT (animation))->YAxisLocationUnit (y_axis_location_unit);
+}
+
+float
+animation_glide_animation_get_y_axis_location_unit (AnimationGlideAnimation *animation)
+{
+ return LookupTypedInterfaceProp (G_OBJECT (animation))->YAxisLocationUnit ();
+}
+
+void
+animation_glide_animation_set_stepper (AnimationGlideAnimation *animation,
+ AnimationStepper *stepper)
+{
+ animation::stepper::Stepper *stepper_ptr = nullptr;
+ g_object_get (stepper, "stepper", (gpointer) &stepper_ptr, NULL);
+
+ LookupTypedInterfaceProp (G_OBJECT (animation))->Stepper (*stepper_ptr);
+}
+
+/**
+ * animation_glide_animation_get_stepper:
+ * @animation: An #AnimationGlideAnimation
+ *
+ * Returns: (transfer full): Get the stepper for this #AnimationGlideAnimation
+ */
+AnimationStepper *
+animation_glide_animation_get_stepper (AnimationGlideAnimation *animation)
+{
+ auto const &stepper (LookupTypedInterfaceProp (G_OBJECT (animation))->Stepper ());
+
+ return animation_stepper_wrapper_new ((gpointer) &stepper);
+}
+
+static void
+animation_glide_animation_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ AnimationGlideAnimation *glide_animation = ANIMATION_GLIDE_ANIMATION (object);
+
+ switch (prop_id)
+ {
+ case PROP_INITIAL_DISTANCE:
+ animation_glide_animation_set_initial_distance (glide_animation, g_value_get_float (value));
+ break;
+ case PROP_X_ROTATION_ANGLE_DEGREES:
+ animation_glide_animation_set_x_rotation_angle_degrees (glide_animation, g_value_get_float (value));
+ break;
+ case PROP_Y_ROTATION_ANGLE_DEGREES:
+ animation_glide_animation_set_y_rotation_angle_degrees (glide_animation, g_value_get_float (value));
+ break;
+ case PROP_X_AXIS_LOCATION_UNIT:
+ animation_glide_animation_set_x_axis_location_unit (glide_animation, g_value_get_float (value));
+ break;
+ case PROP_Y_AXIS_LOCATION_UNIT:
+ animation_glide_animation_set_y_axis_location_unit (glide_animation, g_value_get_float (value));
+ break;
+ case PROP_SCREEN_WIDTH:
+ /* Not writable, except on construction */
+ break;
+ case PROP_TARGET:
+ /* Not writable, except on construction */
+ break;
+ case PROP_STEPPER:
+ animation_glide_animation_set_stepper (glide_animation,
+ ANIMATION_STEPPER (g_value_get_object (value)));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+animation_glide_animation_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ AnimationGlideAnimation *glide_animation = ANIMATION_GLIDE_ANIMATION (object);
+
+ switch (prop_id)
+ {
+ case PROP_INITIAL_DISTANCE:
+ g_value_set_float (value, animation_glide_animation_get_initial_distance (glide_animation));
+ break;
+ case PROP_X_ROTATION_ANGLE_DEGREES:
+ g_value_set_float (value, animation_glide_animation_get_x_rotation_angle_degrees (glide_animation));
+ break;
+ case PROP_Y_ROTATION_ANGLE_DEGREES:
+ g_value_set_float (value, animation_glide_animation_get_y_rotation_angle_degrees (glide_animation));
+ break;
+ case PROP_X_AXIS_LOCATION_UNIT:
+ g_value_set_float (value, animation_glide_animation_get_x_axis_location_unit (glide_animation));
+ break;
+ case PROP_Y_AXIS_LOCATION_UNIT:
+ g_value_set_float (value, animation_glide_animation_get_y_axis_location_unit (glide_animation));
+ break;
+ case PROP_SCREEN_WIDTH:
+ /* Not readable */
+ break;
+ case PROP_TARGET:
+ /* Not readable */
+ break;
+ case PROP_STEPPER:
+ g_value_take_object (value, animation_glide_animation_get_stepper (glide_animation));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static GObject *
+animation_glide_animation_constructor (GType type,
+ unsigned int n_construct_params,
+ GObjectConstructParam *construct_params)
+{
+ replace_named_pointer_prop_in_construct_params_if_null (construct_params,
+ n_construct_params,
+ "stepper",
+ g_value_get_object,
+ g_value_set_object,
+ []() -> gpointer {
+ return animation_linear_stepper_new (300);
+ });
+
+
+ const char * const wanted_properties[] = {
+ "initial-distance",
+ "x-rotation-angle-degrees",
+ "y-rotation-angle-degrees",
+ "x-axis-location-unit",
+ "y-axis-location-unit",
+ "screen-width",
+ "target",
+ "stepper",
+ NULL
+ };
+ g_autoptr(GHashTable) properties_table =
+ static_hash_table_of_values_for_specs (wanted_properties,
+ construct_params,
+ n_construct_params);
+
+ auto *interface =
+ static_cast (InterfaceConstructor ::construct (
+ ForwardFromValueHT (properties_table, g_value_get_float, "initial-distance"),
+ ForwardFromValueHT (properties_table, g_value_get_float, "x-rotation-angle-degrees"),
+ ForwardFromValueHT (properties_table, g_value_get_float, "y-rotation-angle-degrees"),
+ ForwardFromValueHT (properties_table, g_value_get_float, "x-axis-location-unit"),
+ ForwardFromValueHT (properties_table, g_value_get_float, "y-axis-location-unit"),
+ ForwardFromValueHT (properties_table, g_value_get_uint, "screen-width"),
+ ForwardFromValueHT (properties_table, animation_box_from_gvalue, "target"),
+ ForwardFromValueHT (properties_table, animation_stepper_from_gvalue, "stepper")
+ ));
+
+ replace_interface_prop_in_construct_params (construct_params,
+ n_construct_params,
+ g_steal_pointer (&interface));
+
+ return G_OBJECT_CLASS (animation_glide_animation_parent_class)->constructor (type,
+ n_construct_params,
+ construct_params);
+}
+
+static void
+animation_glide_animation_init (AnimationGlideAnimation *model)
+{
+}
+
+
+static void
+animation_glide_animation_class_init (AnimationGlideAnimationClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructor = animation_glide_animation_constructor;
+ object_class->get_property = animation_glide_animation_get_property;
+ object_class->set_property = animation_glide_animation_set_property;
+
+ animation_glide_animation_props[PROP_INITIAL_DISTANCE] =
+ g_param_spec_float ("initial-distance",
+ "Initial Distance",
+ "The initial distance away from the camera",
+ -1.0f,
+ 1.0f,
+ -0.3f,
+ static_cast (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ animation_glide_animation_props[PROP_X_ROTATION_ANGLE_DEGREES] =
+ g_param_spec_float ("x-rotation-angle-degrees",
+ "X Rotation Angle Degrees",
+ "Number of degrees on the X axis to rotate",
+ -360.0f,
+ 360.0f,
+ 0.0f,
+ static_cast (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ animation_glide_animation_props[PROP_Y_ROTATION_ANGLE_DEGREES] =
+ g_param_spec_float ("y-rotation-angle-degrees",
+ "Y Rotation Angle Degrees",
+ "Number of degrees on the Y axis to rotate",
+ -360.0f,
+ 360.0f,
+ 0.0f,
+ static_cast (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ animation_glide_animation_props[PROP_X_AXIS_LOCATION_UNIT] =
+ g_param_spec_float ("x-axis-location-unit",
+ "X Axis Location Unit",
+ "Unit-coordinates of where the X axis is on the surface",
+ 0.0f,
+ 1.0f,
+ 0.2f,
+ static_cast (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ animation_glide_animation_props[PROP_Y_AXIS_LOCATION_UNIT] =
+ g_param_spec_float ("y-axis-location-unit",
+ "Y Axis Location Unit",
+ "Unit-coordinates of where the Y axis is on the surface",
+ 0.0f,
+ 1.0f,
+ 0.5f,
+ static_cast (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ animation_glide_animation_props[PROP_SCREEN_WIDTH] =
+ g_param_spec_uint ("screen-width",
+ "Screen Width",
+ "Width of the screen in pixels",
+ 1,
+ G_MAXUINT,
+ 1,
+ static_cast (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ animation_glide_animation_props[PROP_TARGET] =
+ g_param_spec_boxed ("target",
+ "Target Box",
+ "Box that we are animating to",
+ ANIMATION_TYPE_BOX,
+ static_cast (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ animation_glide_animation_props[PROP_STEPPER] =
+ g_param_spec_object ("stepper",
+ "Stepper",
+ "Stepper to use to progress the animation",
+ ANIMATION_TYPE_STEPPER,
+ static_cast (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_properties (object_class,
+ NPROPS,
+ animation_glide_animation_props);
+}
+
+/**
+ * animation_glide_new:
+ * @initial_distance: Initial distance frm the camera.
+ * @x_rotation_angle_degrees: Degrees of rotation towards the X axis.
+ * @y_rotation_angle_degrees: Degrees of rotation towards the Y axis.
+ * @y_axis_location_unit: Unit-coordinates of where the X axis is on the surface.
+ * @x_axis_location_unit: Unit-coordinates of where the Y axis is on the surface.
+ * @screen_width: Width of the screen, in pixels.
+ * @target_box: The #AnimationBox that we are animating to.
+ * @length: The length of the animation.
+ *
+ * Returns: (transfer full): A new #AnimationGlideAnimation.
+ */
+AnimationGlideAnimation *
+animation_glide_new (float initial_distance,
+ float x_rotation_angle_degrees,
+ float y_rotation_angle_degrees,
+ float x_axis_location_unit,
+ float y_axis_location_unit,
+ unsigned int screen_width,
+ const AnimationBox *target_box,
+ unsigned int length)
+{
+ return ANIMATION_GLIDE_ANIMATION (g_object_new (ANIMATION_TYPE_GLIDE_ANIMATION,
+ "initial-distance", initial_distance,
+ "x-rotation-angle-degrees", x_rotation_angle_degrees,
+ "y-rotation-angle-degrees", y_rotation_angle_degrees,
+ "x-axis-location-unit", x_axis_location_unit,
+ "y-axis-location-unit", y_axis_location_unit,
+ "screen-width", screen_width,
+ "target", target_box,
+ "length", length,
+ NULL));
+}
diff --git a/animation-glib/glide/glide.h b/animation-glib/glide/glide.h
new file mode 100644
index 0000000..af17866
--- /dev/null
+++ b/animation-glib/glide/glide.h
@@ -0,0 +1,66 @@
+/*
+ * animation-glib/glide/glide.h
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject Interface for "glide" animation.
+ */
+#pragma once
+
+#include
+
+#include
+#include
+#include
+
+G_BEGIN_DECLS
+
+#define ANIMATION_TYPE_GLIDE_ANIMATION animation_glide_animation_get_type ()
+G_DECLARE_FINAL_TYPE (AnimationGlideAnimation, animation_glide_animation, ANIMATION, GLIDE_ANIMATION, AnimationTransformAnimation)
+
+void animation_glide_animation_set_initial_distance (AnimationGlideAnimation *animation,
+ float initial_distance);
+float animation_glide_animation_get_initial_distance (AnimationGlideAnimation *animation);
+
+void animation_glide_animation_set_x_rotation_angle_degrees (AnimationGlideAnimation *animation,
+ float x_rotation_angle_degrees);
+float animation_glide_animation_get_x_rotation_angle_degrees (AnimationGlideAnimation *animation);
+
+void animation_glide_animation_set_y_rotation_angle_degrees (AnimationGlideAnimation *animation,
+ float y_rotation_angle_degrees);
+float animation_glide_animation_get_y_rotation_angle_degrees (AnimationGlideAnimation *animation);
+
+void animation_glide_animation_set_x_axis_location_unit (AnimationGlideAnimation *animation,
+ float x_axis_location_unit);
+float animation_glide_animation_get_x_axis_location_unit (AnimationGlideAnimation *animation);
+
+void animation_glide_animation_set_y_axis_location_unit (AnimationGlideAnimation *animation,
+ float y_axis_location_unit);
+float animation_glide_animation_get_y_axis_location_unit (AnimationGlideAnimation *animation);
+
+void animation_glide_animation_set_stepper (AnimationGlideAnimation *animation,
+ AnimationStepper *stepper);
+AnimationStepper * animation_glide_animation_get_stepper (AnimationGlideAnimation *animation);
+
+AnimationGlideAnimation * animation_glide_new (float initial_distance,
+ float x_rotation_angle_degrees,
+ float y_rotation_angle_degrees,
+ float x_axis_location_unit,
+ float y_axis_location_unit,
+ unsigned int screen_width,
+ const AnimationBox *target_box,
+ unsigned int length);
+
+G_END_DECLS
diff --git a/animation-glib/glide/meson.build b/animation-glib/glide/meson.build
new file mode 100644
index 0000000..d5f1026
--- /dev/null
+++ b/animation-glib/glide/meson.build
@@ -0,0 +1,18 @@
+# /animation/glide/meson.build
+#
+# Build the libanimation library (glide animation component).
+#
+# See /LICENCE.md for Copyright information.
+
+glide_introspectable_sources = files([
+ 'glide.cpp'
+])
+
+glide_headers = files([
+ 'glide.h'
+])
+
+animation_glib_introspectable_sources += glide_introspectable_sources
+animation_glib_headers += glide_headers
+
+install_headers(glide_headers, subdir: join_paths(animation_glib_headers_subdir, 'glide'))
diff --git a/animation-glib/meson.build b/animation-glib/meson.build
index fb997bb..78407e6 100644
--- a/animation-glib/meson.build
+++ b/animation-glib/meson.build
@@ -20,18 +20,40 @@
api_version = '0'
-animation_glib_toplevel_headers = ['vector.h']
-animation_glib_toplevel_introspectable_sources = ['vector.cpp']
+animation_glib_toplevel_headers = files([
+ 'box.h',
+ 'vector.h'
+])
+animation_glib_toplevel_introspectable_sources = files([
+ 'box.cpp',
+ 'vector.cpp',
+ 'vector4d.cpp'
+])
+animation_glib_toplevel_private_headers = files([
+ 'constructor-helpers.h',
+ 'vector4d-internal.h'
+])
+animation_glib_toplevel_private_sources = files([
+ 'constructor-helpers.cpp'
+])
-animation_glib_introspectable_sources = []
-animation_glib_private_sources = []
-animation_glib_headers = []
+animation_glib_introspectable_sources = files([])
+animation_glib_private_headers = files([])
+animation_glib_private_sources = files([])
+animation_glib_headers = files([])
animation_glib_headers_subdir = 'animation-glib'
+subdir('bounce')
+subdir('glide')
+subdir('stepper')
+subdir('transform')
subdir('wobbly')
+subdir('zoom')
-animation_glib_introspectable_sources += files(animation_glib_toplevel_introspectable_sources)
-animation_glib_headers += files(animation_glib_toplevel_headers)
+animation_glib_introspectable_sources += animation_glib_toplevel_introspectable_sources
+animation_glib_private_sources += animation_glib_toplevel_private_sources
+animation_glib_headers += animation_glib_toplevel_headers
+animation_glib_private_headers += animation_glib_toplevel_private_headers
install_headers(animation_glib_toplevel_headers, subdir: animation_glib_headers_subdir)
diff --git a/animation-glib/stepper/linear.cpp b/animation-glib/stepper/linear.cpp
new file mode 100644
index 0000000..605784c
--- /dev/null
+++ b/animation-glib/stepper/linear.cpp
@@ -0,0 +1,137 @@
+/*
+ * animation-glib/stepper/linear.cpp
+ *
+ * Copyright 2018 Endless Mobile, Inc.
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject wrapper for linear stepper.
+ */
+
+#include
+#include
+
+#include
+#include
+#include
+
+namespace as = animation::stepper;
+
+struct _AnimationLinearStepper
+{
+ GObject parent_instance;
+};
+
+typedef struct _AnimationLinearStepperPrivate
+{
+} AnimationLinearStepperPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (AnimationLinearStepper,
+ animation_linear_stepper,
+ ANIMATION_TYPE_STEPPER_HOLDER)
+
+enum {
+ PROP_0,
+ PROP_LENGTH,
+ NPROPS
+};
+
+static GParamSpec *animation_linear_stepper_properties[NPROPS];
+
+static void
+animation_linear_stepper_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ case PROP_LENGTH:
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static GObject *
+animation_linear_stepper_constructor (GType type,
+ unsigned int n_construct_params,
+ GObjectConstructParam *construct_params)
+{
+ const char * const wanted_properties[] = {
+ "length",
+ NULL
+ };
+ g_autoptr(GHashTable) properties_table =
+ static_hash_table_of_values_for_specs (wanted_properties,
+ construct_params,
+ n_construct_params);
+
+ auto stepper = as::Linear (ForwardFromValueHT (properties_table, g_value_get_uint, "length"));
+
+ replace_named_pointer_prop_in_construct_params (construct_params,
+ n_construct_params,
+ "stepper",
+ &stepper);
+
+ return G_OBJECT_CLASS (animation_linear_stepper_parent_class)->constructor (type,
+ n_construct_params,
+ construct_params);
+}
+
+static void
+animation_linear_stepper_init (AnimationLinearStepper *model)
+{
+}
+
+static void
+animation_linear_stepper_class_init (AnimationLinearStepperClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructor = animation_linear_stepper_constructor;
+ object_class->set_property = animation_linear_stepper_set_property;
+
+ animation_linear_stepper_properties[PROP_LENGTH] =
+ g_param_spec_uint ("length",
+ "Length",
+ "How long the animation lasts",
+ 1,
+ 5000,
+ 300,
+ static_cast (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_properties (object_class,
+ NPROPS,
+ animation_linear_stepper_properties);
+}
+
+/**
+ * animation_linear_stepper_new:
+ * @length: Length of the transition in milliseconds.
+ *
+ * Return a new #AnimationStepper which linearly increments progress
+ * every time the step() method is called on it.
+ *
+ * Returns: (transfer full): An #AnimationLinearStepper
+ * implementation of #AnimationStepper
+ */
+AnimationStepper *
+animation_linear_stepper_new (unsigned int length)
+{
+ return ANIMATION_STEPPER (g_object_new (ANIMATION_TYPE_LINEAR_STEPPER,
+ "length", length,
+ NULL));
+}
diff --git a/animation-glib/stepper/linear.h b/animation-glib/stepper/linear.h
new file mode 100644
index 0000000..1c83c5f
--- /dev/null
+++ b/animation-glib/stepper/linear.h
@@ -0,0 +1,36 @@
+/*
+ * animation-glib/stepper/linear.h
+ *
+ * Copyright 2018 Endless Mobile, Inc.
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject class for linear stepper.
+ */
+#pragma once
+
+#include
+
+#include
+#include
+
+G_BEGIN_DECLS
+
+#define ANIMATION_TYPE_LINEAR_STEPPER animation_linear_stepper_get_type ()
+G_DECLARE_FINAL_TYPE (AnimationLinearStepper, animation_linear_stepper, ANIMATION, LINEAR_STEPPER, AnimationStepperHolder)
+
+AnimationStepper * animation_linear_stepper_new (unsigned int length);
+
+G_END_DECLS
diff --git a/animation-glib/stepper/meson.build b/animation-glib/stepper/meson.build
new file mode 100644
index 0000000..8eb30b1
--- /dev/null
+++ b/animation-glib/stepper/meson.build
@@ -0,0 +1,42 @@
+# /animation/stepper/meson.build
+#
+# Meson build file for libanimation stepper GObject classes.
+#
+# Copyright (C) 2017, 2018 Endless Mobile, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Build the libanimation library (stepper base component)
+
+stepper_introspectable_sources = files([
+ 'linear.cpp',
+ 'reverse.cpp',
+ 'stepper.cpp',
+ 'stepper-holder.cpp',
+ 'stepper-wrapper.cpp'
+])
+
+stepper_headers = files([
+ 'linear.h',
+ 'reverse.h',
+ 'stepper.h',
+ 'stepper-holder.h',
+ 'stepper-wrapper.h'
+])
+
+animation_glib_introspectable_sources += stepper_introspectable_sources
+animation_glib_headers += stepper_headers
+
+install_headers(stepper_headers, subdir: join_paths(animation_glib_headers_subdir, 'stepper'))
diff --git a/animation-glib/stepper/reverse.cpp b/animation-glib/stepper/reverse.cpp
new file mode 100644
index 0000000..8b3c66c
--- /dev/null
+++ b/animation-glib/stepper/reverse.cpp
@@ -0,0 +1,176 @@
+/*
+ * animation-glib/stepper/reverse.cpp
+ *
+ * Copyright 2018 Endless Mobile, Inc.
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject wrapper for reverse stepper.
+ */
+
+#include
+#include
+
+#include
+#include
+#include
+
+namespace as = animation::stepper;
+
+struct _AnimationReverseStepper
+{
+ GObject parent_instance;
+};
+
+typedef struct _AnimationReverseStepperPrivate
+{
+ AnimationStepper *base_stepper;
+} AnimationReverseStepperPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (AnimationReverseStepper,
+ animation_reverse_stepper,
+ ANIMATION_TYPE_STEPPER_HOLDER)
+
+enum {
+ PROP_0,
+ PROP_BASE_STEPPER,
+ NPROPS
+};
+
+static GParamSpec *animation_reverse_stepper_properties[NPROPS];
+
+static void
+animation_reverse_stepper_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ AnimationReverseStepper *stepper = ANIMATION_REVERSE_STEPPER (object);
+ AnimationReverseStepperPrivate *priv =
+ reinterpret_cast (animation_reverse_stepper_get_instance_private (stepper));
+
+ switch (prop_id)
+ {
+ case PROP_BASE_STEPPER:
+ priv->base_stepper = ANIMATION_STEPPER (g_value_dup_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+animation_reverse_stepper_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ AnimationReverseStepper *stepper = ANIMATION_REVERSE_STEPPER (object);
+ AnimationReverseStepperPrivate *priv =
+ reinterpret_cast (animation_reverse_stepper_get_instance_private (stepper));
+
+ switch (prop_id)
+ {
+ case PROP_BASE_STEPPER:
+ g_value_set_object (value, G_OBJECT (priv->base_stepper));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+animation_reverse_stepper_dispose (GObject *object)
+{
+ AnimationReverseStepper *stepper = ANIMATION_REVERSE_STEPPER (object);
+ AnimationReverseStepperPrivate *priv =
+ reinterpret_cast (animation_reverse_stepper_get_instance_private (stepper));
+
+ g_clear_object (&priv->base_stepper);
+
+ G_OBJECT_CLASS (animation_reverse_stepper_parent_class)->dispose (object);
+}
+
+static GObject *
+animation_reverse_stepper_constructor (GType type,
+ unsigned int n_construct_params,
+ GObjectConstructParam *construct_params)
+{
+ const char * const wanted_properties[] = {
+ "base-stepper",
+ NULL
+ };
+ g_autoptr(GHashTable) properties_table =
+ static_hash_table_of_values_for_specs (wanted_properties,
+ construct_params,
+ n_construct_params);
+
+ auto stepper = as::Reverse (ForwardFromValueHT (properties_table,
+ animation_stepper_from_gvalue,
+ "base-stepper"));
+
+ replace_named_pointer_prop_in_construct_params (construct_params,
+ n_construct_params,
+ "stepper",
+ &stepper);
+
+ return G_OBJECT_CLASS (animation_reverse_stepper_parent_class)->constructor (type,
+ n_construct_params,
+ construct_params);
+}
+
+static void
+animation_reverse_stepper_init (AnimationReverseStepper *model)
+{
+}
+
+static void
+animation_reverse_stepper_class_init (AnimationReverseStepperClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructor = animation_reverse_stepper_constructor;
+ object_class->get_property = animation_reverse_stepper_get_property;
+ object_class->set_property = animation_reverse_stepper_set_property;
+ object_class->dispose = animation_reverse_stepper_dispose;
+
+ animation_reverse_stepper_properties[PROP_BASE_STEPPER] =
+ g_param_spec_object ("base-stepper",
+ "Base Stepper",
+ "Stepper to reverse",
+ ANIMATION_TYPE_STEPPER,
+ static_cast (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_properties (object_class,
+ NPROPS,
+ animation_reverse_stepper_properties);
+}
+
+/**
+ * animation_reverse_stepper_new:
+ * @base_stepper: The stepper to reverse.
+ *
+ * Return a new #AnimationStepper which runs @base_stepper in reverse.
+ *
+ * Returns: (transfer full): An #AnimationReverseStepper
+ * implementation of #AnimationStepper
+ */
+AnimationStepper *
+animation_reverse_stepper_new (AnimationStepper *base_stepper)
+{
+ return ANIMATION_STEPPER (g_object_new (ANIMATION_TYPE_REVERSE_STEPPER,
+ "base-stepper", base_stepper,
+ NULL));
+}
diff --git a/animation-glib/stepper/reverse.h b/animation-glib/stepper/reverse.h
new file mode 100644
index 0000000..0a4f625
--- /dev/null
+++ b/animation-glib/stepper/reverse.h
@@ -0,0 +1,36 @@
+/*
+ * animation-glib/stepper/reverse.h
+ *
+ * Copyright 2018 Endless Mobile, Inc.
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject class for reverse stepper.
+ */
+#pragma once
+
+#include
+
+#include
+#include
+
+G_BEGIN_DECLS
+
+#define ANIMATION_TYPE_REVERSE_STEPPER animation_reverse_stepper_get_type ()
+G_DECLARE_FINAL_TYPE (AnimationReverseStepper, animation_reverse_stepper, ANIMATION, REVERSE_STEPPER, AnimationStepperHolder)
+
+AnimationStepper * animation_reverse_stepper_new (AnimationStepper *base_stepper);
+
+G_END_DECLS
diff --git a/animation-glib/stepper/stepper-holder.cpp b/animation-glib/stepper/stepper-holder.cpp
new file mode 100644
index 0000000..64a96ac
--- /dev/null
+++ b/animation-glib/stepper/stepper-holder.cpp
@@ -0,0 +1,196 @@
+/*
+ * animation-glib/stepper/stepper-holder.cpp
+ *
+ * Copyright 2018 Endless Mobile, Inc.
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject base class for steppers. Copies the stepper
+ * passed to it in its construct parameters.
+ */
+
+#include
+#include
+
+#include
+#include
+
+namespace as = animation::stepper;
+
+struct _AnimationStepperHolder
+{
+ GObject parent_instance;
+};
+
+typedef struct _AnimationStepperHolderPrivate
+{
+ as::Stepper *stepper;
+} AnimationStepperHolderPrivate;
+
+static void animation_stepper_iface_init (AnimationStepperInterface *stepper_iface);
+
+G_DEFINE_TYPE_WITH_CODE (AnimationStepperHolder,
+ animation_stepper_holder,
+ G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (ANIMATION_TYPE_STEPPER, animation_stepper_iface_init)
+ G_ADD_PRIVATE (AnimationStepperHolder))
+
+enum {
+ PROP_0,
+ PROP_STEPPER,
+ NPROPS
+};
+
+static float
+animation_stepper_holder_step (AnimationStepper *stepper,
+ unsigned int ms)
+{
+ AnimationStepperHolderPrivate *priv =
+ reinterpret_cast (animation_stepper_holder_get_instance_private (ANIMATION_STEPPER_HOLDER (stepper)));
+
+ return (*priv->stepper) (ms);
+}
+
+template
+static T *
+copy_ptr_if_set (T *ptr)
+{
+ if (ptr != nullptr)
+ return new T (*ptr);
+
+ return nullptr;
+}
+
+static void
+animation_stepper_holder_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ AnimationStepperHolder *holder = ANIMATION_STEPPER_HOLDER (object);
+ AnimationStepperHolderPrivate *priv =
+ reinterpret_cast (animation_stepper_holder_get_instance_private (holder));
+
+ switch (prop_id)
+ {
+ case PROP_STEPPER:
+ /* We need to copy-construct here as the property is
+ * not transfer full. */
+ priv->stepper = copy_ptr_if_set (reinterpret_cast (g_value_get_pointer (value)));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+animation_stepper_holder_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ AnimationStepperHolder *holder = ANIMATION_STEPPER_HOLDER (object);
+ AnimationStepperHolderPrivate *priv =
+ reinterpret_cast (animation_stepper_holder_get_instance_private (holder));
+
+ switch (prop_id)
+ {
+ case PROP_STEPPER:
+ g_value_set_pointer (value, reinterpret_cast (priv->stepper));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+animation_stepper_holder_finalize (GObject *object)
+{
+ AnimationStepperHolder *holder = ANIMATION_STEPPER_HOLDER (object);
+ AnimationStepperHolderPrivate *priv =
+ reinterpret_cast (animation_stepper_holder_get_instance_private (holder));
+
+ delete priv->stepper;
+ priv->stepper = nullptr;
+
+ G_OBJECT_CLASS (animation_stepper_holder_parent_class)->finalize (object);
+}
+
+static GObject *
+animation_stepper_holder_constructor (GType type,
+ unsigned int n_construct_params,
+ GObjectConstructParam *construct_params)
+{
+ auto defaultStepperHolder = as::Linear (300);
+
+ /* Check the passed stepper_holder prop to ensure that it is set. If not,
+ * then we need to set it to some sensible default value. */
+ for (unsigned int i = 0; i < n_construct_params; ++i)
+ {
+ if (g_strcmp0 (construct_params[i].pspec->name, "stepper") == 0)
+ {
+ if (g_value_get_pointer (construct_params[i].value) == nullptr)
+ g_value_set_pointer (construct_params[i].value, &defaultStepperHolder);
+ }
+ }
+
+ return G_OBJECT_CLASS (animation_stepper_holder_parent_class)->constructor (type,
+ n_construct_params,
+ construct_params);
+}
+
+static void
+animation_stepper_holder_init (AnimationStepperHolder *stepper_holder)
+{
+}
+
+static void
+animation_stepper_iface_init (AnimationStepperInterface *interface)
+{
+ interface->step = animation_stepper_holder_step;
+}
+
+static void
+animation_stepper_holder_class_init (AnimationStepperHolderClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructor = animation_stepper_holder_constructor;
+ object_class->get_property = animation_stepper_holder_get_property;
+ object_class->set_property = animation_stepper_holder_set_property;
+ object_class->finalize = animation_stepper_holder_finalize;
+
+ g_object_class_override_property (object_class,
+ PROP_STEPPER,
+ "stepper");
+}
+
+/**
+ * animation_stepper_holder_new: (skip):
+ * @interface: A pointer to an interlying stepper implementation.
+ *
+ * Create a new #AnimationStepperHolder, an implementation of
+ * #AnimationStepper which copies the underlying stepper when it
+ * is constructed (thus resetting its internal state, as copying
+ * a C++ lambda default-constructs its closure).
+ *
+ * Returns: (transfer full): A new #AnimationStepper with the underlying
+ * stepper copied.
+ */
+AnimationStepper *
+animation_stepper_holder_new (gpointer interface)
+{
+ return ANIMATION_STEPPER (g_object_new (ANIMATION_TYPE_STEPPER_HOLDER, "stepper", interface, NULL));
+}
diff --git a/animation-glib/stepper/stepper-holder.h b/animation-glib/stepper/stepper-holder.h
new file mode 100644
index 0000000..967ce28
--- /dev/null
+++ b/animation-glib/stepper/stepper-holder.h
@@ -0,0 +1,36 @@
+/*
+ * animation-glib/stepper/stepper-holder.h
+ *
+ * Copyright 2018 Endless Mobile, Inc.
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject base class for steppers, which holds a copy of a stepper.
+ */
+#pragma once
+
+#include
+
+#include
+#include
+
+G_BEGIN_DECLS
+
+#define ANIMATION_TYPE_STEPPER_HOLDER animation_stepper_holder_get_type ()
+G_DECLARE_FINAL_TYPE (AnimationStepperHolder, animation_stepper_holder, ANIMATION, STEPPER_HOLDER, GObject)
+
+AnimationStepper * animation_stepper_holder_new (gpointer interface);
+
+G_END_DECLS
diff --git a/animation-glib/stepper/stepper-wrapper.cpp b/animation-glib/stepper/stepper-wrapper.cpp
new file mode 100644
index 0000000..830b0bd
--- /dev/null
+++ b/animation-glib/stepper/stepper-wrapper.cpp
@@ -0,0 +1,160 @@
+/*
+ * animation-glib/stepper/stepper-wrapper.cpp
+ *
+ * Copyright 2018 Endless Mobile, Inc.
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject base class for steppers. Only observes the stepper passed
+ * to it in its construct parameters - not expected to outlive the stepper.
+ */
+
+#include
+#include
+
+#include
+#include
+
+namespace as = animation::stepper;
+
+struct _AnimationStepperWrapper
+{
+ GObject parent_instance;
+};
+
+typedef struct _AnimationStepperWrapperPrivate
+{
+ as::Stepper *stepper;
+} AnimationStepperWrapperPrivate;
+
+static void animation_stepper_iface_init (AnimationStepperInterface *stepper_iface);
+
+G_DEFINE_TYPE_WITH_CODE (AnimationStepperWrapper,
+ animation_stepper_wrapper,
+ G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (ANIMATION_TYPE_STEPPER, animation_stepper_iface_init)
+ G_ADD_PRIVATE (AnimationStepperWrapper))
+
+enum {
+ PROP_0,
+ PROP_STEPPER,
+ NPROPS
+};
+
+static float
+animation_stepper_wrapper_step (AnimationStepper *stepper,
+ unsigned int ms)
+{
+ AnimationStepperWrapperPrivate *priv =
+ reinterpret_cast (animation_stepper_wrapper_get_instance_private (ANIMATION_STEPPER_WRAPPER (stepper)));
+
+ return (*priv->stepper) (ms);
+}
+
+static void
+animation_stepper_wrapper_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ AnimationStepperWrapper *holder = ANIMATION_STEPPER_WRAPPER (object);
+ AnimationStepperWrapperPrivate *priv =
+ reinterpret_cast (animation_stepper_wrapper_get_instance_private (holder));
+
+ switch (prop_id)
+ {
+ case PROP_STEPPER:
+ priv->stepper = reinterpret_cast (g_value_get_pointer (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+animation_stepper_wrapper_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ AnimationStepperWrapper *holder = ANIMATION_STEPPER_WRAPPER (object);
+ AnimationStepperWrapperPrivate *priv =
+ reinterpret_cast (animation_stepper_wrapper_get_instance_private (holder));
+
+ switch (prop_id)
+ {
+ case PROP_STEPPER:
+ g_value_set_pointer (value, reinterpret_cast (priv->stepper));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+animation_stepper_wrapper_finalize (GObject *object)
+{
+ AnimationStepperWrapper *holder = ANIMATION_STEPPER_WRAPPER (object);
+ AnimationStepperWrapperPrivate *priv =
+ reinterpret_cast (animation_stepper_wrapper_get_instance_private (holder));
+
+ delete priv->stepper;
+ priv->stepper = nullptr;
+
+ G_OBJECT_CLASS (animation_stepper_wrapper_parent_class)->finalize (object);
+}
+
+static void
+animation_stepper_wrapper_init (AnimationStepperWrapper *stepper_wrapper)
+{
+}
+
+static void
+animation_stepper_iface_init (AnimationStepperInterface *interface)
+{
+ interface->step = animation_stepper_wrapper_step;
+}
+
+static void
+animation_stepper_wrapper_class_init (AnimationStepperWrapperClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = animation_stepper_wrapper_get_property;
+ object_class->set_property = animation_stepper_wrapper_set_property;
+ object_class->finalize = animation_stepper_wrapper_finalize;
+
+ g_object_class_override_property (object_class,
+ PROP_STEPPER,
+ "stepper");
+}
+
+/**
+ * animation_stepper_wrapper_new: (skip):
+ * @interface: A pointer to an interlying stepper implementation.
+ *
+ * Create a new #AnimationStepperWrapper, an implementation of
+ * #AnimationStepper which only observes the underlying stepper when it
+ * is constructed (keeping its internal state). However, the wrapper
+ * must not outlive the underlying stepper.
+ *
+ * Returns: (transfer full): A new #AnimationStepper with the underlying
+ * stepper merely observed.
+ */
+AnimationStepper *
+animation_stepper_wrapper_new (gpointer interface)
+{
+ return ANIMATION_STEPPER (g_object_new (ANIMATION_TYPE_STEPPER_WRAPPER, "stepper", interface, NULL));
+}
diff --git a/animation-glib/stepper/stepper-wrapper.h b/animation-glib/stepper/stepper-wrapper.h
new file mode 100644
index 0000000..bd59e53
--- /dev/null
+++ b/animation-glib/stepper/stepper-wrapper.h
@@ -0,0 +1,36 @@
+/*
+ * animation-glib/stepper/stepper-wrapper.h
+ *
+ * Copyright 2018 Endless Mobile, Inc.
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject base class for steppers, which holds a copy of a stepper.
+ */
+#pragma once
+
+#include
+
+#include
+#include
+
+G_BEGIN_DECLS
+
+#define ANIMATION_TYPE_STEPPER_WRAPPER animation_stepper_wrapper_get_type ()
+G_DECLARE_FINAL_TYPE (AnimationStepperWrapper, animation_stepper_wrapper, ANIMATION, STEPPER_WRAPPER, GObject)
+
+AnimationStepper * animation_stepper_wrapper_new (gpointer interface);
+
+G_END_DECLS
diff --git a/animation-glib/stepper/stepper.cpp b/animation-glib/stepper/stepper.cpp
new file mode 100644
index 0000000..714f4a2
--- /dev/null
+++ b/animation-glib/stepper/stepper.cpp
@@ -0,0 +1,49 @@
+/*
+ * animation-glib/stepper/stepper.cpp
+ *
+ * Copyright 2018 Endless Mobile, Inc.
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject base interface for steppers.
+ */
+
+#include
+#include
+
+namespace as = animation::stepper;
+
+
+G_DEFINE_INTERFACE (AnimationStepper,
+ animation_stepper,
+ G_TYPE_OBJECT)
+float
+animation_stepper_step (AnimationStepper *stepper,
+ unsigned int ms)
+{
+ g_return_val_if_fail (ANIMATION_IS_STEPPER (stepper), 0.0f);
+
+ return ANIMATION_STEPPER_GET_IFACE (stepper)->step (stepper, ms);
+}
+
+static void
+animation_stepper_default_init (AnimationStepperInterface *iface)
+{
+ g_object_interface_install_property ((gpointer) iface,
+ g_param_spec_pointer ("stepper",
+ "Internal Interface",
+ "Internal C++ interface that this class wraps",
+ static_cast (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
+}
diff --git a/animation-glib/stepper/stepper.h b/animation-glib/stepper/stepper.h
new file mode 100644
index 0000000..40e98f3
--- /dev/null
+++ b/animation-glib/stepper/stepper.h
@@ -0,0 +1,44 @@
+/*
+ * animation-glib/stepper/stepper.h
+ *
+ * Copyright 2018 Endless Mobile, Inc.
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject base interface for steppers.
+ */
+#pragma once
+
+#include
+
+#include
+
+G_BEGIN_DECLS
+
+#define ANIMATION_TYPE_STEPPER animation_stepper_get_type ()
+G_DECLARE_INTERFACE (AnimationStepper, animation_stepper, ANIMATION, STEPPER, GObject)
+
+struct _AnimationStepperInterface
+{
+ GTypeInterface parent_iface;
+
+ float (*step) (AnimationStepper *self,
+ unsigned int ms);
+};
+
+float animation_stepper_step (AnimationStepper *stepper,
+ unsigned int ms);
+
+G_END_DECLS
diff --git a/animation-glib/transform/meson.build b/animation-glib/transform/meson.build
new file mode 100644
index 0000000..6a64bff
--- /dev/null
+++ b/animation-glib/transform/meson.build
@@ -0,0 +1,34 @@
+# /animation/transform/meson.build
+#
+# Toplevel meson build file for libanimation.
+#
+# Copyright (C) 2017, 2018 Endless Mobile, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Build the libanimation library (transform animation base component
+
+transform_introspectable_sources = files([
+ 'transform.cpp'
+])
+
+transform_headers = files([
+ 'transform.h'
+])
+
+animation_glib_introspectable_sources += transform_introspectable_sources
+animation_glib_headers += transform_headers
+
+install_headers(transform_headers, subdir: join_paths(animation_glib_headers_subdir, 'transform'))
diff --git a/animation-glib/transform/transform.cpp b/animation-glib/transform/transform.cpp
new file mode 100644
index 0000000..190fc9d
--- /dev/null
+++ b/animation-glib/transform/transform.cpp
@@ -0,0 +1,202 @@
+/*
+ * animation-glib/transform/transform.cpp
+ *
+ * Copyright 2018 Endless Mobile, Inc.
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject base class for affine transform based animations.
+ */
+
+#include
+
+#include
+#include
+#include
+#include
+
+namespace agd = animation::geometry::dimension;
+namespace at = animation::transform;
+
+typedef struct _AnimationTransformAnimationPrivate
+{
+ at::TransformAnimation *interface;
+} AnimationTransformAnimationPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (AnimationTransformAnimation,
+ animation_transform_animation,
+ G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_INTERFACE,
+ NPROPS
+};
+
+static GParamSpec *animation_transform_animation_props [NPROPS] = { NULL, };
+
+gboolean
+animation_transform_animation_step (AnimationTransformAnimation *transform_animation,
+ unsigned int ms)
+{
+ AnimationTransformAnimationPrivate *priv =
+ reinterpret_cast (animation_transform_animation_get_instance_private (transform_animation));
+
+ return priv->interface->Step (ms);
+}
+
+/**
+ * animation_transform_animation_matrix:
+ * @transform_animation: A #AnimationTransformAnimation
+ *
+ * Get the 4x4 column-major transformation matrix for this
+ * representing the state of this animation.
+ *
+ * Returns: (array fixed-size=16): The 4x4 column-major ordered
+ * transformation matrix.
+ */
+float const *
+animation_transform_animation_matrix (AnimationTransformAnimation *transform_animation)
+{
+ AnimationTransformAnimationPrivate *priv =
+ reinterpret_cast (animation_transform_animation_get_instance_private (transform_animation));
+
+ return priv->interface->Matrix ();
+}
+
+/**
+ * animation_transform_animation_extremes:
+ * @transform_animation: A #AnimationTransformAnimation
+ * @corners: (array fixed-size=4): The four #AnimationVector4D values
+ * describing the location of the surface corners.
+ * @out_extremes: (array fixed-size=4) (out): The transformed four #AnimationVector
+ * values describing the location of the transformed surface
+ * surface corners.
+ *
+ * Get the four co-ordinates of a 3D plane which bound the animated surface.
+ */
+void
+animation_transform_animation_extremes (AnimationTransformAnimation *transform_animation,
+ AnimationVector const *corners,
+ AnimationVector4D *out_extremes)
+{
+ g_return_if_fail (corners != NULL);
+ g_return_if_fail (out_extremes != NULL);
+
+ AnimationTransformAnimationPrivate *priv =
+ reinterpret_cast (animation_transform_animation_get_instance_private (transform_animation));
+
+ std::array points = {
+ animation::Point (corners[0].x, corners[0].y),
+ animation::Point (corners[1].x, corners[1].y),
+ animation::Point (corners[2].x, corners[2].y),
+ animation::Point (corners[3].x, corners[3].y)
+ };
+
+ std::array extremes = priv->interface->Extremes (points);
+
+ agd::assign (out_extremes[0], extremes[0]);
+ agd::assign (out_extremes[1], extremes[1]);
+ agd::assign (out_extremes[2], extremes[2]);
+ agd::assign (out_extremes[3], extremes[3]);
+}
+
+float
+animation_transform_animation_progress (AnimationTransformAnimation *transform_animation)
+{
+ AnimationTransformAnimationPrivate *priv =
+ reinterpret_cast (animation_transform_animation_get_instance_private (transform_animation));
+
+ return priv->interface->Progress ();
+}
+
+static void
+animation_transform_animation_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ AnimationTransformAnimation *transform_animation = ANIMATION_TRANSFORM_ANIMATION (object);
+ AnimationTransformAnimationPrivate *priv =
+ reinterpret_cast (animation_transform_animation_get_instance_private (transform_animation));
+
+ switch (prop_id)
+ {
+ case PROP_INTERFACE:
+ priv->interface = reinterpret_cast (g_value_get_pointer (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+animation_transform_animation_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ AnimationTransformAnimation *transform_animation = ANIMATION_TRANSFORM_ANIMATION (object);
+ AnimationTransformAnimationPrivate *priv =
+ reinterpret_cast (animation_transform_animation_get_instance_private (transform_animation));
+
+ switch (prop_id)
+ {
+ case PROP_INTERFACE:
+ g_value_set_pointer (value, reinterpret_cast (priv->interface));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+animation_transform_animation_finalize (GObject *object)
+{
+ AnimationTransformAnimation *transform_animation = ANIMATION_TRANSFORM_ANIMATION (object);
+ AnimationTransformAnimationPrivate *priv =
+ reinterpret_cast (animation_transform_animation_get_instance_private (transform_animation));
+
+ delete priv->interface;
+ priv->interface = nullptr;
+
+ G_OBJECT_CLASS (animation_transform_animation_parent_class)->finalize (object);
+}
+
+static void
+animation_transform_animation_init (AnimationTransformAnimation *model)
+{
+}
+
+
+static void
+animation_transform_animation_class_init (AnimationTransformAnimationClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = animation_transform_animation_get_property;
+ object_class->set_property = animation_transform_animation_set_property;
+ object_class->finalize = animation_transform_animation_finalize;
+
+ animation_transform_animation_props[PROP_INTERFACE] =
+ g_param_spec_pointer ("interface",
+ "Internal Interface",
+ "Internal C++ interface that this class wraps",
+ static_cast (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_properties (object_class,
+ NPROPS,
+ animation_transform_animation_props);
+}
diff --git a/animation-glib/transform/transform.h b/animation-glib/transform/transform.h
new file mode 100644
index 0000000..58a3be8
--- /dev/null
+++ b/animation-glib/transform/transform.h
@@ -0,0 +1,49 @@
+/*
+ * animation-glib/transform/transform.h
+ *
+ * Copyright 2018 Endless Mobile, Inc.
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject Interface for affine transform animations.
+ */
+#pragma once
+
+#include
+
+#include
+#include
+
+G_BEGIN_DECLS
+
+#define ANIMATION_TYPE_TRANSFORM_ANIMATION animation_transform_animation_get_type ()
+G_DECLARE_DERIVABLE_TYPE (AnimationTransformAnimation, animation_transform_animation, ANIMATION, TRANSFORM_ANIMATION, GObject)
+
+struct _AnimationTransformAnimationClass {
+ GObjectClass parent_class;
+};
+
+gboolean animation_transform_animation_step (AnimationTransformAnimation *transform_animation,
+ unsigned int ms);
+
+float animation_transform_animation_progress (AnimationTransformAnimation *transform_animation);
+
+float const * animation_transform_animation_matrix (AnimationTransformAnimation *transform_animation);
+
+void animation_transform_animation_extremes (AnimationTransformAnimation *transform_animation,
+ AnimationVector const *corners,
+ AnimationVector4D *out_extremes);
+
+G_END_DECLS
diff --git a/animation-glib/vector4d-internal.h b/animation-glib/vector4d-internal.h
new file mode 100644
index 0000000..ca5e305
--- /dev/null
+++ b/animation-glib/vector4d-internal.h
@@ -0,0 +1,99 @@
+/*
+ * animation-glib/vector4d-internal.h
+ *
+ * Copyright 2018 Endless Mobile, Inc.
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject boxed type 4D vector implementation.
+ */
+
+#include
+
+namespace animation
+{
+ namespace geometry
+ {
+ namespace dimension
+ {
+ template <>
+ struct Dimension
+ {
+ typedef double data_type;
+ static const size_t dimensions = 4;
+ };
+
+ template <>
+ struct DimensionAccess
+ {
+ static inline double get (AnimationVector4D const &p)
+ {
+ return p.x;
+ }
+
+ static inline void
+ set (AnimationVector4D &p, double const &value)
+ {
+ p.x = value;
+ }
+ };
+
+ template <>
+ struct DimensionAccess
+ {
+ static inline double get (AnimationVector4D const &p)
+ {
+ return p.y;
+ }
+
+ static inline void
+ set (AnimationVector4D &p, double const &value)
+ {
+ p.y = value;
+ }
+ };
+
+ template <>
+ struct DimensionAccess
+ {
+ static inline double get (AnimationVector4D const &p)
+ {
+ return p.z;
+ }
+
+ static inline void
+ set (AnimationVector4D &p, double const &value)
+ {
+ p.z = value;
+ }
+ };
+
+ template <>
+ struct DimensionAccess
+ {
+ static inline double get (AnimationVector4D const &p)
+ {
+ return p.w;
+ }
+
+ static inline void
+ set (AnimationVector4D &p, double const &value)
+ {
+ p.w = value;
+ }
+ };
+ }
+ }
+}
diff --git a/animation-glib/vector4d.cpp b/animation-glib/vector4d.cpp
new file mode 100644
index 0000000..e54c1d9
--- /dev/null
+++ b/animation-glib/vector4d.cpp
@@ -0,0 +1,39 @@
+/*
+ * animation-glib/vector4d.cpp
+ *
+ * Copyright 2018 Endless Mobile, Inc.
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject boxed type 4D vector implementation.
+ */
+
+#include
+
+static gpointer
+animation_vector4d_copy (gpointer ptr)
+{
+ AnimationVector4D *src = reinterpret_cast (ptr);
+ AnimationVector4D *dst = g_new0 (AnimationVector4D, 1);
+
+ *dst = *src;
+
+ return reinterpret_cast (dst);
+}
+
+G_DEFINE_BOXED_TYPE (AnimationVector4D,
+ animation_vector4d,
+ animation_vector4d_copy,
+ g_free)
diff --git a/animation-glib/vector4d.h b/animation-glib/vector4d.h
new file mode 100644
index 0000000..ff2b2b5
--- /dev/null
+++ b/animation-glib/vector4d.h
@@ -0,0 +1,39 @@
+/*
+ * animation-glib/vector4d.h
+ *
+ * Copyright 2018 Endless Mobile, Inc.
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject boxed type 4D vector implementation.
+ */
+#pragma once
+
+#include
+
+G_BEGIN_DECLS
+
+typedef struct {
+ double x;
+ double y;
+ double z;
+ double w;
+} AnimationVector4D;
+
+#define ANIMATION_TYPE_VECTOR4D animation_vector4d_get_type ()
+
+GType animation_vector4d_get_type (void);
+
+G_END_DECLS
diff --git a/animation-glib/zoom/meson.build b/animation-glib/zoom/meson.build
new file mode 100644
index 0000000..c206a40
--- /dev/null
+++ b/animation-glib/zoom/meson.build
@@ -0,0 +1,18 @@
+# /animation/zoom/meson.build
+#
+# Build the libanimation library (zoom animation component).
+#
+# See /LICENCE.md for Copyright information.
+
+zoom_introspectable_sources = files([
+ 'zoom.cpp'
+])
+
+zoom_headers = files([
+ 'zoom.h'
+])
+
+animation_glib_introspectable_sources += zoom_introspectable_sources
+animation_glib_headers += zoom_headers
+
+install_headers(zoom_headers, subdir: join_paths(animation_glib_headers_subdir, 'zoom'))
diff --git a/animation-glib/zoom/zoom.cpp b/animation-glib/zoom/zoom.cpp
new file mode 100644
index 0000000..6d799a2
--- /dev/null
+++ b/animation-glib/zoom/zoom.cpp
@@ -0,0 +1,295 @@
+/*
+ * animation-glib/zoom/zoom.cpp
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject interface for a zoom animation.
+ */
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace agd = animation::geometry::dimension;
+namespace at = animation::transform;
+namespace az = animation::zoom;
+
+struct _AnimationZoomAnimation
+{
+ AnimationTransformAnimation parent_instance;
+};
+
+typedef struct _AnimationZoomAnimationPrivate
+{
+} AnimationZoomAnimationPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (AnimationZoomAnimation,
+ animation_zoom_animation,
+ ANIMATION_TYPE_TRANSFORM_ANIMATION)
+
+enum {
+ PROP_0,
+ PROP_FROM,
+ PROP_TO,
+ PROP_STEPPER,
+ NPROPS
+};
+
+static GParamSpec *animation_zoom_animation_props [NPROPS] = { NULL, };
+
+void
+animation_zoom_animation_set_from (AnimationZoomAnimation *animation,
+ AnimationBox box)
+{
+ LookupTypedInterfaceProp (G_OBJECT (animation))->From (animation::Box (animation::Point (box.top_left.x,
+ box.top_left.y),
+ animation::Point (box.bottom_right.x,
+ box.bottom_right.y)));
+}
+
+/**
+ * animation_zoom_animation_get_from:
+ * @animation: An #AnimationZoomAnimation
+ * @out_box: (out caller-allocates): Return location for an #AnimationBox to the source
+ *
+ * Get the source box for this animation.
+ */
+void
+animation_zoom_animation_get_from (AnimationZoomAnimation *animation,
+ AnimationBox *out_box)
+{
+ g_return_if_fail (out_box != NULL);
+
+ auto box = LookupTypedInterfaceProp (G_OBJECT (animation))->From ();
+
+ out_box->top_left.x = agd::get <0> (box.topLeft ());
+ out_box->top_left.y = agd::get <1> (box.topLeft ());
+ out_box->bottom_right.x = agd::get <0> (box.bottomRight ());
+ out_box->bottom_right.y = agd::get <1> (box.bottomRight ());
+}
+
+
+/**
+ * animation_zoom_animation_get_to:
+ * @animation: An #AnimationZoomAnimation
+ * @out_box: (out caller-allocates): Return location for an #AnimationBox to the target
+ *
+ * Get the source box for this animation.
+ */
+void
+animation_zoom_animation_get_to (AnimationZoomAnimation *animation,
+ AnimationBox *out_box)
+{
+ g_return_if_fail (out_box != NULL);
+
+ auto box = LookupTypedInterfaceProp (G_OBJECT (animation))->To ();
+
+ out_box->top_left.x = agd::get <0> (box.topLeft ());
+ out_box->top_left.y = agd::get <1> (box.topLeft ());
+ out_box->bottom_right.x = agd::get <0> (box.bottomRight ());
+ out_box->bottom_right.y = agd::get <1> (box.bottomRight ());
+}
+
+void
+animation_zoom_animation_set_stepper (AnimationZoomAnimation *animation,
+ AnimationStepper *stepper)
+{
+ animation::stepper::Stepper *stepper_ptr = nullptr;
+ g_object_get (stepper, "stepper", (gpointer) &stepper_ptr, NULL);
+
+ LookupTypedInterfaceProp (G_OBJECT (animation))->Stepper (*stepper_ptr);
+}
+
+/**
+ * animation_zoom_animation_get_stepper:
+ * @animation: An #AnimationZoomAnimation
+ *
+ * Returns: (transfer full): Get the stepper for this #AnimationZoomAnimation
+ */
+AnimationStepper *
+animation_zoom_animation_get_stepper (AnimationZoomAnimation *animation)
+{
+ auto const &stepper (LookupTypedInterfaceProp (G_OBJECT (animation))->Stepper ());
+
+ return animation_stepper_wrapper_new ((gpointer) &stepper);
+}
+
+static void
+animation_zoom_animation_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ AnimationZoomAnimation *zoom_animation = ANIMATION_ZOOM_ANIMATION (object);
+
+ switch (prop_id)
+ {
+ case PROP_FROM:
+ {
+ AnimationBox *box = reinterpret_cast (g_value_get_boxed (value));
+
+ if (box != nullptr)
+ animation_zoom_animation_set_from (zoom_animation, *box);
+ }
+ break;
+ case PROP_TO:
+ break;
+ case PROP_STEPPER:
+ animation_zoom_animation_set_stepper (zoom_animation, reinterpret_cast (g_value_get_object (value)));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+animation_zoom_animation_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ AnimationZoomAnimation *zoom_animation = ANIMATION_ZOOM_ANIMATION (object);
+
+ switch (prop_id)
+ {
+ case PROP_FROM:
+ {
+ AnimationBox box;
+ animation_zoom_animation_get_from (zoom_animation, &box);
+
+ g_value_set_boxed (value, (gpointer) &box);
+ }
+ break;
+ case PROP_TO:
+ {
+ AnimationBox box;
+ animation_zoom_animation_get_to (zoom_animation, &box);
+
+ g_value_set_boxed (value, (gpointer) &box);
+ }
+ break;
+ case PROP_STEPPER:
+ g_value_take_object (value, animation_zoom_animation_get_stepper (zoom_animation));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static GObject *
+animation_zoom_animation_constructor (GType type,
+ unsigned int n_construct_params,
+ GObjectConstructParam *construct_params)
+{
+ replace_named_pointer_prop_in_construct_params_if_null (construct_params,
+ n_construct_params,
+ "stepper",
+ g_value_get_object,
+ g_value_set_object,
+ []() -> gpointer {
+ return animation_linear_stepper_new (300);
+ });
+
+ const char * const wanted_properties[] = {
+ "from",
+ "to",
+ "stepper",
+ NULL
+ };
+ g_autoptr(GHashTable) properties_table =
+ static_hash_table_of_values_for_specs (wanted_properties,
+ construct_params,
+ n_construct_params);
+
+ auto *interface =
+ static_cast (InterfaceConstructor ::construct (
+ ForwardFromValueHT (properties_table, animation_box_from_gvalue, "from"),
+ ForwardFromValueHT (properties_table, animation_box_from_gvalue, "to"),
+ ForwardFromValueHT (properties_table, animation_stepper_from_gvalue, "stepper")
+ ));
+
+ replace_interface_prop_in_construct_params (construct_params,
+ n_construct_params,
+ g_steal_pointer (&interface));
+
+ return G_OBJECT_CLASS (animation_zoom_animation_parent_class)->constructor (type,
+ n_construct_params,
+ construct_params);
+}
+
+static void
+animation_zoom_animation_init (AnimationZoomAnimation *model)
+{
+}
+
+static void
+animation_zoom_animation_class_init (AnimationZoomAnimationClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructor = animation_zoom_animation_constructor;
+ object_class->get_property = animation_zoom_animation_get_property;
+ object_class->set_property = animation_zoom_animation_set_property;
+
+ animation_zoom_animation_props[PROP_FROM] =
+ g_param_spec_boxed ("from",
+ "From Box",
+ "Box that we are animating from",
+ ANIMATION_TYPE_BOX,
+ static_cast (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ animation_zoom_animation_props[PROP_TO] =
+ g_param_spec_boxed ("to",
+ "To Box",
+ "Box that we are animating to",
+ ANIMATION_TYPE_BOX,
+ static_cast (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ animation_zoom_animation_props[PROP_STEPPER] =
+ g_param_spec_object ("stepper",
+ "Stepper",
+ "Stepper to use to progress the animation",
+ ANIMATION_TYPE_STEPPER,
+ static_cast (G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_properties (object_class,
+ NPROPS,
+ animation_zoom_animation_props);
+}
+
+/**
+ * animation_zoom_new:
+ * @from: The #AnimationBox that we are animating from.
+ * @to: The #AnimationBox that we are animating to (current location).
+ * @stepper: The stepper to use.
+ *
+ * Returns: (transfer full): A new #AnimationZoomAnimation.
+ */
+AnimationZoomAnimation *
+animation_zoom_new (const AnimationBox *current,
+ const AnimationBox *from,
+ const AnimationBox *to,
+ AnimationStepper *stepper)
+{
+ return ANIMATION_ZOOM_ANIMATION (g_object_new (ANIMATION_TYPE_ZOOM_ANIMATION,
+ "from", from,
+ "to", to,
+ "stepper", stepper,
+ NULL));
+}
diff --git a/animation-glib/zoom/zoom.h b/animation-glib/zoom/zoom.h
new file mode 100644
index 0000000..47f4cd0
--- /dev/null
+++ b/animation-glib/zoom/zoom.h
@@ -0,0 +1,50 @@
+/*
+ * animation-glib/zoom/zoom.h
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * GObject Interface for "zoom" animation.
+ */
+#pragma once
+
+#include
+
+#include
+#include
+#include
+#include
+
+G_BEGIN_DECLS
+
+#define ANIMATION_TYPE_ZOOM_ANIMATION animation_zoom_animation_get_type ()
+G_DECLARE_FINAL_TYPE (AnimationZoomAnimation, animation_zoom_animation, ANIMATION, ZOOM_ANIMATION, AnimationTransformAnimation)
+
+void animation_zoom_animation_set_from (AnimationZoomAnimation *animation,
+ AnimationBox box);
+void animation_zoom_animation_get_from (AnimationZoomAnimation *animation,
+ AnimationBox *out_box);
+
+void animation_zoom_animation_get_to (AnimationZoomAnimation *animation,
+ AnimationBox *out_box);
+
+void animation_zoom_animation_set_stepper (AnimationZoomAnimation *animation,
+ AnimationStepper *stepper);
+AnimationStepper * animation_zoom_animation_get_stepper (AnimationZoomAnimation *animation);
+
+AnimationZoomAnimation * animation_zoom_new (const AnimationBox *from,
+ const AnimationBox *to,
+ AnimationStepper *stepper);
+
+G_END_DECLS
diff --git a/animation/bounce/bounce.cpp b/animation/bounce/bounce.cpp
new file mode 100644
index 0000000..bd18566
--- /dev/null
+++ b/animation/bounce/bounce.cpp
@@ -0,0 +1,218 @@
+/*
+ * animation/bounce/bounce.cpp
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * An animation that causes a surface to bounce onto screen, gently
+ * following an attenuating sine wave.
+ */
+
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+namespace agd = animation::geometry::dimension;
+namespace ab = animation::bounce;
+namespace abc = animation::box_calculation;
+namespace am = animation::math;
+namespace atc = animation::transform_calculation;
+
+namespace
+{
+ float SampleSineWave (float progress,
+ unsigned int nBounces)
+ {
+ return ::sin (progress * M_PI * nBounces);
+ }
+
+ /* This animation simulates a gentle bounce on a sine wave from
+ * the center of the window outwards.
+ *
+ * The best way to think of this animation is to think of an attenuating
+ * sine wave squeezed inwards by two bounds that converge on a single point.
+ *
+ * In this case those lines are running from the "initialScale" to 1.0
+ * and the "maximumScale" down to 1.0. We run the sine wave for 2pi * nBounce
+ * iterations (scaling it to fit within the time range), but the effect
+ * of the animation is scaled according to where we are on the bounds.
+ *
+ * Now, rotate the attenuating sine wave so that it is facing towards you
+ * on the z-axis (OpenGL co-ordinates). This is essentially what the animation
+ * is. */
+ float ComputeScaleFactorFromProgressParameters (float progress,
+ float initialScale,
+ float maximumScale,
+ unsigned int nBounces)
+ {
+ /* Squeeze the sine wave into place by applying a linear
+ * interpolation to it */
+ float const targetScale = 1.0f;
+ float sampledSine = SampleSineWave (progress, nBounces);
+ float range = (maximumScale - initialScale) * (1.0f - progress);
+ float scaleFloor = initialScale + (targetScale - initialScale) * progress;
+
+ return scaleFloor + range * sampledSine;
+ }
+
+ void ComputeBounceTransform (glm::mat4 &transform,
+ float progress,
+ float initialScale,
+ float maximumScale,
+ unsigned int nBounces,
+ animation::Box const &targetBox)
+ {
+ animation::Point boxCenterOffset (abc::ComputeBoxCenterOffset (targetBox));
+
+ float const scaleFactor = ComputeScaleFactorFromProgressParameters (progress,
+ initialScale,
+ maximumScale,
+ nBounces);
+ auto centerMat = glm::translate (glm::mat4 (1.0),
+ glm::vec3 (-1 * agd::get <0> (boxCenterOffset),
+ -1 *agd::get <1> (boxCenterOffset),
+ 0.0));
+ auto scaleMat = glm::scale (glm::mat4 (1.0),
+ glm::vec3 (scaleFactor,
+ scaleFactor,
+ 1.0));
+ auto invCenterMat = glm::translate (glm::mat4 (1.0),
+ glm::vec3 (agd::get <0> (boxCenterOffset),
+ agd::get <1> (boxCenterOffset),
+ 0.0));
+
+ transform = invCenterMat * scaleMat * centerMat;
+ }
+}
+
+namespace animation
+{
+ namespace bounce
+ {
+ struct BounceAnimation::Private
+ {
+ Private (float initialScale,
+ float maximumScale,
+ unsigned int nBounce,
+ animation::Box const &target,
+ animation::stepper::Stepper const &stepper);
+
+ float initialScale;
+ float maximumScale;
+ unsigned int nBounce;
+ animation::Box target;
+
+ glm::mat4 transform;
+ float progress;
+
+ animation::stepper::Stepper stepper;
+ };
+
+ BounceAnimation::Private::Private (float initialScale,
+ float maximumScale,
+ unsigned int nBounce,
+ animation::Box const &target,
+ animation::stepper::Stepper const &stepper) :
+ initialScale (initialScale),
+ maximumScale (maximumScale),
+ nBounce (nBounce),
+ target (target),
+ transform (glm::mat4 (1.0)),
+ progress (stepper (0)),
+ stepper (stepper)
+ {
+ ComputeBounceTransform (transform,
+ progress,
+ initialScale,
+ maximumScale,
+ nBounce,
+ target);
+ }
+ }
+}
+
+std::array
+ab::BounceAnimation::Extremes (std::array const &corners) const
+{
+ return std::array {
+ atc::TransformFlattened2DPointBy3DMatrix (corners[0], priv->transform),
+ atc::TransformFlattened2DPointBy3DMatrix (corners[1], priv->transform),
+ atc::TransformFlattened2DPointBy3DMatrix (corners[2], priv->transform),
+ atc::TransformFlattened2DPointBy3DMatrix (corners[3], priv->transform)
+ };
+}
+
+float
+ab::BounceAnimation::Progress () const
+{
+ return priv->progress;
+}
+
+bool
+ab::BounceAnimation::Step (unsigned int ms)
+{
+ priv->progress = am::clamp (priv->stepper (ms), 0.0f, 1.0f);
+
+ ComputeBounceTransform (priv->transform,
+ priv->progress,
+ priv->initialScale,
+ priv->maximumScale,
+ priv->nBounce,
+ priv->target);
+
+ return priv->progress != 0.0f && priv->progress != 1.0f;
+}
+
+float * const
+ab::BounceAnimation::Matrix () const
+{
+ return glm::value_ptr (priv->transform);
+}
+
+ANIMATION_DEFINE_PROPERTY (ab::BounceAnimation, InitialScale, float, priv->initialScale)
+ANIMATION_DEFINE_PROPERTY (ab::BounceAnimation, MaximumScale, float, priv->maximumScale)
+ANIMATION_DEFINE_PROPERTY (ab::BounceAnimation, NBounce, unsigned int, priv->nBounce)
+ANIMATION_DEFINE_PROPERTY (ab::BounceAnimation, Stepper, animation::stepper::Stepper, priv->stepper)
+ANIMATION_DEFINE_READONLY_PROPERTY (ab::BounceAnimation, Target, animation::Box , priv->target)
+
+ab::BounceAnimation::BounceAnimation (float initialScale,
+ float maximumScale,
+ unsigned int nBounce,
+ animation::Box const &target,
+ animation::stepper::Stepper const &stepper) :
+ priv (new ab::BounceAnimation::Private (initialScale,
+ maximumScale,
+ nBounce,
+ target,
+ stepper))
+{
+}
+
+ab::BounceAnimation::~BounceAnimation ()
+{
+}
diff --git a/animation/bounce/bounce.h b/animation/bounce/bounce.h
new file mode 100644
index 0000000..58d079d
--- /dev/null
+++ b/animation/bounce/bounce.h
@@ -0,0 +1,65 @@
+/*
+ * animation/bounce/bounce.h
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * An animation that causes a surface to bounce onto screen, gently
+ * following an attenuating sine wave.
+ */
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#pragma once
+
+namespace animation
+{
+ namespace bounce
+ {
+ class BounceAnimation :
+ public animation::transform::TransformAnimation
+ {
+ public:
+
+ BounceAnimation (float initialScale,
+ float maximumScale,
+ unsigned int nBounce,
+ animation::Box const &target,
+ animation::stepper::Stepper const &stepper);
+ ~BounceAnimation ();
+
+ float * const Matrix () const;
+ float Progress () const;
+ bool Step (unsigned int ms);
+ std::array Extremes (std::array const &corners) const;
+
+ ANIMATION_DECLARE_PROPERTY (BounceAnimation, InitialScale, float)
+ ANIMATION_DECLARE_PROPERTY (BounceAnimation, MaximumScale, float)
+ ANIMATION_DECLARE_PROPERTY (BounceAnimation, NBounce, unsigned int)
+ ANIMATION_DECLARE_PROPERTY (BounceAnimation, Stepper, animation::stepper::Stepper)
+ ANIMATION_DECLARE_READONLY_PROPERTY (BounceAnimation, Target, animation::Box )
+
+ private:
+
+ struct Private;
+ std::unique_ptr priv;
+ };
+ }
+}
diff --git a/animation/bounce/meson.build b/animation/bounce/meson.build
new file mode 100644
index 0000000..4fccbad
--- /dev/null
+++ b/animation/bounce/meson.build
@@ -0,0 +1,34 @@
+# /animation/bounce/meson.build
+#
+# Toplevel meson build file for libanimation.
+#
+# Copyright (C) 2017, 2018 Endless Mobile, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Build the libanimation library (bounce animation component).
+
+bounce_sources = files([
+ 'bounce.cpp'
+])
+
+bounce_headers = files([
+ 'bounce.h'
+])
+
+animation_sources += bounce_sources
+animation_headers += bounce_headers
+
+install_headers(bounce_headers, subdir: join_paths(animation_headers_subdir, 'bounce'))
diff --git a/animation/box_calculation.h b/animation/box_calculation.h
new file mode 100644
index 0000000..8821dec
--- /dev/null
+++ b/animation/box_calculation.h
@@ -0,0 +1,70 @@
+/*
+ * animation/box_calculation.h
+ *
+ * libanimation is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * libanimation is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with eos-companion-app-service. If not, see
+ * .
+ *
+ * Utility functions to calculate points and box offsets.
+ */
+#pragma once
+
+#include
+
+namespace animation
+{
+ namespace box_calculation
+ {
+ inline animation::Point ComputeBoxCenterOffset (animation::Box const &box)
+ {
+ namespace agd = animation::geometry::dimension;
+
+ return animation::Point ((agd::get <0> (box.bottomRight ()) -
+ agd::get <0> (box.topLeft ())) / 2.0,
+ (agd::get <1> (box.bottomRight ()) -
+ agd::get <1> (box.topLeft ())) / 2.0);
+ }
+
+ inline animation::Point ComputeBoxCenter (animation::Box const &box)
+ {
+ namespace agd = animation::geometry::dimension;
+
+ animation::Point topLeft (box.topLeft ());
+ agd::pointwise_add (topLeft, ComputeBoxCenterOffset (box));
+ return topLeft;
+ }
+
+ inline animation::Point ComputeRotationAxisOffset (animation::Box const &box,
+ float u,
+ float v)
+ {
+ namespace agd = animation::geometry::dimension;
+
+ return animation::Point ((agd::get <0> (box.bottomRight ()) -
+ agd::get <0> (box.topLeft ())) * u,
+ (agd::get <1> (box.bottomRight ()) -
+ agd::get <1> (box.topLeft ())) * v);
+ }
+
+ inline animation::Point ComputeRotationAxis (animation::Box const &box,
+ float u,
+ float v)
+ {
+ namespace agd = animation::geometry::dimension;
+
+ animation::Point topLeft (box.topLeft ());
+ agd::pointwise_add (topLeft, ComputeRotationAxisOffset (box, u, v));
+ return topLeft;
+ }
+ }
+}
diff --git a/animation/geometry.h b/animation/geometry.h
index 51413d8..9a1fe65 100644
--- a/animation/geometry.h
+++ b/animation/geometry.h
@@ -367,12 +367,143 @@ namespace animation
dimension::get <1> (p) >= y1 &&
dimension::get <1> (p) <= y2);
}
+
+ /**
+ * Vector4DModel:
+ *
+ * A detached 2D point or vector in space for a given data
+ * type T. This is a structure of two values.
+ *
+ * Vector4DModel implements the Dimension trait, meaning that it
+ * can be used with functions in the animation::geometry::dimension
+ * namespace.
+ */
+ template
+ struct Vector4DModel
+ {
+ Vector4DModel (T x, T y, T z, T w) noexcept :
+ x (x),
+ y (y),
+ z (z),
+ w (w)
+ {
+ }
+
+ Vector4DModel () noexcept :
+ x (0),
+ y (0),
+ z (0),
+ w (0)
+ {
+ }
+
+ Vector4DModel (Vector4DModel const &v) noexcept :
+ x (v.x),
+ y (v.y),
+ z (v.z),
+ w (v.w)
+ {
+ }
+
+ void swap (Vector4DModel &a, Vector4DModel &b) noexcept
+ {
+ std::swap (a.x, b.x);
+ std::swap (a.y, b.y);
+ std::swap (a.z, b.z);
+ std::swap (a.w, b.w);
+ }
+
+ Vector4DModel & operator= (Vector4DModel other) noexcept
+ {
+ swap (*this, other);
+
+ return *this;
+ }
+
+ T x;
+ T y;
+ T z;
+ T w;
+ };
+
+ typedef Vector4DModel Vector4D;
+
+ namespace dimension
+ {
+ template