kopia lustrzana https://github.com/backface/turtlestitch
* change logo
* add stitch preview features: show stitches, show jump stitches * add svg exportpull/3/merge
rodzic
aa981d0e83
commit
37d7015f3a
|
|
@ -24,10 +24,12 @@
|
|||
<script type="text/javascript" src="stitchcode/backend/js/jquery.fileDownload.js"></script>
|
||||
|
||||
<script type="text/javascript" src="stitchcode/FileSaver.js"></script>
|
||||
<script type="text/javascript" src="stitchcode/blocks.js"></script>
|
||||
<script type="text/javascript" src="stitchcode/stitchcodeChangeSetDel.js"></script>
|
||||
<script type="text/javascript" src="stitchcode/stitchcodeGUI.js"></script>
|
||||
<script type="text/javascript" src="stitchcode/stitchcodeChangeSet.js"></script>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
var world;
|
||||
window.onload = function () {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@
|
|||
|
||||
var tStitch = {};
|
||||
|
||||
tStitch.draw_jump = true;
|
||||
tStitch.draw_stitches = true;
|
||||
tStitch.draw_stitch_len = 3;
|
||||
|
||||
tStitch.debug_msg = function (st,clear) {
|
||||
o = new String();
|
||||
if (!clear) {
|
||||
|
|
@ -53,6 +57,23 @@ tStitch.addPoint = function (x,y,jump) {
|
|||
}
|
||||
}
|
||||
|
||||
tStitch.toogleShowStitches = function() {
|
||||
tStitch.draw_stitches = !tStitch.draw_stitches;
|
||||
}
|
||||
|
||||
tStitch.getShowStitches = function() {
|
||||
return tStitch.draw_stitches;
|
||||
}
|
||||
|
||||
tStitch.toogleShowJumpStitches = function() {
|
||||
tStitch.draw_jumps = !tStitch.draw_jumps;
|
||||
}
|
||||
|
||||
tStitch.getShowJumpStitches = function() {
|
||||
return tStitch.draw_jumps;
|
||||
}
|
||||
|
||||
|
||||
|
||||
tStitch.upload = function() {
|
||||
|
||||
|
|
@ -111,6 +132,9 @@ tStitch.upload = function() {
|
|||
/* Sprite */
|
||||
// modified SpriteMorph turtle functions
|
||||
|
||||
// SpriteMorph motion primitives
|
||||
|
||||
|
||||
SpriteMorph.prototype.forward = function (steps) {
|
||||
var dest,
|
||||
dist = steps * this.parent.scale || 0;
|
||||
|
|
@ -126,6 +150,7 @@ SpriteMorph.prototype.forward = function (steps) {
|
|||
|
||||
this.setPosition(dest);
|
||||
this.positionTalkBubble();
|
||||
//this.drawLineX(dest);
|
||||
|
||||
tx = dest.x - this.parent.topLeft().x
|
||||
ty = dest.y - this.parent.topLeft().y
|
||||
|
|
@ -143,6 +168,7 @@ SpriteMorph.prototype.gotoXY = function (x, y, justMe) {
|
|||
|
||||
newX = stage.center().x + (+x || 0) * stage.scale;
|
||||
newY = stage.center().y - (+y || 0) * stage.scale;
|
||||
|
||||
if (this.costume) {
|
||||
dest = new Point(newX, newY).subtract(this.rotationOffset);
|
||||
} else {
|
||||
|
|
@ -151,6 +177,7 @@ SpriteMorph.prototype.gotoXY = function (x, y, justMe) {
|
|||
|
||||
this.setPosition(dest, justMe);
|
||||
this.positionTalkBubble();
|
||||
|
||||
|
||||
tx = dest.x - this.parent.topLeft().x
|
||||
ty = dest.y - this.parent.topLeft().y
|
||||
|
|
@ -159,6 +186,102 @@ SpriteMorph.prototype.gotoXY = function (x, y, justMe) {
|
|||
tStitch.addPoint(tx,ty,tjump);
|
||||
};
|
||||
|
||||
// SpriteMorph drawing:
|
||||
|
||||
SpriteMorph.prototype.drawLine = function (start, dest) {
|
||||
var stagePos = this.parent.bounds.origin,
|
||||
stageScale = this.parent.scale,
|
||||
context = this.parent.penTrails().getContext('2d'),
|
||||
from = start.subtract(stagePos).divideBy(stageScale),
|
||||
to = dest.subtract(stagePos).divideBy(stageScale),
|
||||
damagedFrom = from.multiplyBy(stageScale).add(stagePos),
|
||||
damagedTo = to.multiplyBy(stageScale).add(stagePos),
|
||||
damaged = damagedFrom.rectangle(damagedTo).expandBy(
|
||||
Math.max(this.size * stageScale / 2, 1)
|
||||
).intersect(this.parent.visibleBounds()).spread();
|
||||
|
||||
|
||||
|
||||
if (this.isDown) {
|
||||
context.lineWidth = this.size;
|
||||
context.strokeStyle = this.color.toString();
|
||||
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);
|
||||
context.stroke();
|
||||
if (this.isWarped === false) {
|
||||
this.world().broken.push(damaged);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.drawJumpLine = function (start, dest) {
|
||||
var stagePos = this.parent.bounds.origin,
|
||||
stageScale = this.parent.scale,
|
||||
context = this.parent.penTrails().getContext('2d'),
|
||||
from = start.subtract(stagePos).divideBy(stageScale),
|
||||
to = dest.subtract(stagePos).divideBy(stageScale),
|
||||
damagedFrom = from.multiplyBy(stageScale).add(stagePos),
|
||||
damagedTo = to.multiplyBy(stageScale).add(stagePos),
|
||||
damaged = damagedFrom.rectangle(damagedTo).expandBy(
|
||||
Math.max(this.size * stageScale / 2, 1)
|
||||
).intersect(this.parent.visibleBounds()).spread();
|
||||
|
||||
context.lineWidth = this.size;
|
||||
context.strokeStyle = new Color(255, 0, 0).toString();
|
||||
context.lineCap = 'round';
|
||||
context.lineJoin = 'round';
|
||||
context.beginPath();
|
||||
context.moveTo(from.x, from.y);
|
||||
context.lineTo(to.x, to.y);
|
||||
context.stroke();
|
||||
if (this.isWarped === false) {
|
||||
this.world().broken.push(damaged);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
SpriteMorph.prototype.drawStitch = function (dest) {
|
||||
//dest = dest.subtract(this.topLeft());
|
||||
var s = tStitch.draw_stitch_len;
|
||||
var stagePos = this.parent.bounds.origin,
|
||||
stageScale = this.parent.scale,
|
||||
context = this.parent.penTrails().getContext('2d'),
|
||||
to = dest.subtract(stagePos).divideBy(stageScale),
|
||||
damagedFrom = new Point(to.x-s,to.y-s).multiplyBy(stageScale).add(stagePos),
|
||||
damagedTo = new Point(to.x+s,to.y+s).multiplyBy(stageScale).add(stagePos),
|
||||
damaged = damagedFrom.rectangle(damagedTo).expandBy(
|
||||
Math.max(this.size * stageScale / 2, 1)
|
||||
).intersect(this.parent.visibleBounds()).spread();
|
||||
|
||||
context.lineWidth = this.size;
|
||||
context.strokeStyle = new Color(0, 0, 255).toString();
|
||||
context.lineCap = 'round';
|
||||
context.lineJoin = 'round';
|
||||
|
||||
context.beginPath();
|
||||
context.moveTo(to.x - s, to.y - s );
|
||||
context.lineTo(to.x + s, to.y + s);
|
||||
context.stroke();
|
||||
|
||||
context.beginPath();
|
||||
context.moveTo(to.x - s, to.y + s);
|
||||
context.lineTo(to.x + s, to.y - s);
|
||||
context.stroke();
|
||||
if (this.isWarped === false) {
|
||||
this.world().broken.push(damaged);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
SpriteMorph.prototype.clear = function () {
|
||||
this.parent.clearPenTrails();
|
||||
tStitch.clearPoints();
|
||||
|
|
@ -168,6 +291,50 @@ SpriteMorph.prototype.clear = function () {
|
|||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// SpriteMorph motion - adjustments due to nesting
|
||||
|
||||
SpriteMorph.prototype.moveBy = function (delta, justMe) {
|
||||
// override the inherited default to make sure my parts follow
|
||||
// unless it's justMe (a correction)
|
||||
var start = this.isDown && !justMe && this.parent ?
|
||||
this.rotationCenter() : null;
|
||||
|
||||
// add stitch controls
|
||||
if (this.parent) {
|
||||
if (this.parent.penTrails()) {
|
||||
origin = this.rotationCenter();
|
||||
}
|
||||
}
|
||||
|
||||
SpriteMorph.uber.moveBy.call(this, delta);
|
||||
|
||||
// add stitch controls
|
||||
if (this.parent) {
|
||||
if (this.parent.penTrails() && origin.x > 100) {
|
||||
//alert(origin.x);
|
||||
if (tStitch.draw_stitches) {
|
||||
this.drawStitch(this.rotationCenter());
|
||||
}
|
||||
if (tStitch.draw_jump && !this.isDown) {
|
||||
//this.drawJumpLine(origin,this.rotationCenter());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (start) {
|
||||
this.drawLine(start, this.rotationCenter());
|
||||
}
|
||||
if (!justMe) {
|
||||
this.parts.forEach(function (part) {
|
||||
part.moveBy(delta);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
// Definition of new block categories
|
||||
SpriteMorph.prototype.categories =
|
||||
|
|
|
|||
|
|
@ -1,878 +1 @@
|
|||
|
||||
// this file includes changes just things to deactivate/hide some
|
||||
// stuff and functions we don't need.
|
||||
|
||||
|
||||
// IDE_Morph layout
|
||||
|
||||
IDE_Morph.prototype.fixLayout = function (situation) {
|
||||
// situation is a string, i.e.
|
||||
// 'selectSprite' or 'refreshPalette' or 'tabEditor'
|
||||
var padding = this.padding;
|
||||
|
||||
Morph.prototype.trackChanges = false;
|
||||
|
||||
if (situation !== 'refreshPalette') {
|
||||
// controlBar
|
||||
this.controlBar.setPosition(this.logo.topRight());
|
||||
this.controlBar.setWidth(this.right() - this.controlBar.left());
|
||||
this.controlBar.fixLayout();
|
||||
|
||||
// categories
|
||||
this.categories.setLeft(this.logo.left());
|
||||
this.categories.setTop(this.logo.bottom());
|
||||
}
|
||||
|
||||
// palette
|
||||
this.palette.setLeft(this.logo.left());
|
||||
this.palette.setTop(this.categories.bottom());
|
||||
this.palette.setHeight(this.bottom() - this.palette.top());
|
||||
|
||||
if (situation !== 'refreshPalette') {
|
||||
// stage
|
||||
if (this.isAppMode) {
|
||||
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());
|
||||
} else {
|
||||
// this.stage.setScale(this.isSmallStage ? 0.5 : 1);
|
||||
this.stage.setScale(this.isSmallStage ? this.stageRatio : 1);
|
||||
this.stage.setTop(this.logo.bottom() + padding);
|
||||
this.stage.setRight(this.right());
|
||||
}
|
||||
/*
|
||||
// spriteBar
|
||||
this.spriteBar.setPosition(this.logo.bottomRight().add(padding));
|
||||
this.spriteBar.setExtent(new Point(
|
||||
Math.max(0, this.stage.left() - padding - this.spriteBar.left()),
|
||||
this.categories.bottom() - this.spriteBar.top() - padding
|
||||
));
|
||||
this.spriteBar.fixLayout();
|
||||
*/
|
||||
// spriteEditor
|
||||
if (this.spriteEditor.isVisible) {
|
||||
//this.spriteEditor.setPosition(this.spriteBar.bottomLeft());
|
||||
this.spriteEditor.setPosition(this.logo.bottomRight().add(padding));
|
||||
this.spriteEditor.setExtent(new Point(
|
||||
//this.spriteBar.width(),
|
||||
Math.max(0, this.stage.left() - padding - this.spriteEditor.left()),
|
||||
this.bottom() - this.spriteEditor.top()
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
// corralBar
|
||||
this.corralBar.setLeft(this.stage.left());
|
||||
this.corralBar.setTop(this.stage.bottom() + padding);
|
||||
this.corralBar.setWidth(this.stage.width());
|
||||
|
||||
// corral
|
||||
if (!contains(['selectSprite', 'tabEditor'], situation)) {
|
||||
this.corral.setPosition(this.corralBar.bottomLeft());
|
||||
this.corral.setWidth(this.stage.width());
|
||||
this.corral.setHeight(this.bottom() - this.corral.top());
|
||||
this.corral.fixLayout();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Morph.prototype.trackChanges = true;
|
||||
this.changed();
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.setProjectName = function (string) {
|
||||
this.projectName = string.replace(/['"]/g, ''); // filter quotation marks
|
||||
this.hasChangedMedia = true;
|
||||
this.controlBar.updateLabel();
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.createSpriteBar = function () {
|
||||
// assumes that the categories pane has already been created
|
||||
var rotationStyleButtons = [],
|
||||
thumbSize = new Point(45, 45),
|
||||
nameField,
|
||||
padlock,
|
||||
thumbnail,
|
||||
tabCorner = 15,
|
||||
tabColors = this.tabColors,
|
||||
tabBar = new AlignmentMorph('row', -tabCorner * 2),
|
||||
tab,
|
||||
symbols = ['\u2192', '\u21BB', '\u2194'],
|
||||
labels = ['don\'t rotate', 'can rotate', 'only face left/right'],
|
||||
myself = this;
|
||||
|
||||
if (this.spriteBar) {
|
||||
this.spriteBar.destroy();
|
||||
}
|
||||
|
||||
this.spriteBar = new Morph();
|
||||
this.spriteBar.color = this.frameColor;
|
||||
//this.add(this.spriteBar);
|
||||
|
||||
function addRotationStyleButton(rotationStyle) {
|
||||
var colors = myself.rotationStyleColors,
|
||||
button;
|
||||
|
||||
button = new ToggleButtonMorph(
|
||||
colors,
|
||||
myself, // the IDE is the target
|
||||
function () {
|
||||
if (myself.currentSprite instanceof SpriteMorph) {
|
||||
myself.currentSprite.rotationStyle = rotationStyle;
|
||||
myself.currentSprite.changed();
|
||||
myself.currentSprite.drawNew();
|
||||
myself.currentSprite.changed();
|
||||
}
|
||||
rotationStyleButtons.forEach(function (each) {
|
||||
each.refresh();
|
||||
});
|
||||
},
|
||||
symbols[rotationStyle], // label
|
||||
function () { // query
|
||||
return myself.currentSprite instanceof SpriteMorph
|
||||
&& myself.currentSprite.rotationStyle === rotationStyle;
|
||||
},
|
||||
null, // environment
|
||||
localize(labels[rotationStyle])
|
||||
);
|
||||
|
||||
button.corner = 8;
|
||||
button.labelMinExtent = new Point(11, 11);
|
||||
button.padding = 0;
|
||||
button.labelShadowOffset = new Point(-1, -1);
|
||||
button.labelShadowColor = colors[1];
|
||||
button.labelColor = myself.buttonLabelColor;
|
||||
button.fixLayout();
|
||||
button.refresh();
|
||||
rotationStyleButtons.push(button);
|
||||
button.setPosition(myself.spriteBar.position().add(2));
|
||||
button.setTop(button.top()
|
||||
+ ((rotationStyleButtons.length - 1) * (button.height() + 2))
|
||||
);
|
||||
myself.spriteBar.add(button);
|
||||
if (myself.currentSprite instanceof StageMorph) {
|
||||
button.hide();
|
||||
}
|
||||
return button;
|
||||
}
|
||||
|
||||
addRotationStyleButton(1);
|
||||
addRotationStyleButton(2);
|
||||
addRotationStyleButton(0);
|
||||
this.rotationStyleButtons = rotationStyleButtons;
|
||||
|
||||
thumbnail = new Morph();
|
||||
thumbnail.setExtent(thumbSize);
|
||||
thumbnail.image = this.currentSprite.thumbnail(thumbSize);
|
||||
thumbnail.setPosition(
|
||||
rotationStyleButtons[0].topRight().add(new Point(5, 3))
|
||||
);
|
||||
this.spriteBar.add(thumbnail);
|
||||
|
||||
thumbnail.fps = 3;
|
||||
|
||||
thumbnail.step = function () {
|
||||
if (thumbnail.version !== myself.currentSprite.version) {
|
||||
thumbnail.image = myself.currentSprite.thumbnail(thumbSize);
|
||||
thumbnail.changed();
|
||||
thumbnail.version = myself.currentSprite.version;
|
||||
}
|
||||
};
|
||||
|
||||
nameField = new InputFieldMorph(this.currentSprite.name);
|
||||
nameField.setWidth(100); // fixed dimensions
|
||||
nameField.contrast = 90;
|
||||
nameField.setPosition(thumbnail.topRight().add(new Point(10, 3)));
|
||||
this.spriteBar.add(nameField);
|
||||
nameField.drawNew();
|
||||
nameField.accept = function () {
|
||||
var newName = nameField.getValue();
|
||||
myself.currentSprite.setName(
|
||||
myself.newSpriteName(newName, myself.currentSprite)
|
||||
);
|
||||
nameField.setContents(myself.currentSprite.name);
|
||||
};
|
||||
this.spriteBar.reactToEdit = nameField.accept;
|
||||
|
||||
// padlock
|
||||
padlock = new ToggleMorph(
|
||||
'checkbox',
|
||||
null,
|
||||
function () {
|
||||
myself.currentSprite.isDraggable =
|
||||
!myself.currentSprite.isDraggable;
|
||||
},
|
||||
localize('draggable'),
|
||||
function () {
|
||||
return myself.currentSprite.isDraggable;
|
||||
}
|
||||
);
|
||||
padlock.label.isBold = false;
|
||||
padlock.label.setColor(this.buttonLabelColor);
|
||||
padlock.color = tabColors[2];
|
||||
padlock.highlightColor = tabColors[0];
|
||||
padlock.pressColor = tabColors[1];
|
||||
|
||||
padlock.tick.shadowOffset = MorphicPreferences.isFlat ?
|
||||
new Point() : new Point(-1, -1);
|
||||
padlock.tick.shadowColor = new Color(); // black
|
||||
padlock.tick.color = this.buttonLabelColor;
|
||||
padlock.tick.isBold = false;
|
||||
padlock.tick.drawNew();
|
||||
|
||||
padlock.setPosition(nameField.bottomLeft().add(2));
|
||||
padlock.drawNew();
|
||||
this.spriteBar.add(padlock);
|
||||
if (this.currentSprite instanceof StageMorph) {
|
||||
padlock.hide();
|
||||
}
|
||||
|
||||
// tab bar
|
||||
tabBar.tabTo = function (tabString) {
|
||||
var active;
|
||||
myself.currentTab = tabString;
|
||||
this.children.forEach(function (each) {
|
||||
each.refresh();
|
||||
if (each.state) {active = each; }
|
||||
});
|
||||
active.refresh(); // needed when programmatically tabbing
|
||||
myself.createSpriteEditor();
|
||||
myself.fixLayout('tabEditor');
|
||||
};
|
||||
|
||||
tab = new TabMorph(
|
||||
tabColors,
|
||||
null, // target
|
||||
function () {tabBar.tabTo('scripts'); },
|
||||
localize('Scripts'), // label
|
||||
function () { // query
|
||||
return myself.currentTab === 'scripts';
|
||||
}
|
||||
);
|
||||
tab.padding = 3;
|
||||
tab.corner = tabCorner;
|
||||
tab.edge = 1;
|
||||
tab.labelShadowOffset = new Point(-1, -1);
|
||||
tab.labelShadowColor = tabColors[1];
|
||||
tab.labelColor = this.buttonLabelColor;
|
||||
tab.drawNew();
|
||||
tab.fixLayout();
|
||||
tabBar.add(tab);
|
||||
|
||||
tab = new TabMorph(
|
||||
tabColors,
|
||||
null, // target
|
||||
function () {tabBar.tabTo('costumes'); },
|
||||
localize('Costumes'), // label
|
||||
function () { // query
|
||||
return myself.currentTab === 'costumes';
|
||||
}
|
||||
);
|
||||
tab.padding = 3;
|
||||
tab.corner = tabCorner;
|
||||
tab.edge = 1;
|
||||
tab.labelShadowOffset = new Point(-1, -1);
|
||||
tab.labelShadowColor = tabColors[1];
|
||||
tab.labelColor = this.buttonLabelColor;
|
||||
tab.drawNew();
|
||||
tab.fixLayout();
|
||||
tabBar.add(tab);
|
||||
|
||||
tab = new TabMorph(
|
||||
tabColors,
|
||||
null, // target
|
||||
function () {tabBar.tabTo('sounds'); },
|
||||
localize('Sounds'), // label
|
||||
function () { // query
|
||||
return myself.currentTab === 'sounds';
|
||||
}
|
||||
);
|
||||
tab.padding = 3;
|
||||
tab.corner = tabCorner;
|
||||
tab.edge = 1;
|
||||
tab.labelShadowOffset = new Point(-1, -1);
|
||||
tab.labelShadowColor = tabColors[1];
|
||||
tab.labelColor = this.buttonLabelColor;
|
||||
tab.drawNew();
|
||||
tab.fixLayout();
|
||||
tabBar.add(tab);
|
||||
|
||||
tabBar.fixLayout();
|
||||
tabBar.children.forEach(function (each) {
|
||||
each.refresh();
|
||||
});
|
||||
this.spriteBar.tabBar = tabBar;
|
||||
this.spriteBar.add(this.spriteBar.tabBar);
|
||||
|
||||
this.spriteBar.fixLayout = function () {
|
||||
this.tabBar.setLeft(this.left());
|
||||
this.tabBar.setBottom(this.bottom());
|
||||
};
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.createCorralBar = function () {
|
||||
// assumes the stage has already been created
|
||||
var padding = 5,
|
||||
newbutton,
|
||||
paintbutton,
|
||||
colors = [
|
||||
this.groupColor,
|
||||
this.frameColor.darker(50),
|
||||
this.frameColor.darker(50)
|
||||
];
|
||||
|
||||
if (this.corralBar) {
|
||||
this.corralBar.destroy();
|
||||
}
|
||||
|
||||
this.corralBar = new Morph();
|
||||
this.corralBar.color = this.frameColor;
|
||||
this.corralBar.setHeight(this.logo.height()); // height is fixed
|
||||
//this.add(this.corralBar);
|
||||
|
||||
// new sprite button
|
||||
newbutton = new PushButtonMorph(
|
||||
this,
|
||||
"addNewSprite",
|
||||
new SymbolMorph("turtle", 14)
|
||||
);
|
||||
newbutton.corner = 12;
|
||||
newbutton.color = colors[0];
|
||||
newbutton.highlightColor = colors[1];
|
||||
newbutton.pressColor = colors[2];
|
||||
newbutton.labelMinExtent = new Point(36, 18);
|
||||
newbutton.padding = 0;
|
||||
newbutton.labelShadowOffset = new Point(-1, -1);
|
||||
newbutton.labelShadowColor = colors[1];
|
||||
newbutton.labelColor = this.buttonLabelColor;
|
||||
newbutton.contrast = this.buttonContrast;
|
||||
newbutton.drawNew();
|
||||
newbutton.hint = "add a new Turtle sprite";
|
||||
newbutton.fixLayout();
|
||||
newbutton.setCenter(this.corralBar.center());
|
||||
newbutton.setLeft(this.corralBar.left() + padding);
|
||||
this.corralBar.add(newbutton);
|
||||
|
||||
paintbutton = new PushButtonMorph(
|
||||
this,
|
||||
"paintNewSprite",
|
||||
new SymbolMorph("brush", 15)
|
||||
);
|
||||
paintbutton.corner = 12;
|
||||
paintbutton.color = colors[0];
|
||||
paintbutton.highlightColor = colors[1];
|
||||
paintbutton.pressColor = colors[2];
|
||||
paintbutton.labelMinExtent = new Point(36, 18);
|
||||
paintbutton.padding = 0;
|
||||
paintbutton.labelShadowOffset = new Point(-1, -1);
|
||||
paintbutton.labelShadowColor = colors[1];
|
||||
paintbutton.labelColor = this.buttonLabelColor;
|
||||
paintbutton.contrast = this.buttonContrast;
|
||||
paintbutton.drawNew();
|
||||
paintbutton.hint = "paint a new sprite";
|
||||
paintbutton.fixLayout();
|
||||
paintbutton.setCenter(this.corralBar.center());
|
||||
paintbutton.setLeft(
|
||||
this.corralBar.left() + padding + newbutton.width() + padding
|
||||
);
|
||||
this.corralBar.add(paintbutton);
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.createCorral = function () {
|
||||
// assumes the corral bar has already been created
|
||||
var frame, template, padding = 5, myself = this;
|
||||
|
||||
if (this.corral) {
|
||||
this.corral.destroy();
|
||||
}
|
||||
|
||||
this.corral = new Morph();
|
||||
this.corral.color = this.groupColor;
|
||||
//this.add(this.corral);
|
||||
|
||||
this.corral.stageIcon = new SpriteIconMorph(this.stage);
|
||||
this.corral.stageIcon.isDraggable = false;
|
||||
this.corral.add(this.corral.stageIcon);
|
||||
|
||||
frame = new ScrollFrameMorph(null, null, this.sliderColor);
|
||||
frame.acceptsDrops = false;
|
||||
frame.contents.acceptsDrops = false;
|
||||
|
||||
frame.contents.wantsDropOf = function (morph) {
|
||||
return morph instanceof SpriteIconMorph;
|
||||
};
|
||||
|
||||
frame.contents.reactToDropOf = function (spriteIcon) {
|
||||
myself.corral.reactToDropOf(spriteIcon);
|
||||
};
|
||||
|
||||
frame.alpha = 0;
|
||||
|
||||
this.sprites.asArray().forEach(function (morph) {
|
||||
template = new SpriteIconMorph(morph, template);
|
||||
frame.contents.add(template);
|
||||
});
|
||||
|
||||
this.corral.frame = frame;
|
||||
this.corral.add(frame);
|
||||
|
||||
this.corral.fixLayout = function () {
|
||||
this.stageIcon.setCenter(this.center());
|
||||
this.stageIcon.setLeft(this.left() + padding);
|
||||
this.frame.setLeft(this.stageIcon.right() + padding);
|
||||
this.frame.setExtent(new Point(
|
||||
this.right() - this.frame.left(),
|
||||
this.height()
|
||||
));
|
||||
this.arrangeIcons();
|
||||
this.refresh();
|
||||
};
|
||||
|
||||
this.corral.arrangeIcons = function () {
|
||||
var x = this.frame.left(),
|
||||
y = this.frame.top(),
|
||||
max = this.frame.right(),
|
||||
start = this.frame.left();
|
||||
|
||||
this.frame.contents.children.forEach(function (icon) {
|
||||
var w = icon.width();
|
||||
|
||||
if (x + w > max) {
|
||||
x = start;
|
||||
y += icon.height(); // they're all the same
|
||||
}
|
||||
icon.setPosition(new Point(x, y));
|
||||
x += w;
|
||||
});
|
||||
this.frame.contents.adjustBounds();
|
||||
};
|
||||
|
||||
this.corral.addSprite = function (sprite) {
|
||||
this.frame.contents.add(new SpriteIconMorph(sprite));
|
||||
this.fixLayout();
|
||||
};
|
||||
|
||||
this.corral.refresh = function () {
|
||||
this.stageIcon.refresh();
|
||||
this.frame.contents.children.forEach(function (icon) {
|
||||
icon.refresh();
|
||||
});
|
||||
};
|
||||
|
||||
this.corral.wantsDropOf = function (morph) {
|
||||
return morph instanceof SpriteIconMorph;
|
||||
};
|
||||
|
||||
this.corral.reactToDropOf = function (spriteIcon) {
|
||||
var idx = 1,
|
||||
pos = spriteIcon.position();
|
||||
spriteIcon.destroy();
|
||||
this.frame.contents.children.forEach(function (icon) {
|
||||
if (pos.gt(icon.position()) || pos.y > icon.bottom()) {
|
||||
idx += 1;
|
||||
}
|
||||
});
|
||||
myself.sprites.add(spriteIcon.object, idx);
|
||||
myself.createCorral();
|
||||
myself.fixLayout();
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
// StageMorph user menu
|
||||
|
||||
StageMorph.prototype.userMenu = function () {
|
||||
var ide = this.parentThatIsA(IDE_Morph),
|
||||
menu = new MenuMorph(this),
|
||||
shiftClicked = this.world().currentKey === 16,
|
||||
myself = this;
|
||||
|
||||
if (ide && ide.isAppMode) {
|
||||
// menu.addItem('help', 'nop');
|
||||
return menu;
|
||||
}
|
||||
//menu.addItem("edit", 'edit');
|
||||
menu.addItem("show all", 'showAll');
|
||||
menu.addItem(
|
||||
"pic...",
|
||||
function () {
|
||||
window.open(myself.fullImageClassic().toDataURL());
|
||||
},
|
||||
'open a new window\nwith a picture of the stage'
|
||||
);
|
||||
if (shiftClicked) {
|
||||
menu.addLine();
|
||||
menu.addItem(
|
||||
"turn pen trails into new costume...",
|
||||
function () {
|
||||
var costume = new Costume(
|
||||
myself.trailsCanvas,
|
||||
Date.now().toString()
|
||||
).copy();
|
||||
ide.currentSprite.addCostume(costume);
|
||||
ide.currentSprite.wearCostume(costume);
|
||||
ide.hasChangedMedia = true;
|
||||
},
|
||||
'turn all pen trails and stamps\n' +
|
||||
'into a new costume for the\ncurrently selected sprite',
|
||||
new Color(100, 0, 0)
|
||||
);
|
||||
}
|
||||
return menu;
|
||||
};
|
||||
|
||||
|
||||
IDE_Morph.prototype.createCategories = function () {
|
||||
// assumes the logo has already been created
|
||||
var myself = this;
|
||||
|
||||
if (this.categories) {
|
||||
this.categories.destroy();
|
||||
}
|
||||
this.categories = new Morph();
|
||||
this.categories.color = this.groupColor;
|
||||
this.categories.silentSetWidth(this.logo.width()); // width is fixed
|
||||
|
||||
function addCategoryButton(category) {
|
||||
var labelWidth = 75,
|
||||
colors = [
|
||||
myself.frameColor,
|
||||
myself.frameColor.darker(50),
|
||||
SpriteMorph.prototype.blockColor[category]
|
||||
],
|
||||
button;
|
||||
|
||||
button = new ToggleButtonMorph(
|
||||
colors,
|
||||
myself, // the IDE is the target
|
||||
function () {
|
||||
myself.currentCategory = category;
|
||||
myself.categories.children.forEach(function (each) {
|
||||
each.refresh();
|
||||
});
|
||||
myself.refreshPalette(true);
|
||||
},
|
||||
category[0].toUpperCase().concat(category.slice(1)), // label
|
||||
function () { // query
|
||||
return myself.currentCategory === category;
|
||||
},
|
||||
null, // env
|
||||
null, // hint
|
||||
null, // template cache
|
||||
labelWidth, // minWidth
|
||||
true // has preview
|
||||
);
|
||||
|
||||
button.corner = 8;
|
||||
button.padding = 0;
|
||||
button.labelShadowOffset = new Point(-1, -1);
|
||||
button.labelShadowColor = colors[1];
|
||||
button.labelColor = myself.buttonLabelColor;
|
||||
button.fixLayout();
|
||||
button.refresh();
|
||||
myself.categories.add(button);
|
||||
return button;
|
||||
}
|
||||
|
||||
function fixCategoriesLayout() {
|
||||
var buttonWidth = myself.categories.children[0].width(),
|
||||
buttonHeight = myself.categories.children[0].height(),
|
||||
border = 3,
|
||||
rows = Math.ceil((myself.categories.children.length) / 2),
|
||||
xPadding = (myself.categories.width()
|
||||
- border
|
||||
- buttonWidth * 2) / 3,
|
||||
yPadding = 2,
|
||||
l = myself.categories.left(),
|
||||
t = myself.categories.top(),
|
||||
i = 0,
|
||||
row,
|
||||
col;
|
||||
|
||||
myself.categories.children.forEach(function (button) {
|
||||
i += 1;
|
||||
row = Math.ceil(i / 2);
|
||||
col = 2 - (i % 2);
|
||||
button.setPosition(new Point(
|
||||
l + (col * xPadding + ((col - 1) * buttonWidth)),
|
||||
t + (row * yPadding + ((row - 1) * buttonHeight) + border)
|
||||
));
|
||||
});
|
||||
|
||||
myself.categories.setHeight(
|
||||
(rows + 1) * yPadding
|
||||
+ rows * buttonHeight
|
||||
+ 2 * border
|
||||
);
|
||||
}
|
||||
|
||||
SpriteMorph.prototype.categories.forEach(function (cat) {
|
||||
if (!contains(['lists', 'other','sound','looks'], cat)) {
|
||||
addCategoryButton(cat);
|
||||
}
|
||||
});
|
||||
fixCategoriesLayout();
|
||||
this.add(this.categories);
|
||||
};
|
||||
|
||||
IDE_Morph.prototype.projectMenu = function () {
|
||||
var menu,
|
||||
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);
|
||||
menu.addItem('Project notes...', 'editProjectNotes');
|
||||
menu.addLine();
|
||||
menu.addItem('New', 'createNewProject');
|
||||
menu.addItem('Open...', 'openProjectsBrowser');
|
||||
menu.addItem('Save', "save");
|
||||
if (shiftClicked) {
|
||||
menu.addItem(
|
||||
'Save to disk',
|
||||
'saveProjectToDisk',
|
||||
'experimental - store this project\nin your downloads folder',
|
||||
new Color(100, 0, 0)
|
||||
);
|
||||
}
|
||||
menu.addItem('Save As...', 'saveProjectsBrowser');
|
||||
menu.addLine();
|
||||
menu.addItem(
|
||||
'Import...',
|
||||
function () {
|
||||
var inp = document.createElement('input');
|
||||
if (myself.filePicker) {
|
||||
document.body.removeChild(myself.filePicker);
|
||||
myself.filePicker = null;
|
||||
}
|
||||
inp.type = 'file';
|
||||
inp.style.color = "transparent";
|
||||
inp.style.backgroundColor = "transparent";
|
||||
inp.style.border = "none";
|
||||
inp.style.outline = "none";
|
||||
inp.style.position = "absolute";
|
||||
inp.style.top = "0px";
|
||||
inp.style.left = "0px";
|
||||
inp.style.width = "0px";
|
||||
inp.style.height = "0px";
|
||||
inp.addEventListener(
|
||||
"change",
|
||||
function () {
|
||||
document.body.removeChild(inp);
|
||||
myself.filePicker = null;
|
||||
world.hand.processDrop(inp.files);
|
||||
},
|
||||
false
|
||||
);
|
||||
document.body.appendChild(inp);
|
||||
myself.filePicker = inp;
|
||||
inp.click();
|
||||
},
|
||||
'file menu import hint' // looks up the actual text in the translator
|
||||
);
|
||||
menu.addItem('Export stitch file', 'uploadStitches','Export stage drawing to stitch file (EXP)..');
|
||||
|
||||
menu.addItem(
|
||||
shiftClicked ?
|
||||
'Export project as plain text...' : 'Export project...',
|
||||
function () {
|
||||
if (myself.projectName) {
|
||||
myself.exportProject(myself.projectName, shiftClicked);
|
||||
} else {
|
||||
myself.prompt('Export Project As...', function (name) {
|
||||
myself.exportProject(name);
|
||||
}, null, 'exportProject');
|
||||
}
|
||||
},
|
||||
'show project data as XML\nin a new browser window',
|
||||
shiftClicked ? new Color(100, 0, 0) : null
|
||||
);
|
||||
|
||||
menu.addItem(
|
||||
'Export blocks...',
|
||||
function () {myself.exportGlobalBlocks(); },
|
||||
'show global custom block definitions as XML\nin a new browser window'
|
||||
);
|
||||
|
||||
if (shiftClicked) {
|
||||
menu.addItem(
|
||||
'Export all scripts as pic...',
|
||||
function () {myself.exportScriptsPicture(); },
|
||||
'show a picture of all scripts\nand block definitions',
|
||||
new Color(100, 0, 0)
|
||||
);
|
||||
}
|
||||
|
||||
menu.addLine();
|
||||
menu.addItem(
|
||||
'Import tools',
|
||||
function () {
|
||||
myself.droppedText(
|
||||
myself.getURLsbeOrRelative(
|
||||
'tools.xml'
|
||||
),
|
||||
'tools'
|
||||
);
|
||||
},
|
||||
'load the official library of\npowerful blocks'
|
||||
);
|
||||
menu.addItem(
|
||||
'Libraries...',
|
||||
function () {
|
||||
// read a list of libraries from an external file,
|
||||
var libMenu = new MenuMorph(this, 'Import library'),
|
||||
libUrl = 'http://snap.berkeley.edu/snapsource/libraries/' +
|
||||
'LIBRARIES';
|
||||
|
||||
function loadLib(name) {
|
||||
var url = 'http://snap.berkeley.edu/snapsource/libraries/'
|
||||
+ name
|
||||
+ '.xml';
|
||||
myself.droppedText(myself.getURL(url), name);
|
||||
}
|
||||
|
||||
myself.getURL(libUrl).split('\n').forEach(function (line) {
|
||||
if (line.length > 0) {
|
||||
libMenu.addItem(
|
||||
line.substring(line.indexOf('\t') + 1),
|
||||
function () {
|
||||
loadLib(
|
||||
line.substring(0, line.indexOf('\t'))
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
libMenu.popup(world, pos);
|
||||
},
|
||||
'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.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(
|
||||
'TurtleStich! website',
|
||||
function () {
|
||||
window.open('http://'+window.location.hostname, 'SnapWebsite');
|
||||
}
|
||||
);
|
||||
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());
|
||||
};
|
||||
|
|
|
|||
Plik diff jest za duży
Load Diff
Plik binarny nie jest wyświetlany.
|
Przed Szerokość: | Wysokość: | Rozmiar: 1.4 KiB Po Szerokość: | Wysokość: | Rozmiar: 2.9 KiB |
Plik binarny nie jest wyświetlany.
|
Przed Szerokość: | Wysokość: | Rozmiar: 1.5 KiB |
Ładowanie…
Reference in New Issue