@awayjs/scene
Version:
AwayJS scene classes
398 lines (397 loc) • 15.3 kB
JavaScript
import { __extends } from "tslib";
import { PickEntity, _Pick_PickableBase, } from '@awayjs/view';
import { MaterialEvent, } from '@awayjs/renderer';
import { Rectangle, Box, Vector3D } from '@awayjs/core';
import { ImageSampler, ContextGLTriangleFace, } from '@awayjs/stage';
import { DisplayObjectContainer } from './DisplayObjectContainer';
/**
* The Billboard class represents display objects that represent bitmap images.
* These can be images that you load with the <code>flash.Assets</code> or
* <code>flash.display.Loader</code> classes, or they can be images that you
* create with the <code>Billboard()</code> constructor.
*
* <p>The <code>Billboard()</code> constructor allows you to create a Billboard
* object that contains a reference to a Image2D object. After you create a
* Billboard object, use the <code>addChild()</code> or <code>addChildAt()</code>
* method of the parent DisplayObjectContainer instance to place the bitmap on
* the display list.</p>
*
* <p>A Billboard object can share its Image2D reference among several Billboard
* objects, independent of translation or rotation properties. Because you can
* create multiple Billboard objects that reference the same Image2D object,
* multiple display objects can use the same complex Image2D object without
* incurring the memory overhead of a Image2D object for each display
* object instance.</p>
*
* <p>A Image2D object can be drawn to the screen by a Billboard object in one
* of two ways: by using the default hardware renderer with a single hardware surface,
* or by using the slower software renderer when 3D acceleration is not available.</p>
*
* <p>If you would prefer to perform a batch rendering command, rather than using a
* single surface for each Billboard object, you can also draw to the screen using the
* <code>drawTiles()</code> or <code>drawTriangles()</code> methods which are
* available to <code>flash.display.Tilesheet</code> and <code>flash.display.Graphics
* objects.</code></p>
*
* <p><b>Note:</b> The Billboard class is not a subclass of the InteractiveObject
* class, so it cannot dispatch mouse events. However, you can use the
* <code>addEventListener()</code> method of the display object container that
* contains the Billboard object.</p>
*/
/**
* @todo billboard needed to extend on DisplayObjectContainer in order
* for as3web/away3d adapters to compile without errors
* (in away3d Sprite3D extends on ObjectContainer3D)
*/
var Billboard = /** @class */ (function (_super) {
__extends(Billboard, _super);
function Billboard(material, _pixelSnapping, smoothing) {
if (_pixelSnapping === void 0) { _pixelSnapping = 'auto'; }
if (smoothing === void 0) { smoothing = false; }
var _this = _super.call(this) || this;
_this._pickObjects = {};
_this.preserveDimensions = false;
_this._onInvalidateTextureDelegate = function (event) { return _this._onInvalidateTexture(event); };
_this.style = new Style();
_this.style.sampler = new ImageSampler(false, smoothing, false);
_this.material = material;
_this._updateDimensions();
return _this;
}
Billboard.getNewBillboard = function (material, pixelSnapping, smoothing) {
if (pixelSnapping === void 0) { pixelSnapping = 'auto'; }
if (smoothing === void 0) { smoothing = false; }
if (Billboard._billboards.length) {
var billboard = Billboard._billboards.pop();
billboard.material = material;
//billboard.pixelSnapping = pixelSnapping;
//billboard.smoothing = smoothing;
return billboard;
}
return new Billboard(material, pixelSnapping, smoothing);
};
Object.defineProperty(Billboard.prototype, "assetType", {
/**
*
*/
get: function () {
return Billboard.assetType;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Billboard.prototype, "billboardRect", {
/**
*
*/
get: function () {
return this._billboardRect;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Billboard.prototype, "billboardHeight", {
/**
*
*/
get: function () {
return this._billboardHeight;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Billboard.prototype, "billboardWidth", {
/**
*
*/
get: function () {
return this._billboardWidth;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Billboard.prototype, "material", {
/**
*
*/
get: function () {
return this._material;
},
set: function (value) {
if (value == this._material)
return;
if (this._material)
this._material.removeEventListener(MaterialEvent.INVALIDATE_TEXTURES, this._onInvalidateTextureDelegate);
this._material = value;
if (this._material)
this._material.addEventListener(MaterialEvent.INVALIDATE_TEXTURES, this._onInvalidateTextureDelegate);
this._updateDimensions();
this._invalidateMaterial();
},
enumerable: false,
configurable: true
});
Object.defineProperty(Billboard.prototype, "width", {
/**
*
*/
get: function () {
return this._width;
},
set: function (val) {
if (this._width == val)
return;
this._width = val;
this.scaleX = this._width / this._billboardRect.width;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Billboard.prototype, "height", {
/**
*
*/
get: function () {
return this._height;
},
set: function (val) {
if (this._height == val)
return;
this._height = val;
this.scaleY = this._height / this._billboardRect.height;
},
enumerable: false,
configurable: true
});
Billboard.prototype.invalidateElements = function () {
for (var key in this._pickObjects)
this._pickObjects[key]._onInvalidateElements();
_super.prototype.invalidateElements.call(this);
};
Billboard.prototype.advanceFrame = function () {
//override for billboard
};
Billboard.prototype.getEntity = function () {
return this;
};
/**
* @inheritDoc
*/
Billboard.prototype.dispose = function () {
this.disposeValues();
Billboard._billboards.push(this);
};
Billboard.prototype.clone = function () {
var newInstance = Billboard.getNewBillboard(this._material);
this.copyTo(newInstance);
return newInstance;
};
Billboard.prototype._acceptTraverser = function (traverser) {
if (!this.material) {
return;
}
var texture = this.material.getTextureAt(0);
if (!texture) {
return;
}
var image = this.image;
if (!image || image.isDisposed) {
return;
}
traverser.applyTraversable(this);
};
Object.defineProperty(Billboard.prototype, "image", {
get: function () {
var _a, _b;
if (!this.material) {
return null;
}
var texture = this.material.getTextureAt(0);
if (!texture) {
return null;
}
var image = (_a = this._style) === null || _a === void 0 ? void 0 : _a.getImageAt(texture);
if (image) {
return image;
}
image = (_b = this.material.style) === null || _b === void 0 ? void 0 : _b.getImageAt(texture);
if (image) {
return image;
}
return texture.getImageAt(0);
},
enumerable: false,
configurable: true
});
Billboard.prototype._updateDimensions = function () {
var image = this.image;
if (image && !image.isDisposed) {
var sampler = this.style.sampler;
if (sampler.imageRect) {
this._billboardWidth = sampler.imageRect.width * image.width;
this._billboardHeight = sampler.imageRect.height * image.height;
}
else {
this._billboardWidth = image.rect.width;
this._billboardHeight = image.rect.height;
}
this._billboardRect =
sampler.frameRect || new Rectangle(0, 0, this._billboardWidth, this._billboardHeight);
}
else {
this._billboardWidth = 1;
this._billboardHeight = 1;
this._billboardRect = new Rectangle(0, 0, 1, 1);
}
this.invalidate();
this.invalidateElements();
if (!this.preserveDimensions) {
this._width = this._billboardRect.width * this.scaleX;
this._height = this._billboardRect.height * this.scaleY;
}
else {
this.scaleX = this._width / this._billboardRect.width;
this.scaleY = this._height / this._billboardRect.height;
}
};
Billboard.prototype._onInvalidateProperties = function (event) {
if (event === void 0) { event = null; }
_super.prototype._onInvalidateProperties.call(this, event);
this._updateDimensions();
};
/**
* @private
*/
Billboard.prototype._onInvalidateTexture = function (event) {
this._updateDimensions();
};
Billboard._billboards = new Array();
Billboard.assetType = '[asset Billboard]';
return Billboard;
}(DisplayObjectContainer));
export { Billboard };
import { AttributesBuffer } from '@awayjs/stage';
import { MaterialUtils, _Render_RenderableBase, RenderEntity, Style, TriangleElements } from '@awayjs/renderer';
/**
* @class away.pool.RenderableListItem
*/
var _Render_Billboard = /** @class */ (function (_super) {
__extends(_Render_Billboard, _super);
function _Render_Billboard() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* //TODO
*
* @returns {away.base.TriangleElements}
*/
_Render_Billboard.prototype._getStageElements = function () {
var asset = this.renderable;
var width = asset.billboardWidth;
var height = asset.billboardHeight;
var rect = asset.billboardRect;
var id = width.toString() + height.toString() + rect.toString();
this._id = id;
var elements = _Render_Billboard._samplerElements[id];
if (!elements) {
var left = -rect.x;
var top_1 = -rect.y;
var right = width - rect.x;
var bottom = height - rect.y;
elements = _Render_Billboard._samplerElements[id] = new TriangleElements(new AttributesBuffer(11, 4));
elements.autoDeriveNormals = false;
elements.autoDeriveTangents = false;
/**
* 2 tris with CCW order
* 0(3) 2
* _____
*|\ |
*| \ |
*| \ |
*|___\|
*4 1(5)
*
*/
elements.setPositions([
left, top_1, 0,
right, bottom, 0,
right, top_1, 0,
left, top_1, 0,
left, bottom, 0,
right, bottom, 0
]);
elements.setUVs([0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1]);
} /* else {
elements.setPositions(
[-billboardRect.x, height - billboardRect.y, 0,
width - billboardRect.x, height - billboardRect.y, 0,
width - billboardRect.x, -billboardRect.y, 0,
-billboardRect.x, -billboardRect.y, 0]);
}*/
return this._stage.abstractions.getAbstraction(elements);
};
_Render_Billboard.prototype.draw = function () {
// disable cull, because for render to texture it is bugged
// we flip normals
this._stage.context.setCulling(ContextGLTriangleFace.NONE);
_super.prototype.draw.call(this);
};
_Render_Billboard.prototype._getRenderMaterial = function () {
return this.entity.renderer
.getRenderElements(this.stageElements.elements).abstractions
.getAbstraction(this.renderable.material || MaterialUtils.getDefaultColorMaterial());
};
_Render_Billboard.prototype._getStyle = function () {
return this.renderable.style;
};
_Render_Billboard._samplerElements = new Object();
return _Render_Billboard;
}(_Render_RenderableBase));
export { _Render_Billboard };
/**
* @class away.pool._Render_Shape
*/
var _Pick_Billboard = /** @class */ (function (_super) {
__extends(_Pick_Billboard, _super);
function _Pick_Billboard() {
return _super !== null && _super.apply(this, arguments) || this;
}
_Pick_Billboard.prototype.hitTestPoint = function (x, y, z) {
return true;
};
_Pick_Billboard.prototype.getBoxBounds = function (matrix3D, strokeFlag, cache, target) {
if (matrix3D === void 0) { matrix3D = null; }
if (strokeFlag === void 0) { strokeFlag = true; }
if (cache === void 0) { cache = null; }
if (target === void 0) { target = null; }
if (this._orientedBoxBoundsDirty) {
this._orientedBoxBoundsDirty = false;
var billboardRect = this.pickable.billboardRect;
this._orientedBoxBounds = new Box(billboardRect.x, billboardRect.y, 0, billboardRect.width, billboardRect.height, 0);
}
return (matrix3D
? matrix3D.transformBox(this._orientedBoxBounds)
: this._orientedBoxBounds).union(target, target || cache);
};
_Pick_Billboard.prototype.getSphereBounds = function (center, matrix3D, strokeFlag, cache, target) {
if (matrix3D === void 0) { matrix3D = null; }
if (strokeFlag === void 0) { strokeFlag = true; }
if (cache === void 0) { cache = null; }
if (target === void 0) { target = null; }
//TODO
return target;
};
_Pick_Billboard.prototype.testCollision = function (collision, closestFlag) {
var rayEntryDistance = -collision.rayPosition.z / collision.rayDirection.z;
var position = new Vector3D(collision.rayPosition.x + rayEntryDistance * collision.rayDirection.x, collision.rayPosition.y + rayEntryDistance * collision.rayDirection.y);
collision.pickable = this.pickable;
collision.rayEntryDistance = rayEntryDistance;
collision.position = position;
collision.normal = new Vector3D(0, 0, 1);
return true;
};
return _Pick_Billboard;
}(_Pick_PickableBase));
export { _Pick_Billboard };
RenderEntity.registerRenderable(_Render_Billboard, Billboard);
PickEntity.registerPickable(_Pick_Billboard, Billboard);