kopia lustrzana https://github.com/backface/turtlestitch
rodzic
a918fd1f94
commit
c27fb90305
|
@ -2,12 +2,14 @@
|
||||||
|
|
||||||
## in development:
|
## in development:
|
||||||
* **New Features:**
|
* **New Features:**
|
||||||
|
* export pen trails as SVG
|
||||||
* **Notable Changes:**
|
* **Notable Changes:**
|
||||||
* **Notable Fixes:**
|
* **Notable Fixes:**
|
||||||
* **Translation Updates:**
|
* **Translation Updates:**
|
||||||
|
|
||||||
### 2019-12-02
|
### 2019-12-02
|
||||||
* new dev version
|
* new dev version
|
||||||
|
* objects: export pen trails as SVG (under construction)
|
||||||
|
|
||||||
## v5.3.8:
|
## v5.3.8:
|
||||||
* **Notable Change:**
|
* **Notable Change:**
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<script type="text/javascript" src="src/widgets.js?version=2019-10-16"></script>
|
<script type="text/javascript" src="src/widgets.js?version=2019-10-16"></script>
|
||||||
<script type="text/javascript" src="src/blocks.js?version=2019-11-12"></script>
|
<script type="text/javascript" src="src/blocks.js?version=2019-11-12"></script>
|
||||||
<script type="text/javascript" src="src/threads.js?version=2019-11-29"></script>
|
<script type="text/javascript" src="src/threads.js?version=2019-11-29"></script>
|
||||||
<script type="text/javascript" src="src/objects.js?version=2019-11-29"></script>
|
<script type="text/javascript" src="src/objects.js?version=2019-12-02"></script>
|
||||||
<script type="text/javascript" src="src/gui.js?version=2019-12-02"></script>
|
<script type="text/javascript" src="src/gui.js?version=2019-12-02"></script>
|
||||||
<script type="text/javascript" src="src/paint.js?version=2019-06-27"></script>
|
<script type="text/javascript" src="src/paint.js?version=2019-06-27"></script>
|
||||||
<script type="text/javascript" src="src/lists.js?version=2019-11-15"></script>
|
<script type="text/javascript" src="src/lists.js?version=2019-11-15"></script>
|
||||||
|
|
145
src/objects.js
145
src/objects.js
|
@ -84,7 +84,7 @@ BlockEditorMorph, BlockDialogMorph, PrototypeHatBlockMorph, BooleanSlotMorph,
|
||||||
localize, TableMorph, TableFrameMorph, normalizeCanvas, VectorPaintEditorMorph,
|
localize, TableMorph, TableFrameMorph, normalizeCanvas, VectorPaintEditorMorph,
|
||||||
HandleMorph, AlignmentMorph, Process, XML_Element, WorldMap, copyCanvas*/
|
HandleMorph, AlignmentMorph, Process, XML_Element, WorldMap, copyCanvas*/
|
||||||
|
|
||||||
modules.objects = '2019-November-29';
|
modules.objects = '2019-December-02';
|
||||||
|
|
||||||
var SpriteMorph;
|
var SpriteMorph;
|
||||||
var StageMorph;
|
var StageMorph;
|
||||||
|
@ -688,15 +688,20 @@ SpriteMorph.prototype.initBlocks = function () {
|
||||||
category: 'pen',
|
category: 'pen',
|
||||||
spec: 'pen trails'
|
spec: 'pen trails'
|
||||||
},
|
},
|
||||||
|
|
||||||
// Pen - experimental primitives for development mode
|
|
||||||
doPasteOn: {
|
doPasteOn: {
|
||||||
dev: true,
|
|
||||||
type: 'command',
|
type: 'command',
|
||||||
category: 'pen',
|
category: 'pen',
|
||||||
spec: 'paste on %spr'
|
spec: 'paste on %spr'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Pen - experimental primitives for development mode
|
||||||
|
reportPentrailsAsSVG: {
|
||||||
|
dev: true,
|
||||||
|
type: 'reporter',
|
||||||
|
category: 'pen',
|
||||||
|
spec: 'pen trails (SVG)'
|
||||||
|
},
|
||||||
|
|
||||||
// Control
|
// Control
|
||||||
receiveGo: {
|
receiveGo: {
|
||||||
type: 'hat',
|
type: 'hat',
|
||||||
|
@ -2321,6 +2326,22 @@ SpriteMorph.prototype.blockTemplates = function (category) {
|
||||||
blocks.push('=');
|
blocks.push('=');
|
||||||
blocks.push(this.makeBlockButton(cat));
|
blocks.push(this.makeBlockButton(cat));
|
||||||
|
|
||||||
|
// for debugging: ///////////////
|
||||||
|
|
||||||
|
if (this.world().isDevMode) {
|
||||||
|
blocks.push('-');
|
||||||
|
txt = new TextMorph(localize(
|
||||||
|
'development mode \ndebugging primitives:'
|
||||||
|
));
|
||||||
|
txt.fontSize = 9;
|
||||||
|
txt.setColor(this.paletteTextColor);
|
||||||
|
blocks.push(txt);
|
||||||
|
blocks.push('-');
|
||||||
|
blocks.push(block('reportPentrailsAsSVG'));
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
} else if (cat === 'control') {
|
} else if (cat === 'control') {
|
||||||
|
|
||||||
blocks.push(block('receiveGo'));
|
blocks.push(block('receiveGo'));
|
||||||
|
@ -5171,6 +5192,18 @@ SpriteMorph.prototype.drawLine = function (start, dest) {
|
||||||
).intersect(this.parent.visibleBounds()).spread();
|
).intersect(this.parent.visibleBounds()).spread();
|
||||||
|
|
||||||
if (this.isDown) {
|
if (this.isDown) {
|
||||||
|
// record for future svg conversion // +++
|
||||||
|
this.parent.trailsLog.push(
|
||||||
|
[
|
||||||
|
this.snapPoint(start),
|
||||||
|
this.snapPoint(dest),
|
||||||
|
this.color.copy(),
|
||||||
|
this.size,
|
||||||
|
this.useFlatLineEnds ? 'butt' : 'round'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// draw on the pen-trails layer
|
||||||
context.lineWidth = this.size;
|
context.lineWidth = this.size;
|
||||||
context.strokeStyle = this.color.toString();
|
context.strokeStyle = this.color.toString();
|
||||||
if (this.useFlatLineEnds) {
|
if (this.useFlatLineEnds) {
|
||||||
|
@ -5597,6 +5630,17 @@ SpriteMorph.prototype.bounceOffEdge = function () {
|
||||||
this.positionTalkBubble();
|
this.positionTalkBubble();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// SpriteMorph coordinate conversion // +++
|
||||||
|
|
||||||
|
SpriteMorph.prototype.snapPoint = function(aPoint) { // +++
|
||||||
|
var stage = this.parentThatIsA(StageMorph),
|
||||||
|
origin = stage.center();
|
||||||
|
return new Point(
|
||||||
|
(aPoint.x - origin.x) / stage.scale,
|
||||||
|
(origin.y - aPoint.y) / stage.scale
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
// SpriteMorph rotation center / fixation point manipulation
|
// SpriteMorph rotation center / fixation point manipulation
|
||||||
|
|
||||||
SpriteMorph.prototype.setRotationX = function (absoluteX) {
|
SpriteMorph.prototype.setRotationX = function (absoluteX) {
|
||||||
|
@ -7417,6 +7461,7 @@ StageMorph.prototype.init = function (globals) {
|
||||||
this.activeSounds = []; // do not persist
|
this.activeSounds = []; // do not persist
|
||||||
|
|
||||||
this.trailsCanvas = null;
|
this.trailsCanvas = null;
|
||||||
|
this.trailsLog = []; // +++ each line being [p1, p2, color, width, cap]
|
||||||
this.isThreadSafe = false;
|
this.isThreadSafe = false;
|
||||||
|
|
||||||
this.microphone = new Microphone(); // audio input, do not persist
|
this.microphone = new Microphone(); // audio input, do not persist
|
||||||
|
@ -7622,6 +7667,7 @@ StageMorph.prototype.drawOn = function (aCanvas, aRect) {
|
||||||
StageMorph.prototype.clearPenTrails = function () {
|
StageMorph.prototype.clearPenTrails = function () {
|
||||||
this.cachedPenTrailsMorph = null;
|
this.cachedPenTrailsMorph = null;
|
||||||
this.trailsCanvas = newCanvas(this.dimensions, null, this.trailsCanvas);
|
this.trailsCanvas = newCanvas(this.dimensions, null, this.trailsCanvas);
|
||||||
|
this.trailsLog = []; // +++
|
||||||
this.changed();
|
this.changed();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8421,6 +8467,22 @@ StageMorph.prototype.blockTemplates = function (category) {
|
||||||
blocks.push('=');
|
blocks.push('=');
|
||||||
blocks.push(this.makeBlockButton(cat));
|
blocks.push(this.makeBlockButton(cat));
|
||||||
|
|
||||||
|
// for debugging: ///////////////
|
||||||
|
|
||||||
|
if (this.world().isDevMode) {
|
||||||
|
blocks.push('-');
|
||||||
|
txt = new TextMorph(localize(
|
||||||
|
'development mode \ndebugging primitives:'
|
||||||
|
));
|
||||||
|
txt.fontSize = 9;
|
||||||
|
txt.setColor(this.paletteTextColor);
|
||||||
|
blocks.push(txt);
|
||||||
|
blocks.push('-');
|
||||||
|
blocks.push(block('reportPentrailsAsSVG'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
} else if (cat === 'control') {
|
} else if (cat === 'control') {
|
||||||
|
|
||||||
blocks.push(block('receiveGo'));
|
blocks.push(block('receiveGo'));
|
||||||
|
@ -8769,6 +8831,14 @@ StageMorph.prototype.userMenu = function () {
|
||||||
: 'turn all pen trails and stamps\n' +
|
: 'turn all pen trails and stamps\n' +
|
||||||
'into a new background for the stage'
|
'into a new background for the stage'
|
||||||
);
|
);
|
||||||
|
// +++ experimental
|
||||||
|
if (this.trailsLog.length) {
|
||||||
|
menu.addItem(
|
||||||
|
'svg...',
|
||||||
|
'exportTrailsLogAsSVG',
|
||||||
|
'export pen trails line segments as SVG'
|
||||||
|
);
|
||||||
|
}
|
||||||
return menu;
|
return menu;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8851,6 +8921,73 @@ StageMorph.prototype.thumbnail = function (
|
||||||
return trg;
|
return trg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// StageMorph - exporting the pen trails as SVG // +++
|
||||||
|
|
||||||
|
StageMorph.prototype.exportTrailsLogAsSVG = function () { // +++
|
||||||
|
var ide = this.parentThatIsA(IDE_Morph);
|
||||||
|
|
||||||
|
ide.saveFileAs(
|
||||||
|
this.trailsLogAsSVG(),
|
||||||
|
'image/svg', // +++'image/svg+xml',
|
||||||
|
ide.projectName || this.name
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
StageMorph.prototype.trailsLogAsSVG = function () { // +++
|
||||||
|
var myself = this,
|
||||||
|
bottomLeft = this.trailsLog[0][0],
|
||||||
|
topRight = bottomLeft,
|
||||||
|
maxWidth = this.trailsLog[0][3],
|
||||||
|
shift,
|
||||||
|
box,
|
||||||
|
p1, p2,
|
||||||
|
svg;
|
||||||
|
|
||||||
|
// determine bounding box and max line width
|
||||||
|
this.trailsLog.forEach(function (line) {
|
||||||
|
bottomLeft = bottomLeft.min(line[0]);
|
||||||
|
bottomLeft = bottomLeft.min(line[1]);
|
||||||
|
topRight = topRight.max(line[0]);
|
||||||
|
topRight = topRight.max(line[1]);
|
||||||
|
maxWidth = Math.max(maxWidth, line[3]);
|
||||||
|
});
|
||||||
|
box = bottomLeft.corner(topRight).expandBy(maxWidth / 2);
|
||||||
|
shift = new Point(-bottomLeft.x, topRight.y).translateBy(maxWidth / 2);
|
||||||
|
svg = '<svg ' +
|
||||||
|
'viewBox="0 0 ' + box.width() + ' ' + box.height() + '" ' +
|
||||||
|
'width="' + box.width() + '" height="' + box.height() + '" ' +
|
||||||
|
// 'style="background-color:black" ' + // for supporting backgrounds
|
||||||
|
'xmlns="http://www.w3.org/2000/svg">';
|
||||||
|
|
||||||
|
// to do:
|
||||||
|
// * add source comment ("exported from Snap! etc."
|
||||||
|
// * add "keep aspect ratio" governance
|
||||||
|
// * catch / disable if the trails log is empty
|
||||||
|
// * catch if the trails contain non-vectorizable elements (stamp, fill)
|
||||||
|
// * decide how to handle background colors
|
||||||
|
// * consider a logging limit to prevent an overflowing queue
|
||||||
|
|
||||||
|
// for debugging the viewBox:
|
||||||
|
// svg += '<rect width="100%" height="100%" fill="black"/>'
|
||||||
|
|
||||||
|
this.trailsLog.forEach(function (line) {
|
||||||
|
p1 = myself.normalizePoint(line[0]).translateBy(shift);
|
||||||
|
p2 = myself.normalizePoint(line[1]).translateBy(shift);
|
||||||
|
svg += '<line x1="' + p1.x + '" y1="' + p1.y +
|
||||||
|
'" x2="' + p2.x + '" y2="' + p2.y + '" ' +
|
||||||
|
'style="stroke:' + line[2].toString() + ';' +
|
||||||
|
'stroke-width:' + line[3] +
|
||||||
|
';stroke-linecap:' + line[4] +
|
||||||
|
'" />';
|
||||||
|
});
|
||||||
|
svg += '</svg>';
|
||||||
|
return svg;
|
||||||
|
};
|
||||||
|
|
||||||
|
StageMorph.prototype.normalizePoint = function (snapPoint) { // +++
|
||||||
|
return new Point(snapPoint.x, -snapPoint.y);
|
||||||
|
};
|
||||||
|
|
||||||
// StageMorph hiding and showing:
|
// StageMorph hiding and showing:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Ładowanie…
Reference in New Issue