~ubuntu-branches/ubuntu/karmic/gnash/karmic

« back to all changes in this revision

Viewing changes to libcore/sprite_instance.h

  • Committer: Bazaar Package Importer
  • Author(s): Alexander Sack
  • Date: 2008-10-13 14:29:49 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20081013142949-f6qdvnu4mn05ltdc
Tags: 0.8.4~~bzr9980-0ubuntu1
* new upstream release 0.8.4 (LP: #240325)
* ship new lib usr/lib/gnash/libmozsdk.so.* in mozilla-plugin-gnash
  - update debian/mozilla-plugin-gnash.install
* ship new lib usr/lib/gnash/libgnashnet.so.* in gnash-common
  - update debian/gnash-common.install
* add basic debian/build_head script to build latest CVS head packages.
  - add debian/build_head
* new sound architecture requires build depend on libsdl1.2-dev
  - update debian/control
* head build script now has been completely migrated to bzr (upstream +
  ubuntu)
  - update debian/build_head
* disable kde gui until klash/qt4 has been fixed; keep kde packages as empty
  packages for now.
  - update debian/rules
  - debian/klash.install
  - debian/klash.links
  - debian/klash.manpages
  - debian/konqueror-plugin-gnash.install
* drop libkonq5-dev build dependency accordingly
  - update debian/control
* don't install headers manually anymore. gnash doesnt provide a -dev
  package after all
  - update debian/rules
* update libs installed in gnash-common; libgnashserver-*.so is not available
  anymore (removed); in turn we add the new libgnashcore-*.so
  - update debian/gnash-common.install
* use -Os for optimization and properly pass CXXFLAGS=$(CFLAGS) to configure
  - update debian/rules
* touch firefox .autoreg in postinst of mozilla plugin
  - update debian/mozilla-plugin-gnash.postinst
* link gnash in ubufox plugins directory for the plugin alternative switcher
  - add debian/mozilla-plugin-gnash.links
* suggest ubufox accordingly
  - update debian/control
* add new required build-depends on libgif-dev
  - update debian/control
* add Xb-Npp-Description and Xb-Npp-File as new plugin database meta data
  - update debian/control

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// sprite_instance.h:  Stateful live Sprite instance, for Gnash.
 
2
// 
 
3
//   Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
4
// 
 
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.
 
9
// 
 
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.
 
14
// 
 
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
 
18
 
 
19
// Stateful live Sprite instance
 
20
 
 
21
#ifndef GNASH_SPRITE_INSTANCE_H
 
22
#define GNASH_SPRITE_INSTANCE_H
 
23
 
 
24
#ifdef HAVE_CONFIG_H
 
25
#include "gnashconfig.h" // GNASH_USE_GC, USE_SWFTREE
 
26
#endif
 
27
 
 
28
#include "movie_definition.h" // for inlines
 
29
#include "DisplayList.h" // DisplayList 
 
30
#include "log.h"
 
31
#include "as_environment.h" // for composition
 
32
#include "DynamicShape.h" // for composition
 
33
//#include "LoadVariablesThread.h" // for composition
 
34
#include "Range2d.h"
 
35
#include "dsodefs.h" // for DSOEXPORT
 
36
 
 
37
#ifdef USE_SWFTREE
 
38
# include "tree.hh"
 
39
#endif
 
40
 
 
41
#include <vector>
 
42
#include <list>
 
43
#include <map>
 
44
#include <string>
 
45
 
 
46
// Forward declarations
 
47
namespace gnash {
 
48
    class movie_instance;
 
49
    class swf_event;
 
50
    class drag_state;
 
51
    class LoadVariablesThread;
 
52
    class gradient_record;
 
53
    class edit_text_character;
 
54
    namespace SWF{
 
55
        class PlaceObject2Tag;
 
56
    }
 
57
}
 
58
 
 
59
namespace gnash
 
60
{
 
61
 
 
62
/// Stateful Sprite object. Also known as a MovieClip.
 
63
//
 
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"
 
67
///
 
68
class sprite_instance : public character
 
69
{
 
70
 
 
71
public:
 
72
 
 
73
    typedef std::list<const action_buffer*> ActionList;
 
74
 
 
75
    // definition must match movie_definition::PlayList
 
76
    typedef std::vector<ControlTag*> PlayList;
 
77
 
 
78
    typedef std::vector<swf_event*> SWFEventsVector;
 
79
 
 
80
 
 
81
    /// @param root
 
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.
 
88
    ///
 
89
    ///
 
90
    sprite_instance(movie_definition* def,
 
91
        movie_instance* root, character* parent, int id);
 
92
 
 
93
    virtual ~sprite_instance();
 
94
 
 
95
    enum play_state
 
96
    {
 
97
        PLAY,
 
98
        STOP
 
99
    };
 
100
 
 
101
    /// Type of execute tags
 
102
    //
 
103
    /// TODO: move to ControlTag.h ?
 
104
    ///
 
105
    enum control_tag_type
 
106
    {
 
107
        /// Action tag
 
108
        TAG_ACTION = 1<<0,
 
109
 
 
110
        /// DisplayList tag
 
111
        TAG_DLIST  = 1<<1
 
112
    };
 
113
 
 
114
    // Overridden to use the m_root member
 
115
    virtual movie_instance* get_root() const;
 
116
 
 
117
    /// Return the _root ActionScript property of this sprite.
 
118
    //
 
119
    /// Relative or absolute is determined by
 
120
    /// the _lockroot property, see getLockRoot
 
121
    /// and setLockRoot.
 
122
    ///
 
123
    virtual const sprite_instance* getAsRoot() const;
 
124
 
 
125
    /// \brief
 
126
    /// Return the sprite_definition (or movie_definition)
 
127
    /// from which this sprite_instance has been created
 
128
        movie_definition* get_movie_definition() {
 
129
                return m_def.get();
 
130
        }
 
131
 
 
132
    /// \brief
 
133
    /// Return version of the SWF definition of this instance
 
134
    /// as been parsed from.
 
135
    //
 
136
    int getSWFVersion() const
 
137
    {
 
138
        return m_def->get_version();
 
139
    }
 
140
 
 
141
    /// Get the composite bounds of all component drawing elements
 
142
    rect getBounds() const;
 
143
 
 
144
    // See dox in character.h
 
145
    bool pointInShape(boost::int32_t x, boost::int32_t y) const;
 
146
 
 
147
    // See dox in character.h
 
148
    bool pointInVisibleShape(boost::int32_t x, boost::int32_t y) const;
 
149
 
 
150
    /// return true if the given point is located in a(this) hitable sprite.
 
151
    ///
 
152
    /// all sprites except mouse-insensitive dynamic masks are hitable.
 
153
    /// _visible property is ignored for hitable characters.
 
154
    ///
 
155
    bool pointInHitableShape(boost::int32_t x, boost::int32_t y) const;
 
156
 
 
157
    /// Return 0-based index to current frame
 
158
    size_t get_current_frame() const
 
159
    {
 
160
        return m_current_frame;
 
161
    }
 
162
 
 
163
    size_t get_frame_count() const
 
164
    {
 
165
        return m_def->get_frame_count();
 
166
    }
 
167
 
 
168
    /// Return number of completely loaded frames of this sprite/movie
 
169
    //
 
170
    /// Note: the number is also the last frame accessible (frames
 
171
    /// numberes are 1-based)
 
172
    ///
 
173
    size_t get_loaded_frames() const
 
174
    {
 
175
        return m_def->get_loading_frame();
 
176
    }
 
177
 
 
178
    /// Return total number of bytes in the movie
 
179
    /// (not sprite!)
 
180
    size_t get_bytes_total() const
 
181
    {
 
182
        return isDynamic() ? 0 : m_def->get_bytes_total();
 
183
    }
 
184
 
 
185
    /// Return number of loaded bytes in the movie
 
186
    /// (not sprite!)
 
187
    size_t get_bytes_loaded() const
 
188
    {
 
189
        return isDynamic() ? 0 : m_def->get_bytes_loaded();
 
190
    }
 
191
 
 
192
    const rect& get_frame_size() const
 
193
    {
 
194
        return m_def->get_frame_size();
 
195
    }
 
196
 
 
197
    /// Stop or play the sprite.
 
198
    //
 
199
    /// If stopped, any stream sound associated with this sprite
 
200
    /// will also be stopped.
 
201
    ///
 
202
    DSOEXPORT void set_play_state(play_state s);
 
203
 
 
204
    play_state get_play_state() const { return m_play_state; }
 
205
 
 
206
    character* get_character(int character_id);
 
207
 
 
208
    // delegates to movie_root (possibly wrong)
 
209
    virtual float get_background_alpha() const;
 
210
 
 
211
    // delegates to movie_root 
 
212
    //virtual void get_mouse_state(int& x, int& y, int& buttons);
 
213
 
 
214
    // delegates to movie_root (possibly wrong)
 
215
    void    set_background_color(const rgba& color);
 
216
 
 
217
    //float get_timer() const;
 
218
 
 
219
    void    restart();
 
220
 
 
221
 
 
222
    bool has_looped() const
 
223
    {
 
224
        return m_has_looped;
 
225
    }
 
226
 
 
227
    /// Return true if we have any mouse event handlers.
 
228
    //
 
229
    /// NOTE: this function currently does not consider
 
230
    ///       general mouse event handlers MOUSE_MOVE, MOUSE
 
231
    virtual bool can_handle_mouse_event() const;
 
232
 
 
233
    /// \brief
 
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);
 
238
 
 
239
    // see dox in character.h
 
240
    const character* findDropTarget(boost::int32_t x, boost::int32_t y, character* dragging) const;
 
241
 
 
242
    void setDropTarget(const std::string& tgt)
 
243
    {
 
244
        _droptarget = tgt;
 
245
    }
 
246
 
 
247
    const std::string& getDropTarget() const
 
248
    {
 
249
        return _droptarget;
 
250
    }
 
251
    
 
252
    virtual bool wantsInstanceName() const
 
253
    {
 
254
        return true; // sprites can be referenced 
 
255
    }
 
256
 
 
257
    virtual void    advance();
 
258
 
 
259
    void    advance_sprite();
 
260
 
 
261
    /// Set the sprite state at the specified frame number.
 
262
    //
 
263
    /// 0-based frame numbers!! 
 
264
    ///(in contrast to ActionScript and Flash MX)
 
265
    ///
 
266
    void    goto_frame(size_t target_frame_number);
 
267
 
 
268
    /// Parse frame spec and return a 0-based frame number.
 
269
    //
 
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
 
273
    /// unknwown label).
 
274
    ///
 
275
    /// @param frame_spec
 
276
    /// The frame specification.
 
277
    ///
 
278
    /// @param frameno
 
279
    /// The evaluated frame number (0-based)
 
280
    ///
 
281
    /// @return
 
282
    /// True if the frame_spec could be resolved to a frame number.
 
283
    /// False if the frame_spec was invalid.
 
284
    ///
 
285
    bool get_frame_number(const as_value& frame_spec, size_t& frameno) const;
 
286
 
 
287
    /// MovieClip instances need to handle cxform specially 
 
288
    //
 
289
    /// This is to suppor the Color asobject class
 
290
    ///
 
291
    cxform  get_world_cxform() const;
 
292
 
 
293
    /// Update user-defined color transform
 
294
    //
 
295
    /// This should only be used by the Color AS class
 
296
    ///
 
297
    void set_user_cxform(const cxform& cx)
 
298
    {
 
299
        set_invalidated();
 
300
        _userCxform = cx;
 
301
    }
 
302
 
 
303
    /// Return the user-defined color transform
 
304
    //
 
305
    /// This should only be used by the Color AS class
 
306
    ///
 
307
    cxform  get_user_cxform() const
 
308
    {
 
309
        return _userCxform;
 
310
    }
 
311
 
 
312
    /// Look up the labeled frame, and jump to it.
 
313
    bool goto_labeled_frame(const std::string& label);
 
314
 
 
315
        
 
316
    /// Display (render?) this Sprite/MovieClip, unless invisible
 
317
    void    display();
 
318
    
 
319
    void omit_display();
 
320
 
 
321
    /// Swap depth of the given characters in the DisplayList
 
322
    //
 
323
    /// See DisplayList::swapDepths for more info
 
324
    ///
 
325
    void swapDepths(character* ch1, int newdepth)
 
326
    {
 
327
        m_display_list.swapDepths(ch1, newdepth);
 
328
    }
 
329
 
 
330
    /// Return the character at given depth in our DisplayList.
 
331
    //
 
332
    /// @return NULL if the specified depth is available (no chars there)
 
333
    ///
 
334
    character* get_character_at_depth(int depth);
 
335
 
 
336
    character* add_empty_movieclip(const char* name, int depth);
 
337
 
 
338
    boost::intrusive_ptr<character> add_textfield(const std::string& name,
 
339
            int depth, int x, int y, float width, float height);
 
340
 
 
341
    /// Place a character or mask to the DisplayList.
 
342
    //
 
343
    /// This method instantiates the given character definition
 
344
    /// and places it on the stage at the given depth.
 
345
    ///
 
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.
 
348
    ///
 
349
    /// @param tag
 
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.
 
352
    ///
 
353
    /// @return
 
354
    ///     A pointer to the character being added or NULL
 
355
    ///
 
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()
 
364
    ///
 
365
    /// @param ch
 
366
    /// new character to be used for replacing.
 
367
    ///
 
368
    /// @param depth
 
369
    /// depth at which the old character is to be replaced.
 
370
    ///
 
371
    /// @use_old_cxform
 
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.
 
374
    ///
 
375
    /// @use_old_matrix
 
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.
 
378
    ///
 
379
    void replace_display_object(character* ch,  int depth,
 
380
        bool use_old_cxform,
 
381
        bool use_old_matrix);
 
382
 
 
383
 
 
384
    /// \brief
 
385
    /// Remove the object at the specified depth.
 
386
    //
 
387
    /// NOTE: 
 
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)
 
393
    ///
 
394
    void    remove_display_object(int depth, int /* id */)
 
395
    {
 
396
        set_invalidated();
 
397
        m_display_list.remove_character(depth);
 
398
    }
 
399
 
 
400
    /// Attach the given character instance to current display list
 
401
    //
 
402
    /// @param newch
 
403
    /// The character instance to attach.
 
404
    ///
 
405
    /// @param depth
 
406
    /// The depth to assign to the instance.
 
407
    ///
 
408
    /// @return true on success, false on failure
 
409
    /// FIXME: currently never returns false !
 
410
    ///
 
411
    bool attachCharacter(character& newch, int depth);
 
412
 
 
413
    /// Handle placement event
 
414
    //
 
415
    /// This callback will (not known to be a problem):
 
416
    ///
 
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
 
421
    ///
 
422
    /// The callback will also (known to be bogus):
 
423
    //
 
424
    /// (1) Construct this instance as an ActionScript object.
 
425
    ///     See constructAsScriptObject() method.
 
426
    ///
 
427
    virtual void stagePlacementCallback();
 
428
 
 
429
    /// Unload all contents in the displaylist and this instance
 
430
    /// See character::unload for more info
 
431
    bool unload();
 
432
 
 
433
    /// Mark this sprite as destroyed
 
434
    //
 
435
    /// This is an override of character::destroy()
 
436
    ///
 
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.
 
443
    ///
 
444
    /// When a sprite is destroyed, all its children are also destroyed.
 
445
    /// 
 
446
    /// Note: this function will release most memory associated with
 
447
    /// the sprite as no members or drawable should be needed anymore.
 
448
    ///
 
449
    void destroy();
 
450
        
 
451
    /// Add the given action buffer to the list of action
 
452
    /// buffers to be processed at the end of the next
 
453
    /// frame advance.
 
454
    void    add_action_buffer(const action_buffer* a)
 
455
    {
 
456
        if ( ! _callingFrameActions ) queueAction(*a);
 
457
        else execute_action(*a);
 
458
    }
 
459
 
 
460
    
 
461
    /// \brief
 
462
    /// Execute the given init action buffer, if not done yet
 
463
    /// for the target character id.
 
464
    //
 
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.
 
468
    ///
 
469
    /// @param a
 
470
    /// The action buffer to execute
 
471
    ///
 
472
    /// @param cid
 
473
    /// The referenced character id
 
474
    ///
 
475
    void execute_init_action_buffer(const action_buffer& a, int cid);
 
476
 
 
477
    /// Execute a single action buffer (DOACTION block)
 
478
    void execute_action(const action_buffer& ab);
 
479
 
 
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);
 
