summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gui.js102
-rwxr-xr-xhistory.txt13
-rw-r--r--lang-de.js8
-rwxr-xr-xlang-pt.js26
-rw-r--r--locale.js4
-rw-r--r--morphic.js9
-rw-r--r--objects.js30
-rw-r--r--store.js6
-rw-r--r--threads.js35
9 files changed, 191 insertions, 42 deletions
diff --git a/gui.js b/gui.js
index 0adc325..7640393 100644
--- a/gui.js
+++ b/gui.js
@@ -64,11 +64,11 @@ standardSettings, Sound, BlockMorph, ToggleMorph, InputSlotDialogMorph,
ScriptsMorph, isNil, SymbolMorph, BlockExportDialogMorph,
BlockImportDialogMorph, SnapTranslator, localize, List, InputSlotMorph,
SnapCloud, Uint8Array, HandleMorph, SVG_Costume, fontHeight, hex_sha512,
-sb, CommentMorph, CommandBlockMorph, BlockLabelPlaceHolderMorph*/
+sb, CommentMorph, CommandBlockMorph, BlockLabelPlaceHolderMorph, Audio*/
// Global stuff ////////////////////////////////////////////////////////
-modules.gui = '2014-January-09';
+modules.gui = '2014-February-04';
// Declarations
@@ -2212,6 +2212,16 @@ IDE_Morph.prototype.settingsMenu = function () {
'check for smooth, predictable\nanimations across computers'
);
addPreference(
+ 'Flat line ends',
+ function () {
+ SpriteMorph.prototype.useFlatLineEnds =
+ !SpriteMorph.prototype.useFlatLineEnds;
+ },
+ SpriteMorph.prototype.useFlatLineEnds,
+ 'uncheck for round ends of lines',
+ 'check for flat ends of lines'
+ );
+ addPreference(
'Codification support',
function () {
StageMorph.prototype.enableCodeMapping =
@@ -2233,6 +2243,8 @@ IDE_Morph.prototype.projectMenu = function () {
myself = this,
world = this.world(),
pos = this.controlBar.projectButton.bottomLeft(),
+ graphicsName = this.currentSprite instanceof SpriteMorph ?
+ 'Costumes' : 'Backgrounds',
shiftClicked = (world.currentKey === 16);
menu = new MenuMorph(this);
@@ -2380,9 +2392,94 @@ IDE_Morph.prototype.projectMenu = function () {
'Select categories of additional blocks to add to this project.'
);
+ menu.addItem(
+ localize(graphicsName) + '...',
+ function () {
+ var dir = graphicsName,
+ names = myself.getCostumesList(dir),
+ libMenu = new MenuMorph(
+ myself,
+ localize('Import') + ' ' + localize(dir)
+ );
+
+ function loadCostume(name) {
+ var url = dir + '/' + name,
+ img = new Image();
+ img.onload = function () {
+ var canvas = newCanvas(new Point(img.width, img.height));
+ canvas.getContext('2d').drawImage(img, 0, 0);
+ myself.droppedImage(canvas, name);
+ };
+ img.src = url;
+ }
+
+ names.forEach(function (line) {
+ if (line.length > 0) {
+ libMenu.addItem(
+ line,
+ function () {loadCostume(line); }
+ );
+ }
+ });
+ libMenu.popup(world, pos);
+ },
+ 'Select a costume from the media library'
+ );
+ menu.addItem(
+ localize('Sounds') + '...',
+ function () {
+ var names = this.getCostumesList('Sounds'),
+ libMenu = new MenuMorph(this, 'Import sound');
+
+ function loadSound(name) {
+ var url = 'Sounds/' + name,
+ audio = new Audio();
+ audio.src = url;
+ audio.load();
+ myself.droppedAudio(audio, name);
+ }
+
+ names.forEach(function (line) {
+ if (line.length > 0) {
+ libMenu.addItem(
+ line,
+ function () {loadSound(line); }
+ );
+ }
+ });
+ libMenu.popup(world, pos);
+ },
+ 'Select a sound from the media library'
+ );
+
menu.popup(world, pos);
};
+IDE_Morph.prototype.getCostumesList = function (dirname) {
+ var dir,
+ costumes = [];
+
+ dir = this.getURL(dirname);
+ dir.split('\n').forEach(
+ function (line) {
+ var startIdx = line.search(new RegExp('href="[^./?].*"')),
+ endIdx,
+ name;
+
+ if (startIdx > 0) {
+ name = line.substring(startIdx + 6);
+ endIdx = name.search(new RegExp('"'));
+ name = name.substring(0, endIdx);
+ costumes.push(name);
+ }
+ }
+ );
+ costumes.sort(function (x, y) {
+ return x < y ? -1 : 1;
+ });
+ return costumes;
+};
+
// IDE_Morph menu actions
IDE_Morph.prototype.aboutSnap = function () {
@@ -2602,6 +2699,7 @@ IDE_Morph.prototype.newProject = function () {
StageMorph.prototype.codeMappings = {};
StageMorph.prototype.codeHeaders = {};
StageMorph.prototype.enableCodeMapping = false;
+ SpriteMorph.prototype.useFlatLineEnds = false;
this.setProjectName('');
this.projectNotes = '';
this.createStage();
diff --git a/history.txt b/history.txt
index d2ffc1d..054387a 100755
--- a/history.txt
+++ b/history.txt
@@ -2070,3 +2070,16 @@ ______
* Threads: Revert pull request #295 (xhr-headers), breaks existing installations
* BYOB: Fixed #292 (pulldowns loose lines when exported as library)
* BYOB: Fixed #291 (readonly custom menus become non-readonly when block is edited)
+
+140203
+------
+* Threads: Fixed #313. “Block of sprite” now works for interpolated (“timed”) blocks and for reporters (i.e. SAY FOR, THINK FOR, GLIDE, ASK etc.)
+* Morphic: replace deprecated DOM “body” references with “documentElement”
+
+140204
+------
+* GUI: Import costumes and backgrounds from the project menu, thanks, Brian, for the changeset!
+* GUI: Import sounds from the project menu, thanks, Brian, for the changeset!
+* Objects, Store, GUI: Flat line end option in the settings menu, saved with the project
+* German translation update
+* Objects: Enable playing sounds and notes on Firefox, thanks, Dean Brettle, for this fix!!
diff --git a/lang-de.js b/lang-de.js
index 0b438b5..8b71902 100644
--- a/lang-de.js
+++ b/lang-de.js
@@ -185,7 +185,7 @@ SnapTranslator.dict.de = {
'translator_e-mail':
'jens@moenig.org', // optional
'last_changed':
- '2014-01-09', // this, too, will appear in the Translators tab
+ '2014-02-04', // this, too, will appear in the Translators tab
// GUI
// control bar:
@@ -767,6 +767,12 @@ SnapTranslator.dict.de = {
'ausschalten, um Animationen \ndynamischer auszuf\u00fchren',
'check for smooth, predictable\nanimations across computers':
'einschalten, damit Animationen\n\u00fcberall gleich laufen',
+ 'Flat line ends':
+ 'Flache Pinselstriche',
+ 'check for flat ends of lines':
+ 'einschalten f\u00fcr flache\nPinselstrichenden',
+ 'uncheck for round ends of lines':
+ 'auschalten f\u00fcr runde\nPinselstrichenden',
// inputs
'with inputs':
diff --git a/lang-pt.js b/lang-pt.js
index 9360638..36ae99d 100755
--- a/lang-pt.js
+++ b/lang-pt.js
@@ -185,7 +185,7 @@ SnapTranslator.dict.pt = {
'translator_e-mail':
'mmsequeira@gmail.com',
'last_changed':
- '2013-11-22',
+ '2014-01-12',
// GUI
// control bar:
@@ -447,12 +447,20 @@ SnapTranslator.dict.pt = {
'se %b , então %c senão, %c',
'report %s':
'reporta %s',
- 'stop block':
- 'pára este guião de bloco',
- 'stop script':
- 'pára este guião de objecto',
- 'stop all %stop':
- 'pára tudo %stop',
+ 'stop %stopChoices':
+ 'pára %stopChoices',
+ 'all':
+ 'tudo',
+ 'this script':
+ 'este guião de objecto',
+ 'this block':
+ 'este guião de bloco',
+ 'stop %stopOthersChoices':
+ 'pára %stopOthersChoices',
+ 'all but this script':
+ 'todos os guiões de objecto excepto este',
+ 'other scripts in sprite':
+ 'os outros guiões deste objecto',
'pause all %pause':
'faz pausa em tudo %pause',
'run %cmdRing %inputs':
@@ -950,8 +958,6 @@ SnapTranslator.dict.pt = {
'Este projecto ainda não tem\nnenhum bloco personalizado global.',
'select':
'seleccionar',
- 'all':
- 'todos',
'none':
'nenhum',
@@ -1215,7 +1221,7 @@ SnapTranslator.dict.pt = {
'e^':
'a exponencial',
- // delimiters
+ // delimitadores
'whitespace':
'espaços em branco',
'line':
diff --git a/locale.js b/locale.js
index 3b65ec9..d0b7a49 100644
--- a/locale.js
+++ b/locale.js
@@ -42,7 +42,7 @@
/*global modules, contains*/
-modules.locale = '2014-January-09';
+modules.locale = '2014-February-04';
// Global stuff
@@ -149,7 +149,7 @@ SnapTranslator.dict.de = {
'translator_e-mail':
'jens@moenig.org',
'last_changed':
- '2014-01-09'
+ '2014-02-04'
};
SnapTranslator.dict.it = {
diff --git a/morphic.js b/morphic.js
index c5aa561..b55b180 100644
--- a/morphic.js
+++ b/morphic.js
@@ -1035,7 +1035,7 @@
/*global window, HTMLCanvasElement, getMinimumFontHeight, FileReader, Audio,
FileList, getBlurredShadowSupport*/
-var morphicVersion = '2014-January-09';
+var morphicVersion = '2014-February-03';
var modules = {}; // keep track of additional loaded modules
var useBlurredShadows = getBlurredShadowSupport(); // check for Chrome-bug
@@ -10029,13 +10029,14 @@ WorldMorph.prototype.fillPage = function () {
this.worldCanvas.style.top = "0px";
pos.y = 0;
}
- if (document.body.scrollTop) { // scrolled down b/c of viewport scaling
+ if (document.documentElement.scrollTop) {
+ // scrolled down b/c of viewport scaling
clientHeight = document.documentElement.clientHeight;
}
- if (document.body.scrollLeft) { // scrolled left b/c of viewport scaling
+ if (document.documentElement.scrollLeft) {
+ // scrolled left b/c of viewport scaling
clientWidth = document.documentElement.clientWidth;
}
-
if (this.worldCanvas.width !== clientWidth) {
this.worldCanvas.width = clientWidth;
this.setWidth(clientWidth);
diff --git a/objects.js b/objects.js
index af482b1..52126e2 100644
--- a/objects.js
+++ b/objects.js
@@ -124,7 +124,7 @@ PrototypeHatBlockMorph*/
// Global stuff ////////////////////////////////////////////////////////
-modules.objects = '2014-January-09';
+modules.objects = '2014-February-04';
var SpriteMorph;
var StageMorph;
@@ -186,6 +186,7 @@ SpriteMorph.prototype.sliderColor
SpriteMorph.prototype.isCachingPrimitives = true;
SpriteMorph.prototype.enableNesting = true;
+SpriteMorph.prototype.useFlatLineEnds = false;
SpriteMorph.prototype.highlightColor = new Color(250, 200, 130);
SpriteMorph.prototype.highlightBorder = 8;
@@ -2717,8 +2718,13 @@ SpriteMorph.prototype.drawLine = function (start, dest) {
if (this.isDown) {
context.lineWidth = this.size;
context.strokeStyle = this.color.toString();
- context.lineCap = 'round';
- context.lineJoin = 'round';
+ if (this.useFlatLineEnds) {
+ context.lineCap = 'butt';
+ context.lineJoin = 'miter';
+ } else {
+ context.lineCap = 'round';
+ context.lineJoin = 'round';
+ }
context.beginPath();
context.moveTo(from.x, from.y);
context.lineTo(to.x, to.y);
@@ -5647,17 +5653,21 @@ Note.prototype.setupContext = function () {
if (this.audioContext) { return; }
var AudioContext = (function () {
// cross browser some day?
- return window.AudioContext ||
+ var ctx = window.AudioContext ||
window.mozAudioContext ||
window.msAudioContext ||
window.oAudioContext ||
window.webkitAudioContext;
+ if (!ctx.prototype.hasOwnProperty('createGain')) {
+ ctx.prototype.createGain = ctx.prototype.createGainNode;
+ }
+ return ctx;
}());
if (!AudioContext) {
throw new Error('Web Audio API is not supported\nin this browser');
}
Note.prototype.audioContext = new AudioContext();
- Note.prototype.gainNode = Note.prototype.audioContext.createGainNode();
+ Note.prototype.gainNode = Note.prototype.audioContext.createGain();
Note.prototype.gainNode.gain.value = 0.25; // reduce volume by 1/4
};
@@ -5665,17 +5675,23 @@ Note.prototype.setupContext = function () {
Note.prototype.play = function () {
this.oscillator = this.audioContext.createOscillator();
+ if (!this.oscillator.start) {
+ this.oscillator.start = this.oscillator.noteOn;
+ }
+ if (!this.oscillator.stop) {
+ this.oscillator.stop = this.oscillator.noteOff;
+ }
this.oscillator.type = 0;
this.oscillator.frequency.value =
Math.pow(2, (this.pitch - 69) / 12) * 440;
this.oscillator.connect(this.gainNode);
this.gainNode.connect(this.audioContext.destination);
- this.oscillator.noteOn(0); // deprecated, renamed to start()
+ this.oscillator.start(0);
};
Note.prototype.stop = function () {
if (this.oscillator) {
- this.oscillator.noteOff(0); // deprecated, renamed to stop()
+ this.oscillator.stop(0);
this.oscillator = null;
}
};
diff --git a/store.js b/store.js
index 343dca6..ae9a5d1 100644
--- a/store.js
+++ b/store.js
@@ -61,7 +61,7 @@ SyntaxElementMorph*/
// Global stuff ////////////////////////////////////////////////////////
-modules.store = '2014-January-09';
+modules.store = '2014-February-04';
// XML_Serializer ///////////////////////////////////////////////////////
@@ -378,6 +378,8 @@ SnapSerializer.prototype.loadProjectModel = function (xmlNode) {
}
project.stage.setTempo(model.stage.attributes.tempo);
project.stage.setExtent(StageMorph.prototype.dimensions);
+ SpriteMorph.prototype.useFlatLineEnds =
+ model.stage.attributes.lines === 'flat';
project.stage.isThreadSafe =
model.stage.attributes.threadsafe === 'true';
StageMorph.prototype.enableCodeMapping =
@@ -1340,6 +1342,7 @@ StageMorph.prototype.toXML = function (serializer) {
'<notes>$</notes>' +
'<thumbnail>$</thumbnail>' +
'<stage name="@" costume="@" tempo="@" threadsafe="@" ' +
+ 'lines="@" ' +
'codify="@" ' +
'scheduled="@" ~>' +
'<pentrails>$</pentrails>' +
@@ -1364,6 +1367,7 @@ StageMorph.prototype.toXML = function (serializer) {
this.getCostumeIdx(),
this.getTempo(),
this.isThreadSafe,
+ SpriteMorph.prototype.useFlatLineEnds ? 'flat' : 'round',
this.enableCodeMapping,
StageMorph.prototype.frameRate !== 0,
this.trailsCanvas.toDataURL('image/png'),
diff --git a/threads.js b/threads.js
index d4a6732..93931c1 100644
--- a/threads.js
+++ b/threads.js
@@ -83,7 +83,7 @@ ArgLabelMorph, localize, XML_Element, hex_sha512*/
// Global stuff ////////////////////////////////////////////////////////
-modules.threads = '2014-January-10';
+modules.threads = '2014-Feb-03';
var ThreadManager;
var Process;
@@ -1643,15 +1643,15 @@ Process.prototype.doGlide = function (secs, endX, endY) {
if (!this.context.startTime) {
this.context.startTime = Date.now();
this.context.startValue = new Point(
- this.homeContext.receiver.xPosition(),
- this.homeContext.receiver.yPosition()
+ this.blockReceiver().xPosition(),
+ this.blockReceiver().yPosition()
);
}
if ((Date.now() - this.context.startTime) >= (secs * 1000)) {
- this.homeContext.receiver.gotoXY(endX, endY);
+ this.blockReceiver().gotoXY(endX, endY);
return null;
}
- this.homeContext.receiver.glide(
+ this.blockReceiver().glide(
secs * 1000,
endX,
endY,
@@ -1666,10 +1666,10 @@ Process.prototype.doGlide = function (secs, endX, endY) {
Process.prototype.doSayFor = function (data, secs) {
if (!this.context.startTime) {
this.context.startTime = Date.now();
- this.homeContext.receiver.bubble(data);
+ this.blockReceiver().bubble(data);
}
if ((Date.now() - this.context.startTime) >= (secs * 1000)) {
- this.homeContext.receiver.stopTalking();
+ this.blockReceiver().stopTalking();
return null;
}
this.pushContext('doYield');
@@ -1679,16 +1679,21 @@ Process.prototype.doSayFor = function (data, secs) {
Process.prototype.doThinkFor = function (data, secs) {
if (!this.context.startTime) {
this.context.startTime = Date.now();
- this.homeContext.receiver.doThink(data);
+ this.blockReceiver().doThink(data);
}
if ((Date.now() - this.context.startTime) >= (secs * 1000)) {
- this.homeContext.receiver.stopTalking();
+ this.blockReceiver().stopTalking();
return null;
}
this.pushContext('doYield');
this.pushContext();
};
+Process.prototype.blockReceiver = function () {
+ return this.context ? this.context.receiver || this.homeContext.receiver
+ : this.homeContext.receiver;
+};
+
// Process sound primitives (interpolated)
Process.prototype.doPlaySoundUntilDone = function (name) {
@@ -1723,7 +1728,7 @@ Process.prototype.doStopAllSounds = function () {
Process.prototype.doAsk = function (data) {
var stage = this.homeContext.receiver.parentThatIsA(StageMorph),
- isStage = this.homeContext.receiver instanceof StageMorph,
+ isStage = this.blockReceiver() instanceof StageMorph,
activePrompter;
if (!this.prompter) {
@@ -1733,7 +1738,7 @@ Process.prototype.doAsk = function (data) {
);
if (!activePrompter) {
if (!isStage) {
- this.homeContext.receiver.bubble(data, false, true);
+ this.blockReceiver().bubble(data, false, true);
}
this.prompter = new StagePrompterMorph(isStage ? data : null);
if (stage.scale < 1) {
@@ -1753,7 +1758,7 @@ Process.prototype.doAsk = function (data) {
stage.lastAnswer = this.prompter.inputField.getValue();
this.prompter.destroy();
this.prompter = null;
- if (!isStage) {this.homeContext.receiver.stopTalking(); }
+ if (!isStage) {this.blockReceiver().stopTalking(); }
return null;
}
}
@@ -2288,7 +2293,7 @@ Process.prototype.createClone = function (name) {
// Process sensing primitives
Process.prototype.reportTouchingObject = function (name) {
- var thisObj = this.homeContext.receiver;
+ var thisObj = this.blockReceiver();
if (thisObj) {
return this.objectTouchingObject(thisObj, name);
@@ -2384,7 +2389,7 @@ Process.prototype.reportColorIsTouchingColor = function (color1, color2) {
};
Process.prototype.reportDistanceTo = function (name) {
- var thisObj = this.homeContext.receiver,
+ var thisObj = this.blockReceiver(),
thatObj,
stage,
rc,
@@ -2407,7 +2412,7 @@ Process.prototype.reportDistanceTo = function (name) {
};
Process.prototype.reportAttributeOf = function (attribute, name) {
- var thisObj = this.homeContext.receiver,
+ var thisObj = this.blockReceiver(),
thatObj,
stage;