2 Commits

Author SHA1 Message Date
greenkeeper[bot]
5e46d8b7e2 docs(readme): add Greenkeeper badge 2017-05-06 14:44:55 +00:00
greenkeeper[bot]
e15d7b2422 chore(package): update dependencies 2017-05-06 14:43:20 +00:00
144 changed files with 1536 additions and 5415 deletions

View File

@@ -1,2 +0,0 @@
# Exclude libs.
**/lib/**/*.js

6
.gitignore vendored
View File

@@ -1,4 +1,4 @@
# mac artifacts # mac artefacts
*.DS_Store *.DS_Store
# nodejs local installs # nodejs local installs
@@ -15,12 +15,10 @@ cache
# netbeans project folder # netbeans project folder
nbproject nbproject
# vscode workspace folder
.vscode
# git stackdumps # git stackdumps
*.stackdump *.stackdump
# diffs # diffs
diff.txt diff.txt

75
.jscsrc Normal file
View File

@@ -0,0 +1,75 @@
{
"requireCurlyBraces": [
"if",
"else",
"for",
"while",
"do",
"try",
"catch"
],
"requireOperatorBeforeLineBreak": true,
"requireCamelCaseOrUpperCaseIdentifiers": true,
"maximumLineLength": {
"value": 80,
"allExcept": ["comments", "regex"]
},
"validateIndentation": 2,
"validateQuoteMarks": "'",
"disallowMultipleLineStrings": true,
"disallowMixedSpacesAndTabs": true,
"disallowTrailingWhitespace": true,
"disallowSpaceAfterPrefixUnaryOperators": true,
"disallowMultipleVarDecl": true,
"disallowKeywordsOnNewLine": ["else"],
"requireSpaceAfterKeywords": [
"if",
"else",
"for",
"while",
"do",
"switch",
"return",
"try",
"catch"
],
"requireSpaceBeforeBinaryOperators": [
"=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=",
"&=", "|=", "^=", "+=",
"+", "-", "*", "/", "%", "<<", ">>", ">>>", "&",
"|", "^", "&&", "||", "===", "==", ">=",
"<=", "<", ">", "!=", "!=="
],
"requireSpaceAfterBinaryOperators": true,
"requireSpacesInConditionalExpression": true,
"requireSpaceBeforeBlockStatements": true,
"requireSpacesInForStatement": true,
"requireLineFeedAtFileEnd": true,
"requireSpacesInFunctionExpression": {
"beforeOpeningCurlyBrace": true
},
"disallowSpacesInAnonymousFunctionExpression": {
"beforeOpeningRoundBrace": false
},
"disallowSpacesInsideObjectBrackets": "all",
"disallowSpacesInsideArrayBrackets": "all",
"disallowSpacesInsideParentheses": true,
"disallowMultipleLineBreaks": true,
"disallowNewlineBeforeBlockStatements": true,
"disallowKeywords": ["with"],
"disallowSpacesInFunctionExpression": null,
"disallowSpacesInFunctionDeclaration": null,
"disallowSpacesInCallExpression": true,
"disallowSpaceAfterObjectKeys": false,
"requireSpaceBeforeObjectValues": true,
"requireCapitalizedConstructors": true,
"requireDotNotation": true,
"requireSemicolons": true,
"validateParameterSeparator": ", ",
"jsDoc": null
}

View File