484
 
 
485
    sprite_instance* to_movie () { return this; }
 
486
 
 
487
    /// Load a movie in this sprite, replacing it
 
488
    //
 
489
    /// @param url
 
490
    ///  The url to load the movie from. Can be a bitmap or an SWF.
 
491
    ///
 
492
    /// @param postdata
 
493
    ///  IF not NULL, use as the POST body for HTTP requests
 
494
    ///
 
495
    /// Return: true if it succeeded, false otherwise
 
496
    ///
 
497
    bool loadMovie(const URL& url, const std::string* postdata=NULL);
 
498
 
 
499
    /// \brief
 
500
    /// Load url-encoded variables from the given url, optionally
 
501
    /// sending variables from this timeline too.
 
502
    //
 
503
    ///
 
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)
 
508
    ///
 
509
    /// NOTE: the given url will be securit-checked
 
510
    ///
 
511
    /// @param url
 
512
    /// The url to load variables from. It is expected that
 
513
    /// the caller already checked host security.
 
514
    ///
 
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.
 
519
    ///
 
520
    void loadVariables(URL url, short sendVarsMethod=0);
 
521
 
 
522
    //
 
523
    // ActionScript support
 
524
    //
 
525
 
 
526
    // See dox in as_object.h
 
527
    bool get_member(string_table::key name, as_value* val, 
 
528
        string_table::key nsname = 0);
 
