kopia lustrzana https://github.com/backface/turtlestitch
cloning speedup
significantly speed up sprite cloning through partial shallow-copying of scripts and costumes instead of deep-duplicationdev
rodzic
d7479f90e4
commit
71333021d4
46
blocks.js
46
blocks.js
|
@ -145,11 +145,11 @@ radians, useBlurredShadows, SpeechBubbleMorph, modules, StageMorph,
|
|||
fontHeight, TableFrameMorph, SpriteMorph, Context, ListWatcherMorph,
|
||||
CellMorph, DialogBoxMorph, BlockInputFragmentMorph, PrototypeHatBlockMorph,
|
||||
Costume, IDE_Morph, BlockDialogMorph, BlockEditorMorph, localize, isNil,
|
||||
isSnapObject*/
|
||||
isSnapObject, copy*/
|
||||
|
||||
// Global stuff ////////////////////////////////////////////////////////
|
||||
|
||||
modules.blocks = '2016-May-02';
|
||||
modules.blocks = '2016-May-04';
|
||||
|
||||
var SyntaxElementMorph;
|
||||
var BlockMorph;
|
||||
|
@ -3251,7 +3251,14 @@ BlockMorph.prototype.setCategory = function (aString) {
|
|||
|
||||
// BlockMorph copying
|
||||
|
||||
BlockMorph.prototype.fullCopy = function () {
|
||||
BlockMorph.prototype.fullCopy = function (forClone) {
|
||||
if (forClone) {
|
||||
if (this.hasBlockVars()) {
|
||||
forClone = false;
|
||||
} else {
|
||||
return copy(this);
|
||||
}
|
||||
}
|
||||
var ans = BlockMorph.uber.fullCopy.call(this);
|
||||
ans.removeHighlight();
|
||||
ans.isDraggable = true;
|
||||
|
@ -3261,22 +3268,15 @@ BlockMorph.prototype.fullCopy = function () {
|
|||
ans.allChildren().filter(function (block) {
|
||||
if (block instanceof SyntaxElementMorph) {
|
||||
block.cachedInputs = null;
|
||||
// if (block instanceof InputSlotMorph) {
|
||||
// block.contents().clearSelection();
|
||||
// } else
|
||||
if (block.definition) {
|
||||
block.initializeVariables();
|
||||
}
|
||||
// } else if (block instanceof CursorMorph) {
|
||||
// block.destroy();
|
||||
}
|
||||
return !isNil(block.comment);
|
||||
}).forEach(function (block) {
|
||||
var cmnt = block.comment.fullCopy();
|
||||
block.comment = cmnt;
|
||||
cmnt.block = block;
|
||||
//block.comment = null;
|
||||
|
||||
});
|
||||
ans.cachedInputs = null;
|
||||
return ans;
|
||||
|
@ -3286,6 +3286,12 @@ BlockMorph.prototype.reactToTemplateCopy = function () {
|
|||
this.forceNormalColoring();
|
||||
};
|
||||
|
||||
BlockMorph.prototype.hasBlockVars = function () {
|
||||
return this.anyChild(function (any) {
|
||||
return any.definition && any.definition.variableNames.length;
|
||||
});
|
||||
};
|
||||
|
||||
// BlockMorph events
|
||||
|
||||
BlockMorph.prototype.mouseClickLeft = function () {
|
||||
|
@ -5177,7 +5183,7 @@ ScriptsMorph.prototype.init = function (owner) {
|
|||
|
||||
// ScriptsMorph deep copying:
|
||||
|
||||
ScriptsMorph.prototype.fullCopy = function () {
|
||||
ScriptsMorph.prototype.fullCopy = function (forClone) {
|
||||
var cpy = new ScriptsMorph(),
|
||||
pos = this.position(),
|
||||
child;
|
||||
|
@ -5186,17 +5192,21 @@ ScriptsMorph.prototype.fullCopy = function () {
|
|||
}
|
||||
this.children.forEach(function (morph) {
|
||||
if (!morph.block) { // omit anchored comments
|
||||
child = morph.fullCopy();
|
||||
child.setPosition(morph.position().subtract(pos));
|
||||
child = morph.fullCopy(forClone);
|
||||
cpy.add(child);
|
||||
if (child instanceof BlockMorph) {
|
||||
child.allComments().forEach(function (comment) {
|
||||
comment.align(child);
|
||||
});
|
||||
if (!forClone) {
|
||||
child.setPosition(morph.position().subtract(pos));
|
||||
if (child instanceof BlockMorph) {
|
||||
child.allComments().forEach(function (comment) {
|
||||
comment.align(child);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
cpy.adjustBounds();
|
||||
if (!forClone) {
|
||||
cpy.adjustBounds();
|
||||
}
|
||||
return cpy;
|
||||
};
|
||||
|
||||
|
|
4
gui.js
4
gui.js
|
@ -70,7 +70,7 @@ isSnapObject*/
|
|||
|
||||
// Global stuff ////////////////////////////////////////////////////////
|
||||
|
||||
modules.gui = '2016-May-02';
|
||||
modules.gui = '2016-May-04';
|
||||
|
||||
// Declarations
|
||||
|
||||
|
@ -2835,7 +2835,7 @@ IDE_Morph.prototype.aboutSnap = function () {
|
|||
module, btn1, btn2, btn3, btn4, licenseBtn, translatorsBtn,
|
||||
world = this.world();
|
||||
|
||||
aboutTxt = 'Snap! 4.0.7\nBuild Your Own Blocks\n\n'
|
||||
aboutTxt = 'Snap! 4.0.7.1\nBuild Your Own Blocks\n\n'
|
||||
+ 'Copyright \u24B8 2016 Jens M\u00F6nig and '
|
||||
+ 'Brian Harvey\n'
|
||||
+ 'jens@moenig.org, bh@cs.berkeley.edu\n\n'
|
||||
|
|
|
@ -2908,10 +2908,15 @@ http://snap.berkeley.edu/run#cloud:Username=jens&ProjectName=PathFollower
|
|||
http://snap.berkeley.edu/run#present:Username=jens&ProjectName=cartwheel
|
||||
http://snap.berkeley.edu/run#cloud:Username=jens&ProjectName=rotation
|
||||
|
||||
* new Indonesian translation. Yay!! Thank you, Alexander Liu!!
|
||||
* Translation updates: Slovenian, Portuguese, Chinese
|
||||
* minor bug fixes
|
||||
|
||||
== v4.0.7 ==== - first class sprites
|
||||
|
||||
160504
|
||||
------
|
||||
* Morphic, Objects, Blocks, Threads, GUI: Partially shallow-copy clones for speed
|
||||
* new Estonian translation! Yay!! Thanks, Hasso Tepper!
|
||||
|
||||
|
||||
== v4.0.7.1 ==== - cloning speed-up
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
|
||||
/*global modules, contains*/
|
||||
|
||||
modules.locale = '2016-May-02';
|
||||
modules.locale = '2016-May-04';
|
||||
|
||||
// Global stuff
|
||||
|
||||
|
|
23
morphic.js
23
morphic.js
|
@ -337,7 +337,7 @@
|
|||
(c) an application
|
||||
-------------------
|
||||
Of course, most of the time you don't want to just plain use the
|
||||
standard Morhic World "as is" out of the box, but write your own
|
||||
standard Morphic World "as is" out of the box, but write your own
|
||||
application (something like Scratch!) in it. For such an
|
||||
application you'll create your own morph prototypes, perhaps
|
||||
assemble your own "window frame" and bring it all to life in a
|
||||
|
@ -1054,10 +1054,9 @@
|
|||
|
||||
// Global settings /////////////////////////////////////////////////////
|
||||
|
||||
/*global window, HTMLCanvasElement, getMinimumFontHeight, FileReader, Audio,
|
||||
FileList, getBlurredShadowSupport*/
|
||||
/*global window, HTMLCanvasElement, FileReader, Audio, FileList*/
|
||||
|
||||
var morphicVersion = '2016-February-24';
|
||||
var morphicVersion = '2016-May-04';
|
||||
var modules = {}; // keep track of additional loaded modules
|
||||
var useBlurredShadows = getBlurredShadowSupport(); // check for Chrome-bug
|
||||
|
||||
|
@ -1938,7 +1937,7 @@ Rectangle.prototype.round = function () {
|
|||
Rectangle.prototype.spread = function () {
|
||||
// round me by applying floor() to my origin and ceil() to my corner
|
||||
// expand by 1 to be on the safe side, this eliminates rounding
|
||||
// artefacts caused by Safari's auto-scaling on retina displays
|
||||
// artifacts caused by Safari's auto-scaling on retina displays
|
||||
return this.origin.floor().corner(this.corner.ceil()).expandBy(1);
|
||||
};
|
||||
|
||||
|
@ -2090,6 +2089,20 @@ Node.prototype.forAllChildren = function (aFunction) {
|
|||
aFunction.call(null, this);
|
||||
};
|
||||
|
||||
Node.prototype.anyChild = function (aPredicate) {
|
||||
// includes myself
|
||||
var i;
|
||||
if (aPredicate.call(null, this)) {
|
||||
return true;
|
||||
}
|
||||
for (i = 0; i < this.children.length; i += 1) {
|
||||
if (this.children[i].anyChild(aPredicate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
Node.prototype.allLeafs = function () {
|
||||
var result = [];
|
||||
this.allChildren().forEach(function (element) {
|
||||
|
|
50
objects.js
50
objects.js
|
@ -82,7 +82,7 @@ SpeechBubbleMorph, RingMorph, isNil, FileReader, TableDialogMorph,
|
|||
BlockEditorMorph, BlockDialogMorph, PrototypeHatBlockMorph, localize,
|
||||
TableMorph, TableFrameMorph*/
|
||||
|
||||
modules.objects = '2016-May-02';
|
||||
modules.objects = '2016-May-04';
|
||||
|
||||
var SpriteMorph;
|
||||
var StageMorph;
|
||||
|
@ -1364,7 +1364,7 @@ SpriteMorph.prototype.init = function (globals) {
|
|||
|
||||
// SpriteMorph duplicating (fullCopy)
|
||||
|
||||
SpriteMorph.prototype.fullCopy = function () {
|
||||
SpriteMorph.prototype.fullCopy = function (forClone) {
|
||||
var c = SpriteMorph.uber.fullCopy.call(this),
|
||||
myself = this,
|
||||
arr = [],
|
||||
|
@ -1374,20 +1374,22 @@ SpriteMorph.prototype.fullCopy = function () {
|
|||
c.color = this.color.copy();
|
||||
c.blocksCache = {};
|
||||
c.paletteCache = {};
|
||||
c.scripts = this.scripts.fullCopy();
|
||||
c.scripts = this.scripts.fullCopy(forClone);
|
||||
c.scripts.owner = c;
|
||||
c.variables = this.variables.copy();
|
||||
c.variables.owner = c;
|
||||
c.customBlocks = [];
|
||||
this.customBlocks.forEach(function (def) {
|
||||
cb = def.copyAndBindTo(c);
|
||||
c.customBlocks.push(cb);
|
||||
c.allBlockInstances(def).forEach(function (block) {
|
||||
block.definition = cb;
|
||||
if (!forClone) {
|
||||
this.customBlocks.forEach(function (def) {
|
||||
cb = def.copyAndBindTo(c);
|
||||
c.customBlocks.push(cb);
|
||||
c.allBlockInstances(def).forEach(function (block) {
|
||||
block.definition = cb;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
this.costumes.asArray().forEach(function (costume) {
|
||||
var cst = costume.copy();
|
||||
var cst = forClone ? costume : costume.copy();
|
||||
arr.push(cst);
|
||||
if (costume === myself.costume) {
|
||||
c.costume = cst;
|
||||
|
@ -1404,12 +1406,11 @@ SpriteMorph.prototype.fullCopy = function () {
|
|||
c.anchor = null;
|
||||
c.parts = [];
|
||||
this.parts.forEach(function (part) {
|
||||
var dp = part.fullCopy();
|
||||
var dp = part.fullCopy(forClone);
|
||||
dp.nestingScale = part.nestingScale;
|
||||
dp.rotatesWithAnchor = part.rotatesWithAnchor;
|
||||
c.attachPart(dp);
|
||||
});
|
||||
|
||||
return c;
|
||||
};
|
||||
|
||||
|
@ -2834,12 +2835,30 @@ SpriteMorph.prototype.remove = function () {
|
|||
}
|
||||
};
|
||||
|
||||
// SpriteMorph cloning (experimental)
|
||||
// SpriteMorph cloning
|
||||
|
||||
/*
|
||||
clones are temporary, partially shallow copies of sprites that don't
|
||||
appear as icons in the corral. Clones get deleted when the red stop button
|
||||
is pressed. Shallow-copying clones' scripts and costumes makes spawning
|
||||
very fast, so they can be used for particle system simulations.
|
||||
This speed-up, however, comes at the cost of some detrimental side
|
||||
effects: Changes to a costume or a script of the original sprite are
|
||||
in some cases shared with all of its clones, however such shared changes
|
||||
are hard to predict for users and not actively propagated, so they don't
|
||||
offer any reliable feature, and will not be supported as such.
|
||||
Changes to the original sprite's scripts affect all of its clones, unless
|
||||
the script contains any custom block whose definition contains one or more
|
||||
block variables (in which case the script does get deep-copied).
|
||||
The original sprite's scripting area, costumes wardrobe or sounds jukebox
|
||||
are also not shared. therefore adding or deleting a script, sound or
|
||||
costume in the original sprite has no effect on any of its clones.
|
||||
*/
|
||||
|
||||
SpriteMorph.prototype.createClone = function () {
|
||||
var stage = this.parentThatIsA(StageMorph);
|
||||
if (stage && stage.cloneCount <= 1000) {
|
||||
this.fullCopy().clonify(stage);
|
||||
if (stage && stage.cloneCount <= 2000) {
|
||||
this.fullCopy(true).clonify(stage);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -6636,7 +6655,6 @@ Costume.prototype.copy = function () {
|
|||
var canvas = newCanvas(this.extent()),
|
||||
cpy,
|
||||
ctx;
|
||||
|
||||
ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(this.contents, 0, 0);
|
||||
cpy = new Costume(canvas, this.name ? copy(this.name) : null);
|
||||
|
|
|
@ -61,7 +61,7 @@ StageMorph, SpriteMorph, StagePrompterMorph, Note, modules, isString, copy,
|
|||
isNil, WatcherMorph, List, ListWatcherMorph, alert, console, TableMorph,
|
||||
TableFrameMorph, isSnapObject*/
|
||||
|
||||
modules.threads = '2016-May-02';
|
||||
modules.threads = '2016-May-04';
|
||||
|
||||
var ThreadManager;
|
||||
var Process;
|
||||
|
@ -354,7 +354,7 @@ ThreadManager.prototype.doWhen = function (block, stopIt) {
|
|||
if (invoke(
|
||||
pred,
|
||||
null,
|
||||
null,
|
||||
block.receiver(), // needed for shallow copied clones - was null
|
||||
50,
|
||||
'the predicate takes\ntoo long for a\ncustom hat block',
|
||||
true // suppress errors => handle them right here instead
|
||||
|
|
Ładowanie…
Reference in New Issue