@awayjs/scene
Version:
AwayJS scene classes
1,358 lines (1,179 loc) • 65.4 kB
text/typescript
import {
Transform,
TransformEvent,
Sphere,
Matrix3D,
Rectangle,
Vector3D,
AssetBase,
Loader,
IAbstraction,
} from '@awayjs/core';
import { BlendMode } from '@awayjs/stage';
import {
BoundingBox,
BoundingSphere,
BoundingVolumeType,
IEntity,
BoundsPicker,
HierarchicalProperty,
AlignmentMode,
OrientationMode,
IContainer,
ContainerNode,
View
} from '@awayjs/view';
import {
IMaterial,
Style,
StyleEvent,
RenderableEvent,
ElementsType,
} from '@awayjs/renderer';
import { DisplayObjectContainer } from './DisplayObjectContainer';
import { ControllerBase } from '../controllers/ControllerBase';
import { IBitmapDrawable } from '../base/IBitmapDrawable';
import { PrimitiveCubePrefab } from '../prefabs/PrimitiveCubePrefab';
import { PrimitiveSpherePrefab } from '../prefabs/PrimitiveSpherePrefab';
import { PrimitivePrefabBase } from '../prefabs/PrimitivePrefabBase';
import { IFilter } from '../adapters/IFilter';
import { Sprite } from './Sprite';
import { Settings } from '../Settings';
/**
* The DisplayObject class is the base class for all objects that can be
* placed on the display list. The display list manages all objects displayed
* in flash. Use the DisplayObjectContainer class to arrange the
* display objects in the display list. DisplayObjectContainer objects can
* have child display objects, while other display objects, such as Shape and
* TextField objects, are "leaf" nodes that have only parents and siblings, no
* children.
*
* <p>The DisplayObject class supports fbasic functionality like the <i>x</i>
* and <i>y</i> position of an object, as well as more advanced properties of
* the object such as its transformation matrix. </p>
*
* <p>DisplayObject is an abstract base class; therefore, you cannot call
* DisplayObject directly. Invoking <code>new DisplayObject()</code> throws an
* <code>ArgumentError</code> exception. </p>
*
* <p>All display objects inherit from the DisplayObject class.</p>
*
* <p>The DisplayObject class itself does not include any APIs for rendering
* content onscreen. For that reason, if you want create a custom subclass of
* the DisplayObject class, you will want to extend one of its subclasses that
* do have APIs for rendering content onscreen, such as the Shape, Sprite,
* Bitmap, SimpleButton, TextField, or MovieClip class.</p>
*
* <p>The DisplayObject class contains several broadcast events. Normally, the
* target of any particular event is a specific DisplayObject instance. For
* example, the target of an <code>added</code> event is the specific
* DisplayObject instance that was added to the display list. Having a single
* target restricts the placement of event listeners to that target and in
* some cases the target's ancestors on the display list. With broadcast
* events, however, the target is not a specific DisplayObject instance, but
* rather all DisplayObject instances, including those that are not on the
* display list. This means that you can add a listener to any DisplayObject
* instance to listen for broadcast events. In addition to the broadcast
* events listed in the DisplayObject class's Events table, the DisplayObject
* class also inherits two broadcast events from the EventDispatcher class:
* <code>activate</code> and <code>deactivate</code>.</p>
*
* <p>Some properties previously used in the ActionScript 1.0 and 2.0
* MovieClip, TextField, and Button classes(such as <code>_alpha</code>,
* <code>_height</code>, <code>_pName</code>, <code>_width</code>,
* <code>_x</code>, <code>_y</code>, and others) have equivalents in the
* ActionScript 3.0 DisplayObject class that are renamed so that they no
* longer begin with the underscore(_) character.</p>
*
* <p>For more information, see the "Display Programming" chapter of the
* <i>ActionScript 3.0 Developer's Guide</i>.</p>
*
* @event added Dispatched when a display object is added to the
* display list. The following methods trigger this
* event:
* <code>DisplayObjectContainer.addChild()</code>,
* <code>DisplayObjectContainer.addChildAt()</code>.
* @event addedToScene Dispatched when a display object is added to the on
* scene display list, either directly or through the
* addition of a sub tree in which the display object
* is contained. The following methods trigger this
* event:
* <code>DisplayObjectContainer.addChild()</code>,
* <code>DisplayObjectContainer.addChildAt()</code>.
* @event enterFrame [broadcast event] Dispatched when the playhead is
* entering a new frame. If the playhead is not
* moving, or if there is only one frame, this event
* is dispatched continuously in conjunction with the
* frame rate. This event is a broadcast event, which
* means that it is dispatched by all display objects
* with a listener registered for this event.
* @event exitFrame [broadcast event] Dispatched when the playhead is
* exiting the current frame. All frame scripts have
* been run. If the playhead is not moving, or if
* there is only one frame, this event is dispatched
* continuously in conjunction with the frame rate.
* This event is a broadcast event, which means that
* it is dispatched by all display objects with a
* listener registered for this event.
* @event frameConstructed [broadcast event] Dispatched after the constructors
* of frame display objects have run but before frame
* scripts have run. If the playhead is not moving, or
* if there is only one frame, this event is
* dispatched continuously in conjunction with the
* frame rate. This event is a broadcast event, which
* means that it is dispatched by all display objects
* with a listener registered for this event.
* @event removed Dispatched when a display object is about to be
* removed from the display list. Two methods of the
* DisplayObjectContainer class generate this event:
* <code>removeChild()</code> and
* <code>removeChildAt()</code>.
*
* <p>The following methods of a
* DisplayObjectContainer object also generate this
* event if an object must be removed to make room for
* the new object: <code>addChild()</code>,
* <code>addChildAt()</code>, and
* <code>setChildIndex()</code>. </p>
* @event removedFromScene Dispatched when a display object is about to be
* removed from the display list, either directly or
* through the removal of a sub tree in which the
* display object is contained. Two methods of the
* DisplayObjectContainer class generate this event:
* <code>removeChild()</code> and
* <code>removeChildAt()</code>.
*
* <p>The following methods of a
* DisplayObjectContainer object also generate this
* event if an object must be removed to make room for
* the new object: <code>addChild()</code>,
* <code>addChildAt()</code>, and
* <code>setChildIndex()</code>. </p>
* @event render [broadcast event] Dispatched when the display list
* is about to be updated and rendered. This event
* provides the last opportunity for objects listening
* for this event to make changes before the display
* list is rendered. You must call the
* <code>invalidate()</code> method of the Scene
* object each time you want a <code>render</code>
* event to be dispatched. <code>Render</code> events
* are dispatched to an object only if there is mutual
* trust between it and the object that called
* <code>Scene.invalidate()</code>. This event is a
* broadcast event, which means that it is dispatched
* by all display objects with a listener registered
* for this event.
*
* <p><b>Note: </b>This event is not dispatched if the
* display is not rendering. This is the case when the
* content is either minimized or obscured. </p>
*/
export class DisplayObject extends AssetBase implements IBitmapDrawable, IContainer {
private _mouseChildren: boolean = true;
public _material: IMaterial;
public _style: Style;
private _loader: Loader;
private _mouseX: number;
private _mouseY: number;
private _root: DisplayObjectContainer;
private _boundsVisible: boolean;
private _boundsPrefab: PrimitivePrefabBase;
private _boundsPrefabDirty: boolean;
private _boundsPrimitive: DisplayObject;
private _pName: string;
private _scrollRect: Rectangle;
private _scrollRectPrimitive: Sprite;
private _scrollRectPrimitiveDirty: boolean;
protected _parent: DisplayObjectContainer;
public _sessionID: number = -1;
public _avmDepthID: number = -1;
public pickObjectFromTimeline: boolean;
private _alignmentMode: AlignmentMode = AlignmentMode.REGISTRATION_POINT;
private _scale9Grid: Rectangle;
protected _transform: Transform;
private _visible: boolean = true;
private _maskId: number = -1;
protected _masks: DisplayObject[];
protected _scriptMask: DisplayObject;
private _mouseEnabled: boolean = true;
private _eulers: Vector3D;
public _registrationMatrix3D: Matrix3D;
private _defaultBoundingVolume: BoundingVolumeType;
public cursorType: string;
protected _isInFocus: boolean;
protected _tabEnabled: boolean;
protected _tabIndex: number;
private _maskMode: boolean = false;
private _pickObject: DisplayObjectContainer;
public _hierarchicalPropsDirty: number;
private _onInvalidatePropertiesDelegate: (event: StyleEvent) => void;
private _onInvalidateImagesDelegate: (event: StyleEvent) => void;
public isSlice9ScaledMC: boolean=false;
public isSlice9ScaledSprite: boolean=false;
public avm1Symbol: any;
public isAVMScene: boolean=false;
// this is needed for AVM1 - todo: maybe do this on adapters ?
public placeObjectTag: any=null;
public getScriptPrecedence(): number[] {
if (!this._parent) {
return [];
}
const result = this._parent.getScriptPrecedence();
if (this.placeObjectTag) {
result.push(this.placeObjectTag.actionBlocksPrecedence);
}
return result;
}
public getMouseCursor(): string {
return 'initial';
}
public get tabEnabled(): boolean {
return this._tabEnabled;
}
public set tabEnabled(value: boolean) {
this._tabEnabled = value;
}
public get tabIndex(): number {
return this._tabIndex;
}
public set tabIndex(value: number) {
this._tabIndex = value;
}
public get isInFocus(): boolean {
return this._isInFocus;
}
public set isInFocus(value: boolean) {
this._isInFocus = value;
}
public setFocus(value: boolean, fromMouseDown: boolean = false, sendSoftKeyEvent: boolean = true) {
if (this._isInFocus == value)
return;
this._isInFocus = value;
}
/**
*
*/
public get alignmentMode(): AlignmentMode {
return this._alignmentMode;
}
public set alignmentMode(value: AlignmentMode) {
if (this._alignmentMode == value)
return;
this._alignmentMode = value;
this._invalidateHierarchicalProperty(HierarchicalProperty.SCENE_TRANSFORM);
}
/**
* Indicates the alpha transparency value of the object specified. Valid
* values are 0(fully transparent) to 1(fully opaque). The default value is
* 1. Display objects with <code>alpha</code> set to 0 <i>are</i> active,
* even though they are invisible.
*/
public get alpha(): number {
return this._transform.colorTransform.alphaMultiplier;
}
public set alpha(value: number) {
this._transform.colorTransform.alphaMultiplier = value;
this._transform.invalidateColorTransform();
}
/**
* A value from the BlendMode class that specifies which blend mode to use. A
* bitmap can be drawn internally in two ways. If you have a blend mode
* enabled or an external clipping mask, the bitmap is drawn by adding a
* bitmap-filled square shape to the vector render. If you attempt to set
* this property to an invalid value, Flash runtimes set the value to
* <code>BlendMode.NORMAL</code>.
*
* <p>The <code>blendMode</code> property affects each pixel of the display
* object. Each pixel is composed of three constituent colors(red, green,
* and blue), and each constituent color has a value between 0x00 and 0xFF.
* Flash Player or Adobe AIR compares each constituent color of one pixel in
* the movie clip with the corresponding color of the pixel in the
* background. For example, if <code>blendMode</code> is set to
* <code>BlendMode.LIGHTEN</code>, Flash Player or Adobe AIR compares the red
* value of the display object with the red value of the background, and uses
* the lighter of the two as the value for the red component of the displayed
* color.</p>
*
* <p>The following table describes the <code>blendMode</code> settings. The
* BlendMode class defines string values you can use. The illustrations in
* the table show <code>blendMode</code> values applied to a circular display
* object(2) superimposed on another display object(1).</p>
*/
public _blendMode: BlendMode = BlendMode.LAYER;
public set blendMode(v: BlendMode) {
if (this._blendMode === v) {
return;
}
this._blendMode = v;
if (v === BlendMode.OVERLAY) {
this._transform.invalidateColorTransform();
}
}
public get blendMode() {
if (!Settings.USE_UNSAFE_BLENDS) {
return '';
}
if (Settings.REMAP_BLEND_MODE) {
return Settings.BLEND_MODE_REMAP_TABLE[<string> this._blendMode] || this._blendMode;
}
return this._blendMode;
}
/**
*
*/
public get defaultBoundingVolume(): BoundingVolumeType {
return this._defaultBoundingVolume;
}
public set defaultBoundingVolume(value: BoundingVolumeType) {
if (this._defaultBoundingVolume == value)
return;
this._defaultBoundingVolume = value;
if (this._boundsPrimitive) {
this._boundsPrimitive.dispose();
this._boundsPrimitive = null;
}
this.invalidate();
}
/**
* If set to <code>true</code>, NME will use the software renderer to cache
* an internal bitmap representation of the display object. For native targets,
* this is often much slower than the default hardware renderer. When you
* are using the Flash target, this caching may increase performance for display
* objects that contain complex vector content.
*
* <p>All vector data for a display object that has a cached bitmap is drawn
* to the bitmap instead of the main display. If
* <code>cacheAsBitmapMatrix</code> is null or unsupported, the bitmap is
* then copied to the main display as unstretched, unrotated pixels snapped
* to the nearest pixel boundaries. Pixels are mapped 1 to 1 with the parent
* object. If the bounds of the bitmap change, the bitmap is recreated
* instead of being stretched.</p>
*
* <p>If <code>cacheAsBitmapMatrix</code> is non-null and supported, the
* object is drawn to the off-screen bitmap using that matrix and the
* stretched and/or rotated results of that rendering are used to draw the
* object to the main display.</p>
*
* <p>No internal bitmap is created unless the <code>BBitmap</code>
* property is set to <code>true</code>.</p>
*
* <p>After you set the <code>cacheAsBitmap</code> property to
* <code>true</code>, the rendering does not change, however the display
* object performs pixel snapping automatically. The animation speed can be
* significantly faster depending on the complexity of the vector content.
* </p>
*
* <p>The <code>cacheAsBitmap</code> property is automatically set to
* <code>true</code> whenever you apply a filter to a display object(when
* its <code>filter</code> array is not empty), and if a display object has a
* filter applied to it, <code>cacheAsBitmap</code> is reported as
* <code>true</code> for that display object, even if you set the property to
* <code>false</code>. If you clear all filters for a display object, the
* <code>cacheAsBitmap</code> setting changes to what it was last set to.</p>
*
* <p>A display object does not use a bitmap even if the
* <code>cacheAsBitmap</code> property is set to <code>true</code> and
* instead renders from vector data in the following cases:</p>
*
* <ul>
* <li>The bitmap is too large. In AIR 1.5 and Flash Player 10, the maximum
* size for a bitmap image is 8,191 pixels in width or height, and the total
* number of pixels cannot exceed 16,777,215 pixels.(So, if a bitmap image
* is 8,191 pixels wide, it can only be 2,048 pixels high.) In Flash Player 9
* and earlier, the limitation is is 2880 pixels in height and 2,880 pixels
* in width.</li>
* <li>The bitmap fails to allocate(out of memory error). </li>
* </ul>
*
* <p>The <code>cacheAsBitmap</code> property is best used with movie clips
* that have mostly static content and that do not scale and rotate
* frequently. With such movie clips, <code>cacheAsBitmap</code> can lead to
* performance increases when the movie clip is translated(when its <i>x</i>
* and <i>y</i> position is changed).</p>
*/
private _bitmapCache: boolean;
public get cacheAsBitmap() {
return this._bitmapCache;
}
public set cacheAsBitmap(v: boolean) {
if (v === this._bitmapCache) {
return;
}
if (!Settings.USE_UNSAFE_CACHE_AS_BITMAP) {
return;
}
v && console.warn(
'[@scene/DisplayObject] Unsafe cacheAsBitmap is enabled!' +
'You can disable it by `Settings.USE_UNSAFE_CACHE_AS_BITMAP = false`'
,this.id
);
this._bitmapCache = v;
}
/**
*
*/
public castsShadows: boolean = true;
/**
* Defines the rotation of the 3d object as a <code>Vector3D</code>
* object containing euler angles for rotation around x, y and z axis.
*/
public get eulers(): Vector3D {
if (!this._eulers)
this._eulers = new Vector3D();
this._eulers.x = this.rotationX;
this._eulers.y = this.rotationY;
this._eulers.z = this.rotationZ;
return this._eulers;
}
public set eulers(value: Vector3D) {
// previously this was using the setters for rotationX etc
// but because this will convert from radians to degree, i changed it to update directly
this._transform.rotation.x = value.x;
this._transform.rotation.y = value.y;
this._transform.rotation.z = value.z;
this._transform.invalidateMatrix3D();
}
/**
* An object that can contain any extra data.
*/
public extra: Object;
/**
* An indexed array that contains each filter object currently associated
* with the display object. The flash.filters package contains several
* classes that define specific filters you can use.
*
* <p>Filters can be applied in Flash Professional at design time, or at run
* time by using ActionScript code. To apply a filter by using ActionScript,
* you must make a temporary copy of the entire <code>filters</code> array,
* modify the temporary array, then assign the value of the temporary array
* back to the <code>filters</code> array. You cannot directly add a new
* filter object to the <code>filters</code> array.</p>
*
* <p>To add a filter by using ActionScript, perform the following steps
* (assume that the target display object is named
* <code>myDisplayObject</code>):</p>
*
* <ol>
* <li>Create a new filter object by using the constructor method of your
* chosen filter class.</li>
* <li>Assign the value of the <code>myDisplayObject.filters</code> array
* to a temporary array, such as one named <code>myFilters</code>.</li>
* <li>Add the new filter object to the <code>myFilters</code> temporary
* array.</li>
* <li>Assign the value of the temporary array to the
* <code>myDisplayObject.filters</code> array.</li>
* </ol>
*
* <p>If the <code>filters</code> array is undefined, you do not need to use
* a temporary array. Instead, you can directly assign an array literal that
* contains one or more filter objects that you create. The first example in
* the Examples section adds a drop shadow filter by using code that handles
* both defined and undefined <code>filters</code> arrays.</p>
*
* <p>To modify an existing filter object, you must use the technique of
* modifying a copy of the <code>filters</code> array:</p>
*
* <ol>
* <li>Assign the value of the <code>filters</code> array to a temporary
* array, such as one named <code>myFilters</code>.</li>
* <li>Modify the property by using the temporary array,
* <code>myFilters</code>. For example, to set the quality property of the
* first filter in the array, you could use the following code:
* <code>myFilters[0].quality = 1;</code></li>
* <li>Assign the value of the temporary array to the <code>filters</code>
* array.</li>
* </ol>
*
* <p>At load time, if a display object has an associated filter, it is
* marked to cache itself as a transparent bitmap. From this point forward,
* as long as the display object has a valid filter list, the player caches
* the display object as a bitmap. This source bitmap is used as a source
* image for the filter effects. Each display object usually has two bitmaps:
* one with the original unfiltered source display object and another for the
* final image after filtering. The final image is used when rendering. As
* long as the display object does not change, the final image does not need
* updating.</p>
*
* <p>The flash.filters package includes classes for filters. For example, to
* create a DropShadow filter, you would write:</p>
*
* @throws ArgumentError When <code>filters</code> includes a ShaderFilter
* and the shader output type is not compatible with
* this operation(the shader must specify a
* <code>pixel4</code> output).
* @throws ArgumentError When <code>filters</code> includes a ShaderFilter
* and the shader doesn't specify any image input or
* the first input is not an <code>image4</code> input.
* @throws ArgumentError When <code>filters</code> includes a ShaderFilter
* and the shader specifies an image input that isn't
* provided.
* @throws ArgumentError When <code>filters</code> includes a ShaderFilter, a
* ByteArray or Vector.<Number> instance as a shader
* input, and the <code>width</code> and
* <code>height</code> properties aren't specified for
* the ShaderInput object, or the specified values
* don't match the amount of data in the input data.
* See the <code>ShaderInput.input</code> property for
* more information.
*/
private _filters: Array<IFilter> = null;
public set filters(v: Array<IFilter>) {
if (!Settings.USE_UNSAFE_FILTERS) {
return;
}
this._filters = v;
this._invalidateStyle();
}
public get filters() {
return this._filters;
}
public updateFilters(_newFilters: IFilter[]) {
console.warn('[scene/DisplayObject] - updateFilters is just a stub');
}
/**
* Indicates the instance container index of the DisplayObject. The object can be
* identified in the child list of its parent display object container by
* calling the <code>getChildByIndex()</code> method of the display object
* container.
*
* <p>If the DisplayObject has no parent container, index defaults to 0.</p>
*/
public get index(): number {
if (this._parent)
return this._parent.getChildIndex(this);
return 0;
}
/**
* Returns a LoaderInfo object containing information about loading the file
* to which this display object belongs. The <code>loaderInfo</code> property
* is defined only for the root display object of a SWF file or for a loaded
* Bitmap(not for a Bitmap that is drawn with ActionScript). To find the
* <code>loaderInfo</code> object associated with the SWF file that contains
* a display object named <code>myDisplayObject</code>, use
* <code>myDisplayObject.root.loaderInfo</code>.
*
* <p>A large SWF file can monitor its download by calling
* <code>this.root.loaderInfo.addEventListener(Event.COMPLETE,
* func)</code>.</p>
*/
public get loader(): Loader {
return this._loader;
}
/**
* The calling display object is masked by the specified <code>mask</code>
* object. To ensure that masking works when the Stage is scaled, the
* <code>mask</code> display object must be in an active part of the display
* list. The <code>mask</code> object itself is not drawn. Set
* <code>mask</code> to <code>null</code> to remove the mask.
*
* <p>To be able to scale a mask object, it must be on the display list. To
* be able to drag a mask Sprite object(by calling its
* <code>startDrag()</code> method), it must be on the display list. To call
* the <code>startDrag()</code> method for a mask sprite based on a
* <code>mouseDown</code> event being dispatched by the sprite, set the
* sprite's <code>buttonMode</code> property to <code>true</code>.</p>
*
* <p>When display objects are cached by setting the
* <code>cacheAsBitmap</code> property to <code>true</code> an the
* <code>cacheAsBitmapMatrix</code> property to a Matrix object, both the
* mask and the display object being masked must be part of the same cached
* bitmap. Thus, if the display object is cached, then the mask must be a
* child of the display object. If an ancestor of the display object on the
* display list is cached, then the mask must be a child of that ancestor or
* one of its descendents. If more than one ancestor of the masked object is
* cached, then the mask must be a descendent of the cached container closest
* to the masked object in the display list.</p>
*
* <p><b>Note:</b> A single <code>mask</code> object cannot be used to mask
* more than one calling display object. When the <code>mask</code> is
* assigned to a second display object, it is removed as the mask of the
* first object, and that object's <code>mask</code> property becomes
* <code>null</code>.</p>
*/
public set mask(value: DisplayObject) {
this.scriptMask = value;
}
public get maskMode(): boolean {
return this._maskMode;
}
public set maskMode(value: boolean) {
if (this._maskMode == value)
return;
this._maskMode = value;
this._maskId = value ? this.id : -1;
this._updateMaskMode();
}
public get pickObject(): DisplayObjectContainer {
return this._pickObject;
}
public set pickObject(value: DisplayObjectContainer) {
if (this._pickObject == value)
return;
this._pickObject = (<DisplayObject> value == this)
? null
: value.pickObjectFromTimeline ? value.clone() : value;
if (this._pickObject) {
this._pickObject.mouseChildren = false;
this._pickObject.mouseEnabled = false;
}
}
/**
* Specifies whether this object receives mouse, or other user input,
* messages. The default value is <code>true</code>, which means that by
* default any InteractiveObject instance that is on the display list
* receives mouse events or other user input events. If
* <code>mouseEnabled</code> is set to <code>false</code>, the instance does
* not receive any mouse events(or other user input events like keyboard
* events). Any children of this instance on the display list are not
* affected. To change the <code>mouseEnabled</code> behavior for all
* children of an object on the display list, use
* <code>flash.display.DisplayObjectContainer.mouseChildren</code>.
*
* <p> No event is dispatched by setting this property. You must use the
* <code>addEventListener()</code> method to create interactive
* functionality.</p>
*/
public get mouseEnabled(): boolean {
return this._mouseEnabled;
}
public set mouseEnabled(value: boolean) {
if (this._mouseEnabled == value)
return;
this._mouseEnabled = value;
}
/**
* Indicates the x coordinate of the mouse or user input device position, in
* pixels.
*
* <p><b>Note</b>: For a DisplayObject that has been rotated, the returned x
* coordinate will reflect the non-rotated object.</p>
*/
public get mouseX(): number {
return this._mouseX;
}
/**
* Indicates the y coordinate of the mouse or user input device position, in
* pixels.
*
* <p><b>Note</b>: For a DisplayObject that has been rotated, the returned y
* coordinate will reflect the non-rotated object.</p>
*/
public get mouseY(): number {
return this._mouseY;
}
/**
* Indicates the instance name of the DisplayObject. The object can be
* identified in the child list of its parent display object container by
* calling the <code>getChildByName()</code> method of the display object
* container.
*
* @throws IllegalOperationError If you are attempting to set this property
* on an object that was placed on the timeline
* in the Flash authoring tool.
*/
public get name(): string {
return this._pName ? this._pName : '';
}
public set name(value: string) {
this._pName = value;
}
/**
*
*/
public orientationMode: OrientationMode = OrientationMode.DEFAULT;
/**
* Indicates the DisplayObjectContainer object that contains this display
* object. Use the <code>parent</code> property to specify a relative path to
* display objects that are above the current display object in the display
* list hierarchy.
*
* <p>You can use <code>parent</code> to move up multiple levels in the
* display list as in the following:</p>
*
* @throws SecurityError The parent display object belongs to a security
* sandbox to which you do not have access. You can
* avoid this situation by having the parent movie call
* the <code>Security.allowDomain()</code> method.
*/
public get parent(): DisplayObjectContainer {
return this._parent;
}
/**
* Defines the local point around which the object rotates.
*/
public get registrationPoint(): Vector3D {
if (this._registrationMatrix3D)
return new Vector3D(
-this._registrationMatrix3D._rawData[12] * this.scaleX,
-this._registrationMatrix3D._rawData[13] * this.scaleY,
-this._registrationMatrix3D._rawData[14] * this.scaleZ);
return null;
}
public set registrationPoint(value: Vector3D) {
if (!value) {
if (!this._registrationMatrix3D)
return;
this._registrationMatrix3D._rawData[12] = 0;
this._registrationMatrix3D._rawData[13] = 0;
this._registrationMatrix3D._rawData[14] = 0;
if (this._registrationMatrix3D.isIdentity())
this._registrationMatrix3D = null;
} else {
if (!this._registrationMatrix3D)
this._registrationMatrix3D = new Matrix3D();
this._registrationMatrix3D._rawData[12] = -value.x / this._transform.scale.x;
this._registrationMatrix3D._rawData[13] = -value.y / this._transform.scale.y;
this._registrationMatrix3D._rawData[14] = -value.z / this._transform.scale.z;
}
this._invalidateHierarchicalProperty(HierarchicalProperty.SCENE_TRANSFORM);
}
/**
* Defines the local scale.
*/
public get registrationScale(): Vector3D {
if (this._registrationMatrix3D)
return new Vector3D(
this._registrationMatrix3D._rawData[0],
this._registrationMatrix3D._rawData[5],
this._registrationMatrix3D._rawData[10]);
return null;
}
public set registrationScale(value: Vector3D) {
if (!value) {
if (!this._registrationMatrix3D)
return;
this._registrationMatrix3D._rawData[0] = 1;
this._registrationMatrix3D._rawData[5] = 1;
this._registrationMatrix3D._rawData[10] = 1;
if (this._registrationMatrix3D.isIdentity())
this._registrationMatrix3D = null;
} else {
if (!this._registrationMatrix3D)
this._registrationMatrix3D = new Matrix3D();
this._registrationMatrix3D._rawData[0] = value.x;
this._registrationMatrix3D._rawData[5] = value.y;
this._registrationMatrix3D._rawData[10] = value.z;
}
this._invalidateHierarchicalProperty(HierarchicalProperty.SCENE_TRANSFORM);
}
/**
* For a display object in a loaded SWF file, the <code>root</code> property
* is the top-most display object in the portion of the display list's tree
* structure represented by that SWF file. For a Bitmap object representing a
* loaded image file, the <code>root</code> property is the Bitmap object
* itself. For the instance of the main class of the first SWF file loaded,
* the <code>root</code> property is the display object itself. The
* <code>root</code> property of the Scene object is the Scene object itself.
* The <code>root</code> property is set to <code>null</code> for any display
* object that has not been added to the display list, unless it has been
* added to a display object container that is off the display list but that
* is a child of the top-most display object in a loaded SWF file.
*
* <p>For example, if you create a new Sprite object by calling the
* <code>Sprite()</code> constructor method, its <code>root</code> property
* is <code>null</code> until you add it to the display list(or to a display
* object container that is off the display list but that is a child of the
* top-most display object in a SWF file).</p>
*
* <p>For a loaded SWF file, even though the Loader object used to load the
* file may not be on the display list, the top-most display object in the
* SWF file has its <code>root</code> property set to itself. The Loader
* object does not have its <code>root</code> property set until it is added
* as a child of a display object for which the <code>root</code> property is
* set.</p>
*/
public get root(): DisplayObjectContainer {
return this._root;
}
/**
* Indicates the rotation of the DisplayObject instance, in degrees, from its
* original orientation. Values from 0 to 180 represent clockwise rotation;
* values from 0 to -180 represent counterclockwise rotation. Values outside
* this range are added to or subtracted from 360 to obtain a value within
* the range. For example, the statement <code>my_video.rotation = 450</code>
* is the same as <code> my_video.rotation = 90</code>.
*/
public rotation: number; //TODO
/**
* Indicates the x-axis rotation of the DisplayObject instance, in degrees,
* from its original orientation relative to the 3D parent container. Values
* from 0 to 180 represent clockwise rotation; values from 0 to -180
* represent counterclockwise rotation. Values outside this range are added
* to or subtracted from 360 to obtain a value within the range.
*/
public get rotationX(): number {
return this._transform.rotation.x;
}
public set rotationX(val: number) {
if (this.rotationX == val)
return;
this._transform.rotation.x = val;
this._transform.invalidateMatrix3D();
}
/**
* Indicates the y-axis rotation of the DisplayObject instance, in degrees,
* from its original orientation relative to the 3D parent container. Values
* from 0 to 180 represent clockwise rotation; values from 0 to -180
* represent counterclockwise rotation. Values outside this range are added
* to or subtracted from 360 to obtain a value within the range.
*/
public get rotationY(): number {
return this._transform.rotation.y;
}
public set rotationY(val: number) {
if (this.rotationY == val)
return;
this._transform.rotation.y = val;
this._transform.invalidateMatrix3D();
}
/**
* Indicates the z-axis rotation of the DisplayObject instance, in degrees,
* from its original orientation relative to the 3D parent container. Values
* from 0 to 180 represent clockwise rotation; values from 0 to -180
* represent counterclockwise rotation. Values outside this range are added
* to or subtracted from 360 to obtain a value within the range.
*/
public get rotationZ(): number {
return this._transform.rotation.z;
}
public set rotationZ(val: number) {
if (this.rotationZ == val)
return;
this._transform.rotation.z = val;
this._transform.invalidateMatrix3D();
}
/**
* The current scaling grid that is in effect. If set to <code>null</code>,
* the entire display object is scaled normally when any scale transformation
* is applied.
*
* <p>When you define the <code>scale9Grid</code> property, the display
* object is divided into a grid with nine regions based on the
* <code>scale9Grid</code> rectangle, which defines the center region of the
* grid. The eight other regions of the grid are the following areas: </p>
*
* <ul>
* <li>The upper-left corner outside of the rectangle</li>
* <li>The area above the rectangle </li>
* <li>The upper-right corner outside of the rectangle</li>
* <li>The area to the left of the rectangle</li>
* <li>The area to the right of the rectangle</li>
* <li>The lower-left corner outside of the rectangle</li>
* <li>The area below the rectangle</li>
* <li>The lower-right corner outside of the rectangle</li>
* </ul>
*
* <p>You can think of the eight regions outside of the center(defined by
* the rectangle) as being like a picture frame that has special rules
* applied to it when scaled.</p>
*
* <p>When the <code>scale9Grid</code> property is set and a display object
* is scaled, all text and gradients are scaled normally; however, for other
* types of objects the following rules apply:</p>
*
* <ul>
* <li>Content in the center region is scaled normally. </li>
* <li>Content in the corners is not scaled. </li>
* <li>Content in the top and bottom regions is scaled horizontally only.
* Content in the left and right regions is scaled vertically only.</li>
* <li>All fills(including bitmaps, video, and gradients) are stretched to
* fit their shapes.</li>
* </ul>
*
* <p>If a display object is rotated, all subsequent scaling is normal(and
* the <code>scale9Grid</code> property is ignored).</p>
*
* <p>For example, consider the following display object and a rectangle that
* is applied as the display object's <code>scale9Grid</code>:</p>
*
* <p>A common use for setting <code>scale9Grid</code> is to set up a display
* object to be used as a component, in which edge regions retain the same
* width when the component is scaled.</p>
*
* @throws ArgumentError If you pass an invalid argument to the method.
*/
public get scale9Grid(): Rectangle {
return this._scale9Grid;
}
public set scale9Grid(value: Rectangle) {
this._scale9Grid = value;
this._invalidateHierarchicalProperty(HierarchicalProperty.SCALE9);
}
/**
* Indicates the horizontal scale(percentage) of the object as applied from
* the registration point. The default registration point is(0,0). 1.0
* equals 100% scale.
*
* <p>Scaling the local coordinate system changes the <code>x</code> and
* <code>y</code> property values, which are defined in whole pixels. </p>
*/
public get scaleX(): number {
return this._transform.scale.x;
}
public set scaleX(val: number) {
//this._updateAbsoluteDimension();
this._setScaleX(val);
}
/**
* Indicates the vertical scale(percentage) of an object as applied from the
* registration point of the object. The default registration point is(0,0).
* 1.0 is 100% scale.
*
* <p>Scaling the local coordinate system changes the <code>x</code> and
* <code>y</code> property values, which are defined in whole pixels. </p>
*/
public get scaleY(): number {
return this._transform.scale.y;
}
public set scaleY(val: number) {
//this._updateAbsoluteDimension();
this._setScaleY(val);
}
/**
* Indicates the depth scale(percentage) of an object as applied from the
* registration point of the object. The default registration point is(0,0).
* 1.0 is 100% scale.
*
* <p>Scaling the local coordinate system changes the <code>x</code>,
* <code>y</code> and <code>z</code> property values, which are defined in
* whole pixels. </p>
*/
public get scaleZ(): number {
return this._transform.scale.z;
}
public set scaleZ(val: number) {
//this._updateAbsoluteDimension();
this._setScaleZ(val);
}
/**
* Indicates the horizontal skew(angle) of the object as applied from
* the registration point. The default registration point is(0,0).
*/
public get skewX(): number {
return this._transform.skew.x;
}
public set skewX(val: number) {
if (this.skewX == val)
return;
this._transform.skew.x = val;
this._transform.invalidateMatrix3D();
}
/**
* Indicates the vertical skew(angle) of an object as applied from the
* registration point of the object. The default registration point is(0,0).
*/
public get skewY(): number {
return this._transform.skew.y;
}
public set skewY(val: number) {
if (this.skewY == val)
return;
this._transform.skew.y = val;
this._transform.invalidateMatrix3D();
}
/**
* Indicates the depth skew(angle) of an object as applied from the
* registration point of the object. The default registration point is(0,0).
*/
public get skewZ(): number {
return this._transform.skew.z;
}
public set skewZ(val: number) {
if (this.skewZ == val)
return;
this._transform.skew.z = val;
this._transform.invalidateMatrix3D();
}
/**
* The scroll rectangle bounds of the display object. The display object is
* cropped to the size defined by the rectangle, and it scrolls within the
* rectangle when you change the <code>x</code> and <code>y</code> properties
* of the <code>scrollRect</code> object.
*
* <p>The properties of the <code>scrollRect</code> Rectangle object use the
* display object's coordinate space and are scaled just like the overall
* display object. The corner bounds of the cropped window on the scrolling
* display object are the origin of the display object(0,0) and the point
* defined by the width and height of the rectangle. They are not centered
* around the origin, but use the origin to define the upper-left corner of
* the area. A scrolled display object always scrolls in whole pixel
* increments. </p>
*
* <p>You can scroll an object left and right by setting the <code>x</code>
* property of the <code>scrollRect</code> Rectangle object. You can scroll
* an object up and down by setting the <code>y</code> property of the
* <code>scrollRect</code> Rectangle object. If the display object is rotated
* 90° and you scroll it left and right, the display object actually scrolls
* up and down.</p>
*/
public get scrollRect(): Rectangle {
return this._scrollRect;
}
public set scrollRect(value: Rectangle) {
// @todo: check if rectangle has same values as previous
//if (this._scrollRect == value)
// return;
this._scrollRect = value;
if (!value && this._scrollRectPrimitive) {
const idx = this.masks.indexOf(this._scrollRectPrimitive);
this.masks.splice(idx, 1);
this._scrollRectPrimitive = null;
}
this._transform.invalidatePosition();
this._scrollRectPrimitiveDirty = true;
}
/**
*
*/
public get material(): IMaterial {
return this._material;
}
public set material(value: IMaterial) {
if (this._material == value)
return;
this._material = value;
this._invalidateMaterial();
}
/**
*
*/
public get style(): Style {
return this._style;
}
public set style(value: Style) {
if (this._style == value)
return;
if (this._style) {
this._style.removeEventListener(StyleEvent.INVALIDATE_PROPERTIES, this._onInvalidatePropertiesDelegate);
this._style.removeEventListener(StyleEvent.INVALIDATE_IMAGES, this._onInvalidateImagesDelegate);
}
this._style = value;
if (this._style) {
this._style.addEventListener(StyleEvent.INVALIDATE_PROPERTIES, this._onInvalidatePropertiesDelegate);
this._style.addEventListener(StyleEvent.INVALIDATE_IMAGES, this._onInvalidateImagesDelegate);
}
this._invalidateStyle();
}
/**
*
*/
public get boundsVisible(): boolean {
return this._boundsVisible;
}
public set boundsVisible(value: boolean) {
if (value == this._boundsVisible)
return;
this._boundsVisible = value;
// if (this._boundsVisible && !this.partition)
// this.partition = BasicPartition.getRootPartition(this);
this.invalidate();
}
public getScrollRectPrimitive(): IContainer {
if (this._scrollRectPrimitiveDirty) {
this._scrollRectPrimitiveDirty = false;
if (!this._scrollRectPrimitive) {
this._scrollRectPrimitive = new Sprite();
this._scrollRectPrimitive.maskMode = true;
if (!this.masks)
this.masks = [];
this.masks.push(this._scrollRectPrimitive);
}
this._scrollRectPrimitive.graphics.clear();
this._scrollRectPrimitive.graphics.beginFill(0x0000ff, 1);
this._scrollRectPrimitive.graphics.drawRect(0,0,this._scrollRect.width,this._scrollRect.height);
this._scrollRectPrimitive.graphics.endFill();
}
return this._scrollRectPrimitive;
}
public getBoundsPrimitive(picker: BoundsPicker): IContainer {
if (this._boundsPrimitive == null) {
switch (this._defaultBoundingVolume) {
case BoundingVolumeType.BOX:
case BoundingVolumeType.BOX_BOUNDS:
case BoundingVolumeType.BOX_BOUNDS_FAST:
case BoundingVolumeType.BOX_FAST:
this._boundsPrefab = new PrimitiveCubePrefab(null, ElementsType.LINE);
this._boundsPrimitive = this._boundsPrefab.getNewObject();
break;
case BoundingVolumeType.SPHERE:
case BoundingVolumeType.SPHERE_BOUNDS:
case BoundingVolumeType.SPHERE_BOUNDS_FAST:
case BoundingVolumeType.SPHERE_FAST:
this._boundsPrefab = new PrimitiveSpherePrefab(null, ElementsType.LINE);
this._boundsPrimitive = this._boundsPrefab.getNewObject();
break;
default:
}
this._boundsPrefabDirty = true;
}
if (this._boundsPrefabDirty)
this._updateBoundsPrefab(picker);
return this._boundsPrimitive;
}
/**
* An object with properties pertaining to a display object's matrix, color
* transform, and pixel bounds. The specific properties - matrix,
* colorTransform, and three read-only properties
* (<code>concatenatedMatrix</code>, <code>concatenatedColorTransform</code>,
* and <code>pixelBounds</code>) - are described in the entry for the
* Transform class.
*
* <p>Each of the transform object's properties is itself an object. This
* concept is important because the only way to set new values for the matrix
* or colorTransform objects is to create a new object and copy that object
* into the transform.matrix or transform.colorTransform property.</p>
*
* <p>For example, to increase the <code>tx</code> value of a display
* object's matrix, you must make a copy of the entire matrix object, then
* copy the new object into the matrix property of the transform object:</p>
* <pre xml:space="preserve"><code> public myMatrix:Matrix =
* myDisplayObject.transform.matrix; myMatrix.tx += 10;
* myDisplayObject.transform.matrix = myMatrix; </code></pre>
*
* <p>You cannot directly set the <code>tx</code> property. The following
* code has no effect on <code>myDisplayObject</code>: </p>
* <pre xml:space="preserve"><code> myDisplayObject.transform.matrix.tx +=
* 10; </code></pre>
*
* <p>You can also copy an entire transform object and assign it to another
* display object's transform property. For example, the following code
* copies the entire transform object from <code>myOldDisplayObj</code> to
* <code>myNewDisplayObj</code>:</p>
* <code>myNewDisplayObj.transform = myOldDisplayObj.transform;</code>
*
* <p>The resulting display object, <code>myNewDisplayObj</code>, now has the
* same values for its matrix, color transform, and pixel bounds as the old
* display object, <code>myOldDisplayObj</code>.</p>
*
* <p>Note that AIR for TV devices use hardware acceleration, if it is
* available, for color transforms.</p>
*/
public get transform(): Transform {
return this._transform;
}
/**
* Whether or not the display object is visible. Display objects that are not
* visible are disabled. For example, if <code>visible=false</code> for an
* InteractiveObject instance, it cannot be clicked.
*/
public get visible(): boolean {
return this._visible;
}
public set visible(value: boolean) {
if (this._visible == value)
return;
this._visible = value;
this._invalidateHierarchicalProperty(HierarchicalProperty.VISIBLE);
}
private _mergeMasks(timeline: Array<DisplayObject> | null, script: DisplayObject | null): Array<DisplayObject> {
if (!timeline && !script)
return;
// we can not have mask array, create it
if (!timeline && script)
return [script];
// and make sure that we not have same script mask in it
if (script && !timeline.includes(script))
timeline.push(script);
return timeline;
}
private _setMasks(masks: Arr