mirror of
https://github.com/piskelapp/piskel.git
synced 2023-08-10 21:12:52 +03:00
Compare commits
29 Commits
keyboard-c
...
v0.14.0
Author | SHA1 | Date | |
---|---|---|---|
9d32a8c3aa | |||
64cd724139 | |||
dae08107e2 | |||
779761628e | |||
3e450c3d77 | |||
5c7070b01b | |||
7c215ebcbe | |||
bcee24609f | |||
f420c6f1fd | |||
76429dfd86 | |||
4ebf43fda4 | |||
2f2b4cd9ba | |||
dfb049bbf0 | |||
8c54108a9b | |||
3dd72f9781 | |||
80001eab0e | |||
5ecf351e0f | |||
407b432227 | |||
69cc27557e | |||
cfd3773a2b | |||
0eface45f1 | |||
87893bb4ac | |||
77d26bffa9 | |||
652027bd3f | |||
bf4cc3302a | |||
95c8df1224 | |||
7445357368 | |||
a2369cac0c | |||
51538dff48 |
28
Gruntfile.js
28
Gruntfile.js
@ -47,16 +47,13 @@ module.exports = function(grunt) {
|
||||
var integrationTestPaths = require('./test/casperjs/integration/IntegrationSuite.js').tests;
|
||||
var integrationTests = prefixPaths(integrationTestPaths, "test/casperjs/integration/");
|
||||
|
||||
var getConnectConfig = function (base, port, host) {
|
||||
if (typeof base === 'string') {
|
||||
base = [base];
|
||||
}
|
||||
|
||||
var getConnectConfig = function (base, port, host, open) {
|
||||
return {
|
||||
options: {
|
||||
port: port,
|
||||
hostname : host,
|
||||
base: base
|
||||
base: base,
|
||||
open: open
|
||||
}
|
||||
};
|
||||
};
|
||||
@ -98,18 +95,9 @@ module.exports = function(grunt) {
|
||||
*/
|
||||
|
||||
connect: {
|
||||
prod: getConnectConfig('dest/prod', PORT.PROD, hostname),
|
||||
test: getConnectConfig(['dest/dev', 'test'], PORT.TEST, hostname),
|
||||
dev: getConnectConfig(['dest/dev', 'test'], PORT.DEV, hostname)
|
||||
},
|
||||
|
||||
open : {
|
||||
prod : {
|
||||
path : 'http://' + hostname + ':' + PORT.PROD + '/'
|
||||
},
|
||||
dev : {
|
||||
path : 'http://' + hostname + ':' + PORT.DEV + '/?debug'
|
||||
}
|
||||
prod: getConnectConfig('dest/prod', PORT.PROD, hostname, true),
|
||||
test: getConnectConfig(['dest/dev', 'test'], PORT.TEST, hostname, false),
|
||||
dev: getConnectConfig(['dest/dev', 'test'], PORT.DEV, hostname, 'http://' + hostname + ':' + PORT.DEV + '/?debug')
|
||||
},
|
||||
|
||||
watch: {
|
||||
@ -343,9 +331,9 @@ module.exports = function(grunt) {
|
||||
|
||||
// SERVER TASKS
|
||||
// Start webserver and watch for changes
|
||||
grunt.registerTask('serve', ['build', 'connect:prod', 'open:prod', 'watch:prod']);
|
||||
grunt.registerTask('serve', ['build', 'connect:prod', 'watch:prod']);
|
||||
// Start webserver on src folder, in debug mode
|
||||
grunt.registerTask('play', ['build-dev', 'connect:dev', 'open:dev', 'watch:dev']);
|
||||
grunt.registerTask('play', ['build-dev', 'connect:dev', 'watch:dev']);
|
||||
|
||||
// ALIASES, kept for backward compatibility
|
||||
grunt.registerTask('serve-debug', ['play']);
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "piskel",
|
||||
"version": "0.12.1",
|
||||
"version": "0.14.0",
|
||||
"description": "Pixel art editor",
|
||||
"author": "Julian Descottes <julian.descottes@gmail.com>",
|
||||
"contributors": [
|
||||
@ -45,7 +45,6 @@
|
||||
"grunt-karma": "1.0.0",
|
||||
"grunt-leading-indent": "0.2.0",
|
||||
"grunt-nw-builder": "3.1.0",
|
||||
"grunt-open": "0.2.3",
|
||||
"grunt-replace": "1.0.1",
|
||||
"grunt-spritesmith": "6.4.0",
|
||||
"jasmine-core": "2.6.1",
|
||||
|
@ -56,8 +56,7 @@
|
||||
height: 90px;
|
||||
}
|
||||
|
||||
.browse-backups .session-list-empty,
|
||||
.browse-backups .snapshot-list-empty {
|
||||
.browse-backups .centered-message {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
width: 200px;
|
||||
@ -68,9 +67,18 @@
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
border: 1px solid;
|
||||
}
|
||||
|
||||
.browse-backups .session-list-empty,
|
||||
.browse-backups .snapshot-list-empty {
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.browse-backups .session-list-error,
|
||||
.browse-backups .snapshot-list-error {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.browse-backups .session-item {
|
||||
/* Transition duration should be kept in sync with SelectSession.DELETE_TRANSITION_DURATION */
|
||||
transition: all 500ms;
|
||||
|
18
src/css/dialogs-import.css
vendored
18
src/css/dialogs-import.css
vendored
@ -183,22 +183,14 @@
|
||||
.import-meta-value,
|
||||
.import-meta-label {
|
||||
padding: 2px 4px;
|
||||
border: 1px solid gold;
|
||||
}
|
||||
|
||||
.import-meta-label {
|
||||
border-radius: 2px 0 0 2px;
|
||||
color: var(--highlight-color);
|
||||
border-right-width: 0;
|
||||
}
|
||||
|
||||
.import-meta-title .import-meta-label {
|
||||
border-right-width: 1px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.import-meta-value {
|
||||
border-radius: 0 2px 2px 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
@ -242,7 +234,7 @@
|
||||
.insert-mode-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 5px;
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.import-resize-option :checked + span,
|
||||
@ -250,11 +242,15 @@
|
||||
color: var(--highlight-color);
|
||||
}
|
||||
|
||||
.import-resize-option input,
|
||||
.insert-mode-option input {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
/**
|
||||
* ADJUST SIZE
|
||||
*/
|
||||
.import-resize-anchor-info,
|
||||
.import-resize-option-label {
|
||||
.import-resize-anchor-info {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
|
@ -80,10 +80,16 @@
|
||||
}
|
||||
|
||||
.cursor-coordinates {
|
||||
color:#888;
|
||||
font-size:12px;
|
||||
font-weight:bold;
|
||||
font-family:monospace;
|
||||
color: var(--highlight-color);
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.cursor-coordinates .drawing-zoom {
|
||||
position: absolute;
|
||||
top: -20px;
|
||||
left: 1px;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -60,22 +60,48 @@
|
||||
}
|
||||
|
||||
.settings-item-grid-size,
|
||||
.settings-item-grid-spacing,
|
||||
.settings-item-grid-color {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.settings-item-grid-size > label,
|
||||
.settings-item-grid-spacing > label,
|
||||
.settings-item-grid-color > label {
|
||||
width: 65px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.settings-item-grid-size .size-picker-option {
|
||||
.grid-spacing-container .size-picker-option[data-size='1'] {
|
||||
padding: 7px;
|
||||
}
|
||||
.grid-spacing-container .size-picker-option[data-size='2'] {
|
||||
padding: 6px;
|
||||
}
|
||||
.grid-spacing-container .size-picker-option[data-size='4'] {
|
||||
padding: 5px;
|
||||
}
|
||||
.grid-spacing-container .size-picker-option[data-size='8'] {
|
||||
padding: 4px;
|
||||
}
|
||||
.grid-spacing-container .size-picker-option[data-size='16'] {
|
||||
padding: 3px;
|
||||
}
|
||||
.grid-spacing-container .size-picker-option[data-size='32'] {
|
||||
padding: 2px;
|
||||
}
|
||||
.grid-spacing-container .size-picker-option[data-size='64'] {
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.settings-item-grid-size .size-picker-option,
|
||||
.settings-item-grid-spacing .size-picker-option {
|
||||
border-color: #888;
|
||||
}
|
||||
|
||||
.settings-item-grid-size .size-picker-option:not(.selected):hover {
|
||||
.settings-item-grid-size .size-picker-option:not(.selected):hover,
|
||||
.settings-item-grid-spacing .size-picker-option:not(.selected):hover {
|
||||
border-color: white;
|
||||
}
|
||||
|
||||
@ -131,4 +157,4 @@
|
||||
.settings-version:hover {
|
||||
color: white !important;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,12 @@ body {
|
||||
}
|
||||
|
||||
.checkbox-fix {
|
||||
margin-left: 0;
|
||||
margin: 3px 3px 3px 0;
|
||||
}
|
||||
|
||||
.checkbox-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
|
@ -17,6 +17,7 @@
|
||||
$.subscribe(Events.DRAG_START, this.onDragStart_.bind(this));
|
||||
$.subscribe(Events.DRAG_END, this.onDragEnd_.bind(this));
|
||||
$.subscribe(Events.FRAME_SIZE_CHANGED, this.redraw.bind(this));
|
||||
$.subscribe(Events.ZOOM_CHANGED, this.redraw.bind(this));
|
||||
|
||||
this.redraw();
|
||||
};
|
||||
@ -39,6 +40,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (pskl.app.drawingController) {
|
||||
var zoom = pskl.app.drawingController.compositeRenderer.getZoom().toFixed(2);
|
||||
html += '<div class="drawing-zoom">x' + zoom + '</div>';
|
||||
}
|
||||
|
||||
this.coordinatesContainer.innerHTML = this.getFrameSizeHTML_() + html;
|
||||
};
|
||||
|
||||
|
@ -39,31 +39,36 @@
|
||||
|
||||
ns.SelectSession.prototype.update = function () {
|
||||
pskl.app.backupService.list().then(function (sessions) {
|
||||
var html = '';
|
||||
if (sessions.length === 0) {
|
||||
html = pskl.utils.Template.get('session-list-empty');
|
||||
} else {
|
||||
var sessionItemTemplate = pskl.utils.Template.get('session-list-item');
|
||||
var html = '';
|
||||
sessions.forEach(function (session) {
|
||||
if (session.id === pskl.app.sessionId) {
|
||||
// Do not show backups for the current session.
|
||||
return;
|
||||
}
|
||||
var view = {
|
||||
id: session.id,
|
||||
name: session.name,
|
||||
description: session.description ? '- ' + session.description : '',
|
||||
date: pskl.utils.DateUtils.format(session.endDate, 'the {{Y}}/{{M}}/{{D}} at {{H}}:{{m}}'),
|
||||
count: session.count === 1 ? '1 snapshot' : session.count + ' snapshots'
|
||||
};
|
||||
html += pskl.utils.Template.replace(sessionItemTemplate, view);
|
||||
});
|
||||
}
|
||||
var html = this.getMarkupForSessions_(sessions);
|
||||
this.container.querySelector('.session-list').innerHTML = html;
|
||||
}.bind(this)).catch(function () {
|
||||
var html = pskl.utils.Template.get('session-list-error');
|
||||
this.container.querySelector('.session-list').innerHTML = html;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
ns.SelectSession.prototype.getMarkupForSessions_ = function (sessions) {
|
||||
if (sessions.length === 0) {
|
||||
return pskl.utils.Template.get('session-list-empty');
|
||||
}
|
||||
|
||||
var sessionItemTemplate = pskl.utils.Template.get('session-list-item');
|
||||
return sessions.reduce(function (previous, session) {
|
||||
if (session.id === pskl.app.sessionId) {
|
||||
// Do not show backups for the current session.
|
||||
return previous;
|
||||
}
|
||||
var view = {
|
||||
id: session.id,
|
||||
name: session.name,
|
||||
description: session.description ? '- ' + session.description : '',
|
||||
date: pskl.utils.DateUtils.format(session.endDate, 'the {{Y}}/{{M}}/{{D}} at {{H}}:{{m}}'),
|
||||
count: session.count === 1 ? '1 snapshot' : session.count + ' snapshots'
|
||||
};
|
||||
return previous + pskl.utils.Template.replace(sessionItemTemplate, view);
|
||||
}, '');
|
||||
};
|
||||
|
||||
ns.SelectSession.prototype.destroy = function () {
|
||||
pskl.utils.Event.removeAllEventListeners(this);
|
||||
};
|
||||
|
@ -27,33 +27,42 @@
|
||||
ns.SessionDetails.prototype.onShow = function () {
|
||||
var sessionId = this.backupsController.backupsData.selectedSession;
|
||||
pskl.app.backupService.getSnapshotsBySessionId(sessionId).then(function (snapshots) {
|
||||
var html = '';
|
||||
if (snapshots.length === 0) {
|
||||
// This should normally never happen, all sessions have at least one snapshot and snapshots
|
||||
// can not be individually deleted.
|
||||
console.warn('Could not retrieve snapshots for a session');
|
||||
html = pskl.utils.Template.get('snapshot-list-empty');
|
||||
} else {
|
||||
var sessionItemTemplate = pskl.utils.Template.get('snapshot-list-item');
|
||||
var html = '';
|
||||
snapshots.forEach(function (snapshot) {
|
||||
var view = {
|
||||
id: snapshot.id,
|
||||
name: snapshot.name,
|
||||
description: snapshot.description ? '- ' + snapshot.description : '',
|
||||
date: pskl.utils.DateUtils.format(snapshot.date, 'the {{Y}}/{{M}}/{{D}} at {{H}}:{{m}}'),
|
||||
frames: snapshot.frames === 1 ? '1 frame' : snapshot.frames + ' frames',
|
||||
resolution: pskl.utils.StringUtils.formatSize(snapshot.width, snapshot.height),
|
||||
fps: snapshot.fps
|
||||
};
|
||||
html += pskl.utils.Template.replace(sessionItemTemplate, view);
|
||||
this.updateSnapshotPreview_(snapshot);
|
||||
}.bind(this));
|
||||
}
|
||||
var html = this.getMarkupForSnapshots_(snapshots);
|
||||
this.container.querySelector('.snapshot-list').innerHTML = html;
|
||||
|
||||
// Load the image of the first frame for each sprite and update the list.
|
||||
snapshots.forEach(function (snapshot) {
|
||||
this.updateSnapshotPreview_(snapshot);
|
||||
}.bind(this));
|
||||
}.bind(this)).catch(function () {
|
||||
var html = pskl.utils.Template.get('snapshot-list-error');
|
||||
this.container.querySelector('.snapshot-list').innerHTML = html;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
ns.SessionDetails.prototype.getMarkupForSnapshots_ = function (snapshots) {
|
||||
if (snapshots.length === 0) {
|
||||
// This should normally never happen, all sessions have at least one snapshot and snapshots
|
||||
// can not be individually deleted.
|
||||
console.warn('Could not retrieve snapshots for a session');
|
||||
return pskl.utils.Template.get('snapshot-list-empty');
|
||||
}
|
||||
|
||||
var sessionItemTemplate = pskl.utils.Template.get('snapshot-list-item');
|
||||
return snapshots.reduce(function (previous, snapshot) {
|
||||
var view = {
|
||||
id: snapshot.id,
|
||||
name: snapshot.name,
|
||||
description: snapshot.description ? '- ' + snapshot.description : '',
|
||||
date: pskl.utils.DateUtils.format(snapshot.date, 'the {{Y}}/{{M}}/{{D}} at {{H}}:{{m}}'),
|
||||
frames: snapshot.frames === 1 ? '1 frame' : snapshot.frames + ' frames',
|
||||
resolution: pskl.utils.StringUtils.formatSize(snapshot.width, snapshot.height),
|
||||
fps: snapshot.fps
|
||||
};
|
||||
return previous + pskl.utils.Template.replace(sessionItemTemplate, view);
|
||||
}, '');
|
||||
};
|
||||
|
||||
ns.SessionDetails.prototype.updateSnapshotPreview_ = function (snapshot) {
|
||||
pskl.utils.serialization.Deserializer.deserialize(
|
||||
JSON.parse(snapshot.serialized),
|
||||
|
@ -80,7 +80,13 @@
|
||||
var step = this.wizard.getCurrentStep();
|
||||
|
||||
if (step.name === 'IMAGE_IMPORT') {
|
||||
this.wizard.goTo('SELECT_MODE');
|
||||
if (this.piskelController.isEmpty()) {
|
||||
// If the current sprite is empty finalize immediately and replace the current sprite.
|
||||
this.mergeData.importMode = ns.steps.SelectMode.MODES.REPLACE;
|
||||
this.finalizeImport_();
|
||||
} else {
|
||||
this.wizard.goTo('SELECT_MODE');
|
||||
}
|
||||
} else if (step.name === 'SELECT_MODE') {
|
||||
if (this.mergeData.importMode === ns.steps.SelectMode.MODES.REPLACE) {
|
||||
this.finalizeImport_();
|
||||
|
@ -69,16 +69,15 @@
|
||||
var anchorInfo = this.container.querySelector('.import-resize-anchor-info');
|
||||
if (isBigger && keep) {
|
||||
anchorInfo.innerHTML = [
|
||||
'<span class="import-resize-warning">',
|
||||
'<div class="import-resize-warning">',
|
||||
' Imported content will be cropped!',
|
||||
'</span>',
|
||||
' ',
|
||||
'Select crop origin'
|
||||
'</div>',
|
||||
'Select crop anchor:'
|
||||
].join('');
|
||||
} else if (isBigger) {
|
||||
anchorInfo.innerHTML = 'Select the anchor for resizing the canvas';
|
||||
anchorInfo.innerHTML = 'Select resize anchor:';
|
||||
} else {
|
||||
anchorInfo.innerHTML = 'Select where the import should be positioned';
|
||||
anchorInfo.innerHTML = 'Select position anchor:';
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -42,12 +42,17 @@
|
||||
this.addEventListener(this.frameOffsetY, 'keyup', this.onFrameInputKeyUp_);
|
||||
|
||||
pskl.utils.FileUtils.readImageFile(this.file_, this.onImageLoaded_.bind(this));
|
||||
|
||||
if (this.piskelController.isEmpty()) {
|
||||
this.nextButton.textContent = 'import';
|
||||
}
|
||||
};
|
||||
|
||||
ns.ImageImport.prototype.onNextClick = function () {
|
||||
this.container.classList.add('import-image-loading');
|
||||
this.createPiskelFromImage().then(function (piskel) {
|
||||
this.mergeData.mergePiskel = piskel;
|
||||
this.container.classList.remove('import-image-loading');
|
||||
this.superclass.onNextClick.call(this);
|
||||
}.bind(this)).catch(function (e) {
|
||||
console.error(e);
|
||||
@ -257,9 +262,7 @@
|
||||
context.lineTo(maxWidth * scaleX, y * scaleY);
|
||||
}
|
||||
|
||||
// Set the line style to dashed
|
||||
context.lineWidth = 1;
|
||||
// context.setLineDash([2, 1]);
|
||||
context.strokeStyle = 'gold';
|
||||
context.stroke();
|
||||
|
||||
|
@ -297,4 +297,12 @@
|
||||
ns.PiskelController.prototype.serialize = function () {
|
||||
return pskl.utils.serialization.Serializer.serialize(this.piskel);
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the current sprite is empty. Emptiness here means no pixel has been filled
|
||||
* on any layer or frame for the current sprite.
|
||||
*/
|
||||
ns.PiskelController.prototype.isEmpty = function () {
|
||||
return pskl.app.currentColorsService.getCurrentColors().length === 0;
|
||||
};
|
||||
})();
|
||||
|
@ -18,9 +18,14 @@
|
||||
this.previewContainerEl = document.querySelector('.gif-export-preview');
|
||||
this.uploadButton = document.querySelector('.gif-upload-button');
|
||||
this.downloadButton = document.querySelector('.gif-download-button');
|
||||
this.repeatCheckbox = document.querySelector('.gif-repeat-checkbox');
|
||||
|
||||
// Initialize repeatCheckbox state
|
||||
this.repeatCheckbox.checked = this.getRepeatSetting_();
|
||||
|
||||
this.addEventListener(this.uploadButton, 'click', this.onUploadButtonClick_);
|
||||
this.addEventListener(this.downloadButton, 'click', this.onDownloadButtonClick_);
|
||||
this.addEventListener(this.repeatCheckbox, 'change', this.onRepeatCheckboxChange_);
|
||||
|
||||
var currentColors = pskl.app.currentColorsService.getCurrentColors();
|
||||
var tooManyColors = currentColors.length >= MAX_GIF_COLORS;
|
||||
@ -108,6 +113,7 @@
|
||||
width: width * zoom,
|
||||
height: height * zoom,
|
||||
preserveColors : preserveColors,
|
||||
repeat: this.getRepeatSetting_() ? 0 : -1,
|
||||
transparent : transparent
|
||||
});
|
||||
|
||||
@ -152,6 +158,15 @@
|
||||
return transparentColor;
|
||||
};
|
||||
|
||||
ns.GifExportController.prototype.onRepeatCheckboxChange_ = function () {
|
||||
var checked = this.repeatCheckbox.checked;
|
||||
pskl.UserSettings.set(pskl.UserSettings.EXPORT_GIF_REPEAT, checked);
|
||||
};
|
||||
|
||||
ns.GifExportController.prototype.getRepeatSetting_ = function () {
|
||||
return pskl.UserSettings.get(pskl.UserSettings.EXPORT_GIF_REPEAT);
|
||||
};
|
||||
|
||||
ns.GifExportController.prototype.updateStatus_ = function (imageUrl, error) {
|
||||
if (imageUrl) {
|
||||
var linkTpl = '<a class="highlight" href="{{link}}" target="_blank">{{shortLink}}</a>';
|
||||
|
@ -12,12 +12,25 @@
|
||||
this.pngFilePrefixInput = document.querySelector('.zip-prefix-name');
|
||||
this.pngFilePrefixInput.value = 'sprite_';
|
||||
|
||||
this.splitByLayersCheckbox = document.querySelector('.zip-split-layers-checkbox');
|
||||
this.splitByLayersCheckbox = document.querySelector('.zip-split-layers-checkbox');
|
||||
this.addEventListener(this.splitByLayersCheckbox, 'change', this.onSplitLayersClick_);
|
||||
|
||||
this.useLayerNamesContainer = document.querySelector('.use-layer-names-container');
|
||||
this.useLayerNamesCheckbox = document.querySelector('.zip-use-layer-names-checkbox');
|
||||
this.toggleHideUseLayerNamesCheckbox();
|
||||
|
||||
var zipButton = document.querySelector('.zip-generate-button');
|
||||
this.addEventListener(zipButton, 'click', this.onZipButtonClick_);
|
||||
};
|
||||
|
||||
ns.ZipExportController.prototype.toggleHideUseLayerNamesCheckbox = function () {
|
||||
this.useLayerNamesContainer.style.display = (this.splitByLayersCheckbox.checked ? 'block' : 'none');
|
||||
};
|
||||
|
||||
ns.ZipExportController.prototype.onSplitLayersClick_ = function () {
|
||||
this.toggleHideUseLayerNamesCheckbox();
|
||||
};
|
||||
|
||||
ns.ZipExportController.prototype.onZipButtonClick_ = function () {
|
||||
var zip = new window.JSZip();
|
||||
|
||||
@ -63,6 +76,9 @@
|
||||
var basename = this.pngFilePrefixInput.value;
|
||||
var frameid = pskl.utils.StringUtils.leftPad(i + 1, framePaddingLength, '0');
|
||||
var filename = 'l' + layerid + '_' + basename + frameid + '.png';
|
||||
if (this.useLayerNamesCheckbox.checked) {
|
||||
filename = layer.getName() + '_' + basename + frameid + '.png';
|
||||
}
|
||||
zip.file(filename, pskl.utils.CanvasUtils.getBase64FromCanvas(canvas) + '\n', {base64: true});
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
this.piskelController = piskelController;
|
||||
this.preferencesController = preferencesController;
|
||||
this.sizePicker = new pskl.widgets.SizePicker(this.onSizePickerChanged_.bind(this));
|
||||
this.spacingPicker = new pskl.widgets.SizePicker(this.onSpacingPickerChanged_.bind(this));
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.GridPreferencesController, pskl.controller.settings.AbstractSettingController);
|
||||
@ -40,6 +41,11 @@
|
||||
this.sizePicker.init(document.querySelector('.grid-size-container'));
|
||||
this.sizePicker.setSize(gridWidth);
|
||||
|
||||
//Grid Spacing
|
||||
var gridSpacing = pskl.UserSettings.get(pskl.UserSettings.GRID_SPACING);
|
||||
this.spacingPicker.init(document.querySelector('.grid-spacing-container'));
|
||||
this.spacingPicker.setSize(gridSpacing);
|
||||
|
||||
// Grid color
|
||||
var colorListItemTemplate = pskl.utils.Template.get('color-list-item-template');
|
||||
|
||||
@ -68,6 +74,7 @@
|
||||
|
||||
ns.GridPreferencesController.prototype.destroy = function () {
|
||||
this.sizePicker.destroy();
|
||||
this.spacingPicker.destroy();
|
||||
this.superclass.destroy.call(this);
|
||||
};
|
||||
|
||||
@ -75,6 +82,10 @@
|
||||
pskl.UserSettings.set(pskl.UserSettings.GRID_WIDTH, size);
|
||||
};
|
||||
|
||||
ns.GridPreferencesController.prototype.onSpacingPickerChanged_ = function (size) {
|
||||
pskl.UserSettings.set(pskl.UserSettings.GRID_SPACING, size);
|
||||
};
|
||||
|
||||
ns.GridPreferencesController.prototype.onEnableGridChange_ = function (evt) {
|
||||
pskl.UserSettings.set(pskl.UserSettings.GRID_ENABLED, evt.currentTarget.checked);
|
||||
};
|
||||
|
@ -29,9 +29,7 @@
|
||||
return _requestPromise(request).then(function (event) {
|
||||
this.db = event.target.result;
|
||||
return this.db;
|
||||
}.bind(this)).catch(function (e) {
|
||||
console.log('Failed to initialize IndexedDB, local browser saves will be unavailable.');
|
||||
});
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
ns.PiskelDatabase.prototype.onUpgradeNeeded_ = function (event) {
|
||||
|
@ -32,6 +32,7 @@
|
||||
};
|
||||
|
||||
ns.DrawingTestPlayer.prototype.setupInitialState_ = function () {
|
||||
|
||||
var size = this.initialState.size;
|
||||
var piskel = this.createPiskel_(size.width, size.height);
|
||||
pskl.app.piskelController.setPiskel(piskel);
|
||||
@ -39,9 +40,10 @@
|
||||
$.publish(Events.SELECT_PRIMARY_COLOR, [this.initialState.primaryColor]);
|
||||
$.publish(Events.SELECT_SECONDARY_COLOR, [this.initialState.secondaryColor]);
|
||||
$.publish(Events.SELECT_TOOL, [this.initialState.selectedTool]);
|
||||
if (this.initialState.penSize) {
|
||||
pskl.app.penSizeService.setPenSize(this.initialState.penSize);
|
||||
}
|
||||
|
||||
// Old tests do not have penSize stored in initialState, fallback to 1.
|
||||
var penSize = this.initialState.penSize || 1;
|
||||
pskl.app.penSizeService.setPenSize(this.initialState.penSize);
|
||||
};
|
||||
|
||||
ns.DrawingTestPlayer.prototype.createPiskel_ = function (width, height) {
|
||||
|
@ -34,6 +34,7 @@
|
||||
var serializedFrame = [
|
||||
this.getZoom(),
|
||||
this.getGridWidth(),
|
||||
this.getGridSpacing(),
|
||||
this.getGridColor(),
|
||||
pskl.UserSettings.get('SEAMLESS_MODE'),
|
||||
pskl.UserSettings.get('SEAMLESS_OPACITY'),
|
||||
|
@ -56,6 +56,7 @@
|
||||
this.setDisplaySize(renderingOptions.width, renderingOptions.height);
|
||||
|
||||
this.setGridWidth(this.getUserGridWidth_());
|
||||
this.setGridSpacing(this.getUserGridSpacing_());
|
||||
|
||||
$.subscribe(Events.USER_SETTINGS_CHANGED, this.onUserSettingsChange_.bind(this));
|
||||
};
|
||||
@ -146,6 +147,10 @@
|
||||
this.gridWidth_ = value;
|
||||
};
|
||||
|
||||
ns.FrameRenderer.prototype.setGridSpacing = function (value) {
|
||||
this.gridSpacing_ = value;
|
||||
};
|
||||
|
||||
ns.FrameRenderer.prototype.getGridWidth = function () {
|
||||
if (!this.supportGridRendering) {
|
||||
return 0;
|
||||
@ -154,15 +159,29 @@
|
||||
return this.gridWidth_;
|
||||
};
|
||||
|
||||
ns.FrameRenderer.prototype.getGridSpacing = function () {
|
||||
if (!this.supportGridRendering) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this.gridSpacing_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compute a grid width value best suited to the current display context,
|
||||
* particularly for the current zoom level
|
||||
*/
|
||||
ns.FrameRenderer.prototype.computeGridWidthForDisplay_ = function () {
|
||||
var gridSpacing = this.getGridSpacing();
|
||||
if (this.zoom * gridSpacing < 6) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var gridWidth = this.getGridWidth();
|
||||
while (this.zoom < 6 * gridWidth) {
|
||||
while (gridWidth > 1 && this.zoom < 6 * gridWidth) {
|
||||
gridWidth--;
|
||||
}
|
||||
|
||||
return gridWidth;
|
||||
};
|
||||
|
||||
@ -185,8 +204,11 @@
|
||||
|
||||
ns.FrameRenderer.prototype.onUserSettingsChange_ = function (evt, settingName, settingValue) {
|
||||
var settings = pskl.UserSettings;
|
||||
if (settingName == settings.GRID_WIDTH || settingName == settings.GRID_ENABLED) {
|
||||
if (settingName == settings.GRID_WIDTH ||
|
||||
settingName == settings.GRID_SPACING ||
|
||||
settingName == settings.GRID_ENABLED) {
|
||||
this.setGridWidth(this.getUserGridWidth_());
|
||||
this.setGridSpacing(this.getUserGridSpacing_());
|
||||
}
|
||||
};
|
||||
|
||||
@ -196,6 +218,12 @@
|
||||
return gridEnabled ? width : 0;
|
||||
};
|
||||
|
||||
ns.FrameRenderer.prototype.getUserGridSpacing_ = function () {
|
||||
var gridEnabled = pskl.UserSettings.get(pskl.UserSettings.GRID_ENABLED);
|
||||
var spacing = pskl.UserSettings.get(pskl.UserSettings.GRID_SPACING);
|
||||
return gridEnabled ? spacing : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Transform a screen pixel-based coordinate (relative to the top-left corner of the rendered
|
||||
* frame) into a sprite coordinate in column and row.
|
||||
@ -298,6 +326,7 @@
|
||||
|
||||
// Draw grid.
|
||||
var gridWidth = this.computeGridWidthForDisplay_();
|
||||
var gridSpacing = this.getGridSpacing();
|
||||
if (gridWidth > 0) {
|
||||
var gridColor = this.getGridColor();
|
||||
// Scale out before drawing the grid.
|
||||
@ -313,11 +342,15 @@
|
||||
|
||||
// Draw or clear vertical lines.
|
||||
for (var i = 1 ; i < frame.getWidth() ; i++) {
|
||||
drawOrClear((i * z) - (gridWidth / 2), 0, gridWidth, h * z);
|
||||
if (i % gridSpacing == 0) {
|
||||
drawOrClear((i * z) - (gridWidth / 2), 0, gridWidth, h * z);
|
||||
}
|
||||
}
|
||||
// Draw or clear horizontal lines.
|
||||
for (var j = 1 ; j < frame.getHeight() ; j++) {
|
||||
drawOrClear(0, (j * z) - (gridWidth / 2), w * z, gridWidth);
|
||||
if (j % gridSpacing == 0) {
|
||||
drawOrClear(0, (j * z) - (gridWidth / 2), w * z, gridWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
*/
|
||||
ns.PerformanceReport = function (piskel, colorsCount) {
|
||||
var pixels = piskel.getWidth() * piskel.getHeight();
|
||||
this.resolution = pixels > (500 * 500);
|
||||
this.resolution = pixels > (512 * 512);
|
||||
|
||||
var layersCount = piskel.getLayers().length;
|
||||
this.layers = layersCount > 25;
|
||||
@ -24,10 +24,10 @@
|
||||
var framesCount = piskel.getLayerAt(0).size();
|
||||
this.frames = framesCount > 100;
|
||||
|
||||
this.colors = colorsCount > 100;
|
||||
this.colors = colorsCount >= 256;
|
||||
|
||||
var overallScore = (pixels / 2500) + (layersCount * 4) + framesCount + colorsCount;
|
||||
this.overall = overallScore > 100;
|
||||
var overallScore = (pixels / 2620) + (layersCount * 4) + framesCount + (colorsCount * 100 / 256);
|
||||
this.overall = overallScore > 200;
|
||||
};
|
||||
|
||||
ns.PerformanceReport.prototype.equals = function (report) {
|
||||
|
@ -7,7 +7,9 @@
|
||||
};
|
||||
|
||||
ns.IndexedDbStorageService.prototype.init = function () {
|
||||
this.piskelDatabase.init();
|
||||
this.piskelDatabase.init().catch(function (e) {
|
||||
console.log('Failed to initialize PiskelDatabase, local browser saves will be unavailable.');
|
||||
});
|
||||
};
|
||||
|
||||
ns.IndexedDbStorageService.prototype.save = function (piskel) {
|
||||
@ -30,7 +32,7 @@
|
||||
};
|
||||
|
||||
ns.IndexedDbStorageService.prototype.load = function (name) {
|
||||
this.piskelDatabase.get(name).then(function (piskelData) {
|
||||
return this.piskelDatabase.get(name).then(function (piskelData) {
|
||||
if (typeof piskelData !== 'undefined') {
|
||||
var serialized = piskelData.serialized;
|
||||
pskl.utils.serialization.Deserializer.deserialize(
|
||||
@ -46,7 +48,7 @@
|
||||
};
|
||||
|
||||
ns.IndexedDbStorageService.prototype.remove = function (name) {
|
||||
this.piskelDatabase.delete(name);
|
||||
return this.piskelDatabase.delete(name);
|
||||
};
|
||||
|
||||
ns.IndexedDbStorageService.prototype.getKeys = function () {
|
||||
|
@ -44,10 +44,17 @@
|
||||
};
|
||||
|
||||
ns.VerticalMirrorPen.prototype.getSymmetricCol_ = function(col, frame) {
|
||||
return frame.getWidth() - col - 1;
|
||||
return frame.getWidth() - col - this.getPenSizeOffset_();
|
||||
};
|
||||
|
||||
ns.VerticalMirrorPen.prototype.getSymmetricRow_ = function(row, frame) {
|
||||
return frame.getHeight() - row - 1;
|
||||
return frame.getHeight() - row - this.getPenSizeOffset_();
|
||||
};
|
||||
|
||||
/**
|
||||
* Depending on the pen size, the mirrored index need to have an offset of 1 pixel.
|
||||
*/
|
||||
ns.VerticalMirrorPen.prototype.getPenSizeOffset_ = function(row, frame) {
|
||||
return pskl.app.penSizeService.getPenSize() % 2;
|
||||
};
|
||||
})();
|
||||
|
@ -5,6 +5,7 @@
|
||||
GRID_COLOR : 'GRID_COLOR',
|
||||
GRID_ENABLED : 'GRID_ENABLED',
|
||||
GRID_WIDTH : 'GRID_WIDTH',
|
||||
GRID_SPACING : 'GRID_SPACING',
|
||||
MAX_FPS : 'MAX_FPS',
|
||||
DEFAULT_SIZE : 'DEFAULT_SIZE',
|
||||
CANVAS_BACKGROUND : 'CANVAS_BACKGROUND',
|
||||
@ -17,6 +18,7 @@
|
||||
LAYER_OPACITY : 'LAYER_OPACITY',
|
||||
EXPORT_SCALE: 'EXPORT_SCALE',
|
||||
EXPORT_TAB: 'EXPORT_TAB',
|
||||
EXPORT_GIF_REPEAT: 'EXPORT_GIF_REPEAT',
|
||||
PEN_SIZE : 'PEN_SIZE',
|
||||
RESIZE_SETTINGS: 'RESIZE_SETTINGS',
|
||||
COLOR_FORMAT: 'COLOR_FORMAT',
|
||||
@ -26,6 +28,7 @@
|
||||
'GRID_COLOR' : Constants.TRANSPARENT_COLOR,
|
||||
'GRID_ENABLED' : false,
|
||||
'GRID_WIDTH' : 1,
|
||||
'GRID_SPACING' : 1,
|
||||
'MAX_FPS' : 24,
|
||||
'DEFAULT_SIZE' : {
|
||||
width : Constants.DEFAULT.WIDTH,
|
||||
@ -41,6 +44,7 @@
|
||||
'LAYER_PREVIEW' : true,
|
||||
'EXPORT_SCALE' : 1,
|
||||
'EXPORT_TAB' : 'gif',
|
||||
'EXPORT_GIF_REPEAT' : true,
|
||||
'PEN_SIZE' : 1,
|
||||
'RESIZE_SETTINGS': {
|
||||
maintainRatio : true,
|
||||
|
@ -27,10 +27,9 @@
|
||||
pskl.utils.Dom.removeClass('labeled', this.container);
|
||||
pskl.utils.Dom.removeClass('selected', this.container);
|
||||
var selectedOption;
|
||||
if (size <= 4) {
|
||||
selectedOption = this.container.querySelector('[data-size="' + size + '"]');
|
||||
} else {
|
||||
selectedOption = this.container.querySelector('[data-size="4"]');
|
||||
selectedOption = this.container.querySelector('[data-size="' + size + '"]');
|
||||
if (typeof selectedOption === 'undefined') {
|
||||
selectedOption = this.container.querySelector('[data-size]:last-child');
|
||||
selectedOption.classList.add('labeled');
|
||||
selectedOption.setAttribute('real-size', size);
|
||||
}
|
||||
|
@ -42,4 +42,4 @@
|
||||
"css/widgets-size-picker.css",
|
||||
"css/widgets-tabs.css",
|
||||
"css/widgets-wizard.css"
|
||||
];
|
||||
];
|
||||
|
@ -28,7 +28,11 @@
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="session-list-empty">
|
||||
<div class="session-list-empty">No session found ...</div>
|
||||
<div class="centered-message session-list-empty">No session found ...</div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="session-list-error">
|
||||
<div class="centered-message session-list-error">Could not load backup sessions, something went wrong.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="session-list-item">
|
||||
@ -57,7 +61,11 @@
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="snapshot-list-empty">
|
||||
<div class="snapshot-list-empty">No snapshot found ...</div>
|
||||
<div class="centered-message snapshot-list-empty">No snapshot found ...</div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="snapshot-list-error">
|
||||
<div class="centered-message snapshot-list-error">Could not load snapshots, something went wrong.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="snapshot-list-item">
|
||||
|
@ -25,8 +25,8 @@
|
||||
</div>
|
||||
<div class="import-section import-subsection">
|
||||
<span class="dialog-section-title">Resize to</span>
|
||||
<input type="text" class="textfield import-size-field" name="resize-width"/>x
|
||||
<input type="text" class="textfield import-size-field" name="resize-height"/>
|
||||
<input type="text" class="textfield import-size-field" autocomplete="off" name="resize-width"/>x
|
||||
<input type="text" class="textfield import-size-field" autocomplete="off" name="resize-height"/>
|
||||
</div>
|
||||
<div class="import-section import-subsection">
|
||||
<span class="import-section-title">Smooth resize</span>
|
||||
@ -40,13 +40,13 @@
|
||||
</div>
|
||||
<div class="import-section import-subsection">
|
||||
<span class="dialog-section-title">Frame size</span>
|
||||
<input type="text" class="textfield import-size-field" name="frame-size-x"/>x
|
||||
<input type="text" class="textfield import-size-field" name="frame-size-y"/>
|
||||
<input type="text" class="textfield import-size-field" autocomplete="off" name="frame-size-x"/>x
|
||||
<input type="text" class="textfield import-size-field" autocomplete="off" name="frame-size-y"/>
|
||||
</div>
|
||||
<div class="import-section import-subsection">
|
||||
<span class="dialog-section-title">Offset</span>
|
||||
<input type="text" class="textfield import-size-field" name="frame-offset-x"/>x
|
||||
<input type="text" class="textfield import-size-field" name="frame-offset-y"/>
|
||||
<input type="text" class="textfield import-size-field" autocomplete="off" name="frame-offset-x"/>x
|
||||
<input type="text" class="textfield import-size-field" autocomplete="off" name="frame-offset-y"/>
|
||||
</div>
|
||||
</form>
|
||||
<div class="import-step-buttons">
|
||||
@ -67,11 +67,11 @@
|
||||
<div class="import-mode">
|
||||
<div class="import-mode-title">How do you want to import the new content?</div>
|
||||
<div class="import-mode-section">
|
||||
<span class="import-mode-section-description">Combine the imported content and your sprite.</span>
|
||||
<button class="import-mode-merge-button button-primary button">Merge</button>
|
||||
<span class="import-mode-section-description">Combine with your sprite</span>
|
||||
<button class="import-mode-merge-button button-primary button">Combine</button>
|
||||
</div>
|
||||
<div class="import-mode-section">
|
||||
<span class="import-mode-section-description">Replace your current sprite by the imported content.</span>
|
||||
<span class="import-mode-section-description">Replace your sprite</span>
|
||||
<button class="import-mode-replace-button button-primary button">Replace</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -131,9 +131,6 @@
|
||||
The imported image is bigger than the current sprite.
|
||||
</div>
|
||||
<div class="import-resize-section">
|
||||
<div class="import-resize-option-label">
|
||||
How do you want to proceed?
|
||||
</div>
|
||||
<label class="import-resize-option">
|
||||
<input type="radio" name="resize-mode" id="resize-option-expand" value="expand" {{expandChecked}}/>
|
||||
<span>Expand canvas to {{newSize}}</span>
|
||||
@ -162,19 +159,19 @@
|
||||
</div>
|
||||
|
||||
<div class="import-step-content">
|
||||
<div>Select a frame in your current sprite:</div>
|
||||
<div>Select the insertion frame:</div>
|
||||
<div class="insert-frame-preview"></div>
|
||||
<div class="insert-mode-container">
|
||||
<div class="insert-mode-option-label">
|
||||
How should the imported frames be inserted:
|
||||
Insert imported frames:
|
||||
</div>
|
||||
<label class="insert-mode-option">
|
||||
<input type="radio" name="insert-mode" id="insert-mode-add" value="add" checked="checked"/>
|
||||
<span>Add new frames</span>
|
||||
<span>as new frames</span>
|
||||
</label>
|
||||
<label class="insert-mode-option">
|
||||
<input type="radio" name="insert-mode" id="insert-mode-insert" value="insert"/>
|
||||
<span>Insert in existing frames</span>
|
||||
<span>in existing frames</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="import-step-buttons">
|
||||
@ -184,13 +181,3 @@
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="import-invalid-file">
|
||||
<div class="import-step-container">
|
||||
<div>THIS IS AN INVALID FILEZ</div>
|
||||
<div class="import-step-buttons">
|
||||
<button class="import-back-button button">back</button>
|
||||
<button class="import-next-button button button-primary">next</button>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
@ -15,10 +15,10 @@
|
||||
<p>If you ignore this warning, please save often!</p>
|
||||
<p>To fix the issue, try adjusting your sprite settings:</p>
|
||||
<ul>
|
||||
<li>sprite resolution <sup title="recommended: lower than 256x256, max: 512x512" rel="tooltip" data-placement="top">?</sup></li>
|
||||
<li>number of layers <sup title="recommended: lower than 5, max: 20" rel="tooltip" data-placement="top">?</sup></li>
|
||||
<li>number of frames <sup title="recommended: lower than 25, max: 100" rel="tooltip" data-placement="top">?</sup></li>
|
||||
<li>number of colors <sup title="max: 100" rel="tooltip" data-placement="top">?</sup></li>
|
||||
<li>sprite resolution <sup title="recommended: lower than 512x512" rel="tooltip" data-placement="top">?</sup></li>
|
||||
<li>number of layers <sup title="recommended: less than 10" rel="tooltip" data-placement="top">?</sup></li>
|
||||
<li>number of frames <sup title="recommended: less than 50" rel="tooltip" data-placement="top">?</sup></li>
|
||||
<li>number of colors <sup title="recommended: less than 256" rel="tooltip" data-placement="top">?</sup></li>
|
||||
</ul>
|
||||
<p>We strive to improve Piskel, its performance and stability, but this is a personal project with limited time and resources.
|
||||
We prefer to warn you early rather than having you lose your work.</p>
|
||||
|
@ -9,6 +9,13 @@
|
||||
Too many colors: can not preserve original colors or transparency.
|
||||
</div>
|
||||
</div>
|
||||
<div class="export-panel-section export-panel-row">
|
||||
<input id="gif-repeat-checkbox" class="gif-repeat-checkbox checkbox-fix" type="checkbox" />
|
||||
<label for="gif-repeat-checkbox"
|
||||
title="Uncheck to play the animation only one time."
|
||||
rel="tooltip"
|
||||
data-placement="top">Loop repeatedly</label>
|
||||
</div>
|
||||
<div class="export-panel-section export-panel-row">
|
||||
<button type="button" class="button button-primary gif-download-button">Download</button>
|
||||
<div class="export-info">Download as an animated GIF.</div>
|
||||
|
@ -7,11 +7,15 @@
|
||||
<input type="text" style="flex: 1;" class="zip-prefix-name textfield"
|
||||
autocomplete="off" placeholder="PNG file prefix ...">
|
||||
</div>
|
||||
<div style="margin: 5px 0;">
|
||||
<div class="checkbox-container" style="margin: 5px 0;">
|
||||
<input id="zip-split-layers" class="zip-split-layers-checkbox checkbox-fix" type="checkbox" />
|
||||
<label for="zip-split-layers">Split by layers</label>
|
||||
</div>
|
||||
<div class="checkbox-container use-layer-names-container" style="margin: 5px 0;">
|
||||
<input id="zip-use-layer-names" class="zip-use-layer-names-checkbox checkbox-fix" type="checkbox" />
|
||||
<label for="zip-use-layer-names">Index by layer names</label>
|
||||
</div>
|
||||
<button type="button" class="button button-primary zip-generate-button"/>Download ZIP</button>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
</script>
|
||||
|
@ -19,6 +19,25 @@
|
||||
title="4px" rel="tooltip" data-placement="top" data-size="4"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-item settings-item-grid-spacing">
|
||||
<label>Grid spacing</label>
|
||||
<div class="grid-spacing-container size-picker-container">
|
||||
<div class="size-picker-option"
|
||||
title="1px" rel="tooltip" data-placement="top" data-size="1"></div>
|
||||
<div class="size-picker-option"
|
||||
title="2px" rel="tooltip" data-placement="top" data-size="2"></div>
|
||||
<div class="size-picker-option"
|
||||
title="4px" rel="tooltip" data-placement="top" data-size="4"></div>
|
||||
<div class="size-picker-option"
|
||||
title="8px" rel="tooltip" data-placement="top" data-size="8"></div>
|
||||
<div class="size-picker-option"
|
||||
title="16px" rel="tooltip" data-placement="top" data-size="16"></div>
|
||||
<div class="size-picker-option"
|
||||
title="32px" rel="tooltip" data-placement="top" data-size="32"></div>
|
||||
<div class="size-picker-option"
|
||||
title="64px" rel="tooltip" data-placement="top" data-size="64"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-item settings-item-grid-color">
|
||||
<label>Grid color</label>
|
||||
<div class="grid-colors-list"></div>
|
||||
@ -31,4 +50,4 @@
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
</script>
|
||||
|
@ -17,13 +17,13 @@
|
||||
<span>px</span>
|
||||
</div>
|
||||
<div class="resize-section">
|
||||
<label>
|
||||
<label class="checkbox-container">
|
||||
<input type="checkbox" class="resize-ratio-checkbox checkbox-fix" value="true"/>
|
||||
<span>Maintain aspect ratio</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="resize-section">
|
||||
<label>
|
||||
<label class="checkbox-container">
|
||||
<input type="checkbox" class="resize-content-checkbox checkbox-fix" value="true"/>
|
||||
<span>Resize canvas content</span>
|
||||
</label>
|
||||
|
@ -7,6 +7,7 @@
|
||||
'settings/test-export-png.js',
|
||||
'settings/test-export-png-scale.js',
|
||||
'settings/test-import-image.js',
|
||||
'settings/test-import-image-empty.js',
|
||||
'settings/test-import-image-twice.js',
|
||||
'settings/test-resize-complete.js',
|
||||
'settings/test-resize-content-complete.js',
|
||||
|
@ -9,7 +9,7 @@ casper.test.begin('PNG export test', 13, function(test) {
|
||||
|
||||
test.assert(!isDrawerExpanded(), 'settings drawer is closed');
|
||||
|
||||
// Setup test Piskel
|
||||
// Setup test Piskel
|
||||
setPiskelFromGrid('['+
|
||||
'[B, T],' +
|
||||
'[T, B],' +
|
||||
|
105
test/casperjs/integration/settings/test-import-image-empty.js
Normal file
105
test/casperjs/integration/settings/test-import-image-empty.js
Normal file
@ -0,0 +1,105 @@
|
||||
/* globals casper, setPiskelFromGrid, isDrawerExpanded, getValue, isChecked,
|
||||
evalLine, waitForEvent, replaceFunction, setPiskelFromImageSrc */
|
||||
|
||||
casper.test.begin('Image import test with an empty current sprite', 16, function(test) {
|
||||
test.timeout = test.fail.bind(test, ['Test timed out']);
|
||||
|
||||
// Helper to retrieve the text content of the provided selector
|
||||
// in the current wizard step.
|
||||
var getTextContent = function (selector) {
|
||||
return evalLine('document.querySelector(".current-step ' + selector +'").textContent');
|
||||
};
|
||||
|
||||
function onTestStart() {
|
||||
test.assertExists('#drawing-canvas-container canvas', 'Piskel ready, test starting');
|
||||
|
||||
test.assert(!isDrawerExpanded(), 'settings drawer is closed');
|
||||
|
||||
waitForEvent('PISKEL_RESET', onPiskelReset, test.timeout);
|
||||
|
||||
// 1x1 transparent pixel
|
||||
setPiskelFromGrid('['+
|
||||
'[T]' +
|
||||
']');
|
||||
}
|
||||
|
||||
function onPiskelReset() {
|
||||
// Check the expected piskel was correctly loaded.
|
||||
test.assertEquals(evalLine('pskl.app.currentColorsService.getCurrentColors().length'), 0, 'Has no color');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.isEmpty()'), true, 'Current piskel is considered as empty');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getPiskel().getWidth()'), 1, 'Piskel width is 1 pixel');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getPiskel().getHeight()'), 1, 'Piskel height is 1 pixel');
|
||||
|
||||
// Open export panel.
|
||||
test.assertDoesntExist('.settings-section-import', 'Check if import panel is closed');
|
||||
casper.click('[data-setting="import"]');
|
||||
|
||||
casper.waitForSelector('.settings-section-import', onImportPanelReady, test.timeout, 10000);
|
||||
}
|
||||
|
||||
function onImportPanelReady() {
|
||||
test.assert(isDrawerExpanded(), 'settings drawer is expanded');
|
||||
test.assertExists('.settings-section-import', 'Check if import panel is opened');
|
||||
|
||||
replaceFunction(test,
|
||||
'pskl.utils.FileUtils.readImageFile',
|
||||
function (file, callback) {
|
||||
var image = new Image();
|
||||
image.onload = callback.bind(null, image);
|
||||
// Source for a simple base64 encoded PNG, 2x2, with 2 different colors and 2 transparent pixels.
|
||||
image.src = [
|
||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0',
|
||||
'kAAAAF0lEQVQYVwXBAQEAAACCIPw/uiAYi406Ig4EARK1RMAAAAAASUVORK5CYII='
|
||||
].join('');
|
||||
}
|
||||
);
|
||||
|
||||
casper.echo('Clicking on Browse Images button');
|
||||
test.assertExists('.file-input-button', 'The import image button is available');
|
||||
|
||||
// We can't really control the file picker from the test so we directly fire the event
|
||||
casper.evaluate(
|
||||
'function () {\
|
||||
$.publish(Events.DIALOG_SHOW, {\
|
||||
dialogId : "import",\
|
||||
initArgs : {\
|
||||
rawFiles: [{type: "image", name: "test-name.png"}]\
|
||||
}\
|
||||
});\
|
||||
}'
|
||||
);
|
||||
|
||||
casper.echo('Wait for .import-image-container');
|
||||
casper.waitForSelector('.current-step.import-image-container', onImageImportReady, test.timeout, 10000);
|
||||
}
|
||||
|
||||
function onImageImportReady() {
|
||||
casper.echo('Found import-image-container');
|
||||
|
||||
// Click on export again to close the settings drawer.
|
||||
test.assertEquals(getTextContent('.import-next-button'), 'import',
|
||||
'Next button found, with text content \'import\'');
|
||||
casper.click('.current-step .import-next-button');
|
||||
|
||||
// Since the current sprite is empty clicking on the button should directly finalize the import.
|
||||
casper.waitForSelector('#dialog-container-wrapper:not(.show)', onPopupClosed, test.timeout, 10000);
|
||||
}
|
||||
|
||||
function onPopupClosed() {
|
||||
casper.echo('Import popup is closed, check the imported piskel content');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getPiskel().getWidth()'), 2, 'Piskel width is 2 pixels');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getPiskel().getHeight()'), 2, 'Piskel height is 2 pixels');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getLayers().length'), 1, 'Piskel has 1 layer');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getFrameCount()'), 1, 'Piskel has 1 frame');
|
||||
}
|
||||
|
||||
casper
|
||||
.start(casper.cli.get('baseUrl')+"/?debug&integration-test")
|
||||
.then(function () {
|
||||
casper.echo("URL loaded");
|
||||
casper.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 20000);
|
||||
})
|
||||
.run(function () {
|
||||
test.done();
|
||||
});
|
||||
});
|
@ -1,7 +1,7 @@
|
||||
/* globals casper, setPiskelFromGrid, isDrawerExpanded, getValue, isChecked,
|
||||
evalLine, waitForEvent, replaceFunction, setPiskelFromImageSrc */
|
||||
|
||||
casper.test.begin('Double Image import test', 25, function(test) {
|
||||
casper.test.begin('Double Image import test', 26, function(test) {
|
||||
test.timeout = test.fail.bind(test, ['Test timed out']);
|
||||
|
||||
// Helper to retrieve the text content of the provided selector
|
||||
@ -54,18 +54,21 @@ casper.test.begin('Double Image import test', 25, function(test) {
|
||||
|
||||
test.assert(!isDrawerExpanded(), 'settings drawer is closed');
|
||||
|
||||
waitForEvent('PISKEL_RESET', onPiskelReset, test.timeout);
|
||||
|
||||
// 1x1 black pixel
|
||||
var src = [
|
||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcS',
|
||||
'JAAAADUlEQVQYV2NgYGD4DwABBAEAcCBlCwAAAABJRU5ErkJggg=='
|
||||
].join('');
|
||||
setPiskelFromImageSrc(src);
|
||||
|
||||
// For this test the most important is that the color service picked up the color from the sprite
|
||||
// since it drives which flow will be used for the import.
|
||||
casper.waitForSelector('.palettes-list-color:nth-child(1)', onPiskelPaletteUpdated, test.timeout, 10000);
|
||||
}
|
||||
|
||||
function onPiskelReset() {
|
||||
function onPiskelPaletteUpdated() {
|
||||
// Check the expected piskel was correctly loaded.
|
||||
test.assertEquals(evalLine('pskl.app.currentColorsService.getCurrentColors().length'), 1, 'Has 1 color');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getPiskel().getWidth()'), 1, 'Piskel width is 1 pixel');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getPiskel().getHeight()'), 1, 'Piskel height is 1 pixel');
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* globals casper, setPiskelFromGrid, isDrawerExpanded, getValue, isChecked,
|
||||
evalLine, waitForEvent, replaceFunction, setPiskelFromImageSrc */
|
||||
|
||||
casper.test.begin('Simple Image import test', 26, function(test) {
|
||||
casper.test.begin('Simple Image import test', 27, function(test) {
|
||||
test.timeout = test.fail.bind(test, ['Test timed out']);
|
||||
|
||||
// Helper to retrieve the text content of the provided selector
|
||||
@ -30,18 +30,21 @@ casper.test.begin('Simple Image import test', 26, function(test) {
|
||||
|
||||
test.assert(!isDrawerExpanded(), 'settings drawer is closed');
|
||||
|
||||
waitForEvent('PISKEL_RESET', onPiskelReset, test.timeout);
|
||||
|
||||
// 1x1 black pixel
|
||||
var src = [
|
||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcS',
|
||||
'JAAAADUlEQVQYV2NgYGD4DwABBAEAcCBlCwAAAABJRU5ErkJggg=='
|
||||
].join('');
|
||||
setPiskelFromImageSrc(src);
|
||||
|
||||
// For this test the most important is that the color service picked up the color from the sprite
|
||||
// since it drives which flow will be used for the import.
|
||||
casper.waitForSelector('.palettes-list-color:nth-child(1)', onPiskelPaletteUpdated, test.timeout, 10000);
|
||||
}
|
||||
|
||||
function onPiskelReset() {
|
||||
function onPiskelPaletteUpdated() {
|
||||
// Check the expected piskel was correctly loaded.
|
||||
test.assertEquals(evalLine('pskl.app.currentColorsService.getCurrentColors().length'), 1, 'Has 1 color');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getPiskel().getWidth()'), 1, 'Piskel width is 1 pixel');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getPiskel().getHeight()'), 1, 'Piskel height is 1 pixel');
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
"lighten.darken.json",
|
||||
"move.json",
|
||||
"move-alllayers-allframes.json",
|
||||
"pen.mirror.pensize.json",
|
||||
"pen.secondary.color.json",
|
||||
"selection.rectangular.json",
|
||||
"squares.circles.json",
|
||||
|
@ -10,6 +10,7 @@
|
||||
"layers.top.bottom.json",
|
||||
"move.json",
|
||||
"move-alllayers-allframes.json",
|
||||
"pen.mirror.pensize.json",
|
||||
"pen.secondary.color.json",
|
||||
"selection.rectangular.json",
|
||||
"squares.circles.json",
|
||||
|
125
test/drawing/tests/pen.mirror.pensize.json
Normal file
125
test/drawing/tests/pen.mirror.pensize.json
Normal file
@ -0,0 +1,125 @@
|
||||
{
|
||||
"events": [
|
||||
{
|
||||
"type": "pensize-event",
|
||||
"penSize": 2
|
||||
},
|
||||
{
|
||||
"type": "tool-event",
|
||||
"toolId": "tool-vertical-mirror-pen"
|
||||
},
|
||||
{
|
||||
"event": {
|
||||
"type": "mousedown",
|
||||
"button": 0,
|
||||
"shiftKey": false,
|
||||
"altKey": false,
|
||||
"ctrlKey": false
|
||||
},
|
||||
"coords": {
|
||||
"x": 1,
|
||||
"y": 1
|
||||
},
|
||||
"type": "mouse-event"
|
||||
},
|
||||
{
|
||||
"event": {
|
||||
"type": "mousemove",
|
||||
"button": 0,
|
||||
"shiftKey": false,
|
||||
"altKey": false,
|
||||
"ctrlKey": false
|
||||
},
|
||||
"coords": {
|
||||
"x": 1,
|
||||
"y": 1
|
||||
},
|
||||
"type": "mouse-event"
|
||||
},
|
||||
{
|
||||
"event": {
|
||||
"type": "mousemove",
|
||||
"button": 0,
|
||||
"shiftKey": false,
|
||||
"altKey": false,
|
||||
"ctrlKey": false
|
||||
},
|
||||
"coords": {
|
||||
"x": 1,
|
||||
"y": 2
|
||||
},
|
||||
"type": "mouse-event"
|
||||
},
|
||||
{
|
||||
"event": {
|
||||
"type": "mousemove",
|
||||
"button": 0,
|
||||
"shiftKey": false,
|
||||
"altKey": false,
|
||||
"ctrlKey": false
|
||||
},
|
||||
"coords": {
|
||||
"x": 1,
|
||||
"y": 3
|
||||
},
|
||||
"type": "mouse-event"
|
||||
},
|
||||
{
|
||||
"event": {
|
||||
"type": "mousemove",
|
||||
"button": 0,
|
||||
"shiftKey": false,
|
||||
"altKey": false,
|
||||
"ctrlKey": false
|
||||
},
|
||||
"coords": {
|
||||
"x": 1,
|
||||
"y": 4
|
||||
},
|
||||
"type": "mouse-event"
|
||||
},
|
||||
{
|
||||
"event": {
|
||||
"type": "mousemove",
|
||||
"button": 0,
|
||||
"shiftKey": false,
|
||||
"altKey": false,
|
||||
"ctrlKey": false
|
||||
},
|
||||
"coords": {
|
||||
"x": 1,
|
||||
"y": 5
|
||||
},
|
||||
"type": "mouse-event"
|
||||
},
|
||||
{
|
||||
"event": {
|
||||
"type": "mouseup",
|
||||
"button": 0,
|
||||
"shiftKey": false,
|
||||
"altKey": false,
|
||||
"ctrlKey": false
|
||||
},
|
||||
"coords": {
|
||||
"x": 1,
|
||||
"y": 5
|
||||
},
|
||||
"type": "mouse-event"
|
||||
},
|
||||
{
|
||||
"type": "pensize-event",
|
||||
"penSize": 1
|
||||
}
|
||||
],
|
||||
"initialState": {
|
||||
"size": {
|
||||
"width": 6,
|
||||
"height": 6
|
||||
},
|
||||
"primaryColor": "#000000",
|
||||
"secondaryColor": "rgba(0, 0, 0, 0)",
|
||||
"selectedTool": "tool-pen",
|
||||
"penSize": 1
|
||||
},
|
||||
"png": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGCAYAAADgzO9IAAAAGElEQVQYV2NkYGD4zwABjFAazAdxBkwCAIsLDAFt5z4tAAAAAElFTkSuQmCC"
|
||||
}
|
Reference in New Issue
Block a user