Consolidation of Paint module

This commit is contained in:
Tim Mickel 2016-01-13 18:09:02 -05:00
parent eae6c944f0
commit 93a7b66cc8
3 changed files with 966 additions and 953 deletions

View file

@ -1,3 +1,10 @@
// Originally several files (Paint.js, PaintIO.js, PaintLayout.js)
// were all contributing utility functions to the Paint object.
// To consolidate it into a single module, I've combined these below.
// A nice refactor would be to split them back into the "modules," but that will likely involve
// some serious code changes - determining where the relevant Paint.X are called, if any shared
// data needs to be moved, etc. -TM
var Paint = function () {}; var Paint = function () {};
Paint.xmlns = 'http://www.w3.org/2000/svg'; Paint.xmlns = 'http://www.w3.org/2000/svg';
@ -454,3 +461,962 @@ Paint.dragBackground = function (evt) {
Paint.cmdForGesture = [Paint.ignore, Paint.mouseDown, Paint.pinchStart, Paint.Scroll]; Paint.cmdForGesture = [Paint.ignore, Paint.mouseDown, Paint.pinchStart, Paint.Scroll];
// Originally PaintLayout.js
/////////////////////////////////
//Layout Setup
/////////////////////////////////
Paint.layout = function () {
Paint.topbar();
var div = newHTML('div', 'innerpaint', Paint.frame);
Paint.leftPalette(div);
var workspaceContainer = newHTML('div', 'workspacebkg-container', div);
var workspace = newHTML('div', 'workspacebkg', workspaceContainer);
workspace.setAttribute('id', 'workspacebkg');
Paint.rightPalette(div);
Paint.colorPalette(Paint.frame);
Paint.selectButton('path');
Paint.createSVGeditor(workspace);
};
/////////////////////////////////
//top bar
/////////////////////////////////
Paint.topbar = function () {
var pt = newHTML('div', 'paintop', Paint.frame);
Paint.checkMark(pt);
PaintUndo.setup(pt); // plug here the undo
Paint.nameOfcostume(pt);
};
Paint.checkMark = function (pt) {
var clicky = newHTML('div', 'paintdone', pt);
clicky.id = 'donecheck';
if (isTablet) {
clicky.ontouchstart = Paint.backToProject;
} else {
clicky.onmousedown = Paint.backToProject;
}
};
Paint.nameOfcostume = function (p) {
var sform = newHTML('form', 'spriteform', p);
sform.name = 'spriteform';
var ti = newHTML('input', undefined, sform);
ti.onkeypress = undefined;
ti.autocomplete = 'off';
ti.autocorrect = false;
ti.name = 'name';
ti.maxLength = 25;
ti.firstTime = true;
ti.onfocus = Paint.nameFocus;
ti.onblur = Paint.nameBlur;
ti.onkeypress = Paint.handleNamePress;
ti.onkeyup = Paint.handleKeyRelease;
sform.onsubmit = Paint.submitNameChange;
};
Paint.submitNameChange = function (e) {
e.preventDefault();
var input = e.target;
input.blur();
};
Paint.nameFocus = function (e) {
e.preventDefault();
e.stopPropagation();
var ti = e.target;
ti.firstTime = true;
ScratchJr.activeFocus = ti;
if (isAndroid) {
AndroidInterface.scratchjr_setsoftkeyboardscrolllocation(
ti.getBoundingClientRect().top * window.devicePixelRatio,
ti.getBoundingClientRect().bottom * window.devicePixelRatio
);
}
Undo.aux = Project.getProject(ScratchJr.stage.currentPage.id);
setTimeout(function () {
ti.setSelectionRange(ti.value.length, ti.value.length);
}, 1);
};
Paint.nameBlur = function (e) {
ScratchJr.activeFocus = undefined;
var spr = ScratchJr.getSprite();
var ti = e.target;
var val = ScratchJr.validate(ti.value, spr.name);
ti.value = val.substring(0, ti.maxLength);
ScratchJr.storyStart('Paint.nameBlur');
};
Paint.handleNamePress = function (e) {
var key = e.keyCode || e.which;
if (key == 13) {
Paint.submitNameChange(e);
} else {
var ti = e.target;
if (ti.firstTime) {
ti.firstTime = false;
ti.value = '';
}
if (ti.value.length == 25) {
ScratchAudio.sndFX('boing.wav');
}
}
};
Paint.handleKeyRelease = function (e) {
var key = e.keyCode || e.which;
var ti = e.target;
if (key != 8) {
return;
}
if (ti.firstTime) {
ti.firstTime = false;
ti.value = '';
}
};
/////////////////////////////////
//Left Palette
/////////////////////////////////
Paint.leftPalette = function (div) {
var leftpal = newHTML('div', 'side up', div);
var pal = newHTML('div', 'paintpalette', leftpal);
pal.setAttribute('id', 'paintpalette');
Paint.setupEditPalette(pal);
Paint.createSizeSelector(pal);
};
Paint.setupEditPalette = function (pal) {
var section = newHTML('div', 'section', pal);
section.setAttribute('id', 'painttools');
var list = ['path', 'ellipse', 'rect', 'tri'];
var i = 0;
for (i = 0; i < list.length; i++) {
var but = newHTML('div', 'element off', section);
var icon = newHTML('div', 'tool ' + list[i] + ' off', but);
icon.setAttribute('key', list[i]);
if (isTablet) {
icon.ontouchstart = Paint.setMode;
} else {
icon.onmousedown = Paint.setMode;
}
}
};
Paint.createSizeSelector = function (pal) {
var section = newHTML('div', 'section space', pal);
section.setAttribute('id', 'sizeSelector');
for (var i = 0; i < Paint.pensizes.length; i++) {
var ps = newHTML('div', 'pensizeholder', section);
ps.key = i;
ps.ontouchstart = function (e) {
e.preventDefault();
e.stopPropagation();
var n = Number(this.key);
Paint.strokewidth = Paint.pensizes[Number(this.key)];
Paint.selectPenSize(n);
};
var c = newHTML('div', 'line t' + i, ps);
Paint.drawPenSizeInColor(c);
}
Paint.strokewidth = Paint.pensizes[1];
Paint.selectPenSize(1);
};
////////////////////////////////////////
// Pen sizes
////////////////////////////////////////
Paint.drawPenSizeInColor = function (c) {
c.style.background = Paint.fillcolor;
};
Paint.updateStrokes = function () {
var div = gn('sizeSelector');
if (!div) {
return;
}
for (var i = 0; i < div.childElementCount; i++) {
var elem = div.childNodes[i];
Paint.drawPenSizeInColor(elem.childNodes[0]);
}
};
Paint.selectPenSize = function (str) {
var p = gn('sizeSelector');
for (var i = 0; i < p.childElementCount; i++) {
var elem = p.childNodes[i];
if (elem.key == str) {
elem.setAttribute('class', 'pensizeholder on');
} else {
elem.setAttribute('class', 'pensizeholder off');
}
}
};
/////////////////////////////////
//Right Palette
/////////////////////////////////
Paint.rightPalette = function (div) {
var rightpal = newHTML('div', 'side', div);
Paint.addSidePalette(rightpal, 'selectortools', ['select', 'rotate']);
Paint.addSidePalette(rightpal, 'edittools', ['stamper', 'scissors']);
Paint.addSidePalette(rightpal, 'filltools',
(iOS.camera == '1' && Camera.available) ? ['camera', 'paintbucket'] : ['paintbucket']);
};
Paint.addSidePalette = function (p, id, list) {
var pal = newHTML('div', 'paintpalette short', p);
pal.setAttribute('id', id);
for (var i = 0; i < list.length; i++) {
var but = newHTML('div', 'element off', pal);
var icon = newHTML('div', 'tool ' + list[i] + ' off', but);
icon.setAttribute('key', list[i]);
icon.ontouchstart = Paint.setMode;
}
};
Paint.cameraToolsOn = function () {
gn('backdrop').setAttribute('class', 'modal-backdrop fade dark');
setProps(gn('backdrop').style, {
display: 'block'
});
var topbar = newHTML('div', 'phototopbar', gn('backdrop'));
topbar.setAttribute('id', 'photocontrols');
// var actions = newHTML("div",'actions', topbar);
// var buttons = newHTML('div', 'photobuttons', actions);
var fc = newHTML('div', 'flipcamera', topbar);
fc.setAttribute('id', 'cameraflip');
fc.setAttribute('key', 'cameraflip');
if (isAndroid && !AndroidInterface.scratchjr_has_multiple_cameras()) {
fc.style.display = 'none';
}
fc.ontouchstart = Paint.setMode;
var captureContainer = newHTML('div', 'snapshot-container', gn('backdrop'));
captureContainer.setAttribute('id', 'capture-container');
var capture = newHTML('div', 'snapshot', captureContainer);
capture.setAttribute('id', 'capture');
capture.setAttribute('key', 'camerasnap');
capture.ontouchstart = Paint.setMode;
var cc = newHTML('div', 'cameraclose', topbar);
cc.setAttribute('id', 'cameraclose');
cc.ontouchstart = Paint.closeCameraMode;
};
Paint.closeCameraMode = function () {
ScratchAudio.sndFX('exittap.wav');
Camera.close();
Paint.selectButton('select');
};
Paint.cameraToolsOff = function () {
gn('backdrop').setAttribute('class', 'modal-backdrop fade');
setProps(gn('backdrop').style, {
display: 'none'
});
if (gn('photocontrols')) {
gn('photocontrols').parentNode.removeChild(gn('photocontrols'));
}
if (gn('capture')) {
var captureContainer = gn('capture').parentNode;
var captureContainerParent = captureContainer.parentNode;
captureContainer.removeChild(gn('capture'));
captureContainerParent.removeChild(gn('capture-container'));
}
};
//////////////////////////////////
// canvas Area
//////////////////////////////////
Paint.setUpCanvasArea = function () {
var workspace = gn('workspacebkg');
var dx = Math.floor((workspace.offsetWidth - Paint.workspaceWidth) / 2);
var dy = Math.floor((workspace.offsetHeight - Paint.workspaceHeight) / 2);
var w = Paint.workspaceWidth;
var h = Paint.workspaceHeight;
var div = gn('maincanvas');
div.style.background = '#F5F2F7';
div.style.top = '0px';
div.style.left = '0px';
div.style.width = w + 'px';
div.style.height = h + 'px';
div.cx = div.offsetWidth / 2;
div.cy = div.offsetHeight / 2;
div.dx = dx;
div.dy = dy;
Paint.root.setAttributeNS(null, 'width', w);
Paint.root.setAttributeNS(null, 'height', h);
Paint.drawGrid(w, h);
PaintAction.clearEvents();
};
/////////////////////////////////
//Color Palette
/////////////////////////////////
Paint.colorPalette = function (div) {
var swatchlist = Paint.initSwatchList();
var spalContainer = newHTML('div', 'swatchpalette-container', div);
var spal = newHTML('div', 'swatchpalette', spalContainer);
spal.setAttribute('id', 'swatches');
for (var i = 0; i < swatchlist.length; i++) {
var colour = newHTML('div', 'swatchbucket', spal);
// bucket
var sf = newHTML('div', 'swatchframe', colour);
var sc = newHTML('div', 'swatchcolor', sf);
sc.style.background = swatchlist[i];
//
sf = newHTML('div', 'splasharea off', colour);
Paint.setSplashColor(sf, Paint.splash, swatchlist[i]);
Paint.addImageUrl(sf, Paint.splashshade);
colour.ontouchstart = Paint.selectSwatch;
}
Paint.setSwatchColor(gn('swatches').childNodes[swatchlist.indexOf('#1C1C1C')]);
};
Paint.setSplashColor = function (p, str, color) {
var dataurl = 'data:image/svg+xml;base64,' + btoa(str.replace(/#662D91/g, color));
Paint.addImageUrl(p, dataurl);
};
Paint.addImageUrl = function (p, url) {
var img = document.createElement('img');
img.src = url;
img.style.position = 'absolute';
p.appendChild(img);
};
Paint.selectSwatch = function (e) {
if (e.touches && (e.touches.length > 1)) {
return;
}
e.preventDefault();
e.stopPropagation();
if (Camera.active) {
return;
}
var t;
if (window.event) {
t = window.event.srcElement;
} else {
t = e.target;
}
var b = 'swatchbucket' != t.className;
while (b) {
t = t.parentNode;
b = t && ('swatchbucket' != t.className);
}
if (!t) {
return;
}
ScratchAudio.sndFX('splash.wav');
Paint.setSwatchColor(t);
};
Paint.setSwatchColor = function (t) {
var tools = ['select', 'wand', 'stamper', 'scissors', 'rotate'];
if (t && (tools.indexOf(Paint.mode) > -1)) {
Paint.selectButton('paintbucket');
}
var c = t.childNodes[0].childNodes[0].style.backgroundColor;
for (var i = 0; i < gn('swatches').childElementCount; i++) {
var mycolor = gn('swatches').childNodes[i].childNodes[0].childNodes[0].style.backgroundColor;
if (c == mycolor) {
gn('swatches').childNodes[i].childNodes[1].setAttribute('class', 'splasharea on');
} else {
gn('swatches').childNodes[i].childNodes[1].setAttribute('class', 'splasharea off');
}
}
Paint.fillcolor = c;
Path.quitEditMode();
Paint.updateStrokes();
};
Paint.initSwatchList = function () {
return [
// "#FF5500", // new orange
'#FFD2F2', '#FF99D6', '#FF4583', // red pinks
'#C30001', '#FF0023', '#FF8300', '#FFB200',
'#FFF42E',
'#FFF9C2', // pale yellow
'#E2FFBD', // pale green
'#CFF500', // lime green
'#50D823', // problematic
// "#2BFC49", // less problematic
'#29C130',
// "#56C43B", // ERROR?
'#2BBF8A', // new green
'#027607', '#114D24', //greens
'#FFFFFF', '#CCDDE7', '#61787C', '#1C1C1C', // grays
'#D830A3', // sarah's pink shoes border
'#FF64E9', // purple pinks
'#D999FF', ' #A159D3', // vilote
'#722696', // sarah's violet
'#141463', '#003399', '#1D40ED',
'#0079D3', '#009EFF', '#76C8FF',
'#ACE0FD', '#11B7BC', '#21F9F3', '#C3FCFC', '#54311E',
'#8E572A', '#E4B69D', '#FFCDA4', '#FFEDD7' // skin colors
];
};
/////////////////////////////////////////////////
// Setup SVG Editor
////////////////////////////////////////////////
Paint.createSVGeditor = function (container) {
var div = newHTML('div', 'maincanvas', container);
div.setAttribute('id', 'maincanvas');
div.style.background = '#F5F2F7';
div.style.top = '0px';
div.style.left = '0px';
window.onmousemove = undefined;
window.onmouseup = undefined;
Paint.root = SVGTools.create(div);
Paint.root.setAttribute('class', 'active3d');
xform = Transform.getTranslateTransform();
selxform = Transform.getTranslateTransform();
var layer = SVGTools.createGroup(Paint.root, 'layer1');
layer.setAttribute('style', 'pointer-events:visiblePainted');
SVGTools.createGroup(Paint.root, 'draglayer');
SVGTools.createGroup(Paint.root, 'paintgrid');
gn('paintgrid').setAttribute('opacity', 0.5);
};
Paint.clearWorkspace = function () {
var fcn = function (div) {
while (div.childElementCount > 0) {
div.removeChild(div.childNodes[0]);
}
};
fcn(gn('layer1'));
fcn(gn('paintgrid'));
fcn(gn('draglayer'));
Path.quitEditMode();
};
Paint.drawGrid = function (w, h) {
var attr, path;
if (!Paint.isBkg) {
attr = {
'd': Paint.getGridPath(w, h, 12),
'id': getIdFor('gridpath'),
'opacity': 1,
'stroke': '#dcddde',
'fill': 'none',
'stroke-width': 0.5
};
path = SVGTools.addChild(gn('paintgrid'), 'path', attr);
path.setAttribute('style', 'pointer-events:none;');
}
attr = {
'd': Paint.getGridPath(w, h, Paint.isBkg ? 24 : 48),
'id': getIdFor('gridpath'),
'opacity': 1,
'stroke': '#c1c2c3',
'fill': 'none',
'stroke-width': 0.5
};
path = SVGTools.addChild(gn('paintgrid'), 'path', attr);
path.setAttribute('style', 'pointer-events:none;');
};
Paint.getGridPath = function (w, h, gridsize) {
var str = '';
var dx = gridsize;
// vertical
var cmd;
for (var i = 0; i < w / gridsize; i++) {
cmd = 'M' + dx + ',' + 0 + 'L' + dx + ',' + h;
str += cmd;
dx += gridsize;
}
var dy = gridsize;
// horizontal
for (i = 0; i < h / gridsize; i++) {
cmd = 'M' + 0 + ',' + dy + 'L' + w + ',' + dy;
str += cmd;
dy += gridsize;
}
return str;
};
// Originally PaintIO.js
///////////////////////////
// Loading and saving
//////////////////////////
Paint.initBkg = function (ow, oh) {
Paint.nativeJr = true;
Paint.workspaceWidth = ow;
Paint.workspaceHeight = oh;
Paint.setUpCanvasArea();
var dh = Paint.root.parentNode.parentNode.offsetHeight / (Paint.workspaceHeight + 10);
var dw = Paint.root.parentNode.parentNode.offsetWidth / (Paint.workspaceWidth + 10);
Paint.setZoomTo(Math.min(dw, dh));
document.forms.spriteform.style.visibility = 'hidden';
if (Paint.currentMd5) {
Paint.loadBackground(Paint.currentMd5);
} else {
var attr = {
'id': 'staticbkg',
'opacity': 1,
'fixed': 'yes',
fill: ScratchJr.stagecolor
};
var cmds = [['M', 0, 0], ['L', 480, 0], ['L', 480, 360], ['L', 0, 360], ['L', 0, 0]];
attr.d = SVG2Canvas.arrayToString(cmds);
SVGTools.addChild(gn('layer1'), 'path', attr);
Ghost.drawOffscreen();
PaintUndo.record(true);
}
};
Paint.loadBackground = function (md5) {
if (md5.indexOf('samples/') >= 0) {
// Load sample asset
Paint.loadChar(md5);
} else if (!MediaLib.keys[md5]) {
// Load user asset
iOS.getmedia(md5, nextStep);
} else {
// Load library asset
Paint.getBkg(MediaLib.path + md5);
}
function nextStep (base64) {
var str = atob(base64);
IO.getImagesInSVG(str, function () {
Paint.loadBkg(str);
});
}
};
Paint.getBkg = function (url) {
var xmlrequest = new XMLHttpRequest();
xmlrequest.onreadystatechange = function () {
if (xmlrequest.readyState == 4) {
Paint.createBkgFromXML(xmlrequest.responseText);
}
};
xmlrequest.open('GET', url, true);
xmlrequest.send(null);
};
Paint.loadBkg = function (str) {
Paint.createBkgFromXML(str);
};
Paint.createBkgFromXML = function (str) {
Paint.nativeJr = str.indexOf('Scratch Jr') > -1;
str = str.replace(/>\s*</g, '><');
var xmlDoc = new DOMParser().parseFromString(str, 'text/xml');
var extxml = document.importNode(xmlDoc.documentElement, true);
var flat = Paint.skipUnwantedElements(extxml, []);
for (var i = 0; i < flat.length; i++) {
gn('layer1').appendChild(flat[i]);
if (flat[i].getAttribute('id') == 'fixed') {
flat[i].setAttribute('fixed', 'yes');
}
flat[i].setAttribute('file', 'yes');
}
Paint.doAbsolute(gn('layer1'));
if (!Paint.nativeJr) {
Paint.reassingIds(gn('layer1'));
} // make sure there are unique mask names
// gn("layer1").childNodes[0].setAttribute('id', "staticbkg");
var dh = Paint.root.parentNode.parentNode.offsetHeight / (Paint.workspaceHeight + 10);
var dw = Paint.root.parentNode.parentNode.offsetWidth / (Paint.workspaceWidth + 10);
Paint.setZoomTo(Math.min(dw, dh));
PaintUndo.record(true);
if (!Paint.nativeJr) {
Paint.selectButton('paintbucket');
}
};
Paint.initSprite = function (ow, oh) {
Paint.nativeJr = true;
document.forms.spriteform.style.visibility = 'visible';
document.forms.spriteform.name.value = gn(Paint.currentName) ? gn(Paint.currentName).owner.name : Paint.currentName;
if (ow) {
Paint.workspaceWidth = ow;
}
if (oh) {
Paint.workspaceHeight = oh;
}
if (Paint.currentMd5) {
Paint.loadCharacter(Paint.currentMd5);
} else {
Paint.setUpCanvasArea();
setCanvasSize(
Ghost.maskCanvas,
Math.round(Number(Paint.root.getAttribute('width')) * Paint.currentZoom),
Math.round(Number(Paint.root.getAttribute('height')) * Paint.currentZoom)
);
var dh = Paint.root.parentNode.parentNode.offsetHeight / (Paint.workspaceHeight + 10);
var dw = Paint.root.parentNode.parentNode.offsetWidth / (Paint.workspaceWidth + 10);
Paint.setZoomTo(Math.min(dw, dh));
PaintUndo.record(true);
}
};
Paint.loadCharacter = function (md5) {
if (md5.indexOf('samples/') >= 0) {
// Load sample asset
Paint.loadChar(md5);
} else if (!MediaLib.keys[md5]) {
// Load user asset
iOS.getmedia(md5, nextStep);
} else {
// Load library asset
Paint.loadChar(MediaLib.path + md5);
}
function nextStep (base64) {
var str = atob(base64);
IO.getImagesInSVG(str, function () {
Paint.loadSprite(str);
});
}
};
Paint.loadSprite = function (svg) {
Paint.createCharFromXML(svg, Paint.currentName);
};
Paint.loadChar = function (url) {
var xmlrequest = new XMLHttpRequest();
xmlrequest.onreadystatechange = function () {
if (xmlrequest.readyState == 4) {
Paint.createCharFromXML(xmlrequest.responseText, Paint.currentName);
}
};
xmlrequest.open('GET', url, true);
xmlrequest.send(null);
};
Paint.adjustShapePosition = function (dx, dy) {
xform.setTranslate(dx, dy);
Transform.translateTo(gn('layer1'), xform);
};
///////////////////////////////////
// Saving
/////////////////////////////////
Paint.savePageImage = function (fcn) {
var worthsaving = (gn('layer1').childElementCount > 0);
if (!worthsaving) {
Paint.close();
} else {
Paint.saving = true;
if (fcn) {
Alert.open(Paint.frame, gn('donecheck'), Localization.localize('ALERT_SAVING'), '#28A5DA');
Alert.balloon.style.zIndex = 12000;
}
Paint.svgdata = SVGTools.saveBackground(gn('layer1'), Paint.workspaceWidth, Paint.workspaceHeight);
IO.setMedia(Paint.svgdata, 'svg', function (str) {
Paint.changeBackground(str, fcn);
});
}
};
Paint.changeBackground = function (md5, fcn) {
Paint.saveMD5 = md5;
var type = 'userbkgs';
var mobj = {};
mobj.cond = 'md5 = ? AND version = ?';
mobj.items = ['*'];
mobj.values = [Paint.saveMD5, ScratchJr.version];
IO.query(type, mobj, function (str) {
Paint.checkDuplicateBkg(str, fcn);
});
};
Paint.checkDuplicateBkg = function (str, fcn) {
var list = JSON.parse(str);
if (list.length > 0) {
if (fcn) {
fcn('duplicate');
}
} else {
Paint.addToBkgLib(fcn);
}
};
/////////////////////////////////////
// userbkgs: stores backgrounds
/////////////////////////////////////
/*
[version] =>
[md5] =>
[altmd5] => //for PNG option
[ext] => png / svg
[width] =>
[height] =>
*/
Paint.addToBkgLib = function (fcn) {
var dataurl = IO.getThumbnail(Paint.svgdata, 480, 360, 120, 90);
var pngBase64 = dataurl.split(',')[1];
iOS.setmedia(pngBase64, 'png', setBkgRecord);
function setBkgRecord (pngmd5) {
var json = {};
var keylist = ['md5', 'altmd5', 'version', 'width', 'height', 'ext'];
var values = '?,?,?,?,?,?';
json.values = [Paint.saveMD5, pngmd5, ScratchJr.version, '480', '360', 'svg'];
json.stmt = 'insert into userbkgs (' + keylist.toString() + ') values (' + values + ')';
iOS.stmt(json, fcn);
}
};
Paint.changePage = function () {
ScratchJr.stage.currentPage.setBackground(Paint.saveMD5, ScratchJr.stage.currentPage.updateBkg);
Paint.close();
};
Paint.saveSprite = function (fcn) {
var cname = document.forms.spriteform.name.value;
var worthsaving = (gn('layer1').childElementCount > 0) && (PaintUndo.index > 0);
if (worthsaving) {
Paint.saving = true;
if (fcn) {
Alert.open(Paint.frame, gn('donecheck'), 'Saving...', '#28A5DA');
Alert.balloon.style.zIndex = 12000;
}
Paint.svgdata = SVGTools.saveShape(gn('layer1'), Paint.workspaceWidth, Paint.workspaceHeight);
IO.setMedia(Paint.svgdata, 'svg', function (str) {
Paint.addOrModifySprite(str, fcn);
});
} else {
var type = Paint.getLoadType(Paint.spriteId, cname);
if ((cname != Paint.currentName) && (type == 'modify')) {
ScratchJr.stage.currentPage.modifySpriteName(cname, Paint.spriteId);
} else if (Paint.currentMd5 && (type == 'add')) {
ScratchJr.stage.currentPage.addSprite(Paint.costumeScale, Paint.currentMd5, cname);
}
Paint.close();
}
};
Paint.addOrModifySprite = function (str, fcn) {
Paint.saveMD5 = str;
var mobj = {};
mobj.cond = 'md5 = ? AND version = ?';
mobj.items = ['*'];
mobj.values = [Paint.saveMD5, ScratchJr.version];
IO.query('usershapes', mobj, function (str) {
Paint.checkDuplicate(str, fcn);
});
};
Paint.checkDuplicate = function (str, fcn) {
var list = JSON.parse(str);
if (list.length > 0) {
if (fcn) {
fcn('duplicate');
}
} else {
Paint.addToLib(fcn);
}
};
/////////////////////////////////////
// usershapes: stores costumes
/////////////////////////////////////
/* current data
[md5] =>
[altmd5] => // for PNG -- not used
[version] =>
[scale] =>
[ext] => png / svg
[width] =>
[height] =>
[name] =>
*/
Paint.addToLib = function (fcn) {
var scale = '0.5'; // always saves with 1/2 the size
var cname = document.forms.spriteform.name.value;
cname = ((unescape(cname)).replace(/[0-9]/g, '')).replace(/\s*/g, '');
var box = SVGTools.getBox(gn('layer1')).rounded();
box = box.expandBy(20);
var w = box.width.toString();
var h = box.height.toString();
var dataurl = IO.getThumbnail(Paint.svgdata, w, h, 120, 90);
var pngBase64 = dataurl.split(',')[1];
iOS.setmedia(pngBase64, 'png', setCostumeRecord);
function setCostumeRecord (pngmd5) {
var json = {};
var keylist = ['scale', 'md5', 'altmd5', 'version', 'width', 'height', 'ext', 'name'];
var values = '?,?,?,?,?,?,?,?';
json.values = [scale, Paint.saveMD5, pngmd5, ScratchJr.version, w, h, 'svg', cname];
json.stmt = 'insert into usershapes (' + keylist.toString() + ') values (' + values + ')';
iOS.stmt(json, fcn);
}
};
Paint.changePageSprite = function () {
Paint.close();
var cname = document.forms.spriteform.name.value;
var type = Paint.getLoadType(Paint.spriteId, cname);
switch (type) {
case 'modify':
ScratchJr.stage.currentPage.modifySprite(Paint.saveMD5, cname, Paint.spriteId);
break;
case 'add':
ScratchJr.stage.currentPage.addSprite(Paint.costumeScale, Paint.saveMD5, cname);
break;
default:
ScratchJr.stage.currentPage.update();
break;
}
};
Paint.getLoadType = function (sid, cid) {
if (!cid) {
return 'none';
}
if (sid && cid) {
return 'modify';
}
return 'add';
};
///////////////////////////
// XML import processs
///////////////////////////
Paint.skipUnwantedElements = function (p, res) {
for (var i = 0; i < p.childNodes.length; i++) {
var elem = p.childNodes[i];
if (elem.nodeName == 'metadata') {
continue;
}
if (elem.nodeName == 'defs') {
continue;
}
if (elem.nodeName == 'sodipodi:namedview') {
continue;
}
if (elem.nodeName == '#comment') {
continue;
}
if ((elem.nodeName == 'g') && (elem.id == 'layer1')) {
Paint.skipUnwantedElements(elem, res);
if (elem.removeAttribute('id')) {
elem.removeAttribute('id');
}
} else {
res.push(elem);
}
}
return res;
};
Paint.reassingIds = function (p) {
for (var i = 0; i < p.childNodes.length; i++) {
var elem = p.childNodes[i];
if (elem.parentNode.getAttribute('fixed') == 'yes') {
elem.setAttribute('fixed', 'yes');
}
var id = elem.getAttribute('id');
if (!id) {
elem.setAttribute('id', getIdFor(elem.nodeName));
}
if (elem.nodeName == 'g') {
Paint.reassingIds(elem);
}
}
};
Paint.createCharFromXML = function (str) {
Paint.nativeJr = str.indexOf('Scratch Jr') > -1;
var dx = (Paint.workspaceWidth < 432) ? Math.floor((432 - Paint.workspaceWidth) / 2) : 0;
var dy = (Paint.workspaceHeight < 384) ? Math.floor((384 - Paint.workspaceHeight) / 2) : 0;
if (Paint.workspaceWidth < 432) {
Paint.workspaceWidth = 432;
}
if (Paint.workspaceHeight < 384) {
Paint.workspaceHeight = 384;
}
Paint.setUpCanvasArea();
str = str.replace(/>\s*</g, '><');
var xmlDoc = new DOMParser().parseFromString(str, 'text/xml');
var extxml = document.importNode(xmlDoc.documentElement, true);
var flat = Paint.skipUnwantedElements(extxml, []);
for (var i = 0; i < flat.length; i++) {
gn('layer1').appendChild(flat[i]);
}
Paint.doAbsolute(gn('layer1'));
Paint.adjustShapePosition(dx, dy);
if (!Paint.nativeJr) {
Paint.reassingIds(gn('layer1'));
} // make sure there are unique mask names
Paint.scaleToFit();
Paint.minZoom = Paint.currentZoom < 1 ? Paint.currentZoom / 2 : 1;
var maxpix = 2290 * 2289; // Magic iOS max canvas size
var ratio = maxpix / (Paint.workspaceWidth * Paint.workspaceHeight);
var zoom = Math.floor(Math.sqrt(ratio));
if (zoom < Paint.maxZoom) {
Paint.maxZoom = zoom;
}
PaintUndo.record(true);
if (!Paint.nativeJr) {
Paint.selectButton('paintbucket');
}
};
Paint.doAbsolute = function (div) {
for (var i = 0; i < div.childElementCount; i++) {
var elem = div.childNodes[i];
if (elem.tagName == 'path') {
SVG2Canvas.setAbsolutePath(elem);
}
if (elem.tagName == 'g') {
Paint.doAbsolute(div.childNodes[i]);
}
}
};
Paint.getComponents = function (p, res) {
for (var i = 0; i < p.childNodes.length; i++) {
var elem = p.childNodes[i];
if (elem.nodeName == 'metadata') {
continue;
}
if (elem.nodeName == 'defs') {
continue;
}
if (elem.nodeName == 'sodipodi:namedview') {
continue;
}
if (elem.nodeName == '#comment') {
continue;
}
if (elem.nodeName == 'g') {
Paint.getComponents(elem, res);
if (elem.getAttribute('id')) {
elem.removeAttribute('id');
}
} else {
res.push(elem);
}
}
return res;
};

View file

@ -1,462 +0,0 @@
///////////////////////////
// Loading and saving
//////////////////////////
Paint.initBkg = function (ow, oh) {
Paint.nativeJr = true;
Paint.workspaceWidth = ow;
Paint.workspaceHeight = oh;
Paint.setUpCanvasArea();
var dh = Paint.root.parentNode.parentNode.offsetHeight / (Paint.workspaceHeight + 10);
var dw = Paint.root.parentNode.parentNode.offsetWidth / (Paint.workspaceWidth + 10);
Paint.setZoomTo(Math.min(dw, dh));
document.forms.spriteform.style.visibility = 'hidden';
if (Paint.currentMd5) {
Paint.loadBackground(Paint.currentMd5);
} else {
var attr = {
'id': 'staticbkg',
'opacity': 1,
'fixed': 'yes',
fill: ScratchJr.stagecolor
};
var cmds = [['M', 0, 0], ['L', 480, 0], ['L', 480, 360], ['L', 0, 360], ['L', 0, 0]];
attr.d = SVG2Canvas.arrayToString(cmds);
SVGTools.addChild(gn('layer1'), 'path', attr);
Ghost.drawOffscreen();
PaintUndo.record(true);
}
};
Paint.loadBackground = function (md5) {
if (md5.indexOf('samples/') >= 0) {
// Load sample asset
Paint.loadChar(md5);
} else if (!MediaLib.keys[md5]) {
// Load user asset
iOS.getmedia(md5, nextStep);
} else {
// Load library asset
Paint.getBkg(MediaLib.path + md5);
}
function nextStep (base64) {
var str = atob(base64);
IO.getImagesInSVG(str, function () {
Paint.loadBkg(str);
});
}
};
Paint.getBkg = function (url) {
var xmlrequest = new XMLHttpRequest();
xmlrequest.onreadystatechange = function () {
if (xmlrequest.readyState == 4) {
Paint.createBkgFromXML(xmlrequest.responseText);
}
};
xmlrequest.open('GET', url, true);
xmlrequest.send(null);
};
Paint.loadBkg = function (str) {
Paint.createBkgFromXML(str);
};
Paint.createBkgFromXML = function (str) {
Paint.nativeJr = str.indexOf('Scratch Jr') > -1;
str = str.replace(/>\s*</g, '><');
var xmlDoc = new DOMParser().parseFromString(str, 'text/xml');
var extxml = document.importNode(xmlDoc.documentElement, true);
var flat = Paint.skipUnwantedElements(extxml, []);
for (var i = 0; i < flat.length; i++) {
gn('layer1').appendChild(flat[i]);
if (flat[i].getAttribute('id') == 'fixed') {
flat[i].setAttribute('fixed', 'yes');
}
flat[i].setAttribute('file', 'yes');
}
Paint.doAbsolute(gn('layer1'));
if (!Paint.nativeJr) {
Paint.reassingIds(gn('layer1'));
} // make sure there are unique mask names
// gn("layer1").childNodes[0].setAttribute('id', "staticbkg");
var dh = Paint.root.parentNode.parentNode.offsetHeight / (Paint.workspaceHeight + 10);
var dw = Paint.root.parentNode.parentNode.offsetWidth / (Paint.workspaceWidth + 10);
Paint.setZoomTo(Math.min(dw, dh));
PaintUndo.record(true);
if (!Paint.nativeJr) {
Paint.selectButton('paintbucket');
}
};
Paint.initSprite = function (ow, oh) {
Paint.nativeJr = true;
document.forms.spriteform.style.visibility = 'visible';
document.forms.spriteform.name.value = gn(Paint.currentName) ? gn(Paint.currentName).owner.name : Paint.currentName;
if (ow) {
Paint.workspaceWidth = ow;
}
if (oh) {
Paint.workspaceHeight = oh;
}
if (Paint.currentMd5) {
Paint.loadCharacter(Paint.currentMd5);
} else {
Paint.setUpCanvasArea();
setCanvasSize(
Ghost.maskCanvas,
Math.round(Number(Paint.root.getAttribute('width')) * Paint.currentZoom),
Math.round(Number(Paint.root.getAttribute('height')) * Paint.currentZoom)
);
var dh = Paint.root.parentNode.parentNode.offsetHeight / (Paint.workspaceHeight + 10);
var dw = Paint.root.parentNode.parentNode.offsetWidth / (Paint.workspaceWidth + 10);
Paint.setZoomTo(Math.min(dw, dh));
PaintUndo.record(true);
}
};
Paint.loadCharacter = function (md5) {
if (md5.indexOf('samples/') >= 0) {
// Load sample asset
Paint.loadChar(md5);
} else if (!MediaLib.keys[md5]) {
// Load user asset
iOS.getmedia(md5, nextStep);
} else {
// Load library asset
Paint.loadChar(MediaLib.path + md5);
}
function nextStep (base64) {
var str = atob(base64);
IO.getImagesInSVG(str, function () {
Paint.loadSprite(str);
});
}
};
Paint.loadSprite = function (svg) {
Paint.createCharFromXML(svg, Paint.currentName);
};
Paint.loadChar = function (url) {
var xmlrequest = new XMLHttpRequest();
xmlrequest.onreadystatechange = function () {
if (xmlrequest.readyState == 4) {
Paint.createCharFromXML(xmlrequest.responseText, Paint.currentName);
}
};
xmlrequest.open('GET', url, true);
xmlrequest.send(null);
};
Paint.adjustShapePosition = function (dx, dy) {
xform.setTranslate(dx, dy);
Transform.translateTo(gn('layer1'), xform);
};
///////////////////////////////////
// Saving
/////////////////////////////////
Paint.savePageImage = function (fcn) {
var worthsaving = (gn('layer1').childElementCount > 0);
if (!worthsaving) {
Paint.close();
} else {
Paint.saving = true;
if (fcn) {
Alert.open(Paint.frame, gn('donecheck'), Localization.localize('ALERT_SAVING'), '#28A5DA');
Alert.balloon.style.zIndex = 12000;
}
Paint.svgdata = SVGTools.saveBackground(gn('layer1'), Paint.workspaceWidth, Paint.workspaceHeight);
IO.setMedia(Paint.svgdata, 'svg', function (str) {
Paint.changeBackground(str, fcn);
});
}
};
Paint.changeBackground = function (md5, fcn) {
Paint.saveMD5 = md5;
var type = 'userbkgs';
var mobj = {};
mobj.cond = 'md5 = ? AND version = ?';
mobj.items = ['*'];
mobj.values = [Paint.saveMD5, ScratchJr.version];
IO.query(type, mobj, function (str) {
Paint.checkDuplicateBkg(str, fcn);
});
};
Paint.checkDuplicateBkg = function (str, fcn) {
var list = JSON.parse(str);
if (list.length > 0) {
if (fcn) {
fcn('duplicate');
}
} else {
Paint.addToBkgLib(fcn);
}
};
/////////////////////////////////////
// userbkgs: stores backgrounds
/////////////////////////////////////
/*
[version] =>
[md5] =>
[altmd5] => //for PNG option
[ext] => png / svg
[width] =>
[height] =>
*/
Paint.addToBkgLib = function (fcn) {
var dataurl = IO.getThumbnail(Paint.svgdata, 480, 360, 120, 90);
var pngBase64 = dataurl.split(',')[1];
iOS.setmedia(pngBase64, 'png', setBkgRecord);
function setBkgRecord (pngmd5) {
var json = {};
var keylist = ['md5', 'altmd5', 'version', 'width', 'height', 'ext'];
var values = '?,?,?,?,?,?';
json.values = [Paint.saveMD5, pngmd5, ScratchJr.version, '480', '360', 'svg'];
json.stmt = 'insert into userbkgs (' + keylist.toString() + ') values (' + values + ')';
iOS.stmt(json, fcn);
}
};
Paint.changePage = function () {
ScratchJr.stage.currentPage.setBackground(Paint.saveMD5, ScratchJr.stage.currentPage.updateBkg);
Paint.close();
};
Paint.saveSprite = function (fcn) {
var cname = document.forms.spriteform.name.value;
var worthsaving = (gn('layer1').childElementCount > 0) && (PaintUndo.index > 0);
if (worthsaving) {
Paint.saving = true;
if (fcn) {
Alert.open(Paint.frame, gn('donecheck'), 'Saving...', '#28A5DA');
Alert.balloon.style.zIndex = 12000;
}
Paint.svgdata = SVGTools.saveShape(gn('layer1'), Paint.workspaceWidth, Paint.workspaceHeight);
IO.setMedia(Paint.svgdata, 'svg', function (str) {
Paint.addOrModifySprite(str, fcn);
});
} else {
var type = Paint.getLoadType(Paint.spriteId, cname);
if ((cname != Paint.currentName) && (type == 'modify')) {
ScratchJr.stage.currentPage.modifySpriteName(cname, Paint.spriteId);
} else if (Paint.currentMd5 && (type == 'add')) {
ScratchJr.stage.currentPage.addSprite(Paint.costumeScale, Paint.currentMd5, cname);
}
Paint.close();
}
};
Paint.addOrModifySprite = function (str, fcn) {
Paint.saveMD5 = str;
var mobj = {};
mobj.cond = 'md5 = ? AND version = ?';
mobj.items = ['*'];
mobj.values = [Paint.saveMD5, ScratchJr.version];
IO.query('usershapes', mobj, function (str) {
Paint.checkDuplicate(str, fcn);
});
};
Paint.checkDuplicate = function (str, fcn) {
var list = JSON.parse(str);
if (list.length > 0) {
if (fcn) {
fcn('duplicate');
}
} else {
Paint.addToLib(fcn);
}
};
/////////////////////////////////////
// usershapes: stores costumes
/////////////////////////////////////
/* current data
[md5] =>
[altmd5] => // for PNG -- not used
[version] =>
[scale] =>
[ext] => png / svg
[width] =>
[height] =>
[name] =>
*/
Paint.addToLib = function (fcn) {
var scale = '0.5'; // always saves with 1/2 the size
var cname = document.forms.spriteform.name.value;
cname = ((unescape(cname)).replace(/[0-9]/g, '')).replace(/\s*/g, '');
var box = SVGTools.getBox(gn('layer1')).rounded();
box = box.expandBy(20);
var w = box.width.toString();
var h = box.height.toString();
var dataurl = IO.getThumbnail(Paint.svgdata, w, h, 120, 90);
var pngBase64 = dataurl.split(',')[1];
iOS.setmedia(pngBase64, 'png', setCostumeRecord);
function setCostumeRecord (pngmd5) {
var json = {};
var keylist = ['scale', 'md5', 'altmd5', 'version', 'width', 'height', 'ext', 'name'];
var values = '?,?,?,?,?,?,?,?';
json.values = [scale, Paint.saveMD5, pngmd5, ScratchJr.version, w, h, 'svg', cname];
json.stmt = 'insert into usershapes (' + keylist.toString() + ') values (' + values + ')';
iOS.stmt(json, fcn);
}
};
Paint.changePageSprite = function () {
Paint.close();
var cname = document.forms.spriteform.name.value;
var type = Paint.getLoadType(Paint.spriteId, cname);
switch (type) {
case 'modify':
ScratchJr.stage.currentPage.modifySprite(Paint.saveMD5, cname, Paint.spriteId);
break;
case 'add':
ScratchJr.stage.currentPage.addSprite(Paint.costumeScale, Paint.saveMD5, cname);
break;
default:
ScratchJr.stage.currentPage.update();
break;
}
};
Paint.getLoadType = function (sid, cid) {
if (!cid) {
return 'none';
}
if (sid && cid) {
return 'modify';
}
return 'add';
};
///////////////////////////
// XML import processs
///////////////////////////
Paint.skipUnwantedElements = function (p, res) {
for (var i = 0; i < p.childNodes.length; i++) {
var elem = p.childNodes[i];
if (elem.nodeName == 'metadata') {
continue;
}
if (elem.nodeName == 'defs') {
continue;
}
if (elem.nodeName == 'sodipodi:namedview') {
continue;
}
if (elem.nodeName == '#comment') {
continue;
}
if ((elem.nodeName == 'g') && (elem.id == 'layer1')) {
Paint.skipUnwantedElements(elem, res);
if (elem.removeAttribute('id')) {
elem.removeAttribute('id');
}
} else {
res.push(elem);
}
}
return res;
};
Paint.reassingIds = function (p) {
for (var i = 0; i < p.childNodes.length; i++) {
var elem = p.childNodes[i];
if (elem.parentNode.getAttribute('fixed') == 'yes') {
elem.setAttribute('fixed', 'yes');
}
var id = elem.getAttribute('id');
if (!id) {
elem.setAttribute('id', getIdFor(elem.nodeName));
}
if (elem.nodeName == 'g') {
Paint.reassingIds(elem);
}
}
};
Paint.createCharFromXML = function (str) {
Paint.nativeJr = str.indexOf('Scratch Jr') > -1;
var dx = (Paint.workspaceWidth < 432) ? Math.floor((432 - Paint.workspaceWidth) / 2) : 0;
var dy = (Paint.workspaceHeight < 384) ? Math.floor((384 - Paint.workspaceHeight) / 2) : 0;
if (Paint.workspaceWidth < 432) {
Paint.workspaceWidth = 432;
}
if (Paint.workspaceHeight < 384) {
Paint.workspaceHeight = 384;
}
Paint.setUpCanvasArea();
str = str.replace(/>\s*</g, '><');
var xmlDoc = new DOMParser().parseFromString(str, 'text/xml');
var extxml = document.importNode(xmlDoc.documentElement, true);
var flat = Paint.skipUnwantedElements(extxml, []);
for (var i = 0; i < flat.length; i++) {
gn('layer1').appendChild(flat[i]);
}
Paint.doAbsolute(gn('layer1'));
Paint.adjustShapePosition(dx, dy);
if (!Paint.nativeJr) {
Paint.reassingIds(gn('layer1'));
} // make sure there are unique mask names
Paint.scaleToFit();
Paint.minZoom = Paint.currentZoom < 1 ? Paint.currentZoom / 2 : 1;
var maxpix = 2290 * 2289; // Magic iOS max canvas size
var ratio = maxpix / (Paint.workspaceWidth * Paint.workspaceHeight);
var zoom = Math.floor(Math.sqrt(ratio));
if (zoom < Paint.maxZoom) {
Paint.maxZoom = zoom;
}
PaintUndo.record(true);
if (!Paint.nativeJr) {
Paint.selectButton('paintbucket');
}
};
Paint.doAbsolute = function (div) {
for (var i = 0; i < div.childElementCount; i++) {
var elem = div.childNodes[i];
if (elem.tagName == 'path') {
SVG2Canvas.setAbsolutePath(elem);
}
if (elem.tagName == 'g') {
Paint.doAbsolute(div.childNodes[i]);
}
}
};
Paint.getComponents = function (p, res) {
for (var i = 0; i < p.childNodes.length; i++) {
var elem = p.childNodes[i];
if (elem.nodeName == 'metadata') {
continue;
}
if (elem.nodeName == 'defs') {
continue;
}
if (elem.nodeName == 'sodipodi:namedview') {
continue;
}
if (elem.nodeName == '#comment') {
continue;
}
if (elem.nodeName == 'g') {
Paint.getComponents(elem, res);
if (elem.getAttribute('id')) {
elem.removeAttribute('id');
}
} else {
res.push(elem);
}
}
return res;
};

View file

@ -1,491 +0,0 @@
/////////////////////////////////
//Layout Setup
/////////////////////////////////
Paint.layout = function () {
Paint.topbar();
var div = newHTML('div', 'innerpaint', Paint.frame);
Paint.leftPalette(div);
var workspaceContainer = newHTML('div', 'workspacebkg-container', div);
var workspace = newHTML('div', 'workspacebkg', workspaceContainer);
workspace.setAttribute('id', 'workspacebkg');
Paint.rightPalette(div);
Paint.colorPalette(Paint.frame);
Paint.selectButton('path');
Paint.createSVGeditor(workspace);
};
/////////////////////////////////
//top bar
/////////////////////////////////
Paint.topbar = function () {
var pt = newHTML('div', 'paintop', Paint.frame);
Paint.checkMark(pt);
PaintUndo.setup(pt); // plug here the undo
Paint.nameOfcostume(pt);
};
Paint.checkMark = function (pt) {
var clicky = newHTML('div', 'paintdone', pt);
clicky.id = 'donecheck';
if (isTablet) {
clicky.ontouchstart = Paint.backToProject;
} else {
clicky.onmousedown = Paint.backToProject;
}
};
Paint.nameOfcostume = function (p) {
var sform = newHTML('form', 'spriteform', p);
sform.name = 'spriteform';
var ti = newHTML('input', undefined, sform);
ti.onkeypress = undefined;
ti.autocomplete = 'off';
ti.autocorrect = false;
ti.name = 'name';
ti.maxLength = 25;
ti.firstTime = true;
ti.onfocus = Paint.nameFocus;
ti.onblur = Paint.nameBlur;
ti.onkeypress = Paint.handleNamePress;
ti.onkeyup = Paint.handleKeyRelease;
sform.onsubmit = Paint.submitNameChange;
};
Paint.submitNameChange = function (e) {
e.preventDefault();
var input = e.target;
input.blur();
};
Paint.nameFocus = function (e) {
e.preventDefault();
e.stopPropagation();
var ti = e.target;
ti.firstTime = true;
ScratchJr.activeFocus = ti;
if (isAndroid) {
AndroidInterface.scratchjr_setsoftkeyboardscrolllocation(
ti.getBoundingClientRect().top * window.devicePixelRatio,
ti.getBoundingClientRect().bottom * window.devicePixelRatio
);
}
Undo.aux = Project.getProject(ScratchJr.stage.currentPage.id);
setTimeout(function () {
ti.setSelectionRange(ti.value.length, ti.value.length);
}, 1);
};
Paint.nameBlur = function (e) {
ScratchJr.activeFocus = undefined;
var spr = ScratchJr.getSprite();
var ti = e.target;
var val = ScratchJr.validate(ti.value, spr.name);
ti.value = val.substring(0, ti.maxLength);
ScratchJr.storyStart('Paint.nameBlur');
};
Paint.handleNamePress = function (e) {
var key = e.keyCode || e.which;
if (key == 13) {
Paint.submitNameChange(e);
} else {
var ti = e.target;
if (ti.firstTime) {
ti.firstTime = false;
ti.value = '';
}
if (ti.value.length == 25) {
ScratchAudio.sndFX('boing.wav');
}
}
};
Paint.handleKeyRelease = function (e) {
var key = e.keyCode || e.which;
var ti = e.target;
if (key != 8) {
return;
}
if (ti.firstTime) {
ti.firstTime = false;
ti.value = '';
}
};
/////////////////////////////////
//Left Palette
/////////////////////////////////
Paint.leftPalette = function (div) {
var leftpal = newHTML('div', 'side up', div);
var pal = newHTML('div', 'paintpalette', leftpal);
pal.setAttribute('id', 'paintpalette');
Paint.setupEditPalette(pal);
Paint.createSizeSelector(pal);
};
Paint.setupEditPalette = function (pal) {
var section = newHTML('div', 'section', pal);
section.setAttribute('id', 'painttools');
var list = ['path', 'ellipse', 'rect', 'tri'];
var i = 0;
for (i = 0; i < list.length; i++) {
var but = newHTML('div', 'element off', section);
var icon = newHTML('div', 'tool ' + list[i] + ' off', but);
icon.setAttribute('key', list[i]);
if (isTablet) {
icon.ontouchstart = Paint.setMode;
} else {
icon.onmousedown = Paint.setMode;
}
}
};
Paint.createSizeSelector = function (pal) {
var section = newHTML('div', 'section space', pal);
section.setAttribute('id', 'sizeSelector');
for (var i = 0; i < Paint.pensizes.length; i++) {
var ps = newHTML('div', 'pensizeholder', section);
ps.key = i;
ps.ontouchstart = function (e) {
e.preventDefault();
e.stopPropagation();
var n = Number(this.key);
Paint.strokewidth = Paint.pensizes[Number(this.key)];
Paint.selectPenSize(n);
};
var c = newHTML('div', 'line t' + i, ps);
Paint.drawPenSizeInColor(c);
}
Paint.strokewidth = Paint.pensizes[1];
Paint.selectPenSize(1);
};
////////////////////////////////////////
// Pen sizes
////////////////////////////////////////
Paint.drawPenSizeInColor = function (c) {
c.style.background = Paint.fillcolor;
};
Paint.updateStrokes = function () {
var div = gn('sizeSelector');
if (!div) {
return;
}
for (var i = 0; i < div.childElementCount; i++) {
var elem = div.childNodes[i];
Paint.drawPenSizeInColor(elem.childNodes[0]);
}
};
Paint.selectPenSize = function (str) {
var p = gn('sizeSelector');
for (var i = 0; i < p.childElementCount; i++) {
var elem = p.childNodes[i];
if (elem.key == str) {
elem.setAttribute('class', 'pensizeholder on');
} else {
elem.setAttribute('class', 'pensizeholder off');
}
}
};
/////////////////////////////////
//Right Palette
/////////////////////////////////
Paint.rightPalette = function (div) {
var rightpal = newHTML('div', 'side', div);
Paint.addSidePalette(rightpal, 'selectortools', ['select', 'rotate']);
Paint.addSidePalette(rightpal, 'edittools', ['stamper', 'scissors']);
Paint.addSidePalette(rightpal, 'filltools',
(iOS.camera == '1' && Camera.available) ? ['camera', 'paintbucket'] : ['paintbucket']);
};
Paint.addSidePalette = function (p, id, list) {
var pal = newHTML('div', 'paintpalette short', p);
pal.setAttribute('id', id);
for (var i = 0; i < list.length; i++) {
var but = newHTML('div', 'element off', pal);
var icon = newHTML('div', 'tool ' + list[i] + ' off', but);
icon.setAttribute('key', list[i]);
icon.ontouchstart = Paint.setMode;
}
};
Paint.cameraToolsOn = function () {
gn('backdrop').setAttribute('class', 'modal-backdrop fade dark');
setProps(gn('backdrop').style, {
display: 'block'
});
var topbar = newHTML('div', 'phototopbar', gn('backdrop'));
topbar.setAttribute('id', 'photocontrols');
// var actions = newHTML("div",'actions', topbar);
// var buttons = newHTML('div', 'photobuttons', actions);
var fc = newHTML('div', 'flipcamera', topbar);
fc.setAttribute('id', 'cameraflip');
fc.setAttribute('key', 'cameraflip');
if (isAndroid && !AndroidInterface.scratchjr_has_multiple_cameras()) {
fc.style.display = 'none';
}
fc.ontouchstart = Paint.setMode;
var captureContainer = newHTML('div', 'snapshot-container', gn('backdrop'));
captureContainer.setAttribute('id', 'capture-container');
var capture = newHTML('div', 'snapshot', captureContainer);
capture.setAttribute('id', 'capture');
capture.setAttribute('key', 'camerasnap');
capture.ontouchstart = Paint.setMode;
var cc = newHTML('div', 'cameraclose', topbar);
cc.setAttribute('id', 'cameraclose');
cc.ontouchstart = Paint.closeCameraMode;
};
Paint.closeCameraMode = function () {
ScratchAudio.sndFX('exittap.wav');
Camera.close();
Paint.selectButton('select');
};
Paint.cameraToolsOff = function () {
gn('backdrop').setAttribute('class', 'modal-backdrop fade');
setProps(gn('backdrop').style, {
display: 'none'
});
if (gn('photocontrols')) {
gn('photocontrols').parentNode.removeChild(gn('photocontrols'));
}
if (gn('capture')) {
var captureContainer = gn('capture').parentNode;
var captureContainerParent = captureContainer.parentNode;
captureContainer.removeChild(gn('capture'));
captureContainerParent.removeChild(gn('capture-container'));
}
};
//////////////////////////////////
// canvas Area
//////////////////////////////////
Paint.setUpCanvasArea = function () {
var workspace = gn('workspacebkg');
var dx = Math.floor((workspace.offsetWidth - Paint.workspaceWidth) / 2);
var dy = Math.floor((workspace.offsetHeight - Paint.workspaceHeight) / 2);
var w = Paint.workspaceWidth;
var h = Paint.workspaceHeight;
var div = gn('maincanvas');
div.style.background = '#F5F2F7';
div.style.top = '0px';
div.style.left = '0px';
div.style.width = w + 'px';
div.style.height = h + 'px';
div.cx = div.offsetWidth / 2;
div.cy = div.offsetHeight / 2;
div.dx = dx;
div.dy = dy;
Paint.root.setAttributeNS(null, 'width', w);
Paint.root.setAttributeNS(null, 'height', h);
Paint.drawGrid(w, h);
PaintAction.clearEvents();
};
/////////////////////////////////
//Color Palette
/////////////////////////////////
Paint.colorPalette = function (div) {
var swatchlist = Paint.initSwatchList();
var spalContainer = newHTML('div', 'swatchpalette-container', div);
var spal = newHTML('div', 'swatchpalette', spalContainer);
spal.setAttribute('id', 'swatches');
for (var i = 0; i < swatchlist.length; i++) {
var colour = newHTML('div', 'swatchbucket', spal);
// bucket
var sf = newHTML('div', 'swatchframe', colour);
var sc = newHTML('div', 'swatchcolor', sf);
sc.style.background = swatchlist[i];
//
sf = newHTML('div', 'splasharea off', colour);
Paint.setSplashColor(sf, Paint.splash, swatchlist[i]);
Paint.addImageUrl(sf, Paint.splashshade);
colour.ontouchstart = Paint.selectSwatch;
}
Paint.setSwatchColor(gn('swatches').childNodes[swatchlist.indexOf('#1C1C1C')]);
};
Paint.setSplashColor = function (p, str, color) {
var dataurl = 'data:image/svg+xml;base64,' + btoa(str.replace(/#662D91/g, color));
Paint.addImageUrl(p, dataurl);
};
Paint.addImageUrl = function (p, url) {
var img = document.createElement('img');
img.src = url;
img.style.position = 'absolute';
p.appendChild(img);
};
Paint.selectSwatch = function (e) {
if (e.touches && (e.touches.length > 1)) {
return;
}
e.preventDefault();
e.stopPropagation();
if (Camera.active) {
return;
}
var t;
if (window.event) {
t = window.event.srcElement;
} else {
t = e.target;
}
var b = 'swatchbucket' != t.className;
while (b) {
t = t.parentNode;
b = t && ('swatchbucket' != t.className);
}
if (!t) {
return;
}
ScratchAudio.sndFX('splash.wav');
Paint.setSwatchColor(t);
};
Paint.setSwatchColor = function (t) {
var tools = ['select', 'wand', 'stamper', 'scissors', 'rotate'];
if (t && (tools.indexOf(Paint.mode) > -1)) {
Paint.selectButton('paintbucket');
}
var c = t.childNodes[0].childNodes[0].style.backgroundColor;
for (var i = 0; i < gn('swatches').childElementCount; i++) {
var mycolor = gn('swatches').childNodes[i].childNodes[0].childNodes[0].style.backgroundColor;
if (c == mycolor) {
gn('swatches').childNodes[i].childNodes[1].setAttribute('class', 'splasharea on');
} else {
gn('swatches').childNodes[i].childNodes[1].setAttribute('class', 'splasharea off');
}
}
Paint.fillcolor = c;
Path.quitEditMode();
Paint.updateStrokes();
};
Paint.initSwatchList = function () {
return [
// "#FF5500", // new orange
'#FFD2F2', '#FF99D6', '#FF4583', // red pinks
'#C30001', '#FF0023', '#FF8300', '#FFB200',
'#FFF42E',
'#FFF9C2', // pale yellow
'#E2FFBD', // pale green
'#CFF500', // lime green
'#50D823', // problematic
// "#2BFC49", // less problematic
'#29C130',
// "#56C43B", // ERROR?
'#2BBF8A', // new green
'#027607', '#114D24', //greens
'#FFFFFF', '#CCDDE7', '#61787C', '#1C1C1C', // grays
'#D830A3', // sarah's pink shoes border
'#FF64E9', // purple pinks
'#D999FF', ' #A159D3', // vilote
'#722696', // sarah's violet
'#141463', '#003399', '#1D40ED',
'#0079D3', '#009EFF', '#76C8FF',
'#ACE0FD', '#11B7BC', '#21F9F3', '#C3FCFC', '#54311E',
'#8E572A', '#E4B69D', '#FFCDA4', '#FFEDD7' // skin colors
];
};
/////////////////////////////////////////////////
// Setup SVG Editor
////////////////////////////////////////////////
Paint.createSVGeditor = function (container) {
var div = newHTML('div', 'maincanvas', container);
div.setAttribute('id', 'maincanvas');
div.style.background = '#F5F2F7';
div.style.top = '0px';
div.style.left = '0px';
window.onmousemove = undefined;
window.onmouseup = undefined;
Paint.root = SVGTools.create(div);
Paint.root.setAttribute('class', 'active3d');
xform = Transform.getTranslateTransform();
selxform = Transform.getTranslateTransform();
var layer = SVGTools.createGroup(Paint.root, 'layer1');
layer.setAttribute('style', 'pointer-events:visiblePainted');
SVGTools.createGroup(Paint.root, 'draglayer');
SVGTools.createGroup(Paint.root, 'paintgrid');
gn('paintgrid').setAttribute('opacity', 0.5);
};
Paint.clearWorkspace = function () {
var fcn = function (div) {
while (div.childElementCount > 0) {
div.removeChild(div.childNodes[0]);
}
};
fcn(gn('layer1'));
fcn(gn('paintgrid'));
fcn(gn('draglayer'));
Path.quitEditMode();
};
Paint.drawGrid = function (w, h) {
var attr, path;
if (!Paint.isBkg) {
attr = {
'd': Paint.getGridPath(w, h, 12),
'id': getIdFor('gridpath'),
'opacity': 1,
'stroke': '#dcddde',
'fill': 'none',
'stroke-width': 0.5
};
path = SVGTools.addChild(gn('paintgrid'), 'path', attr);
path.setAttribute('style', 'pointer-events:none;');
}
attr = {
'd': Paint.getGridPath(w, h, Paint.isBkg ? 24 : 48),
'id': getIdFor('gridpath'),
'opacity': 1,
'stroke': '#c1c2c3',
'fill': 'none',
'stroke-width': 0.5
};
path = SVGTools.addChild(gn('paintgrid'), 'path', attr);
path.setAttribute('style', 'pointer-events:none;');
};
Paint.getGridPath = function (w, h, gridsize) {
var str = '';
var dx = gridsize;
// vertical
var cmd;
for (var i = 0; i < w / gridsize; i++) {
cmd = 'M' + dx + ',' + 0 + 'L' + dx + ',' + h;
str += cmd;
dx += gridsize;
}
var dy = gridsize;
// horizontal
for (i = 0; i < h / gridsize; i++) {
cmd = 'M' + 0 + ',' + dy + 'L' + w + ',' + dy;
str += cmd;
dy += gridsize;
}
return str;
};