@@ -12,7 +12,6 @@ module.exports = function(grunt) {
// create a version based on the build timestamp // create a version based on the build timestamp
var dateFormat = require('dateformat'); var dateFormat = require('dateformat');
var version = '-' + dateFormat(new Date(), "yyyy-mm-dd-hh-MM"); var version = '-' + dateFormat(new Date(), "yyyy-mm-dd-hh-MM");
var releaseVersion = require('./package.json').version;
/** /**
* Helper to prefix all strings in provided array with the provided path * Helper to prefix all strings in provided array with the provided path
@@ -83,12 +82,33 @@ module.exports = function(grunt) {
css : ['src/css/**/*.css'] css : ['src/css/**/*.css']
}, },
eslint: { jscs : {
options : {
"config": ".jscsrc",
"maximumLineLength": 120,
"requireCamelCaseOrUpperCaseIdentifiers": "ignoreProperties",
"validateQuoteMarks": { "mark": "'", "escape": true },
"disallowMultipleVarDecl": "exceptUndefined",
"disallowSpacesInAnonymousFunctionExpression": null
},
js : [ 'src/js/**/*.js' , '!src/js/**/lib/**/*.js' ]
},
jshint: {
options: {
undef : true,
latedef : true,
browser : true,
trailing : true,
curly : true,
globals : {'$':true, 'jQuery' : true, 'pskl':true, 'Events':true, 'Constants':true, 'console' : true, 'module':true, 'require':true, 'Q':true, 'Promise': true}
},
files: [ files: [
// Includes // Includes
'Gruntfile.js',
'package.json',
'src/js/**/*.js', 'src/js/**/*.js',
// Exludes // Excludes
// TODO: remove this (for now we still get warnings from the lib folder)
'!src/js/**/lib/**/*.js' '!src/js/**/lib/**/*.js'
] ]
}, },
@@ -174,8 +194,7 @@ module.exports = function(grunt) {
dest: 'dest/tmp/index.html', dest: 'dest/tmp/index.html',
options : { options : {
globals : { globals : {
'version' : version, 'version' : version
'releaseVersion' : releaseVersion
} }
} }
} }
@@ -217,6 +236,20 @@ module.exports = function(grunt) {
src: ['dest/tmp/css/piskel-style-packaged' + version + '.css'], src: ['dest/tmp/css/piskel-style-packaged' + version + '.css'],
dest: 'dest/prod/css/piskel-style-packaged' + version + '.css' dest: 'dest/prod/css/piskel-style-packaged' + version + '.css'
}] }]
},
// remove the fake header from the desktop build
desktop: {
options: {
patterns: [{
match: /<!--standalone-start-->(?:.|[\r\n])*<!--standalone-end-->/,
replacement: "",
description : "Remove everything between standalone-start & standalone-end"
}
]
},
files: [
{src: ['dest/prod/index.html'], dest: 'dest/prod/index.html'}
]
} }
}, },
@@ -286,8 +319,7 @@ module.exports = function(grunt) {
build_dir: './dest/desktop/', // destination folder of releases. build_dir: './dest/desktop/', // destination folder of releases.
win: true, win: true,
linux32: true, linux32: true,
linux64: true, linux64: true
flavor: "normal",
}, },
src: ['./dest/prod/**/*', "./package.json", "!./dest/desktop/"] src: ['./dest/prod/**/*', "./package.json", "!./dest/desktop/"]
}, },
@@ -296,18 +328,7 @@ module.exports = function(grunt) {
downloadUrl: 'https://dl.nwjs.io/', downloadUrl: 'https://dl.nwjs.io/',
osx64: true, osx64: true,
version : "0.19.4", version : "0.19.4",
build_dir: './dest/desktop/', build_dir: './dest/desktop/'
flavor: "normal",
},
src: ['./dest/prod/**/*', "./package.json", "!./dest/desktop/"]
},
macos_old : {
options: {
downloadUrl: 'https://dl.nwjs.io/',
osx64: true,
version : "0.12.3",
build_dir: './dest/desktop/old',
flavor: "normal",
}, },
src: ['./dest/prod/**/*', "./package.json", "!./dest/desktop/"] src: ['./dest/prod/**/*', "./package.json", "!./dest/desktop/"]
} }
@@ -316,13 +337,11 @@ module.exports = function(grunt) {
// TEST TASKS // TEST TASKS
// Run linting // Run linting
grunt.registerTask('lint', ['eslint', 'leadingIndent:css']); grunt.registerTask('lint', ['jscs:js', 'leadingIndent:css', 'jshint']);
// Run unit-tests // Run unit-tests
grunt.registerTask('unit-test', ['karma']); grunt.registerTask('unit-test', ['karma']);
// Run integration tests // Run integration tests
grunt.registerTask('integration-test', ['build-dev', 'connect:test', 'casperjs:integration']); grunt.registerTask('integration-test', ['build-dev', 'connect:test', 'casperjs:integration']);
// Run drawing tests
grunt.registerTask('drawing-test', ['build-dev', 'connect:test', 'casperjs:drawing']);
// Run linting, unit tests, drawing tests and integration tests // Run linting, unit tests, drawing tests and integration tests
grunt.registerTask('test', ['lint', 'unit-test', 'build-dev', 'connect:test', 'casperjs:drawing', 'casperjs:integration']); grunt.registerTask('test', ['lint', 'unit-test', 'build-dev', 'connect:test', 'casperjs:drawing', 'casperjs:integration']);
@@ -337,9 +356,8 @@ module.exports = function(grunt) {
grunt.registerTask('merge-statics', ['concat:js', 'concat:css', 'uglify']); grunt.registerTask('merge-statics', ['concat:js', 'concat:css', 'uglify']);
grunt.registerTask('build', ['clean:prod', 'sprite', 'merge-statics', 'build-index.html', 'replace:mainPartial', 'replace:css', 'copy:prod']); grunt.registerTask('build', ['clean:prod', 'sprite', 'merge-statics', 'build-index.html', 'replace:mainPartial', 'replace:css', 'copy:prod']);
grunt.registerTask('build-dev', ['clean:dev', 'sprite', 'build-index.html', 'copy:dev']); grunt.registerTask('build-dev', ['clean:dev', 'sprite', 'build-index.html', 'copy:dev']);
grunt.registerTask('desktop', ['clean:desktop', 'default', 'nwjs:windows']); grunt.registerTask('desktop', ['clean:desktop', 'default', 'replace:desktop', 'nwjs:windows']);
grunt.registerTask('desktop-mac', ['clean:desktop', 'default', 'nwjs:macos']); grunt.registerTask('desktop-mac', ['clean:desktop', 'default', 'replace:desktop', 'nwjs:macos']);
grunt.registerTask('desktop-mac-old', ['clean:desktop', 'default', 'replace:desktop', 'nwjs:macos_old']);
// SERVER TASKS // SERVER TASKS
// Start webserver and watch for changes // Start webserver and watch for changes

View File

@@ -1,21 +1,52 @@
Piskel Piskel
====== ======
[![Travis Status](https://api.travis-ci.org/piskelapp/piskel.png?branch=master)](https://travis-ci.org/piskelapp/piskel) [![Built with Grunt](https://cdn.gruntjs.com/builtwith.png)](http://gruntjs.com/) [![Greenkeeper badge](https://badges.greenkeeper.io/juliandescottes/piskel.svg)](https://greenkeeper.io/)
Piskel is an easy-to-use sprite editor. It can be used to create game sprites, animations, pixel-art... [![Travis Status](https://api.travis-ci.org/juliandescottes/piskel.png?branch=master)](https://travis-ci.org/juliandescottes/piskel) [![Built with Grunt](https://cdn.gruntjs.com/builtwith.png)](http://gruntjs.com/)
It is the editor used in **[piskelapp.com](http://piskelapp.com)**.
<img A simple web-based tool for Spriting and Pixel art.
src="https://screenletstore.appspot.com/img/95aaa0f0-37a4-11e7-a652-7b8128ce3e3b.png"
title="Piskel editor screenshot"
width="500">
## About Piskel ![Piskel editor screenshot](https://screenletstore.appspot.com/img/8f03e768-ac59-11e3-b2a1-7f5a1b97c420.jpeg "Piskel editor screenshot")
### Built with You can try the standalone editor at **http://juliandescottes.github.io/piskel** or see it integrated in **http://piskelapp.com**.
The Piskel editor is purely built in **JavaScript, HTML and CSS**. Piskel is mainly developped by :
* **[@juliandescottes](https://github.com/juliandescottes)**
* **[@grosbouddha](https://github.com/grosbouddha)**
## What's the point ?
You can use Piskel to do two things :
* **spriting** : create retro-style sprites for games
![Megaman spritesheet](http://piskel-imgstore-a.appspot.com/img/c8081287-ac58-11e3-bd8c-b3c4036c0eee.png "Megaman spritesheet")
* **pixelart** : create crazy/pretty pixelart animations for fun !
![Rabbit jumping](http://piskel-imgstore-a.appspot.com/img/947f2dab-ac58-11e3-949a-b3c4036c0eee.gif "Rabit jumping")
Integrated in **[piskelapp.com](http://piskelapp.com)**, you can share everything you work on with others as easily as you share a link.
## Requirements
Piskel supports the following browsers :
* **Chrome** (latest)
* **Firefox** (latest)
* **Internet Explorer** 11+
... and a fairly recent computer.
We don't plan/want/could be forced into supporting older IEs. For Opera and Safari, we've never tested them but the gap shouldn't be huge.
## Offline version
Offline builds are available. More details in the [dedicated wiki page](https://github.com/juliandescottes/piskel/wiki/Desktop-applications).
## Built with
The Piskel editor is purely built in **JavaScript, HTML and CSS**. It uses Canvas extensively for displaying all them pretty sprites.
We also use the following **libraries** : We also use the following **libraries** :
* [spectrum](https://github.com/bgrins/spectrum) : awesome standalone colorpicker * [spectrum](https://github.com/bgrins/spectrum) : awesome standalone colorpicker
@@ -30,32 +61,17 @@ As well as some **icons** from the [Noun Project](http://thenounproject.com/) :
* Folder by Simple Icons from The Noun Project * Folder by Simple Icons from The Noun Project
* (and probably one or two others) * (and probably one or two others)
### Browser Support
Piskel supports the following browsers:
* **Chrome** (latest)
* **Firefox** (latest)
* **Edge** (latest)
* **Internet Explorer** 11
### Mobile/Tablets
There is no support for mobile.
### Offline builds
Offline builds are available. More details in the [dedicated wiki page](https://github.com/piskelapp/piskel/wiki/Desktop-applications).
## Contributing ? ## Contributing ?
Help is always welcome ! Help is always welcome !
* **Issues** : Found a problem when using the application, want to request a feature, [open an issue](https://github.com/piskelapp/piskel/issues). * **Issues** : Found a problem when using the application, want to request a feature, [open an issue](https://github.com/juliandescottes/piskel/issues).
* **Development** : Have a look at the [wiki](https://github.com/piskelapp/piskel/wiki) to set up the development environment * **Participate** : Have a look at the [wiki](https://github.com/juliandescottes/piskel/wiki) to set up the development environment
## License ## License
Copyright 2017 Julian Descottes Copyright 2016 Julian Descottes
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -69,3 +85,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
## Mobile/Tablets
There is no support for mobile for now.

View File

@@ -6,8 +6,6 @@ const fse = require('fs-extra');
const PISKEL_PATH = path.resolve(__dirname, '..'); const PISKEL_PATH = path.resolve(__dirname, '..');
const PISKELAPP_PATH = path.resolve(__dirname, '../../piskel-website'); const PISKELAPP_PATH = path.resolve(__dirname, '../../piskel-website');
var pjson = require('../package.json');
// Callbacks sorted by call sequence. // Callbacks sorted by call sequence.
function onCopy(err) { function onCopy(err) {
if (err) { if (err) {
@@ -54,17 +52,6 @@ function onDeleteTempPartial(err) {
} }
console.log('Temporary main partial deleted...'); console.log('Temporary main partial deleted...');
fs.writeFile(path.resolve(PISKELAPP_PATH, "static/editor/VERSION"), pjson.version, onVersionFileCreated);
}
function onVersionFileCreated(err) {
if (err) {
console.error('Failed to create temporary main partial...');
return console.error(err);
}
console.log('Version file created...');
console.log('Finished!'); console.log('Finished!');
} }

View File

@@ -1,16 +1,16 @@
{ {
"name": "piskel", "name": "piskel",
"version": "0.12.1", "version": "0.10.0",
"description": "Pixel art editor", "description": "Pixel art editor",
"author": "Julian Descottes <julian.descottes@gmail.com>", "author": "Julian Descottes <julian.descottes@gmail.com>",
"contributors": [ "contributors": [
"Vincent Renaudin" "Vincent Renaudin"
], ],
"homepage": "http://github.com/piskelapp/piskel", "homepage": "http://github.com/juliandescottes/piskel",
"license": "Apache-2.0", "license": "Apache-2.0",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "http://github.com/piskelapp/piskel.git" "url": "http://github.com/juliandescottes/piskel.git"
}, },
"files": [ "files": [
"dest/prod", "dest/prod",
@@ -24,13 +24,12 @@
"test": "grunt test", "test": "grunt test",
"start": "nodewebkit", "start": "nodewebkit",
"preversion": "grunt test build", "preversion": "grunt test build",
"postversion": "git push && git push --tags && npm publish", "postversion": "git push && git push --tags && npm publish"
"release": "grunt && node ./bin/copy-to-piskel-website"
}, },
"devDependencies": { "devDependencies": {
"dateformat": "2.0.0", "dateformat": "2.0.0",
"fs-extra": "3.0.1", "fs-extra": "3.0.1",
"grunt": "0.4.5", "grunt": "^1.0.1",
"grunt-casperjs": "^2.2.1", "grunt-casperjs": "^2.2.1",
"grunt-contrib-clean": "1.1.0", "grunt-contrib-clean": "1.1.0",
"grunt-contrib-concat": "1.0.1", "grunt-contrib-concat": "1.0.1",
@@ -39,10 +38,9 @@
"grunt-contrib-jshint": "1.1.0", "grunt-contrib-jshint": "1.1.0",
"grunt-contrib-uglify": "2.3.0", "grunt-contrib-uglify": "2.3.0",
"grunt-contrib-watch": "1.0.0", "grunt-contrib-watch": "1.0.0",
"grunt-eslint": "^19.0.0", "grunt-include-replace": "5.0.0",
"grunt-include-replace": "4.0.1", "grunt-jscs": "3.0.1",
"grunt-jscs": "2.8.0", "grunt-karma": "2.0.0",
"grunt-karma": "1.0.0",
"grunt-leading-indent": "0.2.0", "grunt-leading-indent": "0.2.0",
"grunt-nw-builder": "3.1.0", "grunt-nw-builder": "3.1.0",
"grunt-open": "0.2.3", "grunt-open": "0.2.3",
@@ -50,9 +48,10 @@
"grunt-spritesmith": "6.4.0", "grunt-spritesmith": "6.4.0",
"jasmine-core": "2.6.1", "jasmine-core": "2.6.1",
"karma": "1.7.0", "karma": "1.7.0",
"karma-chrome-launcher": "2.1.1",
"karma-jasmine": "1.1.0", "karma-jasmine": "1.1.0",
"karma-phantomjs-launcher": "1.0.4", "karma-phantomjs-launcher": "1.0.4",
"load-grunt-tasks": "3.5.0", "load-grunt-tasks": "3.5.2",
"phantomjs": "2.1.7", "phantomjs": "2.1.7",
"phantomjs-polyfill-object-assign": "0.0.2", "phantomjs-polyfill-object-assign": "0.0.2",
"promise-polyfill": "6.0.2", "promise-polyfill": "6.0.2",
@@ -63,6 +62,6 @@
"icon": "dest/prod/logo.png", "icon": "dest/prod/logo.png",
"toolbar": false, "toolbar": false,
"width": 1000, "width": 1000,
"height": 700 "height": 500
} }
} }

View File

@@ -3,19 +3,6 @@
/* Browse local piskels panel */ /* Browse local piskels panel */
/************************************************************************************************/ /************************************************************************************************/
#dialog-container.browse-local {
width: 700px;
height: 500px;
top : 50%;
left : 50%;
position : absolute;
margin-left: -350px;
}
.show #dialog-container.browse-local {
margin-top: -250px;
}
.local-piskel-list { .local-piskel-list {
width: 100%; width: 100%;
} }

View File

@@ -0,0 +1,101 @@
/************************************************************************************************/
/* Import dialog */
/************************************************************************************************/
#dialog-container.import-image {
width: 550px;
height: 360px;
top : 50%;
left : 50%;
position : absolute;
margin-left: -250px;
}
.show #dialog-container.import-image {
margin-top: -150px;
}
.import-subsection {
margin-left: 25px;
}
.import-section:not(.import-subsection) > .dialog-section-title {
width: 50px;
}
.import-section-preview-title {
position: absolute;
margin-left: 50%;
margin-top: -28px;
}
.import-section-preview {
position: absolute;
display: inline-block;
border: 1px dashed #999;
border-radius: 3px;
margin-left: 50%;
}
.import-section-preview img {
max-width: 220px;
max-height: 220px;
display: block;
}
.import-section-preview.no-border {
border-color: transparent;
}
.import-section-preview canvas {
position: absolute;
left: 0;
top: 0;
}
.dialog-section-title {
display : inline-block;
width: 80px;
}
.dialog-section-radio {
margin-top: 15px;
vertical-align: sub;
}
.import-size-field:nth-of-type(2) {
margin-left: 5px;
}
.import-image-file-name {
display: inline-block;
overflow: hidden;
width: 200px;
vertical-align: middle;
word-break : break-all;
white-space: nowrap;
text-overflow: ellipsis;
font-style: italic;
font-weight: normal;
text-shadow: none;
color: var(--highlight-color);
}
[name=smooth-resize-checkbox] {
margin : 0 8px;
}
.dialog-import-body {
padding: 10px 20px;
font-size:1.3em
}
.import-button {
font-size: 1em;
height: 28px;
padding: 0px 10px;
margin-top: 15px;
}

View File

@@ -1,292 +0,0 @@
#dialog-container.import {
width: 500px;
height: 350px;
top : 50%;
left : 50%;
position : absolute;
margin-left: -250px;
margin-top: -175px;
}
.import .dialog-content {
font-size: 1.3em;
}
.import-step-container {
display: flex;
width: 100%;
height: 100%;
box-sizing: border-box;
box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.5);
background: #444;
}
.import-step-content {
padding: 10px;
}
.import-step-buttons {
position: absolute;
bottom: 10px;
right: 10px;
text-align: right;
}
.import-first-step .import-back-button {
display: none;
}
/**
* IMAGE IMPORT STEP
*/
.import-image-container {
padding: 10px;
}
.import-image-loading {
opacity: 0.3;
pointer-events: none;
}
.import-image-loading::after {
content: 'loading image';
position: absolute;
width: 100%;
top: 0;
left: 0;
margin-top: 110px;
text-align: center;
font-size: 3em;
color: white;
text-shadow: 0 0 60px black;
}
.import-subsection {
margin-left: 25px;
}
.import-section:not(.import-subsection) > .dialog-section-title {
width: 50px;
}
.import-section-preview-title {
position: absolute;
margin-left: 50%;
margin-top: -28px;
}
.import-section-preview {
position: absolute;
display: inline-block;
border: 1px dashed #999;
border-radius: 3px;
margin-left: 50%;
top: 10px;
width: 220px;
height: 220px;
display: flex;
align-items: center;
justify-content: center;
}
.import-section-preview img {
max-width: 100%;
max-height: 100%;
display: block;
}
.import-section-preview canvas {
position: absolute;
}
.dialog-section-title {
display : inline-block;
width: 80px;
}
.dialog-section-radio {
margin-top: 15px;
vertical-align: sub;
}
.import-size-field:nth-of-type(2) {
margin-left: 5px;
}
.import-image-file-name {
display: inline-block;
overflow: hidden;
width: 200px;
vertical-align: middle;
word-break : break-all;
white-space: nowrap;
text-overflow: ellipsis;
font-style: italic;
font-weight: normal;
text-shadow: none;
color: var(--highlight-color);
}
[name=smooth-resize-checkbox] {
margin : 0 8px;
}
.dialog-import-body {
padding: 10px 20px;
font-size:1.3em
}
/**
* SELECT MODE
*/
.import-info {
display: flex;
flex-direction: column;
height: 100%;
max-width: 178px;
box-sizing: border-box;
padding: 10px;
border-right: 3px solid gold;
}
.import-preview canvas {
max-width: 100%;
max-height: 100%;
}
.import-meta {
margin-top: 10px;
box-sizing: border-box;
/*center meta information horizontally*/
display: flex;
flex-direction: column;
justify-content: center;
}
.import-meta > div {
height: 22px;
display: flex;
margin-bottom: 5px;
}
.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;
}
.import-missing {
text-align: center;
line-height: 70px;
font-style: italic;
color: #aaa;
}
.import-mode-title {
margin-bottom: 10px
}
.import-mode-section {
display: flex;
border: 3px solid #666;
border-radius: 3px;
padding: 10px;
margin-bottom: 10px;
align-items: center;
}
.import-mode-section .button {
width: 75px;
height: 30px;
font-size: 14px;
margin-left: 10px;
flex-grow: 0;
flex-shrink: 0;
}
.import-mode-section-description {
flex-grow: 1;
}
.import-resize-option,
.insert-mode-option {
display: flex;
align-items: center;
margin-bottom: 5px;
}
.import-resize-option :checked + span,
.insert-mode-option :checked + span {
color: var(--highlight-color);
}
/**
* ADJUST SIZE
*/
.import-resize-anchor-info,
.import-resize-option-label {
margin-bottom: 10px;
}
.import-resize-section {
margin-bottom: 10px;
}
.import-resize-anchor {
margin-top: 20px;
}
.import-resize-option :checked + span {
color: var(--highlight-color);
}
.import-resize-warning {
color: var(--highlight-color);
}
/**
* INSERT LOCATION
*/
.insert-mode-container {
margin-top: 20px;
margin-bottom: 10px;
}
.insert-frame-preview {
margin: 10px 0;
}
.insert-frame-preview .frame-picker-wrapper {
height: 120px;
}

View File

@@ -48,6 +48,19 @@
margin-top: 0; margin-top: 0;
} }
#dialog-container.browse-local {
width: 700px;
height: 500px;
top : 50%;
left : 50%;
position : absolute;
margin-left: -350px;
}
.show #dialog-container.browse-local {
margin-top: -250px;
}
.dialog-wrapper { .dialog-wrapper {
height: 100%; height: 100%;
position : relative; position : relative;

View File

@@ -54,9 +54,6 @@
} }
.add-frame-action { .add-frame-action {
display: flex;
align-items: center;
margin-top: 8px; margin-top: 8px;
padding: 6px 0; padding: 6px 0;
overflow: hidden; overflow: hidden;
@@ -74,7 +71,6 @@
.add-frame-action-icon { .add-frame-action-icon {
margin: 3px; margin: 3px;
float: left; float: left;
flex-shrink: 0;
} }
.add-frame-action .label { .add-frame-action .label {

View File

@@ -1,13 +1,9 @@
/***********************/ .pen-size-container {
/* SIZE PICKER WIDGET */
/***********************/
.size-picker-container {
overflow: hidden; overflow: hidden;
padding: 5px 5px; padding: 5px 5px;
} }
.size-picker-option { .pen-size-option {
float: left; float: left;
box-sizing: border-box; box-sizing: border-box;
width: 20px; width: 20px;
@@ -19,20 +15,20 @@
cursor: pointer; cursor: pointer;
} }
.size-picker-option[data-size='1'] { .pen-size-option[data-size='1'] {
padding: 5px; padding: 5px;
} }
.size-picker-option[data-size='2'] { .pen-size-option[data-size='2'] {
padding: 4px; padding: 4px;
} }
.size-picker-option[data-size='3'] { .pen-size-option[data-size='3'] {
padding: 3px; padding: 3px;
} }
.size-picker-option[data-size='4'] { .pen-size-option[data-size='4'] {
padding: 2px; padding: 2px;
} }
.size-picker-option:before { .pen-size-option:before {
content: ''; content: '';
width: 100%; width: 100%;
height: 100%; height: 100%;
@@ -43,19 +39,19 @@
font-size: 90%; font-size: 90%;
} }
.size-picker-option:hover { .pen-size-option:hover {
border-color: #888; border-color: #888;
} }
.size-picker-option.selected:before { .pen-size-option.selected:before {
background-color: var(--highlight-color); background-color: var(--highlight-color);
} }
.size-picker-option.selected { .pen-size-option.selected {
border-color: var(--highlight-color); border-color: var(--highlight-color);
} }
.size-picker-option.labeled:before { .pen-size-option.labeled:before {
content: attr(real-size); content: attr(real-pen-size);
color: black; color: black;
} }

View File

@@ -5,7 +5,6 @@ html, body {
cursor : default; cursor : default;
font-family: Arial; font-family: Arial;
font-size: 11px; font-size: 11px;
line-height: 1.1;
-webkit-touch-callout: none; -webkit-touch-callout: none;
-webkit-user-select: none; -webkit-user-select: none;
-khtml-user-select: none; -khtml-user-select: none;

View File

@@ -1,14 +1,6 @@
/********************************/ /*******************************/
/* Preferences Settings panel */ /* Application Setting panel */
/********************************/ /*******************************/
.settings-section-preferences {
height: 100%;
position: relative;
overflow: hidden;
margin: 0 20px;
height: 100%;
}
.background-picker-wrapper { .background-picker-wrapper {
display: inline-block; display: inline-block;
@@ -43,11 +35,14 @@
vertical-align: middle; vertical-align: middle;
} }
.layer-opacity-input, .layer-opacity-input {
.tile-mask-opacity-input {
width: 100px; width: 100px;
} }
.seamless-opacity-input {
width: 75px;
}
.settings-opacity-text { .settings-opacity-text {
height: 31px; height: 31px;
display: inline-block; display: inline-block;
@@ -59,76 +54,16 @@
text-align: center; text-align: center;
} }
.settings-item-grid-size,
.settings-item-grid-color {
display: flex;
align-items: center;
}
.settings-item-grid-size > label,
.settings-item-grid-color > label {
width: 65px;
flex-shrink: 0;
}
.settings-item-grid-size .size-picker-option {
border-color: #888;
}
.settings-item-grid-size .size-picker-option:not(.selected):hover {
border-color: white;
}
.grid-width-select, .grid-width-select,
.color-format-select { .color-format-select {
margin: 5px 5px 0 5px; margin: 5px 5px 0 5px;
} }
.settings-section-application > .settings-title {
.grid-colors-list {
overflow: hidden;
padding: 0 5px;
}
.grid-colors-item {
float: left;
width: 20px;
height: 20px;
cursor: pointer;
border: 2px solid #888;
margin-right: 2px;
margin-bottom: 2px;
box-sizing: border-box;
}
.grid-colors-item:hover {
border-color: white;
}
.grid-colors-item.selected {
border-color: gold;
}
.settings-section-preferences > .settings-title {
/* Override the default 10px margin bottom for this panel */ /* Override the default 10px margin bottom for this panel */
margin-bottom: 15px; margin-bottom: 15px;
} }
.settings-section-preferences .button-primary { .settings-section-application .button-primary {
margin-top: 10px; margin-top: 10px;
} }
.settings-version-info {
position: absolute;
bottom: 10px;
right: 10px;
color: #888;
}
/* Override default link styles for the release notes link
It doesn't need to popout too much */
.settings-version,
.settings-version:hover {
color: white !important;
text-decoration: none !important;
}

View File

@@ -100,6 +100,45 @@
line-height: 23px; line-height: 23px;
} }
.export-tabs {
overflow: hidden;
position: relative;
}
.export-tabs:after {
content: "";
display: block;
position: absolute;
bottom: 0;
width: 100%;
height: 1px;
z-index: 0;
background-color: var(--highlight-color);
}
.export-tab {
float: left;
cursor: pointer;
padding: 5px;
border: 1px solid transparent;
border-radius: 2px 2px 0 0;
/* Make sure the tab and its border are positioned above the :after element; */
position: relative;
z-index: 1;
}
.export-tab.selected,
.export-tab:hover {
color: var(--highlight-color);
}
.export-tab.selected {
border-color: var(--highlight-color);
border-bottom-color: #444;
border-style: solid;
border-width: 1px;
}
.export-panel-header { .export-panel-header {
padding: 10px 5px 0px; padding: 10px 5px 0px;
} }

View File

@@ -5,8 +5,103 @@
width: 25%; width: 25%;
} }
.resize-anchor-container { /*****************/
/* ANCHOR WIDGET */
/*****************/
.resize-origin-container {
overflow: hidden;
position: relative; position: relative;
width: 70px;
margin-top: 5px; margin-top: 5px;
display: inline-block; display: inline-block;
} }
.transition .resize-origin-option,
.transition .resize-origin-option:before {
transition: background-color 0.2s, border-color 0.2s;
}
.resize-origin-option {
float: left;
position: relative;
box-sizing: border-box;
margin: 0 1px 1px 0;
width: 20px;
height: 20px;
background : #888;
font-size: 8px;
text-align: center;
cursor: pointer;
}
.disabled .resize-origin-option {
cursor: default;
background : #555;
border-color: #555 !important;
}
.resize-origin-option:hover {
border : 3px solid white;
}
.resize-origin-option.selected {
border : 3px solid var(--highlight-color);
}
.resize-origin-option:before {
content: '';
position: absolute;
display: block;
top: 50%;
left: 50%;
margin: -2px;
}
.resize-origin-option.selected:before {
content: '';
width: 4px;
height: 4px;
background: var(--highlight-color);
}
.disabled .resize-origin-option.selected:before {
background: #555;
}
.disabled .resize-origin-option[data-neighbor]:before {
border-color: #555 !important;
}
.resize-origin-option[data-neighbor]:before {
width: 0;
height: 0;
border-width: 4px;
border-style: solid;
border-color: transparent;
}
.resize-origin-option[data-neighbor="bottom"]:before {
border-top-color: var(--highlight-color);
margin-left: -4px;
}
.resize-origin-option[data-neighbor="left"]:before {
border-right-color: var(--highlight-color);
margin-top: -4px;
margin-left: -6px;
}
.resize-origin-option[data-neighbor="top"]:before {
border-bottom-color: var(--highlight-color);
margin-top: -6px;
margin-left: -4px;
}
.resize-origin-option[data-neighbor="right"]:before {
border-left-color: var(--highlight-color);
margin-top: -4px;
}

113
src/css/sprites.css Normal file
View File

@@ -0,0 +1,113 @@
/*
Icon classes can be used entirely standalone. They are named after their original file names.
```html
<!-- `display: block` sprite -->
<div class="icon-home"></div>
<!-- `display: inline-block` sprite -->
<img class="icon-home" />
```
*/
.icon-cloud_export {
background-image: url(../img/spritesheet.png);
background-position: -512px -276px;
width: 50px;
height: 47px;
}
.icon-dragndrop {
background-image: url(../img/spritesheet.png);
background-position: -564px -173px;
width: 48px;
height: 48px;
}
.icon-duplicate {
background-image: url(../img/spritesheet.png);
background-position: -512px -369px;
width: 16px;
height: 16px;
}
.icon-export {
background-image: url(../img/spritesheet.png);
background-position: -564px -225px;
width: 43px;
height: 42px;
}
.icon-favicon {
background-image: url(../img/spritesheet.png);
background-position: -582px -151px;
width: 16px;
height: 16px;
}
.icon-gallery {
background-image: url(../img/spritesheet.png);
background-position: -512px -225px;
width: 52px;
height: 51px;
}
.icon-garbage {
background-image: url(../img/spritesheet.png);
background-position: 0px 0px;
width: 512px;
height: 512px;
}
.icon-gear {
background-image: url(../img/spritesheet.png);
background-position: -563px -323px;
width: 38px;
height: 37px;
}
.icon-import-icon {
background-image: url(../img/spritesheet.png);
background-position: -576px -69px;
width: 28px;
height: 36px;
}
.icon-keyboard {
background-image: url(../img/spritesheet.png);
background-position: -512px -133px;
width: 70px;
height: 40px;
}
.icon-local-storage-icon {
background-image: url(../img/spritesheet.png);
background-position: -512px 0px;
width: 100px;
height: 69px;
}
.icon-merge-icon {
background-image: url(../img/spritesheet.png);
background-position: -512px -69px;
width: 64px;
height: 64px;
}
.icon-plus {
background-image: url(../img/spritesheet.png);
background-position: -512px -323px;
width: 51px;
height: 46px;
}
.icon-popup-preview-arrow-gold {
background-image: url(../img/spritesheet.png);
background-position: -576px -105px;
width: 24px;
height: 18px;
}
.icon-popup-preview-arrow-white {
background-image: url(../img/spritesheet.png);
background-position: -582px -133px;
width: 24px;
height: 18px;
}
.icon-resize-icon {
background-image: url(../img/spritesheet.png);
background-position: -512px -173px;
width: 52px;
height: 52px;
}
.icon-save {
background-image: url(../img/spritesheet.png);
background-position: -562px -276px;
width: 43px;
height: 42px;
}

View File

@@ -55,10 +55,6 @@ body {
margin-left: 0; margin-left: 0;
} }
.hidden {
display: none;
}
/** /**
* TOOLTIPS * TOOLTIPS
*/ */

View File

@@ -76,11 +76,6 @@
position: relative; position: relative;
} }
.palettes-list-colors.tiny > .palettes-list-color {
width: calc((100% - 35px) / 10);
height: 16px;
}
.palettes-list-color div { .palettes-list-color div {
height: 100%; height: 100%;
} }
@@ -126,8 +121,7 @@
* Color index for the 9 first colors * Color index for the 9 first colors
*/ */
:not(.tiny) > .palettes-list-color:nth-child(-n+10):after { .palettes-list-color:nth-child(-n+10):after {
content: attr(data-color-index);
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
@@ -142,3 +136,39 @@
padding: 2px 3px 2px 3px; padding: 2px 3px 2px 3px;
border-radius: 0 0 0 2px; border-radius: 0 0 0 2px;
} }
.palettes-list-color:nth-child(1):after {
content: "1";
}
.palettes-list-color:nth-child(2):after {
content: "2";
}
.palettes-list-color:nth-child(3):after {
content: "3";
}
.palettes-list-color:nth-child(4):after {
content: "4";
}
.palettes-list-color:nth-child(5):after {
content: "5";
}
.palettes-list-color:nth-child(6):after {
content: "6";
}
.palettes-list-color:nth-child(7):after {
content: "7";
}
.palettes-list-color:nth-child(8):after {
content: "8";
}
.palettes-list-color:nth-child(9):after {
content: "9";
}

View File

@@ -3,38 +3,5 @@
} }
.transformations-container .tool-icon { .transformations-container .tool-icon {
margin: 0 0 5px 0; float:left;
} }
.transformations-container .tools-wrapper {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
height: 46px;
/* Override the float:left set on tools-wrapper in layout.css; */
float: initial;
}
.transformations-container.show-more .tools-wrapper {
height: auto;
/* Compensate the 5px bottom-margin coming from the tool-icon */
margin-bottom: -5px;
}
.transformations-show-more-link {
position: absolute;
color: #999;
right: 10px;
font-weight: normal;
cursor: pointer;
transition: 0.2s linear;
}
.transformations-show-more-link:hover {
color: white;
}
.show-more .transformations-show-more-link {
color: gold;
}

View File

@@ -1,98 +0,0 @@
/*****************/
/* ANCHOR WIDGET */
/*****************/
.anchor-wrapper {
overflow: hidden;
width: 70px;
}
/* When transitioning between enabled and disabled states */
.transition .anchor-option,
.transition .anchor-option:before {
transition: background-color 0.2s, border-color 0.2s;
}
.anchor-option {
float: left;
position: relative;
box-sizing: border-box;
margin: 0 1px 1px 0;
width: 20px;
height: 20px;
background : #888;
font-size: 8px;
text-align: center;
cursor: pointer;
}
.disabled .anchor-option {
cursor: default;
background : #555;
border-color: #555 !important;
}
.anchor-option:hover {
border : 3px solid white;
}
.anchor-option.selected {
border : 3px solid var(--highlight-color);
}
.anchor-option:before {
content: '';
position: absolute;
display: block;
top: 50%;
left: 50%;
margin: -2px;
}
.anchor-option.selected:before {
content: '';
width: 4px;
height: 4px;
background: var(--highlight-color);
}
.disabled .anchor-option.selected:before {
background: #555;
}
.disabled .anchor-option[data-neighbor]:before {
border-color: #555 !important;
}
.anchor-option[data-neighbor]:before {
width: 0;
height: 0;
border-width: 4px;
border-style: solid;
border-color: transparent;
}
.anchor-option[data-neighbor="bottom"]:before {
border-top-color: var(--highlight-color);
margin-left: -4px;
}
.anchor-option[data-neighbor="left"]:before {
border-right-color: var(--highlight-color);
margin-top: -4px;
margin-left: -6px;
}
.anchor-option[data-neighbor="top"]:before {
border-bottom-color: var(--highlight-color);
margin-top: -6px;
margin-left: -4px;
}
.anchor-option[data-neighbor="right"]:before {
border-left-color: var(--highlight-color);
margin-top: -4px;
}

View File

@@ -1,55 +0,0 @@
/***********************/
/* FRAME PICKER WIDGET */
/***********************/
.frame-picker-wrapper {
width: 150px;
height: 150px;
border: 3px solid #666;
border-radius: 3px;
}
.frame-viewer {
width: 100%;
height: calc(100% - 25px);
display: flex;
align-items: center;
justify-content: center;
}
.frame-viewer > canvas,
.frame-viewer > img {
max-width: 100%;
max-height: 100%;
}
.frame-nav {
display: flex;
width: 100%;
height: 24px;
border-top: 1px solid #666;
}
.frame-nav .button {
flex-shrink: 0;
border-radius: 0;
height: 24px;
background-color: #3f3f3f;
}
.frame-nav .button[disabled],
.frame-nav .button[disabled]:hover {
background-color: #aaa;
}
.frame-nav .button + .button {
border-left: 1px solid #333;
}
.frame-nav-input {
min-width: 1px;
border-style: none;
height: 24px;
text-align: center;
}

View File

@@ -1,42 +0,0 @@
/*****************/
/* TABS WIDGET */
/*****************/
.tab-list {
overflow: hidden;
position: relative;
}
.tab-list:after {
content: "";
display: block;
position: absolute;
bottom: 0;
width: 100%;
height: 1px;
z-index: 0;
background-color: var(--highlight-color);
}
.tab-item {
float: left;
cursor: pointer;
padding: 5px;
border: 1px solid transparent;
border-radius: 2px 2px 0 0;
/* Make sure the tab and its border are positioned above the :after element; */
position: relative;
z-index: 1;
}
.tab-item.selected,
.tab-item:hover {
color: var(--highlight-color);
}
.tab-item.selected {
border-color: var(--highlight-color);
border-bottom-color: #444;
border-style: solid;
border-width: 1px;
}

View File

@@ -1,32 +0,0 @@
.wizard-wrapper {
z-index: 1;
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
}
.wizard-step {
z-index: -1;
margin-left: calc(100% + 5px);
position: absolute;
}
.current-step {
z-index: 1;
margin-left: 0;
}
.current-step-in,
.current-step-out {
z-index: 10;
transition: margin-left 200ms;
}
.current-step-in {
margin-left: 0;
}
.current-step-out {
margin-left: 100%;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 693 B

View File

@@ -22,7 +22,9 @@
color:white;"> color:white;">
<span style="top:45%">Loading Piskel ...</span> <span style="top:45%">Loading Piskel ...</span>
</div> </div>
<!--standalone-start-->
@@include('templates/debug-header.html', {}) @@include('templates/debug-header.html', {})
<!--standalone-end-->
<!-- the comment below indicates the beginning of markup reused by the editor integrated in piskelapp.com --> <!-- the comment below indicates the beginning of markup reused by the editor integrated in piskelapp.com -->
<!-- do not delete, do not move :) --> <!-- do not delete, do not move :) -->
@@ -76,17 +78,14 @@
<!-- dialogs partials --> <!-- dialogs partials -->
@@include('templates/dialogs/create-palette.html', {}) @@include('templates/dialogs/create-palette.html', {})
@@include('templates/dialogs/import-image.html', {})
@@include('templates/dialogs/browse-local.html', {}) @@include('templates/dialogs/browse-local.html', {})
@@include('templates/dialogs/cheatsheet.html', {}) @@include('templates/dialogs/cheatsheet.html', {})
@@include('templates/dialogs/import.html', {})
@@include('templates/dialogs/performance-info.html', {}) @@include('templates/dialogs/performance-info.html', {})
@@include('templates/dialogs/unsupported-browser.html', {}) @@include('templates/dialogs/unsupported-browser.html', {})
<!-- settings-panel partials --> <!-- settings-panel partials -->
@@include('templates/settings/preferences.html', {}) @@include('templates/settings/application.html', {})
@@include('templates/settings/preferences/grid.html', {})
@@include('templates/settings/preferences/misc.html', {})
@@include('templates/settings/preferences/tile.html', {})
@@include('templates/settings/resize.html', {}) @@include('templates/settings/resize.html', {})
@@include('templates/settings/save.html', {}) @@include('templates/settings/save.html', {})
@@include('templates/settings/import.html', {}) @@include('templates/settings/import.html', {})

View File

@@ -1,99 +0,0 @@
{
"env": {
"es6": true,
"browser": true
},
"globals": {
"$": true,
"jQuery": true,
"pskl": true,
"Events": true,
"Constants": true,
"console": true,
"module": true,
"require": true,
"Q": true,
"Promise": true
},
"rules": {
"no-undef": 2,
"no-use-before-define": [
2,
{
"functions": false
}
],
"curly": [
2,
"all"
],
"operator-linebreak": [
2,
"after"
],
"camelcase": [
2,
{
"properties": "never"
}
],
"max-len": [
2,
120
],
"indent": [
2,
2,
{
"SwitchCase": 1
}
],
"quotes": [
2,
"single"
],
"no-multi-str": 2,
"no-mixed-spaces-and-tabs": 2,
"no-trailing-spaces": 2,
"space-unary-ops": [
2,
{
"nonwords": false,
"overrides": {}
}
],
"one-var": [
2,
"never"
],
"brace-style": [
2,
"1tbs",
{
"allowSingleLine": true
}
],
"keyword-spacing": [
2,
{}
],
"space-infix-ops": 2,
"space-before-blocks": [
2,
"always"
],
"eol-last": 2,
"space-in-parens": [
2,
"never"
],
"no-multiple-empty-lines": 2,
"no-with": 2,
"no-spaced-func": 2,
"dot-notation": 2,
"semi": [
2,
"always"
]
}
}

View File

@@ -15,7 +15,7 @@ var Events = {
DRAG_START : 'DRAG_START', DRAG_START : 'DRAG_START',
DRAG_END : 'DRAG_END', DRAG_END : 'DRAG_END',
DIALOG_SHOW : 'DIALOG_SHOW', DIALOG_DISPLAY : 'DIALOG_DISPLAY',
DIALOG_HIDE : 'DIALOG_HIDE', DIALOG_HIDE : 'DIALOG_HIDE',
PALETTE_LIST_UPDATED : 'PALETTE_LIST_UPDATED', PALETTE_LIST_UPDATED : 'PALETTE_LIST_UPDATED',

View File

@@ -10,9 +10,6 @@
ns.app = { ns.app = {
init : function () { init : function () {
// Run preferences migration scripts for version v0.12.0
pskl.UserSettings.migrate_to_v0_12();
/** /**
* When started from APP Engine, appEngineToken_ (Boolean) should be set on window.pskl * When started from APP Engine, appEngineToken_ (Boolean) should be set on window.pskl
*/ */
@@ -190,8 +187,8 @@
gui.Window.get().menu = mb; gui.Window.get().menu = mb;
} }
if (!pskl.utils.Environment.isIntegrationTest() && pskl.utils.UserAgent.isUnsupported()) { if (pskl.utils.UserAgent.isUnsupported()) {
$.publish(Events.DIALOG_SHOW, { $.publish(Events.DIALOG_DISPLAY, {
dialogId : 'unsupported-browser' dialogId : 'unsupported-browser'
}); });
} }

View File

@@ -64,10 +64,6 @@
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.RESET_ZOOM, this.resetZoom_.bind(this)); pskl.app.shortcutService.registerShortcut(shortcuts.MISC.RESET_ZOOM, this.resetZoom_.bind(this));
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.INCREASE_ZOOM, this.updateZoom_.bind(this, 1)); pskl.app.shortcutService.registerShortcut(shortcuts.MISC.INCREASE_ZOOM, this.updateZoom_.bind(this, 1));
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.DECREASE_ZOOM, this.updateZoom_.bind(this, -1)); pskl.app.shortcutService.registerShortcut(shortcuts.MISC.DECREASE_ZOOM, this.updateZoom_.bind(this, -1));
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.OFFSET_UP, this.updateOffset_.bind(this, 'up'));
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.OFFSET_RIGHT, this.updateOffset_.bind(this, 'right'));
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.OFFSET_DOWN, this.updateOffset_.bind(this, 'down'));
pskl.app.shortcutService.registerShortcut(shortcuts.MISC.OFFSET_LEFT, this.updateOffset_.bind(this, 'left'));
window.setTimeout(function () { window.setTimeout(function () {
this.afterWindowResize_(); this.afterWindowResize_();
@@ -266,29 +262,6 @@
this.updateZoom_(modifier, coords); this.updateZoom_(modifier, coords);
}; };
/**
* Update the current viewport offset of 1 pixel in the provided direction.
* Direction can be one of 'up', 'right', 'down', 'left'.
* Callback for the OFFSET_${DIR} shortcuts.
*/
ns.DrawingController.prototype.updateOffset_ = function (direction) {
var off = this.getOffset();
if (direction === 'up') {
off.y -= 1;
} else if (direction === 'right') {
off.x += 1;
} else if (direction === 'down') {
off.y += 1;
} else if (direction === 'left') {
off.x -= 1;
}
this.setOffset(
off.x,
off.y
);
};
/** /**
* Update the current zoom level by a given multiplier. * Update the current zoom level by a given multiplier.
* *

View File

@@ -17,7 +17,6 @@
this.rootEl.addEventListener('click', this.onClick_.bind(this)); this.rootEl.addEventListener('click', this.onClick_.bind(this));
this.toggleLayerPreviewEl.addEventListener('click', this.toggleLayerPreview_.bind(this)); this.toggleLayerPreviewEl.addEventListener('click', this.toggleLayerPreview_.bind(this));
this.createButtonTooltips_();
this.initToggleLayerPreview_(); this.initToggleLayerPreview_();
this.renderLayerList_(); this.renderLayerList_();
@@ -46,26 +45,6 @@
} }
}; };
ns.LayersListController.prototype.createButtonTooltips_ = function () {
var addTooltip = pskl.utils.TooltipFormatter.format('Create a layer', null, [
{key : 'shift', description : 'Clone current layer'}
]);
var addButton = this.rootEl.querySelector('[data-action="add"]');
addButton.setAttribute('title', addTooltip);
var moveDownTooltip = pskl.utils.TooltipFormatter.format('Move layer down', null, [
{key : 'shift', description : 'Move to the bottom'}
]);
var moveDownButton = this.rootEl.querySelector('[data-action="down"]');
moveDownButton.setAttribute('title', moveDownTooltip);
var moveUpTooltip = pskl.utils.TooltipFormatter.format('Move layer up', null, [
{key : 'shift', description : 'Move to the top'}
]);
var moveUpButton = this.rootEl.querySelector('[data-action="up"]');
moveUpButton.setAttribute('title', moveUpTooltip);
};
ns.LayersListController.prototype.initToggleLayerPreview_ = function () { ns.LayersListController.prototype.initToggleLayerPreview_ = function () {
var descriptors = [{description : 'Opacity defined in PREFERENCES'}]; var descriptors = [{description : 'Opacity defined in PREFERENCES'}];
var helpText = 'Preview all layers'; var helpText = 'Preview all layers';
@@ -138,7 +117,7 @@
var el = evt.target || evt.srcElement; var el = evt.target || evt.srcElement;
var index; var index;
if (el.classList.contains('button')) { if (el.classList.contains('button')) {
this.onButtonClick_(el, evt); this.onButtonClick_(el);
} else if (el.classList.contains('layer-name')) { } else if (el.classList.contains('layer-name')) {
index = pskl.utils.Dom.getData(el, 'layerIndex'); index = pskl.utils.Dom.getData(el, 'layerIndex');
this.piskelController.setCurrentLayerIndex(parseInt(index, 10)); this.piskelController.setCurrentLayerIndex(parseInt(index, 10));
@@ -166,18 +145,14 @@
this.renderLayerList_(); this.renderLayerList_();
}; };
ns.LayersListController.prototype.onButtonClick_ = function (button, evt) { ns.LayersListController.prototype.onButtonClick_ = function (button) {
var action = button.getAttribute('data-action'); var action = button.getAttribute('data-action');
if (action == 'up') { if (action == 'up') {
this.piskelController.moveLayerUp(evt.shiftKey); this.piskelController.moveLayerUp();
} else if (action == 'down') { } else if (action == 'down') {
this.piskelController.moveLayerDown(evt.shiftKey); this.piskelController.moveLayerDown();
} else if (action == 'add') { } else if (action == 'add') {
if (evt.shiftKey) { this.piskelController.createLayer();
this.piskelController.duplicateCurrentLayer();
} else {
this.piskelController.createLayer();
}
} else if (action == 'delete') { } else if (action == 'delete') {
this.piskelController.removeCurrentLayer(); this.piskelController.removeCurrentLayer();
} else if (action == 'merge') { } else if (action == 'merge') {

View File

@@ -51,17 +51,12 @@
}; };
ns.PalettesListController.prototype.fillColorListContainer = function () { ns.PalettesListController.prototype.fillColorListContainer = function () {
var colors = this.getSelectedPaletteColors_(); var colors = this.getSelectedPaletteColors_();
if (colors.length > 0) { if (colors.length > 0) {
var html = colors.filter(function (color) { var html = colors.map(function (color, index) {
return !!color; return pskl.utils.Template.replace(this.paletteColorTemplate_, {color : color, index : index});
}).map(function (color, index) {
return pskl.utils.Template.replace(this.paletteColorTemplate_, {
color : color,
index : index + 1,
title : color.toUpperCase()
});
}.bind(this)).join(''); }.bind(this)).join('');
this.colorListContainer_.innerHTML = html; this.colorListContainer_.innerHTML = html;
@@ -69,10 +64,6 @@
} else { } else {
this.colorListContainer_.innerHTML = pskl.utils.Template.get('palettes-list-no-colors-partial'); this.colorListContainer_.innerHTML = pskl.utils.Template.get('palettes-list-no-colors-partial');
} }
// If we have more than 10 colors, use tiny mode, where 10 colors will fit on the same
// line.
this.colorListContainer_.classList.toggle('tiny', colors.length > 10);
}; };
ns.PalettesListController.prototype.selectPalette = function (paletteId) { ns.PalettesListController.prototype.selectPalette = function (paletteId) {
@@ -110,7 +101,7 @@
var currentIndex = 0; var currentIndex = 0;
var selectedColor = document.querySelector('.' + PRIMARY_COLOR_CLASSNAME); var selectedColor = document.querySelector('.' + PRIMARY_COLOR_CLASSNAME);
if (selectedColor) { if (selectedColor) {
currentIndex = parseInt(selectedColor.dataset.colorIndex, 10) - 1; currentIndex = parseInt(selectedColor.dataset.colorIndex, 10);
} }
return currentIndex; return currentIndex;
}; };
@@ -148,14 +139,14 @@
}; };
ns.PalettesListController.prototype.onCreatePaletteClick_ = function (evt) { ns.PalettesListController.prototype.onCreatePaletteClick_ = function (evt) {
$.publish(Events.DIALOG_SHOW, { $.publish(Events.DIALOG_DISPLAY, {
dialogId : 'create-palette' dialogId : 'create-palette'
}); });
}; };
ns.PalettesListController.prototype.onEditPaletteClick_ = function (evt) { ns.PalettesListController.prototype.onEditPaletteClick_ = function (evt) {
var paletteId = this.colorPaletteSelect_.value; var paletteId = this.colorPaletteSelect_.value;
$.publish(Events.DIALOG_SHOW, { $.publish(Events.DIALOG_DISPLAY, {
dialogId : 'create-palette', dialogId : 'create-palette',
initArgs : paletteId initArgs : paletteId
}); });

View File

@@ -1,19 +1,23 @@
(function () { (function () {
var ns = $.namespace('pskl.controller'); var ns = $.namespace('pskl.controller');
ns.PenSizeController = function () { ns.PenSizeController = function () {};
this.sizePicker = new pskl.widgets.SizePicker(this.onSizePickerChanged_.bind(this));
};
ns.PenSizeController.prototype.init = function () { ns.PenSizeController.prototype.init = function () {
this.sizePicker.init(document.querySelector('.pen-size-container')); this.container = document.querySelector('.pen-size-container');
pskl.utils.Event.addEventListener(this.container, 'click', this.onPenSizeOptionClick_, this);
$.subscribe(Events.PEN_SIZE_CHANGED, this.onPenSizeChanged_.bind(this)); $.subscribe(Events.PEN_SIZE_CHANGED, this.onPenSizeChanged_.bind(this));
this.updateSelectedOption_(); this.updateSelectedOption_();
}; };
ns.PenSizeController.prototype.onSizePickerChanged_ = function (size) { ns.PenSizeController.prototype.onPenSizeOptionClick_ = function (e) {
pskl.app.penSizeService.setPenSize(size); var size = e.target.dataset.size;
if (!isNaN(size)) {
size = parseInt(size, 10);
pskl.app.penSizeService.setPenSize(size);
}
}; };
ns.PenSizeController.prototype.onPenSizeChanged_ = function (e) { ns.PenSizeController.prototype.onPenSizeChanged_ = function (e) {
@@ -21,7 +25,19 @@
}; };
ns.PenSizeController.prototype.updateSelectedOption_ = function () { ns.PenSizeController.prototype.updateSelectedOption_ = function () {
pskl.utils.Dom.removeClass('labeled', this.container);
pskl.utils.Dom.removeClass('selected', this.container);
var size = pskl.app.penSizeService.getPenSize(); var size = pskl.app.penSizeService.getPenSize();
this.sizePicker.setSize(size); var selectedOption;
if (size <= 4) {
selectedOption = this.container.querySelector('[data-size="' + size + '"]');
} else {
selectedOption = this.container.querySelector('[data-size="4"]');
selectedOption.classList.add('labeled');
selectedOption.setAttribute('real-pen-size', size);
}
if (selectedOption) {
selectedOption.classList.add('selected');
}
}; };
})(); })();

View File

@@ -1,30 +1,22 @@
(function () { (function () {
var ns = $.namespace('pskl.controller'); var ns = $.namespace('pskl.controller');
var SHOW_MORE_CLASS = 'show-more';
ns.TransformationsController = function () { ns.TransformationsController = function () {
this.tools = [ this.tools = [
new pskl.tools.transform.Flip(), new pskl.tools.transform.Flip(),
new pskl.tools.transform.Rotate(), new pskl.tools.transform.Rotate(),
new pskl.tools.transform.Clone(), new pskl.tools.transform.Clone(),
new pskl.tools.transform.Center(), new pskl.tools.transform.Center()
new pskl.tools.transform.Crop(),
]; ];
this.toolIconBuilder = new pskl.tools.ToolIconBuilder(); this.toolIconBuilder = new pskl.tools.ToolIconBuilder();
}; };
ns.TransformationsController.prototype.init = function () { ns.TransformationsController.prototype.init = function () {
this.container = document.querySelector('.transformations-container'); var container = document.querySelector('.transformations-container');
this.container.addEventListener('click', this.onTransformationClick_.bind(this)); this.toolsContainer = container.querySelector('.tools-wrapper');
container.addEventListener('click', this.onTransformationClick_.bind(this));
this.showMoreLink = this.container.querySelector('.transformations-show-more-link');
this.showMoreLink.addEventListener('click', this.toggleShowMoreTools_.bind(this));
this.createToolsDom_(); this.createToolsDom_();
this.updateShowMoreLink_();
$.subscribe(Events.USER_SETTINGS_CHANGED, this.onUserSettingsChange_.bind(this));
}; };
ns.TransformationsController.prototype.applyTool = function (toolId, evt) { ns.TransformationsController.prototype.applyTool = function (toolId, evt) {
@@ -38,35 +30,13 @@
ns.TransformationsController.prototype.onTransformationClick_ = function (evt) { ns.TransformationsController.prototype.onTransformationClick_ = function (evt) {
var toolId = evt.target.dataset.toolId; var toolId = evt.target.dataset.toolId;
if (toolId) { this.applyTool(toolId, evt);
this.applyTool(toolId, evt);
}
};
ns.TransformationsController.prototype.toggleShowMoreTools_ = function (evt) {
var showMore = pskl.UserSettings.get(pskl.UserSettings.TRANSFORM_SHOW_MORE);
pskl.UserSettings.set(pskl.UserSettings.TRANSFORM_SHOW_MORE, !showMore);
};
ns.TransformationsController.prototype.onUserSettingsChange_ = function (evt, settingName) {
if (settingName == pskl.UserSettings.TRANSFORM_SHOW_MORE) {
this.updateShowMoreLink_();
}
};
ns.TransformationsController.prototype.updateShowMoreLink_ = function () {
var showMoreEnabled = pskl.UserSettings.get(pskl.UserSettings.TRANSFORM_SHOW_MORE);
this.container.classList.toggle(SHOW_MORE_CLASS, showMoreEnabled);
// Hide the link in case there are 4 or less tools available.
this.showMoreLink.classList.toggle('hidden', this.tools.length < 5);
}; };
ns.TransformationsController.prototype.createToolsDom_ = function() { ns.TransformationsController.prototype.createToolsDom_ = function() {
var html = this.tools.reduce(function (p, tool) { var html = this.tools.reduce(function (p, tool) {
return p + this.toolIconBuilder.createIcon(tool, 'left'); return p + this.toolIconBuilder.createIcon(tool, 'left');
}.bind(this), ''); }.bind(this), '');
var toolsContainer = this.container.querySelector('.tools-wrapper'); this.toolsContainer.innerHTML = html;
toolsContainer.innerHTML = html;
}; };
})(); })();

View File

@@ -9,7 +9,7 @@
// This method is not attached to the prototype because we want to trigger it // This method is not attached to the prototype because we want to trigger it
// from markup generated for a notification message. // from markup generated for a notification message.
ns.UserWarningController.showPerformanceInfoDialog = function () { ns.UserWarningController.showPerformanceInfoDialog = function () {
$.publish(Events.DIALOG_SHOW, { $.publish(Events.DIALOG_DISPLAY, {
dialogId: 'performance-info' dialogId: 'performance-info'
}); });
}; };

View File

@@ -4,19 +4,14 @@
ns.AbstractDialogController = function () {}; ns.AbstractDialogController = function () {};
ns.AbstractDialogController.prototype.init = function () { ns.AbstractDialogController.prototype.init = function () {
var closeButton = document.querySelector('.dialog-close'); this.closeButton = document.querySelector('.dialog-close');
this.addEventListener(closeButton, 'click', this.closeDialog); this.closeButton.addEventListener('click', this.closeDialog.bind(this));
}; };
ns.AbstractDialogController.prototype.addEventListener = function (el, type, cb) { ns.AbstractDialogController.prototype.destroy = function () {};
pskl.utils.Event.addEventListener(el, type, cb, this);
};
ns.AbstractDialogController.prototype.destroy = function () {
pskl.utils.Event.removeAllEventListeners(this);
};
ns.AbstractDialogController.prototype.closeDialog = function () { ns.AbstractDialogController.prototype.closeDialog = function () {
this.destroy();
$.publish(Events.DIALOG_HIDE); $.publish(Events.DIALOG_HIDE);
}; };

View File

@@ -1,7 +1,8 @@
(function () { (function () {
var ns = $.namespace('pskl.controller.dialogs'); var ns = $.namespace('pskl.controller.dialogs');
ns.BrowseLocalController = function (piskelController) {}; ns.BrowseLocalController = function (piskelController) {
};
pskl.utils.inherit(ns.BrowseLocalController, ns.AbstractDialogController); pskl.utils.inherit(ns.BrowseLocalController, ns.AbstractDialogController);

View File

@@ -13,12 +13,11 @@
this.cheatsheetEl = document.getElementById('cheatsheetContainer'); this.cheatsheetEl = document.getElementById('cheatsheetContainer');
this.eventTrapInput = document.getElementById('cheatsheetEventTrap'); this.eventTrapInput = document.getElementById('cheatsheetEventTrap');
this.addEventListener('.cheatsheet-restore-defaults', 'click', this.onRestoreDefaultsClick_); pskl.utils.Event.addEventListener('.cheatsheet-restore-defaults', 'click', this.onRestoreDefaultsClick_, this);
this.addEventListener(this.cheatsheetEl, 'click', this.onCheatsheetClick_); pskl.utils.Event.addEventListener(this.cheatsheetEl, 'click', this.onCheatsheetClick_, this);
this.addEventListener(this.eventTrapInput, 'keydown', this.onEventTrapKeydown_); pskl.utils.Event.addEventListener(this.eventTrapInput, 'keydown', this.onEventTrapKeydown_, this);
this.onShortcutsChanged_ = this.onShortcutsChanged_.bind(this); $.subscribe(Events.SHORTCUTS_CHANGED, this.onShortcutsChanged_.bind(this));
$.subscribe(Events.SHORTCUTS_CHANGED, this.onShortcutsChanged_);
this.initMarkup_(); this.initMarkup_();
document.querySelector('.cheatsheet-helptext').setAttribute('title', this.getHelptextTitle_()); document.querySelector('.cheatsheet-helptext').setAttribute('title', this.getHelptextTitle_());
@@ -26,11 +25,8 @@
ns.CheatsheetController.prototype.destroy = function () { ns.CheatsheetController.prototype.destroy = function () {
this.eventTrapInput.blur(); this.eventTrapInput.blur();
pskl.utils.Event.removeAllEventListeners();
$.unsubscribe(Events.SHORTCUTS_CHANGED, this.onShortcutsChanged_);
this.cheatsheetEl = null; this.cheatsheetEl = null;
this.superclass.destroy.call(this);
}; };
ns.CheatsheetController.prototype.onRestoreDefaultsClick_ = function () { ns.CheatsheetController.prototype.onRestoreDefaultsClick_ = function () {
@@ -144,8 +140,7 @@
title : title, title : title,
icon : descriptor.iconClass, icon : descriptor.iconClass,
description : description, description : description,
// Avoid sanitization key : this.formatKey_(shortcut.getDisplayKey()),
'!key!' : this.formatKey_(shortcut.getDisplayKey()),
className : shortcutClasses.join(' ') className : shortcutClasses.join(' ')
}); });

View File

@@ -19,12 +19,12 @@
var downloadButton = document.querySelector('.create-palette-download-button'); var downloadButton = document.querySelector('.create-palette-download-button');
var importFileButton = document.querySelector('.create-palette-import-button'); var importFileButton = document.querySelector('.create-palette-import-button');
this.addEventListener(this.nameInput, 'input', this.onNameInputChange_); this.nameInput.addEventListener('input', this.onNameInputChange_.bind(this));
this.addEventListener(this.hiddenFileInput, 'change', this.onFileInputChange_); this.hiddenFileInput.addEventListener('change', this.onFileInputChange_.bind(this));
this.addEventListener(buttonsContainer, 'click', this.onButtonClick_); buttonsContainer.addEventListener('click', this.onButtonClick_.bind(this));
this.addEventListener(downloadButton, 'click', this.onDownloadButtonClick_); downloadButton.addEventListener('click', this.onDownloadButtonClick_.bind(this));
this.addEventListener(importFileButton, 'click', this.onImportFileButtonClick_); importFileButton.addEventListener('click', this.onImportFileButtonClick_.bind(this));
var colorsListContainer = document.querySelector('.colors-container'); var colorsListContainer = document.querySelector('.colors-container');
this.colorsListWidget = new pskl.widgets.ColorsList(colorsListContainer); this.colorsListWidget = new pskl.widgets.ColorsList(colorsListContainer);
@@ -66,10 +66,7 @@
ns.CreatePaletteController.prototype.destroy = function () { ns.CreatePaletteController.prototype.destroy = function () {
this.colorsListWidget.destroy(); this.colorsListWidget.destroy();
this.superclass.destroy.call(this);
this.nameInput = null; this.nameInput = null;
this.hiddenFileInput = null;
}; };
ns.CreatePaletteController.prototype.onButtonClick_ = function (evt) { ns.CreatePaletteController.prototype.onButtonClick_ = function (evt) {

View File

@@ -14,9 +14,9 @@
template : 'templates/dialogs/browse-local.html', template : 'templates/dialogs/browse-local.html',
controller : ns.BrowseLocalController controller : ns.BrowseLocalController
}, },
'import' : { 'import-image' : {
template : 'templates/dialogs/import.html', template : 'templates/dialogs/import-image.html',
controller : ns.importwizard.ImportWizard controller : ns.ImportImageController
}, },
'performance-info' : { 'performance-info' : {
template : 'templates/dialogs/performance-info.html', template : 'templates/dialogs/performance-info.html',
@@ -38,7 +38,7 @@
this.dialogContainer_ = document.getElementById('dialog-container'); this.dialogContainer_ = document.getElementById('dialog-container');
this.dialogWrapper_ = document.getElementById('dialog-container-wrapper'); this.dialogWrapper_ = document.getElementById('dialog-container-wrapper');
$.subscribe(Events.DIALOG_SHOW, this.onDialogDisplayEvent_.bind(this)); $.subscribe(Events.DIALOG_DISPLAY, this.onDialogDisplayEvent_.bind(this));
$.subscribe(Events.DIALOG_HIDE, this.hideDialog.bind(this)); $.subscribe(Events.DIALOG_HIDE, this.hideDialog.bind(this));
var createPaletteShortcut = pskl.service.keyboard.Shortcuts.COLOR.CREATE_PALETTE; var createPaletteShortcut = pskl.service.keyboard.Shortcuts.COLOR.CREATE_PALETTE;
@@ -51,6 +51,7 @@
// adding the .animated class here instead of in the markup to avoid an animation during app startup // adding the .animated class here instead of in the markup to avoid an animation during app startup
this.dialogWrapper_.classList.add('animated'); this.dialogWrapper_.classList.add('animated');
pskl.utils.Event.addEventListener(this.dialogWrapper_, 'click', this.onWrapperClicked_, this); pskl.utils.Event.addEventListener(this.dialogWrapper_, 'click', this.onWrapperClicked_, this);
}; };
ns.DialogsController.prototype.onCreatePaletteShortcut_ = function () { ns.DialogsController.prototype.onCreatePaletteShortcut_ = function () {

View File

@@ -0,0 +1,261 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs');
ns.ImportImageController = function (piskelController) {
this.importedImage_ = null;
this.file_ = null;
};
pskl.utils.inherit(ns.ImportImageController, ns.AbstractDialogController);
ns.ImportImageController.prototype.init = function (file) {
this.superclass.init.call(this);
this.file_ = file;
this.importPreview = $('.import-section-preview');
this.fileNameContainer = $('.import-image-file-name');
this.importType = $('[name=import-type]');
this.resizeWidth = $('[name=resize-width]');
this.resizeHeight = $('[name=resize-height]');
this.smoothResize = $('[name=smooth-resize-checkbox]');
this.frameSizeX = $('[name=frame-size-x]');
this.frameSizeY = $('[name=frame-size-y]');
this.frameOffsetX = $('[name=frame-offset-x]');
this.frameOffsetY = $('[name=frame-offset-y]');
this.importType.change(this.onImportTypeChange_.bind(this));
this.resizeWidth.keyup(this.onResizeInputKeyUp_.bind(this, 'width'));
this.resizeHeight.keyup(this.onResizeInputKeyUp_.bind(this, 'height'));
this.frameSizeX.keyup(this.onFrameInputKeyUp_.bind(this, 'frameSizeX'));
this.frameSizeY.keyup(this.onFrameInputKeyUp_.bind(this, 'frameSizeY'));
this.frameOffsetX.keyup(this.onFrameInputKeyUp_.bind(this, 'frameOffsetX'));
this.frameOffsetY.keyup(this.onFrameInputKeyUp_.bind(this, 'frameOffsetY'));
this.importImageForm = $('[name=import-image-form]');
this.importImageForm.submit(this.onImportFormSubmit_.bind(this));
pskl.utils.FileUtils.readImageFile(this.file_, this.onImageLoaded_.bind(this));
};
ns.ImportImageController.prototype.onImportTypeChange_ = function (evt) {
if (this.getImportType_() === 'single') {
// Using single image, so remove the frame grid
this.hideFrameGrid_();
} else {
// Using spritesheet import, so draw the frame grid in the preview
var x = this.sanitizeInputValue_(this.frameOffsetX, 0);
var y = this.sanitizeInputValue_(this.frameOffsetY, 0);
var w = this.sanitizeInputValue_(this.frameSizeX, 1);
var h = this.sanitizeInputValue_(this.frameSizeY, 1);
this.drawFrameGrid_(x, y, w, h);
}
};
ns.ImportImageController.prototype.onImportFormSubmit_ = function (evt) {
evt.originalEvent.preventDefault();
this.importImageToPiskel_();
};
ns.ImportImageController.prototype.onResizeInputKeyUp_ = function (from, evt) {
if (this.importedImage_) {
this.synchronizeResizeFields_(evt.target.value, from);
}
};
ns.ImportImageController.prototype.onFrameInputKeyUp_ = function (from, evt) {
if (this.importedImage_) {
this.synchronizeFrameFields_(evt.target.value, from);
}
};
ns.ImportImageController.prototype.synchronizeResizeFields_ = function (value, from) {
value = parseInt(value, 10);
if (isNaN(value)) {
value = 0;
}
var height = this.importedImage_.height;
var width = this.importedImage_.width;
// Select single image import type since the user changed a value here
this.importType.filter('[value="single"]').attr('checked', 'checked');
if (from === 'width') {
this.resizeHeight.val(Math.round(value * height / width));
} else {
this.resizeWidth.val(Math.round(value * width / height));
}
};
ns.ImportImageController.prototype.synchronizeFrameFields_ = function (value, from) {
value = parseInt(value, 10);
if (isNaN(value)) {
value = 0;
}
// Parse the frame input values
var frameSizeX = this.sanitizeInputValue_(this.frameSizeX, 1);
var frameSizeY = this.sanitizeInputValue_(this.frameSizeY, 1);
var frameOffsetX = this.sanitizeInputValue_(this.frameOffsetX, 0);
var frameOffsetY = this.sanitizeInputValue_(this.frameOffsetY, 0);
// Select spritesheet import type since the user changed a value here
this.importType.filter('[value="sheet"]').attr('checked', 'checked');
// Draw the grid
this.drawFrameGrid_(frameOffsetX, frameOffsetY, frameSizeX, frameSizeY);
};
ns.ImportImageController.prototype.sanitizeInputValue_ = function(input, minValue) {
var value = parseInt(input.val(), 10);
if (value <= minValue || isNaN(value)) {
input.val(minValue);
value = minValue;
}
return value;
};
ns.ImportImageController.prototype.getImportType_ = function () {
return this.importType.filter(':checked').val();
};
ns.ImportImageController.prototype.onImageLoaded_ = function (image) {
this.importedImage_ = image;
var w = this.importedImage_.width;
var h = this.importedImage_.height;
// FIXME : We remove the onload callback here because JsGif will insert
// the image again and we want to avoid retriggering the image onload
this.importedImage_.onload = function () {};
var fileName = this.extractFileNameFromPath_(this.file_.name);
this.fileNameContainer.text(fileName);
this.fileNameContainer.attr('title', fileName);
this.resizeWidth.val(w);
this.resizeHeight.val(h);
this.frameSizeX.val(w);
this.frameSizeY.val(h);
this.frameOffsetX.val(0);
this.frameOffsetY.val(0);
this.importPreview.width('auto');
this.importPreview.height('auto');
this.importPreview.html('');
this.importPreview.append(this.createImagePreview_());
};
ns.ImportImageController.prototype.createImagePreview_ = function () {
var image = document.createElement('IMG');
image.src = this.importedImage_.src;
return image;
};
ns.ImportImageController.prototype.extractFileNameFromPath_ = function (path) {
var parts = [];
if (path.indexOf('/') !== -1) {
parts = path.split('/');
} else if (path.indexOf('\\') !== -1) {
parts = path.split('\\');
} else {
parts = [path];
}
return parts[parts.length - 1];
};
ns.ImportImageController.prototype.importImageToPiskel_ = function () {
if (this.importedImage_) {
if (window.confirm('You are about to create a new Piskel, unsaved changes will be lost.')) {
pskl.app.importService.newPiskelFromImage(
this.importedImage_,
{
importType: this.getImportType_(),
frameSizeX: this.getImportType_() === 'single' ?
this.resizeWidth.val() : this.sanitizeInputValue_(this.frameSizeX, 1),
frameSizeY: this.getImportType_() === 'single' ?
this.resizeHeight.val() : this.sanitizeInputValue_(this.frameSizeY, 1),
frameOffsetX: this.sanitizeInputValue_(this.frameOffsetX, 0),
frameOffsetY: this.sanitizeInputValue_(this.frameOffsetY, 0),
smoothing: !!this.smoothResize.prop('checked')
},
this.closeDialog.bind(this)
);
}
}
};
ns.ImportImageController.prototype.drawFrameGrid_ = function (frameX, frameY, frameW, frameH) {
if (!this.importedImage_) {
return;
}
// Grab the sizes of the source and preview images
var width = this.importedImage_.width;
var height = this.importedImage_.height;
var previewWidth = this.importPreview.width();
var previewHeight = this.importPreview.height();
var canvasWrapper = this.importPreview.children('canvas');
var canvas = canvasWrapper.get(0);
if (!canvasWrapper.length) {
// Create a new canvas for the grid
canvas = pskl.utils.CanvasUtils.createCanvas(
previewWidth + 1,
previewHeight + 1);
this.importPreview.append(canvas);
canvasWrapper = $(canvas);
}
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
// Calculate the number of whole frames
var countX = Math.floor((width - frameX) / frameW);
var countY = Math.floor((height - frameY) / frameH);
if (countX > 0 && countY > 0) {
var scaleX = previewWidth / width;
var scaleY = previewHeight / height;
var maxWidth = countX * frameW + frameX;
var maxHeight = countY * frameH + frameY;
// Draw the vertical lines
for (var x = frameX + 0.5; x < maxWidth + 1 && x < width + 1; x += frameW) {
context.moveTo(x * scaleX, frameY * scaleY);
context.lineTo(x * scaleX, maxHeight * scaleY);
}
// Draw the horizontal lines
for (var y = frameY + 0.5; y < maxHeight + 1 && y < height + 1; y += frameH) {
context.moveTo(frameX * scaleX, y * scaleY);
context.lineTo(maxWidth * scaleX, y * scaleY);
}
// Set the line style to dashed
context.lineWidth = 1;
context.setLineDash([2, 1]);
context.strokeStyle = '#000000';
context.stroke();
// Show the canvas
canvasWrapper.show();
this.importPreview.addClass('no-border');
} else {
this.hideFrameGrid_();
}
};
ns.ImportImageController.prototype.hideFrameGrid_ = function() {
this.importPreview.children('canvas').hide();
this.importPreview.removeClass('no-border');
};
})();

View File

@@ -1,198 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs.importwizard');
var stepDefinitions = {
'IMAGE_IMPORT' : {
controller : ns.steps.ImageImport,
template : 'import-image-import'
},
'ADJUST_SIZE' : {
controller : ns.steps.AdjustSize,
template : 'import-adjust-size'
},
'INSERT_LOCATION' : {
controller : ns.steps.InsertLocation,
template : 'import-insert-location'
},
'SELECT_MODE' : {
controller : ns.steps.SelectMode,
template : 'import-select-mode'
}
};
ns.ImportWizard = function (piskelController, args) {
this.piskelController = piskelController;
// Merge data object used by steps to communicate and share their
// results.
this.mergeData = {
rawFiles : [],
mergePiskel: null,
origin: null,
resize: null,
insertIndex: null,
insertMode: null
};
};
pskl.utils.inherit(ns.ImportWizard, pskl.controller.dialogs.AbstractDialogController);
ns.ImportWizard.prototype.init = function (initArgs) {
this.superclass.init.call(this);
// Prepare mergeData object and wizard steps.
this.mergeData.rawFiles = initArgs.rawFiles;
this.steps = this.createSteps_();
// Start wizard widget.
var wizardContainer = document.querySelector('.import-wizard-container');
this.wizard = new pskl.widgets.Wizard(this.steps, wizardContainer);
this.wizard.init();
if (this.hasSingleImage_()) {
this.wizard.goTo('IMAGE_IMPORT');
} else if (this.hasSinglePiskelFile_()) {
// If a piskel file was provided we can directly go to
pskl.utils.PiskelFileUtils.loadFromFile(this.mergeData.rawFiles[0],
// onSuccess
function (piskel) {
this.mergeData.mergePiskel = piskel;
this.wizard.goTo('SELECT_MODE');
}.bind(this),
// onError
function (reason) {
this.closeDialog();
$.publish(Events.PISKEL_FILE_IMPORT_FAILED, [reason]);
}.bind(this)
);
} else {
console.error('Unsupported import. Only single piskel or single image are supported at the moment.');
this.closeDialog();
}
};
ns.ImportWizard.prototype.back = function () {
this.wizard.back();
this.wizard.getCurrentStep().instance.onShow();
};
ns.ImportWizard.prototype.next = function () {
var step = this.wizard.getCurrentStep();
if (step.name === 'IMAGE_IMPORT') {
this.wizard.goTo('SELECT_MODE');
} else if (step.name === 'SELECT_MODE') {
if (this.mergeData.importMode === ns.steps.SelectMode.MODES.REPLACE) {
this.finalizeImport_();
} else if (this.hasSameSize_()) {
this.wizard.goTo('INSERT_LOCATION');
} else {
this.wizard.goTo('ADJUST_SIZE');
}
} else if (step.name === 'ADJUST_SIZE') {
this.wizard.goTo('INSERT_LOCATION');
} else if (step.name === 'INSERT_LOCATION') {
this.finalizeImport_();
}
};
ns.ImportWizard.prototype.destroy = function (file) {
Object.keys(this.steps).forEach(function (stepName) {
var step = this.steps[stepName];
step.instance.destroy();
step.instance = null;
step.el = null;
}.bind(this));
this.superclass.destroy.call(this);
};
ns.ImportWizard.prototype.createSteps_ = function () {
// The IMAGE_IMPORT step is used only if there is a single image file
// being imported.
var hasSingleImage = this.hasSingleImage_();
var steps = {};
Object.keys(stepDefinitions).forEach(function (stepName) {
if (stepName === 'IMAGE_IMPORT' && !hasSingleImage) {
return;
}
var definition = stepDefinitions[stepName];
var el = pskl.utils.Template.getAsHTML(definition.template);
var instance = new definition.controller(this.piskelController, this, el);
instance.init();
steps[stepName] = {
name: stepName,
el: el,
instance: instance
};
}.bind(this));
if (hasSingleImage) {
steps.IMAGE_IMPORT.el.classList.add('import-first-step');
} else {
steps.SELECT_MODE.el.classList.add('import-first-step');
}
return steps;
};
ns.ImportWizard.prototype.finalizeImport_ = function () {
var piskel = this.mergeData.mergePiskel;
var mode = this.mergeData.importMode;
if (mode === ns.steps.SelectMode.MODES.REPLACE) {
// Replace the current piskel and close the dialog.
var message = 'This will replace your current animation,' +
' are you sure you want to continue?';
if (window.confirm(message)) {
this.piskelController.setPiskel(piskel);
this.closeDialog();
}
} else if (mode === ns.steps.SelectMode.MODES.MERGE) {
var merge = pskl.utils.MergeUtils.merge(this.piskelController.getPiskel(), piskel, {
insertIndex: this.mergeData.insertIndex,
insertMode: this.mergeData.insertMode,
origin: this.mergeData.origin,
resize: this.mergeData.resize
});
this.piskelController.setPiskel(merge);
// Set the first imported layer as selected.
var importedLayers = piskel.getLayers().length;
var currentLayers = this.piskelController.getLayers().length;
this.piskelController.setCurrentLayerIndex(currentLayers - importedLayers);
this.closeDialog();
}
};
ns.ImportWizard.prototype.hasSameSize_ = function () {
var piskel = this.mergeData.mergePiskel;
if (!piskel) {
return false;
}
return piskel.width === this.piskelController.getWidth() &&
piskel.height === this.piskelController.getHeight();
};
ns.ImportWizard.prototype.hasSingleImage_ = function () {
if (this.mergeData.rawFiles.length !== 1) {
return false;
}
var file = this.mergeData.rawFiles[0];
return file.type.indexOf('image') === 0;
};
ns.ImportWizard.prototype.hasSinglePiskelFile_ = function () {
if (this.mergeData.rawFiles.length !== 1) {
return false;
}
var file = this.mergeData.rawFiles[0];
return (/\.piskel$/).test(file.name);
};
})();

View File

@@ -1,65 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs.importwizard.steps');
ns.AbstractImportStep = function (piskelController, importController, container) {
this.piskelController = piskelController;
this.container = container;
this.importController = importController;
this.mergeData = this.importController.mergeData;
};
ns.AbstractImportStep.prototype.init = function () {
this.nextButton = this.container.querySelector('.import-next-button');
this.backButton = this.container.querySelector('.import-back-button');
this.addEventListener(this.nextButton, 'click', this.onNextClick);
this.addEventListener(this.backButton, 'click', this.onBackClick);
};
ns.AbstractImportStep.prototype.addEventListener = function (el, type, cb) {
pskl.utils.Event.addEventListener(el, type, cb, this);
};
ns.AbstractImportStep.prototype.destroy = function () {
if (this.framePickerWidget) {
this.framePickerWidget.destroy();
}
pskl.utils.Event.removeAllEventListeners(this);
};
ns.AbstractImportStep.prototype.onNextClick = function () {
this.importController.next(this);
};
ns.AbstractImportStep.prototype.onBackClick = function () {
this.importController.back(this);
};
ns.AbstractImportStep.prototype.onShow = function () {
var mergePiskel = this.mergeData.mergePiskel;
if (!mergePiskel) {
return;
}
if (!this.framePickerWidget) {
var framePickerContainer = this.container.querySelector('.import-preview');
this.framePickerWidget = new pskl.widgets.FramePicker(mergePiskel, framePickerContainer);
this.framePickerWidget.init();
} else if (this.framePickerWidget.piskel != mergePiskel) {
// If the piskel displayed by the frame picker is different from the previous one,
// refresh the widget.
this.framePickerWidget.piskel = mergePiskel;
this.framePickerWidget.setFrameIndex(1);
}
var metaHtml = pskl.utils.Template.getAndReplace('import-meta-content', {
name : mergePiskel.getDescriptor().name,
dimensions : pskl.utils.StringUtils.formatSize(mergePiskel.getWidth(), mergePiskel.getHeight()),
frames : mergePiskel.getFrameCount(),
layers : mergePiskel.getLayers().length
});
this.container.querySelector('.import-meta').innerHTML = metaHtml;
};
})();

View File

@@ -1,110 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs.importwizard.steps');
ns.AdjustSize = function (piskelController, importController, container) {
this.superclass.constructor.apply(this, arguments);
};
ns.AdjustSize.OPTIONS = {
KEEP: 'keep',
EXPAND: 'expand'
};
pskl.utils.inherit(ns.AdjustSize, ns.AbstractImportStep);
ns.AdjustSize.prototype.init = function () {
this.superclass.init.call(this);
// Create anchor widget
var anchorContainer = this.container.querySelector('.import-resize-anchor-container');
this.anchorWidget = new pskl.widgets.AnchorWidget(anchorContainer, this.onAnchorChange_.bind(this));
this.anchorWidget.setOrigin('TOPLEFT');
this.resizeInfoContainer = this.container.querySelector('.import-resize-info');
this.addEventListener(this.resizeInfoContainer, 'change', this.onResizeOptionChange_);
// By default, set the mode to expand to avoid losing any image content.
this.mergeData.resize = ns.AdjustSize.OPTIONS.EXPAND;
};
ns.AdjustSize.prototype.destroy = function () {
this.anchorWidget.destroy();
this.superclass.destroy.call(this);
};
ns.AdjustSize.prototype.onShow = function () {
this.refresh_();
this.superclass.onShow.call(this);
};
ns.AdjustSize.prototype.refresh_ = function () {
var isBigger = this.isImportedPiskelBigger_();
var keep = this.mergeData.resize === ns.AdjustSize.OPTIONS.KEEP;
// Refresh resize partial
var size = this.formatPiskelSize_(this.piskelController.getPiskel());
var newSize = this.formatPiskelSize_(this.mergeData.mergePiskel);
var markup;
if (isBigger) {
markup = pskl.utils.Template.getAndReplace('import-resize-bigger-partial', {
size : size,
newSize : newSize,
keepChecked : keep ? 'checked="checked"' : '',
expandChecked : keep ? '' : 'checked="checked"'
});
} else {
markup = pskl.utils.Template.getAndReplace('import-resize-smaller-partial', {
size : size,
newSize : newSize
});
}
this.resizeInfoContainer.innerHTML = markup;
// Update anchor widget
if (this.mergeData.origin) {
this.anchorWidget.setOrigin(this.mergeData.origin);
}
// Update anchor widget info
var anchorInfo = this.container.querySelector('.import-resize-anchor-info');
if (isBigger && keep) {
anchorInfo.innerHTML = [
'<span class="import-resize-warning">',
' Imported content will be cropped!',
'</span>',
' ',
'Select crop origin'
].join('');
} else if (isBigger) {
anchorInfo.innerHTML = 'Select the anchor for resizing the canvas';
} else {
anchorInfo.innerHTML = 'Select where the import should be positioned';
}
};
ns.AdjustSize.prototype.onAnchorChange_ = function (origin) {
this.mergeData.origin = origin;
};
ns.AdjustSize.prototype.onResizeOptionChange_ = function () {
var value = this.resizeInfoContainer.querySelector(':checked').value;
if (this.mergeData.resize != value) {
this.mergeData.resize = value;
this.refresh_();
}
};
ns.AdjustSize.prototype.isImportedPiskelBigger_ = function () {
var piskel = this.mergeData.mergePiskel;
if (!piskel) {
return false;
}
return piskel.width > this.piskelController.getWidth() ||
piskel.height > this.piskelController.getHeight();
};
ns.AdjustSize.prototype.formatPiskelSize_ = function (piskel) {
return pskl.utils.StringUtils.formatSize(piskel.width, piskel.height);
};
})();

View File

@@ -1,279 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs.importwizard.steps');
ns.ImageImport = function (piskelController, importController, container) {
this.superclass.constructor.apply(this, arguments);
this.importedImage_ = null;
this.file_ = null;
};
pskl.utils.inherit(ns.ImageImport, ns.AbstractImportStep);
ns.ImageImport.prototype.init = function (file) {
this.superclass.init.call(this);
// This step is only used if rawFiles contains a single image.
this.file_ = this.mergeData.rawFiles[0];
this.importPreview = this.container.querySelector('.import-section-preview');
this.fileNameContainer = this.container.querySelector('.import-image-file-name');
this.singleImportType = this.container.querySelector('[name=import-type][value=single]');
this.sheetImportType = this.container.querySelector('[name=import-type][value=sheet]');
this.resizeWidth = this.container.querySelector('[name=resize-width]');
this.resizeHeight = this.container.querySelector('[name=resize-height]');
this.smoothResize = this.container.querySelector('[name=smooth-resize-checkbox]');
this.frameSizeX = this.container.querySelector('[name=frame-size-x]');
this.frameSizeY = this.container.querySelector('[name=frame-size-y]');
this.frameOffsetX = this.container.querySelector('[name=frame-offset-x]');
this.frameOffsetY = this.container.querySelector('[name=frame-offset-y]');
this.addEventListener(this.singleImportType, 'change', this.onImportTypeChange_);
this.addEventListener(this.sheetImportType, 'change', this.onImportTypeChange_);
this.addEventListener(this.resizeWidth, 'keyup', this.onResizeInputKeyUp_);
this.addEventListener(this.resizeHeight, 'keyup', this.onResizeInputKeyUp_);
this.addEventListener(this.frameSizeX, 'keyup', this.onFrameInputKeyUp_);
this.addEventListener(this.frameSizeY, 'keyup', this.onFrameInputKeyUp_);
this.addEventListener(this.frameOffsetX, 'keyup', this.onFrameInputKeyUp_);
this.addEventListener(this.frameOffsetY, 'keyup', this.onFrameInputKeyUp_);
pskl.utils.FileUtils.readImageFile(this.file_, this.onImageLoaded_.bind(this));
};
ns.ImageImport.prototype.onNextClick = function () {
this.container.classList.add('import-image-loading');
this.createPiskelFromImage().then(function (piskel) {
this.mergeData.mergePiskel = piskel;
this.superclass.onNextClick.call(this);
}.bind(this)).catch(function (e) {
console.error(e);
});
};
ns.ImageImport.prototype.onShow = function () {
this.container.classList.remove('import-image-loading');
};
ns.ImageImport.prototype.createPiskelFromImage = function () {
var name = this.extractFileNameFromPath_(this.file_.name);
// Remove extension from filename.
name = name.replace(/\.[a-zA-Z]+$/, '');
var deferred = Q.defer();
pskl.app.importService.newPiskelFromImage(
this.importedImage_,
{
importType: this.getImportType_(),
frameSizeX: this.getImportType_() === 'single' ?
this.resizeWidth.value : this.sanitizeInputValue_(this.frameSizeX, 1),
frameSizeY: this.getImportType_() === 'single' ?
this.resizeHeight.value : this.sanitizeInputValue_(this.frameSizeY, 1),
frameOffsetX: this.sanitizeInputValue_(this.frameOffsetX, 0),
frameOffsetY: this.sanitizeInputValue_(this.frameOffsetY, 0),
smoothing: !!this.smoothResize.checked,
name: name
},
deferred.resolve
);
return deferred.promise;
};
ns.ImageImport.prototype.onImportTypeChange_ = function (evt) {
if (this.getImportType_() === 'single') {
// Using single image, so remove the frame grid
this.hideFrameGrid_();
} else {
// Using spritesheet import, so draw the frame grid in the preview
var x = this.sanitizeInputValue_(this.frameOffsetX, 0);
var y = this.sanitizeInputValue_(this.frameOffsetY, 0);
var w = this.sanitizeInputValue_(this.frameSizeX, 1);
var h = this.sanitizeInputValue_(this.frameSizeY, 1);
this.drawFrameGrid_(x, y, w, h);
}
};
ns.ImageImport.prototype.onResizeInputKeyUp_ = function (evt) {
var from = evt.target.getAttribute('name');
if (this.importedImage_) {
this.synchronizeResizeFields_(evt.target.value, from);
}
};
ns.ImageImport.prototype.onFrameInputKeyUp_ = function (evt) {
if (this.importedImage_) {
this.synchronizeFrameFields_(evt.target.value);
}
};
ns.ImageImport.prototype.synchronizeResizeFields_ = function (value, from) {
value = parseInt(value, 10);
if (isNaN(value)) {
value = 0;
}
var height = this.importedImage_.height;
var width = this.importedImage_.width;
// Select single image import type since the user changed a value here
this.singleImportType.checked = true;
if (from === 'resize-width') {
this.resizeHeight.value = Math.round(value * height / width);
} else {
this.resizeWidth.value = Math.round(value * width / height);
}
};
ns.ImageImport.prototype.synchronizeFrameFields_ = function (value) {
value = parseInt(value, 10);
if (isNaN(value)) {
value = 0;
}
// Parse the frame input values
var frameSizeX = this.sanitizeInputValue_(this.frameSizeX, 1);
var frameSizeY = this.sanitizeInputValue_(this.frameSizeY, 1);
var frameOffsetX = this.sanitizeInputValue_(this.frameOffsetX, 0);
var frameOffsetY = this.sanitizeInputValue_(this.frameOffsetY, 0);
// Select spritesheet import type since the user changed a value here
this.sheetImportType.checked = true;
// Draw the grid
this.drawFrameGrid_(frameOffsetX, frameOffsetY, frameSizeX, frameSizeY);
};
ns.ImageImport.prototype.sanitizeInputValue_ = function(input, minValue) {
var value = parseInt(input.value, 10);
if (value <= minValue || isNaN(value)) {
input.value = minValue;
value = minValue;
}
return value;
};
ns.ImageImport.prototype.getImportType_ = function () {
if (this.singleImportType.checked) {
return this.singleImportType.value;
} else if (this.sheetImportType.checked) {
return this.sheetImportType.value;
} else {
throw 'Could not find the currently selected import type';
}
};
ns.ImageImport.prototype.onImageLoaded_ = function (image) {
this.importedImage_ = image;
var w = this.importedImage_.width;
var h = this.importedImage_.height;
// FIXME : We remove the onload callback here because JsGif will insert
// the image again and we want to avoid retriggering the image onload
this.importedImage_.onload = function () {};
var fileName = this.extractFileNameFromPath_(this.file_.name);
this.fileNameContainer.textContent = fileName;
this.fileNameContainer.setAttribute('title', fileName);
this.resizeWidth.value = w;
this.resizeHeight.value = h;
this.frameSizeX.value = w;
this.frameSizeY.value = h;
this.frameOffsetX.value = 0;
this.frameOffsetY.value = 0;
this.importPreview.innerHTML = '';
this.importPreview.appendChild(this.createImagePreview_());
};
ns.ImageImport.prototype.createImagePreview_ = function () {
var image = document.createElement('IMG');
image.src = this.importedImage_.src;
return image;
};
ns.ImageImport.prototype.extractFileNameFromPath_ = function (path) {
var parts = [];
if (path.indexOf('/') !== -1) {
parts = path.split('/');
} else if (path.indexOf('\\') !== -1) {
parts = path.split('\\');
} else {
parts = [path];
}
return parts[parts.length - 1];
};
ns.ImageImport.prototype.drawFrameGrid_ = function (frameX, frameY, frameW, frameH) {
if (!this.importedImage_) {
return;
}
// Grab the sizes of the source and preview images
var width = this.importedImage_.width;
var height = this.importedImage_.height;
var image = this.importPreview.querySelector('img');
var previewWidth = image.offsetWidth;
var previewHeight = image.offsetHeight;
var canvas = this.importPreview.querySelector('canvas');
if (!canvas) {
// Create a new canvas for the grid
canvas = pskl.utils.CanvasUtils.createCanvas(
previewWidth + 1,
previewHeight + 1);
this.importPreview.appendChild(canvas);
}
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
// Calculate the number of whole frames
var countX = Math.floor((width - frameX) / frameW);
var countY = Math.floor((height - frameY) / frameH);
if (countX > 0 && countY > 0) {
var scaleX = previewWidth / width;
var scaleY = previewHeight / height;
var maxWidth = countX * frameW + frameX;
var maxHeight = countY * frameH + frameY;
// Draw the vertical lines
for (var x = frameX + 0.5; x < maxWidth + 1 && x < width + 1; x += frameW) {
context.moveTo(x * scaleX, frameY * scaleY);
context.lineTo(x * scaleX, maxHeight * scaleY);
}
// Draw the horizontal lines
for (var y = frameY + 0.5; y < maxHeight + 1 && y < height + 1; y += frameH) {
context.moveTo(frameX * scaleX, y * scaleY);
context.lineTo(maxWidth * scaleX, y * scaleY);
}
// Set the line style to dashed
context.lineWidth = 1;
// context.setLineDash([2, 1]);
context.strokeStyle = 'gold';
context.stroke();
// Show the canvas
canvas.style.display = 'block';
} else {
this.hideFrameGrid_();
}
};
ns.ImageImport.prototype.hideFrameGrid_ = function() {
var canvas = this.importPreview.querySelector('canvas');
if (canvas) {
canvas.style.display = 'none';
}
};
})();

View File

@@ -1,59 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs.importwizard.steps');
ns.InsertLocation = function () {
this.superclass.constructor.apply(this, arguments);
};
ns.InsertLocation.MODES = {
ADD : 'add',
INSERT : 'insert'
};
pskl.utils.inherit(ns.InsertLocation, ns.AbstractImportStep);
ns.InsertLocation.prototype.init = function () {
this.superclass.init.call(this);
this.framePreview = this.container.querySelector('.insert-frame-preview');
this.currentPiskelFramePickerWidget = new pskl.widgets.FramePicker(
this.piskelController.getPiskel(), this.framePreview);
this.insertModeContainer = this.container.querySelector('.insert-mode-container');
this.addEventListener(this.insertModeContainer, 'change', this.onInsertModeChange_);
this.mergeData.insertMode = ns.InsertLocation.MODES.ADD;
};
ns.InsertLocation.prototype.onInsertModeChange_ = function () {
var value = this.insertModeContainer.querySelector(':checked').value;
this.mergeData.insertMode = value;
if (this.mergeData.insertMode === ns.InsertLocation.MODES.ADD) {
this.currentPiskelFramePickerWidget.setFirstFrameIndex(0);
} else {
this.currentPiskelFramePickerWidget.setFirstFrameIndex(1);
}
};
ns.InsertLocation.prototype.onShow = function () {
// Initialize the frame picker on show, to be able to calculate correctly the
// container's offsetWidth and offsetHeight.
this.currentPiskelFramePickerWidget.init();
var currentFrameIndex = this.piskelController.getCurrentFrameIndex();
this.currentPiskelFramePickerWidget.setFrameIndex(currentFrameIndex + 1);
this.currentPiskelFramePickerWidget.setFirstFrameIndex(0);
this.superclass.onShow.call(this);
};
ns.InsertLocation.prototype.onNextClick = function () {
var insertIndex = this.currentPiskelFramePickerWidget.getFrameIndex();
this.mergeData.insertIndex = insertIndex;
this.superclass.onNextClick.call(this);
};
ns.InsertLocation.prototype.destroy = function () {
this.currentPiskelFramePickerWidget.destroy();
this.superclass.destroy.call(this);
};
})();

View File

@@ -1,42 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.dialogs.importwizard.steps');
ns.SelectMode = function (piskelController, importController, container) {
this.superclass.constructor.apply(this, arguments);
};
ns.SelectMode.MODES = {
REPLACE : 'replace',
MERGE : 'merge'
};
pskl.utils.inherit(ns.SelectMode, ns.AbstractImportStep);
ns.SelectMode.prototype.init = function () {
this.superclass.init.call(this);
var replaceButton = this.container.querySelector('.import-mode-replace-button');
var mergeButton = this.container.querySelector('.import-mode-merge-button');
this.addEventListener(replaceButton, 'click', this.onReplaceButtonClick_);
this.addEventListener(mergeButton, 'click', this.onMergeButtonClick_);
};
ns.SelectMode.prototype.onShow = function () {
this.superclass.onShow.call(this);
};
ns.SelectMode.prototype.destroy = function () {
this.superclass.destroy.call(this);
};
ns.SelectMode.prototype.onReplaceButtonClick_ = function () {
this.mergeData.importMode = ns.SelectMode.MODES.REPLACE;
this.onNextClick();
};
ns.SelectMode.prototype.onMergeButtonClick_ = function () {
this.mergeData.importMode = ns.SelectMode.MODES.MERGE;
this.onNextClick();
};
})();

View File

@@ -12,15 +12,11 @@
/** /**
* Set the current piskel. Will reset the selected frame and layer unless specified * Set the current piskel. Will reset the selected frame and layer unless specified
* @param {Object} piskel * @param {Object} piskel
* @param {Object} options: * @param {Boolean} preserveState if true, keep the selected frame and layer
* preserveState {Boolean} if true, keep the selected frame and layer
* noSnapshot {Boolean} if true, do not save a snapshot in the piskel
* history for this call to setPiskel
*/ */
ns.PiskelController.prototype.setPiskel = function (piskel, options) { ns.PiskelController.prototype.setPiskel = function (piskel, preserveState) {
this.piskel = piskel; this.piskel = piskel;
options = options || {}; if (!preserveState) {
if (!options.preserveState) {
this.currentLayerIndex = 0; this.currentLayerIndex = 0;
this.currentFrameIndex = 0; this.currentFrameIndex = 0;
} }
@@ -159,7 +155,8 @@
}; };
ns.PiskelController.prototype.getFrameCount = function () { ns.PiskelController.prototype.getFrameCount = function () {
return this.piskel.getFrameCount(); var layer = this.piskel.getLayerAt(0);
return layer.size();
}; };
ns.PiskelController.prototype.setCurrentFrameIndex = function (index) { ns.PiskelController.prototype.setCurrentFrameIndex = function (index) {
@@ -234,14 +231,6 @@
return name; return name;
}; };
ns.PiskelController.prototype.duplicateCurrentLayer = function () {
var layer = this.getCurrentLayer();
var clone = pskl.utils.LayerUtils.clone(layer);
var currentLayerIndex = this.getCurrentLayerIndex();
this.piskel.addLayerAt(clone, currentLayerIndex + 1);
this.setCurrentLayerIndex(currentLayerIndex + 1);
};
ns.PiskelController.prototype.createLayer = function (name) { ns.PiskelController.prototype.createLayer = function (name) {
if (!name) { if (!name) {
name = this.generateLayerName_(); name = this.generateLayerName_();
@@ -251,9 +240,9 @@
for (var i = 0 ; i < this.getFrameCount() ; i++) { for (var i = 0 ; i < this.getFrameCount() ; i++) {
layer.addFrame(this.createEmptyFrame_()); layer.addFrame(this.createEmptyFrame_());
} }
var currentLayerIndex = this.getCurrentLayerIndex(); this.piskel.addLayer(layer);
this.piskel.addLayerAt(layer, currentLayerIndex + 1); this.setCurrentLayerIndex(this.piskel.getLayers().length - 1);
this.setCurrentLayerIndex(currentLayerIndex + 1);
} else { } else {
throw 'Layer name should be unique'; throw 'Layer name should be unique';
} }
@@ -263,15 +252,15 @@
return this.piskel.getLayersByName(name).length > 0; return this.piskel.getLayersByName(name).length > 0;
}; };
ns.PiskelController.prototype.moveLayerUp = function (toTop) { ns.PiskelController.prototype.moveLayerUp = function () {
var layer = this.getCurrentLayer(); var layer = this.getCurrentLayer();
this.piskel.moveLayerUp(layer, toTop); this.piskel.moveLayerUp(layer);
this.selectLayer(layer); this.selectLayer(layer);
}; };
ns.PiskelController.prototype.moveLayerDown = function (toBottom) { ns.PiskelController.prototype.moveLayerDown = function () {
var layer = this.getCurrentLayer(); var layer = this.getCurrentLayer();
this.piskel.moveLayerDown(layer, toBottom); this.piskel.moveLayerDown(layer);
this.selectLayer(layer); this.selectLayer(layer);
}; };

View File

@@ -31,7 +31,6 @@
this.saveWrap_('duplicateFrameAt', true); this.saveWrap_('duplicateFrameAt', true);
this.saveWrap_('moveFrame', true); this.saveWrap_('moveFrame', true);
this.saveWrap_('createLayer', true); this.saveWrap_('createLayer', true);
this.saveWrap_('duplicateCurrentLayer', true);
this.saveWrap_('mergeDownLayerAt', true); this.saveWrap_('mergeDownLayerAt', true);
this.saveWrap_('moveLayerUp', true); this.saveWrap_('moveLayerUp', true);
this.saveWrap_('moveLayerDown', true); this.saveWrap_('moveLayerDown', true);
@@ -49,25 +48,14 @@
return this.piskelController; return this.piskelController;
}; };
/** ns.PublicPiskelController.prototype.setPiskel = function (piskel, preserveState) {
* Set the current piskel. Will reset the selected frame and layer unless specified this.piskelController.setPiskel(piskel, preserveState);
* @param {Object} piskel
* @param {Object} options:
* preserveState {Boolean} if true, keep the selected frame and layer
* noSnapshot {Boolean} if true, do not save a snapshot in the piskel
* history for this call to setPiskel
*/
ns.PublicPiskelController.prototype.setPiskel = function (piskel, options) {
this.piskelController.setPiskel(piskel, options);
$.publish(Events.FRAME_SIZE_CHANGED); $.publish(Events.FRAME_SIZE_CHANGED);
$.publish(Events.PISKEL_RESET); $.publish(Events.PISKEL_RESET);
$.publish(Events.PISKEL_SAVE_STATE, {
if (!options || !options.noSnapshot) { type : pskl.service.HistoryService.SNAPSHOT
$.publish(Events.PISKEL_SAVE_STATE, { });
type : pskl.service.HistoryService.SNAPSHOT
});
}
}; };
ns.PublicPiskelController.prototype.resetWrap_ = function (methodName) { ns.PublicPiskelController.prototype.resetWrap_ = function (methodName) {

View File

@@ -102,7 +102,7 @@
this.disablePreviewSizeWidget_('No other option available'); this.disablePreviewSizeWidget_('No other option available');
validSizes = ['original']; validSizes = ['original'];
} else if (seamlessModeEnabled) { } else if (seamlessModeEnabled) {
this.disablePreviewSizeWidget_('Disabled in tile mode'); this.disablePreviewSizeWidget_('Disabled in seamless mode');
validSizes = ['original']; validSizes = ['original'];
} else { } else {
this.enablePreviewSizeWidget_(); this.enablePreviewSizeWidget_();
@@ -309,8 +309,7 @@
var isSeamless = pskl.UserSettings.get(pskl.UserSettings.SEAMLESS_MODE); var isSeamless = pskl.UserSettings.get(pskl.UserSettings.SEAMLESS_MODE);
this.renderer.setRepeated(isSeamless); this.renderer.setRepeated(isSeamless);
var width; var height, width;
var height;
if (isSeamless) { if (isSeamless) {
height = PREVIEW_SIZE; height = PREVIEW_SIZE;

View File

@@ -0,0 +1,144 @@
(function () {
var ns = $.namespace('pskl.controller.settings');
ns.ApplicationSettingsController = function () {};
pskl.utils.inherit(ns.ApplicationSettingsController, pskl.controller.settings.AbstractSettingController);
ns.ApplicationSettingsController.prototype.init = function() {
this.backgroundContainer = document.querySelector('.background-picker-wrapper');
this.addEventListener(this.backgroundContainer, 'click', this.onBackgroundClick_);
// Highlight selected background :
var background = pskl.UserSettings.get(pskl.UserSettings.CANVAS_BACKGROUND);
var selectedBackground = this.backgroundContainer.querySelector('[data-background=' + background + ']');
if (selectedBackground) {
selectedBackground.classList.add('selected');
}
// Grid display and size
var gridWidth = pskl.UserSettings.get(pskl.UserSettings.GRID_WIDTH);
var gridSelect = document.querySelector('.grid-width-select');
var selectedOption = gridSelect.querySelector('option[value="' + gridWidth + '"]');
if (selectedOption) {
selectedOption.setAttribute('selected', 'selected');
}
this.addEventListener(gridSelect, 'change', this.onGridWidthChange_);
// Seamless mode
var seamlessMode = pskl.UserSettings.get(pskl.UserSettings.SEAMLESS_MODE);
var seamlessModeCheckbox = document.querySelector('.seamless-mode-checkbox');
if (seamlessMode) {
seamlessModeCheckbox.setAttribute('checked', seamlessMode);
}
this.addEventListener(seamlessModeCheckbox, 'change', this.onSeamlessModeChange_);
// Max FPS
var maxFpsInput = document.querySelector('.max-fps-input');
maxFpsInput.value = pskl.UserSettings.get(pskl.UserSettings.MAX_FPS);
this.addEventListener(maxFpsInput, 'change', this.onMaxFpsChange_);
// Color format
var colorFormat = pskl.UserSettings.get(pskl.UserSettings.COLOR_FORMAT);
var colorFormatSelect = document.querySelector('.color-format-select');
var selectedColorFormatOption = colorFormatSelect.querySelector('option[value="' + colorFormat + '"]');
if (selectedColorFormatOption) {
selectedColorFormatOption.setAttribute('selected', 'selected');
}
this.addEventListener(colorFormatSelect, 'change', this.onColorFormatChange_);
// Layer preview opacity
var layerOpacityInput = document.querySelector('.layer-opacity-input');
layerOpacityInput.value = pskl.UserSettings.get(pskl.UserSettings.LAYER_OPACITY);
this.addEventListener(layerOpacityInput, 'change', this.onLayerOpacityChange_);
this.addEventListener(layerOpacityInput, 'input', this.onLayerOpacityChange_);
this.updateLayerOpacityText_(layerOpacityInput.value);
// Seamless mask opacity
var seamlessOpacityInput = document.querySelector('.seamless-opacity-input');
seamlessOpacityInput.value = pskl.UserSettings.get(pskl.UserSettings.SEAMLESS_OPACITY);
this.addEventListener(seamlessOpacityInput, 'change', this.onSeamlessOpacityChange_);
this.addEventListener(seamlessOpacityInput, 'input', this.onSeamlessOpacityChange_);
this.updateSeamlessOpacityText_(seamlessOpacityInput.value);
// Form
this.applicationSettingsForm = document.querySelector('[name="application-settings-form"]');
this.addEventListener(this.applicationSettingsForm, 'submit', this.onFormSubmit_);
};
ns.ApplicationSettingsController.prototype.onGridWidthChange_ = function (evt) {
var width = parseInt(evt.target.value, 10);
pskl.UserSettings.set(pskl.UserSettings.GRID_WIDTH, width);
};
ns.ApplicationSettingsController.prototype.onColorFormatChange_ = function (evt) {
pskl.UserSettings.set(pskl.UserSettings.COLOR_FORMAT, evt.target.value);
};
ns.ApplicationSettingsController.prototype.onSeamlessModeChange_ = function (evt) {
pskl.UserSettings.set(pskl.UserSettings.SEAMLESS_MODE, evt.currentTarget.checked);
};
ns.ApplicationSettingsController.prototype.onBackgroundClick_ = function (evt) {
var target = evt.target;
var background = target.dataset.background;
if (background) {
pskl.UserSettings.set(pskl.UserSettings.CANVAS_BACKGROUND, background);
var selected = this.backgroundContainer.querySelector('.selected');
if (selected) {
selected.classList.remove('selected');
}
target.classList.add('selected');
}
};
ns.ApplicationSettingsController.prototype.onMaxFpsChange_ = function (evt) {
var target = evt.target;
var fps = parseInt(target.value, 10);
if (fps && !isNaN(fps)) {
pskl.UserSettings.set(pskl.UserSettings.MAX_FPS, fps);
} else {
target.value = pskl.UserSettings.get(pskl.UserSettings.MAX_FPS);
}
};
ns.ApplicationSettingsController.prototype.onLayerOpacityChange_ = function (evt) {
var target = evt.target;
var opacity = parseFloat(target.value);
if (!isNaN(opacity)) {
pskl.UserSettings.set(pskl.UserSettings.LAYER_OPACITY, opacity);
pskl.UserSettings.set(pskl.UserSettings.LAYER_PREVIEW, opacity !== 0);
this.updateLayerOpacityText_(opacity);
} else {
target.value = pskl.UserSettings.get(pskl.UserSettings.LAYER_OPACITY);
}
};
ns.ApplicationSettingsController.prototype.onSeamlessOpacityChange_ = function (evt) {
var target = evt.target;
var opacity = parseFloat(target.value);
if (!isNaN(opacity)) {
pskl.UserSettings.set(pskl.UserSettings.SEAMLESS_OPACITY, opacity);
this.updateSeamlessOpacityText_(opacity);
} else {
target.value = pskl.UserSettings.get(pskl.UserSettings.SEAMLESS_OPACITY);
}
};
ns.ApplicationSettingsController.prototype.updateLayerOpacityText_ = function (opacity) {
var layerOpacityText = document.querySelector('.layer-opacity-text');
layerOpacityText.innerHTML = opacity;
};
ns.ApplicationSettingsController.prototype.updateSeamlessOpacityText_ = function (opacity) {
var seamlessOpacityText = document.querySelector('.seamless-opacity-text');
seamlessOpacityText.innerHTML = opacity;
};
ns.ApplicationSettingsController.prototype.onFormSubmit_ = function (evt) {
evt.preventDefault();
$.publish(Events.CLOSE_SETTINGS_DRAWER);
};
})();

View File

@@ -71,7 +71,7 @@
}; };
ns.ImportController.prototype.onBrowseLocalClick_ = function (evt) { ns.ImportController.prototype.onBrowseLocalClick_ = function (evt) {
$.publish(Events.DIALOG_SHOW, { $.publish(Events.DIALOG_DISPLAY, {
dialogId : 'browse-local' dialogId : 'browse-local'
}); });
this.closeDrawer_(); this.closeDrawer_();
@@ -79,39 +79,40 @@
ns.ImportController.prototype.openPiskelFile_ = function (file) { ns.ImportController.prototype.openPiskelFile_ = function (file) {
if (this.isPiskel_(file)) { if (this.isPiskel_(file)) {
$.publish(Events.DIALOG_SHOW, { pskl.utils.PiskelFileUtils.loadFromFile(file,
dialogId : 'import', // onSuccess
initArgs : { function (piskel) {
rawFiles: [file] pskl.app.piskelController.setPiskel(piskel);
} },
}); // onError
function (reason) {
$.publish(Events.PISKEL_FILE_IMPORT_FAILED, [reason]);
});
this.closeDrawer_(); this.closeDrawer_();
} else {
this.closeDrawer_();
console.error('The selected file is not a piskel file');
} }
}; };
ns.ImportController.prototype.importPictureFromFile_ = function () { ns.ImportController.prototype.importPictureFromFile_ = function () {
var files = this.hiddenFileInput.files; var files = this.hiddenFileInput.files;
// TODO : Simply filter and remove stuff if (files.length == 1) {
var areImages = Array.prototype.every.call(files, function (file) { var file = files[0];
return file.type.indexOf('image') === 0; if (this.isImage_(file)) {
}); $.publish(Events.DIALOG_DISPLAY, {
if (areImages) { dialogId : 'import-image',
$.publish(Events.DIALOG_SHOW, { initArgs : file
dialogId : 'import', });
initArgs : { this.closeDrawer_();
rawFiles: files } else {
} this.closeDrawer_();
}); console.error('File is not an image : ' + file.type);
this.closeDrawer_(); }
} else {
this.closeDrawer_();
console.error('Some files are not images');
} }
}; };
ns.ImportController.prototype.isImage_ = function (file) {
return file.type.indexOf('image') === 0;
};
ns.ImportController.prototype.isPiskel_ = function (file) { ns.ImportController.prototype.isPiskel_ = function (file) {
return (/\.piskel$/).test(file.name); return (/\.piskel$/).test(file.name);
}; };

View File

@@ -1,35 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.settings');
var tabs = {
'misc' : {
template : 'templates/settings/preferences/misc.html',
controller : ns.preferences.MiscPreferencesController
},
'grid' : {
template : 'templates/settings/preferences/grid.html',
controller : ns.preferences.GridPreferencesController
},
'tile' : {
template : 'templates/settings/preferences/tile.html',
controller : ns.preferences.TilePreferencesController
}
};
ns.PreferencesController = function () {
this.tabsWidget = new pskl.widgets.Tabs(tabs, this, pskl.UserSettings.PREFERENCES_TAB);
};
pskl.utils.inherit(ns.PreferencesController, pskl.controller.settings.AbstractSettingController);
ns.PreferencesController.prototype.init = function() {
var container = document.querySelector('.settings-section-preferences');
this.tabsWidget.init(container);
};
ns.PreferencesController.prototype.destroy = function () {
this.tabsWidget.destroy();
this.superclass.destroy.call(this);
};
})();

View File

@@ -3,8 +3,8 @@
var settings = { var settings = {
'user' : { 'user' : {
template : 'templates/settings/preferences.html', template : 'templates/settings/application.html',
controller : ns.PreferencesController controller : ns.ApplicationSettingsController
}, },
'resize' : { 'resize' : {
template : 'templates/settings/resize.html', template : 'templates/settings/resize.html',

View File

@@ -22,7 +22,6 @@
ns.ExportController = function (piskelController) { ns.ExportController = function (piskelController) {
this.piskelController = piskelController; this.piskelController = piskelController;
this.tabsWidget = new pskl.widgets.Tabs(tabs, this, pskl.UserSettings.EXPORT_TAB);
this.onSizeInputChange_ = this.onSizeInputChange_.bind(this); this.onSizeInputChange_ = this.onSizeInputChange_.bind(this);
}; };
@@ -48,16 +47,47 @@
this.onSizeInputChange_(); this.onSizeInputChange_();
// Initialize tabs and panel // Initialize tabs and panel
var container = document.querySelector('.settings-section-export'); this.exportPanel = document.querySelector('.export-panel');
this.tabsWidget.init(container); this.exportTabs = document.querySelector('.export-tabs');
this.addEventListener(this.exportTabs, 'click', this.onTabsClicked_);
var tab = pskl.UserSettings.get(pskl.UserSettings.EXPORT_TAB);
this.selectTab(tab);
}; };
ns.ExportController.prototype.destroy = function () { ns.ExportController.prototype.destroy = function () {
this.sizeInputWidget.destroy(); this.sizeInputWidget.destroy();
this.tabsWidget.destroy(); this.currentController.destroy();
this.superclass.destroy.call(this); this.superclass.destroy.call(this);
}; };
ns.ExportController.prototype.selectTab = function (tabId) {
if (!tabs[tabId] || this.currentTab == tabId) {
return;
}
if (this.currentController) {
this.currentController.destroy();
}
this.exportPanel.innerHTML = pskl.utils.Template.get(tabs[tabId].template);
this.currentController = new tabs[tabId].controller(this.piskelController, this);
this.currentController.init();
this.currentTab = tabId;
pskl.UserSettings.set(pskl.UserSettings.EXPORT_TAB, tabId);
var selectedTab = this.exportTabs.querySelector('.selected');
if (selectedTab) {
selectedTab.classList.remove('selected');
}
this.exportTabs.querySelector('[data-tab-id="' + tabId + '"]').classList.add('selected');
};
ns.ExportController.prototype.onTabsClicked_ = function (e) {
var tabId = pskl.utils.Dom.getData(e.target, 'tabId');
this.selectTab(tabId);
};
ns.ExportController.prototype.onScaleChange_ = function () { ns.ExportController.prototype.onScaleChange_ = function () {
var value = parseFloat(this.scaleInput.value); var value = parseFloat(this.scaleInput.value);
if (!isNaN(value)) { if (!isNaN(value)) {

View File

@@ -85,8 +85,7 @@
var isTransparent = layers.some(function (l) {return l.isTransparent();}); var isTransparent = layers.some(function (l) {return l.isTransparent();});
var preserveColors = !isTransparent && currentColors.length < MAX_GIF_COLORS; var preserveColors = !isTransparent && currentColors.length < MAX_GIF_COLORS;
var transparentColor; var transparentColor, transparent;
var transparent;
// transparency only supported if preserveColors is true, see Issue #357 // transparency only supported if preserveColors is true, see Issue #357
if (preserveColors) { if (preserveColors) {
transparentColor = this.getTransparentColor(currentColors); transparentColor = this.getTransparentColor(currentColors);

View File

@@ -190,7 +190,7 @@
var json = { var json = {
'frames': frames, 'frames': frames,
'meta': { 'meta': {
'app': 'https://github.com/piskelapp/piskel/', 'app': 'https://github.com/juliandescottes/piskel/',
'version': '1.0', 'version': '1.0',
'image': name + '.png', 'image': name + '.png',
'format': 'RGBA8888', 'format': 'RGBA8888',

View File

@@ -1,90 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.settings.preferences');
var colorsMap = {
'transparent': Constants.TRANSPARENT_COLOR,
'white': '#FFF1E8',
'light-gray': '#C2C3C7',
'dark-gray': '#5F574F',
'black': '#000000',
'blue': '#29ADFF',
'dark-blue': '#1D2B53',
'green': '#00E436',
'dark-green': '#008751',
'peach': '#FFCCAA',
'pink': '#FF77A8',
'yellow': '#FFEC27',
'orange': '#FFA300',
'red': '#FF004D',
};
ns.GridPreferencesController = function (piskelController, preferencesController) {
this.piskelController = piskelController;
this.preferencesController = preferencesController;
this.sizePicker = new pskl.widgets.SizePicker(this.onSizePickerChanged_.bind(this));
};
pskl.utils.inherit(ns.GridPreferencesController, pskl.controller.settings.AbstractSettingController);
ns.GridPreferencesController.prototype.init = function () {
// Grid enabled
var isEnabled = pskl.UserSettings.get(pskl.UserSettings.GRID_ENABLED);
var enableGridCheckbox = document.querySelector('.enable-grid-checkbox');
if (isEnabled) {
enableGridCheckbox.setAttribute('checked', 'true');
}
this.addEventListener(enableGridCheckbox, 'change', this.onEnableGridChange_);
// Grid size
var gridWidth = pskl.UserSettings.get(pskl.UserSettings.GRID_WIDTH);
this.sizePicker.init(document.querySelector('.grid-size-container'));
this.sizePicker.setSize(gridWidth);
// Grid color
var colorListItemTemplate = pskl.utils.Template.get('color-list-item-template');
var gridColor = pskl.UserSettings.get(pskl.UserSettings.GRID_COLOR);
var gridColorSelect = document.querySelector('#grid-color');
var markup = '';
Object.keys(colorsMap).forEach(function (key, index) {
var background = colorsMap[key];
if (key === 'transparent') {
background = 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZ' +
'F8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)';
}
markup += pskl.utils.Template.replace(colorListItemTemplate, {
color: colorsMap[key],
title: key,
background: background,
':selected': gridColor === colorsMap[key]
});
});
this.gridColorList = document.querySelector('.grid-colors-list');
this.gridColorList.innerHTML = markup;
this.addEventListener(this.gridColorList, 'click', this.onGridColorClicked_.bind(this));
};
ns.GridPreferencesController.prototype.destroy = function () {
this.sizePicker.destroy();
this.superclass.destroy.call(this);
};
ns.GridPreferencesController.prototype.onSizePickerChanged_ = function (size) {
pskl.UserSettings.set(pskl.UserSettings.GRID_WIDTH, size);
};
ns.GridPreferencesController.prototype.onEnableGridChange_ = function (evt) {
pskl.UserSettings.set(pskl.UserSettings.GRID_ENABLED, evt.currentTarget.checked);
};
ns.GridPreferencesController.prototype.onGridColorClicked_ = function (evt) {
var color = evt.target.dataset.color;
if (color) {
pskl.UserSettings.set(pskl.UserSettings.GRID_COLOR, color);
this.gridColorList.querySelector('.selected').classList.remove('selected');
evt.target.classList.add('selected');
}
};
})();

View File

@@ -1,88 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.settings.preferences');
ns.MiscPreferencesController = function (piskelController, preferencesController) {
this.piskelController = piskelController;
this.preferencesController = preferencesController;
};
pskl.utils.inherit(ns.MiscPreferencesController, pskl.controller.settings.AbstractSettingController);
ns.MiscPreferencesController.prototype.init = function () {
this.backgroundContainer = document.querySelector('.background-picker-wrapper');
this.addEventListener(this.backgroundContainer, 'click', this.onBackgroundClick_);
// Highlight selected background :
var background = pskl.UserSettings.get(pskl.UserSettings.CANVAS_BACKGROUND);
var selectedBackground = this.backgroundContainer.querySelector('[data-background=' + background + ']');
if (selectedBackground) {
selectedBackground.classList.add('selected');
}
// Max FPS
var maxFpsInput = document.querySelector('.max-fps-input');
maxFpsInput.value = pskl.UserSettings.get(pskl.UserSettings.MAX_FPS);
this.addEventListener(maxFpsInput, 'change', this.onMaxFpsChange_);
// Color format
var colorFormat = pskl.UserSettings.get(pskl.UserSettings.COLOR_FORMAT);
var colorFormatSelect = document.querySelector('.color-format-select');
var selectedColorFormatOption = colorFormatSelect.querySelector('option[value="' + colorFormat + '"]');
if (selectedColorFormatOption) {
selectedColorFormatOption.setAttribute('selected', 'selected');
}
this.addEventListener(colorFormatSelect, 'change', this.onColorFormatChange_);
// Layer preview opacity
var layerOpacityInput = document.querySelector('.layer-opacity-input');
layerOpacityInput.value = pskl.UserSettings.get(pskl.UserSettings.LAYER_OPACITY);
this.addEventListener(layerOpacityInput, 'change', this.onLayerOpacityChange_);
this.addEventListener(layerOpacityInput, 'input', this.onLayerOpacityChange_);
this.updateLayerOpacityText_(layerOpacityInput.value);
};
ns.MiscPreferencesController.prototype.onBackgroundClick_ = function (evt) {
var target = evt.target;
var background = target.dataset.background;
if (background) {
pskl.UserSettings.set(pskl.UserSettings.CANVAS_BACKGROUND, background);
var selected = this.backgroundContainer.querySelector('.selected');
if (selected) {
selected.classList.remove('selected');
}
target.classList.add('selected');
}
};
ns.MiscPreferencesController.prototype.onColorFormatChange_ = function (evt) {
pskl.UserSettings.set(pskl.UserSettings.COLOR_FORMAT, evt.target.value);
};
ns.MiscPreferencesController.prototype.onMaxFpsChange_ = function (evt) {
var target = evt.target;
var fps = parseInt(target.value, 10);
if (fps && !isNaN(fps)) {
pskl.UserSettings.set(pskl.UserSettings.MAX_FPS, fps);
} else {
target.value = pskl.UserSettings.get(pskl.UserSettings.MAX_FPS);
}
};
ns.MiscPreferencesController.prototype.onLayerOpacityChange_ = function (evt) {
var target = evt.target;
var opacity = parseFloat(target.value);
if (!isNaN(opacity)) {
pskl.UserSettings.set(pskl.UserSettings.LAYER_OPACITY, opacity);
pskl.UserSettings.set(pskl.UserSettings.LAYER_PREVIEW, opacity !== 0);
this.updateLayerOpacityText_(opacity);
} else {
target.value = pskl.UserSettings.get(pskl.UserSettings.LAYER_OPACITY);
}
};
ns.MiscPreferencesController.prototype.updateLayerOpacityText_ = function (opacity) {
var layerOpacityText = document.querySelector('.layer-opacity-text');
layerOpacityText.innerHTML = (opacity * 1).toFixed(2);
};
})();

View File

@@ -1,47 +0,0 @@
(function () {
var ns = $.namespace('pskl.controller.settings.preferences');
ns.TilePreferencesController = function (piskelController, preferencesController) {
this.piskelController = piskelController;
this.preferencesController = preferencesController;
};
pskl.utils.inherit(ns.TilePreferencesController, pskl.controller.settings.AbstractSettingController);
ns.TilePreferencesController.prototype.init = function () {
// Tile mode
var tileMode = pskl.UserSettings.get(pskl.UserSettings.SEAMLESS_MODE);
var tileModeCheckbox = document.querySelector('.tile-mode-checkbox');
if (tileMode) {
tileModeCheckbox.setAttribute('checked', tileMode);
}
this.addEventListener(tileModeCheckbox, 'change', this.onTileModeChange_);
// Tile mask opacity
var tileMaskOpacityInput = document.querySelector('.tile-mask-opacity-input');
tileMaskOpacityInput.value = pskl.UserSettings.get(pskl.UserSettings.SEAMLESS_OPACITY);
this.addEventListener(tileMaskOpacityInput, 'change', this.onTileMaskOpacityChange_);
this.addEventListener(tileMaskOpacityInput, 'input', this.onTileMaskOpacityChange_);
this.updateTileMaskOpacityText_(tileMaskOpacityInput.value);
};
ns.TilePreferencesController.prototype.onTileModeChange_ = function (evt) {
pskl.UserSettings.set(pskl.UserSettings.SEAMLESS_MODE, evt.currentTarget.checked);
};
ns.TilePreferencesController.prototype.onTileMaskOpacityChange_ = function (evt) {
var target = evt.target;
var opacity = parseFloat(target.value);
if (!isNaN(opacity)) {
pskl.UserSettings.set(pskl.UserSettings.SEAMLESS_OPACITY, opacity);
this.updateTileMaskOpacityText_(opacity);
} else {
target.value = pskl.UserSettings.get(pskl.UserSettings.SEAMLESS_OPACITY);
}
};
ns.TilePreferencesController.prototype.updateTileMaskOpacityText_ = function (opacity) {
var seamlessOpacityText = document.querySelector('.tile-mask-opacity-text');
seamlessOpacityText.innerHTML = (opacity * 1).toFixed(2);
};
})();

View File

@@ -1,31 +1,12 @@
(function () { (function () {
var ns = $.namespace('pskl.widgets'); var ns = $.namespace('pskl.controller.settings.resize');
var OPTION_CLASSNAME = 'anchor-option'; var OPTION_CLASSNAME = 'resize-origin-option';
// Maybe move to HTML ...
var WIDGET_TEMPLATE =
'<div class="anchor-option" title="top left" data-origin="TOPLEFT"></div>' +
'<div class="anchor-option" title="top" data-origin="TOP"></div>' +
'<div class="anchor-option" title="top right" data-origin="TOPRIGHT"></div>' +
'<div class="anchor-option" title="middle left" data-origin="MIDDLELEFT"></div>' +
'<div class="anchor-option" title="middle" data-origin="MIDDLE"></div>' +
'<div class="anchor-option" title="middle right" data-origin="MIDDLERIGHT"></div>' +
'<div class="anchor-option" title="bottom left" data-origin="BOTTOMLEFT"></div>' +
'<div class="anchor-option" title="bottom" data-origin="BOTTOM"></div>' +
'<div class="anchor-option" title="bottom right" data-origin="BOTTOMRIGHT"></div>';
ns.AnchorWidget = function (container, onChangeCallback) {
this.onChangeCallback = onChangeCallback;
this.wrapper = document.createElement('div');
this.wrapper.classList.add('anchor-wrapper');
this.wrapper.innerHTML = WIDGET_TEMPLATE;
container.innerHTML = '';
container.appendChild(this.wrapper);
ns.AnchorWidget = function (container) {
this.container = container;
this.disabled = false; this.disabled = false;
pskl.utils.Event.addEventListener(this.wrapper, 'click', this.onResizeOriginClick_, this); pskl.utils.Event.addEventListener(this.container, 'click', this.onResizeOriginClick_, this);
}; };
ns.AnchorWidget.ORIGIN = { ns.AnchorWidget.ORIGIN = {
@@ -42,7 +23,7 @@
ns.AnchorWidget.prototype.destroy = function (evt) { ns.AnchorWidget.prototype.destroy = function (evt) {
pskl.utils.Event.removeAllEventListeners(this); pskl.utils.Event.removeAllEventListeners(this);
this.wrapper = null; this.container = null;
}; };
ns.AnchorWidget.prototype.onResizeOriginClick_ = function (evt) { ns.AnchorWidget.prototype.onResizeOriginClick_ = function (evt) {
@@ -54,20 +35,16 @@
ns.AnchorWidget.prototype.setOrigin = function (origin) { ns.AnchorWidget.prototype.setOrigin = function (origin) {
this.origin = origin; this.origin = origin;
var previous = this.wrapper.querySelector('.' + OPTION_CLASSNAME + '.selected'); var previous = document.querySelector('.' + OPTION_CLASSNAME + '.selected');
if (previous) { if (previous) {
previous.classList.remove('selected'); previous.classList.remove('selected');
} }
var selected = this.wrapper.querySelector('.' + OPTION_CLASSNAME + '[data-origin="' + origin + '"]'); var selected = document.querySelector('.' + OPTION_CLASSNAME + '[data-origin="' + origin + '"]');
if (selected) { if (selected) {
selected.classList.add('selected'); selected.classList.add('selected');
this.refreshNeighbors_(selected); this.refreshNeighbors_(selected);
} }
if (typeof this.onChangeCallback === 'function') {
this.onChangeCallback(origin);
}
}; };
ns.AnchorWidget.prototype.getOrigin = function () { ns.AnchorWidget.prototype.getOrigin = function () {
@@ -76,18 +53,18 @@
ns.AnchorWidget.prototype.disable = function () { ns.AnchorWidget.prototype.disable = function () {
this.disabled = true; this.disabled = true;
this.wrapper.classList.add('transition'); this.container.classList.add('transition');
this.wrapper.classList.add('disabled'); this.container.classList.add('disabled');
}; };
ns.AnchorWidget.prototype.enable = function () { ns.AnchorWidget.prototype.enable = function () {
this.disabled = false; this.disabled = false;
this.wrapper.classList.remove('disabled'); this.container.classList.remove('disabled');
window.setTimeout(this.wrapper.classList.remove.bind(this.wrapper.classList, 'transition'), 250); window.setTimeout(this.container.classList.remove.bind(this.container.classList, 'transition'), 250);
}; };
ns.AnchorWidget.prototype.refreshNeighbors_ = function (selected) { ns.AnchorWidget.prototype.refreshNeighbors_ = function (selected) {
var options = this.wrapper.querySelectorAll('.' + OPTION_CLASSNAME); var options = document.querySelectorAll('.' + OPTION_CLASSNAME);
for (var i = 0 ; i < options.length ; i++) { for (var i = 0 ; i < options.length ; i++) {
options[i].removeAttribute('data-neighbor'); options[i].removeAttribute('data-neighbor');
} }

View File

@@ -6,8 +6,8 @@
this.container = document.querySelector('.resize-canvas'); this.container = document.querySelector('.resize-canvas');
var anchorWidgetContainer = this.container.querySelector('.resize-anchor-container'); var anchorWidgetContainer = this.container.querySelector('.resize-origin-container');
this.anchorWidget = new pskl.widgets.AnchorWidget(anchorWidgetContainer); this.anchorWidget = new ns.AnchorWidget(anchorWidgetContainer);
this.defaultSizeController = new ns.DefaultSizeController(piskelController); this.defaultSizeController = new ns.DefaultSizeController(piskelController);
}; };
@@ -28,7 +28,7 @@
}); });
var settings = pskl.UserSettings.get('RESIZE_SETTINGS'); var settings = pskl.UserSettings.get('RESIZE_SETTINGS');
var origin = pskl.widgets.AnchorWidget.ORIGIN[settings.origin] || 'TOPLEFT'; var origin = ns.AnchorWidget.ORIGIN[settings.origin] || ns.AnchorWidget.ORIGIN.TOPLEFT;
this.anchorWidget.setOrigin(origin); this.anchorWidget.setOrigin(origin);
if (settings.resizeContent) { if (settings.resizeContent) {
@@ -61,21 +61,27 @@
ns.ResizeController.prototype.onResizeFormSubmit_ = function (evt) { ns.ResizeController.prototype.onResizeFormSubmit_ = function (evt) {
evt.preventDefault(); evt.preventDefault();
var currentPiskel = this.piskelController.getPiskel(); var resizedLayers = this.piskelController.getLayers().map(this.resizeLayer_.bind(this));
var piskel = pskl.utils.ResizeUtils.resizePiskel(currentPiskel, {
width : parseInt(this.widthInput.value, 10),
height : parseInt(this.heightInput.value, 10),
origin: this.anchorWidget.getOrigin(),
resizeContent: this.resizeContentCheckbox.checked
});
pskl.app.piskelController.setPiskel(piskel, { var currentPiskel = this.piskelController.getPiskel();
preserveState: true var fps = this.piskelController.getFPS();
}); var piskel = pskl.model.Piskel.fromLayers(resizedLayers, fps, currentPiskel.getDescriptor());
// propagate savepath to new Piskel
piskel.savePath = currentPiskel.savePath;
pskl.app.piskelController.setPiskel(piskel, true);
$.publish(Events.CLOSE_SETTINGS_DRAWER); $.publish(Events.CLOSE_SETTINGS_DRAWER);
}; };
ns.ResizeController.prototype.resizeLayer_ = function (layer) {
var opacity = layer.getOpacity();
var resizedFrames = layer.getFrames().map(this.resizeFrame_.bind(this));
var resizedLayer = pskl.model.Layer.fromFrames(layer.getName(), resizedFrames);
resizedLayer.setOpacity(opacity);
return resizedLayer;
};
ns.ResizeController.prototype.onResizeContentChange_ = function (evt) { ns.ResizeController.prototype.onResizeContentChange_ = function (evt) {
var target = evt.target; var target = evt.target;
if (target.checked) { if (target.checked) {
@@ -101,4 +107,55 @@
maintainRatio : !!this.maintainRatioCheckbox.checked maintainRatio : !!this.maintainRatioCheckbox.checked
}); });
}; };
/***********************/
/* RESIZE LOGIC */
/***********************/
ns.ResizeController.prototype.resizeFrame_ = function (frame) {
var width = parseInt(this.widthInput.value, 10);
var height = parseInt(this.heightInput.value, 10);
if (this.resizeContentCheckbox.checked) {
return pskl.utils.FrameUtils.resize(frame, width, height, false);
} else {
var resizedFrame = new pskl.model.Frame(width, height);
frame.forEachPixel(function (color, x, y) {
var translated = this.translateCoordinates_(x, y, frame, resizedFrame);
if (resizedFrame.containsPixel(translated.x, translated.y)) {
resizedFrame.setPixel(translated.x, translated.y, color);
}
}.bind(this));
return resizedFrame;
}
};
ns.ResizeController.prototype.translateCoordinates_ = function (x, y, frame, resizedFrame) {
return {
x : this.translateX_(x, frame.width, resizedFrame.width),
y : this.translateY_(y, frame.height, resizedFrame.height)
};
};
ns.ResizeController.prototype.translateX_ = function (x, width, resizedWidth) {
var origin = this.anchorWidget.getOrigin();
if (origin.indexOf('LEFT') != -1) {
return x;
} else if (origin.indexOf('RIGHT') != -1) {
return x - (width - resizedWidth);
} else {
return x - Math.round((width - resizedWidth) / 2);
}
};
ns.ResizeController.prototype.translateY_ = function (y, height, resizedHeight) {
var origin = this.anchorWidget.getOrigin();
if (origin.indexOf('TOP') != -1) {
return y;
} else if (origin.indexOf('BOTTOM') != -1) {
return y - (height - resizedHeight);
} else {
return y - Math.round((height - resizedHeight) / 2);
}
};
})(); })();

View File

@@ -85,7 +85,7 @@
which : domEvent.which, which : domEvent.which,
shiftKey : domEvent.shiftKey, shiftKey : domEvent.shiftKey,
altKey : domEvent.altKey, altKey : domEvent.altKey,
ctrlKey : domEvent.ctrlKey || domEvent.metaKey, ctrlKey : domEvent.ctrlKey,
target : { target : {
nodeName : domEvent.target.nodeName nodeName : domEvent.target.nodeName
} }
@@ -142,12 +142,6 @@
recordEvent.type = 'instrumented-event'; recordEvent.type = 'instrumented-event';
recordEvent.methodName = methodName; recordEvent.methodName = methodName;
recordEvent.args = Array.prototype.slice.call(args, 0); recordEvent.args = Array.prototype.slice.call(args, 0);
if (methodName === 'setPiskel' && args[1].noSnapshot) {
// Skip recording calls to setPiskel that don't trigger a save.
return;
}
this.events.push(recordEvent); this.events.push(recordEvent);
} }
}; };

File diff suppressed because one or more lines are too long

View File

@@ -70,10 +70,6 @@
}); });
}; };
ns.Piskel.prototype.getFrameCount = function () {
return this.getLayerAt(0).size();
};
ns.Piskel.prototype.addLayer = function (layer) { ns.Piskel.prototype.addLayer = function (layer) {
this.layers.push(layer); this.layers.push(layer);
}; };
@@ -82,28 +78,20 @@
this.layers.splice(index, 0, layer); this.layers.splice(index, 0, layer);
}; };
ns.Piskel.prototype.moveLayerUp = function (layer, toTop) { ns.Piskel.prototype.moveLayerUp = function (layer) {
var index = this.layers.indexOf(layer); var index = this.layers.indexOf(layer);
var toIndex = toTop ? this.layers.length - 1 : index + 1; if (index > -1 && index < this.layers.length - 1) {
this.moveLayer_(index, toIndex); this.layers[index] = this.layers[index + 1];
}; this.layers[index + 1] = layer;
}
ns.Piskel.prototype.moveLayerDown = function (layer, toBottom) { };
var index = this.layers.indexOf(layer);
var toIndex = toBottom ? 0 : index - 1; ns.Piskel.prototype.moveLayerDown = function (layer) {
this.moveLayer_(index, toIndex); var index = this.layers.indexOf(layer);
}; if (index > 0) {
this.layers[index] = this.layers[index - 1];
/** this.layers[index - 1] = layer;
* Move the layer at the provided index to the provided toIndex.
*/
ns.Piskel.prototype.moveLayer_ = function (fromIndex, toIndex) {
if (fromIndex == -1 || toIndex == -1 || fromIndex == toIndex) {
return;
} }
toIndex = pskl.utils.Math.minmax(toIndex, 0, this.layers.length - 1);
var layer = this.layers.splice(fromIndex, 1)[0];
this.layers.splice(toIndex, 0, layer);
}; };
ns.Piskel.prototype.removeLayer = function (layer) { ns.Piskel.prototype.removeLayer = function (layer) {

View File

@@ -34,7 +34,6 @@
var serializedFrame = [ var serializedFrame = [
this.getZoom(), this.getZoom(),
this.getGridWidth(), this.getGridWidth(),
this.getGridColor(),
pskl.UserSettings.get('SEAMLESS_MODE'), pskl.UserSettings.get('SEAMLESS_MODE'),
pskl.UserSettings.get('SEAMLESS_OPACITY'), pskl.UserSettings.get('SEAMLESS_OPACITY'),
offset.x, offset.y, offset.x, offset.y,

View File

@@ -55,7 +55,7 @@
this.displayCanvas = null; this.displayCanvas = null;
this.setDisplaySize(renderingOptions.width, renderingOptions.height); this.setDisplaySize(renderingOptions.width, renderingOptions.height);
this.setGridWidth(this.getUserGridWidth_()); this.setGridWidth(pskl.UserSettings.get(pskl.UserSettings.GRID_WIDTH));
$.subscribe(Events.USER_SETTINGS_CHANGED, this.onUserSettingsChange_.bind(this)); $.subscribe(Events.USER_SETTINGS_CHANGED, this.onUserSettingsChange_.bind(this));
}; };
@@ -138,10 +138,6 @@
this.offset.y = y; this.offset.y = y;
}; };
ns.FrameRenderer.prototype.getGridColor = function () {
return pskl.UserSettings.get(pskl.UserSettings.GRID_COLOR);
};
ns.FrameRenderer.prototype.setGridWidth = function (value) { ns.FrameRenderer.prototype.setGridWidth = function (value) {
this.gridWidth_ = value; this.gridWidth_ = value;
}; };
@@ -184,18 +180,11 @@
}; };
ns.FrameRenderer.prototype.onUserSettingsChange_ = function (evt, settingName, settingValue) { ns.FrameRenderer.prototype.onUserSettingsChange_ = function (evt, settingName, settingValue) {
var settings = pskl.UserSettings; if (settingName == pskl.UserSettings.GRID_WIDTH) {
if (settingName == settings.GRID_WIDTH || settingName == settings.GRID_ENABLED) { this.setGridWidth(settingValue);
this.setGridWidth(this.getUserGridWidth_());
} }
}; };
ns.FrameRenderer.prototype.getUserGridWidth_ = function () {
var gridEnabled = pskl.UserSettings.get(pskl.UserSettings.GRID_ENABLED);
var width = pskl.UserSettings.get(pskl.UserSettings.GRID_WIDTH);
return gridEnabled ? width : 0;
};
/** /**
* Transform a screen pixel-based coordinate (relative to the top-left corner of the rendered * Transform a screen pixel-based coordinate (relative to the top-left corner of the rendered
* frame) into a sprite coordinate in column and row. * frame) into a sprite coordinate in column and row.
@@ -263,24 +252,14 @@
var displayContext = this.displayCanvas.getContext('2d'); var displayContext = this.displayCanvas.getContext('2d');
displayContext.save(); displayContext.save();
var translateX = this.margin.x - this.offset.x * z; // Draw background
var translateY = this.margin.y - this.offset.y * z; displayContext.fillStyle = Constants.ZOOMED_OUT_BACKGROUND_COLOR;
displayContext.fillRect(0, 0, this.displayCanvas.width - 1, this.displayCanvas.height - 1);
var isZoomedOut = translateX > 0 || translateY > 0; displayContext.translate(
// Draw the background / zoomed-out color only if needed. Otherwise the clearRect this.margin.x - this.offset.x * z,
// happening after that will clear "out of bounds" and seems to be doing nothing this.margin.y - this.offset.y * z
// on some chromebooks (cf https://github.com/piskelapp/piskel/issues/651) );
if (isZoomedOut) {
// Draw background
displayContext.fillStyle = Constants.ZOOMED_OUT_BACKGROUND_COLOR;
// The -1 on the width and height here is a workaround for a Chrome-only bug
// that was potentially fixed, but is very hardware dependant. Seems to be
// triggered when doing clear rect or fill rect using the full width & height
// of a canvas. (https://bugs.chromium.org/p/chromium/issues/detail?id=469906)
displayContext.fillRect(0, 0, this.displayCanvas.width - 1, this.displayCanvas.height - 1);
}
displayContext.translate(translateX, translateY);
// Scale up to draw the canvas content // Scale up to draw the canvas content
displayContext.scale(z, z); displayContext.scale(z, z);
@@ -299,25 +278,15 @@
// Draw grid. // Draw grid.
var gridWidth = this.computeGridWidthForDisplay_(); var gridWidth = this.computeGridWidthForDisplay_();
if (gridWidth > 0) { if (gridWidth > 0) {
var gridColor = this.getGridColor();
// Scale out before drawing the grid. // Scale out before drawing the grid.
displayContext.scale(1 / z, 1 / z); displayContext.scale(1 / z, 1 / z);
// Clear vertical lines.
var drawOrClear;
if (gridColor === Constants.TRANSPARENT_COLOR) {
drawOrClear = displayContext.clearRect.bind(displayContext);
} else {
displayContext.fillStyle = gridColor;
drawOrClear = displayContext.fillRect.bind(displayContext);
}
// Draw or clear vertical lines.
for (var i = 1 ; i < frame.getWidth() ; i++) { for (var i = 1 ; i < frame.getWidth() ; i++) {
drawOrClear((i * z) - (gridWidth / 2), 0, gridWidth, h * z); displayContext.clearRect((i * z) - (gridWidth / 2), 0, gridWidth, h * z);
} }
// Draw or clear horizontal lines. // Clear horizontal lines.
for (var j = 1 ; j < frame.getHeight() ; j++) { for (var j = 1 ; j < frame.getHeight() ; j++) {
drawOrClear(0, (j * z) - (gridWidth / 2), w * z, gridWidth); displayContext.clearRect(0, (j * z) - (gridWidth / 2), w * z, gridWidth);
} }
} }

View File

@@ -32,7 +32,7 @@
ns.BeforeUnloadService.prototype.onBeforeUnload = function (evt) { ns.BeforeUnloadService.prototype.onBeforeUnload = function (evt) {
pskl.app.backupService.backup(); pskl.app.backupService.backup();
if (pskl.app.savedStatusService.isDirty()) { if (pskl.app.savedStatusService.isDirty()) {
var confirmationMessage = 'Your current sprite has unsaved changes. Are you sure you want to quit?'; var confirmationMessage = 'Your Piskel seems to have unsaved changes';
evt = evt || window.event; evt = evt || window.event;
if (evt) { if (evt) {

View File

@@ -35,13 +35,7 @@
var isPiskel = /\.piskel$/i.test(file.name); var isPiskel = /\.piskel$/i.test(file.name);
var isPalette = /\.(gpl|txt|pal)$/i.test(file.name); var isPalette = /\.(gpl|txt|pal)$/i.test(file.name);
if (isImage) { if (isImage) {
$.publish(Events.DIALOG_SHOW, { this.readImageFile_(file);
dialogId : 'import',
initArgs : {
rawFiles: [file]
}
});
// pskl.utils.FileUtils.readImageFile(file, this.onImageLoaded_.bind(this));
} else if (isPiskel) { } else if (isPiskel) {
pskl.utils.PiskelFileUtils.loadFromFile(file, this.onPiskelFileLoaded_, this.onPiskelFileError_); pskl.utils.PiskelFileUtils.loadFromFile(file, this.onPiskelFileLoaded_, this.onPiskelFileError_);
} else if (isPalette) { } else if (isPalette) {
@@ -50,6 +44,10 @@
} }
}; };
ns.FileDropperService.prototype.readImageFile_ = function (imageFile) {
pskl.utils.FileUtils.readFile(imageFile, this.processImageSource_.bind(this));
};
ns.FileDropperService.prototype.onPaletteLoaded_ = function (palette) { ns.FileDropperService.prototype.onPaletteLoaded_ = function (palette) {
pskl.app.paletteService.savePalette(palette); pskl.app.paletteService.savePalette(palette);
pskl.UserSettings.set(pskl.UserSettings.SELECTED_PALETTE, palette.id); pskl.UserSettings.set(pskl.UserSettings.SELECTED_PALETTE, palette.id);
@@ -65,6 +63,12 @@
$.publish(Events.PISKEL_FILE_IMPORT_FAILED, [reason]); $.publish(Events.PISKEL_FILE_IMPORT_FAILED, [reason]);
}; };
ns.FileDropperService.prototype.processImageSource_ = function (imageSource) {
var importedImage = new Image();
importedImage.onload = this.onImageLoaded_.bind(this, importedImage);
importedImage.src = imageSource;
};
ns.FileDropperService.prototype.onImageLoaded_ = function (importedImage) { ns.FileDropperService.prototype.onImageLoaded_ = function (importedImage) {
if (this.isMultipleFiles_) { if (this.isMultipleFiles_) {
this.piskelController.addFrameAtCurrentIndex(); this.piskelController.addFrameAtCurrentIndex();

View File

@@ -28,24 +28,19 @@
/** /**
* Given an image object and some options, create a new Piskel and open it * Given an image object and some options, create a new Piskel and open it
* for editing. * for editing.
* @param {Image} image * @param {!Image} image
* @param {Object} options * @param {!Object} options
* - {String} importType 'single' if not spritesheet * @param {!string} options.importType - 'single' if not spritesheet
* - {String} name * @param {!number} options.frameSizeX
* - {Boolean} smoothing * @param {!number} options.frameSizeY
* - {Number} frameSizeX * @param {number} [options.frameOffsetX] only used in spritesheet imports.
* - {Number} frameSizeY * @param {number} [options.frameOffsetY] only used in spritesheet imports.
* - {Number} frameOffsetX (only used in spritesheet imports) * @param {!boolean} options.smoothing
* - {Number} frameOffsetY (only used in spritesheet imports) * @param {function} [onComplete]
* @param {Function} onComplete
* Callback called when the new piskel has been created, with the new piskel
* as single argument.
*/ */
ns.ImportService.prototype.newPiskelFromImage = function (image, options, onComplete) { ns.ImportService.prototype.newPiskelFromImage = function (image, options, onComplete) {
onComplete = onComplete || Constants.EMPTY_FUNCTION; onComplete = onComplete || Constants.EMPTY_FUNCTION;
var importType = options.importType; var importType = options.importType;
var name = options.name;
var smoothing = options.smoothing;
var frameSizeX = options.frameSizeX; var frameSizeX = options.frameSizeX;
var frameSizeY = options.frameSizeY; var frameSizeY = options.frameSizeY;
var frameOffsetX = options.frameOffsetX; var frameOffsetX = options.frameOffsetX;
@@ -61,28 +56,26 @@
return pskl.utils.CanvasUtils.createFromImageData(frame.data); return pskl.utils.CanvasUtils.createFromImageData(frame.data);
}); });
var piskel;
if (importType === 'single' || images.length > 1) { if (importType === 'single' || images.length > 1) {
// Single image import or animated gif // Single image import or animated gif
piskel = this.createPiskelFromImages_(images, name, frameSizeX, frameSizeY, smoothing); this.createPiskelFromImages_(images, frameSizeX, frameSizeY, options.smoothing);
} else { } else {
// Spritesheet // Spritesheet
var frameImages = this.createImagesFromSheet_(images[0], frameSizeX, frameSizeY, frameOffsetX, frameOffsetY); var frameImages = this.createImagesFromSheet_(images[0]);
piskel = this.createPiskelFromImages_(frameImages, name, frameSizeX, frameSizeY, smoothing); this.createPiskelFromImages_(frameImages, frameSizeX, frameSizeY, options.smoothing);
} }
onComplete(piskel); onComplete();
}.bind(this), }.bind(this),
error: function () { error: function () {
var piskel;
if (importType === 'single') { if (importType === 'single') {
// Single image // Single image
piskel = this.createPiskelFromImages_([image], name, frameSizeX, frameSizeY, smoothing); this.createPiskelFromImages_([image], frameSizeX, frameSizeY, options.smoothing);
} else { } else {
// Spritesheet // Spritesheet
var frameImages = this.createImagesFromSheet_(image, frameSizeX, frameSizeY, frameOffsetX, frameOffsetY); var frameImages = this.createImagesFromSheet_(image, frameSizeX, frameSizeY, frameOffsetX, frameOffsetY);
piskel = this.createPiskelFromImages_(frameImages, name, frameSizeX, frameSizeY, smoothing); this.createPiskelFromImages_(frameImages, frameSizeX, frameSizeY, options.smoothing);
} }
onComplete(piskel); onComplete();
}.bind(this) }.bind(this)
}); });
}; };
@@ -115,13 +108,14 @@
* @param {!boolean} smoothing * @param {!boolean} smoothing
* @private * @private
*/ */
ns.ImportService.prototype.createPiskelFromImages_ = function (images, name, ns.ImportService.prototype.createPiskelFromImages_ = function (images,
frameSizeX, frameSizeY, smoothing) { frameSizeX, frameSizeY, smoothing) {
name = name || 'Imported piskel';
var frames = this.createFramesFromImages_(images, frameSizeX, frameSizeY, smoothing); var frames = this.createFramesFromImages_(images, frameSizeX, frameSizeY, smoothing);
var layer = pskl.model.Layer.fromFrames('Layer 1', frames); var layer = pskl.model.Layer.fromFrames('Layer 1', frames);
var descriptor = new pskl.model.piskel.Descriptor(name, ''); var descriptor = new pskl.model.piskel.Descriptor('Imported piskel', '');
return pskl.model.Piskel.fromLayers([layer], Constants.DEFAULT.FPS, descriptor); var piskel = pskl.model.Piskel.fromLayers([layer], Constants.DEFAULT.FPS, descriptor);
this.piskelController_.setPiskel(piskel);
}; };
/** /**

View File

@@ -3,7 +3,6 @@
8 : 'back', 8 : 'back',
13 : 'enter', 13 : 'enter',
27 : 'esc', 27 : 'esc',
32 : 'space',
37 : 'left', 37 : 'left',
38 : 'up', 38 : 'up',
39 : 'right', 39 : 'right',

View File

@@ -60,12 +60,7 @@
FULL_PREVIEW : createShortcut('full-preview', 'Select full size preview', 'alt+3'), FULL_PREVIEW : createShortcut('full-preview', 'Select full size preview', 'alt+3'),
ONION_SKIN : createShortcut('onion-skin', 'Toggle onion skin', 'alt+O'), ONION_SKIN : createShortcut('onion-skin', 'Toggle onion skin', 'alt+O'),
LAYER_PREVIEW : createShortcut('layer-preview', 'Toggle layer preview', 'alt+L'), LAYER_PREVIEW : createShortcut('layer-preview', 'Toggle layer preview', 'alt+L'),
MERGE_ANIMATION : createShortcut('import-animation', 'Open merge animation popup', 'ctrl+shift+M'), CLOSE_POPUP : createShortcut('close-popup', 'Close an opened popup', 'ESC')
CLOSE_POPUP : createShortcut('close-popup', 'Close an opened popup', 'ESC'),
OFFSET_UP : createShortcut('move-up', 'Move viewport up', 'shift+up'),
OFFSET_RIGHT : createShortcut('move-right', 'Move viewport right', 'shift+right'),
OFFSET_DOWN : createShortcut('move-down', 'Move viewport down', 'shift+down'),
OFFSET_LEFT : createShortcut('move-left', 'Move viewport left', 'shift+left'),
}, },
STORAGE : { STORAGE : {

View File

@@ -35,11 +35,7 @@
var evenY = (coords.y0 + coords.y1) % 2; var evenY = (coords.y0 + coords.y1) % 2;
var rX = coords.x1 - xC; var rX = coords.x1 - xC;
var rY = coords.y1 - yC; var rY = coords.y1 - yC;
var x, y, angle, r;
var x;
var y;
var angle;
var r;
if (penSize == 1) { if (penSize == 1) {
for (x = coords.x0 ; x <= xC ; x++) { for (x = coords.x0 ; x <= xC ; x++) {

View File

@@ -97,31 +97,8 @@
linePixels = pskl.PixelUtils.getLinePixels(col, this.startCol, row, this.startRow); linePixels = pskl.PixelUtils.getLinePixels(col, this.startCol, row, this.startRow);
} }
//draw the square ends of the line pskl.PixelUtils.resizePixels(linePixels, penSize).forEach(function (point) {
pskl.PixelUtils.resizePixel(linePixels[0].col, linePixels[0].row, penSize) targetFrame.setPixel(point[0], point[1], color);
.forEach(function (point) {targetFrame.setPixel(point[0], point[1], color);});
pskl.PixelUtils.resizePixel(linePixels[linePixels.length - 1].col, linePixels[linePixels.length - 1].row, penSize)
.forEach(function (point) {targetFrame.setPixel(point[0], point[1],color);});
//for each step along the line, draw an x centered on that pixel of size penSize
linePixels.forEach(function (point) {
for (var i = 0; i < penSize; i++) {
targetFrame.setPixel(
point.col - Math.floor(penSize / 2) + i, point.row - Math.floor(penSize / 2) + i, color
);
targetFrame.setPixel(
point.col - Math.floor(penSize / 2) + i, point.row + Math.ceil(penSize / 2) - i - 1, color
);
//draw an additional x directly next to the first to prevent unwanted dithering
if (i !== 0) {
targetFrame.setPixel(
point.col - Math.floor(penSize / 2) + i, point.row - Math.floor(penSize / 2) + i - 1, color
);
targetFrame.setPixel(
point.col - Math.floor(penSize / 2) + i, point.row + Math.ceil(penSize / 2) - i, color
);
}
}
}); });
}; };

View File

@@ -1,127 +0,0 @@
(function () {
var ns = $.namespace('pskl.tools.transform');
ns.Crop = function () {
this.toolId = 'tool-crop';
this.helpText = 'Crop the sprite';
this.tooltipDescriptors = [
{
description : 'Crop to fit the content or the selection. ' +
'Applies to all frames and layers!'
}
];
};
// This transform tool is the only one that adapts to the current selection and can't
// rely on the default AbstractTransformTool behavior.
pskl.utils.inherit(ns.Crop, pskl.tools.Tool);
ns.Crop.prototype.applyTransformation = function (evt) {
var frames = this.getFrames_();
var boundaries;
if (pskl.app.selectionManager.currentSelection) {
// If we have a selection, we will compute the boundaries of the selection instead
// of looping on the frames.
boundaries = this.getBoundariesForSelection_();
} else {
boundaries = pskl.tools.transform.TransformUtils.getBoundaries(frames);
}
var applied = this.applyTool_(frames, boundaries);
if (applied) {
this.raiseSaveStateEvent({
boundaries : boundaries
});
}
};
ns.Crop.prototype.replay = function (frame, replayData) {
var frames = this.getFrames_();
this.applyTool_(frames, replayData.boundaries);
};
ns.Crop.prototype.applyTool_ = function (frames, boundaries) {
if (boundaries.minx >= boundaries.maxx) {
return false;
}
var currentPiskel = pskl.app.piskelController.getPiskel();
var width = 1 + boundaries.maxx - boundaries.minx;
var height = 1 + boundaries.maxy - boundaries.miny;
if (width === currentPiskel.getWidth() && height === currentPiskel.getHeight()) {
// Do not perform an unnecessary resize if it's a noop.
return false;
}
frames.forEach(function (frame) {
pskl.tools.transform.TransformUtils.moveFramePixels(frame, -boundaries.minx, -boundaries.miny);
});
var piskel = pskl.utils.ResizeUtils.resizePiskel(currentPiskel, {
width : 1 + boundaries.maxx - boundaries.minx,
height : 1 + boundaries.maxy - boundaries.miny,
origin: 'TOP-LEFT',
resizeContent: false
});
// Clear the current selection.
$.publish(Events.SELECTION_DISMISSED);
// Replace the current piskel with the resized version.
pskl.app.piskelController.setPiskel(piskel, {
preserveState: true,
// Saving is already handled by recording the transform tool action, no need for
// an expensive snapshot.
noSnapshot: true
});
return true;
};
/**
* Retrieve the list of frames for the current piskel in a single flat array.
*/
ns.Crop.prototype.getFrames_ = function () {
var currentPiskel = pskl.app.piskelController.getPiskel();
// Get all frames in a single array.
var frames = currentPiskel.getLayers().map(function (l) {
return l.getFrames();
}).reduce(function (p, n) {
return p.concat(n);
});
return frames;
};
/**
* Retrieve a boundaries object {minx, maxx, miny, maxy} for the current selection.
*/
ns.Crop.prototype.getBoundariesForSelection_ = function () {
var selectionManager = pskl.app.selectionManager;
var pixels = selectionManager.currentSelection.pixels;
// Fetch the first frame to perform out-of-bound checks.
var currentPiskel = pskl.app.piskelController.getPiskel();
var exampleFrame = currentPiskel.getLayerAt(0).getFrameAt(0);
// Anything different from Constants.TRANSPARENT_COLOR toInt().
var FAKE_COLOR = 1;
// Create a fake frame reimplementing the forEachPixel API.
var selectionFrame = {
forEachPixel : function (callback) {
for (var i = 0; i < pixels.length ; i++) {
var pixel = pixels[i];
// Selections might contain out of bound pixels, filter those out.
if (exampleFrame.containsPixel(pixel.col, pixel.row)) {
callback(FAKE_COLOR, pixel.col, pixel.row);
}
}
}
};
return pskl.tools.transform.TransformUtils.getBoundaries([selectionFrame]);
};
})();

