UNPKG

@awayjs/graphics

Version:
419 lines (418 loc) 16.5 kB
import { __extends } from "tslib"; import { AssetBase } from '@awayjs/core'; import { PickEntity, _Pick_PickableBase, PickGroup } from '@awayjs/view'; import { StyleEvent, ElementsEvent, TriangleElements } from '@awayjs/renderer'; /** * Graphic wraps a Elements as a scene graph instantiation. A Graphic is owned by a Sprite object. * * * @see away.base.ElementsBase * @see away.entities.Sprite * * @class away.base.Graphic */ var Shape = /** @class */ (function (_super) { __extends(Shape, _super); /** * Creates a new Shape object */ function Shape(elements, material, style, count, offset) { if (material === void 0) { material = null; } if (style === void 0) { style = null; } if (count === void 0) { count = 0; } if (offset === void 0) { offset = 0; } var _this = _super.call(this) || this; _this._renderObjects = {}; _this._pickObjects = {}; _this.usages = 0; _this.count = 0; _this.offset = 0; _this.particleCollection = null; _this.originalFillStyle = null; /** * Process per-triangle hit test - superslow for huge elements */ _this.deepHitCheck = true; _this._onInvalidatePropertiesDelegate = function (event) { return _this._onInvalidateProperties(event); }; _this._onInvalidateVerticesDelegate = function (event) { return _this._onInvalidateVertices(event); }; _this._elements = elements; _this._elements.addEventListener(ElementsEvent.INVALIDATE_VERTICES, _this._onInvalidateVerticesDelegate); _this._elements.usages++; _this._material = material; _this._style = style; if (_this._style) _this._style.addEventListener(StyleEvent.INVALIDATE_PROPERTIES, _this._onInvalidatePropertiesDelegate); _this.count = count; _this.offset = offset; return _this; } Shape.getShape = function (elements, material, style, count, offset) { if (material === void 0) { material = null; } if (style === void 0) { style = null; } if (count === void 0) { count = 0; } if (offset === void 0) { offset = 0; } if (Shape._pool.length) { var shape = Shape._pool.pop(); shape.elements = elements; shape.material = material; shape.style = style; shape.count = count; shape.offset = offset; return shape; } return new Shape(elements, material, style, count, offset); }; Shape.clearPool = function () { Shape._pool = []; }; Shape.quadElement = function (rect, slices, genUv) { if (slices === void 0) { slices = 1; } if (genUv === void 0) { genUv = false; } var verts = []; var uvs = []; var w = rect.width / slices; var h = rect.height / slices; var ix = rect.x; var iy = rect.y; for (var i = 0; i < slices; i++) { for (var j = 0; j < slices; j++) { var x = ix + j * w; var y = iy + i * h; var right = x + w; var bottom = y + h; verts.push(x, y, 0, right, bottom, 0, right, y, 0, x, y, 0, x, bottom, 0, right, bottom, 0); if (uvs) { uvs.push(j / slices, i / slices, (j + 1) / slices, (i + 1) / slices, (j + 1) / slices, i / slices, j / slices, i / slices, j / slices, (i + 1) / slices, (j + 1) / slices, (i + 1) / slices); } } } var elements = new TriangleElements(); elements.setPositions(verts); genUv && elements.setUVs(uvs); return elements; }; // legacy Shape.getElement = function (rectangle) { var x = rectangle.x, y = rectangle.y, right = rectangle.right, bottom = rectangle.bottom; var elements = new TriangleElements(); elements.setPositions([ x, y, 0, right, y, 0, right, bottom, 0, x, y, 0, x, bottom, 0, right, bottom, 0, ]); return elements; }; Shape.getTriangleElement = function (rectangle, cache, uv, slices) { var _this = this; if (cache === void 0) { cache = true; } if (uv === void 0) { uv = false; } if (slices === void 0) { slices = 1; } var id = rectangle.toString(); var elements = cache ? this._imageShapeElements[id] : null; if (!elements) { elements = Shape.quadElement(rectangle, slices, uv); if (cache) { this._imageShapeElements[id] = elements; // remove it from pool, when forget about shared usage elements.addEventListener(AssetEvent.CLEAR, function () { delete _this._imageShapeElements[id]; elements.usages = 0; }); elements.usages++; } } return elements; }; Object.defineProperty(Shape.prototype, "elements", { /** * The Elements object which provides the geometry data for this Shape. */ get: function () { return this._elements; }, set: function (value) { if (this._elements == value) return; if (this._elements) { this._elements.removeEventListener(ElementsEvent.INVALIDATE_VERTICES, this._onInvalidateVerticesDelegate); this._elements.usages--; if (!this._elements.usages) this._elements.dispose(); } this._elements = value; if (this._elements) { this._elements.addEventListener(ElementsEvent.INVALIDATE_VERTICES, this._onInvalidateVerticesDelegate); this._elements.usages++; } this.invalidateElements(); }, enumerable: false, configurable: true }); Object.defineProperty(Shape.prototype, "assetType", { /** * */ get: function () { return Shape.assetType; }, enumerable: false, configurable: true }); Object.defineProperty(Shape.prototype, "material", { /** * The material used to render the current Shape. * If set to null, the containing Graphics's material will be used instead. */ get: function () { return this._material; }, set: function (value) { if (this._material == value) return; this._material = value; this.invalidateMaterial(); }, enumerable: false, configurable: true }); Object.defineProperty(Shape.prototype, "style", { /** * The style used to render the current Shape. If set to null, its parent Sprite's style will be used instead. */ get: function () { return this._style; }, set: function (value) { if (this._style == value) return; if (this._style) this._style.removeEventListener(StyleEvent.INVALIDATE_PROPERTIES, this._onInvalidatePropertiesDelegate); this._style = value; if (this._style) this._style.addEventListener(StyleEvent.INVALIDATE_PROPERTIES, this._onInvalidatePropertiesDelegate); this.invalidateStyle(); }, enumerable: false, configurable: true }); /** * */ Shape.prototype.dispose = function () { _super.prototype.clear.call(this); this.usages = 0; this.elements = null; this.material = null; this.style = null; this.particleCollection = null; Shape._pool.push(this); }; Shape.prototype.invalidateElements = function () { for (var key in this._pickObjects) this._pickObjects[key]._onInvalidateElements(); for (var key in this._renderObjects) this._renderObjects[key]._onInvalidateElements(); }; Shape.prototype.invalidateMaterial = function () { for (var key in this._renderObjects) this._renderObjects[key]._onInvalidateMaterial(); }; Shape.prototype.invalidateStyle = function () { for (var key in this._renderObjects) this._renderObjects[key]._onInvalidateStyle(); }; Shape.prototype._onInvalidateProperties = function (event) { this.invalidateStyle(); }; Shape.prototype._onInvalidateVertices = function (event) { if (event.attributesView != event.target.positions) return; this.invalidate(); }; /** * //TODO * * @param shortestCollisionDistance * @param findClosest * @returns {boolean} * * @internal */ Shape.prototype.applyTransformation = function (transform) { this._elements.applyTransformation(transform, this.count, this.offset); }; Shape.prototype.scale = function (scale) { this._elements.scale(scale, this.count, this.offset); }; Shape.prototype.scaleUV = function (scaleU, scaleV) { if (scaleU === void 0) { scaleU = 1; } if (scaleV === void 0) { scaleV = 1; } this._elements.scaleUV(scaleU, scaleV, this.count, this.offset); }; Shape._pool = new Array(); Shape.assetType = '[asset Shape]'; Shape._imageShapeElements = {}; return Shape; }(AssetBase)); export { Shape }; import { AssetEvent } from '@awayjs/core'; import { _Render_RenderableBase, RenderEntity, MaterialUtils, LineElements } from '@awayjs/renderer'; import { BitmapFillStyle } from '../draw/fills/BitmapFillStyle'; /** * @class away.pool._Render_Shape */ var _Render_Shape = /** @class */ (function (_super) { __extends(_Render_Shape, _super); function _Render_Shape() { return _super !== null && _super.apply(this, arguments) || this; } /** * //TODO * * @param renderEntity * @param shape * @param level * @param indexOffset */ _Render_Shape.prototype.init = function (shape, renderEntity) { _super.prototype.init.call(this, shape, renderEntity); }; _Render_Shape.prototype.onClear = function () { _super.prototype.onClear.call(this); this._scaleX = null; this._scaleY = null; this._scale9Elements = null; }; /** * * @returns {ElementsBase} * @protected */ _Render_Shape.prototype._getStageElements = function () { var shape = this.renderable; this._offset = shape.offset; this._count = shape.count; var _scale9Container = this.entity.node.getScale9Container(); if (_scale9Container) { return this._stage.abstractions .getAbstraction(this.updateScale9(_scale9Container.scale9Grid, _scale9Container.transform.scale.x, _scale9Container.transform.scale.y)); } var container = this.entity.node.container; var elements = container.animator ? container.animator.getRenderableElements(this, shape.elements) : shape.elements; return this._stage.abstractions.getAbstraction(elements); }; _Render_Shape.prototype._getRenderMaterial = function () { var shape = this.renderable; return this.entity.renderer .getRenderElements(shape.elements).abstractions .getAbstraction(shape.material || this.entity.node.container.material || this.getDefaultMaterial()); }; _Render_Shape.prototype._getStyle = function () { return this.renderable.style || this.entity.node.container.style; }; _Render_Shape.prototype.getDefaultMaterial = function () { return this.stageElements.elements instanceof LineElements ? MaterialUtils.getDefaultColorMaterial() : MaterialUtils.getDefaultTextureMaterial(); }; _Render_Shape.prototype.updateScale9 = function (scale9Grid, scaleX, scaleY) { if (!this._scale9Elements) { var uvMatrix = null; var generateUV = false; var shape = this.renderable; if (shape.originalFillStyle instanceof BitmapFillStyle) uvMatrix = shape.originalFillStyle.getUVMatrix(); if (shape.elements instanceof TriangleElements) { generateUV = !shape.elements.uvs && !!uvMatrix; } // kill UV matrix if we will generate UV if (generateUV) { shape.style.uvMatrix = null; } var bounds = PickGroup.getInstance() .getBoundsPicker(this.entity.node) .getBoxBounds(this.entity.node, true, true); this._scale9Elements = shape.elements.prepareScale9(bounds, scale9Grid, true, generateUV, uvMatrix); } if (this._scaleX != scaleX || this._scaleY != scaleY) { this._scaleX = scaleX; this._scaleY = scaleY; this._scale9Elements.updateScale9(scaleX, scaleY); } return this._scale9Elements; }; return _Render_Shape; }(_Render_RenderableBase)); export { _Render_Shape }; /** * @class away.pool._Render_Shape */ var _Pick_Shape = /** @class */ (function (_super) { __extends(_Pick_Shape, _super); function _Pick_Shape() { return _super !== null && _super.apply(this, arguments) || this; } _Pick_Shape.prototype.hitTestPoint = function (x, y, z) { var box = this.getBoxBounds(); var shape = this.pickable; //early out for box test if (box == null || !box.contains(x, y, z)) return false; return shape.elements.hitTestPoint(this._pool.node, x, y, z, box, shape.count, shape.offset); }; _Pick_Shape.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; } var shape = this.pickable; if (matrix3D) return shape.elements.getBoxBounds(this._pool.node, strokeFlag, matrix3D, cache, target, shape.count, shape.offset); if (this._orientedBoxBoundsDirty) { this._orientedBoxBoundsDirty = false; this._orientedBoxBounds = shape.elements.getBoxBounds(this._pool.node, strokeFlag, null, this._orientedBoxBounds, null, shape.count, shape.offset); } if (this._orientedBoxBounds != null) target = this._orientedBoxBounds.union(target, target || cache); return target; }; _Pick_Shape.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; } var shape = this.pickable; if (matrix3D) return shape.elements.getSphereBounds(center, matrix3D, strokeFlag, cache, target, shape.count, shape.offset); if (this._orientedSphereBoundsDirty) { this._orientedSphereBoundsDirty = false; this._orientedSphereBounds = shape.elements.getSphereBounds(center, null, strokeFlag, this._orientedSphereBounds, null, shape.count, shape.offset); } if (this._orientedSphereBounds != null) target = this._orientedSphereBounds.union(target, target || cache); return target; }; _Pick_Shape.prototype.testCollision = function (collision, findClosestCollision) { var box = this.getBoxBounds(); var shape = this.pickable; //early out for box test if (box == null || !box.rayIntersection(collision.rayPosition, collision.rayDirection)) return false; if (!shape.deepHitCheck) { return true; } return shape.elements.testCollision(collision, box, findClosestCollision, shape.material || collision.containerNode.container.material, shape.count || shape.elements.numVertices, shape.offset); }; return _Pick_Shape; }(_Pick_PickableBase)); export { _Pick_Shape }; RenderEntity.registerRenderable(_Render_Shape, Shape); PickEntity.registerPickable(_Pick_Shape, Shape);