529
        
 
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);
 
533
 
 
534
    /// Overridden to look in DisplayList for a match
 
535
    as_object* get_path_element(string_table::key key);
 
536
 
 
537
    /// Execute the actions for the specified frame. 
 
538
    //
 
539
    /// The frame_spec could be an integer or a string.
 
540
    ///
 
541
    virtual void call_frame_actions(const as_value& frame_spec);
 
542
 
 
543
    // delegates to movie_root 
 
544
    virtual void stop_drag();
 
545
 
 
546
    /// Duplicate this sprite in its timeline
 
547
    //
 
548
    /// Add the new character at a the given depth to this sprite
 
549
    /// parent displaylist.
 
550
    ///
 
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
 
555
    ///
 
556
    /// @param init_object
 
557
    /// If not null, will be used to copy properties over.
 
558
    ///
 
559
    boost::intrusive_ptr<sprite_instance> duplicateMovieClip(
 
560
        const std::string& newname,
 
561
        int newdepth, as_object* init_object=NULL);
 
562
        
 
563
    /// Dispatch event handler(s), if any.
 
564
    virtual bool on_event(const event_id& id);
 
565
 
 
566
    // inherited from character class, see dox in character.h
 
567
    as_environment& get_environment() {
 
568
        return m_as_environment;
 
569
    }
 
