@awayjs/scene
Version:
AwayJS scene classes
247 lines (246 loc) • 12.5 kB
JavaScript
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 };