dragonbones-runtime
Version:
the tools to build dragonbones file for diffrent framework
591 lines (544 loc) • 22.4 kB
text/typescript
//////////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014-present, Egret Technology.
// All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Egret nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY EGRET AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL EGRET AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;LOSS OF USE, DATA,
// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////////////
namespace egret {
/**
* The Bitmap class represents display objects that represent bitmap images.
* The Bitmap() constructor allows you to create a Bitmap object that contains a reference to a BitmapData object.
* After you create a Bitmap object, use the addChild() or addChildAt() method of the parent DisplayObjectContainer
* instance to place the bitmap on the display list.A Bitmap object can share its texture reference among several
* Bitmap objects, independent of translation or rotation properties. Because you can create multiple Bitmap objects
* that reference the same texture object, multiple display objects can use the same complex texture object
* without incurring the memory overhead of a texture object for each display object instance.
*
* @see egret.Texture
* @version Egret 2.4
* @platform Web,Native
* @includeExample egret/display/Bitmap.ts
* @language en_US
*/
/**
* Bitmap 类表示用于显示位图图片的显示对象。
* 利用 Bitmap() 构造函数,可以创建包含对 BitmapData 对象引用的 Bitmap 对象。创建了 Bitmap 对象后,
* 使用父级 DisplayObjectContainer 实例的 addChild() 或 addChildAt() 方法可以将位图放在显示列表中。
* 一个 Bitmap 对象可在若干 Bitmap 对象之中共享其 texture 引用,与缩放或旋转属性无关。
* 由于能够创建引用相同 texture 对象的多个 Bitmap 对象,因此,多个显示对象可以使用相同的 texture 对象,
* 而不会因为每个显示对象实例使用一个 texture 对象而产生额外内存开销。
*
* @see egret.Texture
* @version Egret 2.4
* @platform Web,Native
* @includeExample egret/display/Bitmap.ts
* @language zh_CN
*/
export class Bitmap extends DisplayObject {
/**
* Initializes a Bitmap object to refer to the specified Texture object.
* @param value The Texture object being referenced.
* @version Egret 2.4
* @platform Web,Native
* @language en_US
*/
/**
* 创建一个引用指定 Texture 实例的 Bitmap 对象
* @param value 被引用的 Texture 实例
* @version Egret 2.4
* @platform Web,Native
* @language zh_CN
*/
public constructor(value?: Texture) {
super();
this.$renderNode = new sys.NormalBitmapNode();
this.$setTexture(value);
if (value) {
(<sys.NormalBitmapNode>this.$renderNode).rotated = value.$rotated;
}
}
protected $texture: Texture = null;
public $bitmapData: BitmapData = null;
protected $bitmapX: number = 0;
protected $bitmapY: number = 0;
protected $bitmapWidth: number = 0;
protected $bitmapHeight: number = 0;
protected $offsetX: number = 0;
protected $offsetY: number = 0;
protected $textureWidth: number = 0;
protected $textureHeight: number = 0;
protected $sourceWidth: number = 0;
protected $sourceHeight: number = 0;
protected $smoothing: boolean = Bitmap.defaultSmoothing;
protected $explicitBitmapWidth: number = NaN;
protected $explicitBitmapHeight: number = NaN;
/**
* @private
* 显示对象添加到舞台
*/
$onAddToStage(stage: Stage, nestLevel: number): void {
super.$onAddToStage(stage, nestLevel);
let texture = this.$texture;
if (texture) {
BitmapData.$addDisplayObject(this, texture.$bitmapData);
}
}
/**
* @private
* 显示对象从舞台移除
*/
$onRemoveFromStage(): void {
super.$onRemoveFromStage();
let texture = this.$texture;
if (texture) {
BitmapData.$removeDisplayObject(this, texture.$bitmapData);
}
}
/**
* The Texture object being referenced.
* If you pass the constructor of type BitmapData or last set for bitmapData, this value returns null.
* @version Egret 2.4
* @platform Web,Native
* @language en_US
*/
/**
* 被引用的 Texture 对象。
* 如果传入构造函数的类型为 BitmapData 或者最后设置的为 bitmapData,则此值返回 null。
* @version Egret 2.4
* @platform Web,Native
* @language zh_CN
*/
public get texture(): Texture {
return this.$texture;
}
public set texture(value: Texture) {
let self = this;
self.$setTexture(value);
if (value && self.$renderNode) {
(<sys.BitmapNode>self.$renderNode).rotated = value.$rotated;
}
}
/**
* @private
*/
$setTexture(value: Texture): boolean {
let self = this;
let oldBitmapData = self.$texture;
if (value == oldBitmapData) {
return false;
}
self.$texture = value;
if (value) {
self.$refreshImageData();
}
else {
if (oldBitmapData) {
BitmapData.$removeDisplayObject(self, oldBitmapData.$bitmapData);
}
self.setImageData(null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
self.$renderDirty = true;
let p = self.$parent;
if (p && !p.$cacheDirty) {
p.$cacheDirty = true;
p.$cacheDirtyUp();
}
let maskedObject = self.$maskedObject;
if (maskedObject && !maskedObject.$cacheDirty) {
maskedObject.$cacheDirty = true;
maskedObject.$cacheDirtyUp();
}
return true;
}
if (self.$stage) {
if (oldBitmapData) {
let oldHashCode: number = oldBitmapData.$bitmapData.hashCode;
let newHashCode: number = value.$bitmapData.hashCode;
if (oldHashCode == newHashCode) {
self.$renderDirty = true;
let p = self.$parent;
if (p && !p.$cacheDirty) {
p.$cacheDirty = true;
p.$cacheDirtyUp();
}
let maskedObject = self.$maskedObject;
if (maskedObject && !maskedObject.$cacheDirty) {
maskedObject.$cacheDirty = true;
maskedObject.$cacheDirtyUp();
}
return true;
}
BitmapData.$removeDisplayObject(self, oldBitmapData.$bitmapData);
}
BitmapData.$addDisplayObject(self, value.$bitmapData);
}
self.$renderDirty = true;
let p = self.$parent;
if (p && !p.$cacheDirty) {
p.$cacheDirty = true;
p.$cacheDirtyUp();
}
let maskedObject = self.$maskedObject;
if (maskedObject && !maskedObject.$cacheDirty) {
maskedObject.$cacheDirty = true;
maskedObject.$cacheDirtyUp();
}
return true;
}
$setBitmapData(value): void {
this.$setTexture(value);
}
/**
* @private
*/
public $refreshImageData(): void {
let texture: Texture = this.$texture;
if (texture) {
this.setImageData(texture.$bitmapData,
texture.$bitmapX, texture.$bitmapY,
texture.$bitmapWidth, texture.$bitmapHeight,
texture.$offsetX, texture.$offsetY,
texture.$getTextureWidth(), texture.$getTextureHeight(),
texture.$sourceWidth, texture.$sourceHeight);
}
}
/**
* @private
*/
private setImageData(bitmapData: BitmapData, bitmapX: number, bitmapY: number, bitmapWidth: number, bitmapHeight: number,
offsetX: number, offsetY: number, textureWidth: number, textureHeight: number, sourceWidth: number, sourceHeight: number): void {
this.$bitmapData = bitmapData;
this.$bitmapX = bitmapX;
this.$bitmapY = bitmapY;
this.$bitmapWidth = bitmapWidth;
this.$bitmapHeight = bitmapHeight;
this.$offsetX = offsetX;
this.$offsetY = offsetY;
this.$textureWidth = textureWidth;
this.$textureHeight = textureHeight;
this.$sourceWidth = sourceWidth;
this.$sourceHeight = sourceHeight;
}
/**
* @private
*/
$scale9Grid: egret.Rectangle = null;
/**
* Represent a Rectangle Area that the 9 scale area of Image.
* Notice: This property is valid only when <code>fillMode</code>
* is <code>BitmapFillMode.SCALE</code>.
*
* @version Egret 2.4
* @platform Web,Native
* @language en_US
*/
/**
* 矩形区域,它定义素材对象的九个缩放区域。
* 注意:此属性仅在<code>fillMode</code>为<code>BitmapFillMode.SCALE</code>时有效。
*
* @version Egret 2.4
* @platform Web,Native
* @language zh_CN
*/
public get scale9Grid(): egret.Rectangle {
return this.$scale9Grid;
}
public set scale9Grid(value: egret.Rectangle) {
let self = this;
self.$scale9Grid = value;
self.$renderDirty = true;
let p = self.$parent;
if (p && !p.$cacheDirty) {
p.$cacheDirty = true;
p.$cacheDirtyUp();
}
let maskedObject = self.$maskedObject;
if (maskedObject && !maskedObject.$cacheDirty) {
maskedObject.$cacheDirty = true;
maskedObject.$cacheDirtyUp();
}
}
/**
* @private
*/
$fillMode: string = "scale";
/**
* Determines how the bitmap fills in the dimensions.
* <p>When set to <code>BitmapFillMode.REPEAT</code>, the bitmap
* repeats to fill the region.</p>
* <p>When set to <code>BitmapFillMode.SCALE</code>, the bitmap
* stretches to fill the region.</p>
*
* @default <code>BitmapFillMode.SCALE</code>
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web
* @language en_US
*/
/**
* 确定位图填充尺寸的方式。
* <p>设置为 <code>BitmapFillMode.REPEAT</code>时,位图将重复以填充区域。</p>
* <p>设置为 <code>BitmapFillMode.SCALE</code>时,位图将拉伸以填充区域。</p>
*
* @default <code>BitmapFillMode.SCALE</code>
*
* @version Egret 2.4
* @version eui 1.0
* @platform Web
* @language zh_CN
*/
public get fillMode(): string {
return this.$fillMode;
}
public set fillMode(value: string) {
this.$setFillMode(value);
}
$setFillMode(value: string): boolean {
if (value == this.$fillMode) {
return false;
}
this.$fillMode = value;
return true;
}
/**
* The default value of whether or not is smoothed when scaled.
* When object such as Bitmap is created,smoothing property will be set to this value.
* @default true。
* @version Egret 3.0
* @platform Web
* @language en_US
*/
/**
* 控制在缩放时是否进行平滑处理的默认值。
* 在 Bitmap 等对象创建时,smoothing 属性会被设置为该值。
* @default true。
* @version Egret 3.0
* @platform Web
* @language zh_CN
*/
public static defaultSmoothing: boolean = true;
/**
* Whether or not the bitmap is smoothed when scaled.
* @version Egret 2.4
* @platform Web
* @language en_US
*/
/**
* 控制在缩放时是否对位图进行平滑处理。
* @version Egret 2.4
* @platform Web
* @language zh_CN
*/
public get smoothing(): boolean {
return this.$smoothing;
}
public set smoothing(value: boolean) {
value = !!value;
if (value == this.$smoothing) {
return;
}
this.$smoothing = value;
(<sys.BitmapNode>this.$renderNode).smoothing = value;
}
/**
* @private
*
* @param value
*/
$setWidth(value: number): boolean {
let self = this;
if (value < 0 || value == self.$explicitBitmapWidth) {
return false;
}
self.$explicitBitmapWidth = value;
self.$renderDirty = true;
let p = self.$parent;
if (p && !p.$cacheDirty) {
p.$cacheDirty = true;
p.$cacheDirtyUp();
}
let maskedObject = self.$maskedObject;
if (maskedObject && !maskedObject.$cacheDirty) {
maskedObject.$cacheDirty = true;
maskedObject.$cacheDirtyUp();
}
return true;
}
/**
* @private
*
* @param value
*/
$setHeight(value: number): boolean {
let self = this;
if (value < 0 || value == self.$explicitBitmapHeight) {
return false;
}
self.$explicitBitmapHeight = value;
self.$renderDirty = true;
let p = self.$parent;
if (p && !p.$cacheDirty) {
p.$cacheDirty = true;
p.$cacheDirtyUp();
}
let maskedObject = self.$maskedObject;
if (maskedObject && !maskedObject.$cacheDirty) {
maskedObject.$cacheDirty = true;
maskedObject.$cacheDirtyUp();
}
return true;
}
/**
* @private
* 获取显示宽度
*/
$getWidth(): number {
return isNaN(this.$explicitBitmapWidth) ? this.$getContentBounds().width : this.$explicitBitmapWidth;
}
/**
* @private
* 获取显示宽度
*/
$getHeight(): number {
return isNaN(this.$explicitBitmapHeight) ? this.$getContentBounds().height : this.$explicitBitmapHeight;
}
/**
* @private
*/
$measureContentBounds(bounds: Rectangle): void {
if (this.$bitmapData) {
let w: number = !isNaN(this.$explicitBitmapWidth) ? this.$explicitBitmapWidth : this.$textureWidth;
let h: number = !isNaN(this.$explicitBitmapHeight) ? this.$explicitBitmapHeight : this.$textureHeight;
bounds.setTo(0, 0, w, h);
}
else {
let w = !isNaN(this.$explicitBitmapWidth) ? this.$explicitBitmapWidth : 0;
let h = !isNaN(this.$explicitBitmapHeight) ? this.$explicitBitmapHeight : 0;
bounds.setTo(0, 0, w, h);
}
}
/**
* @private
*/
$updateRenderNode(): void {
if (this.$texture) {
let destW: number = !isNaN(this.$explicitBitmapWidth) ? this.$explicitBitmapWidth : this.$textureWidth;
let destH: number = !isNaN(this.$explicitBitmapHeight) ? this.$explicitBitmapHeight : this.$textureHeight;
let scale9Grid = this.scale9Grid || this.$texture["scale9Grid"];
if (scale9Grid) {
if (this.$renderNode instanceof sys.NormalBitmapNode) {
this.$renderNode = new sys.BitmapNode();
}
sys.BitmapNode.$updateTextureDataWithScale9Grid(<sys.NormalBitmapNode>this.$renderNode, this.$bitmapData, scale9Grid,
this.$bitmapX, this.$bitmapY, this.$bitmapWidth, this.$bitmapHeight,
this.$offsetX, this.$offsetY, this.$textureWidth, this.$textureHeight,
destW, destH, this.$sourceWidth, this.$sourceHeight, this.$smoothing);
}
else {
if (this.fillMode == egret.BitmapFillMode.REPEAT && this.$renderNode instanceof sys.NormalBitmapNode) {
this.$renderNode = new sys.BitmapNode();
}
sys.BitmapNode.$updateTextureData(<sys.NormalBitmapNode>this.$renderNode, this.$bitmapData,
this.$bitmapX, this.$bitmapY, this.$bitmapWidth, this.$bitmapHeight,
this.$offsetX, this.$offsetY, this.$textureWidth, this.$textureHeight,
destW, destH, this.$sourceWidth, this.$sourceHeight, this.$fillMode, this.$smoothing);
}
}
}
private _pixelHitTest: boolean = false;
/**
* Specifies whether this object use precise hit testing by checking the alpha value of each pixel.If pixelHitTest
* is set to true,the transparent area of the bitmap will be touched through.<br/>
* Note:If the image is loaded from cross origin,that we can't access to the pixel data,so it might cause
* the pixelHitTest property invalid.
* @default false
* @version Egret 2.4
* @platform Web,Native
* @language en_US
*/
/**
* 是否开启精确像素碰撞。设置为true显示对象本身的透明区域将能够被穿透。<br/>
* 注意:若图片资源是以跨域方式从外部服务器加载的,将无法访问图片的像素数据,而导致此属性失效。
* @default false
* @version Egret 2.4
* @platform Web,Native
* @language zh_CN
*/
public get pixelHitTest(): boolean {
return this._pixelHitTest;
}
public set pixelHitTest(value: boolean) {
this._pixelHitTest = !!value;
}
$hitTest(stageX: number, stageY: number): DisplayObject {
let target = super.$hitTest(stageX, stageY);
if (target && this._pixelHitTest) {
target = this.hitTestPixel(stageX, stageY);
}
return target;
}
/**
* @private
*/
private hitTestPixel(stageX: number, stageY: number): DisplayObject {
let m = this.$getInvertedConcatenatedMatrix();
let localX = m.a * stageX + m.c * stageY + m.tx;
let localY = m.b * stageX + m.d * stageY + m.ty;
let data: number[];
let displayList = this.$displayList;
if (displayList) {
let buffer = displayList.renderBuffer;
try {
data = buffer.getPixels(localX - displayList.offsetX, localY - displayList.offsetY);
}
catch (e) {
console.log(this.$texture);
throw new Error(sys.tr(1039));
}
}
else {
let buffer = sys.customHitTestBuffer;
buffer.resize(3, 3);
let node = this.$getRenderNode();
let matrix = Matrix.create();
matrix.identity();
matrix.translate(1 - localX, 1 - localY);
sys.systemRenderer.drawNodeToBuffer(node, buffer, matrix, true);
Matrix.release(matrix);
try {
data = buffer.getPixels(1, 1);
}
catch (e) {
console.log(this.$texture);
throw new Error(sys.tr(1039));
}
}
if (data[3] === 0) {
return null;
}
return this;
}
}
}