Merge branch 'master' into feature-export-to-file

This commit is contained in:
jdescottes
2014-07-12 00:46:27 +02:00
37 changed files with 541 additions and 117 deletions

View File

@@ -96,6 +96,10 @@
border: #999 3px solid;
}
.tile-view {
position : relative;
}
.preview-tile .tile-overlay {
z-index: 10;
position: absolute;

View File

@@ -97,11 +97,18 @@
background-size: 23px 23px;
}
.tool-icon.tool-colorswap {
background-image: url(../img/tools/swap-colors.png);
background-position: 6px 6px;
background-size: 36px 36px;
}
/*
* Tool cursors:
*/
.tool-paint-bucket .drawing-canvas-container:hover {
.tool-paint-bucket .drawing-canvas-container:hover,
.tool-colorswap .drawing-canvas-container:hover {
cursor: url(../img/icons/paint-bucket.png) 12 12, pointer;
}
@@ -228,4 +235,28 @@
);
}
.tools-tooltip-container {
text-align: left;
padding-bottom: 5px;
}
.tools-tooltip-shortcut {
color:gold;
}
.tools-tooltip-descriptor {
color:#999;
}
.tools-tooltip-descriptor-button {
padding:2px;
border:1px Solid #999;
font-size:0.8em;
margin-right:5px;
width:35px;
text-align:center;
border-radius:3px;
display:inline-block;
line-height: 10px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@@ -22,7 +22,11 @@
color:white;">
<span style="top:45%">Loading Piskel ...</span>
</div>
<script type="text/javascript" src="js/lib/iframeLoader.js"></script>
<script type="text/javascript" src="js/lib/iframeLoader-0.1.0.js"></script>
<!-- the comment below indicates the beginning of markup reused by the editor integrated in piskelapp.com -->
<!-- do not delete, do not move :) -->
<!--body-main-start-->
<div id="main-wrapper" class="main-wrapper">
<iframe src="templates/drawing-tools.html" onload="iframeloader.onLoad(event)" data-iframe-loader="display"></iframe>
@@ -69,6 +73,10 @@
</div>
<iframe src="templates/cheatsheet.html" onload="iframeloader.onLoad(event)" data-iframe-loader="display"></iframe>
<script type="text/javascript" src="piskel-boot.js"></script>
<!--body-main-end-->
<!-- the comment above indicates the end of the markup reused by the editor integrated in piskelapp.com -->
<!-- do not delete, do not move :) -->
<script type="text/javascript" src="piskel-boot-0.1.0.js"></script>
</body>
</html>

View File

