CVSROOT: /sources/gnash Module name: gnash Changes by: Sandro Santilli <strk> 07/04/10 21:44:14
Modified files: . : ChangeLog server : sprite_instance.cpp sprite_instance.h server/vm : ASHandlers.cpp testsuite/actionscript.all: MovieClip.as Log message: * server/sprite_instance.{cpp,h}: add duplicateMovieClip method for use by MovieClip.duplicateMovieClip and ActionDuplicateClip. * server/vm/ASHandlers.cpp (ActionDuplicateClip): use the new sprite_instance::duplicateMovieClip method fixing a bogus assumption about the parent to duplicate into. * testsuite/actionscript.all/MovieClip.as: add small test for ActionDuplicateClip. CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.2834&r2=1.2835 http://cvs.savannah.gnu.org/viewcvs/gnash/server/sprite_instance.cpp?cvsroot=gnash&r1=1.229&r2=1.230 http://cvs.savannah.gnu.org/viewcvs/gnash/server/sprite_instance.h?cvsroot=gnash&r1=1.92&r2=1.93 http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/ASHandlers.cpp?cvsroot=gnash&r1=1.85&r2=1.86 http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/actionscript.all/MovieClip.as?cvsroot=gnash&r1=1.47&r2=1.48 Patches: Index: ChangeLog =================================================================== RCS file: /sources/gnash/gnash/ChangeLog,v retrieving revision 1.2834 retrieving revision 1.2835 diff -u -b -r1.2834 -r1.2835 --- ChangeLog 10 Apr 2007 21:31:00 -0000 1.2834 +++ ChangeLog 10 Apr 2007 21:44:14 -0000 1.2835 @@ -1,3 +1,13 @@ +2007-04-10 Sandro Santilli <[EMAIL PROTECTED]> + + * server/sprite_instance.{cpp,h}: add duplicateMovieClip method + for use by MovieClip.duplicateMovieClip and ActionDuplicateClip. + * server/vm/ASHandlers.cpp (ActionDuplicateClip): use the new + sprite_instance::duplicateMovieClip method fixing a bogus assumption + about the parent to duplicate into. + * testsuite/actionscript.all/MovieClip.as: add small test for + ActionDuplicateClip. + 2007-04-10 Tomas Groth Christensen <[EMAIL PROTECTED]> * server/asobj/NetStreamFfmpeg.h: Fixed a bug in the Index: server/sprite_instance.cpp =================================================================== RCS file: /sources/gnash/gnash/server/sprite_instance.cpp,v retrieving revision 1.229 retrieving revision 1.230 diff -u -b -r1.229 -r1.230 --- server/sprite_instance.cpp 10 Apr 2007 15:48:39 -0000 1.229 +++ server/sprite_instance.cpp 10 Apr 2007 21:44:14 -0000 1.230 @@ -396,59 +396,28 @@ if (fn.nargs < 2) { IF_VERBOSE_ASCODING_ERRORS( - log_aserror("duplicateMovieClip needs 2 or 3 args\n"); + log_aserror("MovieClip.duplicateMovieClip() needs 2 or 3 args"); ); return as_value(); } - // strk question: Would a call to - // sprite->get_movie_defition()->create_instance() - // and an add_display_object taking a character_instance - // instead of a character *id* be more appropriate ? - // (sounds more general) + std::string newname = fn.arg(0).to_std_string(&(fn.env())); + int depth = int(fn.arg(1).to_number()); - // Copy event handlers from sprite - // We should not copy 'm_action_buffer' since the 'm_method' already contains it - std::vector<swf_event*> event_handlers; - const std::map<event_id, as_value>& sprite_events = sprite->get_event_handlers(); - typedef std::map<event_id, as_value>::const_iterator event_iterator; - for (event_iterator it = sprite_events.begin(), - itEnd = sprite_events.end(); - it != itEnd; ++it ) - { - swf_event* e = new swf_event; // FIXME: who will delete this ? - e->m_event = it->first; - e->m_method = it->second; - event_handlers.push_back(e); - } - - character* parent = sprite->get_parent(); - sprite_instance* parent_sprite = parent ? parent->to_movie() : NULL; - character* ch = NULL; - if (parent_sprite) - { - ch = parent_sprite->add_display_object( - sprite->get_id(), - fn.arg(0).to_string(), - event_handlers, - int(fn.arg(1).to_number()), - true, // replace if depth is occupied (to drop) - sprite->get_cxform(), - sprite->get_matrix(), - sprite->get_ratio(), - sprite->get_clip_depth()); - - ch->setDynamic(); + boost::intrusive_ptr<sprite_instance> ch; // Copy members from initObject - if (fn.nargs == 3 && ch) + if (fn.nargs == 3) { boost::intrusive_ptr<as_object> initObject = fn.arg(2).to_object(); - if ( initObject ) ch->copyProperties(*initObject); + ch = sprite->duplicateMovieClip(newname, depth, initObject.get()); } - + else + { + ch = sprite->duplicateMovieClip(newname, depth); } - return as_value(ch); + + return as_value(ch.get()); } static as_value sprite_goto_and_play(const fn_call& fn) @@ -1866,6 +1835,58 @@ return txt_char; } +boost::intrusive_ptr<sprite_instance> +sprite_instance::duplicateMovieClip(const std::string& newname, int depth, + as_object* initObject) +{ + character* parent_ch = get_parent(); + if ( ! parent_ch ) + { + log_error("Can't clone root the movie"); + return NULL; + } + sprite_instance* parent = parent_ch->to_movie(); + if ( ! parent ) + { + log_error("%s parent is not a sprite, can't clone", getTarget().c_str()); + return NULL; + } + + boost::intrusive_ptr<sprite_instance> newsprite = new sprite_instance(m_def.get(), + m_root, parent, get_id()); + newsprite->set_name(newname.c_str()); + + newsprite->setDynamic(); + + if ( initObject ) newsprite->copyProperties(*initObject); + //else newsprite->copyProperties(*this); + + + // Copy event handlers from sprite + // We should not copy 'm_action_buffer' since the 'm_method' already contains it + const std::map<event_id, as_value>& sprite_events = get_event_handlers(); + typedef std::map<event_id, as_value>::const_iterator event_iterator; + for (event_iterator it = sprite_events.begin(), + itEnd = sprite_events.end(); + it != itEnd; ++it ) + { + swf_event* e = new swf_event; // FIXME: who will delete this ? + e->m_event = it->first; + e->m_method = it->second; + e->attach_to(newsprite.get()); + } + + parent->m_display_list.place_character( + newsprite.get(), + depth, + get_cxform(), + get_matrix(), + get_ratio(), + get_clip_depth()); + + return newsprite; +} + void sprite_instance::clone_display_object(const std::string& name, const std::string& newname, int depth) { @@ -1889,6 +1910,11 @@ // @@ TODO need to duplicate ch's event handlers, and presumably other members? // Probably should make a character::clone() function to handle this. } + else + { + log_error("clone_display_object(%s, %s, %d): could not find a character named %s to clone", + name.c_str(), newname.c_str(), depth, name.c_str()); + } } void sprite_instance::remove_display_object(const tu_string& name_tu) @@ -2719,7 +2745,7 @@ int clip_depth) { assert(m_def != NULL); - // log_msg("%s: character %s, id is %d", __FUNCTION__, name, character_id); // FIXME: debugging crap + //log_msg("%s: character %s, id is %d, depth is %d", __FUNCTION__, name, character_id, depth); // FIXME: debugging crap character_def* cdef = m_def->get_character_def(character_id); if (cdef == NULL) Index: server/sprite_instance.h =================================================================== RCS file: /sources/gnash/gnash/server/sprite_instance.h,v retrieving revision 1.92 retrieving revision 1.93 diff -u -b -r1.92 -r1.93 --- server/sprite_instance.h 10 Apr 2007 15:48:39 -0000 1.92 +++ server/sprite_instance.h 10 Apr 2007 21:44:14 -0000 1.93 @@ -17,7 +17,7 @@ // // -/* $Id: sprite_instance.h,v 1.92 2007/04/10 15:48:39 strk Exp $ */ +/* $Id: sprite_instance.h,v 1.93 2007/04/10 21:44:14 strk Exp $ */ // Stateful live Sprite instance @@ -530,10 +530,22 @@ // delegates to movie_root virtual void stop_drag(); - /// Duplicate the object with the specified name - /// and add it with a new name at a new depth. - void clone_display_object(const std::string& name, - const std::string& newname, int depth); + /// Duplicate this sprite in its timeline + // + /// Add the new character at a the given depth to this sprite + /// parent displaylist. + /// + /// NOTE: the call will fail for the root movie (no parent). + /// NOTE2: any character at the given target depth will be + /// replaced by the new character + /// NOTE3: event handlers will also be copied + /// + /// @param init_object + /// If not null, will be used to copy properties over. + /// + boost::intrusive_ptr<sprite_instance> duplicateMovieClip( + const std::string& newname, + int newdepth, as_object* init_object=NULL); /// Remove the object with the specified name. // @@ -737,6 +749,11 @@ private: + /// Duplicate the object with the specified name + /// and add it with a new name at a new depth. + void clone_display_object(const std::string& name, + const std::string& newname, int depth); + /// Reset the DisplayList for proper loop-back or goto_frame // /// The DisplayList is cleared by all but dynamic characters Index: server/vm/ASHandlers.cpp =================================================================== RCS file: /sources/gnash/gnash/server/vm/ASHandlers.cpp,v retrieving revision 1.85 retrieving revision 1.86 diff -u -b -r1.85 -r1.86 --- server/vm/ASHandlers.cpp 10 Apr 2007 17:41:42 -0000 1.85 +++ server/vm/ASHandlers.cpp 10 Apr 2007 21:44:14 -0000 1.86 @@ -14,7 +14,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -/* $Id: ASHandlers.cpp,v 1.85 2007/04/10 17:41:42 strk Exp $ */ +/* $Id: ASHandlers.cpp,v 1.86 2007/04/10 21:44:14 strk Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -1141,23 +1141,36 @@ void SWFHandlers::ActionDuplicateClip(ActionExec& thread) { -// GNASH_REPORT_FUNCTION; + GNASH_REPORT_FUNCTION; as_environment& env = thread.env; thread.ensureStack(3); - sprite_instance* si = env.get_target()->to_movie(); - if ( ! si ) + int depth = int(env.top(0).to_number(&env))+character::staticDepthOffset; + std::string newname = env.top(1).to_std_string(&env); + std::string path = env.top(2).to_std_string(&env); + + character* ch = env.find_target(path); + if ( ! ch ) { - log_error("environment target is not a sprite_instance while executing ActionDuplicateClip"); + IF_VERBOSE_ASCODING_ERRORS( + log_aserror("Path given to duplicateMovieClip(%s) doesn't point to a character", + path.c_str()); + ); + return; } - else + + boost::intrusive_ptr<sprite_instance> sprite = ch->to_movie(); + if ( ! sprite ) { - si->clone_display_object( - env.top(2).to_std_string(), - env.top(1).to_std_string(), - (int) env.top(0).to_number(&env)); + IF_VERBOSE_ASCODING_ERRORS( + log_aserror("Path given to duplicateMovieClip(%s) is not a sprite", + path.c_str()); + ); + return; } + + sprite->duplicateMovieClip(newname, depth); env.drop(3); } Index: testsuite/actionscript.all/MovieClip.as =================================================================== RCS file: /sources/gnash/gnash/testsuite/actionscript.all/MovieClip.as,v retrieving revision 1.47 retrieving revision 1.48 diff -u -b -r1.47 -r1.48 --- testsuite/actionscript.all/MovieClip.as 6 Apr 2007 15:53:24 -0000 1.47 +++ testsuite/actionscript.all/MovieClip.as 10 Apr 2007 21:44:14 -0000 1.48 @@ -1,5 +1,5 @@ // -// Copyright (C) 2005, 2006 Free Software Foundation, Inc. +// Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -22,7 +22,7 @@ // compile this test case with Ming makeswf, and then // execute it like this gnash -1 -r 0 -v out.swf -rcsid="$Id: MovieClip.as,v 1.47 2007/04/06 15:53:24 strk Exp $"; +rcsid="$Id: MovieClip.as,v 1.48 2007/04/10 21:44:14 strk Exp $"; #include "check.as" @@ -310,6 +310,24 @@ #endif // OUTPUT_VERSION >= 6 //---------------------------------------------- +// Test duplicateMovieClip +//---------------------------------------------- +#if OUTPUT_VERSION >= 6 +_root.createEmptyMovieClip("original", 61); +_root.original.createEmptyMovieClip("child1", 1); +_root.original._x = 100; +check_equals(typeof(_root.original), 'movieclip'); +check_equals(typeof(_root.original.child1), 'movieclip'); +check_equals(_root.original._x, 100); + +duplicateMovieClip(_root.original, "copy1", 63); +check_equals(typeof(_root.copy1), 'movieclip'); +check_equals(typeof(_root.copy1.child1), 'undefined'); +check_equals(_root.copy1.getDepth(), 63); +check_equals(_root.copy1._x, 100); +#endif // OUTPUT_VERSION >= 6 + +//---------------------------------------------- // Test timeline variables //---------------------------------------------- _______________________________________________ Gnash-commit mailing list Gnash-commit@gnu.org http://lists.gnu.org/mailman/listinfo/gnash-commit