revert changes

This commit is contained in:
Emmanuele Bassi 2006-09-08 20:57:31 +00:00
parent ba32170d94
commit 4dea33e123
7 changed files with 475 additions and 1070 deletions

View File

@ -1,5 +1,3 @@
NULL =
MARSHALFILES = clutter-marshal.c clutter-marshal.h MARSHALFILES = clutter-marshal.c clutter-marshal.h
ENUMFILES = clutter-enum-types.c clutter-enum-types.h ENUMFILES = clutter-enum-types.c clutter-enum-types.h
GLIB_GENMARSHAL=`pkg-config --variable=glib_genmarshal glib-2.0` GLIB_GENMARSHAL=`pkg-config --variable=glib_genmarshal glib-2.0`
@ -7,28 +5,26 @@ GLIB_MKENUMS=`pkg-config --variable=glib_mkenums glib-2.0`
BUILT_SOURCES = $(MARSHALFILES) $(ENUMFILES) BUILT_SOURCES = $(MARSHALFILES) $(ENUMFILES)
source_h = \ source_h = \
$(srcdir)/clutter-keysyms.h \ $(srcdir)/clutter-keysyms.h \
$(srcdir)/clutter-util.h \ $(srcdir)/clutter-util.h \
$(srcdir)/clutter-fixed.h \ $(srcdir)/clutter-fixed.h \
$(srcdir)/clutter-event.h \ $(srcdir)/clutter-event.h \
$(srcdir)/clutter-color.h \ $(srcdir)/clutter-color.h \
$(srcdir)/clutter-feature.h \ $(srcdir)/clutter-feature.h \
$(srcdir)/clutter-timeline.h \ $(srcdir)/clutter-timeline.h \
$(srcdir)/clutter-actor.h \ $(srcdir)/clutter-actor.h \
$(srcdir)/clutter-group.h \ $(srcdir)/clutter-group.h \
$(srcdir)/clutter-stage.h \ $(srcdir)/clutter-stage.h \
$(srcdir)/clutter-rectangle.h \ $(srcdir)/clutter-rectangle.h \
$(srcdir)/clutter-texture.h \ $(srcdir)/clutter-texture.h \
$(srcdir)/clutter-clone-texture.h \ $(srcdir)/clutter-clone-texture.h \
$(srcdir)/clutter-label.h \ $(srcdir)/clutter-label.h \
$(srcdir)/clutter-behaviour.h \ $(srcdir)/clutter-behaviour.h \
$(srcdir)/clutter-opacity-behaviour.h \ $(srcdir)/clutter-behaviours.h \
$(srcdir)/clutter-blink-behaviour.h \ $(srcdir)/clutter-alpha.h \
$(srcdir)/clutter-alpha.h \ $(srcdir)/clutter-media.h \
$(srcdir)/clutter-media.h \ $(srcdir)/clutter-main.h
$(srcdir)/clutter-main.h \
$(NULL)
clutter-marshal.h: clutter-marshal.list clutter-marshal.h: clutter-marshal.list
( $(GLIB_GENMARSHAL) --prefix=clutter_marshal \ ( $(GLIB_GENMARSHAL) --prefix=clutter_marshal \
@ -75,26 +71,24 @@ clutter-enum-types.c: clutter-enum-types.h
CLEANFILES = $(BUILT_SOURCES) stamp-clutter-enum-types.h CLEANFILES = $(BUILT_SOURCES) stamp-clutter-enum-types.h
source_c = clutter-main.c \ source_c = clutter-main.c \
clutter-util.c \ clutter-util.c \
clutter-feature.c \ clutter-feature.c \
clutter-event.c \ clutter-event.c \
clutter-color.c \ clutter-color.c \
clutter-timeline.c \ clutter-timeline.c \
clutter-group.c \ clutter-group.c \
clutter-stage.c \ clutter-stage.c \
clutter-rectangle.c \ clutter-rectangle.c \
clutter-texture.c \ clutter-texture.c \
clutter-clone-texture.c \ clutter-clone-texture.c \
clutter-label.c \ clutter-label.c \
clutter-actor.c \ clutter-actor.c \
clutter-behaviour.c \ clutter-behaviour.c \
clutter-opacity-behaviour.c \ clutter-behaviours.c \
clutter-blink-behaviour.c \ clutter-alpha.c \
clutter-alpha.c \ clutter-media.c \
clutter-media.c \ clutter-enum-types.c
clutter-enum-types.c \
$(NULL)
source_h_priv = clutter-private.h source_h_priv = clutter-private.h

View File

@ -5,7 +5,6 @@
* *
* Authored By Matthew Allum <mallum@openedhand.com> * Authored By Matthew Allum <mallum@openedhand.com>
* Jorn Baayen <jorn@openedhand.com> * Jorn Baayen <jorn@openedhand.com>
* Emmanuele Bassi <ebassi@openedhand.com>
* *
* Copyright (C) 2006 OpenedHand * Copyright (C) 2006 OpenedHand
* *
@ -32,137 +31,78 @@
* *
* #ClutterAlpha is a class for calculating an alpha value as a function * #ClutterAlpha is a class for calculating an alpha value as a function
* of time. * of time.
*
* When you create a #ClutterAlpha object you should attach a #ClutterTimeline
* to it, to be used as a time source. You need to supply the alpha
* function to be invoked at each timeline "tick"; some common alpha functions
* are available.
*/ */
#include "config.h"
#include "clutter-alpha.h" #include "clutter-alpha.h"
#include "clutter-main.h" #include "clutter-main.h"
#include "clutter-marshal.h" #include "clutter-marshal.h"
G_DEFINE_TYPE (ClutterAlpha, G_DEFINE_TYPE (ClutterAlpha, clutter_alpha, G_TYPE_OBJECT);
clutter_alpha,
G_TYPE_INITIALLY_UNOWNED);
struct _ClutterAlphaPrivate struct ClutterAlphaPrivate
{ {
ClutterTimeline *timeline; ClutterTimeline *timeline;
guint timeline_new_frame_id;
guint32 alpha; guint32 alpha;
ClutterAlphaFunc func; ClutterAlphaFunc func;
gpointer data;
GDestroyNotify destroy;
gint delay;
guint is_paused : 1;
}; };
enum enum
{ {
PROP_0, PROP_0,
PROP_TIMELINE, PROP_TIMELINE,
PROP_DELAY, PROP_FUNC,
PROP_IS_PAUSED,
PROP_ALPHA PROP_ALPHA
}; };
/* Alpha funcs */ /* Alpha funcs */
/**
* clutter_alpha_ramp_inc_func:
* @alpha: a #ClutterAlpha
* @data: user data (ignored)
*
* Return value:
*
* Since: 0.2
*/
guint32 guint32
clutter_alpha_ramp_inc_func (ClutterAlpha *alpha, clutter_alpha_ramp_inc_func (ClutterAlpha *alpha)
gpointer data)
{ {
ClutterTimeline *timeline; int current_frame_num, nframes;
gint current_frame_num, nframes;
g_return_val_if_fail (CLUTTER_IS_ALPHA (alpha), 0); current_frame_num =
clutter_timeline_get_current_frame (alpha->priv->timeline);
nframes =
clutter_timeline_get_n_frames (alpha->priv->timeline);
timeline = clutter_alpha_get_timeline (alpha); return (current_frame_num * CLUTTER_ALPHA_MAX_ALPHA) / nframes;
current_frame_num = clutter_timeline_get_current_frame (timeline);
nframes = clutter_timeline_get_n_frames (timeline);
return (current_frame_num * CLUTTER_ALPHA_MAX) / nframes;
} }
/**
* clutter_alpha_ramp_dec_func:
* @alpha: a #ClutterAlpha
* @data: user data (ignored)
*
* Return value:
*
* Since: 0.2
*/
guint32 guint32
clutter_alpha_ramp_dec_func (ClutterAlpha *alpha, clutter_alpha_ramp_dec_func (ClutterAlpha *alpha)
gpointer data)
{ {
ClutterTimeline *timeline; int current_frame_num, nframes;
gint current_frame_num, nframes;
g_return_val_if_fail (CLUTTER_IS_ALPHA (alpha), 0); current_frame_num =
clutter_timeline_get_current_frame (alpha->priv->timeline);
nframes =
clutter_timeline_get_n_frames (alpha->priv->timeline);
timeline = clutter_alpha_get_timeline (alpha); return ((nframes - current_frame_num) * CLUTTER_ALPHA_MAX_ALPHA) / nframes;
current_frame_num = clutter_timeline_get_current_frame (timeline);
nframes = clutter_timeline_get_n_frames (timeline);
return ((nframes - current_frame_num) * CLUTTER_ALPHA_MAX) / nframes;
} }
/**
* clutter_alpha_ramp_func:
* @alpha: a #ClutterAlpha
* @data: user data (ignored)
*
* Return value:
*
* Since: 0.2
*/
guint32 guint32
clutter_alpha_ramp_func (ClutterAlpha *alpha, clutter_alpha_ramp_func (ClutterAlpha *alpha)
gpointer data)
{ {
ClutterTimeline *timeline; int current_frame_num, nframes;
gint current_frame_num, nframes;
guint32 retval;
g_return_val_if_fail (CLUTTER_IS_ALPHA (alpha), 0); current_frame_num =
clutter_timeline_get_current_frame (alpha->priv->timeline);
nframes =
clutter_timeline_get_n_frames (alpha->priv->timeline);
timeline = clutter_alpha_get_timeline (alpha); if (current_frame_num > (nframes/2))
current_frame_num = clutter_timeline_get_current_frame (timeline);
nframes = clutter_timeline_get_n_frames (timeline);
if (current_frame_num > (nframes / 2))
{ {
retval = (nframes - current_frame_num) * CLUTTER_ALPHA_MAX; return ((nframes - current_frame_num)
retval = retval / (nframes / 2); * CLUTTER_ALPHA_MAX_ALPHA) / (nframes/2);
} }
else else
{ {
retval = current_frame_num * CLUTTER_ALPHA_MAX; return (current_frame_num * CLUTTER_ALPHA_MAX_ALPHA) / (nframes/2);
retval = retval / (nframes / 2);
} }
return retval;
} }
/* Object */ /* Object */
@ -172,24 +112,16 @@ timeline_new_frame_cb (ClutterTimeline *timeline,
guint current_frame_num, guint current_frame_num,
ClutterAlpha *alpha) ClutterAlpha *alpha)
{ {
ClutterAlphaPrivate *priv = alpha->priv; ClutterAlphaPrivate *priv;
if (priv->is_paused) priv = alpha->priv;
return;
if ((priv->delay != -1) && (current_frame_num < priv->delay))
return;
/* Update alpha value */ /* Update alpha value */
if (priv->func) if (priv->func) {
{ priv->alpha = priv->func(alpha);
g_object_ref (alpha);
g_object_notify (G_OBJECT (alpha), "alpha");
priv->alpha = priv->func (alpha, priv->data); }
g_object_notify (G_OBJECT (alpha), "alpha");
g_object_unref (alpha);
}
} }
static void static void
@ -198,18 +130,19 @@ clutter_alpha_set_property (GObject *object,
const GValue *value, const GValue *value,
GParamSpec *pspec) GParamSpec *pspec)
{ {
ClutterAlpha *alpha = CLUTTER_ALPHA (object); ClutterAlpha *alpha;
ClutterAlphaPrivate *priv;
alpha = CLUTTER_ALPHA(object);
priv = alpha->priv;
switch (prop_id) switch (prop_id)
{ {
case PROP_TIMELINE: case PROP_TIMELINE:
clutter_alpha_set_timeline (alpha, g_value_get_object (value)); clutter_alpha_set_timeline (alpha, g_value_get_object (value));
break; break;
case PROP_DELAY: case PROP_FUNC:
alpha->priv->delay = g_value_get_int (value); priv->func = g_value_get_pointer (value);
break;
case PROP_IS_PAUSED:
alpha->priv->is_paused = g_value_get_boolean (value);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@ -223,24 +156,23 @@ clutter_alpha_get_property (GObject *object,
GValue *value, GValue *value,
GParamSpec *pspec) GParamSpec *pspec)
{ {
ClutterAlpha *alpha;
ClutterAlphaPrivate *priv; ClutterAlphaPrivate *priv;
priv = CLUTTER_ALPHA (object)->priv; alpha = CLUTTER_ALPHA(object);
priv = alpha->priv;
switch (prop_id) switch (prop_id)
{ {
case PROP_TIMELINE: case PROP_TIMELINE:
g_value_set_object (value, priv->timeline); g_value_set_object (value, priv->timeline);
break; break;
case PROP_FUNC:
g_value_set_pointer (value, priv->func);
break;
case PROP_ALPHA: case PROP_ALPHA:
g_value_set_uint (value, priv->alpha); g_value_set_uint (value, priv->alpha);
break; break;
case PROP_DELAY:
g_value_set_int (value, priv->delay);
break;
case PROP_IS_PAUSED:
g_value_set_boolean (value, priv->is_paused);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -250,24 +182,13 @@ clutter_alpha_get_property (GObject *object,
static void static void
clutter_alpha_finalize (GObject *object) clutter_alpha_finalize (GObject *object)
{ {
ClutterAlphaPrivate *priv = CLUTTER_ALPHA (object)->priv;
if (priv->destroy)
{
priv->destroy (priv->data);
priv->data = NULL;
priv->destroy = NULL;
priv->func = NULL;
}
G_OBJECT_CLASS (clutter_alpha_parent_class)->finalize (object); G_OBJECT_CLASS (clutter_alpha_parent_class)->finalize (object);
} }
static void static void
clutter_alpha_dispose (GObject *object) clutter_alpha_dispose (GObject *object)
{ {
ClutterAlpha *self = CLUTTER_ALPHA (object); ClutterAlpha *self = CLUTTER_ALPHA(object);
clutter_alpha_set_timeline (self, NULL); clutter_alpha_set_timeline (self, NULL);
@ -280,7 +201,7 @@ clutter_alpha_class_init (ClutterAlphaClass *klass)
{ {
GObjectClass *object_class; GObjectClass *object_class;
object_class = G_OBJECT_CLASS (klass); object_class = (GObjectClass*) klass;
object_class->set_property = clutter_alpha_set_property; object_class->set_property = clutter_alpha_set_property;
object_class->get_property = clutter_alpha_get_property; object_class->get_property = clutter_alpha_get_property;
@ -289,98 +210,52 @@ clutter_alpha_class_init (ClutterAlphaClass *klass)
g_type_class_add_private (klass, sizeof (ClutterAlphaPrivate)); g_type_class_add_private (klass, sizeof (ClutterAlphaPrivate));
/** g_object_class_install_property
* ClutterAlpha:timeline (object_class, PROP_TIMELINE,
* g_param_spec_object ("timeline",
* The #ClutterTimeline object to be used when calculating "Timeline",
* the alpha value. "Timeline",
* CLUTTER_TYPE_TIMELINE,
* Since: 0.2 G_PARAM_READWRITE));
*/
g_object_class_install_property (object_class, g_object_class_install_property
PROP_TIMELINE, (object_class, PROP_FUNC,
g_param_spec_object ("timeline", g_param_spec_pointer ("func",
"Timeline", "Alpha function",
"Timeline", "Alpha function",
CLUTTER_TYPE_TIMELINE, G_PARAM_READWRITE));
G_PARAM_READWRITE));
/** g_object_class_install_property
* ClutterAlpha:alpha (object_class, PROP_ALPHA,
* g_param_spec_uint ("alpha",
* The last computed value of the alpha function. "Alpha value",
* "Alpha value",
* Since: 0.2 0,
*/ CLUTTER_ALPHA_MAX_ALPHA,
g_object_class_install_property (object_class, 0,
PROP_ALPHA, G_PARAM_READABLE));
g_param_spec_uint ("alpha",
"Alpha",
"Alpha value",
CLUTTER_ALPHA_MIN,
CLUTTER_ALPHA_MAX,
CLUTTER_ALPHA_MIN,
G_PARAM_READABLE));
/**
* ClutterAlpha:delay
*
* The number of frames that should be skipped before
* starting the calculation of the alpha function.
*
* Since: 0.2
*/
g_object_class_install_property (object_class,
PROP_DELAY,
g_param_spec_int ("delay",
"Delay",
"The number of frames that should be skipped "
"before computing the alpha function",
0,
G_MAXINT,
0,
G_PARAM_READWRITE));
/**
* ClutterAlpha:is-paused
*
* Whether the #ClutterAlpha should be paused or not;
* the timeline bound to the #ClutterAlpha object will
* continue to run.
*
* Since: 0.2
*/
g_object_class_install_property (object_class,
PROP_IS_PAUSED,
g_param_spec_boolean ("is-paused",
"Is Paused",
"Whether the alpha should be paused or not",
FALSE,
G_PARAM_READWRITE));
} }
static void static void
clutter_alpha_init (ClutterAlpha *self) clutter_alpha_init (ClutterAlpha *self)
{ {
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self,
CLUTTER_TYPE_ALPHA, CLUTTER_TYPE_ALPHA,
ClutterAlphaPrivate); ClutterAlphaPrivate);
self->priv->func = CLUTTER_ALPHA_RAMP_INC; self->priv->func = CLUTTER_ALPHA_RAMP_INC;
self->priv->delay = -1;
self->priv->is_paused = FALSE;
} }
/** /**
* clutter_alpha_get_value: * clutter_alpha_get_alpha:
* @alpha: A #ClutterAlpha * @alpha: A #ClutterAlpha
* *
* Query the current alpha value. * Query the current alpha value.
* *
* Return value: The current alpha value for the alpha * Return Value: The current alpha value for the alpha
*
* Since: 0.2
*/ */
guint32 gint32
clutter_alpha_get_value (ClutterAlpha *alpha) clutter_alpha_get_alpha (ClutterAlpha *alpha)
{ {
g_return_val_if_fail (CLUTTER_IS_ALPHA (alpha), FALSE); g_return_val_if_fail (CLUTTER_IS_ALPHA (alpha), FALSE);
@ -391,248 +266,74 @@ clutter_alpha_get_value (ClutterAlpha *alpha)
* clutter_alpha_set_func: * clutter_alpha_set_func:
* @alpha: A #ClutterAlpha * @alpha: A #ClutterAlpha
* @func: A #ClutterAlphaAlphaFunc * @func: A #ClutterAlphaAlphaFunc
* @data: the data to be passed to func or %NULL
* @destroy: the function to be called when removing the previous
* alpha function or %NULL
* *
* Since: 0.2
*/ */
void void
clutter_alpha_set_func (ClutterAlpha *alpha, clutter_alpha_set_func (ClutterAlpha *alpha,
ClutterAlphaFunc func, ClutterAlphaFunc func)
gpointer data,
GDestroyNotify destroy)
{ {
ClutterAlphaPrivate *priv; alpha->priv->func = func;
g_return_if_fail (CLUTTER_IS_ALPHA (alpha));
g_return_if_fail (func != NULL);
priv = alpha->priv;
if (priv->destroy)
{
priv->destroy (priv->data);
priv->destroy = NULL;
priv->data = NULL;
}
priv->func = func;
priv->data = data;
priv->destroy = destroy;
} }
/** /**
* clutter_alpha_set_timeline: * clutter_alpha_set_timeline:
* @alpha: A #ClutterAlpha * @alpha: A #ClutterAlpha
* @timeline: A #ClutterTimeline or %NULL to unset the timeline * @timeline: A #ClutterTimeline
* *
* Binds @timeline to @alpha. Since an alpha is a function of time, * Binds @alpha to @timeline.
* @timeline will be used to compute the alpha each time the "new-frame"
* signal of @timeline is emitted.
*
* Since: 0.2
*/ */
void void
clutter_alpha_set_timeline (ClutterAlpha *alpha, clutter_alpha_set_timeline (ClutterAlpha *alpha,
ClutterTimeline *timeline) ClutterTimeline *timeline)
{ {
ClutterAlphaPrivate *priv; if (alpha->priv->timeline)
g_return_if_fail (CLUTTER_IS_ALPHA (alpha));
g_return_if_fail (timeline == NULL || CLUTTER_IS_TIMELINE (timeline));
priv = alpha->priv;
g_object_ref (alpha);
if (priv->timeline)
{ {
g_signal_handlers_disconnect_by_func (priv->timeline, g_signal_handler_disconnect (alpha->priv->timeline,
timeline_new_frame_cb, alpha->priv->timeline_new_frame_id);
alpha);
g_object_unref (priv->timeline); g_object_unref (alpha->priv->timeline);
priv->timeline = NULL; alpha->priv->timeline = NULL;
} }
if (timeline) if (timeline)
{ {
priv->timeline = g_object_ref (timeline); alpha->priv->timeline = g_object_ref (timeline);
g_signal_connect (priv->timeline, "new-frame", alpha->priv->timeline_new_frame_id =
G_CALLBACK (timeline_new_frame_cb), g_signal_connect (alpha->priv->timeline,
alpha); "new-frame",
G_CALLBACK (timeline_new_frame_cb),
alpha);
} }
g_object_notify (G_OBJECT (alpha), "timeline");
g_object_unref (alpha);
} }
/** /**
* clutter_alpha_get_timeline: * clutter_alpha_get_timeline:
* @alpha: A #ClutterAlpha * @alpha: A #ClutterAlpha
* *
* Gets the #ClutterTimeline object bound to @alpha. * Return value: The #ClutterTimeline
*
* Return value: The #ClutterTimeline bount to @alpa or %NULL.
*
* Since: 0.2
*/ */
ClutterTimeline * ClutterTimeline *
clutter_alpha_get_timeline (ClutterAlpha *alpha) clutter_alpha_get_timeline (ClutterAlpha *alpha)
{ {
g_return_val_if_fail (CLUTTER_IS_ALPHA (alpha), NULL);
return alpha->priv->timeline; return alpha->priv->timeline;
} }
/**
* clutter_alpha_get_delay:
* @alpha: a #ClutterAlpha
*
* Gets the delay used by @alpha. See clutter_alpha_set_delay().
*
* Return value: the number of frames to wait, or -1
*
* Since: 0.2
*/
gint
clutter_alpha_get_delay (ClutterAlpha *alpha)
{
g_return_val_if_fail (CLUTTER_IS_ALPHA (alpha), -1);
return alpha->priv->delay;
}
/**
* clutter_alpha_set_delay:
* @alpha: a #ClutterAlpha
* @delay: the number of frames to wait or -1 for no delay
*
* Sets the number of timeline frames to wait before starting to
* compute the alpha value.
*
* Since: 0.2
*/
void
clutter_alpha_set_delay (ClutterAlpha *alpha,
gint delay)
{
g_return_if_fail (CLUTTER_IS_ALPHA (alpha));
if (alpha->priv->delay != delay)
{
g_object_ref (alpha);
alpha->priv->delay = delay;
g_object_notify (G_OBJECT (alpha), "delay");
g_object_unref (alpha);
}
}
/**
* clutter_alpha_get_is_paused:
* @alpha: a #ClutterAlpha
*
* Gets whether @alpha is in paused state or not.
* See clutter_alpha_set_is_paused().
*
* Return value: %TRUE if @alpha is paused
*
* Since: 0.2
*/
gboolean
clutter_alpha_get_is_paused (ClutterAlpha *alpha)
{
g_return_val_if_fail (CLUTTER_IS_ALPHA (alpha), FALSE);
return alpha->priv->is_paused;
}
/**
* clutter_alpha_set_is_paused:
* @alpha: a #ClutterAlpha
* @is_paused: %TRUE to pause the alpha
*
* Pauses the calculation of the alpha value of @alpha. This is
* independent of the running state of the #ClutterTimeline bount
* to @alpha.
*
* Since: 0.2
*/
void
clutter_alpha_set_is_paused (ClutterAlpha *alpha,
gboolean is_paused)
{
g_return_if_fail (CLUTTER_IS_ALPHA (alpha));
if (alpha->priv->is_paused != is_paused)
{
g_object_ref (alpha);
alpha->priv->is_paused = is_paused;
g_object_notify (G_OBJECT (alpha), "is-paused");
g_object_unref (alpha);
}
}
/** /**
* clutter_alpha_new: * clutter_alpha_new:
* @timeline: a #ClutterTimeline or %NULL * @timeline: #ClutterTimeline timeline
* @func: a #ClutterAlphaFunc alpha function * @func: #ClutterAlphaFunc alpha function
* @data: data to be passed to func, or %NULL
* *
* Creates a new #ClutterAlpha instance, using @timeline as the time * Create a new #ClutterAlpha instance.
* source and @func as the function to compute the alpha(t) value.
* *
* Return value: a new #ClutterAlpha * Return Value: a new #ClutterAlpha
*
* Since: 0.2
*/ */
ClutterAlpha * ClutterAlpha*
clutter_alpha_new (ClutterTimeline *timeline, clutter_alpha_new (ClutterTimeline *timeline,
ClutterAlphaFunc func, ClutterAlphaFunc func)
gpointer data)
{ {
return clutter_alpha_new_full (timeline, func, data, NULL); return g_object_new (CLUTTER_TYPE_ALPHA,
} "timeline", timeline,
"func", func,
/** NULL);
* clutter_alpha_new_full:
* @timeline: #ClutterTimeline or %NULL
* @func: a #ClutterAlphaFunc
* @data: data to be passed to func
* @destroy: function to be called when removing the alpha function
*
* Creates a new #ClutterAlpha instance, using @timeline as the
* time source and @func as the function to compute the alpha(t)
* value.
*
* You should use this constructor in bindings or if you want to
* let the #ClutterAlpha object control the lifetime of @data.
*
* Return value: the newly created #ClutterAlpha instance
*
* Since: 0.2
*/
ClutterAlpha *
clutter_alpha_new_full (ClutterTimeline *timeline,
ClutterAlphaFunc func,
gpointer data,
GDestroyNotify destroy)
{
ClutterAlpha *retval;
g_return_val_if_fail (timeline == NULL || CLUTTER_IS_TIMELINE (timeline), NULL);
g_return_val_if_fail (func != NULL, NULL);
retval = g_object_new (CLUTTER_TYPE_ALPHA,
"timeline", timeline,
NULL);
clutter_alpha_set_func (retval, func, data, destroy);
return retval;
} }

View File

@ -5,7 +5,6 @@
* *
* Authored By Matthew Allum <mallum@openedhand.com> * Authored By Matthew Allum <mallum@openedhand.com>
* Jorn Baayen <jorn@openedhand.com> * Jorn Baayen <jorn@openedhand.com>
* Emmanuele Bassi <ebassi@openedhand.com>
* *
* Copyright (C) 2006 OpenedHand * Copyright (C) 2006 OpenedHand
* *
@ -25,41 +24,54 @@
* Boston, MA 02111-1307, USA. * Boston, MA 02111-1307, USA.
*/ */
#ifndef __CLUTTER_ALPHA_H__ #ifndef _HAVE_CLUTTER_ALPHA_H
#define __CLUTTER_ALPHA_H__ #define _HAVE_CLUTTER_ALPHA_H
/* clutter-alpha.h */ /* clutter-alpha.h */
#include <glib-object.h> #include <glib-object.h>
#include <clutter/clutter-timeline.h>
#include "clutter-timeline.h"
G_BEGIN_DECLS G_BEGIN_DECLS
#define CLUTTER_TYPE_ALPHA (clutter_alpha_get_type ()) #define CLUTTER_TYPE_ALPHA clutter_alpha_get_type()
#define CLUTTER_ALPHA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ALPHA, ClutterAlpha))
#define CLUTTER_ALPHA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ALPHA, ClutterAlphaClass))
#define CLUTTER_IS_ALPHA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ALPHA))
#define CLUTTER_IS_ALPHA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ALPHA))
#define CLUTTER_ALPHA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ALPHA, ClutterAlphaClass))
typedef struct _ClutterAlpha ClutterAlpha; #define CLUTTER_ALPHA(obj) \
typedef struct _ClutterAlphaClass ClutterAlphaClass; (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
typedef struct _ClutterAlphaPrivate ClutterAlphaPrivate; CLUTTER_TYPE_ALPHA, ClutterAlpha))
typedef guint32 (*ClutterAlphaFunc) (ClutterAlpha *alpha, #define CLUTTER_ALPHA_CLASS(klass) \
gpointer data); (G_TYPE_CHECK_CLASS_CAST ((klass), \
CLUTTER_TYPE_ALPHA, ClutterAlphaClass))
#define CLUTTER_IS_ALPHA(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
CLUTTER_TYPE_ALPHA))
#define CLUTTER_IS_ALPHA_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
CLUTTER_TYPE_ALPHA))
#define CLUTTER_ALPHA_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
CLUTTER_TYPE_ALPHA, ClutterAlphaClass))
typedef struct _ClutterAlpha ClutterAlpha;
typedef struct _ClutterAlphaClass ClutterAlphaClass;
typedef struct ClutterAlphaPrivate ClutterAlphaPrivate;
typedef guint32 (*ClutterAlphaFunc) (ClutterAlpha *alpha);
struct _ClutterAlpha struct _ClutterAlpha
{ {
GInitiallyUnowned parent; GObject parent;
/*< private >*/
ClutterAlphaPrivate *priv; ClutterAlphaPrivate *priv;
}; };
struct _ClutterAlphaClass struct _ClutterAlphaClass
{ {
GInitiallyUnowned parent_class; GObjectClass parent_class;
void (*_clutter_alpha_1) (void); void (*_clutter_alpha_1) (void);
void (*_clutter_alpha_2) (void); void (*_clutter_alpha_2) (void);
@ -68,37 +80,34 @@ struct _ClutterAlphaClass
void (*_clutter_alpha_5) (void); void (*_clutter_alpha_5) (void);
}; };
#define CLUTTER_ALPHA_MIN 0x0000 #define CLUTTER_ALPHA_MAX_ALPHA 0xffff
#define CLUTTER_ALPHA_MAX 0xffff
GType clutter_alpha_get_type (void) G_GNUC_CONST; ClutterAlpha *
ClutterAlpha * clutter_alpha_new (ClutterTimeline *timeline, clutter_alpha_new (ClutterTimeline *timeline,
ClutterAlphaFunc func, ClutterAlphaFunc func);
gpointer data);
ClutterAlpha * clutter_alpha_new_full (ClutterTimeline *timeline,
ClutterAlphaFunc func,
gpointer data,
GDestroyNotify destroy);
guint32 clutter_alpha_get_value (ClutterAlpha *alpha);
void clutter_alpha_set_func (ClutterAlpha *alpha,
ClutterAlphaFunc func,
gpointer data,
GDestroyNotify destroy);
gint clutter_alpha_get_delay (ClutterAlpha *alpha);
void clutter_alpha_set_delay (ClutterAlpha *alpha,
gint delay);
gboolean clutter_alpha_get_is_paused (ClutterAlpha *alpha);
void clutter_alpha_set_is_paused (ClutterAlpha *alpha,
gboolean is_paused);
ClutterTimeline *clutter_alpha_get_timeline (ClutterAlpha *alpha);
void clutter_alpha_set_timeline (ClutterAlpha *alpha,
ClutterTimeline *timeline);
gint32
clutter_alpha_get_alpha (ClutterAlpha *alpha);
/* predefined alpha functions */ void
guint32 clutter_alpha_ramp_inc_func (ClutterAlpha *alpha, gpointer data); clutter_alpha_set_func (ClutterAlpha *alpha,
guint32 clutter_alpha_ramp_dec_func (ClutterAlpha *alpha, gpointer data); ClutterAlphaFunc func);
guint32 clutter_alpha_ramp_func (ClutterAlpha *alpha, gpointer data);
void
clutter_alpha_set_timeline (ClutterAlpha *alpha,
ClutterTimeline *timeline);
ClutterTimeline *
clutter_alpha_get_timeline (ClutterAlpha *alpha);
guint32
clutter_alpha_ramp_inc_func (ClutterAlpha *alpha);
guint32
clutter_alpha_ramp_dec_func (ClutterAlpha *alpha);
guint32
clutter_alpha_ramp_func (ClutterAlpha *alpha);
#define CLUTTER_ALPHA_RAMP_INC clutter_alpha_ramp_inc_func #define CLUTTER_ALPHA_RAMP_INC clutter_alpha_ramp_inc_func
#define CLUTTER_ALPHA_RAMP_DEC clutter_alpha_ramp_dec_func #define CLUTTER_ALPHA_RAMP_DEC clutter_alpha_ramp_dec_func

View File

@ -31,154 +31,156 @@
#include "config.h" #include "config.h"
#include <string.h>
#include <gobject/gobjectnotifyqueue.c>
#include "clutter-actor.h" #include "clutter-actor.h"
#include "clutter-behaviour.h" #include "clutter-behaviour.h"
#include "clutter-marshal.h" #include "clutter-marshal.h"
struct _ClutterBehaviourPrivate G_DEFINE_TYPE (ClutterBehaviour, clutter_behaviour, G_TYPE_OBJECT);
{
ClutterAlpha *alpha;
GSList *actors; struct ClutterBehaviourPrivate
{
GObject *object;
GParamSpec *param_spec;
guint notify_id;
GSList *actors;
}; };
enum enum
{ {
PROP_0, PROP_0,
PROP_OBJECT,
PROP_ALPHA PROP_PROPERTY
}; };
enum enum {
{ SIGNAL_PROPERTY_CHANGE,
NOTIFY_BEHAVIOUR,
SIGNAL_LAST SIGNAL_LAST
}; };
static GObjectClass *clutter_behaviour_parent_class = NULL; static guint signals[SIGNAL_LAST];
static GParamSpecPool *pspec_pool = NULL;
static GObjectNotifyContext property_notify_context = { 0, };
static guint behaviour_signals[SIGNAL_LAST] = { 0, };
static GQuark quark_property_bridge = 0;
#define CLUTTER_BEHAVIOUR_GET_PRIVATE(obj) \ #define CLUTTER_BEHAVIOUR_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
CLUTTER_TYPE_BEHAVIOUR, \ CLUTTER_TYPE_BEHAVIOUR, \
ClutterBehaviourPrivate)) ClutterBehaviourPrivate))
static void static void
clutter_behaviour_dispatch_property_changed (ClutterBehaviour *behaviour, _clutter_behaviour_dispose (GObject *object)
guint n_pspecs,
GParamSpec **pspecs)
{ {
guint i; ClutterBehaviour *self = CLUTTER_BEHAVIOUR(object);
for (i = 0; i < n_pspecs; i++) if (self->priv)
{ {
g_signal_emit (behaviour, /* FIXME: remove all actors */
behaviour_signals[NOTIFY_BEHAVIOUR],
g_quark_from_string (pspecs[i]->name),
pspecs[i]);
}
}
static void clutter_behaviour_set_object (self, NULL);
clutter_behaviour_base_finalize (ClutterBehaviourClass *klass)
{
GList *list, *node;
list = g_param_spec_pool_list_owned (pspec_pool,
G_OBJECT_CLASS_TYPE (klass));
for (node = list; node != NULL; node = node->next)
{
GParamSpec *pspec = node->data;
g_param_spec_pool_remove (pspec_pool, pspec);
g_param_spec_unref (pspec);
} }
g_list_free (list); G_OBJECT_CLASS (clutter_behaviour_parent_class)->dispose (object);
} }
static void static void
clutter_behaviour_finalize (GObject *object) _clutter_behaviour_finalize (GObject *object)
{ {
ClutterBehaviour *self = CLUTTER_BEHAVIOUR (object); ClutterBehaviour *self = CLUTTER_BEHAVIOUR(object);
if (self->priv->alpha) if (self->priv)
g_object_unref (self->priv->alpha);
if (self->priv->actors)
{ {
g_slist_foreach (self->priv->actors, g_free(self->priv);
(GFunc) g_object_unref, self->priv = NULL;
NULL);
g_slist_free (self->priv->actors);
} }
G_OBJECT_CLASS (clutter_behaviour_parent_class)->finalize (object); G_OBJECT_CLASS (clutter_behaviour_parent_class)->finalize (object);
} }
static void static void
clutter_behaviour_set_property (GObject *object, _clutter_behaviour_set_property (GObject *object,
guint prop_id, guint prop_id,
const GValue *value, const GValue *value,
GParamSpec *pspec) GParamSpec *pspec)
{ {
ClutterBehaviour *behaviour;
behaviour = CLUTTER_BEHAVIOUR(object);
switch (prop_id) switch (prop_id)
{ {
case PROP_OBJECT:
clutter_behaviour_set_object (behaviour, g_value_get_object (value));
break;
case PROP_PROPERTY:
clutter_behaviour_set_property (behaviour, g_value_get_string (value));
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
} }
static void static void
clutter_behaviour_get_property (GObject *object, _clutter_behaviour_get_property (GObject *object,
guint prop_id, guint prop_id,
GValue *value, GValue *value,
GParamSpec *pspec) GParamSpec *pspec)
{ {
ClutterBehaviour *behaviour;
ClutterBehaviourPrivate *priv;
behaviour = CLUTTER_BEHAVIOUR(object);
priv = CLUTTER_BEHAVIOUR_GET_PRIVATE(behaviour);
switch (prop_id) switch (prop_id)
{ {
case PROP_OBJECT:
g_value_set_object (value, priv->object);
break;
case PROP_PROPERTY:
g_value_set_string (value, priv->param_spec->name);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
} }
static void
property_notify_dispatcher (GObject *object,
guint n_pspecs,
GParamSpec **pspecs)
{
CLUTTER_BEHAVIOUR_GET_CLASS (object)->dispatch_property_changed (CLUTTER_BEHAVIOUR (object), n_pspecs, pspecs);
}
static void static void
clutter_behaviour_class_init (ClutterBehaviourClass *klass) clutter_behaviour_class_init (ClutterBehaviourClass *klass)
{ {
GObjectClass *object_class; GObjectClass *object_class;
object_class = G_OBJECT_CLASS (klass); object_class = (GObjectClass*) klass;
clutter_behaviour_parent_class = g_type_class_peek_parent (klass); object_class->finalize = _clutter_behaviour_finalize;
pspec_pool = g_param_spec_pool_new (FALSE); object_class->dispose = _clutter_behaviour_dispose;
property_notify_context.quark_notify_queue = object_class->set_property = _clutter_behaviour_set_property;
g_quark_from_static_string ("ClutterBehaviour-notify-queue"); object_class->get_property = _clutter_behaviour_get_property;
property_notify_context.dispatcher =
property_notify_dispatcher;
quark_property_bridge = g_quark_from_static_string ("clutter-property-bridge");
object_class->finalize = clutter_behaviour_finalize; g_object_class_install_property
object_class->set_property = clutter_behaviour_set_property; (object_class, PROP_OBJECT,
object_class->get_property = clutter_behaviour_get_property; g_param_spec_object ("object",
"Object",
"Object whose property to monitor",
G_TYPE_OBJECT,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
klass->dispatch_property_changed = clutter_behaviour_dispatch_property_changed; g_object_class_install_property
(object_class, PROP_PROPERTY,
g_param_spec_string ("property",
"Property",
"Property to monitor",
NULL,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
signals[SIGNAL_PROPERTY_CHANGE] =
g_signal_new ("property-change",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ClutterBehaviourClass, property_change),
NULL, NULL,
clutter_marshal_VOID__OBJECT_POINTER,
G_TYPE_NONE,
2, G_TYPE_OBJECT, G_TYPE_POINTER);
g_type_class_add_private (object_class, sizeof (ClutterBehaviourPrivate)); g_type_class_add_private (object_class, sizeof (ClutterBehaviourPrivate));
} }
@ -189,415 +191,157 @@ clutter_behaviour_init (ClutterBehaviour *self)
ClutterBehaviourPrivate *priv; ClutterBehaviourPrivate *priv;
self->priv = priv = CLUTTER_BEHAVIOUR_GET_PRIVATE (self); self->priv = priv = CLUTTER_BEHAVIOUR_GET_PRIVATE (self);
priv->actors = NULL;
} }
GType ClutterBehaviour*
clutter_behaviour_get_type (void) clutter_behaviour_new (GObject *object,
const char *property)
{ {
static GType behaviour_type = 0; ClutterBehaviour *behave;
if (G_UNLIKELY (behaviour_type == 0)) behave = g_object_new (CLUTTER_TYPE_BEHAVIOUR,
{ "object", object,
const GTypeInfo behaviour_info = "property", property,
{ NULL);
sizeof (ClutterBehaviourClass),
NULL, /* base init */
(GBaseFinalizeFunc) clutter_behaviour_base_finalize,
(GClassInitFunc) clutter_behaviour_class_init,
NULL,
NULL,
sizeof (ClutterBehaviour),
0,
(GInstanceInitFunc) clutter_behaviour_init,
NULL,
};
behaviour_type = return behave;
g_type_register_static (G_TYPE_OBJECT, "ClutterBehaviour",
&behaviour_info,
G_TYPE_FLAG_ABSTRACT);
}
return behaviour_type;
}
/**
* clutter_behaviour_apply:
* @behaviour: a #ClutterBehaviour
* @actor: a #ClutterActor
*
* Applies @behaviour to @actor.
*
* This function holds a reference on @actor.
*
* Since: 0.2
*/
void
clutter_behaviour_apply (ClutterBehaviour *behaviour,
ClutterActor *actor)
{
g_return_if_fail (CLUTTER_IS_BEHAVIOUR (behaviour));
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
if (g_slist_find (behaviour->priv->actors, actor))
{
g_warning ("The behaviour of type `%s' has already been "
"applied to the actor of type `%s'",
G_OBJECT_TYPE_NAME (behaviour),
G_OBJECT_TYPE_NAME (actor));
return;
}
g_object_ref (behaviour);
g_object_freeze_notify (G_OBJECT (behaviour));
g_object_ref (actor);
behaviour->priv->actors = g_slist_append (behaviour->priv->actors, actor);
g_object_thaw_notify (G_OBJECT (behaviour));
g_object_unref (behaviour);
}
/**
* clutter_behaviour_remove:
* @behaviour: a #ClutterBehaviour
* @actor: a #ClutterActor
*
* Removes @behaviour from the list of behaviours
* applied to @actor.
*
* This function removes a reference on @actor.
*
* Since: 0.2
*/
void
clutter_behaviour_remove (ClutterBehaviour *behaviour,
ClutterActor *actor)
{
g_return_if_fail (CLUTTER_IS_BEHAVIOUR (behaviour));
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
g_object_ref (behaviour);
g_object_freeze_notify (G_OBJECT (behaviour));
if (g_slist_find (behaviour->priv->actors, (gconstpointer) actor))
{
behaviour->priv->actors = g_slist_remove (behaviour->priv->actors, actor);
g_object_unref (actor);
}
else
{
g_warning ("The behaviour of type `%s' was not applied "
"to the actor of type `%s'",
G_OBJECT_TYPE_NAME (behaviour),
G_OBJECT_TYPE_NAME (actor));
}
g_object_thaw_notify (G_OBJECT (behaviour));
g_object_unref (behaviour);
}
/**
* clutter_behaviour_actors_foreach:
* @behaviour: a #ClutterBehaviour
* @func: the function you want to apply to all #ClutterActor objects
* @data: data to be passed to @func
*
* Applies @func to all the actors bound to @behaviour.
*
* Since: 0.2
*/
void
clutter_behaviour_actors_foreach (ClutterBehaviour *behaviour,
GFunc func,
gpointer data)
{
g_return_if_fail (CLUTTER_IS_BEHAVIOUR (behaviour));
g_return_if_fail (func != NULL);
g_slist_foreach (behaviour->priv->actors, func, data);
}
/**
* clutter_behaviour_get_actors:
* @behaviour: a #ClutterBehaviour
*
* Gets the list of all #ClutterActor objects bound to @behaviour.
*
* Return value: a GSList with all the actors. The elements of
* the list are owned by the #ClutterBehaviour and should not
* be freed or modified. You should free the list when done.
*
* Since: 0.2
*/
GSList *
clutter_behaviour_get_actors (ClutterBehaviour *behaviour)
{
GSList *retval, *l;
g_return_val_if_fail (CLUTTER_IS_ACTOR (behaviour), NULL);
retval = NULL;
for (l = behaviour->priv->actors; l != NULL; l = l->next)
retval = g_slist_prepend (retval, l->data);
return g_slist_reverse (retval);
}
typedef struct
{
GType actor_type;
gchar *actor_property;
ClutterAlphaTransform transform_func;
} BridgeData;
static void
bridge_data_free (BridgeData *data)
{
g_free (data->actor_property);
g_slice_free (BridgeData, data);
}
static void
clutter_behaviour_apply_value (ClutterBehaviour *behaviour,
GType actor_type,
const gchar *actor_property,
const GValue *value)
{
GSList *l;
for (l = behaviour->priv->actors; l != NULL; l = l->next)
{
ClutterActor *actor = l->data;
if (G_OBJECT_TYPE (actor) == actor_type)
{
g_object_set_property (G_OBJECT (actor),
actor_property,
value);
}
}
}
static void
alpha_notify_func (ClutterAlpha *alpha,
GParamSpec *alpha_pspec,
ClutterBehaviour *behaviour)
{
ClutterBehaviourClass *klass;
GParamSpec **pspecs;
guint n_pspecs, i;
GValue alpha_value = { 0, };
klass = CLUTTER_BEHAVIOUR_GET_CLASS (behaviour);
g_value_init (&alpha_value, G_TYPE_UINT);
g_value_set_uint (&alpha_value, clutter_alpha_get_value (alpha));
pspecs = clutter_behaviour_class_list_properties (klass, &n_pspecs);
for (i = 0; i < n_pspecs; i++)
{
BridgeData *data;
GParamSpec *redirect;
GValue transform_value = { 0, };
gboolean res;
redirect = g_param_spec_get_redirect_target (pspecs[i]);
if (!redirect)
redirect = pspecs[i];
data = g_param_spec_get_qdata (redirect, quark_property_bridge);
g_assert (data != NULL);
res = data->transform_func (behaviour, redirect,
&alpha_value,
&transform_value);
if (!res)
continue;
clutter_behaviour_apply_value (behaviour,
data->actor_type,
data->actor_property,
&transform_value);
}
g_free (pspecs);
} }
void void
clutter_behaviour_set_alpha (ClutterBehaviour *behaviour, clutter_behaviour_apply (ClutterBehaviour *behave, ClutterActor *actor)
ClutterAlpha *alpha)
{ {
ClutterBehaviourPrivate *priv; g_return_if_fail (actor != NULL);
g_return_if_fail (CLUTTER_IS_BEHAVIOUR (behaviour)); if (g_slist_find (behave->priv->actors, (gconstpointer)actor))
g_return_if_fail (alpha == NULL || CLUTTER_IS_ALPHA (alpha));
priv = behaviour->priv;
if (priv->alpha == alpha)
return; return;
g_object_ref (behaviour); g_object_ref (actor);
behave->priv->actors = g_slist_append (behave->priv->actors, actor);
if (priv->alpha)
{
g_signal_handlers_disconnect_by_func (priv->alpha,
alpha_notify_func,
behaviour);
g_object_unref (priv->alpha);
priv->alpha = NULL;
}
if (alpha)
{
priv->alpha = alpha;
g_object_ref_sink (priv->alpha);
g_signal_connect (priv->alpha, "notify::alpha",
G_CALLBACK (alpha_notify_func),
behaviour);
}
g_object_notify (G_OBJECT (behaviour), "alpha");
g_object_unref (behaviour);
} }
ClutterAlpha *
clutter_behaviour_get_alpha (ClutterBehaviour *behaviour)
{
g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR (behaviour), NULL);
if (behaviour->priv->alpha)
return g_object_ref (behaviour->priv->alpha);
return NULL;
}
/**
* clutter_behaviour_class_bind_property:
* @klass: a #ClutterBehaviourClass
* @actor_type: the type of the actor's class
* @actor_property: the name of the actor's class property
* @pspec: a #GParamSpec
*
* FIXME
*
* Since: 0.2
*/
void void
clutter_behaviour_class_bind_property (ClutterBehaviourClass *klass, clutter_behaviour_remove (ClutterBehaviour *behave, ClutterActor *actor)
GType actor_type,
const gchar *actor_property,
ClutterAlphaTransform func)
{ {
GParamSpec *overridden, *pspec; g_return_if_fail (actor != NULL);
GObjectClass *actor_class;
BridgeData *bridge_data;
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_CLASS (klass)); if (g_slist_find (behave->priv->actors, (gconstpointer)actor))
g_return_if_fail (actor_type != G_TYPE_INVALID);
g_return_if_fail (actor_property != NULL);
g_return_if_fail (func != NULL);
actor_class = g_type_class_ref (actor_type);
if (!actor_class)
{ {
g_warning (G_STRLOC ": unable to find class `%s'", g_object_unref (actor);
g_type_name (actor_type)); behave->priv->actors = g_slist_remove (behave->priv->actors, actor);
return;
} }
pspec = g_object_class_find_property (actor_class, actor_property);
if (!pspec)
{
g_warning (G_STRLOC ": objects of class `%s' do not have a "
"property called `%s'",
g_type_name (actor_type),
actor_property);
}
g_type_class_unref (actor_class);
overridden = g_param_spec_override (pspec->name, pspec);
bridge_data = g_slice_new (BridgeData);
bridge_data->actor_type = actor_type;
bridge_data->actor_property = g_strdup (actor_property);
bridge_data->transform_func = func;
g_param_spec_ref (overridden);
g_param_spec_set_qdata_full (overridden, quark_property_bridge,
bridge_data,
(GDestroyNotify) bridge_data_free);
g_param_spec_pool_insert (pspec_pool, overridden, G_OBJECT_CLASS_TYPE (klass));
} }
/** void
* clutter_behaviour_class_list_properties: clutter_behaviour_remove_all (ClutterBehaviour *behave)
* @klass: a #ClutterBehaviourClass
* @n_pspecs: return location for the number of properties found
*
* FIXME
*
* Return value: an allocated list of #GParamSpec objects. Use
* g_free() on the returned value when done.
*
* Since: 0.2
*/
GParamSpec **
clutter_behaviour_class_list_properties (ClutterBehaviourClass *klass,
guint *n_pspecs)
{ {
GParamSpec **pspecs; /* tofix */
guint n;
pspecs = g_param_spec_pool_list (pspec_pool,
G_OBJECT_CLASS_TYPE (klass),
&n);
if (n_pspecs)
*n_pspecs = n;
return pspecs;
} }
/** void
* clutter_behaviour_class_find_property: clutter_behaviour_actors_foreach (ClutterBehaviour *behave,
* @klass: a #ClutterBehaviourClass GFunc func,
* @property_name: the name of the property gpointer userdata)
*
* FIXME
*
* Return value: a #GParamSpec or %NULL
*
* Since: 0.2
*/
GParamSpec *
clutter_behaviour_class_find_property (ClutterBehaviourClass *klass,
const gchar *property_name)
{ {
GParamSpec *pspec; g_slist_foreach (behave->priv->actors, func, userdata);
GParamSpec *redirect; }
g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR_CLASS (klass), NULL); GObject*
g_return_val_if_fail (property_name != NULL, NULL); clutter_behaviour_get_object (ClutterBehaviour *behave)
{
return behave->priv->object;
}
pspec = g_param_spec_pool_lookup (pspec_pool, void
property_name, clutter_behaviour_set_object (ClutterBehaviour *behave,
G_OBJECT_CLASS_TYPE (klass), GObject *object)
TRUE); {
if (pspec) ClutterBehaviourPrivate *priv;
const char *property;
priv = CLUTTER_BEHAVIOUR_GET_PRIVATE(behave);
if (priv->object)
{ {
redirect = g_param_spec_get_redirect_target (pspec); property = clutter_behaviour_get_property (behave);
if (redirect) clutter_behaviour_set_property (behave, NULL);
return redirect;
else g_object_unref(priv->object);
return pspec; priv->object = NULL;
} }
else
property = NULL;
if (object)
{
priv->object = g_object_ref(object);
if (property)
clutter_behaviour_set_property (behave, property);
}
}
const char *
clutter_behaviour_get_property (ClutterBehaviour *behave)
{
if (behave->priv->param_spec)
return behave->priv->param_spec->name;
else else
return NULL; return NULL;
} }
GParamSpec *
clutter_behaviour_get_param_spec (ClutterBehaviour *behave)
{
return behave->priv->param_spec;
}
static void
notify_cb (GObject *object,
GParamSpec *param_spec,
ClutterBehaviour *behave)
{
g_signal_emit (behave,
signals[SIGNAL_PROPERTY_CHANGE],
0,
object,
param_spec);
}
void
clutter_behaviour_set_property (ClutterBehaviour *behave,
const char *property)
{
g_return_if_fail (behave->priv->object);
if (behave->priv->notify_id)
{
g_signal_handler_disconnect (behave->priv->object,
behave->priv->notify_id);
behave->priv->notify_id = 0;
}
behave->priv->param_spec = NULL;
if (property)
{
guint signal_id;
GClosure *closure;
behave->priv->param_spec =
g_object_class_find_property (G_OBJECT_GET_CLASS (behave->priv->object),
property);
g_return_if_fail (behave->priv->param_spec);
signal_id = g_signal_lookup ("notify",
G_OBJECT_TYPE (behave->priv->object));
closure = g_cclosure_new ((GCallback) notify_cb, behave, NULL);
behave->priv->notify_id =
g_signal_connect_closure_by_id (behave->priv->object,
signal_id,
g_quark_from_string (property),
closure,
FALSE);
}
}

View File

@ -1,59 +1,39 @@
/* #ifndef _HAVE_CLUTTER_BEHAVIOUR_H
* Clutter. #define _HAVE_CLUTTER_BEHAVIOUR_H
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
* Emmanuele Bassi <ebassi@openedhand.com>
*
* Copyright (C) 2006 OpenedHand
*
* This library 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 of the License, or (at your option) any later version.
*
* This library 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 this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __CLUTTER_BEHAVIOUR_H__
#define __CLUTTER_BEHAVIOUR_H__
#include <glib-object.h> #include <glib-object.h>
#include <clutter/clutter-actor.h>
#include <clutter/clutter-alpha.h>
G_BEGIN_DECLS G_BEGIN_DECLS
#define CLUTTER_TYPE_BEHAVIOUR (clutter_behaviour_get_type ()) #define CLUTTER_TYPE_BEHAVIOUR clutter_behaviour_get_type()
#define CLUTTER_BEHAVIOUR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BEHAVIOUR, ClutterBehaviour))
#define CLUTTER_BEHAVIOUR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BEHAVIOUR, ClutterBehaviourClass))
#define CLUTTER_IS_BEHAVIOUR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BEHAVIOUR))
#define CLUTTER_IS_BEHAVIOUR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BEHAVIOUR))
#define CLUTTER_BEHAVIOUR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BEHAVIOUR, ClutterBehaviourClass))
typedef struct _ClutterBehaviour ClutterBehaviour; #define CLUTTER_BEHAVIOUR(obj) \
typedef struct _ClutterBehaviourPrivate ClutterBehaviourPrivate; (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
typedef struct _ClutterBehaviourClass ClutterBehaviourClass; CLUTTER_TYPE_BEHAVIOUR, ClutterBehaviour))
typedef gboolean (*ClutterAlphaTransform) (ClutterBehaviour *behaviour, #define CLUTTER_BEHAVIOUR_CLASS(klass) \
GParamSpec *pspec, (G_TYPE_CHECK_CLASS_CAST ((klass), \
const GValue *src, CLUTTER_TYPE_BEHAVIOUR, ClutterBehaviourClass))
GValue *dest);
#define CLUTTER_IS_BEHAVIOUR(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
CLUTTER_TYPE_BEHAVIOUR))
#define CLUTTER_IS_BEHAVIOUR_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
CLUTTER_TYPE_BEHAVIOUR))
#define CLUTTER_BEHAVIOUR_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
CLUTTER_TYPE_BEHAVIOUR, ClutterBehaviourClass))
typedef struct _ClutterBehaviour ClutterBehaviour;
typedef struct ClutterBehaviourPrivate ClutterBehaviourPrivate;
typedef struct _ClutterBehaviourClass ClutterBehaviourClass;
struct _ClutterBehaviour struct _ClutterBehaviour
{ {
GObject parent_instance; GObject parent;
/*< private >*/
ClutterBehaviourPrivate *priv; ClutterBehaviourPrivate *priv;
}; };
@ -61,64 +41,48 @@ struct _ClutterBehaviourClass
{ {
GObjectClass parent_class; GObjectClass parent_class;
/* override this to change the way behaviour properties void (* property_change) (ClutterBehaviour *behave,
* are dispatched GObject *object,
*/ GParamSpec *param_spec);
void (*dispatch_property_changed) (ClutterBehaviour *behaviour,
guint n_pspecs,
GParamSpec **pspecs);
/* signals */
void (*notify_behaviour) (ClutterBehaviour *behaviour,
GParamSpec *pspec);
/* padding, for future expansion */
void (*_clutter_behaviour_1) (void);
void (*_clutter_behaviour_2) (void);
void (*_clutter_behaviour_3) (void);
void (*_clutter_behaviour_4) (void);
}; };
GType clutter_behaviour_get_type (void) G_GNUC_CONST; GType clutter_behaviour_get_type (void);
void clutter_behaviour_apply (ClutterBehaviour *behaviour, ClutterBehaviour*
ClutterActor *actor); clutter_behaviour_new (GObject *object,
void clutter_behaviour_remove (ClutterBehaviour *behaviour, const char *property);
ClutterActor *actor);
void clutter_behaviour_actors_foreach (ClutterBehaviour *behaviour,
GFunc func,
gpointer userdata);
GSList * clutter_behaviour_get_actors (ClutterBehaviour *behaviour);
void clutter_behaviour_set_alpha (ClutterBehaviour *behaviour,
ClutterAlpha *alpha);
ClutterAlpha *clutter_behaviour_get_alpha (ClutterBehaviour *behaviour);
void
clutter_behaviour_apply (ClutterBehaviour *behave, ClutterActor *actor);
void
clutter_behaviour_remove (ClutterBehaviour *behave, ClutterActor *actor);
#define CLUTTER_BEHAVIOUR_WARN_INVALID_TRANSFORM(behaviour,pspec,value) \ void
G_STMT_START { \ clutter_behaviour_remove_all (ClutterBehaviour *behave);
ClutterBehaviour *_behaviour = (ClutterBehaviour *) behaviour; \
GParamSpec *_pspec = (GParamSpec *) pspec; \
GValue *_value = (GValue *) value; \
g_warning ("%s: behaviours of type `%s' are unable to transform values " \
"of type `%s' into values of type `%s' for property `%s'", \
G_STRLOC, \
g_type_name (G_OBJECT_TYPE (_behaviour)), \
g_type_name (G_VALUE_TYPE (_value)), \
g_type_name (G_PARAM_SPEC_TYPE (_pspec)), \
_pspec->name); \
} G_STMT_END
GParamSpec **clutter_behaviour_class_list_properties (ClutterBehaviourClass *klass, void
guint *n_pspecs); clutter_behaviour_actors_foreach (ClutterBehaviour *behave,
GParamSpec * clutter_behaviour_class_find_property (ClutterBehaviourClass *klass, GFunc func,
const gchar *property_name); gpointer userdata);
void clutter_behaviour_class_bind_property (ClutterBehaviourClass *klass,
GType actor_type,
const gchar *actor_property,
ClutterAlphaTransform func);
void
clutter_behaviour_set_object (ClutterBehaviour *behave,
GObject *object);
GObject*
clutter_behaviour_get_object (ClutterBehaviour *behave);
void
clutter_behaviour_set_property (ClutterBehaviour *behave,
const char *property);
const char*
clutter_behaviour_get_property (ClutterBehaviour *behave);
GParamSpec*
clutter_behaviour_get_param_spec (ClutterBehaviour *behave);
G_END_DECLS G_END_DECLS
#endif /* __CLUTTER_BEHAVIOUR_H__ */ #endif

