diff --git a/clutter/clutter-alpha.c b/clutter/clutter-alpha.c index 57b057aa1..ae88454b7 100644 --- a/clutter/clutter-alpha.c +++ b/clutter/clutter-alpha.c @@ -64,6 +64,31 @@ * * * + * + * ClutterAlpha custom properties for #ClutterScript + * #ClutterAlpha defines a custom "function" property for + * #ClutterScript which allows to reference a custom alpha function + * available in the source code. Setting the "function" property + * is equivalent to calling clutter_alpha_set_func() with the + * specified function name. No user data or #GDestroyNotify is + * available to be passed. + * + * Defining a ClutterAlpha in ClutterScript + * The following JSON fragment defines a #ClutterAlpha + * using a #ClutterTimeline with id "timeline-01" and an alpha + * function called my_sine_alpha(). The defined #ClutterAlpha + * instance can be reused in multiple #ClutterBehaviour + * definitions. + * + * { + * "id" : "sine-alpha", + * "timeline" : "timeline-01", + * "function" : "my_sine_alpha" + * } + * + * + * + * * Since: 0.2 */ @@ -73,15 +98,23 @@ #include +#include + #include "clutter-alpha.h" #include "clutter-debug.h" #include "clutter-enum-types.h" #include "clutter-main.h" #include "clutter-marshal.h" #include "clutter-private.h" +#include "clutter-scriptable.h" -G_DEFINE_TYPE (ClutterAlpha, clutter_alpha, G_TYPE_INITIALLY_UNOWNED); +static void clutter_scriptable_iface_init (ClutterScriptableIface *iface); +G_DEFINE_TYPE_WITH_CODE (ClutterAlpha, + clutter_alpha, + G_TYPE_INITIALLY_UNOWNED, + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE, + clutter_scriptable_iface_init)); struct _ClutterAlphaPrivate { @@ -197,6 +230,73 @@ clutter_alpha_dispose (GObject *object) G_OBJECT_CLASS (clutter_alpha_parent_class)->dispose (object); } +static ClutterAlphaFunc +resolve_alpha_func (const gchar *name) +{ + static GModule *module = NULL; + ClutterAlphaFunc func; + + CLUTTER_NOTE (SCRIPT, "Looking up '%s' alpha function", name); + + if (G_UNLIKELY (module == NULL)) + module = g_module_open (NULL, G_MODULE_BIND_LAZY); + + if (g_module_symbol (module, name, (gpointer) &func)) + { + CLUTTER_NOTE (SCRIPT, "Found '%s' alpha function in the symbols table", + name); + return func; + } + + return NULL; +} + +static void +clutter_alpha_set_custom_property (ClutterScriptable *scriptable, + ClutterScript *script, + const gchar *name, + const GValue *value) +{ + if (strncmp (name, "function", 8) == 0) + { + g_assert (G_VALUE_HOLDS (value, G_TYPE_POINTER)); + if (g_value_get_pointer (value) != NULL) + { + clutter_alpha_set_func (CLUTTER_ALPHA (scriptable), + g_value_get_pointer (value), + NULL, NULL); + } + } + else + g_object_set_property (G_OBJECT (scriptable), name, value); +} + +static gboolean +clutter_alpha_parse_custom_node (ClutterScriptable *scriptable, + ClutterScript *script, + GValue *value, + const gchar *name, + JsonNode *node) +{ + if (strncmp (name, "function", 8) == 0) + { + const gchar *func_name = json_node_get_string (node); + + g_value_init (value, G_TYPE_POINTER); + g_value_set_pointer (value, resolve_alpha_func (func_name)); + + return TRUE; + } + + return FALSE; +} + +static void +clutter_scriptable_iface_init (ClutterScriptableIface *iface) +{ + iface->parse_custom_node = clutter_alpha_parse_custom_node; + iface->set_custom_property = clutter_alpha_set_custom_property; +} static void clutter_alpha_class_init (ClutterAlphaClass *klass)