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
# nodejs local installs
@@ -15,12 +15,10 @@ cache
# netbeans project folder
nbproject
# vscode workspace folder
.vscode
# git stackdumps
*.stackdump
# diffs
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
var dateFormat = require('dateformat');
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
@@ -83,12 +82,33 @@ module.exports = function(grunt) {
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: [
// Includes
'Gruntfile.js',
'package.json',
'src/js/**/*.js',
// Exludes
// TODO: remove this (for now we still get warnings from the lib folder)
// Excludes
'!src/js/**/lib/**/*.js'
]
},
@@ -174,8 +194,7 @@ module.exports = function(grunt) {
dest: 'dest/tmp/index.html',
options : {
globals : {
'version' : version,
'releaseVersion' : releaseVersion
'version' : version
}
}
}
@@ -217,6 +236,20 @@ module.exports = function(grunt) {
src: ['dest/tmp/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.
win: true,
linux32: true,
linux64: true,
flavor: "normal",
linux64: true
},
src: ['./dest/prod/**/*', "./package.json", "!./dest/desktop/"]
},
@@ -296,18 +328,7 @@ module.exports = function(grunt) {
downloadUrl: 'https://dl.nwjs.io/',
osx64: true,
version : "0.19.4",
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",
build_dir: './dest/desktop/'
},
src: ['./dest/prod/**/*', "./package.json", "!./dest/desktop/"]
}
@@ -316,13 +337,11 @@ module.exports = function(grunt) {
// TEST TASKS
// Run linting
grunt.registerTask('lint', ['eslint', 'leadingIndent:css']);
grunt.registerTask('lint', ['jscs:js', 'leadingIndent:css', 'jshint']);
// Run unit-tests
grunt.registerTask('unit-test', ['karma']);
// Run integration tests
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
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('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('desktop', ['clean:desktop', 'default', 'nwjs:windows']);
grunt.registerTask('desktop-mac', ['clean:desktop', 'default', 'nwjs:macos']);
grunt.registerTask('desktop-mac-old', ['clean:desktop', 'default', 'replace:desktop', 'nwjs:macos_old']);
grunt.registerTask('desktop', ['clean:desktop', 'default', 'replace:desktop', 'nwjs:windows']);
grunt.registerTask('desktop-mac', ['clean:desktop', 'default', 'replace:desktop', 'nwjs:macos']);
// SERVER TASKS
// Start webserver and watch for changes

View File

@@ -1,21 +1,52 @@
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...
It is the editor used in **[piskelapp.com](http://piskelapp.com)**.
[![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/)
<img
src="https://screenletstore.appspot.com/img/95aaa0f0-37a4-11e7-a652-7b8128ce3e3b.png"
title="Piskel editor screenshot"
width="500">
A simple web-based tool for Spriting and Pixel art.
## 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** :
* [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
* (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 ?
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).
* **Development** : Have a look at the [wiki](https://github.com/piskelapp/piskel/wiki) to set up the development environment
* **Issues** : Found a problem when using the application, want to request a feature, [open an issue](https://github.com/juliandescottes/piskel/issues).
* **Participate** : Have a look at the [wiki](https://github.com/juliandescottes/piskel/wiki) to set up the development environment
## License
Copyright 2017 Julian Descottes
Copyright 2016 Julian Descottes
Licensed under the Apache License, Version 2.0 (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
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 PISKELAPP_PATH = path.resolve(__dirname, '../../piskel-website');
var pjson = require('../package.json');
// Callbacks sorted by call sequence.
function onCopy(err) {
if (err) {
@@ -54,17 +52,6 @@ function onDeleteTempPartial(err) {
}
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!');
}

View File

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

View File

@@ -3,19 +3,6 @@
/* 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 {
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;
}
#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 {
height: 100%;
position : relative;

View File

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

View File

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

View File

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

View File

@@ -1,14 +1,6 @@
/********************************/
/* Preferences Settings panel */
/********************************/
.settings-section-preferences {
height: 100%;
position: relative;
overflow: hidden;
margin: 0 20px;
height: 100%;
}
/*******************************/
/* Application Setting panel */
/*******************************/
.background-picker-wrapper {
display: inline-block;
@@ -43,11 +35,14 @@
vertical-align: middle;
}
.layer-opacity-input,
.tile-mask-opacity-input {
.layer-opacity-input {
width: 100px;
}
.seamless-opacity-input {
width: 75px;
}
.settings-opacity-text {
height: 31px;
display: inline-block;
@@ -59,76 +54,16 @@
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,
.color-format-select {
margin: 5px 5px 0 5px;
}
.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 {
.settings-section-application > .settings-title {
/* Override the default 10px margin bottom for this panel */
margin-bottom: 15px;
}
.settings-section-preferences .button-primary {
.settings-section-application .button-primary {
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;
}
.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 {
padding: 10px 5px 0px;
}

View File

@@ -5,8 +5,103 @@
width: 25%;
}
.resize-anchor-container {
/*****************/
/* ANCHOR WIDGET */
/*****************/
.resize-origin-container {
overflow: hidden;
position: relative;
width: 70px;
margin-top: 5px;
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;
}
.hidden {
display: none;
}
/**
* TOOLTIPS
*/

View File

@@ -76,11 +76,6 @@
position: relative;
}
.palettes-list-colors.tiny > .palettes-list-color {
width: calc((100% - 35px) / 10);
height: 16px;
}
.palettes-list-color div {
height: 100%;
}
@@ -126,8 +121,7 @@
* Color index for the 9 first colors
*/
:not(.tiny) > .palettes-list-color:nth-child(-n+10):after {
content: attr(data-color-index);
.palettes-list-color:nth-child(-n+10):after {
position: absolute;
top: 0;
right: 0;
@@ -142,3 +136,39 @@
padding: 2px 3px 2px 3px;
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 {
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;">
<span style="top:45%">Loading Piskel ...</span>
</div>
<!--standalone-start-->
@@include('templates/debug-header.html', {})
<!--standalone-end-->
<!-- the comment below indicates the beginning of markup reused by the editor integrated in piskelapp.com -->
<!-- do not delete, do not move :) -->
@@ -76,17 +78,14 @@
<!-- dialogs partials -->
@@include('templates/dialogs/create-palette.html', {})
@@include('templates/dialogs/import-image.html', {})
@@include('templates/dialogs/browse-local.html', {})
@@include('templates/dialogs/cheatsheet.html', {})
@@include('templates/dialogs/import.html', {})
@@include('templates/dialogs/performance-info.html', {})
@@include('templates/dialogs/unsupported-browser.html', {})
<!-- settings-panel partials -->
@@include('templates/settings/preferences.html', {})
@@include('templates/settings/preferences/grid.html', {})
@@include('templates/settings/preferences/misc.html', {})
@@include('templates/settings/preferences/tile.html', {})
@@include('templates/settings/application.html', {})
@@include('templates/settings/resize.html', {})
@@include('templates/settings/save.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_END : 'DRAG_END',
DIALOG_SHOW : 'DIALOG_SHOW',
DIALOG_DISPLAY : 'DIALOG_DISPLAY',
DIALOG_HIDE : 'DIALOG_HIDE',
PALETTE_LIST_UPDATED : 'PALETTE_LIST_UPDATED',

View File

@@ -10,9 +10,6 @@
ns.app = {
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
*/
@@ -190,8 +187,8 @@
gui.Window.get().menu = mb;
}
if (!pskl.utils.Environment.isIntegrationTest() && pskl.utils.UserAgent.isUnsupported()) {
$.publish(Events.DIALOG_SHOW, {
if (pskl.utils.UserAgent.isUnsupported()) {
$.publish(Events.DIALOG_DISPLAY, {
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.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.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 () {
this.afterWindowResize_();
@@ -266,29 +262,6 @@
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.
*

View File

@@ -17,7 +17,6 @@
this.rootEl.addEventListener('click', this.onClick_.bind(this));
this.toggleLayerPreviewEl.addEventListener('click', this.toggleLayerPreview_.bind(this));
this.createButtonTooltips_();
this.initToggleLayerPreview_();
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 () {
var descriptors = [{description : 'Opacity defined in PREFERENCES'}];
var helpText = 'Preview all layers';
@@ -138,7 +117,7 @@
var el = evt.target || evt.srcElement;
var index;
if (el.classList.contains('button')) {
this.onButtonClick_(el, evt);
this.onButtonClick_(el);
} else if (el.classList.contains('layer-name')) {
index = pskl.utils.Dom.getData(el, 'layerIndex');
this.piskelController.setCurrentLayerIndex(parseInt(index, 10));
@@ -166,18 +145,14 @@
this.renderLayerList_();
};
ns.LayersListController.prototype.onButtonClick_ = function (button, evt) {
ns.LayersListController.prototype.onButtonClick_ = function (button) {
var action = button.getAttribute('data-action');
if (action == 'up') {
this.piskelController.moveLayerUp(evt.shiftKey);
this.piskelController.moveLayerUp();
} else if (action == 'down') {
this.piskelController.moveLayerDown(evt.shiftKey);
this.piskelController.moveLayerDown();
} else if (action == 'add') {
if (evt.shiftKey) {
this.piskelController.duplicateCurrentLayer();
} else {
this.piskelController.createLayer();
}
this.piskelController.createLayer();
} else if (action == 'delete') {
this.piskelController.removeCurrentLayer();
} else if (action == 'merge') {

View File

@@ -51,17 +51,12 @@
};
ns.PalettesListController.prototype.fillColorListContainer = function () {
var colors = this.getSelectedPaletteColors_();
if (colors.length > 0) {
var html = colors.filter(function (color) {
return !!color;
}).map(function (color, index) {
return pskl.utils.Template.replace(this.paletteColorTemplate_, {
color : color,
index : index + 1,
title : color.toUpperCase()
});
var html = colors.map(function (color, index) {
return pskl.utils.Template.replace(this.paletteColorTemplate_, {color : color, index : index});
}.bind(this)).join('');
this.colorListContainer_.innerHTML = html;
@@ -69,10 +64,6 @@
} else {
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) {
@@ -110,7 +101,7 @@
var currentIndex = 0;
var selectedColor = document.querySelector('.' + PRIMARY_COLOR_CLASSNAME);
if (selectedColor) {
currentIndex = parseInt(selectedColor.dataset.colorIndex, 10) - 1;
currentIndex = parseInt(selectedColor.dataset.colorIndex, 10);
}
return currentIndex;
};
@@ -148,14 +139,14 @@
};
ns.PalettesListController.prototype.onCreatePaletteClick_ = function (evt) {
$.publish(Events.DIALOG_SHOW, {
$.publish(Events.DIALOG_DISPLAY, {
dialogId : 'create-palette'
});
};
ns.PalettesListController.prototype.onEditPaletteClick_ = function (evt) {
var paletteId = this.colorPaletteSelect_.value;
$.publish(Events.DIALOG_SHOW, {
$.publish(Events.DIALOG_DISPLAY, {
dialogId : 'create-palette',
initArgs : paletteId
});

View File

@@ -1,19 +1,23 @@
(function () {
var ns = $.namespace('pskl.controller');
ns.PenSizeController = function () {
this.sizePicker = new pskl.widgets.SizePicker(this.onSizePickerChanged_.bind(this));
};
ns.PenSizeController = 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));
this.updateSelectedOption_();
};
ns.PenSizeController.prototype.onSizePickerChanged_ = function (size) {
pskl.app.penSizeService.setPenSize(size);
ns.PenSizeController.prototype.onPenSizeOptionClick_ = function (e) {
var size = e.target.dataset.size;
if (!isNaN(size)) {
size = parseInt(size, 10);
pskl.app.penSizeService.setPenSize(size);
}
};
ns.PenSizeController.prototype.onPenSizeChanged_ = function (e) {
@@ -21,7 +25,19 @@
};
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();
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 () {
var ns = $.namespace('pskl.controller');
var SHOW_MORE_CLASS = 'show-more';
ns.TransformationsController = function () {
this.tools = [
new pskl.tools.transform.Flip(),
new pskl.tools.transform.Rotate(),
new pskl.tools.transform.Clone(),
new pskl.tools.transform.Center(),
new pskl.tools.transform.Crop(),
new pskl.tools.transform.Center()
];
this.toolIconBuilder = new pskl.tools.ToolIconBuilder();
};
ns.TransformationsController.prototype.init = function () {
this.container = document.querySelector('.transformations-container');
this.container.addEventListener('click', this.onTransformationClick_.bind(this));
this.showMoreLink = this.container.querySelector('.transformations-show-more-link');
this.showMoreLink.addEventListener('click', this.toggleShowMoreTools_.bind(this));
var container = document.querySelector('.transformations-container');
this.toolsContainer = container.querySelector('.tools-wrapper');
container.addEventListener('click', this.onTransformationClick_.bind(this));
this.createToolsDom_();
this.updateShowMoreLink_();
$.subscribe(Events.USER_SETTINGS_CHANGED, this.onUserSettingsChange_.bind(this));
};
ns.TransformationsController.prototype.applyTool = function (toolId, evt) {
@@ -38,35 +30,13 @@
ns.TransformationsController.prototype.onTransformationClick_ = function (evt) {
var toolId = evt.target.dataset.toolId;
if (toolId) {
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);
this.applyTool(toolId, evt);
};
ns.TransformationsController.prototype.createToolsDom_ = function() {
var html = this.tools.reduce(function (p, tool) {
return p + this.toolIconBuilder.createIcon(tool, 'left');
}.bind(this), '');
var toolsContainer = this.container.querySelector('.tools-wrapper');
toolsContainer.innerHTML = html;
this.toolsContainer.innerHTML = html;
};
})();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -14,9 +14,9 @@
template : 'templates/dialogs/browse-local.html',
controller : ns.BrowseLocalController
},
'import' : {
template : 'templates/dialogs/import.html',
controller : ns.importwizard.ImportWizard
'import-image' : {
template : 'templates/dialogs/import-image.html',
controller : ns.ImportImageController
},
'performance-info' : {
template : 'templates/dialogs/performance-info.html',
@@ -38,7 +38,7 @@
this.dialogContainer_ = document.getElementById('dialog-container');
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));
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
this.dialogWrapper_.classList.add('animated');
pskl.utils.Event.addEventListener(this.dialogWrapper_, 'click', this.onWrapperClicked_, this);
};
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
* @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
* @param {Boolean} preserveState if true, keep the selected frame and layer
*/
ns.PiskelController.prototype.setPiskel = function (piskel, options) {
ns.PiskelController.prototype.setPiskel = function (piskel, preserveState) {
this.piskel = piskel;
options = options || {};
if (!options.preserveState) {
if (!preserveState) {
this.currentLayerIndex = 0;
this.currentFrameIndex = 0;
}
@@ -159,7 +155,8 @@
};
ns.PiskelController.prototype.getFrameCount = function () {
return this.piskel.getFrameCount();
var layer = this.piskel.getLayerAt(0);
return layer.size();
};
ns.PiskelController.prototype.setCurrentFrameIndex = function (index) {
@@ -234,14 +231,6 @@
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) {
if (!name) {
name = this.generateLayerName_();
@@ -251,9 +240,9 @@
for (var i = 0 ; i < this.getFrameCount() ; i++) {
layer.addFrame(this.createEmptyFrame_());
}
var currentLayerIndex = this.getCurrentLayerIndex();
this.piskel.addLayerAt(layer, currentLayerIndex + 1);
this.setCurrentLayerIndex(currentLayerIndex + 1);
this.piskel.addLayer(layer);
this.setCurrentLayerIndex(this.piskel.getLayers().length - 1);
} else {
throw 'Layer name should be unique';
}
@@ -263,15 +252,15 @@
return this.piskel.getLayersByName(name).length > 0;
};
ns.PiskelController.prototype.moveLayerUp = function (toTop) {
ns.PiskelController.prototype.moveLayerUp = function () {
var layer = this.getCurrentLayer();
this.piskel.moveLayerUp(layer, toTop);
this.piskel.moveLayerUp(layer);
this.selectLayer(layer);
};
ns.PiskelController.prototype.moveLayerDown = function (toBottom) {
ns.PiskelController.prototype.moveLayerDown = function () {
var layer = this.getCurrentLayer();
this.piskel.moveLayerDown(layer, toBottom);
this.piskel.moveLayerDown(layer);
this.selectLayer(layer);
};

View File

@@ -31,7 +31,6 @@
this.saveWrap_('duplicateFrameAt', true);
this.saveWrap_('moveFrame', true);
this.saveWrap_('createLayer', true);
this.saveWrap_('duplicateCurrentLayer', true);
this.saveWrap_('mergeDownLayerAt', true);
this.saveWrap_('moveLayerUp', true);
this.saveWrap_('moveLayerDown', true);
@@ -49,25 +48,14 @@
return this.piskelController;
};
/**
* Set the current piskel. Will reset the selected frame and layer unless specified
* @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);
ns.PublicPiskelController.prototype.setPiskel = function (piskel, preserveState) {
this.piskelController.setPiskel(piskel, preserveState);
$.publish(Events.FRAME_SIZE_CHANGED);
$.publish(Events.PISKEL_RESET);
if (!options || !options.noSnapshot) {
$.publish(Events.PISKEL_SAVE_STATE, {
type : pskl.service.HistoryService.SNAPSHOT
});
}
$.publish(Events.PISKEL_SAVE_STATE, {
type : pskl.service.HistoryService.SNAPSHOT
});
};
ns.PublicPiskelController.prototype.resetWrap_ = function (methodName) {

View File

@@ -102,7 +102,7 @@
this.disablePreviewSizeWidget_('No other option available');
validSizes = ['original'];
} else if (seamlessModeEnabled) {
this.disablePreviewSizeWidget_('Disabled in tile mode');
this.disablePreviewSizeWidget_('Disabled in seamless mode');
validSizes = ['original'];
} else {
this.enablePreviewSizeWidget_();
@@ -309,8 +309,7 @@
var isSeamless = pskl.UserSettings.get(pskl.UserSettings.SEAMLESS_MODE);
this.renderer.setRepeated(isSeamless);
var width;
var height;
var height, width;
if (isSeamless) {
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) {
$.publish(Events.DIALOG_SHOW, {
$.publish(Events.DIALOG_DISPLAY, {
dialogId : 'browse-local'
});
this.closeDrawer_();
@@ -79,39 +79,40 @@
ns.ImportController.prototype.openPiskelFile_ = function (file) {
if (this.isPiskel_(file)) {
$.publish(Events.DIALOG_SHOW, {
dialogId : 'import',
initArgs : {
rawFiles: [file]
}
});
pskl.utils.PiskelFileUtils.loadFromFile(file,
// onSuccess
function (piskel) {
pskl.app.piskelController.setPiskel(piskel);
},
// onError
function (reason) {
$.publish(Events.PISKEL_FILE_IMPORT_FAILED, [reason]);
});
this.closeDrawer_();
} else {
this.closeDrawer_();
console.error('The selected file is not a piskel file');
}
};
ns.ImportController.prototype.importPictureFromFile_ = function () {
var files = this.hiddenFileInput.files;
// TODO : Simply filter and remove stuff
var areImages = Array.prototype.every.call(files, function (file) {
return file.type.indexOf('image') === 0;
});
if (areImages) {
$.publish(Events.DIALOG_SHOW, {
dialogId : 'import',
initArgs : {
rawFiles: files
}
});
this.closeDrawer_();
} else {
this.closeDrawer_();
console.error('Some files are not images');
if (files.length == 1) {
var file = files[0];
if (this.isImage_(file)) {
$.publish(Events.DIALOG_DISPLAY, {
dialogId : 'import-image',
initArgs : file
});
this.closeDrawer_();
} else {
this.closeDrawer_();
console.error('File is not an image : ' + file.type);
}
}
};
ns.ImportController.prototype.isImage_ = function (file) {
return file.type.indexOf('image') === 0;
};
ns.ImportController.prototype.isPiskel_ = function (file) {
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 = {
'user' : {
template : 'templates/settings/preferences.html',
controller : ns.PreferencesController
template : 'templates/settings/application.html',
controller : ns.ApplicationSettingsController
},
'resize' : {
template : 'templates/settings/resize.html',

View File

@@ -22,7 +22,6 @@
ns.ExportController = function (piskelController) {
this.piskelController = piskelController;
this.tabsWidget = new pskl.widgets.Tabs(tabs, this, pskl.UserSettings.EXPORT_TAB);
this.onSizeInputChange_ = this.onSizeInputChange_.bind(this);
};
@@ -48,16 +47,47 @@
this.onSizeInputChange_();
// Initialize tabs and panel
var container = document.querySelector('.settings-section-export');
this.tabsWidget.init(container);
this.exportPanel = document.querySelector('.export-panel');
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 () {
this.sizeInputWidget.destroy();
this.tabsWidget.destroy();
this.currentController.destroy();
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 () {
var value = parseFloat(this.scaleInput.value);
if (!isNaN(value)) {

View File

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

View File

@@ -190,7 +190,7 @@
var json = {
'frames': frames,
'meta': {
'app': 'https://github.com/piskelapp/piskel/',
'app': 'https://github.com/juliandescottes/piskel/',
'version': '1.0',
'image': name + '.png',
'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 () {
var ns = $.namespace('pskl.widgets');
var ns = $.namespace('pskl.controller.settings.resize');
var OPTION_CLASSNAME = 'anchor-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);
var OPTION_CLASSNAME = 'resize-origin-option';
ns.AnchorWidget = function (container) {
this.container = container;
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 = {
@@ -42,7 +23,7 @@
ns.AnchorWidget.prototype.destroy = function (evt) {
pskl.utils.Event.removeAllEventListeners(this);
this.wrapper = null;
this.container = null;
};
ns.AnchorWidget.prototype.onResizeOriginClick_ = function (evt) {
@@ -54,20 +35,16 @@
ns.AnchorWidget.prototype.setOrigin = function (origin) {
this.origin = origin;
var previous = this.wrapper.querySelector('.' + OPTION_CLASSNAME + '.selected');
var previous = document.querySelector('.' + OPTION_CLASSNAME + '.selected');
if (previous) {
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) {
selected.classList.add('selected');
this.refreshNeighbors_(selected);
}
if (typeof this.onChangeCallback === 'function') {
this.onChangeCallback(origin);
}
};
ns.AnchorWidget.prototype.getOrigin = function () {
@@ -76,18 +53,18 @@
ns.AnchorWidget.prototype.disable = function () {
this.disabled = true;
this.wrapper.classList.add('transition');
this.wrapper.classList.add('disabled');
this.container.classList.add('transition');
this.container.classList.add('disabled');
};
ns.AnchorWidget.prototype.enable = function () {
this.disabled = false;
this.wrapper.classList.remove('disabled');
window.setTimeout(this.wrapper.classList.remove.bind(this.wrapper.classList, 'transition'), 250);
this.container.classList.remove('disabled');
window.setTimeout(this.container.classList.remove.bind(this.container.classList, 'transition'), 250);
};
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++) {
options[i].removeAttribute('data-neighbor');
}

View File

@@ -6,8 +6,8 @@
this.container = document.querySelector('.resize-canvas');
var anchorWidgetContainer = this.container.querySelector('.resize-anchor-container');
this.anchorWidget = new pskl.widgets.AnchorWidget(anchorWidgetContainer);
var anchorWidgetContainer = this.container.querySelector('.resize-origin-container');
this.anchorWidget = new ns.AnchorWidget(anchorWidgetContainer);
this.defaultSizeController = new ns.DefaultSizeController(piskelController);
};
@@ -28,7 +28,7 @@
});
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);
if (settings.resizeContent) {
@@ -61,21 +61,27 @@
ns.ResizeController.prototype.onResizeFormSubmit_ = function (evt) {
evt.preventDefault();
var currentPiskel = this.piskelController.getPiskel();
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
});
var resizedLayers = this.piskelController.getLayers().map(this.resizeLayer_.bind(this));
pskl.app.piskelController.setPiskel(piskel, {
preserveState: true
});
var currentPiskel = this.piskelController.getPiskel();
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);
};
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) {
var target = evt.target;
if (target.checked) {
@@ -101,4 +107,55 @@
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,
shiftKey : domEvent.shiftKey,
altKey : domEvent.altKey,
ctrlKey : domEvent.ctrlKey || domEvent.metaKey,
ctrlKey : domEvent.ctrlKey,
target : {
nodeName : domEvent.target.nodeName
}
@@ -142,12 +142,6 @@
recordEvent.type = 'instrumented-event';
recordEvent.methodName = methodName;
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);
}
};

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) {
this.layers.push(layer);
};
@@ -82,28 +78,20 @@
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 toIndex = toTop ? this.layers.length - 1 : index + 1;
this.moveLayer_(index, toIndex);
};
ns.Piskel.prototype.moveLayerDown = function (layer, toBottom) {
var index = this.layers.indexOf(layer);
var toIndex = toBottom ? 0 : index - 1;
this.moveLayer_(index, toIndex);
};
/**
* 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;
if (index > -1 && index < this.layers.length - 1) {
this.layers[index] = this.layers[index + 1];
this.layers[index + 1] = layer;
}
};
ns.Piskel.prototype.moveLayerDown = function (layer) {
var index = this.layers.indexOf(layer);
if (index > 0) {
this.layers[index] = this.layers[index - 1];
this.layers[index - 1] = layer;
}
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) {

View File

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

View File

@@ -55,7 +55,7 @@
this.displayCanvas = null;
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));
};
@@ -138,10 +138,6 @@
this.offset.y = y;
};
ns.FrameRenderer.prototype.getGridColor = function () {
return pskl.UserSettings.get(pskl.UserSettings.GRID_COLOR);
};
ns.FrameRenderer.prototype.setGridWidth = function (value) {
this.gridWidth_ = value;
};
@@ -184,18 +180,11 @@
};
ns.FrameRenderer.prototype.onUserSettingsChange_ = function (evt, settingName, settingValue) {
var settings = pskl.UserSettings;
if (settingName == settings.GRID_WIDTH || settingName == settings.GRID_ENABLED) {
this.setGridWidth(this.getUserGridWidth_());
if (settingName == pskl.UserSettings.GRID_WIDTH) {
this.setGridWidth(settingValue);
}
};
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
* frame) into a sprite coordinate in column and row.
@@ -263,24 +252,14 @@
var displayContext = this.displayCanvas.getContext('2d');
displayContext.save();
var translateX = this.margin.x - this.offset.x * z;
var translateY = this.margin.y - this.offset.y * z;
// Draw background
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;
// Draw the background / zoomed-out color only if needed. Otherwise the clearRect
// happening after that will clear "out of bounds" and seems to be doing nothing
// 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);
displayContext.translate(
this.margin.x - this.offset.x * z,
this.margin.y - this.offset.y * z
);
// Scale up to draw the canvas content
displayContext.scale(z, z);
@@ -299,25 +278,15 @@
// Draw grid.
var gridWidth = this.computeGridWidthForDisplay_();
if (gridWidth > 0) {
var gridColor = this.getGridColor();
// Scale out before drawing the grid.
displayContext.scale(1 / z, 1 / z);
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.
// Clear vertical lines.
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++) {
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) {
pskl.app.backupService.backup();
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;
if (evt) {

View File

@@ -35,13 +35,7 @@
var isPiskel = /\.piskel$/i.test(file.name);
var isPalette = /\.(gpl|txt|pal)$/i.test(file.name);
if (isImage) {
$.publish(Events.DIALOG_SHOW, {
dialogId : 'import',
initArgs : {
rawFiles: [file]
}
});
// pskl.utils.FileUtils.readImageFile(file, this.onImageLoaded_.bind(this));
this.readImageFile_(file);
} else if (isPiskel) {
pskl.utils.PiskelFileUtils.loadFromFile(file, this.onPiskelFileLoaded_, this.onPiskelFileError_);
} 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) {
pskl.app.paletteService.savePalette(palette);
pskl.UserSettings.set(pskl.UserSettings.SELECTED_PALETTE, palette.id);
@@ -65,6 +63,12 @@
$.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) {
if (this.isMultipleFiles_) {
this.piskelController.addFrameAtCurrentIndex();

View File

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

View File

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

View File

@@ -60,12 +60,7 @@
FULL_PREVIEW : createShortcut('full-preview', 'Select full size preview', 'alt+3'),
ONION_SKIN : createShortcut('onion-skin', 'Toggle onion skin', 'alt+O'),
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'),
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'),
CLOSE_POPUP : createShortcut('close-popup', 'Close an opened popup', 'ESC')
},
STORAGE : {

View File

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

View File

@@ -97,31 +97,8 @@
linePixels = pskl.PixelUtils.getLinePixels(col, this.startCol, row, this.startRow);
}
//draw the square ends of the line
pskl.PixelUtils.resizePixel(linePixels[0].col, linePixels[0].row, penSize)
.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
);
}
}
pskl.PixelUtils.resizePixels(linePixels, penSize).forEach(function (point) {
targetFrame.setPixel(point[0], point[1], 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;
},
getBoundaries : function(frames) {
var minx = +Infinity;
var miny = +Infinity;
center : function(frame) {
// Figure out the boundary
var minx = frame.width;
var miny = frame.height;
var maxx = 0;
var maxy = 0;
var transparentColorInt = pskl.utils.colorToInt(Constants.TRANSPARENT_COLOR);
frames.forEach(function (frame) {
frame.forEachPixel(function (color, x, y) {
if (color !== transparentColorInt) {
minx = Math.min(minx, x);
maxx = Math.max(maxx, x);
miny = Math.min(miny, y);
maxy = Math.max(maxy, y);
}
});
frame.forEachPixel(function (color, x, y) {
if (color !== transparentColorInt) {
minx = Math.min(minx, x);
maxx = Math.max(maxx, x);
miny = Math.min(miny, y);
maxy = Math.max(maxy, y);
}
});
return {
minx: minx,
maxx: maxx,
miny: miny,
maxy: maxy,
};
},
// Calculate how much to move the pixels
var bw = (maxx - minx + 1) / 2;
var bh = (maxy - miny + 1) / 2;
var fw = frame.width / 2;
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();
frame.forEachPixel(function(color, x, y) {
var _x = x;
@@ -106,24 +104,7 @@
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;
}
};

View File

@@ -19,10 +19,6 @@
}
}
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.
*/
throttle : function (fn, interval) {
var last;
var timer;
var last, timer;
return function () {
var now = Date.now();
if (last && now < last + interval) {

View File

@@ -2,13 +2,6 @@
var ns = $.namespace('pskl.utils');
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) {
var framesA = layerA.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 cellCount = frame.getWidth() * frame.getHeight();
while (queue.length > 0) {
loopCount++;
loopCount ++;
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);
return (padding + input).slice(-length);
},
formatSize : function (width, height) {
return width + '\u00D7' + height;
}
};
})();

View File

@@ -15,23 +15,11 @@
return templates[templateId];
},
getAsHTML : function (templateId) {
var template = ns.Template.get(templateId);
if (!template) {
return;
}
return ns.Template.createFromHTML(template);
},
createFromHTML : function (html) {
var dummyEl = ns.Template._getDummyEl();
dummyEl.innerHTML = html;
var element = dummyEl.children[0];
if (!pskl.utils.UserAgent.isIE11) {
dummyEl.innerHTML = '';
}
dummyEl.innerHTML = '';
return element;
},
@@ -62,15 +50,6 @@
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.
*/
@@ -81,24 +60,16 @@
dummyEl.textContent = string;
var sanitizedString = dummyEl.innerHTML;
if (!pskl.utils.UserAgent.isIE11) {
dummyEl.innerHTML = '';
}
dummyEl.innerHTML = '';
return sanitizedString;
},
_getDummyEl : pskl.utils.UserAgent.isIE11 ?
// IE11 specific implementation
function () {
return document.createElement('div');
} :
// Normal, sane browsers implementation.
function () {
if (!ns.Template._dummyEl) {
ns.Template._dummyEl = document.createElement('div');
}
return ns.Template._dummyEl;
_getDummyEl : function () {
if (!ns.Template._dummyEl) {
ns.Template._dummyEl = document.createElement('div');
}
return ns.Template._dummyEl;
}
};
})();

View File

@@ -2,8 +2,6 @@
var ns = $.namespace('pskl');
ns.UserSettings = {
GRID_COLOR : 'GRID_COLOR',
GRID_ENABLED : 'GRID_ENABLED',
GRID_WIDTH : 'GRID_WIDTH',
MAX_FPS : 'MAX_FPS',
DEFAULT_SIZE : 'DEFAULT_SIZE',
@@ -20,12 +18,8 @@
PEN_SIZE : 'PEN_SIZE',
RESIZE_SETTINGS: 'RESIZE_SETTINGS',
COLOR_FORMAT: 'COLOR_FORMAT',
TRANSFORM_SHOW_MORE: 'TRANSFORM_SHOW_MORE',
PREFERENCES_TAB: 'PREFERENCES_TAB',
KEY_TO_DEFAULT_VALUE_MAP_ : {
'GRID_COLOR' : Constants.TRANSPARENT_COLOR,
'GRID_ENABLED' : false,
'GRID_WIDTH' : 1,
'GRID_WIDTH' : 0,
'MAX_FPS' : 24,
'DEFAULT_SIZE' : {
width : Constants.DEFAULT.WIDTH,
@@ -48,8 +42,6 @@
origin : 'TOPLEFT'
},
COLOR_FORMAT: 'hex',
TRANSFORM_SHOW_MORE: false,
PREFERENCES_TAB: 'misc',
},
/**
@@ -85,7 +77,7 @@
/**
* @private
*/
readFromLocalStorage_ : function (key) {
readFromLocalStorage_ : function(key) {
var value = window.localStorage[key];
if (typeof value != 'undefined') {
value = JSON.parse(value);
@@ -96,7 +88,7 @@
/**
* @private
*/
writeToLocalStorage_ : function (key, value) {
writeToLocalStorage_ : function(key, value) {
// TODO(grosbouddha): Catch storage exception here.
window.localStorage[key] = JSON.stringify(value);
},
@@ -111,7 +103,7 @@
/**
* @private
*/
checkKeyValidity_ : function (key) {
checkKeyValidity_ : function(key) {
if (key.indexOf(pskl.service.keyboard.Shortcut.USER_SETTINGS_PREFIX) === 0) {
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 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 () {
var piskelData = this.data_.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) {
var layer = this.deserializeLayer(serializedLayer);

View File

@@ -17,7 +17,7 @@
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');
this.hslRgbColorPicker = new pskl.widgets.HslRgbColorPicker(colorPickerContainer, this.onColorUpdated_.bind(this));
@@ -40,10 +40,6 @@
};
ns.ColorsList.prototype.destroy = function () {
pskl.utils.Event.removeAllEventListeners(this);
$(this.container).sortable('destroy');
this.hslRgbColorPicker.destroy();
this.container = 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 changeEvent = (isChrome || isFirefox) ? 'input' : 'change';
pskl.utils.Event.addEventListener(this.container, changeEvent, this.onPickerChange_, this);
pskl.utils.Event.addEventListener(this.container, 'keydown', this.onPickerChange_, this);
// Cannot use pskl.utils.Event with useCapture for now ...
this.onBlur_ = this.onBlur_.bind(this);
this.container.addEventListener('blur', this.onBlur_, true);
this.container.addEventListener(changeEvent, this.onPickerChange_.bind(this));
this.container.addEventListener('keydown', this.onKeydown_.bind(this));
this.container.addEventListener('blur', this.onBlur_.bind(this), true);
this.spectrumEl = this.container.querySelector('.color-picker-spectrum');
@@ -37,13 +34,6 @@
};
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.spectrumEl = null;
};
@@ -227,8 +217,7 @@
var dimension = slider.dataset.dimension;
var model = slider.dataset.model;
var start;
var end;
var start, end;
var isHueSlider = dimension === 'h';
if (!isHueSlider) {
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');
ns.ImageProcessorWorker = function () {
var currentStep;
var currentProgress;
var currentTotal;
var currentStep, currentProgress, currentTotal;
var initStepCounter_ = function (total) {
currentStep = 0;

View File

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

View File

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

View File

@@ -15,13 +15,14 @@
"css/settings-resize.css",
"css/settings-save.css",
"css/tools.css",
"css/pensize.css",
"css/icons.css",
"css/color-picker-slider.css",
"css/dialogs.css",
"css/dialogs-browse-local.css",
"css/dialogs-cheatsheet.css",
"css/dialogs-create-palette.css",
"css/dialogs-import.css",
"css/dialogs-import-image.css",
"css/dialogs-performance-info.css",
"css/dialogs-unsupported-browser.css",
"css/notifications.css",
@@ -35,10 +36,5 @@
"css/bootstrap/bootstrap.css",
"css/bootstrap/bootstrap-tooltip-custom.css",
"css/frames-list.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"
"css/minimap.css"
];

View File

@@ -4,48 +4,16 @@
}
.fake-piskelapp-header {
position: relative;
text-align: center;
height: 40px;
line-height: 40px;
font-size: 24px;
background: black;
color: gold;
z-index: 100;
}
.piskel-name.piskel-name-saving {
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>
<div class="fake-piskelapp-header">
<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>
<div class="fake-piskelapp-header"><span class="piskel-name"></span></div>

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