View File

@@ -64,34 +64,32 @@
return frame; return frame;
}, },
getBoundaries : function(frames) { center : function(frame) {
var minx = +Infinity; // Figure out the boundary
var miny = +Infinity; var minx = frame.width;
var miny = frame.height;
var maxx = 0; var maxx = 0;
var maxy = 0; var maxy = 0;
var transparentColorInt = pskl.utils.colorToInt(Constants.TRANSPARENT_COLOR); var transparentColorInt = pskl.utils.colorToInt(Constants.TRANSPARENT_COLOR);
frame.forEachPixel(function (color, x, y) {
frames.forEach(function (frame) { if (color !== transparentColorInt) {
frame.forEachPixel(function (color, x, y) { minx = Math.min(minx, x);
if (color !== transparentColorInt) { maxx = Math.max(maxx, x);
minx = Math.min(minx, x); miny = Math.min(miny, y);
maxx = Math.max(maxx, x); maxy = Math.max(maxy, y);
miny = Math.min(miny, y); }
maxy = Math.max(maxy, y);
}
});
}); });
return { // Calculate how much to move the pixels
minx: minx, var bw = (maxx - minx + 1) / 2;
maxx: maxx, var bh = (maxy - miny + 1) / 2;
miny: miny, var fw = frame.width / 2;
maxy: maxy, var fh = frame.height / 2;
};
},
moveFramePixels : function (frame, dx, dy) { var dx = Math.floor(fw - bw - minx);
var dy = Math.floor(fh - bh - miny);
// Actually move the pixels
var clone = frame.clone(); var clone = frame.clone();
frame.forEachPixel(function(color, x, y) { frame.forEachPixel(function(color, x, y) {
var _x = x; var _x = x;
@@ -106,24 +104,7 @@
frame.setPixel(_x, _y, Constants.TRANSPARENT_COLOR); frame.setPixel(_x, _y, Constants.TRANSPARENT_COLOR);
} }
}); });
},
center : function(frame) {
// Figure out the boundary
var boundaries = ns.TransformUtils.getBoundaries([frame]);
// Calculate how much to move the pixels
var bw = (boundaries.maxx - boundaries.minx + 1) / 2;
var bh = (boundaries.maxy - boundaries.miny + 1) / 2;
var fw = frame.width / 2;
var fh = frame.height / 2;
var dx = Math.floor(fw - bw - boundaries.minx);
var dy = Math.floor(fh - bh - boundaries.miny);
// Actually move the pixels
ns.TransformUtils.moveFramePixels(frame, dx, dy);
return frame; return frame;
} }
}; };

