kopia lustrzana https://github.com/backface/turtlestitch
optimized performance for sprite rendering and rotation
rodzic
4ac02f9873
commit
d96b234c63
|
@ -3,15 +3,17 @@
|
|||
## in development:
|
||||
* **New Features:**
|
||||
* **Notable Changes:**
|
||||
* optimized performance for backgrounds and pen trails
|
||||
* optimized performance for sprite rendering and rotation
|
||||
* added support for counting down using the "numbers" reporter
|
||||
* **Notable Fixes:**
|
||||
* optimized performance for backgrounds and pen trails
|
||||
* removed "current" option from "switch to costume" block's drop-down menu
|
||||
* **Translation Updates:**
|
||||
|
||||
### 2019-10-29
|
||||
* threads: added support for counting down using the "numbers" reporter
|
||||
* morphic: improved canvas recycling
|
||||
* objects: optimized sprite rendering and rotating
|
||||
|
||||
### 2019-10-28
|
||||
* new dev version
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<script type="text/javascript" src="src/widgets.js?version=2019-10-16"></script>
|
||||
<script type="text/javascript" src="src/blocks.js?version=2019-10-28"></script>
|
||||
<script type="text/javascript" src="src/threads.js?version=2019-10-29"></script>
|
||||
<script type="text/javascript" src="src/objects.js?version=2019-10-28"></script>
|
||||
<script type="text/javascript" src="src/objects.js?version=2019-10-29"></script>
|
||||
<script type="text/javascript" src="src/gui.js?version=2019-10-28"></script>
|
||||
<script type="text/javascript" src="src/paint.js?version=2019-06-27"></script>
|
||||
<script type="text/javascript" src="src/lists.js?version=2019-10-23"></script>
|
||||
|
|
|
@ -84,7 +84,7 @@ BlockEditorMorph, BlockDialogMorph, PrototypeHatBlockMorph, BooleanSlotMorph,
|
|||
localize, TableMorph, TableFrameMorph, normalizeCanvas, VectorPaintEditorMorph,
|
||||
HandleMorph, AlignmentMorph, Process, XML_Element, WorldMap*/
|
||||
|
||||
modules.objects = '2019-October-28';
|
||||
modules.objects = '2019-October-29';
|
||||
|
||||
var SpriteMorph;
|
||||
var StageMorph;
|
||||
|
@ -1721,6 +1721,11 @@ SpriteMorph.prototype.fullCopy = function (forClone) {
|
|||
arr = [],
|
||||
cb, effect;
|
||||
|
||||
// make sure the clone has its own canvas to recycle
|
||||
c.image = null;
|
||||
c.drawNew();
|
||||
|
||||
// un-share individual properties
|
||||
c.instances = [];
|
||||
c.stopTalking();
|
||||
c.color = this.color.copy();
|
||||
|
@ -1829,6 +1834,7 @@ SpriteMorph.prototype.drawNew = function () {
|
|||
isLoadingCostume,
|
||||
cst,
|
||||
pic, // (flipped copy of) actual costume based on my rotation style
|
||||
imageSide,
|
||||
stageScale,
|
||||
newX,
|
||||
corners = [],
|
||||
|
@ -1883,13 +1889,26 @@ SpriteMorph.prototype.drawNew = function () {
|
|||
|
||||
// create a new, adequately dimensioned canvas
|
||||
// and draw the costume on it
|
||||
this.image = newCanvas(costumeExtent, true);
|
||||
if (this.rotationStyle === 1) { // rotate freely in all directions
|
||||
imageSide = Math.sqrt(
|
||||
Math.pow(pic.width(), 2) + Math.pow(pic.height(), 2)
|
||||
) * this.scale * stageScale;
|
||||
this.image = newCanvas(
|
||||
new Point(imageSide, imageSide),
|
||||
true,
|
||||
this.image
|
||||
);
|
||||
} else { // don't actually rotate
|
||||
this.image = newCanvas(costumeExtent, true, this.image);
|
||||
}
|
||||
this.silentSetExtent(costumeExtent);
|
||||
ctx = this.image.getContext('2d');
|
||||
ctx.save();
|
||||
ctx.scale(this.scale * stageScale, this.scale * stageScale);
|
||||
ctx.translate(shift.x, shift.y);
|
||||
ctx.rotate(radians(facing - 90));
|
||||
ctx.drawImage(pic.contents, 0, 0);
|
||||
ctx.restore();
|
||||
|
||||
// apply graphics effects to image
|
||||
this.image = this.applyGraphicsEffects(this.image);
|
||||
|
@ -1913,7 +1932,7 @@ SpriteMorph.prototype.drawNew = function () {
|
|||
);
|
||||
this.silentSetExtent(new Point(newX, newX));
|
||||
this.setCenter(currentCenter, true); // just me
|
||||
SpriteMorph.uber.drawNew.call(this, facing);
|
||||
SpriteMorph.uber.drawNew.call(this, facing, this.image); // recycle
|
||||
this.rotationOffset = this.extent().divideBy(2);
|
||||
this.image = this.applyGraphicsEffects(this.image);
|
||||
if (isLoadingCostume) { // retry until costume is done loading
|
||||
|
@ -1994,10 +2013,10 @@ SpriteMorph.prototype.getImageData = function () {
|
|||
if (this.version !== this.imageData.version) {
|
||||
var stage = this.parentThatIsA(StageMorph),
|
||||
ext = this.extent(),
|
||||
newExtent = {
|
||||
x: Math.floor(ext.x / stage.scale),
|
||||
y: Math.floor(ext.y / stage.scale)
|
||||
},
|
||||
newExtent = new Point(
|
||||
Math.floor(ext.x / stage.scale),
|
||||
Math.floor(ext.y / stage.scale)
|
||||
),
|
||||
canvas = newCanvas(newExtent, true),
|
||||
canvasContext,
|
||||
imageData;
|
||||
|
@ -2008,8 +2027,12 @@ SpriteMorph.prototype.getImageData = function () {
|
|||
Math.floor(ext.y),
|
||||
0, 0, newExtent.x, newExtent.y
|
||||
);
|
||||
imageData = canvas.getContext("2d")
|
||||
.getImageData(0, 0, newExtent.x, newExtent.y).data;
|
||||
imageData = canvasContext.getImageData(
|
||||
0,
|
||||
0,
|
||||
newExtent.x,
|
||||
newExtent.y
|
||||
).data;
|
||||
this.imageData = {
|
||||
version : this.version,
|
||||
pixels : new Uint32Array(imageData.buffer.slice(0))
|
||||
|
@ -2023,18 +2046,24 @@ SpriteMorph.prototype.projectionSnap = function() {
|
|||
center = this.center().subtract(stage.position())
|
||||
.divideBy(stage.scale),
|
||||
cst = this.costume || this.image,
|
||||
w, h,
|
||||
offset,
|
||||
snap,
|
||||
ctx;
|
||||
|
||||
if (cst instanceof Costume) {
|
||||
cst = cst.contents;
|
||||
w = cst.width;
|
||||
h = cst.height;
|
||||
} else {
|
||||
w = this.width();
|
||||
h = this.height();
|
||||
}
|
||||
offset = new Point(
|
||||
Math.floor(center.x - (cst.width / 2)),
|
||||
Math.floor(center.y - (cst.height / 2))
|
||||
Math.floor(center.x - (w / 2)),
|
||||
Math.floor(center.y - (h / 2))
|
||||
);
|
||||
snap = newCanvas(new Point(cst.width, cst.height), true);
|
||||
snap = newCanvas(new Point(w, h), true);
|
||||
ctx = snap.getContext('2d');
|
||||
ctx.drawImage(cst, 0, 0);
|
||||
ctx.globalCompositeOperation = 'source-in';
|
||||
|
@ -4249,6 +4278,7 @@ SpriteMorph.prototype.overlappingPixels = function (otherSprite) {
|
|||
thatImg = otherSprite.image;
|
||||
|
||||
if (oRect.width() < 1 || oRect.height() < 1 ||
|
||||
!this.image || !otherSprite.image ||
|
||||
!this.image.width || !this.image.height ||
|
||||
!otherSprite.image.width || !otherSprite.image.height
|
||||
) {
|
||||
|
@ -4587,7 +4617,7 @@ SpriteMorph.prototype.applyGraphicsEffects = function (canvas) {
|
|||
// For every effect: apply transform of that effect(canvas, stored value)
|
||||
// Graphic effects from Scratch are heavily based on ScratchPlugin.c
|
||||
|
||||
var ctx, imagedata;
|
||||
var ctx, imagedata, w, h;
|
||||
|
||||
function transform_fisheye(imagedata, value) {
|
||||
var pixels, newImageData, newPixels, centerX, centerY,
|
||||
|
@ -4868,12 +4898,14 @@ SpriteMorph.prototype.applyGraphicsEffects = function (canvas) {
|
|||
}
|
||||
|
||||
if (this.graphicsChanged()) {
|
||||
if (!canvas.width || !canvas.height) {
|
||||
w = Math.ceil(this.width());
|
||||
h = Math.ceil(this.height());
|
||||
if (!canvas.width || !canvas.height || !w || !h) {
|
||||
// too small to get image data, abort
|
||||
return canvas;
|
||||
}
|
||||
ctx = canvas.getContext("2d");
|
||||
imagedata = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
imagedata = ctx.getImageData(0, 0, w, h);
|
||||
|
||||
if (this.graphicsValues.fisheye) {
|
||||
imagedata = transform_fisheye(
|
||||
|
@ -6856,17 +6888,17 @@ SpriteMorph.prototype.inheritedMethods = function () {
|
|||
// SpriteMorph thumbnail
|
||||
|
||||
SpriteMorph.prototype.thumbnail = function (extentPoint) {
|
||||
/*
|
||||
answer a new Canvas of extentPoint dimensions containing
|
||||
my thumbnail representation keeping the originial aspect ratio
|
||||
*/
|
||||
// answer a new Canvas of extentPoint dimensions containing
|
||||
// my thumbnail representation keeping the originial aspect ratio
|
||||
var src = this.image, // at this time sprites aren't composite morphs
|
||||
w = this.width(),
|
||||
h = this.height(),
|
||||
scale = Math.min(
|
||||
(extentPoint.x / src.width),
|
||||
(extentPoint.y / src.height)
|
||||
(extentPoint.x / w),
|
||||
(extentPoint.y / h)
|
||||
),
|
||||
xOffset = (extentPoint.x - (src.width * scale)) / 2,
|
||||
yOffset = (extentPoint.y - (src.height * scale)) / 2,
|
||||
xOffset = (extentPoint.x - (w * scale)) / 2,
|
||||
yOffset = (extentPoint.y - (h * scale)) / 2,
|
||||
trg = newCanvas(extentPoint),
|
||||
ctx = trg.getContext('2d');
|
||||
|
||||
|
@ -6887,7 +6919,7 @@ SpriteMorph.prototype.thumbnail = function (extentPoint) {
|
|||
if (this.isCorpse) {
|
||||
ctx.globalAlpha = 0.3;
|
||||
}
|
||||
if (src.width && src.height) {
|
||||
if (w && h) {
|
||||
ctx.scale(scale, scale);
|
||||
ctx.drawImage(
|
||||
src,
|
||||
|
|
Ładowanie…
Reference in New Issue