@@ -9,8 +9,9 @@
this.tools = [
toDescriptor('simplePen', 'P', new pskl.drawingtools.SimplePen()),
toDescriptor('verticalMirrorPen', 'V', new pskl.drawingtools.VerticalMirrorPen()),
toDescriptor('eraser', 'E', new pskl.drawingtools.Eraser()),
toDescriptor('paintBucket', 'B', new pskl.drawingtools.PaintBucket()),
toDescriptor('colorSwap', 'A', new pskl.drawingtools.ColorSwap()),
toDescriptor('eraser', 'E', new pskl.drawingtools.Eraser()),
toDescriptor('stroke', 'L', new pskl.drawingtools.Stroke()),
toDescriptor('rectangle', 'R', new pskl.drawingtools.Rectangle()),
toDescriptor('circle', 'C', new pskl.drawingtools.Circle()),
@@ -130,14 +131,10 @@
return pskl.utils.Template.replace(tpl, {
cssclass : classList.join(' '),
toolid : toolId,
title : this.getTooltipText_(tool)
title : tool.instance.getTooltipText(tool.shortcut)
});
};
ns.ToolController.prototype.getTooltipText_ = function (tool) {
return tool.instance.helpText + ' (' + tool.shortcut + ')';
};
ns.ToolController.prototype.addKeyboardShortcuts_ = function () {
for(var i = 0 ; i < this.tools.length ; i++) {
pskl.app.shortcutService.addShortcut(this.tools[i].shortcut, this.onKeyboardShortcut_.bind(this));

View File

@@ -43,7 +43,7 @@
try {
overlay.setPixel(this.highlightedPixelCol, this.highlightedPixelRow, Constants.TRANSPARENT_COLOR);
} catch (e) {
console.warn('ns.BaseTool.prototype.hideHighlightedPixel failed');
window.console.warn('ns.BaseTool.prototype.hideHighlightedPixel failed');
}
this.highlightedPixelRow = null;
this.highlightedPixelCol = null;
@@ -58,11 +58,45 @@
});
};
ns.BaseTool.prototype.getHelpText = function() {
return this.shortHelpText || this.helpText;
};
ns.BaseTool.prototype.getTooltipText = function(shortcut) {
var tpl = pskl.utils.Template.get('drawing-tool-tooltip-container-template');
var descriptors = "";
if (Array.isArray(this.tooltipDescriptors)) {
this.tooltipDescriptors.forEach(function (descriptor) {
descriptors += this.getTooltipDescription(descriptor);
}.bind(this));
}
return pskl.utils.Template.replace(tpl, {
helptext : this.getHelpText(),
shortcut : shortcut,
descriptors : descriptors
});
};
ns.BaseTool.prototype.getTooltipDescription = function(descriptor) {
var tpl;
if (descriptor.key) {
tpl = pskl.utils.Template.get('drawing-tool-tooltip-descriptor-template');
descriptor.key = descriptor.key.toUpperCase();
if (pskl.utils.UserAgent.isMac) {
descriptor.key = descriptor.key.replace('CTRL', 'CMD');
}
} else {
tpl = pskl.utils.Template.get('drawing-tool-tooltip-descriptor-simple-template');
}
return pskl.utils.Template.replace(tpl, descriptor);
};
ns.BaseTool.prototype.releaseToolAt = function(col, row, color, frame, overlay, event) {};
/**
* Bresenham line algorihtm: Get an array of pixels from
* Bresenham line algorithm: Get an array of pixels from
* start and end coordinates.
*
* http://en.wikipedia.org/wiki/Bresenham's_line_algorithm

View File

@@ -10,6 +10,7 @@
ns.ShapeTool.call(this);
this.toolId = "tool-circle";
this.helpText = "Circle tool";
};

View File

@@ -0,0 +1,58 @@
/**
* @provide pskl.drawingtools.ColorSwap
*
*/
(function() {
var ns = $.namespace("pskl.drawingtools");
ns.ColorSwap = function() {
this.toolId = "tool-colorswap";
this.helpText = "Paint all pixels of the same color";
this.tooltipDescriptors = [
{key : 'ctrl', description : 'Apply to all layers'},
{key : 'shift', description : 'Apply to all frames'}
];
};
pskl.utils.inherit(ns.ColorSwap, ns.BaseTool);
/**
* @override
*/
ns.ColorSwap.prototype.applyToolAt = function(col, row, color, frame, overlay, event) {
if (frame.containsPixel(col, row)) {
var sampledColor = frame.getPixel(col, row);
var allLayers = pskl.utils.UserAgent.isMac ? event.metaKey : event.ctrlKey;
var allFrames = event.shiftKey;
this.swapColors(sampledColor, color, allLayers, allFrames);
$.publish(Events.PISKEL_SAVE_STATE, {
type : pskl.service.HistoryService.SNAPSHOT
});
}
};
ns.ColorSwap.prototype.swapColors = function(oldColor, newColor, allLayers, allFrames) {
var swapPixelColor = function (pixelColor,x,y,frame) {
if (pixelColor == oldColor) {
frame.pixels[x][y] = newColor;
}
};
var currentLayer = pskl.app.piskelController.getCurrentLayer();
var currentFrameIndex = pskl.app.piskelController.getCurrentFrameIndex();
pskl.app.piskelController.getPiskel().getLayers().forEach(function (l) {
if (allLayers || l === currentLayer) {
l.getFrames().forEach(function (f, frameIndex) {
if (allFrames || frameIndex === currentFrameIndex) {
f.forEachPixel(swapPixelColor);
f.version++;
}
});
}
});
};
})();

