summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbinary.js1099
-rwxr-xr-xbinary.sh92
-rw-r--r--config.xml15
-rwxr-xr-xdesktop.sh34
-rwxr-xr-xmobile.sh65
-rw-r--r--morphic.js5
-rw-r--r--objects.js52
-rw-r--r--package.json8
-rwxr-xr-xsnap.html10
-rw-r--r--threads.js126
10 files changed, 1502 insertions, 4 deletions
diff --git a/binary.js b/binary.js
new file mode 100755
index 0000000..d1a9b21
--- /dev/null
+++ b/binary.js
@@ -0,0 +1,1099 @@
+/*
+
+ gui.js
+
+ a programming environment
+ based on morphic.js, blocks.js, threads.js and objects.js
+ inspired by Scratch
+
+ written by Jens Mönig
+ jens@moenig.org
+
+ Copyright (C) 2014 by Jens Mönig
+
+ This file is part of Snap!.
+
+ Snap! is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as
+ published by the Free Software Foundation, either version 3 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+ prerequisites:
+ --------------
+ needs blocks.js, threads.js, objects.js and morphic.js
+
+
+ toc
+ ---
+ the following list shows the order in which all constructors are
+ defined. Use this list to locate code in this document:
+
+ IDE_Morph
+
+
+ credits
+ -------
+ Nathan Dinsmore contributed saving and loading of projects,
+ ypr-Snap! project conversion and countless bugfixes
+ Ian Reynolds contributed handling and visualization of sounds
+
+*/
+
+/*global modules, Morph, SpriteMorph, Color, newCanvas,
+VariableFrame, Point, MenuMorph,
+morphicVersion, DialogBoxMorph, ToggleButtonMorph, contains,
+StageMorph, PushButtonMorph, Process, SnapSerializer, MorphicPreferences,
+SymbolMorph,
+BlockImportDialogMorph, SnapTranslator, localize, List */
+
+// Global stuff ////////////////////////////////////////////////////////
+
+modules.gui = '2014-July-30';
+
+// Declarations
+
+var IDE_Morph;
+
+// IDE_Morph ///////////////////////////////////////////////////////////
+
+// I am SNAP's top-level frame, the Editor window
+
+// IDE_Morph inherits from Morph:
+
+IDE_Morph.prototype = new Morph();
+IDE_Morph.prototype.constructor = IDE_Morph;
+IDE_Morph.uber = Morph.prototype;
+
+// IDE_Morph preferences settings and skins
+
+IDE_Morph.prototype.setDefaultDesign = function () {
+ MorphicPreferences.isFlat = false;
+ SpriteMorph.prototype.paletteColor = new Color(55, 55, 55);
+ SpriteMorph.prototype.paletteTextColor = new Color(230, 230, 230);
+ StageMorph.prototype.paletteTextColor
+ = SpriteMorph.prototype.paletteTextColor;
+ StageMorph.prototype.paletteColor = SpriteMorph.prototype.paletteColor;
+ SpriteMorph.prototype.sliderColor
+ = SpriteMorph.prototype.paletteColor.lighter(30);
+
+ IDE_Morph.prototype.buttonContrast = 30;
+ IDE_Morph.prototype.backgroundColor = new Color(40, 40, 40);
+ IDE_Morph.prototype.frameColor = SpriteMorph.prototype.paletteColor;
+
+ IDE_Morph.prototype.groupColor
+ = SpriteMorph.prototype.paletteColor.lighter(8);
+ IDE_Morph.prototype.sliderColor = SpriteMorph.prototype.sliderColor;
+ IDE_Morph.prototype.buttonLabelColor = new Color(255, 255, 255);
+ IDE_Morph.prototype.tabColors = [
+ IDE_Morph.prototype.groupColor.darker(40),
+ IDE_Morph.prototype.groupColor.darker(60),
+ IDE_Morph.prototype.groupColor
+ ];
+ IDE_Morph.prototype.rotationStyleColors = IDE_Morph.prototype.tabColors;
+ IDE_Morph.prototype.appModeColor = new Color();
+ IDE_Morph.prototype.scriptsPaneTexture = 'scriptsPaneTexture.gif';
+ IDE_Morph.prototype.padding = 5;
+};
+
+IDE_Morph.prototype.setFlatDesign = function () {
+ MorphicPreferences.isFlat = true;
+ SpriteMorph.prototype.paletteColor = new Color(255, 255, 255);
+ SpriteMorph.prototype.paletteTextColor = new Color(70, 70, 70);
+ StageMorph.prototype.paletteTextColor
+ = SpriteMorph.prototype.paletteTextColor;
+ StageMorph.prototype.paletteColor = SpriteMorph.prototype.paletteColor;
+ SpriteMorph.prototype.sliderColor = SpriteMorph.prototype.paletteColor;
+
+ IDE_Morph.prototype.buttonContrast = 30;
+ IDE_Morph.prototype.backgroundColor = new Color(200, 200, 200);
+ IDE_Morph.prototype.frameColor = new Color(255, 255, 255);
+
+ IDE_Morph.prototype.groupColor = new Color(230, 230, 230);
+ IDE_Morph.prototype.sliderColor = SpriteMorph.prototype.sliderColor;
+ IDE_Morph.prototype.buttonLabelColor = new Color(70, 70, 70);
+ IDE_Morph.prototype.tabColors = [
+ IDE_Morph.prototype.groupColor.lighter(60),
+ IDE_Morph.prototype.groupColor.darker(10),
+ IDE_Morph.prototype.groupColor
+ ];
+ IDE_Morph.prototype.rotationStyleColors = [
+ IDE_Morph.prototype.groupColor,
+ IDE_Morph.prototype.groupColor.darker(10),
+ IDE_Morph.prototype.groupColor.darker(30)
+ ];
+ IDE_Morph.prototype.appModeColor = IDE_Morph.prototype.frameColor;
+ IDE_Morph.prototype.scriptsPaneTexture = null;
+ IDE_Morph.prototype.padding = 1;
+};
+
+IDE_Morph.prototype.setDefaultDesign();
+
+// IDE_Morph instance creation:
+
+function IDE_Morph(isAutoFill) {
+ this.init(isAutoFill);
+}
+
+IDE_Morph.prototype.init = function (isAutoFill) {
+ // global font setting
+ MorphicPreferences.globalFontFamily = 'Helvetica, Arial';
+
+ // restore saved user preferences
+ this.userLanguage = null;
+
+ // additional properties:
+ this.source = 'local';
+ this.serializer = new SnapSerializer();
+
+ this.globalVariables = new VariableFrame();
+ this.currentSprite = new SpriteMorph(this.globalVariables);
+ this.sprites = new List([this.currentSprite]);
+ this.currentCategory = 'motion';
+ this.currentTab = 'scripts';
+ this.projectName = '';
+ this.projectNotes = '';
+
+ this.logo = null;
+ this.controlBar = null;
+ this.stage = null;
+
+ this.isAutoFill = isAutoFill || true;
+
+ this.filePicker = null;
+ this.hasChangedMedia = false;
+
+ this.isAnimating = true;
+ this.stageRatio = 1; // for IDE animations, e.g. when zooming
+
+ this.loadNewProject = false; // flag when starting up translated
+ this.shield = null;
+
+ // initialize inherited properties:
+ IDE_Morph.uber.init.call(this);
+
+ // override inherited properites:
+ this.color = this.appModeColor;
+};
+
+IDE_Morph.prototype.openIn = function (world) {
+ var hash;
+
+ this.buildPanes();
+ world.add(this);
+
+ this.reactToWorldResize(world.bounds);
+
+ function getURL(url) {
+ try {
+ var request = new XMLHttpRequest();
+ request.open('GET', url, false);
+ request.send();
+ if (request.status === 200) {
+ return request.responseText;
+ }
+ throw new Error('unable to retrieve ' + url);
+ } catch (err) {
+ return;
+ }
+ }
+
+ function interpretUrlAnchors() {
+ if (location.hash.substr(0, 6) === '#open:') {
+ hash = location.hash.substr(6);
+ if (hash.charAt(0) === '%'
+ || hash.search(/\%(?:[0-9a-f]{2})/i) > -1) {
+ hash = decodeURIComponent(hash);
+ }
+ if (contains(
+ ['project', 'blocks', 'sprites', 'snapdata'].map(
+ function (each) {
+ return hash.substr(0, 8).indexOf(each);
+ }
+ ),
+ 1
+ )) {
+ this.droppedText(hash);
+ } else {
+ this.droppedText(getURL(hash));
+ }
+ }
+ }
+
+ if (this.userLanguage) {
+ this.setLanguage(this.userLanguage, interpretUrlAnchors);
+ } else {
+ interpretUrlAnchors.call(this);
+ }
+};
+
+// IDE_Morph construction
+
+IDE_Morph.prototype.buildPanes = function () {
+ this.createLogo();
+ this.createControlBar();
+ this.createStage();
+};
+
+IDE_Morph.prototype.createLogo = function () {
+ var myself = this;
+
+ if (this.logo) {
+ this.logo.destroy();
+ }
+
+ this.logo = new Morph();
+ this.logo.texture = 'snap_logo_sm.png';
+ this.logo.drawNew = function () {
+ this.image = newCanvas(this.extent());
+ var context = this.image.getContext('2d');
+ context.fillStyle = this.color;
+ context.fillRect(0, 0, this.width(), this.height());
+ if (this.texture) {
+ this.drawTexture(this.texture);
+ }
+ };
+
+ this.logo.drawCachedTexture = function () {
+ var context = this.image.getContext('2d');
+ context.drawImage(
+ this.cachedTexture,
+ 5,
+ Math.round((this.height() - this.cachedTexture.height) / 2)
+ );
+ this.changed();
+ };
+
+ this.logo.mouseClickLeft = function () {
+ myself.snapMenu();
+ };
+
+ this.logo.color = new Color();
+ this.logo.setExtent(new Point(200, 28)); // dimensions are fixed
+ this.add(this.logo);
+};
+
+IDE_Morph.prototype.createControlBar = function () {
+ // assumes the logo has already been created
+ var padding = 5,
+ button,
+ stopButton,
+ pauseButton,
+ startButton,
+ x,
+ colors = [
+ this.groupColor,
+ this.frameColor.darker(50),
+ this.frameColor.darker(50)
+ ],
+ myself = this;
+
+ if (this.controlBar) {
+ this.controlBar.destroy();
+ }
+
+ this.controlBar = new Morph();
+ this.controlBar.color = this.appModeColor;
+ this.controlBar.setHeight(this.logo.height()); // height is fixed
+ this.controlBar.mouseClickLeft = function () {
+ this.world().fillPage();
+ };
+ this.add(this.controlBar);
+
+ // stopButton
+ button = new PushButtonMorph(
+ this,
+ 'stopAllScripts',
+ new SymbolMorph('octagon', 14)
+ );
+ button.corner = 12;
+ button.color = colors[0];
+ button.highlightColor = colors[1];
+ button.pressColor = colors[2];
+ button.labelMinExtent = new Point(36, 18);
+ button.padding = 0;
+ button.labelShadowOffset = new Point(-1, -1);
+ button.labelShadowColor = colors[1];
+ button.labelColor = new Color(200, 0, 0);
+ button.contrast = this.buttonContrast;
+ button.drawNew();
+ // button.hint = 'stop\nevery-\nthing';
+ button.fixLayout();
+ stopButton = button;
+ this.controlBar.add(stopButton);
+
+ //pauseButton
+ button = new ToggleButtonMorph(
+ null, //colors,
+ myself, // the IDE is the target
+ 'togglePauseResume',
+ [
+ new SymbolMorph('pause', 12),
+ new SymbolMorph('pointRight', 14)
+ ],
+ function () { // query
+ return myself.isPaused();
+ }
+ );
+
+ button.corner = 12;
+ button.color = colors[0];
+ button.highlightColor = colors[1];
+ button.pressColor = colors[2];
+ button.labelMinExtent = new Point(36, 18);
+ button.padding = 0;
+ button.labelShadowOffset = new Point(-1, -1);
+ button.labelShadowColor = colors[1];
+ button.labelColor = new Color(255, 220, 0);
+ button.contrast = this.buttonContrast;
+ button.drawNew();
+ // button.hint = 'pause/resume\nall scripts';
+ button.fixLayout();
+ button.refresh();
+ pauseButton = button;
+ this.controlBar.add(pauseButton);
+ this.controlBar.pauseButton = pauseButton; // for refreshing
+
+ // startButton
+ button = new PushButtonMorph(
+ this,
+ 'pressStart',
+ new SymbolMorph('flag', 14)
+ );
+ button.corner = 12;
+ button.color = colors[0];
+ button.highlightColor = colors[1];
+ button.pressColor = colors[2];
+ button.labelMinExtent = new Point(36, 18);
+ button.padding = 0;
+ button.labelShadowOffset = new Point(-1, -1);
+ button.labelShadowColor = colors[1];
+ button.labelColor = new Color(0, 200, 0);
+ button.contrast = this.buttonContrast;
+ button.drawNew();
+ // button.hint = 'start green\nflag scripts';
+ button.fixLayout();
+ startButton = button;
+ this.controlBar.add(startButton);
+ this.controlBar.startButton = startButton;
+
+ this.controlBar.fixLayout = function () {
+ x = this.right() - padding;
+ [stopButton, pauseButton, startButton].forEach(
+ function (button) {
+ button.setCenter(myself.controlBar.center());
+ button.setRight(x);
+ x -= button.width();
+ x -= padding;
+ }
+ );
+
+ x = myself.right() - StageMorph.prototype.dimensions.x;
+
+ this.updateLabel();
+ };
+
+ this.controlBar.updateLabel = function () {
+ if (this.label) {
+ this.label.destroy();
+ }
+ };
+};
+
+IDE_Morph.prototype.createStage = function () {
+ // assumes that the logo pane has already been created
+ if (this.stage) {
+ this.stage.destroy();
+ }
+ StageMorph.prototype.frameRate = 0;
+ this.stage = new StageMorph(this.globalVariables);
+ this.stage.setExtent(this.stage.dimensions); // dimensions are fixed
+ if (this.currentSprite instanceof SpriteMorph) {
+ this.currentSprite.setPosition(
+ this.stage.center().subtract(
+ this.currentSprite.extent().divideBy(2)
+ )
+ );
+ this.stage.add(this.currentSprite);
+ }
+ this.add(this.stage);
+};
+
+IDE_Morph.prototype.createCorral = function () {
+};
+
+// IDE_Morph resizing
+
+IDE_Morph.prototype.setExtent = function (point) {
+ var minExt,
+ ext;
+
+ // determine the minimum dimensions making sense for the current mode
+ minExt = StageMorph.prototype.dimensions.add(
+ this.controlBar.height() + 10
+ );
+ ext = point.max(minExt);
+ IDE_Morph.uber.setExtent.call(this, ext);
+ this.fixLayout();
+};
+
+// IDE_Morph events
+
+IDE_Morph.prototype.reactToWorldResize = function (rect) {
+ if (this.isAutoFill) {
+ this.setPosition(rect.origin);
+ this.setExtent(rect.extent());
+ }
+ if (this.filePicker) {
+ document.body.removeChild(this.filePicker);
+ this.filePicker = null;
+ }
+};
+
+// IDE_Morph layout
+
+IDE_Morph.prototype.fixLayout = function () {
+ var padding = this.padding;
+
+ Morph.prototype.trackChanges = false;
+
+ // controlBar
+ this.controlBar.setPosition(this.logo.topRight());
+ this.controlBar.setWidth(this.right() - this.controlBar.left());
+ this.controlBar.fixLayout();
+
+ // stage
+ this.stage.setScale(Math.floor(Math.min(
+ (this.width() - padding * 2) / this.stage.dimensions.x,
+ (this.height() - this.controlBar.height() * 2 - padding * 2)
+ / this.stage.dimensions.y
+ ) * 10) / 10);
+ this.stage.setCenter(this.center());
+
+ Morph.prototype.trackChanges = true;
+ this.changed();
+};
+
+IDE_Morph.prototype.droppedText = function (aString, name) {
+ var lbl = name ? name.split('.')[0] : '';
+ if (aString.indexOf('<project') === 0) {
+ return this.openProjectString(aString);
+ }
+ if (aString.indexOf('<snapdata') === 0) {
+ return this.openCloudDataString(aString);
+ }
+ if (aString.indexOf('<blocks') === 0) {
+ return this.openBlocksString(aString, lbl, true);
+ }
+ if (aString.indexOf('<sprites') === 0) {
+ return this.openSpritesString(aString);
+ }
+ if (aString.indexOf('<media') === 0) {
+ return this.openMediaString(aString);
+ }
+};
+
+// IDE_Morph events
+
+IDE_Morph.prototype.pressStart = function () {
+ if (this.world().currentKey === 16) { // shiftClicked
+ this.toggleFastTracking();
+ } else {
+ this.runScripts();
+ }
+};
+
+IDE_Morph.prototype.toggleFastTracking = function () {
+ if (this.stage.isFastTracked) {
+ this.stopFastTracking();
+ } else {
+ this.startFastTracking();
+ }
+};
+
+IDE_Morph.prototype.toggleVariableFrameRate = function () {
+ if (StageMorph.prototype.frameRate) {
+ StageMorph.prototype.frameRate = 0;
+ this.stage.fps = 0;
+ } else {
+ StageMorph.prototype.frameRate = 30;
+ this.stage.fps = 30;
+ }
+};
+
+IDE_Morph.prototype.startFastTracking = function () {
+ this.stage.isFastTracked = true;
+ this.stage.fps = 0;
+ this.controlBar.startButton.labelString = new SymbolMorph('flash', 14);
+ this.controlBar.startButton.drawNew();
+ this.controlBar.startButton.fixLayout();
+};
+
+IDE_Morph.prototype.stopFastTracking = function () {
+ this.stage.isFastTracked = false;
+ this.stage.fps = this.stage.frameRate;
+ this.controlBar.startButton.labelString = new SymbolMorph('flag', 14);
+ this.controlBar.startButton.drawNew();
+ this.controlBar.startButton.fixLayout();
+};
+
+IDE_Morph.prototype.runScripts = function () {
+ this.stage.fireGreenFlagEvent();
+};
+
+IDE_Morph.prototype.togglePauseResume = function () {
+ if (this.stage.threads.isPaused()) {
+ this.stage.threads.resumeAll(this.stage);
+ } else {
+ this.stage.threads.pauseAll(this.stage);
+ }
+ this.controlBar.pauseButton.refresh();
+};
+
+IDE_Morph.prototype.isPaused = function () {
+ if (!this.stage) {return false; }
+ return this.stage.threads.isPaused();
+};
+
+IDE_Morph.prototype.stopAllScripts = function () {
+ this.stage.fireStopAllEvent();
+};
+
+IDE_Morph.prototype.selectSprite = function (sprite) {
+ this.currentSprite = sprite;
+ this.currentSprite.scripts.fixMultiArgs();
+};
+
+// IDE_Morph menus
+
+IDE_Morph.prototype.snapMenu = function () {
+ var menu,
+ world = this.world();
+
+ menu = new MenuMorph(this);
+ menu.addItem('About...', 'aboutSnap');
+ menu.addLine();
+ menu.addItem(
+ 'Reference manual',
+ function () {
+ window.open('help/SnapManual.pdf', 'SnapReferenceManual');
+ }
+ );
+ menu.addItem(
+ 'Snap! website',
+ function () {
+ window.open('http://snap.berkeley.edu/', 'SnapWebsite');
+ }
+ );
+ menu.addItem(
+ 'Download source',
+ function () {
+ window.open(
+ 'http://snap.berkeley.edu/snapsource/snap.zip',
+ 'SnapSource'
+ );
+ }
+ );
+ if (world.isDevMode) {
+ menu.addLine();
+ menu.addItem(
+ 'Switch back to user mode',
+ 'switchToUserMode',
+ 'disable deep-Morphic\ncontext menus'
+ + '\nand show user-friendly ones',
+ new Color(0, 100, 0)
+ );
+ } else if (world.currentKey === 16) { // shift-click
+ menu.addLine();
+ menu.addItem(
+ 'Switch to dev mode',
+ 'switchToDevMode',
+ 'enable Morphic\ncontext menus\nand inspectors,'
+ + '\nnot user-friendly!',
+ new Color(100, 0, 0)
+ );
+ }
+ menu.popup(world, this.logo.bottomLeft());
+};
+
+// IDE_Morph menu actions
+
+IDE_Morph.prototype.aboutSnap = function () {
+ var dlg, aboutTxt, noticeTxt, creditsTxt, versions = '', translations,
+ module, btn1, btn2, btn3, btn4, licenseBtn, translatorsBtn,
+ world = this.world();
+
+ aboutTxt = 'Snap! 4.0\nBuild Your Own Blocks\n\n--- beta ---\n\n'
+ + 'Copyright \u24B8 2014 Jens M\u00F6nig and '
+ + 'Brian Harvey\n'
+ + 'jens@moenig.org, bh@cs.berkeley.edu\n\n'
+
+ + 'Snap! is developed by the University of California, Berkeley\n'
+ + ' with support from the National Science Foundation '
+ + 'and MioSoft. \n'
+
+ + 'The design of Snap! is influenced and inspired by Scratch,\n'
+ + 'from the Lifelong Kindergarten group at the MIT Media Lab\n\n'
+
+ + 'for more information see http://snap.berkeley.edu\n'
+ + 'and http://scratch.mit.edu';
+
+ noticeTxt = localize('License')
+ + '\n\n'
+ + 'Snap! is free software: you can redistribute it and/or modify\n'
+ + 'it under the terms of the GNU Affero General Public License as\n'
+ + 'published by the Free Software Foundation, either version 3 of\n'
+ + 'the License, or (at your option) any later version.\n\n'
+
+ + 'This program is distributed in the hope that it will be useful,\n'
+ + 'but WITHOUT ANY WARRANTY; without even the implied warranty of\n'
+ + 'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n'
+ + 'GNU Affero General Public License for more details.\n\n'
+
+ + 'You should have received a copy of the\n'
+ + 'GNU Affero General Public License along with this program.\n'
+ + 'If not, see http://www.gnu.org/licenses/';
+
+ creditsTxt = localize('Contributors')
+ + '\n\nNathan Dinsmore: Saving/Loading, Snap-Logo Design, '
+ + 'countless bugfixes'
+ + '\nKartik Chandra: Paint Editor'
+ + '\nMichael Ball: Time/Date UI, many bugfixes'
+ + '\n"Ava" Yuan Yuan: Graphic Effects'
+ + '\nKyle Hotchkiss: Block search design'
+ + '\nIan Reynolds: UI Design, Event Bindings, '
+ + 'Sound primitives'
+ + '\nIvan Motyashov: Initial Squeak Porting'
+ + '\nDavide Della Casa: Morphic Optimizations'
+ + '\nAchal Dave: Web Audio'
+ + '\nJoe Otto: Morphic Testing and Debugging';
+
+ for (module in modules) {
+ if (Object.prototype.hasOwnProperty.call(modules, module)) {
+ versions += ('\n' + module + ' (' +
+ modules[module] + ')');
+ }
+ }
+ if (versions !== '') {
+ versions = localize('current module versions:') + ' \n\n' +
+ 'morphic (' + morphicVersion + ')' +
+ versions;
+ }
+ translations = localize('Translations') + '\n' + SnapTranslator.credits();
+
+ dlg = new DialogBoxMorph();
+ dlg.inform('About Snap', aboutTxt, world);
+ btn1 = dlg.buttons.children[0];
+ translatorsBtn = dlg.addButton(
+ function () {
+ dlg.body.text = translations;
+ dlg.body.drawNew();
+ btn1.show();
+ btn2.show();
+ btn3.hide();
+ btn4.hide();
+ licenseBtn.hide();
+ translatorsBtn.hide();
+ dlg.fixLayout();
+ dlg.drawNew();
+ dlg.setCenter(world.center());
+ },
+ 'Translators...'
+ );
+ btn2 = dlg.addButton(
+ function () {
+ dlg.body.text = aboutTxt;
+ dlg.body.drawNew();
+ btn1.show();
+ btn2.hide();
+ btn3.show();
+ btn4.show();
+ licenseBtn.show();
+ translatorsBtn.hide();
+ dlg.fixLayout();
+ dlg.drawNew();
+ dlg.setCenter(world.center());
+ },
+ 'Back...'
+ );
+ btn2.hide();
+ licenseBtn = dlg.addButton(
+ function () {
+ dlg.body.text = noticeTxt;
+ dlg.body.drawNew();
+ btn1.show();
+ btn2.show();
+ btn3.hide();
+ btn4.hide();
+ licenseBtn.hide();
+ translatorsBtn.hide();
+ dlg.fixLayout();
+ dlg.drawNew();
+ dlg.setCenter(world.center());
+ },
+ 'License...'
+ );
+ btn3 = dlg.addButton(
+ function () {
+ dlg.body.text = versions;
+ dlg.body.drawNew();
+ btn1.show();
+ btn2.show();
+ btn3.hide();
+ btn4.hide();
+ licenseBtn.hide();
+ translatorsBtn.hide();
+ dlg.fixLayout();
+ dlg.drawNew();
+ dlg.setCenter(world.center());
+ },
+ 'Modules...'
+ );
+ btn4 = dlg.addButton(
+ function () {
+ dlg.body.text = creditsTxt;
+ dlg.body.drawNew();
+ btn1.show();
+ btn2.show();
+ translatorsBtn.show();
+ btn3.hide();
+ btn4.hide();
+ licenseBtn.hide();
+ dlg.fixLayout();
+ dlg.drawNew();
+ dlg.setCenter(world.center());
+ },
+ 'Credits...'
+ );
+ translatorsBtn.hide();
+ dlg.fixLayout();
+ dlg.drawNew();
+};
+
+IDE_Morph.prototype.openProjectString = function (str) {
+ var msg,
+ myself = this;
+ this.nextSteps([
+ function () {
+ msg = myself.showMessage('Opening project...');
+ },
+ function () {
+ myself.rawOpenProjectString(str);
+ },
+ function () {
+ msg.destroy();
+ }
+ ]);
+};
+
+IDE_Morph.prototype.rawOpenProjectString = function (str) {
+ StageMorph.prototype.hiddenPrimitives = {};
+ StageMorph.prototype.codeMappings = {};
+ StageMorph.prototype.codeHeaders = {};
+ StageMorph.prototype.enableCodeMapping = false;
+ if (Process.prototype.isCatchingErrors) {
+ try {
+ this.serializer.openProject(this.serializer.load(str), this);
+ } catch (err) {
+ this.showMessage('Load failed: ' + err);
+ }
+ } else {
+ this.serializer.openProject(this.serializer.load(str), this);
+ }
+ this.stopFastTracking();
+};
+
+IDE_Morph.prototype.openBlocksString = function (str, name, silently) {
+ var msg,
+ myself = this;
+ this.nextSteps([
+ function () {
+ msg = myself.showMessage('Opening blocks...');
+ },
+ function () {
+ myself.rawOpenBlocksString(str, name, silently);
+ },
+ function () {
+ msg.destroy();
+ }
+ ]);
+};
+
+IDE_Morph.prototype.rawOpenBlocksString = function (str, name, silently) {
+ // name is optional (string), so is silently (bool)
+ var blocks,
+ myself = this;
+ if (Process.prototype.isCatchingErrors) {
+ try {
+ blocks = this.serializer.loadBlocks(str, myself.stage);
+ } catch (err) {
+ this.showMessage('Load failed: ' + err);
+ }
+ } else {
+ blocks = this.serializer.loadBlocks(str, myself.stage);
+ }
+ if (silently) {
+ blocks.forEach(function (def) {
+ def.receiver = myself.stage;
+ myself.stage.globalBlocks.push(def);
+ myself.stage.replaceDoubleDefinitionsFor(def);
+ });
+ this.showMessage(
+ 'Imported Blocks Module' + (name ? ': ' + name : '') + '.',
+ 2
+ );
+ } else {
+ new BlockImportDialogMorph(blocks, this.stage, name).popUp();
+ }
+};
+
+IDE_Morph.prototype.openSpritesString = function (str) {
+ var msg,
+ myself = this;
+ this.nextSteps([
+ function () {
+ msg = myself.showMessage('Opening sprite...');
+ },
+ function () {
+ myself.rawOpenSpritesString(str);
+ },
+ function () {
+ msg.destroy();
+ }
+ ]);
+};
+
+IDE_Morph.prototype.rawOpenSpritesString = function (str) {
+ if (Process.prototype.isCatchingErrors) {
+ try {
+ this.serializer.loadSprites(str, this);
+ } catch (err) {
+ this.showMessage('Load failed: ' + err);
+ }
+ } else {
+ this.serializer.loadSprites(str, this);
+ }
+};
+
+IDE_Morph.prototype.openMediaString = function (str) {
+ if (Process.prototype.isCatchingErrors) {
+ try {
+ this.serializer.loadMedia(str);
+ } catch (err) {
+ this.showMessage('Load failed: ' + err);
+ }
+ } else {
+ this.serializer.loadMedia(str);
+ }
+ this.showMessage('Imported Media Module.', 2);
+};
+
+IDE_Morph.prototype.openProject = function (name) {
+ var str;
+ if (name) {
+ this.showMessage('opening project\n' + name);
+ str = localStorage['-snap-project-' + name];
+ this.openProjectString(str);
+ location.hash = '#open:' + str;
+ }
+};
+
+IDE_Morph.prototype.switchToUserMode = function () {
+ var world = this.world();
+
+ world.isDevMode = false;
+ Process.prototype.isCatchingErrors = true;
+ this.controlBar.updateLabel();
+ this.isAutoFill = true;
+ this.isDraggable = false;
+ this.siblings().forEach(function (morph) {
+ if (morph instanceof DialogBoxMorph) {
+ world.add(morph); // bring to front
+ } else {
+ morph.destroy();
+ }
+ });
+ this.flushBlocksCache();
+ // prevent non-DialogBoxMorphs from being dropped
+ // onto the World in user-mode
+ world.reactToDropOf = function (morph) {
+ if (!(morph instanceof DialogBoxMorph)) {
+ world.hand.grab(morph);
+ }
+ };
+ this.showMessage('entering user mode', 1);
+
+};
+
+IDE_Morph.prototype.switchToDevMode = function () {
+ var world = this.world();
+
+ world.isDevMode = true;
+ Process.prototype.isCatchingErrors = false;
+ this.controlBar.updateLabel();
+ this.isAutoFill = false;
+ this.isDraggable = true;
+ this.setExtent(world.extent().subtract(100));
+ this.setPosition(world.position().add(20));
+ this.flushBlocksCache();
+ // enable non-DialogBoxMorphs to be dropped
+ // onto the World in dev-mode
+ delete world.reactToDropOf;
+ this.showMessage(
+ 'entering development mode.\n\n'
+ + 'error catching is turned off,\n'
+ + 'use the browser\'s web console\n'
+ + 'to see error messages.'
+ );
+};
+
+IDE_Morph.prototype.flushBlocksCache = function (category) {
+ // if no category is specified, the whole cache gets flushed
+ if (category) {
+ this.stage.blocksCache[category] = null;
+ this.stage.children.forEach(function (m) {
+ if (m instanceof SpriteMorph) {
+ m.blocksCache[category] = null;
+ }
+ });
+ } else {
+ this.stage.blocksCache = {};
+ this.stage.children.forEach(function (m) {
+ if (m instanceof SpriteMorph) {
+ m.blocksCache = {};
+ }
+ });
+ }
+};
+
+// IDE_Morph localization
+
+IDE_Morph.prototype.setLanguage = function (lang, callback) {
+ var translation = document.getElementById('language'),
+ src = 'lang-' + lang + '.js',
+ myself = this;
+ SnapTranslator.unload();
+ if (translation) {
+ document.head.removeChild(translation);
+ }
+ if (lang === 'en') {
+ return this.reflectLanguage('en', callback);
+ }
+ myself.userLanguage = lang;
+ translation = document.createElement('script');
+ translation.id = 'language';
+ translation.onload = function () {
+ myself.reflectLanguage(lang, callback);
+ };
+ document.head.appendChild(translation);
+ translation.src = src;
+};
+
+IDE_Morph.prototype.reflectLanguage = function (lang, callback) {
+ var projectData;
+ SnapTranslator.language = lang;
+ if (!this.loadNewProject) {
+ if (Process.prototype.isCatchingErrors) {
+ try {
+ projectData = this.serializer.serialize(this.stage);
+ } catch (err) {
+ this.showMessage('Serialization failed: ' + err);
+ }
+ } else {
+ projectData = this.serializer.serialize(this.stage);
+ }
+ }
+ SpriteMorph.prototype.initBlocks();
+ this.fixLayout();
+ if (this.loadNewProject) {
+ this.newProject();
+ } else {
+ this.openProjectString(projectData);
+ }
+ this.saveSetting('language', lang);
+ if (callback) {callback.call(this); }
+};
+
+// IDE_Morph synchronous Http data fetching
+
+IDE_Morph.prototype.getURL = function (url) {
+ var request = new XMLHttpRequest(),
+ myself = this;
+ try {
+ request.open('GET', url, false);
+ request.send();
+ if (request.status === 200) {
+ return request.responseText;
+ }
+ throw new Error('unable to retrieve ' + url);
+ } catch (err) {
+ myself.showMessage(err);
+ return;
+ }
+};
+
+IDE_Morph.prototype.getURLsbeOrRelative = function (url) {
+ var request = new XMLHttpRequest(),
+ myself = this;
+ try {
+ request.open('GET', 'http://snap.berkeley.edu/snapsource/' +
+ url, false);
+ request.send();
+ if (request.status === 200) {
+ return request.responseText;
+ }
+ return myself.getURL(url);
+ } catch (err) {
+ myself.showMessage(err);
+ return;
+ }
+};
+
+// IDE_Morph user dialog shortcuts
+
+IDE_Morph.prototype.showMessage = function (message, secs) {
+ var m = new MenuMorph(null, message),
+ intervalHandle;
+ m.popUpCenteredInWorld(this.world());
+ if (secs) {
+ intervalHandle = setInterval(function () {
+ m.destroy();
+ clearInterval(intervalHandle);
+ }, secs * 1000);
+ }
+ return m;
+};
+
+IDE_Morph.prototype.inform = function (title, message) {
+ new DialogBoxMorph().inform(
+ title,
+ localize(message),
+ this.world()
+ );
+};
+
+IDE_Morph.prototype.confirm = function (message, title, action) {
+ new DialogBoxMorph(null, action).askYesNo(
+ title,
+ localize(message),
+ this.world()
+ );
+};
+
+IDE_Morph.prototype.prompt = function (message, callback, choices, key) {
+ (new DialogBoxMorph(null, callback)).withKey(key).prompt(
+ message,
+ '',
+ this.world(),
+ null,
+ choices
+ );
+};
diff --git a/binary.sh b/binary.sh
new file mode 100755
index 0000000..212e7cb
--- /dev/null
+++ b/binary.sh
@@ -0,0 +1,92 @@
+#!/bin/bash
+
+if [[ "$snapsource" == "" ]]
+then
+ export snapsource="https://github.com/Gubolin/snap.git"
+fi
+
+if [[ $# < 2 ]]
+then
+ echo "Usage: binary.sh OPTION PLATFORM [FILE]"
+ echo ""
+ echo "OPTIONS:"
+ echo " -m Mobile"
+ echo " -d Desktop"
+ echo ""
+ echo "PLATFORMS:"
+ echo " Mobile amazon-fireos android blackberry10 firefoxos ios ubuntu wp8 win8 tizen"
+ echo " Desktop win osx linux32 linux64"
+ echo ""
+ echo "If FILE is given, it will be #open-ed inside Snap\! immediately"
+ exit 0
+fi
+
+scriptdir=$(readlink -e ".")
+
+# Requirements:
+# git
+# UglifyJS2 (https://github.com/mishoo/UglifyJS2)
+
+ide=true
+platform=$2
+
+# presentation mode
+if [[ "$3" != "" ]]
+then
+ ide=false
+fi
+
+if [ $ide == false ]
+then
+ if [ -f "$3" ]
+ then
+ content=$(cat $3)
+ else
+ ide=true
+ fi
+fi
+
+buildsource=$(mktemp -d)
+git clone $snapsource $buildsource
+cd "$buildsource"
+git checkout mobileapp
+
+rm -rf .git/
+
+if [ $ide == false ]
+then
+ # minimize everything
+ rm lang* ypr.js paint.js cloud.js gui.js
+
+ sed -i '/paint\.js"/d' snap.html
+ sed -i '/cloud\.js"/d' snap.html
+ sed -i 's/gui\.js"/binary\.js"/' snap.html
+
+ # load custom project from file
+ sed -i '/sha512\.js"/a\
+ <script type="text/javascript" src="code.js"></script> ' snap.html
+
+ echo "var code =" > code.js
+ echo "'$content'" >> code.js
+ echo ";" >> code.js
+
+ sed -i "/ide\.openIn/a\
+ ide.droppedText(code); " snap.html
+else
+ rm binary.js
+fi
+
+# compress all js files
+find . -name '*.js' | xargs -I {} uglifyjs {} -o {} -c
+
+# return to the directory where the script was called from
+cd "$scriptdir"
+
+# run helper scripts for building
+
+if [[ $1 == "-m" ]]
+then
+ ./mobile.sh "$2" "$buildsource"
+else
+ ./desktop.sh "$2" "$buildsource"
+fi
diff --git a/config.xml b/config.xml
new file mode 100644
index 0000000..36a7bcf
--- /dev/null
+++ b/config.xml
@@ -0,0 +1,15 @@
+<?xml version='4.0' encoding='utf-8'?>
+<widget id="edu.berkeley.snap" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+ <name>Snap!</name>
+ <description>
+ Snap! Build Your Own Blocks
+ A visual, blocks based programming language inspired by Scratch
+ </description>
+ <author email="jens@moenig.org" href="http://snap.berkeley.edu">
+ Jens Mönig and Brian Harvey
+ </author>
+ <content src="snap.html" />
+ <access origin="*" />
+ <preference name="Fullscreen" value="true" />
+ <icon src="www/snap_logo_sm.png" />
+</widget>
diff --git a/desktop.sh b/desktop.sh
new file mode 100755
index 0000000..72b0786
--- /dev/null
+++ b/desktop.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+if [[ "$snapsource" == "" ]]
+then
+ export snapsource="https://github.com/Gubolin/snap.git"
+fi
+
+if [[ $1 = "" ]]
+then
+ echo "Usage: desktop.sh PLATFORM [BUILDSOURCE]"
+ exit 0
+fi
+
+scriptdir=$(readlink -e ".")
+
+# Requirements:
+# git, zip, nodejs
+# node-webkit (https://github.com/rogerwang/node-webkit), node-webkit-builder (https://github.com/mllrsohn/node-webkit-builder)
+
+builddir=$(mktemp -d)
+
+if [[ $2 == "" ]]
+then
+ git clone "$snapsource" $builddir
+ cd $builddir/
+ git checkout mobileapp
+else
+ mv "$2" $builddir
+ cd $builddir/
+fi
+
+nwbuild -p "$1" .
+
+mv build/* $scriptdir/
diff --git a/mobile.sh b/mobile.sh
new file mode 100755
index 0000000..6ec8a0e
--- /dev/null
+++ b/mobile.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+
+if [[ "$snapsource" == "" ]]
+then
+ export snapsource="https://github.com/Gubolin/snap.git"
+fi
+
+if [[ $1 = "" ]]
+then
+ echo "Usage: mobile.sh PLATFORM [BUILDSOURCE]"
+ exit 0
+fi
+
+scriptdir=$(readlink -e ".")
+
+# Requirements:
+# git, nodejs, android SDK / other platform(s)
+# cordova (https://cordova.apache.org/)
+
+if [[ $2 != "" ]]
+then
+ buildsource=$(readlink -e "$2")
+fi
+
+builddir=$(mktemp -d)
+
+cordova create $builddir edu.berkeley.snap "Snap\!"
+cd $builddir
+rm -rf www config.xml
+
+if [[ $2 == "" ]]
+then
+ git clone "$snapsource" www
+ cd www/
+ git checkout mobileapp
+else
+ mv "$buildsource" www
+ cd www
+fi
+
+# add mobile-specific library; it's made available at runtime
+sed -i '/link rel="shortcut icon"/a\
+ <script type="text/javascript" src="cordova.js"></script>' snap.html
+
+# add everything needed and build for $device
+cordova platform add "$1"
+cordova plugin add org.apache.cordova.plugin.softkeyboard
+cordova plugin add org.apache.cordova.vibration
+cordova plugin add org.apache.cordova.device-motion
+cordova plugin add org.apache.cordova.device-orientation
+cordova plugin add org.apache.cordova.geolocation
+cordova plugin add de.appplant.cordova.plugin.local-notification
+
+if [[ $1 == "android" ]]
+then
+ # Remove default icons
+ cd "$builddir/platforms/android"
+ find -name '*.png' | xargs rm
+fi
+
+cordova build "$1"
+
+cd $builddir
+# TODO other platforms
+find -name '*.apk' | xargs -I {} mv {} $scriptdir
diff --git a/morphic.js b/morphic.js
index 9616897..4a16597 100644
--- a/morphic.js
+++ b/morphic.js
@@ -10790,6 +10790,11 @@ WorldMorph.prototype.edit = function (aStringOrTextMorph) {
this.virtualKeyboard.style.top = this.cursor.top() + pos.y + "px";
this.virtualKeyboard.style.left = this.cursor.left() + pos.x + "px";
this.virtualKeyboard.focus();
+ if (cordova) {
+ if (cordova.plugins.SoftKeyboard) { // Android only
+ cordova.plugins.SoftKeyboard.show(); // Issue #81
+ }
+ }
}
if (MorphicPreferences.useSliderForInput) {
diff --git a/objects.js b/objects.js
index 327dd30..95581c5 100644
--- a/objects.js
+++ b/objects.js
@@ -415,6 +415,11 @@ SpriteMorph.prototype.initBlocks = function () {
spec: 'go back %n layers',
defaults: [1]
},
+ doNotify: {
+ type: 'command',
+ category: 'looks',
+ spec: 'notification with title %s and content %s'
+ },
doScreenshot: {
type: 'command',
category: 'looks',
@@ -933,6 +938,31 @@ SpriteMorph.prototype.initBlocks = function () {
category: 'sensing',
spec: 'current %dates'
},
+ doVibrate: {
+ type: 'command',
+ category: 'sensing',
+ spec: 'vibrate %n seconds'
+ },
+ reportCompassHeading: {
+ type: 'reporter',
+ category: 'sensing',
+ spec: 'current compass heading'
+ },
+ reportAccelerationX: {
+ type: 'reporter',
+ category: 'sensing',
+ spec: 'current acceleration along the x axes'
+ },
+ reportAccelerationY: {
+ type: 'reporter',
+ category: 'sensing',
+ spec: 'current acceleration along the y axes'
+ },
+ reportAccelerationZ: {
+ type: 'reporter',
+ category: 'sensing',
+ spec: 'current acceleration along the z axes'
+ },
reportLanguage: {
type: 'reporter',
category: 'sensing',
@@ -1818,6 +1848,8 @@ SpriteMorph.prototype.blockTemplates = function (category) {
blocks.push('-');
blocks.push(block('comeToFront'));
blocks.push(block('goBack'));
+ blocks.push('-');
+ blocks.push(block('doNotify'));
// for debugging: ///////////////
@@ -1988,6 +2020,14 @@ SpriteMorph.prototype.blockTemplates = function (category) {
blocks.push('-');
blocks.push(block('reportLanguage'));
blocks.push(block('reportLocation'));
+ blocks.push('-');
+ blocks.push(block('doVibrate'));
+ blocks.push('-');
+ blocks.push(block('reportCompassHeading'));
+ blocks.push('-');
+ blocks.push(block('reportAccelerationX'));
+ blocks.push(block('reportAccelerationY'));
+ blocks.push(block('reportAccelerationZ'));
// for debugging: ///////////////
@@ -4434,6 +4474,8 @@ StageMorph.prototype.init = function (globals) {
this.paletteCache = {}; // not to be serialized (!)
this.lastAnswer = ''; // last user input, do not persist
this.activeSounds = []; // do not persist
+ this.acceleration = null; // do not persist
+ this.compassHeading = null; // do not persist
this.streamingCamera = false;
this.lastCameraCanvas = null;
this.lastCameraMotion = new Point(0, 0);
@@ -5082,6 +5124,8 @@ StageMorph.prototype.blockTemplates = function (category) {
blocks.push('-');
blocks.push(block('show'));
blocks.push(block('hide'));
+ blocks.push('-');
+ blocks.push(block('doNotify'));
// for debugging: ///////////////
@@ -5230,6 +5274,14 @@ StageMorph.prototype.blockTemplates = function (category) {
blocks.push('-');
blocks.push(block('reportLanguage'));
blocks.push(block('reportLocation'));
+ blocks.push('-');
+ blocks.push(block('doVibrate'));
+ blocks.push('-');
+ blocks.push(block('reportCompassHeading'));
+ blocks.push('-');
+ blocks.push(block('reportAccelerationX'));
+ blocks.push(block('reportAccelerationY'));
+ blocks.push(block('reportAccelerationZ'));
// for debugging: ///////////////
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..678a69c
--- /dev/null
+++ b/package.json
@@ -0,0 +1,8 @@
+{
+ "name": "Snap!",
+ "version": "4.0",
+ "main": "snap.html",
+ "window": {
+ "toolbar": false
+ }
+}
diff --git a/snap.html b/snap.html
index 703ccb1..5126b08 100755
--- a/snap.html
+++ b/snap.html
@@ -21,16 +21,26 @@
<script type="text/javascript" src="octokit.js/octokit.js"></script>
<script type="text/javascript" src="github.js"></script>
<script type="text/javascript" src="sha512.js"></script>
+<<<<<<< HEAD
<script type="text/javascript" src="Snapin8r/snapin8r.min.js"></script>
<script type="text/javascript" src="vkBeautify/vkbeautify.js"></script>
<script type="text/javascript" src="diff-merge/dist/diff.js"></script>
+=======
+
+>>>>>>> mobileapp
<script type="text/javascript">
var world;
window.onload = function () {
world = new WorldMorph(document.getElementById('world'));
world.worldCanvas.focus();
+<<<<<<< HEAD
new IDE_Morph().openIn(world);
setInterval(loop, 10);
+=======
+ var ide = new IDE_Morph()
+ ide.openIn(world);
+ setInterval(loop, 1);
+>>>>>>> mobileapp
};
function loop() {
world.doOneCycle();
diff --git a/threads.js b/threads.js
index 1665d0b..9626b89 100644
--- a/threads.js
+++ b/threads.js
@@ -2274,6 +2274,20 @@ Process.prototype.reportTextSplit = function (string, delimiter) {
return new List(str.split(del));
};
+// Process notification operations
+
+Process.prototype.doNotify = function (title, content) {
+ // TODO webkitNotification
+ if (window.plugin) {
+ if (window.plugin.notification) {
+ window.plugin.notification.local.add({
+ message: content,
+ title: title
+ });
+ }
+ }
+};
+
// Process debugging
Process.prototype.alert = function (data) {
@@ -2794,6 +2808,114 @@ Process.prototype.reportDate = function (datefn) {
return result;
};
+Process.prototype.getCompassHeading = function () {
+ var stage = this.homeContext.receiver.parentThatIsA(StageMorph);
+
+ stage.compassHeading = null;
+ if (navigator.compass) {
+ navigator.compass.getCurrentHeading(
+ function (result) {
+ stage.compassHeading = result;
+ },
+ function () {
+ stage.compassHeading =
+ {'magneticHeading': 0, 'trueHeading': 0,
+ 'headingAccuracy': 0, 'timestamp': 0};
+ }
+ );
+ } else {
+ stage.compassHeading =
+ {'magneticHeading': 0, 'trueHeading': 0,
+ 'headingAccuracy': 0, 'timestamp': 0};
+ }
+};
+
+Process.prototype.reportCompassHeading = function () {
+ var stage = this.homeContext.receiver.parentThatIsA(StageMorph);
+
+ if (this.context.wait) {
+ if (stage.compassHeading !== null) {
+ return stage.compassHeading.magneticHeading;
+ }
+ } else {
+ this.context.wait = true;
+ this.getCompassHeading();
+ }
+ this.pushContext('doYield');
+ this.pushContext();
+};
+
+Process.prototype.getAcceleration = function () {
+ var stage = this.homeContext.receiver.parentThatIsA(StageMorph);
+
+ stage.acceleration = null;
+ if (navigator.accelerometer) {
+ navigator.accelerometer.getCurrentAcceleration(
+ function (result) {
+ stage.acceleration = result;
+ },
+ function () {
+ stage.acceleration =
+ {'timestamp': 0, 'z': 0, 'y': 0, 'x': 0};
+ }
+ );
+ } else {
+ stage.acceleration =
+ {'timestamp': 0, 'z': 0, 'y': 0, 'x': 0};
+ }
+};
+
+Process.prototype.reportAccelerationX = function () {
+ var stage = this.homeContext.receiver.parentThatIsA(StageMorph);
+
+ if (this.context.wait) {
+ if (stage.acceleration !== null) {
+ return stage.acceleration.x;
+ }
+ } else {
+ this.context.wait = true;
+ this.getAcceleration();
+ }
+ this.pushContext('doYield');
+ this.pushContext();
+};
+
+Process.prototype.reportAccelerationY = function () {
+ var stage = this.homeContext.receiver.parentThatIsA(StageMorph);
+
+ if (this.context.wait) {
+ if (stage.acceleration !== null) {
+ return stage.acceleration.y;
+ }
+ } else {
+ this.context.wait = true;
+ this.getAcceleration();
+ }
+ this.pushContext('doYield');
+ this.pushContext();
+};
+
+Process.prototype.reportAccelerationZ = function () {
+ var stage = this.homeContext.receiver.parentThatIsA(StageMorph);
+
+ if (this.context.wait) {
+ if (stage.acceleration !== null) {
+ return stage.acceleration.z;
+ }
+ } else {
+ this.context.wait = true;
+ this.getAcceleration();
+ }
+ this.pushContext('doYield');
+ this.pushContext();
+};
+
+Process.prototype.doVibrate = function (seconds) {
+ if ("vibrate" in navigator) {
+ window.navigator.vibrate(seconds * 1000);
+ }
+};
+
// Process code mapping
/*
@@ -3203,8 +3325,6 @@ Process.prototype.reportFrameCount = function () {
activeAudio audio buffer for interpolated operations, don't persist
activeNote audio oscillator for interpolated ops, don't persist
activeStream video element for camera streaming, don't persist
- isLambda marker for return ops
- isImplicitLambda marker for return ops
isCustomBlock marker for return ops
emptySlots caches the number of empty slots for reification
tag string or number to optionally identify the Context,
@@ -3232,8 +3352,6 @@ function Context(
this.activeAudio = null;
this.activeNote = null;
this.activeStream = null;
- this.isLambda = false; // marks the end of a lambda
- this.isImplicitLambda = false; // marks the end of a C-shaped slot
this.isCustomBlock = false; // marks the end of a custom block's stack
this.emptySlots = 0; // used for block reification
this.tag = null; // lexical catch-tag for custom blocks