1 // MovieClip.h: Stateful live Sprite instance, for Gnash. 2 // 3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 4 // Free Software Foundation, Inc 5 // 6 // This program is free software; you can redistribute it and/or modify 7 // it under the terms of the GNU General Public License as published by 8 // the Free Software Foundation; either version 3 of the License, or 9 // (at your option) any later version. 10 // 11 // This program is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with this program; if not, write to the Free Software 18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 20 // Stateful live Sprite instance 21 22 #ifndef GNASH_MOVIECLIP_H 23 #define GNASH_MOVIECLIP_H 24 25 #ifdef HAVE_CONFIG_H 26 #include "gnashconfig.h" 27 #endif 28 29 #include <vector> 30 #include <map> 31 #include <string> 32 #include <boost/ptr_container/ptr_list.hpp> 33 #include <boost/intrusive_ptr.hpp> 34 35 #include "ControlTag.h" 36 #include "movie_definition.h" // for inlines 37 #include "DisplayObjectContainer.h" 38 #include "as_environment.h" // for composition 39 #include "DynamicShape.h" // for composition 40 #include "dsodefs.h" // for DSOEXPORT 41 42 // Forward declarations 43 namespace gnash { 44 class Movie; 45 class swf_event; 46 class drag_state; 47 class LoadVariablesThread; 48 class GradientRecord; 49 class TextField; 50 class BitmapData_as; 51 class CachedBitmap; 52 class DisplayList; 53 namespace SWF { 54 class PlaceObject2Tag; 55 } 56 } 57 58 namespace gnash { 59 60 /// A MovieClip is a container for DisplayObjects. 61 // 62 /// TODO: This class should inherit from Sprite 63 // 64 /// In AS3 is it distinguished from a Sprite by having a timeline, i.e. 65 /// more than one frame. In AS2, there is no Sprite class. 66 // 67 /// There are basically two types of MovieClip: dynamic and non-dynamic. 68 /// Dynamic clips are created using createEmptyMovieClip() or 69 /// duplicateMovieClip(). Non-dynamic MovieClips are parsed from a SWF file. 70 /// The isDynamic() member function is the only way to tell the difference 71 /// (see following paragraph). 72 // 73 /// The presence of a definition (the _def member) reveals whether the 74 /// MovieClip was constructed with an immutable definition or not. MovieClips 75 /// created using createEmptyMovieClip() have no definition. MovieClips 76 /// constructed using duplicateMovieClip() have the same definition as the 77 /// duplicated clip. They are "dynamic", but may have a definition! 78 // 79 /// A MovieClip always has an _swf member. This is the top-level SWF 80 /// (Movie) containing either the definition or the code from 81 /// which the MovieClip was created. The _url member and SWF version are 82 /// dependent on the _swf. Exports are also sought in this Movie. 83 class DSOTEXPORT MovieClip : public DisplayObjectContainer 84 { 85 public: 86 87 typedef std::vector<TextField*> TextFields; 88 89 /// A container for textfields, indexed by their variable name 90 typedef std::map<ObjectURI, TextFields, ObjectURI::LessThan> 91 TextFieldIndex; 92 93 typedef std::map<std::string, std::string> MovieVariables; 94 95 typedef movie_definition::PlayList PlayList; 96 97 enum PlayState 98 { 99 PLAYSTATE_PLAY, 100 PLAYSTATE_STOP 101 }; 102 103 /// Construct a MovieClip instance 104 // 105 /// @param def 106 /// Pointer to the movie_definition this object is an 107 /// instance of (may be a top-level movie or a sprite). 108 /// This may be 0 if there is no immutable definition. 109 /// 110 /// @param root 111 /// The "relative" _swf of this sprite, which is the 112 /// instance of top-level sprite defined by the same 113 /// SWF that also contained *this* sprite definition. 114 /// Note that this can be *different* from the top-level 115 /// movie accessible through the VM, in case this sprite 116 /// was defined in an externally loaded movie. 117 /// 118 /// @param parent 119 /// Parent of the created instance in the display list. 120 /// May be 0 for top-level movies (_level#). 121 MovieClip(as_object* object, const movie_definition* def, 122 Movie* root, DisplayObject* parent); 123 124 virtual ~MovieClip(); 125 126 // Return the originating SWF 127 virtual Movie* get_root() const; 128 129 virtual bool trackAsMenu(); 130 131 /// Queue event in the global action queue. 132 // 133 /// notifyEvent(id) will be called by execution of the queued 134 /// action 135 void queueEvent(const event_id& id, int lvl); 136 137 void queueLoad(); 138 139 /// Return the _root ActionScript property of this sprite. 140 // 141 /// Relative or absolute is determined by the _lockroot property, 142 /// see getLockRoot and setLockRoot. May return this. 143 virtual MovieClip* getAsRoot(); 144 145 /// Get the composite bounds of all component drawing elements 146 virtual SWFRect getBounds() const; 147 148 // See dox in DisplayObject.h 149 virtual bool pointInShape(std::int32_t x, std::int32_t y) const; 150 151 // See dox in DisplayObject.h 152 virtual bool pointInVisibleShape(std::int32_t x, std::int32_t y) const; 153 154 /// return true if the given point is located in a(this) hitable sprite. 155 /// 156 /// all sprites except mouse-insensitive dynamic masks are hitable. 157 /// _visible property is ignored for hitable DisplayObjects. 158 virtual bool pointInHitableShape(std::int32_t x, std::int32_t y) const; 159 160 /// Return 0-based index to current frame get_current_frame()161 size_t get_current_frame() const 162 { 163 return _currentFrame; 164 } 165 get_frame_count()166 size_t get_frame_count() const 167 { 168 return _def ? _def->get_frame_count() : 1; 169 } 170 171 /// Return number of completely loaded frames of this sprite/movie 172 // 173 /// Note: the number is also the last frame accessible (frames 174 /// numberes are 1-based) 175 /// get_loaded_frames()176 size_t get_loaded_frames() const 177 { 178 return _def ? _def->get_loading_frame() : 1; 179 } 180 181 /// Return total number of bytes in the movie 182 /// (not sprite!) get_bytes_total()183 size_t get_bytes_total() const 184 { 185 return isDynamic() ? 0 : _def->get_bytes_total(); 186 } 187 188 /// Return number of loaded bytes in the movie 189 /// (not sprite!) get_bytes_loaded()190 size_t get_bytes_loaded() const 191 { 192 return isDynamic() ? 0 : _def->get_bytes_loaded(); 193 } 194 get_frame_size()195 const SWFRect& get_frame_size() const 196 { 197 static const SWFRect r; 198 return _def ? _def->get_frame_size() : r; 199 } 200 201 /// Stop or play the sprite. 202 // 203 /// If stopped, any stream sound associated with this sprite 204 /// will also be stopped. 205 /// 206 DSOEXPORT void setPlayState(PlayState s); 207 getPlayState()208 PlayState getPlayState() const { return _playState; } 209 210 // delegates to movie_root (possibly wrong) 211 void set_background_color(const rgba& color); 212 213 /// Return true if we have any mouse event handlers. 214 // 215 /// NOTE: this function currently does not consider 216 /// general mouse event handlers MOUSE_MOVE, MOUSE 217 virtual bool mouseEnabled() const; 218 219 /// \brief 220 /// Return the topmost entity that the given point 221 /// covers that can receive mouse events. NULL if 222 /// none. Coords are in parent's frame. 223 virtual InteractiveObject* topmostMouseEntity(std::int32_t x, 224 std::int32_t y); 225 226 // see dox in DisplayObject.h 227 const DisplayObject* findDropTarget(std::int32_t x, std::int32_t y, 228 DisplayObject* dragging) const; 229 setDropTarget(const std::string & tgt)230 void setDropTarget(const std::string& tgt) { 231 _droptarget = tgt; 232 } 233 getDropTarget()234 const std::string& getDropTarget() const { 235 return _droptarget; 236 } 237 238 /// Advance to the next frame of the MovieClip. 239 // 240 /// Actions will be executed or pushed to the queue as necessary. 241 virtual void advance(); 242 243 /// Set the sprite state at the specified frame number. 244 // 245 /// 0-based frame numbers!! 246 ///(in contrast to ActionScript and Flash MX) 247 /// 248 DSOEXPORT void goto_frame(size_t target_frame_number); 249 250 /// Parse frame spec and return a 0-based frame number. 251 // 252 /// If frame spec cannot be converted to !NAN and !Infinity number 253 /// it will be converted to a string and considered a 254 /// frame label (returns false if referring to an 255 /// unknwown label). 256 /// 257 /// @param frame_spec 258 /// The frame specification. 259 /// 260 /// @param frameno 261 /// The evaluated frame number (0-based) 262 /// 263 /// @return 264 /// True if the frame_spec could be resolved to a frame number. 265 /// False if the frame_spec was invalid. 266 bool get_frame_number(const as_value& frame_spec, size_t& frameno) const; 267 268 /// Look up the labeled frame, and jump to it. 269 bool goto_labeled_frame(const std::string& label); 270 271 /// Render this MovieClip. 272 virtual void display(Renderer& renderer, const Transform& xform); 273 274 /// Draw this MovieClip 275 // 276 /// This is effectively the same as display(), but uses only the passed 277 /// transform. 278 void draw(Renderer& renderer, const Transform& xform); 279 280 void omit_display(); 281 282 /// Swap depth of the given DisplayObjects in the DisplayList 283 // 284 /// See DisplayList::swapDepths for more info swapDepths(DisplayObject * ch1,int newdepth)285 void swapDepths(DisplayObject* ch1, int newdepth) 286 { 287 _displayList.swapDepths(ch1, newdepth); 288 } 289 290 /// Return the DisplayObject at given depth in our DisplayList. 291 // 292 /// @return NULL if the specified depth is available (no chars there) 293 DisplayObject* getDisplayObjectAtDepth(int depth); 294 295 /// Attach a DisplayObject at the specified depth. 296 DisplayObject* addDisplayListObject(DisplayObject* obj, int depth); 297 298 /// Place a DisplayObject or mask to the DisplayList. 299 // 300 /// This method instantiates the given DisplayObject definition 301 /// and places it on the stage at the given depth. 302 /// 303 /// If the specified depth is already occupied, it results a no-ops. 304 /// Otherwise, a new DisplayObject will be created and onload handler 305 /// will be triggerred. 306 /// 307 /// @param tag 308 /// A swf defined placement tag (PlaceObject, or PlaceObject2, 309 /// or PlaceObject3). 310 /// No ownership transfer, the tag is still owned by the 311 /// movie_definition class. 312 /// 313 /// @param dlist 314 /// The display list to add the DisplayObject to. 315 /// 316 /// @return 317 /// A pointer to the DisplayObject being added or NULL 318 DisplayObject* add_display_object(const SWF::PlaceObject2Tag* tag, 319 DisplayList& dlist); 320 321 /// Proxy of DisplayList::moveDisplayObject() 322 void move_display_object(const SWF::PlaceObject2Tag* tag, 323 DisplayList& dlist); 324 325 /// Proxy of DisplayList::replaceDisplayObject() 326 void replace_display_object(const SWF::PlaceObject2Tag* tag, 327 DisplayList& dlist); 328 329 /// Proxy of DisplayList::removeDisplayObject() 330 void remove_display_object(const SWF::PlaceObject2Tag* tag, 331 DisplayList& dlist); 332 333 /// \brief 334 /// Remove the object at the specified depth. 335 // 336 /// NOTE: 337 /// (1)the id parameter is currently unused, but 338 /// required to avoid breaking of inheritance from movie.h. 339 /// (2)the id might be used for specifying a DisplayObject 340 /// in the depth(think about multiple DisplayObjects within the same 341 /// depth, not tested and a rare case) 342 void remove_display_object(int depth, int /*id*/); 343 344 void unloadMovie(); 345 346 /// Attach the given DisplayObject instance to current display list 347 // 348 /// @param newch The DisplayObject instance to attach. 349 /// @param depth The depth to assign to the instance. 350 void attachCharacter(DisplayObject& newch, int depth, as_object* initObject); 351 352 /// Handle placement event 353 // 354 /// This callback will (not known to be a problem): 355 /// 356 /// (1) Register ourselves with the global instance list 357 /// (2) Take note of our original target path 358 /// (3) Register as listener of core broadcasters 359 /// (4) Execute tags of frame 0 360 /// 361 /// The callback will also (known to be bogus): 362 // 363 /// (1) Construct this instance as an ActionScript object. 364 /// See constructAsScriptObject() method, including constructing 365 /// registered class and adding properties. 366 virtual void construct(as_object* initObj = nullptr); 367 368 /// Mark this sprite as destroyed 369 // 370 /// This is an override of DisplayObject::destroy() 371 /// 372 /// A sprite should be destroyed when is removed from the display 373 /// list and is not more needed for names (target) resolutions. 374 /// Sprites are needed for names resolution whenever themselves 375 /// or a contained object has an onUnload event handler defined, 376 /// in which case we want the event handler to find the 'this' 377 /// variable w/out attempting to rebind it. 378 /// 379 /// When a sprite is destroyed, all its children are also destroyed. 380 /// 381 /// Note: this function will release most memory associated with 382 /// the sprite as no members or drawable should be needed anymore. 383 void destroy(); 384 385 /// Add the given action buffer to the list of action 386 /// buffers to be processed at the end of the next 387 /// frame advance. add_action_buffer(const action_buffer * a)388 void add_action_buffer(const action_buffer* a) 389 { 390 if (!_callingFrameActions) queueAction(*a); 391 else execute_action(*a); 392 } 393 394 395 /// \brief 396 /// Execute the given init action buffer, if not done yet 397 /// for the target DisplayObject id. 398 // 399 /// The action will normally be pushed on queue, but will 400 /// be executed immediately if we are executing actions 401 /// resulting from a callFame instead. 402 /// 403 /// @param a 404 /// The action buffer to execute 405 /// 406 /// @param cid 407 /// The referenced DisplayObject id 408 void execute_init_action_buffer(const action_buffer& a, int cid); 409 410 /// Execute a single action buffer (DOACTION block) 411 void execute_action(const action_buffer& ab); 412 to_movie()413 MovieClip* to_movie () { return this; } 414 415 /// The various methods for sending data in requests. 416 // 417 /// Used in loadMovie, getURL, loadVariables etc. 418 enum VariablesMethod 419 { 420 METHOD_NONE = 0, 421 METHOD_GET, 422 METHOD_POST 423 }; 424 425 // See dox in DisplayObject.h 426 virtual void getLoadedMovie(Movie* newMovie); 427 428 /// \brief 429 /// Load url-encoded variables from the given url, optionally 430 /// sending variables from this timeline too. 431 // 432 /// A LoadVariablesThread will be started to load and parse variables 433 /// and added to the _loadVariableRequests. Then, at every ::advance_sprite 434 /// any completed threads will be processed 435 /// (see processCompletedLoadVariableRequests) 436 /// 437 /// NOTE: the given url will be security-checked 438 /// 439 /// @param urlstr: The url to load variables from. 440 /// 441 /// @param sendVarsMethod: The VariablesMethod to use. If METHOD_NONE, 442 /// no data will be sent. 443 void loadVariables(const std::string& urlstr, 444 VariablesMethod sendVarsMethod); 445 446 /// Get TextField variables 447 // 448 /// TODO: this is unlikely to be the best way of doing it, and it would 449 /// simplify things if this function could be dropped. 450 bool getTextFieldVariables(const ObjectURI& uri, as_value& val); 451 452 // Set TextField variables 453 // 454 /// TODO: this is also unlikely to be the best way to do it. 455 bool setTextFieldVariables(const ObjectURI& uri, const as_value& val); 456 457 /// Search for a named object on the DisplayList 458 // 459 /// These are properties, but not attached as genuine members to the 460 /// MovieClip object. They take priority over DisplayObject magic 461 /// properties and inherited properties, but not over own properties. 462 // 463 /// @param name Object identifier. This function handles 464 /// case-sensitivity. 465 /// @return The object if found, otherwise 0. 466 DisplayObject* getDisplayListObject(const ObjectURI& uri); 467 468 /// Overridden to look in DisplayList for a match 469 as_object* pathElement(const ObjectURI& uri); 470 471 /// Execute the actions for the specified frame. 472 // 473 /// The frame_spec could be an integer or a string. 474 virtual void call_frame_actions(const as_value& frame_spec); 475 476 /// Duplicate this sprite in its timeline 477 // 478 /// Add the new DisplayObject at a the given depth to this sprite 479 /// parent displaylist. 480 /// 481 /// NOTE: the call will fail for the root movie (no parent). 482 /// NOTE2: any DisplayObject at the given target depth will be 483 /// replaced by the new DisplayObject 484 /// NOTE3: event handlers will also be copied 485 /// 486 /// @param newname 487 /// Name for the copy 488 /// 489 /// @param newdepth 490 /// Depth for the copy 491 /// 492 /// @param init_object 493 /// If not null, will be used to copy properties over. 494 MovieClip* duplicateMovieClip(const std::string& newname, 495 int newdepth, as_object* init_object = nullptr); 496 497 /// Called when a mouse event affects this MovieClip mouseEvent(const event_id & id)498 virtual void mouseEvent(const event_id& id) { 499 notifyEvent(id); 500 } 501 502 /// Dispatch event handler(s), if any. 503 // 504 /// This handles key, mouse, and specific MovieClip events. 505 /// TODO: split this sensibly. 506 void notifyEvent(const event_id& id); 507 508 // inherited from DisplayObject class, see dox in DisplayObject.h get_environment()509 virtual as_environment& get_environment() { 510 return _environment; 511 } 512 513 /// \brief 514 /// Set a TextField variable to this timeline 515 // 516 /// A TextField variable is a variable that acts 517 /// as a setter/getter for a TextField 'text' member. 518 void set_textfield_variable(const ObjectURI& name, TextField* ch); 519 520 void add_invalidated_bounds(InvalidatedRanges& ranges, bool force); 521 getDisplayList()522 const DisplayList& getDisplayList() const { 523 return _displayList; 524 } 525 526 /// Return the next highest available depth 527 // 528 /// Placing an object at the depth returned by 529 /// this function should result in a DisplayObject 530 /// that is displayd above all others getNextHighestDepth()531 int getNextHighestDepth() const { 532 return _displayList.getNextHighestDepth(); 533 } 534 535 /// Set the currently playing m_sound_stream_id 536 // 537 // TODO: rename to setStreamingSoundId 538 void setStreamSoundId(int id); 539 540 /// Remove this sprite from the stage. 541 // 542 /// This function is intended to be called by 543 /// effect of a removeMovieClip() ActionScript call 544 /// and implements the checks required for this specific 545 /// case. 546 /// 547 /// Callers are: 548 /// - The ActionRemoveClip tag handler. 549 /// - The global removeMovieClip(target) function. 550 /// - The MovieClip.removeMovieClip() method. 551 /// 552 /// The removal will not occur if the depth of this 553 /// DisplayObjects is not in the "dynamic" range [0..1048575] 554 /// as described at the following URL: 555 /// 556 /// http://www.senocular.com/flash/tutorials/depths/?page=2 557 /// 558 /// A testcases for this behaviour can be found in 559 /// 560 /// testsuite/misc-ming.all/displaylist_depths_test.swf 561 void removeMovieClip(); 562 563 /// Direct access to the Graphics object for drawing. graphics()564 DynamicShape& graphics() { 565 set_invalidated(); 566 return _drawable; 567 } 568 569 /// Set focus to this MovieClip 570 // 571 /// @return true if this MovieClip can receive focus. 572 virtual bool handleFocus(); 573 574 /// @} Drawing API 575 576 /// Set all variables in the given map with their corresponding values 577 DSOEXPORT void setVariables(const MovieVariables& vars); 578 579 /// Enumerate child DisplayObjects 580 // 581 /// See DisplayObject::enumerateNonProperties for more info. 582 virtual void visitNonProperties(KeyVisitor& v) const; 583 584 /// Delete DisplayObjects removed from the stage 585 /// from the display lists 586 void cleanupDisplayList(); 587 588 /// Queue the given action buffer 589 // 590 /// The action will be pushed on the current 591 /// global list (see movie_root). 592 /// 593 void queueAction(const action_buffer& buf); 594 595 /// Construct this instance as an ActionScript object 596 // 597 /// This method invokes the constructor associated with our 598 /// definition, either MovieClip or any user-speficied one 599 /// (see sprite_definition::registerClass). 600 /// It will also invoke the onClipConstruct and onConstruct handlers. 601 void constructAsScriptObject(); 602 603 /// Return true if getAsRoot() should return the *relative* root, 604 /// false otherwise. getLockRoot()605 bool getLockRoot() const { return _lockroot; } 606 607 /// Set whether getAsRoot() should return the *relative* root, 608 /// false otherwise. True for relative root. setLockRoot(bool lr)609 void setLockRoot(bool lr) { _lockroot=lr; } 610 611 /// Return the version of the SWF this MovieClip was parsed from. 612 virtual int getDefinitionVersion() const; 613 614 protected: 615 616 /// Unload all contents in the displaylist and this instance 617 // 618 /// Return true if there was an unloadHandler. 619 virtual bool unloadChildren(); 620 621 /// Mark sprite-specific reachable resources. 622 // 623 /// sprite-specific reachable resources are: 624 /// - DisplayList items (current, backup and frame0 ones) 625 /// - Canvas for dynamic drawing (_drawable) 626 /// - sprite environment 627 /// - definition the sprite has been instantiated from 628 /// - Textfields having an associated variable registered in this instance. 629 /// - Relative root of this instance (_swf) 630 /// 631 virtual void markOwnResources() const; 632 633 // Used by BitmapMovie. placeDisplayObject(DisplayObject * ch,int depth)634 void placeDisplayObject(DisplayObject* ch, int depth) { 635 _displayList.placeDisplayObject(ch, depth); 636 } 637 638 private: 639 640 /// Process any completed loadVariables request 641 void processCompletedLoadVariableRequests(); 642 643 /// Process a completed loadVariables request 644 void processCompletedLoadVariableRequest(LoadVariablesThread& request); 645 646 647 /// Execute the tags associated with the specified frame. 648 // 649 /// @param frame 650 /// Frame number. 0-based 651 /// 652 /// @param dlist 653 /// The display list to have control tags act upon. 654 /// 655 /// @param typeflags 656 /// Which kind of control tags we want to execute. 657 void executeFrameTags(size_t frame, DisplayList& dlist, 658 int typeflags = SWF::ControlTag::TAG_DLIST | 659 SWF::ControlTag::TAG_ACTION); 660 661 void stopStreamSound(); 662 663 /// Return value of the 'enabled' property cast to a boolean value. 664 // 665 /// This is true if not found (undefined to bool evaluates to false). 666 // 667 /// When a MovieClip is "disabled", its handlers of button-like events 668 /// are disabled, and automatic tab ordering won't include it. 669 bool isEnabled() const; 670 671 /// Check whether a point hits our drawable shape. 672 // 673 /// This is possible because the drawable does not have its own 674 /// transform, so we can use our own. The points are expressed in 675 /// world space. 676 bool hitTestDrawable(std::int32_t x, std::int32_t y) const; 677 678 /// Advance to a previous frame. 679 // 680 /// This function will basically restore the DisplayList as it supposedly 681 /// was *before* executing tags in target frame and then execute target 682 /// frame tags (both DLIST and ACTION ones). 683 /// 684 /// In practice, it will: 685 /// 686 /// - Remove from current DisplayList: 687 /// - Timeline instances constructed after target frame 688 /// - Timeline instances constructed before or at the target frame but no 689 /// more at the original depth 690 /// - Dynamic instances found in the static depth zone 691 /// - Execute all displaylist tags from first to one-before target frame, 692 /// appropriately setting _currentFrame as it goes, finally execute 693 /// both displaylist and action 694 /// tags for target frame. 695 /// 696 /// Callers of this methods are: 697 /// - goto_frame (for jump-backs) 698 /// - advance_sprite (for loop-back) 699 /// 700 /// See: 701 // http://www.gnashdev.org/wiki/index.php/TimelineControl 702 /// #Timeline_instances 703 /// 704 /// @param targetFrame 705 /// The target frame for which we're willing to restore the static 706 /// DisplayList. 707 /// 0-based. 708 // 709 /// POSTCONDITIONS: 710 /// 711 /// - _currentFrame == targetFrame 712 /// 713 /// TODO: consider using this same function for jump-forward too, 714 /// with some modifications... 715 /// 716 void restoreDisplayList(size_t targetFrame); 717 718 /// Increment _currentFrame, and take care of looping. 719 void increment_frame_and_check_for_loop(); 720 721 /// Unregister textfield variables bound to unloaded TextFields 722 void cleanup_textfield_variables(); 723 724 /// This is either sprite_definition (for sprites defined by 725 /// DefineSprite tag) or movie_def_impl (for the top-level movie). 726 const boost::intrusive_ptr<const movie_definition> _def; 727 728 /// List of loadVariables requests 729 typedef boost::ptr_list<LoadVariablesThread> LoadVariablesThreads; 730 731 /// List of active loadVariable requests 732 // 733 /// At ::advance_sprite time, all completed requests will 734 /// be processed (variables imported in this timeline scope) 735 /// and removed from the list. 736 LoadVariablesThreads _loadVariableRequests; 737 738 /// The SWF that this MovieClip belongs to. 739 Movie* _swf; 740 741 /// The canvas for dynamic drawing 742 DynamicShape _drawable; 743 744 PlayState _playState; 745 746 /// This timeline's variable scope 747 as_environment _environment; 748 749 /// We'll only allocate Textfield variables map if 750 /// we need them (ie: anyone calls set_textfield_variable) 751 /// 752 std::unique_ptr<TextFieldIndex> _text_variables; 753 754 std::string _droptarget; 755 756 // 0-based index to current frame 757 size_t _currentFrame; 758 759 /// soundid for current playing stream. If no stream set to -1 760 int m_sound_stream_id; 761 762 // true if this sprite reached the last frame and restarted 763 bool _hasLooped; 764 765 // true if orphaned tags (tags found after last advertised showframe) 766 // have been executed at least once. 767 bool _flushedOrphanedTags; 768 769 // true is we're calling frame actions 770 bool _callingFrameActions; 771 772 bool _lockroot; 773 774 bool _onLoadCalled; 775 }; 776 777 } // end of namespace gnash 778 779 #endif // GNASH_SPRITE_INSTANCE_H 780