From 5ab0ed5a0038fa8eeada40eab5be4174ae82fa18 Mon Sep 17 00:00:00 2001 From: Matthew Allum Date: Thu, 27 Sep 2007 21:38:38 +0000 Subject: [PATCH] 2007-09-27 Matthew Allum * clutter/clutter-event.c: * clutter/clutter-event.h: * clutter/clutter-main.c: Further event tweaks; - Ref the event actor source - Protect against off stage events (button releases) - Move more into ClutterEventAny - Add a click count to button event (as yet unused) - Minor cleanups * clutter/clutter-actor.c: Make scale x/y a property. * clutter/clutter-private.h: Remove _clutter_actor_apply_modelview* * clutter/eglx/clutter-backend-egl.c: Warning cleanup * clutter/eglx/clutter-stage-egl.c: * clutter/glx/clutter-stage-glx.c: * clutter/sdl/clutter-stage-sdl.c: Avoid setting viewport directly, but set sync flag. * clutter/pango/pangoclutter-render.c: (draw_glyph): Minor cleanups. * clutter/Makefile.am: * tests/Makefile.am: * tests/test-score.c * clutter/clutter.h: * clutter/clutter-score.h: * clutter/clutter-score.c: Add very initial (broken) ClutterScore implementation. --- ChangeLog | 37 ++ clutter/Makefile.am | 2 + clutter/clutter-actor.c | 81 ++++- clutter/clutter-event.c | 6 +- clutter/clutter-event.h | 13 + clutter/clutter-group.c | 4 +- clutter/clutter-main.c | 36 +- clutter/clutter-private.h | 4 - clutter/clutter-score.c | 501 ++++++++++++++++++++++++++++ clutter/clutter-score.h | 126 +++++++ clutter/clutter.h | 1 + clutter/eglx/clutter-backend-egl.c | 2 +- clutter/eglx/clutter-stage-egl.c | 9 +- clutter/glx/clutter-stage-glx.c | 10 +- clutter/pango/pangoclutter-render.c | 17 +- clutter/sdl/clutter-stage-sdl.c | 8 +- tests/Makefile.am | 3 +- tests/test-score.c | 36 ++ 18 files changed, 833 insertions(+), 63 deletions(-) create mode 100644 clutter/clutter-score.c create mode 100644 clutter/clutter-score.h create mode 100644 tests/test-score.c diff --git a/ChangeLog b/ChangeLog index 37ab64e60..196b99745 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,40 @@ +2007-09-27 Matthew Allum + + * clutter/clutter-event.c: + * clutter/clutter-event.h: + * clutter/clutter-main.c: + Further event tweaks; + - Ref the event actor source + - Protect against off stage events (button releases) + - Move more into ClutterEventAny + - Add a click count to button event (as yet unused) + - Minor cleanups + + * clutter/clutter-actor.c: + Make scale x/y a property. + + * clutter/clutter-private.h: + Remove _clutter_actor_apply_modelview* + + * clutter/eglx/clutter-backend-egl.c: + Warning cleanup + + * clutter/eglx/clutter-stage-egl.c: + * clutter/glx/clutter-stage-glx.c: + * clutter/sdl/clutter-stage-sdl.c: + Avoid setting viewport directly, but set sync flag. + + * clutter/pango/pangoclutter-render.c: (draw_glyph): + Minor cleanups. + + * clutter/Makefile.am: + * tests/Makefile.am: + * tests/test-score.c + * clutter/clutter.h: + * clutter/clutter-score.h: + * clutter/clutter-score.c: + Add very initial (broken) ClutterScore implementation. + 2007-09-25 Ross Burton Merge from stable. diff --git a/clutter/Makefile.am b/clutter/Makefile.am index 3f8681043..63a80b833 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -68,6 +68,7 @@ source_h = \ $(srcdir)/clutter-stage.h \ $(srcdir)/clutter-texture.h \ $(srcdir)/clutter-timeline.h \ + $(srcdir)/clutter-score.h \ $(srcdir)/clutter-timeout-pool.h \ $(srcdir)/clutter-types.h \ $(srcdir)/clutter-units.h \ @@ -151,6 +152,7 @@ source_c = \ clutter-rectangle.c \ clutter-texture.c \ clutter-timeline.c \ + clutter-score.c \ clutter-timeout-pool.c \ clutter-util.c \ clutter-vbox.c \ diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index 5bddecc11..cf84eea9b 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -82,7 +82,9 @@ enum PROP_HAS_CLIP, PROP_OPACITY, PROP_NAME, - PROP_VISIBLE + PROP_VISIBLE, + PROP_SCALE_X, + PROP_SCALE_Y }; enum @@ -106,6 +108,12 @@ enum static guint actor_signals[LAST_SIGNAL] = { 0, }; +static +void _clutter_actor_apply_modelview_transform (ClutterActor * self); + +static +void _clutter_actor_apply_modelview_transform_recursive (ClutterActor * self); + static gboolean redraw_update_idle (gpointer data) { @@ -397,7 +405,8 @@ clutter_actor_transform_point (ClutterActor *actor, * @vertex: The translated #ClutterVertex * * Transforms point in coordinates relative to the actor - * into screen coordiances + * into screen coordiances with the current actor tranform + * (i.e. scale, rotation etc) * * Since: 0.4 **/ @@ -582,7 +591,7 @@ clutter_actor_get_vertices (ClutterActor *self, * This function does not push/pop matrix; it is the responsibility * of the caller to do so as appropriate */ -void +static void _clutter_actor_apply_modelview_transform (ClutterActor * self) { ClutterActorPrivate *priv = self->priv; @@ -640,7 +649,7 @@ _clutter_actor_apply_modelview_transform (ClutterActor * self) * This function does not push/pop matrix; it is the responsibility * of the caller to do so as appropriate */ -void +static void _clutter_actor_apply_modelview_transform_recursive (ClutterActor * self) { ClutterActor * parent; @@ -878,6 +887,18 @@ clutter_actor_set_property (GObject *object, else clutter_actor_hide (actor); break; + case PROP_SCALE_X: + clutter_actor_set_scalex + (actor, + CLUTTER_FLOAT_TO_FIXED (g_value_get_double (value)), + priv->scale_y); + break; + case PROP_SCALE_Y: + clutter_actor_set_scalex + (actor, + priv->scale_x, + CLUTTER_FLOAT_TO_FIXED (g_value_get_double (value))); + break; case PROP_CLIP: { ClutterGeometry *geom = g_value_get_boxed (value); @@ -935,6 +956,12 @@ clutter_actor_get_property (GObject *object, case PROP_CLIP: g_value_set_boxed (value, &(priv->clip)); break; + case PROP_SCALE_X: + g_value_set_double (value, CLUTTER_FIXED_TO_DOUBLE (priv->scale_x)); + break; + case PROP_SCALE_Y: + g_value_set_double (value, CLUTTER_FIXED_TO_DOUBLE (priv->scale_y)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1099,6 +1126,43 @@ clutter_actor_class_init (ClutterActorClass *klass) "Name of the actor", NULL, CLUTTER_PARAM_READWRITE)); + + /** + * ClutterActor::scale-x: + * + * The horizontal scale of the actor + * + * Since: 0.6 + */ + g_object_class_install_property + (object_class, + PROP_SCALE_X, + g_param_spec_double ("scale-x", + "Scale-X", + "Scale X", + 0.0, + G_MAXDOUBLE, + 1.0, + CLUTTER_PARAM_READWRITE)); + + /** + * ClutterActor::scale-y: + * + * The vertical scale of the actor + * + * Since: 0.6 + */ + g_object_class_install_property + (object_class, + PROP_SCALE_Y, + g_param_spec_double ("scale-y", + "Scale-Y", + "Scale Y", + 0.0, + G_MAXDOUBLE, + 1.0, + CLUTTER_PARAM_READWRITE)); + /** * ClutterActor::destroy: @@ -1887,6 +1951,15 @@ clutter_actor_set_scalex (ClutterActor *self, self->priv->scale_x = scale_x; self->priv->scale_y = scale_y; + g_object_ref (self); + g_object_freeze_notify (G_OBJECT (self)); + + g_object_notify (G_OBJECT (self), "scale-x"); + g_object_notify (G_OBJECT (self), "scale-y"); + + g_object_thaw_notify (G_OBJECT (self)); + g_object_unref (self); + if (CLUTTER_ACTOR_IS_VISIBLE (self)) clutter_actor_queue_redraw (self); } diff --git a/clutter/clutter-event.c b/clutter/clutter-event.c index d93c95e6a..1f9e426ee 100644 --- a/clutter/clutter-event.c +++ b/clutter/clutter-event.c @@ -404,6 +404,11 @@ clutter_event_free (ClutterEvent *event) { if (G_LIKELY (event)) { + ClutterActor *source = NULL; + + source = clutter_event_get_source (event); + if (source) + g_object_unref (source); g_slice_free (ClutterEvent, event); } } @@ -422,7 +427,6 @@ ClutterEvent * clutter_event_get (void) { ClutterMainContext *context = clutter_context_get_default (); - GList *item; if (!context->events_queue) return NULL; diff --git a/clutter/clutter-event.h b/clutter/clutter-event.h index fcedc3175..38ee54297 100644 --- a/clutter/clutter-event.h +++ b/clutter/clutter-event.h @@ -51,6 +51,10 @@ typedef enum { CLUTTER_BUTTON5_MASK = 1 << 12 } ClutterModifierType; +typedef enum { + CLUTTER_EVENT_FLAG_COOKED = 1 << 0, +} ClutterEventFlags; + typedef enum { CLUTTER_NOTHING = 0, @@ -100,12 +104,15 @@ typedef struct _ClutterInputDevice ClutterInputDevice; struct _ClutterAnyEvent { ClutterEventType type; + guint32 time; + ClutterEventFlags flags; }; struct _ClutterKeyEvent { ClutterEventType type; guint32 time; + ClutterEventFlags flags; ClutterModifierType modifier_state; guint keyval; guint16 hardware_keycode; @@ -116,10 +123,12 @@ struct _ClutterButtonEvent { ClutterEventType type; guint32 time; + ClutterEventFlags flags; gint x; gint y; ClutterModifierType modifier_state; guint32 button; + guint click_count; gdouble *axes; /* Future use */ ClutterInputDevice *device; /* Future use */ ClutterActor *source; @@ -129,6 +138,7 @@ struct _ClutterMotionEvent { ClutterEventType type; guint32 time; + ClutterEventFlags flags; gint x; gint y; ClutterModifierType modifier_state; @@ -141,6 +151,7 @@ struct _ClutterScrollEvent { ClutterEventType type; guint32 time; + ClutterEventFlags flags; gint x; gint y; ClutterScrollDirection direction; @@ -153,6 +164,8 @@ struct _ClutterScrollEvent struct _ClutterStageStateEvent { ClutterEventType type; + guint32 time; + ClutterEventFlags flags; ClutterStageState changed_mask; ClutterStageState new_state; }; diff --git a/clutter/clutter-group.c b/clutter/clutter-group.c index 6d56459e8..5071116f7 100644 --- a/clutter/clutter-group.c +++ b/clutter/clutter-group.c @@ -406,8 +406,8 @@ sort_z_order (gconstpointer a, { int depth_a, depth_b; - depth_a = clutter_actor_get_depth (a); - depth_b = clutter_actor_get_depth (b); + depth_a = clutter_actor_get_depth (CLUTTER_ACTOR(a)); + depth_b = clutter_actor_get_depth (CLUTTER_ACTOR(b)); if (depth_a == depth_b) return 0; diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index b5986b7d0..b3940d198 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -148,7 +148,7 @@ clutter_redraw (void) CLUTTER_UNSET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES); } - /* Call through ti the actual backend to do the painting down from + /* Call through to the actual backend to do the painting down from * the stage. It will likely need to swap buffers, vblank sync etc * which will be windowing system dependant. */ @@ -200,6 +200,10 @@ clutter_get_motion_events_enabled (void) void clutter_do_event (ClutterEvent *event) { + /* FIXME: This should probably be clutter_cook_event() - it would + * take a raw event from the backend and 'cook' it so its more tasty. + * + */ ClutterMainContext *context; ClutterBackend *backend; ClutterActor *stage; @@ -207,16 +211,13 @@ clutter_do_event (ClutterEvent *event) context = clutter_context_get_default (); backend = context->backend; - stage = _clutter_backend_get_stage (backend); + stage = _clutter_backend_get_stage (backend); + if (!stage) return; CLUTTER_TIMESTAMP (EVENT, "Event received"); - /* TODO: - * - */ - switch (event->type) { case CLUTTER_NOTHING: @@ -224,7 +225,6 @@ clutter_do_event (ClutterEvent *event) case CLUTTER_DESTROY_NOTIFY: case CLUTTER_DELETE: - /* FIXME: handle delete working in stage */ if (clutter_stage_event (CLUTTER_STAGE (stage), event)) clutter_main_quit (); break; @@ -237,8 +237,7 @@ clutter_do_event (ClutterEvent *event) g_return_if_fail (actor != NULL); - /* FIXME: should we ref ? */ - event->key.source = actor; + event->key.source = g_object_ref(actor); /* bubble up */ do @@ -253,7 +252,7 @@ clutter_do_event (ClutterEvent *event) if (context->motion_events_per_actor == FALSE) { /* Only stage gets motion events */ - event->motion.source = stage; + event->motion.source = g_object_ref(stage); clutter_actor_event (stage, event); break; } @@ -268,6 +267,15 @@ clutter_do_event (ClutterEvent *event) clutter_event_get_coords (event, &x, &y); + /* Safety on - probably a release off stage ? + * FIXME: should likely deliver the release somehow - grabs ? + */ + if (x > CLUTTER_STAGE_WIDTH() + || y > CLUTTER_STAGE_HEIGHT() + || x < 0 + || y < 0) + break; + /* Map the event to a reactive actor */ actor = _clutter_do_pick (CLUTTER_STAGE (stage), x, y, @@ -277,9 +285,9 @@ clutter_do_event (ClutterEvent *event) x, y, actor); if (event->type == CLUTTER_SCROLL) - event->scroll.source = actor; + event->scroll.source = g_object_ref(actor); else - event->button.source = actor; + event->button.source = g_object_ref(actor); /* Motion enter leave events */ if (event->type == CLUTTER_MOTION) @@ -293,13 +301,15 @@ clutter_do_event (ClutterEvent *event) } motion_last_actor = actor; } - + /* Send the event to the actor and all parents always the * stage. * * FIXME: for an optimisation should check if there are * actually any reactive actors and avoid the pick all togeather * (signalling just the stage). Should be big help for gles. + * + * FIXME: Actors be able to stop emission. */ while (actor) { diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h index ac42da470..4d25a68a7 100644 --- a/clutter/clutter-private.h +++ b/clutter/clutter-private.h @@ -137,10 +137,6 @@ ClutterActor* _clutter_do_pick (ClutterStage *stage, /* Does this need to be private ? */ void clutter_do_event (ClutterEvent *event); -void _clutter_actor_apply_modelview_transform (ClutterActor * self); - -void _clutter_actor_apply_modelview_transform_recursive (ClutterActor * self); - G_END_DECLS #endif /* _HAVE_CLUTTER_PRIVATE_H */ diff --git a/clutter/clutter-score.c b/clutter/clutter-score.c new file mode 100644 index 000000000..9e13e864a --- /dev/null +++ b/clutter/clutter-score.c @@ -0,0 +1,501 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * Copyright (C) 2007 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. + */ + +/* + * IDEAS: + * API; + * - add() + * + an new timeline to beginning of score + * - append (timeline_existing, timeline_new, delay) + * + appends a new timeline to an existing one + * + * ScoreEntry + * { + * Timeline *base; + * GList *next_timelines; - to start on completion of base, + * (points to score entrys) + * Callback id; + * delay + * } + * + * start()/stop(),remove(),remove_all() ? + */ + +/** + * SECTION:clutter-score @short_description: A class for sequencing + * multiple #ClutterTimelines in order + * + * #ClutterScore is a base class for sequencing multiple timelines in order. + */ + +#ifndef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "clutter-score.h" +#include "clutter-main.h" +#include "clutter-marshal.h" +#include "clutter-private.h" +#include "clutter-debug.h" + +G_DEFINE_TYPE (ClutterScore, clutter_score, G_TYPE_OBJECT); + +typedef struct ClutterScoreEntry +{ + ClutterTimeline *timeline; + gulong handler_id; + GSList *child_entries; + ClutterScore *score; +} +ClutterScoreEntry; + +struct _ClutterScorePrivate +{ + GSList *entries; + GHashTable *running_timelines; + guint loop : 1; +}; + +enum +{ + PROP_0, + PROP_LOOP +}; + +enum +{ + NEW_TIMELINE, + STARTED, + PAUSED, + COMPLETED, + + LAST_SIGNAL +}; + +static int score_signals[LAST_SIGNAL] = { 0 }; + +static void start_entry (ClutterScoreEntry *entry); + +/* Object */ + +static void +clutter_score_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterScore *score; + ClutterScorePrivate *priv; + + score = CLUTTER_SCORE(object); + priv = score->priv; + + switch (prop_id) + { + case PROP_LOOP: + priv->loop = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_score_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterScore *score; + ClutterScorePrivate *priv; + + score = CLUTTER_SCORE(object); + priv = score->priv; + + switch (prop_id) + { + case PROP_LOOP: + g_value_set_boolean (value, priv->loop); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +clutter_score_finalize (GObject *object) +{ + G_OBJECT_CLASS (clutter_score_parent_class)->finalize (object); +} + +static void +clutter_score_dispose (GObject *object) +{ + ClutterScore *self = CLUTTER_SCORE(object); + ClutterScorePrivate *priv; + + priv = self->priv; + + if (priv != NULL) + { + + } + + G_OBJECT_CLASS (clutter_score_parent_class)->dispose (object); +} + + +static void +clutter_score_class_init (ClutterScoreClass *klass) +{ + GObjectClass *object_class; + + object_class = (GObjectClass*) klass; + + object_class->set_property = clutter_score_set_property; + object_class->get_property = clutter_score_get_property; + object_class->finalize = clutter_score_finalize; + object_class->dispose = clutter_score_dispose; + + g_type_class_add_private (klass, sizeof (ClutterScorePrivate)); + + +#if 0 + /** + * ClutterScore::new-frame: + * @score: the score which received the signal + * @timeline: the number of the new frame + * + * The ::new-timeline signal is emitted each time a new timeline in the + * score is reached. + */ + score_signals[NEW_TIMELINE] = + g_signal_new ("new-timeline", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterScoreClass, new_frame), + NULL, NULL, + clutter_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, CLUTTER_TYPE_TIMELINE); + score_signals[COMPLETED] = + g_signal_new ("completed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterScoreClass, completed), + NULL, NULL, + clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + score_signals[STARTED] = + g_signal_new ("started", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterScoreClass, started), + NULL, NULL, + clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); + score_signals[PAUSED] = + g_signal_new ("paused", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterScoreClass, paused), + NULL, NULL, + clutter_marshal_VOID__VOID, + G_TYPE_NONE, 0); +#endif +} + +static void +clutter_score_init (ClutterScore *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE(self, + CLUTTER_TYPE_SCORE, + ClutterScorePrivate); + + self->priv->running_timelines = g_hash_table_new(NULL, NULL); +} + +/** + * clutter_score_set_loop: + * @score: a #ClutterScore + * @loop: %TRUE for enable looping + * + * Sets whether @score should loop. + */ +void +clutter_score_set_loop (ClutterScore *score, + gboolean loop) +{ + g_return_if_fail (CLUTTER_IS_SCORE (score)); + + if (score->priv->loop != loop) + { + g_object_ref (score); + + score->priv->loop = loop; + + g_object_notify (G_OBJECT (score), "loop"); + g_object_unref (score); + } +} + +/** + * clutter_score_get_loop: + * @score: a #ClutterScore + * + * Gets whether @score is looping + * + * Return value: %TRUE if the score is looping + */ +gboolean +clutter_score_get_loop (ClutterScore *score) +{ + g_return_val_if_fail (CLUTTER_IS_SCORE (score), FALSE); + + return score->priv->loop; +} + +/** + * clutter_score_rewind: + * @score: A #ClutterScore + * + * Rewinds #ClutterScore to frame 0. + **/ +void +clutter_score_rewind (ClutterScore *score) +{ + g_return_if_fail (CLUTTER_IS_SCORE (score)); + +} + +/** + * clutter_score_is_playing: + * @score: A #ClutterScore + * + * Query state of a #ClutterScore instance. + * + * Return Value: TRUE if score is currently playing, FALSE if not. + */ +gboolean +clutter_score_is_playing (ClutterScore *score) +{ + g_return_val_if_fail (CLUTTER_IS_SCORE (score), FALSE); + + return !!g_hash_table_size(score->priv->running_timelines); +} + +static void +on_timeline_finish (ClutterTimeline *timeline, + ClutterScoreEntry *entry) +{ + GSList *item; + + g_hash_table_remove (entry->score->priv->running_timelines, + GINT_TO_POINTER(entry->handler_id)); + g_signal_handler_disconnect (timeline, entry->handler_id); + + printf("completed %li\n", entry->handler_id); + + for (item = entry->child_entries; item != NULL; item = item->next) + { + ClutterScoreEntry *child_entry = item->data; + start_entry (child_entry); + } + + if (clutter_score_is_playing (entry->score) == FALSE) + { + /* Score has finished - fire 'completed' signal */ + /* Also check if looped etc */ + printf("looks like we finished\n"); + } +} + +static void +start_entry (ClutterScoreEntry *entry) +{ + entry->handler_id = g_signal_connect (entry->timeline, + "completed", + G_CALLBACK (on_timeline_finish), + entry); + + printf("started %li\n", entry->handler_id); + + g_hash_table_insert (entry->score->priv->running_timelines, + GINT_TO_POINTER(entry->handler_id), + entry); + + clutter_timeline_start (entry->timeline); +} + +/** + * clutter_score_start: + * @score: A #ClutterScore + * + * Query state of a #ClutterScore instance. + * + * Return Value: TRUE if score is currently playing, FALSE if not. + */ +void +clutter_score_start (ClutterScore *score) +{ + GSList *item; + ClutterScorePrivate *priv; + + g_return_if_fail (CLUTTER_IS_SCORE (score)); + + priv = score->priv; + + for (item = priv->entries; item != NULL; item = item->next) + { + ClutterScoreEntry *entry = item->data; + + start_entry (entry); + } +} + +/** + * clutter_score_start: + * @score: A #ClutterScore + * + * Query state of a #ClutterScore instance. + * + * Return Value: TRUE if score is currently playing, FALSE if not. + */ +void +clutter_score_stop (ClutterScore *score) +{ + g_return_if_fail (CLUTTER_IS_SCORE (score)); + + /* foreach hash / pause */ +} + +static ClutterScoreEntry* +find_entry (GSList *list, ClutterTimeline *timeline) +{ + GSList *item; + ClutterScoreEntry *res = NULL; + + if (list == NULL) + return NULL; + + for (item = list; item != NULL && res == NULL; item = item->next) + { + ClutterScoreEntry *entry = item->data; + + g_assert (entry != NULL); + + if (entry->timeline == timeline) + return entry; + + if (entry->child_entries) + res = find_entry (entry->child_entries, timeline); + } + + return res; +} + +/** + * clutter_score_append: + * @score: A #ClutterScore + * @timeline_existing: A #ClutterTimeline in the score + * @timeline_new: A new #ClutterTimeline to start when #timeline_existing has + * completed, + * + * Appends a new timeline to an one existing in the score. + * + */ +void +clutter_score_append (ClutterScore *score, + ClutterTimeline *timeline_existing, + ClutterTimeline *timeline_new) +{ + ClutterScorePrivate *priv; + ClutterScoreEntry *entry, *entry_new; + + priv = score->priv; + + /* Appends a timeline to the end of another */ + if ((entry = find_entry (priv->entries, timeline_existing)) != NULL) + { + entry_new = g_new0(ClutterScoreEntry, 1); + entry->timeline = g_object_ref (timeline_new); + entry->score = score; + entry->child_entries = g_slist_append (entry->child_entries, entry); + } +} + +/** + * clutter_score_add: + * @score: A #ClutterScore + * @timeline: A #ClutterTimeline + * + * Adds a new initial timeline to start when the score is started. + * + */ +void +clutter_score_add (ClutterScore *score, + ClutterTimeline *timeline) +{ + ClutterScorePrivate *priv; + ClutterScoreEntry *entry; + + priv = score->priv; + + /* Added timelines are always started first */ + entry = g_new0(ClutterScoreEntry, 1); + entry->timeline = g_object_ref (timeline); + entry->score = score; + score->priv->entries = g_slist_append (score->priv->entries, entry); +} + +void +clutter_score_remove (ClutterScore *score, + ClutterTimeline *timeline_parent, + ClutterTimeline *timeline) +{ + +} + +void +clutter_score_remove_all (ClutterScore *score) +{ + +} + + +/** + * clutter_score_new: + * + * Create a new #ClutterScore instance. + * + * Return Value: a new #ClutterScore + */ +ClutterScore* +clutter_score_new () +{ + return g_object_new (CLUTTER_TYPE_SCORE, NULL); +} diff --git a/clutter/clutter-score.h b/clutter/clutter-score.h new file mode 100644 index 000000000..3eb81c3fd --- /dev/null +++ b/clutter/clutter-score.h @@ -0,0 +1,126 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Authored By Matthew Allum + * + * 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 _HAVE_CLUTTER_SCORE_H +#define _HAVE_CLUTTER_SCORE_H + +/* clutter-score.h */ + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_SCORE clutter_score_get_type() + +#define CLUTTER_SCORE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + CLUTTER_TYPE_SCORE, ClutterScore)) + +#define CLUTTER_SCORE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + CLUTTER_TYPE_SCORE, ClutterScoreClass)) + +#define CLUTTER_IS_SCORE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + CLUTTER_TYPE_SCORE)) + +#define CLUTTER_IS_SCORE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + CLUTTER_TYPE_SCORE)) + +#define CLUTTER_SCORE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + CLUTTER_TYPE_SCORE, ClutterScoreClass)) + +typedef struct _ClutterScore ClutterScore; +typedef struct _ClutterScoreClass ClutterScoreClass; +typedef struct _ClutterScorePrivate ClutterScorePrivate; + +struct _ClutterScore +{ + /*< private >*/ + GObject parent; + ClutterScorePrivate *priv; +}; + +struct _ClutterScoreClass +{ + GObjectClass parent_class; + + void (*started) (ClutterScore *score); + void (*completed) (ClutterScore *score); + void (*paused) (ClutterScore *score); + + void (*_clutter_score_1) (void); + void (*_clutter_score_2) (void); + void (*_clutter_score_3) (void); + void (*_clutter_score_4) (void); + void (*_clutter_score_5) (void); +}; + +GType clutter_score_get_type (void) G_GNUC_CONST; + +ClutterScore *clutter_score_new (void); + +void +clutter_score_set_loop (ClutterScore *score, + gboolean loop); + +gboolean +clutter_score_get_loop (ClutterScore *score); + +void +clutter_score_rewind (ClutterScore *score); + +gboolean +clutter_score_is_playing (ClutterScore *score); +void +clutter_score_start (ClutterScore *score); + +void +clutter_score_stop (ClutterScore *score); + +void +clutter_score_append (ClutterScore *score, + ClutterTimeline *timeline_existing, + ClutterTimeline *timeline_new); + +void +clutter_score_add (ClutterScore *score, + ClutterTimeline *timeline); + +void +clutter_score_remove (ClutterScore *score, + ClutterTimeline *timeline_parent, + ClutterTimeline *timeline); + +void +clutter_score_remove_all (ClutterScore *score); + + +G_END_DECLS + +#endif diff --git a/clutter/clutter.h b/clutter/clutter.h index 1dbe2e7d1..8252be61f 100644 --- a/clutter/clutter.h +++ b/clutter/clutter.h @@ -57,6 +57,7 @@ #include "clutter-texture.h" #include "clutter-timeout-pool.h" #include "clutter-timeline.h" +#include "clutter-score.h" #include "clutter-types.h" #include "clutter-units.h" #include "clutter-util.h" diff --git a/clutter/eglx/clutter-backend-egl.c b/clutter/eglx/clutter-backend-egl.c index f58bcfe99..29158d513 100644 --- a/clutter/eglx/clutter-backend-egl.c +++ b/clutter/eglx/clutter-backend-egl.c @@ -76,7 +76,7 @@ clutter_backend_egl_post_parse (ClutterBackend *backend, backend_egl->display_name = g_strdup (clutter_display_name); - backend_egl->edpy = eglGetDisplay(backend_egl->xdpy); + backend_egl->edpy = eglGetDisplay((NativeDisplayType)backend_egl->xdpy); dpi = (((double) DisplayHeight (backend_egl->xdpy, backend_egl->xscreen_num) * 25.4) / (double) DisplayHeightMM (backend_egl->xdpy, backend_egl->xscreen_num)); diff --git a/clutter/eglx/clutter-stage-egl.c b/clutter/eglx/clutter-stage-egl.c index 3216a84cc..c0ac8018d 100644 --- a/clutter/eglx/clutter-stage-egl.c +++ b/clutter/eglx/clutter-stage-egl.c @@ -89,7 +89,6 @@ clutter_stage_egl_realize (ClutterActor *actor) EGLConfig configs[2]; EGLint config_count; EGLBoolean status; - ClutterPerspective perspective; gboolean is_offscreen; @@ -183,13 +182,7 @@ clutter_stage_egl_realize (ClutterActor *actor) /* FIXME */ } - clutter_stage_get_perspectivex (CLUTTER_STAGE (actor), &perspective); - cogl_setup_viewport (clutter_actor_get_width (actor), - clutter_actor_get_height (actor), - perspective.fovy, - perspective.aspect, - perspective.z_near, - perspective.z_far); + CLUTTER_SET_PRIVATE_FLAGS(actor, CLUTTER_ACTOR_SYNC_MATRICES); } static void diff --git a/clutter/glx/clutter-stage-glx.c b/clutter/glx/clutter-stage-glx.c index 8cc8d2b34..cdc2aebbc 100644 --- a/clutter/glx/clutter-stage-glx.c +++ b/clutter/glx/clutter-stage-glx.c @@ -392,14 +392,8 @@ clutter_stage_glx_realize (ClutterActor *actor) } - clutter_stage_get_perspectivex (CLUTTER_STAGE (actor), &perspective); - cogl_setup_viewport (clutter_actor_get_width (actor), - clutter_actor_get_height (actor), - perspective.fovy, - perspective.aspect, - perspective.z_near, - perspective.z_far); - + /* Make sure the viewport gets set up correctly */ + CLUTTER_SET_PRIVATE_FLAGS(actor, CLUTTER_ACTOR_SYNC_MATRICES); return; fail: diff --git a/clutter/pango/pangoclutter-render.c b/clutter/pango/pangoclutter-render.c index 56afcdec3..5528ab0e7 100644 --- a/clutter/pango/pangoclutter-render.c +++ b/clutter/pango/pangoclutter-render.c @@ -58,7 +58,7 @@ typedef struct tc_slice { int avail, y; } tc_slice; -static int tc_generation; +static int tc_generation = 0; static tc_slice slices[TC_HEIGHT / TC_ROUND]; static tc_texture *first_texture; @@ -339,11 +339,6 @@ draw_glyph (PangoRenderer *renderer_, _pango_clutter_font_set_cache_glyph_data (font, glyph, g); } - /* - if (renderer->curtex) - glEnd (); - */ - tc_get (&g->tex, bm.width, bm.height); g->left = bm.left; @@ -365,8 +360,9 @@ draw_glyph (PangoRenderer *renderer_, CGL_UNSIGNED_BYTE, bm.bitmap); + glTexParameteri (CGL_TEXTURE_2D, GL_GENERATE_MIPMAP, FALSE); + renderer->curtex = g->tex.name; - /* glBegin (GL_QUADS); */ } else CLUTTER_NOTE (PANGO, g_message ("cache succsess %i\n", glyph)); @@ -380,15 +376,8 @@ draw_glyph (PangoRenderer *renderer_, if (g->tex.name != renderer->curtex) { - /* - if (renderer->curtex) - glEnd (); - */ - cogl_texture_bind (CGL_TEXTURE_2D, g->tex.name); renderer->curtex = g->tex.name; - - /* glBegin (GL_QUADS); */ } cogl_texture_quad (x, diff --git a/clutter/sdl/clutter-stage-sdl.c b/clutter/sdl/clutter-stage-sdl.c index d950b3068..ec9f3db81 100644 --- a/clutter/sdl/clutter-stage-sdl.c +++ b/clutter/sdl/clutter-stage-sdl.c @@ -78,13 +78,7 @@ clutter_stage_sdl_realize (ClutterActor *actor) return; } - clutter_stage_get_perspectivex (CLUTTER_STAGE (actor), &perspective); - cogl_setup_viewport (clutter_actor_get_width (actor), - clutter_actor_get_height (actor), - perspective.fovy, - perspective.aspect, - perspective.z_near, - perspective.z_far); + CLUTTER_SET_PRIVATE_FLAGS(actor, CLUTTER_ACTOR_SYNC_MATRICES); } static void diff --git a/tests/Makefile.am b/tests/Makefile.am index 8f82da967..97a1750fe 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,7 +1,7 @@ noinst_PROGRAMS = test-textures test-events test-offscreen test-scale \ test-actors test-behave test-text test-entry test-project \ test-boxes test-perspective test-rotate test-depth \ - test-threads test-timeline + test-threads test-timeline test-score INCLUDES = -I$(top_srcdir)/ LDADD = $(top_builddir)/clutter/libclutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.la @@ -23,5 +23,6 @@ test_rotate_SOURCES = test-rotate.c test_depth_SOURCES = test-depth.c test_threads_SOURCES = test-threads.c test_timeline_SOURCES = test-timeline.c +test_score_SOURCES = test-score.c EXTRA_DIST = redhand.png diff --git a/tests/test-score.c b/tests/test-score.c new file mode 100644 index 000000000..6dd18d383 --- /dev/null +++ b/tests/test-score.c @@ -0,0 +1,36 @@ +#include +#include +#include + + +int +main (int argc, char **argv) +{ + ClutterScore *score; + ClutterTimeline *timeline_1; + ClutterTimeline *timeline_2; + ClutterTimeline *timeline_3; + + clutter_init (&argc, &argv); + + timeline_1 = clutter_timeline_new (10, 120); + timeline_2 = clutter_timeline_clone (timeline_1); + timeline_3 = clutter_timeline_clone (timeline_1); + + score = clutter_score_new(); + clutter_score_add (score, timeline_1); + clutter_score_append (score, timeline_1, timeline_2); +#if 0 + clutter_score_append (score, timeline_2, timeline_3); +#endif + clutter_score_start (score); + + clutter_main (); + + g_object_unref (score); + g_object_unref (timeline_1); + g_object_unref (timeline_2); + g_object_unref (timeline_3); + + return EXIT_SUCCESS; +}