View File

@@ -19,10 +19,6 @@
} }
} }
return isNodeWebkit; return isNodeWebkit;
},
isIntegrationTest : function () {
return window.location.href.indexOf('integration-test') !== -1;
} }
}; };

View File

@@ -21,8 +21,7 @@
* every X milliseconds, where X is the provided interval. * every X milliseconds, where X is the provided interval.
*/ */
throttle : function (fn, interval) { throttle : function (fn, interval) {
var last; var last, timer;
var timer;
return function () { return function () {
var now = Date.now(); var now = Date.now();
if (last && now < last + interval) { if (last && now < last + interval) {

View File

@@ -2,13 +2,6 @@
var ns = $.namespace('pskl.utils'); var ns = $.namespace('pskl.utils');
ns.LayerUtils = { ns.LayerUtils = {
clone : function (layer) {
var clonedFrames = layer.getFrames().map(function (frame) {
return frame.clone();
});
return pskl.model.Layer.fromFrames(layer.getName() + ' (clone)', clonedFrames);
},
mergeLayers : function (layerA, layerB) { mergeLayers : function (layerA, layerB) {
var framesA = layerA.getFrames(); var framesA = layerA.getFrames();
var framesB = layerB.getFrames(); var framesB = layerB.getFrames();

View File

@@ -1,89 +0,0 @@
(function () {
var ns = $.namespace('pskl.utils');
ns.MergeUtils = {
/**
* Merge two piskel instances in a new piskel instance
* @param {Piskel} piskel
* The original piskel (name and description will be preserved)
* @param {Piskel} importedPiskel
* The imported piskel
* @param {Object} options
* - index: {Number} index where the new frames should be appended
* - resize: {String} either "expand" or "keep"
* - origin: {String} can be any of the existing AnchorWidget origins.
* - insertMode: {String} either "insert" or "add"
*
* @return {Piskel} The new Piskel instance created
*/
merge : function (piskel, importedPiskel, options) {
var isImportedPiskelBigger =
importedPiskel.getWidth() > piskel.getWidth() ||
importedPiskel.getHeight() > piskel.getHeight();
// First make sure both the piskel and the imported piskel use the target dimensions.
if (isImportedPiskelBigger && options.resize === 'expand') {
piskel = pskl.utils.ResizeUtils.resizePiskel(piskel, {
width : Math.max(piskel.getWidth(), importedPiskel.getWidth()),
height : Math.max(piskel.getHeight(), importedPiskel.getHeight()),
origin : options.origin,
resizeContent: false
});
} else {
importedPiskel = pskl.utils.ResizeUtils.resizePiskel(importedPiskel, {
width : piskel.getWidth(),
height : piskel.getHeight(),
origin : options.origin,
resizeContent: false
});
}
var insertIndex = options.insertIndex;
if (options.insertMode === 'insert') {
// The index provided by the frame picker is 1-based.
// When adding new frames, this works out fine, but if we want to
// insert the new content in existing frames, we need to get the real
// 0-based index of the selected frame.
insertIndex = insertIndex - 1;
}
// Add necessary frames in the original piskel.
var importedFrameCount = importedPiskel.getFrameCount();
for (var i = 0 ; i < importedFrameCount ; i++) {
var index = i + insertIndex;
// For a given index, a new frame should be added either if we are using "add" insert mode
// or if the current index is not supported by the original piskel.
if (options.insertMode === 'add' || index >= piskel.getFrameCount()) {
ns.MergeUtils.addFrameToLayers_(piskel, index);
}
}
// Import the layers in the original piskel.
importedPiskel.getLayers().forEach(function (layer) {
var name = layer.getName() + ' (imported)';
var importedLayer = new pskl.model.Layer(name);
for (var i = 0 ; i < piskel.getFrameCount() ; i++) {
var importedIndex = i - insertIndex;
var frame = layer.getFrameAt(importedIndex);
if (!frame) {
frame = ns.MergeUtils.createEmptyFrame_(piskel);
}
importedLayer.addFrame(frame);
}
piskel.addLayer(importedLayer);
});
return piskel;
},
createEmptyFrame_ : function (piskel) {
return new pskl.model.Frame(piskel.getWidth(), piskel.getHeight());
},
addFrameToLayers_ : function (piskel, index) {
piskel.getLayers().forEach(function (l) {
l.addFrameAt(ns.MergeUtils.createEmptyFrame_(piskel), index);
});
}
};
})();

View File

@@ -182,7 +182,7 @@
var loopCount = 0; var loopCount = 0;
var cellCount = frame.getWidth() * frame.getHeight(); var cellCount = frame.getWidth() * frame.getHeight();
while (queue.length > 0) { while (queue.length > 0) {
loopCount++; loopCount ++;
var currentItem = queue.pop(); var currentItem = queue.pop();

View File

@@ -1,85 +0,0 @@
(function () {
var ns = $.namespace('pskl.utils');
ns.ResizeUtils = {
/**
* Resize the provided piskel instance and return a new instance using the provided resize options
* @param {Piskel} piskel [description]
* @param {Object} options
* - width {Number} target width after the resize
* - height {Number} target height after the resize
* - resizeContent {Booleam} true of the sprite content should be resized
* - origin {String} should be a valid AnchorWidget origin
* @return {Piskel} The resized piskel
*/
resizePiskel : function (piskel, options) {
var fps = piskel.getFPS();
var resizedLayers = piskel.getLayers().map(function (layer) {
return ns.ResizeUtils.resizeLayer(layer, options);
});
var resizedPiskel = pskl.model.Piskel.fromLayers(resizedLayers, fps, piskel.getDescriptor());
// propagate savepath to new Piskel
resizedPiskel.savePath = piskel.savePath;
return resizedPiskel;
},
resizeLayer : function (layer, options) {
var opacity = layer.getOpacity();
var resizedFrames = layer.getFrames().map(function (frame) {
return ns.ResizeUtils.resizeFrame(frame, options);
});
var resizedLayer = pskl.model.Layer.fromFrames(layer.getName(), resizedFrames);
resizedLayer.setOpacity(opacity);
return resizedLayer;
},
resizeFrame : function (frame, options) {
var width = options.width;
var height = options.height;
var origin = options.origin;
if (options.resizeContent) {
return pskl.utils.FrameUtils.resize(frame, width, height, false);
} else {
var resizedFrame = new pskl.model.Frame(width, height);
frame.forEachPixel(function (color, x, y) {
var translated = ns.ResizeUtils.translateCoordinates(x, y, frame, resizedFrame, origin);
if (resizedFrame.containsPixel(translated.x, translated.y)) {
resizedFrame.setPixel(translated.x, translated.y, color);
}
});
return resizedFrame;
}
},
translateCoordinates : function (x, y, frame, resizedFrame, origin) {
return {
x : ns.ResizeUtils.translateX(x, frame.width, resizedFrame.width, origin),
y : ns.ResizeUtils.translateY(y, frame.height, resizedFrame.height, origin)
};
},
translateX : function (x, width, resizedWidth, origin) {
if (origin.indexOf('LEFT') != -1) {
return x;
} else if (origin.indexOf('RIGHT') != -1) {
return x - (width - resizedWidth);
} else {
return x - Math.round((width - resizedWidth) / 2);
}
},
translateY : function (y, height, resizedHeight, origin) {
if (origin.indexOf('TOP') != -1) {
return y;
} else if (origin.indexOf('BOTTOM') != -1) {
return y - (height - resizedHeight);
} else {
return y - Math.round((height - resizedHeight) / 2);
}
}
};
})();

View File

@@ -6,9 +6,5 @@
var padding = new Array(length).join(pad); var padding = new Array(length).join(pad);
return (padding + input).slice(-length); return (padding + input).slice(-length);
}, },
formatSize : function (width, height) {
return width + '\u00D7' + height;
}
}; };
})(); })();

View File

@@ -15,23 +15,11 @@
return templates[templateId]; return templates[templateId];
}, },
getAsHTML : function (templateId) {
var template = ns.Template.get(templateId);
if (!template) {
return;
}
return ns.Template.createFromHTML(template);
},
createFromHTML : function (html) { createFromHTML : function (html) {
var dummyEl = ns.Template._getDummyEl(); var dummyEl = ns.Template._getDummyEl();
dummyEl.innerHTML = html; dummyEl.innerHTML = html;
var element = dummyEl.children[0]; var element = dummyEl.children[0];
dummyEl.innerHTML = '';
if (!pskl.utils.UserAgent.isIE11) {
dummyEl.innerHTML = '';
}
return element; return element;
}, },
@@ -62,15 +50,6 @@
return template; return template;
}, },
getAndReplace : function (templateId, dict) {
var result = '';
var tpl = pskl.utils.Template.get(templateId);
if (tpl) {
result = pskl.utils.Template.replace(tpl, dict);
}
return result;
},
/** /**
* Sanitize the provided string to make it safer for using in templates. * Sanitize the provided string to make it safer for using in templates.
*/ */
@@ -81,24 +60,16 @@
dummyEl.textContent = string; dummyEl.textContent = string;
var sanitizedString = dummyEl.innerHTML; var sanitizedString = dummyEl.innerHTML;
if (!pskl.utils.UserAgent.isIE11) { dummyEl.innerHTML = '';
dummyEl.innerHTML = '';
}
return sanitizedString; return sanitizedString;
}, },
_getDummyEl : pskl.utils.UserAgent.isIE11 ? _getDummyEl : function () {
// IE11 specific implementation if (!ns.Template._dummyEl) {
function () { ns.Template._dummyEl = document.createElement('div');
return document.createElement('div');
} :
// Normal, sane browsers implementation.
function () {
if (!ns.Template._dummyEl) {
ns.Template._dummyEl = document.createElement('div');
}
return ns.Template._dummyEl;
} }
return ns.Template._dummyEl;
}
}; };
})(); })();