570
 
 
571
    /// \brief
 
572
    /// Set a TextField variable to this timeline
 
573
    //
 
574
    /// A TextField variable is a variable that acts
 
575
    /// as a setter/getter for a TextField 'text' member.
 
576
    ///
 
577
    void set_textfield_variable(const std::string& name,
 
578
            edit_text_character* ch);
 
579
 
 
580
    void add_invalidated_bounds(InvalidatedRanges& ranges, bool force);
 
581
    
 
582
    void dump_character_tree(const std::string prefix) const;
 
583
            
 
584
 
 
585
    const DisplayList& getDisplayList() const {
 
586
            return m_display_list;
 
587
    }
 
588
 
 
589
    /// Return the next highest available depth
 
590
    //
 
591
    /// Placing an object at the depth returned by
 
592
    /// this function should result in a character
 
593
    /// that is displayd above all others
 
594
    ///
 
595
    int getNextHighestDepth() const {
 
596
        return m_display_list.getNextHighestDepth();
 
597
    }
 
598
 
 
599
    void testInvariant() const {
 
600
        assert(m_play_state == PLAY || m_play_state == STOP);
 
601
 
 
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());
 
606
#ifndef GNASH_USE_GC 
 
607
        assert(get_ref_count() > 0); // or we're constructed but
 