View File

@@ -11,7 +11,14 @@
ns.Lighten = function() {
this.superclass.constructor.call(this);
this.toolId = "tool-lighten";
this.helpText = "Lighten (hold ctrl for Darken)";
this.helpText = "Lighten";
this.tooltipDescriptors = [
{key : 'ctrl', description : 'Darken'},
{key : 'shift', description : 'Apply only once per pixel'}
];
this.resetUsedPixels_();
};
@@ -31,7 +38,7 @@
var frameColor = frame.getPixel(col, row);
var pixelColor = overlayColor === Constants.TRANSPARENT_COLOR ? frameColor : overlayColor;
var isDarken = event.ctrlKey || event.cmdKey;
var isDarken = pskl.utils.UserAgent.isMac ? event.metaKey : event.ctrlKey;
var isSinglePass = event.shiftKey;
var isTransparent = pixelColor === Constants.TRANSPARENT_COLOR;

View File

@@ -10,7 +10,8 @@
ns.ShapeTool.call(this);
this.toolId = "tool-rectangle";
this.helpText = "Rectangle tool";
this.shortHelpText = "Rectangle tool";
};
pskl.utils.inherit(ns.Rectangle, ns.ShapeTool);

View File

@@ -8,6 +8,10 @@
// Shapes's first point coordinates (set in applyToolAt)
this.startCol = null;
this.startRow = null;
this.tooltipDescriptors = [
{key : 'shift', description : 'Keep 1 to 1 ratio'}
];
};
pskl.utils.inherit(ns.ShapeTool, ns.BaseTool);

View File