View File

@@ -2,8 +2,6 @@
var ns = $.namespace('pskl'); var ns = $.namespace('pskl');
ns.UserSettings = { ns.UserSettings = {
GRID_COLOR : 'GRID_COLOR',
GRID_ENABLED : 'GRID_ENABLED',
GRID_WIDTH : 'GRID_WIDTH', GRID_WIDTH : 'GRID_WIDTH',
MAX_FPS : 'MAX_FPS', MAX_FPS : 'MAX_FPS',
DEFAULT_SIZE : 'DEFAULT_SIZE', DEFAULT_SIZE : 'DEFAULT_SIZE',
@@ -20,12 +18,8 @@
PEN_SIZE : 'PEN_SIZE', PEN_SIZE : 'PEN_SIZE',
RESIZE_SETTINGS: 'RESIZE_SETTINGS', RESIZE_SETTINGS: 'RESIZE_SETTINGS',
COLOR_FORMAT: 'COLOR_FORMAT', COLOR_FORMAT: 'COLOR_FORMAT',
TRANSFORM_SHOW_MORE: 'TRANSFORM_SHOW_MORE',
PREFERENCES_TAB: 'PREFERENCES_TAB',
KEY_TO_DEFAULT_VALUE_MAP_ : { KEY_TO_DEFAULT_VALUE_MAP_ : {
'GRID_COLOR' : Constants.TRANSPARENT_COLOR, 'GRID_WIDTH' : 0,
'GRID_ENABLED' : false,
'GRID_WIDTH' : 1,
'MAX_FPS' : 24, 'MAX_FPS' : 24,
'DEFAULT_SIZE' : { 'DEFAULT_SIZE' : {
width : Constants.DEFAULT.WIDTH, width : Constants.DEFAULT.WIDTH,
@@ -48,8 +42,6 @@
origin : 'TOPLEFT' origin : 'TOPLEFT'
}, },
COLOR_FORMAT: 'hex', COLOR_FORMAT: 'hex',
TRANSFORM_SHOW_MORE: false,
PREFERENCES_TAB: 'misc',
}, },
/** /**
@@ -85,7 +77,7 @@
/** /**
* @private * @private
*/ */
readFromLocalStorage_ : function (key) { readFromLocalStorage_ : function(key) {
var value = window.localStorage[key]; var value = window.localStorage[key];
if (typeof value != 'undefined') { if (typeof value != 'undefined') {
value = JSON.parse(value); value = JSON.parse(value);
@@ -96,7 +88,7 @@
/** /**
* @private * @private
*/ */
writeToLocalStorage_ : function (key, value) { writeToLocalStorage_ : function(key, value) {
// TODO(grosbouddha): Catch storage exception here. // TODO(grosbouddha): Catch storage exception here.
window.localStorage[key] = JSON.stringify(value); window.localStorage[key] = JSON.stringify(value);
}, },
@@ -111,7 +103,7 @@
/** /**
* @private * @private
*/ */
checkKeyValidity_ : function (key) { checkKeyValidity_ : function(key) {
if (key.indexOf(pskl.service.keyboard.Shortcut.USER_SETTINGS_PREFIX) === 0) { if (key.indexOf(pskl.service.keyboard.Shortcut.USER_SETTINGS_PREFIX) === 0) {
return true; return true;
} }
@@ -122,20 +114,4 @@
} }
} }
}; };
// Migration script for version 11 to version 12. Initialize the GRID_ENABLED pref from
// the current GRID_WIDTH and update the stored grid width to 1 if it was set to 0.
// SHOULD BE REMOVED FOR RELEASE 13.
ns.UserSettings.migrate_to_v0_12 = function () {
var storedGridEnabled = ns.UserSettings.readFromLocalStorage_('GRID_ENABLED');
if (typeof storedGridEnabled === 'undefined' || storedGridEnabled === null) {
var gridWidth = ns.UserSettings.get('GRID_WIDTH');
ns.UserSettings.writeToLocalStorage_('GRID_ENABLED', gridWidth > 0);
}
var storedGridWidth = ns.UserSettings.readFromLocalStorage_('GRID_WIDTH');
if (storedGridWidth === 0) {
ns.UserSettings.writeToLocalStorage_('GRID_WIDTH', 1);
}
};
})(); })();