608
                                     // not stored in a boost::intrusive_ptr
 
609
#endif
 
610
    }
 
611
 
 
612
    /// Set the currently playing m_sound_stream_id
 
613
    // 
 
614
    // TODO: rename to setStreamingSoundId
 
615
    //
 
616
    void setStreamSoundId(int id);
 
617
 
 
618
    /// Remove this sprite from the stage.
 
619
    //
 
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
 
623
    /// case.
 
624
    ///
 
625
    /// Callers are:
 
626
    /// - The ActionRemoveClip tag handler.
 
627
    /// - The global removeMovieClip(target) function.
 
628
    /// - The MovieClip.removeMovieClip() method.
 
629
    ///
 
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:
 
633
    /// 
 
634
    /// http://www.senocular.com/flash/tutorials/depths/?page=2
 
635
    ///
 
636
    /// A testcases for this behaviour can be found in 
 
637
    ///
 
638
    /// testsuite/misc-ming.all/displaylist_depths_test.swf
 
639
    ///
 
640
    void removeMovieClip();
 
641
 
 
642
    /// @{ Drawing API
 
643
    
 
644
    void lineStyle(boost::uint16_t thickness, const rgba& color,
 
645
        bool vScale=true, bool hScale=true,
 
646
        bool pixelHinting=false,
 
647
        bool noClose=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)
 
