CVSROOT: /sources/gnash Module name: gnash Changes by: Sandro Santilli <strk> 07/09/07 11:56:07
Modified files: . : ChangeLog server : dlist.cpp movie_instance.cpp movie_root.cpp sprite_instance.cpp sprite_instance.h testsuite : MovieTester.cpp testsuite/misc-ming.all: action_execution_order_extend_test.c action_execution_order_test2.c action_execution_order_test4.c action_execution_order_test5.c action_execution_order_test7.c action_execution_order_test9.c testsuite/misc-swfc.all: action_execution_order_test10.sc movieclip_destruction_test2.sc testsuite/swfdec: PASSING swfdec_gnash_tester Log message: * server/dlist.cpp (output operator): don't compare iterators from different sequences ! * server/movie_instance.cpp (advance): don't invoke ONLOAD event handler, the event will be queued by ::construct instead * server/movie_root.cpp (setRootMovie): process actions queued by effect of root movie construction. * server/sprite_instance.{cpp,h}: - Drop do_action(), m_action_list and m_on_event_load_called members. - Make ::construct virtual so it can be overridden by movie_instance. - Have add_action_buffer queue globally or execute actions immediately depending on a new (misnamed) _callingFrameActions flag (I want to cleanup this part next). Basically, all actions are queued to the global list, with two exceptions: init actions and callFrame actions. - Expose a new public queueAction(action_buf&) method, currenly unused but possibly for use in a cleanup of the preceding queue-or-execute actions handling. - Move registration as core broadcaster listener code into its own function (registerAsListener). - Refactor restoreDisplayList() to also execute *action* tags of target frame, so to get order right. - Far cleaner advance_sprite() implementation. * testsuite/MovieTester.cpp (ctor): properly construct root movie, and render after construction. * testsuite/swfdec/swfdec_gnash_tester: advance 10 times as intended by swfdec testsuite, not 11 as we needed to do due to gnash bugs. * testsuite/misc-ming.all/: action_execution_order_extend_test.c, action_execution_order_test2.c, action_execution_order_test4.c, action_execution_order_test5.c, action_execution_order_test7.c, action_execution_order_test9.c, action_execution_order_test10.sc: SUCCESSES ! * testsuite/misc-swfc.all/movieclip_destruction_test2.sc: SUCCESSES ! * testsuite/swfdec/PASSING: SUCCESSES ! CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.4245&r2=1.4246 http://cvs.savannah.gnu.org/viewcvs/gnash/server/dlist.cpp?cvsroot=gnash&r1=1.88&r2=1.89 http://cvs.savannah.gnu.org/viewcvs/gnash/server/movie_instance.cpp?cvsroot=gnash&r1=1.16&r2=1.17 http://cvs.savannah.gnu.org/viewcvs/gnash/server/movie_root.cpp?cvsroot=gnash&r1=1.84&r2=1.85 http://cvs.savannah.gnu.org/viewcvs/gnash/server/sprite_instance.cpp?cvsroot=gnash&r1=1.330&r2=1.331 http://cvs.savannah.gnu.org/viewcvs/gnash/server/sprite_instance.h?cvsroot=gnash&r1=1.136&r2=1.137 http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/MovieTester.cpp?cvsroot=gnash&r1=1.47&r2=1.48 http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/misc-ming.all/action_execution_order_extend_test.c?cvsroot=gnash&r1=1.9&r2=1.10 http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/misc-ming.all/action_execution_order_test2.c?cvsroot=gnash&r1=1.3&r2=1.4 http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/misc-ming.all/action_execution_order_test4.c?cvsroot=gnash&r1=1.5&r2=1.6 http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/misc-ming.all/action_execution_order_test5.c?cvsroot=gnash&r1=1.2&r2=1.3 http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/misc-ming.all/action_execution_order_test7.c?cvsroot=gnash&r1=1.2&r2=1.3 http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/misc-ming.all/action_execution_order_test9.c?cvsroot=gnash&r1=1.4&r2=1.5 http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/misc-swfc.all/action_execution_order_test10.sc?cvsroot=gnash&r1=1.3&r2=1.4 http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/misc-swfc.all/movieclip_destruction_test2.sc?cvsroot=gnash&r1=1.8&r2=1.9 http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/swfdec/PASSING?cvsroot=gnash&r1=1.28&r2=1.29 http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/swfdec/swfdec_gnash_tester?cvsroot=gnash&r1=1.10&r2=1.11 Patches: Index: ChangeLog =================================================================== RCS file: /sources/gnash/gnash/ChangeLog,v retrieving revision 1.4245 retrieving revision 1.4246 diff -u -b -r1.4245 -r1.4246 --- ChangeLog 7 Sep 2007 07:38:44 -0000 1.4245 +++ ChangeLog 7 Sep 2007 11:56:05 -0000 1.4246 @@ -1,5 +1,40 @@ 2007-09-07 Sandro Santilli <[EMAIL PROTECTED]> + * server/dlist.cpp (output operator): don't compare iterators from + different sequences ! + * server/movie_instance.cpp (advance): don't invoke ONLOAD event + handler, the event will be queued by ::construct instead + * server/movie_root.cpp (setRootMovie): process actions + queued by effect of root movie construction. + * server/sprite_instance.{cpp,h}: + - Drop do_action(), m_action_list and m_on_event_load_called members. + - Make ::construct virtual so it can be overridden by movie_instance. + - Have add_action_buffer queue globally or execute actions immediately depending + on a new (misnamed) _callingFrameActions flag (I want to cleanup this part next). + Basically, all actions are queued to the global list, with two + exceptions: init actions and callFrame actions. + - Expose a new public queueAction(action_buf&) method, currenly + unused but possibly for use in a cleanup of the preceding queue-or-execute + actions handling. + - Move registration as core broadcaster listener code into its own + function (registerAsListener). + - Refactor restoreDisplayList() to also execute *action* tags of + target frame, so to get order right. + - Far cleaner advance_sprite() implementation. + * testsuite/MovieTester.cpp (ctor): properly construct root movie, + and render after construction. + * testsuite/swfdec/swfdec_gnash_tester: advance 10 times as intended + by swfdec testsuite, not 11 as we needed to do due to gnash bugs. + * testsuite/misc-ming.all/: action_execution_order_extend_test.c, + action_execution_order_test2.c, action_execution_order_test4.c, + action_execution_order_test5.c, action_execution_order_test7.c, + action_execution_order_test9.c, action_execution_order_test10.sc: + SUCCESSES ! + * testsuite/misc-swfc.all/movieclip_destruction_test2.sc: SUCCESSES ! + * testsuite/swfdec/PASSING: SUCCESSES ! + +2007-09-07 Sandro Santilli <[EMAIL PROTECTED]> + * testsuite/misc-mtasc.all/: level5.as, level99.as: check that at time of first-frame actions execution for loaded movies, _currentframe is set to 1. Index: server/dlist.cpp =================================================================== RCS file: /sources/gnash/gnash/server/dlist.cpp,v retrieving revision 1.88 retrieving revision 1.89 diff -u -b -r1.88 -r1.89 --- server/dlist.cpp 5 Sep 2007 19:27:49 -0000 1.88 +++ server/dlist.cpp 7 Sep 2007 11:56:06 -0000 1.89 @@ -1068,7 +1068,7 @@ ++it) { const DisplayItem& item = *it; - if ( it != dl._charsByDepth.begin() ) os << " | "; + if ( it != dl._timelineChars.begin() ) os << " | "; os << "ch id:" << item->get_id() << " name:" << item->get_name() << " depth:" << item->get_depth(); Index: server/movie_instance.cpp =================================================================== RCS file: /sources/gnash/gnash/server/movie_instance.cpp,v retrieving revision 1.16 retrieving revision 1.17 diff -u -b -r1.16 -r1.17 --- server/movie_instance.cpp 7 Sep 2007 07:10:20 -0000 1.16 +++ server/movie_instance.cpp 7 Sep 2007 11:56:06 -0000 1.17 @@ -125,12 +125,6 @@ advance_sprite(delta_time); - if (m_on_event_load_called == false) - { - on_event(event_id::LOAD); // root onload - m_on_event_load_called = true; - } - //_def->resumeLoader(); } Index: server/movie_root.cpp =================================================================== RCS file: /sources/gnash/gnash/server/movie_root.cpp,v retrieving revision 1.84 retrieving revision 1.85 diff -u -b -r1.84 -r1.85 --- server/movie_root.cpp 7 Sep 2007 07:10:20 -0000 1.84 +++ server/movie_root.cpp 7 Sep 2007 11:56:06 -0000 1.85 @@ -103,6 +103,10 @@ movie_root::setRootMovie(movie_instance* movie) { setLevel(0, movie); + + // actions in first frame of _level0 must execute now, before next advance, + // or they'll be executed with _currentframe being set to 2 + processActionQueue(); } /* private */ Index: server/sprite_instance.cpp =================================================================== RCS file: /sources/gnash/gnash/server/sprite_instance.cpp,v retrieving revision 1.330 retrieving revision 1.331 diff -u -b -r1.330 -r1.331 --- server/sprite_instance.cpp 7 Sep 2007 07:34:36 -0000 1.330 +++ server/sprite_instance.cpp 7 Sep 2007 11:56:06 -0000 1.331 @@ -1710,20 +1710,19 @@ oldDisplayList(), _drawable(new DynamicShape), _drawable_inst(_drawable->create_character_instance(this, 0)), - m_action_list(), //m_goto_frame_action_list(), m_play_state(PLAY), m_current_frame(0), m_has_looped(false), is_jumping_back(false), + _callingFrameActions(false), m_init_actions_executed(), m_as_environment(), m_has_key_event(false), m_has_mouse_event(false), _text_variables(), m_sound_stream_id(-1), - m_def(def), - m_on_event_load_called(false) + m_def(def) { assert(m_def != NULL); assert(m_root != NULL); @@ -1878,25 +1877,6 @@ } -// Take care of this frame's actions. -void sprite_instance::do_actions() -{ - testInvariant(); - - IF_VERBOSE_ACTION( - log_action(_("Executing " SIZET_FMT " actions in frame " SIZET_FMT - "/" SIZET_FMT " of sprite %s"), - m_action_list.size(), - m_current_frame+1, - m_def->get_frame_count(), getTargetPath().c_str()); - ); - - execute_actions(m_action_list); - assert(m_action_list.empty()); - - testInvariant(); -} - bool sprite_instance::get_frame_number(const as_value& frame_spec, size_t& frameno) const { @@ -1940,39 +1920,24 @@ return; } - size_t original_size = m_action_list.size(); - // Set the current sound_stream_id to -1, meaning that no stream are // active. If there are an active stream it will be updated while // executing the execute_tags. set_sound_stream_id(-1); // Execute the execute_tag actions - - const PlayList& playlist = m_def->get_playlist(frame_number); - for (size_t i=0, n=playlist.size(); i<n; ++i) - { - execute_tag* e = playlist[i]; - if (e->is_action_tag()) - { - e->execute(this); - } - } - - // - // exetract target frame actions and execute them + // We set _callingFrameActions to true so that add_action_buffer + // will execute immediately instead of queuing them. + // NOTE: in case gotoFrame is executed by code in the called frame + // we'll temporarly clear the _callingFrameActions flag + // to properly queue actions back on the global queue. // - ActionList::iterator it = m_action_list.begin(); - for(size_t i =0; i<original_size; i++) { it++; } - ActionList::iterator original_end = it; - - ActionList frame_actions(original_end, m_action_list.end()); - // erase the target frame actions from the orignal list - m_action_list.erase(original_end, m_action_list.end()); - // Note: this function may invalidate the iterators above - execute_actions(frame_actions); + _callingFrameActions=true; + const PlayList& playlist = m_def->get_playlist(frame_number); + std::for_each(playlist.begin(), playlist.end(), + boost::bind(&execute_tag::execute_action, _1, this)); + _callingFrameActions=false; - assert(m_action_list.size() == original_size); } character* sprite_instance::add_empty_movieclip(const char* name, int depth) @@ -2118,16 +2083,23 @@ } #endif +/* public */ +void +sprite_instance::queueAction(const action_buffer& action) +{ + movie_root& root = _vm.getRoot(); + root.pushAction(action, boost::intrusive_ptr<sprite_instance>(this)); +} + /* private */ void sprite_instance::queueActions(ActionList& actions) { - movie_root& root = VM::get().getRoot(); for(ActionList::iterator it=actions.begin(), itEnd=actions.end(); it != itEnd; ++it) { const action_buffer* buf = *it; - root.pushAction(*buf, boost::intrusive_ptr<sprite_instance>(this)); + queueAction(*buf); } } @@ -2136,6 +2108,17 @@ { testInvariant(); +#ifdef GNASH_DEBUG + log_debug("Event %s invoked for sprite %s", id.get_function_name().c_str(), getTarget().c_str()); +#endif + + // We do not execute ENTER_FRAME if unloaded + if ( id.m_id == event_id::ENTER_FRAME && isUnloaded() ) + { + log_debug("Sprite %s ignored ENTER_FRAME event (is unloaded)", getTarget().c_str()); + return false; + } + if ( id.is_button_event() && ! isEnabled() ) { log_debug("Sprite %s ignored button-like event %s as not 'enabled'", @@ -2159,6 +2142,23 @@ // Fall through and call the function also, if it's defined! + // NOTE: user-defined onLoad is not invoked if the corresponding + // clip-defined onLoad is not present (zou mentions if + // NO clip-defined events are instead) + // + // Note that this can't be true for sprites + // not placed by PlaceObject + // + if ( id.m_id == event_id::LOAD ) + { + if ( get_parent() && ! called ) + { + log_debug("Sprite %s won't check for user-defined LOAD event (didn't have a clipLoad event defined)", getTarget().c_str()); + testInvariant(); + return false; + } + } + // Check for member function. if( ! id.is_key_event ()) { @@ -2246,6 +2246,7 @@ //GNASH_REPORT_FUNCTION; assert(!isUnloaded()); + assert(!_callingFrameActions); // call_frame shoudl never trigger advance_sprite // Process any pending loadVariables request processCompletedLoadVariableRequests(); @@ -2253,27 +2254,28 @@ // mouse drag. character::do_mouse_drag(); - if (m_on_event_load_called) - { - on_event(event_id::ENTER_FRAME); - if ( isUnloaded() ) - { - log_debug("%s enterFrame event handler unloaded self", getTarget().c_str()); - // TODO: check if we should still advance the frame counter - // can be checked, if we're still reachable, by fetching _currentframe. - return; - } - } - #ifdef GNASH_DEBUG size_t frame_count = m_def->get_frame_count(); - log_msg(_("sprite '%s' ::advance_sprite is at frame %u/%u " - "- onload called: %d - oldDIsplayList has %d elements"), - getTargetPath().c_str(), m_current_frame, - frame_count, m_on_event_load_called, oldDisplayList.size()); + log_msg(_("Advance_sprite for sprite '%s' - frame %u/%u " + "- oldDIsplayList has %d elements"), + getTarget().c_str(), m_current_frame, + frame_count, oldDisplayList.size()); #endif + // Advance DisplayList elements already placed (even if looping back ?) + { +#ifdef GNASH_DEBUG + log_msg("Advancing %d childs of sprite %s in current DisplayList:", m_display_list.size(), getTarget().c_str()); +#endif + m_display_list.dump(); + AdvancerVisitor visitor(delta_time); + m_display_list.visitByReversePlacement(visitor); + } + + + queueEvent(event_id::ENTER_FRAME); + // Update current and next frames. if (m_play_state == PLAY) { @@ -2283,8 +2285,6 @@ int prev_frame = m_current_frame; - if (m_on_event_load_called) - { #ifdef GNASH_DEBUG log_msg(_("on_event_load called, incrementing")); #endif @@ -2292,7 +2292,6 @@ #ifdef GNASH_DEBUG log_msg(_("after increment we are at frame %u/%u"), m_current_frame, frame_count); #endif - } // Execute the current frame's tags. // First time execute_frame_tags(0) executed in dlist.cpp(child) or movie_def_impl(root) @@ -2300,16 +2299,21 @@ { if ( m_current_frame == 0 && has_looped() ) { - // TODO: check why this would be any different - // then calling restoreDisplayList(0) instead.. - // Ah! I think I know.. +#ifdef GNASH_DEBUG + log_debug("Jumping back to frame 0 of sprite %s", getTarget().c_str()); +#endif restoreDisplayList(0); // seems OK to me. } - - // TODO: Make sure m_current_frame is 0-based during execution of DLIST tags + else + { +#ifdef GNASH_DEBUG + log_debug("Executing frame%d (0-based) tags of sprite %s", m_current_frame, getTarget().c_str()); +#endif + // Make sure m_current_frame is 0-based during execution of DLIST tags execute_frame_tags(m_current_frame, TAG_DLIST|TAG_ACTION); } } + } #ifdef GNASH_DEBUG else { @@ -2319,51 +2323,6 @@ } #endif - // Advance DisplayList elements which has not been just-added. - // - // These are elements in oldDisplayList cleared of all but elements - // still in current DisplayList (the other must have been removed - // by RemoveObject tags). I'm not sure we should do this actually, - // as maybe we need to execute actions in removed objects *before* - // we drop them... - // - // We do *not* dispatch UNLOAD event on the removed objects here - // as we assume the event was dispatched by execution of the - // RemoveObject tag itself. I might be wrong though, will come - // back to this issue later. - // - // Note that we work on a *copy* of oldDisplayList as we're going - // to need oldDisplayList again later, to extract the list of - // newly added characters - // - { - AdvancerVisitor visitor(delta_time); - oldDisplayList.visitByReversePlacement(visitor); - } - - // Now execute actions on this timeline, after actions - // in old childs timelines have been executed. - //log_msg(_("Executing actions in %s timeline"), getTargetPath().c_str()); - do_actions(); - - // Finally, execute actions in (we actually "advance") newly added - // (and not unloaded) childs - // - // These are elements in the current DisplayList, cleared - // by all unloaded elements and by non-unloaded elements in - // oldDisplayList. - // - // Of course we do NOT call UNLOAD events here, as - // the chars we're clearing have *not* been removed: - // we're simply doing internal work here... - // - { - AdvancerVisitor visitor(delta_time); - DisplayList newlyAdded = m_display_list; - newlyAdded.clear(oldDisplayList, false); // keep only newly added - newlyAdded.visitAll(visitor); - } - // Remember current state of the DisplayList for next iteration oldDisplayList = m_display_list; } @@ -2373,45 +2332,16 @@ { // GNASH_REPORT_FUNCTION; + log_msg(_("Advance sprite '%s' at frame %u/%u " + "- oldDIsplayList has %d elements"), + getTargetPath().c_str(), m_current_frame, + get_frame_count(), oldDisplayList.size()); + // child movieclip frame rate is the same the root movieclip frame rate // that's why it is not needed to analyze 'm_time_remainder' - if (m_on_event_load_called == false) - { -#ifdef GNASH_DEBUG - log_msg(_("Calling ONLOAD event")); -#endif - on_event(event_id::LOAD); // clip onload - if (isUnloaded()) - { - log_debug("%s load event handler unloaded self", getTarget().c_str()); - return; - } - - if (m_has_key_event) - { -#ifdef NEW_KEY_LISTENER_LIST_DESIGN - // TODO: Don't do this at every advancement - // OnClip key handlers should be registered at construction time, - // User defined handlers should be registered explicitly by Key.addListener(); - _vm.getRoot().add_key_listener(KeyListener(this, KeyListener::ON_CLIP_DEF)); -#else - _vm.getRoot().add_key_listener(this); -#endif - } - // Mouse events listening is done in has_mouse_event directly. - // This shows to work better for attachMovieTest.swf, - // but might actually be a completely unrelated issue. - // In particular, copying event handlers in attachMovie should - // be more closely inspected (and need more ad-hoc testcases) - //if (m_has_mouse_event) - //{ - //_vm.getRoot().add_mouse_listener(this); - //} - } advance_sprite(delta_time); - m_on_event_load_called = true; } void @@ -2460,9 +2390,10 @@ m_display_list = newList; } - // 3. Execute all displaylist tags from first to target frame + // 3. Execute all displaylist tags from first to target frame, with + // target frame tag execution including ACTION tags - for (size_t f = 0; f<=tgtFrame; ++f) + for (size_t f = 0; f<tgtFrame; ++f) { // // Set m_current_frame so it is correct (0-based) during @@ -2473,6 +2404,16 @@ execute_frame_tags(f, TAG_DLIST); } + // call_frame (setting _callignFrameActions) should never trigger ::advance, + // at most it shoudl trigger goto_frame which would temporarly set _callingFrameAction to false + // ::advance and ::goto_frame are supposedly the only callers to restoreDisplayList + // + assert(!_callingFrameActions); + + // Finally, execute target frame tags, both ACTION and DLIST + m_current_frame = tgtFrame; + execute_frame_tags(tgtFrame, TAG_DLIST|TAG_ACTION); + is_jumping_back = false; // finished jumping back } @@ -2626,7 +2567,7 @@ { // We'd immediately return if target_frame_number == m_current_frame assert(target_frame_number > m_current_frame); - for (size_t f = m_current_frame+1; f<=target_frame_number; ++f) + for (size_t f = m_current_frame+1; f<target_frame_number; ++f) { // Second argument requests that only "DisplayList" tags // are executed. This means NO actions will be @@ -2634,46 +2575,21 @@ execute_frame_tags(f, TAG_DLIST); } m_current_frame = target_frame_number; - } #if defined(GNASH_DEBUG_TIMELINE) cout << "At end of DisplayList reconstruction, m_current_frame is " << m_current_frame << endl; #endif - /// Backup current action list, as we're going to use it - /// to fetch actions in the target frame - ActionList actionListBackup = m_action_list; - - // m_action_list contains actions from frame 'target_frame_number' - // to frame 'm_current_frame', too much than needed, clear it first. - // TODO: check this, we didn't execute TAG_ACTION tags... - // Can it be we're cleaning up too many actions here ? - m_action_list.clear(); - - // Get the actions of target frame.(We don't have a direct way to - // do this, so use execute_frame_tags instead). - execute_frame_tags(target_frame_number, TAG_ACTION); + // Now execute target frame tags (queuing actions) + // NOTE: just in case we're being called by code in a called frame + // we'll backup and resume the _callingFrameActions flag + bool callingFrameActionsBackup = _callingFrameActions; + _callingFrameActions = false; + execute_frame_tags(target_frame_number, TAG_DLIST|TAG_ACTION); + _callingFrameActions = callingFrameActionsBackup; + } assert(m_current_frame == target_frame_number); - - - // After entering to advance_sprite() m_current_frame points to frame - // that already is executed. - // Macromedia Flash do goto_frame then run actions from this frame. - // We do too. - - // Stores the target frame actions to m_goto_frame_action_list, which - // will be executed in after advancing child characters. - // When actions execution order will be fixed all of this might - // become obsoleted and the target frame actions could be pushed - // directly on the preexisting m_action_list (and no need to back it up). - // - //m_goto_frame_action_list = m_action_list; - queueActions(m_action_list); - - // Restore ActionList from backup - m_action_list = actionListBackup; - } bool sprite_instance::goto_labeled_frame(const std::string& label) @@ -3319,6 +3235,32 @@ method_name, method_arg_fmt, args); } +void +sprite_instance::registerAsListener() +{ + if (m_has_key_event) + { +#ifdef NEW_KEY_LISTENER_LIST_DESIGN + // TODO: Don't do this at every advancement + // OnClip key handlers should be registered at construction time, + // User defined handlers should be registered explicitly by Key.addListener(); + _vm.getRoot().add_key_listener(KeyListener(this, KeyListener::ON_CLIP_DEF)); +#else + _vm.getRoot().add_key_listener(this); +#endif + } + // Mouse events listening is done in has_mouse_event directly. + // This shows to work better for attachMovieTest.swf, + // but might actually be a completely unrelated issue. + // In particular, copying event handlers in attachMovie should + // be more closely inspected (and need more ad-hoc testcases) + //if (m_has_mouse_event) + //{ + //_vm.getRoot().add_mouse_listener(this); + //} +} + + // WARNING: THIS SNIPPET NEEDS THE CHARACTER TO BE "INSTANTIATED", which is // it's target path needs to exist, or any as_value for it will be @@ -3328,18 +3270,24 @@ { assert(!isUnloaded()); - _origTarget = getTarget(); - #ifdef GNASH_DEBUG log_msg(_("Constructing sprite '%s'"), _origTarget.c_str()); #endif + // Take note of our original target (for soft references) + _origTarget = getTarget(); + + // Register this sprite as a core broadcasters listener + registerAsListener(); + // We *might* avoid this, but better safe then sorry m_def->ensure_frame_loaded(0); // Backup the DisplayList *before* manipulating it ! + // TODO: still needed ? what for ? assert( oldDisplayList.empty() ); + // Execute CONSTRUCT event immediately on_event(event_id::CONSTRUCT); if (isUnloaded()) { @@ -3348,7 +3296,41 @@ return; } + // Now execute frame tags and take care of queuing the LOAD event. + // + // DLIST tags are executed immediately while ACTION tags are queued. + // + // For _root movie, LOAD event is invoked *after* actions in first frame + // See misc-ming.all/action_execution_order_test4.{c,swf} + // + assert(!_callingFrameActions); // or will not be queuing actions + if ( get_parent() == 0 ) + { + +#ifdef GNASH_DEBUG + log_debug(_("Executing tags of frame0 in sprite %s"), getTarget().c_str()); +#endif + execute_frame_tags(0, TAG_DLIST|TAG_ACTION); + +#ifdef GNASH_DEBUG + log_debug(_("Queuing ONLOAD event for sprite %s"), getTarget().c_str()); +#endif + queueEvent(event_id::LOAD); + + } + else + { + +#ifdef GNASH_DEBUG + log_debug(_("Queuing ONLOAD event for sprite %s"), getTarget().c_str()); +#endif + queueEvent(event_id::LOAD); + +#ifdef GNASH_DEBUG + log_debug(_("Executing tags of frame0 in sprite %s"), getTarget().c_str()); +#endif execute_frame_tags(0, TAG_DLIST|TAG_ACTION); + } if ( _name.empty() ) { @@ -3357,6 +3339,7 @@ // If the instance doesn't have a name, it will NOT be // an ActionScript referenciable object so we don't have // anything more to do. + return; } @@ -3387,6 +3370,7 @@ bool sprite_instance::unload() { + assert(!isUnloaded()); #ifdef GNASH_DEBUG log_msg(_("Unloading sprite '%s'"), getTargetPath().c_str()); #endif Index: server/sprite_instance.h =================================================================== RCS file: /sources/gnash/gnash/server/sprite_instance.h,v retrieving revision 1.136 retrieving revision 1.137 diff -u -b -r1.136 -r1.137 --- server/sprite_instance.h 4 Sep 2007 20:50:00 -0000 1.136 +++ server/sprite_instance.h 7 Sep 2007 11:56:06 -0000 1.137 @@ -245,9 +245,6 @@ //virtual void advance_root(float delta_time); virtual void advance_sprite(float delta_time); - /// Take care of this frame's actions. - void do_actions(); - /// Set the sprite state at the specified frame number. // /// 0-based frame numbers!! @@ -392,10 +389,9 @@ /// when calling user-defined constructors). /// /// TODO: check if we only need to construct "named" instances - /// TODO: consider moving this function up to the 'character' class. /// TODO: possibly have this function call the onConstruct() event handler /// - void construct(); + virtual void construct(); /// Unload all contents in the displaylist and this instance /// See character::unload for more info @@ -478,7 +474,8 @@ /// frame advance. void add_action_buffer(const action_buffer* a) { - m_action_list.push_back(a); + if ( ! _callingFrameActions ) queueAction(*a); + else execute_action(*a); } /// Execute a single action buffer (DOACTION block) @@ -754,8 +751,23 @@ /// from the display lists void cleanupDisplayList(); + /// Queue the given action buffer + // + /// The action will be pushed on the current + /// global list (see movie_root). + /// + void queueAction(const action_buffer& buf); + private: + /// Register this sprite as a listener of core broadcasters + // + /// This is currently only used for key events broadcaster + /// and it's supposed to be called only once (or should we + /// also call it whenever onKey* user-defined function is defined ? + /// + void registerAsListener(); + /// \brief /// Return value of the 'enabled' property, casted to a boolean value. /// True if not found (undefined to bool evaluates to false). @@ -796,15 +808,25 @@ const std::string& newname, int depth); #endif - /// Reconstruct the DisplayList for proper loop-back operations + /// Advance to a previous frame. // - /// This function will: + /// This function will basically restore the DisplayList as it supposedly + /// was *before* executing tags in target frame and then execute target + /// frame tags (both DLIST and ACTION ones). + /// + /// In practice, it will: /// /// - Remove from current DisplayList: /// - Timeline instances constructed after target frame /// - Timeline instances constructed before or at the target frame but no more at the original depth /// - Dynamic instances found in the static depth zone - /// - Execute all displaylist tags from first to target frame, incrementing m_current_frame as it goes + /// - Execute all displaylist tags from first to one-before target frame, + /// appropriately setting m_current_frame as it goes, finally execute both displaylist and action + /// tags for target frame. + /// + /// Callers of this methods are: + /// - goto_frame (for jump-backs) + /// - advance_sprite (for loop-back) /// /// See: http://www.gnashdev.org/wiki/index.php/TimelineControl#Timeline_instances /// @@ -816,8 +838,6 @@ /// /// - m_current_frame == targetFrame /// - /// NOTES: resetDisplayList() above should likely just call restoreDisplayList(0); - /// /// TODO: consider using this same function for jump-forward too, /// with some modifications... /// @@ -868,8 +888,6 @@ /// boost::intrusive_ptr<character> _drawable_inst; - ActionList m_action_list; - // this is deprecated, we'll be pushing gotoframe target // actions to the global action queue //ActionList m_goto_frame_action_list; @@ -885,6 +903,9 @@ // true is the sprite is jumping back. bool is_jumping_back; + // true is we're calling frame actions + bool _callingFrameActions; + // a bit-array class would be ideal for this std::vector<bool> m_init_actions_executed; @@ -950,8 +971,6 @@ /// DefineSprite tag) or movie_def_impl (for the top-level movie). boost::intrusive_ptr<movie_definition> m_def; - bool m_on_event_load_called; - /// List of loadVariables requests typedef std::list<LoadVariablesThread*> LoadVariablesThreads; Index: testsuite/MovieTester.cpp =================================================================== RCS file: /sources/gnash/gnash/testsuite/MovieTester.cpp,v retrieving revision 1.47 retrieving revision 1.48 diff -u -b -r1.47 -r1.48 --- testsuite/MovieTester.cpp 7 Sep 2007 00:11:27 -0000 1.47 +++ testsuite/MovieTester.cpp 7 Sep 2007 11:56:06 -0000 1.48 @@ -95,10 +95,6 @@ // Now complete load of the movie _movie_def->completeLoad(); _movie_def->ensure_frame_loaded(_movie_def->get_frame_count()); - _movie_root->setRootMovie( _movie_def->create_movie_instance() ); - - _movie = _movie_root->get_root_movie(); - assert(_movie); // Activate verbosity so that self-contained testcases are // also used @@ -106,13 +102,23 @@ dbglogfile.setVerbosity(1); - // Now place the root movie on the stage - advance(); + auto_ptr<movie_instance> mi ( _movie_def->create_movie_instance() ); + + // Set _movie before calling ::render + _movie = mi.get(); + + // Finally, place the root movie on the stage ... + _movie_root->setRootMovie( mi.release() ); + + // ... and render it + render(); } void MovieTester::render(render_handler& h, InvalidatedRanges& invalidated_regions) { + assert(_movie); + set_render_handler(&h); h.set_invalidated_regions(invalidated_regions); Index: testsuite/misc-ming.all/action_execution_order_extend_test.c =================================================================== RCS file: /sources/gnash/gnash/testsuite/misc-ming.all/action_execution_order_extend_test.c,v retrieving revision 1.9 retrieving revision 1.10 diff -u -b -r1.9 -r1.10 --- testsuite/misc-ming.all/action_execution_order_extend_test.c 1 Jul 2007 10:54:47 -0000 1.9 +++ testsuite/misc-ming.all/action_execution_order_extend_test.c 7 Sep 2007 11:56:07 -0000 1.10 @@ -168,7 +168,7 @@ with Ming)?? */ check_equals(mo, "_root.y3", "'mc_red onUnload called'"); /* mc_blu Onload is not called */ - xcheck_equals(mo, "_root.y4", "undefined"); + check_equals(mo, "_root.y4", "undefined"); /* actions in main timeline is executed *after* mc_blu.onEnterFrame */ check_equals(mo, "_root.y5", "'as_in_root'"); /* actions in main timeline is executed *before* mc_blu.onUnload */ Index: testsuite/misc-ming.all/action_execution_order_test2.c =================================================================== RCS file: /sources/gnash/gnash/testsuite/misc-ming.all/action_execution_order_test2.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -b -r1.3 -r1.4 --- testsuite/misc-ming.all/action_execution_order_test2.c 5 Sep 2007 15:48:08 -0000 1.3 +++ testsuite/misc-ming.all/action_execution_order_test2.c 7 Sep 2007 11:56:07 -0000 1.4 @@ -106,7 +106,7 @@ SWFMovie_nextFrame(mo); /* 2nd frame */ /* Action order is not dependent on DisplayList depth here! */ - xcheck_equals(mo, "_root.x1", "'depth10+depth12+depth11+'"); + check_equals(mo, "_root.x1", "'depth10+depth12+depth11+'"); SWFMovie_nextFrame(mo); /* 3rd frame */ mc_red4 = newSWFMovieClip(); Index: testsuite/misc-ming.all/action_execution_order_test4.c =================================================================== RCS file: /sources/gnash/gnash/testsuite/misc-ming.all/action_execution_order_test4.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -b -r1.5 -r1.6 --- testsuite/misc-ming.all/action_execution_order_test4.c 6 Sep 2007 18:59:51 -0000 1.5 +++ testsuite/misc-ming.all/action_execution_order_test4.c 7 Sep 2007 11:56:07 -0000 1.6 @@ -224,7 +224,7 @@ SWFMovie_nextFrame(mo); /* 4th frame */ check_equals(mo, "_root.x0", "'01+02+03+'"); - xcheck_equals(mo, "_root.x1", "'1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+'"); + check_equals(mo, "_root.x1", "'1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+'"); check_equals(mo, "_root.x2", "'as_start+as_end+load_called+'"); add_actions(mo, " _root.totals(); stop(); "); SWFMovie_nextFrame(mo); /* 5th frame */ Index: testsuite/misc-ming.all/action_execution_order_test5.c =================================================================== RCS file: /sources/gnash/gnash/testsuite/misc-ming.all/action_execution_order_test5.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -b -r1.2 -r1.3 --- testsuite/misc-ming.all/action_execution_order_test5.c 1 Jul 2007 10:54:48 -0000 1.2 +++ testsuite/misc-ming.all/action_execution_order_test5.c 7 Sep 2007 11:56:07 -0000 1.3 @@ -224,7 +224,7 @@ SWFMovie_nextFrame(mo); /* 4th frame of _root */ /* checks */ - xcheck_equals(mo, "_root.x1", "'1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+'"); + check_equals(mo, "_root.x1", "'1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+'"); add_actions(mo, " _root.totals(); stop(); "); SWFMovie_nextFrame(mo); /* 5th frame of _root */ Index: testsuite/misc-ming.all/action_execution_order_test7.c =================================================================== RCS file: /sources/gnash/gnash/testsuite/misc-ming.all/action_execution_order_test7.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -b -r1.2 -r1.3 --- testsuite/misc-ming.all/action_execution_order_test7.c 1 Jul 2007 10:54:49 -0000 1.2 +++ testsuite/misc-ming.all/action_execution_order_test7.c 7 Sep 2007 11:56:07 -0000 1.3 @@ -73,7 +73,7 @@ SWFMovie_nextFrame(mo); /* 4th frame */ SWFDisplayItem_remove(it); - xcheck_equals(mo, "_root.x", "1"); + check_equals(mo, "_root.x", "1"); check_equals(mo, "typeof(mc)", "'undefined'"); add_actions(mo, " _root.totals(); stop(); "); SWFMovie_nextFrame(mo); /* 5th frame */ Index: testsuite/misc-ming.all/action_execution_order_test9.c =================================================================== RCS file: /sources/gnash/gnash/testsuite/misc-ming.all/action_execution_order_test9.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -b -r1.4 -r1.5 --- testsuite/misc-ming.all/action_execution_order_test9.c 1 Jul 2007 10:54:49 -0000 1.4 +++ testsuite/misc-ming.all/action_execution_order_test9.c 7 Sep 2007 11:56:07 -0000 1.5 @@ -93,7 +93,7 @@ SWFDisplayItem_remove(it2); // Gnash fails because actions in "mc1" got executed, see expected behaviour - xcheck_equals(mo, "typeof(_root.x)", "'undefined'"); + check_equals(mo, "typeof(_root.x)", "'undefined'"); add_actions(mo, " _root.totals(); stop(); "); SWFMovie_nextFrame(mo); // 6th frame Index: testsuite/misc-swfc.all/action_execution_order_test10.sc =================================================================== RCS file: /sources/gnash/gnash/testsuite/misc-swfc.all/action_execution_order_test10.sc,v retrieving revision 1.3 retrieving revision 1.4 diff -u -b -r1.3 -r1.4 --- testsuite/misc-swfc.all/action_execution_order_test10.sc 7 Sep 2007 07:17:44 -0000 1.3 +++ testsuite/misc-swfc.all/action_execution_order_test10.sc 7 Sep 2007 11:56:07 -0000 1.4 @@ -128,7 +128,7 @@ .frame 6 .action: - xcheck_equals(_root.as_order, '0+1+2+3+4+5+6+7+8+9+10+'); + check_equals(_root.as_order, '0+1+2+3+4+5+6+7+8+9+10+'); _root.note(_root.as_order); totals(); stop(); Index: testsuite/misc-swfc.all/movieclip_destruction_test2.sc =================================================================== RCS file: /sources/gnash/gnash/testsuite/misc-swfc.all/movieclip_destruction_test2.sc,v retrieving revision 1.8 retrieving revision 1.9 diff -u -b -r1.8 -r1.9 --- testsuite/misc-swfc.all/movieclip_destruction_test2.sc 3 Sep 2007 07:42:59 -0000 1.8 +++ testsuite/misc-swfc.all/movieclip_destruction_test2.sc 7 Sep 2007 11:56:07 -0000 1.9 @@ -113,8 +113,8 @@ .del mc3 // Remove mc3 by RemoveObject2 .action: - xcheck_equals(mc2UnlaodedCount, 1); // mc2.onUnload triggered - xcheck_equals(mc3UnlaodedCount, 1); // mc3.onUnload triggered + check_equals(mc2UnlaodedCount, 1); // mc2.onUnload triggered + check_equals(mc3UnlaodedCount, 1); // mc3.onUnload triggered check_equals(mc1Ref.valueOf(), null); check_equals(mc2Ref, mc2); check_equals(mc3Ref, mc3); @@ -140,8 +140,8 @@ check_equals(mc3.testvar, 100); mc2.removMovieClip(); mc3.removMovieClip(); - xcheck_equals(mc2UnlaodedCount, 1); // mc2.onUnload not triggered again - xcheck_equals(mc2UnlaodedCount, 1); // mc3.onUnload not triggered again + check_equals(mc2UnlaodedCount, 1); // mc2.onUnload not triggered again + check_equals(mc2UnlaodedCount, 1); // mc3.onUnload not triggered again check_equals(typeof(mc2), 'movieclip'); // mc2 is still accessible check_equals(typeof(mc3), 'movieclip'); // mc3 is still accessible check_equals(mc2.getDepth(), -16387); @@ -153,8 +153,8 @@ mc2.onUnload(); mc3.onUnload(); - xcheck_equals(mc2UnlaodedCount, 2); // we can still invoke onUnload - xcheck_equals(mc2UnlaodedCount, 2); // we can still invoke onUnload + check_equals(mc2UnlaodedCount, 2); // we can still invoke onUnload + check_equals(mc2UnlaodedCount, 2); // we can still invoke onUnload .end Index: testsuite/swfdec/PASSING =================================================================== RCS file: /sources/gnash/gnash/testsuite/swfdec/PASSING,v retrieving revision 1.28 retrieving revision 1.29 diff -u -b -r1.28 -r1.29 --- testsuite/swfdec/PASSING 1 Sep 2007 01:20:47 -0000 1.28 +++ testsuite/swfdec/PASSING 7 Sep 2007 11:56:07 -0000 1.29 @@ -196,3 +196,10 @@ remove-depths-6.swf remove-depths-7.swf remove-depths-8.swf +children.swf +currentframe.swf +doaction-after-placeobject.swf +lifetime1.swf +load-4.swf +load-5.swf +order.swf Index: testsuite/swfdec/swfdec_gnash_tester =================================================================== RCS file: /sources/gnash/gnash/testsuite/swfdec/swfdec_gnash_tester,v retrieving revision 1.10 retrieving revision 1.11 diff -u -b -r1.10 -r1.11 --- testsuite/swfdec/swfdec_gnash_tester 6 Sep 2007 13:09:36 -0000 1.10 +++ testsuite/swfdec/swfdec_gnash_tester 7 Sep 2007 11:56:07 -0000 1.11 @@ -23,10 +23,9 @@ fi # NOTE: We're supposed to advance 10 frames. -# We advance 11 times as for Gnash the first call to ::advance -# simply constructs the root movie (will be fixed eventually) +# We allow 11 loop-backs (just for fun, we probably can support more) # -${GPROCESSOR} -r11 -f11 -v "$in" | grep TRACE | sed 's/.*TRACE: //' | fromdos > $out +${GPROCESSOR} -r11 -f10 -v "$in" | grep TRACE | sed 's/.*TRACE: //' | fromdos > $out if test "$?" != 0; then echo "gprocessor returned an error" exit 1 _______________________________________________ Gnash-commit mailing list Gnash-commit@gnu.org http://lists.gnu.org/mailman/listinfo/gnash-commit