View File

@@ -14,6 +14,6 @@
var descriptor = new pskl.model.piskel.Descriptor('Deserialized piskel', ''); var descriptor = new pskl.model.piskel.Descriptor('Deserialized piskel', '');
var layer = pskl.model.Layer.fromFrames('Layer 1', frames); var layer = pskl.model.Layer.fromFrames('Layer 1', frames);
this.callback_(pskl.model.Piskel.fromLayers([layer], Constants.DEFAULT.FPS, descriptor)); this.callback_(pskl.model.Piskel.fromLayers([layer], Constants.DEFAULTS.FPS, descriptor));
}; };
})(); })();

View File

@@ -9,7 +9,7 @@
ns.Deserializer_v1.prototype.deserialize = function () { ns.Deserializer_v1.prototype.deserialize = function () {
var piskelData = this.data_.piskel; var piskelData = this.data_.piskel;
var descriptor = new pskl.model.piskel.Descriptor('Deserialized piskel', ''); var descriptor = new pskl.model.piskel.Descriptor('Deserialized piskel', '');
var piskel = new pskl.model.Piskel(piskelData.width, piskelData.height, Constants.DEFAULT.FPS, descriptor); var piskel = new pskl.model.Piskel(piskelData.width, piskelData.height, Constants.DEFAULTS.FPS, descriptor);
piskelData.layers.forEach(function (serializedLayer) { piskelData.layers.forEach(function (serializedLayer) {
var layer = this.deserializeLayer(serializedLayer); var layer = this.deserializeLayer(serializedLayer);

View File

@@ -17,7 +17,7 @@
items: '.create-palette-color' items: '.create-palette-color'
}); });
pskl.utils.Event.addEventListener(this.colorsList, 'click', this.onColorContainerClick_, this); this.colorsList.addEventListener('click', this.onColorContainerClick_.bind(this));
var colorPickerContainer = container.querySelector('.color-picker-container'); var colorPickerContainer = container.querySelector('.color-picker-container');
this.hslRgbColorPicker = new pskl.widgets.HslRgbColorPicker(colorPickerContainer, this.onColorUpdated_.bind(this)); this.hslRgbColorPicker = new pskl.widgets.HslRgbColorPicker(colorPickerContainer, this.onColorUpdated_.bind(this));
@@ -40,10 +40,6 @@
}; };
ns.ColorsList.prototype.destroy = function () { ns.ColorsList.prototype.destroy = function () {
pskl.utils.Event.removeAllEventListeners(this);
$(this.container).sortable('destroy');
this.hslRgbColorPicker.destroy(); this.hslRgbColorPicker.destroy();
this.container = null; this.container = null;
this.colorsList = null; this.colorsList = null;

View File

@@ -1,168 +0,0 @@
(function () {
var ns = $.namespace('pskl.widgets');
var WIDGET_MARKUP =
'<div class="frame-viewer"></div>' +
'<div class="frame-nav">' +
'<button class="button frame-nav-first">&lt;&lt;</button>' +
'<button class="button frame-nav-previous">&lt;</button>' +
'<input class="textfield frame-nav-input" type="text">' +
'<button class="button frame-nav-next">&gt;</button>' +
'<button class="button frame-nav-last">&gt;&gt;</button>' +
'</div>';
/**
* The frame picker widget displays a a simple UI to view the frames of a piskel.
* UI controls allow the user to browser through the frames
* @param {Piskel} piskel
* The piskel instance for which we want to preview frames.
* @param {Node} container
* Node in which the widget should be inserted.
*/
ns.FramePicker = function (piskel, container) {
this.piskel = piskel;
this.container = container;
this.firstFrameIndex = 1;
// Create internal wrapper that will contain the widget.
this.wrapper = document.createElement('div');
this.wrapper.innerHTML = WIDGET_MARKUP;
this.wrapper.classList.add('frame-picker-wrapper');
this.frameViewer = this.wrapper.querySelector('.frame-viewer');
this.firstButton = this.wrapper.querySelector('.frame-nav-first');
this.previousButton = this.wrapper.querySelector('.frame-nav-previous');
this.nextButton = this.wrapper.querySelector('.frame-nav-next');
this.lastButton = this.wrapper.querySelector('.frame-nav-last');
this.input = this.wrapper.querySelector('.frame-nav-input');
};
ns.FramePicker.prototype.init = function () {
// Add widget to its container
this.container.appendChild(this.wrapper);
// Attach event listeners
this.addEventListener(this.firstButton, 'click', this.onFirstClicked_);
this.addEventListener(this.previousButton, 'click', this.onPreviousClicked_);
this.addEventListener(this.nextButton, 'click', this.onNextClicked_);
this.addEventListener(this.lastButton, 'click', this.onLastClicked_);
this.addEventListener(this.input, 'change', this.onInputChange_);
// Select the first frame
this.setFrameIndex(1);
};
ns.FramePicker.prototype.setFirstFrameIndex = function (index) {
this.firstFrameIndex = index;
// Set the current frame index once again to normalize and update the UI if needed.
this.setFrameIndex(this.currentFrameIndex);
};
ns.FramePicker.prototype.destroy = function () {
if (this.wrapper.parentNode) {
this.wrapper.parentNode.removeChild(this.wrapper);
}
pskl.utils.Event.removeAllEventListeners(this);
};
ns.FramePicker.prototype.onFirstClicked_ = function () {
this.setFrameIndex(this.firstFrameIndex);
};
ns.FramePicker.prototype.onPreviousClicked_ = function () {
this.setFrameIndex(this.currentFrameIndex - 1);
};
ns.FramePicker.prototype.onNextClicked_ = function () {
this.setFrameIndex(this.currentFrameIndex + 1);
};
ns.FramePicker.prototype.onLastClicked_ = function () {
this.setFrameIndex(this.piskel.getFrameCount());
};
ns.FramePicker.prototype.onInputChange_ = function () {
var index = parseInt(this.input.value, 10);
if (isNaN(index)) {
this.input.value = 1;
return;
}
index = Math.max(this.firstFrameIndex, index);
index = Math.min(this.getFrameCount_(), index);
if (index !== this.currentFrameIndex) {
this.setFrameIndex(index);
}
};
ns.FramePicker.prototype.getFrameCount_ = function () {
return this.piskel.getLayerAt(0).getFrames().length;
};
ns.FramePicker.prototype.addEventListener = function (el, type, callback) {
pskl.utils.Event.addEventListener(el, type, callback, this);
};
ns.FramePicker.prototype.getFrameIndex = function () {
return this.currentFrameIndex;
};
ns.FramePicker.prototype.setFrameIndex = function (frameIndex) {
frameIndex = Math.max(this.firstFrameIndex, frameIndex);
frameIndex = Math.min(this.getFrameCount_(), frameIndex);
this.currentFrameIndex = frameIndex;
this.input.value = frameIndex;
var image = this.getFrameAsImage_(frameIndex);
image.classList.add('canvas-background');
this.frameViewer.innerHTML = '';
this.frameViewer.appendChild(image);
var frameCount = this.getFrameCount_();
this.setEnabled_(this.firstButton, frameIndex !== this.firstFrameIndex);
this.setEnabled_(this.previousButton, frameIndex !== this.firstFrameIndex);
this.setEnabled_(this.nextButton, frameIndex !== frameCount);
this.setEnabled_(this.lastButton, frameIndex !== frameCount);
if (frameIndex === 0) {
this.previousButton.setAttribute('disabled', true);
this.firstButton.setAttribute('disabled', true);
}
};
ns.FramePicker.prototype.getFrameAsImage_ = function (frameIndex) {
if (frameIndex === 0) {
return new Image();
}
var frame = pskl.utils.LayerUtils.mergeFrameAt(this.piskel.getLayers(), frameIndex - 1);
var zoom = this.getZoomLevel_();
return pskl.utils.FrameUtils.toImage(frame, zoom);
};
ns.FramePicker.prototype.getZoomLevel_ = function () {
var viewerWidth = this.frameViewer.offsetWidth;
var viewerHeight = this.frameViewer.offsetHeight;
var wZoom = viewerWidth / this.piskel.width;
var hZoom = viewerHeight / this.piskel.height;
return Math.min(hZoom, wZoom);
};
/**
* DOM helper to enable / disable as DOM element.
* @param {Node} el
* The element to enable / disable.
* @param {Boolean} enabled
* Should the element be disabled or enabled.
*/
ns.FramePicker.prototype.setEnabled_ = function (el, enabled) {
if (enabled) {
el.removeAttribute('disabled');
} else {
el.setAttribute('disabled', true);
}
};
})();

View File

@@ -17,12 +17,9 @@
var isChrome = pskl.utils.UserAgent.isChrome; var isChrome = pskl.utils.UserAgent.isChrome;
var changeEvent = (isChrome || isFirefox) ? 'input' : 'change'; var changeEvent = (isChrome || isFirefox) ? 'input' : 'change';
pskl.utils.Event.addEventListener(this.container, changeEvent, this.onPickerChange_, this); this.container.addEventListener(changeEvent, this.onPickerChange_.bind(this));
pskl.utils.Event.addEventListener(this.container, 'keydown', this.onPickerChange_, this); this.container.addEventListener('keydown', this.onKeydown_.bind(this));
this.container.addEventListener('blur', this.onBlur_.bind(this), true);
// Cannot use pskl.utils.Event with useCapture for now ...
this.onBlur_ = this.onBlur_.bind(this);
this.container.addEventListener('blur', this.onBlur_, true);
this.spectrumEl = this.container.querySelector('.color-picker-spectrum'); this.spectrumEl = this.container.querySelector('.color-picker-spectrum');
@@ -37,13 +34,6 @@
}; };
ns.HslRgbColorPicker.prototype.destroy = function () { ns.HslRgbColorPicker.prototype.destroy = function () {
// Remove event listeners.
pskl.utils.Event.removeAllEventListeners(this);
this.container.removeEventListener('blur', this.onBlur_, true);
// Destroy spectrum widget.
$(this.spectrumEl).spectrum('destroy');
this.container = null; this.container = null;
this.spectrumEl = null; this.spectrumEl = null;
}; };
@@ -227,8 +217,7 @@
var dimension = slider.dataset.dimension; var dimension = slider.dataset.dimension;
var model = slider.dataset.model; var model = slider.dataset.model;
var start; var start, end;
var end;
var isHueSlider = dimension === 'h'; var isHueSlider = dimension === 'h';
if (!isHueSlider) { if (!isHueSlider) {
var colors = this.getSliderBackgroundColors_(model, dimension); var colors = this.getSliderBackgroundColors_(model, dimension);

View File

@@ -1,50 +0,0 @@
(function () {
var ns = $.namespace('pskl.widgets');
ns.SizePicker = function (onChange) {
this.onChange = onChange;
};
ns.SizePicker.prototype.init = function (container) {
this.container = container;
pskl.utils.Event.addEventListener(this.container, 'click', this.onSizeOptionClick_, this);
};
ns.SizePicker.prototype.destroy = function () {
pskl.utils.Event.removeAllEventListeners(this);
};
ns.SizePicker.prototype.getSize = function () {
var selectedOption = this.container.querySelector('.selected');
return selectedOption ? selectedOption.dataset.size : null;
};
ns.SizePicker.prototype.setSize = function (size) {
if (this.getSize() === size) {
return;
}
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.classList.add('labeled');
selectedOption.setAttribute('real-size', size);
}
if (selectedOption) {
selectedOption.classList.add('selected');
}
};
ns.SizePicker.prototype.onSizeOptionClick_ = function (e) {
var size = e.target.dataset.size;
if (!isNaN(size)) {
size = parseInt(size, 10);
this.onChange(size);
this.setSize(size);
}
};
})();

View File

@@ -1,57 +0,0 @@
(function () {
var ns = $.namespace('pskl.widgets');
ns.Tabs = function (tabs, parentController, settingsName) {
this.tabs = tabs;
this.parentController = parentController;
this.settingsName = settingsName;
this.currentTab = null;
this.currentController = null;
};
ns.Tabs.prototype.init = function (container) {
this.tabListEl = container.querySelector('.tab-list');
this.tabContentlEl = container.querySelector('.tab-content');
pskl.utils.Event.addEventListener(this.tabListEl, 'click', this.onTabsClicked_, this);
var tab = pskl.UserSettings.get(this.settingsName);
if (tab) {
this.selectTab(tab);
}
};
ns.Tabs.prototype.destroy = function () {
if (this.currentController) {
this.currentController.destroy();
}
pskl.utils.Event.removeAllEventListeners(this);
};
ns.Tabs.prototype.selectTab = function (tabId) {
if (!this.tabs[tabId] || this.currentTab == tabId) {
return;
}
if (this.currentController) {
this.currentController.destroy();
}
this.tabContentlEl.innerHTML = pskl.utils.Template.get(this.tabs[tabId].template);
this.currentController = new this.tabs[tabId].controller(pskl.app.piskelController, this.parentController);
this.currentController.init();
this.currentTab = tabId;
pskl.UserSettings.set(this.settingsName, tabId);
var selectedTab = this.tabListEl.querySelector('.selected');
if (selectedTab) {
selectedTab.classList.remove('selected');
}
this.tabListEl.querySelector('[data-tab-id="' + tabId + '"]').classList.add('selected');
};
ns.Tabs.prototype.onTabsClicked_ = function (e) {
var tabId = pskl.utils.Dom.getData(e.target, 'tabId');
this.selectTab(tabId);
};
})();

View File

@@ -1,107 +0,0 @@
(function () {
var ns = $.namespace('pskl.widgets');
var TRANSITION_DURATION = 200;
/**
* Simple layout widget to display one step element (DOM Element) at a time.
* When switching to another step, the new step element will slide over the
* current step element. When going back to the previous step, the current
* step element will slide out from the container to reveal the previous one.
*
* @param {Object} steps map of step descriptions with the step name as the key.
* Each step description contains:
* - el {Element} the DOM Element corresponding to this step
* - name {String} the name of the step (redundant with the key)
* @param {Element} container the DOM Element in which the wizard should be
* displayed.
*/
ns.Wizard = function (steps, container) {
this.steps = steps;
this.container = container;
// Create internal wrapper that will contain the wizard steps.
this.wrapper = document.createElement('div');
this.wrapper.classList.add('wizard-wrapper');
this.currentStep = null;
this.previousSteps = [];
};
ns.Wizard.prototype.init = function () {
// Prepare all steps and add them in the wrapper.
Object.keys(this.steps).forEach(function (stepName) {
var step = this.steps[stepName];
step.el.classList.add('wizard-step');
this.wrapper.appendChild(step.el);
}.bind(this));
this.container.appendChild(this.wrapper);
};
ns.Wizard.prototype.getStep = function (stepName) {
return this.steps[stepName];
};
ns.Wizard.prototype.getCurrentStep = function () {
return this.currentStep;
};
/**
* Transition to the step cirresponding to the provided step name.
* Animation will be skipped if no current step is displayed.
*/
ns.Wizard.prototype.goTo = function (stepName) {
var step = this.steps[stepName];
if (!step) {
console.error('Wizard could not go to unknown step: ' + stepName);
return;
}
var previousStep = this.currentStep;
this.currentStep = step;
this.currentStep.instance.onShow();
if (previousStep) {
this.previousSteps.push(previousStep);
// Update classes to trigger animation.
this.currentStep.el.classList.add('current-step-in');
window.setTimeout(function () {
// Cleanup transition classes after animation.
this.currentStep.el.classList.remove('current-step-in');
previousStep.el.classList.remove('current-step');
this.currentStep.el.classList.add('current-step');
}.bind(this), TRANSITION_DURATION);
} else {
this.currentStep.el.classList.add('current-step');
}
};
/**
* Go back to the previous step displayed, if available.
*/
ns.Wizard.prototype.back = function () {
var previousStep = this.previousSteps.pop();
if (!previousStep) {
console.error('Wizard has no previous step to go to.');
return;
}
var backedStep = this.currentStep;
if (!backedStep) {
console.error('Wizard is in an invalid state');
}
this.currentStep = previousStep;
// Update classes to trigger animation.
backedStep.el.classList.add('current-step-out');
backedStep.el.classList.remove('current-step');
this.currentStep.el.classList.add('current-step');
window.setTimeout(function () {
// Cleanup transition classes after animation.
backedStep.el.classList.remove('current-step-out');
}.bind(this), TRANSITION_DURATION);
};
})();

View File

@@ -2,9 +2,7 @@
var ns = $.namespace('pskl.worker.imageprocessor'); var ns = $.namespace('pskl.worker.imageprocessor');
ns.ImageProcessorWorker = function () { ns.ImageProcessorWorker = function () {
var currentStep; var currentStep, currentProgress, currentTotal;
var currentProgress;
var currentTotal;
var initStepCounter_ = function (total) { var initStepCounter_ = function (total) {
currentStep = 0; currentStep = 0;

View File

@@ -18,7 +18,6 @@
loadingMask.style.opacity = 0; loadingMask.style.opacity = 0;
window.setTimeout(function () {loadingMask.parentNode.removeChild(loadingMask);}, 600); window.setTimeout(function () {loadingMask.parentNode.removeChild(loadingMask);}, 600);
pskl.app.init(); pskl.app.init();
pskl._releaseVersion = '@@releaseVersion';
// cleanup // cleanup
delete window.pskl_exports; delete window.pskl_exports;
delete window.loadDebugScripts; delete window.loadDebugScripts;

View File

@@ -30,10 +30,8 @@
"js/utils/FrameUtils.js", "js/utils/FrameUtils.js",
"js/utils/ImageResizer.js", "js/utils/ImageResizer.js",
"js/utils/LayerUtils.js", "js/utils/LayerUtils.js",
"js/utils/MergeUtils.js",
"js/utils/PixelUtils.js", "js/utils/PixelUtils.js",
"js/utils/PiskelFileUtils.js", "js/utils/PiskelFileUtils.js",
"js/utils/ResizeUtils.js",
"js/utils/StringUtils.js", "js/utils/StringUtils.js",
"js/utils/Template.js", "js/utils/Template.js",
"js/utils/TooltipFormatter.js", "js/utils/TooltipFormatter.js",
@@ -122,15 +120,13 @@
// Settings sub-controllers // Settings sub-controllers
"js/controller/settings/AbstractSettingController.js", "js/controller/settings/AbstractSettingController.js",
"js/controller/settings/preferences/GridPreferencesController.js", "js/controller/settings/ApplicationSettingsController.js",
"js/controller/settings/preferences/MiscPreferencesController.js",
"js/controller/settings/preferences/TilePreferencesController.js",
"js/controller/settings/PreferencesController.js",
"js/controller/settings/exportimage/GifExportController.js", "js/controller/settings/exportimage/GifExportController.js",
"js/controller/settings/exportimage/PngExportController.js", "js/controller/settings/exportimage/PngExportController.js",
"js/controller/settings/exportimage/ZipExportController.js", "js/controller/settings/exportimage/ZipExportController.js",
"js/controller/settings/exportimage/MiscExportController.js", "js/controller/settings/exportimage/MiscExportController.js",
"js/controller/settings/exportimage/ExportController.js", "js/controller/settings/exportimage/ExportController.js",
"js/controller/settings/resize/AnchorWidget.js",
"js/controller/settings/resize/ResizeController.js", "js/controller/settings/resize/ResizeController.js",
"js/controller/settings/resize/DefaultSizeController.js", "js/controller/settings/resize/DefaultSizeController.js",
"js/controller/settings/SaveController.js", "js/controller/settings/SaveController.js",
@@ -142,14 +138,9 @@
// Dialogs sub-controllers // Dialogs sub-controllers
"js/controller/dialogs/AbstractDialogController.js", "js/controller/dialogs/AbstractDialogController.js",
"js/controller/dialogs/CreatePaletteController.js", "js/controller/dialogs/CreatePaletteController.js",
"js/controller/dialogs/ImportImageController.js",
"js/controller/dialogs/BrowseLocalController.js", "js/controller/dialogs/BrowseLocalController.js",
"js/controller/dialogs/CheatsheetController.js", "js/controller/dialogs/CheatsheetController.js",
"js/controller/dialogs/importwizard/steps/AbstractImportStep.js",
"js/controller/dialogs/importwizard/steps/AdjustSize.js",
"js/controller/dialogs/importwizard/steps/ImageImport.js",
"js/controller/dialogs/importwizard/steps/InsertLocation.js",
"js/controller/dialogs/importwizard/steps/SelectMode.js",
"js/controller/dialogs/importwizard/ImportWizard.js",
"js/controller/dialogs/PerformanceInfoController.js", "js/controller/dialogs/PerformanceInfoController.js",
"js/controller/dialogs/UnsupportedBrowserController.js", "js/controller/dialogs/UnsupportedBrowserController.js",
@@ -157,15 +148,10 @@
"js/controller/dialogs/DialogsController.js", "js/controller/dialogs/DialogsController.js",
// Widgets // Widgets
"js/widgets/AnchorWidget.js",
"js/widgets/ColorsList.js", "js/widgets/ColorsList.js",
"js/widgets/FramePicker.js",
"js/widgets/HslRgbColorPicker.js", "js/widgets/HslRgbColorPicker.js",
"js/widgets/SizeInput.js", "js/widgets/SizeInput.js",
"js/widgets/SizePicker.js",
"js/widgets/SynchronizedInputs.js", "js/widgets/SynchronizedInputs.js",
"js/widgets/Tabs.js",
"js/widgets/Wizard.js",
// Services // Services
"js/service/storage/StorageService.js", "js/service/storage/StorageService.js",
@@ -231,7 +217,6 @@
"js/tools/transform/AbstractTransformTool.js", "js/tools/transform/AbstractTransformTool.js",
"js/tools/transform/Center.js", "js/tools/transform/Center.js",
"js/tools/transform/Clone.js", "js/tools/transform/Clone.js",
"js/tools/transform/Crop.js",
"js/tools/transform/Flip.js", "js/tools/transform/Flip.js",
"js/tools/transform/Rotate.js", "js/tools/transform/Rotate.js",
"js/tools/transform/TransformUtils.js", "js/tools/transform/TransformUtils.js",

View File

@@ -15,13 +15,14 @@
"css/settings-resize.css", "css/settings-resize.css",
"css/settings-save.css", "css/settings-save.css",
"css/tools.css", "css/tools.css",
"css/pensize.css",
"css/icons.css", "css/icons.css",
"css/color-picker-slider.css", "css/color-picker-slider.css",
"css/dialogs.css", "css/dialogs.css",
"css/dialogs-browse-local.css", "css/dialogs-browse-local.css",
"css/dialogs-cheatsheet.css", "css/dialogs-cheatsheet.css",
"css/dialogs-create-palette.css", "css/dialogs-create-palette.css",
"css/dialogs-import.css", "css/dialogs-import-image.css",
"css/dialogs-performance-info.css", "css/dialogs-performance-info.css",
"css/dialogs-unsupported-browser.css", "css/dialogs-unsupported-browser.css",
"css/notifications.css", "css/notifications.css",
@@ -35,10 +36,5 @@
"css/bootstrap/bootstrap.css", "css/bootstrap/bootstrap.css",
"css/bootstrap/bootstrap-tooltip-custom.css", "css/bootstrap/bootstrap-tooltip-custom.css",
"css/frames-list.css", "css/frames-list.css",
"css/minimap.css", "css/minimap.css"
"css/widgets-anchor.css",
"css/widgets-frame-picker.css",
"css/widgets-size-picker.css",
"css/widgets-tabs.css",
"css/widgets-wizard.css"
]; ];

View File

@@ -4,48 +4,16 @@
} }
.fake-piskelapp-header { .fake-piskelapp-header {
position: relative;
text-align: center; text-align: center;
height: 40px; height: 40px;
line-height: 40px; line-height: 40px;
font-size: 24px; font-size: 24px;
background: black; background: black;
color: gold; color: gold;
z-index: 100;
} }
.piskel-name.piskel-name-saving { .piskel-name.piskel-name-saving {
color: red; color: red;
} }
.new-piskel-desktop {
position: absolute;
display: flex;
top: 7px;
right: 7px;
height: 26px;
width: 26px;
border-radius: 3px;
font-size: 22px;
color: black;
background: gold;
text-decoration: none;
align-items: center;
justify-content: center;
}
</style> </style>
<div class="fake-piskelapp-header"> <div class="fake-piskelapp-header"><span class="piskel-name"></span></div>
<a
href="index.html"
target="_blank"
class="new-piskel-desktop button button-primary"
title="Create a new sprite"
rel="tooltip"
data-placement="left"
>+</a>
<span class="piskel-name"></span>
</div>

Some files were not shown because too many files have changed in this diff Show More