652
    {
 
653
        _drawable->lineStyle(thickness, color, vScale, hScale,
 
654
            pixelHinting, noClose,
 
655
            startCapStyle, endCapStyle, joinStyle,
 
656
            miterLimitFactor);
 
657
    }
 
658
 
 
659
    void resetLineStyle()
 
660
    {
 
661
        _drawable->resetLineStyle();
 
662
    }
 
663
 
 
664
    void beginFill(const rgba& color)
 
665
    {
 
666
        _drawable->beginFill(color);
 
667
    }
 
668
 
 
669
    void beginLinearGradientFill(const std::vector<gradient_record>& grad, const matrix& mat)
 
670
    {
 
671
        _drawable->beginLinearGradientFill(grad, mat);
 
672
    }
 
673
 
 
674
    void beginRadialGradientFill(const std::vector<gradient_record>& grad, const matrix& mat)
 
675
    {
 
676
        _drawable->beginRadialGradientFill(grad, mat);
 
677
    }
 
678
 
 
679
    void endFill()
 
680
    {
 
681
        _drawable->endFill();
 
682
    }
 
683
 
 
684
    void moveTo(boost::int32_t x, boost::int32_t y)
 
685
    {
 
686
        _drawable->moveTo(x, y);
 
687
    }
 
688
 
 
689
    void lineTo(boost::int32_t x, boost::int32_t y)
 
690
    {
 
691
        set_invalidated();
 
692
        _drawable->lineTo(x, y, getSWFVersion());
 
693
    }
 
694
 
 
695
    void curveTo(boost::int32_t cx, boost::int32_t cy, 
 
696
                 boost::int32_t ax, boost::int32_t ay)
 
697
    {
 
698
        set_invalidated();
 
699
        _drawable->curveTo(cx, cy, ax, ay, getSWFVersion());
 
700
    }
 
701
 
 
702
    void clear()
 
703
    {
 
704
        set_invalidated();
 
705
        _drawable->clear();
 
706
    }
 
707
 
 
708
    /// @} Drawing API
 
709
    
 
710
 
 
711
    typedef std::map<std::string, std::string> VariableMap;
 
712
 
 
713
    /// Set all variables in the given map with their corresponding values
 
714
    DSOEXPORT void setVariables(VariableMap& vars);
 
715
 
 
716
    /// Enumerate child characters
 
717
    //
 
718
    /// See as_object::enumerateNonProperties(as_environment&) for more info.
 
719
    ///
 
720
    virtual void enumerateNonProperties(as_environment&) const;
 
721
 
 
722
    /// Delete characters removed from the stage
 
723
    /// from the display lists
 
724
    void cleanupDisplayList();
 
725
 
 
726
        /// Queue the given action buffer
 
727
        //
 
728
        /// The action will be pushed on the current
 
729
        /// global list (see movie_root).
 
730
        ///
 
731
        void queueAction(const action_buffer& buf);
 
732
 
 
733
    /// Construct this instance as an ActionScript object
 
