2 * Copyright (C) 2006-2008 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
24 #include "swfdec_actor.h"
25 #include "swfdec_as_internal.h"
26 #include "swfdec_as_strings.h"
27 #include "swfdec_debug.h"
28 #include "swfdec_button_movie.h"
29 #include "swfdec_player_internal.h"
30 #include "swfdec_resource.h"
31 #include "swfdec_sandbox.h"
32 #include "swfdec_sprite_movie.h"
35 G_DEFINE_ABSTRACT_TYPE (SwfdecActor
, swfdec_actor
, SWFDEC_TYPE_MOVIE
)
38 swfdec_actor_dispose (GObject
*object
)
40 SwfdecActor
*actor
= SWFDEC_ACTOR (object
);
43 swfdec_event_list_free (actor
->events
);
47 G_OBJECT_CLASS (swfdec_actor_parent_class
)->dispose (object
);
51 swfdec_actor_iterate_end (SwfdecActor
*actor
)
53 SwfdecMovie
*movie
= SWFDEC_MOVIE (actor
);
55 return movie
->parent
== NULL
||
56 movie
->state
< SWFDEC_MOVIE_STATE_REMOVED
;
60 swfdec_actor_mouse_events (SwfdecActor
*actor
)
62 SwfdecAsObject
*object
;
64 /* root movies don't get event */
65 if (SWFDEC_MOVIE (actor
)->parent
== NULL
)
67 /* look if we have a script that gets events */
68 if (actor
->events
&& swfdec_event_list_has_mouse_events (actor
->events
))
70 /* otherwise, require at least one of the custom script handlers */
71 object
= SWFDEC_AS_OBJECT (actor
);
72 if (swfdec_as_object_has_variable (object
, SWFDEC_AS_STR_onRollOver
) ||
73 swfdec_as_object_has_variable (object
, SWFDEC_AS_STR_onRollOut
) ||
74 swfdec_as_object_has_variable (object
, SWFDEC_AS_STR_onDragOver
) ||
75 swfdec_as_object_has_variable (object
, SWFDEC_AS_STR_onDragOut
) ||
76 swfdec_as_object_has_variable (object
, SWFDEC_AS_STR_onPress
) ||
77 swfdec_as_object_has_variable (object
, SWFDEC_AS_STR_onRelease
) ||
78 swfdec_as_object_has_variable (object
, SWFDEC_AS_STR_onReleaseOutside
))
84 swfdec_actor_mouse_in (SwfdecActor
*actor
)
86 if (swfdec_player_is_mouse_pressed (SWFDEC_PLAYER (swfdec_gc_object_get_context (actor
))))
87 swfdec_actor_queue_script (actor
, SWFDEC_EVENT_DRAG_OVER
);
89 swfdec_actor_queue_script (actor
, SWFDEC_EVENT_ROLL_OVER
);
93 swfdec_actor_mouse_out (SwfdecActor
*actor
)
95 if (swfdec_player_is_mouse_pressed (SWFDEC_PLAYER (swfdec_gc_object_get_context (actor
))))
96 swfdec_actor_queue_script (actor
, SWFDEC_EVENT_DRAG_OUT
);
98 swfdec_actor_queue_script (actor
, SWFDEC_EVENT_ROLL_OUT
);
102 swfdec_actor_mouse_press (SwfdecActor
*actor
, guint button
)
106 swfdec_actor_queue_script (actor
, SWFDEC_EVENT_PRESS
);
110 swfdec_actor_mouse_release (SwfdecActor
*actor
, guint button
)
112 SwfdecPlayer
*player
;
117 player
= SWFDEC_PLAYER (swfdec_gc_object_get_context (actor
));
118 if (player
->priv
->mouse_below
== actor
)
119 swfdec_actor_queue_script (actor
, SWFDEC_EVENT_RELEASE
);
121 swfdec_actor_queue_script (actor
, SWFDEC_EVENT_RELEASE_OUTSIDE
);
125 swfdec_actor_mouse_move (SwfdecActor
*actor
, double x
, double y
)
127 /* nothing to do here, it's just there so we don't need to check for NULL */
131 swfdec_actor_key_press (SwfdecActor
*actor
, guint keycode
, guint character
)
133 swfdec_actor_queue_script (actor
, SWFDEC_EVENT_KEY_DOWN
);
137 swfdec_actor_key_release (SwfdecActor
*actor
, guint keycode
, guint character
)
139 swfdec_actor_queue_script (actor
, SWFDEC_EVENT_KEY_UP
);
143 swfdec_actor_constructor (GType type
, guint n_construct_properties
,
144 GObjectConstructParam
*construct_properties
)
146 SwfdecPlayerPrivate
*priv
;
149 object
= G_OBJECT_CLASS (swfdec_actor_parent_class
)->constructor (type
,
150 n_construct_properties
, construct_properties
);
152 priv
= SWFDEC_PLAYER (swfdec_gc_object_get_context (object
))->priv
;
153 /* NB: adding to the movies list happens before swfdec_movie_initialize().
154 * swfdec_movie_initialize() does a gotoAndPlay(0) for Sprites which can
155 * cause new movies to be created (and added to this list).
157 priv
->actors
= g_list_prepend (priv
->actors
, object
);
163 swfdec_actor_class_init (SwfdecActorClass
*klass
)
165 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
167 object_class
->constructor
= swfdec_actor_constructor
;
168 object_class
->dispose
= swfdec_actor_dispose
;
170 klass
->iterate_end
= swfdec_actor_iterate_end
;
171 klass
->mouse_events
= swfdec_actor_mouse_events
;
172 klass
->mouse_in
= swfdec_actor_mouse_in
;
173 klass
->mouse_out
= swfdec_actor_mouse_out
;
174 klass
->mouse_press
= swfdec_actor_mouse_press
;
175 klass
->mouse_release
= swfdec_actor_mouse_release
;
176 klass
->mouse_move
= swfdec_actor_mouse_move
;
177 klass
->key_press
= swfdec_actor_key_press
;
178 klass
->key_release
= swfdec_actor_key_release
;
182 swfdec_actor_init (SwfdecActor
*actor
)
184 swfdec_sound_matrix_init_identity (&actor
->sound_matrix
);
188 swfdec_sprite_movie_set_constructor (SwfdecSpriteMovie
*movie
)
190 SwfdecMovie
*mov
= SWFDEC_MOVIE (movie
);
191 SwfdecAsContext
*context
= swfdec_gc_object_get_context (movie
);
192 SwfdecAsObject
*constructor
= NULL
;
194 g_assert (mov
->resource
!= NULL
);
199 name
= swfdec_resource_get_export_name (mov
->resource
,
200 SWFDEC_CHARACTER (movie
->sprite
));
202 name
= swfdec_as_context_get_string (context
, name
);
203 constructor
= swfdec_player_get_export_class (SWFDEC_PLAYER (context
),
207 if (constructor
== NULL
) {
208 swfdec_sandbox_use (SWFDEC_MOVIE (movie
)->resource
->sandbox
);
209 swfdec_as_object_set_constructor_by_name (SWFDEC_AS_OBJECT (movie
),
210 SWFDEC_AS_STR_MovieClip
, NULL
);
211 swfdec_sandbox_unuse (SWFDEC_MOVIE (movie
)->resource
->sandbox
);
214 swfdec_as_object_set_constructor (SWFDEC_AS_OBJECT (movie
), constructor
);
220 swfdec_actor_execute (SwfdecActor
*actor
, SwfdecEventType condition
,
223 SwfdecAsObject
*thisp
;
226 gboolean need_constructor
= FALSE
;
228 g_return_if_fail (SWFDEC_IS_ACTOR (actor
));
230 version
= swfdec_movie_get_version (SWFDEC_MOVIE (actor
));
232 if (SWFDEC_IS_BUTTON_MOVIE (actor
)) {
233 /* these conditions don't exist for buttons */
234 if (condition
== SWFDEC_EVENT_CONSTRUCT
|| condition
< SWFDEC_EVENT_PRESS
)
236 thisp
= SWFDEC_AS_OBJECT (SWFDEC_MOVIE (actor
)->parent
);
238 while (!SWFDEC_IS_SPRITE_MOVIE (thisp
))
239 thisp
= SWFDEC_AS_OBJECT (SWFDEC_MOVIE (thisp
)->parent
);
243 thisp
= SWFDEC_AS_OBJECT (actor
);
247 if (condition
== SWFDEC_EVENT_CONSTRUCT
) {
250 need_constructor
= swfdec_sprite_movie_set_constructor (SWFDEC_SPRITE_MOVIE (actor
));
251 } else if (condition
== SWFDEC_EVENT_ENTER
) {
252 if (SWFDEC_MOVIE (actor
)->state
>= SWFDEC_MOVIE_STATE_REMOVED
)
254 } else if (condition
== SWFDEC_EVENT_SCROLL
|| condition
== SWFDEC_EVENT_CHANGED
) {
255 SwfdecAsValue argv
[2];
256 SwfdecMovie
*movie
= SWFDEC_MOVIE (actor
);
258 if (condition
== SWFDEC_EVENT_SCROLL
)
259 SWFDEC_AS_VALUE_SET_STRING (&argv
[0], SWFDEC_AS_STR_onScroller
);
261 SWFDEC_AS_VALUE_SET_STRING (&argv
[0], SWFDEC_AS_STR_onChanged
);
262 SWFDEC_AS_VALUE_SET_MOVIE (&argv
[1], movie
);
263 swfdec_sandbox_use (movie
->resource
->sandbox
);
264 swfdec_as_object_call (SWFDEC_AS_OBJECT (actor
),
265 SWFDEC_AS_STR_broadcastMessage
, 2, argv
, NULL
);
266 swfdec_sandbox_unuse (movie
->resource
->sandbox
);
270 swfdec_sandbox_use (SWFDEC_MOVIE (actor
)->resource
->sandbox
);
272 swfdec_event_list_execute (actor
->events
, thisp
, condition
, key
);
274 /* FIXME: how do we compute the version correctly here? */
276 name
= swfdec_event_type_get_name (condition
);
278 swfdec_as_object_call (SWFDEC_AS_OBJECT (actor
), name
, 0, NULL
, NULL
);
280 if (condition
== SWFDEC_EVENT_CONSTRUCT
&& need_constructor
)
281 swfdec_as_object_call (thisp
, SWFDEC_AS_STR_constructor
, 0, NULL
, NULL
);
283 swfdec_sandbox_unuse (SWFDEC_MOVIE (actor
)->resource
->sandbox
);
287 * swfdec_actor_queue_script_with_key:
288 * @movie: a #SwfdecMovie
289 * @condition: the event that should happen
290 * @key: the key for this event
292 * Queues execution of all scripts associated with the given event and key.
295 swfdec_actor_queue_script_with_key (SwfdecActor
*actor
,
296 SwfdecEventType condition
, guint8 key
)
298 SwfdecPlayer
*player
;
301 g_return_if_fail (SWFDEC_IS_ACTOR (actor
));
303 if (!SWFDEC_IS_SPRITE_MOVIE (actor
) && !SWFDEC_IS_BUTTON_MOVIE (actor
))
305 /* can happen for mouse/keyboard events on the initial movie */
306 if (SWFDEC_MOVIE (actor
)->resource
->sandbox
== NULL
) {
307 SWFDEC_INFO ("movie %s not yet initialized, skipping event", SWFDEC_MOVIE (actor
)->name
);
312 case SWFDEC_EVENT_INITIALIZE
:
313 importance
= SWFDEC_PLAYER_ACTION_QUEUE_INIT
;
315 case SWFDEC_EVENT_CONSTRUCT
:
316 importance
= SWFDEC_PLAYER_ACTION_QUEUE_CONSTRUCT
;
318 case SWFDEC_EVENT_LOAD
:
319 case SWFDEC_EVENT_ENTER
:
320 case SWFDEC_EVENT_UNLOAD
:
321 case SWFDEC_EVENT_MOUSE_MOVE
:
322 case SWFDEC_EVENT_MOUSE_DOWN
:
323 case SWFDEC_EVENT_MOUSE_UP
:
324 case SWFDEC_EVENT_KEY_UP
:
325 case SWFDEC_EVENT_KEY_DOWN
:
326 case SWFDEC_EVENT_DATA
:
327 case SWFDEC_EVENT_PRESS
:
328 case SWFDEC_EVENT_RELEASE
:
329 case SWFDEC_EVENT_RELEASE_OUTSIDE
:
330 case SWFDEC_EVENT_ROLL_OVER
:
331 case SWFDEC_EVENT_ROLL_OUT
:
332 case SWFDEC_EVENT_DRAG_OVER
:
333 case SWFDEC_EVENT_DRAG_OUT
:
334 case SWFDEC_EVENT_KEY_PRESS
:
335 case SWFDEC_EVENT_CHANGED
:
336 case SWFDEC_EVENT_SCROLL
:
337 importance
= SWFDEC_PLAYER_ACTION_QUEUE_NORMAL
;
340 g_return_if_reached ();
343 player
= SWFDEC_PLAYER (swfdec_gc_object_get_context (actor
));
344 swfdec_player_add_action (player
, actor
, condition
, key
, importance
);
348 * swfdec_actor_queue_script:
349 * @movie: a #SwfdecMovie
350 * @condition: the event that should happen
352 * Queues execution of all scripts associated with the given event.
355 swfdec_actor_queue_script (SwfdecActor
*actor
, SwfdecEventType condition
)
357 swfdec_actor_queue_script_with_key (actor
, condition
, 0);
361 * swfdec_actor_get_mouse_events:
362 * @movie: a #SwfdecActor
364 * Checks if this actor should respond to mouse events.
366 * Returns: %TRUE if this movie can receive mouse events
369 swfdec_actor_get_mouse_events (SwfdecActor
*actor
)
371 SwfdecActorClass
*klass
;
373 g_return_val_if_fail (SWFDEC_IS_ACTOR (actor
), FALSE
);
375 klass
= SWFDEC_ACTOR_GET_CLASS (actor
);
376 if (klass
->mouse_events
)
377 return klass
->mouse_events (actor
);
383 swfdec_actor_has_focusrect (SwfdecActor
*actor
)
385 g_return_val_if_fail (SWFDEC_IS_ACTOR (actor
), FALSE
);
387 if (!SWFDEC_IS_BUTTON_MOVIE (actor
) &&
388 !SWFDEC_IS_SPRITE_MOVIE (actor
))
391 if (actor
->focusrect
== SWFDEC_FLASH_MAYBE
) {
392 actor
= SWFDEC_ACTOR (swfdec_movie_get_root (SWFDEC_MOVIE (actor
)));
394 g_assert (actor
->focusrect
!= SWFDEC_FLASH_MAYBE
);
396 return actor
->focusrect
!= SWFDEC_FLASH_NO
;