mirror of
https://github.com/piskelapp/piskel.git
synced 2023-08-10 21:12:52 +03:00
Compare commits
2 Commits
v0.11.1
...
greenkeepe
Author | SHA1 | Date | |
---|---|---|---|
5e46d8b7e2 | |||
e15d7b2422 |
21
Gruntfile.js
21
Gruntfile.js
@ -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
|
||||
@ -195,8 +194,7 @@ module.exports = function(grunt) {
|
||||
dest: 'dest/tmp/index.html',
|
||||
options : {
|
||||
globals : {
|
||||
'version' : version,
|
||||
'releaseVersion' : releaseVersion
|
||||
'version' : version
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -321,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/"]
|
||||
},
|
||||
@ -331,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/"]
|
||||
}
|
||||
@ -372,7 +358,6 @@ module.exports = function(grunt) {
|
||||
grunt.registerTask('build-dev', ['clean:dev', 'sprite', 'build-index.html', 'copy:dev']);
|
||||
grunt.registerTask('desktop', ['clean:desktop', 'default', 'replace:desktop', 'nwjs:windows']);
|
||||
grunt.registerTask('desktop-mac', ['clean:desktop', 'default', 'replace:desktop', 'nwjs:macos']);
|
||||
grunt.registerTask('desktop-mac-old', ['clean:desktop', 'default', 'replace:desktop', 'nwjs:macos_old']);
|
||||
|
||||
// SERVER TASKS
|
||||
// Start webserver and watch for changes
|
||||
|
@ -1,6 +1,8 @@
|
||||
Piskel
|
||||
======
|
||||
|
||||
[](https://greenkeeper.io/)
|
||||
|
||||
[](https://travis-ci.org/juliandescottes/piskel) [](http://gruntjs.com/)
|
||||
|
||||
A simple web-based tool for Spriting and Pixel art.
|
||||
|
@ -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!');
|
||||
}
|
||||
|
||||
|
16
package.json
16
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "piskel",
|
||||
"version": "0.11.1",
|
||||
"version": "0.10.0",
|
||||
"description": "Pixel art editor",
|
||||
"author": "Julian Descottes <julian.descottes@gmail.com>",
|
||||
"contributors": [
|
||||
@ -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,9 +38,9 @@
|
||||
"grunt-contrib-jshint": "1.1.0",
|
||||
"grunt-contrib-uglify": "2.3.0",
|
||||
"grunt-contrib-watch": "1.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",
|
||||
@ -49,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",
|
||||
|
@ -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%;
|
||||
}
|
||||
|
101
src/css/dialogs-import-image.css
Normal file
101
src/css/dialogs-import-image.css
Normal 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;
|
||||
}
|
292
src/css/dialogs-import.css
vendored
292
src/css/dialogs-import.css
vendored
@ -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;
|
||||
}
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -1,16 +1,6 @@
|
||||
/*******************************/
|
||||
/* Application Setting panel */
|
||||
/*******************************/
|
||||
.application-settings-form {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.settings-section-application {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
margin: 0 20px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.background-picker-wrapper {
|
||||
display: inline-block;
|
||||
@ -77,18 +67,3 @@
|
||||
.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;
|
||||
}
|
@ -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
113
src/css/sprites.css
Normal 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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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%;
|
||||
}
|
@ -78,9 +78,9 @@
|
||||
|
||||
<!-- 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', {})
|
||||
|
||||
|
@ -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',
|
||||
|
@ -187,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'
|
||||
});
|
||||
}
|
||||
|
@ -17,7 +17,6 @@
|
||||
this.rootEl.addEventListener('click', this.onClick_.bind(this));
|
||||
this.toggleLayerPreviewEl.addEventListener('click', this.toggleLayerPreview_.bind(this));
|
||||
|
||||
this.initCreateLayerButton_();
|
||||
this.initToggleLayerPreview_();
|
||||
|
||||
this.renderLayerList_();
|
||||
@ -46,14 +45,6 @@
|
||||
}
|
||||
};
|
||||
|
||||
ns.LayersListController.prototype.initCreateLayerButton_ = function () {
|
||||
var tooltip = 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', tooltip);
|
||||
};
|
||||
|
||||
ns.LayersListController.prototype.initToggleLayerPreview_ = function () {
|
||||
var descriptors = [{description : 'Opacity defined in PREFERENCES'}];
|
||||
var helpText = 'Preview all layers';
|
||||
@ -126,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));
|
||||
@ -154,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();
|
||||
} else if (action == 'down') {
|
||||
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') {
|
||||
|
@ -139,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
|
||||
});
|
||||
|
@ -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'
|
||||
});
|
||||
};
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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(' ')
|
||||
});
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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 () {
|
||||
|
261
src/js/controller/dialogs/ImportImageController.js
Normal file
261
src/js/controller/dialogs/ImportImageController.js
Normal 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');
|
||||
};
|
||||
|
||||
})();
|
@ -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);
|
||||
};
|
||||
})();
|
@ -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;
|
||||
};
|
||||
|
||||
})();
|
@ -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);
|
||||
};
|
||||
})();
|
@ -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';
|
||||
}
|
||||
};
|
||||
})();
|
@ -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);
|
||||
};
|
||||
})();
|
@ -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();
|
||||
};
|
||||
})();
|
@ -155,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) {
|
||||
@ -230,13 +231,6 @@
|
||||
return name;
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.duplicateCurrentLayer = function () {
|
||||
var layer = this.getCurrentLayer();
|
||||
var clone = pskl.utils.LayerUtils.clone(layer);
|
||||
this.piskel.addLayer(clone);
|
||||
this.setCurrentLayerIndex(this.piskel.getLayers().length - 1);
|
||||
};
|
||||
|
||||
ns.PiskelController.prototype.createLayer = function (name) {
|
||||
if (!name) {
|
||||
name = this.generateLayerName_();
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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');
|
||||
}
|
@ -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,19 +61,27 @@
|
||||
ns.ResizeController.prototype.onResizeFormSubmit_ = function (evt) {
|
||||
evt.preventDefault();
|
||||
|
||||
var resizedLayers = this.piskelController.getLayers().map(this.resizeLayer_.bind(this));
|
||||
|
||||
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 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) {
|
||||
@ -99,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);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
File diff suppressed because one or more lines are too long
@ -70,10 +70,6 @@
|
||||
});
|
||||
};
|
||||
|
||||
ns.Piskel.prototype.getFrameCount = function () {
|
||||
return this.getLayerAt(0).size();
|
||||
};
|
||||
|
||||
ns.Piskel.prototype.addLayer = function (layer) {
|
||||
this.layers.push(layer);
|
||||
};
|
||||
|
@ -252,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/juliandescottes/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);
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -60,7 +60,6 @@
|
||||
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')
|
||||
},
|
||||
|
||||
|
@ -19,10 +19,6 @@
|
||||
}
|
||||
}
|
||||
return isNodeWebkit;
|
||||
},
|
||||
|
||||
isIntegrationTest : function () {
|
||||
return window.location.href.indexOf('integration-test') !== -1;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
};
|
||||
})();
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
@ -6,9 +6,5 @@
|
||||
var padding = new Array(length).join(pad);
|
||||
return (padding + input).slice(-length);
|
||||
},
|
||||
|
||||
formatSize : function (width, height) {
|
||||
return width + '\u00D7' + height;
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
@ -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));
|
||||
};
|
||||
})();
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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"><<</button>' +
|
||||
'<button class="button frame-nav-previous"><</button>' +
|
||||
'<input class="textfield frame-nav-input" type="text">' +
|
||||
'<button class="button frame-nav-next">></button>' +
|
||||
'<button class="button frame-nav-last">>></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);
|
||||
}
|
||||
};
|
||||
})();
|
@ -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;
|
||||
};
|
||||
|
@ -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);
|
||||
};
|
||||
})();
|
@ -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;
|
||||
|
@ -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",
|
||||
@ -128,6 +126,7 @@
|
||||
"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",
|
||||
@ -139,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",
|
||||
|
||||
@ -154,13 +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/SynchronizedInputs.js",
|
||||
"js/widgets/Wizard.js",
|
||||
|
||||
// Services
|
||||
"js/service/storage/StorageService.js",
|
||||
|
@ -22,7 +22,7 @@
|
||||
"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",
|
||||
@ -36,8 +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-wizard.css"
|
||||
"css/minimap.css"
|
||||
];
|
@ -43,7 +43,7 @@
|
||||
<script type="text/template" id="cheatsheet-shortcut-template">
|
||||
<li class="cheatsheet-shortcut {{className}}" data-shortcut-id="{{id}}">
|
||||
<div class="cheatsheet-icon {{icon}}"></div>
|
||||
<span class="cheatsheet-key" rel="tooltip" data-placement="top" title="{{title}}">{{!key!}}</span>
|
||||
<span class="cheatsheet-key" rel="tooltip" data-placement="top" title="{{title}}">{{key}}</span>
|
||||
<span class="cheatsheet-description">{{description}}</span>
|
||||
</li>
|
||||
</script>
|
51
src/templates/dialogs/import-image.html
Normal file
51
src/templates/dialogs/import-image.html
Normal file
@ -0,0 +1,51 @@
|
||||
<script type="text/template" id="templates/dialogs/import-image.html">
|
||||
<div class="dialog-wrapper">
|
||||
<h3 class="dialog-head">
|
||||
Import Image
|
||||
<span class="dialog-close">X</span>
|
||||
</h3>
|
||||
<div class="dialog-import-body">
|
||||
<form action="" method="POST" name="import-image-form">
|
||||
<div class="import-section">
|
||||
<span class="dialog-section-title">Name :</span><span class="import-image-file-name"></span>
|
||||
</div>
|
||||
<div class="import-section">
|
||||
<div class="import-section-preview-title">Preview :</div>
|
||||
<div class="import-section-preview"></div>
|
||||
</div>
|
||||
<div class="import-section">
|
||||
<label class="dialog-section-radio-label">
|
||||
<input class="dialog-section-radio" name="import-type" value="single" type="radio" checked="checked">
|
||||
Import as single image
|
||||
</label>
|
||||
</div>
|
||||
<div class="import-section import-subsection">
|
||||
<span class="dialog-section-title">Resize to</span>
|
||||
<input type="text" class="textfield import-size-field" name="resize-width"/>x
|
||||
<input type="text" class="textfield import-size-field" name="resize-height"/>
|
||||
</div>
|
||||
<div class="import-section import-subsection">
|
||||
<span class="import-section-title">Smooth resize</span>
|
||||
<input type="checkbox" class="checkbox-fix" checked="checked" name="smooth-resize-checkbox" value="1"/>
|
||||
</div>
|
||||
<div class="import-section">
|
||||
<label class="dialog-section-radio-label">
|
||||
<input class="dialog-section-radio" name="import-type" value="sheet" type="radio">
|
||||
Import as spritesheet
|
||||
</label>
|
||||
</div>
|
||||
<div class="import-section import-subsection">
|
||||
<span class="dialog-section-title">Frame size</span>
|
||||
<input type="text" class="textfield import-size-field" name="frame-size-x"/>x
|
||||
<input type="text" class="textfield import-size-field" name="frame-size-y"/>
|
||||
</div>
|
||||
<div class="import-section import-subsection">
|
||||
<span class="dialog-section-title">Offset</span>
|
||||
<input type="text" class="textfield import-size-field" name="frame-offset-x"/>x
|
||||
<input type="text" class="textfield import-size-field" name="frame-offset-y"/>
|
||||
</div>
|
||||
<input type="submit" name="import-submit" class="button button-primary import-button" value="Import"/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
@ -1,196 +0,0 @@
|
||||
<script type="text/template" id="templates/dialogs/import.html">
|
||||
<div class="dialog-wrapper">
|
||||
<h3 class="dialog-head">
|
||||
Import and Merge
|
||||
<span class="dialog-close">X</span>
|
||||
</h3>
|
||||
<div class="dialog-content import-wizard-container"></div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="import-image-import">
|
||||
<div class="import-step-container import-image-container">
|
||||
<form action="" method="POST" name="import-image-form">
|
||||
<div class="import-section">
|
||||
<span class="dialog-section-title">Name :</span><span class="import-image-file-name"></span>
|
||||
</div>
|
||||
<div class="import-section">
|
||||
<div class="import-section-preview"></div>
|
||||
</div>
|
||||
<div class="import-section">
|
||||
<label class="dialog-section-radio-label">
|
||||
<input class="dialog-section-radio" name="import-type" value="single" type="radio" checked="checked">
|
||||
Import as single image
|
||||
</label>
|
||||
</div>
|
||||
<div class="import-section import-subsection">
|
||||
<span class="dialog-section-title">Resize to</span>
|
||||
<input type="text" class="textfield import-size-field" name="resize-width"/>x
|
||||
<input type="text" class="textfield import-size-field" name="resize-height"/>
|
||||
</div>
|
||||
<div class="import-section import-subsection">
|
||||
<span class="import-section-title">Smooth resize</span>
|
||||
<input type="checkbox" class="checkbox-fix" checked="checked" name="smooth-resize-checkbox" value="1"/>
|
||||
</div>
|
||||
<div class="import-section">
|
||||
<label class="dialog-section-radio-label">
|
||||
<input class="dialog-section-radio" name="import-type" value="sheet" type="radio">
|
||||
Import as spritesheet
|
||||
</label>
|
||||
</div>
|
||||
<div class="import-section import-subsection">
|
||||
<span class="dialog-section-title">Frame size</span>
|
||||
<input type="text" class="textfield import-size-field" name="frame-size-x"/>x
|
||||
<input type="text" class="textfield import-size-field" name="frame-size-y"/>
|
||||
</div>
|
||||
<div class="import-section import-subsection">
|
||||
<span class="dialog-section-title">Offset</span>
|
||||
<input type="text" class="textfield import-size-field" name="frame-offset-x"/>x
|
||||
<input type="text" class="textfield import-size-field" name="frame-offset-y"/>
|
||||
</div>
|
||||
</form>
|
||||
<div class="import-step-buttons">
|
||||
<button class="import-back-button button">back</button>
|
||||
<button class="import-next-button button button-primary">next</button>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="import-select-mode">
|
||||
<div class="import-step-container">
|
||||
<div class="import-info">
|
||||
<div class="import-preview"></div>
|
||||
<div class="import-meta"></div>
|
||||
</div>
|
||||
|
||||
<div class="import-step-content">
|
||||
<div class="import-mode">
|
||||
<div class="import-mode-title">How do you want to import the new content?</div>
|
||||
<div class="import-mode-section">
|
||||
<span class="import-mode-section-description">Combine the imported content and your sprite.</span>
|
||||
<button class="import-mode-merge-button button-primary button">Merge</button>
|
||||
</div>
|
||||
<div class="import-mode-section">
|
||||
<span class="import-mode-section-description">Replace your current sprite by the imported content.</span>
|
||||
<button class="import-mode-replace-button button-primary button">Replace</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="import-step-buttons">
|
||||
<button class="import-back-button button">back</button>
|
||||
<button style="display: none" class="import-next-button button button-primary">next</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="import-meta-content">
|
||||
<div class="import-name">
|
||||
<span class="import-meta-label">Name</span>
|
||||
<span class="import-meta-value" title="{{name}}">{{name}}</span>
|
||||
</div>
|
||||
<div class="import-dimensions">
|
||||
<span class="import-meta-label">Dimensions</span>
|
||||
<span class="import-meta-value">{{dimensions}}</span>
|
||||
</div>
|
||||
<div class="import-frames">
|
||||
<span class="import-meta-label">Frames</span>
|
||||
<span class="import-meta-value">{{frames}}</span>
|
||||
</div>
|
||||
<div class="import-layers">
|
||||
<span class="import-meta-label">Layers</span>
|
||||
<span class="import-meta-value">{{layers}}</span>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="import-adjust-size">
|
||||
<div class="import-step-container">
|
||||
|
||||
<div class="import-info">
|
||||
<div class="import-preview"></div>
|
||||
<div class="import-meta"></div>
|
||||
</div>
|
||||
|
||||
<div class="import-step-content">
|
||||
<div class="import-resize-info"></div>
|
||||
<div class="import-resize-anchor import-resize-section">
|
||||
<div class="import-resize-anchor-info"></div>
|
||||
<div class="import-resize-anchor-container"></div>
|
||||
</div>
|
||||
<div class="import-step-buttons">
|
||||
<button class="import-back-button button">back</button>
|
||||
<button class="import-next-button button button-primary">next</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="import-resize-bigger-partial">
|
||||
<div class="import-resize-bigger">
|
||||
<div class="import-resize-section">
|
||||
The imported image is bigger than the current sprite.
|
||||
</div>
|
||||
<div class="import-resize-section">
|
||||
<div class="import-resize-option-label">
|
||||
How do you want to proceed?
|
||||
</div>
|
||||
<label class="import-resize-option">
|
||||
<input type="radio" name="resize-mode" id="resize-option-expand" value="expand" {{expandChecked}}/>
|
||||
<span>Expand canvas to {{newSize}}</span>
|
||||
</label>
|
||||
<label class="import-resize-option">
|
||||
<input type="radio" name="resize-mode" id="resize-option-keep" value="keep" {{keepChecked}}/>
|
||||
<span>Keep canvas size at {{size}}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="import-resize-smaller-partial">
|
||||
<div class="import-resize-smaller">
|
||||
<div class="import-resize-section">
|
||||
The image being imported is smaller ({{newSize}}) than the canvas size ({{size}}).
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="import-insert-location">
|
||||
<div class="import-step-container">
|
||||
<div class="import-info">
|
||||
<div class="import-preview"></div>
|
||||
<div class="import-meta"></div>
|
||||
</div>
|
||||
|
||||
<div class="import-step-content">
|
||||
<div>Select a frame in your current sprite:</div>
|
||||
<div class="insert-frame-preview"></div>
|
||||
<div class="insert-mode-container">
|
||||
<div class="insert-mode-option-label">
|
||||
How should the imported frames be inserted:
|
||||
</div>
|
||||
<label class="insert-mode-option">
|
||||
<input type="radio" name="insert-mode" id="insert-mode-add" value="add" checked="checked"/>
|
||||
<span>Add new frames</span>
|
||||
</label>
|
||||
<label class="insert-mode-option">
|
||||
<input type="radio" name="insert-mode" id="insert-mode-insert" value="insert"/>
|
||||
<span>Insert in existing frames</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="import-step-buttons">
|
||||
<button class="import-back-button button">back</button>
|
||||
<button class="import-next-button button button-primary">import</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="import-invalid-file">
|
||||
<div class="import-step-container">
|
||||
<div>THIS IS AN INVALID FILEZ</div>
|
||||
<div class="import-step-buttons">
|
||||
<button class="import-back-button button">back</button>
|
||||
<button class="import-next-button button button-primary">next</button>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
@ -7,7 +7,7 @@
|
||||
<div class="toolbox-buttons">
|
||||
<button data-action="add"
|
||||
class="button layers-button piskel-icon-plus"
|
||||
rel="tooltip" data-placement="top" ></button>
|
||||
title="Create a new layer" rel="tooltip" data-placement="top" ></button>
|
||||
|
||||
<button data-action="up"
|
||||
class="button layers-button piskel-icon-arrow-up-fat"
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script type="text/html" id="templates/settings/application.html">
|
||||
<form action="" method="POST" name="application-settings-form" class="application-settings-form">
|
||||
<form action="" method="POST" name="application-settings-form">
|
||||
<div class="settings-section settings-section-application">
|
||||
<div class="settings-title">
|
||||
General
|
||||
@ -66,14 +66,6 @@
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="settings-version-info">
|
||||
Piskel
|
||||
<span rel="tooltip" data-placement="bottom" title="View release notes">
|
||||
<a class="settings-version" target="_blank"
|
||||
href="https://github.com/piskelapp/piskel/releases/tag/v@@releaseVersion">v@@releaseVersion</a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<input type="submit" class="button button-primary" value="Apply settings" />
|
||||
</div>
|
||||
</form>
|
||||
|
@ -30,7 +30,17 @@
|
||||
</div>
|
||||
<div class="resize-section">
|
||||
<span class="resize-section-title">Anchor</span>
|
||||
<div class="resize-anchor-container"></div>
|
||||
<div class="resize-origin-container">
|
||||
<div class="resize-origin-option" title="top left" data-origin="TOPLEFT"></div>
|
||||
<div class="resize-origin-option" title="top" data-origin="TOP"></div>
|
||||
<div class="resize-origin-option" title="top right" data-origin="TOPRIGHT"></div>
|
||||
<div class="resize-origin-option" title="middle left" data-origin="MIDDLELEFT"></div>
|
||||
<div class="resize-origin-option" title="middle" data-origin="MIDDLE"></div>
|
||||
<div class="resize-origin-option" title="middle right" data-origin="MIDDLERIGHT"></div>
|
||||
<div class="resize-origin-option" title="bottom left" data-origin="BOTTOMLEFT"></div>
|
||||
<div class="resize-origin-option" title="bottom" data-origin="BOTTOM"></div>
|
||||
<div class="resize-origin-option" title="bottom right" data-origin="BOTTOMRIGHT"></div>
|
||||
</div>
|
||||
</div>
|
||||
<input type="submit" class="button button-primary resize-button" value="Resize" />
|
||||
</form>
|
||||
|
@ -3,8 +3,6 @@
|
||||
'settings/test-export-gif-simple.js',
|
||||
'settings/test-export-png.js',
|
||||
'settings/test-export-png-scale.js',
|
||||
'settings/test-import-image.js',
|
||||
'settings/test-import-image-twice.js',
|
||||
'settings/test-resize-complete.js',
|
||||
'settings/test-resize-content-complete.js',
|
||||
'settings/test-resize-default-size.js',
|
||||
|
@ -110,8 +110,8 @@ function waitForEvent(eventName, onSuccess, onError) {
|
||||
function replaceFunction(test, path, method) {
|
||||
// Check the path provided corresponds to an existing method, otherwise the
|
||||
// test probably needs to be updated.
|
||||
test.assertEquals(evalLine('typeof ' + path), 'function',
|
||||
path + ' is still a function');
|
||||
test.assertEquals(evalLine('typeof ' + path),'function',
|
||||
'The prototype of GifExportController still contains downloadImageData_ as a function');
|
||||
|
||||
// Replace the method in content.
|
||||
casper.evaluate('function () {' + path + ' = ' + method + '}');
|
||||
|
@ -108,7 +108,7 @@ casper.test.begin('Simple GIF (<256 colors) export test, with 2x scaling', 16, f
|
||||
.start(casper.cli.get('baseUrl')+"/?debug")
|
||||
.then(function () {
|
||||
casper.echo("URL loaded");
|
||||
casper.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 20000);
|
||||
casper.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 10000);
|
||||
})
|
||||
.run(function () {
|
||||
test.done();
|
||||
|
@ -97,7 +97,7 @@ casper.test.begin('Simple GIF (<256 colors) export test', 14, function(test) {
|
||||
.start(casper.cli.get('baseUrl')+"/?debug")
|
||||
.then(function () {
|
||||
casper.echo("URL loaded");
|
||||
casper.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 20000);
|
||||
casper.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 10000);
|
||||
})
|
||||
.run(function () {
|
||||
test.done();
|
||||
|
@ -74,7 +74,7 @@ casper.test.begin('Complex GIF export test', 11, function(test) {
|
||||
.start(casper.cli.get('baseUrl')+"/?debug")
|
||||
.then(function () {
|
||||
casper.echo("URL loaded");
|
||||
casper.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 20000);
|
||||
casper.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 10000);
|
||||
})
|
||||
.run(function () {
|
||||
test.done();
|
||||
|
@ -112,7 +112,7 @@ casper.test.begin('PNG export test, with 2x scaling', 16, function(test) {
|
||||
.start(casper.cli.get('baseUrl')+"/?debug")
|
||||
.then(function () {
|
||||
casper.echo("URL loaded");
|
||||
casper.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 20000);
|
||||
casper.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 10000);
|
||||
})
|
||||
.run(function () {
|
||||
test.done();
|
||||
|
@ -101,7 +101,7 @@ casper.test.begin('PNG export test', 13, function(test) {
|
||||
.start(casper.cli.get('baseUrl')+"/?debug")
|
||||
.then(function () {
|
||||
casper.echo("URL loaded");
|
||||
casper.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 20000);
|
||||
casper.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 10000);
|
||||
})
|
||||
.run(function () {
|
||||
test.done();
|
||||
|
@ -1,192 +0,0 @@
|
||||
/* globals casper, setPiskelFromGrid, isDrawerExpanded, getValue, isChecked,
|
||||
evalLine, waitForEvent, replaceFunction, setPiskelFromImageSrc */
|
||||
|
||||
casper.test.begin('Double Image import test', 25, function(test) {
|
||||
test.timeout = test.fail.bind(test, ['Test timed out']);
|
||||
|
||||
// Helper to retrieve the text content of the provided selector
|
||||
// in the current wizard step.
|
||||
var getTextContent = function (selector) {
|
||||
selector = '.current-step ' + selector;
|
||||
return evalLine('document.querySelector("' + selector +'").textContent');
|
||||
};
|
||||
|
||||
// Helper to retrieve the value of a meta-information from the import
|
||||
// preview displayed on each of the import steps
|
||||
var getMetaValue = function (name) {
|
||||
return getTextContent('.import-' + name +' .import-meta-value');
|
||||
};
|
||||
|
||||
var fireDialogShowEvent = function (name) {
|
||||
casper.evaluate(
|
||||
'function () {\
|
||||
$.publish(Events.DIALOG_SHOW, {\
|
||||
dialogId : "import",\
|
||||
initArgs : {\
|
||||
rawFiles: [{type: "image", name: "test-name.png"}]\
|
||||
}\
|
||||
});\
|
||||
}'
|
||||
);
|
||||
};
|
||||
|
||||
var mockReadImageFile = function (imageDataUrl) {
|
||||
replaceFunction(test,
|
||||
'pskl.utils.FileUtils.readImageFile',
|
||||
'function (file, callback) {\
|
||||
var image = new Image();\
|
||||
image.onload = callback.bind(null, image);\
|
||||
image.src = "' + imageDataUrl +'";\
|
||||
}'
|
||||
);
|
||||
};
|
||||
|
||||
function onTestStart() {
|
||||
test.assertExists('#drawing-canvas-container canvas', 'Piskel ready, test starting');
|
||||
|
||||
// Bypass all confirm dialogs.
|
||||
replaceFunction(test,
|
||||
'window.confirm',
|
||||
function () {
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
test.assert(!isDrawerExpanded(), 'settings drawer is closed');
|
||||
|
||||
waitForEvent('PISKEL_RESET', onPiskelReset, test.timeout);
|
||||
|
||||
// 1x1 black pixel
|
||||
var src = [
|
||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcS',
|
||||
'JAAAADUlEQVQYV2NgYGD4DwABBAEAcCBlCwAAAABJRU5ErkJggg=='
|
||||
].join('');
|
||||
setPiskelFromImageSrc(src);
|
||||
}
|
||||
|
||||
function onPiskelReset() {
|
||||
// Check the expected piskel was correctly loaded.
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getPiskel().getWidth()'), 1, 'Piskel width is 1 pixel');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getPiskel().getHeight()'), 1, 'Piskel height is 1 pixel');
|
||||
|
||||
// Open export panel.
|
||||
test.assertDoesntExist('.settings-section-import', 'Check if import panel is closed');
|
||||
casper.click('[data-setting="import"]');
|
||||
|
||||
casper.waitForSelector('.settings-section-import', onImportPanelReady, test.timeout, 10000);
|
||||
}
|
||||
|
||||
function onImportPanelReady() {
|
||||
test.assert(isDrawerExpanded(), 'settings drawer is expanded');
|
||||
test.assertExists('.settings-section-import', 'Check if import panel is opened');
|
||||
|
||||
mockReadImageFile([
|
||||
// Source for a simple base64 encoded PNG, 2x2, with 2 different colors and 2 transparent pixels.
|
||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0',
|
||||
'kAAAAF0lEQVQYVwXBAQEAAACCIPw/uiAYi406Ig4EARK1RMAAAAAASUVORK5CYII='
|
||||
].join(''));
|
||||
|
||||
casper.echo('Clicking on Browse Images button');
|
||||
test.assertExists('.file-input-button', 'The import image button is available');
|
||||
|
||||
// We can't really control the file picker from the test so we directly fire the event
|
||||
fireDialogShowEvent();
|
||||
|
||||
casper.echo('Wait for .import-image-container');
|
||||
casper.waitForSelector('.current-step.import-image-container', onImageImportReady, test.timeout, 10000);
|
||||
}
|
||||
|
||||
function onImageImportReady() {
|
||||
casper.echo('Found import-image-container');
|
||||
|
||||
// Click on export again to close the settings drawer.
|
||||
test.assertEquals(getTextContent('.import-next-button'), 'next',
|
||||
'Next button found and has the expected text content');
|
||||
casper.click('.current-step .import-next-button');
|
||||
casper.waitForSelector('.current-step .import-mode', onSelectModeReady, test.timeout, 10000);
|
||||
}
|
||||
|
||||
function onSelectModeReady() {
|
||||
casper.echo('Select Mode step is displayed');
|
||||
|
||||
casper.echo('Click on replace-button and wait for popup to close');
|
||||
casper.click('.current-step .import-mode-replace-button');
|
||||
casper.waitForSelector('#dialog-container-wrapper:not(.show)', onPopupClosed, test.timeout, 10000);
|
||||
}
|
||||
|
||||
function onPopupClosed() {
|
||||
casper.echo('Import popup is closed, check the imported piskel content');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getPiskel().getWidth()'), 2, 'Piskel width is 2 pixels');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getPiskel().getHeight()'), 2, 'Piskel height is 2 pixels');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getLayers().length'), 1, 'Piskel has 1 layer');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getFrameCount()'), 1, 'Piskel has 1 frame');
|
||||
|
||||
// Need to wait a bit for the popup to be actually destroyed!
|
||||
casper.wait(1000, onPopupDestroyed);
|
||||
}
|
||||
|
||||
function onPopupDestroyed() {
|
||||
// Now we reopen the import panel a second time to check that the destroy of the previous import
|
||||
// wizard was successful.
|
||||
test.assertDoesntExist('.expanded .settings-section-import', 'Check if import panel is closed');
|
||||
casper.click('[data-setting="import"]');
|
||||
|
||||
casper.waitForSelector('.expanded .settings-section-import', onImportPanelReady2, test.timeout, 10000);
|
||||
}
|
||||
|
||||
function onImportPanelReady2() {
|
||||
test.assert(isDrawerExpanded(), 'settings drawer is expanded(2)');
|
||||
test.assertExists('.settings-section-import', 'Check if import panel is opened');
|
||||
|
||||
mockReadImageFile([
|
||||
// 1 x 1 black pixel
|
||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcS',
|
||||
'JAAAADUlEQVQYV2NgYGD4DwABBAEAcCBlCwAAAABJRU5ErkJggg=='
|
||||
].join(''));
|
||||
|
||||
casper.echo('Clicking on Browse Images button');
|
||||
test.assertExists('.file-input-button', 'The import image button is available');
|
||||
|
||||
// We can't really control the file picker from the test so we directly fire the event
|
||||
fireDialogShowEvent();
|
||||
|
||||
casper.echo('Wait for .import-image-container');
|
||||
casper.waitForSelector('.current-step', onImageImportReady2, test.timeout, 10000);
|
||||
}
|
||||
|
||||
function onImageImportReady2() {
|
||||
casper.echo('Found import-image-container (again)');
|
||||
|
||||
// Click on export again to close the settings drawer.
|
||||
test.assertEquals(getTextContent('.import-next-button'), 'next',
|
||||
'Next button found and has the expected text content');
|
||||
casper.click('.current-step .import-next-button');
|
||||
casper.waitForSelector('.current-step .import-mode', onSelectModeReady2, test.timeout, 10000);
|
||||
}
|
||||
|
||||
function onSelectModeReady2() {
|
||||
casper.echo('Select Mode step is displayed (again)');
|
||||
|
||||
casper.echo('Click on replace-button and wait for popup to close');
|
||||
casper.click('.current-step .import-mode-replace-button');
|
||||
casper.waitForSelector('#dialog-container-wrapper:not(.show)', onPopupClosed2, test.timeout, 10000);
|
||||
}
|
||||
|
||||
function onPopupClosed2() {
|
||||
casper.echo('Import popup is closed, check the imported piskel content');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getPiskel().getWidth()'), 1, 'Piskel width is 1 pixel');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getPiskel().getHeight()'), 1, 'Piskel height is 1 pixel');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getLayers().length'), 1, 'Piskel has 1 layer');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getFrameCount()'), 1, 'Piskel has 1 frame');
|
||||
}
|
||||
|
||||
casper
|
||||
.start(casper.cli.get('baseUrl')+"/?debug&integration-test")
|
||||
.then(function () {
|
||||
casper.echo("URL loaded");
|
||||
casper.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 20000);
|
||||
})
|
||||
.run(function () {
|
||||
test.done();
|
||||
});
|
||||
});
|
@ -1,148 +0,0 @@
|
||||
/* globals casper, setPiskelFromGrid, isDrawerExpanded, getValue, isChecked,
|
||||
evalLine, waitForEvent, replaceFunction, setPiskelFromImageSrc */
|
||||
|
||||
casper.test.begin('Simple Image import test', 26, function(test) {
|
||||
test.timeout = test.fail.bind(test, ['Test timed out']);
|
||||
|
||||
// Helper to retrieve the text content of the provided selector
|
||||
// in the current wizard step.
|
||||
var getTextContent = function (selector) {
|
||||
selector = '.current-step ' + selector;
|
||||
return evalLine('document.querySelector("' + selector +'").textContent');
|
||||
};
|
||||
|
||||
// Helper to retrieve the value of a meta-information from the import
|
||||
// preview displayed on each of the import steps
|
||||
var getMetaValue = function (name) {
|
||||
return getTextContent('.import-' + name +' .import-meta-value');
|
||||
};
|
||||
|
||||
var checkImportPreview = function (test) {
|
||||
casper.echo('Check the content of the import preview');
|
||||
test.assertEquals(getMetaValue('name'), 'test-name', 'Imported image has the expected name');
|
||||
test.assertEquals(getMetaValue('dimensions'), '2\u00D72', 'Imported image has the expected size');
|
||||
test.assertEquals(getMetaValue('frames'), '1', 'Imported image has the expected frames');
|
||||
test.assertEquals(getMetaValue('layers'), '1', 'Imported image has the expected layers');
|
||||
};
|
||||
|
||||
function onTestStart() {
|
||||
test.assertExists('#drawing-canvas-container canvas', 'Piskel ready, test starting');
|
||||
|
||||
test.assert(!isDrawerExpanded(), 'settings drawer is closed');
|
||||
|
||||
waitForEvent('PISKEL_RESET', onPiskelReset, test.timeout);
|
||||
|
||||
// 1x1 black pixel
|
||||
var src = [
|
||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcS',
|
||||
'JAAAADUlEQVQYV2NgYGD4DwABBAEAcCBlCwAAAABJRU5ErkJggg=='
|
||||
].join('');
|
||||
setPiskelFromImageSrc(src);
|
||||
}
|
||||
|
||||
function onPiskelReset() {
|
||||
// Check the expected piskel was correctly loaded.
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getPiskel().getWidth()'), 1, 'Piskel width is 1 pixel');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getPiskel().getHeight()'), 1, 'Piskel height is 1 pixel');
|
||||
|
||||
// Open export panel.
|
||||
test.assertDoesntExist('.settings-section-import', 'Check if import panel is closed');
|
||||
casper.click('[data-setting="import"]');
|
||||
|
||||
casper.waitForSelector('.settings-section-import', onImportPanelReady, test.timeout, 10000);
|
||||
}
|
||||
|
||||
function onImportPanelReady() {
|
||||
test.assert(isDrawerExpanded(), 'settings drawer is expanded');
|
||||
test.assertExists('.settings-section-import', 'Check if import panel is opened');
|
||||
|
||||
replaceFunction(test,
|
||||
'pskl.utils.FileUtils.readImageFile',
|
||||
function (file, callback) {
|
||||
var image = new Image();
|
||||
image.onload = callback.bind(null, image);
|
||||
// Source for a simple base64 encoded PNG, 2x2, with 2 different colors and 2 transparent pixels.
|
||||
image.src = [
|
||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0',
|
||||
'kAAAAF0lEQVQYVwXBAQEAAACCIPw/uiAYi406Ig4EARK1RMAAAAAASUVORK5CYII='
|
||||
].join('');
|
||||
}
|
||||
);
|
||||
|
||||
casper.echo('Clicking on Browse Images button');
|
||||
test.assertExists('.file-input-button', 'The import image button is available');
|
||||
|
||||
// We can't really control the file picker from the test so we directly fire the event
|
||||
casper.evaluate(
|
||||
'function () {\
|
||||
$.publish(Events.DIALOG_SHOW, {\
|
||||
dialogId : "import",\
|
||||
initArgs : {\
|
||||
rawFiles: [{type: "image", name: "test-name.png"}]\
|
||||
}\
|
||||
});\
|
||||
}'
|
||||
);
|
||||
|
||||
casper.echo('Wait for .import-image-container');
|
||||
casper.waitForSelector('.current-step.import-image-container', onImageImportReady, test.timeout, 10000);
|
||||
}
|
||||
|
||||
function onImageImportReady() {
|
||||
casper.echo('Found import-image-container');
|
||||
|
||||
// Click on export again to close the settings drawer.
|
||||
test.assertEquals(getTextContent('.import-next-button'), 'next',
|
||||
'Next button found and has the expected text content');
|
||||
casper.click('.current-step .import-next-button');
|
||||
casper.waitForSelector('.current-step .import-mode', onSelectModeReady, test.timeout, 10000);
|
||||
}
|
||||
|
||||
function onSelectModeReady() {
|
||||
casper.echo('Select Mode step is displayed');
|
||||
checkImportPreview(test);
|
||||
|
||||
casper.echo('Go to next step (adjust size)');
|
||||
casper.click('.current-step .import-mode-merge-button');
|
||||
casper.waitForSelector('.current-step .import-resize-info', onAdjustSizeReady, test.timeout, 10000);
|
||||
}
|
||||
|
||||
function onAdjustSizeReady() {
|
||||
casper.echo('Adjust size step is displayed');
|
||||
checkImportPreview(test);
|
||||
|
||||
casper.echo('Go to next step (insert location)');
|
||||
casper.click('.current-step .import-next-button');
|
||||
casper.waitForSelector('.current-step .insert-mode-container', onInsertLocationReady, test.timeout, 10000);
|
||||
}
|
||||
|
||||
function onInsertLocationReady() {
|
||||
casper.echo('Insert location step is displayed');
|
||||
checkImportPreview(test);
|
||||
|
||||
casper.echo('Select the mode "insert in existing frames"');
|
||||
casper.click('#insert-mode-insert');
|
||||
|
||||
casper.echo('Finalize the import');
|
||||
casper.click('.import-next-button');
|
||||
casper.waitForSelector('#dialog-container-wrapper:not(.show)', onPopupClosed, test.timeout, 10000);
|
||||
}
|
||||
|
||||
function onPopupClosed() {
|
||||
casper.echo('Import popup is closed, check the imported piskel content');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getPiskel().getWidth()'), 2, 'Piskel width is 2 pixels');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getPiskel().getHeight()'), 2, 'Piskel height is 2 pixels');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getLayers().length'), 2, 'Piskel has 2 layers');
|
||||
test.assertEquals(evalLine('pskl.app.piskelController.getFrameCount()'), 1, 'Piskel has 1 frame');
|
||||
}
|
||||
|
||||
casper
|
||||
.start(casper.cli.get('baseUrl')+"/?debug&integration-test")
|
||||
.then(function () {
|
||||
casper.echo("URL loaded");
|
||||
casper.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 20000);
|
||||
})
|
||||
.run(function () {
|
||||
test.done();
|
||||
});
|
||||
});
|
@ -69,7 +69,7 @@ casper.test.begin('Test resize feature works, and check the output', 19, functio
|
||||
.start(casper.cli.get('baseUrl')+"/?debug")
|
||||
.then(function () {
|
||||
this.echo("URL loaded");
|
||||
this.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 20000);
|
||||
this.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 10000);
|
||||
})
|
||||
.run(function () {
|
||||
test.done();
|
||||
|
@ -38,11 +38,11 @@ casper.test.begin('Test resize content works, and check the output', 18, functio
|
||||
|
||||
test.assertExists('.resize-content-checkbox', 'Check if resize ratio checkbox is available');
|
||||
test.assert(!isChecked('.resize-content-checkbox'), 'Keep content checkbox is unchecked');
|
||||
test.assertExists('.anchor-wrapper:not(.disabled)', 'Check the resize anchor widget is currently disabled');
|
||||
test.assertExists('.resize-origin-container:not(.disabled)', 'Check the resize origin widget is currently disabled');
|
||||
|
||||
casper.click('.resize-content-checkbox');
|
||||
// Enabling "Resize content" will disabled the resize anchor widget.
|
||||
casper.waitForSelector('.anchor-wrapper.disabled', onResizeOriginDisabled, test.timeout, 10000);
|
||||
// Enabling "Resize content" will disabled the resize origin widget.
|
||||
casper.waitForSelector('.resize-origin-container.disabled', onResizeOriginDisabled, test.timeout, 10000);
|
||||
}
|
||||
|
||||
function onResizeOriginDisabled() {
|
||||
@ -70,7 +70,7 @@ casper.test.begin('Test resize content works, and check the output', 18, functio
|
||||
.start(casper.cli.get('baseUrl')+"/?debug")
|
||||
.then(function () {
|
||||
this.echo("URL loaded");
|
||||
this.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 20000);
|
||||
this.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 10000);
|
||||
})
|
||||
.run(function () {
|
||||
test.done();
|
||||
|
@ -53,7 +53,7 @@ casper.test.begin('Test updating default size works', 14 , function(test) {
|
||||
.start(casper.cli.get('baseUrl')+"/?debug")
|
||||
.then(function () {
|
||||
this.echo("URL loaded");
|
||||
this.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 20000);
|
||||
this.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 10000);
|
||||
})
|
||||
.run(function () {
|
||||
test.done();
|
||||
|
@ -89,7 +89,7 @@ casper.test.begin('Test resize panel width/height inputs are synchronized', 28 ,
|
||||
.start(casper.cli.get('baseUrl')+"/?debug")
|
||||
.then(function () {
|
||||
this.echo("URL loaded");
|
||||
this.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 20000);
|
||||
this.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 10000);
|
||||
})
|
||||
.run(function () {
|
||||
test.done();
|
||||
|
@ -46,7 +46,7 @@ casper.test.begin('Test resize feature works, and check the output', 20, functio
|
||||
test.assert(!isChecked('.resize-content-checkbox'), 'Keep content checkbox is unchecked');
|
||||
|
||||
// Check that the default origin selected is top left.
|
||||
var selectedOrigin = evalLine('document.querySelector(".anchor-option.selected").getAttribute("data-origin")');
|
||||
var selectedOrigin = evalLine('document.querySelector(".resize-origin-option.selected").getAttribute("data-origin")');
|
||||
test.assertEquals(selectedOrigin, 'TOPLEFT');
|
||||
|
||||
// Change the origin to bottom right.
|
||||
@ -78,7 +78,7 @@ casper.test.begin('Test resize feature works, and check the output', 20, functio
|
||||
.start(casper.cli.get('baseUrl')+"/?debug")
|
||||
.then(function () {
|
||||
this.echo("URL loaded");
|
||||
this.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 20000);
|
||||
this.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 10000);
|
||||
})
|
||||
.run(function () {
|
||||
test.done();
|
||||
|
@ -55,7 +55,7 @@ casper.test.begin('Test resize feature works', 16 , function(test) {
|
||||
.start(casper.cli.get('baseUrl')+"/?debug")
|
||||
.then(function () {
|
||||
this.echo("URL loaded");
|
||||
this.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 20000);
|
||||
this.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 10000);
|
||||
})
|
||||
.run(function () {
|
||||
test.done();
|
||||
|
@ -75,7 +75,7 @@ casper.test.begin('Settings Test', 18, function(test) {
|
||||
.start(casper.cli.get('baseUrl')+"/?debug")
|
||||
.then(function () {
|
||||
this.echo("URL loaded");
|
||||
this.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 20000);
|
||||
this.waitForSelector('#drawing-canvas-container canvas', onTestStart, test.timeout, 10000);
|
||||
})
|
||||
.run(function () {
|
||||
test.done();
|
||||
|
@ -5,7 +5,6 @@
|
||||
"color.picker.json",
|
||||
"frames.fun.json",
|
||||
"history.basic.json",
|
||||
"layers.duplicate.json",
|
||||
"layers.fun.json",
|
||||
"layers.merge.json",
|
||||
"lighten.darken.json",
|
||||
|
@ -4,7 +4,6 @@
|
||||
"color.picker.json",
|
||||
"frames.fun.json",
|
||||
"history.basic.json",
|
||||
"layers.duplicate.json",
|
||||
"layers.fun.json",
|
||||
"layers.merge.json",
|
||||
"move.json",
|
||||
|
@ -1,207 +0,0 @@
|
||||
{
|
||||
"events": [
|
||||
{
|
||||
"event": {
|
||||
"type": "mousedown",
|
||||
"button": 0,
|
||||
"shiftKey": false,
|
||||
"altKey": false,
|
||||
"ctrlKey": false
|
||||
},
|
||||
"coords": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"type": "mouse-event"
|
||||
},
|
||||
{
|
||||
"event": {
|
||||
"type": "mousemove",
|
||||
"button": 0,
|
||||
"shiftKey": false,
|
||||
"altKey": false,
|
||||
"ctrlKey": false
|
||||
},
|
||||
"coords": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"type": "mouse-event"
|
||||
},
|
||||
{
|
||||
"event": {
|
||||
"type": "mousemove",
|
||||
"button": 0,
|
||||
"shiftKey": false,
|
||||
"altKey": false,
|
||||
"ctrlKey": false
|
||||
},
|
||||
"coords": {
|
||||
"x": 1,
|
||||
"y": 0
|
||||
},
|
||||
"type": "mouse-event"
|
||||
},
|
||||
{
|
||||
"event": {
|
||||
"type": "mousemove",
|
||||
"button": 0,
|
||||
"shiftKey": false,
|
||||
"altKey": false,
|
||||
"ctrlKey": false
|
||||
},
|
||||
"coords": {
|
||||
"x": 2,
|
||||
"y": 0
|
||||
},
|
||||
"type": "mouse-event"
|
||||
},
|
||||
{
|
||||
"event": {
|
||||
"type": "mouseup",
|
||||
"button": 0,
|
||||
"shiftKey": false,
|
||||
"altKey": false,
|
||||
"ctrlKey": false
|
||||
},
|
||||
"coords": {
|
||||
"x": 2,
|
||||
"y": 0
|
||||
},
|
||||
"type": "mouse-event"
|
||||
},
|
||||
{
|
||||
"type": "instrumented-event",
|
||||
"methodName": "duplicateFrameAt",
|
||||
"args": [
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "color-event",
|
||||
"color": "#ff0000",
|
||||
"isPrimary": true
|
||||
},
|
||||
{
|
||||
"event": {
|
||||
"type": "mousedown",
|
||||
"button": 0,
|
||||
"shiftKey": false,
|
||||
"altKey": false,
|
||||
"ctrlKey": false
|
||||
},
|
||||
"coords": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"type": "mouse-event"
|
||||
},
|
||||
{
|
||||
"event": {
|
||||
"type": "mousemove",
|
||||
"button": 0,
|
||||
"shiftKey": false,
|
||||
"altKey": false,
|
||||
"ctrlKey": false
|
||||
},
|
||||
"coords": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"type": "mouse-event"
|
||||
},
|
||||
{
|
||||
"event": {
|
||||
"type": "mousemove",
|
||||
"button": 0,
|
||||
"shiftKey": false,
|
||||
"altKey": false,
|
||||
"ctrlKey": false
|
||||
},
|
||||
"coords": {
|
||||
"x": 1,
|
||||
"y": 0
|
||||
},
|
||||
"type": "mouse-event"
|
||||
},
|
||||
{
|
||||
"event": {
|
||||
"type": "mousemove",
|
||||
"button": 0,
|
||||
"shiftKey": false,
|
||||
"altKey": false,
|
||||
"ctrlKey": false
|
||||
},
|
||||
"coords": {
|
||||
"x": 2,
|
||||
"y": 0
|
||||
},
|
||||
"type": "mouse-event"
|
||||
},
|
||||
{
|
||||
"event": {
|
||||
"type": "mouseup",
|
||||
"button": 0,
|
||||
"shiftKey": false,
|
||||
"altKey": false,
|
||||
"ctrlKey": false
|
||||
},
|
||||
"coords": {
|
||||
"x": 2,
|
||||
"y": 0
|
||||
},
|
||||
"type": "mouse-event"
|
||||
},
|
||||
{
|
||||
"type": "instrumented-event",
|
||||
"methodName": "duplicateCurrentLayer",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"type": "transformtool-event",
|
||||
"toolId": "tool-rotate",
|
||||
"event": {
|
||||
"shiftKey": true,
|
||||
"altKey": false,
|
||||
"ctrlKey": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "instrumented-event",
|
||||
"methodName": "duplicateCurrentLayer",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"type": "transformtool-event",
|
||||
"toolId": "tool-rotate",
|
||||
"event": {
|
||||
"shiftKey": true,
|
||||
"altKey": false,
|
||||
"ctrlKey": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "keyboard-event",
|
||||
"event": {
|
||||
"which": 90,
|
||||
"shiftKey": false,
|
||||
"altKey": false,
|
||||
"ctrlKey": true,
|
||||
"target": {
|
||||
"nodeName": "BODY"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"initialState": {
|
||||
"size": {
|
||||
"width": 2,
|
||||
"height": 2
|
||||
},
|
||||
"primaryColor": "#000000",
|
||||
"secondaryColor": "rgba(0, 0, 0, 0)",
|
||||
"selectedTool": "tool-pen",
|
||||
"penSize": 1
|
||||
},
|
||||
"png": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAACCAYAAAB/qH1jAAAAHUlEQVQYV2NkYGD4zwAjGBgYGKFsxv8MDP8ZgXwAURIFAdLn5x4AAAAASUVORK5CYII="
|
||||
}
|
@ -53,30 +53,4 @@ describe("LayerUtils test", function() {
|
||||
['rgba(255,0,0,0.5)', B]
|
||||
]);
|
||||
});
|
||||
|
||||
it("clones a layer", function() {
|
||||
var grid1 = [
|
||||
[B, T],
|
||||
[T, B]
|
||||
];
|
||||
|
||||
var grid2 = [
|
||||
[R, B],
|
||||
[B, R]
|
||||
];
|
||||
|
||||
// when
|
||||
var layer = new pskl.model.Layer('l1');
|
||||
layer.addFrame(pskl.model.Frame.fromPixelGrid(grid1));
|
||||
layer.addFrame(pskl.model.Frame.fromPixelGrid(grid2));
|
||||
|
||||
// then
|
||||
var clone = pskl.utils.LayerUtils.clone(layer);
|
||||
var clonedFrame = clone.getFrameAt(0);
|
||||
|
||||
// verify
|
||||
frameEqualsGrid(clone.getFrameAt(0), grid1);
|
||||
frameEqualsGrid(clone.getFrameAt(1), grid2);
|
||||
expect(clone.getName()).toBe('l1 (clone)');
|
||||
});
|
||||
});
|
@ -1,153 +0,0 @@
|
||||
describe("MergeUtils suite", function() {
|
||||
var B = '#000000';
|
||||
var R = '#ff0000';
|
||||
var T = Constants.TRANSPARENT_COLOR;
|
||||
|
||||
var createPiskelFromGrid = function (grid, name) {
|
||||
var frame = pskl.model.Frame.fromPixelGrid(grid);
|
||||
var layer = pskl.model.Layer.fromFrames("l1", [frame]);
|
||||
return pskl.model.Piskel.fromLayers([layer], 12, {
|
||||
name: name || "piskel",
|
||||
description: "desc"
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple helper to create a monochrome sprite for the provided color,
|
||||
* number of rows and columns.
|
||||
*/
|
||||
var getPiskel = function (color, rows, cols) {
|
||||
var grid = [];
|
||||
for (var i = 0 ; i < rows ; i++) {
|
||||
grid[i] = [];
|
||||
for (var j = 0 ; j < cols ; j++) {
|
||||
grid[i][j] = color;
|
||||
}
|
||||
}
|
||||
return createPiskelFromGrid(grid);
|
||||
};
|
||||
|
||||
it("merges 2 piskel - insertMode:add same size", function () {
|
||||
var piskel1 = getPiskel(B, 2, 2);
|
||||
var piskel2 = getPiskel(R, 2, 2);
|
||||
|
||||
var mergedPiskel = pskl.utils.MergeUtils.merge(piskel1, piskel2, {
|
||||
index: 0,
|
||||
resize: "expand",
|
||||
origin: "TOPLEFT",
|
||||
insertMode: "add"
|
||||
});
|
||||
|
||||
expect(mergedPiskel.getWidth()).toBe(2);
|
||||
expect(mergedPiskel.getHeight()).toBe(2);
|
||||
expect(mergedPiskel.getLayers().length).toBe(2);
|
||||
expect(mergedPiskel.getLayers()[0].getFrames().length).toBe(2);
|
||||
});
|
||||
|
||||
it("merges 2 piskel - insertMode:insert same size", function () {
|
||||
var piskel1 = getPiskel(B, 2, 2);
|
||||
var piskel2 = getPiskel(R, 2, 2);
|
||||
|
||||
var mergedPiskel = pskl.utils.MergeUtils.merge(piskel1, piskel2, {
|
||||
index: 0,
|
||||
resize: "expand",
|
||||
origin: "TOPLEFT",
|
||||
insertMode: "insert"
|
||||
});
|
||||
|
||||
expect(mergedPiskel.getWidth()).toBe(2);
|
||||
expect(mergedPiskel.getHeight()).toBe(2);
|
||||
expect(mergedPiskel.getLayers().length).toBe(2);
|
||||
expect(mergedPiskel.getLayers()[0].getFrames().length).toBe(1);
|
||||
});
|
||||
|
||||
it("merges 2 piskel - resize:expand with bigger imported piskel", function () {
|
||||
var piskel1 = getPiskel(B, 2, 2);
|
||||
var piskel2 = getPiskel(R, 4, 4);
|
||||
|
||||
var mergedPiskel = pskl.utils.MergeUtils.merge(piskel1, piskel2, {
|
||||
index: 0,
|
||||
resize: "expand",
|
||||
origin: "TOPLEFT",
|
||||
insertMode: "insert"
|
||||
});
|
||||
|
||||
expect(mergedPiskel.getWidth()).toBe(4);
|
||||
expect(mergedPiskel.getHeight()).toBe(4);
|
||||
});
|
||||
|
||||
it("merges 2 piskel - resize:keep with bigger imported piskel", function () {
|
||||
var piskel1 = getPiskel(B, 2, 2);
|
||||
var piskel2 = getPiskel(R, 4, 4);
|
||||
|
||||
var mergedPiskel = pskl.utils.MergeUtils.merge(piskel1, piskel2, {
|
||||
index: 0,
|
||||
resize: "keep",
|
||||
origin: "TOPLEFT",
|
||||
insertMode: "insert"
|
||||
});
|
||||
|
||||
expect(mergedPiskel.getWidth()).toBe(2);
|
||||
expect(mergedPiskel.getHeight()).toBe(2);
|
||||
});
|
||||
|
||||
it("merges 2 piskel - resize:expand with taller but thinner imported piskel", function () {
|
||||
var piskel1 = getPiskel(B, 2, 2);
|
||||
var piskel2 = getPiskel(R, 1, 4);
|
||||
|
||||
var mergedPiskel = pskl.utils.MergeUtils.merge(piskel1, piskel2, {
|
||||
index: 0,
|
||||
resize: "expand",
|
||||
origin: "TOPLEFT",
|
||||
insertMode: "insert"
|
||||
});
|
||||
|
||||
expect(mergedPiskel.getWidth()).toBe(2);
|
||||
expect(mergedPiskel.getHeight()).toBe(4);
|
||||
});
|
||||
|
||||
it("merges 2 piskel - resize:expand with wider but shorter imported piskel", function () {
|
||||
var piskel1 = getPiskel(B, 2, 2);
|
||||
var piskel2 = getPiskel(R, 4, 1);
|
||||
|
||||
var mergedPiskel = pskl.utils.MergeUtils.merge(piskel1, piskel2, {
|
||||
index: 0,
|
||||
resize: "expand",
|
||||
origin: "TOPLEFT",
|
||||
insertMode: "insert"
|
||||
});
|
||||
|
||||
expect(mergedPiskel.getWidth()).toBe(4);
|
||||
expect(mergedPiskel.getHeight()).toBe(2);
|
||||
});
|
||||
|
||||
it("merges 2 piskel - resize:expand with bigger original piskel", function () {
|
||||
var piskel1 = getPiskel(B, 3, 3);
|
||||
var piskel2 = getPiskel(R, 1, 1);
|
||||
|
||||
var mergedPiskel = pskl.utils.MergeUtils.merge(piskel1, piskel2, {
|
||||
index: 0,
|
||||
resize: "expand",
|
||||
origin: "TOPLEFT",
|
||||
insertMode: "insert"
|
||||
});
|
||||
|
||||
expect(mergedPiskel.getWidth()).toBe(3);
|
||||
expect(mergedPiskel.getHeight()).toBe(3);
|
||||
});
|
||||
|
||||
it("merges 2 piskel - resize:keep with bigger original piskel", function () {
|
||||
var piskel1 = getPiskel(B, 3, 3);
|
||||
var piskel2 = getPiskel(R, 1, 1);
|
||||
|
||||
var mergedPiskel = pskl.utils.MergeUtils.merge(piskel1, piskel2, {
|
||||
index: 0,
|
||||
resize: "keep",
|
||||
origin: "TOPLEFT",
|
||||
insertMode: "insert"
|
||||
});
|
||||
|
||||
expect(mergedPiskel.getWidth()).toBe(3);
|
||||
expect(mergedPiskel.getHeight()).toBe(3);
|
||||
});
|
||||
});
|
@ -1,25 +0,0 @@
|
||||
describe("Deserializer v0 test", function() {
|
||||
|
||||
var black = '#000000';
|
||||
var transparent = Constants.TRANSPARENT_COLOR;
|
||||
var data = [
|
||||
[
|
||||
["#000000", "TRANSPARENT"],
|
||||
["TRANSPARENT", "#000000"]
|
||||
]
|
||||
];
|
||||
|
||||
it("deserializes data serialized for model v0 correctly", function (done) {
|
||||
var deserializer = pskl.utils.serialization.Deserializer;
|
||||
deserializer.deserialize(data, function (p) {
|
||||
// Check the frame has been properly deserialized
|
||||
expect(p.getLayerAt(0).getFrames().length).toBe(1);
|
||||
var frame = p.getLayerAt(0).getFrameAt(0);
|
||||
test.testutils.frameEqualsGrid(frame, [
|
||||
[black, transparent],
|
||||
[transparent, black]
|
||||
]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
@ -1,28 +0,0 @@
|
||||
describe("Deserializer v1 test", function() {
|
||||
var B = '#000000';
|
||||
var T = Constants.TRANSPARENT_COLOR;
|
||||
var data = {
|
||||
"modelVersion": 1,
|
||||
"piskel": {
|
||||
"height": 2,
|
||||
"width": 2,
|
||||
"layers": [
|
||||
"{\"name\":\"Layer 1\",\"frames\":[\"[[\\\"#000000\\\",\\\"TRANSPARENT\\\"],[\\\"TRANSPARENT\\\",\\\"#000000\\\"]]\"]}"
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
it("deserializes data serialized for model v0 correctly", function (done) {
|
||||
var deserializer = pskl.utils.serialization.Deserializer;
|
||||
deserializer.deserialize(data, function (p) {
|
||||
// Check the frame has been properly deserialized
|
||||
expect(p.getLayerAt(0).getFrames().length).toBe(1);
|
||||
var frame = p.getLayerAt(0).getFrameAt(0);
|
||||
test.testutils.frameEqualsGrid(frame, [
|
||||
[B, T],
|
||||
[T, B]
|
||||
]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
@ -12,17 +12,17 @@ describe("Serialization/Deserialization test", function() {
|
||||
delete pskl.app.piskelController;
|
||||
});
|
||||
|
||||
it("serializes frames correctly", function (done) {
|
||||
if("serializes frames correctly", function () {
|
||||
// Create piskel.
|
||||
var descriptor = new pskl.model.piskel.Descriptor('piskelName', 'piskelDesc');
|
||||
var piskel = new pskl.model.Piskel(1, 1, 1, descriptor);
|
||||
// Add layer.
|
||||
piskel.addLayer(new pskl.model.Layer('layer1'));
|
||||
// Add frame.
|
||||
piskel.getLayerAt(0).addFrame(pskl.model.Frame.fromPixelGrid(test.testutils.toFrameGrid([
|
||||
piskel.getLayerAt(0).addFrame(pskl.model.Frame.fromPixelGrid([
|
||||
["red", "black"],
|
||||
["blue", "green"]
|
||||
])));
|
||||
]));
|
||||
|
||||
// Verify the frame is successfully added in the layer.
|
||||
expect(piskel.getLayerAt(0).getFrames().length).toBe(1);
|
||||
@ -34,13 +34,13 @@ describe("Serialization/Deserialization test", function() {
|
||||
// Check the frame has been properly deserialized
|
||||
expect(p.getLayerAt(0).getFrames().length).toBe(1);
|
||||
var frame = p.getLayerAt(0).getFrameAt(0);
|
||||
test.testutils.frameEqualsGrid(frame, [
|
||||
test.testutils.frameEqualsGrid(flattened, [
|
||||
["red", "black"],
|
||||
["blue", "green"]
|
||||
]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
it("serializes layer opacity", function(done) {
|
||||
var descriptor = new pskl.model.piskel.Descriptor('piskelName', 'piskelDesc');
|
||||
|
Reference in New Issue
Block a user