UNPKG

@awayjs/scene

Version:
398 lines (397 loc) 15.3 kB
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);