734
    //
 
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.
 
739
    ///
 
740
    void constructAsScriptObject();
 
741
 
 
742
 
 
743
    /// Return true if get_root() should return the *relative* root,
 
744
    /// false otherwise.
 
745
    bool getLockRoot() const { return _lockroot; }
 
746
 
 
747
    /// Set whether get_root() should return the *relative* root,
 
748
    /// false otherwise. True for relative root.
 
749
    ///
 
750
    void setLockRoot(bool lr) { _lockroot=lr; }
 
751
 
 
752
    /// Getter-setter for MovieClip._lockroot
 
753
    static as_value lockroot_getset(const fn_call& fn);
 
754
 
 
755
#ifdef USE_SWFTREE
 
756
    // Override to append display list info, see dox in character.h
 
757
    virtual InfoTree::iterator getMovieInfo(InfoTree& tr, InfoTree::iterator it);
 
758
#endif
 
759
 
 
760
private:
 
761
 
 
762
    void stopStreamSound();
 
763
 
 
764
    /// Register this sprite as a listener of core broadcasters
 
765
    //
 
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 ?
 
769
    ///
 
770
    void registerAsListener();
 
771
 
 
772
    /// \brief
 
773
    /// Return value of the 'enabled' property, casted to a boolean value.
 
774
    /// True if not found (undefined to bool evaluates to false).
 
775
    //
 
776
    /// When a MovieClip is "disabled", its handlers of button-like events 
 
777
    /// are disabled, and automatic tab ordering won't include it.
 
778
    ///
 
779
    /// See event_id::is_button_event().
 
780
    ///
 
781
    bool isEnabled() const;
 
782
 
 
783
    // See dox in character.h
 
784
    bool allowHandCursor() const;
 
785
 
 
786
    /// Forbid copy
 
787
    sprite_instance(const sprite_instance&);
 
788
 
 
789
    /// Forbid assignment
 
790
    sprite_instance& operator=(const sprite_instance&);
 
791
 
 
792
    /// Advance to a previous frame.
 
793
    //
 
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).
 
797
    ///
 
798
    /// In practice, it will:
 
799
    ///
 
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.
 
807
    ///
 
808
    /// Callers of this methods are:
 
809
    /// - goto_frame (for jump-backs)
 
810
    /// - advance_sprite (for loop-back)
 
811
    ///
 
812
    /// See: http://www.gnashdev.org/wiki/index.php/TimelineControl#Timeline_instances
 
813
    ///
 
814
    /// @param targetFrame
 
815
    /// The target frame for which we're willing to restore the static DisplayList.
 
816
    /// 0-based.
 
817
    //
 
818
    /// POSTCONDITIONS:
 
819
    ///
 
820
    /// - m_current_frame == targetFrame
 
821
    ///
 
822
    /// TODO: consider using this same function for jump-forward too,
 
823
    ///       with some modifications...
 
824
    ///
 
825
    void restoreDisplayList(size_t targetFrame);
 
826
 
 
827
    /// Queue actions in the action list
 
828
    //
 
829
    /// The list of action will be pushed on the current
 
830
    /// global list (see movie_root).
 
831
    ///
 
832
    void queueActions(ActionList& action_list);
 
833
 
 
834
    /// Execute the actions in the action list
 
835
    //
 
836
    /// The list of action will be consumed starting from the first
 
837
    /// element. When the function returns the list should be empty.
 
838
    ///
 
839
    void execute_actions(ActionList& action_list);
 
840
 
 
841
    // TODO: shouldn't we keep this by intrusive_ptr ?
 
842
    movie_instance* m_root;
 
843
 
 
844
    /// Current Display List contents.
 
845
    DisplayList m_display_list;
 
846
 
 
847
    /// The canvas for dynamic drawing
 
848
    //
 
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 ...
 
856
    ///
 
857
    boost::intrusive_ptr<DynamicShape> _drawable;
 
858
 
 
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?)
 
862
    ///
 
863
    boost::intrusive_ptr<character> _drawable_inst;
 
864
 
 
865
    // this is deprecated, we'll be pushing gotoframe target
 
866
    // actions to the global action queue
 
867
    //ActionList    m_goto_frame_action_list;
 