View File

@ -8,8 +8,7 @@
#include "clutter-event.h" #include "clutter-event.h"
#include "clutter-timeline.h" #include "clutter-timeline.h"
#include "clutter-behaviour.h" #include "clutter-behaviour.h"
#include "clutter-opacity-behaviour.h" #include "clutter-behaviours.h"
#include "clutter-blink-behaviour.h"
#include "clutter-stage.h" #include "clutter-stage.h"
#include "clutter-actor.h" #include "clutter-actor.h"
#include "clutter-rectangle.h" #include "clutter-rectangle.h"

View File

@ -14,9 +14,6 @@ main (int argc, char *argv[])
clutter_init (&argc, &argv); clutter_init (&argc, &argv);
stage = clutter_stage_get_default (); stage = clutter_stage_get_default ();
g_signal_connect (stage, "button-press-event",
G_CALLBACK (clutter_main_quit),
NULL);
pixbuf = gdk_pixbuf_new_from_file ("redhand.png", NULL); pixbuf = gdk_pixbuf_new_from_file ("redhand.png", NULL);
@ -33,14 +30,13 @@ main (int argc, char *argv[])
/* Make a timeline */ /* Make a timeline */
timeline = clutter_timeline_new (100, 30); /* num frames, fps */ timeline = clutter_timeline_new (100, 30); /* num frames, fps */
g_object_set (timeline, "loop", TRUE, 0); g_object_set(timeline, "loop", TRUE, 0);
/* Set an alpha func to power behaviour - ramp is constant rise/fall */ /* Set an alpha func to power behaviour - ramp is constant rise/fall */
alpha = clutter_alpha_new (timeline, CLUTTER_ALPHA_RAMP, NULL); alpha = clutter_alpha_new (timeline, CLUTTER_ALPHA_RAMP);
/* Create a behaviour for that time line */ /* Create a behaviour for that time line */
behave = clutter_opacity_behaviour_new (0X33, 0xff, 0x00); behave = clutter_behaviour_opacity_new_from_alpha (alpha, 0X33, 0xff);
clutter_behaviour_set_alpha (CLUTTER_BEHAVIOUR (behave), alpha);
/* Apply it to our actor */ /* Apply it to our actor */
clutter_behaviour_apply (behave, hand); clutter_behaviour_apply (behave, hand);
@ -52,7 +48,5 @@ main (int argc, char *argv[])
clutter_main(); clutter_main();
g_object_unref (behave);
return 0; return 0;
} }