1
// sprite_instance.h: Stateful live Sprite instance, for Gnash.
3
// Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5
// This program is free software; you can redistribute it and/or modify
6
// it under the terms of the GNU General Public License as published by
7
// the Free Software Foundation; either version 3 of the License, or
8
// (at your option) any later version.
10
// This program is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
// GNU General Public License for more details.
15
// You should have received a copy of the GNU General Public License
16
// along with this program; if not, write to the Free Software
17
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
// Stateful live Sprite instance
21
#ifndef GNASH_SPRITE_INSTANCE_H
22
#define GNASH_SPRITE_INSTANCE_H
25
#include "gnashconfig.h" // GNASH_USE_GC, USE_SWFTREE
28
#include "movie_definition.h" // for inlines
29
#include "DisplayList.h" // DisplayList
31
#include "as_environment.h" // for composition
32
#include "DynamicShape.h" // for composition
33
//#include "LoadVariablesThread.h" // for composition
35
#include "dsodefs.h" // for DSOEXPORT
46
// Forward declarations
51
class LoadVariablesThread;
52
class gradient_record;
53
class edit_text_character;
55
class PlaceObject2Tag;
62
/// Stateful Sprite object. Also known as a MovieClip.
64
/// Instance of this class are also known as "timelines".
65
/// This means that they define a variable scope (see
66
/// the as_environment member) and are divided into "frames"
68
class sprite_instance : public character
73
typedef std::list<const action_buffer*> ActionList;
75
// definition must match movie_definition::PlayList
76
typedef std::vector<ControlTag*> PlayList;
78
typedef std::vector<swf_event*> SWFEventsVector;
82
/// The "relative" _root of this sprite, which is the
83
/// instance of top-level sprite defined by the same
84
/// SWF that also contained *this* sprite definition.
85
/// Note that this can be *different* from the top-level
86
/// movie accessible trought the VM, in case this sprite
87
/// was defined in an externally loaded movie.
90
sprite_instance(movie_definition* def,
91
movie_instance* root, character* parent, int id);
93
virtual ~sprite_instance();
101
/// Type of execute tags
103
/// TODO: move to ControlTag.h ?
105
enum control_tag_type
114
// Overridden to use the m_root member
115
virtual movie_instance* get_root() const;
117
/// Return the _root ActionScript property of this sprite.
119
/// Relative or absolute is determined by
120
/// the _lockroot property, see getLockRoot
123
virtual const sprite_instance* getAsRoot() const;
126
/// Return the sprite_definition (or movie_definition)
127
/// from which this sprite_instance has been created
128
movie_definition* get_movie_definition() {
133
/// Return version of the SWF definition of this instance
134
/// as been parsed from.
136
int getSWFVersion() const
138
return m_def->get_version();
141
/// Get the composite bounds of all component drawing elements
142
rect getBounds() const;
144
// See dox in character.h
145
bool pointInShape(boost::int32_t x, boost::int32_t y) const;
147
// See dox in character.h
148
bool pointInVisibleShape(boost::int32_t x, boost::int32_t y) const;
150
/// return true if the given point is located in a(this) hitable sprite.
152
/// all sprites except mouse-insensitive dynamic masks are hitable.
153
/// _visible property is ignored for hitable characters.
155
bool pointInHitableShape(boost::int32_t x, boost::int32_t y) const;
157
/// Return 0-based index to current frame
158
size_t get_current_frame() const
160
return m_current_frame;
163
size_t get_frame_count() const
165
return m_def->get_frame_count();
168
/// Return number of completely loaded frames of this sprite/movie
170
/// Note: the number is also the last frame accessible (frames
171
/// numberes are 1-based)
173
size_t get_loaded_frames() const
175
return m_def->get_loading_frame();
178
/// Return total number of bytes in the movie
180
size_t get_bytes_total() const
182
return isDynamic() ? 0 : m_def->get_bytes_total();
185
/// Return number of loaded bytes in the movie
187
size_t get_bytes_loaded() const
189
return isDynamic() ? 0 : m_def->get_bytes_loaded();
192
const rect& get_frame_size() const
194
return m_def->get_frame_size();
197
/// Stop or play the sprite.
199
/// If stopped, any stream sound associated with this sprite
200
/// will also be stopped.
202
DSOEXPORT void set_play_state(play_state s);
204
play_state get_play_state() const { return m_play_state; }
206
character* get_character(int character_id);
208
// delegates to movie_root (possibly wrong)
209
virtual float get_background_alpha() const;
211
// delegates to movie_root
212
//virtual void get_mouse_state(int& x, int& y, int& buttons);
214
// delegates to movie_root (possibly wrong)
215
void set_background_color(const rgba& color);
217
//float get_timer() const;
222
bool has_looped() const
227
/// Return true if we have any mouse event handlers.
229
/// NOTE: this function currently does not consider
230
/// general mouse event handlers MOUSE_MOVE, MOUSE
231
virtual bool can_handle_mouse_event() const;
234
/// Return the topmost entity that the given point
235
/// covers that can receive mouse events. NULL if
236
/// none. Coords are in parent's frame.
237
virtual character* get_topmost_mouse_entity(boost::int32_t x, boost::int32_t y);
239
// see dox in character.h
240
const character* findDropTarget(boost::int32_t x, boost::int32_t y, character* dragging) const;
242
void setDropTarget(const std::string& tgt)
247
const std::string& getDropTarget() const
252
virtual bool wantsInstanceName() const
254
return true; // sprites can be referenced
257
virtual void advance();
259
void advance_sprite();
261
/// Set the sprite state at the specified frame number.
263
/// 0-based frame numbers!!
264
///(in contrast to ActionScript and Flash MX)
266
void goto_frame(size_t target_frame_number);
268
/// Parse frame spec and return a 0-based frame number.
270
/// If frame spec cannot be converted to !NAN and !Infinity number
271
/// it will be converted to a string and considered a
272
/// frame label (returns false if referring to an
275
/// @param frame_spec
276
/// The frame specification.
279
/// The evaluated frame number (0-based)
282
/// True if the frame_spec could be resolved to a frame number.
283
/// False if the frame_spec was invalid.
285
bool get_frame_number(const as_value& frame_spec, size_t& frameno) const;
287
/// MovieClip instances need to handle cxform specially
289
/// This is to suppor the Color asobject class
291
cxform get_world_cxform() const;
293
/// Update user-defined color transform
295
/// This should only be used by the Color AS class
297
void set_user_cxform(const cxform& cx)
303
/// Return the user-defined color transform
305
/// This should only be used by the Color AS class
307
cxform get_user_cxform() const
312
/// Look up the labeled frame, and jump to it.
313
bool goto_labeled_frame(const std::string& label);
316
/// Display (render?) this Sprite/MovieClip, unless invisible
321
/// Swap depth of the given characters in the DisplayList
323
/// See DisplayList::swapDepths for more info
325
void swapDepths(character* ch1, int newdepth)
327
m_display_list.swapDepths(ch1, newdepth);
330
/// Return the character at given depth in our DisplayList.
332
/// @return NULL if the specified depth is available (no chars there)
334
character* get_character_at_depth(int depth);
336
character* add_empty_movieclip(const char* name, int depth);
338
boost::intrusive_ptr<character> add_textfield(const std::string& name,
339
int depth, int x, int y, float width, float height);
341
/// Place a character or mask to the DisplayList.
343
/// This method instantiates the given character definition
344
/// and places it on the stage at the given depth.
346
/// If the specified depth is already occupied, it results a no-ops.
347
/// Otherwise, a new character will be created and onload handler will be triggerred.
350
/// A swf defined placement tag(PlaceObject, or PlaceObject2, or PlaceObject3)
351
/// No ownership transfer, the tag is still owned by the movie_definition class.
354
/// A pointer to the character being added or NULL
356
character* add_display_object(const SWF::PlaceObject2Tag* tag, DisplayList& dlist);
357
/// Proxy of DisplayList::move_character()
358
void move_display_object(const SWF::PlaceObject2Tag* tag, DisplayList& dlist);
359
/// Proxy of DisplayList::replace_character()
360
void replace_display_object(const SWF::PlaceObject2Tag* tag, DisplayList& dlist);
361
/// Proxy of DisplayList::remove_character()
362
void remove_display_object(const SWF::PlaceObject2Tag* tag, DisplayList& dlist);
363
/// Proxy of DisplayList::remove_character()
366
/// new character to be used for replacing.
369
/// depth at which the old character is to be replaced.
372
/// if true, the cxform of the new character will be set to the old one.
373
/// if false, the cxform of the new character will be untouched.
376
/// if true, the transformation matrix of the new character will be set to the old one.
377
/// if false, the transformation matrix of the new character will be untouched.
379
void replace_display_object(character* ch, int depth,
381
bool use_old_matrix);
385
/// Remove the object at the specified depth.
388
/// (1)the id parameter is currently unused, but
389
/// required to avoid breaking of inheritance from movie.h.
390
/// (2)the id might be used for specifying a character
391
/// in the depth(think about multiple characters within the same
392
/// depth, not tested and a rare case)
394
void remove_display_object(int depth, int /* id */)
397
m_display_list.remove_character(depth);
400
/// Attach the given character instance to current display list
403
/// The character instance to attach.
406
/// The depth to assign to the instance.
408
/// @return true on success, false on failure
409
/// FIXME: currently never returns false !
411
bool attachCharacter(character& newch, int depth);
413
/// Handle placement event
415
/// This callback will (not known to be a problem):
417
/// (1) Register ourselves with the global instance list
418
/// (2) Take note of our original target path
419
/// (3) Register as listener of core broadcasters
420
/// (4) Execute tags of frame 0
422
/// The callback will also (known to be bogus):
424
/// (1) Construct this instance as an ActionScript object.
425
/// See constructAsScriptObject() method.
427
virtual void stagePlacementCallback();
429
/// Unload all contents in the displaylist and this instance
430
/// See character::unload for more info
433
/// Mark this sprite as destroyed
435
/// This is an override of character::destroy()
437
/// A sprite should be destroyed when is removed from the display
438
/// list and is not more needed for names (target) resolutions.
439
/// Sprites are needed for names resolution whenever themselves
440
/// or a contained object has an onUnload event handler defined,
441
/// in which case we want the event handler to find the 'this'
442
/// variable w/out attempting to rebind it.
444
/// When a sprite is destroyed, all its children are also destroyed.
446
/// Note: this function will release most memory associated with
447
/// the sprite as no members or drawable should be needed anymore.
451
/// Add the given action buffer to the list of action
452
/// buffers to be processed at the end of the next
454
void add_action_buffer(const action_buffer* a)
456
if ( ! _callingFrameActions ) queueAction(*a);
457
else execute_action(*a);
462
/// Execute the given init action buffer, if not done yet
463
/// for the target character id.
465
/// The action will normally be pushed on queue, but will
466
/// be executed immediately if we are executing actions
467
/// resulting from a callFame instead.
470
/// The action buffer to execute
473
/// The referenced character id
475
void execute_init_action_buffer(const action_buffer& a, int cid);
477
/// Execute a single action buffer (DOACTION block)
478
void execute_action(const action_buffer& ab);
480
/// For debugging -- return the id of the character
481
/// at the specified depth.
482
/// Return -1 if nobody's home.
483
int get_id_at_depth(int depth);
485
sprite_instance* to_movie () { return this; }
487
/// Load a movie in this sprite, replacing it
490
/// The url to load the movie from. Can be a bitmap or an SWF.
493
/// IF not NULL, use as the POST body for HTTP requests
495
/// Return: true if it succeeded, false otherwise
497
bool loadMovie(const URL& url, const std::string* postdata=NULL);
500
/// Load url-encoded variables from the given url, optionally
501
/// sending variables from this timeline too.
504
/// A LoadVariablesThread will be started to load and parse variables
505
/// and added to the _loadVariableRequests. Then, at every ::advance_sprite
506
/// any completed threads will be processed
507
/// (see processCompletedLoadVariableRequests)
509
/// NOTE: the given url will be securit-checked
512
/// The url to load variables from. It is expected that
513
/// the caller already checked host security.
515
/// @param sendVarsMethod
516
/// If 0 (the default) no variables will be sent.
517
/// If 1, GET will be used.
518
/// If 2, POST will be used.
520
void loadVariables(URL url, short sendVarsMethod=0);
523
// ActionScript support
526
// See dox in as_object.h
527
bool get_member(string_table::key name, as_value* val,
528
string_table::key nsname = 0);
530
// See dox in as_object.h
531
virtual bool set_member(string_table::key name, const as_value& val,
532
string_table::key nsname = 0, bool ifFound=false);
534
/// Overridden to look in DisplayList for a match
535
as_object* get_path_element(string_table::key key);
537
/// Execute the actions for the specified frame.
539
/// The frame_spec could be an integer or a string.
541
virtual void call_frame_actions(const as_value& frame_spec);
543
// delegates to movie_root
544
virtual void stop_drag();
546
/// Duplicate this sprite in its timeline
548
/// Add the new character at a the given depth to this sprite
549
/// parent displaylist.
551
/// NOTE: the call will fail for the root movie (no parent).
552
/// NOTE2: any character at the given target depth will be
553
/// replaced by the new character
554
/// NOTE3: event handlers will also be copied
556
/// @param init_object
557
/// If not null, will be used to copy properties over.
559
boost::intrusive_ptr<sprite_instance> duplicateMovieClip(
560
const std::string& newname,
561
int newdepth, as_object* init_object=NULL);
563
/// Dispatch event handler(s), if any.
564
virtual bool on_event(const event_id& id);
566
// inherited from character class, see dox in character.h
567
as_environment& get_environment() {
568
return m_as_environment;
572
/// Set a TextField variable to this timeline
574
/// A TextField variable is a variable that acts
575
/// as a setter/getter for a TextField 'text' member.
577
void set_textfield_variable(const std::string& name,
578
edit_text_character* ch);
580
void add_invalidated_bounds(InvalidatedRanges& ranges, bool force);
582
void dump_character_tree(const std::string prefix) const;
585
const DisplayList& getDisplayList() const {
586
return m_display_list;
589
/// Return the next highest available depth
591
/// Placing an object at the depth returned by
592
/// this function should result in a character
593
/// that is displayd above all others
595
int getNextHighestDepth() const {
596
return m_display_list.getNextHighestDepth();
599
void testInvariant() const {
600
assert(m_play_state == PLAY || m_play_state == STOP);
602
// m_current_frame may be 0, since this is our initial
603
// condition. Still, frame count might be 0 as well, and
604
// loaded frames too !
605
//assert(m_current_frame < m_def->get_frame_count());
607
assert(get_ref_count() > 0); // or we're constructed but
608
// not stored in a boost::intrusive_ptr
612
/// Set the currently playing m_sound_stream_id
614
// TODO: rename to setStreamingSoundId
616
void setStreamSoundId(int id);
618
/// Remove this sprite from the stage.
620
/// This function is intended to be called by
621
/// effect of a removeMovieClip() ActionScript call
622
/// and implements the checks required for this specific
626
/// - The ActionRemoveClip tag handler.
627
/// - The global removeMovieClip(target) function.
628
/// - The MovieClip.removeMovieClip() method.
630
/// The removal will not occur if the depth of this
631
/// characters is not in the "dynamic" range [0..1048575]
632
/// as described at the following URL:
634
/// http://www.senocular.com/flash/tutorials/depths/?page=2
636
/// A testcases for this behaviour can be found in
638
/// testsuite/misc-ming.all/displaylist_depths_test.swf
640
void removeMovieClip();
644
void lineStyle(boost::uint16_t thickness, const rgba& color,
645
bool vScale=true, bool hScale=true,
646
bool pixelHinting=false,
648
cap_style_e startCapStyle=CAP_ROUND,
649
cap_style_e endCapStyle=CAP_ROUND,
650
join_style_e joinStyle=JOIN_ROUND,
651
float miterLimitFactor=1.0f)
653
_drawable->lineStyle(thickness, color, vScale, hScale,
654
pixelHinting, noClose,
655
startCapStyle, endCapStyle, joinStyle,
659
void resetLineStyle()
661
_drawable->resetLineStyle();
664
void beginFill(const rgba& color)
666
_drawable->beginFill(color);
669
void beginLinearGradientFill(const std::vector<gradient_record>& grad, const matrix& mat)
671
_drawable->beginLinearGradientFill(grad, mat);
674
void beginRadialGradientFill(const std::vector<gradient_record>& grad, const matrix& mat)
676
_drawable->beginRadialGradientFill(grad, mat);
681
_drawable->endFill();
684
void moveTo(boost::int32_t x, boost::int32_t y)
686
_drawable->moveTo(x, y);
689
void lineTo(boost::int32_t x, boost::int32_t y)
692
_drawable->lineTo(x, y, getSWFVersion());
695
void curveTo(boost::int32_t cx, boost::int32_t cy,
696
boost::int32_t ax, boost::int32_t ay)
699
_drawable->curveTo(cx, cy, ax, ay, getSWFVersion());
711
typedef std::map<std::string, std::string> VariableMap;
713
/// Set all variables in the given map with their corresponding values
714
DSOEXPORT void setVariables(VariableMap& vars);
716
/// Enumerate child characters
718
/// See as_object::enumerateNonProperties(as_environment&) for more info.
720
virtual void enumerateNonProperties(as_environment&) const;
722
/// Delete characters removed from the stage
723
/// from the display lists
724
void cleanupDisplayList();
726
/// Queue the given action buffer
728
/// The action will be pushed on the current
729
/// global list (see movie_root).
731
void queueAction(const action_buffer& buf);
733
/// Construct this instance as an ActionScript object
735
/// This method invokes the constructor associated with our
736
/// definition, either MovieClip or any user-speficied one
737
/// (see sprite_definition::registerClass).
738
/// It will also invoke the onClipConstruct and onConstruct handlers.
740
void constructAsScriptObject();
743
/// Return true if get_root() should return the *relative* root,
745
bool getLockRoot() const { return _lockroot; }
747
/// Set whether get_root() should return the *relative* root,
748
/// false otherwise. True for relative root.
750
void setLockRoot(bool lr) { _lockroot=lr; }
752
/// Getter-setter for MovieClip._lockroot
753
static as_value lockroot_getset(const fn_call& fn);
756
// Override to append display list info, see dox in character.h
757
virtual InfoTree::iterator getMovieInfo(InfoTree& tr, InfoTree::iterator it);
762
void stopStreamSound();
764
/// Register this sprite as a listener of core broadcasters
766
/// This is currently only used for key events broadcaster
767
/// and it's supposed to be called only once (or should we
768
/// also call it whenever onKey* user-defined function is defined ?
770
void registerAsListener();
773
/// Return value of the 'enabled' property, casted to a boolean value.
774
/// True if not found (undefined to bool evaluates to false).
776
/// When a MovieClip is "disabled", its handlers of button-like events
777
/// are disabled, and automatic tab ordering won't include it.
779
/// See event_id::is_button_event().
781
bool isEnabled() const;
783
// See dox in character.h
784
bool allowHandCursor() const;
787
sprite_instance(const sprite_instance&);
789
/// Forbid assignment
790
sprite_instance& operator=(const sprite_instance&);
792
/// Advance to a previous frame.
794
/// This function will basically restore the DisplayList as it supposedly
795
/// was *before* executing tags in target frame and then execute target
796
/// frame tags (both DLIST and ACTION ones).
798
/// In practice, it will:
800
/// - Remove from current DisplayList:
801
/// - Timeline instances constructed after target frame
802
/// - Timeline instances constructed before or at the target frame but no more at the original depth
803
/// - Dynamic instances found in the static depth zone
804
/// - Execute all displaylist tags from first to one-before target frame,
805
/// appropriately setting m_current_frame as it goes, finally execute both displaylist and action
806
/// tags for target frame.
808
/// Callers of this methods are:
809
/// - goto_frame (for jump-backs)
810
/// - advance_sprite (for loop-back)
812
/// See: http://www.gnashdev.org/wiki/index.php/TimelineControl#Timeline_instances
814
/// @param targetFrame
815
/// The target frame for which we're willing to restore the static DisplayList.
820
/// - m_current_frame == targetFrame
822
/// TODO: consider using this same function for jump-forward too,
823
/// with some modifications...
825
void restoreDisplayList(size_t targetFrame);
827
/// Queue actions in the action list
829
/// The list of action will be pushed on the current
830
/// global list (see movie_root).
832
void queueActions(ActionList& action_list);
834
/// Execute the actions in the action list
836
/// The list of action will be consumed starting from the first
837
/// element. When the function returns the list should be empty.
839
void execute_actions(ActionList& action_list);
841
// TODO: shouldn't we keep this by intrusive_ptr ?
842
movie_instance* m_root;
844
/// Current Display List contents.
845
DisplayList m_display_list;
847
/// The canvas for dynamic drawing
849
/// WARNING: since DynamicShape is a character_def, which is
850
/// in turn a ref_counted, we'd better keep
851
/// this by intrusive_ptr, even if we're the sole
852
/// owners. The problem is in case a pointer to this
853
/// instance ever gets passed to some function wrapping
854
/// it into an intrusive_ptr, in which case the stack
855
/// object will be destroyed, with horrible consequences ...
857
boost::intrusive_ptr<DynamicShape> _drawable;
859
/// The need of an instance here is due to the renderer
860
/// insising on availability a shape_character_def instance
861
/// that has a parent (why?)
863
boost::intrusive_ptr<character> _drawable_inst;
865
// this is deprecated, we'll be pushing gotoframe target
866
// actions to the global action queue
867
//ActionList m_goto_frame_action_list;
869
play_state m_play_state;
871
// 0-based index to current frame
872
size_t m_current_frame;
874
// true if this sprite reached the last frame and restarted
877
// true is we're calling frame actions
878
bool _callingFrameActions;
880
/// This timeline's variable scope
881
as_environment m_as_environment;
883
/// Increment m_current_frame, and take care of looping.
884
void increment_frame_and_check_for_loop();
886
typedef boost::intrusive_ptr< edit_text_character > TextFieldPtr;
887
typedef std::vector< TextFieldPtr > TextFieldPtrVect;
889
/// A container for textfields, indexed by their variable name
890
typedef std::map< std::string, TextFieldPtrVect > TextFieldMap;
892
/// We'll only allocate Textfield variables map if
893
/// we need them (ie: anyone calls set_textfield_variable)
895
std::auto_ptr<TextFieldMap> _text_variables;
898
/// Returns a vector of TextField associated with the given variable name,
899
/// or NULL if no such variable name is known.
901
/// A TextField variable is a variable that acts
902
/// as a setter/getter for a TextField 'text' member.
904
/// Search is case-sensitive.
906
/// @todo find out wheter we should be case sensitive or not
908
/// @return a pointer inside a vector, will be invalidated by modifications
909
/// of the vector (set_textfield_variable)
911
TextFieldPtrVect* get_textfield_variable(const std::string& name);
913
/// Unregister textfield variables bound to unloaded TextFields
914
void cleanup_textfield_variables();
916
/// soundid for current playing stream. If no stream set to -1
917
int m_sound_stream_id;
921
std::string _droptarget;
927
void place_character(character* ch, int depth)
929
m_display_list.place_character(ch, depth);
932
/// Execute the tags associated with the specified frame.
935
/// Frame number. 0-based
938
/// Which kind of control tags we want to execute.
939
/// See control_tag_type enum.
941
void execute_frame_tags(size_t frame, DisplayList& dlist, int typeflags=TAG_DLIST|TAG_ACTION);
944
/// This is either sprite_definition (for sprites defined by
945
/// DefineSprite tag) or movie_def_impl (for the top-level movie).
946
boost::intrusive_ptr<movie_definition> m_def;
948
/// List of loadVariables requests
949
typedef std::list<LoadVariablesThread*> LoadVariablesThreads;
951
/// List of active loadVariable requests
953
/// At ::advance_sprite time, all completed requests will
954
/// be processed (variables imported in this timeline scope)
955
/// and removed from the list.
956
LoadVariablesThreads _loadVariableRequests;
958
/// Process any completed loadVariables request
959
void processCompletedLoadVariableRequests();
961
/// Process a completed loadVariables request
962
void processCompletedLoadVariableRequest(LoadVariablesThread& request);
965
/// Mark sprite-specific reachable resources and invoke
966
/// the parent's class version (markCharacterReachable)
968
/// sprite-specific reachable resources are:
969
/// - DisplayList items (current, backup and frame0 ones)
970
/// - Canvas for dynamic drawing (_drawable)
971
/// - Drawable instance (_drawable_inst)
972
/// - sprite environment
973
/// - definition the sprite has been instantiated from
974
/// - Textfields having an associated variable registered in this instance.
975
/// - Relative root of this instance (m_root)
977
virtual void markReachableResources() const;
978
#endif // GNASH_USE_GC
981
/// Initialize the global MovieClip class
982
void movieclip_class_init(as_object& global);
985
} // end of namespace gnash
987
#endif // GNASH_SPRITE_INSTANCE_H