868
 
 
869
    play_state  m_play_state;
 
870
 
 
871
    // 0-based index to current frame
 
872
    size_t      m_current_frame;
 
873
 
 
874
    // true if this sprite reached the last frame and restarted
 
875
    bool        m_has_looped;
 
876
 
 
877
    // true is we're calling frame actions
 
878
    bool _callingFrameActions;
 
879
 
 
880
    /// This timeline's variable scope
 
881
    as_environment  m_as_environment;
 
882
 
 
883
    /// Increment m_current_frame, and take care of looping.
 
884
    void increment_frame_and_check_for_loop();
 
885
 
 
886
    typedef boost::intrusive_ptr< edit_text_character > TextFieldPtr;
 
887
    typedef std::vector< TextFieldPtr > TextFieldPtrVect;
 
888
 
 
889
    /// A container for textfields, indexed by their variable name
 
890
    typedef std::map< std::string, TextFieldPtrVect > TextFieldMap;
 
891
 
 
892
    /// We'll only allocate Textfield variables map if
 
893
    /// we need them (ie: anyone calls set_textfield_variable)
 
894
    ///
 
895
    std::auto_ptr<TextFieldMap> _text_variables;
 
896
 
 
897
    /// \brief
 
898
    /// Returns a vector of TextField associated with the given variable name,
 
899
    /// or NULL if no such variable name is known.
 
900
    //
 
901
    /// A TextField variable is a variable that acts
 
902
    /// as a setter/getter for a TextField 'text' member.
 
903
    ///
 
904
    /// Search is case-sensitive.
 
905
    ///
 
906
    /// @todo find out wheter we should be case sensitive or not
 
907
    ///
 
908
    /// @return a pointer inside a vector, will be invalidated by modifications
 
909
    ///         of the vector (set_textfield_variable)
 
910
    ///
 
911
    TextFieldPtrVect* get_textfield_variable(const std::string& name);
 
912
 
 
913
    /// Unregister textfield variables bound to unloaded TextFields
 
914
    void cleanup_textfield_variables();
 
915
 
 
916
    /// soundid for current playing stream. If no stream set to -1
 
917
    int m_sound_stream_id;
 
918
 
 
919
    cxform _userCxform;
 
920
 
 
921
    std::string _droptarget;
 
922
 
 
923
    bool _lockroot;
 
924
 
 
925
protected:
 
926
 
 
927
    void place_character(character* ch, int depth)  
 
928
    {       
 
929
        m_display_list.place_character(ch, depth);  
 
930
    }
 
931
 
 
932
    /// Execute the tags associated with the specified frame.
 
933
    ///
 
934
    /// @param frame
 
935
    /// Frame number. 0-based
 
936
    ///
 
937
    /// @param typeflags
 
938
    ///     Which kind of control tags we want to execute. 
 
939
    /// See control_tag_type enum.
 
940
    ///
 
941
    void execute_frame_tags(size_t frame, DisplayList& dlist, int typeflags=TAG_DLIST|TAG_ACTION);
 
942
 
 
943
    /// \brief
 
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;
 
947
 
 
948
    /// List of loadVariables requests
 
949
    typedef std::list<LoadVariablesThread*> LoadVariablesThreads;
 
950
 
 
951
    /// List of active loadVariable requests 
 
952
    //
 
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;
 
957
 
 
958
    /// Process any completed loadVariables request
 
959
    void processCompletedLoadVariableRequests();
 
960
 
 
961
    /// Process a completed loadVariables request
 
962
    void processCompletedLoadVariableRequest(LoadVariablesThread& request);
 
963
 
 
964
#ifdef GNASH_USE_GC
 
965
    /// Mark sprite-specific reachable resources and invoke
 
966
    /// the parent's class version (markCharacterReachable)
 
967
    //
 
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)
 
976
    ///
 
977
    virtual void markReachableResources() const;
 
978
#endif // GNASH_USE_GC
 
979
};
 
980
 
 
981
/// Initialize the global MovieClip class
 
982
void movieclip_class_init(as_object& global);
 
983
 
 
984
 
 
985
} // end of namespace gnash
 
986
 
 
987
#endif // GNASH_SPRITE_INSTANCE_H