Paint editor integration

pull/3/merge
jmoenig 2013-05-14 13:47:13 +02:00
rodzic 3f92313ae4
commit b250bb2683
3 zmienionych plików z 195 dodań i 339 usunięć

189
gui.js
Wyświetl plik

@ -68,7 +68,7 @@ sb, CommentMorph, CommandBlockMorph*/
// Global stuff ////////////////////////////////////////////////////////
modules.gui = '2013-May-10';
modules.gui = '2013-May-14';
// Declarations
@ -1105,7 +1105,8 @@ IDE_Morph.prototype.createSpriteEditor = function () {
IDE_Morph.prototype.createCorralBar = function () {
// assumes the stage has already been created
var padding = 5,
button,
newbutton,
paintbutton,
colors = [
this.groupColor,
this.frameColor.darker(50),
@ -1122,28 +1123,51 @@ IDE_Morph.prototype.createCorralBar = function () {
this.add(this.corralBar);
// new sprite button
button = new PushButtonMorph(
newbutton = new PushButtonMorph(
this,
'addNewSprite',
new SymbolMorph('turtle', 14)
"addNewSprite",
new SymbolMorph("turtle", 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(255, 255, 255);
button.contrast = this.buttonContrast;
button.drawNew();
button.hint = 'add a new sprite';
button.fixLayout();
button.setCenter(this.corralBar.center());
button.setLeft(this.corralBar.left() + padding);
this.corralBar.add(button);
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 = new Color(255, 255, 255);
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 = new Color(255, 255, 255);
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 () {
@ -1548,6 +1572,30 @@ IDE_Morph.prototype.addNewSprite = function () {
this.selectSprite(sprite);
};
IDE_Morph.prototype.paintNewSprite = function() {
var sprite = new SpriteMorph(this.globalVariables),
cos = new Costume(),
myself = this;
sprite.name = sprite.name +
(this.corral.frame.contents.children.length + 1);
sprite.setCenter(this.stage.center());
this.stage.add(sprite);
this.sprites.add(sprite);
this.corral.addSprite(sprite);
this.selectSprite(sprite);
cos.edit(
this.world(),
this,
true,
function() {myself.removeSprite(sprite); },
function () {
sprite.addCostume(cos);
sprite.wearCostume(cos);
}
);
};
IDE_Morph.prototype.duplicateSprite = function (sprite) {
var duplicate = sprite.fullCopy();
@ -4724,16 +4772,38 @@ CostumeIconMorph.prototype.fixLayout
CostumeIconMorph.prototype.userMenu = function () {
var menu = new MenuMorph(this);
if (!(this.object instanceof Costume)) {return null; }
menu.addItem("edit", 'editCostume');
menu.addItem("rename", 'renameCostume');
menu.addItem("delete", 'removeCostume');
menu.addItem("export", 'exportCostume');
menu.addItem("edit", "editCostume");
if (this.world().currentKey === 16) { // shift clicked
menu.addItem(
'edit rotation point only...',
'editRotationPointOnly',
null,
new Color(100, 0, 0)
);
}
menu.addItem("rename", "renameCostume");
menu.addLine();
menu.addItem("duplicate", "duplicateCostume");
menu.addItem("delete", "removeCostume");
menu.addLine();
menu.addItem("export", "exportCostume");
return menu;
};
CostumeIconMorph.prototype.editCostume = function () {
if (this.object instanceof SVG_Costume) {
this.object.editRotationPointOnly(this.world());
} else {
this.object.edit(
this.world(),
this.parentThatIsA(IDE_Morph)
);
}
};
CostumeIconMorph.prototype.editRotationPointOnly = function () {
var ide = this.parentThatIsA(IDE_Morph);
this.object.edit(this.world());
this.object.editRotationPointOnly(this.world());
ide.hasChangedMedia = true;
};
@ -4756,11 +4826,31 @@ CostumeIconMorph.prototype.renameCostume = function () {
);
};
CostumeIconMorph.prototype.duplicateCostume = function() {
var wardrobe = this.parentThatIsA(WardrobeMorph),
ide = this.parentThatIsA(IDE_Morph),
newcos = this.object.copy(),
split = newcos.name.split(" ");
if (split[split.length - 1] === "copy") {
newcos.name += " 2";
} else if (isNaN(split[split.length - 1])) {
newcos.name = newcos.name + " copy";
} else {
split[split.length - 1] = Number(split[split.length - 1]) + 1;
newcos.name = split.join(" ");
}
wardrobe.sprite.addCostume(newcos);
wardrobe.updateList();
if (ide) {
ide.currentSprite.wearCostume(newcos);
}
};
CostumeIconMorph.prototype.removeCostume = function () {
var wardrobe = this.parentThatIsA(WardrobeMorph),
idx = this.parent.children.indexOf(this),
ide = this.parentThatIsA(IDE_Morph);
wardrobe.removeCostumeAt(idx - 1);
wardrobe.removeCostumeAt(idx - 2);
if (ide.currentSprite.costume === this.object) {
ide.currentSprite.wearCostume(null);
}
@ -5016,7 +5106,8 @@ WardrobeMorph.prototype.updateList = function () {
oldPos = this.contents.position(),
icon,
template,
txt;
txt,
paintbutton;
this.changed();
oldFlag = Morph.prototype.trackChanges;
@ -5035,15 +5126,42 @@ WardrobeMorph.prototype.updateList = function () {
myself.addContents(icon);
y = icon.bottom() + padding;
paintbutton = new PushButtonMorph(
this,
"paintNew",
new SymbolMorph("brush", 15)
);
paintbutton.padding = 0;
paintbutton.corner = 12;
paintbutton.color = IDE_Morph.prototype.groupColor;
paintbutton.highlightColor = IDE_Morph.prototype.frameColor.darker(50);
paintbutton.pressColor = paintbutton.highlightColor;
paintbutton.labelMinExtent = new Point(36, 18);
paintbutton.labelShadowOffset = new Point(-1, -1);
paintbutton.labelShadowColor = paintbutton.highlightColor;
paintbutton.labelColor = new Color(255, 255, 255);
paintbutton.contrast = this.buttonContrast;
paintbutton.drawNew();
paintbutton.hint = "Paint a new costume";
paintbutton.setPosition(new Point(x, y));
paintbutton.fixLayout();
paintbutton.setCenter(icon.center());
paintbutton.setLeft(icon.right() + padding * 4);
this.addContents(paintbutton);
txt = new TextMorph(localize(
'costumes tab help' // look up long string in translator
"costumes tab help" // look up long string in translator
));
txt.fontSize = 9;
txt.setColor(new Color(230, 230, 230));
txt.setPosition(new Point(x, y));
this.addContents(txt);
y = txt.bottom() + padding;
this.sprite.costumes.asArray().forEach(function (costume) {
template = icon = new CostumeIconMorph(costume, template);
icon.setPosition(new Point(x, y));
@ -5085,6 +5203,19 @@ WardrobeMorph.prototype.removeCostumeAt = function (idx) {
this.updateList();
};
WardrobeMorph.prototype.paintNew = function() {
var cos = new Costume(newCanvas(), "Untitled"),
ide = this.parentThatIsA(IDE_Morph),
myself = this;
cos.edit(this.world(), null, true, null, function() {
myself.sprite.addCostume(cos);
myself.updateList();
if (ide) {
ide.currentSprite.wearCostume(cos);
}
});
};
// Wardrobe drag & drop
WardrobeMorph.prototype.wantsDropOf = function (morph) {

Wyświetl plik

@ -63,7 +63,10 @@
*/
// gloabls from lists.js:
// globals from paint.js:
/*global PaintEditorMorph*/
// globals from lists.js:
/*global ListWatcherMorph*/
@ -120,7 +123,7 @@ PrototypeHatBlockMorph*/
// Global stuff ////////////////////////////////////////////////////////
modules.objects = '2013-April-30';
modules.objects = '2013-May-14';
var SpriteMorph;
var StageMorph;
@ -4532,7 +4535,7 @@ Costume.prototype.shrinkWrap = function () {
ext.x,
ext.y
);
this.rotationCenter = this.rotationCenter.add(bb.origin);
this.rotationCenter = this.rotationCenter.subtract(bb.origin);
this.contents = pic;
this.version = Date.now();
};
@ -4639,7 +4642,34 @@ Costume.prototype.flipped = function () {
// Costume actions
Costume.prototype.edit = function (aWorld) {
Costume.prototype.edit = function (aWorld, anIDE, isnew, oncancel, onsubmit) {
var myself = this,
editor = new PaintEditorMorph();
editor.oncancel = oncancel || nop;
editor.openIn(
aWorld,
isnew ?
newCanvas(new Point(480, 360)) :
this.contents,
isnew ?
new Point(240, 180) :
this.rotationCenter,
function (img, rc) {
myself.contents = img;
myself.rotationCenter = rc;
myself.shrinkWrap();
myself.version = Date.now();
aWorld.changed();
if (anIDE) {
anIDE.currentSprite.wearCostume(myself);
anIDE.hasChangedMedia = true;
}
(onsubmit || nop)();
}
);
};
Costume.prototype.editRotationPointOnly = function (aWorld) {
var editor = new CostumeEditorMorph(this),
action,
dialog,

307
paint.js
Wyświetl plik

@ -54,7 +54,7 @@
FrameMorph, PushButtonMorph, Color, SymbolMorph, newCanvas, Morph, TextMorph,
CostumeIconMorph, IDE_Morph, Costume, SpriteMorph, nop, Image, WardrobeMorph,
TurtleIconMorph, localize, MenuMorph, InputFieldMorph, SliderMorph,
ToggleMorph, ToggleButtonMorph, BoxMorph, modules, radians, SVG_Costume
ToggleMorph, ToggleButtonMorph, BoxMorph, modules, radians
*/
// Global stuff ////////////////////////////////////////////////////////
@ -887,308 +887,3 @@ PaintCanvasMorph.prototype.typeInPadding
PaintCanvasMorph.prototype.contrast
= InputFieldMorph.prototype.contrast;
// Changes to gui.js and object.js (temporarily here) //////////////////
// These will be incorporated into the respective files later
// They add costume editing functionality to Snap!.
////////////////////////////////////////////////////////////////////////
CostumeIconMorph.prototype.editCostume = function () {
if (this.object instanceof SVG_Costume) {
this.object.editRotationPointOnly(this.world());
} else {
this.object.edit(
this.world(),
this.parentThatIsA(IDE_Morph)
);
}
};
Costume.prototype.edit = function (aWorld, anIDE, isnew, oncancel, onsubmit) {
var myself = this,
editor = new PaintEditorMorph();
editor.oncancel = oncancel || nop;
editor.openIn(
aWorld,
isnew ?
newCanvas(new Point(480, 360)) :
this.contents,
isnew ?
new Point(240, 180) :
this.rotationCenter,
function (img, rc) {
myself.contents = img;
myself.rotationCenter = rc;
myself.shrinkWrap();
myself.version = Date.now();
aWorld.changed();
if (anIDE) {
anIDE.currentSprite.wearCostume(myself);
anIDE.hasChangedMedia = true;
}
(onsubmit || nop)();
}
);
};
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 = new Color(255, 255, 255);
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 = new Color(255, 255, 255);
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.paintNewSprite = function() {
var sprite = new SpriteMorph(this.globalVariables),
cos = new Costume(),
myself = this;
sprite.name = sprite.name +
(this.corral.frame.contents.children.length + 1);
sprite.setCenter(this.stage.center());
this.stage.add(sprite);
this.sprites.add(sprite);
this.corral.addSprite(sprite);
this.selectSprite(sprite);
cos.edit(
this.world(),
this,
true,
function() {myself.removeSprite(sprite); },
function () {
sprite.addCostume(cos);
sprite.wearCostume(cos);
}
);
};
WardrobeMorph.prototype.updateList = function () {
var myself = this,
x = this.left() + 5,
y = this.top() + 5,
padding = 4,
oldFlag = Morph.prototype.trackChanges,
oldPos = this.contents.position(),
icon,
template,
txt,
paintbutton;
this.changed();
oldFlag = Morph.prototype.trackChanges;
Morph.prototype.trackChanges = false;
this.contents.destroy();
this.contents = new FrameMorph(this);
this.contents.acceptsDrops = false;
this.contents.reactToDropOf = function (icon) {
myself.reactToDropOf(icon);
};
this.addBack(this.contents);
icon = new TurtleIconMorph(this.sprite);
icon.setPosition(new Point(x, y));
myself.addContents(icon);
y = icon.bottom() + padding;
paintbutton = new PushButtonMorph(
this,
"paintNew",
new SymbolMorph("brush", 15)
);
paintbutton.padding = 0;
paintbutton.corner = 12;
paintbutton.color = IDE_Morph.prototype.groupColor;
paintbutton.highlightColor = IDE_Morph.prototype.frameColor.darker(50);
paintbutton.pressColor = paintbutton.highlightColor;
paintbutton.labelMinExtent = new Point(36, 18);
paintbutton.labelShadowOffset = new Point(-1, -1);
paintbutton.labelShadowColor = paintbutton.highlightColor;
paintbutton.labelColor = new Color(255, 255, 255);
paintbutton.contrast = this.buttonContrast;
paintbutton.drawNew();
paintbutton.hint = "Paint a new costume";
paintbutton.setPosition(new Point(x, y));
paintbutton.fixLayout();
paintbutton.setCenter(icon.center());
paintbutton.setLeft(icon.right() + padding * 4);
this.addContents(paintbutton);
txt = new TextMorph(localize(
"costumes tab help" // look up long string in translator
));
txt.fontSize = 9;
txt.setColor(new Color(230, 230, 230));
txt.setPosition(new Point(x, y));
this.addContents(txt);
y = txt.bottom() + padding;
this.sprite.costumes.asArray().forEach(function (costume) {
template = icon = new CostumeIconMorph(costume, template);
icon.setPosition(new Point(x, y));
myself.addContents(icon);
y = icon.bottom() + padding;
});
this.costumesVersion = this.sprite.costumes.lastChanged;
this.contents.setPosition(oldPos);
this.adjustScrollBars();
Morph.prototype.trackChanges = oldFlag;
this.changed();
this.updateSelection();
};
WardrobeMorph.prototype.paintNew = function() {
var cos = new Costume(newCanvas(), "Untitled"),
myself = this;
cos.edit(this.world(), null, true, null, function() {
myself.sprite.addCostume(cos);
myself.updateList();
if (myself.parentThatIsA(IDE_Morph)) {
myself.parentThatIsA(IDE_Morph).currentSprite.wearCostume(cos);
}
});
};
CostumeIconMorph.prototype.userMenu = function () {
var menu = new MenuMorph(this);
if (!(this.object instanceof Costume)) {return null; }
menu.addItem("edit", "editCostume");
if (this.world().currentKey === 16) { // shift clicked
menu.addItem(
'edit rotation point only...',
'editRotationPointOnly',
null,
new Color(100, 0, 0)
);
}
menu.addItem("rename", "renameCostume");
menu.addLine();
menu.addItem("duplicate", "duplicateCostume");
menu.addItem("delete", "removeCostume");
menu.addLine();
menu.addItem("export", "exportCostume");
return menu;
};
CostumeIconMorph.prototype.duplicateCostume = function() {
var wardrobe = this.parentThatIsA(WardrobeMorph),
ide = this.parentThatIsA(IDE_Morph),
newcos = this.object.copy(),
split = newcos.name.split(" ");
if (split[split.length - 1] === "copy") {
newcos.name += " 2";
} else if (isNaN(split[split.length - 1])) {
newcos.name = newcos.name + " copy";
} else {
split[split.length - 1] = Number(split[split.length - 1]) + 1;
newcos.name = split.join(" ");
}
wardrobe.sprite.addCostume(newcos);
wardrobe.updateList();
if (ide) {
ide.currentSprite.wearCostume(newcos);
}
};
// I had to change this because adding a "paint new" button changed the offset
// of the costume (so the 5th child would be the 3rd costume, not the 4th as
// it was before with only the text morph child).
CostumeIconMorph.prototype.removeCostume = function () {
var wardrobe = this.parentThatIsA(WardrobeMorph),
idx = this.parent.children.indexOf(this),
ide = this.parentThatIsA(IDE_Morph);
wardrobe.removeCostumeAt(idx - 2);
if (ide.currentSprite.costume === this.object) {
ide.currentSprite.wearCostume(null);
}
};
Costume.prototype.shrinkWrap = function () {
// adjust my contents' bounds to my visible bounding box
var bb = this.boundingBox(),
ext = bb.extent(),
pic = newCanvas(ext),
ctx = pic.getContext('2d');
ctx.drawImage(
this.contents,
bb.origin.x,
bb.origin.y,
ext.x,
ext.y,
0,
0,
ext.x,
ext.y
);
this.rotationCenter = this.rotationCenter.subtract(bb.origin);
this.contents = pic;
this.version = Date.now();
};