UNPKG

@awayjs/scene

Version:
247 lines (246 loc) 12.5 kB
import { __extends } from "tslib"; import { Matrix, ColorUtils } from '@awayjs/core'; import { GraphicsPathCommand, GraphicsFillStyle, GradientFillStyle, BitmapFillStyle, SolidFillStyle, GraphicsStrokeStyle, Graphics, GraphicsPath, } from '@awayjs/graphics'; import { Sprite } from './Sprite'; var ONCE_EMIT_MORPH_ERROR = Object.create(null); function once(obj, error) { if (error === void 0) { error = ''; } var has = ONCE_EMIT_MORPH_ERROR[obj._id + error]; ONCE_EMIT_MORPH_ERROR[obj._id + error] = true; if (!has) { console.warn('[MorphSprite] - id', obj.id, error, obj); } return !has; } var MorphSprite = /** @class */ (function (_super) { __extends(MorphSprite, _super); function MorphSprite() { var _this = _super !== null && _super.apply(this, arguments) || this; _this._frameCaches = {}; return _this; } MorphSprite.getNewMorphSprite = function (graphics, material) { if (graphics === void 0) { graphics = null; } if (material === void 0) { material = null; } if (MorphSprite._morphSprites.length) { var sprite = MorphSprite._morphSprites.pop(); sprite.graphics = graphics || Graphics.getGraphics(); sprite.material = material; return sprite; } return new MorphSprite(graphics, material); }; Object.defineProperty(MorphSprite.prototype, "assetType", { get: function () { return MorphSprite.assetType; }, enumerable: false, configurable: true }); MorphSprite.prototype.reset = function () { _super.prototype.reset.call(this); this.setRatio(0); }; MorphSprite.prototype._blendStyle = function (startPath, endPath, newPath, ratio) { var ratioStart = 1 - ratio; var ratioEnd = ratio; var color; var alpha; var startFillStyle = startPath.style.fillStyle; var endFillStyle = endPath.style.fillStyle; var resultFillStyle; if (startPath.style.data_type != endPath.style.data_type) { throw ('Error in morph data - different styles of pathes'); } switch (startFillStyle.data_type) { case SolidFillStyle.data_type: { var startStyle = startFillStyle; var endStyle = endFillStyle; alpha = ratioStart * startStyle.alpha + ratioEnd * endStyle.alpha; color = ColorUtils.interpolateFloat32Color(startStyle.color, endStyle.color, ratio); resultFillStyle = new SolidFillStyle(color, alpha); break; } case GradientFillStyle.data_type: { var newColors = []; var newRatios = []; var newAlphas = []; var startStyle = startFillStyle; var endStyle = endFillStyle; var clen = startStyle.colors.length; for (var c = 0; c < clen; c++) { newColors[newColors.length] = ColorUtils.interpolateFloat32Color(startStyle.colors[c], endStyle.colors[c], ratio); newAlphas[newAlphas.length] = ratioStart * startStyle.alphas[c] + ratioEnd * endStyle.alphas[c]; newRatios[newRatios.length] = ratioStart * startStyle.ratios[c] + ratioEnd * endStyle.ratios[c]; } //todo: interpolate uvtransform var startTrans = startStyle.matrix; var endTrans = endStyle.matrix; var newTrans = new Matrix(); newTrans.a = startTrans.a * ratioStart + endTrans.a * ratioEnd; newTrans.b = startTrans.b * ratioStart + endTrans.b * ratioEnd; newTrans.c = startTrans.c * ratioStart + endTrans.c * ratioEnd; newTrans.d = startTrans.d * ratioStart + endTrans.d * ratioEnd; newTrans.tx = startTrans.tx * ratioStart + endTrans.tx * ratioEnd; newTrans.ty = startTrans.ty * ratioStart + endTrans.ty * ratioEnd; resultFillStyle = new GradientFillStyle(startStyle.type, newColors, newAlphas, newRatios, newTrans, startStyle.spreadMethod, startStyle.interpolationMethod, startStyle.focalPointRatio); break; } case BitmapFillStyle.data_type: { //todo //console.warn("MorphSprite: BitmapFillStyle not implemented!"); var startStyle = startFillStyle; var endStyle = endFillStyle; //todo: interpolate uvtransform var startTrans = startStyle.matrix; var endTrans = endStyle.matrix; var newTrans = new Matrix(); newTrans.a = startTrans.a * ratioStart + endTrans.a * ratioEnd; newTrans.b = startTrans.b * ratioStart + endTrans.b * ratioEnd; newTrans.c = startTrans.c * ratioStart + endTrans.c * ratioEnd; newTrans.d = startTrans.d * ratioStart + endTrans.d * ratioEnd; newTrans.tx = startTrans.tx * ratioStart + endTrans.tx * ratioEnd; newTrans.ty = startTrans.ty * ratioStart + endTrans.ty * ratioEnd; resultFillStyle = new BitmapFillStyle(startStyle.material, newTrans, startStyle.repeat, startStyle.smooth); break; } } if (startPath.style.data_type === GraphicsStrokeStyle.data_type) { var startStyle = startPath.style; var endStyle = endPath.style; var thickness = ratioStart * startStyle.thickness + ratioEnd * endStyle.thickness; newPath.style = new GraphicsStrokeStyle(resultFillStyle, thickness, startStyle.jointstyle, startStyle.capstyle, startStyle.miterLimit, startStyle.scaleMode); } else { newPath.style = new GraphicsFillStyle(resultFillStyle); } }; MorphSprite.prototype._blendContours = function (startPath, endPath, newPath, ratio) { var ratioStart = 1 - ratio; var ratioEnd = ratio; var len_contours = startPath.commands.length; if (endPath.commands.length !== len_contours) { //len_contours = Math.min(endPath._commands.length, len_contours); throw ('Error in morph data - different number of contour'); } var startDataCnt = 0; var endDataCnt = 0; var startLastX = 0; var startLastY = 0; var endLastX = 0; var endLastY = 0; var startData = startPath.data; var endData = endPath.data; for (var c = 0; c < len_contours; c++) { var startCmd = startPath.commands[c]; var endCmd = endPath.commands[c]; switch (startCmd) { case GraphicsPathCommand.MOVE_TO: if (endCmd != GraphicsPathCommand.MOVE_TO) { throw ('Error in morph data - both shapes must start with Move too command'); } startLastX = startData[startDataCnt++]; startLastY = startData[startDataCnt++]; endLastX = endData[endDataCnt++]; endLastY = endData[endDataCnt++]; newPath.moveTo(ratioStart * startLastX + ratioEnd * endLastX, ratioStart * startLastY + ratioEnd * endLastY); break; case GraphicsPathCommand.LINE_TO: if (endCmd == GraphicsPathCommand.LINE_TO) { startLastX = startData[startDataCnt++]; startLastY = startData[startDataCnt++]; endLastX = endData[endDataCnt++]; endLastY = endData[endDataCnt++]; newPath.lineTo(ratioStart * startLastX + ratioEnd * endLastX, ratioStart * startLastY + ratioEnd * endLastY); } else if (endCmd == GraphicsPathCommand.CURVE_TO) { var ctrX = startLastX + (startData[startDataCnt++] - startLastX) / 2; var ctrY = startLastY + (startData[startDataCnt++] - startLastY) / 2; newPath.curveTo(ratioStart * ctrX + ratioEnd * endData[endDataCnt++], ratioStart * ctrY + ratioEnd * endData[endDataCnt++], ratioStart * startData[startDataCnt - 2] + ratioEnd * endData[endDataCnt++], ratioStart * startData[startDataCnt - 1] + ratioEnd * endData[endDataCnt++]); startLastX = startData[startDataCnt - 2]; startLastY = startData[startDataCnt - 1]; endLastX = endData[endDataCnt - 2]; endLastY = endData[endDataCnt - 1]; } break; case GraphicsPathCommand.CURVE_TO: if (endCmd == GraphicsPathCommand.LINE_TO) { var ctrX = endLastX + (endData[endDataCnt++] - endLastX) / 2; var ctrY = endLastY + (endData[endDataCnt++] - endLastY) / 2; newPath.curveTo(ratioStart * startData[startDataCnt++] + ratioEnd * ctrX, ratioStart * startData[startDataCnt++] + ratioEnd * ctrY, ratioStart * startData[startDataCnt++] + ratioEnd * endData[endDataCnt - 2], ratioStart * startData[startDataCnt++] + ratioEnd * endData[endDataCnt - 1]); startLastX = startData[startDataCnt - 2]; startLastY = startData[startDataCnt - 1]; endLastX = endData[endDataCnt - 2]; endLastY = endData[endDataCnt - 1]; } else if (endCmd == GraphicsPathCommand.CURVE_TO) { newPath.curveTo(ratioStart * startData[startDataCnt++] + ratioEnd * endData[endDataCnt++], ratioStart * startData[startDataCnt++] + ratioEnd * endData[endDataCnt++], ratioStart * startData[startDataCnt++] + ratioEnd * endData[endDataCnt++], ratioStart * startData[startDataCnt++] + ratioEnd * endData[endDataCnt++]); startLastX = startData[startDataCnt - 2]; startLastY = startData[startDataCnt - 1]; endLastX = endData[endDataCnt - 2]; endLastY = endData[endDataCnt - 1]; } break; } } }; MorphSprite.prototype.setRatio = function (ratio) { var lookupRatio = (ratio * 0xffff | 0); var destination = this._graphics; if (this._ratio === lookupRatio) { return; } this._ratio = lookupRatio; //@ts-ignore if (destination.buildQueueTags) { /** * if we use latest API, use buildQueueTags * true - because grpahics can be nested (has reference copy) * end need update root graphics */ //@ts-ignore destination.buildQueueTags(true); } else { // fallback to legacy // trigger a queue execution if one is needed destination.endFill(); destination.clear(); } if (destination.start.length !== destination.end.length) { throw ('Error in morph data - different number of pathes'); } var len = destination.start.length; for (var i = 0; i < len; i++) { var newPath = new GraphicsPath(); var startPath = destination.start[i]; var endPath = destination.end[i]; this._blendStyle(startPath, endPath, newPath, ratio); this._blendContours(startPath, endPath, newPath, ratio); destination.add_queued_path(newPath); } /** * call internal endFill, because regular endFill not run shape builder * clear = true is required because otherwithe we will prepend path */ // @ts-ignore destination._endFillInternal(true); }; /** * @inheritDoc */ MorphSprite.prototype.dispose = function () { this.disposeValues(); this._frameCaches = {}; MorphSprite._morphSprites.push(this); }; MorphSprite.prototype.clone = function () { var newInstance = MorphSprite.getNewMorphSprite(); this.copyTo(newInstance); return newInstance; }; MorphSprite.assetType = '[asset MorphSprite]'; MorphSprite._morphSprites = new Array(); return MorphSprite; }(Sprite)); export { MorphSprite };