@@ -5,7 +5,12 @@
this.superclass.constructor.call(this);
this.toolId = "tool-vertical-mirror-pen";
this.helpText = "Vertical Mirror pen tool (hold CTRL for Horizontal, hold SHIFT for both)";
this.helpText = "Vertical Mirror pen";
this.tooltipDescriptors = [
{key : 'ctrl', description : 'Use horizontal axis'},
{key : 'shift', description : 'Use horizontal and vertical axis'}
];
};
pskl.utils.inherit(ns.VerticalMirrorPen, ns.SimplePen);
@@ -30,11 +35,12 @@
var mirroredCol = this.getSymmetricCol_(col, frame);
var mirroredRow = this.getSymmetricRow_(row, frame);
if (!event.ctrlKey) {
var hasCtrlKey = pskl.utils.UserAgent.isMac ? event.metaKey : event.ctrlKey;
if (!hasCtrlKey) {
this.superclass.applyToolAt.call(this, mirroredCol, row, color, frame, overlay);
}
if (event.shiftKey || event.ctrlKey) {
if (event.shiftKey || hasCtrlKey) {
this.superclass.applyToolAt.call(this, col, mirroredRow, color, frame, overlay);
}

View File

@@ -15,6 +15,12 @@
this.startRow = null;
this.selection = null;
this.tooltipDescriptors = [
{description : "Drag the selection to move it. You may switch to other layers and frames."},
{key : 'ctrl+c', description : 'Copy the selected area'},
{key : 'ctrl+v', description : 'Paste the copied area'}
];
};
pskl.utils.inherit(ns.BaseSelect, ns.BaseTool);

View File

@@ -8,7 +8,8 @@
ns.RectangleSelect = function() {
this.toolId = "tool-rectangle-select";
this.helpText = "Rectangle selection tool";
this.helpText = "Rectangle selection";
ns.BaseSelect.call(this);
this.hasSelection = false;

View File

@@ -8,7 +8,8 @@
ns.ShapeSelect = function() {
this.toolId = "tool-shape-select";
this.helpText = "Shape selection tool";
this.helpText = "Shape selection";
ns.BaseSelect.call(this);
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -37,11 +37,7 @@
var storeFrame = function (iframe) {
var script=document.createElement("script");
script.setAttribute("type", "text/html");
if (window.pskl && window.pskl.appEngineToken_) {
script.setAttribute("id", iframe.getAttribute("src").replace('../',''));
} else {
script.setAttribute("id", iframe.getAttribute("src"));
}
script.setAttribute("id", iframe.getAttribute("src").replace(/.*templates[^\/]*\//,'templates/'));
script.innerHTML = iframe.contentWindow.document.body.innerHTML;
iframe.parentNode.removeChild(iframe);
document.body.appendChild(script);
@@ -52,5 +48,5 @@
var iframe = event.target || event.srcElement;
processFrame(iframe);
}
}
};
})();

View File

@@ -84,28 +84,30 @@
return [this.id, this.version].join('-');
};
ns.Frame.prototype.setPixel = function (col, row, color) {
if (this.containsPixel(col, row)) {
var p = this.pixels[col][row];
ns.Frame.prototype.setPixel = function (x, y, color) {
if (this.containsPixel(x, y)) {
var p = this.pixels[x][y];
if (p !== color) {
this.pixels[col][row] = color;
this.pixels[x][y] = color;
this.version++;
}
}
};
ns.Frame.prototype.getPixel = function (col, row) {
if (this.containsPixel(col, row)) {
return this.pixels[col][row];
ns.Frame.prototype.getPixel = function (x, y) {
if (this.containsPixel(x, y)) {
return this.pixels[x][y];
} else {
return null;
}
};
ns.Frame.prototype.forEachPixel = function (callback) {
for (var col = 0 ; col < this.getWidth() ; col++) {
for (var row = 0 ; row < this.getHeight() ; row++) {
callback(this.getPixel(col, row), col, row);
var width = this.getWidth();
var height = this.getHeight();
for (var x = 0 ; x < width ; x++) {
for (var y = 0 ; y < height ; y++) {
callback(this.pixels[x][y], x, y, this);
}
}
};
@@ -122,29 +124,6 @@
return col >= 0 && row >= 0 && col < this.width && row < this.height;
};
ns.Frame.prototype.saveState = function () {
// remove all states past current state
this.previousStates.length = this.stateIndex + 1;
// push new state
this.previousStates.push(this.getPixels());
// set the stateIndex to latest saved state
this.stateIndex = this.previousStates.length - 1;
};
ns.Frame.prototype.loadPreviousState = function () {
if (this.stateIndex > 0) {
this.stateIndex--;
this.setPixels(this.previousStates[this.stateIndex]);
}
};
ns.Frame.prototype.loadNextState = function () {
if (this.stateIndex < this.previousStates.length - 1) {
this.stateIndex++;
this.setPixels(this.previousStates[this.stateIndex]);
}
};
ns.Frame.prototype.isSameSize = function (otherFrame) {
return this.getHeight() == otherFrame.getHeight() && this.getWidth() == otherFrame.getWidth();
};

View File

@@ -19,7 +19,6 @@
$.subscribe(Events.SELECTION_MOVE_REQUEST, $.proxy(this.onSelectionMoved_, this));
pskl.app.shortcutService.addShortcut('ctrl+V', this.paste.bind(this));
pskl.app.shortcutService.addShortcut('ctrl+shift+V', this.pasteOpaqueOnly.bind(this));
pskl.app.shortcutService.addShortcut('ctrl+X', this.cut.bind(this));
pskl.app.shortcutService.addShortcut('ctrl+C', this.copy.bind(this));
pskl.app.shortcutService.addShortcut('del', this.erase.bind(this));
@@ -92,13 +91,6 @@
};
ns.SelectionManager.prototype.paste = function() {
if(this.currentSelection && this.currentSelection.hasPastedContent) {
var pixels = this.currentSelection.pixels;
this.pastePixels(pixels);
}
};
ns.SelectionManager.prototype.pasteOpaqueOnly = function() {
if(this.currentSelection && this.currentSelection.hasPastedContent) {
var pixels = this.currentSelection.pixels;
var opaquePixels = pixels.filter(function (p) {

View File

@@ -55,6 +55,9 @@
};
ns.CheatsheetService.prototype.toDescriptor_ = function (shortcut, description, icon) {
if (pskl.utils.UserAgent.isMac) {
shortcut = shortcut.replace('ctrl', 'cmd');
}
return {
'shortcut' : shortcut,
'description' : description,
@@ -84,7 +87,7 @@
ns.CheatsheetService.prototype.initMarkupForTools_ = function () {
var descriptors = pskl.app.toolController.tools.map(function (tool) {
return this.toDescriptor_(tool.shortcut, tool.instance.helpText, 'tool-icon ' + tool.instance.toolId);
return this.toDescriptor_(tool.shortcut, tool.instance.getHelpText(), 'tool-icon ' + tool.instance.toolId);
}.bind(this));
this.initMarkupAbstract_(descriptors, '.cheatsheet-tool-shortcuts');

View File

@@ -107,7 +107,7 @@
};
ns.ShortcutService.prototype.isCtrlKeyPressed_ = function (evt) {
return this.isMac_() ? evt.metaKey : evt.ctrlKey;
return pskl.utils.UserAgent.isMac ? evt.metaKey : evt.ctrlKey;
};
ns.ShortcutService.prototype.isShiftKeyPressed_ = function (evt) {
@@ -117,8 +117,4 @@
ns.ShortcutService.prototype.isAltKeyPressed_ = function (evt) {
return evt.altKey;
};
ns.ShortcutService.prototype.isMac_ = function () {
return navigator.appVersion.indexOf("Mac") != -1;
};
})();

View File

@@ -1,14 +1,18 @@
(function () {
var ns = $.namespace("pskl.utils");
var templates = {};
ns.Template = {
get : function (templateId) {
var template = document.getElementById(templateId);
if (template) {
return template.innerHTML;
} else {
console.error("Could not find template for id :", templateId);
if (!templates[templateId]) {
var template = document.getElementById(templateId);
if (template) {
templates[templateId] = template.innerHTML;
} else {
console.error("Could not find template for id :", templateId);
}
}
return templates[templateId];
},
createFromHTML : function (html) {

View File

@@ -4,8 +4,10 @@
ns.UserAgent = {
isIE : /MSIE/i.test( ua ),
isIE11 : /trident/i.test( ua ),
isChrome : /Chrome/i.test( ua ),
isFirefox : /Firefox/i.test( ua )
isFirefox : /Firefox/i.test( ua ),
isMac : /Mac/.test( ua )
};
ns.UserAgent.version = (function () {

View File

@@ -1,9 +1,15 @@
(function () {
var version = '@@version';
var versionHasNotBeenReplaced = version.indexOf('@@') === 0;
if (versionHasNotBeenReplaced) {
version = '';
}
window.onPiskelReady = function () {
var loadingMask = document.getElementById('loading-mask');
loadingMask.style.opacity = 0;
window.setTimeout(function () {loadingMask.parentNode.removeChild(loadingMask);}, 600)
window.setTimeout(function () {loadingMask.parentNode.removeChild(loadingMask);}, 600);
pskl.app.init();
// cleanup
delete window.pskl_exports;
@@ -36,18 +42,18 @@
document.head.appendChild(link);
};
if (window.location.href.indexOf("debug") != -1) {
if (window.location.href.indexOf('debug') != -1) {
window.pskl_exports = {};
var scriptIndex = 0;
window.loadNextScript = function () {
if (scriptIndex == window.pskl_exports.scripts.length) {
window.onPiskelReady();
} else {
loadScript(window.pskl_exports.scripts[scriptIndex], "loadNextScript()");
loadScript(window.pskl_exports.scripts[scriptIndex], 'loadNextScript()');
scriptIndex ++;
}
};
loadScript("piskel-script-list.js", "loadNextScript()");
loadScript('piskel-script-list.js', 'loadNextScript()');
window.loadStyles = function () {
var styles = window.pskl_exports.styles;
@@ -55,22 +61,22 @@
loadStyle(styles[i]);
}
};
loadScript("piskel-style-list.js", "loadStyles()");
loadScript('piskel-style-list.js', 'loadStyles()');
} else {
var script;
if (window.location.href.indexOf("pack") != -1) {
script = "js/piskel-packaged.js";
if (window.location.href.indexOf('pack') != -1) {
script = 'js/piskel-packaged' + version + '.js';
} else {
script = "js/piskel-packaged-min.js";
script = 'js/piskel-packaged-min' + version + '.js';
}
loadStyle('css/piskel-style-packaged.css');
loadStyle('css/piskel-style-packaged' + version + '.css');
var loaderInterval = window.setInterval(function () {
if (document.querySelectorAll("[data-iframe-loader]").length === 0) {
if (document.querySelectorAll('[data-iframe-loader]').length === 0) {
window.clearInterval(loaderInterval);
loadScript(script, "onPiskelReady()");
loadScript(script, 'onPiskelReady()');
} else {
console.log("waiting for templates to load ....");
window.console.log('waiting for templates to load ....');
}
}, 100);
}

View File

@@ -4,17 +4,6 @@
// Core libraries
"js/lib/jquery-1.8.0.js","js/lib/jquery-ui-1.10.3.custom.js","js/lib/pubsub.js","js/lib/bootstrap/bootstrap.js",
// GIF Encoding libraries
"js/lib/gif/gif.worker.js",
"js/lib/gif/gif.js",
"js/lib/gif/libgif.js",
// JSZip https://github.com/Stuk/jszip
"js/lib/jszip/jszip.min.js",
// Spectrum color-picker library
"js/lib/spectrum/spectrum.js",
// Application wide configuration
"js/Constants.js",
"js/Events.js",
@@ -41,6 +30,17 @@
"js/utils/serialization/backward/Deserializer_v0.js",
"js/utils/serialization/backward/Deserializer_v1.js",
// GIF Encoding libraries
"js/lib/gif/gif.worker.js",
"js/lib/gif/gif.js",
"js/lib/gif/libgif.js",
// JSZip https://github.com/Stuk/jszip
"js/lib/jszip/jszip.min.js",
// Spectrum color-picker library
"js/lib/spectrum/spectrum.js",
// Application libraries-->
"js/rendering/DrawingLoop.js",
@@ -132,6 +132,7 @@
"js/drawingtools/selectiontools/RectangleSelect.js",
"js/drawingtools/selectiontools/ShapeSelect.js",
"js/drawingtools/ColorPicker.js",
"js/drawingtools/ColorSwap.js",
// Application controller and initialization
"js/app.js"
];

View File

@@ -1,10 +1,9 @@
<div class="sticky-section left-sticky-section" id="tool-section">
<div class="sticky-section-wrap">
<div class="vertical-centerer">
<script type="text/template" id="drawing-tool-item-template">
<li rel="tooltip" data-placement="right" class="{{cssclass}}" data-tool-id="{{toolid}}" title="{{title}}"></li>
</script>
<ul id="tools-container" class="tools-wrapper"></ul>
<ul id="tools-container" class="tools-wrapper">
<!-- Drawing tools will be inserted here -->
</ul>
<div class="palette-wrapper">
<div
class="tool-icon tool-color-picker"
@@ -31,4 +30,34 @@
</div>
</div>
</div>
<!-- Templates -->
<!-- Drawing tool icon-button -->
<script type="text/template" id="drawing-tool-item-template">
<li rel="tooltip" data-placement="right" class="{{cssclass}}" data-tool-id="{{toolid}}" title="{{title}}"></li>
</script>
<!-- Drawing tool tooltip container -->
<script type="text/template" id="drawing-tool-tooltip-container-template">
<div class='tools-tooltip-container'>
<div>{{helptext}} <span class='tools-tooltip-shortcut'>({{shortcut}})</span></div>
{{descriptors}}
</div>
</script>
<!-- Drawing tool tooltip line for modifier -->
<script type="text/template" id="drawing-tool-tooltip-descriptor-template">
<div class='tools-tooltip-descriptor'>
<span class='tools-tooltip-descriptor-button'>{{key}}</span>
{{description}}
</div>
</script>
<!-- Drawing tool tooltip line -->
<script type="text/template" id="drawing-tool-tooltip-descriptor-simple-template">
<div class='tools-tooltip-descriptor'>
{{description}}
</div>
</script>
</div>