Convert remaining modules

This commit is contained in:
Tim Mickel 2016-01-21 15:32:41 -05:00
parent bf07d98ccd
commit 1c32ecf0a5
9 changed files with 4628 additions and 4507 deletions

View file

@ -1,4 +1,10 @@
var Block = function (spec, isPalette, scale) {
import BlockSpecs from './BlockSpecs';
import BlockArg from './BlockArg';
import ScratchJr from '../ScratchJr';
import {setProps, setCanvasSize, scaleMultiplier} from '../../utils/lib';
export default class Block {
constructor (spec, isPalette, scale) {
this.div = document.createElement('div');
// Top-level block parent shouldn't accept pointer events
@ -17,7 +23,8 @@ var Block = function (spec, isPalette, scale) {
position: 'absolute',
left: '0px',
top: '0px',
webkitTransform: 'translate(' + (-this.blockshape.width / 2) + 'px, ' + (-this.blockshape.height / 2) + 'px) ' +
webkitTransform: 'translate(' + (-this.blockshape.width / 2) + 'px, ' +
(-this.blockshape.height / 2) + 'px) ' +
'scale(' + (1 / window.devicePixelRatio) + ') ' +
'translate(' + (this.blockshape.width / 2) + 'px, ' + (this.blockshape.height / 2) + 'px)',
pointerEvents: 'all'
@ -31,9 +38,9 @@ var Block = function (spec, isPalette, scale) {
}
this.createArgument();
this.div.owner = this;
};
}
Block.prototype.getWidth = function () {
getWidth () {
if (this.blocktype == 'repeat') {
return 176;
}
@ -44,16 +51,16 @@ Block.prototype.getWidth = function () {
return 84;
}
return 76;
};
}
Block.prototype.getHeight = function () {
getHeight () {
if (this.blocktype == 'repeat') {
return 82;
}
return 66;
};
}
Block.prototype.setBlockshapeFromSpecs = function (spec, isPalette, scale) {
setBlockshapeFromSpecs (spec, isPalette, scale) {
this.spec = spec;
this.isReporter = (spec[1] == 'reporter');
this.blocktype = spec[0];
@ -83,9 +90,9 @@ Block.prototype.setBlockshapeFromSpecs = function (spec, isPalette, scale) {
this.hrubberband = 0;
this.vrubberband = 0;
this.done = false;
};
}
Block.prototype.addShadow = function () {
addShadow () {
this.shadow = document.createElement('canvas');
this.div.appendChild(this.shadow);
setProps(this.shadow.style, {
@ -94,7 +101,8 @@ Block.prototype.addShadow = function () {
top: '4px',
opacity: this.inpalette ? Settings.paletteBlockShadowOpacity : 1,
visibility: 'hidden',
webkitTransform: 'translate(' + (-this.blockshape.width / 2) + 'px, ' + (-this.blockshape.height / 2) + 'px) ' +
webkitTransform: 'translate(' + (-this.blockshape.width / 2) + 'px, ' +
(-this.blockshape.height / 2) + 'px) ' +
'scale(' + (1 / window.devicePixelRatio) + ') ' +
'translate(' + (this.blockshape.width / 2) + 'px, ' + (this.blockshape.height / 2) + 'px)',
pointerEvents: 'all'
@ -108,23 +116,24 @@ Block.prototype.addShadow = function () {
if (!img.complete) {
img.onload = function () {
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0,
img.width * this.scale * window.devicePixelRatio, img.height * this.scale * window.devicePixelRatio);
img.width * this.scale * window.devicePixelRatio,
img.height * this.scale * window.devicePixelRatio);
};
} else {
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0,
img.width * this.scale * window.devicePixelRatio, img.height * this.scale * window.devicePixelRatio);
}
};
}
Block.prototype.lift = function () {
lift () {
this.shadow.style.visibility = 'visible';
};
}
Block.prototype.drop = function () {
drop () {
this.shadow.style.visibility = 'hidden';
};
}
Block.prototype.addHighlight = function () {
addHighlight () {
var img = this.spec[5];
if (!img) {
return;
@ -137,7 +146,8 @@ Block.prototype.addHighlight = function () {
left: '0px',
top: '0px',
visibility: 'hidden',
webkitTransform: 'translate(' + (-this.blockshape.width / 2) + 'px, ' + (-this.blockshape.height / 2) + 'px) ' +
webkitTransform: 'translate(' + (-this.blockshape.width / 2) +
'px, ' + (-this.blockshape.height / 2) + 'px) ' +
'scale(' + (1 / window.devicePixelRatio) + ') ' +
'translate(' + (this.blockshape.width / 2) + 'px, ' + (this.blockshape.height / 2) + 'px)',
pointerEvents: 'all'
@ -146,15 +156,16 @@ Block.prototype.addHighlight = function () {
if (!img.complete) {
img.onload = function () {
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0,
img.width * this.scale * window.devicePixelRatio, img.height * this.scale * window.devicePixelRatio);
img.width * this.scale * window.devicePixelRatio,
img.height * this.scale * window.devicePixelRatio);
};
} else {
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0,
img.width * this.scale * window.devicePixelRatio, img.height * this.scale * window.devicePixelRatio);
}
};
}
Block.prototype.drawBlock = function () {
drawBlock () {
var cnv = this.blockshape;
var ctx = this.blockshape.getContext('2d');
ctx.clearRect(0, 0, cnv.width, cnv.height);
@ -166,9 +177,9 @@ Block.prototype.drawBlock = function () {
} else {
this.drawBlockType();
}
};
}
Block.prototype.drawBlockType = function () {
drawBlockType () {
var ctx = this.blockshape.getContext('2d');
ctx.drawImage(this.image, 0, 0, this.image.width, this.image.height, 0, 0,
this.image.width * this.scale * window.devicePixelRatio,
@ -181,7 +192,8 @@ Block.prototype.drawBlockType = function () {
position: 'absolute',
left: '0px',
top: '0px',
webkitTransform: 'translate(' + (-this.blockshape.width / 2) + 'px, ' + (-this.blockshape.height / 2) + 'px) ' +
webkitTransform: 'translate(' + (-this.blockshape.width / 2) + 'px, ' +
(-this.blockshape.height / 2) + 'px) ' +
'scale(' + (1 / window.devicePixelRatio) + ') ' +
'translate(' + (this.blockshape.width / 2) + 'px, ' + (this.blockshape.height / 2) + 'px)',
pointerEvents: 'all'
@ -190,15 +202,15 @@ Block.prototype.drawBlockType = function () {
this.drawIcon();
}
this.done = true;
};
}
Block.prototype.updateBlock = function () {
updateBlock () {
if (this.arg && this.arg.argType == 'p') {
this.arg.updateIcon();
}
};
}
Block.prototype.highlight = function () {
highlight () {
if (this.blocktype.indexOf('caret') > -1) {
return;
}
@ -209,16 +221,16 @@ Block.prototype.highlight = function () {
return;
}
this.shine.style.visibility = 'visible';
};
}
Block.prototype.unhighlight = function () {
unhighlight () {
if (this.blocktype.indexOf('caret') > -1) {
return;
}
this.shine.style.visibility = 'hidden';
};
}
Block.prototype.drawIcon = function () {
drawIcon () {
var dx = 0;
var dy = 0;
var ctx = this.blockicon.getContext('2d');
@ -240,9 +252,9 @@ Block.prototype.drawIcon = function () {
break;
}
this.drawMyIcon(ctx, dx, dy);
};
}
Block.prototype.drawMyIcon = function (ctx, dx, dy) {
drawMyIcon (ctx, dx, dy) {
var me = this;
var icon = this.icon;
if (!icon.complete) {
@ -256,23 +268,23 @@ Block.prototype.drawMyIcon = function (ctx, dx, dy) {
icon.width * me.scale * window.devicePixelRatio,
icon.height * me.scale * window.devicePixelRatio);
}
};
}
Block.prototype.createArgument = function () {
createArgument () {
if (this.spec[4] == null) {
return;
}
this.arg = new BlockArg(this);
};
}
Block.prototype.getArgValue = function () {
getArgValue () {
if (this.arg == null) {
return null;
}
return this.arg.argValue;
};
}
Block.prototype.getSoundName = function (list) {
getSoundName (list) {
var val = this.arg.argValue;
if (Number(val).toString() == 'NaN') {
return val;
@ -281,15 +293,15 @@ Block.prototype.getSoundName = function (list) {
return list[0];
}
return list[val];
};
}
Block.prototype.update = function (spr) {
update (spr) {
if (this.arg) {
this.arg.update(spr);
}
};
}
Block.prototype.setSound = function (bt) {
setSound (bt) {
var p = this.arg.div;
p.parentNode.removeChild(p);
var icon = this.blockicon;
@ -299,9 +311,9 @@ Block.prototype.setSound = function (bt) {
this.setBlockshapeFromSpecs(specs);
this.drawBlock();
this.createArgument();
};
}
Block.prototype.duplicateBlock = function (dx, dy, spr) {
duplicateBlock (dx, dy, spr) {
var op = this.blocktype;
var specs = BlockSpecs.defs[op];
specs[4] = this.getArgValue();
@ -314,9 +326,9 @@ Block.prototype.duplicateBlock = function (dx, dy, spr) {
bbx.moveBlock(dx, dy);
bbx.update(spr);
return bbx;
};
}
Block.prototype.resolveDocks = function () {
resolveDocks () {
var w = this.getWidth();
var h = this.getHeight();
if (this.aStart) {
@ -336,17 +348,17 @@ Block.prototype.resolveDocks = function () {
} else {
return [['flow', true, 0, h / 2], ['flow', false, w - this.notchSize(), h / 2]];
}
};
}
Block.prototype.notchSize = function () {
notchSize () {
return 11;
};
}
//////////////////////////////////////////
// Connect / Disconnect
/////////////////////////////////////////
//////////////////////////////////////////
// Connect / Disconnect
/////////////////////////////////////////
Block.prototype.connectBlock = function (myn, you, yourn) {
connectBlock (myn, you, yourn) {
if (this.isConnectedAfterFirst(myn, you, yourn)) {
return;
}
@ -360,24 +372,24 @@ Block.prototype.connectBlock = function (myn, you, yourn) {
last.next = theend;
theend.prev = last;
}
};
}
Block.prototype.getMyDock = function (dockn) {
getMyDock (dockn) {
var myprops = this.cShape ? ['prev', 'inside', 'next'] : ['prev', 'next'];
return this[myprops[dockn]];
};
}
Block.prototype.setMyDock = function (dockn, you) {
setMyDock (dockn, you) {
var myprops = this.cShape ? ['prev', 'inside', 'next'] : ['prev', 'next'];
this[myprops[dockn]] = you;
};
}
Block.prototype.getMyDockNum = function (you) {
getMyDockNum (you) {
var connections = this.cShape ? [this.prev, this.inside, this.next] : [this.prev, this.next];
return connections.indexOf(you);
};
}
Block.prototype.isConnectedAfterFirst = function (myn, you) {
isConnectedAfterFirst (myn, you) {
if (myn == 0) {
return false;
}
@ -392,23 +404,23 @@ Block.prototype.isConnectedAfterFirst = function (myn, you) {
var thefirst = this.findFirst();
thefirst.connectBlock(0, prev, n);
return true;
};
}
Block.prototype.findLast = function () {
findLast () {
if (this.next == null) {
return this;
}
return this.next.findLast();
};
}
Block.prototype.findFirst = function () {
findFirst () {
if (this.prev == null) {
return this;
}
return this.prev.findFirst();
};
}
Block.prototype.connectLast = function (myn, you, yourn) {
connectLast (myn, you, yourn) {
if (myn != 0) {
return;
}
@ -436,9 +448,9 @@ Block.prototype.connectLast = function (myn, you, yourn) {
}
yourtail.prev = mylast;
}
};
}
Block.prototype.detachBlock = function () {
detachBlock () {
var you = this.prev;
if (you == null) {
return;
@ -449,26 +461,26 @@ Block.prototype.detachBlock = function () {
} else {
you.next = null;
}
};
}
//////////////////////////////////////////
// Move
/////////////////////////////////////////
//////////////////////////////////////////
// Move
/////////////////////////////////////////
Block.prototype.moveBlock = function (dx, dy) {
moveBlock (dx, dy) {
this.div.top = dy;
this.div.left = dx;
this.div.style.webkitTransform = 'translate3d(' + this.div.left + 'px,' + this.div.top + 'px, 0)';
};
}
/////////////////////////////////
// Forever and Repeat
////////////////////////////////
/////////////////////////////////
// Forever and Repeat
////////////////////////////////
// Repeat size 176 by 82
// Repeat size 176 by 82
Block.prototype.redrawRepeat = function () {
redrawRepeat () {
this.redrawShape(this.blockshape, this.image);
if (this.blocktype.indexOf('caret') < 0) {
this.redrawShape(this.shadow, this.shadowimg);
@ -483,9 +495,9 @@ Block.prototype.redrawRepeat = function () {
this.arg.div.style.left = (this.blockshape.width / window.devicePixelRatio - 66 * this.scale) + 'px';
this.blockicon.style.top = dy + 'px';
this.arg.div.style.top = (this.blockshape.height / window.devicePixelRatio - 11 * this.scale) + 'px';
};
}
Block.prototype.redrawShape = function (cnv, img) {
redrawShape (cnv, img) {
setCanvasSize(this.div,
(92 + this.hrubberband + 84) * this.scale,
(100 + this.vrubberband) * this.scale);
@ -516,4 +528,5 @@ Block.prototype.redrawShape = function (cnv, img) {
45 * scaleAndRatio, 53 * scaleAndRatio);
ctx.drawImage(img, 93, 29, img.width - 93, 53, 92 * scaleAndRatio + this.hrubberband * scaleAndRatio,
29 * scaleAndRatio + this.vrubberband * scaleAndRatio, 83 * scaleAndRatio, 53 * scaleAndRatio);
};
}
}

View file

@ -1,3 +1,12 @@
import ScratchJr from '../ScratchJr';
import BlockSpecs from './BlockSpecs';
import Menu from './Menu';
import Undo from '../ui/Undo';
import {setCanvasSize, setProps, writeText, scaleMultiplier,
newHTML, newDiv, newCanvas, getStringSize, isTablet,
newP, globalx, globaly} from '../../utils/lib';
import Localization from '../../utils/Localization';
/*
Argument types
@ -9,7 +18,8 @@ r: number for recorded sound block
p: page icons
*/
var BlockArg = function (block) {
export default class BlockArg {
constructor (block) {
this.daddy = block;
this.type = 'blockarg';
this.argType = block.spec[3];
@ -69,43 +79,43 @@ var BlockArg = function (block) {
default:
break;
}
};
}
BlockArg.prototype.update = function () {
update () {
if (this.argType == 'r') {
this.div.childNodes[0].textContent = this.argValue;
}
if (this.arg && (this.argType == 'p')) {
this.arg.updateIcon();
}
};
}
BlockArg.prototype.getScreenPt = function () {
getScreenPt () {
return {
x: globalx(this.daddy.div),
y: globaly(this.daddy.div)
};
};
}
BlockArg.prototype.addNumArg = function () {
addNumArg () {
var str = this.argValue.toString();
if (this.daddy.inpalette) {
return this.addLabel(str, false);
} else {
return this.addNumArgument(str);
}
};
}
BlockArg.prototype.addTextArg = function () {
addTextArg () {
var str = this.argValue.toString();
if (this.daddy.inpalette) {
return this.addLabel(str, true);
} else {
return this.addTextArgument(str, true);
}
};
}
BlockArg.prototype.addLabel = function (str, isText) {
addLabel (str, isText) {
var scale = this.daddy.scale;
var dx = isText ? 8 : 16;
var dy = 57;
@ -153,9 +163,9 @@ BlockArg.prototype.addLabel = function (str, isText) {
writeText(ctx, font, '#77787b', str, h * window.devicePixelRatio - 3,
Math.round((w * window.devicePixelRatio - lsize) / 2));
return div;
};
}
BlockArg.prototype.addNumArgument = function (str) {
addNumArgument (str) {
var div = newHTML('div', 'numfield', this.daddy.div);
if (this.daddy.blocktype == 'repeat') {
setProps(div.style, {
@ -168,53 +178,55 @@ BlockArg.prototype.addNumArgument = function (str) {
ti.owner = this;
ti.textContent = str;
this.arg = div;
// Expand the parent div to incorporate the size of the button, else on Android 4.2 the bottom part of the button
// Expand the parent div to incorporate the size of the button,
// else on Android 4.2 the bottom part of the button
// will not be clickable.
div.parentNode.height += 10 * window.devicePixelRatio;
setCanvasSize(div.parentNode, div.parentNode.width, div.parentNode.height);
return div;
};
}
BlockArg.prototype.addTextArgument = function (str) {
addTextArgument (str) {
var div = newHTML('div', 'textfield', this.daddy.div);
var ti = newHTML('h3', undefined, div);
this.input = ti;
ti.owner = this;
ti.textContent = str;
this.arg = div;
// Expand the parent div to incorporate the size of the button, else on Android 4.2 the bottom part of the button
// Expand the parent div to incorporate the size of the button,
// else on Android 4.2 the bottom part of the button
// will not be clickable.
div.parentNode.height += 10 * window.devicePixelRatio;
setCanvasSize(div.parentNode, div.parentNode.width, div.parentNode.height);
return div;
};
}
BlockArg.prototype.setValue = function (val) {
setValue (val) {
if (!this.input) {
return;
}
this.argValue = val;
this.input.textContent = val;
};
}
BlockArg.prototype.isText = function () {
isText () {
return (this.argType != 'n');
};
}
/////////////////////////////////
// Menu drop downs
//////////////////////////////
/////////////////////////////////
// Menu drop downs
//////////////////////////////
BlockArg.prototype.getIconFrom = function (key, list) {
getIconFrom (key, list) {
for (var i = 0; i < list.length; i++) {
if (list[i].indexOf(key) > -1) {
return list[i];
}
}
return list[0];
};
}
BlockArg.prototype.addImageMenu = function (fcn) {
addImageMenu (fcn) {
this.drawChoice(this.daddy.blockicon);
this.button = this.addPressButton();
if (!this.daddy.inpalette) {
@ -235,9 +247,9 @@ BlockArg.prototype.addImageMenu = function (fcn) {
setCanvasSize(this.button.parentNode, this.button.parentNode.width, this.button.parentNode.height);
}
return this.daddy.blockicon;
};
}
BlockArg.prototype.drawChoice = function (cnv) {
drawChoice (cnv) {
var ctx = cnv.getContext('2d');
ctx.clearRect(0, 0, cnv.width, cnv.height);
var icon = BlockSpecs.getImageFrom('assets/blockicons/' + this.icon, 'svg');
@ -254,9 +266,9 @@ BlockArg.prototype.drawChoice = function (cnv) {
icon.height * scale * window.devicePixelRatio);
}
return cnv;
};
}
BlockArg.prototype.addPressButton = function () {
addPressButton () {
var scale = this.daddy.scale;
var dx;
if (this.daddy.inpalette) {
@ -283,9 +295,9 @@ BlockArg.prototype.addPressButton = function () {
ctx.drawImage(img, 0, 0);
}
return field;
};
}
BlockArg.prototype.pressDropDown = function (e, fcn) {
pressDropDown (e, fcn) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
@ -299,15 +311,16 @@ BlockArg.prototype.pressDropDown = function (e, fcn) {
return;
}
Menu.openDropDown(this.daddy.div, fcn);
};
}
BlockArg.prototype.closePictureMenu = function (e, mu, b, c) {
closePictureMenu (e, mu, b, c) {
e.preventDefault();
var value = b.owner.arg.argValue;
b.owner.arg.argValue = c.substring(c.indexOf('_') + 1, c.length);
var ctx = b.owner.blockicon.getContext('2d');
b.icon = BlockSpecs.getImageFrom('assets/blockicons/' + c, 'svg');
ctx.clearRect(0, 0, 85 * scaleMultiplier * window.devicePixelRatio, 66 * scaleMultiplier * window.devicePixelRatio);
ctx.clearRect(0, 0, 85 * scaleMultiplier * window.devicePixelRatio,
66 * scaleMultiplier * window.devicePixelRatio);
if (!b.icon.complete) {
b.icon.onload = function () {
var w = b.icon.width;
@ -337,15 +350,16 @@ BlockArg.prototype.closePictureMenu = function (e, mu, b, c) {
ScratchJr.storyStart('BlockArg.prototype.closePictureMenu');
}
Menu.openMenu = undefined;
};
}
BlockArg.prototype.menuCloseSpeeds = function (e, mu, b, c) {
menuCloseSpeeds (e, mu, b, c) {
e.preventDefault();
var value = b.owner.arg.argValue;
b.owner.arg.argValue = BlockSpecs.speeds.indexOf(c);
var ctx = b.owner.blockicon.getContext('2d');
b.icon = BlockSpecs.getImageFrom('assets/blockicons/' + c, 'svg');
ctx.clearRect(0, 0, 64 * scaleMultiplier * window.devicePixelRatio, 64 * scaleMultiplier * window.devicePixelRatio);
ctx.clearRect(0, 0, 64 * scaleMultiplier * window.devicePixelRatio,
64 * scaleMultiplier * window.devicePixelRatio);
// On Android 4.2, clearRect does not work right away. Need to tickle the DOM
b.owner.blockicon.style.display = 'none';
b.owner.blockicon.offsetHeight;
@ -377,13 +391,13 @@ BlockArg.prototype.menuCloseSpeeds = function (e, mu, b, c) {
ScratchJr.storyStart('BlockArg.prototype.menuCloseSpeeds');
}
Menu.openMenu = undefined;
};
}
//////////////////////////
// Page Icon
//////////////////////////
//////////////////////////
// Page Icon
//////////////////////////
BlockArg.prototype.pageIcon = function (num) {
pageIcon (num) {
var dpr = window.devicePixelRatio;
var page = ScratchJr.stage.pages[num - 1];
var icon = document.createElement('canvas');
@ -436,9 +450,9 @@ BlockArg.prototype.pageIcon = function (num) {
ictx.fill();
writeText(ictx, 'bold ' + (12 * dpr) + 'px ' + Settings.blockArgFont, 'white', page.num, 26 * dpr, 58 * dpr);
return icon;
};
}
BlockArg.prototype.updateIcon = function () {
updateIcon () {
var num = this.argValue;
var page = ScratchJr.stage.pages[num - 1];
page.num = num;
@ -447,4 +461,5 @@ BlockArg.prototype.updateIcon = function () {
var ctx = block.blockshape.getContext('2d');
ctx.drawImage(this.div, 0, 0, this.div.width, this.div.height, 0, 0,
this.div.width * block.scale, this.div.height * block.scale);
};
}
}

View file

@ -1,4 +1,21 @@
var Page = function (id, data, fcn) {
import ScratchJr from '../ScratchJr';
import Project from '../../ui/Project';
import Thumbs from '../../ui/Thumbs';
import UI from '../../ui/UI';
import Sprite from './Sprite';
import Palette from './Palette';
import BlockSpecs from '../blocks/BlockSpecs';
import iOS from '../../iPad/iOS';
import IO from '../../iPad/IO';
import Undo from '../ui/Undo';
import Matrix from '../geom/Matrix';
import Vector from '../geom/Vector';
import {newHTML, newDiv, gn,
setCanvasSizeScaledToWindowDocumentHeight,
DEGTOR, getIdFor, setProps, isTablet} from '../../utils/lib';
export default class Page {
constructor (id, data, fcn) {
var container = ScratchJr.stage.pagesdiv;
this.div = newHTML('div', 'stagepage', container); // newDiv(container,0,0, 480, 360, {position: 'absolute'});
this.div.owner = this;
@ -19,9 +36,9 @@ var Page = function (id, data, fcn) {
} else {
this.loadPageData(data, fcn);
}
};
}
Page.prototype.loadPageData = function (data, fcn) {
loadPageData (data, fcn) {
this.currentSpriteName = data.lastSprite;
if (data.textstartat) {
this.textstartat = Number(data.textstartat);
@ -60,14 +77,14 @@ Page.prototype.loadPageData = function (data, fcn) {
fcn();
}
}
};
}
Page.prototype.emptyPage = function () {
emptyPage () {
this.clearBackground();
this.createCat();
};
}
Page.prototype.setCurrentSprite = function (spr) { // set the sprite and toggles UI if no sprite is available
setCurrentSprite (spr) { // set the sprite and toggles UI if no sprite is available
if (ScratchJr.getSprite()) {
ScratchJr.getSprite().unselect();
}
@ -82,15 +99,15 @@ Page.prototype.setCurrentSprite = function (spr) { // set the sprite and toggles
Palette.hide();
gn('scripts').style.display = 'none';
}
};
}
Page.prototype.clearBackground = function () {
clearBackground () {
while (this.bkg.childElementCount > 0) {
this.bkg.removeChild(this.bkg.childNodes[0]);
}
};
}
Page.prototype.setBackground = function (name, fcn) {
setBackground (name, fcn) {
if (name == 'undefined') {
return;
}
@ -136,18 +153,18 @@ Page.prototype.setBackground = function (name, fcn) {
});
}
}
};
}
Page.prototype.setSVG = function (str) {
setSVG (str) {
var xmlDoc = new DOMParser().parseFromString(str, 'text/xml');
var extxml = document.importNode(xmlDoc.documentElement, true);
if (extxml.childNodes[0].nodeName == '#comment') {
extxml.removeChild(extxml.childNodes[0]);
}
this.svg = extxml;
};
}
Page.prototype.setBackgroundImage = function (url, fcn) {
setBackgroundImage (url, fcn) {
var img = document.createElement('img');
img.src = url;
this.bkg.originalImg = img.cloneNode(false);
@ -177,35 +194,35 @@ Page.prototype.setBackgroundImage = function (url, fcn) {
fcn();
}
}
};
}
Page.prototype.setPageSprites = function (showstate) {
setPageSprites (showstate) {
var list = JSON.parse(this.sprites);
for (var i = 0; i < list.length; i++) {
gn(list[i]).style.visibility = showstate;
}
};
}
Page.prototype.redoChangeBkg = function (data) {
redoChangeBkg (data) {
var me = this;
var md5 = data[this.id].md5 ? data[this.id].md5 : 'none';
this.setBackground(md5, me.updateThumb);
};
}
//////////////////////////////////////
// page thumbnail
/////////////////////////////////////
//////////////////////////////////////
// page thumbnail
/////////////////////////////////////
Page.prototype.updateThumb = function (page) {
updateThumb (page) {
var me = page ? page : ScratchJr.stage.currentPage;
if (!me.thumbnail) {
return;
}
var c = me.thumbnail.childNodes[0].childNodes[0];
me.setPageThumb(c);
};
}
Page.prototype.pageThumbnail = function (p) {
pageThumbnail (p) {
var tb = newHTML('div', 'pagethumb', p);
tb.setAttribute('id', getIdFor('pagethumb'));
tb.owner = this.id;
@ -228,9 +245,9 @@ Page.prototype.pageThumbnail = function (p) {
}
this.thumbnail = tb;
return tb;
};
}
Page.prototype.setPageThumb = function (c) {
setPageThumb (c) {
var w0, h0;
if (Settings.edition == 'PBS') {
w0 = 136;
@ -272,17 +289,17 @@ Page.prototype.setPageThumb = function (c) {
ctx.drawImage(BlockSpecs.canvasMask, 0, 0, w, h);
ctx.restore();
}
};
}
Page.prototype.stampSpriteAt = function (ctx, spr, scale) {
stampSpriteAt (ctx, spr, scale) {
if (!spr.shown) {
return;
}
var img = (spr.type == 'sprite') ? spr.originalImg : spr.outline;
this.drawSpriteImage(ctx, img, spr, scale);
};
}
Page.prototype.drawSpriteImage = function (ctx, img, spr, scale) {
drawSpriteImage (ctx, img, spr, scale) {
if (!spr.shown) {
return;
}
@ -312,9 +329,9 @@ Page.prototype.drawSpriteImage = function (ctx, img, spr, scale) {
}));
ctx.drawImage(img, 0, 0, imgw, imgh, pos.x, pos.y, Math.floor(sw * scale), Math.floor(sh * scale));
ctx.restore();
};
}
Page.prototype.getMatrixFor = function (spr) {
getMatrixFor (spr) {
var sx = new Matrix();
var angle = spr.angle ? -spr.angle : 0;
if (spr.flip) {
@ -324,13 +341,13 @@ Page.prototype.getMatrixFor = function (spr) {
var rx = new Matrix();
rx.rotate(angle);
return sx.multiply(rx);
};
}
/////////////////////
// Saving
/////////////////////
/////////////////////
// Saving
/////////////////////
Page.prototype.encodePage = function () {
encodePage () {
var p = this.div;
var spritelist = JSON.parse(this.sprites);
var data = {};
@ -342,7 +359,8 @@ Page.prototype.encodePage = function () {
}
data.num = this.num;
this.currentSpriteName = !this.currentSpriteName ?
undefined : (gn(this.currentSpriteName).owner.type == 'sprite') ? this.currentSpriteName : this.getSprites()[0];
undefined : (gn(this.currentSpriteName).owner.type == 'sprite') ?
this.currentSpriteName : this.getSprites()[0];
data.lastSprite = this.currentSpriteName;
for (var j = 0; j < spritelist.length; j++) {
data[spritelist[j]] = Project.encodeSprite(spritelist[j]);
@ -356,9 +374,9 @@ Page.prototype.encodePage = function () {
}
data.layers = layers;
return data;
};
}
Page.prototype.getSprites = function () {
getSprites () {
var spritelist = JSON.parse(this.sprites);
var res = [];
for (var i = 0; i < spritelist.length; i++) {
@ -367,14 +385,14 @@ Page.prototype.getSprites = function () {
}
}
return res;
};
}
/////////////////////////////
// Object creation
/////////////////////////////
/////////////////////////////
// Object creation
/////////////////////////////
Page.prototype.createText = function () {
createText () {
var textAttr = {
shown: true,
type: 'text',
@ -399,16 +417,16 @@ Page.prototype.createText = function () {
textAttr.page = this;
textAttr.id = getIdFor('Text');
new Sprite(textAttr);
};
}
Page.prototype.createCat = function () {
createCat () {
var sprAttr = UI.mascotData(ScratchJr.stage.currentPage);
Project.mediaCount++;
var me = this;
new Sprite(sprAttr, me.pageAdded);
};
}
Page.prototype.update = function (spr) {
update (spr) {
if (spr) {
Undo.record({
action: 'modify',
@ -428,9 +446,9 @@ Page.prototype.update = function (spr) {
Thumbs.updateSprites();
}
Thumbs.updatePages();
};
}
Page.prototype.updateBkg = function () {
updateBkg () {
var me = ScratchJr.stage.currentPage;
ScratchJr.storyStart('Page.prototype.updateBkg');
Undo.record({
@ -439,17 +457,17 @@ Page.prototype.updateBkg = function () {
who: me.id
});
Thumbs.updatePages();
};
}
Page.prototype.spriteAdded = function (spr) {
spriteAdded (spr) {
var me = spr.div.parentNode.owner;
me.setCurrentSprite(spr);
me.update(spr);
UI.spriteInView(spr);
ScratchJr.onHold = false;
};
}
Page.prototype.pageAdded = function (spr) {
pageAdded (spr) {
var me = spr.div.parentNode.owner;
Project.mediaCount--;
me.setCurrentSprite(spr);
@ -463,9 +481,9 @@ Page.prototype.pageAdded = function (spr) {
}
Thumbs.updateSprites();
Thumbs.updatePages();
};
}
Page.prototype.addSprite = function (scale, md5, cname) {
addSprite (scale, md5, cname) {
ScratchJr.onHold = true;
var sprAttr = {
flip: false,
@ -490,13 +508,13 @@ Page.prototype.addSprite = function (scale, md5, cname) {
sprAttr.name = cname;
sprAttr.md5 = md5;
new Sprite(sprAttr, this.spriteAdded);
};
}
Page.prototype.createSprite = function (data) {
createSprite (data) {
new Sprite(data, this.spriteAdded);
};
}
Page.prototype.modifySprite = function (md5, cid, sid) {
modifySprite (md5, cid, sid) {
var sprite = gn(unescape(sid)).owner;
if (!sprite) {
sprite = ScratchJr.getSprite();
@ -508,9 +526,9 @@ Page.prototype.modifySprite = function (md5, cid, sid) {
function gotImage (dataurl) {
sprite.setCostume(dataurl, me.spriteAdded);
}
};
}
Page.prototype.modifySpriteName = function (cid, sid) {
modifySpriteName (cid, sid) {
var sprite = gn(unescape(sid)).owner;
if (!sprite) {
sprite = ScratchJr.getSprite();
@ -523,4 +541,5 @@ Page.prototype.modifySpriteName = function (cid, sid) {
who: sprite.id
});
ScratchJr.storyStart('Page.prototype.modifySpriteName');
};
}
}

View file

@ -1,11 +1,17 @@
var Runtime = function () {
import ScratchJr from '../ScratchJr';
import Project from '../../ui/Project';
import Prims from './Prims';
import Thread from './Thread';
export default class Runtime {
constructor () {
this.threadsRunning = [];
this.thread = undefined;
this.intervalId = undefined;
this.yield = false;
};
}
Runtime.prototype.beginTimer = function () {
beginTimer () {
if (this.intervalId != null) {
window.clearInterval(this.intervalId);
}
@ -16,9 +22,9 @@ Runtime.prototype.beginTimer = function () {
Project.saving = false;
// Prims.time = (new Date() - 0);
this.threadsRunning = [];
};
}
Runtime.prototype.tickTask = function () {
tickTask () {
ScratchJr.updateRunStopButtons();
if (this.threadsRunning.length < 1) {
return;
@ -33,9 +39,9 @@ Runtime.prototype.tickTask = function () {
for (var j = 0; j < this.threadsRunning.length; j++) {
this.step(j);
}
};
}
Runtime.prototype.inactive = function () {
inactive () {
if (this.threadsRunning.length < 1) {
return true;
}
@ -48,14 +54,15 @@ Runtime.prototype.inactive = function () {
if (t.isRunning && (t.firstBlock.blocktype != 'ontouch')) {
inactive = false;
}
if ((t.firstBlock.blocktype == 'ontouch') && (t.thisblock != null) && (t.thisblock.blocktype != 'ontouch')) {
if ((t.firstBlock.blocktype == 'ontouch') && (t.thisblock != null)
&& (t.thisblock.blocktype != 'ontouch')) {
inactive = false;
}
}
return inactive;
};
}
Runtime.prototype.step = function (n) {
step (n) {
this.yield = false;
this.thread = this.threadsRunning[n];
while (true) { // eslint-disable-line no-constant-condition
@ -77,36 +84,36 @@ Runtime.prototype.step = function (n) {
this.runPrim();
}
}
};
}
Runtime.prototype.addRunScript = function (spr, b) {
addRunScript (spr, b) {
this.restartThread(spr, b);
};
}
Runtime.prototype.stopThreads = function () {
stopThreads () {
for (var i in this.threadsRunning) {
this.threadsRunning[i].stop();
}
this.threadsRunning = [];
};
}
Runtime.prototype.stopThreadBlock = function (b) {
stopThreadBlock (b) {
for (var i in this.threadsRunning) {
if (this.threadsRunning[i].firstBlock == b) {
this.threadsRunning[i].stop();
}
}
};
}
Runtime.prototype.stopThreadSprite = function (spr) {
stopThreadSprite (spr) {
for (var i in this.threadsRunning) {
if (this.threadsRunning[i].spr == spr) {
this.threadsRunning[i].stop();
}
}
};
}
Runtime.prototype.removeRunScript = function (spr) {
removeRunScript (spr) {
var res = [];
for (var i in this.threadsRunning) {
if (this.threadsRunning[i].spr == spr) {
@ -123,9 +130,9 @@ Runtime.prototype.removeRunScript = function (spr) {
}
}
return res;
};
}
Runtime.prototype.runPrim = function () {
runPrim () {
if (this.thread.oldblock != null) {
this.thread.oldblock.unhighlight();
}
@ -142,9 +149,9 @@ Runtime.prototype.runPrim = function () {
Prims.time = (new Date() - 0);
token(this.thread);
}
};
}
Runtime.prototype.endCase = function () {
endCase () {
if (this.thread.oldblock != null) {
this.thread.oldblock.unhighlight();
}
@ -155,9 +162,9 @@ Runtime.prototype.endCase = function () {
this.thread.thisblock = thing;
this.runPrim();
}
};
}
Runtime.prototype.restartThread = function (spr, b, active) {
restartThread (spr, b, active) {
var newThread = new Thread(spr, b);
var wasRunning = false;
for (var i = 0; i < this.threadsRunning.length; i++) {
@ -176,4 +183,5 @@ Runtime.prototype.restartThread = function (spr, b, active) {
this.threadsRunning.push(newThread);
}
return newThread;
};
}
}

View file

@ -7,15 +7,38 @@
// d. Create Mask for pixel detection and cache it on the browser
////////////////////////////////////////////////////////////
var Sprite = function (attr, whenDone) {
import ScratchJr from '../ScratchJr';
import Project from '../../ui/Project';
import Thumbs from '../../ui/Thumbs';
import UI from '../../ui/UI';
import BlockSpecs from '../blocks/BlockSpecs';
import iOS from '../../iPad/iOS';
import IO from '../../iPad/IO';
import Undo from '../ui/Undo';
import ScriptsPane from '../ui/ScriptsPane';
import SVG2Canvas from '../../utils/SVG2Canvas';
import SVGTools from '../../painteditor/SVGTools';
import Rectangle from '../../geom/Rectangle';
import Events from '../../utils/Events';
import Localization from '../../utils/Localization';
import ScratchAudio from '../../utils/ScratchAudio';
import Scripts from '../ui/Scripts';
import {newHTML, newDiv, newP, gn,
setCanvasSizeScaledToWindowDocumentHeight,
DEGTOR, getIdFor, setProps, isTablet, isiOS,
isAndroid, fitInRect, scaleMultiplier, setCanvasSize,
globaly, globalx, rgbToHex} from '../../utils/lib';
export default class Sprite {
constructor (attr, whenDone) {
if (attr.type == 'sprite') {
this.createSprite(attr.page, attr.md5, attr.id, attr, whenDone);
} else {
this.createText(attr, whenDone);
}
};
}
Sprite.prototype.createSprite = function (page, md5, id, attr, fcn) {
createSprite (page, md5, id, attr, fcn) {
ScratchJr.storyStart('Sprite.prototype.createSprite');
this.div = document.createElement('div');
setProps(this.div.style, {
@ -48,9 +71,9 @@ Sprite.prototype.createSprite = function (page, md5, id, attr, fcn) {
function gotImage (dataurl) {
me.setCostume(dataurl, fcn);
}
};
}
Sprite.prototype.getAsset = function (whenDone) {
getAsset (whenDone) {
var md5 = this.md5;
var spr = this;
var url = (MediaLib.keys[md5]) ? MediaLib.path + md5 : (md5.indexOf('/') < 0) ? iOS.path + md5 : md5;
@ -66,7 +89,7 @@ Sprite.prototype.getAsset = function (whenDone) {
function doNext (str) {
str = str.replace(/>\s*</g, '><');
spr.setSVG(str);
if ((str.indexOf('xlink:href') < 0) && iOS.path {
if ((str.indexOf('xlink:href') < 0) && iOS.path) {
whenDone(url); // does not have embedded images
} else {
var base64 = IO.getImageDataURL(spr.md5, btoa(str));
@ -75,18 +98,18 @@ Sprite.prototype.getAsset = function (whenDone) {
});
}
}
};
}
Sprite.prototype.setSVG = function (str) {
setSVG (str) {
var xmlDoc = new DOMParser().parseFromString(str, 'text/xml');
var extxml = document.importNode(xmlDoc.documentElement, true);
if (extxml.childNodes[0].nodeName == '#comment') {
extxml.removeChild(extxml.childNodes[0]);
}
this.svg = extxml;
};
}
Sprite.prototype.setCostume = function (dataurl, fcn) {
setCostume (dataurl, fcn) {
var img = document.createElement('img');
img.src = dataurl;
this.img = img;
@ -106,9 +129,9 @@ Sprite.prototype.setCostume = function (dataurl, fcn) {
} else {
sprite.displaySprite(fcn);
}
};
}
Sprite.prototype.displaySprite = function (whenDone) {
displaySprite (whenDone) {
var w = this.img.width;
var h = this.img.height;
this.div.style.width = this.img.width + 'px';
@ -119,9 +142,9 @@ Sprite.prototype.displaySprite = function (whenDone) {
this.h = h;
this.setPos(this.xcoor, this.ycoor);
this.doRender(whenDone);
};
}
Sprite.prototype.doRender = function (whenDone) {
doRender (whenDone) {
this.drawBorder(); // canvas draw border
this.render();
SVG2Canvas.drawInCanvas(this); // canvas draws mask for pixel detection
@ -130,9 +153,9 @@ Sprite.prototype.doRender = function (whenDone) {
if (whenDone) {
whenDone(this);
}
};
}
Sprite.prototype.drawBorder = function () {
drawBorder () {
// TODO: Merge these to get better thumbnail rendering on iOS
var w, h, extxml;
if (isAndroid) {
@ -153,13 +176,13 @@ Sprite.prototype.drawBorder = function () {
setCanvasSize(this.border, w, h);
SVG2Canvas.drawBorder(extxml, this.border.getContext('2d'));
}
};
}
//////////////////////////////////////
// sprite thumbnail
/////////////////////////////////////
//////////////////////////////////////
// sprite thumbnail
/////////////////////////////////////
Sprite.prototype.spriteThumbnail = function (p) {
spriteThumbnail (p) {
var tb = newHTML('div', 'spritethumb off', p);
tb.setAttribute('id', getIdFor('spritethumb'));
tb.type = 'spritethumb';
@ -179,9 +202,9 @@ Sprite.prototype.spriteThumbnail = function (p) {
newHTML('div', 'brush', tb);
this.thumbnail = tb;
return tb;
};
}
Sprite.prototype.updateSpriteThumb = function () {
updateSpriteThumb () {
var tb = this.thumbnail;
if (!tb) {
return;
@ -189,9 +212,9 @@ Sprite.prototype.updateSpriteThumb = function () {
var cnv = tb.childNodes[0];
this.drawMyImage(cnv, cnv.width, cnv.height);
tb.childNodes[1].textContent = this.name;
};
}
Sprite.prototype.drawMyImage = function (cnv, w, h) {
drawMyImage (cnv, w, h) {
if (!this.img) {
return;
}
@ -220,13 +243,13 @@ Sprite.prototype.drawMyImage = function (cnv, w, h) {
} else {
ctx.drawImage(img, 0, 0, imgw, imgh, ix, iy, iw, ih);
}
};
}
///////////////////////////////////////////////////////////////////////////////
// sprite Primitives
//////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// sprite Primitives
//////////////////////////////////////////////////////////////////////////////
Sprite.prototype.goHome = function () {
goHome () {
this.setPos(this.homex, this.homey);
this.scale = this.homescale;
this.shown = this.homeshown;
@ -234,9 +257,9 @@ Sprite.prototype.goHome = function () {
this.div.style.opacity = this.shown ? 1 : 0;
this.setHeading(0);
this.render();
};
}
Sprite.prototype.touchingAny = function () {
touchingAny () {
if (!this.shown) {
return false;
}
@ -270,9 +293,9 @@ Sprite.prototype.touchingAny = function () {
}
}
return false;
};
}
Sprite.prototype.verifyHit = function (other) {
verifyHit (other) {
var ctx = ScratchJr.workingCanvas.getContext('2d');
var ctx2 = ScratchJr.workingCanvas2.getContext('2d');
ctx.clearRect(0, 0, 480, 360);
@ -290,7 +313,8 @@ Sprite.prototype.verifyHit = function (other) {
this.stamp(ctx);
// Normally, we could do a source-over followed by a source-in to detect where the two images collide.
// However, unfortunately, behavior on Android 4.2 and Android 4.4+ varies.
// On Android 4.4+, we could potentially use this more efficient strategy, but we opted for using a single strategy
// On Android 4.4+, we could potentially use this more efficient strategy,
// but we opted for using a single strategy
// that works on all platforms, despite it being less efficient.
// A future optimization could detect the behavior and use
// the right strategy.
@ -315,18 +339,18 @@ Sprite.prototype.verifyHit = function (other) {
}
}
return false;
};
}
Sprite.prototype.getAlpha = function (data, node, w) {
getAlpha (data, node, w) {
return data[(node.x * 4) + node.y * w * 4 + 3];
};
}
Sprite.prototype.setHeading = function (angle) {
setHeading (angle) {
this.angle = angle % 360;
this.render();
};
}
Sprite.prototype.setPos = function (dx, dy) {
setPos (dx, dy) {
this.dirx = ((dx - this.xcoor) == 0) ? 1 : (dx - this.xcoor) / Math.abs(dx - this.xcoor);
this.diry = ((dy - this.ycoor) == 0) ? 1 : (dy - this.ycoor) / Math.abs(dy - this.ycoor);
this.xcoor = dx;
@ -339,17 +363,17 @@ Sprite.prototype.setPos = function (dx, dy) {
top: '0px'
});
this.updateBubble();
};
}
Sprite.prototype.wrap = function () {
wrap () {
if (this.type == 'text') {
this.wrapText();
} else {
this.wrapChar();
}
};
}
Sprite.prototype.wrapChar = function () {
wrapChar () {
if (this.xcoor < 0) {
this.xcoor = 480 + this.xcoor;
}
@ -362,9 +386,9 @@ Sprite.prototype.wrapChar = function () {
if (this.ycoor >= 360) {
this.ycoor = this.ycoor - 360;
}
};
}
Sprite.prototype.wrapText = function () {
wrapText () {
var max = this.cx > 480 ? this.cx : 480;
var min = this.cx > 480 ? 480 - this.cx : 0;
if (this.xcoor < min) {
@ -379,9 +403,9 @@ Sprite.prototype.wrapText = function () {
if (this.ycoor >= 360) {
this.ycoor = this.ycoor - 360;
}
};
}
Sprite.prototype.render = function () {
render () {
// TODO: Merge these to get better thumbnail rendering on iOS
var dx, dy, mtx;
if (isAndroid) {
@ -426,9 +450,9 @@ Sprite.prototype.render = function () {
}
this.setTransform(mtx);
}
};
}
Sprite.prototype.select = function () {
select () {
if (this.borderOn) {
return;
}
@ -452,9 +476,9 @@ Sprite.prototype.select = function () {
});
this.borderOn = true;
this.render();
};
}
Sprite.prototype.unselect = function () {
unselect () {
if (!this.borderOn) {
return;
}
@ -463,32 +487,32 @@ Sprite.prototype.unselect = function () {
}
this.div.appendChild(this.img);
this.borderOn = false;
};
}
Sprite.prototype.setTransform = function (transform) {
setTransform (transform) {
this.div.style.webkitTransform = transform;
};
}
Sprite.prototype.screenLeft = function () {
screenLeft () {
return Math.round(this.xcoor - this.cx * this.scale);
};
}
Sprite.prototype.screenTop = function () {
screenTop () {
return Math.round(this.ycoor - this.cy * this.scale);
};
}
Sprite.prototype.noScaleFor = function () {
noScaleFor () {
this.setScaleTo(this.defaultScale);
};
}
Sprite.prototype.changeSizeBy = function (num) {
changeSizeBy (num) {
var n = Number(num) + Number(this.scale) * 100;
this.scale = this.getScale(n / 100);
this.setPos(this.xcoor, this.ycoor);
this.render();
};
}
Sprite.prototype.setScaleTo = function (n) {
setScaleTo (n) {
n = this.getScale(n);
if (n == this.scale) {
return;
@ -496,9 +520,9 @@ Sprite.prototype.setScaleTo = function (n) {
this.scale = n;
this.setPos(this.xcoor, this.ycoor);
this.render();
};
}
Sprite.prototype.getScale = function (n) {
getScale (n) {
var mins = Math.max(Math.max(this.w, this.h) * n, 36);
var maxs = Math.min(Math.min(this.w, this.h) * n, 360);
if (mins == 36) {
@ -508,9 +532,9 @@ Sprite.prototype.getScale = function (n) {
return 360 / Math.min(this.w, this.h);
}
return n;
};
}
Sprite.prototype.getBox = function () {
getBox () {
var box = {
x: this.screenLeft(),
y: this.screenTop(),
@ -518,31 +542,32 @@ Sprite.prototype.getBox = function () {
height: this.h * this.scale
};
return box;
};
}
Sprite.prototype.getBoxWithEffects = function () {
getBoxWithEffects () {
if (this.type == 'text') {
return new Rectangle(this.screenLeft(), this.screenTop(), this.w * this.scale, this.h * this.scale);
}
var max = Math.max(this.outline.width, this.outline.height);
var w = Math.floor(max * 1.5 * this.scale);
var h = Math.floor(max * 1.5 * this.scale);
return new Rectangle(Math.floor(this.xcoor - w / 2), Math.floor(this.ycoor - h / 2), Math.floor(w), Math.floor(h));
};
return new Rectangle(Math.floor(this.xcoor - w / 2),
Math.floor(this.ycoor - h / 2), Math.floor(w), Math.floor(h));
}
//////////////////////////////////////////////////
// Balloon
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// Balloon
//////////////////////////////////////////////////
Sprite.prototype.closeBalloon = function () {
closeBalloon () {
if (!this.balloon) {
return;
}
this.balloon.parentNode.removeChild(this.balloon);
this.balloon = undefined;
};
}
Sprite.prototype.openBalloon = function (label) {
openBalloon (label) {
if (this.balloon) {
this.closeBalloon();
}
@ -596,9 +621,9 @@ Sprite.prototype.openBalloon = function (label) {
visibility: 'visible'
});
this.drawBalloon();
};
}
Sprite.prototype.updateBubble = function () {
updateBubble () {
if (this.balloon == null) {
return;
}
@ -616,9 +641,9 @@ Sprite.prototype.updateBubble = function () {
this.balloon.left = dx;
this.balloon.top = dy;
this.drawBalloon();
};
}
Sprite.prototype.drawBalloon = function () {
drawBalloon () {
var img = this.balloon.childNodes[0];
var w = this.balloon.offsetWidth;
var h = this.balloon.offsetHeight;
@ -646,13 +671,13 @@ Sprite.prototype.drawBalloon = function () {
var b = a[1].split('h-1');
str = a[0] + 'h' + (-side1 + 7 + curve) + b[0] + 'h' + (-side2 + 7 + curve) + b[1];
img.src = 'data:image/svg+xml;base64,' + btoa(str);
};
}
/////////////////////////////////////
// Sprite rendering
////////////////////////////////////
/////////////////////////////////////
// Sprite rendering
////////////////////////////////////
Sprite.prototype.stamp = function (ctx, deltax, deltay) {
stamp (ctx, deltax, deltay) {
var w = this.outline.width * this.scale;
var h = this.outline.height * this.scale;
var dx = deltax ? deltax : 0;
@ -665,13 +690,13 @@ Sprite.prototype.stamp = function (ctx, deltax, deltay) {
}
ctx.drawImage(this.outline, -w / 2, -h / 2, w, h);
ctx.restore();
};
}
/////////////////////////////////////
// Text Creation
/////////////////////////////////////
/////////////////////////////////////
// Text Creation
/////////////////////////////////////
Sprite.prototype.createText = function (attr, whenDone) {
createText (attr, whenDone) {
var page = attr.page;
setProps(this, attr);
this.div = newHTML('p', 'textsprite', page.div);
@ -707,9 +732,9 @@ Sprite.prototype.createText = function (attr, whenDone) {
whenDone(this);
}
}
};
}
Sprite.prototype.setTextBox = function () {
setTextBox () {
var sform = document.forms.activetextbox;
sform.textsprite = this;
var box = this.getBox();
@ -771,9 +796,9 @@ Sprite.prototype.setTextBox = function () {
height: (this.fontsize + 10) + 'px'
});
}
};
}
Sprite.prototype.unfocusText = function () {
unfocusText () {
ScratchJr.blur();
document.body.scrollTop = 0;
document.body.scrollLeft = 0;
@ -808,9 +833,9 @@ Sprite.prototype.unfocusText = function () {
ScratchJr.onBackButtonCallback.pop();
AndroidInterface.scratchjr_forceHideKeyboard();
}
};
}
Sprite.prototype.deleteText = function (record) {
deleteText (record) {
var id = this.id;
var page = ScratchJr.stage.currentPage;
page.textstartat = (this.ycoor + (this.fontsize * 1.35)) > 360 ? 36 : this.ycoor;
@ -833,32 +858,32 @@ Sprite.prototype.deleteText = function (record) {
});
ScratchJr.storyStart('Sprite.prototype.deleteText');
}
};
}
Sprite.prototype.noChars = function (str) {
noChars (str) {
for (var i = 0; i < str.length; i++) {
if (str[i] != ' ') {
return false;
}
}
return true;
};
}
Sprite.prototype.contractText = function () {
contractText () {
var form = document.forms.activetextbox;
this.str = form.typing.value.substring(0, form.typing.maxLength);
this.recalculateText();
};
}
Sprite.prototype.clickOnText = function (e) {
clickOnText (e) {
e.stopPropagation();
this.setTextBox();
gn('textbox').style.visibility = 'visible';
this.div.style.visibility = 'hidden';
this.activateInput();
};
}
Sprite.prototype.activateInput = function () {
activateInput () {
this.oldvalue = this.str;
var ti = document.forms.activetextbox.typing;
gn('textbox').style.visibility = 'visible';
@ -892,9 +917,9 @@ Sprite.prototype.activateInput = function () {
}, 100);
}
}
};
}
Sprite.prototype.handleWrite = function (e) {
handleWrite (e) {
var key = e.keyCode || e.which;
var ti = e.target;
if (key == 13) {
@ -906,24 +931,24 @@ Sprite.prototype.handleWrite = function (e) {
this.deactivateInput();
}
}
};
}
Sprite.prototype.handleKeyUp = function (e) {
handleKeyUp (e) {
var ti = e.target;
if (!(ti.parentNode).textsprite) {
return;
}
(ti.parentNode).textsprite.str = ti.value;
};
}
Sprite.prototype.deactivateInput = function () {
deactivateInput () {
var ti = document.forms.activetextbox.typing;
ti.onblur = undefined;
ti.onkeypress = undefined;
ti.onsubmit = undefined;
};
}
Sprite.prototype.activate = function () {
activate () {
var list = fitInRect(this.w, this.h, ScriptsPane.watermark.offsetWidth, ScriptsPane.watermark.offsetHeight);
var div = ScriptsPane.watermark;
while (div.childElementCount > 0) {
@ -939,26 +964,26 @@ Sprite.prototype.activate = function () {
zoom: Math.floor((list[2] / this.w) * 100) + '%'
};
setProps(img.style, attr);
};
}
Sprite.prototype.getSVGimage = function (svg) {
getSVGimage (svg) {
var img = document.createElement('img');
var str = (new XMLSerializer()).serializeToString(svg);
str = str.replace(/ href="data:image/g, ' xlink:href="data:image');
img.src = 'data:image/svg+xml;base64,' + btoa(str);
return img;
};
}
/////////////////////////////////////////////////
// Text fcn
////////////////////////////////////////////////
/////////////////////////////////////////////////
// Text fcn
////////////////////////////////////////////////
Sprite.prototype.setColor = function (c) {
setColor (c) {
this.color = c;
this.div.style.color = this.color;
};
}
Sprite.prototype.setFontSize = function (n) {
setFontSize (n) {
if (n < 12) {
n = 12;
}
@ -966,9 +991,9 @@ Sprite.prototype.setFontSize = function (n) {
n = 72;
}
this.fontsize = n;
};
}
Sprite.prototype.recalculateText = function () {
recalculateText () {
this.div.style.color = this.color;
this.div.style.fontSize = this.fontsize + 'px';
this.div.textContent = this.str;
@ -988,9 +1013,9 @@ Sprite.prototype.recalculateText = function () {
ctx.textBaseline = 'top';
ctx.fillText(this.str, 0, 0);
this.setPos(this.xcoor, this.ycoor);
};
}
Sprite.prototype.startShaking = function () {
startShaking () {
var p = this.div.parentNode;
var shake = newHTML('div', 'shakeme', p);
shake.id = 'shakediv';
@ -1038,9 +1063,9 @@ Sprite.prototype.startShaking = function () {
cb.id = 'deletesprite';
this.div = shake;
this.div.owner = this;
};
}
Sprite.prototype.stopShaking = function () {
stopShaking () {
if (this.div.id != 'shakediv') {
return;
}
@ -1066,9 +1091,9 @@ Sprite.prototype.stopShaking = function () {
}
this.setTransform(mtx);
}
};
}
Sprite.prototype.drawCloseButton = function () {
drawCloseButton () {
var ctx = this.div.getContext('2d');
var img = document.createElement('img');
img.src = 'assets/ui/closeit.svg';
@ -1079,13 +1104,13 @@ Sprite.prototype.drawCloseButton = function () {
} else {
ctx.drawImage(img, 0, 0);
}
};
}
//////////////////////////////////////////
// Save data
/////////////////////////////////////////
//////////////////////////////////////////
// Save data
/////////////////////////////////////////
Sprite.prototype.getData = function () {
getData () {
var data = (this.type == 'sprite') ? this.getSpriteData() : this.getTextBoxData();
if (this.type != 'sprite') {
return data;
@ -1098,9 +1123,9 @@ Sprite.prototype.getData = function () {
}
data.scripts = res;
return data;
};
}
Sprite.prototype.getSpriteData = function () {
getSpriteData () {
var data = {};
data.shown = this.shown;
data.type = this.type;
@ -1125,9 +1150,9 @@ Sprite.prototype.getSpriteData = function () {
data.homeshown = this.homeshown;
data.homeflip = this.homeflip;
return data;
};
}
Sprite.prototype.getTextBoxData = function () {
getTextBoxData () {
var data = {};
data.shown = this.shown;
data.type = this.type;
@ -1145,4 +1170,5 @@ Sprite.prototype.getTextBoxData = function () {
data.color = this.color;
data.fontsize = this.fontsize;
return data;
};
}
}

View file

@ -1,4 +1,21 @@
var Stage = function (div) {
import ScratchJr from '../ScratchJr';
import Project from '../../ui/Project';
import Thumbs from '../../ui/Thumbs';
import UI from '../../ui/UI';
import Undo from '../ui/Undo';
import ScriptsPane from '../ui/ScriptsPane';
import Rectangle from '../../geom/Rectangle';
import Events from '../../utils/Events';
import ScratchAudio from '../../utils/ScratchAudio';
import Vector from '../../geom/Vector';
import Page from './Page';
import {newHTML, newDiv, gn,
getIdFor, setProps,
scaleMultiplier, setCanvasSize,
globaly, globalx} from '../../utils/lib';
export default class Stage {
constructor (div) {
this.currentPage = undefined;
this.div = newHTML('div', 'stage', div);
this.div.setAttribute('id', 'stage');
@ -24,35 +41,35 @@ var Stage = function (div) {
x: 0,
y: 0
};
};
}
Stage.prototype.setStageScaleAndPosition = function (scale, x, y) {
setStageScaleAndPosition (scale, x, y) {
this.stageScale = scale;
setProps(gn('stage').style, {
webkitTransform: 'translate(' + (-this.width / 2) + 'px, ' + (-this.height / 2) + 'px) ' +
'scale(' + scale + ') ' +
'translate(' + (this.width / 2 + x) + 'px, ' + (this.height / 2 + y) + 'px)'
});
};
}
Stage.prototype.getPagesID = function () {
getPagesID () {
var res = [];
for (var i = 0; i < this.pages.length; i++) {
res.push(this.pages[i].id);
}
return res;
};
}
Stage.prototype.getPage = function (id) {
getPage (id) {
for (var i = 0; i < this.pages.length; i++) {
if (this.pages[i].id == id) {
return this.pages[i];
}
}
return this.pages[0];
};
}
Stage.prototype.resetPage = function (obj) {
resetPage (obj) {
var page = obj.div;
for (var i = 0; i < page.childElementCount; i++) {
var spr = page.childNodes[i].owner;
@ -63,19 +80,19 @@ Stage.prototype.resetPage = function (obj) {
spr.goHome();
}
}
};
}
Stage.prototype.resetPages = function () {
resetPages () {
for (var i = 0; i < ScratchJr.stage.pages.length; i++) {
Stage.prototype.resetPage(ScratchJr.stage.pages[i]);
}
};
}
//goto page
//goto page
Stage.prototype.gotoPage = function (n) {
gotoPage (n) {
if (n < 1) {
return;
}
@ -86,9 +103,9 @@ Stage.prototype.gotoPage = function (n) {
return;
}
this.setPage(this.pages[n - 1], true);
};
}
Stage.prototype.setPage = function (page, isOn) {
setPage (page, isOn) {
ScratchJr.stopStrips();
var sc = ScratchJr.getSprite() ? gn(ScratchJr.stage.currentPage.currentSpriteName + '_scripts') : undefined;
if (sc) {
@ -109,9 +126,9 @@ Stage.prototype.setPage = function (page, isOn) {
if (isOn) {
this.loadPageThreads();
}
};
}
Stage.prototype.loadPageThreads = function () {
loadPageThreads () {
ScratchJr.blur();
var page = this.currentPage;
for (var i = 0; i < page.div.childElementCount; i++) {
@ -130,13 +147,13 @@ Stage.prototype.loadPageThreads = function () {
ScratchJr.runtime.addRunScript(spr, b);
}
}
};
}
//Copy Sprite
/////////////////////////////////'
//Copy Sprite
/////////////////////////////////'
Stage.prototype.copySprite = function (el, thumb) {
copySprite (el, thumb) {
ScratchAudio.sndFX('copy.wav');
Thumbs.overpage(thumb);
var data = Project.encodeSprite(el.owner);
@ -171,13 +188,13 @@ Stage.prototype.copySprite = function (el, thumb) {
ScratchJr.storyStart('Stage.prototype.copySprite');
};
Project.recreateObject(page, name, data, whenDone, page.id == stg.currentPage.id);
};
}
//Delete page
//Delete page
Stage.prototype.deletePage = function (str, data) {
deletePage (str, data) {
// reserve a next id to be able to Undo deleting the first page
ScratchJr.storyStart('Stage.prototype.deletePage'); // Record a change for sample projects in story-starter mode
var pageid = getIdFor('page');
@ -234,15 +251,15 @@ Stage.prototype.deletePage = function (str, data) {
});
}
}
};
}
Stage.prototype.setViewPage = function (page) {
setViewPage (page) {
this.currentPage = page;
this.currentPage.div.style.visibility = 'visible';
this.currentPage.setPageSprites('visible');
};
}
Stage.prototype.removePageBlocks = function (str) {
removePageBlocks (str) {
var indx = this.getPagesID().indexOf(str);
for (var n = 0; n < this.pages.length; n++) {
var page = this.pages[n];
@ -274,13 +291,13 @@ Stage.prototype.removePageBlocks = function (str) {
}
}
}
};
}
//Events MouseDown
//Events MouseDown
Stage.prototype.mouseDown = function (e) {
mouseDown (e) {
if (e.touches && (e.touches.length > 1)) {
return;
}
@ -321,9 +338,9 @@ Stage.prototype.mouseDown = function (e) {
} else {
this.mouseDownOnSprite(hitobj, pt);
}
};
}
Stage.prototype.checkShaking = function (pt, target) {
checkShaking (pt, target) {
if (!ScratchJr.shaking) {
return target;
}
@ -333,9 +350,9 @@ Stage.prototype.checkShaking = function (pt, target) {
var h = gn('deletesprite').offsetHeight;
var rect = new Rectangle(dx, dy, w, h);
return rect.hitRect(pt) ? gn('deletesprite') : target;
};
}
Stage.prototype.mouseDownOnSprite = function (spr, pt) {
mouseDownOnSprite (spr, pt) {
this.initialPoint = {
x: pt.x,
y: pt.y
@ -346,9 +363,9 @@ Stage.prototype.mouseDownOnSprite = function (spr, pt) {
Events.holdit(spr.div, this.startShaking);
}
this.setEvents();
};
}
Stage.prototype.whoIsIt = function (ctx, pt) {
whoIsIt (ctx, pt) {
var page = this.currentPage.div;
var spr, pixel;
for (var i = page.childElementCount - 1; i > -1; i--) {
@ -386,9 +403,9 @@ Stage.prototype.whoIsIt = function (ctx, pt) {
}
}
return undefined;
};
}
Stage.prototype.getStagePt = function (evt) {
getStagePt (evt) {
var pt = Events.getTargetPoint(evt);
var mc = this.div;
var dx = globalx(mc);
@ -398,9 +415,9 @@ Stage.prototype.getStagePt = function (evt) {
pt.x /= this.stageScale;
pt.y /= this.stageScale;
return pt;
};
}
Stage.prototype.setEvents = function () {
setEvents () {
var me = this;
window.ontouchmove = function (evt) {
me.mouseMove(evt);
@ -408,9 +425,9 @@ Stage.prototype.setEvents = function () {
window.ontouchend = function (evt) {
me.mouseUp(evt);
};
};
}
Stage.prototype.startShaking = function (b) {
startShaking (b) {
if (!b.owner) {
return;
}
@ -418,18 +435,18 @@ Stage.prototype.startShaking = function (b) {
ScratchJr.shaking = b;
ScratchJr.stopShaking = ScratchJr.stage.stopShaking;
b.owner.startShaking();
};
}
Stage.prototype.stopShaking = function (b) {
stopShaking (b) {
if (!b.owner) {
return;
}
b.owner.stopShaking();
ScratchJr.shaking = undefined;
ScratchJr.stopShaking = undefined;
};
}
Stage.prototype.startSpriteDrag = function () {
startSpriteDrag () {
var spr = Events.dragthumbnail.owner;
spr.threads = ScratchJr.runtime.removeRunScript(spr);
this.currentPage.div.appendChild(Events.dragthumbnail);
@ -439,9 +456,9 @@ Stage.prototype.startSpriteDrag = function () {
};
Events.dragged = true;
ScratchJr.changed = true;
};
}
Stage.prototype.mouseMove = function (e) {
mouseMove (e) {
if (!Events.dragthumbnail) {
return;
}
@ -467,17 +484,17 @@ Stage.prototype.mouseMove = function (e) {
x: pt.x,
y: pt.y
};
};
}
Stage.prototype.wrapDelta = function (spr, delta) {
wrapDelta (spr, delta) {
if (spr.type == 'text') {
return this.wrapText(spr, delta);
} else {
return this.wrapChar(spr, delta);
}
};
}
Stage.prototype.wrapChar = function (spr, delta) {
wrapChar (spr, delta) {
if ((delta.x + spr.xcoor) < 0) {
delta.x -= (spr.xcoor + delta.x);
}
@ -491,9 +508,9 @@ Stage.prototype.wrapChar = function (spr, delta) {
delta.y += (359 - (spr.ycoor + delta.y));
}
return delta;
};
}
Stage.prototype.wrapText = function (spr, delta) {
wrapText (spr, delta) {
var max = spr.cx > 480 ? spr.cx : 480;
var min = spr.cx > 480 ? 480 - spr.cx : 0;
if ((delta.x + spr.xcoor) <= min) {
@ -509,9 +526,9 @@ Stage.prototype.wrapText = function (spr, delta) {
delta.y += (359 - (spr.ycoor + delta.y));
}
return delta;
};
}
Stage.prototype.mouseUp = function (e) {
mouseUp (e) {
var spr = Events.dragthumbnail.owner;
if (Events.timeoutEvent) {
clearTimeout(Events.timeoutEvent);
@ -529,29 +546,29 @@ Stage.prototype.mouseUp = function (e) {
Events.clearEvents();
Events.dragged = false;
Events.dragthumbnail = undefined;
};
}
Stage.prototype.moveElementBy = function (spr) {
moveElementBy (spr) {
if (!ScratchJr.inFullscreen) {
spr.homex = spr.xcoor;
spr.homey = spr.ycoor;
spr.homeflip = spr.flip;
}
Thumbs.updatePages();
};
}
Stage.prototype.clickOnSprite = function (e, spr) {
clickOnSprite (e, spr) {
e.preventDefault();
ScratchJr.clearSelection();
ScratchJr.startScriptsFor(spr, ['onclick']);
ScratchJr.startCurrentPageStrips(['ontouch']);
};
}
//Delete Sprite
/////////////////////////////////'
//Delete Sprite
/////////////////////////////////'
Stage.prototype.removeSprite = function (sprite) {
removeSprite (sprite) {
ScratchJr.shaking = undefined;
ScratchJr.stopShaking = undefined;
ScratchAudio.sndFX('cut.wav');
@ -562,9 +579,9 @@ Stage.prototype.removeSprite = function (sprite) {
}
this.currentPage.updateThumb();
this.updatePageBlocks();
};
}
Stage.prototype.removeCharacter = function (spr) {
removeCharacter (spr) {
ScratchJr.runtime.stopThreadSprite(spr);
this.removeFromPage(spr);
Undo.record({
@ -574,16 +591,16 @@ Stage.prototype.removeCharacter = function (spr) {
});
ScratchJr.storyStart('Stage.prototype.removeCharacter');
Thumbs.updateSprites();
};
}
Stage.prototype.updatePageBlocks = function () {
updatePageBlocks () {
for (var i = 0; i < ScratchJr.stage.pages.length; i++) {
var page = ScratchJr.stage.pages[i];
ScriptsPane.updateScriptsPageBlocks(JSON.parse(page.sprites));
}
};
}
Stage.prototype.removeFromPage = function (spr) {
removeFromPage (spr) {
var id = spr.id;
var sc = gn(id + '_scripts');
var page = this.currentPage;
@ -606,9 +623,9 @@ Stage.prototype.removeFromPage = function (spr) {
var sprites = page.getSprites();
page.setCurrentSprite((sprites.length > 0) ? gn(sprites[0]).owner : undefined);
}
};
}
Stage.prototype.renumberPageBlocks = function (list) {
renumberPageBlocks (list) {
var pages = this.getPagesID();
for (var n = 0; n < this.pages.length; n++) {
var page = this.pages[n];
@ -630,9 +647,9 @@ Stage.prototype.renumberPageBlocks = function (list) {
}
}
}
};
}
Stage.prototype.clickOnElement = function (e, spr) {
clickOnElement (e, spr) {
if (spr.owner.type == 'text') {
if (!ScratchJr.inFullscreen) {
spr.owner.clickOnText(e);
@ -640,13 +657,13 @@ Stage.prototype.clickOnElement = function (e, spr) {
} else if (spr.owner.type == 'sprite') {
this.clickOnSprite(e, spr.owner);
}
};
}
//Stage clear
///////////////////////////////////////
//Stage clear
///////////////////////////////////////
Stage.prototype.clear = function () {
clear () {
for (var i = 0; i < this.pages.length; i++) {
this.removePage(this.pages[i]);
}
@ -654,9 +671,9 @@ Stage.prototype.clear = function () {
while (this.pagesdiv.childElementCount > 0) {
this.pagesdiv.removeChild(this.pagesdiv.childNodes[0]);
}
};
}
Stage.prototype.removePage = function (p) {
removePage (p) {
var list = JSON.parse(p.sprites);
for (var j = 0; j < list.length; j++) {
var name = list[j];
@ -668,13 +685,13 @@ Stage.prototype.removePage = function (p) {
sprite.parentNode.removeChild(sprite);
}
p.div.parentNode.removeChild(p.div);
};
}
//Debugging hit masks
///////////////////////////
//Debugging hit masks
///////////////////////////
Stage.prototype.sd = function () {
sd () {
var stg = gn('stage');
var mask = newDiv(gn('stageframe'), stg.offsetLeft + 1, stg.offsetTop + 1, 482, 362,
{
@ -684,17 +701,17 @@ Stage.prototype.sd = function () {
});
mask.setAttribute('id', 'pagemask');
mask.appendChild(ScratchJr.workingCanvas);
};
}
Stage.prototype.on = function () {
on () {
gn('pagemask').style.visibility = 'visible';
};
}
Stage.prototype.off = function () {
off () {
gn('pagemask').style.visibility = 'hidden';
};
}
Stage.prototype.sm = function (spr) {
sm (spr) {
var stg = gn('stage');
var w = spr.outline.width;
var h = spr.outline.height;
@ -706,12 +723,13 @@ Stage.prototype.sm = function (spr) {
});
mask.setAttribute('id', 'spritemask');
mask.appendChild(spr.outline);
};
}
Stage.prototype.son = function () {
son () {
gn('spritemask').style.visibility = 'visible';
};
}
Stage.prototype.soff = function () {
soff () {
gn('spritemask').style.visibility = 'hidden';
};
}
}

View file

@ -1,4 +1,9 @@
var Thread = function (s, block) {
import Prims from './Prims';
import Grid from '../ui/Grid';
import Vector from '../../geom/Vector';
export default class Thread {
constructor (s, block) {
this.firstBlock = block.findFirst();
this.thisblock = block;
this.oldblock = null;
@ -17,9 +22,9 @@ var Thread = function (s, block) {
this.isRunning = true;
this.time = 0; // for debugging purposes
return this;
};
}
Thread.prototype.clear = function () {
clear () {
this.stack = [];
this.firstTime = true;
this.count = -1;
@ -31,9 +36,9 @@ Thread.prototype.clear = function () {
this.distance = -1;
this.called = [];
this.thisblock = this.firstBlock;
};
}
Thread.prototype.duplicate = function () {
duplicate () {
var thread = new Thread(this.spr, this.firstBlock);
thread.count = -1;
thread.firstBlock = this.firstBlock;
@ -51,9 +56,9 @@ Thread.prototype.duplicate = function () {
thread.called = this.called;
thread.isRunning = this.isRunning;
return thread;
};
}
Thread.prototype.deselect = function (b) {
deselect (b) {
while (b != null) {
b.unhighlight();
if (b.inside) {
@ -62,21 +67,21 @@ Thread.prototype.deselect = function (b) {
}
b = b.next;
}
};
}
Thread.prototype.stop = function (b) {
stop (b) {
this.stopping(b);
this.isRunning = false;
};
}
Thread.prototype.stopping = function (b) {
stopping (b) {
this.endPrim(b);
this.deselect(this.firstBlock);
this.clear();
this.spr.closeBalloon();
};
}
Thread.prototype.endPrim = function (stopMine) {
endPrim (stopMine) {
if (!this.thisblock) {
return;
}
@ -156,4 +161,5 @@ Thread.prototype.endPrim = function (stopMine) {
s.setHeading(angle);
break;
}
};
}
}

View file

@ -2,7 +2,17 @@
// Scripts
///////////////////////////////////////////////
var Scripts = function (spr) {
import ScratchJr from '../ScratchJr';
import Block from '../blocks/Block';
import BlockSpecs from '../blocks/BlockSpecs';
import ScriptsPane from './ScriptsPane';
import Events from '../../utils/Events';
import ScratchAudio from '../../utils/ScratchAudio';
import {gn, newHTML, setCanvasSize, setProps,
localx, localy, scaleMultiplier, hit3DRect, isTablet} from '../../utils/lib';
export default class Scripts {
constructor (spr) {
this.flowCaret = null;
this.spr = spr;
this.dragList = [];
@ -14,25 +24,25 @@ var Scripts = function (spr) {
this.sc.owner = this;
this.sc.top = 0;
this.sc.left = 0;
};
}
Scripts.prototype.activate = function () {
activate () {
setProps(this.sc.style, {
visibility: 'visible'
});
};
}
Scripts.prototype.deactivate = function () {
deactivate () {
setProps(this.sc.style, {
visibility: 'hidden'
});
};
}
////////////////////////////////////////////////
// Events MouseDown
////////////////////////////////////////////////
////////////////////////////////////////////////
// Events MouseDown
////////////////////////////////////////////////
Scripts.prototype.scriptsMouseDown = function (e) {
scriptsMouseDown (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
@ -88,13 +98,13 @@ Scripts.prototype.scriptsMouseDown = function (e) {
return;
}
ScriptsPane.dragBackground(e);
};
}
////////////////////////////////////////////////
// Events MouseUP
////////////////////////////////////////////////
////////////////////////////////////////////////
// Events MouseUP
////////////////////////////////////////////////
Scripts.prototype.addBlockToScripts = function (b, dx, dy) {
addBlockToScripts (b, dx, dy) {
if ((this.flowCaret != null) && (this.flowCaret.div.parentNode == this.sc)) {
this.sc.removeChild(this.flowCaret.div);
}
@ -115,10 +125,10 @@ Scripts.prototype.addBlockToScripts = function (b, dx, dy) {
this.sendToBack(b.owner);
}
this.dragList = [];
};
}
Scripts.prototype.sendToBack = function (b) {
sendToBack (b) {
if (!b.inside) {
return;
}
@ -132,17 +142,17 @@ Scripts.prototype.sendToBack = function (b) {
you = you.next;
}
this.layout(b);
};
}
Scripts.prototype.snapToPlace = function (drag) {
snapToPlace (drag) {
if ((drag.length < 2) && drag[0].cShape) {
this.snapCshape(drag);
} else {
this.snapBlock(drag);
}
};
}
Scripts.prototype.snapBlock = function (drag) {
snapBlock (drag) {
var me = drag[0];
var last = me.findLast();
var res = this.findClosest(this.available(0, me, drag), me);
@ -155,9 +165,9 @@ Scripts.prototype.snapBlock = function (drag) {
return;
}
this.snapToDock(res, last, last.cShape ? 2 : 1, drag);
};
}
Scripts.prototype.snapCshape = function (drag) {
snapCshape (drag) {
var me = drag[0];
var last = me.findLast();
var res = this.findClosest(this.available(0, me, drag), me);
@ -177,9 +187,9 @@ Scripts.prototype.snapCshape = function (drag) {
if (this.isValid(me, res, 2)) {
this.snapToDock(res, last, 2, drag);
}
};
}
Scripts.prototype.isValid = function (me, res, myn) {
isValid (me, res, myn) {
if (res == null) {
return false;
}
@ -208,11 +218,11 @@ Scripts.prototype.isValid = function (me, res, myn) {
return false;
}
return true;
};
}
Scripts.prototype.insideCShape = function (you) {
insideCShape (you) {
while (you != null) {
var next = you.prev;
if (next == null) {
@ -225,9 +235,9 @@ Scripts.prototype.insideCShape = function (you) {
you = next;
}
return false;
};
}
Scripts.prototype.snapToDock = function (choice, me, place, drag) {
snapToDock (choice, me, place, drag) {
if (choice == null) {
return;
}
@ -251,9 +261,9 @@ Scripts.prototype.snapToDock = function (choice, me, place, drag) {
drag[i].moveBlock(drag[i].div.left + bestxy[0], drag[i].div.top + bestxy[1]);
}
me.connectBlock(place, choice[0], choice[1]);
};
}
Scripts.prototype.available = function (myn, me, drag) {
available (myn, me, drag) {
var thisxy = null;
var res = [];
var you = null;
@ -286,15 +296,15 @@ Scripts.prototype.available = function (myn, me, drag) {
}
}
return res;
};
}
Scripts.prototype.magnitude = function (p) {
magnitude (p) {
var x = p[0];
var y = p[1];
return Math.sqrt((x * x) + (y * y));
};
}
Scripts.prototype.findClosest = function (choices) {
findClosest (choices) {
var min = 9999;
var item = null;
for (var i = 0; i < choices.length; i++) {
@ -305,9 +315,9 @@ Scripts.prototype.findClosest = function (choices) {
}
}
return item;
};
}
Scripts.prototype.getDockDxDy = function (b1, n1, b2, n2) {
getDockDxDy (b1, n1, b2, n2) {
var d1 = (b1.resolveDocks())[n1];
var d2 = (b2.resolveDocks())[n2];
if (b1 == b2) {
@ -327,14 +337,14 @@ Scripts.prototype.getDockDxDy = function (b1, n1, b2, n2) {
var x2 = b2.div.left + d2[2] * b2.scale;
var y2 = b2.div.top + d2[3] * b2.scale;
return [x1 - x2, y1 - y2];
};
}
Scripts.prototype.layout = function (block) {
layout (block) {
var first = block.findFirst();
this.layoutStrip(first);
};
}
Scripts.prototype.layoutStrip = function (b) {
layoutStrip (b) {
while (b != null) {
if (b.cShape) {
this.layoutCshape(b);
@ -342,9 +352,9 @@ Scripts.prototype.layoutStrip = function (b) {
this.layoutNextBlock(b);
b = b.next;
}
};
}
Scripts.prototype.layoutNextBlock = function (b) {
layoutNextBlock (b) {
if (b.next != null) {
var you = b.next;
var bestxy = this.getDockDxDy(b, b.cShape ? 2 : 1, you, 0);
@ -353,9 +363,9 @@ Scripts.prototype.layoutNextBlock = function (b) {
}
you.moveBlock(you.div.left + bestxy[0], you.div.top + bestxy[1]);
}
};
}
Scripts.prototype.layoutCshape = function (b) {
layoutCshape (b) {
var inside = 0;
var maxh = 0;
var oldh = b.hrubberband;
@ -371,14 +381,14 @@ Scripts.prototype.layoutCshape = function (b) {
b.hrubberband = inside;
b.redrawRepeat();
b.moveBlock(b.div.left, b.div.top + (oldh - b.vrubberband) * b.scale);
};
}
Scripts.prototype.adjustPos = function (me, myn, you, yourn) {
adjustPos (me, myn, you, yourn) {
var bestxy = this.getDockDxDy(you, yourn, me, myn);
me.moveBlock(me.div.left + bestxy[0], me.div.top + bestxy[1]);
};
}
Scripts.prototype.adjustCheight = function (b) {
adjustCheight (b) {
var old = b;
var h = b.blockshape.height;
b = b.next;
@ -390,9 +400,9 @@ Scripts.prototype.adjustCheight = function (b) {
}
h /= (old.scale * window.devicePixelRatio);
return (h > 66) ? h - 66 : 0;
};
}
Scripts.prototype.adjustCinside = function (b) {
adjustCinside (b) {
var first = b;
var last = b;
while (b != null) {
@ -402,9 +412,9 @@ Scripts.prototype.adjustCinside = function (b) {
var w = last.blockshape.width / last.scale / window.devicePixelRatio +
(last.div.left - first.div.left) / last.scale;
return w - (last.cShape ? 76 : 76);
};
}
Scripts.prototype.getBlocks = function () {
getBlocks () {
var res = [];
var sc = this.sc;
for (var i = 0; i < sc.childElementCount; i++) {
@ -421,17 +431,17 @@ Scripts.prototype.getBlocks = function () {
res.push(b);
}
return res;
};
}
Scripts.prototype.findGroup = function (b) {
findGroup (b) {
if (b.type != 'block') {
return [];
}
var res = [];
return this.findingGroup(res, b);
};
}
Scripts.prototype.findingGroup = function (res, b) {
findingGroup (res, b) {
while (b != null) {
res.push(b);
if (b.cShape) {
@ -440,9 +450,9 @@ Scripts.prototype.findingGroup = function (res, b) {
b = b.next;
}
return res;
};
}
Scripts.prototype.gettopblocks = function () {
gettopblocks () {
var list = this.getBlocks();
var res = [];
for (var n = 0; n < list.length; n++) {
@ -454,11 +464,11 @@ Scripts.prototype.gettopblocks = function () {
}
}
return res;
};
}
// A version of gettopblocks that also returns strips which
// may be currently starting with a caret and blocks in the dragDiv
Scripts.prototype.getEncodableBlocks = function () {
// A version of gettopblocks that also returns strips which
// may be currently starting with a caret and blocks in the dragDiv
getEncodableBlocks () {
var list = [];
var sc = this.sc;
for (var i =0; i < sc.childElementCount; i++){
@ -474,16 +484,16 @@ Scripts.prototype.getEncodableBlocks = function () {
if (list[n].prev == null) res.push(list[n]);
}
return res;
};
}
Scripts.prototype.redisplay = function () {
redisplay () {
var list = this.gettopblocks();
for (var n = 0; n < list.length; n++) {
this.layout(list[n]);
}
};
}
Scripts.prototype.getBlocksType = function (list) {
getBlocksType (list) {
var res = [];
var blocks = this.getBlocks();
for (var i = 0; i < list.length; i++) {
@ -495,9 +505,9 @@ Scripts.prototype.getBlocksType = function (list) {
}
}
return res;
};
}
Scripts.prototype.prepareCaret = function (b) { // Block data structure
prepareCaret (b) { // Block data structure
var last = b.findLast();
var bt = this.getCaretType(last);
if (this.flowCaret != null) {
@ -509,9 +519,9 @@ Scripts.prototype.prepareCaret = function (b) { // Block data structure
} // don't have a caret
this.flowCaret = this.newCaret(bt);
this.flowCaret.isCaret = true;
};
}
Scripts.prototype.newCaret = function (bt) { // Block data structure
newCaret (bt) { // Block data structure
var parent = this.sc;
var bbx = new Block(BlockSpecs.defs[bt], false, scaleMultiplier);
setProps(bbx.div.style, {
@ -524,13 +534,13 @@ Scripts.prototype.newCaret = function (bt) { // Block data structure
parent.appendChild(bbx.div);
bbx.moveBlock(0, 0);
return bbx;
};
}
////////////////////////////////////////////
// Caret
///////////////////////////////////////////
////////////////////////////////////////////
// Caret
///////////////////////////////////////////
Scripts.prototype.getCaretType = function (b) {
getCaretType (b) {
if (this.dragList[0].aStart) {
return 'caretstart';
}
@ -541,13 +551,13 @@ Scripts.prototype.getCaretType = function (b) {
return 'caretrepeat';
}
return 'caretcmd';
};
}
////////////////////////////////////////////////
// Events MouseMove
////////////////////////////////////////////////
////////////////////////////////////////////////
// Events MouseMove
////////////////////////////////////////////////
Scripts.prototype.removeCaret = function () {
removeCaret () {
if (this.flowCaret == null) {
return;
}
@ -586,9 +596,9 @@ Scripts.prototype.removeCaret = function () {
this.flowCaret.redrawRepeat();
}
this.flowCaret.div.style.visibility = 'hidden';
};
}
Scripts.prototype.insertCaret = function (x, y) {
insertCaret (x, y) {
if (this.flowCaret == null) {
return;
}
@ -600,9 +610,9 @@ Scripts.prototype.insertCaret = function (x, y) {
if (this.flowCaret.div.style.visibility == 'visible') {
this.layout(this.flowCaret);
}
};
}
Scripts.prototype.deleteBlocks = function () {
deleteBlocks () {
ScratchJr.storyStart('Scripts.prototype.deleteBlocks');
ScriptsPane.cleanCarets();
ScratchAudio.sndFX('cut.wav');
@ -616,9 +626,9 @@ Scripts.prototype.deleteBlocks = function () {
}
b.div.parentNode.removeChild(b.div);
}
};
}
Scripts.prototype.recreateStrip = function (list) {
recreateStrip (list) {
var res = [];
var b = null;
var loops = ['repeat'];
@ -670,14 +680,14 @@ Scripts.prototype.recreateStrip = function (list) {
this.layout(res[0]);
}
return res;
};
}
/////////////////////////////////
// Load
////////////////////////////////
/////////////////////////////////
// Load
////////////////////////////////
Scripts.prototype.recreateBlock = function (data) {
recreateBlock (data) {
var op = data[0];
var val = data[1] == 'null' ? null : data[1];
var dx = data[2];
@ -696,4 +706,5 @@ Scripts.prototype.recreateBlock = function (data) {
this.sc.appendChild(bbx.div);
bbx.update(this.spr);
return bbx;
};
}
}

View file

@ -2,7 +2,11 @@
// Scrolling Pane
////////////////////////////////////////////////
var Scroll = function (div, id, w, h, cfcn, ofcn) {
import Events from '../../utils/Events';
import {newDiv, newHTML, CSSTransition3D, isTablet, setCanvasSize} from '../../utils/lib';
export default class Scroll {
constructor (div, id, w, h, cfcn, ofcn) {
this.hasHorizontal = true;
this.hasVertical = true;
this.arrowDistance = 6;
@ -17,19 +21,19 @@ var Scroll = function (div, id, w, h, cfcn, ofcn) {
this.getContent = cfcn;
this.getObjects = ofcn;
div.scroll = this; // for now;
};
}
Scroll.prototype.update = function () {
update () {
this.adjustCanvas();
this.refresh();
this.bounceBack();
};
}
/////////////////////////////////////////////////////////////
// Arrows
////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
// Arrows
////////////////////////////////////////////////////////////
Scroll.prototype.addArrows = function (sc, w, h) {
addArrows (sc, w, h) {
this.aleft = newHTML('div', 'leftarrow', sc);
this.aleft.style.height = h + 'px';
var larrow = newHTML('span', undefined, this.aleft);
@ -86,20 +90,20 @@ Scroll.prototype.addArrows = function (sc, w, h) {
};
}
};
}
/////////////////////////////////////////////////////////////
// Scrolling
////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
// Scrolling
////////////////////////////////////////////////////////////
Scroll.prototype.repositionArrows = function (h) {
repositionArrows (h) {
this.aleft.style.height = h + 'px';
this.aleft.childNodes[0].style.top = Math.floor((h - this.aleft.childNodes[0].offsetHeight) / 2) + 'px';
this.aright.style.height = h + 'px';
this.aright.childNodes[0].style.top = Math.floor((h - this.aright.childNodes[0].offsetHeight) / 2) + 'px';
};
}
Scroll.prototype.getAdjustment = function (rect) { // rect of the dragg block canvas
getAdjustment (rect) { // rect of the dragg block canvas
var d = this.contents.parentNode; // scripts
var w = d.offsetWidth;
var h = d.offsetHeight;
@ -128,9 +132,9 @@ Scroll.prototype.getAdjustment = function (rect) { // rect of the dragg block ca
return 'left';
}
return 'none';
};
}
Scroll.prototype.bounceBack = function () {
bounceBack () {
var owner = this;
var p = this.contents; // scriptscontainer
var bc = this.getContent(); // blockcanvas
@ -198,13 +202,13 @@ Scroll.prototype.bounceBack = function () {
}
break;
}
};
}
/////////////////////////////////////////////////////////////
// Refreshing
////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
// Refreshing
////////////////////////////////////////////////////////////
Scroll.prototype.refresh = function () {
refresh () {
var p = this.contents; // scriptscontainer
var bc = this.getContent(); // blockcanvas
var w = p.offsetWidth;
@ -243,9 +247,9 @@ Scroll.prototype.refresh = function () {
this.aright.style.visibility = needright;
this.aup.style.visibility = needup;
this.adown.style.visibility = needdown;
};
}
Scroll.prototype.adjustCanvas = function () {
adjustCanvas () {
var bc = this.getContent(); // blockcanvas
var p = this.contents; // scriptscontainer
var w = p.offsetWidth;
@ -310,21 +314,21 @@ Scroll.prototype.adjustCanvas = function () {
this.moveBlocks(-minx, -miny);
Events.move3D(bc, minx, miny);
}
};
}
Scroll.prototype.moveBlocks = function (dx, dy) {
moveBlocks (dx, dy) {
var allblocks = this.getObjects();
for (var i = 0; i < allblocks.length; i++) {
var b = allblocks[i];
b.moveBlock(b.div.left + dx, b.div.top + dy);
}
};
}
/////////////////////////////////////////////////////////////
// Scrolling
////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
// Scrolling
////////////////////////////////////////////////////////////
Scroll.prototype.scrolldown = function (e) {
scrolldown (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
@ -350,9 +354,9 @@ Scroll.prototype.scrolldown = function (e) {
}
};
CSSTransition3D(sc, transition);
};
}
Scroll.prototype.scrollup = function (e) {
scrollup (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
@ -378,9 +382,9 @@ Scroll.prototype.scrollup = function (e) {
}
};
CSSTransition3D(sc, transition);
};
}
Scroll.prototype.scrollright = function (e) {
scrollright (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
@ -406,9 +410,9 @@ Scroll.prototype.scrollright = function (e) {
}
};
CSSTransition3D(sc, transition);
};
}
Scroll.prototype.scrollleft = function (e) {
scrollleft (e) {
if (isTablet && e.touches && (e.touches.length > 1)) {
return;
}
@ -434,9 +438,9 @@ Scroll.prototype.scrollleft = function (e) {
}
};
CSSTransition3D(sc, transition);
};
}
Scroll.prototype.fitToScreen = function () {
fitToScreen () {
var p = this.contents;
var sc = this.getContent();
var valx = sc.left;
@ -479,4 +483,5 @@ Scroll.prototype.fitToScreen = function () {
break;
}
Events.move3D(sc, valx, valy);
};
}
}