Update with current status
[gnash.git] / libcore / DisplayObject.h
blob624948f64d2dd917a7a4795d28799657423eefb1
1 //
2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
3 // 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
20 #ifndef GNASH_DISPLAY_OBJECT_H
21 #define GNASH_DISPLAY_OBJECT_H
23 #ifdef HAVE_CONFIG_H
24 #include "gnashconfig.h" // USE_SWFTREE
25 #endif
27 #include <vector>
28 #include <map>
29 #include <string>
30 #include <cassert>
31 #include <cstdint> // For C99 int types
32 #include <boost/noncopyable.hpp>
33 #include <boost/logic/tribool.hpp>
35 #include "ObjectURI.h"
36 #include "GC.h"
37 #include "Transform.h"
38 #include "event_id.h"
39 #include "SWFRect.h"
40 #include "SWFMatrix.h"
41 #include "SWFCxForm.h"
42 #include "dsodefs.h"
43 #include "snappingrange.h"
44 #ifdef USE_SWFTREE
45 # include "tree.hh"
46 #endif
49 //#define DEBUG_SET_INVALIDATED 1
51 // Forward declarations
52 namespace gnash {
53 class MovieClip;
54 class movie_root;
55 class fn_call;
56 class Movie;
57 class ExecutableCode;
58 class action_buffer;
59 class movie_definition;
60 class StaticText;
61 class InteractiveObject;
62 class Renderer;
63 class as_object;
64 class as_value;
65 class as_environment;
66 class DisplayObject;
67 class KeyVisitor;
68 namespace SWF {
69 class TextRecord;
73 namespace gnash {
75 /// Returns true if the DisplayObject is referenceable in ActionScript
77 /// A DisplayObject is referenceable if it has an associated object.
78 bool isReferenceable(const DisplayObject& d);
80 /// Set special properties
82 /// This sets the magic properties of DisplayObjects.
84 /// @param key The string table key of the property to set.
85 /// @param obj The DisplayObject whose property should be set
86 /// @param val An as_value representing the new value of the property.
87 /// Some values may be rejected.
88 bool setDisplayObjectProperty(DisplayObject& obj, const ObjectURI& uri,
89 const as_value& val);
91 /// Get special properties
93 /// This gets the magic properties of DisplayObjects and handles special
94 /// MovieClip properties such as DisplayList members.
96 /// @param key The uri of the property to get.
97 /// @param obj The DisplayObject whose property should be got
98 /// @param val An as_value to be set to the value of the property.
99 bool getDisplayObjectProperty(DisplayObject& obj, const ObjectURI& uri,
100 as_value& val);
102 /// Get a property by its numeric index.
104 /// Used by ASHandlers to get the DisplayObject properties indexed by number
106 /// @param index The index of the property to get.
107 /// @param o The DisplayObject whose property should be got
108 /// @param val An as_value to be set to the value of the property.
109 void getIndexedProperty(size_t index, DisplayObject& o, as_value& val);
111 /// Set a property by its numeric index.
113 /// Used by ASHandlers to set the DisplayObject properties indexed by number
115 /// @param index The index of the property to set.
116 /// @param o The DisplayObject whose property should be set
117 /// @param val An as_value representing the new value of the property.
118 /// Some values may be rejected.
119 void setIndexedProperty(size_t index, DisplayObject& o, const as_value& val);
121 /// Copy SWFMatrix and caches from given DisplayObjecta
123 /// @param from The DisplayObject to copy from
124 /// @param to The DisplayObject to copy to.
125 void copyMatrix(const DisplayObject& from, DisplayObject& to);
127 /// Get concatenated SWFMatrix (all ancestor transforms and our SWFMatrix)
129 /// Maps from our local space into "world" space
130 /// (i.e. root movie space).
132 /// @param includeRoot Whether the transform of the Stage (_root)
133 /// should be concatenated. This is required to be
134 /// false for pointInBounds.
135 SWFMatrix getWorldMatrix(const DisplayObject& d, bool includeRoot = true);
137 /// Get concatenated color transform of a DisplayObject
139 /// Maps from our local space into normal color space.
140 SWFCxForm getWorldCxForm(const DisplayObject& d);
142 /// DisplayObject is the base class for all DisplayList objects.
144 /// It represents a single active element in a movie. This class does not
145 /// supply any interactivity. The hierarchy of DisplayObjects in a movie
146 /// provides all visual elements in a SWF. The DisplayObject hierarchy
147 /// is independent of ActionScript resources, but can be controlled via AS.
149 /// DisplayObjects that can be controlled through ActionScript have an
150 /// associated as_object. DisplayObjects such as Shape, do not have an
151 /// associated object and cannot be referenced in AS.
153 /// Derived classes include InteractiveObject, StaticText, Bitmap,
154 /// Video, and Shape.
156 /// All DisplayObjects may be constructed during SWF parsing. In this case
157 /// they are constructed using an immutable, non-copyable SWF::DefinitionTag.
158 /// This tag should never be changed!
160 /// Most DisplayObjects may also be constructed dynamically. In AS3, Bitmaps
161 /// and Shapes can be dynamically created. Dynamically-created DisplayObjects
162 /// must not have a SWF::DefinitionTag!
164 /// The presence of a definition tag may be used to distinguish static from
165 /// dynamic DisplayObjects, but tags are not always stored. They are not
166 /// stored in most InteractiveObjects because most properties can be
167 /// overridden during SWF execution.
168 class DSOTEXPORT DisplayObject : public GcResource, boost::noncopyable
170 public:
172 /// Construct a DisplayObject
174 /// @param mr The movie_root containing the DisplayObject hierarchy.
175 /// All DisplayObjects may need movie_root resources.
176 /// @param object An object to be associated with this DisplayObject.
177 /// If this is non-null, the DisplayObject will be
178 /// referenceable in ActionScript. Referenceable
179 /// DisplayObjects may access AS resources through their
180 /// associated object.
181 /// @param parent The parent of the new DisplayObject. This may be null.
182 DisplayObject(movie_root& mr, as_object* object, DisplayObject* parent);
184 virtual ~DisplayObject() {}
186 /// The lowest placeable and accessible depth for a DisplayObject.
187 /// Macromedia Flash help says: depth starts at -16383 (0x3FFF)
189 /// See: http://www.senocular.com/flash/tutorials/depths/?page=2
191 /// See also http://www.kirupa.com/developer/actionscript/depths2.htm
193 /// The only way to exceed these bounds is with createEmptyMoveClip(),
194 /// which can be placed at any depth within +/- 2**31.
195 static const int lowerAccessibleBound = -16384;
197 /// This is the maximum depth a MovieClip DisplayObject can be placed
198 /// at (attachMovie). Kirupa (see above) says 2130690045, but this
199 /// seems not to be included in the range.
200 static const int upperAccessibleBound = 2130690044;
202 /// This is the amount added to displaylist tag defined depths.
203 /// DisplayObjects placed by tags (vs. DisplayObjects instantiated by
204 /// ActionScript) always have negative depths by effect of this offset.
205 static const int staticDepthOffset = lowerAccessibleBound;
207 /// This is the offset at which DisplayObject's depth is
208 /// shifted when a DisplayObject is removed from stage but
209 /// an onUnload event handler is defined.
211 /// Example: a DisplayObject at depth 60 gets moved to
212 /// depth -32829 (-32769-60) when unloaded and
213 /// an onUnload event handler is defined for it
214 /// or any of its childs.
216 /// So, to recap:
217 /// 1: -32769 to -16385 are removed
218 /// 2: -16384 to 0 are statics
219 /// 3: Max depth for a PlaceObject call is 16384 (which becomes
220 /// 0 in the statics)
221 /// (all of the above correct?)
222 static const int removedDepthOffset = -32769;
224 /// This value is used for m_clip_depth when
225 /// the DisplayObject is not a layer mask.
227 /// Depths below -16384 are illegal, so this
228 /// value should not collide with real depths.
230 static const int noClipDepthValue = -1000000;
232 /// Return a reference to the variable scope of this DisplayObject.
233 virtual as_environment& get_environment() {
234 // MovieClip must override this
235 // and any other DisplayObject will have
236 // a parent!
237 assert(_parent != nullptr);
238 return _parent->get_environment();
241 /// Enumerate any non-proper properties
243 /// This function allows enumeration of properties that are
244 /// derived from the DisplayObject type, e.g. DisplayList members.
246 /// The default implementation adds nothing
247 virtual void visitNonProperties(KeyVisitor&) const {}
249 /// \brief
250 /// Return the parent of this DisplayObject, or NULL if
251 /// the DisplayObject has no parent.
252 DisplayObject* parent() const
254 return _parent;
257 /// Set the parent of this DisplayObject
259 /// In AS3, DisplayObjects may be created before being attached to
260 /// a parent. In AS2, this is only used for external movies
261 void set_parent(DisplayObject* parent)
263 _parent = parent;
266 virtual MovieClip* to_movie() { return nullptr; }
268 int get_depth() const { return _depth; }
270 void set_depth(int d) { _depth = d; }
272 /// Get sound volume for this DisplayObject
273 int getVolume() const { return _volume; }
275 /// Set sound volume for this DisplayObject
276 void setVolume(int vol) { _volume = vol; }
278 /// Get concatenated sound volume for this DisplayObject
280 /// NOTE: the concatenated volume does NOT include
281 /// global volume settings, which is the one
282 /// controlled by Sound instances created passing
283 /// null, undefined or no argument to constructor.
285 int getWorldVolume() const;
287 /// DisplayObjects can return the version of the SWF they were parsed from.
288 virtual int getDefinitionVersion() const {
289 return -1;
292 const Transform& transform() const {
293 return _transform;
297 /// Set local transform SWFMatrix for this DisplayObject
299 /// @param m the new SWFMatrix to assign to this DisplayObject
301 /// @param updateCache if true, updates the cache values
302 /// from the SWFMatrix (only if SWFMatrix != current SWFMatrix)
304 void setMatrix(const SWFMatrix& m, bool updateCache = false);
306 /// Set the xscale value of current SWFMatrix
308 /// This is used when setting _xscale.
309 /// See xscale_getset.
311 /// @param factor scale factor, in percent
313 void set_x_scale(double factor);
315 /// Set the yscale value of current SWFMatrix
317 /// This is used when setting _yscale
318 /// See yscale_getset.
320 /// @param factor scale factor, in percent
322 void set_y_scale(double factor);
324 /// Set the rotation value of current SWFMatrix
327 /// This is used when setting _rotation
328 /// See rotation_getset
330 /// @param rot rotation in degrees. will be trimmed to
331 /// the -180 .. 180 range, can be passed outside it.
333 void set_rotation(double rot);
335 /// Set the width of this DisplayObject, modifying its SWFMatrix
337 /// This is used when setting _width
339 /// @param w new width, in TWIPS.
341 /// TextField does this differently (caches not updated).
342 virtual void setWidth(double width);
344 /// Set the height of this DisplayObject, modifying its SWFMatrix
346 /// This is used when setting _height
348 /// @param h new height, in TWIPS.
350 virtual void setHeight(double height);
352 void setCxForm(const SWFCxForm& cx)
354 if (_transform.colorTransform != cx) {
355 set_invalidated();
356 _transform.colorTransform = cx;
360 std::uint16_t get_ratio() const { return _ratio; }
362 void set_ratio(std::uint16_t r) {
363 if (r != _ratio) set_invalidated();
364 _ratio = r;
367 /// Returns the clipping depth (if any) of this DisplayObject.
368 /// The parameter tells us to use the DisplayObject as a mask for
369 /// all the objects contained in the display list from _depth
370 /// to m_clipping_depth inclusive.
371 ///
372 /// The value returned by get_clip_depth() is only valid when isMaskLayer()
373 /// returns true!
374 ///
375 int get_clip_depth() const { return m_clip_depth; }
377 /// See get_clip_depth()
378 void set_clip_depth(int d)
380 m_clip_depth = d;
383 /// Returns true when the DisplayObject (and its childs) is used as a mask
384 /// for other DisplayObjects at higher depth (up to get_clip_depth).
385 /// isMaskLayer() does not return true when one of its
386 /// parents is a mask and the DisplayObject itself is not.
388 /// See also isDynamicMask() and isMask()
389 ///
390 bool isMaskLayer() const
392 return (m_clip_depth != noClipDepthValue && !_maskee);
395 /// Returns true when the DisplayObject (and its childs) is used as a mask
396 /// for another DisplayObject.
397 /// isDynamicMask() does not return true when one of its
398 /// parents is a mask and the DisplayObject itself is not.
400 /// NOTE: there's no way to obtain the maskee from a dynamic mask
402 /// See also isMaskLayer() and isMask()
403 ///
404 bool isDynamicMask() const
406 return (_maskee);
409 /// Return the DisplayObject masking this instance (if any)
410 DisplayObject* getMask() const
412 #if GNASH_PARANOIA_LEVEL > 1
413 if (_mask) assert(_mask->_maskee == this);
414 #endif
415 return _mask;
418 /// Register a DisplayObject as a mask for this instance.
420 /// @param mask The DisplayObject to use as a mask, possibly NULL.
421 /// A reference to us will be registered with the mask, if
422 /// not null, so it'll know it's a mask for us, and would stop
423 /// being a mask for anything else.
425 void setMask(DisplayObject* mask);
427 /// Set DisplayObject name, initializing the original target member
428 void set_name(const ObjectURI& uri) {
429 _name = uri;
432 const ObjectURI& get_name() const { return _name; }
434 /// Get the built-in function handlers code for the given event
436 /// NOTE: this function is only for getting statically-defined
437 /// event handlers, which are the ones attached to a DisplayObject
438 /// with a PlaceObject2. It's the DisplayObject's responsibility
439 /// to properly fetch any user-defined event handler, which
440 /// are the ones attached to a DisplayObject with ActionScript code.
442 std::unique_ptr<ExecutableCode> get_event_handler(const event_id& id) const;
444 /// Set a built-in function handler for the given event
446 /// Mark the DisplayObject as having mouse or Key event
447 /// handlers if this is the case.
449 /// NOTE: this function is only for registering statically-defined
450 /// event handlers, which are the ones attached to a DisplayObject
451 /// with a PlaceObject2. It's the DisplayObject's responsibility
452 /// to properly invoke any user-defined event handler, which
453 /// are the ones attached to a DisplayObject with ActionScript code.
455 /// @param id
456 /// The event triggering the handler.
458 /// @param code
459 /// An action buffer to execute when given event is triggered.
460 /// The buffer is externally owned (not copied), make sure it
461 /// is kept alive for the whole lifetime of this DisplayObject.
463 void add_event_handler(const event_id& id, const action_buffer& code);
465 /// Render the DisplayObject.
467 /// All DisplayObjects must have a display() function.
468 virtual void display(Renderer& renderer, const Transform& xform) = 0;
470 /// Search for StaticText objects
472 /// If this is a StaticText object and contains SWF::TextRecords, these
473 /// are written to the passed parameter.
474 /// @ return 0 if this object is not a StaticText or contains no text.
475 virtual StaticText* getStaticText(std::vector<const SWF::TextRecord*>&,
476 size_t&) {
477 return nullptr;
480 virtual SWFRect getBounds() const = 0;
482 /// Return true if the given point falls in this DisplayObject's bounds
484 /// @param x Point x coordinate in world space
485 /// @param y Point y coordinate in world space
486 /// @return Whether (x, y) is within the DisplayObject's bounds.
487 /// This ignores _root's transform.
488 bool pointInBounds(std::int32_t x, std::int32_t y) const
490 SWFRect bounds = getBounds();
491 const SWFMatrix wm = getWorldMatrix(*this, false);
492 wm.transform(bounds);
493 return bounds.point_test(x, y);
496 /// Return true if the given point falls in this DisplayObject's shape
498 /// @param x Point x coordinate in world space
499 /// @param y Point y coordinate in world space
500 /// @return Whether (x, y) is within the DisplayObject's bounds.
501 virtual bool pointInShape(std::int32_t x, std::int32_t y) const = 0;
503 /// true if the given point falls in this DisplayObject's visible shape
505 /// Point coordinates are in world TWIPS
507 /// The default implementation returns false if the DisplayObject is
508 /// not visible, calling pointInShape() otherwise.
510 /// Note that this is good for simple DisplayObjects but needs
511 /// to be overridden for DisplayObjects with childs. When a
512 /// DisplayObject has childs it must take into account the case
513 /// in which some childs are visible and some are not.
515 virtual bool pointInVisibleShape(std::int32_t x, std::int32_t y) const
517 if (!visible()) return false;
518 if (isDynamicMask() || isMaskLayer()) return false;
519 return pointInShape(x, y);
522 /// Return the relative root of this DisplayObject
524 /// The "relative" is the Movie created by
525 /// the same SWF definition that contained the
526 /// definition of this DisplayObject.
528 /// The default implementation is to invoke get_root
529 /// against this DisplayObject's parent.
531 virtual Movie* get_root() const {
532 return parent()->get_root();
535 /// Return the _root ActionScript property of this DisplayObject.
537 /// By default calls get_root(). The resulting MovieClip may be passed
538 /// to actionscript methods, so it is not const. As the override in
539 /// MovieClip may return this, the method cannot be const either.
540 virtual MovieClip* getAsRoot();
542 /// Find the object which is one degree removed from us,
543 /// given the relative pathname.
545 /// If the pathname is "..", then return our parent.
546 /// If the pathname is ".", then return ourself. If
547 /// the pathname is "_level0" or "_root", then return
548 /// the root movie.
550 /// Otherwise, the name should refer to one our our
551 /// named DisplayObjects, so we return it.
553 /// NOTE: In ActionScript 2.0, top level names (like
554 /// "_root" and "_level0") are CASE SENSITIVE.
555 /// Character names in a display list are CASE
556 /// SENSITIVE. Member names are CASE INSENSITIVE. Gah.
558 /// In ActionScript 1.0, everything seems to be CASE
559 /// INSENSITIVE.
561 virtual as_object* pathElement(const ObjectURI& uri);
563 /// \brief
564 /// Return true if PlaceObjects tag are allowed to move
565 /// this DisplayObject.
567 /// Once a DisplayObject has been transformed by ActionScript,
568 /// further transformation trought non-action SWF constrol tags
569 /// is not allowed.
571 /// See scriptTransformed()
573 bool get_accept_anim_moves() const
575 return ! _scriptTransformed && ! _dynamicallyCreated;
578 /// Was this DisplayObject dynamically created ?
580 /// "Dynamically created" means created trough ActionScript.
582 /// NOTE, With current code:
583 /// - Characters created by means of a loadMovie are
584 /// NOT set as dynamic (should check if they should)
585 /// - Characters created by attachMovie ARE dynamic
586 /// - Characters created by duplicateMovieClip ARE dynamic
587 /// - Characters created by createEmptyMovieClip ARE dynamic
588 /// - Characters created by new Video ARE dynamic
589 /// - Characters created by createTextField ARE dynamic
592 bool isDynamic() const {
593 return _dynamicallyCreated;
596 /// Mark this DisplayObject as dynamically created
597 void setDynamic() {
598 _dynamicallyCreated = true;
601 /// \brief
602 /// Call this function when the sprite has been
603 /// transformed due to ActionScript code.
605 /// This information will be used while executing
606 /// PlaceObject tags in that ActionScript-transformed
607 /// DisplayObjects won't be allowed to be moved.
609 /// TODO: make protected
611 void transformedByScript()
613 _scriptTransformed = true;
616 /// Set whether this DisplayObject should be rendered
618 /// TODO: handle all visible getter/setters in DisplayObject, not in
619 /// subclasses, and drop this / make it private.
620 void set_visible(bool visible);
622 // Return true if this DisplayObject should be rendered
623 bool visible() const { return _visible; }
625 /// Return true if an handler for the given event is defined
627 /// NOTE that we look for both clip-defined and user-defined
628 /// handlers, which is likely error prone since we're doing
629 /// this in a non-virtual function. Main use for this method
630 /// is for being called by ::unload() to verify an Unload handler
631 /// is available.
632 bool hasEventHandler(const event_id& id) const;
634 /// DisplayObjects are not a mouse entity by default.
636 /// Override this function for InteractiveObjects.
637 virtual InteractiveObject* topmostMouseEntity(std::int32_t,
638 std::int32_t) {
639 return nullptr;
642 /// Find highest depth DisplayObject whose shape contains the given
643 /// point and is not the DisplayObject being dragged or any of its childs.
645 /// Point coordinates in global twips.
646 virtual const DisplayObject* findDropTarget(std::int32_t x,
647 std::int32_t y, DisplayObject* dragging) const
649 if (this != dragging && visible() && pointInVisibleShape(x, y)) {
650 return this;
653 return nullptr;
656 /// Return whether this DisplayObject has been invalidated or not
657 bool invalidated() const {
658 return _invalidated;
661 /// Return whether this DisplayObject has and invalidated child or not
662 bool childInvalidated() const {
663 return _child_invalidated;
666 /// Notify a change in the DisplayObject's appearance.
667 virtual void update() {
668 set_invalidated();
671 /// \brief
672 /// This function marks the DisplayObject as being modified in aspect
673 /// and keeps track of current invalidated bounds the first time
674 /// it's called after each call to clear_invalidated().
676 /// Call this function *before* any change in this DisplayObject
677 /// that modifies its rendering. This information will be used
678 /// to detect visual changes that need to be redrawn.
680 /// It is *important* to call this function *before* the change
681 /// rather then after as it will also take care of updating the
682 /// previously invalidated bounds (m_old_invalidated_bounds)
684 /// Calling this function multiple time is a no-op, unless
685 /// clear_invalidated() is called in between.
687 /// NOTE: Marking a DisplayObject as invalidated automatically marks
688 /// its parent as being invalidated.
690 /// @see \ref region_update
692 void set_invalidated();
693 void set_invalidated(const char* debug_file, int debug_line);
696 /// Calls set_invalidated() and extends old_invalidated_ranges to the
697 /// given value so that also this area gets re-rendered (used when
698 /// replacing DisplayObjects).
699 void extend_invalidated_bounds(const InvalidatedRanges& ranges);
702 /// Called by a child to signalize it has changed visibily. The
703 /// difference to set_invalidated() is that *this* DisplayObject does
704 /// not need to redraw itself completely. This function will
705 /// recursively inform all its parents of the change.
706 void set_child_invalidated();
708 /// Clear invalidated flag and reset m_old_invalidated_bounds to null.
710 /// It is very important that each DisplayObject with any m_XXXX_invalidated
711 /// flag set calls clear_invalidated() during the rendering of one frame.
712 /// Basically this means each call to display() must match a call to
713 /// clear_invalidated. This includes no-op display() calls, i.e. when the
714 /// DisplayObject is outside of the screen. The DisplayList must still call
715 /// clear_invalidated() even if display() is not necessary.
717 /// Not doing so will result in a stale invalidated flag which in turn will
718 /// prevent the parent to be informed when this DisplayObject (or a
719 /// child) is invalidated again (see set_invalidated() recursion).
720 void clear_invalidated() {
721 _invalidated = false;
722 _child_invalidated = false;
723 m_old_invalidated_ranges.setNull();
726 /// \brief
727 /// Add the DisplayObject's invalidated bounds *to* the given ranges list.
729 /// NOTE that this method should include the bounds that it
730 /// covered the last time clear_invalidated() was called,
731 /// as those need to be rerendered as well (to clear the region
732 /// previously occupied by this DisplayObject).
734 /// That's why it returns the *union* of old_invalidated_ranges and
735 /// the current bounds. The function is also used internally by
736 /// set_invalidated() to update m_old_invalidated_ranges itself (you may
737 /// notice some kind of circular reference), but that's no problem since
738 /// old_invalidated_ranges is NULL during that call.
740 /// It is used to determine what area needs to be re-rendered.
741 /// The coordinates are world coordinates (in TWIPS).
742 /// Only instances with _invalidated flag set are checked unless
743 /// force is set.
745 virtual void add_invalidated_bounds(InvalidatedRanges& ranges, bool force);
747 /// Called instead of display() when the DisplayObject is not visible
748 /// on stage.
749 /// Used to clear the invalidated flags.
750 virtual void omit_display() { clear_invalidated(); };
752 /// Callback invoked whenever a DisplayObject is placed on stage
754 /// This function must be called when the DisplayObject is placed on
755 /// stage for the first time.
757 /// The DisplayObject version of this call sets the original target
758 /// of the DisplayObject, for soft references to work.
759 /// If you override the method remember to call saveOriginalTarget()
760 /// as the first thing.
762 /// This handles all ActionScript construction and initialization events.
763 virtual void construct(as_object* /*init*/ = nullptr)
765 saveOriginalTarget();
768 /// Unload this instance from the stage.
770 /// This function must be called when the DisplayObject is removed
771 /// from the stage.
772 /// It will take care of properly calling
773 /// unload against any child DisplayObjects and queuing the
774 /// 'UNLOAD' event handler.
776 /// @return true if any onUnload event handler was defined
777 /// by either this or any child DisplayObjects, false
778 /// otherwise.
779 bool unload();
781 /// Accept a loaded Movie
782 virtual void getLoadedMovie(Movie* newMovie);
784 /// Return true if this DisplayObject was unloaded from the stage
785 bool unloaded() const {
786 return _unloaded;
789 /// Mark this DisplayObject as destroyed
791 /// A DisplayObject should be destroyed when is removed from the display
792 /// list and is not more needed for names (target) resolutions.
793 /// Sprites are needed for names resolution whenever themselves
794 /// or a contained object has an onUnload event handler defined,
795 /// in which case we want the event handler to find the 'this'
796 /// variable w/out attempting to rebind it.
798 /// Note: this function can safely release most memory associated
799 /// with the DisplayObject as it will not be needed anymore.
801 virtual void destroy();
803 /// Return true if this DisplayObject was destroyed.
805 /// See destroy() for more info.
807 bool isDestroyed() const { return _destroyed; }
809 /// Returns true when the DisplayObject bounds intersect with the current
810 /// rendering clipping area.
812 /// There is no need to do any rendering for this DisplayObject when this
813 /// function returns false because the renderer will not change any pixels
814 /// in the area where this DisplayObject is placed.
815 bool boundsInClippingArea(Renderer& renderer) const;
817 /// Return full path to this object, in slash notation
819 /// e.g. "/sprite1/sprite2/ourSprite"
821 std::string getTargetPath() const;
823 /// Return original target path to this object, in dot notation
824 /// as of at construction time.
826 /// This is needed to properly dereference dangling soft-references
827 /// See testcase misc-swfc.all/soft_reference_test1.sc
829 const std::string& getOrigTarget() const
831 return _origTarget;
834 /// Return full path to this object, in dot notation
836 /// e.g. "_level0.sprite1.sprite2.ourSprite"
838 std::string DSOEXPORT getTarget() const;
840 /// Return true if this DisplayObject is a selectable TextField
842 /// This method is used by Gui to set up an appropriate cursor
843 /// for input textfields.
845 virtual bool isSelectableTextField() const { return false; }
847 /// \brief
848 /// Return true if this DisplayObject allows turning the cursor
849 /// into an hand shape when it happens to be the one receiving
850 /// mouse events.
851 bool DSOEXPORT allowHandCursor() const;
853 #ifdef USE_SWFTREE
854 typedef tree<std::pair<std::string, std::string> > InfoTree;
855 /// Append DisplayObject info in the tree
857 /// @param tr
858 /// The tree to append movie to
860 /// @param it
861 /// The iterator to append info to.
863 /// @return iterator the appended subtree
864 virtual InfoTree::iterator getMovieInfo(InfoTree& tr,
865 InfoTree::iterator it);
866 #endif
868 /// Used to assign a name to unnamed instances
869 ObjectURI getNextUnnamedInstanceName();
871 enum BlendMode
873 BLENDMODE_UNDEFINED = 0,
874 BLENDMODE_NORMAL = 1,
875 BLENDMODE_LAYER,
876 BLENDMODE_MULTIPLY,
877 BLENDMODE_SCREEN,
878 BLENDMODE_LIGHTEN,
879 BLENDMODE_DARKEN,
880 BLENDMODE_DIFFERENCE,
881 BLENDMODE_ADD,
882 BLENDMODE_SUBTRACT,
883 BLENDMODE_INVERT,
884 BLENDMODE_ALPHA,
885 BLENDMODE_ERASE,
886 BLENDMODE_OVERLAY,
887 BLENDMODE_HARDLIGHT = 14
890 BlendMode getBlendMode() const {
891 return _blendMode;
894 void setBlendMode(BlendMode bm) {
895 _blendMode = bm;
898 // action_buffer is externally owned
899 typedef std::vector<const action_buffer*> BufferList;
900 typedef std::map<event_id, BufferList> Events;
902 /// Set the current focus to this DisplayObject.
904 /// @return false if the DisplayObject cannot receive focus, true if it can
905 /// (and does).
907 /// Button, Textfield and MovieClip can receive focus. In SWF6 and above,
908 /// MovieClip can only receive focus if the focusEnabled property
909 /// evaluates to true.
910 virtual bool handleFocus() {
911 return false;
914 /// Some DisplayObjects require actions on losing focus.
916 /// Default is a no-op. TextField implements this function.
917 virtual void killFocus() {}
919 double rotation() const {
920 return _rotation;
923 double scaleX() const {
924 return _xscale;
927 double scaleY() const {
928 return _yscale;
931 as_object* object() const {
932 return _object;
935 /// Getter-setter for blendMode.
936 static as_value blendMode(const fn_call& fn);
938 /// Mark all reachable resources.
940 /// Try not to override this function in derived classes. This always
941 /// marks the base class's resources and calls markOwnResources() to
942 /// take care of any further GC resources.
943 virtual void markReachableResources() const;
945 /// Called by markReachableResources()
947 /// DisplayObjects should mark their own resources in this function.
948 virtual void markOwnResources() const {}
950 boost::tribool focusRect() const {
951 return _focusRect;
954 void focusRect(boost::tribool focus) {
955 _focusRect = focus;
958 protected:
960 /// Render a dynamic mask for a specified DisplayObject
962 /// Dynamic masks are rendered out-of-turn when the object they are masking
963 /// is drawn.
965 /// A MaskRenderer object should be constructed at the beginning of
966 /// relevant display() functions; it then takes care of rendering the
967 /// mask with the appropriate transform and cleaning up afterwards.
968 class MaskRenderer
970 public:
971 MaskRenderer(Renderer& r, const DisplayObject& o);
972 ~MaskRenderer();
973 private:
974 Renderer& _renderer;
975 DisplayObject* _mask;
978 virtual bool unloadChildren() { return false; }
980 /// Get the movie_root to which this DisplayObject belongs.
981 movie_root& stage() const {
982 return _stage;
985 /// Register currently computable target as
986 /// the "original" one. This will be used by
987 /// soft references (as_value) and should be
988 /// called as soon as the stagePlacementCallback
989 /// is invoked.
991 void saveOriginalTarget()
993 _origTarget=getTarget();
996 const Events& get_event_handlers() const
998 return _event_handlers;
1001 void set_event_handlers(const Events& copyfrom);
1003 /// Name of this DisplayObject (if any)
1004 ObjectURI _name;
1006 DisplayObject* _parent;
1008 /// look for '.', 'this', '..', '_parent', '_level0' and '_root'
1010 /// NOTE: case insensitive up to SWF6, sensitive from SWF7 up
1012 as_object* getPathElementSeparator(string_table::key key);
1014 /// \brief
1015 /// Bounds of this DisplayObject instance before first invalidation
1016 /// since last call to clear_invalidated().
1018 /// This stores the bounds of the DisplayObject before it has been
1019 /// changed, ie. the position when set_invalidated() is being called.
1020 /// While drawing, both the old and the new bounds are updated (rendered).
1021 /// When moving a DisplayObject A to B then both the position A needs
1022 /// to be re-rendered (to reveal the backgrond) and the position B
1023 /// needs to be re-rendered (to show the DisplayObject in its new
1024 /// position). The bounds may be identical or overlap, but
1025 /// SnappingRanges takes care of that.
1026 ///
1027 /// Will be set by set_invalidated() and used by
1028 /// get_invalidated_bounds().
1029 InvalidatedRanges m_old_invalidated_ranges;
1031 private:
1033 /// Register a DisplayObject masked by this instance
1034 void setMaskee(DisplayObject* maskee);
1036 /// The as_object to which this DisplayObject is attached.
1037 as_object* _object;
1039 /// The movie_root to which this DisplayObject belongs.
1040 movie_root& _stage;
1042 Transform _transform;
1044 Events _event_handlers;
1046 /// Cache values for ActionScript access.
1047 /// NOTE: not all DisplayObjects need this, just the
1048 /// ones which are ActionScript-referenceable
1049 double _xscale, _yscale, _rotation;
1051 /// The depth of this DisplayObject.
1052 std::int32_t _depth;
1054 boost::tribool _focusRect;
1056 /// Volume control associated to this DisplayObject
1058 /// This is used by Sound objects
1060 /// NOTE: probably only ActionScript-referenceable DisplayObjects
1061 /// need this (assuming soft ref don't rebind to other
1062 /// kind of DisplayObjects).
1064 int _volume;
1066 std::uint16_t _ratio;
1067 int m_clip_depth;
1069 /// The DisplayObject masking this instance (if any)
1070 DisplayObject* _mask;
1072 /// The DisplayObject masked by this instance (if any)
1073 DisplayObject* _maskee;
1075 /// Original target, as at construction time
1076 std::string _origTarget;
1078 BlendMode _blendMode;
1080 bool _visible;
1082 /// Whether this DisplayObject has been transformed by ActionScript code
1084 /// Once we've been moved by ActionScript,
1085 /// Don't accept moves from anim tags (PlaceObject)
1087 /// See get_accept_anim_moves() function
1089 bool _scriptTransformed;
1091 bool _dynamicallyCreated;
1093 /// Set to yes when this instance has been unloaded
1094 bool _unloaded;
1096 /// This flag should be set to true by a call to destroy()
1097 bool _destroyed;
1099 /// \brief
1100 /// Set when the visual aspect of this particular DisplayObject or movie
1101 /// has been changed and redrawing is necessary.
1103 /// This is initialized to true as the initial state for
1104 /// any DisplayObject is the "invisible" state (it wasn't there)
1105 /// so it starts in invalidated mode.
1107 bool _invalidated;
1109 /// Just like _invalidated but set when a child is invalidated instead
1110 /// of this DisplayObject instance. _invalidated and _child_invalidated
1111 /// can be set at the same time.
1112 bool _child_invalidated;
1117 /// Get local transform SWFMatrix for this DisplayObject
1118 inline const SWFMatrix&
1119 getMatrix(const DisplayObject& o)
1121 return o.transform().matrix;
1124 inline const SWFCxForm&
1125 getCxForm(const DisplayObject& o)
1127 return o.transform().colorTransform;
1130 inline SWFMatrix
1131 getWorldMatrix(const DisplayObject& d, bool includeRoot)
1133 SWFMatrix m = d.parent() ?
1134 getWorldMatrix(*d.parent(), includeRoot) : SWFMatrix();
1136 if (d.parent() || includeRoot) m.concatenate(getMatrix(d));
1137 return m;
1140 inline SWFCxForm
1141 getWorldCxForm(const DisplayObject& d)
1143 SWFCxForm cx = d.parent() ? getWorldCxForm(*d.parent()) : SWFCxForm();
1144 cx.concatenate(getCxForm(d));
1145 return cx;
1148 inline bool
1149 isReferenceable(const DisplayObject& d)
1151 return d.object();
1154 /// Return the as_object associated with a DisplayObject if it exists
1156 /// @param d The DisplayObject to check. May be null.
1157 /// @return null if either the DisplayObject or the associated object is
1158 /// null. Otherwise the associated object.
1159 inline as_object*
1160 getObject(const DisplayObject* d)
1162 return d ? d->object() : nullptr;
1165 /// Stream operator for DisplayObject blend mode.
1166 std::ostream&
1167 operator<<(std::ostream& o, DisplayObject::BlendMode bm);
1169 } // end namespace gnash
1172 #ifdef DEBUG_SET_INVALIDATED
1173 #define set_invalidated() set_invalidated(__FILE__, __LINE__)
1174 #endif
1177 #endif // GNASH_CHARACTER_H
1180 // Local Variables:
1181 // mode: C++
1182 // indent-tabs-mode: t
1183 // End: